ArgoCDGitOpsKubernetes

ArgoCD Multi-Cluster Deployment Patterns

November 202410 min read

Managing GitOps deployments across multiple Kubernetes clusters requires thoughtful architecture. The control plane model provides centralized governance while maintaining flexibility for individual environments.

Architecture Overview

In the control plane model, a central ArgoCD instance manages downstream clusters:

┌─────────────────────────────────────────────────────────┐
│                  Control Plane Cluster                   │
│  ┌─────────────────────────────────────────────────────┐ │
│  │              ArgoCD (Hub Instance)                   │ │
│  │  - ApplicationSets                                   │ │
│  │  - Cluster Secrets                                   │ │
│  │  - RBAC Policies                                     │ │
│  └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
                           │
           ┌───────────────┼───────────────┐
           │               │               │
           ▼               ▼               ▼
    ┌───────────┐   ┌───────────┐   ┌───────────┐
    │    Dev    │   │  Staging  │   │   Prod    │
    │  Cluster  │   │  Cluster  │   │  Cluster  │
    └───────────┘   └───────────┘   └───────────┘

Setting Up the Control Plane

1. Installing ArgoCD

Deploy ArgoCD to your management cluster:

install-argocd.sh
# Create namespace
kubectl create namespace argocd

# Install ArgoCD with HA configuration
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd \
  --namespace argocd \
  --set server.replicas=2 \
  --set controller.replicas=2 \
  --set repoServer.replicas=2 \
  --set redis-ha.enabled=true

# Get initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d

2. Registering Target Clusters

Add downstream clusters using secrets or the ArgoCD CLI:

cluster-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: prod-cluster
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster
    environment: production
type: Opaque
stringData:
  name: prod-cluster
  server: https://prod-cluster.example.com
  config: |
    {
      "bearerToken": "<service-account-token>",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64-encoded-ca-cert>"
      }
    }

ApplicationSets for Multi-Cluster

ApplicationSets enable declarative, template-driven Application generation:

Cluster Generator

Deploy to all clusters matching specific labels:

applicationset-cluster.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: platform-services
  namespace: argocd
spec:
  generators:
    - clusters:
        selector:
          matchLabels:
            environment: production
  template:
    metadata:
      name: '{{name}}-platform-services'
    spec:
      project: platform
      source:
        repoURL: https://github.com/org/platform-services
        targetRevision: HEAD
        path: 'clusters/{{name}}'
      destination:
        server: '{{server}}'
        namespace: platform
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

Git Directory Generator

Generate Applications based on directory structure:

applicationset-git.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: team-applications
  namespace: argocd
spec:
  generators:
    - git:
        repoURL: https://github.com/org/app-configs
        revision: HEAD
        directories:
          - path: 'teams/*/apps/*'
  template:
    metadata:
      name: '{{path.basename}}'
    spec:
      project: '{{path[1]}}'  # team name
      source:
        repoURL: https://github.com/org/app-configs
        targetRevision: HEAD
        path: '{{path}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{path.basename}}'

Image Updater Integration

Automate image updates with ArgoCD Image Updater:

application-with-image-updater.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
  annotations:
    argocd-image-updater.argoproj.io/image-list: myapp=ghcr.io/org/myapp
    argocd-image-updater.argoproj.io/myapp.update-strategy: semver
    argocd-image-updater.argoproj.io/myapp.allow-tags: regexp:^v[0-9]+\.[0-9]+\.[0-9]+$
    argocd-image-updater.argoproj.io/write-back-method: git
spec:
  project: default
  source:
    repoURL: https://github.com/org/app-configs
    targetRevision: HEAD
    path: apps/my-app
  destination:
    server: https://kubernetes.default.svc
    namespace: my-app

RBAC and Project Configuration

Define projects to isolate teams and control access:

appproject.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: team-alpha
  namespace: argocd
spec:
  description: Team Alpha applications
  sourceRepos:
    - 'https://github.com/org/team-alpha-*'
  destinations:
    - namespace: 'team-alpha-*'
      server: '*'
  clusterResourceWhitelist:
    - group: ''
      kind: Namespace
  namespaceResourceWhitelist:
    - group: '*'
      kind: '*'
  roles:
    - name: developer
      policies:
        - p, proj:team-alpha:developer, applications, *, team-alpha/*, allow
      groups:
        - team-alpha-developers

Best Practices

  • Use ApplicationSets over individual Applications - Reduces configuration duplication and enables consistent deployments.
  • Implement progressive delivery - Deploy to dev/staging before production using wave annotations or separate ApplicationSets.
  • Enable automated sync with safeguards - Use selfHeal and prune but configure appropriate sync windows for production.
  • Centralize secrets management - Use external-secrets with AWS Secrets Manager or HashiCorp Vault.
  • Monitor sync status - Set up alerts for failed syncs and degraded applications.

Monitoring and Observability

ArgoCD exposes Prometheus metrics for monitoring:

Key metrics to monitor
# Sync status
argocd_app_info{sync_status="OutOfSync"}

# Health status
argocd_app_info{health_status="Degraded"}

# Sync duration
argocd_app_sync_total

# Controller queue depth
argocd_app_reconcile_bucket

Conclusion

The control plane model for ArgoCD provides a scalable approach to multi-cluster GitOps. By centralizing management while distributing workloads, you gain visibility and control without sacrificing flexibility.

ApplicationSets are the key to managing complexity at scale - they transform cluster configuration from imperative scripts to declarative templates that adapt as your infrastructure grows.

Amar Sattaur

Staff DevOps Engineer with experience architecting multi-cluster ArgoCD deployments for enterprise environments.