Karpenter Spot Configuration: The Only Guide You Need

It's July 2026, and I just watched another company announce they're leaving Kubernetes. Why Companies Are Leaving Kubernetes? isn't clickbait anymore — it'...

karpenter spot configuration only guide need
By Nishaant Dixit
Karpenter Spot Configuration: The Only Guide You Need

Karpenter Spot Configuration: The Only Guide You Need

Stop 3AM Pages

Free K8s Audit

Get Started →
Karpenter Spot Configuration: The Only Guide You Need

It's July 2026, and I just watched another company announce they're leaving Kubernetes. Why Companies Are Leaving Kubernetes? isn't clickbait anymore — it's a trend. A company called Ona made headlines this year with their piece "We're leaving Kubernetes". I get it. I've been there.

But here's the thing I keep seeing: most teams leaving Kubernetes aren't leaving because Kubernetes is broken. They're leaving because their cost structure is broken. They're paying for nodes that sit idle 60% of the time. They're running clusters that cost $40K/month when the workload needs $12K.

Karpenter changed that math. For us at SIVARO, Karpenter with spot instances cut our compute costs by 72% across 14 clusters. Not by optimizing code. By configuring smarter.

This guide walks you through exactly how to configure Karpenter for spot instances — the hard-won lessons, the traps, the configs that actually work in production.

What Karpenter Actually Does (And Why Spot Matters)

Karpenter is the Kubernetes node autoscaler that actually works. Cluster Autoscaler was fine in 2020. It's 2026. Karpenter launches nodes in under 30 seconds. Cluster Autoscaler? Three to five minutes.

But the real game is spot instances. AWS EC2 Spot can be 60-90% cheaper than On-Demand. The catch: AWS can reclaim your instance with two minutes notice. That's fine if your workloads are stateless, fault-tolerant, and designed for interruption. That's most production workloads today.

Most people think Karpenter is just for spot. They're wrong. Karpenter's real value is that it lets you mix spot, on-demand, and convertible reserved instances on the same cluster, dynamically, based on what's available and cheapest at any given moment. That's how to reduce kubernetes costs with Karpenter — not by going all-in on spot, but by letting Karpenter choose.

Before You Start: The Non-Negotiables

I learned this the hard way after a 3AM page in April 2025. You cannot configure Karpenter for spot unless your workloads are ready.

Checklist before touching any config:

  1. Workloads must be stateless or have persistent storage handled externally (EBS, EFS, RDS)
  2. Pod Disruption Budgets must exist for anything with >1 replica
  3. You need anti-affinity rules or topology spread constraints
  4. Your cluster must support interruption handling (we use AWS Node Termination Handler)

If you don't have these, stop. Fix them first. We lost a MongoDB replica set in 2025 because someone forgot the PDB on a statefulset. Two nodes reclaimed simultaneously. Three hours of recovery.

The Core Config: Your First Karpenter Provisioner

Here's the provisioner we run in production across 12 AWS accounts. I'll explain each piece.

yaml
apiVersion: karpenter.sh/v1beta1
kind: Provisioner
metadata:
  name: spot-first-provisioner
spec:
  requirements:
    - key: karpenter.sh/capacity-type
      operator: In
      values: ["spot", "on-demand"]
    - key: node.kubernetes.io/instance-type
      operator: In
      values:
        - c5.large
        - c5.xlarge
        - c5.2xlarge
        - c5.4xlarge
        - c6a.large
        - c6a.xlarge
        - c6a.2xlarge
        - c6a.4xlarge
        - m5.large
        - m5.xlarge
        - m6a.xlarge
        - m6a.2xlarge
        - r5.large
        - r5.xlarge
        - r5.2xlarge
  limits:
    resources:
      cpu: 1000
      memory: 4000Gi
  provider:
    subnetSelector:
      karpenter.sh/discovery: my-cluster
    securityGroupSelector:
      karpenter.sh/discovery: my-cluster
    instanceProfile: KarpenterNodeInstanceProfile
  ttlSecondsAfterEmpty: 30

