Kubernetes scheduling explainer
Paste your nodes and a pod or Deployment and see which nodes it can run on and why — every scheduler filter per node, the scores and weights that pick the winner, the FailedScheduling message, preemption victims, and N replicas placed one after another — checked against the real kube-scheduler v1.36.
Added
Works with
- Helm and Kustomize renderer Containers and Kubernetesreceives a rendered Deployment, StatefulSet or Pod from a chart or overlay
How to use it
Why is my pod Pending? Why did all three replicas land in one zone? Paste the cluster and the workload and this page runs the same filters and scores as kube-scheduler’s default profile, node by node, and shows its reasoning.
How to use it
-
The cluster. Paste
kubectl get nodes,pods,pdb,priorityclass -A -o yaml(or-o json) — any mix of Node, Pod, PodDisruptionBudget, PriorityClass, RuntimeClass and Namespace objects. Pods count when they are bound to a listed node and not Succeeded or Failed. No cluster at hand? The Node builder makes groups of nodes over zones with labels and taints, or load an example. -
The pod. Paste a Pod, Deployment, StatefulSet, ReplicaSet, Job or CronJob. Replicas default to the workload’s; change them to see where the next ones would go. Like the API server, the page adds the default
not-ready/unreachableNoExecute tolerations (300 s) unless you untick it. -
Read the result.
-
Filters — for every node, each filter in the scheduler’s order: NodeUnschedulable (cordoned), NodeName, TaintToleration (NoSchedule and NoExecute;
tolerationSecondsnoted), NodeAffinity (nodeSelectorand required terms with In/NotIn/Exists/DoesNotExist/Gt/Lt andmatchFields), NodePorts, NodeResourcesFit (requests — including sidecar and init containers, pod-level resources and RuntimeClass overhead — against allocatable minus what bound pods request, and the pod count), PodTopologySpread (skew per domain,minDomains,nodeAffinityPolicy,nodeTaintsPolicy,matchLabelKeys) and InterPodAffinity (required affinity and anti-affinity, and other pods' anti-affinity against this one). The outlined cell is the first failure — the one the scheduler reports. -
Scores — for nodes that pass: TaintToleration ×3 (PreferNoSchedule taints), NodeAffinity ×2 (preferred terms), PodTopologySpread ×2 (ScheduleAnyway constraints, or the built-in spreading over hostname and zone when the pod has none and a Service or controller selects it), InterPodAffinity ×2 (preferred terms both ways, and others' required affinity), NodeResourcesFit ×1 (least allocated, counting 100m/200Mi for containers without requests), NodeResourcesBalancedAllocation ×1 (since v1.36: how much the pod improves the node’s CPU/memory balance) and ImageLocality ×1 (
status.imageson the node). -
When nothing fits: the FailedScheduling message exactly as
kubectl describe podshows it, and preemption — which nodes could make room by evicting lower-priority pods, which pods would go (most important spared first, PodDisruptionBudgets respected where possible), and why that node was chosen (fewest PDB violations, lowest victim priority, smallest priority sum, fewest victims, latest start time).preemptionPolicy: Neveris honoured. -
Replicas — each replica placed in turn, seeing the ones before it, so you can watch spreading, anti-affinity and resource exhaustion play out. Click a row for its tables.
-
The examples cover a mixed cluster with control-plane, cordoned, spot and GPU nodes; preemption
with a PDB; required pod affinity with anti-affinity; a pod that fits nowhere for five different
reasons; minDomains; scoring by resources, balance and images; soft rules; host ports with
sidecars; and a priority that never preempts.
Not modelled: volumes (VolumeBinding, VolumeZone, attach limits), Dynamic Resource Allocation claims, scheduler extenders and custom profiles, and the random tie-break (ties are shown). Pods created by a DaemonSet are pinned to their node; here a DaemonSet’s replicas are tried on the whole cluster.
Related: build manifests with the manifest builder, render a chart or
overlay in the Helm and Kustomize renderer and send its Deployment here
with Check scheduling, watch the control loop in the Kubernetes simulator,
and find the kubectl commands for taints, cordons and describe in the
kubectl helper.
How it was checked
The model follows the plugin source of kube-scheduler v1.36.1 (the plugins under pkg/scheduler/framework/plugins,
the default plugin set and weights in default_plugins.go, and FitError for the message). Every example was then replayed on a throwaway cluster running the real
kube-scheduler v1.36.1 (under kwok, with simulated nodes): the placements of all replicas, the
FailedScheduling messages character for character, the preempted pod and all 275 per-plugin scores
the scheduler logged agree with this page. The tests keep that record.
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser; nothing you type leaves this page.