Scheduler Decision Cycle
A new Pod has no Node yet, so how does Kubernetes decide where it runs? The Scheduler pulls the Pod off its queue, filters out the Nodes that cannot fit it, scores the survivors to find the best home, and writes that choice back as a binding object. From there the Kubelet on the chosen Node picks the Pod up on its own watch and starts the containers. That one write is the whole of its placement decision, and the Scheduler itself never starts anything.
Play the animation 5 steps, animated, best on a wide screen
Scheduler Decision Cycle, step by step
-
A new Pod my-app-7d4-x2k9p reaches the Scheduler on its watch with spec.nodeName empty. Until that field is set, no Kubelet will start it. The Scheduler pops it off the active queue and runs one scheduling cycle.
Play from step 1 -
Filter plugins test each Node against the Pod requirements, and in a large cluster they stop once enough Nodes fit. Node-1 carries a NoSchedule taint without a matching toleration, Node-2 lacks the requested memory. Both are dropped before scoring.
Play from step 2 -
Surviving Nodes are ranked by score plugins like NodeResourcesFit, NodeAffinity and PodTopologySpread. Each returns 0 to 100 per Node and the weighted sum of all of them ranks the Nodes: Node-3 78, Node-4 92. See the Pod Priority and Preemption card.
Play from step 3 -
Highest score wins, ties broken at random. The Scheduler assumes the Pod on Node-4, counting its requests for the next Pod. It POSTs a Binding to the binding subresource, not a Pod patch, and the API writes it into ETCD, which acks the Raft commit.
Play from step 4 -
The Kubelet on Node-4 watches /api/v1/pods?fieldSelector=spec.nodeName=Node-4, so the write arrives there as an ADDED event. It pulls the image and starts the containers, and the Pod goes from Pending to Running.
Play from step 5