Kubernetes Cost Optimization with Karpenter and Spot Instances: A 2026 Guide
I was staring at a $180,000 monthly AWS bill for a cluster running a batch inference pipeline. The workload was bursty, mostly stateless, and the nodes were almost all on-demand, sitting half-empty during off-peak hours. I knew we were wasting money. But every attempt at savings — reserved instances, custom scripts to manage spot, even the Cluster Autoscaler — left us either overpaying or getting interrupted.
Then we switched to Karpenter with spot instances.
Within two months, that bill dropped to $85,000. Interruptions? Less than 3% of pods got preempted, and because Karpenter spreads workloads across spot instance types and zones, even those went almost unnoticed.
This isn't a fairy tale. It's what happens when you combine the right autoscaler with the right pricing model. But kubernetes cost optimization karpenter spot instances isn't just a magic incantation — you need to set it up right, monitor it, and avoid the common mistakes that turn cheap compute into expensive chaos.
In this guide, I'll walk you through what I've learned building data infrastructure at SIVARO. We'll cover how Karpenter differs from the Cluster Autoscaler, how to configure spot instances so they don't wreck your reliability, which monitoring tools actually help, and the rightsizing strategies that make spot savings stick.
Let's cut the waste.
Why Your Kubernetes Bill Is Still Too High (and Karpenter Isn't a Silver Bullet)
Most teams think the problem is simple: "We're paying for compute we don't use." So they try to pack pods tighter, maybe squeeze the CPU requests, and hope the cloud provider stops charging. That's like trying to lose weight by loosening your belt.
The real waste comes from three places:
1. Over-provisioned node pools. You carve out fixed instance families (say, m5.large) and never change them. When your pods need more memory, you add more nodes — same family, same hour rate. Econ 101: buying only the most expensive item on the menu.
2. Ignoring interruptible capacity. Spot instances are 60-90% cheaper than on-demand in AWS, Azure, and GCP. Yet many teams avoid them because the Cluster Autoscaler doesn't handle interruptions well. It just waits for a new node to spin up — no intelligence about which instance types are least likely to be reclaimed.
3. Static scaling. The Cluster Autoscaler looks at pending pods and picks the cheapest node from a predefined list. It doesn't consider bin-packing efficiency, spot instance diversity, or drift in workload demands. It's a blunt instrument.
Karpenter fixes #1 and #3 directly. For #2, it makes spot instances usable at scale — but only if you configure it right. I'll show you how.
Karpenter vs. Cluster Autoscaler: The 2026 Verdict
I'm going to be blunt: if you're starting a new Kubernetes cluster today, or if you're migrating to Kubernetes in 2026, don't use the Cluster Autoscaler. It's not that it's broken — it's that Karpenter solves the same problem better, faster, and cheaper.
Let me give you a concrete comparison from a deployment we did at SIVARO in early 2025. We had a cluster with 1,200 pods running a mix of streaming and batch workloads. The Cluster Autoscaler (CA) managed 12 node groups across 3 instance families. Karpenter took over with a single NodePool and a NodeClass pointing to 20+ instance types, sizes, and zones.
- Time to scale from 500 to 1,000 pods: CA: 8 minutes (waiting for ASG to spin up new EC2 instances). Karpenter: 90 seconds (launching instances directly via EC2 fleet).
- Cost per pod per month: CA: $0.38. Karpenter: $0.21.
- Interruption rate with spot: CA: 8% of pods terminated monthly. Karpenter (with
consolidationandttlSecondsAfterEmptyoptimized): 2.1%.
Why the difference? Karpenter doesn't rely on node groups. It makes provisioning decisions per-node, instantly, using a scoring algorithm that considers:
- Bin packing — how efficiently pods fill the node's resources.
- Cost — prefers cheaper instance types (including spot) with lower interruption rates.
- Availability — spreads across zones to avoid correlated failures.
The Cluster Autoscaler is tied to Auto Scaling Groups and launch templates. You define a fixed set of instance types. Karpenter says, "Here's a list of types I can use — decide at runtime."
If you want a deeper head-to-head, Cast AI's comparison from last year is still accurate. But the key takeaway is: Karpenter is better for cost, speed, and flexibility — especially when you add spot instances.
How Karpenter Makes Spot Instances Actually Work
Most people think: "Spot instances get killed, so my pods get interrupted. That's bad."
They're not wrong. But they're not seeing the full picture. Spot interruptions happen, but Karpenter handles them smarter than any other autoscaler.
The trick isn't to avoid interruptions — it's to make them invisible to your workloads.
Karpenter does this three ways:
1. Instance diversity. When you define a NodePool, you can list dozens of instance types (e.g., c5.large, c6i.large, m5.large, m6a.xlarge, r6g.medium, etc.). Karpenter picks the cheapest currently available spot instance across all of them. If one type gets reclaimed, Karpenter just uses another. The probability of all types being reclaimed simultaneously is close to zero.
2. Preemption awareness. Karpenter watches EC2's instance rebalance recommendations. Before a node is terminated, it drains the pods gracefully. It also sets up terminationGracePeriodSeconds to give your app time to checkpoint or restart.
3. Consolidation + spot. Karpenter's consolidationPolicy: "WhenUnderutilized" feature moves pods from expensive nodes (including spot nodes that no longer have cheap spot pricing) to cheaper ones. This means if a spot instance's market price spikes, Karpenter will eventually migrate the pods to a different spot type — or even to an on-demand node if spot is too volatile. It's self-healing cost optimization.
I've seen teams run 80% spot in production with >99.9% uptime using this setup. My record at SIVARO: a 3-month stretch with zero spot-related pod terminations. Because Karpenter kept rotating instance types before AWS could reclaim them.
Configuring Karpenter for Spot: A Practical Example
Here's a Karpenter NodePool configuration we use at SIVARO for a general-purpose workload that can tolerate spot interruptions. This is for AWS (EKS). GCP and Azure have similar concepts.
yaml
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: spot-general
spec:
template:
spec:
requirements:
- key: "karpenter.sh/capacity-type"
operator: In
values: ["spot", "on-demand"] # Allow both, but spot preferred
- key: "node.kubernetes.io/instance-type"
operator: In
values:
- "c5.large"
- "c5a.large"
- "c6i.large"
- "c6a.large"
- "m5.large"
- "m5a.large"
- "m6i.large"
- "m6a.large"
- "r5.large"
- "r6i.large"
- "t3.large" # Burstable for low-CPU workloads
- key: "topology.kubernetes.io/zone"
operator: In
values:
- "us-east-1a"
- "us-east-1b"
- "us-east-1c"
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
disruption:
consolidationPolicy: WhenUnderutilized
expireAfter: 720h # 30 days, force refresh
budgets:
- nodes: "10%" # Don't disrupt more than 10% at once
And the corresponding EC2NodeClass:
yaml
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: default
spec:
amiFamily: Bottlerocket
role: "KarpenterNodeRole-eks-cluster"
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "my-cluster"
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "my-cluster"
tags:
Name: Karpenter-spot
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 50Gi
volumeType: gp3
# Optional: limit spot interruption rate
# karpenter.k8s.aws/spot-interruption-threshold: 5%
Notice a few decisions:
- Allowed spot and on-demand in same pool. Karpenter will always try spot first, but if no spot is available or too risky, it falls back to on-demand. This keeps your pods running.
- Instance diversity is key. I've listed 11 instance types. You want at least 10-15 to maximize spot availability.
- Consolidation policy
WhenUnderutilizedmeans Karpenter will automatically replace expensive nodes with cheaper ones, including moving from on-demand to spot if spot becomes available later. - Bottlerocket AMI for security and minimal footprint. You could use AL2 or Ubuntu, but Bottlerocket is optimized for container workloads and reduces node startup time.
For a workload that must not be interrupted (e.g., a stateful database), you'd use a different NodePool with capacity-type: on-demand only. But that's a small fraction of your cluster.
The Cost Monitoring Stack You Need Alongside Karpenter
Karpenter cuts costs, but you can't manage what you can't see. You need kubernetes cost monitoring tools karpenter integrated with your cluster to track spot savings, node utilization, and waste.
I've tried most tools on the market. Here's my honest take after running them side by side for six months:
-
Kubecost — Great for chargeback and allocation. Shows cost per namespace, deployment, label. But its savings recommendations are generic. It doesn't understand Karpenter's dynamic pricing. Use it for visibility, not optimization.
-
Cast AI — Actually Karpenter-aware. It shows you how much each karpenter-provisioned node costs, including spot vs on-demand split. Their cost optimization engine can even adjust Karpenter instance lists. But it's a SaaS with per-node pricing; for large clusters it gets expensive.
-
ScaleOps — Good for real-time rightsizing and spot management. It integrates with Karpenter's drift detection. I used it on a 500-node cluster and it saved ~15% on top of Karpenter's baseline.
-
StormForge — Focuses on ML-driven rightsizing. It adjusts pod resource requests based on historical usage. That's orthogonal to Karpenter, but both together reduce waste. StormForge works better when you have stable, predictable workloads.
-
KRR / VPA — Free but manual. KRR (Kubernetes Resource Recommender) gives suggestions; you have to implement them. The Vertical Pod Autoscaler can adjust requests automatically but can cause restarts.
For a detailed comparison, check this 2026 roundup of kubernetes cost monitoring tools comparison. My quick recommendation: start with Kubecost free tier for visibility, then add Cast AI or ScaleOps for action.
But here's the thing — all these tools miss one metric: spot interruption rate per instance type. Karpenter exposes metrics via Prometheus (karpenter_nodes_terminated, karpenter_spot_interruption_count). You should create a dashboard showing which spot types are getting reclaimed most often, then prune them from your NodePool. We used Grafana with this query:
promql
sum by (instance_type) (
rate(karpenter_nodes_terminated{reason="spot-interruption"}[24h])
)
If c5a.large shows 10x more interruptions than c6i.large, remove it from the instance list. That simple move dropped our interruption rate by 40%.
Rightsizing + Karpenter: The Real Combo
Here's the dirty secret: Karpenter optimizes node selection, but pod resource requests still matter. If you request 4 CPUs and 16GB for a container that uses 0.5 CPU and 2GB, Karpenter will happily provision a big node and waste 87% of its capacity. Karpenter can't fix bad requests.
You need to rightsize your containers. Use the Horizontal Pod Autoscaler (HPA) for scale, and the Vertical Pod Autoscaler (VPA) or a tool like KRR to adjust requests.
But careful: VPA and Karpenter can conflict. VPA changes pod requests, which may cause Karpenter to re-bind pods to different nodes. The official recommendation is to use VPA in "Off" mode (only recommend, not apply) for pods that Karpenter manages. Or use the vpa mutating webhook with updateMode: Auto only for stateless deployments where restarts are acceptable.
At SIVARO, we use a custom rightsizing pipeline. Twice a month, we export pod resource usage from Prometheus, run KRR, and generate a YAML patch for deployments. Then we deploy the patches during a maintenance window. It takes 2 hours of engineering time and saves ~$8,000/month on a 300-node cluster.
If you want automation, LeanOps's 2026 guide has a good workflow combining VPA with Karpenter's node drift.
Common Pitfalls and How to Avoid Them
I've made every mistake in the book. Here's a few so you don't have to.
Pitfall 1: Too few instance types in the NodePool. If you only list 3, you lose spot diversity. AWS may reclaim all three types at once. Then your cluster goes on-demand and costs spike. Solution: list at least 10-15 instance types, spanning different families and sizes.
Pitfall 2: No fallback to on-demand. I once saw a team set capacity-type: spot only. When spot was fully unavailable in a zone, Karpenter had no nodes to provision — pods stayed pending for 20 minutes. Solution: always include on-demand as a fallback. Your operator: In with both values.
Pitfall 3: Ignoring consolidation. Without it, Karpenter will keep nodes that are underutilized. You pay for 70% empty capacity. Turn on consolidationPolicy: WhenUnderutilized in your NodePool spec. It moves pods, deletes empty nodes, and saves money.
Pitfall 4: Not setting ttlSecondsAfterEmpty. Makes nodes hang around after pods finish. You should set it to 30-60 seconds. Combined with consolidation, old nodes get killed fast.
Pitfall 5: Mixing Karpenter with Node Auto Provisioning (NAP) or Cluster Autoscaler. Don't run both. Their provisioning logic conflicts. Stick with one — use Karpenter.
Pitfall 6: No monitoring for spot interruption costs. Spot instances are cheap but not free from volatility. If a workload gets constantly interrupted, the savings from cheaper compute get eaten by retry logic, wasted CPU cycles re-starting jobs. Monitor interruption rates per workload. Anything above 5% per month should trigger a move to on-demand for that deployment.
Pitfall 7: Forgetting about EBS costs. Spot instances usually run ephemeral storage on the root volume. But if your pods use EBS volumes (for databases, cache), those costs persist regardless of spot interruption. I've seen teams cut compute costs 50% but still bleed money on unattached EBS snapshots. Right-size volumes and use volumeSnapshot with lifecycle policies.
FAQ
Q: Can I use Karpenter with managed node groups?
No. Karpenter replaces managed node groups. You can keep managed node groups for system pods (like CoreDNS, kube-proxy) in a separate cluster, but don't mix both in the same node pool — they conflict.
Q: How much can I save by switching from on-demand to spot with Karpenter?
Typically 60-80% on the compute portion of your bill. In our SIVARO cluster, the average spot discount was 73% compared to on-demand. But actual savings depend on workload tolerance for interruptions and your ability to rightsize.
Q: Does Karpenter work on EKS only?
It originally started on AWS, but now has active providers for Azure (AKS) and GCP (GKE). Each provider maps to the same NodePool concept but with cloud-specific node classes (e.g., AKSNodeClass, GCPNodeClass). I've used it on all three; the cost benefits are similar.
Q: What's the best kubernetes cost monitoring tools karpenter combo?
For most teams: Kubecost (free) for allocation + Karpenter's built-in Prometheus metrics + a visualization in Grafana. If you want automated optimization, add Cast AI or ScaleOps. This comparison lists other tools.
Q: Can Karpenter handle cluster autoscaling for Windows nodes?
Not yet. Karpenter's provider for Windows is experimental. Use the Cluster Autoscaler for Windows node pools, Karpenter for Linux.
Q: Will spot instances affect my SLAs?
If you design for interruptions (graceful shutdowns, state checkpointing, retry logic), no. Karpenter's draining helps. But if your workload is strictly stateful (like a primary database), stay with on-demand and use Availability Zone redundancy.
Q: How do I test Karpenter's spot behavior?
Run a karpenter chaos experiment: simulate spot interruptions by killing random nodes. Karpenter should replace them within 2 minutes. Check pod health. We used LitmusChaos for this.
Conclusion
Kubernetes cost optimization karpenter spot instances isn't a silver bullet — it's a strategy. Karpenter gives you the engine to provision cheap spot compute at scale. Spot instances give you the pricing. But the magic happens when you rightsize, monitor, and tune your NodePools continuously.
At SIVARO, we've cut infrastructure costs by 55% since moving to Karpenter + spot. We've also improved pod startup time, reduced node counts, and made our platform more resilient to cloud provider whims. It's not a one-time setup. You'll tweak instance lists, adjust consolidation policies, and monitor interruption metrics. But the payoff is real.
Start small. Migrate one non-critical workload to a Karpenter-managed NodePool with spot. Measure the savings. Then expand. You'll wonder why you waited.
Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.