Skip to main content
In this lesson we’ll cover Kubernetes node affinity — a flexible way to control which nodes a Pod can be scheduled onto. Node affinity builds on the simple nodeSelector mechanism and adds more expressive operators, logical combinations, and scheduling preferences so you can describe placement rules that match your cluster topology and workload requirements.
A dark-themed diagram titled "PODs to Nodes" showing three server/device illustrations — a larger one on the left labeled "Large" and two smaller ones to the right. Each device has an icon and label beneath it: Node 1, Node 2, and Node 3.
Why node affinity? Suppose you have a large data-processing Pod that must run on a large node (node01). The simplest way to express this is with a nodeSelector, but nodeSelector only supports exact-match semantics and cannot express logical operators (OR/NOT), existence checks, or weighted preferences. Example: nodeSelector (exact-match only)
Node affinity offers equivalent placement rules, plus many additional capabilities. You can express match operators such as In, NotIn, Exists, DoesNotExist, Gt, and Lt. You can also mark rules as required or preferred. Equivalent required node affinity example:
What the fields mean:
  • affinity.nodeAffinity holds node placement rules.
  • requiredDuringSchedulingIgnoredDuringExecution encodes scheduling and execution behavior (see below).
  • nodeSelectorTerms is an array of terms; each term is a conjunction of matchExpressions. Multiple terms act like OR between terms.
  • Each matchExpression contains a key, an operator (for example In, NotIn, Exists), and optionally values.
Examples for common match patterns:
  • Match multiple acceptable sizes (OR via values):
  • Exclude a particular label value:
  • Require label presence regardless of value:
Operators at a glance For the complete operator semantics and examples, see the Kubernetes docs: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity Affinity behavior types The long property names encode behavior for two phases of a Pod’s lifecycle: during scheduling and during execution. Available (and planned) node-affinity types:
preferredDuringSchedulingIgnoredDuringExecution entries accept a weight (1–100) and a preference (a nodeSelectorTerm). The scheduler attempts to maximize the sum of weights when selecting a node.
requiredDuringSchedulingRequiredDuringExecution is a planned mode that would enforce affinity at runtime and could evict running Pods if node labels change. Do not rely on this behavior in production unless it is available and you understand eviction consequences.
Preferred affinity example (weights) A preference entry pairs a weight with a preference (a nodeSelectorTerm). The scheduler scores nodes and tries to maximize total weight.
Best practices and guidance
  • Use nodeSelector when you need a simple exact-match requirement (it’s compact and clear).
  • Use nodeAffinity when you need complex logic: multiple values, logical combinations, existence checks, numeric comparisons, or scheduling preferences.
  • Choose required... when the Pod absolutely must be placed on certain nodes; use preferred... for soft preferences so workloads remain schedulable even if preferred nodes are busy.
  • Remember that IgnoredDuringExecution means label changes after scheduling won’t evict the Pod.
Quick comparison Summary
  • Node affinity provides richer placement controls than nodeSelector.
  • Use In, NotIn, Exists, Gt, Lt, etc., to express complex rules.
  • Decide between required... and preferred... based on whether constraints are mandatory or best-effort.
  • Test affinity rules in a staging cluster to ensure correct scheduling and to understand any interactions with node label changes.
Links and references

Watch Video

Practice Lab