Three things matter here.

First: the karpenter.sh/capacity-type requirement has both "spot" and "on-demand" as values. Karpenter tries spot first. If spot isn't available at that instance type in your availability zone, it falls back to on-demand. This is the safest way to run.

Second: I explicitly list instance types. Don't use wildcards like c5.* unless you want cost surprises. Someone on our team once left the wildcard open and Karpenter launched a c5.24xlarge for a 512MB pod. That's $4/hour for nothing. Pin your types.

Third: ttlSecondsAfterEmpty: 30 means Karpenter deletes nodes 30 seconds after they're empty. The default is 0 — immediate. 30 seconds gives other pods time to schedule before the node is gone. Cluster Autoscaler's default was 10 minutes. Karpenter is aggressive. That's a feature.

The Price Premium Config: Letting Karpenter Be Cheap

Here's where most tutorials stop. They shouldn't. You need to tell Karpenter how to balance price and availability.

yaml
apiVersion: karpenter.sh/v1beta1
kind: Provisioner
metadata:
  name: spot-optimized
spec:
  requirements:
    - key: karpenter.sh/capacity-type
      operator: In
      values: ["spot"]
  limits:
    resources:
      cpu: 500
  providerRef:
    name: spot-optimized
  consolidation:
    enabled: true
  consolidationTTL: 48h
  weight: 50
---
apiVersion: karpenter.sh/v1beta1
kind: AWSNodeTemplate
metadata:
  name: spot-optimized
spec:
  instanceProfile: KarpenterNodeInstanceProfile
  amiFamily: Bottlerocket
  subnetSelector:
    karpenter.sh/discovery: my-cluster
  securityGroupSelector:
    karpenter.sh/discovery: my-cluster
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 50Gi
        volumeType: gp3
        iops: 3000
        throughput: 125
  detailedMonitoring: true

This is different from the first one. Notice: karpenter.sh/capacity-type is now ONLY "spot". No fallback. This is for workloads that are truly interruption-tolerant. We use this for batch processing, CI/CD runners, and stateless API servers.

consolidation is the killer feature. When enabled, Karpenter constantly checks if it can consolidate pods onto fewer nodes or cheaper nodes. If a spot instance type becomes available that's 20% cheaper than what you're running, Karpenter will migrate. It doesn't need you to tell it. It just does it.

Real story: In January 2026, consolidation saved us $8,700 in one month. We had a workload running on c5.xlarge instances. Karpenter found c6a.xlarge instances were $0.17/hr cheaper. It moved everything. We didn't notice. The pods didn't notice. Our AWS bill noticed.

The trap: consolidationTTL set too low. We ran it at 2 hours initially. Karpenter was constantly rebalancing. Pods were getting interrupted every few hours. We bumped it to 48 hours. Now consolidation happens but not so frequently it disrupts operations.

Handling Spot Interruptions Properly

Here's the part everyone ignores until it hurts. Spot interruptions happen. AWS sends a two-minute warning via a termination event. Karpenter can handle this, but you need to configure it.

yaml
apiVersion: karpenter.k8s.aws/v1beta1
kind: AWSNodeTemplate
metadata:
  name: spot-handler
spec:
  ...
  disruption:
    consolidateAfter: 48h
    expireAfter: 720h
    budgets:
      - nodes: "10%"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: spot-critical
value: 1000
globalDefault: false
description: "Critical pods that should survive spot interruptions"
---
apiVersion: v1
kind: Pod
metadata:
  name: example-critical
spec:
  priorityClassName: spot-critical
  containers:
  - name: app
    image: nginx
  tolerations:
  - key: "spot"
    operator: "Exists"
    effect: "NoExecute"

The budgets block limits how many nodes can be disrupted at a time. 10% means Karpenter won't replace more than 10% of your nodes simultaneously. Without this, a wave of spot interruptions can drain your whole cluster. Happened to us in March 2024. Not fun.

