Karpenter — Deploy to a Specific Node Type

Amazon EKS Auto Mode includes Karpenter pre-installed with a default general-purpose NodePool that provisions standard AMD64 on-demand instances.
However, specialized workloads often require specific instance families (e.g. Memory-Optimized r series, Compute-Optimized c series, GPU instances, or Spot instances).
By combining custom Karpenter NodePools with Kubernetes taints, tolerations, and nodeSelectors, you can pin specific workloads to tailor-made EC2 instance types while preventing other pods from scheduling on them.
NodeClass Scope
In EKS Auto Mode, the default NodeClass (group: eks.amazonaws.com) is managed by AWS. You can reference it directly in your custom NodePools without creating a custom NodeClass unless you need bespoke subnets or storage.
📺 Video Walkthrough
Architecture: Workload Pinning with Taints & Labels
graph TD
Pod["Pod with Toleration & nodeSelector<br/>(instancegroup: spot-m)"]
DefaultNP["Default NodePool<br/>(General Purpose On-Demand)"]
SpotMNP["Custom NodePool: spot-m-nodepool<br/>Taint: instance-type=spot-m:NoSchedule<br/>Label: instancegroup=spot-m-instancegroup"]
Pod -. "Bypasses Taint & Matches Label" .-> SpotMNP
SpotMNP --> EC2["EC2 Memory-Optimized Spot Instance (m7i, m6i)"]
Step 1. Define Custom NodePool with Taints & Labels
The NodePool below restricts instance generation to m series Spot instances, applies a label to newly created nodes, and places a NoSchedule taint so general workloads do not schedule here.
spot-m-nodepool.yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: spot-m-nodepool
spec:
template:
metadata:
labels:
instancegroup: spot-m-instancegroup
spec:
expireAfter: 336h
nodeClassRef:
group: eks.amazonaws.com
kind: NodeClass
name: default
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot"]
- key: eks.amazonaws.com/instance-category
operator: In
values: ["m"]
taints:
- key: instance-type
value: "spot-m"
effect: NoSchedule
Step 2. Configure Application with Tolerations & NodeSelector
The deployment below specifies both:
1. tolerations: Allows the pod to tolerate the instance-type=spot-m:NoSchedule taint.
2. nodeSelector: Directs Karpenter to match the node label instancegroup: spot-m-instancegroup.
spot-m-echoserver.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: echoserver
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: echoserver
template:
metadata:
labels:
app: echoserver
spec:
nodeSelector:
instancegroup: spot-m-instancegroup
tolerations:
- key: "instance-type"
operator: "Equal"
value: "spot-m"
effect: "NoSchedule"
containers:
- name: demo-echo
image: k8s.gcr.io/e2e-test-images/echoserver:2.5
ports:
- containerPort: 8080
resources:
requests:
cpu: "500m"
memory: "512Mi"
Verification
# 1. Apply NodePool and Deployment
kubectl apply -f spot-m-nodepool.yaml
kubectl apply -f spot-m-echoserver.yaml
# 2. Watch Karpenter provision the dedicated Spot instance
kubectl get nodeclaims -o wide
# 3. Verify the pod is running on the newly created node
kubectl get pods -l app=echoserver -o wide