CKAD — Node Selection
Why Control Node Placement?
By default, the Kubernetes scheduler places Pods on any node with enough resources. Sometimes you need more control — you might want Pods on GPU nodes, in specific availability zones, or away from certain workloads.
Kubernetes provides several mechanisms for controlling Pod placement:
| Mechanism | Complexity | Use Case |
|---|---|---|
nodeSelector |
Simple | Match specific node labels |
| Node affinity | Medium | Flexible rules with preferences |
| Taints & tolerations | Medium | Prevent scheduling on certain nodes |
| Pod affinity/anti-affinity | Advanced | Co-locate or spread Pods relative to each other |
nodeSelector (Simple)
The simplest way to constrain Pods to specific nodes. The Pod will only be scheduled on nodes that have ALL the specified labels.
apiVersion: v1
kind: Pod
metadata:
name: gpu-app
spec:
nodeSelector:
accelerator: nvidia-gpu
containers:
- name: app
image: my-gpu-app:v1
# Label a node first
kubectl label node worker-1 accelerator=nvidia-gpu
# Verify the label
kubectl get nodes --show-labels | grep accelerator
# Now create the Pod — it will be scheduled on worker-1
kubectl apply -f gpu-pod.yaml
nodeSelector Behavior
| Scenario | Result |
|---|---|
| Node with matching labels exists | Pod scheduled on that node |
| Multiple nodes match | Scheduler picks the best one based on resource availability |
| No nodes match | Pod stays in Pending state |
| Label removed from node | Running Pods stay; new Pods won’t schedule there |
Node Affinity (Advanced)
Node affinity is a more expressive version of nodeSelector. It supports “preferred” rules (soft constraints) and set-based operators.
Required Affinity (Hard Constraint)
The Pod MUST be scheduled on a matching node. If no nodes match, the Pod stays Pending.
apiVersion: v1
kind: Pod
metadata:
name: zone-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1a
- us-east-1b
containers:
- name: app
image: nginx:1.27
Preferred Affinity (Soft Constraint)
The scheduler TRIES to place the Pod on a matching node, but will use other nodes if necessary.
apiVersion: v1
kind: Pod
metadata:
name: preferred-zone
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1a
- weight: 20
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1b
containers:
- name: app
image: nginx:1.27
Node Affinity Operators
| Operator | Description | Example |
|---|---|---|
In |
Value is in the set | zone In [us-east-1a, us-east-1b] |
NotIn |
Value is NOT in the set | zone NotIn [us-west-2a] |
Exists |
Key exists (any value) | gpu Exists |
DoesNotExist |
Key does not exist | spot DoesNotExist |
Gt |
Value is greater than | cores Gt 4 |
Lt |
Value is less than | cores Lt 16 |
nodeSelector vs Node Affinity
| Feature | nodeSelector | Node Affinity |
|---|---|---|
| Syntax | Simple key-value pairs | Expressive match expressions |
| Hard constraint | Yes (only) | Yes (required) |
| Soft constraint | No | Yes (preferred) with weights |
| Multiple conditions | AND only | AND and OR (multiple nodeSelectorTerms) |
| Set operators | No | Yes (In, NotIn, Exists, etc.) |
| When to use | Simple cases | Complex scheduling requirements |
Taints and Tolerations (Preview)
Taints are the opposite of affinity — they repel Pods from nodes. A Pod must have a matching toleration to be scheduled on a tainted node.
# Add a taint to a node
kubectl taint nodes worker-1 gpu=nvidia:NoSchedule
# Remove a taint
kubectl taint nodes worker-1 gpu=nvidia:NoSchedule-
# Pod with a toleration
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
tolerations:
- key: "gpu"
operator: "Equal"
value: "nvidia"
effect: "NoSchedule"
containers:
- name: app
image: my-gpu-app:v1
| Taint Effect | Behavior |
|---|---|
NoSchedule |
Don’t schedule new Pods without matching toleration |
PreferNoSchedule |
Try to avoid scheduling, but allow if necessary |
NoExecute |
Evict existing Pods that don’t have matching toleration |
Exam tip: For the CKAD exam, focus on nodeSelector and basic node affinity. Taints and tolerations appear more frequently in the CKA exam, but you should understand the basic concept.
Common Node Labels
Kubernetes automatically adds labels to nodes that you can use for scheduling:
| Label | Description | Example Value |
|---|---|---|
kubernetes.io/hostname |
Node hostname | worker-1 |
kubernetes.io/os |
Operating system | linux |
kubernetes.io/arch |
CPU architecture | amd64, arm64 |
topology.kubernetes.io/zone |
Availability zone | us-east-1a |
topology.kubernetes.io/region |
Region | us-east-1 |
node.kubernetes.io/instance-type |
Instance type (cloud) | m5.large |
# View all labels on a node
kubectl get node worker-1 --show-labels
# Filter by a specific label
kubectl get nodes -l topology.kubernetes.io/zone=us-east-1a
Next: Put it all together with Hands-On Lab & Practice →