Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

argocd-gitops-platform

Production-ready GitOps bootstrap using the ArgoCD App of Apps pattern. One command installs ArgoCD; from that point the cluster is fully GitOps-driven β€” every tool, every environment, every config change flows through Git.

License: MIT ArgoCD Kubernetes Helm


Architecture

Architecture Diagram

πŸ“ Edit in Excalidraw β€” open the .excalidraw file at excalidraw.com to edit interactively.

  Git Repository
  β”œβ”€β”€ bootstrap/        ──► ArgoCD (root Application)
  β”‚   └── root-app.yaml       β”‚
  β”œβ”€β”€ platform/               β”‚  manages
  β”‚   β”œβ”€β”€ argocd/      ◄───────
  β”‚   β”œβ”€β”€ cert-manager/ ◄──────  App of Apps
  β”‚   └── ingress-nginx/ β—„β”€β”€β”€β”€β”˜
  └── apps/
      β”œβ”€β”€ dev/          ──► dev cluster namespace
      β”œβ”€β”€ staging/      ──► staging cluster namespace
      └── prod/         ──► prod cluster namespace

  ArgoCD ──► Sync ──► Kubernetes API ──► Deployed Resources
         └──► Notifications ──► Slack / Email

Table of Contents


The App of Apps Pattern

Standard ArgoCD installations require someone to manually create each Application object. The App of Apps pattern solves this: you create one root Application that points to a directory of other Application manifests. ArgoCD then self-manages itself and every tool from Git.

kubectl apply -f bootstrap/root-app.yaml
# β†’ ArgoCD syncs root-app.yaml
# β†’ root-app discovers platform/ directory
# β†’ platform apps deploy: ArgoCD itself, cert-manager, ingress-nginx
# β†’ apps/ ApplicationSets create per-environment Applications
# Everything else is automated

This means:

  • New cluster? kubectl apply -f bootstrap/root-app.yaml and walk away
  • New environment? Add a directory under apps/ and push
  • New platform tool? Add an Application under platform/ and push

Repository Structure

argocd-gitops-platform/
β”œβ”€β”€ bootstrap/
β”‚   └── root-app.yaml              # The single apply that starts everything
β”œβ”€β”€ platform/                      # Platform-level Applications
β”‚   β”œβ”€β”€ argocd/
β”‚   β”‚   β”œβ”€β”€ application.yaml       # ArgoCD self-manages via GitOps
β”‚   β”‚   └── values.yaml            # ArgoCD Helm values (RBAC, ingress, etc.)
β”‚   β”œβ”€β”€ cert-manager/
β”‚   β”‚   β”œβ”€β”€ application.yaml
β”‚   β”‚   └── values.yaml
β”‚   └── ingress-nginx/
β”‚       β”œβ”€β”€ application.yaml
β”‚       └── values.yaml
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ dev/
β”‚   β”‚   └── applicationset.yaml    # ApplicationSet generating dev Applications
β”‚   β”œβ”€β”€ staging/
β”‚   β”‚   └── applicationset.yaml
β”‚   └── prod/
β”‚       └── applicationset.yaml
β”œβ”€β”€ workloads/                     # Application Helm chart definitions
β”‚   └── <app-name>/
β”‚       β”œβ”€β”€ Chart.yaml
β”‚       └── values/
β”‚           β”œβ”€β”€ dev.yaml
β”‚           β”œβ”€β”€ staging.yaml
β”‚           └── prod.yaml
β”œβ”€β”€ notifications/
β”‚   └── slack-config.yaml          # Slack notification templates
β”œβ”€β”€ rbac/
β”‚   └── policy.csv                 # ArgoCD RBAC policy (multi-tenant)
└── scripts/
    └── bootstrap.sh               # Idempotent one-command cluster bootstrap

Prerequisites

Tool Version Install
kubectl β‰₯ 1.28 brew install kubectl
helm β‰₯ 3.12 brew install helm
argocd CLI β‰₯ 2.9 brew install argocd
A running K8s cluster GKE / EKS / kind / k3s β€”

Bootstrap

# 1. Clone
git clone https://github.com/ashiq-ali/argocd-gitops-platform
cd argocd-gitops-platform

# 2. Fork this repo and update the repoURL in bootstrap/root-app.yaml
#    Change: repoURL: https://github.com/ashiq-ali/argocd-gitops-platform
#    To:     repoURL: https://github.com/<YOUR_ORG>/argocd-gitops-platform

# 3. Install ArgoCD (only needed the first time)
kubectl create namespace argocd
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd \
  --namespace argocd \
  --version 6.7.3 \
  --wait

# 4. Apply the root Application β€” this is the ONLY manual step
kubectl apply -f bootstrap/root-app.yaml

# 5. Wait for everything to sync
kubectl -n argocd get applications -w

# 6. Get the initial admin password
argocd admin initial-password -n argocd

# 7. Access the UI
kubectl port-forward svc/argocd-server -n argocd 8080:443
# Open https://localhost:8080

Or use the idempotent bootstrap script:

./scripts/bootstrap.sh \
  --repo-url https://github.com/YOUR_ORG/argocd-gitops-platform \
  --cluster-name production

Platform Tools

Three platform tools are managed via GitOps from day 1:

ArgoCD (self-managed)

ArgoCD manages itself via platform/argocd/application.yaml. Upgrades happen through Git:

# Upgrade ArgoCD: edit the targetRevision in platform/argocd/values.yaml
git commit -m "chore: upgrade argocd to 2.11.0"
git push
# ArgoCD detects the change and self-upgrades

cert-manager

