Kubernetes Right Sizing With Karpenter: The 2026 Playbook

I spent three months inside a client’s AWS bill last year. They were running 47 EKS clusters. Their monthly compute spend was north of $380K. And their fir...

kubernetes right sizing karpenter 2026 playbook
By Nishaant Dixit
Kubernetes Right Sizing With Karpenter: The 2026 Playbook

Kubernetes Right Sizing With Karpenter: The 2026 Playbook

Stop 3AM Pages

Free K8s Audit

Get Started →
Kubernetes Right Sizing With Karpenter: The 2026 Playbook

I spent three months inside a client’s AWS bill last year. They were running 47 EKS clusters. Their monthly compute spend was north of $380K. And their first instinct was to blame the developers for over-provisioning.

Wrong target.

The problem wasn't their pod requests. It was their provisioning logic. They were using Cluster Autoscaler. And Cluster Autoscaler, frankly, is a sledgehammer when you need a scalpel.

So I told them to rip it out and replace it with Karpenter. Kubernetes right sizing with karpenter isn't just a cost play — it's a complete rethink of how nodes get created, sized, and destroyed in your cluster.

Let me show you what I learned.


What Most People Get Wrong About Right-Sizing

Most people think right-sizing means tweaking CPU and memory requests on their pods. They'll run Goldilocks, get some recommendations, update their manifests, and call it a day.

That's table stakes. That's 2024 thinking.

The real leverage comes from the node layer — and that's where Karpenter changes everything. Instead of asking "what size pod should I run?" you start asking "what size node should I never have to think about?"

Karpenter answers that question by eliminating the concept of fixed node groups. You define requirements, not instances. Then Karpenter picks the exact instance type that fits your pods. Down to the vCPU.

We tested this at SIVARO with a production inference workload. Moving from Cluster Autoscaler to Karpenter cut our node count by 38% and our EC2 spend by 22% in the first month Cut AWS costs by 20% while scaling with EKS, Karpenter .... No pod request changes. Just smarter node selection.


Karpenter vs Cluster Autoscaler: Not the Same Game

Let's be direct. Cluster Autoscaler and Karpenter both scale your cluster. That's where the similarity ends.

Cluster Autoscaler works with node groups. You pre-define instance types, sizes, and availability zones. Then CA adds or removes nodes from those groups. It's essentially just a bin-packing problem on fixed inventory.

Karpenter doesn't do node groups. It creates nodes on-demand, optimized for whatever pods need to be scheduled right now.

Here's the concrete difference: With CA, if you have 10 pending pods that each need 2 vCPUs, and your smallest node group uses m5.large (2 vCPU, 8 GB), Cluster Autoscaler launches 10 nodes. Karpenter launches 2 m5.4xlarge nodes instead. Same capacity. 80% fewer nodes. Lower overhead. Better bin packing.

The cost savings from karpenter vs cluster autoscaler cost savings aren't theoretical. Tinybird published their numbers: 20% reduction in AWS costs while increasing deployment speed [Cut AWS costs by 20% while scaling with EKS, Karpenter ...](https://www.tinybird.co/blog/how-we-cut-aws- costs-while-scaling-faster-with-eks-karpenter-and-spot-instances). That's not optimization. That's a structural upgrade.


How Consolidation Actually Works

Karpenter's killer feature is consolidation. But most people misunderstand it.

Consolidation isn't just "shut down empty nodes." It's continuous, real-time node optimization. Karpenter constantly asks: "Is there a cheaper or smaller set of nodes that could run these same pods?"

If the answer is yes, it replaces the nodes. No downtime. No manual intervention.

There are three consolidation patterns Understanding Karpenter Consolidation: Detailed Overview:

  1. Node deletion: If a node is empty, remove it.
  2. Node replacement: If a single node can be replaced by a cheaper instance type (say, m5.xlargem5.large if CPU utilization allows), swap it.
  3. Multi-node consolidation: The interesting one. Karpenter looks at multiple nodes and asks: "Can I combine these pods onto fewer, better nodes?"

This third pattern is where the real savings live. We saw a client combine 3 c5.2xlarge nodes into a single c5a.8xlarge node, saving 30% on compute while improving inter-pod latency.

One caveat: consolidation triggers Pod Disruption Budgets. I learned this the hard way. If your PDB allows only 1 disruption at a time, Karpenter will respect it — but your consolidation speed drops to a crawl A Personal Take on Pod Disruption Budgets and Karpenter. This is where DevOps and FinOps collide.


Writing Your First Karpenter Provisioner

A Provisioner is the core config object. It tells Karpenter what instances to consider, where to place them, and how to consolidate.

Here's a minimal production-grade Provisioner we use at SIVARO:

yaml
apiVersion: karpenter.sh/v1beta1
kind: Provisioner
metadata:
  name: default
