Attracting Pods to Specific Nodes
While Taints repel Pods from nodes, Affinity attracts Pods toward nodes with specific characteristics. Affinity is defined on the Pod, not the node. You're expressing the Pod's preferences or requirements about where it wants to live.
Node Affinity works by matching against Node Labels. Kubernetes ships with a set of well-known labels that cloud providers populate automatically:
| Label | Example Value |
|---|---|
topology.kubernetes.io/zone |
us-east-1a |
topology.kubernetes.io/region |
us-east-1 |
kubernetes.io/arch |
amd64 or arm64 |
node.kubernetes.io/instance-type |
m5.xlarge |
You can also add your own labels: kubectl label nodes node-01 disk=ssd.
Hard vs. Soft Affinity
Node Affinity comes in two flavors that control what happens when no matching node exists:
Hard Affinity — requiredDuringSchedulingIgnoredDuringExecution:
The Pod will only schedule on a node that satisfies the rule — for example, a region label that must be one of a specific set of allowed regions. If no matching node exists, the Pod stays Pending indefinitely. Use this for non-negotiable requirements like data residency compliance.
Soft Affinity — preferredDuringSchedulingIgnoredDuringExecution:
The scheduler tries to honor the preference but will schedule the Pod on any available node if no match exists. Each preference has a weight (1–100) that the scheduler uses to score nodes — a higher-weighted preference for a specific instance type, say, combined with a lower-weighted preference for SSD-backed storage. Here, the scheduler scores nodes: an m5.xlarge with SSD gets 100 points, an m5.xlarge without SSD gets 80, a non-matching node with SSD gets 20, and a generic node gets 0. The highest-scoring available node wins.
The IgnoredDuringExecution Caveat
Both affinity types contain IgnoredDuringExecution in their names. This means: once a Pod is running, changes to node labels do not evict it. If you relabel a node so it no longer matches a running Pod's affinity, the Pod keeps running there. A future RequiredDuringExecution variant (in alpha as of Kubernetes 1.27) will eventually enforce affinity continuously, but it is not yet production-ready.
Affinity Operators
The operator field in matchExpressions supports:
| Operator | Meaning |
|---|---|
In |
Label value is in the list |
NotIn |
Label value is not in the list |
Exists |
Label key exists (any value) |
DoesNotExist |
Label key does not exist |
Gt / Lt |
Numeric comparison (for integer label values) |