Managing Amazon EKS at Fleet Scale
GitOps at Fleet Scale: Hundreds of EKS Clusters Without Losing Control
A deeper, more current companion to the fleet-management series: how to run dozens or hundreds of EKS clusters through GitOps without losing control — Argo CD’s single pane versus Flux’s distributed pull, the GitOps bridge that wires them to your IaC, the scaling ceilings that actually bite, and the December 2025 managed EKS Capability that changes the build-versus-buy math.
The bottom line
There's no universal winner — anyone who says otherwise is selling something. At a few hundred EKS clusters the decision reduces to one axis: a centralized single pane of glass versus distributed autonomy.
Argo CD hub-and-spoke gives you templated fleet rollouts and one dashboard, but it concentrates blast radius in a central control plane and hits UI and reconciliation limits that force you to shard the application controller. Flux's one-controller-per-cluster model is more resilient and the honest answer for edge and air-gapped clusters, but you lose the single pane. Most large fleets converge on a hybrid: Flux for the platform layer on every cluster, one central Argo CD for application releases, wired together by the GitOps bridge. And since December 2025, AWS will run the Argo hub for you as a managed EKS Capability, changing the build-versus-buy math for the control plane.
- The axis: centralized (Argo hub-and-spoke, one dashboard, concentrated risk) vs distributed (Flux per cluster, resilient, no single pane).
- Argo scales, but you work for it: benchmarks reach 10,000 apps / 97 clusters (AWS) and 50,000 apps / 500 clusters (CNOE) — only with controller sharding and QPS tuning. The UI, not the controller, is the softer ceiling.
- Flux trades the dashboard for resilience: each cluster keeps reconciling if the rest of the fleet burns; no central plane that must reach every cluster's API.
- The GitOps bridge lets Terraform hand cluster metadata (IAM roles, endpoints) to Argo via a cluster Secret — without Terraform and GitOps fighting over cluster state.
- Hybrid is where most large fleets land: Flux for infra, Argo for apps, with a hard repo boundary so they never write the same directory.
- New in 2026: AWS's managed EKS Capability for Argo CD runs the hub outside your clusters and handles cross-account/cross-region and private-endpoint reach.
What fleet GitOps gives you
- One source of truth — the repo, not a laptop — with drift caught and self-healed on every cluster.
- One change fans out to N clusters through an ApplicationSet cluster generator keyed off labels.
- A managed path now exists: AWS runs the Argo hub for you as the EKS Capability.
What it won't do for free
- There's no universal winner — centralized single pane and distributed autonomy are a genuine trade.
- Argo reaches tens of thousands of apps only with controller sharding and QPS tuning; the UI drags first.
- A central hub is a real blast radius — size it like production or accept a fleet-wide freeze on outage.
What actually breaks at fleet scale — Three clusters and three hundred are not the same problem
GitOps at three clusters is solved: point one Argo CD or Flux at a repo and move on. "Fleet scale" gets its own playbook because three things stop being free past a few dozen clusters.
The centralized bet — Argo CD hub-and-spoke — one dashboard drives the whole fleet
Hub-and-spoke puts one Argo CD instance — the hub — in charge of many workload clusters, the spokes. The hub holds one Kubernetes Secret per spoke, and Argo's ApplicationSet cluster generator reads those Secrets to produce one Argo Application per matching cluster.1 That's what makes onboarding automatic: drop a labeled Secret in and the controller deploys everything for that cluster, no further edits.
Label selectors are how you carve the fleet into groups
Argo CD has no native "cluster group" object, so you build groups out of labels on the cluster Secret, and an ApplicationSet's cluster generator uses a label selector to hit only matching clusters.1 Label a batch tier: canary and one ApplicationSet deploys just to them — a tiered-rollout primitive, straight from a selector. Need per-cluster overlays? Nest a Git generator (enumerating overlay paths) and the cluster generator inside a Matrix generator, and you get the Cartesian product of overlays × clusters.1
App-of-apps or ApplicationSet — you'll likely use both
Two patterns get conflated. The Argo project steers fleet operators toward the ApplicationSet cluster generator for most bootstrapping, but many teams use both — app-of-apps for the first bootstrap, then ApplicationSets for team self-service on top.2
| Pattern | What it is | Best when |
|---|---|---|
| App-of-apps | An Argo Application whose children are themselves Applications — full manual control | Each app is different (different repo, chart, config) |
| ApplicationSet | A controller that generates Applications from a generator + template | The same app across many clusters |
Wiring the fleet without Terraform fighting you — The GitOps bridge pattern
Here's the problem the hub-and-spoke diagram hides. Cluster add-ons need cloud metadata Terraform owns but Argo CD wants at install time — the IAM role ARN for an IRSA-backed controller, a load balancer's DNS name, the cluster's API endpoint. The tempting fix, running the Helm charts through Terraform's Kubernetes provider, puts Terraform and GitOps in a fight over live cluster state, and you get conflicts.3 The GitOps bridge settles it cleanly: Terraform writes the metadata as labels and annotations on the Argo CD cluster Secret, and stops there.3
AWS's EKS Blueprints reference implementation makes this concrete. Each spoke Secret carries an awsAuthConfig block with the spoke's clusterName and a roleARN the hub assumes to deploy into that spoke — so the hub reaches every spoke by IAM role assumption, with no long-lived credentials copied around.4 ApplicationSets for add-ons and workloads then generate a per-spoke app-of-apps (workloads-${env}) for each registered cluster.4
Where the single control plane starts to hurt — Argo CD's UI and reconcile limits — and how sharding buys headroom
The centralized model has a ceiling, and it's worth knowing exactly where — the honest answer is "further than you'd guess, but not for free."
The controller scales — with sharding and tuning
Two independent benchmarks put real numbers on it. AWS drove a single Argo CD to 10,000 applications across 97 clusters,5 and CNOE pushed to 50,000 applications across 500 clusters on three m5.2xlarge nodes.6 The chart shows what sharding the controller and raising client QPS did to full-sync time.
The tuning lessons from those runs are specific and reusable:
- Sharding is the big lever. Set
ARGOCD_CONTROLLER_REPLICASand pick a--sharding-method:legacy(UID-based, uneven),round-robin(even), orconsistent-hashing(least reshuffling on topology change). The last two are marked experimental.7 - Client QPS/burst mattered most in both benchmarks; CNOE saw a ~52% sync-time cut from QPS tuning alone.56
- The status/operation processor knobs barely moved the needle at scale in AWS's test — raise them, but don't expect them to save you.5
- Sharding algorithm is a real choice: CNOE measured consistent-hashing-with-bounded-loads causing only 15 shard reassignments when going from 10 shards to 9, versus far more churn from the others.6
Worth noting: the official docs set no hard per-instance limit — the guidance is entirely benchmark-driven, with tuning recommendations calibrated "for 1000 applications."7
The UI is the softer ceiling
The controller shards; the web UI doesn't, not as gracefully. It starts to drag past about 1,000 applications per instance, and community reports bear that out: the UI goes sluggish at 1,500+ apps, and one instance with roughly 8,000 apps from ~2,000 ApplicationSets took about 35 seconds just to load the application list.8 The cause is architectural — the server fetches every application, then filters by RBAC, so the cost grows with total app count no matter what you're viewing; server-side pagination is the fix maintainers are working toward.8
When the hub goes down, what goes with it — Central control-plane blast radius
Everything above is the cost of success. The cost of failure is the real argument against centralizing. The hub reaches into every spoke's Kubernetes API to reconcile it — that's the single pane, and what makes the hub a single point of failure holding one very powerful set of credentials with write access to the whole fleet.12 Compromise or wedge it, and the whole fleet's delivery path goes down with it.
That's not a reason to never centralize. Running clusters keep running — a dead hub doesn't delete your workloads. But it freezes all deployment, drift correction, and self-heal across the fleet at once — exactly the shared fate a distributed model refuses to accept.
The distributed bet — Flux — one controller per cluster, no shared fate
Flux flips the topology. In the standalone model each cluster runs its own Flux controllers, pulling its own slice of a fleet repo directly. As Flux maintainer Stefan Prodan puts it, this "minimizes attack surface and blast radius" and lets clusters "function autonomously even during outages."12 There's no central plane holding fleet-wide credentials, and no hub whose death freezes the rest.
The price is exactly what centralization was buying: the single pane. Each cluster is bootstrapped and watched on its own, so fleet-wide sync status comes from aggregated metrics, not one dashboard.12 Flux can run hub-and-spoke too — a central Flux reaching into spoke API servers — but that hands back the single point of failure and networking complexity you distributed to avoid.12
Edge and air-gapped clusters make the choice for you
For edge, IoT, and air-gapped or classified clusters, distributed isn't a preference — it's close to a requirement. Argo's central control plane must reach every managed cluster's Kubernetes API, exactly what a strict air-gap forbids. Flux's per-cluster controller pulls locally, needs no central API server, and travels lighter on resource-constrained nodes.13 AWS's prescriptive guidance points to Flux for "edge computing or IoT scenarios where resources might be constrained."11
How you lay out the repo for a fleet — Structure is the part people underestimate
Both tools live or die by repo structure. The Flux fleet repository splits into three top-level trees.14
The pattern that scales: onboard a new cluster by wiring the Flux Terraform provider into the cluster-provisioning pipeline, so the cluster bootstraps itself against its clusters/<name> path as it's created.12 The Argo equivalent is the GitOps bridge — the cluster registers by having a labeled Secret, and the ApplicationSet cluster generator takes it from there.
Shipping safely across the fleet — Progressive delivery and drift correction
Drift detection and self-heal — the everyday guarantee
Both tools continuously reconcile Git against live state. In Argo CD, automated sync with prune: true and selfHeal: true reverts manual changes back to Git (retried after a 5-second self-heal timeout) and prunes anything you deleted from Git.15 That's the real GitOps guarantee at fleet scale — not "we deployed it once" but "the cluster is continuously dragged back to the repo," on every one of the hundreds of clusters, with nobody watching.
Progressive delivery — Argo Rollouts vs Flagger
Neither Argo CD nor Flux does canary analysis itself; each pairs with a progressive-delivery controller, and the choice usually follows the ecosystem you already picked.
| Dimension | Argo Rollouts | Flagger |
|---|---|---|
| Manifest model | Replaces Deployment with a Rollout custom resource | Keeps standard Deployment; zero manifest changes |
| Control style | Explicit, ordered steps with manual approval gates | Declarative analysis spec; auto-progresses by step weight |
| Ecosystem fit | Argo CD (health checks + UI extension built in) | Flux ecosystem |
| Strategies | Both: canary, blue-green, A/B | |
The practical read: if your fleet runs Argo CD, reach for Argo Rollouts and get the integrated UI; if it runs Flux, Flagger's zero-touch, metric-driven promotion is the natural fit.16
The answer most large fleets reach — The hybrid — Flux for infra, Argo for apps
Once you've felt both sides, the hybrid stops looking like a compromise and starts looking like the point: Flux runs inside every cluster for the platform layer — resilient, distributed, no shared fate for the infrastructure everything else leans on — while one central Argo CD owns application releases, giving developers the dashboard and app-centric view they want.17 AWS's prescriptive guidance maps onto the split: Argo CD for visual, app-centric, multi-cluster management with enterprise RBAC and SSO; Flux for lightweight, strongly multi-tenant, IaC-driven platform management.11
What AWS just changed — The managed EKS Capability for Argo CD (December 2025)
The build-versus-buy math for the Argo hub shifted in late 2025. AWS launched the Amazon EKS Capability for Argo CD: a fully managed Argo CD running in AWS-managed service accounts outside your clusters, with AWS handling scaling, upgrades, inter-cluster communication, and token refresh.18 It takes over exactly the hardest parts of self-managed hub-and-spoke:
- Cross-account and cross-region reach via EKS Access Entries — without VPC peering — including clusters with private API endpoints.18
- Identity through IAM Identity Center instead of hand-rolled OIDC.18
- Native ECR and Secrets Manager integration, including automatic ECR authentication without the token-refresh workarounds self-managed hubs need.18
It's still Argo CD — ApplicationSets, the hub-and-spoke topology, the single pane — so everything above about UI limits and blast radius still applies conceptually. What changes is you no longer operate, scale, or patch the hub yourself. If you're standing up fleet GitOps on EKS in 2026, this is the first option to price out before you self-host.
Choose this when — Decision thresholds, not vibes
| If your situation is… | Lean toward |
|---|---|
| You want one dashboard, app-centric workflows, and developer self-service across the fleet | Argo CD hub-and-spoke |
| You're on EKS and want to skip operating the hub entirely | Managed EKS Capability for Argo CD |
| Clusters are at the edge, air-gapped, resource-constrained, or must survive independently | Flux, one controller per cluster |
| Blast radius / no-shared-fate is your top constraint | Flux distributed (or Flux hybrid) |
| You have strong multi-tenancy and IaC-heavy platform needs plus app teams who want a UI | Hybrid: Flux infra + Argo apps |
| A single Argo instance is creeping past ~1,000–2,000 apps and the UI is dragging | Shard the controller and/or split into multiple instances |
Common pitfalls — The failures that actually bite fleets
- Treating the Argo UI ceiling as the controller ceiling. The controller shards to tens of thousands of apps; the UI degrades around 1,000. Plan instance-splitting around the UI, not the controller.8
- Running Terraform's Helm/Kubernetes providers against a GitOps-managed cluster. It causes state conflicts — that's the exact problem the GitOps bridge exists to avoid.3
- Letting a central Argo hub become an un-budgeted single point of failure. If a hub outage freezing all fleet deployment is unacceptable, you wanted the distributed model.12
- Hybrid without a repo ownership boundary. Two controllers writing the same resource is an outage you built yourself.17
- Assuming a central control plane can reach air-gapped clusters. It can't; that's a Flux job.13
Sources
- Argo CD docs — ApplicationSet Cluster Generator (label selectors, cluster Secrets, Matrix generator)
- Argo CD Discussion #11892 — Bootstrapping: ApplicationSets vs App-of-apps; Argo CD docs — Cluster Bootstrapping
- gitops-bridge-dev/gitops-bridge — the GitOps bridge pattern (Terraform metadata into the cluster Secret)
- AWS EKS Blueprints — Multi-Cluster Hub & Spoke Argo CD (awsAuthConfig, roleARN, per-spoke ApplicationSets)
- AWS Open Source Blog — Argo CD Application Controller Scalability Testing on Amazon EKS (10k apps / 97 clusters; sharding; QPS), Sep 13 2023
- CNOE — Argo CD Benchmarking: 50k apps / 500 clusters, sharding algorithms compared, Nov 21 2023
- Argo CD docs — High Availability (sharding methods, controller replicas, processor/QPS tuning; no hard per-instance limit)
- Argo CD Discussion #8446 — UI slow with 1.5k+ applications (fetch-all-then-RBAC-filter root cause; pagination)
- OneUptime — Argo CD single vs multiple instances (practitioner rule of thumb: ~1,000–2,000 apps/instance) — practitioner estimate
- Akuity — Argo CD scalability (1,000 clusters / 50,000 apps) — vendor claim
- AWS Prescriptive Guidance — Argo CD and Flux use cases (feature comparison, when to choose each)
- Stefan Prodan (Flux maintainer) — FluxCD Multi-Cluster Architecture (standalone vs hub-spoke, blast radius, fleet repo, Terraform provider onboarding), May 22 2024
- OneUptime — Flux CD vs Argo CD for air-gapped environments (central plane must reach cluster APIs) — practitioner, architecturally corroborated
- Flux docs — Ways of structuring your repositories; fluxcd/flux2-multi-tenancy — fleet repo layout (clusters / infrastructure / tenants)
- Argo CD docs — Automated Sync Policy (prune, selfHeal, self-heal timeout)
- Flagger vs Argo Rollouts comparison; Buoyant — Flagger vs Argo Rollouts — practitioner, triangulated
- Pelotech — Argo CD vs Flux (hybrid: Flux for infra + central Argo for apps; repo ownership boundary)
- AWS Containers Blog — Deep dive: streamlining GitOps with the Amazon EKS Capability for Argo CD (managed hub, cross-account/region, private endpoints), Dec 18 2025