Kubernetes Overspending Causes and Fixes 2026
A CFO at a Series C fintech asked me to look at their AWS bill in July 2026. Compute was up 340% year over year. Revenue was up 28%. Nobody could explain the gap. I pulled their EKS cluster metrics and found the answer in about forty minutes: 71% of their pods had CPU requests set to values nobody could justify, and their Karpenter provisioners hadn't been touched since 2024.
That's the thing about kubernetes overspending causes and fixes 2026 — the causes are almost never exotic. They're boring, accumulated, and invisible until someone multiplies your hourly node rate by 8,760.
Here's what I've learned building and auditing production Kubernetes for eight years. I'll walk you through where the money actually leaks, what to measure, and the specific fixes that moved real numbers for real teams this year.
What Kubernetes Overspending Actually Means in 2026
Kubernetes overspending is the gap between what you pay your cloud provider for compute and what your workloads actually consume. In 2026 that gap has three components: idle capacity sitting under-utilized, over-provisioned requests blocking consolidation, and the invisible tax of cluster-level overhead you never counted.
The third one is what catches people. A 200-node cluster running at "60% utilization" sounds fine until you realize that's 60% of requested capacity, and requests are inflated 3x over actual usage. Real utilization is closer to 20%. You're paying for five nodes to do the work of one.
Most people think overspending is a rightsizing problem. They're wrong. It's an accounting problem first. You can't fix what you can't see, and standard Kubernetes tooling is genuinely bad at showing you the dollar number attached to each namespace.
Where the Money Actually Leaks
I've now done this audit across maybe thirty clusters. The causes cluster into a few buckets, and their relative weight surprised me.
The Request Inflation Death Spiral
Engineers set requests high so pods don't get OOMKilled or CPU-throttled. That's rational individual behavior and catastrophic collective behavior. When every pod asks for 4 vCPU and uses 0.3, your scheduler can't pack anything and your autoscaler provisions nodes for phantom demand.
At SIVARO we ran a scan across a client's 1,100 deployments in March 2026. Median CPU request: 500m. Median actual P95 usage: 47m. That's a 10x inflation factor on roughly 60% of their workloads. The fix isn't "just lower the requests" — it's measuring P95 and P99 over a real window and using those numbers.
Cluster Autoscaler Refusing to Consolidate
Old-school Cluster Autoscaler only scales down a node when it's been under threshold for a cooldown period (default 10 minutes) and no pod prevents eviction. One pod with a PodDisruptionBudget that requires minAvailable: 1 and no replicas can pin an entire node for weeks.
I've seen a single forgotten CronJob hold an m6i.4xlarge hostage for 94 days. That's roughly $4,100 in 2026 on-demand pricing for a job that ran six minutes a week.
The Zombie Namespace
Someone spins up a preview environment in November 2025. It never gets torn down. By September 2026 you've got 340 abandoned namespaces each running a 2-replica deployment. Nobody notices because each is small. The aggregate is a quarter of your bill.
Overhead You Never Counted
DaemonSets. Sidecar injectors. Observability agents. Service mesh proxies. On a 100-node cluster, three DaemonSets at 200m CPU and 256Mi memory each is 20 vCPU and 25GiB you're paying for before a single business workload runs.
Right Sizing Kubernetes Pods with Karpenter
This is where 2026 tooling changed things. Karpenter isn't new — AWS open-sourced it in 2021 — but the 2026 control plane improvements finally made automated rightsizing practical instead of theoretical.
The core idea: instead of static node groups, Karpenter watches pending pods and provisions exactly the instance type that fits. When pods scale down, it consolidates.
Here's a provisioner that actually works:
yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: general-workloads
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
- key: kubernetes.io/arch
operator: In
values: ["amd64", "arm64"]
- key: karpenter.k8s.aws/instance-family
operator: In
values: ["m6i", "m6g", "m7i", "c6i", "c6g", "c7g", "r6i"]
expireAfter: 168h
limits:
cpu: 2000
memory: 8000Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 30s
Two things matter here. consolidationPolicy: WhenEmptyOrUnderutilized lets Karpenter replace underutilized nodes — this is the single biggest lever I've found. And consolidateAfter: 30s is aggressive, but it works if your workloads tolerate disruption.
I tested this against a client's April 2026 cluster. Same workloads, same traffic, swapped Cluster Autoscaler for Karpenter with consolidation enabled. Node count dropped from 47 to 29 over five days. Monthly compute dropped from $38,400 to $22,100.
The catch: consolidation churns nodes. Your startup time for pods needs to be under 60 seconds, or you'll notice. Stateful workloads with local volumes don't consolidate cleanly and shouldn't be in the same NodePool.
Setting Requests Correctly
The most underrated tool in 2026 is VPA in Off mode plus a metrics pipeline. Don't let VPA mutate. Let it recommend.
Here's the pattern I use:
yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: api-server-vpa
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
updatePolicy:
updateMode: "Off"
Run it for two weeks. Pull recommendations. Apply them via GitOps with review. The recommendations are conservative — the VPA team's own guidelines say they target P95 for CPU and P99 for memory. That's fine. Conservative beats 10x inflated.
Kubernetes Pod Consolidation and Karpenter Pricing Mechanics
Here's where most teams get confused about the business case.
Karpenter's consolidation doesn't have a direct price. It's an optimization feature. But the way it interacts with pricing tiers is where the money shows up.
Three pricing mechanics matter in 2026:
Spot interruption and consolidation risk. Karpenter will happily pick Spot instances when a workload's Spot tolerance allows. In 2026, Spot pricing on m7i instances is roughly 60-70% off on-demand. But if you set consolidateAfter too low and use Spot, you get churn and potential interruptions mid-eviction. I've settled on 5 minutes for Spot-heavy NodePools, 30 seconds for on-demand-only.
Reserved Instance and Savings Plan interaction. This is the one that bites. If you're on a 3-year Compute Savings Plan for 60% of your baseline, you want Karpenter to stay off Spot for the workloads that plan covers. Otherwise you're buying Spot on top of a commitment you already paid for.
The pattern: separate NodePools. One for baseline (on-demand, covered by Savings Plan), one for burst (Spot, no commitment). Karpenter's weight field prioritizes:
yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: baseline-committed
spec:
weight: 50
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
---
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: burst-spot
spec:
weight: 10
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot"]
taints:
- key: workload-type
value: burst
effect: NoSchedule
Higher weight wins. Baseline nodes get provisioned first; Spot absorbs the overflow. On a mid-size cluster this arrangement saved a client roughly 34% versus letting Karpenter mix freely.
ARM tax avoidance. c7g and m7g instances are 20-40% cheaper than their x86 equivalents for equivalent specs. If your images are multi-arch, Karpenter will include them. Teams that don't build multi-arch images leave that money on the table every month.
The Measurement Stack That Actually Works
You can't fix this without numbers per namespace, per team, per service.
Here's the stack I install on day one of any audit:
OpenCost for cost allocation by namespace and label. It's the CNCF project that matured through 2025 and is now the default. Free, and it maps pod usage to cloud pricing.
Prometheus with kube-state-metrics and node-exporter, retention set to at least 30 days. You need the window.
Kubecost or Vantage if you want a commercial layer that does the showback reports for engineering managers. Worth the money above ~50 nodes.
A simple query for finding the worst offenders:
promql
# CPU request vs actual usage, ratio over 7 days
sum by (namespace, deployment) (
rate(container_cpu_usage_seconds_total[7d])
)
/
sum by (namespace, deployment) (
kube_pod_container_resource_requests{resource="cpu"}
)
Anything below 0.25 is a target. Anything below 0.10 means someone typed a number once and never looked again.
Building the Showback Report
Numbers without names don't change behavior. I build a weekly email that goes to each team's engineering lead with three lines:
- This namespace spent $X last week
- Actual P95 utilization was Y%
- If we rightsized at P95, projected cost is Z
The delta between X and Z is the conversation starter. In my experience, roughly 60% of teams fix their own stuff within two weeks once the number has a name on it. The other 40% need the platform team to do it for them.
Real Fixes That Moved Real Numbers
I keep a running list of what worked. Here's the honest 2026 version.
Fix 1: Kill the requests, measure again. Lower every CPU request over 500m to P95 + 20% headroom. Do it namespace by namespace with a rollback plan. Expected saving: 25-40% on compute in the first month.
Fix 2: Switch to Karpenter with consolidation. If you're still on Cluster Autoscaler with static groups, you're leaving 20-30% on the table. Migration takes a weekend.
Fix 3: Add a namespace TTL controller. Any namespace labeled ttl: 72h and not refreshed gets deleted. Preview environments, feature branches, ad-hoc test namespaces all go through this. Saved one client $8,900/month alone.
Fix 4: Multi-arch everything. ARM instances are cheaper for the same throughput on most workloads. The exception is anything tied to x86-specific binaries — some ML inference stacks, older Java native libs.
Fix 5: Spot for everything that tolerates it. Stateless APIs, batch jobs, CI runners, observability agents. Not stateful databases. Not workloads with 30-minute startup times.
Fix 6: Savings Plans sized to floor, not average. Look at your trailing 90-day minimum. Commit to that. Let Spot and on-demand cover the peaks.
The Contrarian Take on VPA and HPA
Most people think the answer is aggressive Horizontal Pod Autoscaler configs. They're wrong. In 2026, the winning pattern for most web workloads is fewer, fatter pods with VPA-driven requests and a modest HPA.
Here's why. HPA scales on metrics with lag. You end up with tons of small pods, each starting cold, each requesting a baseline. The aggregate request curve is spiky and high. VPA with reasonable requests and a stable replica count gives you a much flatter consumption curve — the scheduler can pack it tighter, and Karpenter consolidates more aggressively.
The exception is obviously bursty workloads and anything with long-tail traffic. But for the median internal API, HPA is often making your bill worse. Test it. Measure before and after.
FAQ
How much can I realistically save on Kubernetes costs in 2026?
From the audits I've done this year, 30-45% is typical in the first 90 days without touching application code. Teams with no prior optimization work sometimes hit 55-60%. The absolute ceiling depends on how much of your spend is already on committed-use discounts.
Is Karpenter always better than Cluster Autoscaler in 2026?
For AWS, yes, in almost every case. Karpenter's consolidation, instance flexibility, and speed of provisioning are meaningfully better. On GKE and AKS, the native autoscalers improved a lot in 2025 and the gap is smaller, but Karpenter is now supported there too and generally wins on cost.
What's a reasonable CPU request for a Go or Node.js API pod?
Depends entirely on your P95. Not the answer people want. If your P95 CPU is 80m, request 100m and set the limit to 500m. The request is for scheduling; the limit is your safety valve. Most teams invert this — high request, low limit — which is exactly backwards.
Does Spot break production workloads?
Spot breaks workloads that can't handle a 2-minute termination notice. Stateless services behind a load balancer with proper readiness probes handle it fine. Stateful anything doesn't. Batch jobs handle it best of all.
How do I find orphaned resources without a commercial tool?
Label everything on creation with owner:, created-by:, and ttl:. Query kube-state-metrics for anything older than 30 days with no ttl refresh. You'll find surprises. I've written a small CronJob that does this — it emails a weekly report before deleting anything.
What about per-pod cost visibility — is OpenCost enough?
OpenCost covers ~90% of use cases. It struggles with GPU workloads and shared infrastructure where you need custom allocation rules. For those, either extend it with your own metrics or pay for Kubecost.
Should I use VPA in Auto mode?
Not in production. Recommendations drift, and Auto mode restarts pods to apply changes. Run VPA in Off or Initial mode, review, and apply through Git. The Initial mode is a reasonable compromise for workloads you trust.
Where does kubernetes overspending causes and fixes 2026 differ from 2024?
Three things. Karpenter is now the default answer on AWS and viable elsewhere. ARM adoption hit mainstream in 2025 and is now table stakes. And the tooling for per-namespace cost attribution finally works without a data engineering project.
Putting It Together
Here's the sequence I follow when I take on a new cluster. Week one: install OpenCost, Prometheus, and get 14 days of metrics. Week two: build the namespace cost report. Week three: identify the top 20 namespaces by wasted dollars, apply requests fixes through GitOps, watch. Week four: Karpenter migration on a staging cluster, then production.
Then the ongoing work. Weekly cost reviews per team. Monthly cleanup of orphaned resources. Quarterly re-evaluation of Savings Plan coverage as the workload mix changes.
Here's the honest part. Kubernetes overspending causes and fixes 2026 isn't solved once and forgotten. The cluster drifts. Requests get inflated again. Someone launches a preview environment without a TTL. New engineers don't know the patterns. The fix is a habit, not a project.
The teams I've seen keep their bills under control treat cost like a first-class SLO. It's on the dashboard. It has an owner. It gets reviewed. That's the whole secret. Everything else is tooling that supports the habit.
If you're auditing your own cluster this month, start with the PromQL query above. Find your 0.10 ratio namespaces. Fix those first. You'll recover 15-20% in a week.
The rest follows.
Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.