Every scheduling decision runs through named extension points you can plug into.
Since 1.19 the scheduler is a framework. Built-in behaviour such as taints, affinity, preemption and volume binding are all plugins at these points.
1
QueueSortorder pending Pods
2
PreFilterprecompute, early reject
3
Filterremove infeasible nodes
!
PostFilteronly if none feasible: preemption
4
Scorerank feasible nodes
5
Reservehold resources on the winner
6
Permitapprove, deny or wait: gang scheduling
7
PreBinde.g. provision a volume
8
Bindwrite nodeName
9
PostBindinformational
PostFilter = preemption
When filtering finds nothing, the default plugin checks whether evicting lower-priority Pods would make room.
Permit = gang scheduling
A distributed training job needs all its Pods or none. Plugins in Volcano or Kueue hold Pods here until the whole group fits.
Why you care
Specialised needs (GPU, batch, topology) are added as plugins or extra schedulers, not by forking Kubernetes.