Node affinity is a rule in a Pod manifest that constrains which nodes can run the Pod. It can select nodes by labels, much like `nodeSelector`, but supports more expressive conditions—including excluding nodes with a particular label. section 7.3.2
Listing 7.5 Using a set-based label selector
apiVersion: v1
kind: Pod
metadata:
name: kiada-front-end-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions: #1
- key: node-role #2
operator: In #2
values: #2
- front-end #2
- key: skip-me #3
operator: DoesNotExist #3
...
This Pod requires a node labeled `node-role: front-end` that does not have a `skip-me` label. The rule sits under `spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution`. section 7.3.2
Read the selector from the outside in:
- A node must match at least one `nodeSelectorTerms` entry. Within a term, it must match every `matchExpressions` entry. section 7.3.2
- Each expression has a label key and an operator. `In` and `NotIn` compare values; `Exists` and `DoesNotExist` test for a key. `Lt` and `Gt` compare against a single value. section 7.3.2
When no node qualifies
Label the front-end nodes with `skip-me=true`, then check the Pods with `kubectl get pods`. The Pod requiring the label to be absent remains `Pending`, while the simpler `nodeSelector` Pod is shown running. section 7.3.2
Listing 7.6 Using a field selector in nodeAffinity
apiVersion: v1
kind: Pod
metadata:
name: kiada-front-end-skip-specific-node
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields: #1
- key: metadata.name #2
operator: NotIn #2
values: #2
- node-a #2
...
Affinity can also select by node fields: use `matchFields` instead of `matchExpressions`. Here, `metadata.name` with `NotIn` prevents placement on `node-a`. section 7.4.2
Affinity can also be added by a controller. A DaemonSet controller adds a different node-affinity rule to each Pod it creates, targeting a specific node. It leaves `nodeName` empty so the Kubernetes Scheduler schedules the Pod while considering its resource requirements and other properties. section 17.1.2





