Free lesson · CKA Prep Program · Module 3: Workloads and scheduling
Control Placement with Taints, Tolerations and Affinity
Scheduling is matchmaking with rules: taints say who is refused, tolerations say who is excused, affinity says who is preferred. Together they place workloads exactly where they belong.
13 min reading
Objectives
- Repel pods from nodes with taints and admit them back with tolerations
- Attract pods to nodes or to each other with affinity rules
- Combine node affinity with pod anti-affinity for spread plus fit
- Read a Pending pod and tell placement failure apart from resource shortage
Why this matters
Dedicated GPU nodes should not fill with web pods. Replicas of one service should not share a single rack. System pods must land everywhere including cordoned-looking nodes. Labels plus rules express all of this declaratively, and the scheduler enforces it every placement. The exam turns these into Pending-pod puzzles: the events name the failed predicate if you read them.
Concepts
A taint on a node repels pods unless they tolerate it, with three effects: NoSchedule blocks new placements, PreferNoSchedule discourages them, NoExecute evicts existing pods too (optionally after tolerationSeconds). Control-plane nodes carry a NoSchedule taint by default, which is why user pods avoid them without any configuration on your part.
Tolerations excuse pods from taints by key, operator and effect. They never attract: a tolerating pod may still land anywhere. System DaemonSets tolerate everything precisely so they cover tainted nodes as well.
Affinity attracts. Node affinity constrains which nodes qualify (required rules are hard, preferred rules weight the choice). Pod affinity co-locates with selected pods; pod anti-affinity spreads apart, which is how you keep replicas off the same node or the same zone with topologyKey. Combine them: node affinity for fit (GPU, SSD, zone), anti-affinity for spread.
Worked example
GPU work only on GPU nodes, replicas never sharing a node:
# taint the GPU pool once, per node
kubectl taint nodes gpu-1 gpu=true:NoSchedule
# workload tolerates the taint, requires the label, spreads itself
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- { key: gpu, operator: In, values: ["true"] }
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels: { app: trainer }
topologyKey: kubernetes.io/hostname
tolerations:
- { key: gpu, operator: Exists, effect: NoSchedule }Web pods without the toleration never touch gpu-1. Trainer replicas land only on GPU nodes and never two on one host. Remove the toleration and watch them go Pending with a taint event: the error message is the lesson.
Exam notes
Toleration without affinity lands anywhere: admitting is not attracting, and questions exploit the confusion. topologyKey: kubernetes.io/hostname spreads per node; the zone key spreads per zone. And NoExecute evicts running pods, so adding it mid-day restarts workloads: check tolerationSeconds before touching live taints.
Quick check
A 4-question self-check. Your answers stay on your device, are never stored or sent. Only a passing score (for example 3 of 4) is saved, and only to unlock lesson progress: at least 3 correct is required before a lesson counts as complete. It never counts toward any certification assessment.
Lesson feedback
No published feedback yet.
Log in and complete the lesson to leave feedback.
Exercise
Taint one lab node, then write a deployment that is the only workload allowed on it while its three replicas never share a node. Show the taint command, the toleration, both affinity blocks, and the describe output that proves placement.
Pass criteria
Taint plus toleration match; node affinity requires the label; anti-affinity spreads on hostname; describe shows one pod per node with only this workload on the tainted node.