Kubernetes Scheduling Guideline Set
Kubernetes Scheduling Guideline Set outlines best practices for efficient, reliable, and scalable container orchestration in Kubernetes clusters.
Kubernetes Scheduling Guideline Set describes the practices for influencing where Pods are placed within a cluster — how workloads are steered toward or away from specific nodes, kept together with or apart from other workloads, and prioritized when resources are scarce. Scheduling in Kubernetes is handled by the scheduler component, which evaluates a Pod against filtering and scoring rules to select a node, but that decision can be shaped extensively through the constructs described here.
Node Selection Mechanisms
nodeSelector
nodeSelector is the simplest placement constraint: a flat key-value match against node labels. A Pod with a nodeSelector will only be scheduled onto nodes carrying all the specified labels. It is coarse and does not support expressions, but is sufficient for simple cases such as pinning workloads to a specific hardware class.
Node Affinity
Node affinity extends nodeSelector with expressive matching (In, NotIn, Exists, Gt, Lt) and two enforcement strengths:
requiredDuringSchedulingIgnoredDuringExecutionbehaves as a hard constraint — the Pod will not be scheduled unless it is satisfied.preferredDuringSchedulingIgnoredDuringExecutionbehaves as a soft constraint — the scheduler favors matching nodes but will still place the Pod elsewhere if no match is available.
The "IgnoredDuringExecution" suffix means that if node labels change after the Pod is already running, the Pod is not evicted retroactively.
Node Taints and Tolerations
Taints are applied to nodes to repel Pods by default; tolerations are applied to Pods to permit them to be scheduled on tainted nodes despite the taint. This is the inverse mechanism from affinity: affinity pulls Pods toward nodes, taints push Pods away unless explicitly tolerated. Taints commonly mark nodes as reserved for specific workloads, or mark nodes as degraded/cordoned for maintenance.
Inter-Pod Placement Rules
Pod Affinity
Pod affinity allows a Pod to request placement on nodes that are already running Pods matching a given label selector, typically scoped by a topologyKey such as kubernetes.io/hostname or a zone label. This is used to colocate tightly coupled workloads, for example placing a cache alongside the service that depends on it to minimize network latency.
Pod Anti-Affinity
Pod anti-affinity does the opposite — it steers Pods away from nodes already running Pods matching a selector. This is commonly applied to replicas of the same Deployment, ensuring that multiple replicas spread across different nodes or zones rather than landing on the same node, which would create a single point of failure.
Topology Spread Constraints
topologySpreadConstraints provide a more direct mechanism for even distribution across a defined topology domain (node, zone, region), using maxSkew to bound how unevenly Pods matching a selector may be distributed. This is generally preferred over anti-affinity for pure spreading goals because it expresses the intent directly rather than as a side effect of repulsion rules.
Resource-Driven Scheduling
Requests as the Scheduling Signal
The scheduler filters out any node that cannot satisfy a Pod's resource requests. Pods without requests are treated as needing negligible resources, which can lead to overcommitment and later eviction under pressure — this is why resource declaration guidelines and scheduling guidelines are tightly linked.
Priority and Preemption
PriorityClass objects assign a numeric priority to Pods. When the cluster lacks capacity for a higher-priority pending Pod, the scheduler can preempt (evict) lower-priority Pods on a node to make room, provided the preemption would actually allow the higher-priority Pod to fit. Priority is also used to determine eviction order under node resource pressure, independent of QoS class.
Workload-Specific Scheduling Controls
Pod Disruption Budgets
A PodDisruptionBudget (PDB) does not influence initial placement, but constrains voluntary disruptions (node drains, cluster upgrades) by declaring the minimum number or percentage of replicas that must remain available. Schedulers and cluster operations tooling respect PDBs when deciding how many Pods of a workload can be evicted simultaneously.
DaemonSets and Scheduling Bypass
DaemonSet Pods are scheduled by a dedicated controller logic that ensures one Pod per matching node, bypassing normal replica-count scheduling. Taints and node affinity still apply to determine which nodes qualify.
Example Configuration
apiVersion: apps/v1
kind: Deployment
metadata:
name: codartium-api
spec:
replicas: 3
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: codartium-api
topologyKey: "kubernetes.io/hostname"
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-pool
operator: In
values: ["general-purpose"]
tolerations:
- key: "dedicated"
operator: "Equal"
value: "codartium"
effect: "NoSchedule"
containers:
- name: codartium-api
image: registry.example.com/codartium-api@sha256:def456...
resources:
requests:
cpu: "500m"
memory: "512Mi"
Practical Consequences
A well-designed scheduling configuration produces a cluster where critical workloads land on appropriate hardware, replicas are spread for resilience against node or zone failure, and capacity contention resolves in favor of the workloads that matter most. Neglecting these guidelines commonly results in all replicas of a service landing on the same node — turning a single node failure into a full outage — or critical workloads being starved of resources by lower-priority batch jobs during periods of contention.