Configure Multi-Cluster with Flux
Manage several clusters from one repository, with shared infrastructure and per-cluster differences.
Flux scales to many clusters by running one set of controllers in each cluster, all following the same Git repository at different paths. There is no central hub to register clusters with. This guide shows how to lay out a single repository for staging and production, bootstrap each cluster, order infrastructure before applications, and when to use a remote-cluster setup instead.
One repository, one path per cluster
Flux follows a simple rule: every cluster is bootstrapped against its own folder under clusters/. A repository serving two clusters looks like this:
fleet-infra/
├── clusters/
│ ├── staging/
│ │ ├── flux-system/ # created by bootstrap
│ │ ├── infrastructure.yaml
│ │ └── apps.yaml
│ └── production/
│ ├── flux-system/
│ ├── infrastructure.yaml
│ └── apps.yaml
├── infrastructure/
│ ├── base/ # shared: ingress, cert-manager, monitoring
│ ├── staging/
│ └── production/
└── apps/
├── base/
├── staging/
└── production/
Shared definitions live in base/ folders, and each environment folder holds the Kustomize overlay for what differs (see the overlays guide).
Bootstrap each cluster
Switch your kubectl context to each cluster in turn and bootstrap against the same repository with a different path:
kubectl config use-context staging
flux bootstrap github --owner=<user> --repository=fleet-infra \
--branch=main --path=clusters/staging --personal
kubectl config use-context production
flux bootstrap github --owner=<user> --repository=fleet-infra \
--branch=main --path=clusters/production --personal
Each cluster now has its own Flux installation and its own flux-system folder in Git. Adding a third cluster later is one more bootstrap command with a new path.
Point each cluster at its own overlays
clusters/production/apps.yaml applies the production overlay:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps
namespace: flux-system
spec:
interval: 10m
dependsOn:
- name: infrastructure
sourceRef:
kind: GitRepository
name: flux-system
path: ./apps/production
prune: true
wait: true
clusters/staging/apps.yaml is identical except for path: ./apps/staging. The infrastructure Kustomization points at ./infrastructure/<env> in the same way, and has wait: true so applications only start once the ingress controller, certificate manager, and similar components are ready. The dependsOn field is what enforces that order.
Verify across clusters
Flux has no central dashboard, so check each cluster from its own context:
flux get kustomizations --context staging
flux get kustomizations --context production
Both should show Ready. Compare what Git says is deployed with what each cluster reports using flux tree and flux get all -A. For fleet-wide visibility, teams often collect Flux’s Prometheus metrics into Grafana.
Promote from staging to production
Because both clusters read the same repository, promotion is a commit. A common flow is:
- Change
apps/stagingand let Flux apply it to the staging cluster. - Test and verify.
- Make the same change in
apps/productionin a reviewed pull request, or tag a release that the productionGitRepositorytracks (see the overlays guide).
Alternative: one control cluster, many remote clusters
Instead of running Flux in every cluster, you can run it in one place and have its Kustomizations and HelmReleases apply to other clusters. Set spec.kubeConfig on the resource to a Secret that holds the remote cluster’s kubeconfig:
spec:
kubeConfig:
secretRef:
name: production-kubeconfig
This centralizes control, but it also puts credentials for every cluster in the control cluster. That differs from the usual Flux model, where credentials never leave each cluster and a compromised cluster can’t reach the others. Prefer a Flux installation per cluster unless you have a clear reason to centralize, such as lightweight edge clusters. If you do go this way, use cloud workload identity instead of long-lived kubeconfigs where your platform supports it, and look at the Flux Operator for managing fleets at scale.
Good habits
- Keep each cluster’s
flux-systemfolder out of shared overlays. Bootstrap owns it. - Use
dependsOnso infrastructure, CRDs, and controllers install before the apps that need them. - Give each cluster its own SOPS key (see the secrets guide) so staging can’t decrypt production secrets.
- Upgrade Flux one cluster at a time, starting with a non-production cluster, by re-running
flux bootstrapwith a newer CLI.
Popular Guides
-
Push vs Pull: How Flux Delivers to Kubernetes Why pull-based, Git-driven delivery changes how you deploy, secure, and recover clusters. -
Deploy Your First Application with a GitRepository and Kustomization Point Flux at manifests in Git using a Kustomization resource and watch it sync. -
Control Sync Behavior: Intervals, Prune, Drift Correction, and Rollback Decide when Flux applies changes, what it deletes, how to pause it, and how to undo a bad deploy. -
Automate Image Updates with Flux Image Automation Let Flux detect new container image tags and commit them back to Git. -
Flux CD vs Argo CD: Choosing a GitOps Tool Compare architecture, UI, Helm, secrets, tenancy, and image automation to pick the right tool.