Skip to main content

Affinity

A Kubernetes scheduling rule that expresses attraction constraints — directing the scheduler to prefer or require that pods land on specific nodes or near specific other pods. Comes in two forms: Node Affinity (pod-to-node preferences) and Pod Affinity/Anti-Affinity (pod-to-pod co-location or separation rules).

Affinity — Telling the Scheduler Where Your Pods Belong

The Full Picture: Taints vs Affinity

These two mechanisms are often confused because they both influence scheduling. Here is the distinction:

Taints (on Nodes) Affinity (on Pods)
Node says: "Stay away unless you tolerate me" Pod says: "I want to be near X" or "I must be on Y"
Push-based repulsion Pull-based attraction

They work together. Taints keep unwanted pods off nodes. Affinity rules pull the right pods to the right nodes.

Node Affinity — Pod Wants a Specific Node Type

Use case: Zerodha's market-data processing pods need GPU nodes. Regular pods should not land there.

YAML
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # HARD rule — must match
nodeSelectorTerms:
- matchExpressions:
- key: node.kubernetes.io/instance-type
operator: In
values:
- p3.2xlarge # GPU instance type
- p3.8xlarge
preferredDuringSchedulingIgnoredDuringExecution: # SOFT rule — try to match
- weight: 80 # 0-100, higher = stronger preference
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- ap-south-1a # Prefer Mumbai AZ-A

The two scheduling modes:

Mode Behavior
requiredDuringSchedulingIgnoredDuringExecution Pod will NOT schedule if no matching node found (hard requirement)
preferredDuringSchedulingIgnoredDuringExecution Pod tries to schedule on matching node, but falls back if none available
Remember

The IgnoredDuringExecution part means if a node's labels change after a pod is already running, the pod is NOT evicted. The rule only applies at scheduling time.

Pod Anti-Affinity — Spread Pods Across Nodes/Zones

Use case: Swiggy's order-service runs 6 replicas. If all 6 land on one node and that node dies, the entire service goes down. Anti-affinity forces the scheduler to spread them out.

YAML
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: order-service # Don't place me near other order-service pods
topologyKey: kubernetes.io/hostname # "near" means "on the same node"

This guarantees no two order-service pods share a node. For zone-level HA, change topologyKey to topology.kubernetes.io/zone.

Pod Affinity — Keep Pods Together

Use case: A data-processing pod and its Redis sidecar should always land on the same node to minimize latency.

YAML
spec:
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: redis-cache
topologyKey: kubernetes.io/hostname # "with" means "on the same node"

Quick Decision Tree

◈ DIAGRAM
+------------------------------------------------------+
| Do you need to control where a pod lands? |
+------------------------------------------------------+
| |
v v
+---------------------+ +------------------------+
| Based on node | | Based on other pods? |
| hardware/labels? | +------------------------+
| -> Node Affinity | | |
+---------------------+ v v
| +------------+ +------------+
v | Stay AWAY | | Stay NEAR |
+-------+-------+ | from pods | | a pod |
| | | -> Anti- | | -> Pod |
v v | Affinity | | Affinity |
+--------+ +---------+ +------------+ +------------+
| Hard | | Soft | | Spread replicas across |
| must | | prefer | | nodes/zones for HA |
| land | | to land | +----------------------------+
| required preferred |
+--------+ +---------+
Common Mistake

Using required anti-affinity with more replicas than nodes. If you have 3 nodes and 4 replicas with required anti-affinity, the 4th pod will be stuck in Pending forever — there is no node without an existing pod to satisfy the constraint. Use preferred unless you are certain about your node count.

Frequently Asked Questions

What's the practical difference between affinity and a nodeSelector?

nodeSelector is a simple equality match on node labels — a pod either lands on a matching node or stays Pending. Affinity supports much richer logic: preferred (soft, best-effort) versus required (hard) rules, set-based operators like In/NotIn, and — uniquely — pod-to-pod rules, letting you co-locate pods that talk to each other frequently or spread replicas across failure domains for resilience.

What's a common gotcha with affinity rules?

Overusing requiredDuringSchedulingIgnoredDuringExecution constraints can leave pods stuck Pending when no node satisfies every rule simultaneously, especially during a rolling update when capacity is temporarily tight. Most teams default to preferred rules for anti-affinity (spread replicas across zones/nodes when possible) and reserve required rules for genuine hard constraints, like GPU-only workloads. Debugging a stuck pod starts with kubectl describe pod, whose Events section names the exact rule that blocked scheduling.