DevOps

Kubernetes Cost Optimization: Right-Sizing Pods, Nodes, and Namespaces

E
Elena RodriguezLead DevOps Engineer
April 2, 202611 min read
Kubernetes Cost Optimization: Right-Sizing Pods, Nodes, and Namespaces
← Back to Insights

We covered multi-region Kubernetes architecture in our scaling best practices guide. This one is about the other half of the K8s conversation: cost. In our experience, Kubernetes clusters routinely run at 30-40% actual utilization against what's requested — meaning enterprises are often paying for roughly double the compute they need, purely from conservative resource requests nobody has revisited since they were first set.

Why Kubernetes Waste Is Different From VM Waste

An oversized EC2 instance is a single line item you can spot on a bill. Kubernetes waste is distributed — hundreds of pods each requesting slightly more CPU and memory than they use, compounding into nodes that are bin-packed based on inflated numbers. This is exactly why generic cloud cost tools that don't understand container-level allocation miss the majority of Kubernetes waste; it's invisible at the account level and only visible at the pod level.

Step 1: Measure Before You Touch Anything

Never right-size off gut feel or a single day of metrics. Run the Vertical Pod Autoscaler in recommendation-only mode (updateMode: "Off") for at least 1-2 weeks, capturing at least one peak-traffic period, before changing any resource requests. Tools like Goldilocks visualize VPA recommendations across a namespace, making this a lot faster than querying Prometheus manually pod by pod.

Step 2: Right-Size Requests to P95, Not Average

Setting requests at average usage guarantees you'll hit OOMKills and CPU throttling during normal traffic variance. Our standard approach:

  • CPU requests: Set at P90-P95 of observed usage over the measurement window.
  • Memory requests: Set slightly more conservatively (P95-P99) since OOMKills are more disruptive than CPU throttling.
  • Limits: Set CPU limits generously above requests (or unset, depending on your noisy-neighbor tolerance) and memory limits at a level that absorbs legitimate spikes without allowing a true runaway process to take down the node.

Step 3: Fix the Node Layer with Karpenter

Traditional Cluster Autoscaler scales pre-defined node groups, which forces you to guess the "right" instance types in advance. We generally migrate AWS-based clients to Karpenter, which calculates the exact instance type and size needed for pending pods and provisions it directly — no pre-defined node groups, no guessing, and typically faster provisioning (seconds rather than minutes) with tighter bin-packing.

Step 4: Use Spot for Fault-Tolerant Workloads

Stateless services behind a Horizontal Pod Autoscaler with multiple replicas are ideal Spot candidates — a single node interruption just means Kubernetes reschedules the affected pods elsewhere. We cover the broader Spot strategy in our AWS discount guide; the same principles apply directly to Kubernetes node pools.

Step 5: Namespace-Level Quotas and Attribution

Without ResourceQuotas per namespace, individual teams have no natural ceiling on requests, and cost attribution back to teams (per our cost allocation guide) becomes guesswork. Setting namespace quotas does double duty: it caps runaway resource requests and gives you a clean unit for showback reporting.

What This Looks Like in Practice

In a recent engagement covered in our Kubernetes scaling post, applying this right-sizing process across a client's clusters alongside a migration to Karpenter reduced their node-hour costs by roughly a third, without a single additional OOMKill incident in the following month — because the right-sizing was based on measured P95 data, not a guess.

Ongoing Governance, Not a One-Time Project

Resource requests drift again as code changes and traffic patterns shift. We recommend re-running the VPA recommendation pass quarterly, and using continuous Kubernetes cost visibility inside FinOps Co-Pilot to catch newly-introduced over-provisioning before it becomes the new normal. Want a cluster audit? Talk to our DevOps team.

Frequently Asked Questions

What is the biggest source of Kubernetes waste?

Over-provisioned resource requests, consistently — conservative "just in case" sizing that directly drives oversized, underutilized nodes.

Is Karpenter worth switching to from Cluster Autoscaler?

For AWS-based clusters, yes in most cases — it provisions the exact instance type needed in seconds rather than scaling pre-defined node groups.

How do you right-size without causing OOMKills?

Use historical usage data over 1-2 weeks including peak load, set requests near P95 usage, and set limits higher to absorb short spikes.

More Insights

Ready to Apply These Insights?

Schedule a consultation with our architects to discuss your specific challenges.

Get Started Today