Kubernetes Ecosystem: From User to Contributor, Episode 9
← EP08: Karpenter · EP09: Karpenter vs Cluster Autoscaler · EP10: KubeVirt →
10 min read
TL;DR
- Karpenter vs Cluster Autoscaler comes down to an architectural ceiling: Cluster Autoscaler has to work generically across every cloud’s own autoscaling-group abstraction, which caps how smart its instance-selection can ever be
- Karpenter throws away the node-group abstraction and talks to the cloud’s instance-provisioning API directly — that’s the actual reason AWS built a new tool instead of extending Cluster Autoscaler
- Karpenter provisions faster and consolidates more aggressively for cost savings; Cluster Autoscaler’s scale-down behavior is deliberately more conservative
- Cluster Autoscaler remains the only mature option for several smaller cloud providers that don’t have a Karpenter provider implementation yet
- Recommendation: use Karpenter on AWS (and increasingly GKE) if you want its cost and speed advantages; stay on Cluster Autoscaler if you need one consistent tool across multiple clouds or you’re on a cloud Karpenter doesn’t support yet
- Contribution opportunity: building a Karpenter provider for a smaller, currently-unsupported cloud is real, meaningful, and directly helps teams stuck on Cluster Autoscaler’s more limited model purely for lack of an alternative
The Big Picture
CLUSTER AUTOSCALER KARPENTER
─────────────────── ─────────
Generic abstraction: "a node group Direct: "the cloud's actual
that can scale from N to M" instance-provisioning API"
│ │
Has to work the same way whether Talks to EC2's RunInstances API
it's an AWS ASG, a GCP MIG, or an (or the equivalent) directly —
Azure VMSS — lowest common no generic abstraction ceiling
denominator by necessity to work around
│ │
Instance type is WHATEVER the Instance type is COMPUTED per
node group was pre-configured with pending pod, from a flexible
allowed range
Karpenter vs Cluster Autoscaler isn’t “new tool, old tool” — it’s a direct consequence of Cluster Autoscaler’s cross-cloud genericness being both its strength (works everywhere) and its ceiling (can never be smarter than the lowest common denominator of every cloud’s node-group abstraction).
Why AWS Built Karpenter Instead of Improving Cluster Autoscaler
Cluster Autoscaler was designed to work identically across clouds by scaling pre-existing node groups — ASGs on AWS, Managed Instance Groups on GCP, VM Scale Sets on Azure. That design constraint is exactly what limits it: it can only ever choose among the instance types and sizes someone already configured into a node group ahead of time, and it can only scale that group up or down as a unit.
AWS’s actual motivation for building Karpenter was to remove that ceiling entirely for their own cloud — by talking to EC2’s provisioning APIs directly, Karpenter can select from the full range of instance types AWS offers for every single provisioning decision, not just whatever a handful of pre-configured node groups happen to offer.
Provisioning Speed Compared
# Cluster Autoscaler: must first identify which existing node group to
# scale, then wait for that group's own scaling mechanism (an ASG launch,
# for instance) to complete
$ kubectl get events --field-selector reason=TriggeredScaleUp
# typically 1-3 minutes to a new node being schedulable
# Karpenter: computes the instance directly and calls the provisioning
# API without an intermediate node-group scaling step
$ kubectl get nodeclaims
# typically under a minute from pending pod to a schedulable node
The speed difference isn’t marginal at scale — for workloads with bursty, latency-sensitive scaling needs (batch job spikes, CI runner fleets), the extra minute or two Cluster Autoscaler’s node-group indirection adds is a real, felt difference, not a rounding error.
Cost Efficiency: Consolidation vs CA’s More Conservative Scale-Down
Karpenter’s consolidation behavior (EP08) actively looks for cheaper node configurations continuously, not just when pods are pending. Cluster Autoscaler’s scale-down logic is deliberately more conservative — it removes clearly-empty or clearly-underutilized nodes, but doesn’t proactively repack workloads onto fewer, better-fitting nodes the way Karpenter does by design. Teams migrating from Cluster Autoscaler to Karpenter commonly report meaningful compute cost reductions purely from this behavioral difference, independent of any instance-selection improvement.
Where Cluster Autoscaler Is Still the Right Choice
Multi-cloud consistency needs: if your platform runs on AWS, GCP, and Azure and you want one autoscaling tool behaving identically everywhere, Cluster Autoscaler’s cross-cloud design is a genuine advantage — Karpenter’s provider maturity still varies significantly by cloud.
Clouds without a mature Karpenter provider: several smaller cloud providers have no Karpenter implementation at all — Cluster Autoscaler, or that cloud’s own native autoscaler, remains the only real option.
Teams not hitting Cluster Autoscaler’s actual limits: if your workloads are stable, predictable, and your existing node groups already fit them well, Karpenter’s advantages may not be worth a migration — Cluster Autoscaler is mature, stable, and well-understood.
The Recommendation
On AWS specifically, and increasingly on GKE: default to Karpenter. The provisioning speed and consolidation cost savings are real and well-documented at this point, and this is where Karpenter’s provider maturity is strongest.
On any cloud without a mature Karpenter provider, or in a genuinely multi-cloud platform wanting one consistent tool: stay on Cluster Autoscaler. Don’t migrate for the sake of using the newer tool if your actual cloud or requirements don’t play to Karpenter’s strengths yet.
Don’t run both against the same node pool. Pick one scaler per cluster (or per clearly-separated node pool if you’re genuinely transitioning) — having both react to the same pending pods produces exactly the kind of conflicting-controller behavior you’d expect.
⚠ Production Gotchas
Migrating from Cluster Autoscaler to Karpenter mid-cluster requires careful sequencing, not a simultaneous cutover. Run them against separate, clearly labeled node pools during migration, and fully decommission Cluster Autoscaler’s management of a pool before letting Karpenter manage the same workloads.
Cluster Autoscaler’s node-group-based cost estimates and Karpenter’s per-instance cost awareness aren’t directly comparable without normalizing for what each is actually measuring. Don’t assume a raw percentage cost-savings figure from a vendor blog post transfers directly to your own workload mix.
Karpenter provider maturity genuinely varies by cloud — check the specific provider’s current feature list, not just “does Karpenter support my cloud” as a yes/no question.
Quick Reference
| Cluster Autoscaler | Karpenter | |
|---|---|---|
| Abstraction | Pre-defined node groups | Direct instance provisioning |
| Cross-cloud consistency | Strong (by design) | Varies — provider maturity differs by cloud |
| Provisioning speed | Slower (node-group indirection) | Faster (direct API calls) |
| Cost optimization | Conservative scale-down | Active, continuous consolidation |
| Best fit | Multi-cloud, stable workloads, unsupported clouds | AWS/GKE, dynamic workloads, cost-sensitive fleets |
Contribution Opportunity: A Karpenter Provider for an Unsupported Cloud
The limitation: Teams running on smaller cloud providers — several exist with real production Kubernetes usage but no Karpenter implementation — are stuck with Cluster Autoscaler’s node-group model purely because nobody has built the equivalent Karpenter provider for their cloud, not because Cluster Autoscaler is actually the better fit for their workload.
Why it’s hard to fix: Building a new cloud provider for Karpenter means implementing that cloud’s instance-provisioning API integration, its spot/preemptible-equivalent interruption handling, and its networking/subnet discovery model from scratch — a genuine, multi-week engineering effort with no existing template for that specific cloud, even though the AWS and GCP providers exist as architectural references.
What a contribution-shaped fix looks like: Karpenter’s core (kubernetes-sigs/karpenter) is explicitly designed to support multiple cloud providers as separate implementations of a defined interface — the AWS and GCP provider source code is the reference for what a new provider needs to implement. For an engineer who already runs production Kubernetes on an unsupported cloud, building a minimal provider — even one covering just basic on-demand instance provisioning, without full spot/consolidation parity at first — is a real, high-value, currently-missing contribution that directly serves other teams on that same cloud stuck with no alternative to Cluster Autoscaler.
Key Takeaways
- Karpenter exists because Cluster Autoscaler’s cross-cloud node-group abstraction is a genuine architectural ceiling, not because Cluster Autoscaler was poorly built
- Karpenter provisions faster and consolidates more aggressively for cost savings — real, measurable advantages on the clouds it supports well
- Cluster Autoscaler remains the right choice for genuine multi-cloud consistency needs and for clouds without a mature Karpenter provider
- Never run both scalers against the same node pool simultaneously
- Building a Karpenter provider for a currently-unsupported cloud is a real, high-value contribution with existing architectural references (AWS, GCP) to learn from
What’s Next
Every tool so far in this series has assumed container workloads. EP10 closes the series with KubeVirt — running actual virtual machines as first-class citizens alongside pods on the same cluster, and why that migration path still matters in a container-first world.
Next: EP10 — KubeVirt: Running VMs on Kubernetes — and Why That Still Matters
Get EP10 in your inbox when it publishes → linuxcent.com/subscribe