Taints, Tolerations, and Node Affinity
Taints and tolerations
- Taint on node → repels Pods without matching toleration
- Toleration on Pod → allowed on tainted node
- Taints do not guarantee placement on a node: only who may run there
kubectl taint nodes node1 app=blue:NoSchedule
kubectl taint nodes node1 app=blue:NoSchedule-
| Effect | Behaviour |
|---|
NoSchedule | No new Pods without toleration |
PreferNoSchedule | Try to avoid, not guaranteed |
NoExecute | Evict running Pods without toleration |
tolerations:
- key: app
operator: Equal
value: blue
effect: NoSchedule
Node selector
- Label node →
nodeSelector in Pod spec - Limitation: no OR / NOT: use nodeAffinity for complex rules
nodeSelector:
size: Large
Node affinity
| Type | Scheduling | If label changes after schedule |
|---|
requiredDuringSchedulingIgnoredDuringExecution | Must match | Pod not evicted |
preferredDuringSchedulingIgnoredDuringExecution | Prefer match | Pod not evicted |
- Operators:
In, NotIn, Exists, DoesNotExist, Gt, Lt
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: size
operator: In
values: [Large, Medium]
When to use what
| Goal | Mechanism |
|---|
| Block certain Pods from a node | Taints + tolerations |
| Require Pods on specific nodes | Node affinity |
| Dedicated nodes + dedicated Pods | Taint node and nodeAffinity on Pod |
DaemonSet on every node
DaemonSets often need tolerations so they also run on control-plane nodes:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-monitor
spec:
selector:
matchLabels:
app: node-monitor
template:
metadata:
labels:
app: node-monitor
spec:
nodeSelector:
kubernetes.io/os: linux
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
containers:
- name: monitor
image: busybox
command: ["sh", "-c", "while true; do echo $(hostname); sleep 30; done"]
Exam tips
- Taints ≠ guaranteed placement: pair with node affinity for dedicated workloads
- Remove taint: append
- to key (app=blue:NoSchedule-) - DaemonSet controller creates one Pod per matching node; Pod template still needs tolerations for tainted nodes