Infrastructure

From Pet Clusters to a Fleet: Multi-Cluster Kubernetes Without Snowflakes

TuniCyberLabs Team
7 min read

Turning a collection of snowflake Kubernetes clusters into a declaratively managed fleet: lifecycle as code, layered config, and upgrade waves.

The second Kubernetes cluster is always justified: production needed isolation from staging, or a new region demanded local presence. By the tenth, most organizations discover they are running a collection of pets — each cluster with its own version, add-on stack, and undocumented quirks that one engineer remembers. Fleet management is the discipline of turning that collection into cattle: clusters that are provisioned, configured, upgraded, and destroyed through one declarative pipeline.

This is not a scale problem reserved for hyperscalers. Data residency obligations under GDPR, sector regulation like NIS2, blast-radius isolation for regulated workloads, per-customer tenancy, and edge deployments all push cluster counts upward long before headcount does. The question is not whether you will run many clusters, but whether they will drift apart.

Cluster Lifecycle as Code

The foundational rule is that no cluster is ever created or modified by hand. Managed control planes — EKS, AKS, GKE — driven by Terraform or OpenTofu modules get most teams there; Cluster API goes further by making clusters themselves Kubernetes resources, reconciled by a management cluster exactly the way a Deployment reconciles pods. The specific tool matters less than the properties you enforce: every cluster is instantiated from a versioned definition, carries no state that cannot be regenerated, and can be rebuilt from Git in under a day. That rebuild time is your honest disaster recovery metric — and the real test of whether you own a fleet or a herd of pets with config files.

Give every cluster a small structured identity — environment, region, tier, compliance scope — expressed as labels in a registry. Argo CD cluster secrets or a Fleet inventory both work. Every downstream decision, from which add-ons deploy to which upgrade wave applies, should key off those labels rather than off a cluster's name.

Configuration Flows Down in Layers

Fleet configuration fails in two symmetrical ways: full duplication per cluster, which guarantees drift, and one shared blob, which guarantees that a bad change hits everything at once. The workable pattern sits between them:

  • Fleet-wide baseline: CNI, ingress controller, cert-manager, observability agents, and admission policies, versioned once and rolled out progressively.
  • Class overlays: the differences between production and non-production, or between EU and non-EU clusters, expressed as overlays selected by cluster labels.
  • Per-cluster leaf config: kept deliberately tiny — endpoints, sizing, DNS names. When a leaf file starts growing, a class is missing from the layer above.

Argo CD ApplicationSets with the cluster generator, Flux with per-cluster Kustomizations, and Rancher Fleet all implement this shape. Enforce the invariants with policy rather than review: Kyverno or Gatekeeper rules shipped inside the baseline layer mean every new cluster is compliant on first boot instead of after its first audit.

Upgrades Are the Recurring Tax

Kubernetes ships three releases a year and supports roughly one year of patches, so a fleet is permanently mid-upgrade — the work never finishes, it only gets cheaper. API removals punish procrastination; the ingress and PodSecurityPolicy migrations taught everyone that lesson. A wave-based process keeps the tax predictable:

1. Track version skew centrally and hold a hard rule: no cluster runs more than one minor version behind the fleet target. 2. Read the deprecation and removal notes before planning, and scan live manifests for removed APIs with tools like kubent or Pluto. 3. Upgrade a designated canary cluster first and run conformance tests plus representative workload smoke tests against it. 4. Roll remaining clusters in waves ordered by blast radius — development, internal production, customer-facing — with explicit bake time between waves. 5. Rotate node pools with surge capacity, and verify PodDisruptionBudgets exist before the wave starts, not while it is draining nodes.

A fleet run this way changes the economics of everything downstream. Opening a new market becomes stamping out a cluster from an existing class rather than a quarter-long infrastructure project; an auditor asking about the EU environment gets a Git diff instead of a meeting series; and losing a cluster to a bad upgrade or a regional outage becomes a rebuild procedure instead of an existential event. The organizations that treat cluster count as a routine scaling dimension — not a crisis — are the ones that stopped treating any single cluster as special.

TAGS
KubernetesMulti-ClusterCluster APIFleet ManagementInfrastructure as Code

Need help with
this topic
?

Our team specializes in the technologies and strategies discussed in this article. Let's talk about how we can help your business.

Get in Touch