Kubernetes 调度器基础:调度器工作原理、调度队列、调度周期与绑定周期

Kubernetes 调度器(kube-scheduler)是控制平面的核心组件之一,负责将待调度的 Pod 分配到最合适的 Node 上。理解调度器的内部工作原理、调度队列机制以及调度周期与绑定周期的划分,是掌握控制平面调度策略的基石。

2.1 调度器工作原理概述

kube-scheduler 以独立进程运行在控制平面节点上,通过 watch 机制监听 API Server 中未调度的 Pod(即 spec.nodeName 为空)。调度器为每个待调度 Pod 执行一个完整的调度周期,最终将 Pod 与 Node 的绑定关系写入 etcd。

调度器的核心工作流程可概括为以下步骤:

  1. 监听与过滤:从 API Server 获取未调度的 Pod 和所有 Node 的实时状态。
  2. 预选(Predicates):过滤掉不满足 Pod 调度约束的 Node(如资源不足、端口冲突、污点容忍等)。
  3. 优选(Priorities):对通过预选的 Node 进行打分,选出最优节点。
  4. 绑定(Bind):将 Pod 与选中的 Node 绑定,更新 API Server 中的 Pod 对象。
关键概念: 调度器并不直接与 kubelet 通信,而是通过 API Server 更新 Pod 的 spec.nodeName 字段。kubelet 通过 watch 机制感知到绑定变化后,才会在本地启动容器。

2.2 调度队列(Scheduling Queue)

调度队列是调度器的“待办事项列表”,负责管理所有等待调度的 Pod。Kubernetes 1.23+ 版本默认使用 PrioritySort 队列排序策略,确保高优先级 Pod 优先被调度。

调度队列内部维护了三个子队列:

子队列 作用 典型场景
ActiveQ 存放所有可立即调度的 Pod 新创建的 Pod、重试调度的 Pod
BackoffQ 存放调度失败后等待重试的 Pod 资源不足、节点不可达等临时错误
UnschedulableQ 存放因不可调度条件而阻塞的 Pod 污点不匹配、节点选择器不满足、持久卷不可用

调度器通过 Pod 的优先级 和 重试时间戳 动态调整 Pod 在队列中的位置。当集群资源发生变化(如新节点加入、资源释放),调度器会触发 移动操作,将 UnschedulableQ 或 BackoffQ 中的 Pod 移回 ActiveQ 重新尝试调度。

实践建议: 如果集群中出现大量 Pod 长时间处于 Pending 状态,可以检查调度队列的深度和 Pod 所在的子队列。使用 kubectl describe pod <pod-name> 查看调度事件,或通过 kube-scheduler 的 metrics 接口(/metrics)监控队列指标。

2.3 调度周期(Scheduling Cycle)与绑定周期(Binding Cycle)

Kubernetes 调度器将单个 Pod 的调度过程拆分为两个独立的阶段:调度周期 和 绑定周期。这种分离设计使得调度器可以在绑定周期中执行异步操作(如卷挂载、网络配置),而不会阻塞后续 Pod 的调度。

调度周期与绑定周期流程 调度周期与绑定周期流程 调度周期 预选(Predicates) 优选(Priorities) 绑定周期 绑定(Bind) 异步扩展点 结果传递 调度队列 Pod 出队 绑定完成,Pod 移出队列 说明:调度周期是同步的,绑定周期是异步的。调度器在调度周期结束后立即开始下一个 Pod 的调度, 绑定周期在后台并行执行,从而提升整体调度吞吐量。

2.4 调度周期详解

调度周期是同步执行的,调度器会依次调用一组 调度插件(Scheduling Plugins)。每个插件实现一个或多个扩展点(Extension Points),扩展点按固定顺序执行:

扩展点 执行顺序 典型插件 作用
QueueSort 1 PrioritySort 对调度队列中的 Pod 排序
PreFilter 2 NodeResourcesFit 预检查 Pod 的调度约束
Filter 3 NodeUnschedulable, TaintToleration 过滤不满足条件的 Node
PostFilter 4 DefaultPreemption 处理调度失败(如抢占)
PreScore 5 NodeResourcesBalancedAllocation 为打分阶段准备数据
Score 6 NodeResourcesLeastAllocated, ImageLocality 对 Node 打分(0-100)
NormalizeScore 7 — 归一化分数
Reserve 8 VolumeBinding 预留资源,避免并发冲突
Permit 9 — 批准或延迟绑定
注意: 如果 Filter 阶段没有 Node 通过,调度器会触发 PostFilter 扩展点,尝试抢占(Preemption)低优先级 Pod 以释放资源。抢占成功后,被抢占的 Pod 会被删除并重新加入调度队列。

2.5 绑定周期详解

绑定周期是异步执行的,调度器在调度周期结束后立即开始下一个 Pod 的调度,同时将绑定任务提交给后台协程。绑定周期包含以下扩展点:

  • PreBind:在绑定前执行准备工作,如动态创建 PersistentVolume(通过 WaitForFirstConsumer 模式)。
  • Bind:执行实际的绑定操作,默认通过 API Server 更新 Pod 的 spec.nodeName。
  • PostBind:绑定完成后执行清理或通知操作。

绑定周期的异步特性使得调度器可以同时处理多个 Pod 的绑定,显著提升大规模集群的调度效率。但这也意味着绑定周期中的失败(如卷创建超时)不会阻塞调度周期,调度器会通过重试机制处理绑定失败。

2.6 调度器性能与可观测性

调度器的性能直接影响集群的响应速度。以下是关键性能指标和观测手段:

指标 Prometheus 指标名称 说明
调度队列深度 scheduler_queue_incoming_pods_total 入队 Pod 总数
调度延迟 scheduler_scheduling_attempt_duration_seconds 单次调度尝试耗时
绑定延迟 scheduler_binding_duration_seconds 绑定操作耗时
抢占次数 scheduler_preemption_attempts_total 抢占尝试次数
排查技巧: 当 Pod 长时间 Pending 时,查看 kube-scheduler 日志(--v=4 或更高)可以获取详细的调度决策。使用 kubectl get events --field-selector involvedObject.kind=Pod 查看调度事件,快速定位问题。

2.7 调度器扩展机制

Kubernetes 调度器支持通过 Scheduling Framework 进行扩展,开发者可以编写自定义调度插件并注册到扩展点。常见的扩展场景包括:

  • 自定义 Filter 插件:实现硬件加速器、GPU 拓扑等特殊约束。
  • 自定义 Score 插件:根据业务优先级(如成本、地域亲和性)调整打分。
  • 自定义 Bind 插件:实现多集群调度或自定义绑定逻辑。

调度器插件通过 --config 参数加载配置文件,支持动态启用/禁用内置插件和加载外部插件。

调度器插件扩展点架构 调度器插件扩展点架构 调度周期扩展点 PreFilter / Filter Score / NormalizeScore Reserve / Permit 绑定周期扩展点 PreBind Bind PostBind 调度队列 ActiveQ BackoffQ UnschedulableQ