Karpenter Complete Guide 2026: Smarter Kubernetes Node Autoscaling
Karpenter replaces Cluster Autoscaler with faster, more cost-efficient node provisioning. Learn architecture, NodePools, disruption budgets, Spot integration, and production best practices.
Cluster Autoscaler has been the default Kubernetes node autoscaling solution for years. It works — but it's slow, it's tied to Auto Scaling Groups, and it makes suboptimal instance choices. Karpenter was built to fix all of that.
This guide covers Karpenter architecture, configuration, Spot instance integration, and production-ready patterns for 2026.
What is Karpenter?
Karpenter is an open-source Kubernetes node provisioner built by AWS (now a CNCF project). Instead of working through Auto Scaling Groups, Karpenter talks directly to cloud provider APIs to provision exactly the right nodes for pending pods.
Key differences from Cluster Autoscaler:
| Feature | Cluster Autoscaler | Karpenter |
|---|---|---|
| Provisioning speed | 2-5 minutes | 30-60 seconds |
| Instance selection | Fixed ASG types | Best-fit from any instance family |
| Spot support | ASG-based spot | First-class, multi-family spot |
| Bin packing | Limited | Aggressive consolidation |
| AWS-native | Partial | Deep integration |
Architecture Overview
┌─────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ Pod (Pending) → Karpenter Controller │
│ ↓ │
│ NodePool + EC2NodeClass │
│ ↓ │
│ AWS EC2 Fleet API │
│ ↓ │
│ New Node Joins Cluster (under 60s) │
└─────────────────────────────────────────┘
Karpenter watches for unschedulable pods, evaluates which node types would fit, and calls EC2 directly to provision the best-fit instance. No ASG required.
Installing Karpenter on EKS
Prerequisites:
- EKS cluster (1.23+)
- AWS CLI configured
helmandkubectlinstalled
Step 1: Set environment variables
export CLUSTER_NAME="my-eks-cluster"
export AWS_DEFAULT_REGION="us-east-1"
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export TEMPOUT=$(mktemp)Step 2: Create IAM roles
# Download and apply CloudFormation template
curl -fsSL https://raw.githubusercontent.com/aws/karpenter-provider-aws/v1.0.0/website/content/en/preview/getting-started/getting-started-with-karpenter/cloudformation.yaml > $TEMPOUT
aws cloudformation deploy \
--stack-name "Karpenter-${CLUSTER_NAME}" \
--template-file "${TEMPOUT}" \
--capabilities CLOUD_FORMATION_DECLARE_IAM_RESOURCES \
--parameter-overrides "ClusterName=${CLUSTER_NAME}"Step 3: Install with Helm
helm registry logout public.ecr.aws
helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter \
--version "1.0.0" \
--namespace "kube-system" \
--set "settings.clusterName=${CLUSTER_NAME}" \
--set "settings.interruptionQueue=${CLUSTER_NAME}" \
--set controller.resources.requests.cpu=1 \
--set controller.resources.requests.memory=1Gi \
--set controller.resources.limits.cpu=1 \
--set controller.resources.limits.memory=1Gi \
--waitVerify:
kubectl get pods -n kube-system -l app.kubernetes.io/name=karpenterLearn Karpenter hands-on: KodeKloud has EKS labs that walk through Karpenter installation and configuration in real AWS environments.
NodePool Configuration
NodePool (formerly Provisioner) defines what kinds of nodes Karpenter can create.
Basic NodePool:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: kubernetes.io/os
operator: In
values: ["linux"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["2"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
limits:
cpu: 1000
memory: 1000Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1mNodePool with Spot instances:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: spot-pool
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"] # Spot preferred, on-demand fallback
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-size
operator: NotIn
values: ["nano", "micro", "small"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 30s
budgets:
- nodes: "20%" # Don't disrupt more than 20% of nodes at onceEC2NodeClass Configuration
EC2NodeClass defines AWS-specific node configuration (AMI, subnets, security groups).
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
amiSelectorTerms:
- alias: al2023@latest # Amazon Linux 2023, always latest
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: my-eks-cluster
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: my-eks-cluster
role: "KarpenterNodeRole-my-eks-cluster"
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 50Gi
volumeType: gp3
encrypted: true
iops: 3000
throughput: 125
tags:
Environment: production
ManagedBy: KarpenterSpot Instance Best Practices
Karpenter's Spot integration is superior to Cluster Autoscaler because it diversifies across instance families automatically.
Best practices for Spot:
# Allow many instance types to maximize Spot availability
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r", "t"]
- key: karpenter.k8s.aws/instance-cpu
operator: In
values: ["4", "8", "16", "32"]Handle Spot interruptions with pod disruption budgets:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: "75%"
selector:
matchLabels:
app: my-appUse node affinity for critical workloads to prefer on-demand:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]Disruption and Consolidation
Karpenter's consolidation actively removes underutilized nodes to save cost — a feature Cluster Autoscaler struggles with.
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 5m
budgets:
# Never disrupt during business hours for production
- schedule: "0 9 * * 1-5" # 9 AM Mon-Fri UTC
duration: 9h
nodes: "0" # 0 = no disruption during this window
# Allow normal consolidation otherwise
- nodes: "10%"Monitoring Karpenter
Key metrics to watch:
# Pending pods (should be near 0 in steady state)
karpenter_pods_state{state="Pending"}
# Node provisioning latency
karpenter_nodes_termination_time_seconds_bucket
# Node count by capacity type
karpenter_nodes_total{capacity_type="spot"}
karpenter_nodes_total{capacity_type="on-demand"}Useful kubectl commands:
# See what Karpenter is doing
kubectl logs -n kube-system -l app.kubernetes.io/name=karpenter --follow
# List all Karpenter-managed nodes
kubectl get nodes -l karpenter.sh/nodepool
# Check NodePool status
kubectl get nodepools
kubectl describe nodepool default
# View NodeClaims (Karpenter's node records)
kubectl get nodeclaimsCommon Issues
Pods still pending after Karpenter install:
# Check if Karpenter can see pending pods
kubectl get events --field-selector reason=FailedScheduling
# Check Karpenter controller logs
kubectl logs -n kube-system deploy/karpenter -c controller | grep -i errorKarpenter not consolidating nodes:
- Check that
consolidationPolicyis set on your NodePool - Verify pods don't have
karpenter.sh/do-not-disrupt: "true"annotation - Check disruption budgets aren't blocking
Instance not available in region:
- Broaden your instance category/size requirements
- Add more instance families (c, m, r, t, i, d)
Karpenter vs Cluster Autoscaler: When to Use Which
Use Karpenter when:
- Running on EKS (first-class support)
- Cost optimization is a priority
- You need fast provisioning (under 60s)
- Using Spot instances heavily
Stick with Cluster Autoscaler when:
- Running on GKE or AKS (Karpenter AWS-specific)
- Using managed node groups extensively
- Team is not ready to manage NodePool configs
Karpenter can cut your AWS EC2 costs by 40-60% on variable workloads. Deploy it on DigitalOcean Kubernetes managed clusters or EKS for immediate cost savings.
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
AWS EKS Pods Stuck in Pending State: Causes and Fixes
Pods stuck in Pending on EKS are caused by a handful of known issues — insufficient node capacity, taint mismatches, PVC problems, and more. Here's how to diagnose and fix each one.
AWS EKS vs Google GKE vs Azure AKS — Which Managed Kubernetes to Use in 2026?
Honest comparison of EKS, GKE, and AKS in 2026: pricing, developer experience, networking, autoscaling, and which one to pick for your use case.
Build a Complete AWS Infrastructure with Terraform from Scratch (2026)
Full project walkthrough: provision a production-grade AWS VPC, EKS cluster, RDS, S3, and IAM with Terraform. Real code, real architecture, ready to use.