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),每个扩展点可以注册一个或多个插件。这种设计使得调度器的行为高度可定制,无需修改核心代码即可实现自定义调度逻辑。
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 阶段设置了超时(如等待外部资源就绪),则绑定周期会等待超时或条件满足后再执行。
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 可以输出详细的调度周期日志。