Context
EKS clusters serving 50+ microservices across development and production, scaled by Cluster Autoscaler on On-Demand instances.
The problem
Cluster Autoscaler scales node groups, so capacity arrives in the shapes you defined in advance rather than the shapes the pending pods actually need. That mismatch shows up as paid-for headroom. The obvious saving, Spot instances, carries an obvious risk, and applying it uniformly would trade cost for reliability on services that cannot absorb an interruption.
- step: Pending podsreal requirements
- step: Karpenterprovisions to fit
- control: Interruption toleranceper workload
- result: Spoteligible non-prod
- result: On-Demandcritical services
Approach
- 01
Replace Cluster Autoscaler with Karpenter
Karpenter provisions nodes against the actual requirements of pending pods rather than scaling predefined groups, which removes most of the shape mismatch.
- 02
Separate workloads by interruption tolerance
The saving comes from knowing which workloads can be interrupted. Eligible non-production workloads moved to Spot; critical services stayed on On-Demand deliberately.
- 03
Assume the capacity disappears
Spot was treated as capacity that will be taken away, not as cheaper On-Demand. The workloads moved onto it were horizontally scalable and replaceable, so Kubernetes can reschedule and Karpenter can bring up replacement capacity as availability shifts. Anything that could not absorb an interruption stayed on capacity suited to it, rather than being pushed onto Spot to make the savings number larger.
- 04
Expand only after the behaviour is validated
Rolled out incrementally, checking workload behaviour and cost impact before widening. A production Kubernetes fleet is not a single experiment, and the blast radius of getting capacity policy wrong is every service on the cluster.
- 05
Keep the split explicit
Capacity type is a property of the workload, not a global cluster setting, so the reliability trade is made per service and stays visible.