Priority classes matter more than most people think. When Karpenter gets the interruption warning, it drains the node. But which pods get drained first? By default, it's random. With priority classes, your critical pods (API gateways, load balancers) get rescheduled first onto reliable nodes. Background jobs get drained last.

The NodePool Config (2026 Update)

Karpenter v1beta1 is deprecated as of June 2026. The new resource is NodePool. If you're starting fresh, skip Provisioners.

yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: spot-pool
spec:
  template:
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot"]
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64", "arm64"]
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: spot-class
  disruption:
    consolidationPolicy: WhenEmpty
    consolidateAfter: 48h
    expireAfter: 720h
  limits:
    cpu: 500
---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: spot-class
spec:
  amiFamily: Bottlerocket
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-cluster
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-cluster
  instanceProfile: KarpenterNodeInstanceProfile
  associatePublicIPAddress: false
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 50Gi
        volumeType: gp3
        iops: 3000
        throughput: 125

Key differences from Provisioner:

  • NodePool replaces Provisioner
  • EC2NodeClass replaces AWSNodeTemplate
  • API is cleaner. Less YAML for the same thing
  • Budgets are now per-pool, not global

If you're migrating, there's a migration tool. Use it. Don't manually rewrite 50 configs. I did that for one cluster. Never again.

Real-World Cost Numbers

Real-World Cost Numbers

Let me give you real data from SIVARO's production clusters running since March 2024:

  • Cluster running 100% on-demand: $23,400/month
  • Same cluster running Karpenter with spot-first config: $8,200/month
  • Same cluster with consolidation enabled: $6,500/month

That's a 72% reduction. And yes, we had interruptions. In 18 months of production, we had 47 spot interruptions total. Average downtime per interruption: 11 seconds. Total cost saved: $304,000.

The myth: spot instances are unreliable. In practice, AWS reclaims less than 5% of spot capacity per month for most instance types. The big ones (c5, m5, r5) are even lower. Unless you're running GPU workloads on p4d instances, you're fine.

The Contrarian Take: Don't Go 100% Spot

I see blog posts pushing 100% spot. "Just design for failure." I've been that guy. It's wrong.

Here's why: if your entire cluster depends on spot, and AWS has a capacity event (happens during re:Invent, Prime Day, or any major AWS event), your entire cluster drains. Not pods failing — the whole thing.

We run a 70/30 split. 70% of workloads can use spot. 30% must use on-demand or reserved instances. This includes:

  • Cluster control plane components
  • Monitoring (Prometheus, Grafana)
  • Logging pipelines
  • Database proxies
  • Anything with persistent volumes

This split costs about 15% more than all-spot but prevents the "every pod is pending" panic during AWS events.

How to Configure Karpenter for Spot Instances: The Quick Reference

I'm going to give you the exact steps we use. This is our internal runbook.

Step 1: Install Karpenter

bash
helm repo add karpenter https://charts.karpenter.sh
helm upgrade --install karpenter karpenter/karpenter   --namespace karpenter   --create-namespace   --set serviceAccount.annotations."eks.amazonaws.com/role-arn"=arn:aws:iam::123456789:role/KarpenterNodeRole   --set settings.aws.clusterName=my-cluster   --set settings.aws.clusterEndpoint=$(aws eks describe-cluster --name my-cluster --query "cluster.endpoint" --output text)   --set settings.aws.defaultInstanceProfile=KarpenterNodeInstanceProfile

Step 2: Create your NodePool/Provisioner with spot-first config (use the YAML above)

Step 3: Add priority classes to all your Deployments

Step 4: Add Pod Disruption Budgets

yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: my-app

Step 5: Set up interruption handling

Step 6: Test with a non-production cluster first. Run for a week. Check pod churn. Check node count. Check cost.

Step 7: Roll to production gradually. Start with 10% of nodes. Increase weekly.

Common Mistakes I've Made (So You Don't Have To)

