In OpenShift (OCP) and Kubernetes, Node Selectors and Node Affinity are mechanisms used to attract pods to specific nodes based on key-value labels assigned to those nodes.
While Taints are used to repel pods, Node Selectors and Node Affinity actively tell the OpenShift scheduler where your applications should be placed.
1. Node Selectors (Simple & Direct)
A Node Selector is the simplest way to constrain pods to nodes with specific labels. You label a node, and then add a matching nodeSelector key-value pair to your Pod or Deployment specification.
- Best For: Simple, binary placement requirements (e.g., “put this pod on SSD storage”).
- Limitation: It only supports hard
ANDlogic and exact string matches (key=value). It cannot do “OR” conditions, regex, or soft preferences.
CLI Example – Labeling a node:
Bash
oc label node worker-1 storage=fast-ssd
YAML Example – Assigning a Pod via nodeSelector:
YAML
apiVersion: apps/v1kind: Deploymentmetadata: name: database-appspec: template: spec: nodeSelector: storage: fast-ssd # Pod will ONLY land on nodes with this exact label containers: - name: postgres image: quay.io/postgresql/postgresql-13:latest
2. Node Affinity (Advanced & Flexible)
Node Affinity expands on Node Selectors by introducing expressive rules, logical operators (e.g., In, NotIn, Exists, DoesNotExist, Gt, Lt), and soft preferences.
Node Affinity offers two distinct rules:
requiredDuringSchedulingIgnoredDuringExecution(Hard Rule): The scheduler must find a node matching the rule to place the pod. If no matching node exists, the pod remains in aPendingstate.preferredDuringSchedulingIgnoredDuringExecution(Soft Rule): The scheduler tries to find a node matching the criteria. If no matching node is available, it places the pod on an alternative node anyway.
What does “IgnoredDuringExecution” mean?
If a node’s labels change after a pod is already running on it, OpenShift will not evict or move the pod. It only evaluates the rule during the initial scheduling phase.
YAML Example – Advanced Node Affinity Placement:
YAML
apiVersion: apps/v1kind: Deploymentmetadata: name: analytics-processorspec: template: spec: affinity: nodeAffinity: # HARD RULE: Must be in us-east-1a OR us-east-1b requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: topology.kubernetes.io/zone operator: In values: - us-east-1a - us-east-1b # SOFT RULE: Prefers high-memory nodes, but falls back if unavailable preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 # Priority score (1-100) preference: matchExpressions: - key: node-role.kubernetes.io/high-mem operator: Exists containers: - name: spark-worker image: quay.io/analytics/spark:latest
3. Node Selectors vs. Node Affinity vs. Taints
| Feature | Node Selector | Node Affinity | Taints & Tolerations |
| Direction | Attracts pods to nodes. | Attracts pods to nodes. | Repels pods from nodes. |
| Complexity | Simple exact match (key=value). | Complex expressions (In, Exists, weights). | Key-Value-Effect match (key=value:Effect). |
| Flexibility | Hard requirement only. | Supports both Hard and Soft (preferred) rules. | Supports Hard (NoSchedule, NoExecute) and Soft (PreferNoSchedule). |
| Primary Use Case | Quick, simple node pinning. | Multi-zone awareness, environment routing, hardware affinity. | Isolating control plane nodes, reserving GPUs, maintaining nodes. |
Pro Tip: For complex enterprise deployments, combine Node Affinity (to group your pods into specific infrastructure zones) with Taints & Tolerations (to prevent unapproved workloads from creeping into those zones).