kubernetes/kubernetes
kube-scheduler
The kube-scheduler is the component that decides which node each new pod runs on. Architecturally it is a single binary with a pluggable framework: every constraint, preference, and post-bind hook is a plugin registered through the pkg/scheduler/framework API.
Directory layout
cmd/kube-scheduler/
├── scheduler.go # main(), 5 lines
└── app/
├── server.go # NewSchedulerCommand, Run
└── options/ # KubeSchedulerOptions, profile config
pkg/scheduler/
├── scheduler.go # The Scheduler struct, Run loop
├── schedule_one.go # Per-pod scheduling cycle
├── schedule_one_podgroup.go # Gang/podgroup scheduling
├── eventhandlers.go # Informer event → queue routing
├── extender.go # Legacy HTTP-based extender support
├── apis/config/ # KubeSchedulerConfiguration types
├── backend/
│ ├── api_cache/ # Read-side cache used by plugins
│ ├── api_dispatcher/ # Async write batching (gated by SchedulerAsyncAPICalls)
│ ├── cache/ # Internal node-and-pod cache; see also debugger/
│ └── queue/ # The scheduling queue: active / backoff / unschedulable / gated
├── framework/
│ ├── interface.go # Plugin extension-point interfaces
│ ├── types.go # NodeInfo, PodInfo, CycleState, QueuedPodInfo
│ ├── runtime/ # Plugin orchestrator + instrumentation
│ ├── plugins/ # Built-in plugins (see below)
│ ├── preemption/ # Preemption helper used by the default-preemption plugin
│ ├── parallelize/ # Bounded-parallelism helper for filter/score
│ ├── api_calls/ # Bind/Patch/Update wrappers that respect the dispatcher
│ └── autoscaler_contract/ # Hooks consumed by Cluster Autoscaler
├── metrics/ # Prometheus metrics
└── profile/ # Multi-profile config evaluationHow a pod gets scheduled
graph TD
Q[SchedulingQueue] -->|NextPod| Cycle[Scheduling cycle]
Cycle --> PreFilter
PreFilter --> Filter
Filter -->|fits| Score
Filter -->|none fit| Preempt[PostFilter / preemption]
Score --> NormalizeScore
NormalizeScore --> Reserve
Reserve --> Permit
Permit --> PreBind
PreBind --> Bind
Bind --> PostBind
Preempt -.requeue.-> QThe cycle is in pkg/scheduler/schedule_one.go. It:
- Pulls a pod off the active queue.
- Snapshots the cluster state (a copy of
pkg/scheduler/backend/cache.Cache). - Runs
PreFilterplugins — they can compute per-pod state stored in the framework'sCycleState. - Runs
Filterplugins against every node in parallel. Nodes returningUnschedulableare eliminated. - If at least one node fits, run
PreScorethenScoreplugins. Each plugin returns a 0–100 score per node. NormalizeScorelets a plugin re-scale its scores. The scheduler then computes a weighted sum across plugins.- The highest-scored node wins ties via random selection.
Reserveplugins are called to mark the assumed pod-on-node binding (e.g., volume binding holds claim reservations).Permitplugins can delay (e.g., gang scheduling) or reject. If they delay, the pod is requeued.PreBindruns (including the volume-binding plugin's actual PVC bind). On error,Reserveis rolled back.Bindplugins (default: writePod.Spec.NodeNamevia Patch). External binders are also allowed.PostBindfor any cleanup or notification.
If Filter returns no candidates, PostFilter plugins run — most importantly defaultpreemption (pkg/scheduler/framework/plugins/defaultpreemption), which can evict lower-priority pods from a candidate node to make room.
The scheduling queue
pkg/scheduler/backend/queue implements a four-band priority queue:
- Active queue — pods ready to be scheduled, ordered by priority.
- Backoff queue — pods that failed scheduling recently. Re-enter the active queue after exponential backoff.
- Unschedulable pods map — pods that no node fits. Re-evaluated when a relevant cluster event occurs (a node becomes Ready, a Resource is freed, a PodAntiAffinity peer is deleted, …).
- Gated pods — pods whose
SchedulingGateshave not been removed.
Cluster events are mapped to "which pods should we reconsider" via the EventToRegister set each plugin declares. This avoids waking every unschedulable pod for every irrelevant change.
Built-in plugins
Located in pkg/scheduler/framework/plugins/:
| Plugin | Extension points | Purpose |
|---|---|---|
nodename |
Filter | Honour Pod.Spec.NodeName |
nodeunschedulable |
Filter | Skip nodes with Spec.Unschedulable |
nodeaffinity |
Filter, Score | NodeSelector + NodeAffinity |
noderesources (fit, balanced, leastallocated, mostallocated, requestedtocapacityratio) |
Filter, Score, PreScore | CPU/memory/ephemeral-storage fit and balancing |
nodevolumelimits |
Filter | Per-CSI-driver attach limits |
nodeports |
Filter | hostPort conflicts |
tainttoleration |
Filter, PreScore, Score | NoSchedule / PreferNoSchedule |
podtopologyspread |
PreFilter, Filter, PreScore, Score | Spread by topologyKey |
interpodaffinity |
PreFilter, Filter, PreScore, Score | Pod affinity / antiaffinity |
volumebinding |
PreFilter, Filter, Reserve, PreBind | PVC binding decisions |
volumerestrictions / volumezone |
Filter | Volume-specific constraints |
imagelocality |
Score | Prefer nodes that already have the image |
defaultbinder |
Bind | The Patch-based default binder |
defaultpreemption |
PostFilter | Standard preemption |
dynamicresources |
PreFilter, Filter, Reserve, PreBind, PostBind | Dynamic Resource Allocation |
gangscheduling / podgrouppodscount |
Permit, Reserve, Filter | Gang/PodGroup support |
nodedeclaredfeatures |
Filter | Match Pod.Spec.NodeRequirements against Node.Status.Features |
topologyaware |
Filter, Score | Topology-aware scheduling for heterogeneous clusters |
queuesort |
QueueSort | Default ordering for the active queue |
schedulinggates |
PreEnqueue | Implement Pod.Spec.SchedulingGates |
The full registry is in pkg/scheduler/framework/plugins/registry.go.
Profiles
A KubeSchedulerConfiguration lets cluster operators define multiple profiles. A profile is a named (plugin-set, plugin-config) tuple; pods opt into a profile via Pod.Spec.SchedulerName. The default profile is named default-scheduler. Multi-profile clusters can run several scheduling policies in one binary.
Async API calls
The SchedulerAsyncAPICalls feature gate (and the pkg/scheduler/backend/api_dispatcher) decouples scheduling decisions from API-server write latency. With the gate on, the scheduler's bind/patch/update calls are queued through an APIDispatcher that batches and serializes them. The internal cache reflects the post-write state immediately so the next scheduling cycle can proceed.
Sub-page
- Scheduling framework deep dive — the interfaces every plugin implements, how
CycleStateflows, how parallelism works.
Key source files
| File | Purpose |
|---|---|
pkg/scheduler/scheduler.go |
The Scheduler struct, Run loop |
pkg/scheduler/schedule_one.go |
Per-pod scheduling cycle |
pkg/scheduler/eventhandlers.go |
Informer events → queue updates |
pkg/scheduler/framework/interface.go |
Plugin extension-point interfaces |
pkg/scheduler/framework/runtime/framework.go |
Plugin runner |
pkg/scheduler/framework/plugins/registry.go |
Plugin registry |
pkg/scheduler/backend/queue/scheduling_queue.go |
The four-band queue |
pkg/scheduler/backend/cache/cache.go |
Internal node + pod cache |
cmd/kube-scheduler/app/server.go |
Boot, Cobra command |
Integration points
- kube-apiserver — the only thing the scheduler talks to. It uses informers for read and Patch for write.
- Cluster Autoscaler — reads
pkg/scheduler/framework/autoscaler_contractto predict whether a pending pod would fit if a new node existed. - Volume controller —
volumebindingplugin coordinates with the PV controller in kube-controller-manager. - DRA driver kubelet plugins — the
dynamicresourcesplugin readsResourceSliceand writesResourceClaimallocations consumed by kubelet.
Entry points for modification
- Adding a new plugin: implement one or more extension-point interfaces from
pkg/scheduler/framework/interface.go, register it inpkg/scheduler/framework/plugins/registry.go, optionally add a config schema underpkg/scheduler/apis/config/. - Tuning a profile: edit
KubeSchedulerConfigurationYAML or change the default inpkg/scheduler/apis/config/v1. - Replacing the binder: implement a
BindPluginthat talks to your custom binder service; disabledefaultbinderin the profile.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.