Node affinity and anti-affinity in Kubernetes - Time & Space Complexity
We want to understand how the time to schedule pods changes when using node affinity and anti-affinity rules in Kubernetes.
Specifically, how does the scheduler's work grow as the number of nodes and pods increases?
Analyze the time complexity of this node affinity and anti-affinity snippet.
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: kubernetes.io/hostname
This pod requires nodes labeled with "disktype=ssd" and avoids nodes with pods labeled "app=frontend" on the same host.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The scheduler checks each node's labels and running pods to match affinity and anti-affinity rules.
- How many times: It repeats this check for every node and for pods on those nodes.
As the number of nodes (n) and pods per node (m) grow, the scheduler must check more labels and pods.
| Input Size (n nodes, m pods/node) | Approx. Operations |
|---|---|
| 10 nodes, 5 pods/node | ~50 checks |
| 100 nodes, 10 pods/node | ~1000 checks |
| 1000 nodes, 20 pods/node | ~20,000 checks |
Pattern observation: The checks grow roughly with the number of nodes times the pods per node.
Time Complexity: O(n * m)
This means the scheduler's work grows proportionally with the number of nodes and pods it must evaluate.
[X] Wrong: "The scheduler only checks node labels once, so time stays the same no matter how many pods or nodes there are."
[OK] Correct: The scheduler must check each node and the pods on it to apply affinity and anti-affinity rules, so more nodes and pods mean more checks.
Understanding how scheduling time grows helps you explain how Kubernetes handles workloads efficiently and what might slow it down as clusters grow.
What if we changed requiredDuringSchedulingIgnoredDuringExecution to preferredDuringSchedulingIgnoredDuringExecution? How would the time complexity change?
Practice
nodeAffinity in Kubernetes primarily control?Solution
Step 1: Understand nodeAffinity purpose
Node affinity is used to specify rules about which nodes a pod can run on, based on labels assigned to nodes.Step 2: Compare options to nodeAffinity function
Options B, C, and D relate to pod startup order, network policies, and resource limits, which are unrelated to node affinity.Final Answer:
Which nodes a pod can be scheduled on based on node labels -> Option AQuick Check:
nodeAffinity controls pod placement on nodes [OK]
- Confusing node affinity with pod resource limits
- Thinking node affinity controls pod startup order
- Mixing node affinity with network policies
Solution
Step 1: Identify required node affinity syntax
Required node affinity uses the keyrequiredDuringSchedulingIgnoredDuringExecutionwithnodeSelectorTermsandmatchExpressionsto specify node labels.Step 2: Check options for correct structure
"nodeAffinity": {"requiredDuringSchedulingIgnoredDuringExecution": {"nodeSelectorTerms": [{"matchExpressions": [{"key": "disktype", "operator": "In", "values": ["ssd"]}]}]}} matches the required node affinity syntax. "nodeAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [{"weight": 1, "preference": {"matchExpressions": [{"key": "disktype", "operator": "In", "values": ["ssd"]}]}}]} is preferred affinity, C is nodeSelector (different syntax), and D is pod affinity, not node affinity.Final Answer:
"nodeAffinity": {"requiredDuringSchedulingIgnoredDuringExecution": {"nodeSelectorTerms": [{"matchExpressions": [{"key": "disktype", "operator": "In", "values": ["ssd"]}]}]}} -> Option DQuick Check:
Required node affinity uses requiredDuringSchedulingIgnoredDuringExecution [OK]
- Confusing preferred and required affinity syntax
- Using podAffinity instead of nodeAffinity
- Mixing nodeSelector with nodeAffinity syntax
zone: us-east-1a but no label disk: ssd?
{
"affinity": {
"nodeAffinity": {
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{
"matchExpressions": [
{"key": "zone", "operator": "In", "values": ["us-east-1a"]},
{"key": "disk", "operator": "In", "values": ["ssd"]}
]
}
]
}
}
}
}Solution
Step 1: Analyze required node affinity conditions
Required node affinity means all match expressions must be true for scheduling. The node must have bothzone: us-east-1aanddisk: ssdlabels.Step 2: Check node labels against requirements
The node haszone: us-east-1abut lacksdisk: ssd. This fails the required condition, so the pod cannot be scheduled there.Final Answer:
The pod will not be scheduled on the node because it lacks the required disk label -> Option BQuick Check:
Required affinity needs all labels matched [OK]
- Assuming partial label match is enough
- Confusing required with preferred affinity
- Thinking pod schedules with warnings on missing labels
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: myapp
topologyKey: "kubernetes.io/hostname"
Solution
Step 1: Understand pod anti-affinity types
Preferred anti-affinity suggests avoiding co-location but does not enforce it strictly. Required anti-affinity enforces pods not to be scheduled together.Step 2: Analyze the pod spec anti-affinity type
The spec usespreferredDuringSchedulingIgnoredDuringExecution, which is a soft rule. This allows pods to be scheduled on the same node if needed.Final Answer:
Using preferred instead of required anti-affinity allows scheduling on same node -> Option CQuick Check:
Preferred anti-affinity is a soft rule [OK]
- Confusing preferred and required anti-affinity
- Assuming labelSelector syntax is wrong without checking
- Thinking topologyKey must be zone for anti-affinity
app=frontend never run on the same node as pods with label app=backend. Which affinity configuration achieves this?Solution
Step 1: Identify requirement to prevent co-location of pods
Pod anti-affinity prevents pods from running on the same node as other pods matching certain labels.Step 2: Choose required anti-affinity for strict enforcement
UsingrequiredDuringSchedulingIgnoredDuringExecutionenforces pods never co-locate on the same node.Step 3: Match labelSelector to pods to avoid
The labelSelector should match pods withapp=backendto prevent frontend pods from scheduling on same node.Final Answer:
Use podAntiAffinity with requiredDuringSchedulingIgnoredDuringExecution and labelSelector matchingapp=backend-> Option AQuick Check:
Pod anti-affinity + required = strict pod separation [OK]
- Using nodeAffinity instead of podAntiAffinity for pod separation
- Using preferred instead of required anti-affinity for strict rules
- Confusing podAffinity with podAntiAffinity
Ready to prove it?
Pass the test and this pattern moves unknown
