Kubernetes 调度器基础:调度器工作原理、调度队列、调度周期与绑定周期
Kubernetes 调度器(kube-scheduler)是控制平面的核心组件之一,负责将待调度的 Pod 分配到最合适的 Node 上。理解调度器的内部工作原理、调度队列机制以及调度周期与绑定周期的划分,是掌握控制平面调度策略的基石。
2.1 调度器工作原理概述
kube-scheduler 以独立进程运行在控制平面节点上,通过 watch 机制监听 API Server 中未调度的 Pod(即 spec.nodeName 为空)。调度器为每个待调度 Pod 执行一个完整的调度周期,最终将 Pod 与 Node 的绑定关系写入 etcd。
调度器的核心工作流程可概括为以下步骤:
- 监听与过滤:从 API Server 获取未调度的 Pod 和所有 Node 的实时状态。
- 预选(Predicates):过滤掉不满足 Pod 调度约束的 Node(如资源不足、端口冲突、污点容忍等)。
- 优选(Priorities):对通过预选的 Node 进行打分,选出最优节点。
- 绑定(Bind):将 Pod 与选中的 Node 绑定,更新 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 重新尝试调度。
kubectl describe pod <pod-name> 查看调度事件,或通过 kube-scheduler 的 metrics 接口(/metrics)监控队列指标。
2.3 调度周期(Scheduling Cycle)与绑定周期(Binding Cycle)
Kubernetes 调度器将单个 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 | — | 批准或延迟绑定 |
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 |
抢占尝试次数 |
--v=4 或更高)可以获取详细的调度决策。使用 kubectl get events --field-selector involvedObject.kind=Pod 查看调度事件,快速定位问题。
2.7 调度器扩展机制
Kubernetes 调度器支持通过 Scheduling Framework 进行扩展,开发者可以编写自定义调度插件并注册到扩展点。常见的扩展场景包括:
- 自定义 Filter 插件:实现硬件加速器、GPU 拓扑等特殊约束。
- 自定义 Score 插件:根据业务优先级(如成本、地域亲和性)调整打分。
- 自定义 Bind 插件:实现多集群调度或自定义绑定逻辑。
调度器插件通过 --config 参数加载配置文件,支持动态启用/禁用内置插件和加载外部插件。