2. 调度器工作原理:调度队列、调度周期与绑定周期、调度器扩展点(Scheduling Framework)

Kubernetes 调度器(kube-scheduler)的核心职责是为每个待调度的 Pod 找到一个最合适的 Node。理解其内部工作原理,是掌握亲和性规则与网络拓扑通信机制的基础。本章将深入剖析调度器的三大核心模块:调度队列、调度周期与绑定周期,以及调度框架(Scheduling Framework)的扩展点机制。

2.1 调度队列:Pod 的等待与排序

调度队列是调度器的入口,负责管理所有等待调度的 Pod。它并非简单的 FIFO 队列,而是根据 Pod 的优先级、调度重试次数等因素进行动态排序。

队列类型 说明 关键特性
activeQ(活跃队列) 存放所有等待调度的 Pod,按优先级排序。 高优先级的 Pod 会优先被调度。
backoffQ(回退队列) 存放调度失败的 Pod,等待一段时间后重试。 重试间隔呈指数级增长,避免频繁重试。
unschedulableQ(不可调度队列) 存放因资源不足、节点不匹配等原因无法调度的 Pod。 当集群状态发生变化(如新节点加入)时,会重新评估。
关键机制:调度器通过 PodInformer 监听 API Server 中的 Pod 变化。当一个新的 Pod 被创建且 spec.nodeName 为空时,它会被加入 activeQ。调度器会持续从 activeQ 中取出 Pod 进行调度。

2.2 调度周期与绑定周期:一次完整的调度决策

一次完整的调度过程被分为两个逻辑阶段:调度周期(Scheduling Cycle)和绑定周期(Binding Cycle)。这两个阶段是串行执行的,但调度器可以并行处理多个 Pod 的调度周期。

调度周期与绑定周期流程 调度周期(Scheduling Cycle) 1. 从 activeQ 取出 Pod 2. 执行 Filter 插件(预选) 3. 执行 Score 插件(优选) 4. 执行 Reserve 插件(预留资源) 5. 执行 Permit 插件(许可) 输出:选定的 Node 名称 串行 绑定周期(Binding Cycle) 1. 执行 WaitOnPermit(等待许可) 2. 执行 PreBind 插件(预绑定) 3. 执行 Bind 插件(绑定) 4. 执行 PostBind 插件(后绑定) 输出:Pod 被绑定到 Node 说明:调度周期是同步的,绑定周期是异步的。调度器可以同时处理多个 Pod 的调度周期,但绑定周期按顺序执行。
性能优化点:调度周期是“找”节点的过程,绑定周期是“用”节点的过程。由于绑定周期涉及与 API Server 的交互(写入 binding 资源),将其异步化可以显著提升调度器的吞吐量。

2.3 调度框架(Scheduling Framework)与扩展点

Kubernetes 1.19 之后引入了 Scheduling Framework,将调度器的核心逻辑抽象为一系列可插拔的扩展点(Extension Points)。这使得用户可以自定义调度逻辑,而无需修改调度器核心代码。

调度框架将调度周期和绑定周期细分为多个扩展点,每个扩展点可以注册多个插件。插件按顺序执行,任何一个插件都可以否决(拒绝)当前的调度决策。

2.4 核心扩展点详解

扩展点 所属阶段 作用 典型插件示例
QueueSort 调度队列 对 activeQ 中的 Pod 进行排序。 PrioritySort
PreFilter 调度周期 预处理 Pod 信息,为 Filter 做准备。 NodeResourcesFit
Filter 调度周期 过滤掉不满足条件的 Node(预选)。 NodeAffinity, TaintToleration
PostFilter 调度周期 当 Filter 后无可用 Node 时,尝试替代方案。 Preemption(抢占)
PreScore 调度周期 为 Score 阶段准备评分数据。 —
Score 调度周期 对通过 Filter 的 Node 进行打分(优选)。 NodeResourcesBalancedAllocation
NormalizeScore 调度周期 对 Score 结果进行归一化处理。 —
Reserve 调度周期 在选定 Node 上预留资源,防止冲突。 VolumeBinding
Permit 调度周期 批准或延迟绑定操作。 —
PreBind 绑定周期 在绑定前执行准备工作。 VolumeBinding
Bind 绑定周期 将 Pod 绑定到 Node(写入 API Server)。 DefaultBinder
PostBind 绑定周期 绑定后的清理或通知工作。 —
注意:自定义插件必须实现对应的接口,并通过 --config 参数传递给 kube-scheduler。错误的插件实现可能导致调度器崩溃或调度决策异常。

2.5 调度框架的插件执行流程

以下 SVG 展示了调度框架中,一个 Pod 从进入调度队列到完成绑定的完整插件执行流程。

Scheduling Framework 扩展点执行流程 QueueSort 调度周期(Scheduling Cycle) PreFilter Filter PostFilter PreScore Score NormalizeScore Reserve Permit 绑定周期(Binding Cycle) WaitOnPermit PreBind Bind PostBind 说明:深蓝色节点为调度周期扩展点,绿色节点为绑定周期扩展点。红色节点(PostFilter)在 Filter 失败时触发。

2.6 自定义调度器与多调度器

Kubernetes 支持在一个集群中运行多个调度器实例。Pod 可以通过 spec.schedulerName 字段指定使用哪个调度器。默认调度器的名称为 default-scheduler。

实践建议:对于需要特殊调度策略的工作负载(如 GPU 任务、延迟敏感型服务),建议编写自定义调度器插件,而不是修改默认调度器。这样可以保持集群的稳定性和可维护性。
# 示例:Pod 指定使用自定义调度器
apiVersion: v1
kind: Pod
metadata:
  name: my-gpu-pod
spec:
  schedulerName: my-custom-scheduler  # 指定调度器名称
  containers:
  - name: gpu-container
    image: nvidia/cuda:11.0-base
    resources:
      limits:
        nvidia.com/gpu: 1

2.7 本章小结

  • 调度队列:通过 activeQ、backoffQ、unschedulableQ 三级队列管理 Pod 的调度状态,确保高优先级 Pod 优先被处理。
  • 调度周期与绑定周期:调度周期负责“找”节点,绑定周期负责“用”节点。两者串行执行,但调度周期可以并行处理多个 Pod。
  • Scheduling Framework:通过 12 个扩展点实现了调度逻辑的完全可插拔。用户可以通过编写插件来定制 Filter、Score、Bind 等行为。
  • 多调度器支持:允许在集群中运行多个调度器实例,满足不同工作负载的差异化调度需求。
下一阶段:在理解了调度器的工作原理后,我们将进入第 3 章,深入探讨节点亲和性(nodeAffinity)与 Pod 间亲和性/反亲和性(podAffinity/podAntiAffinity)的配置与实战案例。