Karpenter Custom NodePool as Default

Amazon EKS Auto Mode comes pre-configured with Karpenter and a default general-purpose NodePool that provisions on-demand AMD64 instances with a default weight of 0.
While this ensures any standard pod can schedule immediately, production environments often demand customized compute defaults — such as prioritizing Spot instances, enforcing ARM64 (Graviton) for cost efficiency, or consuming pre-purchased Savings Plans / Reserved Instances.
This guide demonstrates how to define a custom NodePool with higher scheduling priority to override the default EKS Auto NodePool.
📺 Video Walkthrough
How Karpenter Weighted Scheduling Works
Karpenter allows you to prioritize NodePools using the spec.weight attribute:
graph TD
Pod["Incoming Pod (Pending)"] --> Karpenter["Karpenter Autoscaler"]
Karpenter --> Eval{"Evaluate NodePool Weights"}
Eval -- "Weight: 50 (Selected First)" --> PrimNP["Custom Primary NodePool<br/>(Spot + On-Demand, Graviton/AMD64)"]
Eval -- "Weight: 0 (Fallback)" --> DefNP["AWS Default NodePool<br/>(On-Demand AMD64)"]
- When evaluating pending pods, Karpenter sorts eligible NodePools in descending order by weight.
- A NodePool with
weight: 50is evaluated before a NodePool withweight: 0. - If the primary NodePool cannot satisfy the pod requirements (e.g. Spot capacity unavailable or limit reached), Karpenter falls back to subsequent lower-weighted pools.
Step 1. Define the Custom Primary NodePool
The NodePool below sets weight: 50 and allows both spot and on-demand capacity types across c, m, and r instance categories.
primary-nodepool.yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: primary-nodepool
spec:
weight: 50 # Higher priority than EKS Auto default (0)
template:
spec:
expireAfter: 336h
nodeClassRef:
group: eks.amazonaws.com
kind: NodeClass
name: default
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
- key: eks.amazonaws.com/instance-category
operator: In
values: ["c", "m", "r"]
- key: eks.amazonaws.com/instance-generation
operator: Gt
values: ["5"]
- key: kubernetes.io/arch
operator: In
values:
- amd64
- arm64
- key: kubernetes.io/os
operator: In
values:
- linux
terminationGracePeriod: 24h0m0s
Step 2. Apply and Verify Scheduling Priority
# 1. Apply the primary NodePool
kubectl apply -f primary-nodepool.yaml
# 2. Verify registered NodePools and weights
kubectl get nodepools -o custom-columns=NAME:.metadata.name,WEIGHT:.spec.weight
# 3. Deploy a standard workload without any special tolerations or selectors
kubectl create deployment nginx-test --image=nginx --replicas=3
# 4. Confirm that new nodes were provisioned by primary-nodepool
kubectl get nodeclaims -o wide
When checking the provisioned NodeClaim, Karpenter will record primary-nodepool as the owner, preferring Spot instances and multi-arch nodes.
Advanced Use Case: Reserved Capacity Prioritization
If your AWS account has purchased Savings Plans or Regional Reserved Instances for specific instance families (e.g. m6i.large), you can set a custom NodePool targeting m6i On-Demand with weight: 100. Karpenter will continuously saturate your committed capacity before falling back to Spot or general-purpose instances.