Consolidating underused Kubernetes clusters to cut fixed cost
Every cluster carries a fixed overhead before a single pod runs: control plane, system nodes, load balancers, and monitoring agents. Running eight clusters at 15 percent utilisation is expensive in a specific, measurable way.
Quick answer
Count the fixed cost per cluster first: a managed control plane is about $73 a month on the major clouds, plus 2 to 3 system nodes at roughly $70 to $140 each, plus an ingress load balancer at about $16 to $25, plus monitoring agents per node. That is commonly $400 to $900 a month before a single application pod runs. Eight clusters at 15 percent utilisation consolidated into three at 50 percent removes five times that overhead plus the stranded node capacity. Use namespaces with resource quotas and network policies for isolation, and keep separate clusters only where compliance, blast radius, or version skew genuinely require it.
Cluster sprawl happens for good reasons. A team wants isolation, an environment needs a different Kubernetes version, a compliance boundary requires separation, or spinning up a cluster is simply easier than negotiating for a namespace. The cost is invisible in the same way: no single cluster is expensive, but the fixed overhead multiplied across a dozen of them is substantial.
What a cluster costs before it does anything
| Component | Typical monthly cost |
|---|---|
| Managed control plane | ~$73 |
| System node pool (2 to 3 nodes) | $140 to $420 |
| Ingress load balancer | $16 to $25 |
| NAT gateway for private nodes | ~$33 base |
| Monitoring and logging agents | $50 to $200 |
| Fixed total | $310 to $750 |
Twelve clusters at an average $500 of fixed overhead is $6,000 a month before any workload. But the fixed cost is only half the problem. The larger half is stranded capacity: a cluster running at 15 percent node utilisation wastes 85 percent of every node it runs, and small clusters cannot bin pack efficiently because there are not enough workloads to fill the gaps. The idle mechanics are in Kubernetes idle cost explained.
Step 1: inventory with utilisation, not just count
For every cluster, record node count and type, total requested CPU and memory against total allocatable, actual used CPU and memory, the reason the cluster exists separately, and its Kubernetes version. The request versus allocatable ratio tells you how full the scheduler thinks it is; the used versus requested ratio tells you how much of that is real.
Two patterns emerge. Clusters under 30 percent requested capacity are consolidation candidates. Clusters where requested is high but used is low have an over-requesting problem instead, which is a right-sizing exercise covered in right-sizing Kubernetes pods, and consolidating them without fixing requests just moves the waste.
Step 2: decide which separations are real
Some cluster boundaries must stay. Regulated workloads with an audited isolation requirement. Production versus non-production, where a shared control plane means a non-production mistake can affect production. Radically different Kubernetes versions during a migration. Genuinely different blast radius requirements, such as a critical payment path.
Most other boundaries are habit. Per team clusters, per application clusters, and per environment clusters within non-production are usually namespace boundaries wearing a cluster costume. Namespaces with resource quotas, limit ranges, network policies, and RBAC provide strong isolation for anything short of a compliance boundary.
Step 3: consolidate in the safe direction
Merge non-production first, and merge the smallest clusters into a larger one rather than creating a new target cluster, which would add a thirteenth cluster to the estate mid migration. For each workload moved, create the namespace with a resource quota sized to its current requests, apply network policies before moving traffic, migrate during a low traffic window, and verify for a week before decommissioning the source cluster.
Decommissioning is where the saving lands, and it is the step most often left incomplete. A cluster with no workloads still bills its control plane, system nodes, load balancers, and NAT gateway. The migration is not finished until the source cluster is deleted.
Step 4: make the consolidated cluster efficient
Consolidation only pays if the target cluster bin packs well. Three things make that happen. Multiple node pools sized differently so small and large workloads land appropriately. An autoscaler that provisions node shapes matched to pending pods rather than adding uniform nodes, which is the core advantage described in Karpenter versus cluster autoscaler. And accurate resource requests, because the scheduler packs against requests, so a cluster full of pods requesting four times what they use will be half empty and still refuse new pods.
The numbers
Take eight non-production clusters averaging $500 fixed overhead and 20 nodes each at 15 percent utilisation. Fixed cost is $4,000 a month; 160 nodes at an average $100 each is $16,000; total $20,000. Consolidated into two clusters at 55 percent utilisation, the same workload needs roughly 45 nodes. That is $1,000 fixed plus $4,500 of nodes, about $5,500 a month, a saving of roughly $14,500. Even allowing for headroom and a less optimistic packing ratio, halving the bill is a realistic target.
The risks to plan for
Blast radius grows: an incident in a consolidated cluster affects more teams, so pod disruption budgets, priority classes, and quotas become load bearing rather than nice to have. Noisy neighbours become possible without limit ranges. Cost attribution gets harder once teams share a cluster, which is solved with namespace level cost allocation as described in Kubernetes cost per namespace. And cluster upgrades affect everyone at once, so the upgrade process needs to be better than it was when each team could upgrade independently. Price the consolidated topology from Terraform against the resource catalog before committing to the plan.
FAQ
What does an empty Kubernetes cluster cost?
Typically $310 to $750 a month before any application pod runs: about $73 for a managed control plane, $140 to $420 for 2 to 3 system nodes, $16 to $25 for an ingress load balancer, about $33 base for a NAT gateway if nodes are private, and $50 to $200 for monitoring and logging agents. Twelve clusters at an average $500 of overhead is $6,000 a month of pure fixed cost.
Why do small clusters waste more than large ones?
Because they cannot bin pack efficiently. A small cluster has too few workloads to fill the gaps between node capacity and pod requests, so it runs at low utilisation structurally, not through neglect. A cluster at 15 percent node utilisation wastes 85 percent of every node it runs, and that stranded capacity usually exceeds the fixed control plane overhead.
Which cluster separations are worth keeping?
Regulated workloads with an audited isolation requirement, production versus non-production so a non-production mistake cannot affect production, radically different Kubernetes versions during a migration, and genuinely different blast radius requirements such as a critical payment path. Per team, per application, and per non-production environment clusters are usually namespace boundaries wearing a cluster costume.
How much does cluster consolidation save?
Eight non-production clusters averaging $500 of fixed overhead and 20 nodes each at 15 percent utilisation cost about $20,000 a month. Consolidated into two clusters at 55 percent utilisation the same workload needs roughly 45 nodes, about $5,500 a month, a saving near $14,500. Even with conservative packing assumptions, halving the bill is a realistic target.
What is the most commonly missed step in consolidation?
Decommissioning the source cluster. A cluster with no workloads still bills its control plane, system nodes, load balancers, and NAT gateway, so the saving does not land until it is deleted. Migrations frequently stall with workloads moved and old clusters left running just in case, which means paying for both topologies at once.
What are the risks of consolidating clusters?
Blast radius grows, so pod disruption budgets, priority classes, and quotas become load bearing rather than optional. Noisy neighbours become possible without limit ranges. Cost attribution gets harder once teams share a cluster, which namespace level allocation solves. And upgrades affect everyone at once, so the upgrade process must be better than when each team upgraded independently.
What to do next
Model the consolidated topology before you commit. C3X prices Kubernetes infrastructure from Terraform against a live resource catalog. Start with the quickstart.
Share this post
Try C3X on your own Terraform
Free and open source. No API key required. One command to install, one command to estimate.