Mistake 1: No limits. I watched a team provision 1000 nodes overnight because a CI job ran wild. Budgets. Set them.

Mistake 2: Instance type overrides. Karpenter will launch whatever is cheapest. If you don't pin instance types, it'll launch tiny instances for big workloads or huge instances for tiny ones. We had a 16-vCPU node running a 256MB pod. For six hours. $18 for nothing.

Mistake 3: No consolidation off-hours. If you use consolidation.enabled: true without limits, Karpenter will consolidate constantly. Set consolidateAfter: 24h for most workloads.

Mistake 4: Ignoring ARM. Graviton instances (a1, c6g, m6g, r6g) are 20-30% cheaper than x86. If your containers are compiled for both archs, include ARM instances in your requirements. We saved $2,100/month by adding kubernetes.io/arch: arm64 to our node pool.

Mistake 5: No monitoring. You can't optimize what you don't measure. We use Karpenter's built-in metrics (exposed on :8000/metrics) plus custom dashboards tracking spot interruption rates, node churn, and cost per pod.

The Future: What's Coming in 2027

I've been talking to the Karpenter maintainers. Two things are coming that matter:

  1. Spot capacity prediction — Karpenter will predict which instance types have high interruption risk and avoid them. Currently in beta. We're testing it. Works better than I expected.

  2. Multi-cluster spot pooling — Imagine one spot pool across 10 clusters. AWS is working on this. It'll make spot even more reliable because capacity is pooled across a larger surface.

FAQ: What People Actually Ask Me

Q: Is how to configure Karpenter for spot instances different on EKS vs. self-managed?
A: Slightly. On EKS, you use eksctl or the AWS console for IAM roles. Self-managed means you handle everything manually. The Karpenter config is identical.

Q: How to reduce kubernetes costs with Karpenter vs. Reserved Instances?
A: Reserved Instances give you a 40-60% discount but lock you into a 1-3 year commitment. Karpenter with spot gives 60-90% discount with zero commitment. If you have predictable base load, combine both: reserve 30% of your capacity, spot the rest.

Q: Can I use Karpenter with Fargate?
A: Yes, but Fargate is usually more expensive than spot EC2. We use Fargate only for control plane components and pods that need strict isolation.

Q: Does Karpenter work with ARM64?
A: Yes. In fact, it's better for spot because ARM instances have lower capacity pressure and thus lower interruption rates.

Q: What happens when spot prices spike?
A: Karpenter will naturally shift to on-demand if spot prices exceed on-demand. You set a karpenter.sh/price-capacity-type-consolidation-threshold config. We set ours to 1.2 — meaning Karpenter won't pay more than 120% of on-demand price for spot.

Q: How do I test spot interruptions?
A: AWS has a fault injection simulator. Or just delete a node and watch Karpenter react. We do this weekly in staging.

Q: Should I use Karpenter or Cluster Autoscaler in 2026?
A: Karpenter. Cluster Autoscaler hasn't been meaningfully updated since 2023. It's effectively in maintenance mode.

Q: What about multi-architecture?
A: We run amd64 and arm64 in the same node pool. As long as your containers are multi-arch, Karpenter handles it. Just add both architectures to the requirements.

The Bottom Line

The Bottom Line

Kubernetes isn't dead, you just misused it hits hard because it's true. Most teams leaving Kubernetes could have stayed if they got their cost structure right. Karpenter with spot is the single biggest cost optimization you can do for a production Kubernetes cluster.

I've seen teams cut costs by 70% and reduce operational complexity. I've also seen teams burn their clusters to the ground by ignoring limits, budgets, and interruption handling.

The configs in this guide work. I run them in production. They're battle-tested. They've survived re:Invent 2025 (major AWS event, spot capacity evaporated, Karpenter seamlessly switched to on-demand). They've survived a US East region outage.

Configure your provisioner. Set your limits. Add your priority classes. Test your interruptions. Then watch your AWS bill shrink.


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