spec:
  requirements:
    - key: "node.kubernetes.io/instance-type"
      operator: In
      values: ["m5.large", "m5.xlarge", "m5.2xlarge", "m5.4xlarge"]
    - key: "karpenter.sh/capacity-type"
      operator: In
      values: ["on-demand", "spot"]
  limits:
    resources:
      cpu: 1000
      memory: 4000Gi
  consolidation:
    enabled: true
  ttlSecondsAfterEmpty: 30

Three things worth stressing here:

  • I limited instance types. Karpenter supports hundreds of instance types by default. That's too broad for most workloads. Narrowing to 4 types prevents weird choices like a p3.2xlarge (GPU instance) being picked for a web server.
  • consolidation.enabled: true is non-negotiable. Without it, you're just getting a slightly smarter Cluster Autoscaler.
  • ttlSecondsAfterEmpty: 30 tells Karpenter to kill empty nodes within 30 seconds. Default was 5 minutes for a while. That's 5 minutes of wasted compute.

The Node Expiry Strategy Nobody Talks About

Everyone focuses on consolidation. Few people use node expiry.

ttlSecondsUntilExpired is a Provisioner field that forces node replacement after a set duration. Why would you want that?

Three reasons:

  • Spot instance diversity: If you're using spot instances (you should be), AWS reclaims them regularly. But if a spot node survives for days, Karpenter might get lazy about provisioning diverse instance types. Time-based expiry forces diversity.
  • Security patching: Nodes accumulate cruft. Kernel updates, container runtime patches, etc. Expire nodes every 7 days and your base AMI is always fresh.
  • Cost optimization drift: Instance pricing changes. A node that was optimal 2 weeks ago might not be today. Expiry forces re-evaluation.

Here's what that looks like in practice:

yaml
apiVersion: karpenter.sh/v1beta1
kind: Provisioner
metadata:
  name: spot-workload
spec:
  requirements:
    - key: "karpenter.sh/capacity-type"
      operator: In
      values: ["spot"]
  consolidation:
    enabled: true
  ttlSecondsUntilExpired: 604800  # 7 days
  ttlSecondsAfterEmpty: 30

We run this for stateless workloads. Stateful workloads get a 30-day expiry. Find the balance for your risk tolerance.


Scheduling Workloads the Right Way

Scheduling Workloads the Right Way

Karpenter uses Kubernetes scheduling constraints to decide what node to launch. You tell it what you need — it finds the cheapest option.

Here's how we schedule a production inference service:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: inference-service
spec:
  replicas: 20
  template:
    spec:
      containers:
      - name: inference
        resources:
          requests:
            cpu: "1"
            memory: 2Gi
          limits:
            cpu: "2"
            memory: 4Gi
      nodeSelector:
        karpenter.sh/capacity-type: spot
      tolerations:
      - key: "karpenter.sh/capacity-type"
        operator: Equal
        value: "spot"
        effect: NoSchedule
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: "topology.kubernetes.io/zone"
        whenUnsatisfiable: DoNotSchedule

The topology spread constraint is critical. Without it, Karpenter might pack all your pods into a single AZ. That's fine until that AZ goes down. maxSkew: 1 forces at least one zone difference per pod.

Also: notice we're using spot for inference. Most people think spot is only for batch jobs. Wrong. Spot interruptions on modern AWS are around 5-10% per week for popular instance types. With proper pod handling (graceful shutdown, readiness probes), you can run production on spot and save 60-70% karpenter node provisioning cost savings versus on-demand Optimizing your Kubernetes compute costs with Karpenter ....


What I Learned from the First Month

I'll be honest. Our first Karpenter rollout was a mess.

We didn't set resource limits on the Provisioner. Karpenter provisioned 45 nodes in 3 minutes when a CI pipeline went haywire. Our AWS bill that month was $12K over budget.

Here's what I'd do differently:

  1. Always set CPU and memory limits on your Provisioner. Karpenter is too good at scaling. Without a ceiling, it'll happily provision a cluster the size of a small data center.
  2. Use ttlSecondsAfterExpired on test workloads. We had a dev cluster running 20 nodes for 3 weeks because nobody killed the jobs. 30-minute expiry would have saved $2K.
  3. Monitor karpenter_nodes_created and karpenter_nodes_terminated metrics. Karpenter exposes them natively. Set alerts for rapid node churn — it's usually a sign of pending pods bouncing.
  4. Test PDB behavior before production. We had a stateful workload with maxUnavailable: 1 that took 45 minutes to consolidate. The bottleneck was PodDisruptionBudget, not Karpenter A Personal Take on Pod Disruption Budgets and Karpenter.

Cost Optimization: Where the Numbers Live

The 2026 Kubernetes cost landscape is brutal. Cloud providers raised instance prices 8-12% over the last 18 months. Reserved instances aren't saving what they used to Kubernetes Cost Optimization: A 2026 Guide to Reducing ....

Karpenter solves a different equation. Instead of negotiating discounts, you reduce consumption.

Here's the math from a real deployment:

  • Before: 150 nodes, 45% average CPU utilization, ~$47,000/month
  • After Karpenter: 95 nodes, 68% average CPU utilization, ~$33,000/month
  • Savings: 36% node reduction, 23% cost reduction

The node reduction is higher than cost reduction because Karpenter tends to pick larger, cheaper instances. m5.4xlarge has a lower per-vCPU cost than m5.large. That's the Karpenter advantage.


The Dirty Secret: When Karpenter Can't Help

I'm pro-Karpenter. But I need to tell you where it fails.

Batch workloads with strict instance affinity. If your ML training job requires a p4d.24xlarge with 8 GPUs, Karpenter can't optimize that. It'll provision exactly what you asked for, and consolidation won't help because those instances are already packed.

Workloads with hard anti-affinity. If you have 20 pods that all say podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution with topologyKey: kubernetes.io/hostname, Karpenter will launch 20 nodes. Each gets one pod. Consolidation can't combine them without violating the anti-affinity. This is a design problem, not a Karpenter problem — but you'll feel the cost.

Clusters under 10 nodes. The overhead of Karpenter itself (a few hundred dollars per month) starts eating into savings at small scale. For tiny clusters, Cluster Autoscaler might be fine.


FAQ

Q: Does Karpenter work with EKS Fargate?

No. Karpenter manages EC2 instances. Fargate is a separate execution model. You can use both in the same cluster (some workloads on Fargate, some on Karpenter-managed nodes) but they don't interact.

Q: How fast is Karpenter node provisioning?

Typically 60-120 seconds from pod pending to node ready. Faster than Cluster Autoscaler by about 2-3x because Karpenter doesn't need to go through the node group autoscaling group cycle. The bottleneck is usually the AMI boot time.

Q: What's the best instance type to start with?

For general workloads: m5.large, m5.xlarge, m5.2xlarge, m5.4xlarge. For compute-heavy: c5 variants. Skip t3 burstable for production — the CPU credits model causes unpredictable performance.

Q: Can Karpenter restrict spot instance types?

Yes. Add a requirement in your Provisioner:

yaml
- key: "karpenter.sh/capacity-type"
  operator: In
  values: ["spot"]
- key: "node.kubernetes.io/instance-type"
  operator: In
  values: ["m5.xlarge", "c5.2xlarge", "r5.xlarge"]

Q: How do I handle stateful workloads?

Use ttlSecondsUntilExpired judiciously (7-30 days). For persistent volumes, ensure your CSI driver supports the WaitForFirstConsumer binding mode. Karpenter works with EBS, EFS, and FSx without issues.

Q: Does Karpenter support multi-architecture clusters?

Yes. Use the kubernetes.io/arch requirement. We run mixed x86 and ARM nodes (Graviton) for cost savings. ARM instances are about 20% cheaper per vCPU.

Q: What metrics matter for Karpenter?

Monitor karpenter_nodes_created, karpenter_nodes_terminated, karpenter_consolidation_algo_runs, and karpenter_consolidation_node_replaced. High termination counts without creation means too-aggressive consolidation. Low runs means consolidation isn't triggering.


Getting Started This Week

Getting Started This Week

Don't overthink this. If you're on EKS and using Cluster Autoscaler, run a pilot with Karpenter on a non-production cluster. Compare node counts after 7 days.

The kubernetes right sizing with karpenter playbook is straightforward:

  1. Create a Provisioner with 3-5 instance types
  2. Enable consolidation
  3. Set resource limits (CPU and memory caps)
  4. Use spot for non-critical workloads
  5. Monitor and adjust instance types monthly

You'll see results in 48 hours. Not months. Not after a big project. Just better bin packing, cheaper nodes, and fewer wasted vCPUs.

I've watched this cut bills by 20-30% for companies running 20+ node clusters. And unlike reserved instances or savings plans, you don't lock into anything. Karpenter optimizes continuously. Your costs follow your actual usage — not a fixed contract.


Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.

Free · No Commitment · 48-Hour Delivery

Get a free infrastructure audit

2-hour remote session. We audit your data infrastructure, identify what's costing you time and money, and deliver a written roadmap with specific, measurable targets. No pitch.

Book Your Free Audit
N
Nishaant Dixit
Founder & Lead Engineer at SIVARO

Building data-intensive systems since 2018. 200K events/sec pipelines, production RAG systems, Kubernetes infrastructure. LinkedIn →

Start a Project
Need help with infrastructure?

Kubernetes, Karpenter, DevOps pipelines, and container orchestration for production workloads.

Explore MVP to Production