Karpenter Explained: Why Not Just Use Cluster Autoscaler?
When working with Kubernetes, one thing we need to get right is how the cluster scales when more workloads arrive.
Let’s say you have an application running on Amazon EKS. Everything is working fine, but suddenly, traffic increases. More pods need to be created, and the existing nodes don’t have enough resources to accommodate them.
Those pods remain in the Pending state until Kubernetes finds enough capacity to schedule them.
Now, how does the cluster get more nodes?
This is where node autoscaling solutions like Cluster Autoscaler and Karpenter come into the picture.
Both help scale your Kubernetes infrastructure, but they approach the problem differently.
What Is Karpenter?
Karpenter is an open-source node provisioning solution for Kubernetes that automatically launches and manages compute capacity based on workload requirements.
Instead of relying on predefined node groups, Karpenter evaluates the requirements of pending pods and provisions suitable nodes to run them.
It also helps reduce cloud spending through intelligent instance selection and consolidation, where underutilized nodes can be replaced or removed when their workloads can run elsewhere.
So, why would we choose Karpenter over Cluster Autoscaler?
Let’s understand that.
Why Karpenter? Why Not Cluster Autoscaler?
First, let’s look at how Cluster Autoscaler works.
How Cluster Autoscaler Works
Imagine you have an EKS cluster with a few managed node groups.
Your application needs more replicas, but the existing nodes don’t have enough resources to schedule the new pods.
Here’s what happens:
- Pod becomes Pending: Kubernetes cannot schedule the pod because there isn’t enough available capacity.
- Cluster Autoscaler detects the problem: It checks for unschedulable pods through its periodic evaluation.
- Node group scales up: Cluster Autoscaler requests an increase in the desired size of the associated Auto Scaling Group.
- EC2 instance launches: The Auto Scaling Group launches a new instance from its configured launch settings.
- Node joins the cluster: The instance initializes and registers as a Kubernetes worker node.
- Pod gets scheduled: Kubernetes schedules the pending pod onto the available node.
As you can see, several steps need to happen before the pod can run.
The actual time depends on factors such as instance launch time, node initialization, and the configuration of the cluster. It can take a few minutes for the new node to become ready.
Another limitation is that Cluster Autoscaler typically works with predefined node groups. The instance types available for scaling depend on how those groups are configured.
For example, if you need different instance types for different workloads, you may need multiple node groups with different configurations.
This isn’t necessarily a bad thing, but managing multiple node groups can become complicated as your workloads grow.
And this is where Karpenter offers a different approach.
How Does Karpenter Solve This?
Karpenter takes a more direct approach to node provisioning.
Instead of waiting for a node group to scale up, it evaluates pending pods and determines what kind of compute capacity would be suitable for them.
Here’s how it works:
- Pending pods are detected: Karpenter watches Kubernetes events and identifies pods that cannot be scheduled.
- Compute requirements are evaluated: It considers resource requests, scheduling constraints, and the available instance options.
- Suitable instance types are selected: Karpenter determines which instances can satisfy the workload requirements.
- EC2 instances are provisioned: Karpenter interacts directly with AWS APIs to launch the required instances, rather than requesting a node group scale-up.
- Nodes join the cluster: The instances initialize and register with Kubernetes.
- Pods get scheduled: Once the nodes are ready, Kubernetes schedules the pending pods.
The main difference is that Karpenter chooses the compute capacity based on workload requirements instead of being restricted to scaling a particular predefined node group.
For example, if your application needs more CPU capacity, Karpenter can evaluate suitable instance types that meet the pod’s requirements and your provisioning constraints.
You don’t have to create a separate node group for every possible instance type.
Of course, the selected instance must still satisfy your configuration, availability, and scheduling requirements.
Cluster Autoscaler vs. Karpenter
Let’s compare their approaches.
1. Scaling Approach
- Cluster Autoscaler: Scales existing node groups.
- Karpenter: Provisions nodes based on workload requirements.
2. Pod Detection
- Cluster Autoscaler: Periodically evaluates unschedulable pods.
- Karpenter: Watches Kubernetes events and responds to scheduling needs.
3. Node Provisioning
- Cluster Autoscaler: Requests a node group scale-up.
- Karpenter: Calls cloud provider APIs directly to provision capacity.
4. Instance Selection
- Cluster Autoscaler: Depends on the instance types configured in node groups.
- Karpenter: Evaluates suitable instance types based on workload requirements and configured constraints.
5. Node Group Dependency
- Cluster Autoscaler: Typically relies on predefined node groups.
- Karpenter: Can provision nodes without requiring predefined node groups.
6. Configuration
- Cluster Autoscaler: Managing multiple node groups can increase configuration complexity.
- Karpenter: Provisioning requirements can be defined using Karpenter resources.
7. Cost Optimization
- Cluster Autoscaler: Cost optimization depends on node group configuration and scaling policies.
- Karpenter: Supports flexible instance selection and consolidation to help reduce costs.
8. Best Suited For
- Cluster Autoscaler: Environments built around existing node groups.
- Karpenter: Environments that need flexible, workload-driven node provisioning.
A quick note on provisioning speed: Cluster Autoscaler does not inherently take 3–3.5 minutes, and Karpenter does not guarantee provisioning in 30 seconds. These are possible observed timings, not fixed guarantees. Actual performance depends on factors such as EC2 instance launch time, node initialization, and cluster configuration.
Karpenter Workflow
Let’s simplify the entire process.
Pending Pod → Karpenter Controller → AWS API → EC2 Instance → Worker Node → Running Pod
Here’s what happens at each stage:
- Pending Pod: A pod cannot be scheduled because the cluster lacks suitable capacity.
- Karpenter Controller: Detects the scheduling problem and evaluates the pod’s resource requirements and constraints.
- AWS API: Karpenter requests the appropriate compute capacity from AWS.
- EC2 Instance: AWS launches an instance that meets the provisioning requirements.
- Worker Node: The instance initializes and registers with the Kubernetes cluster.
- Running Pod: Kubernetes schedules the pending pod once suitable capacity is available.
That’s the basic idea behind Karpenter.
Karpenter Architecture: How It Works
Now that we understand why Karpenter is useful, let’s look at how it actually works behind the scenes.
There are a few components we need to understand before looking at the complete workflow.
1. Core Components
The main components we will focus on are:
- Karpenter Controller
- NodePool
- EC2NodeClass
- NodeClaim
- AWS APIs and EC2 instances
Let’s understand what each one does.
Get Anish Bhat K’s stories in your inbox
Join Medium for free to get updates from this writer.
Karpenter Controller
The controller is the main component responsible for observing unschedulable pods, evaluating their resource requirements, and deciding when new nodes are needed.
It uses the configuration defined in the NodePool and EC2NodeClass to determine what kind of node can be provisioned and how to provision it.
NodePool
A NodePool defines the requirements and constraints for the nodes Karpenter can provision.
For example, you can configure:
- Permitted instance families and sizes.
- CPU architecture, such as x86–64 or ARM64.
- Capacity type, such as On-Demand or Spot.
- Scheduling requirements and labels.
- Resource limits for the NodePool.
- Node disruption and expiration policies.
Karpenter evaluates these constraints along with the pending pods’ resource requests and scheduling requirements to select suitable instance types.
One important point: Karpenter doesn’t simply choose an instance based on CPU and memory alone. It also considers scheduling constraints, instance availability, architecture, capacity type, and other requirements.
EC2NodeClass
While the NodePool defines what kind of node we need, the EC2NodeClass defines the AWS-specific configuration required to launch it.
For example:
- Amazon Machine Image (AMI) selection.
- Subnets.
- Security groups.
- IAM instance profile or role configuration.
- Root volume settings.
- Instance metadata options.
These settings tell Karpenter how to configure the EC2 instances it provisions.
The EC2NodeClass is specific to AWS. Other cloud providers have their own provider-specific configuration.
Both NodePool and EC2NodeClass are Kubernetes custom resources defined through CustomResourceDefinitions (CRDs).
2. What Is a NodeClaim?
Now, suppose a pod is pending because the existing nodes don’t have enough resources.
Karpenter evaluates the pod’s requirements, checks the NodePool and EC2NodeClass configurations, and determines what capacity needs to be added.
It then creates a NodeClaim.
Think of a NodeClaim as a representation of the node Karpenter intends to provision. It captures the requirements for that node and tracks its provisioning lifecycle.
You don’t normally need to create NodeClaims manually. Karpenter generates them as part of its provisioning process.
Here’s the complete flow:
Pending Pod → Karpenter Controller → NodePool + EC2NodeClass → NodeClaim → AWS APIs → EC2 Instance → Kubernetes Node → Pod Scheduled
Once the NodeClaim is created, Karpenter uses the AWS configuration to launch a suitable EC2 instance.
The instance initializes and registers with the Kubernetes cluster. Once the node is ready and has sufficient resources, the pending pod can be scheduled.
That’s the basic architecture behind Karpenter.
3. Consolidation: How Karpenter Helps Reduce Costs
Provisioning nodes is only one part of the story. What happens when those nodes are no longer being used efficiently?
Let’s say you have three nodes, and their workloads are using only 25%, 30%, and 5% of their available resources.
You might be paying for more compute capacity than your workloads actually need.
This is where consolidation comes in.
Karpenter identifies opportunities to reduce the number of nodes or replace existing nodes with more cost-effective alternatives, provided the workloads can still be scheduled and the relevant constraints are satisfied.
For example, if workloads running across three underutilized nodes can fit onto two nodes, Karpenter may consolidate them onto the smaller set of nodes and terminate the unnecessary capacity.
The general process looks like this:
- Karpenter identifies an opportunity to consolidate nodes.
- It determines whether the workloads can be moved without violating scheduling requirements.
- If required, it provisions replacement capacity.
- It moves the workloads by allowing Kubernetes to reschedule the affected pods.
- Once the old nodes are no longer needed, Karpenter terminates them.
The exact process depends on the consolidation opportunity and the disruption policies configured for the NodePool.
One thing to remember: consolidation doesn’t mean Karpenter will always reduce the node count. Sometimes replacing an expensive instance with a cheaper, more suitable one can also help optimize costs.
4. Drift: Handling Configuration Changes
Another useful feature is drift detection.
Imagine you have an existing NodePool and EC2NodeClass. Your nodes were provisioned using a particular AMI, subnet configuration, or set of security groups.
Later, you update the configuration.
What happens to the nodes that were already created?
Karpenter can detect certain changes that make existing nodes inconsistent with the desired configuration. This process is called drift detection.
For example, a change to the AMI selection or certain NodePool requirements may cause existing nodes to become drifted.
The general workflow is:
- An administrator updates the NodePool or EC2NodeClass.
- Karpenter detects that an existing node no longer matches the desired configuration.
- Karpenter identifies the affected node as drifted.
- If disruption is permitted, Karpenter initiates replacement according to its disruption policies.
- A replacement node is provisioned when required.
- Workloads are rescheduled, and the old node is terminated.
This helps keep the cluster aligned with the desired infrastructure configuration without requiring administrators to manually replace every affected node.
However, not every configuration change triggers drift. Karpenter evaluates whether the change affects the node’s desired state, and disruption budgets and other constraints can delay replacement.
5. Node Expiration: Keeping Nodes Fresh
Drift handles certain configuration changes. Node expiration addresses a different concern: how long a node should remain in the cluster.
Over time, nodes may need to be recycled to help maintain consistent infrastructure and apply updated operating system images or security patches.
Karpenter supports node expiration through the expireAfter setting in a NodePool's disruption configuration.
For example, you could configure:
expireAfter: 1000h
This sets an expiration period of 1,000 hours for nodes created under that NodePool.
Once a node reaches its expiration time, Karpenter initiates its disruption and replacement process, subject to the applicable policies and constraints.
The general flow is:
Node Reaches Expiration → Replacement Capacity Provisioned When Needed → Workloads Rescheduled → Old Node Terminated
Keep in mind that expiration doesn’t automatically install operating system patches on an existing node. Instead, it helps recycle nodes so that newly provisioned instances can use the currently configured AMI and bootstrap configuration.
For this approach to help with security updates, the AMI selection and update process must also be maintained.
6. Spot Interruption Handling
If you’re using AWS Spot Instances to reduce costs, this is another feature worth understanding.
Spot Instances are cheaper than On-Demand Instances, but AWS can reclaim them when it needs the capacity back.
AWS generally provides a two-minute warning before reclaiming a Spot Instance, although certain interruption scenarios have different behavior.
There is one important thing to remember: Karpenter cannot guarantee that every pod will be rescheduled before a Spot Instance is reclaimed. The outcome depends on the available capacity, pod scheduling requirements, disruption handling, and application configuration.
For production workloads, applications should still be designed to tolerate interruptions, and critical workloads may need On-Demand capacity.
This is one reason why understanding Karpenter’s provisioning and disruption behavior matters when running workloads on EKS.
Final Thoughts
Karpenter is more than a way to add nodes when a Kubernetes cluster runs out of capacity. It also provides flexibility in instance selection, helps optimize resource utilization, and supports node lifecycle management through features such as consolidation, drift detection, expiration, and Spot interruption handling.
If you’re working with Amazon EKS, understanding these components will help you make better decisions about how your cluster scales, manages infrastructure changes, and controls compute costs.
The important thing is to understand not just how Karpenter provisions a node, but also how it decides which node to provision, when to replace one, and when it can safely remove one.