Automatically provisions TLS certificates from Let's Encrypt for all Ingress resources annotated with:

annotations:
  cert-manager.io/cluster-issuer: letsencrypt-prod

ingress-nginx

Handles external HTTP/HTTPS traffic. After bootstrap, create Ingress resources normally β€” they'll get a real IP/hostname from the cloud load balancer.


Multi-Environment Applications

Each environment uses an ApplicationSet to generate Applications from a directory structure:

# apps/dev/applicationset.yaml
spec:
  generators:
    - git:
        repoURL: https://github.com/YOUR_ORG/argocd-gitops-platform
        revision: main
        directories:
          - path: workloads/*
  template:
    spec:
      destination:
        namespace: '{{path.basename}}-dev'
      helm:
        valueFiles:
          - values/dev.yaml

To add a new application to all environments:

mkdir -p workloads/my-new-app/values
cat > workloads/my-new-app/Chart.yaml << EOF
apiVersion: v2
name: my-new-app
version: 0.1.0
dependencies:
  - name: my-new-app
    version: "1.0.0"
    repository: "https://charts.myorg.io"
EOF

cat > workloads/my-new-app/values/dev.yaml << EOF
my-new-app:
  replicaCount: 1
  image.tag: dev-latest
EOF

git add workloads/my-new-app
git commit -m "feat: add my-new-app to all environments"
git push
# ArgoCD picks it up within 3 minutes (default poll interval)

ApplicationSets

ApplicationSets automate Application creation across environments. This repo uses the Git Directory generator which creates one Application per subdirectory:

workloads/
β”œβ”€β”€ api-service/      β†’ Application: api-service-dev, api-service-staging, api-service-prod
β”œβ”€β”€ worker/           β†’ Application: worker-dev, worker-staging, worker-prod
└── frontend/         β†’ Application: frontend-dev, frontend-staging, frontend-prod

Each ApplicationSet also sets automated sync and self-heal so drift is corrected automatically:

syncPolicy:
  automated:
    prune: true      # Remove resources deleted from Git
    selfHeal: true   # Revert manual kubectl changes

RBAC

Multi-tenant RBAC is defined in rbac/policy.csv:

# Platform team β€” admin on everything
p, role:platform-admin, applications, *, */*, allow
p, role:platform-admin, clusters, *, *, allow

# Dev team β€” read-only on prod, full on dev/staging
p, role:dev-team, applications, get, */*, allow
p, role:dev-team, applications, *, *-dev/*, allow
p, role:dev-team, applications, *, *-staging/*, allow

# Read-only (auditors)
p, role:read-only, applications, get, */*, allow
p, role:read-only, logs, get, */*, allow

# Group mappings (SSO via Okta/Google)
g, [email protected], role:platform-admin
g, [email protected], role:dev-team

Slack Notifications

Configure Slack alerts for sync events, health changes, and deployment completions:

# 1. Create a Slack webhook secret
kubectl create secret generic argocd-notifications-secret \
  -n argocd \
  --from-literal=slack-token=xoxb-YOUR-SLACK-BOT-TOKEN

# 2. Annotate Applications for notifications
kubectl annotate application my-app \
  notifications.argoproj.io/subscribe.on-sync-succeeded.slack=deployments-channel \
  notifications.argoproj.io/subscribe.on-health-degraded.slack=alerts-channel

Notification templates in notifications/slack-config.yaml include deployment summaries with app name, sync revision, and diff link.


Promoting Across Environments

The recommended promotion flow β€” no branch-per-environment:

# 1. Deploy to dev (automatic on merge to main)
git merge feature/my-change
git push origin main

# 2. Validate in dev, then promote to staging
# Edit workloads/my-app/values/staging.yaml
git commit -m "chore: promote my-app v1.2.3 to staging"
git push

# 3. After staging sign-off, promote to prod
# Edit workloads/my-app/values/prod.yaml
git commit -m "chore: promote my-app v1.2.3 to prod"
git push
# ArgoCD syncs within 3 minutes; Slack notification confirms

For urgent prod rollbacks:

# Revert the last commit
git revert HEAD
git push
# ArgoCD self-heals within seconds

Disaster Recovery

Full cluster recovery from scratch:

# New cluster, same Git repo
kubectl create namespace argocd
helm install argocd argo/argo-cd --namespace argocd --wait
kubectl apply -f bootstrap/root-app.yaml
# All platform tools and applications restore from Git automatically
# Recovery time: ~10 minutes for platform tools, then app pods come up

The only state outside Git is:

  • TLS certificates (cert-manager re-issues automatically)
  • Application secrets (restore from your secrets manager β€” External Secrets Operator recommended)

Troubleshooting

Application stuck in OutOfSync forever

argocd app diff my-app          # See what's different
argocd app sync my-app --force  # Force sync
# If still stuck, check for Helm rendering errors:
argocd app manifests my-app

ComparisonError: failed to load target state

Usually a Helm chart values error. Check:

argocd app logs my-app
helm template workloads/my-app --values workloads/my-app/values/dev.yaml

Notifications not arriving

kubectl logs -n argocd deployment/argocd-notifications-controller | grep -i slack
# Verify the token in the secret is valid

ArgoCD UI unreachable after upgrade

ArgoCD self-upgrade can briefly disrupt the UI. Wait 2 minutes and refresh. If still down:

kubectl rollout restart deployment/argocd-server -n argocd

Built to demonstrate production GitOps workflows from hands-on ArgoCD experience at Virgin Media O2.

About

Production-ready GitOps bootstrap using ArgoCD App of Apps pattern | Multi-environment | Slack notifications | RBAC

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages