Kubernetes Scheduler
Kubernetes Scheduler 负责将 Pending 状态的 Pod 分配到合适的 Node 上,是从 调度策略 -> 算法实现 -> 决策输出 的核心组件。
- ☘️ 调度器的目标
- 🔧 调度器的架构
- 🔄 调度器工作流程(Filter -> Score -> Bind)
- 🔌 调度插件(Kubernetes 1.33 完整插件体系)
- 🧩 调度器的算法逻辑
- 🧲 Affinity / AntiAffinity / Taint / Toleration
- ⚡ 优雅抢占(Preemption)
- 🪝 调度扩展:自定义调度器 / 多调度器
- 📈 调度性能优化
- 🧪 调度问题排查指南
Kubernetes Scheduler 的目标:
在满足约束条件的前提下,选择最合适的节点。
约束条件包括:
| 类型 | 示例 |
|---|---|
| 硬约束(必须满足) | CPU/Mem 足够、NodeSelector、Taints、Volume、PodAffinity |
| 软约束(尽量满足) | Spread 分散、负载最小、镜像本地存在等 |
ASCII 图帮助理解:
Pod(Pending)
│
▼
[Informers] ---> Scheduler Queue --> Scheduling Cycle
│
▼
┌──────────────────────────────┐
Filter (预选阶段)
├──────────────────────────────┤
Score (评分阶段)
├──────────────────────────────┤
PreFilter / PreScore / Permit
├──────────────────────────────┤
Bind (绑定阶段)
└──────────────────────────────┘
- 调度周期 (Scheduling Cycle):从过滤 -> 评分 -> 绑定
- 绑定周期 (Binding Cycle):独立异步处理绑定。
Pod 创建后进入 Pending -> 被调度器 watch 到 -> 加入队列。
队列带优先级,可使用 PriorityClass 影响调度先后顺序。
逐个节点检查是否能调度:
过滤原因:
- CPU/Mem request 不满足
- Node 未准备好 NotReady
- Taint 不可容忍
- NodeSelector / NodeAffinity 不匹配
- PodAffinity / AntiAffinity 不满足
- HostPort 冲突
- CSI PV 不可挂载
- runtime class 不匹配
- hugepages / GPU 不满足
Filter 阶段产物:
- ✅ 可调度节点列表
- ❌ 如果列表为空 -> 调度失败(触发抢占或延时重试)
对每个可调度节点评分(0~100)。常见 scoring:
⭐ LeastAllocated
选择剩余资源最多的节点 -> 越空节点优先。
⭐ BalancedAllocation
选择 CPU/Mem 使用比例接近的节点 -> 避免只压满 CPU 或内存。
⭐ SelectorSpread
Pod 尽量分散到不同节点 -> 提高可靠性。
⭐ ImageLocality
节点上已存在镜像 -> 分高 -> 减少拉取时间。
最终分数 = 所有 scoring 插件的加权累加。
得分最高的节点获得调度权。
如多节点得分相同 -> RoundRobin / 随机选择。
Scheduler 将结果写入 Pod:
Pod.Spec.NodeName = <node>
Kubelet Watch 到后开始真正创建容器。
调度器通过插件组成,主要分:
| 阶段 | 功能 | 插件 |
|---|---|---|
| PreFilter | 准备调度所需数据 | NodePorts、PodAffinity |
| Filter | 硬约束过滤 | NodeResourcesFit、TaintToleration、VolumeRestrictions |
| PostFilter | 回调 / 抢占 | DefaultPreemption |
| PreScore | 评分前处理 | PodTopologySpread |
| Score | 节点评分 | LeastAllocated、BalancedAllocation、ImageLocality |
| Reserve | 临时占用资源 | VolumeBinding |
| Permit | 可阻塞调度 | QueueSort |
| PreBind | 绑定前动作 | VolumeBinding |
| Bind | 最终绑定 | DefaultBinder |
| PostBind | 结束日志 | - |
(过滤掉不可能运行的节点)
(在可行节点中找最优节点)
Kubernetes 调度器 = 硬约束过滤 + 软约束评分 + 决策绑定
调度最常用的机制:
nodeSelector:
disktype: ssd
支持 In、NotIn、Gt/Lt、软约束 preferred。
Pod 之间亲和/反亲和:
例如:强制不同节点:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
Taint / Toleration(污点与容忍)
Node 有 Taint -> Pod 需要对应 toleration 才能调度进去。
当高优先级 Pod 调度失败时:
- 查找可以驱逐的低优先级 Pod
- 计算“代价最小”的节点
- Evict 最少数量的 Pod
被抢占 Pod 进入 Terminating,完成后高优先级 Pod 重试调度。
给 Pod 指定:
schedulerName: custom-scheduler
即可让其使用非默认调度器。
- 基于调度插件(最推荐)
- 多调度器
- 调度器 extender(旧机制)
- 自定义调度程序
大型集群(2000+ Node)需关注性能:
- 使用 Coscheduling / Batch 调度(AI 高频场景)
- 使用 PreFilter、Cache 优化
- 关闭不必要的调度插件
- 调大 Kube-Scheduler QPS / Burst
- 使用调度器 profile
kubectl describe pod <pod>
常见异常:
- 0/3 nodes are available: 3 Insufficient cpu
- node(s) had untolerated taint
- pod didn’t match pod affinity
journalctl -u kube-scheduler -f
kubectl alpha schedule pod <pod.yaml>
Kubernetes Scheduler = Watch -> Filter(硬约束) -> Score(软约束) -> Bind(决策)
通过调度插件实现可插拔策略,并支持多调度器、抢占、优先级、Pod/Node Affinity、Taints。