Skip to content
Rahul Shishodiaon GitHub LinkedIn profile

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-   # remove (key-)
EffectBehaviour
NoScheduleNo new Pods without toleration
PreferNoScheduleTry to avoid, not guaranteed
NoExecuteEvict running Pods without toleration
tolerations:
- key: app
  operator: Equal    # or Exists
  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

TypeSchedulingIf label changes after schedule
requiredDuringSchedulingIgnoredDuringExecutionMust matchPod not evicted
preferredDuringSchedulingIgnoredDuringExecutionPrefer matchPod 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

GoalMechanism
Block certain Pods from a nodeTaints + tolerations
Require Pods on specific nodesNode affinity
Dedicated nodes + dedicated PodsTaint 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