TL; DR: here are the steps to deploy to multiple Kubernetes clusters using a single ArgoCD server + Application Sets. Let’s get to it.
Add a Kubernetes Cluster to ArgoCD
First, we’ll use the argocd
CLI. Just in case you don’t have it yet, it’s easy to install. Assuming kubectl
is already configured and has admin access to more than 1 Kubernetes clusters.
# login to argocd # mine is sso-enabled. this can be done using username and password too argocd login argocd.my-domain.name --sso # list context names of all kubernetes clusters kubectl config get-contexts -o name # add a cluster by its context name, ie. pick one from previous step # this will create service account, etc. in the target cluster # and save the token of the service account for ArgoCD to authenticate with argocd cluster add --grpc-web my_kubernetes_cluster_context_name # verify via the list command argocd cluster list --grpc-web # for the sake of simplicity let's rename the cluster argocd cluster set my_kubernetes_cluster_context_name --grpc-web --name beta
Check the ArgoCD Project
Usually apps in the default project can be deployed to any cluster – in ArgoCD’s term, destination. If it’s a new project, we’d make sure it has the cluster as one of its destinations.

Use Application Set to Deploy
With Application Set, an Application can be deployed to multiple clusters using a template like this:
# application-set.yaml # this will create 3 apps one in each cluster apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: my-multi-cluster-app namespace: argocd spec: generators: - list: elements: - cluster: alpha # this is where the argocd resides too, so in-cluster it is destination_cluster_name: in-cluster - cluster: beta destination_cluster_name: beta - cluster: theta destination_cluster_name: theta goTemplate: true goTemplateOptions: - missingkey=error ignoreApplicationDifferences: - jsonPointers: - /spec/syncPolicy - /spec/source/targetRevision template: metadata: finalizers: - resources-finalizer.argocd.argoproj.io labels: app.kubernetes.io/instance: my-multi-cluster-app cluster: '{{.cluster}}' name: my-multi-cluster-app name: my-multi-cluster-app-{{.cluster}} spec: destination: name: '{{ .destination_cluster_name }}' namespace: my-app-namespace project: default path: . repoURL: git@github.com:my-org/my-gitops.git syncPolicy: automated: prune: true selfHeal: true syncOptions: - ApplyOutOfSyncOnly=true
🙂