Karpenter Provider AWS: Node Provisioning Without Node Groups
Karpenter is a Kubernetes Node Autoscaler built for flexibility, performance, and simplicity.
At a glance
- What is it?
- Karpenter watches for unschedulable pods and provisions EC2 capacity to fit them, replacing the node-group model with a controller that reads pod constraints directly. This is a review of what the repository exposes, how it installs, and where it stops being the right tool.
- Who is it for?
- Adopt Karpenter Provider AWS if you run EKS, can grant the controller EC2 and IAM permissions, and want node shapes decided per pod rather than per node group. Do not adopt it if you run Kubernetes outside AWS, if you cannot tolerate a controller holding EC2 create and terminate rights, or if your platform team has no capacity to own NodePool and EC2NodeClass definitions.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The scheduling gap Karpenter Provider AWS closes
The Kubernetes scheduler is good at placing pods on nodes that already exist. It has no opinion about creating them. For years the answer was the Cluster Autoscaler plus a set of node groups: you decide ahead of time that you want a pool of m5.large and a pool of c5.xlarge, set min and max sizes, and hope the pods that arrive fit one of the shapes you guessed. When they do not, they stay Pending until someone edits an Auto Scaling group.
Karpenter starts from the other direction. According to the README, it watches for pods that the Kubernetes scheduler has marked as unschedulable, evaluates the constraints those pods carry (resource requests, node selectors, affinities, tolerations, topology spread constraints), provisions nodes that meet the requirements, and removes nodes when they are no longer needed. The unit of decision is the pod, not the group. That is the whole design difference, and it explains why the project has no node group concept at all.
The audience is platform and infrastructure engineers running Amazon EKS who are willing to hand node lifecycle decisions to a controller. The repository is Go, licensed Apache-2.0, and the last push was on 2026-09-21, so the codebase is current. The latest release listed is v1.14.1, marked LTS, from 2026-08-21, with v1.11.3 and v1.10.2 from 2026-07-17 still published alongside it.
How the controller turns pending pods into EC2 instances
The go.mod file is the clearest map of the mechanism. The module requires aws-sdk-go-v2/service/ec2, service/eks, service/iam, service/pricing, service/ssm, service/sqs, service/sts, service/fis, service/arczonalshift and service/timestreamwrite. Each of those maps to a job the controller does. EC2 is where instances are created and terminated. Pricing and SSM are where instance-type and AMI facts come from. SQS is the interruption queue that carries Spot interruption notices and instance state changes. EKS is how the controller learns which cluster it belongs to. FIS and arczonalshift relate to fault injection and zonal shift handling for resilience features.
The dependency on github.com/awslabs/operatorpkg and operatorpkg/aws matters for anyone reading the code. Karpenter's core reconciliation loop lives in the sigs.k8s.io/karpenter module, and this repository is the AWS-specific provider layered on top of it. That is why the project is named karpenter-provider-aws rather than karpenter. The provider supplies the cloud calls; the upstream module supplies the scheduling and lifecycle logic. If you are debugging why a node was chosen, the decision logic and the EC2 call live in different repositories.
The custom resources follow the same split. A NodePool describes what kinds of nodes are acceptable (instance families, capacity types, zones, taints, disruption budgets). An EC2NodeClass describes how to build them (AMI selection, subnets, security groups, IAM instance profile). The controller reads both, intersects them with the pending pods' constraints, and calls EC2. The Makefile confirms the feature-gate surface: nodeRepair, reservedCapacity, spotToSpotConsolidation, nodeOverlay, staticCapacity and capacityBuffer are all set through Helm values in the project's own install target, which tells you these are the toggles the maintainers exercise.
Installing Karpenter Provider AWS with the Helm chart
The README points to the documentation site at karpenter.sh for installation rather than embedding steps, so the authoritative procedure lives there. The repository's Makefile does show the shape of the install the maintainers use for development, and the Helm values in it are real. The chart is published as karpenter-crd and karpenter, and the OCI registry path aws/karpenter appears in the related searches for this project, which is consistent with the chart being distributed as an OCI artifact.
The Makefile's HELM_OPTS block is the concrete evidence for what a Karpenter install sets. It configures the cluster name, the interruption queue, the IRSA role annotation, the controller resource requests and the feature gates:
HELM_OPTS ?= --set serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn=${KARPENTER_IAM_ROLE_ARN} \
--set settings.clusterName=${CLUSTER_NAME} \
--set settings.interruptionQueue=${CLUSTER_NAME} \
--set settings.enableZonalShift=${ENABLE_ZONAL_SHIFT}\
--set controller.resources.requests.cpu=1 \
--set controller.resources.requests.memory=1Gi \
--set controller.resources.limits.cpu=1 \
--set controller.resources.limits.memory=1Gi \
--set settings.featureGates.nodeRepair=true \
--set settings.featureGates.reservedCapacity=true \
--set settings.featureGates.spotToSpotConsolidation=true \
--set settings.featureGates.nodeOverlay=true \
--set settings.featureGates.staticCapacity=true \
--set settings.featureGates.capacityBuffer=true \
--set settings.preferencePolicy=Ignore \
--set logLevel=debug \
--create-namespaceThose are the exact keys the project passes to Helm: settings.clusterName, settings.interruptionQueue, settings.enableZonalShift, the serviceAccount annotation key with its escaped dots, the controller resource requests and limits, the six feature gates, settings.preferencePolicy, logLevel and --create-namespace. After the release settles you should see a karpenter controller running and, once you apply a NodePool, nodes appearing in response to pending pods rather than to an Auto Scaling group event.
The second half of a first real use is the NodePool and EC2NodeClass pair. The repository keeps examples under examples/v1/, which is where to look for the current API version rather than copying an older blog post. Applying a NodePool alone is not enough; without an EC2NodeClass the controller has no AMI, subnet or security group information and cannot build an instance. That two-object requirement is the most common first-run mistake.
The Makefile also records the variables used to build and deploy the controller image during development:
KARPENTER_NAMESPACE ?= kube-system
KO_DOCKER_REPO ?= ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/dev
KOCACHE ?= ~/.koIf a NodePool reports a ready condition of False, the message points at the missing or invalid EC2NodeClass field, not at the pods.
Where Karpenter Provider AWS is the wrong tool
The provider is AWS-only by construction. Every cloud call in go.mod is an AWS SDK call, and the repository name says so. The related searches include Karpenter GCP and Karpenter cloud providers, which reflects a real question, but this repository answers it narrowly: it is the AWS provider. Running Karpenter elsewhere means a different provider implementation, not a configuration flag here.
The second limit is operational surface. Karpenter needs permission to create and terminate EC2 instances, read SSM parameters for AMIs, read pricing, and consume an SQS interruption queue. The Makefile builds an IAM role ARN named ${CLUSTER_NAME}-karpenter and annotates the service account with it, so the expected model is IRSA. If your organization treats instance termination as a privileged action requiring human approval, Karpenter's consolidation behaviour is directly at odds with that policy. It removes nodes when they are no longer needed, and that is a feature you cannot half-enable.
The third limit is that node shapes become emergent rather than declared. With node groups, capacity is a number you can read off a dashboard. With Karpenter, the number of instances and their types are outputs of the pending-pod set and the NodePool constraints. Teams that need a fixed, auditable instance inventory for compliance reasons will find this uncomfortable, and the repository does not offer a mode that pins the fleet to a predetermined list.
Finally, the README does not document rollback. There is no uninstall or revert procedure in it, and the Helm values in the Makefile are development-oriented (logLevel=debug, preferencePolicy=Ignore). Anyone planning a migration should read the karpenter.sh docs for the removal path rather than inferring one from the repository.
Karpenter versus the Cluster Autoscaler, concretely
The honest alternative is the Kubernetes Cluster Autoscaler, and the difference is not performance, it is where the decision is made. The Cluster Autoscaler scales Auto Scaling groups. It sees that pods are pending, checks whether increasing an existing group's desired capacity would help, and if so asks EC2 Auto Scaling to do it. The group's instance type, subnet and AMI are fixed when the group is created. If no group can accommodate the pod, the pod waits.
Karpenter skips the group. It reads the pod's own constraints and picks an instance type that satisfies them, subject to the NodePool. That means a workload with a specific GPU requirement or an unusual memory-to-CPU ratio can be satisfied without anyone having pre-created a matching group. It also means consolidation can move workloads onto fewer or cheaper instances without a group boundary in the way.
The cost of that flexibility is that you now own two custom resources per capacity profile and a controller with broad EC2 permissions. With the Cluster Autoscaler you own Auto Scaling group definitions and an IAM policy scoped to those groups. Neither is strictly safer; they fail differently. The Cluster Autoscaler fails by leaving pods pending when no group matches. Karpenter fails by provisioning something you did not expect if a NodePool is written too permissively. Writing NodePool requirements tightly is the equivalent of the Cluster Autoscaler's group definition, and it is the part teams most often leave loose.
Licence, upgrade cadence and what maintenance costs
The repository is Apache-2.0, and it ships a NOTICE file and a THIRD_PARTY_LICENSES file at the top level. Apache-2.0 is permissive and includes an explicit patent grant, which matters for a component that sits in the control plane of your cluster. It does not, on its own, tell you anything about the licences of the vendored dependencies; the THIRD_PARTY_LICENSES file is there for that, and it is the file to read if your legal process requires it. Nothing here is legal advice, and the licence text governs.
Upgrade cost is the more practical concern. The release list shows three lines maintained in parallel: v1.14.1 as LTS, plus v1.11.3 and v1.10.2. That pattern tells you the project expects users to lag, and that the LTS line is the one to pin if you do not want to chase API changes. Because NodePool and EC2NodeClass are versioned custom resources, an upgrade is not only a controller image change; the CRDs move with it. The examples/ directory is versioned (examples/v1/) for exactly this reason. A safe upgrade reads the release notes for the CRD version, applies the matching karpenter-crd chart first, then the controller.
The build also pins a specific Go toolchain (go 1.26.6 in go.mod) and uses ko for image builds, with KO_DOCKER_REPO and KOCACHE variables in the Makefile. That matters only if you intend to build from source; consumers of the Helm chart never touch it.
Editorial conclusion
Adopt Karpenter Provider AWS if you run EKS, can grant the controller EC2 and IAM permissions, and want node shapes decided per pod rather than per node group. Do not adopt it if you run Kubernetes outside AWS, if you cannot tolerate a controller holding EC2 create and terminate rights, or if your platform team has no capacity to own NodePool and EC2NodeClass definitions. Before committing, verify three things in your own cluster: that the Helm chart version you pin matches the Karpenter CRD version your cluster already has, that the interruptionQueue setting points at a queue that actually receives EC2 Spot and instance-state events, and that your PodDisruptionBudgets will not block the consolidation path. The repository's own Makefile shows the expected install shape, including the IRSA role annotation and the settings.clusterName and settings.interruptionQueue values.
Frequently asked questions
Which cloud providers support Karpenter?
This repository is the AWS provider, and every cloud API call in its go.mod is an AWS SDK call. Support for other clouds would come from a separate provider implementation, not from a setting in this one.
What is Karpenter Provider AWS?
It is the AWS-specific provider for Karpenter, an open-source Kubernetes node provisioning project. According to the README, it watches for pods the scheduler marked unschedulable, evaluates their constraints, provisions nodes that meet the requirements, and removes nodes when they are no longer needed.
Is Karpenter open-source?
Yes. The repository is licensed Apache-2.0 and carries a LICENSE, NOTICE and THIRD_PARTY_LICENSES file at the top level.
Who created Karpenter?
The repository is published under the aws GitHub organization as aws/karpenter-provider-aws. The README does not name individual authors; the CODEOWNERS file in the repository root is where ownership is recorded.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/aws-karpenter-provider-aws)