CKA — Node Affinity
CKA Exam Domain
| Domain | Weight |
|---|---|
| Workloads & Scheduling | 15% |
Node affinity questions on the CKA exam often require you to write YAML from scratch. Memorize the structure — it’s verbose but predictable.
What Is Node Affinity?
Node affinity is the advanced version of nodeSelector. It gives you expressive rules for placing Pods on nodes using set-based operators, soft preferences, and complex logic.
Node affinity lives under .spec.affinity.nodeAffinity and supports two scheduling modes:
| Mode | Behavior |
|---|---|
requiredDuringSchedulingIgnoredDuringExecution |
Hard — Pod won’t schedule if no node matches |
preferredDuringSchedulingIgnoredDuringExecution |
Soft — Scheduler tries to match, but falls back if needed |
The
IgnoredDuringExecutionpart means that if a node’s labels change after the Pod is running, the Pod is not evicted.
requiredDuringSchedulingIgnoredDuringExecution
This is a hard requirement. The Pod will stay Pending if no node satisfies the rule.
apiVersion: v1
kind: Pod
metadata:
name: affinity-required
spec:
containers:
- name: nginx
image: nginx:1.27
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
- nvme
This Pod will only schedule on nodes where disktype is ssd or nvme.
kubectl apply -f affinity-required.yaml
kubectl get pod affinity-required -o wide
preferredDuringSchedulingIgnoredDuringExecution
This is a soft preference. The scheduler will try to honor it, but if no matching node is available, the Pod is scheduled elsewhere.
apiVersion: v1
kind: Pod
metadata:
name: affinity-preferred
spec:
containers:
- name: nginx
image: nginx:1.27
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: zone
operator: In
values:
- us-east-1a
- weight: 20
preference:
matchExpressions:
- key: zone
operator: In
values:
- us-east-1b
The weight field (1–100) tells the scheduler how strongly to prefer each rule. Higher weight = stronger preference. Here, us-east-1a is strongly preferred over us-east-1b.
Affinity Operators
| Operator | Description | Example |
|---|---|---|
In |
Label value is in the given set | values: [ssd, nvme] |
NotIn |
Label value is not in the given set | values: [hdd] |
Exists |
Label key exists (value doesn’t matter) | key: gpu |
DoesNotExist |
Label key does not exist | key: gpu |
Gt |
Label value is greater than (numeric) | values: ["4"] |
Lt |
Label value is less than (numeric) | values: ["8"] |
Exam Tip:
GtandLtcompare the label value as an integer. The value must still be specified as a string in YAML.
Multiple Match Expressions
Understanding AND vs OR logic is critical:
- Multiple
matchExpressionswithin the samenodeSelectorTermsentry → AND (all must match) - Multiple
nodeSelectorTermsentries → OR (any one can match)
AND example — node must have both labels:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values: ["ssd"]
- key: zone
operator: In
values: ["us-east-1a"]
OR example — node must match either term:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values: ["ssd"]
- matchExpressions:
- key: zone
operator: In
values: ["us-east-1a"]
Pod Affinity and Anti-Affinity
While node affinity matches Pods to nodes, Pod affinity and anti-affinity match Pods to other Pods using topologyKey.
Pod Affinity — Co-locate Pods
Schedule a Pod on the same node (or zone) as another Pod:
apiVersion: v1
kind: Pod
metadata:
name: web-frontend
spec:
containers:
- name: nginx
image: nginx:1.27
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostname
This Pod will only be scheduled on a node that already runs a Pod with app=cache.
Pod Anti-Affinity — Spread Pods Apart
Prevent Pods from landing on the same node:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
Each replica lands on a different node. This is a common pattern for high availability.
topologyKeydefines the scope:kubernetes.io/hostname= same node,topology.kubernetes.io/zone= same zone.
nodeSelector vs Node Affinity
| Feature | nodeSelector | Node Affinity |
|---|---|---|
| Syntax | Simple key-value | Verbose YAML under .spec.affinity |
| Match type | Exact match only | Set-based operators |
| Soft preference | Not supported | preferredDuringScheduling |
| OR logic | Not supported | Multiple nodeSelectorTerms |
| Complexity | Low | Medium |
| CKA frequency | Common | Very common |
kubectl Commands
# Label a node for affinity matching
kubectl label nodes <node-name> <key>=<value>
# Check Pod scheduling
kubectl get pod <pod-name> -o wide
# Describe Pod to see affinity rules and events
kubectl describe pod <pod-name>
# View node labels
kubectl get nodes --show-labels
# Dry-run to generate Pod YAML
kubectl run affinity-test --image=nginx --dry-run=client -o yaml > pod.yaml
Practice Questions
Q1. Create a Pod with a hard node affinity rule that schedules only on nodes with zone set to us-east-1a or us-west-2a.
Show Answer
apiVersion: v1
kind: Pod
metadata:
name: zone-pod
spec:
containers:
- name: nginx
image: nginx:1.27
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: zone
operator: In
values:
- us-east-1a
- us-west-2a
Q2. Write a soft affinity rule that prefers nodes with tier=frontend (weight 70) but falls back to any node.
Show Answer
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 70
preference:
matchExpressions:
- key: tier
operator: In
values:
- frontend
Q3. What is the difference between multiple matchExpressions in one nodeSelectorTerms entry vs multiple nodeSelectorTerms entries?
Show Answer
- Multiple
matchExpressionsin onenodeSelectorTermsentry = AND (all must match). - Multiple
nodeSelectorTermsentries = OR (any one must match).
Q4. Create a Deployment with 3 replicas that uses pod anti-affinity to ensure each replica runs on a different node.
Show Answer
apiVersion: apps/v1
kind: Deployment
metadata:
name: spread-deploy
spec:
replicas: 3
selector:
matchLabels:
app: spread
template:
metadata:
labels:
app: spread
spec:
containers:
- name: nginx
image: nginx:1.27
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- spread
topologyKey: kubernetes.io/hostname
Q5. A Pod has requiredDuringSchedulingIgnoredDuringExecution with disktype In [ssd]. After the Pod is running, you remove the disktype label from the node. What happens?
Show Answer
Nothing. The IgnoredDuringExecution part means the Pod is not evicted if node labels change after scheduling. The Pod continues to run.