1. 调度基础回顾:Kubernetes 调度器工作原理、调度流程、调度框架扩展点概述
1.1 调度器核心职责与工作模型
Kubernetes 调度器(kube-scheduler)是控制平面的核心组件之一,负责将待调度的 Pod 绑定到最合适的 Node 上。其本质是一个 资源匹配与约束满足 问题:在满足 Pod 的亲和性、资源请求、污点容忍等约束条件下,为每个未调度的 Pod 选择一个最优节点。
调度器以 “调度周期” 为单位工作,每个 Pod 独立经历一次完整的调度流程。调度器通过 Kubernetes 的 Watch 机制 监听 API Server 中未指定 nodeName 的 Pod,将其加入内部调度队列,依次处理。
关键指标: 调度吞吐量(Pods/sec)、调度延迟(P99 < 100ms 为健康)、调度失败率(因资源不足/污点不匹配等)。
1.2 调度流程:从入队到绑定
一个完整的调度周期分为两个阶段:调度周期(Scheduling Cycle) 和 绑定周期(Binding Cycle)。调度周期是串行的,绑定周期可以并行执行。
| 阶段 | 步骤 | 说明 |
|---|---|---|
| 调度周期 | 1. 过滤(Filter) | 遍历所有 Node,剔除不满足 Pod 约束的节点(如资源不足、端口冲突、污点不匹配)。 |
| 2. 打分(Score) | 对通过过滤的 Node 进行优先级评分(0-100),分数越高越优。 | |
| 3. 选定(Select) | 选择得分最高的 Node;若多个 Node 同分,则随机选择一个。 | |
| 绑定周期 | 4. 绑定(Bind) | 将 Pod 的 nodeName 字段写入 API Server,完成绑定。 |
注意: 调度周期是“乐观”的——它基于缓存中的节点信息做决策,不持有锁。如果绑定周期中节点状态发生变化(如资源被其他 Pod 抢占),绑定可能失败,调度器会重新调度该 Pod。
1.3 调度框架(Scheduling Framework)与扩展点
Kubernetes 从 v1.19 开始引入 调度框架(Scheduling Framework),将调度流程拆解为多个可插拔的扩展点(Extension Points)。调度框架允许开发者在不修改调度器核心代码的情况下,通过实现特定接口来注入自定义调度逻辑。
调度框架将调度周期和绑定周期细分为以下 11 个扩展点,按执行顺序排列:
| 阶段 | 扩展点 | 作用 | 典型用途 |
|---|---|---|---|
| 调度周期 | QueueSort | 对调度队列中的 Pod 排序 | 实现优先级抢占排序 |
| PreFilter | 预处理 Pod 信息,校验调度参数 | 检查 Pod 的卷挂载需求 | |
| Filter | 过滤不满足条件的 Node | 污点容忍检查、资源充足性检查 | |
| PostFilter | 过滤后无可用 Node 时的处理 | 触发抢占(Preemption) | |
| PreScore / Score / NormalizeScore | 对 Node 进行打分与归一化 | 自定义资源权重、节点亲和性评分 | |
| 绑定周期 | Reserve | 预留资源,防止并发冲突 | 预留 GPU 显存 |
| Permit | 批准或拒绝绑定(可等待) | 实现多调度器协调 | |
| PreBind / Bind / PostBind | 执行绑定及绑定后处理 | 动态创建网络资源、记录调度事件 |
重要: 调度框架的扩展点并非全部必须实现。大多数场景下,只需实现 Filter 和 Score 两个扩展点即可完成自定义调度策略。污点容忍规则主要在 Filter 扩展点中检查,而架构适配(如 GPU、NUMA 拓扑)通常在 Score 或 Reserve 中处理。
1.4 调度器工作原理总结
理解调度器的工作原理是优化调度的基础。以下是需要牢记的 三个核心认知:
- 调度是“乐观”的: 调度器基于缓存做决策,不持有锁。绑定周期中若节点状态变化,可能导致调度失败并重新调度。
- 调度框架是可扩展的: 11 个扩展点覆盖了调度全生命周期,污点容忍规则主要在 Filter 扩展点实现,架构适配(如 GPU、NUMA)主要在 Score 和 Reserve 扩展点实现。
- 调度性能瓶颈: 过滤阶段是 CPU 密集型(遍历所有 Node),打分阶段是 I/O 密集型(读取节点状态)。优化方向包括:减少过滤节点数(如使用 NodeSelector)、缓存节点信息、并行打分。