Kubernetes Taint and Toleration Placement
Kubernetes Taint and Toleration Placement manages node scheduling by restricting pod placement based on taints and tolerations.
Kubernetes Taint and Toleration Placement is a scheduling mechanism that works in the opposite direction from affinity: rather than a Pod expressing which nodes it wants, a node expresses which Pods it is willing to accept, by carrying a taint that repels every Pod except those explicitly declaring a matching toleration. This inversion — node-driven exclusion rather than Pod-driven inclusion — makes taints and tolerations the natural tool for reserving nodes for a specific purpose, since the default behavior is exclusion, and only Pods explicitly opting in via a toleration are considered at all.
A taint consists of a key, an optional value, and an effect (NoSchedule, PreferNoSchedule, or NoExecute), applied to a node; a toleration on a Pod spec matches a specific taint (or a broader class of taints) and permits that Pod to be scheduled onto (or, for NoExecute, to remain running on) a node carrying it.
Taint Effects
NoSchedule
The most commonly used effect: a Pod without a matching toleration is never scheduled onto a node with a NoSchedule taint, though Pods already running there before the taint was applied are not evicted.
kubectl taint nodes node-worker-05 dedicated=gpu:NoSchedule
PreferNoSchedule
A softer version of NoSchedule — the scheduler tries to avoid placing non-tolerating Pods on the tainted node, but will do so if no better alternative exists, functioning more like a scoring penalty than a hard filter.
NoExecute
The strongest effect: not only does it prevent new non-tolerating Pods from being scheduled, it also evicts any already-running non-tolerating Pods from the node, typically used for taints applied automatically in response to node conditions (node.kubernetes.io/not-ready, node.kubernetes.io/unreachable).
kubectl taint nodes node-worker-05 maintenance=true:NoExecute
Toleration Matching Rules
Exact Match
A toleration with operator: Equal matches a taint only if the key, value, and effect all match exactly.
tolerations:
- key: "dedicated"
value: "gpu"
operator: "Equal"
effect: "NoSchedule"
Existence-Based Match
A toleration with operator: Exists (and no value specified) matches any taint with the given key, regardless of its value — useful when tolerating a taint whose value might vary or is not known in advance.
tolerations:
- key: "dedicated"
operator: "Exists"
effect: "NoSchedule"
Universal Toleration
Omitting key entirely, combined with operator: Exists, matches every taint in the cluster regardless of key, value, or effect — an intentionally broad toleration reserved for workloads (like certain DaemonSets) that genuinely need to run everywhere, taints notwithstanding.
tolerations:
- operator: "Exists"
tolerationSeconds for NoExecute
A toleration for a NoExecute taint can include tolerationSeconds, specifying how long the Pod is allowed to remain on the node after the taint is applied before being evicted, rather than being evicted immediately — used to give a Pod a grace period to finish in-flight work before removal.
tolerations:
- key: "node.kubernetes.io/not-ready"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 300
Common Use Cases
Reserving Specialized Hardware
Tainting GPU or other specialized-hardware nodes ensures only Pods explicitly requesting and tolerating that hardware are scheduled there, preventing ordinary workloads from consuming scarce, expensive capacity meant for a specific purpose.
Control-Plane Node Isolation
Control-plane nodes are tainted by default (node-role.kubernetes.io/control-plane:NoSchedule) to keep ordinary application workloads off them, reserving their capacity for the control plane's own components — infrastructure daemons intentionally needing to run there add a matching toleration explicitly.
Automatic Node-Condition Taints
Kubernetes automatically applies NoExecute taints in response to node conditions (disk pressure, memory pressure, network unavailability), triggering automatic eviction of Pods that do not tolerate those specific conditions, forming the basis of Kubernetes' built-in node-problem eviction behavior.
Taints vs. Node Affinity
Taints and tolerations answer "which Pods is this node willing to accept," while node affinity answers "which nodes does this Pod want" — the two mechanisms are complementary rather than redundant, and a common pattern combines both: a nodeSelector or nodeAffinity rule opting a Pod into a specific node class, paired with a matching toleration allowing it past that class's taint, since affinity alone cannot override a taint's default exclusion.
Example
apiVersion: v1
kind: Pod
metadata:
name: codartium-taint-example
spec:
nodeSelector:
gpu: "true"
tolerations:
- key: "dedicated"
value: "gpu"
operator: "Equal"
effect: "NoSchedule"
containers:
- name: gpu-app
image: codartium/gpu-app:latest
kubectl taint nodes node-gpu-01 dedicated=gpu:NoSchedule
kubectl describe node node-gpu-01 | grep Taints