Karpenter Saved Us 40% on Kubernetes — Here's How
I remember the morning the AWS bill hit $187,000.
April 2024. We had 47 node groups, three autoscalers fighting each other, and 23% of our cluster running idle. The CTO asked me one question: "Are we even getting value from Kubernetes?"
That question is why I'm writing this today.
I'm Nishaant Dixit, founder of SIVARO. We build data infrastructure and production AI systems. We ran Kubernetes across 12 accounts, 6 regions, and processed 200K events per second. And we almost quit Kubernetes entirely.
The industry is shifting. Why Companies Are Leaving Kubernetes? isn't clickbait — it's a real trend. One engineer deleted Kubernetes from 70% of their services in 2026 and saved $416K. Even ONA publicly announced they're leaving Kubernetes.
But here's what I've learned: Kubernetes isn't dead, you just misused it. The problem wasn't Kubernetes. The problem was how we provisioned capacity.
Karpenter changed that.
This guide walks you through exactly how to reduce kubernetes costs with karpenter — not theory, but what we actually did at SIVARO. The node group configurations. The spot instance strategy. The consolidation policies. The mistakes we made. The numbers we saved.
What Karpenter Actually Does (and Why Cluster Autoscaler Can't)
Let me be blunt: Cluster Autoscaler is a band-aid.
Cluster Autoscaler looks at pending pods, sees they need resources, and adds nodes. Sounds fine. But here's the problem — it operates on node groups. You define a node group with an instance type, a minimum size, a maximum size. If your workload needs a c6i.4xlarge but your node group only has m5.large, you either overprovision or your pods stay pending.
Karpenter doesn't work that way.
Karpenter reads pod specifications — CPU, memory, GPU, topology constraints — and provisions instances directly against those requirements. It doesn't care about node groups. It doesn't care about ASGs. It looks at your pods, picks the cheapest instance type that fits, and launches it. In seconds.
Here's the critical difference: karpenter vs cluster autoscaler cost comparison shows Karpenter wins on density. A study by AWS in 2024 found Karpenter increased pod density by 23-31% compared to Cluster Autoscaler across comparable workloads. Why? Because Cluster Autoscaler rounds up to the next instance size in your node group. Karpenter finds the exact instance that matches your pod requirements.
We tested this at SIVARO. With Cluster Autoscaler, our average pod-to-node ratio was 3.4 pods per node. After switching to Karpenter, it hit 5.2. That's 53% more pods per node. That's real cost reduction.
How to Reduce Kubernetes Costs with Karpenter: The Setup
Before we get into configuration, you need to understand cost drivers.
Your Kubernetes bill breaks down into three buckets:
- Compute — EC2 instances running your workloads
- Cluster overhead — control plane, system pods, monitoring
- Data transfer and storage — EBS, EFS, NAT gateway, Load Balancers
Karpenter primarily attacks bucket #1. But the savings ripple into #2 and #3.
Step 1: Install Karpenter (the right way)
Most tutorials tell you to install Karpenter with default settings. Don't. Defaults optimize for availability, not cost.
Here's our production karpenter.yaml:
yaml
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
requirements:
- key: "karpenter.sh/capacity-type"
operator: In
values: ["spot", "on-demand"]
- key: "node.kubernetes.io/instance-type"
operator: In
values:
- "c6i.large"
- "c6i.xlarge"
- "c6i.2xlarge"
- "c6i.4xlarge"
- "m6i.large"
- "m6i.xlarge"
- "m6i.2xlarge"
- "m6i.4xlarge"
- "r6i.large"
- "r6i.xlarge"
- "r6i.2xlarge"
- "r6i.4xlarge"
- "g5.xlarge"
- "g5.2xlarge"
nodeClassRef:
name: default
limits:
cpu: 1000
disruption:
consolidationPolicy: WhenUnderutilized
expireAfter: 720h
Notice what I didn't include: t3.*, t4g.*, or any burstable instances. Burstable instances look cheap, but under sustained load they steal CPU credits. Your pods get throttled. The cost of debugging throttled applications always outweighs the savings.
Also notice the consolidation policy: WhenUnderutilized. That's the magic. This tells Karpenter: "If you can consolidate pods onto fewer nodes and delete the empty ones, do it."
Step 2: Configure Spot Instance Strategy
Here's where the real money is.
AWS spot instances offer 60-90% discounts compared to on-demand. The reason most teams don't use them? Fear of interruption. But Karpenter handles interruptions natively with the NodePool consolidation policy and interruption handling.
karpenter spot instance cost savings kubernetes isn't just about picking spot — it's about how you diversify.
Never use a single instance type for spot. AWS can reclaim all instances of a specific type in an AZ. Spread across families, generations, and sizes.
yaml
spec:
requirements:
- key: "karpenter.sh/capacity-type"
operator: In
values: ["spot"]
- 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"
We used 8 instance types for our CPU workloads. Spans Intel and AMD, different generations, different sizes. If AWS reclaims all c5.large instances, Karpenter falls back to c6i.large or m5.large. Your pods stay running.
Real number: Before Karpenter, we ran 100% on-demand. Average EC2 cost per month: $68,000. After switching to Karpenter with spot-first strategy: $27,000. That's a 60% reduction. On the same workloads.
The Consolidation Engine: Where Karpenter Earns Its Keep
Most people think Karpenter saves money through spot instances. Wrong. Spot helps, but consolidation is where the real magic lives.
Karpenter's consolidation runs as a continuous loop. It looks at every node and asks: "Can I move these pods to other nodes and delete this node?" If yes, it does it. Immediately. Not on a schedule. Not when someone remembers.
This catches two things:
1. Idle capacity during low traffic. Your batch jobs finish at 2 AM. Workers stay running. A manual cleanup might happen at 8 AM. With Cluster Autoscaler, that idle capacity sits for hours. Karpenter consolidates in minutes.
2. Bin-packing inefficiency. Say you have a c6i.4xlarge running three pods that each use 2GB memory and 1 CPU. The node has 16 CPU and 32GB memory. You're using 18% of the node. Karpenter sees a c6i.xlarge with 4 CPU and 8GB would fit those pods. It drains the big node, launches the small one, and saves you money.
karpenter vs cluster autoscaler cost comparison on consolidation alone: Cluster Autoscaler can't do this. It only scales down based on utilization thresholds in node groups. It doesn't rebalance across instance types. Karpenter does.
I'll give you a specific example. June 2026, we had a customer data pipeline that ran for 4 hours every night. With Cluster Autoscaler, we burned 12 r6i.8xlarge instances for those 4 hours. Each cost $1.68/hour. Total per night: $80.64. Per month: $2,419.
With Karpenter, the pipeline ran on 8 r6i.4xlarge instances that consolidated down to 4 during the last hour. Cost per night: $31.36. Per month: $940. That's a 61% reduction.
Node Class Configuration: Don't Skip This
Karpenter's NodeClass defines the underlying infrastructure. AMI selection, security groups, subnet tags, block device mappings. Get this wrong and you'll either overspend or break workloads.
Here's the configuration we run in production:
yaml
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: default
spec:
amiFamily: AL2
role: "KarpenterNodeRole-${CLUSTER_NAME}"
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}"
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}"
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 80Gi
volumeType: gp3
iops: 3000
throughput: 125
deleteOnTermination: true
encrypted: true
tags:
Name: "karpenter/${CLUSTER_NAME}"
karpenter.sh/discovery: "${CLUSTER_NAME}"
Two things to note:
AMI Family. We use AL2 (Amazon Linux 2). Bottlerocket is popular for security, but we found AL2 easier to debug and tune. Your choice may vary. Just don't use EKS Optimized Amazon Linux with Docker — use containerd. It's faster and uses less memory.
Block device mappings. 80GB gp3 with 3000 IOPS. Most people use too-small volumes and hit IOPS throttling under load. The cost difference between 30GB and 80GB is negligible — pennies per instance. The cost of pod evictions from disk pressure is real.
Advanced Cost Optimization Techniques
Use Node Templates with Taints and Tolerations
If you run batch jobs that need GPU, don't let them consume your general-purpose pool. Separate them with taints.
yaml
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: gpu
spec:
template:
spec:
requirements:
- key: "node.kubernetes.io/instance-type"
operator: In
values: ["g5.xlarge", "g5.2xlarge", "g4dn.xlarge"]
taints:
- key: "nvidia.com/gpu"
value: "true"
effect: "NoSchedule"
disruption:
consolidationPolicy: WhenUnderutilized
GPU instances are expensive. A g5.2xlarge costs $1.22/hour. Letting non-GPU pods land there doubles your cost. Taint everything.
Set Resource Limits on NodePools
Don't let Karpenter spend unlimited money. Set limits on your NodePools:
yaml
spec:
limits:
cpu: 500
memory: 1000Gi
When the limit is reached, Karpenter stops provisioning new nodes. Your pods will stay pending instead of accidentally spinning up 50 p4d.24xlarge instances at $32/hour each. Yes, I've seen it happen.
Use drift Consolidation
Karpenter 0.35+ supports drift detection. When your NodeClass changes (new AMI, different security group), Karpenter detects that running nodes are "drifted" from the desired state. It replaces them incrementally, not all at once.
This is huge for security patching. Before Karpenter, we had to cordon, drain, and replace nodes manually or through Node Termination Handler. It was slow. We skipped patches. Karpenter handles this automatically.
What I Wish Someone Told Me Before Switching
Karpenter isn't magic for stateful workloads.
If you run statefulsets with PVCs, Karpenter can consolidate nodes, but it can't move PVCs across AZs. If your pods are bound to us-east-1a EBS volumes and that AZ runs out of capacity, you're stuck. We learned this the hard way with a Cassandra cluster.
Solution: Use Topology Spread Constraints with zone topology. Force pods to distribute across zones. Then Karpenter will maintain capacity in each zone.
Karpenter doesn't handle cluster autoscaler's "scale-to-zero" well.
If you want to completely shut down a cluster during off-hours, Karpenter can't do that natively. You need a separate controller or a cronjob to scale deployments to zero. AWS released Karpenter's NodePool pause feature in 2025, but it's still experimental.
The learning curve is steeper than you expect.
Cluster Autoscaler's config is simple: set min/max in ASG. Done. Karpenter requires understanding NodePools, NodeClasses, consolidation policies, interruption handling, and drift detection. Expect a week of tuning before it feels stable.
But that week pays for itself.
The Real Cost Numbers
Let me give you our actual numbers from SIVARO. We run a multi-tenant data platform. 200K events per second. 15 microservices, 4 batch pipelines, 2 real-time inference systems.
Before Karpenter (Cluster Autoscaler + 100% on-demand):
- Average EC2 monthly cost: $68,000
- Average node count: 247
- Average pod density: 3.4 pods/node
- Monthly cluster overhead (control plane + system pods): $4,200
After Karpenter (spot-first + consolidation):
- Average EC2 monthly cost: $27,000
- Average node count: 142
- Average pod density: 5.2 pods/node
- Monthly cluster overhead: $2,100
Savings: 60.3% on compute. 50% on cluster overhead. Total annual savings: $492,000.
But — and this matters — we didn't get there in a week. We got there in 6 weeks. The first week actually increased costs because we hadn't tuned consolidation correctly and Karpenter kept spinning up new nodes before old ones drained. Week 2: broke even. Week 6: 60% savings.
FAQ
Q: Does Karpenter work with EKS Fargate?
A: Yes, but it's a different optimization. Fargate profiles take priority over Karpenter for matching pods. We found Fargate useful for system pods (CoreDNS, VPA, etc.) and Karpenter for workloads. Fargate for system pods costs about $200-$400/month for a medium cluster. Worth it for stability.
Q: How does karpenter vs cluster autoscaler cost comparison look for GPU workloads?
A: Cluster Autoscaler loses badly here. GPU instance types have massive variation (g4dn vs p4d vs trn1). Cluster Autoscaler needs a node group per GPU type. Karpenter dynamically picks the cheapest GPU that fits. We saw 40% savings on SageMaker-compatible GPU workloads.
Q: What happens when spot instances get reclaimed?
A: Karpenter drains the node, marks the pods as disrupted, and Kubernetes reschedules them. Karpenter provisions replacement nodes in seconds. If you run stateless workloads, this is transparent. For stateful workloads, use Topology Spread Constraints and avoid single-AZ dependencies.
Q: Can Karpenter reduce Kubernetes costs without using spot instances?
A: Yes. Consolidation alone saves 15-25%. Even with 100% on-demand, you'll get better density than Cluster Autoscaler. But why would you skip spot? The risk profile is manageable.
Q: Is Karpenter production-ready in 2026?
A: Yes. Karpenter hit v1.0 in early 2026. We've been running it in production since 0.34. The API is stable. The only edge case is very large clusters (1000+ nodes) where the controller can lag by 30-60 seconds during massive scale-ups.
Q: How do I migrate from Cluster Autoscaler to Karpenter without downtime?
A: Run both simultaneously. Install Karpenter, create NodePools, but don't remove Cluster Autoscaler yet. Set karpenter.sh/capacity-type in your workloads. Let Karpenter handle new pods. Watch for a week. Remove Cluster Autoscaler annotations from your node groups. Then disable Cluster Autoscaler. We did this over 2 weekends.
Q: Does Karpenter support multi-architecture clusters (ARM + x86)?
A: Yes. Define separate NodePools for ARM instances (like c7g.large) and x86 instances. Use nodeSelector in your pods. We run ARM for stateless services (45% cheaper) and x86 for legacy dependencies. Integration was straightforward.
Q: What's the biggest mistake teams make with Karpenter?
A: Not setting resource requests on pods. Karpenter reads requests, not limits. If your pods don't have requests set, Karpenter assumes minimum resource needs and may oversubscribe nodes. Always set requests to the 90th percentile usage. Use VPA if you need recommendations.
Final Thought
Kubernetes isn't dying. It's maturing.
The teams leaving Kubernetes aren't leaving because Kubernetes is bad. They're leaving because they paid too much for capacity they didn't need. They ran Cluster Autoscaler with static node groups and thought that was "cloud native."
It wasn't.
How to reduce kubernetes costs with karpenter comes down to one principle: provision exactly what you need, exactly when you need it, at the cheapest possible price. Karpenter gives you the tool. The discipline is yours.
Here's my direct advice: If you're running Kubernetes today and your EC2 spend is over $10,000/month, switch to Karpenter. Do it this month. You'll save 40-60% or you'll learn exactly where your cost problems are. Either way, you win.
We did. And we're still on Kubernetes.
Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.