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

Kubernetes 调度器(kube-scheduler)的核心职责是为待调度的 Pod 找到最合适的节点。这一过程由三大核心组件协同完成:调度队列(Scheduling Queue)负责管理待调度 Pod 的优先级与顺序;调度框架(Scheduling Framework)提供可扩展的插件化调度管线;调度周期与绑定周期则定义了从“选节点”到“写绑定”的完整生命周期。

2.1 调度队列(Scheduling Queue)

调度队列是调度器的“输入缓冲区”,负责接收、排序和去重待调度的 Pod。Kubernetes 默认使用 PriorityQueue 实现,内部维护三个子队列:

队列名称 存储内容 出队顺序 典型场景
activeQ 可立即调度的 Pod 按优先级(Priority)降序,同优先级按入队时间 新创建的 Pod、重试的 Pod
backoffQ 调度失败且处于退避期的 Pod 退避时间到期后移至 activeQ 因资源不足、污点不匹配等临时失败
unschedulableQ 因集群状态变化可能可调度的 Pod 收到 Node/CSI/PV 变更事件后重新评估 因节点不可用、存储不可达等结构性原因失败
关键指标:调度队列深度(scheduler_queue_incoming_pods_total)和 Pod 在队列中的等待时间(scheduler_pod_queue_duration_seconds)是排查调度延迟的首要监控指标。

调度队列的入队与出队逻辑遵循以下步骤:

  1. 入队:Pod 通过 Informer 机制监听 API Server,新 Pod 或更新后的 Pod 被加入 activeQ。
  2. 排序:activeQ 使用最小堆(heap)实现,比较函数优先检查 Pod 的 spec.priority,再比较 creationTimestamp。
  3. 出队:调度主循环调用 NextPod() 从 activeQ 取出优先级最高的 Pod。
  4. 回退:调度失败后,根据失败次数计算退避时间(指数退避,最大 10 秒),放入 backoffQ。
  5. 重试:集群资源变更时,unschedulableQ 中的 Pod 被批量移回 activeQ 或 backoffQ。
避坑指南:如果大量高优先级 Pod 持续涌入,低优先级 Pod 可能长期滞留在队列中(饥饿问题)。建议配合 Pod Priority Preemption 和 调度框架的 QueueSort 插件 进行公平性调优。

2.2 调度框架(Scheduling Framework)

调度框架是 Kubernetes 1.19+ 引入的插件化调度管线,它将调度过程拆解为多个可扩展的扩展点(Extension Points)。每个扩展点允许用户注册自定义插件,实现调度策略的灵活定制。

调度框架扩展点架构图 调度周期(Scheduling Cycle) QueueSort PreFilter Filter PostFilter PreScore Score Normalize Reserve Permit 绑定周期(Binding Cycle) PreBind Bind PostBind 扩展点说明 • QueueSort:定义 Pod 出队顺序,默认按优先级排序。 • PreFilter/Filter:过滤不满足条件的节点(如资源不足、污点不匹配)。 • PostFilter:Filter 后无可用节点时执行抢占(Preemption)逻辑。 • PreScore/Score/NormalizeScore:对候选节点打分,选出最优节点。 • Reserve/Permit/PreBind/Bind/PostBind:绑定周期内的预留、许可与绑定操作。

调度框架的核心设计原则包括:

  • 插件化:每个扩展点可注册多个插件,插件按顺序执行,任一插件返回失败则终止当前周期。
  • 可组合:用户可通过 KubeSchedulerConfiguration 配置文件启用/禁用/排序插件,无需修改调度器代码。
  • 状态共享:插件可通过 CycleState 在调度周期内传递数据,避免重复计算。
实践案例:网络拓扑感知调度可通过实现 Score 扩展点 的插件,读取节点拓扑标签(如 topology.kubernetes.io/zone),为同可用区的节点赋予更高分数,从而减少跨 AZ 流量。

2.3 调度周期与绑定周期

调度器将一个 Pod 的完整调度过程分为两个阶段:调度周期(Scheduling Cycle) 和 绑定周期(Binding Cycle)。调度周期是串行的,绑定周期是并行的,两者通过 Permit 扩展点 衔接。

阶段 执行顺序 是否阻塞 核心扩展点 输出
调度周期 串行(一次一个 Pod) 是 QueueSort → PreFilter → Filter → PostFilter → PreScore → Score → NormalizeScore → Reserve 选中的节点名称
绑定周期 并行(多个 Pod 可同时绑定) 否 Permit → PreBind → Bind → PostBind Pod 与节点的绑定关系写入 API Server
重要区别:调度周期是“选节点”,绑定周期是“写绑定”。调度周期失败不会影响其他 Pod,绑定周期失败可能导致 Pod 处于“已预留但未绑定”的中间状态,需要 Unreserve 插件 清理预留资源。

调度周期与绑定周期的完整交互流程如下:

  1. 出队:调度主循环从 activeQ 取出一个 Pod,进入调度周期。
  2. 过滤与打分:依次执行 PreFilter、Filter、PostFilter(可选)、PreScore、Score、NormalizeScore,选出最优节点。
  3. 预留:Reserve 插件在选中的节点上预留资源(如 CSI 卷挂载点),防止并发调度冲突。
  4. 许可:Permit 插件决定是否允许进入绑定周期(可设置超时或等待依赖)。
  5. 绑定:PreBind 执行前置操作(如动态创建 PV),Bind 将 Pod 的 spec.nodeName 写入 API Server,PostBind 执行后置清理。
  6. 异步等待:绑定周期完成后,调度器继续处理下一个 Pod,kubelet 监听到绑定事件后启动 Pod。
调度周期与绑定周期时序图 调度周期(串行) 绑定周期(并行) 1. QueueSort → 出队 Pod 2. PreFilter → Filter → 过滤节点 3. Score → 选出最优节点 4. Reserve → 预留资源 5. Permit → 许可检查 6. PreBind → 前置操作 7. Bind → 写入 API Server 8. PostBind → 后置清理 Permit 通过 Reserve 完成
性能优化:调度周期串行执行保证了节点选择的原子性,避免两个 Pod 同时选中同一节点导致资源冲突。绑定周期并行执行则充分利用了 API Server 的并发写入能力,显著提升大规模集群的调度吞吐量。

2.4 核心组件协作总结

调度队列、调度框架、调度/绑定周期三者协作关系如下:

  • 调度队列 提供有序的 Pod 输入流,确保高优先级 Pod 优先被处理。
  • 调度框架 将调度过程拆解为可插拔的扩展点,允许用户自定义过滤、打分、绑定逻辑。
  • 调度周期 负责串行选节点,绑定周期 负责并行写绑定,两者通过 Permit 扩展点解耦。

理解这三个核心组件是掌握 Kubernetes 调度器架构的基础,也是后续实现网络拓扑感知调度、自定义调度插件开发的必备知识。