Kubernetes Scheduler Scoring Behavior
Kubernetes Scheduler Scoring Behavior determines node selection by evaluating resource availability, constraints, and affinity rules to schedule pods efficiently.
Kubernetes Scheduler Scoring Behavior is the detailed mechanics of how the scheduler ranks feasible nodes — those that survived the filtering phase — against each other to select the single best placement for a Pod, using a configurable set of weighted scoring plugins that each contribute an independent signal to a combined, per-node total. Where filtering answers a binary question per node, scoring answers a comparative one across every feasible node simultaneously, and understanding how individual plugin scores combine into a final ranking explains placement outcomes that would otherwise seem arbitrary among several equally "valid" nodes.
Every scoring plugin returns a normalized score (typically 0-100) for each feasible node, which is then multiplied by that plugin's configured weight and summed across all active plugins to produce the node's final aggregate score.
Built-In Scoring Plugins
NodeResourcesFit
Scores nodes based on how well the Pod's resource requests align with the node's remaining allocatable capacity, using a configurable strategy — LeastAllocated (default in many configurations) favors nodes with more free capacity remaining, spreading load across the cluster, while MostAllocated favors nodes that are already more heavily utilized, which is useful for bin-packing strategies aiming to consolidate workloads onto fewer nodes to allow others to scale down or be reclaimed.
InterPodAffinity
Scores nodes based on how well they satisfy preferredDuringSchedulingIgnoredDuringExecution pod affinity and anti-affinity terms, weighted by each term's own configured weight, summed across every matching preference.
NodeAffinity
Scores nodes based on satisfaction of preferredDuringSchedulingIgnoredDuringExecution node affinity terms, similarly weighted and summed per matching term.
TaintToleration
Scores nodes lower if they carry PreferNoSchedule taints the Pod does not tolerate, providing the soft-avoidance behavior that distinguishes PreferNoSchedule from the hard-filtering NoSchedule effect.
PodTopologySpread
Scores nodes based on how placing the Pod there would affect topology spread skew for any configured ScheduleAnyway topology spread constraints, favoring nodes that keep the distribution more balanced.
ImageLocality
Favors nodes that already have the Pod's container image cached locally, reducing image pull time and network transfer — a practical optimization especially relevant for large images or bandwidth-constrained environments.
Weighting Plugins
Default Weights
Each built-in plugin has a sensible default weight reflecting its typical importance relative to the others, but cluster operators can adjust these weights (or disable specific plugins entirely) through the scheduler's configuration, tailoring scoring behavior to their specific priorities — for example, weighting NodeResourcesFit more heavily in a cost-sensitive cluster prioritizing tight bin-packing.
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
plugins:
score:
enabled:
- name: NodeResourcesFit
weight: 5
- name: InterPodAffinity
weight: 2
The Combined Score
The node with the highest combined total across every active, weighted plugin is selected, with ties broken through an internal randomization mechanism to avoid deterministically favoring the same node repeatedly under equal scores.
Scoring Only Applies After Filtering
No Rescue for Infeasible Nodes
Scoring never runs against a node that failed filtering — a node scoring poorly is still a viable placement target if it was among the feasible set, while a node that would have scored perfectly is never even considered if it failed a hard filter like insufficient resources or an untolerated taint. This ordering (hard filter first, soft scoring second) is fundamental to correctly reasoning about scheduler behavior.
Observing Scoring Decisions
kubectl get events --field-selector involvedObject.name=codartium-app,reason=Scheduled
Scheduler scoring decisions are not directly exposed via kubectl in granular per-plugin detail by default; deeper investigation into specific scoring behavior typically requires enabling verbose scheduler logging or scheduler framework tracing, reserved for genuinely puzzling placement decisions rather than routine troubleshooting.
Example
apiVersion: v1
kind: Pod
metadata:
name: codartium-scoring-example
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: disktype
operator: In
values: ["ssd"]
containers:
- name: app
image: codartium/app:latest