Here is an uncomfortable finding from the CNCF: 49% of organizations reported that Kubernetes increased their cloud costs. Only 24% said it reduced them.
Read that again. The infrastructure platform sold on resource efficiency is making nearly half of teams' bills go up. And the reason is not hard to find: Kubernetes makes it easy to provision resources. It makes it much harder to ensure you are actually using them.
The 2025 Kubernetes Cost Benchmark from CAST AI - based on 2,100+ organizations - found average CPU utilization across clusters at just 10%. Average memory utilization: 23%. That is not a Kubernetes problem. That is a configuration and tooling problem. And it means the average cluster has 5–10x more headroom than teams realize, most of it being billed and wasted simultaneously.
The good news: teams that actively manage K8s costs consistently report 30–50% reductions. Aggressive programs report 47–70%. This guide is the technical playbook for getting there - on EKS and GKE specifically.
Why Kubernetes Doesn't Save Money by Default
When teams first move to Kubernetes, they typically configure resource requests and limits once - based on estimates or conservative "safe" numbers from a launch meeting - and then never touch them again. A container requesting 2 vCPU that averages 200m in production is 10x overprovisioned. You pay for the node capacity that hosts every over-requested CPU and memory unit.
The problem compounds at the cluster level. If every pod over-requests by 3x, bin-packing efficiency collapses. You need far more nodes than the actual workload demands. Each node sits partially idle, accruing compute charges.
Three interventions fix most of this: smarter autoscaling with Karpenter, pod rightsizing with VPA, and granular cost visibility with Kubecost or OpenCost. Layer in Spot nodes and you compound savings further. Let's cover each in detail.
Karpenter vs Cluster Autoscaler: The Honest Comparison
For EKS teams in 2026, the practical answer is Karpenter - unless you have a specific reason to stay with Cluster Autoscaler.
How they differ architecturally:
Cluster Autoscaler (CA) works within predefined node groups. You configure your ASGs, CA monitors for unschedulable pods, and scales the node group up or down within those boundaries. It is the multi-cloud, Kubernetes SIG-supported option - mature, battle-tested across AWS, GCP, Azure, and on-prem.
Karpenter bypasses node groups entirely. It speaks directly to the EC2 Fleet API, evaluates pending pods and their constraints in a single decision, and provisions exactly the right instance type from hundreds of options. It also consolidates proactively: when workloads shift, Karpenter replaces underutilized nodes with smaller ones automatically.
The performance gap is significant: Independent 2025–2026 benchmarks on 100+ clusters measured node provisioning at roughly 3–4 minutes for CA versus ~55 seconds for Karpenter. In capacity-fallback scenarios, Karpenter retries alternative instance types and Availability Zones in seconds via the Fleet API. CA is constrained to the instance types configured in each node group.
Cost impact in production: EKS estates combining Karpenter consolidation, VPA-driven rightsizing, and ~78% Spot usage have achieved audited 47.6% total Kubernetes cost reduction over nine months - £1.2 million annualized savings without turning off any business-critical services.
# Karpenter NodePool: mixed Spot/On-Demand with Graviton
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: general-workers
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
- key: kubernetes.io/arch
operator: In
values: ["arm64"] # Graviton for better price-performance
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["m", "c", "r"] # Diversify instance families
nodeClassRef:
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
name: default
disruption:
consolidationPolicy: WhenUnderutilized
consolidateAfter: 1m
limits:
cpu: 1000
memory: 2000Gi
When to stay with CA: Multi-cloud environments where Karpenter's AWS-specificity is a constraint, organizations with complex existing ASG integrations, or teams that need stable behavior across heterogeneous cloud providers. Karpenter reached v1.0 GA in 2024 for AWS and is still a CNCF Sandbox project - maturing fast but newer than CA.
VPA: The Pod Rightsizing Engine You Are Probably Not Using
Vertical Pod Autoscaler (VPA) continuously analyzes historical CPU and memory usage per container using decaying weighted histograms, targeting high percentiles - typically P95 for memory - to provide headroom without gross over-provisioning. Left to observe a workload for a week or more against real traffic patterns, it tells you exactly what your pods actually need.
The production breakthrough in 2025: Kubernetes 1.35 graduated in-place pod resize to stable. VPA's InPlaceOrRecreate update mode can now adjust CPU and memory requests without restarting pods - a major change for latency-sensitive production workloads where the previous eviction-and-restart requirement was a deal-breaker.
Typical results: VPA adoption cuts CPU waste by ~30% and memory by ~20–25%, with overall cluster cost reductions of roughly 20–30% as improved requests feed into better bin-packing. One large EKS programme attributed ~£26,000/month (~£310K annualized) specifically to VPA plus Goldilocks, as part of the broader optimization that cut total K8s spend by nearly half.
# VPA: Start in Off mode to observe without applying
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: api-server-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
updatePolicy:
updateMode: "Off" # Observe first. Switch to InPlaceOrRecreate once confident.
resourcePolicy:
containerPolicies:
- containerName: api-server
minAllowed:
cpu: 50m
memory: 64Mi
maxAllowed:
cpu: "2"
memory: 4Gi # Bounds prevent extreme recommendations
The VPA and HPA anti-pattern to avoid: Never run VPA and HPA on the same resource metric for the same pods. If both watch CPU, you create a feedback loop: VPA lowers CPU requests, HPA's percentage-of-request math triggers more replicas, VPA sees lower per-pod CPU and lowers requests further. Restrict VPA to stateful services, caches, and JVM workloads. Use HPA or KEDA for horizontally scalable deployments.
GKE: Autopilot vs Standard - The Cost Breakdown
GKE gives you a choice other managed Kubernetes platforms do not: Standard mode (you manage nodes) or Autopilot (Google manages everything, you pay per pod request).
- GKE Standard: ~$0.10/hour (~$72/month) per cluster for the control plane, plus GCE VM costs for nodes. You control node types, Spot VMs, committed use discounts.
- GKE Autopilot: ~$0.0673/hour for a pod requesting 1 vCPU, 2 GiB memory, 1 GiB ephemeral storage. Control plane cost included. You pay only for what pods request.
The breakeven rule of thumb: If your Standard cluster consistently runs above 60–80% node utilization with committed use discounts applied, Standard wins. Below that threshold - especially for spiky or stateless workloads - Autopilot often wins because you are not paying for idle capacity.
| Scenario | GKE Standard (3 nodes) | GKE Autopilot | Winner |
|---|
| Low utilization (~30%) | ~$290/month | ~$130/month | Autopilot |
| High utilization (~80%) | ~$210/month (with CUDs) | ~$250/month | Standard |
| Spiky stateless workloads | ~$290/month flat | Scales with demand | Autopilot |
| GPU/AI workloads | Full flexibility | Limited GPU support | Standard |
GKE's 10th birthday update (August 2025): Google moved GKE to a single paid tier, including enterprise capabilities - Fleets, Teams, Config Management, Policy Controller - in Standard mode at no additional tiered premium. This simplifies cost modeling and removes a barrier to consistent governance across clusters.
A hybrid strategy is gaining traction: Autopilot for general stateless applications, Standard for specialized or always-on capacity with GPUs and committed discounts. Google Cloud Next 2025 highlighted Autopilot's improved pod scheduling speed and capacity right-sizing as further arguments for this approach.
Spot and Preemptible Nodes: The 60–90% Discount Play
Spot Instances on AWS and Spot VMs on GKE are the single highest-discount optimization available in Kubernetes - savings of 60–90% on compute for the capacity you move to Spot. Used carefully, they are not as risky as teams fear. Less than 5% of Spot Instances are interrupted before customers terminate them intentionally, according to AWS guidance.
For EKS with Karpenter:
Karpenter uses AWS's Price-Capacity-Optimized allocation strategy: it selects Spot pools with higher capacity availability first, then chooses the lowest-price option within those pools. Combined with multi-AZ and multi-instance-family diversification, interruption rates stay consistently below 5% for most workloads. Real-world EKS clusters running ~70–80% Spot with proper PodDisruptionBudgets have achieved 60–70% compute cost reductions without SLA breaches.
# PodDisruptionBudget: protect against mass eviction during interruptions
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-server-pdb
spec:
maxUnavailable: 25%
selector:
matchLabels:
app: api-server
---
# Toleration for Spot nodes - add to Deployment spec
tolerations:
- key: "karpenter.sh/capacity-type"
operator: "Equal"
value: "spot"
effect: "NoSchedule"
For GKE with Spot VMs:
Create dedicated Spot VM node pools with a taint (cloud.google.com/gke-spot=true:NoSchedule). Configure workloads with both a toleration and a preferred node affinity - prefer Spot, fall back to On-Demand. Use the ANY location policy on the Spot node pool so the autoscaler considers all zones when scaling.
# Prefer Spot nodes, fall back to On-Demand if unavailable
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: cloud.google.com/gke-spot
operator: In
values: ["true"]
Never run on Spot: Production databases, stateful services without checkpoint/resume logic, anything with a strict SLA that cannot tolerate the 2-minute interruption window. The discount disappears if data loss or downtime becomes a consequence.
OpenCost vs Kubecost: Choosing Your Cost Allocation Layer
You cannot optimize what you cannot measure. For Kubernetes, cost allocation comes down to two main options.
OpenCost is the CNCF-governed open-source engine. Apache-2.0 licensed, Prometheus-native, designed as the "Prometheus of cloud cost monitoring." It provides namespace and label-level cost modeling using on-demand list prices. What it does not do: reconcile Reserved Instance discounts, Savings Plans, Spot pricing, or credits. It shows what you would pay at list price, not what you actually paid.
Kubecost builds on OpenCost and adds the commercial layer: billing API reconciliation (actual costs, not list prices), multi-cluster aggregation, richer UI, governance, budget alerts, rightsizing recommendations, and enterprise auth. Kubecost 3.0 added GPU-aware rightsizing - a timely addition as AI/ML workloads move onto clusters.
| Feature | OpenCost | Kubecost (Free) | Kubecost (Paid) |
|---|
| Namespace allocation | Yes | Yes | Yes |
| Label-based allocation | Yes | Yes | Yes |
| RI/SP/Spot reconciliation | No | No | Yes |
| Multi-cluster support | No | Single cluster | Yes |
| SSO / enterprise auth | No | No | Yes |
| GPU rightsizing | No | Limited | Yes (v3.0) |
| Pricing | Free | Free | ~$449+/month |
CNCF's 2024 FinOps microsurvey: Kubecost adoption at ~23%, OpenCost at ~11%. The gap reflects Kubecost's role as a turnkey platform. OpenCost's traction comes from teams embedding cost data into existing Prometheus-based observability stacks.
The practical recommendation: Start with OpenCost to establish baseline visibility (zero cost, Prometheus-native). Upgrade to Kubecost when you need actual-cost reconciliation, multi-cluster views, or enterprise governance features.
AWS re:Invent 2024: Split Cost Allocation Data for EKS
One of the most meaningful EKS cost developments from re:Invent 2024 went somewhat underreported: AWS extended Split Cost Allocation Data to enable pod-level cost reporting in Cost and Usage Reports.
Previously, EKS compute costs appeared as EC2 node charges with no visibility into which pods, namespaces, or teams consumed what. With Split Cost Allocation Data enabled, and Amazon Managed Service for Prometheus or CloudWatch Container Insights feeding utilization data, EKS compute charges can now be apportioned at the namespace, deployment, or label level in your CUR.
# Enable cost allocation tag for EKS namespace tracking
aws ce update-cost-allocation-tags-status --cost-allocation-tags-status TagKey=kubernetes_namespace,Status=Active
# Then enable Split Cost Allocation Data via:
# AWS Console: Billing > Data Exports > Split Cost Allocation Data > Enable for EKS
This does not replace Kubecost or OpenCost for teams that need real-time in-cluster visibility and actual-cost reconciliation. But it is a free, meaningful upgrade for teams already using CUR-based FinOps workflows and cost dashboards built on Athena or a data warehouse. If you are on EKS and not using this yet, enable it today.
The Kubernetes Cost Optimization Checklist
Work through this layer by layer. The average cluster has problems across all of these - fixing one without the others leaves significant savings on the table.
Visibility
Deploy OpenCost or Kubecost for namespace and label-level cost allocation Enable AWS Split Cost Allocation Data for EKS (or GKE Billing Export) Set up cost-per-namespace dashboards visible to engineering teams Establish per-namespace cost thresholds that trigger Slack/PagerDuty alerts Pod Rightsizing
Deploy VPA in Off mode across all namespaces - observe for at least one week Review recommendations against actual P95 usage and apply to lowest-risk workloads Switch mature services to InPlaceOrRecreate update mode (requires Kubernetes 1.35+) Eliminate resource requests set to zero or containers with no limits set Autoscaling
Evaluate Karpenter vs CA - pilot Karpenter on new node pools for EKS Enable Karpenter consolidation (consolidationPolicy: WhenUnderutilized) Review and tighten HPA min/max replicas based on actual traffic patterns Deploy KEDA for workloads that can scale to zero replicas during idle periods Spot and Preemptible Capacity
Create dedicated Spot node pools or provisioners with taints and tolerations Move batch, CI/CD, and stateless workloads to Spot Add PodDisruptionBudgets to all stateful and production workloads Configure multi-AZ and multi-instance-family diversification GKE Specific
Evaluate Autopilot vs Standard per cluster based on actual utilization Consider hybrid: Autopilot for stateless apps, Standard for GPU and always-on Enable Committed Use Discounts for Standard cluster node types FinOps Culture
Assign a cost owner to each namespace or team Include cost per namespace in engineering SLO dashboards alongside latency and error rate Run monthly K8s cost reviews - track savings per optimization initiative Frequently Asked Questions
Kubernetes actually increased our cloud costs after migration. Is that normal?
Unfortunately, yes - for teams that have not actively managed resource requests and cluster configuration. The CNCF reports 49% of organizations saw costs increase. The fix follows a clear order: visibility first (Kubecost or OpenCost), then rightsizing (VPA), then autoscaling improvements (Karpenter), then Spot adoption. Most teams go from "K8s is expensive" to "K8s is cheap" within 2–3 months of systematic effort.
Is Karpenter safe for production use?
Yes, for most EKS workloads. Karpenter reached v1.0 GA in 2024 and AWS now recommends it as the default for new EKS clusters. Migration from CA to Karpenter requires care - progressive rollout by environment (dev then staging then prod) and validation that existing pod constraints (affinity rules, topology spread) work correctly under Karpenter's scheduling model.
What is the right Spot percentage for an EKS cluster?
For stateless web services and batch workloads, 70–80% Spot is achievable with appropriate PodDisruptionBudgets, multi-AZ and multi-instance-family diversification, and graceful shutdown handling within the 2-minute interruption window. The remaining 20–30% On-Demand base covers stateful workloads and provides a buffer against large-scale Spot interruptions.
Does GKE Autopilot work for AI and ML workloads?
Autopilot has historically had limited GPU support, making Standard mode the default choice for GPU workloads. GKE's roadmap post Google Cloud Next 2025 suggests improvements are coming, but for GPU-intensive AI/ML workloads today, Standard mode with dedicated GPU node pools and committed use discounts remains the more cost-effective and flexible option.
How much can VPA realistically save in a production cluster?
Production case studies consistently report VPA delivering 20–30% cluster cost reductions when combined with proper HPA/KEDA configuration. The outlier case - £1.2M annualized savings from a single EKS programme - included VPA as one of several components alongside Karpenter consolidation and Spot adoption. VPA alone, in a cluster that has never been rightsized, commonly saves 20–25% in the first pass.