2. 调度器核心组件解析:调度队列、调度框架、调度周期与绑定周期

Kubernetes 调度器(kube-scheduler)的内部架构可以抽象为三个核心组件:调度队列(Scheduling Queue)、调度框架(Scheduling Framework)以及由框架驱动的调度周期(Scheduling Cycle)与绑定周期(Binding Cycle)。理解这四个要素的协作关系,是进行性能调优和故障排查的基础。

核心认知:调度队列负责管理待调度 Pod 的优先级与顺序;调度框架提供了一套可扩展的插件化接口;调度周期是“为 Pod 选择一个合适 Node”的决策过程;绑定周期则是“将决策结果持久化并通知各组件”的执行过程。

2.1 调度队列(Scheduling Queue)

调度队列是 Pod 进入调度流程的入口。它负责对等待调度的 Pod 进行排序、去重和重试管理。kube-scheduler 内部维护了一个优先级队列,Pod 的排序依据是其 PriorityClass 和 QueueSort 插件 的排序结果。

队列类型 作用 典型场景
activeQ 存放所有等待调度的 Pod,按优先级排序 新创建的 Pod、因抢占被重新入队的 Pod
backoffQ 存放调度失败后进入退避期的 Pod 因资源不足、节点污点等临时错误失败的 Pod
unschedulableQ 存放调度失败且无法通过退避解决的 Pod 因节点选择器不匹配、持久卷挂载失败等硬约束失败的 Pod
调优要点:当集群规模较大(>1000 Node)时,unschedulableQ 中的 Pod 可能会因周期性重试(默认为 5 分钟)而产生不必要的调度循环。可以通过调整 --unschedulableQSize 和 --backoffQSize 参数来优化内存占用。

2.2 调度框架(Scheduling Framework)

调度框架是 kube-scheduler 自 v1.19 版本引入的插件化架构。它将调度流程拆解为多个扩展点(Extension Points),每个扩展点可以注册一个或多个插件。这种设计使得调度器的行为高度可定制,无需修改核心代码即可实现自定义调度逻辑。

调度框架扩展点与插件注册流程 调度队列 调度框架扩展点 QueueSort PreFilter Filter PostFilter PreScore Score NormalizeScore Reserve Permit PreBind Bind PostBind 绑定结果 说明:调度框架将调度流程拆解为多个扩展点,每个扩展点可注册多个插件。插件按顺序执行,任一插件失败则终止当前周期。 调度周期包含 QueueSort → PreFilter → Filter → PostFilter → PreScore → Score → NormalizeScore;绑定周期包含 Reserve → Permit → PreBind → Bind → PostBind。

2.3 调度周期(Scheduling Cycle)

调度周期是调度框架中选择节点的阶段。它从调度队列中取出一个 Pod,经过一系列扩展点,最终为该 Pod 选定一个最合适的 Node。调度周期是串行的,即同一时间只有一个 Pod 在执行调度周期。

  • QueueSort:对 activeQ 中的 Pod 进行排序,决定下一个调度的 Pod。
  • PreFilter:对 Pod 进行前置检查,例如检查 Pod 的 Volume 拓扑约束是否满足。
  • Filter:遍历所有 Node,过滤掉不满足 Pod 调度条件的 Node(如资源不足、污点不匹配)。
  • PostFilter:当 Filter 阶段没有找到可用 Node 时,执行抢占逻辑(Preemption)或记录失败原因。
  • PreScore / Score / NormalizeScore:对通过 Filter 的 Node 进行打分,选出最优节点。
性能瓶颈点:Filter 阶段是调度周期中最耗时的部分。当集群节点数超过 5000 时,每个 Pod 的 Filter 操作需要遍历所有 Node,导致调度延迟显著增加。建议启用 NodeResourcesFit 插件的 LeastAllocated 策略,并配合 --permit-wait-timeout 参数控制等待超时。

2.4 绑定周期(Binding Cycle)

绑定周期是调度框架中执行绑定的阶段。它负责将调度周期的决策结果(Pod 与 Node 的绑定关系)持久化到 etcd,并通知 kubelet 启动 Pod。与调度周期不同,绑定周期是异步并发的,多个 Pod 可以同时执行绑定操作。

扩展点 作用 失败处理
Reserve 在 Node 上预留资源,防止其他 Pod 抢占 释放预留资源,Pod 重新入队
Permit 等待外部条件满足(如等待其他 Pod 完成) 超时后拒绝绑定,Pod 重新入队
PreBind 执行绑定前的准备工作(如创建 Volume) 回滚已执行的操作
Bind 将 Pod 与 Node 的绑定关系写入 etcd 重试或失败后重新调度
PostBind 绑定成功后的清理或通知操作 仅记录日志,不影响调度结果

2.5 调度周期与绑定周期的协作流程

调度周期和绑定周期通过 Permit 扩展点 进行衔接。调度周期结束后,Pod 进入 Permit 阶段,等待绑定周期开始。如果 Permit 阶段设置了超时(如等待外部资源就绪),则绑定周期会等待超时或条件满足后再执行。

调度周期与绑定周期协作流程 调度周期(串行) QueueSort → Filter → Score 选择一个最优 Node Permit 等待条件满足 或超时 绑定周期 (异步并发) Reserve → Bind 绑定失败 → Pod 重新入队 说明:调度周期是串行的,确保同一时间只有一个 Pod 被调度,避免资源竞争。 绑定周期是异步并发的,多个 Pod 可以同时执行绑定操作,提高吞吐量。绑定失败后 Pod 会重新进入调度队列等待重试。

2.6 核心组件调优参数速查

组件 关键参数 默认值 调优建议
调度队列 --unschedulableQSize 1024 集群规模 > 5000 Pod 时建议增大至 2048
调度队列 --backoffQSize 1024 与 unschedulableQSize 保持一致
调度框架 --permit-wait-timeout 0(无超时) 建议设置为 30s,避免 Permit 插件永久阻塞
调度周期 --node-score-weight 1 根据业务优先级调整打分权重
绑定周期 --bind-timeout 100s 网络延迟高时适当增大至 200s
排查思路:当 Pod 长时间处于 Pending 状态时,首先检查调度队列状态:kubectl get pods -o wide | grep Pending。然后查看 scheduler 日志中的 Unschedulable 或 Backoff 关键字,定位是哪个扩展点失败。使用 kube-scheduler --v=5 可以输出详细的调度周期日志。