← Back to blog

2026-06-03 · 8 min read

Running Kubernetes on a Budget: Lessons From Cost-Constrained Engineering

Practical ways to run Kubernetes without burning money, right-sizing, autoscaling to zero, spot nodes, and the cost-aware habits I learned engineering from a constrained environment.

#kubernetes#finops#cost-optimization#devops#cloud
Running Kubernetes on a Budget: Lessons From Cost-Constrained Engineering

Running Kubernetes on a Budget: Lessons From Cost-Constrained Engineering

Kubernetes has a reputation for being expensive. It doesn't have to be. A lot of the cost comes from defaults nobody revisited and resources nobody owns. Engineering from a constrained environment taught me to treat every idle CPU as money on fire, and those habits translate directly into cheaper, healthier clusters for anyone.

Here's what actually moves the needle.

1. Right-size requests and limits (the biggest win)

The single most common cause of cloud waste on Kubernetes is over-requested pods. A pod that requests 1 CPU but uses 100m reserves 10x what it needs, and the scheduler packs nodes based on requests, so you pay for the reservation, not the usage.

  • Measure real usage with kubectl top and Prometheus over a representative window.
  • Set requests close to the p95 of actual usage; set limits to protect noisy neighbours.
  • Use the Vertical Pod Autoscaler in recommendation mode to get data-driven numbers.

This alone routinely cuts node count by 30-50%.

2. Autoscale nodes: and scale to zero

  • Cluster Autoscaler or Karpenter adds/removes nodes with demand. Karpenter is faster and bin-packs better, consolidating workloads onto fewer nodes.
  • For non-prod and batch, scale to zero when idle. A dev cluster running 24/7 at 5% utilisation is pure waste.

3. Use spot / preemptible nodes for the right workloads

Stateless services, CI runners, and batch jobs don't need on-demand pricing. Spot/preemptible nodes are 60-90% cheaper.

  • Run them in a dedicated node pool with taints, and tolerate interruptions.
  • Keep a small on-demand pool for stateful or interruption-sensitive workloads.
  • Spread across instance types and zones so a single capacity reclaim doesn't take you down.

4. Set quotas so cost can't run away

ResourceQuota and LimitRange per namespace put a ceiling on what each team can consume. This turns "cost surprise" into "cost boundary", a team can't accidentally request 200 CPUs.

5. Clean up the quiet waste

  • Orphaned PersistentVolumes after pods are deleted.
  • Unused LoadBalancer services: each one is a paid cloud load balancer.
  • Idle environments left running over weekends.
  • Over-replicated deployments sized for traffic that never came.

A monthly sweep catches most of it; better, automate the detection.

6. Make cost visible

You can't fix what no one sees. Tools like OpenCost or Kubecost attribute spend to namespaces and teams. When a team sees their own bill, behaviour changes faster than any mandate.

7. Pick managed vs self-hosted deliberately

The control plane, databases, and queues are where "self-host to save money" often backfires, you trade a predictable bill for unpredictable on-call. Sometimes the cheaper option overall is the managed service. Cost includes engineering time, not just the invoice.

The mindset that makes it stick

Cost-aware engineering isn't austerity, it's discipline. The same instincts that keep a cluster cheap (measure real usage, remove waste, right-size, automate) are the instincts that keep it reliable. Efficiency and resilience are the same skill pointed at different metrics.

If your Kubernetes bill is climbing and no one's quite sure why, that's a solvable problem, and usually a 30-50% one.


I help teams get their Kubernetes and cloud costs under control as part of my consulting work. Reach out if that's you.

Share:LinkedInXWhatsApp

Related articles

Reactions & comments