Karpenter on EKS: How It Works, How to Configure It, and Where It Falls Short

Last reviewed: August 13, 2026. Karpenter evolves quickly — check the official compatibility matrix and release notes before upgrading production clusters.
Static node groups force a familiar tradeoff: pay for spare capacity you may not use, or run lean and risk waiting for new nodes when traffic spikes. Karpenter (GitHub) moves more of that decision to runtime. When Kubernetes cannot place a pod, Karpenter evaluates the pod's resource requests and scheduling constraints, then provisions compatible compute directly from the cloud provider.
On AWS, Karpenter can choose among the instance types, Availability Zones, architectures, and capacity types allowed by your configuration. For On-Demand capacity, price is a major selection factor; for Spot, AWS capacity selection also accounts for availability and interruption risk rather than simply choosing the lowest sticker price.
This guide covers how Karpenter works, a current EKS installation path, the v1 NodePool and EC2NodeClass APIs, disruption controls, platform support, important limitations, alternatives, and where DevZero can add value for teams already running Karpenter.
What is Karpenter?#
Karpenter is an open-source Kubernetes node lifecycle manager. It watches for unschedulable pods, evaluates their constraints, provisions nodes that can run them, and later removes or replaces nodes when they are no longer needed or when a more efficient configuration is available.
AWS created Karpenter in 2021. The project reached v1.0 in August 2024, bringing stable APIs and a clearer long-term compatibility model. Today the Karpenter core is multi-cloud, while individual providers implement cloud-specific infrastructure behavior. For a broader, cloud-agnostic introduction, see our complete guide to Karpenter; this guide focuses on running it well on EKS.
Key features#
- Dynamic node provisioning. Nodes are launched in response to actual pending workloads rather than only scaling predefined node groups.
- Flexible instance selection. You define constraints; Karpenter chooses compatible capacity at provisioning time.
- Constraint-aware scheduling. Karpenter considers CPU and memory requests, taints, tolerations, affinity, topology, architecture, zones, and provider-specific attributes.
- Node consolidation and drift handling. Karpenter can remove empty nodes, replace underutilized nodes, and roll nodes when configuration changes.
- Cloud-neutral scheduling API.
NodePooldescribes scheduling and lifecycle policy, while provider-specific NodeClass resources describe the infrastructure underneath.
The key difference from Cluster Autoscaler is architectural: Cluster Autoscaler primarily changes the size of node groups you already created; Karpenter can choose the node shape at launch time from a broader set of allowed options.
How Karpenter works#
The lifecycle is straightforward:
Detection. Kubernetes marks pods unschedulable and Karpenter observes them.
Constraint evaluation. Karpenter reads resource requests, labels, taints, tolerations, affinity, topology, architecture, storage constraints, and other scheduling requirements.
Capacity selection. Karpenter finds compatible instance types, zones, and capacity types allowed by the relevant NodePool.
Provisioning. The cloud provider implementation launches a node.
Bootstrapping. The node joins the cluster with the required role, labels, taints, and kubelet configuration.
Scheduling. Kubernetes schedules the pending workload onto the new capacity.
Disruption and consolidation. Karpenter can later remove, replace, or consolidate nodes according to your disruption policy, budgets, drift state, and expiry settings.
This is reactive scaling: Karpenter responds to pending work. It does not forecast a traffic spike on its own. Karpenter also has adjacent mechanisms such as CapacityBuffers for maintaining spare capacity, but those are distinct from predictive forecasting.
How to install Karpenter on Amazon EKS#
A safe Karpenter installation is more than a Helm command. On AWS you need controller permissions, a node IAM role, cluster access for launched nodes, subnet and security-group discovery, and — if you enable interruption handling — the SQS/EventBridge infrastructure that feeds interruption events to Karpenter.
The most reliable approach is to use the infrastructure template maintained with the AWS Karpenter provider for the version you plan to install, then install the controller with that same version.
Prerequisites#
You need:
- A supported Amazon EKS cluster and Kubernetes version.
kubectl, AWS CLI,eksctl, and Helm 3.- AWS permissions to create or modify IAM roles and policies, CloudFormation resources, EKS access, SQS/EventBridge resources, and EC2 tags.
- A small amount of non-Karpenter capacity for critical system components and the Karpenter controller itself.
- A controller identity method:
- EKS Pod Identity: install the EKS Pod Identity Agent and create a Pod Identity association for the Karpenter service account.
- IRSA: configure the cluster IAM OIDC provider and associate the Karpenter service account with an IAM role.
Do not treat OIDC as a universal prerequisite: it is required for IRSA, not for EKS Pod Identity.
Set variables and choose a compatible version#
Use the compatibility matrix before choosing a release. For example, Kubernetes 1.36 requires Karpenter 1.13 or later at the time of this review.
export KARPENTER_NAMESPACE="kube-system"
export KARPENTER_VERSION="<compatible-stable-version>"
export K8S_VERSION="<your-kubernetes-version>"
export CLUSTER_NAME="my-cluster"
export AWS_DEFAULT_REGION="us-west-2"
export AWS_ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
export AWS_PARTITION="aws"
export TEMPOUT="$(mktemp)"For AL2023, resolve a current EKS-optimized AMI alias version and pin it in the EC2NodeClass rather than silently following the newest image:
export ALIAS_VERSION="$(aws ssm get-parameter \
--name "/aws/service/eks/optimized-ami/${K8S_VERSION}/amazon-linux-2023/x86_64/standard/recommended/image_id" \
--query Parameter.Value | xargs aws ec2 describe-images \
--query 'Images[0].Name' --image-ids | sed -r 's/^.*(v[[:digit:]]+).*$/\1/')"Create the AWS-side Karpenter prerequisites#
The AWS Karpenter provider publishes a CloudFormation template with the controller policies, node role, interruption queue, and related resources required by the official getting-started flow. Use the template from the exact Karpenter version you are installing:
curl -fsSL \
"https://raw.githubusercontent.com/aws/karpenter-provider-aws/v${KARPENTER_VERSION}/website/content/en/preview/getting-started/getting-started-with-karpenter/cloudformation.yaml" \
> "${TEMPOUT}"
aws cloudformation deploy \
--stack-name "Karpenter-${CLUSTER_NAME}" \
--template-file "${TEMPOUT}" \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides "ClusterName=${CLUSTER_NAME}"If you manage IAM and interruption handling yourself, reproduce the equivalent permissions and resources rather than skipping this step. In particular, do not set settings.interruptionQueue unless the referenced SQS queue and event routing exist.
If your AWS account has not previously used EC2 Spot, create the EC2 Spot service-linked role once:
aws iam create-service-linked-role --aws-service-name spot.amazonaws.com || trueTag both subnets and security groups for discovery#
Your EC2NodeClass can select subnets and security groups by the discovery tag. The tag value must match the cluster name used in your selectors.
aws ec2 create-tags \
--resources subnet-0123456789abcdef0 subnet-0123456789abcdef1 \
--tags Key=karpenter.sh/discovery,Value="${CLUSTER_NAME}"
aws ec2 create-tags \
--resources sg-0123456789abcdef0 \
--tags Key=karpenter.sh/discovery,Value="${CLUSTER_NAME}"For an existing cluster, verify that your selected subnets have the routing and IP capacity needed for new nodes and pods.
Configure the controller identity and node access#
For EKS Pod Identity, ensure the Pod Identity Agent is installed, then associate the Karpenter service account with the controller role created for the cluster.
For IRSA, ensure the cluster OIDC provider exists and annotate the Karpenter service account with the controller role.
Separately, the IAM role used by Karpenter-created nodes must be authorized to join the cluster. On newer EKS setups, prefer an EKS access entry where appropriate; older installations may still use the aws-auth ConfigMap. The official versioned setup template and EKS documentation should be your source of truth for this step.
Install Karpenter from the OCI Helm registry#
Karpenter is distributed as an OCI Helm chart in public ECR; there is no traditional Helm repository to add.
helm registry logout public.ecr.aws 2>/dev/null || true
helm upgrade --install karpenter \
oci://public.ecr.aws/karpenter/karpenter \
--version "${KARPENTER_VERSION}" \
--namespace "${KARPENTER_NAMESPACE}" \
--create-namespace \
--set "settings.clusterName=${CLUSTER_NAME}" \
--set "settings.interruptionQueue=${CLUSTER_NAME}" \
--set controller.resources.requests.cpu=1 \
--set controller.resources.requests.memory=1Gi \
--set controller.resources.limits.cpu=1 \
--set controller.resources.limits.memory=1Gi \
--waitIf you did not create interruption handling, omit the settings.interruptionQueue value instead of pointing it at a nonexistent queue.
Verify the controller before creating capacity:
kubectl get pods -n "${KARPENTER_NAMESPACE}" -l app.kubernetes.io/name=karpenter
kubectl logs -n "${KARPENTER_NAMESPACE}" -l app.kubernetes.io/name=karpenter -c controller --tail=100Create an EC2NodeClass and NodePool#
In the v1 APIs, NodePool is the cloud-neutral scheduling and lifecycle policy. EC2NodeClass contains AWS-specific configuration.
A practical baseline is to allow a category and generation range instead of hard-coding only one or two instance types. That gives Karpenter room to find available and cost-efficient capacity while you still control the boundaries.
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
role: "KarpenterNodeRole-my-cluster"
amiSelectorTerms:
- alias: "al2023@vYYYYMMDD"
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
---
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: kubernetes.io/os
operator: In
values: ["linux"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand", "spot"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["2"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
expireAfter: 720h
limits:
cpu: "1000"
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1mReplace the AMI alias with the pinned ALIAS_VERSION you resolved for your cluster. In the v1 API, amiSelectorTerms is required; do not rely on amiFamily alone.
Test provisioning#
Create a workload that asks for more CPU than the current cluster has available:
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate
spec:
replicas: 0
selector:
matchLabels:
app: inflate
template:
metadata:
labels:
app: inflate
spec:
terminationGracePeriodSeconds: 0
containers:
- name: inflate
image: public.ecr.aws/eks-distro/kubernetes/pause:3.7
resources:
requests:
cpu: "1"kubectl apply -f inflate.yaml
kubectl scale deployment inflate --replicas 5
kubectl get nodeclaims -o wide -wIn a second terminal, watch the controller:
kubectl logs -f -n "${KARPENTER_NAMESPACE}" \
-l app.kubernetes.io/name=karpenter -c controllerWhen the new nodes are Ready and the pods are Running, scale the test back down and confirm consolidation behavior:
kubectl delete deployment inflateClean up safely#
For a test cluster, remove workloads first, then uninstall Karpenter and delete the Karpenter CloudFormation stack only after you have confirmed that no production workloads depend on Karpenter-managed nodes.
For a production cluster, do not remove CRDs, node roles, or controller infrastructure casually. Deleting Karpenter CRDs can affect the resources that track node lifecycle.
What changed in Karpenter v1#
Older guides often refer to Provisioner and TTL fields such as ttlSecondsAfterEmpty and ttlSecondsUntilExpired. In v1, the key concepts are:
NodePoolreplaces the old provisioning policy model.expireAfterlives underspec.template.specand controls node lifetime.consolidationPolicyandconsolidateAftercontrol consolidation behavior.EC2NodeClassdefines AWS infrastructure details.amiSelectorTermsis required for AWS v1 NodeClass configuration and should be pinned deliberately.
For upgrades across minor versions, read the release notes and migration guidance rather than assuming every behavior is unchanged.
Karpenter best practices#
1. Give Karpenter options, not unlimited freedom#
A NodePool that allows only two instance types limits Karpenter's ability to find capacity. A completely unconstrained pool can create cost or governance surprises. A better pattern is to constrain by architecture, instance category, generation, zones, and capacity type while leaving enough compatible shapes for Karpenter to optimize.
2. Split NodePools by workload behavior#
GPU, batch, latency-sensitive production, and interruption-tolerant workloads often need different taints, instance families, capacity types, and disruption tolerances. Avoid one global NodePool when workload classes have materially different requirements.
3. Use disruption budgets deliberately#
Karpenter NodePool disruption budgets can rate-limit voluntary disruption. The reasons field matters: a budget that lists only Underutilized does not block Empty or Drifted disruptions.
For example, this blocks underutilization-driven consolidation during an eight-hour UTC window on weekdays:
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
budgets:
- nodes: "20%"
- nodes: "0"
schedule: "0 9 * * 1-5"
duration: 8h
reasons: ["Underutilized"]If you want the zero-node budget to cover all voluntary reasons, omit reasons or list the additional reasons you want covered. Also remember that Karpenter disruption schedules are interpreted in UTC.
4. Use PodDisruptionBudgets for critical workloads#
Karpenter's voluntary disruption path uses Kubernetes eviction semantics and respects blocking PDBs. Define PodDisruptionBudgets before enabling aggressive consolidation for important replicated services. PDBs are not a substitute for having enough replicas or sound application-level availability design, but they are an important guardrail.
5. Treat consolidateAfter as tuning, not a constant#
WhenEmptyOrUnderutilized is a common consolidation policy. Current Karpenter defaults may use a very short consolidateAfter, so setting a longer value such as 1m is an explicit choice that can reduce churn in bursty clusters. Tune it to workload behavior rather than copying a value blindly.
6. Enable Spot selectively#
Spot can materially lower compute cost, but interruption tolerance must exist at the application layer. Use multiple compatible instance types and Availability Zones, and let Karpenter fall back to On-Demand where your policy permits it.
7. Watch NodeClaims and controller decisions#
Node count alone does not explain why Karpenter acted. Useful starting points include:
kubectl get nodepools
kubectl get nodeclaims -o wide
kubectl describe nodeclaim <name>
kubectl logs -n kube-system -l app.kubernetes.io/name=karpenter -c controllerLimitations of Karpenter#
Karpenter is powerful, but it is not a complete Kubernetes cost or workload optimization system.
- It is reactive, not predictive. Karpenter normally creates capacity after pods become unschedulable.
CapacityBufferscan maintain spare capacity, but Karpenter does not independently forecast business demand. - Cloud-provider maturity differs. AWS remains the reference implementation. Azure has a managed Karpenter-based Node Auto-Provisioning path. Other providers vary in maturity and support model.
- AWS IAM and bootstrap configuration are real operational work. Controller roles, node roles, discovery, cluster access, and interruption handling all need to line up.
- Misconfigured constraints can cost money. Broad or contradictory requirements can produce expensive or unavailable capacity.
- Consolidation works by disrupting workloads. Karpenter's voluntary disruption path drains nodes: the pods on a consolidated or replaced node are evicted and rescheduled elsewhere. For stateless replicas that is routine. For anything with in-memory state, warm caches, slow startup, or long-running work, every consolidation pass is a restart with a real cost — and aggressive consolidation converts node savings into application churn.
- Disruption decisions are not workload-aware. When Karpenter chooses which nodes to consolidate, it reasons about node cost and utilization — not about how expensive an interruption is for the pods running there, how long they take to start and warm up, or how much in-flight work an eviction throws away. The available guardrails (
PodDisruptionBudgets, thekarpenter.sh/do-not-disruptannotation, disruption budgets) can block or rate-limit disruption, but they are blunt on/off controls: they say "don't disrupt this," not "this pod costs 20 minutes of JVM warmup to move." - It optimizes around declared pod requests. If a pod asks for 4 CPUs and regularly uses 500 millicores, Karpenter still has to schedule around the 4-CPU request. It does not, by itself, decide that the request should be smaller.
The last points matter together: Karpenter can improve node-level efficiency while workload-level over-allocation remains untouched — and the more aggressively it consolidates, the more the workloads on those nodes pay for it in restarts it cannot price.
Cross-platform support: where things stand#
Karpenter now has implementations across more providers than the original AWS/Azure/GCP framing suggests. The upstream project lists implementations for AWS, Azure, GCP, Cluster API, Alibaba Cloud, OCI, IBM Cloud, Proxmox, Hetzner, and others. They are not all equally mature or vendor-supported.
| Platform | Status | NodeClass / provider model | What to know |
|---|---|---|---|
| AWS (EKS) | Reference implementation | EC2NodeClass | Broadest Karpenter feature maturity and the primary upstream AWS provider path. |
| Azure (AKS) | Microsoft-managed Node Auto-Provisioning available | AKSNodeClass | AKS can automatically deploy and manage Karpenter-based NAP. Azure-specific labels, defaults, and NodeClass settings differ from AWS. |
| Google Cloud (GKE) | Community provider | GCENodeClass | A live community provider exists for GKE Standard, but it is not a Google-managed Karpenter offering. Treat versioning and support expectations accordingly. |
| Cluster API and other providers | Varies | Provider-specific | Useful where a provider implementation fits your environment, but evaluate maintenance, feature coverage, and production support individually. |
AWS (EKS)#
If you want the most established self-managed Karpenter experience, EKS remains the reference path. AWS supports both Spot and On-Demand capacity, and the provider integrates with EKS identity and interruption infrastructure.
AWS also offers EKS Auto Mode, a managed alternative that handles more node lifecycle operations for you. Auto Mode adds an EKS management charge on top of normal EC2 pricing; the charge varies by instance type. In AWS's current pricing examples, the management component works out to roughly 12% of the EC2 instance price for the examples shown, but you should check current pricing for your actual instance mix and region.
Azure (AKS)#
AKS Node Auto-Provisioning uses Karpenter and is managed by Azure. In AKS Automatic, NAP is preconfigured; in AKS Standard, you can enable and configure it explicitly. NodePool remains part of the model, but the cloud-specific resource is AKSNodeClass, and Azure-specific labels, defaults, networking, image, disk, and kubelet settings differ from AWS.
Google Cloud (GKE)#
A community Karpenter provider for GKE is active and supports GKE Standard. It is not a Google-managed Karpenter product, so evaluate its release maturity, compatibility, and support model separately from GKE's native autoscaling products. GKE Autopilot also manages its own node infrastructure and is not the environment for an external node provisioner.
Karpenter alternatives and complements#
Cluster Autoscaler#
Cluster Autoscaler is mature and widely deployed. It scales node groups you define in advance, so it is less flexible about choosing node shape at provisioning time, but that predictability can be valuable in environments that prefer tightly controlled groups.
KEDA#
KEDA scales workloads based on external signals such as queue depth, event streams, or metrics. It scales pods rather than nodes, so it often complements Karpenter: KEDA can create additional pod demand, then Karpenter can create the nodes required to run those pods.
EKS Auto Mode#
For AWS teams that want less operational ownership, EKS Auto Mode provides managed node lifecycle behavior and other managed capabilities. The tradeoff is less direct control plus an additional management fee.
GKE Autopilot#
Autopilot is Google's more managed Kubernetes operating model. It removes much of the node-management burden but also changes the amount of low-level infrastructure control available to the platform team.
AWS Fargate#
Fargate removes node management for supported pod workloads. It is a different operating model from Karpenter and is not suitable for every Kubernetes workload or cluster add-on pattern.
Where DevZero fits for teams already running Karpenter#
Three different decisions affect Kubernetes infrastructure cost:
- What a workload asks for. CPU, memory, and GPU requests influence how much capacity the scheduler must reserve.
- Where the workload lands. Placement determines how efficiently the cluster packs that demand.
- What nodes exist underneath. Karpenter is especially strong at this layer: provisioning and consolidating infrastructure around the demand it sees.
Karpenter does not independently decide whether the resource requests in a workload spec reflect real usage. That creates an opportunity for a workload optimization layer to complement node autoscaling.
Datadog's State of Cloud Costs 2024 found that 83% of container costs in its analyzed sample were associated with idle resources: about 54% with cluster idle and 29% with workload idle caused by resource requests larger than workload needs. Those numbers are not a universal benchmark for every cluster, but they illustrate why node optimization and workload rightsizing solve different parts of the problem.
DevZero as a complement to upstream Karpenter#
DevZero's workload tooling can analyze observed CPU, memory, and GPU behavior and generate recommendations that move requests closer to actual demand. Its scheduler can use workload profiles to improve placement. In that model, upstream Karpenter can continue handling node lifecycle while DevZero focuses on the demand and placement signals feeding the cluster.
This is most useful when:
- your Karpenter nodes look reasonably consolidated but workload requests are consistently much larger than observed usage;
- consolidation is creating churn because poor placement leaves fragmented capacity behind;
- consolidation restarts are expensive for your workloads — slow startup, warm caches, long-running jobs — and you want moves that preserve running state via checkpoint/restore instead of evictions, with disruption decisions that account for workload classification;
- you want automated or policy-driven workload rightsizing rather than periodically editing requests by hand.
DevZero Node Operator as a Karpenter-controller replacement#
For teams that want DevZero to manage node lifecycle as well, DevZero documents a migration from upstream Karpenter to its Node Operator. DevZero states that the Node Operator is compatible with existing Karpenter NodePool, NodeClaim, and EC2NodeClass resources, allowing a controller swap rather than a full re-platforming of the cluster.
Its documented migration flow backs up the current resources, scales the upstream controller down, installs the DevZero controller, verifies existing NodeClaims and nodes, and provides a rollback path. DevZero also documents additional features including cost-aware optimization, workload-classification-aware disruption, managed node policies, and an implicit PDB safeguard.
Because those are DevZero product claims, evaluate them in a non-production cluster and compare the resulting behavior against your availability and cost requirements before migrating production node ownership.
Rightsizing and live migration: where the caveats matter#
DevZero's Write Operator applies resource recommendations through three mechanisms: in-place vertical scaling on Kubernetes 1.33+, which patches CPU and memory on a running pod without any restart (memory-limit decreases apply in place on 1.34+ behind an explicit per-workload opt-in); checkpoint/restore-based live migration for supported workloads that need to move; and standard workload-spec changes with a rolling restart as the fallback. DevZero's documentation says that live migration uses CRIU to preserve process state while applying updated resources — see automated pod rightsizing without restarts for how the mechanisms fit together.
Live migration is not universal. DevZero documents conditions where it is skipped or fails — for example, image mismatches, lack of a running source pod, an unavailable node agent, or restore failure. In those cases, the operator can fall back to a standard rolling restart. Workload support and prerequisites also matter, so teams should review the current compatibility documentation before assuming a resize will be restart-free.
When upstream Karpenter alone may be enough#
You may not need another optimization layer if:
- workload requests are already well-tuned and continuously maintained;
- your cluster packs efficiently and consolidation churn is low;
- you are comfortable managing Karpenter policies, IAM, and disruption controls directly;
- the added platform, policy, or commercial overhead of another system would outweigh the savings.
Karpenter is already a strong node autoscaler. DevZero is most compelling when the remaining problem is outside Karpenter's core scope: workload request accuracy, placement quality, policy-driven optimization, or a desire for a more managed node-optimization layer.
A practical way to evaluate the fit#
Before buying or migrating anything, compare one to two weeks of actual CPU and memory usage against requests for your highest-cost namespaces. Then check:
- how much requested capacity is consistently unused;
- how frequently Karpenter consolidates or moves workloads;
- how many nodes remain underutilized because workloads cannot pack tightly;
- whether the operational effort of manual rightsizing is sustainable;
- whether a DevZero pilot reduces cost or churn without violating your SLOs.
That gives you a measurable baseline instead of treating either Karpenter or DevZero as a generic cost-saving switch.
See how much of your Karpenter fleet is reserved for requests nothing uses. Analyze your cluster in minutes:
npx devzero@latest analyze-clusterFrequently Asked Questions#
Is Karpenter free?#
Karpenter itself is open source under Apache 2.0, so there is no Karpenter license fee. You still pay for the compute and other AWS resources it provisions, plus the resources used by the controller. Managed alternatives such as EKS Auto Mode have separate AWS management charges in addition to EC2 pricing.
Can I run Karpenter and Cluster Autoscaler at the same time?#
During a migration, yes — but avoid overlapping ownership. Two autoscalers should not independently manage the same capacity. The documented migration pattern is to bring Karpenter online, verify it, then scale Cluster Autoscaler down and reduce the old node groups in a controlled way.
Does Karpenter work on GKE?#
A community provider exists for GKE Standard, but it is not a Google-managed Karpenter service. Evaluate its current release, API stability, supported features, and support model before treating it as equivalent to the AWS reference implementation.
What is the difference between a NodePool and a NodeClass?#
NodePool describes scheduling and lifecycle policy: requirements, taints, labels, limits, expiry, and disruption. A NodeClass is provider-specific infrastructure configuration. On AWS that resource is EC2NodeClass; on Azure it is AKSNodeClass; community providers define their own equivalents. A NodePool references one NodeClass through nodeClassRef.
How fast does Karpenter provision a node?#
Karpenter calls the cloud compute API directly, but total time still depends on instance availability, image boot time, networking, kubelet registration, daemon startup, and the workload itself. Measure startup latency in your own cluster rather than relying on a single published number. Karpenter exposes karpenter_pods_startup_duration_seconds for observing pod startup duration.
Which Karpenter version do I need for Kubernetes 1.36?#
At the time of this review, the official compatibility matrix lists Karpenter 1.13 or later for Kubernetes 1.36. Always re-check the matrix before a Kubernetes or Karpenter upgrade.
Does Karpenter support scheduled or predictive scaling?#
It is not a demand-forecasting autoscaler. Karpenter reacts to schedulability and node state. You can use disruption-budget schedules to control when voluntary scale-down is allowed, and CapacityBuffers can reserve spare capacity ahead of demand, but those mechanisms are different from predictive traffic forecasting.
Bottom line#
Karpenter is one of the strongest ways to make Kubernetes node capacity responsive to the workloads that actually need to run. On EKS, it is mature enough for production use when the surrounding IAM, discovery, interruption, disruption, and availability controls are designed carefully.
But Karpenter can only optimize the infrastructure around the demand Kubernetes declares. If resource requests are inflated or placement leaves the cluster fragmented, node autoscaling cannot eliminate all of the waste by itself.
For teams already operating Karpenter well, that is the point at which a workload optimization layer such as DevZero becomes worth evaluating. Start with measurement: compare requests with real usage, quantify consolidation churn, and run a controlled pilot. If the remaining waste is primarily at the workload or placement layer, DevZero addresses a problem Karpenter was not designed to solve.
Sources and further reading#
- Karpenter documentation
- Karpenter: Getting Started on EKS
- Karpenter compatibility matrix
- Karpenter disruption documentation
- Karpenter project provider list
- AKS Node Auto-Provisioning
- AKSNodeClass configuration
- Community Karpenter provider for GCP
- Amazon EKS pricing
- Datadog State of Cloud Costs
- DevZero: Migration from Karpenter
- DevZero: Live Migration