Skip to main content
Course/Security & Scale/Taints, Tolerations & Node Affinity
4/875 min
Security & Scale

Taints, Tolerations & Node Affinity

Control where Pods land with node labels, taints, tolerations, and affinity rules.

advanced75 minRead β†’ Lab β†’ Quiz β†’ Practice
🧠 Brain Warm-Up
🧠 Brain Warm-Up: If a node gets tainted with NoExecute due to a sudden hardware fault, what determines how quickly running Pods are evicted? Can a Pod delay its own eviction using tolerations? Think about how the scheduler or node controller implements this time window.

The Kubernetes Scheduling Pipeline

The kube-scheduler runs as a control plane loop, matching newly created, unscheduled Pods (spec.nodeName is blank) to the most appropriate node in the cluster. It achieves this in three consecutive phases:

  1. Filtering (Predicates): Filters out nodes that do not satisfy the Pod's hardware requirements or constraints.
  2. Scoring (Priorities): Ranks the remaining nodes by scoring them (from 0 to 100) using priority functions (e.g., node affinity weight, image locality, balanced resource usage).
  3. Binding: The scheduler selects the highest-scoring node and writes a binding object to the API server, which sets the Pod's spec.nodeName. The node's local kubelet then detects this assignment and spins up the container via the CRI gRPC API.

The Scheduling Pipeline

Incoming Pod Spec (Constraints)

β”‚

β–Ό

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”

β”‚ SCHEDULER FILTERING PHASE β”‚

β”‚ - Node Taints vs Pod Tolerations β”‚

β”‚ - NodeSelectors & Node Affinity (requiredDuring...) β”‚

β”‚ - Resource limits/requests vs Node Allocatable capacity β”‚

β”‚ - Pod Topology Spread & Co-location constraints β”‚

β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”‚

Filtered Nodes (Survivors)

β”‚

β–Ό

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”

β”‚ SCHEDULER SCORING PHASE β”‚

β”‚ - Node Affinity Weighting (preferredDuring...) β”‚

β”‚ - Image Locality (prefer nodes with image already cached) β”‚

β”‚ - Inter-pod Affinity / Anti-affinity scoring β”‚

β”‚ - Balanced Resource Allocation (CPU/Memory spread) β”‚

β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”‚

Highest-Scored Node Chosen

β”‚

β–Ό

Bind Request

(Writes spec.nodeName via API)

Node Taints and Pod Tolerations

Taints are applied to nodes to allow them to repel a set of Pods. Tolerations are applied to Pods to allow (but not force) them to schedule on nodes with matching taints.

Format: kubectl taint nodes key=value:effect

EffectBehaviour
NoSchedule(Hard) The scheduler will not place new Pods without a matching toleration on this node. Existing running Pods remain unaffected.
PreferNoSchedule(Soft) The scheduler tries to avoid placing Pods without a matching toleration on this node, but will do so if no other capacity exists.
NoExecute(Evictive) Pods without a matching toleration are immediately evicted if already running on the node, and new Pods are blocked.

Eviction Delay via tolerationSeconds

If a Pod tolerates a NoExecute taint (e.g., taints applied by the Node Lifecycle Controller like node.kubernetes.io/unreachable during network partitions), it can specify a tolerationSeconds limit:

tolerations:
- key: "node.kubernetes.io/unreachable"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 300

This tells Kubernetes: "If this node becomes unreachable, let my Pod stay running on it for 5 minutes before evicting it."

Expressive Node Selection

nodeSelector

The simplest constraint. Requires an exact match of key-value labels on the node:

spec:
  nodeSelector:
    disktype: ssd

Node Affinity

The advanced successor to nodeSelector. Supports logical operators (In, NotIn, Exists, DoesNotExist, Gt, Lt) and contains two categories:

  • Hard: requiredDuringSchedulingIgnoredDuringExecution (Must match)
  • Soft: preferredDuringSchedulingIgnoredDuringExecution (Weighted priority from 1 to 100, scheduler scores these nodes higher)

The *IgnoredDuringExecution* suffix means that if node labels change after scheduling, the Pod remains running (does not get evicted).

Inter-Pod Affinity & Anti-Affinity

These rules constraint scheduling based on labels of Pods already running on nodes in specific topology domains.

  • Topology Domains: Defined by topologyKey (e.g., kubernetes.io/hostname for nodes, or topology.kubernetes.io/zone for cloud availability zones).
  • Anti-Affinity: Crucial for high-availability. Prevents co-locating replicas on the same hardware or zone.
⚠️ WARNING
Inter-pod affinity and anti-affinity require significant CPU overhead in large clusters because the scheduler must evaluate label selectors across all nodes. Use them carefully to avoid scheduling bottlenecks.