Kubernetes Scheduler Architecture
Kubernetes Scheduler Architecture explains how the scheduler assigns workloads to nodes, ensuring efficient resource utilization and optimal cluster performance.
Kubernetes Scheduler Architecture is the internal design of kube-scheduler as a pluggable, extension-point-driven pipeline: the specific stages a scheduling cycle passes through internally, and the framework through which custom logic can be inserted at defined points in that pipeline without replacing the scheduler wholesale. Where scheduling as a concept describes the filtering-and-scoring decision at a high level, scheduler architecture describes how that decision is actually implemented as a sequence of internal stages within the scheduling framework.
The Scheduling Framework
Extension Points as the Organizing Principle
The scheduler is internally organized around a fixed sequence of named extension points, PreFilter, Filter, PostFilter, PreScore, Score, Reserve, Permit, PreBind, Bind, and PostBind, each of which can host one or more plugins, with the scheduler's overall behavior emerging from the ordered execution of whichever plugins are registered at each point.
# Illustrative scheduler configuration enabling/disabling plugins per extension point
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
plugins:
filter:
enabled:
- name: NodeResourcesFit
- name: NodeAffinity
score:
enabled:
- name: NodeResourcesBalancedAllocation
weight: 1
The Two-Cycle Structure
Scheduling Cycle
The scheduling cycle formally runs sequentially, one Pod at a time, and is responsible for filtering the node set down to feasible candidates and scoring them to select a winner; because it mutates shared scheduler state, it is architecturally restricted to sequential execution to avoid race conditions between concurrently scheduled Pods.
Binding Cycle
The binding cycle formally runs the Reserve, Permit, PreBind, Bind, and PostBind stages, and is architecturally permitted to run concurrently across multiple Pods, since by this stage each Pod has already been assigned a specific node and no longer contends for the same shared scheduling state.
Extension Point Semantics
PreFilter and Filter
PreFilter plugins formally perform pre-processing and can abort the cycle early if a Pod is fundamentally unschedulable regardless of any specific node; Filter plugins then formally evaluate each candidate node individually, and a node failing any enabled Filter plugin is excluded from further consideration.
PostFilter
PostFilter plugins formally run only when no feasible node was found after filtering, most notably implementing preemption logic, evaluating whether evicting lower-priority Pods elsewhere could make room for the currently unscheduled one.
Score
Score plugins formally assign each surviving node a numeric value, combined across plugins using configured weights, with the highest-combined-score node selected as the scheduling decision's output, subject to a defined tie-breaking procedure among equally scored nodes.
Reserve and Permit
Reserve plugins formally record provisional resource reservations against the selected node before binding completes, allowing the scheduler to account for in-flight scheduling decisions when evaluating subsequent Pods; Permit plugins formally can delay, approve, or deny the binding of a specific Pod, used for coordination scenarios such as gang scheduling.
Bind
Bind plugins formally perform the actual API write that sets a Pod's spec.nodeName; if no Bind plugin claims responsibility for a given Pod, the scheduler falls back to a default binding implementation.
Multiple Scheduler Profiles
Named Profiles Within One Binary
A single scheduler configuration can define multiple named profiles, each with its own plugin set and enabled/disabled configuration, with Pods routed to a specific profile via spec.schedulerName, allowing several distinct scheduling behaviors to be served from one running scheduler process rather than requiring entirely separate scheduler deployments.
profiles:
- schedulerName: default-scheduler
- schedulerName: codartium-batch-scheduler
plugins:
score:
enabled:
- name: NodeResourcesMostAllocated
Out-of-Tree Extension
Scheduler Extenders
Prior to the plugin framework's introduction, and still supported for specific cases, scheduler extenders allow an external HTTP service to be consulted at defined points, filtering and prioritizing, via webhook calls, formally similar in spirit to admission webhooks but scoped specifically to scheduling decisions rather than general admission.
kubectl -n kube-system logs deployment/kube-scheduler
kubectl get events --field-selector reason=FailedScheduling -n codartium-team
Why the Scheduler Is Architected This Way
Structuring scheduling as a sequence of narrowly scoped extension points, rather than a single monolithic decision function, is what formally allows specialized placement logic, custom resource-aware scoring, gang scheduling coordination, preemption policy, to be added or replaced independently at exactly the stage it belongs to, without requiring modification to the stages that handle unrelated concerns.