3.8 Node Taints & Pod Tolerations
Key Takeaways
- Taints are applied to nodes to repel unauthorized Pods; Tolerations are applied to Pods to allow (but not force) scheduling on tainted nodes.
- A Taint consists of key, value, and effect (Key=Value:Effect); supported effects are NoSchedule, PreferNoSchedule, and NoExecute.
- NoExecute taints immediately evict running non-tolerating Pods, or delay eviction according to tolerationSeconds.
- Toleration matching requires either operator: Equal (matching key, value, and effect) or operator: Exists (matching key and effect regardless of value).
- Dedicated node pools (e.g., GPU hardware or PCI-DSS isolated compute) require combining Taints/Tolerations with Node Affinity for bidirectional isolation.
Node Taints & Pod Tolerations
While Node Affinity attracts Pods to specific nodes, Taints and Tolerations work in reverse: Taints allow a node to repel a set of Pods, ensuring that arbitrary workloads do not land on specialized, reserved, or unhealthy hardware. Tolerations are applied to Pod manifests, allowing (but not forcing) the Pod to schedule onto nodes with matching taints.
1. Taints and Tolerations Mechanics
+-----------------------------------------------------------------------------------------+
| TAINTS AND TOLERATIONS MECHANICS |
| |
| [Node 1: Tainted] (dedicated=gpu:NoSchedule) |
| ^ |
| | |
| +------+---------------------------------------+ |
| | | |
| [Pod A: No Toleration] [Pod B: Toleration for dedicated=gpu] |
| --> REPELLED (Cannot schedule on Node 1) --> ALLOWED (Can schedule on Node 1) |
| |
| * Critical Rule: Tolerations ALLOW scheduling; they do not FORCE scheduling. |
| To guarantee Pod B ONLY lands on Node 1, combine with Node Affinity! |
+-----------------------------------------------------------------------------------------+
Applying and Removing Taints via kubectl
# Syntax: kubectl taint nodes <node-name> key=value:effect
kubectl taint nodes worker-gpu-01 dedicated=gpu:NoSchedule
# Applying a taint without a value (key:effect)
kubectl taint nodes worker-02 maintenance:NoExecute
# Inspect taints applied to a node
kubectl describe node worker-gpu-01 | grep -i taints
# Output: Taints: dedicated=gpu:NoSchedule
# Removing a taint (append a minus '-' sign to the effect)
kubectl taint nodes worker-gpu-01 dedicated=gpu:NoSchedule-
kubectl taint nodes worker-02 maintenance:NoExecute-
2. The Three Taint Effects Deep Dive
A taint's Effect determines the enforcement behavior applied by kube-scheduler and kubelet:
| Taint Effect | Impact on Pending (New) Pods | Impact on Already Running Pods | Primary Production Use Case |
|---|---|---|---|
NoSchedule | Pods without a matching toleration will not be scheduled on the node. | Existing Pods already running on the node continue running unaffected. | Dedicated node pools (e.g. GPU compute, high-memory datastores, control-plane nodes). |
PreferNoSchedule | Scheduler attempts to avoid placing the Pod on the node, but will place it there if no other compute is available. | Existing Pods continue running unaffected. | Non-critical preferences (e.g. edge nodes, spot/preemptible instances, bursting pools). |
NoExecute | Pods without a matching toleration will not be scheduled on the node. | Existing Pods without matching toleration are immediately evicted from the node. | Active node maintenance, draining, hardware failures, kernel upgrades. |
3. Pod Toleration Syntax and Matching Rules
A Pod defines tolerations in spec.tolerations using either the Equal or Exists operator.
Example 1: Exact Match with operator: Equal
Requires exact matching of key, value, and effect:
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
Example 2: Key Matching with operator: Exists
Matches any taint with the specified key regardless of its value:
spec:
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
Example 3: Universal Match (Match All Taints)
Leaving key empty with operator: Exists matches all keys, values, and effects (used by cluster-critical DaemonSets like CNI and logging agents):
spec:
tolerations:
- operator: "Exists"
4. tolerationSeconds and Delayed Eviction under NoExecute
When a node is tainted with NoExecute, running Pods that tolerate the taint can specify tolerationSeconds to define a grace period before eviction:
spec:
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 300
- key: "node.kubernetes.io/not-ready"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 300
If the node enters NotReady or Unreachable state, kubelet delays eviction for 300 seconds (5 minutes), allowing transient network partitions to recover without triggering unnecessary Pod rescheduling.
5. Built-in System Taints Injected by Node Controller
The Kubernetes control plane automatically injects node taints when node conditions degrade:
node.kubernetes.io/not-ready: Node is unhealthy and not ready to receive Pods.node.kubernetes.io/unreachable: Node controller has lost communication with kubelet.node.kubernetes.io/memory-pressure: Node memory is exhausted.node.kubernetes.io/disk-pressure: Node disk capacity is exhausted.node.kubernetes.io/pid-pressure: Node process ID space is exhausted.node.kubernetes.io/network-unavailable: Node network CNI is uninitialized.node.kubernetes.io/unschedulable: Node is cordoned (kubectl cordon <node>).
6. Constructing Dedicated Node Pools: The Bidirectional Isolation Pattern
A frequent CKA exam requirement is dedicating nodes exclusively to a specific workload (e.g. GPU compute for machine learning) such that:
- Standard workloads CANNOT run on the GPU nodes.
- GPU workloads CANNOT run on standard CPU nodes.
The Complete 3-Step Implementation
- Taint the specialized nodes to repel all standard workloads:
kubectl taint nodes gpu-node-01 sku=gpu:NoSchedule - Label the specialized nodes for targeting:
kubectl label nodes gpu-node-01 sku=gpu - Configure the ML Pods with both a Toleration (to pass the taint) AND Node Affinity / nodeSelector (to force placement on the labeled nodes):
apiVersion: v1
kind: Pod
metadata:
name: gpu-training-pipeline
spec:
# 1. Force Pod onto GPU nodes
nodeSelector:
sku: gpu
# 2. Allow Pod to tolerate the GPU taint
tolerations:
- key: "sku"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
containers:
- name: model-trainer
image: tensorflow/tensorflow:latest-gpu
An operator taints a worker node with 'kubectl taint nodes node1 environment=production:NoSchedule'. There are currently 10 web application Pods running on node1 that lack any tolerations. What happens to these 10 running Pods?
Which of the following toleration definitions correctly matches ANY taint with key 'storage-heavy', regardless of its value, with effect NoSchedule?
An administrator wishes to set up dedicated GPU nodes in a Kubernetes cluster so that ONLY GPU-intensive workloads can run on them, and GPU workloads NEVER land on standard CPU nodes. What configuration pattern is required?