Skip to main content
Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Kubernetes Scheduler

Kubernetes Scheduler 负责将 Pending 状态的 Pod 分配到合适的 Node 上,是从 调度策略 -> 算法实现 -> 决策输出 的核心组件。

目录

  1. ☘️ 调度器的目标
  2. 🔧 调度器的架构
  3. 🔄 调度器工作流程(Filter -> Score -> Bind)
  4. 🔌 调度插件(Kubernetes 1.33 完整插件体系)
  5. 🧩 调度器的算法逻辑
  6. 🧲 Affinity / AntiAffinity / Taint / Toleration
  7. ⚡ 优雅抢占(Preemption)
  8. 🪝 调度扩展:自定义调度器 / 多调度器
  9. 📈 调度性能优化
  10. 🧪 调度问题排查指南

1. 调度器目标(核心概念)

Kubernetes Scheduler 的目标:

在满足约束条件的前提下,选择最合适的节点。

约束条件包括:

类型 示例
硬约束(必须满足) CPU/Mem 足够、NodeSelector、Taints、Volume、PodAffinity
软约束(尽量满足) Spread 分散、负载最小、镜像本地存在等

2. Scheduler 架构(v1.33 标准流程)

ASCII 图帮助理解:

Pod(Pending)
[Informers] ---> Scheduler Queue --> Scheduling Cycle
            ┌──────────────────────────────┐
                 Filter (预选阶段)
            ├──────────────────────────────┤
                 Score  (评分阶段)
            ├──────────────────────────────┤
              PreFilter / PreScore / Permit
            ├──────────────────────────────┤
                 Bind (绑定阶段)
            └──────────────────────────────┘
  • 调度周期 (Scheduling Cycle):从过滤 -> 评分 -> 绑定
  • 绑定周期 (Binding Cycle):独立异步处理绑定。

3. 调度工作流程详解

📌 3.1 进入队列(Scheduling Queue)

Pod 创建后进入 Pending -> 被调度器 watch 到 -> 加入队列。

队列带优先级,可使用 PriorityClass 影响调度先后顺序。

📌 3.2 Filter(预选阶段)

逐个节点检查是否能调度:

过滤原因:

  • CPU/Mem request 不满足
  • Node 未准备好 NotReady
  • Taint 不可容忍
  • NodeSelector / NodeAffinity 不匹配
  • PodAffinity / AntiAffinity 不满足
  • HostPort 冲突
  • CSI PV 不可挂载
  • runtime class 不匹配
  • hugepages / GPU 不满足

Filter 阶段产物:

  • ✅ 可调度节点列表
  • ❌ 如果列表为空 -> 调度失败(触发抢占或延时重试)

📌 3.3 Score(评分阶段)

对每个可调度节点评分(0~100)。常见 scoring:

⭐ LeastAllocated

选择剩余资源最多的节点 -> 越空节点优先。

⭐ BalancedAllocation

选择 CPU/Mem 使用比例接近的节点 -> 避免只压满 CPU 或内存。

⭐ SelectorSpread

Pod 尽量分散到不同节点 -> 提高可靠性。

⭐ ImageLocality

节点上已存在镜像 -> 分高 -> 减少拉取时间。

最终分数 = 所有 scoring 插件的加权累加。

📌 3.4 最终节点选择

得分最高的节点获得调度权。

如多节点得分相同 -> RoundRobin / 随机选择。

📌 3.5 Bind(绑定阶段)

Scheduler 将结果写入 Pod:

Pod.Spec.NodeName = <node>

Kubelet Watch 到后开始真正创建容器。

4. Kubernetes 1.33 全调度插件体系(最全最新)

调度器通过插件组成,主要分:

阶段 功能 插件
PreFilter 准备调度所需数据 NodePorts、PodAffinity
Filter 硬约束过滤 NodeResourcesFit、TaintToleration、VolumeRestrictions
PostFilter 回调 / 抢占 DefaultPreemption
PreScore 评分前处理 PodTopologySpread
Score 节点评分 LeastAllocated、BalancedAllocation、ImageLocality
Reserve 临时占用资源 VolumeBinding
Permit 可阻塞调度 QueueSort
PreBind 绑定前动作 VolumeBinding
Bind 最终绑定 DefaultBinder
PostBind 结束日志 -

5. 调度算法核心逻辑

📍 Filter = 可行性

(过滤掉不可能运行的节点)

📍 Score = 优化性

(在可行节点中找最优节点)

📍 Bind = 最终决策写回

Kubernetes 调度器 = 硬约束过滤 + 软约束评分 + 决策绑定

6. Affinity / AntiAffinity / Taint / Toleration

调度最常用的机制:

NodeSelector(最简单硬约束)

nodeSelector:
  disktype: ssd

NodeAffinity(更强)

支持 In、NotIn、Gt/Lt、软约束 preferred。

PodAffinity / AntiAffinity

Pod 之间亲和/反亲和:

例如:强制不同节点:

podAntiAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    - topologyKey: kubernetes.io/hostname

Taint / Toleration(污点与容忍)

Node 有 Taint -> Pod 需要对应 toleration 才能调度进去。

7. 优雅抢占(Preemption)

当高优先级 Pod 调度失败时:

  • 查找可以驱逐的低优先级 Pod
  • 计算“代价最小”的节点
  • Evict 最少数量的 Pod

被抢占 Pod 进入 Terminating,完成后高优先级 Pod 重试调度。

8. 调度扩展

⛓️ 自定义调度器

给 Pod 指定:

schedulerName: custom-scheduler

即可让其使用非默认调度器。

🧱 调度器扩展方式

  1. 基于调度插件(最推荐)
  2. 多调度器
  3. 调度器 extender(旧机制)
  4. 自定义调度程序

9. 调度性能优化

大型集群(2000+ Node)需关注性能:

  1. 使用 Coscheduling / Batch 调度(AI 高频场景)
  2. 使用 PreFilter、Cache 优化
  3. 关闭不必要的调度插件
  4. 调大 Kube-Scheduler QPS / Burst
  5. 使用调度器 profile

10. 调度问题排查(实际很常用)

查看 Pod 为何调度失败

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。