Node autoscaling evolved from manual provisioning to a reactive Cluster Autoscaler, then to Karpenter, which was born at AWS in 2020. This episode traces that history and breaks down the latency, cost, and complexity problems Karpenter aims to solve.

In episode 0 you prepared the environment: an EKS cluster, an IAM role, and a Karpenter 1.14.0 controller running in the karpenter namespace. Now it's time to ask the most fundamental question: why does Karpenter need to exist? Why does Kubernetes, which already has a built-in scheduler, still need another tool to manage nodes?
The answer lies in the history of node autoscaling in Kubernetes. It's a long story, from the days of manual provisioning, through the era of the reactive and slow Cluster Autoscaler, to the birth of Karpenter at AWS in 2020. This episode traces that journey and breaks down the three big problems Karpenter aims to solve: provisioning latency, cost efficiency, and operational complexity.
Node autoscaling is not a new concept. From the very beginning, Kubernetes clusters needed a way to add and remove capacity automatically. The evolution can be summarized in the following timeline:
2020 Karpenter born at AWS, sub-second to second provisioning
2022 Karpenter donated to kubernetes-sigs (open source)
2024 Karpenter v1.0 released, API reaches GA status
2026 Version 1.14.0 supports Kubernetes 1.29-1.36Before autoscaling matured, operations teams added nodes manually: create an EC2 instance, install kubelet, register it to the cluster, then wait for the scheduler to place pods. This process was slow, error-prone, and couldn't respond to sudden traffic spikes. That's where Cluster Autoscaler came in.
Cluster Autoscaler (CA) was the first popular approach. CA works reactively: it monitors pods in Pending status, then adds nodes to a predefined nodegroup. Here are its key characteristics:
This model works for simple cases, but it starts to break down at scale. Teams ended up creating many nodegroups to accommodate different needs: small ones for bursts, large ones for memory-heavy workloads, and so on. The result: ballooning costs, low utilization, and increasingly complex configuration.
Karpenter was developed by AWS starting in 2020 with the goal of changing how node provisioning works. Instead of being nodegroup-based, Karpenter calculates the needs of the pods waiting in the queue, then chooses the most optimal instance for those needs — and launches it directly on EC2.
Karpenter's two main breakthroughs:
In 2022, AWS released Karpenter to kubernetes-sigs, making it a community-managed open source project. Two years later, in 2024, Karpenter reached v1.0 — the v1 API became stable and the old beta versions were removed. Since then Karpenter has kept evolving; the 1.14.0 version you installed in episode 0 supports Kubernetes 1.29 to 1.36.
When a pod can't be scheduled, every second of delay is both an operational cost and a poor user experience. CA can take 2-5 minutes just to add a node. Karpenter reduces that to seconds, even sub-seconds in certain cases, because it calls the EC2 instance launch service directly.
Karpenter reduces costs through three mechanisms:
A single Karpenter controller replaces dozens of nodegroups and ASGs along with their autoscalers. You no longer manage instance templates everywhere; just define a NodePool as a policy, and Karpenter handles the rest.
To truly appreciate the difference between CA and Karpenter, there's no better way than observing it directly. When the cluster lacks capacity, pods queue up in Pending status. This event can be seen through events:
kubectl get events --sort-by=.lastTimestamp | tail -20
kubectl get pods --field-selector=status.phase=Pending -ANotice the FailedScheduling entry in the reason column — that's the moment the autoscaling controller starts working. On a cluster using Cluster Autoscaler, the gap between this event and a ready node is usually several minutes. With Karpenter, which you'll install in episode 3, compare the timing yourself; the difference feels real when the node is ready within seconds.
Tip
kubectl get events --sort-by=.lastTimestamp is the most useful debugging habit you can cultivate from now on. The FailedScheduling event is written proof that a pod needs new capacity — and that's Karpenter's main trigger, which we'll break down in episode 2.
| Aspect | Cluster Autoscaler | Karpenter |
|---|---|---|
| Model | Explicit Nodegroup/ASG | Pod-need-based policy |
| Speed | Minutes | Seconds to sub-seconds |
| Instance selection | Fixed nodegroup template | Optimal per pod (binpacking) |
| Spot | Manual, per nodegroup | Integrated, can be per NodePool |
| Consolidation | None | Built-in via disruption |
| Operational cost | Many nodegroups | One controller |
Besides CA, there are also commercial approaches like Cast AI that offer cost optimization and node management as a service. We'll do an in-depth comparison of Karpenter, CA, and Cast AI specifically in episode 22 of this series.
Note
Karpenter is also available for other clouds. The NodePool and NodeClass concepts are generic — on Azure it uses the Azure version of NodeClass, on AWS it uses EC2NodeClass. Throughout this series we focus on the AWS implementation because it's the most mature and the most widely used in production.
This episode explained why Karpenter was born and what problems it solves. Karpenter is the answer to Cluster Autoscaler's limitations of being reactive, slow, and nodegroup-based. Born at AWS in 2020, donated to kubernetes-sigs in 2022, and reaching v1.0 in 2024, Karpenter offers sub-second provisioning, optimal instance selection, binpacking, Spot support, and automatic consolidation.
Key takeaways:
In episode 2 we'll tear down Karpenter's architecture: how the controller listens for unscheduled pods, selects a matching NodePool, and calls the cloud provider to launch nodes. The NodePool and NodeClass concepts will become a shared language for all the hands-on episodes that follow. See you there!