kubernetes/kubernetes
Scheduling framework
The framework is the contract between the scheduler core and its plugins. Everything in pkg/scheduler/framework/plugins/ implements one or more of these interfaces.
Extension points
Defined in pkg/scheduler/framework/interface.go:
| Interface | Called when | Return |
|---|---|---|
QueueSortPlugin |
Building the active queue | Less function for QueuedPodInfo |
PreEnqueuePlugin |
Before a pod enters the active queue | Allow / hold |
PreFilterPlugin |
Beginning of a scheduling cycle | Compute per-pod state stored in CycleState |
FilterPlugin |
For each candidate node | Fit / Unschedulable / UnschedulableAndUnresolvable |
PostFilterPlugin |
When no node fit | Optional preemption attempt |
PreScorePlugin |
After Filter, before Score |
Compute scoring inputs |
ScorePlugin |
For each fitting node | 0–100 score |
ScoreExtensions.NormalizeScore |
After Score |
Optional rescale |
ReservePlugin |
Best node chosen | Reserve / Unreserve hooks |
PermitPlugin |
After Reserve | Allow / Deny / Wait |
PreBindPlugin |
Before Bind | Mutate cluster state required for bind (e.g. PVC binding) |
BindPlugin |
The actual bind | Patch Pod.Spec.NodeName (default) |
PostBindPlugin |
After Bind | Notification only |
A plugin can implement any subset of these. PreFilter and PreScore exist so plugins can compute expensive per-pod state once and reuse it through CycleState.
CycleState
pkg/scheduler/framework/cycle_state.go is a thread-safe map keyed by string. Plugins use it to pass data between extension points within a single scheduling cycle. Each plugin stores its own typed value (e.g. interpodaffinityState, volumebinding.stateData).
CycleState.Clone() is called when the scheduler runs Filter against multiple nodes in parallel — each goroutine gets a snapshot.
NodeInfo and the snapshot
pkg/scheduler/framework/types.go defines NodeInfo, the scheduler's per-node summary (allocated resources, running pods, taints, image set, …). The cache in pkg/scheduler/backend/cache keeps a NodeInfo per node and refreshes incrementally on informer events.
Each scheduling cycle starts by snapshotting the cache (scheduler.Cache.UpdateSnapshot). Filter and Score run against the snapshot, so the inputs are stable for the duration of the cycle.
Parallelism
pkg/scheduler/framework/parallelize provides bounded-parallel iteration. Filter runs across nodes via Until(ctx, len(nodes), func(i int){...}). The default parallelism is 16, configurable via KubeSchedulerConfiguration.Parallelism.
Events that wake unschedulable pods
When a Filter plugin returns Unschedulable, the pod ends up in the unschedulable map. To know when to retry, each plugin declares its EventsToRegister — a list of (GVK, ActionType) pairs that affect its decision. The queue framework subscribes to those events and re-queues only the affected pods.
For example, the noderesources plugin registers on Node Add, Node Update, and Pod Delete. The volumebinding plugin registers on PV Add, PVC Add/Update, StorageClass Add, and so on.
This is what keeps a 5,000-node cluster from re-evaluating every pending pod for every irrelevant cluster change.
Profiles and weights
A profile (KubeSchedulerProfile in pkg/scheduler/apis/config) selects which plugins are enabled per extension point and assigns Score weights. The same binary can run multiple profiles concurrently; pods select via Pod.Spec.SchedulerName.
Adding a plugin: minimum viable example
Implement one of the interfaces:
type Plugin struct{ handle framework.Handle } func (p *Plugin) Name() string { return "MyPlugin" } func (p *Plugin) Filter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, info fwk.NodeInfo) *fwk.Status { // ... }Provide a constructor:
func New(_ context.Context, _ runtime.Object, h framework.Handle) (framework.Plugin, error) { return &Plugin{handle: h}, nil }Register in
pkg/scheduler/framework/plugins/registry.go(or use an out-of-tree scheduler binary that registers viaapp.WithPlugin).Enable in a profile:
profiles: - schedulerName: default-scheduler plugins: filter: enabled: - name: MyPluginTest with
pkg/scheduler/testing/helpers —MakeNode,MakePod,RegisterFilterPlugin, etc.
Key source files
| File | Purpose |
|---|---|
pkg/scheduler/framework/interface.go |
Plugin interfaces |
pkg/scheduler/framework/types.go |
NodeInfo, PodInfo, QueuedPodInfo |
pkg/scheduler/framework/cycle_state.go |
Per-cycle state map |
pkg/scheduler/framework/runtime/framework.go |
Plugin orchestrator |
pkg/scheduler/framework/parallelize/parallelism.go |
Bounded-parallel iterator |
pkg/scheduler/framework/preemption/preemption.go |
Preemption helper |
pkg/scheduler/backend/queue/scheduling_queue.go |
The four-band queue, event subscription |
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.