Learn Karpenter - Utilization & Cost Optimization
Episode 9 of 23

Learn Karpenter - Utilization & Cost Optimization

Optimizing cluster costs by prioritizing Spot, choosing efficient instance families, and avoiding overprovisioning; and handling EC2 Spot interruptions and health events automatically through Karpenter's queue processor with pod drain and re-scheduling.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 8 you saw how pod-side scheduling constraints determine NodePool selection. Episode 9 covers the cost side: how to make Karpenter work as cheaply as possible without sacrificing availability. We'll break down two big themes — cost-aware scaling, which defines the pricing strategy, and interruption handling, which keeps applications alive when AWS reclaims capacity.

After this episode, you'll understand how to prioritize Spot, choose efficient instance families, avoid overprovisioning, and how Karpenter responds to EC2 interruption notifications automatically.

Cost-Aware Scaling

Prioritize Spot for Tolerant Workloads

Spot is the key to Karpenter's biggest savings. Spot instance prices on AWS are far cheaper than On-Demand, and Karpenter is designed to leverage them via the values list on the karpenter.sh/capacity-type requirement. Stateless, fault-tolerant workloads — like backend APIs, worker queues, and batch jobs — are a great fit for Spot.

Spot priority with On-Demand fallback
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: spot-first
spec:
  template:
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot", "on-demand"]
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default

Tip

The order of values in values sets preference, not a hard rule. The leftmost value like spot is tried first, and the values to its right become backup when the first capacity isn't available.

Choose Efficient Instance Families

Not all instance types are equally efficient for one workload. Newer generation instances usually offer better performance per unit price than their predecessors. Karpenter supports the karpenter.k8s.aws/instance-generation requirement to filter instance generations.

Limit instance generation and family
spec:
  template:
    spec:
      requirements:
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["4"]
        - key: node.kubernetes.io/instance-type
          operator: In
          values:
            - m7g.large
            - m7g.xlarge
            - c7g.large
            - r7g.large

The Gt operator above asks for generations greater than four, so Karpenter won't pick old-generation instances that waste money for the same need.

Avoid Overprovisioning

Overprovisioning happens when available capacity far exceeds the need. The most common cause is an instance type that's too large. This is where binpacking from episode 6 comes into play: let Karpenter pick the smallest sufficient size, and limit the instance type list so it doesn't stray far from the real need.

StrategyEffect on Cost
Spot firstBig discount for tolerant workloads
Filter for latest generationBetter performance per unit price
Limit instance sizeAvoids overprovisioning
Active consolidationIdle nodes automatically trimmed

Separating Spot and On-Demand per NodePool

For workloads that must not be interrupted, create a separate NodePool that only contains on-demand. This strategy keeps cost and availability boundaries clear without complicating configuration.

On-demand-only NodePool
spec:
  template:
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["on-demand"]

Interruption Handling

What Happens When a Spot Instance Is Reclaimed

Spot capacity can be reclaimed by AWS at any time. Before termination, AWS sends a two-minute notice. In addition, AWS also sends health events like instance rebalance recommendations and failed status checks. If this happens to a node without handling, the pods inside simply disappear.

Karpenter's Queue Processor

Karpenter handles this via a component called the queue processor. The sequence is as follows:

  1. AWS EventBridge detects an interruption, rebalance, or termination event on an instance.
  2. The event is forwarded to an SQS queue configured specifically for Karpenter.
  3. The Karpenter controller reads that queue and finds the affected node.
  4. The node is immediately drained and its pods re-scheduled onto another node before the instance actually dies.

The queue name configuration lives in the karpenter-global-settings ConfigMap in the karpenter namespace.

Queue name in karpenter-global-settings
apiVersion: v1
kind: ConfigMap
metadata:
  name: karpenter-global-settings
  namespace: karpenter
data:
  aws.interruptionQueueName: karpenter-queue-production

Important

The SQS queue must be created and connected to EventBridge before Karpenter is installed. Without this queue, Karpenter can't receive interruption notifications and Spot nodes will be lost without a drain.

Process Order on Interruption

When an interruption notification is received, Karpenter doesn't delete the node immediately. The process is gradual: the karpenter.sh/interruption annotation is attached to the node to mark the cause, pods start draining, a new node is created if needed, and only after all pods have moved is the instance terminated.

See nodes that received interruption notifications
kubectl get nodes -l karpenter.sh/managed=true -o jsonpath='{.items[?(@.metadata.annotations.karpenter\.sh/interruption)].metadata.name}'

Warning

The two-minute window given by AWS is a hard limit. Make sure your workload doesn't depend on long-running drain phases, like dumping large persistence, so the process finishes before the instance is terminated.

Healthy Spot vs Problem Nodes

Besides Spot interruptions, the queue processor also responds to health events. If EC2 detects a problematic instance via status checks, Karpenter treats that node like a node about to be terminated: drained and replaced. This keeps the cluster healthy even when the underlying instance starts failing.

Common Mistakes

Spot for Stateful Workloads

Putting a database or single-replica queue on Spot is an invitation to trouble. An interruption at any moment will cut the service. Limit Spot to workloads that can disappear and be born again.

Ignoring Queue Configuration

Installing Karpenter without creating the SQS queue leaves interruption protection inactive. Make sure the EventBridge, SQS, and ConfigMap chain is correct before production.

Closing

Cost and availability aren't mutually exclusive. With proper Spot priority, efficient instance selection, and automatic interruption handling, Karpenter can cut costs while keeping applications available.

Key takeaways:

  • Spot is the main savings source — place tolerant workloads on Spot with On-Demand fallback.
  • Instance filtering matters — the right generation and family avoids waste.
  • Interruption isn't the end of the world — the queue processor turns a two-minute notice into a clean drain and re-schedule.
  • Queue configuration must be checked — without EventBridge and SQS, interruption protection doesn't work.

In episode 10, you'll learn to separate workloads across several NodePools with weight and taints, plus best practices for running Karpenter across multiple clusters. See you there!