A strategy for moving from Cluster Autoscaler to Karpenter: when to switch, a gradual migration with coexistence, converting nodegroups into NodePools, differences in scheduling behavior, and managing downtime during the rollout.

In episode 15 you put together capacity best practices and FinOps for Karpenter. But you may be wondering: what if the cluster is still running Cluster Autoscaler (CA)? Replacing the node autoscaler in a production cluster feels intimidating — CA has been running for a long time, workloads have adapted to its behavior, and one mistake can leave the whole cluster stuck without new nodes.
This episode covers migrating from Cluster Autoscaler to Karpenter systematically. You will learn when to replace CA, run both side by side, convert nodegroups into NodePools, understand the differences in scheduling behavior, and manage downtime during the rollout.
Cluster Autoscaler is node-group based: it only adds or removes instances within a predefined group. Karpenter works directly at the instance level, so it is more flexible. Consider migrating when:
Important
Don't migrate just because it's a trend. If your cluster is small, your workloads are uniform, and you are not sensitive to scale-up latency, CA may be good enough. Migration pays off when speed, cost, or instance flexibility become real problems.
Karpenter and Cluster Autoscaler can coexist in the same cluster as long as one condition is met: they must not manage the same node group. CA only moves the number of instances within a specific node group, while Karpenter creates its own nodes. If both touch the same node group, a scaling war breaks out: CA scales up, Karpenter scales down.
kubectl scale deployment cluster-autoscaler \
-n kube-system \
--replicas=0A safe gradual strategy:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: migration
spec:
template:
spec:
taints:
- key: karpenter.sh/migrated
effect: NoSchedule
disruption:
consolidationPolicy: WhenUnderutilizedPods that are moved add the karpenter.sh/migrated toleration so they are scheduled onto Karpenter nodes, while other workloads keep running on the old node groups without disruption.
Existing node groups are not automatically managed by Karpenter. You must express the same intent as a NodePool and a NodeClass. The conversion map is simple: the instance type intent of a node group becomes requirements, and the launch template becomes a NodeClass.
| Cluster Autoscaler concept | Karpenter concept |
|---|---|
| Node group | NodePool |
| Launch template / launch configuration | EC2NodeClass |
| Instance type list | requirements in the NodePool |
| Max size | Resource limits in spec or budget practices |
| Node group taints | taints in the NodePool template |
| Node tags | tags in the NodeClass |
Note that Karpenter does not know an explicit max size per NodePool. Capacity limits are enforced through a combination of limits on resources, disruption budgets, or tagging policies. Adjust team expectations: this behavior is more flexible but requires disciplined control.
Karpenter and CA differ fundamentally in how they view capacity. CA asks "are there pods that cannot be scheduled, and can the node group grow?", while Karpenter runs a binpacking simulation against instance types before deciding to create a node.
# Node dengan label managed oleh Karpenter
kubectl get nodes -l karpenter.sh/nodepool
# Node yang berasal dari node group eksisting
kubectl get nodes -l eks.amazonaws.com/nodegroupThese differences have a real impact: Karpenter packs pods more tightly, so fewer nodes are used; it selects instances that match pod needs exactly, and it does not wait for node group availability. As a result, applications that rely on deterministic placement must be verified again.
Workloads written for CA often carry the annotation cluster-autoscaler.kubernetes.io/safe-to-evict: "false" to prevent eviction during scale-down. Karpenter does not read this annotation. Instead, use a Pod Disruption Budget to govern pods that must not be disturbed during consolidation.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: apiWarning
After migrating, audit all cluster-autoscaler.kubernetes.io/safe-to-evict annotations. Pods that were previously immune to scale-down will now be evicted by consolidation as well. Convert that protection into a PDB, or critical pods could die in the middle of the first consolidation cycle.
A well-planned migration does not require downtime. The key is having new nodes available before removing old ones: make sure the Karpenter NodePool is active and new workloads are ready, and only then turn off CA and shrink the node groups.
The most sensitive point is the difference in terminationGracePeriodSeconds and drain behavior. CA and Karpenter both drain, but the order and priority differ. Test on a staging environment with production-like load, and prepare a rollback by keeping the original CA configuration.
Tip
For a quick rollback, don't delete the node groups immediately after migrating. Keep the node groups small for one or two release cycles. If Karpenter has problems, you can simply bring CA back and restore the deployment without rebuilding infrastructure from scratch.
Migrating from Cluster Autoscaler is a project that can go smoothly if done gradually and with the right protection.
Key takeaways:
cluster-autoscaler.kubernetes.io/safe-to-evict is not read by Karpenter, so audit and convert it before consolidation becomes active.The migration is done, and Karpenter now manages the primary capacity. But there are many advanced features still unexplored. In episode 17 we cover Advanced Features — static capacity and dedicated nodes such as bare metal and on-premises via NodeClass, then Karpenter on other platforms such as AKS, EKS Anywhere, and community providers. See you there!