Karpenter vs cluster-autoscaler in 2026
Both node autoscalers are now SIG Autoscaling subprojects, and in July 2026 they started sharing an API. What actually differs, and how to choose.
Ben Ennis
Published July 27, 2026
The interesting thing about this comparison in 2026 is that it has stopped being a rivalry. Both projects are subprojects of SIG Autoscaling, both are actively released, and this month they shipped overlapping features against a shared specification. The question is no longer which one wins. It is which parts of the API are now common and which differences are load-bearing.
The architectural difference, stated precisely
The Kubernetes documentation puts it plainly. Cluster Autoscaler “adds or removes Nodes to pre-configured Node groups. Node groups generally map to some sort of cloud provider resource group,” while Karpenter “auto-provisions Nodes based on NodePool configurations provided by the cluster operator” (node autoscaling concepts).
That single difference produces most of the others. Cluster Autoscaler’s unit of work is the node group, and its FAQ requires that within a group “all machines have identical capacity and have the same set of assigned labels.” To offer a workload a choice of instance shapes, you create a node group per shape and let an expander pick between them. Karpenter’s unit of work is the NodeClaim: it reads the pending pod’s requirements, solves for an instance type, and launches it.
For a homogeneous cluster this distinction barely matters. For a cluster with GPU jobs, ARM builds, memory-heavy caches, and spot-tolerant batch, it is the whole game — the node-group approach turns into two dozen groups nobody wants to maintain.
Where each one is honest about its limits
Cluster Autoscaler documents its own scaling envelope, which is more than most projects do. The FAQ states it “should handle up to 1000 nodes running 30 pods each” and that no performance testing has been done above that. It publishes latency targets too: under 30 seconds on clusters below 100 nodes, averaging about 5 seconds, and under 60 seconds between 100 and 1000 nodes. It also warns that the pod affinity predicate is “about 3 orders of magnitude slower than for all other predicates combined,” which is a real constraint if your scheduling rules are complex.
Karpenter publishes no equivalent figures, and the widely-quoted “Karpenter provisions nodes in under a minute” numbers do not come from AWS documentation. Treat them as vendor marketing until someone publishes a methodology.
Disruption is the real differentiator
Karpenter’s disruption model is the
feature people actually adopt it for, and it is more aggressive by default than most
teams realise. The default consolidationPolicy is WhenEmptyOrUnderutilized with
consolidateAfter: 0s, meaning Karpenter will replace a running node with a cheaper one
the moment the maths works. The default disruption budget, if you define none, is a single
budget of nodes: 10%, and expireAfter defaults to 720h.
Karpenter v1.14 added a third policy, Balanced, which considers whether cost savings
outweigh the disruption to running pods — a middle ground between WhenEmpty and the
default. Existing NodePools are unaffected unless you opt in. Most comparison content
predates it.
Two details bite people. Blocking PodDisruptionBudgets and the
karpenter.sh/do-not-disrupt annotation prevent voluntary disruption only; the docs are
explicit that neither excludes a node from expiration, spot interruption, node repair, or
manual deletion. And drift detection will replace nodes whose spec no longer matches the
NodePool — correct behaviour that looks like unexplained churn the first time an AMI
reference changes underneath you.
Cluster Autoscaler’s equivalent is thinner: scale down when utilisation falls below
scale-down-utilization-threshold (default 0.5), evaluated on a 10-second scan interval.
No drift, no cost-aware replacement, no budgets with cron windows.
The convergence nobody mentions
Here is the 2026 story. SIG Autoscaling proposed a
CapacityBuffer API
in the autoscaling.x-k8s.io group as a cross-autoscaler specification for provisioning
headroom — replacing the pause-pod overprovisioning hack everyone has been running for
years. The proposal names a second implementation in Karpenter as a graduation
requirement for v1.
Karpenter delivered it. The
v1.14 upgrade guide records that the
release “graduates the Capacity Buffers API to v1beta1 and ships a new
autoscaling.x-k8s.io_capacitybuffers CRD.” The same release added Dynamic Resource
Allocation support; Cluster Autoscaler 1.36 shipped DRA partitionable-device support in
the same month. Two autoscalers, one API group, overlapping feature velocity.
Google has built on the same specification: GKE’s active buffer is implemented against the OSS CapacityBuffer API, and Google’s published figures for standby buffers report P50 pod scheduling dropping from four to six minutes to single-digit seconds, at a “low single-digit percent” cost overhead. Those are the only first-party latency numbers in this space worth quoting.
How to actually choose
Run Cluster Autoscaler if your cluster is homogeneous, under a thousand nodes, already built around managed node groups, and on a cloud where Karpenter has no first-party provider. It is stable, well-understood, and its constraints are documented.
Run Karpenter if instance-shape diversity is real, if spot economics matter, or if you are
on a platform that already manages it for you. On AWS,
EKS Auto Mode runs Karpenter as a managed component
and enforces a 21-day maximum node lifetime. On Azure,
node auto-provisioning
is managed Karpenter with NodePool and AKSNodeClass CRDs. Note that the GCP and
Alibaba providers are third-party, not first-party cloud vendor projects.
One migration warning that still catches people: Karpenter v1.1.0 dropped v1beta1 API
support entirely. Anything still on v1beta1 must go through v1.0’s conversion webhooks
before upgrading further.
Frequently asked questions
Is Karpenter a CNCF project?+
Can I run both at once?+
Why is Karpenter constantly replacing my nodes?+
consolidationPolicy defaults to WhenEmptyOrUnderutilized with consolidateAfter: 0s, so it acts immediately whenever a cheaper packing exists. Set consolidateAfter to a few minutes, add disruption budgets, or try the new Balanced policy in v1.14.Does a PodDisruptionBudget stop Karpenter from removing a node?+
karpenter.sh/do-not-disrupt annotation do not block expiration, spot interruption, node repair, or manual deletion. Use expireAfter and terminationGracePeriod deliberately.Is cluster-autoscaler still maintained?+
Read next
- Try the tool: Kubernetes YAML linter
- Try the tool: YAML ↔ JSON converter
- Try the tool: cron expression parser
Tags: #kubernetes, #autoscaling, #karpenter, #eks