Node rules look at node labels. Sometimes the question is about the neighbours: put the cache next to the web Pods that use it, keep two database replicas off the same machine. That is pod affinity and pod anti-affinity.
Anti-affinity: spread out
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: cache
topologyKey: kubernetes.io/hostnameRead it as: do not place this Pod on a node that already has a Pod labelled app=cache. Put that in the cache Deployment's own template and no two replicas share a node.
Affinity: move in together
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: cache
topologyKey: kubernetes.io/hostnamePlace this Pod only on a node that already runs an app=cache Pod. The web tier lands beside its cache, and traffic between them never leaves the machine.
topologyKey
The key names a node label. Two nodes with the same value for it count as the same place. kubernetes.io/hostname is unique per node, so "same place" means "same node". With topology.kubernetes.io/zone the rule works per zone: spread across zones, or stay within one.
Required and preferred
Both forms exist here too. preferred… carries a weight and a podAffinityTerm, and only tilts the score. A preferred anti-affinity spreads replicas when it can and doubles them up rather than leaving them Pending.
Reading it
0/3 nodes are available: 3 node(s) didn't match pod anti-affinity rules.
0/3 nodes are available: 3 node(s) didn't match pod affinity rules.The first means every node already has a matching Pod. The second means no node has one yet, a common surprise when the Pod you want to sit next to has not started.