1. 调度器概述:K8s 调度器架构、调度流程、调度器组件
Kubernetes 调度器(kube-scheduler)是控制平面的核心组件之一,负责将待调度的 Pod 绑定到最合适的 Node 上。调度器并不直接执行 Pod 的创建或运行,而是通过监听 API Server 中的 Pod 变化,执行一系列过滤与打分算法,最终做出调度决策并写入绑定记录。理解调度器的架构、流程与组件,是分析其性能瓶颈与优化策略的前提。
1.1 调度器架构
Kubernetes 调度器采用 插件化(Plugin-based) 架构,核心调度框架(Scheduling Framework)定义了一组扩展点(Extension Points),调度器通过注册不同的插件来填充这些扩展点。这种设计使得调度策略高度可定制,同时也为性能优化提供了清晰的边界。
架构要点: 调度器本身是一个独立的二进制进程,通过
--config 参数加载调度配置(KubeSchedulerConfiguration),配置中定义了启用的插件列表、插件权重、以及调度策略。
1.2 调度流程
调度器对每个待调度的 Pod 执行一个完整的调度周期(Scheduling Cycle),该周期分为两个主要阶段:过滤阶段(Filtering) 和 打分阶段(Scoring)。过滤阶段选出所有满足 Pod 调度约束的 Node,打分阶段则对这些 Node 进行排序,最终选择得分最高的 Node 执行绑定。
完整的调度流程包含以下步骤:
| 步骤 | 阶段 | 说明 | 关键扩展点 |
|---|---|---|---|
| 1 | 排序 | 对调度队列中的 Pod 进行排序,确保高优先级 Pod 优先调度 | QueueSort |
| 2 | 预过滤 | 对 Pod 进行预处理,如检查 Pod 是否满足某些全局约束 | PreFilter |
| 3 | 过滤 | 遍历所有 Node,执行过滤插件,剔除不满足条件的 Node | Filter |
| 4 | 后过滤 | 处理过滤阶段的结果,如处理抢占(Preemption)逻辑 | PostFilter |
| 5 | 预打分 | 对候选 Node 进行预处理,为打分阶段准备数据 | PreScore |
| 6 | 打分 | 对每个候选 Node 执行打分插件,计算综合得分 | Score |
| 7 | 归一化 | 对打分结果进行归一化处理,确保不同插件的分数可比较 | NormalizeScore |
| 8 | 预留 | 预留资源,防止调度周期内的资源竞争 | Reserve |
| 9 | 许可 | 检查调度决策是否被其他组件(如准入控制器)允许 | Permit |
| 10 | 预绑定 | 执行绑定前的预处理,如创建存储卷 | PreBind |
| 11 | 绑定 | 将 Pod 绑定到选定的 Node,写入 API Server | Bind |
| 12 | 后绑定 | 绑定后的清理或通知操作 | PostBind |
性能关注点: 过滤阶段和打分阶段是调度器 CPU 消耗最高的两个环节。当集群规模较大(Node 数量 > 1000)时,过滤阶段的 Node 遍历开销和打分阶段的插件计算开销会显著增长,成为性能瓶颈的主要来源。
1.3 调度器组件
调度器的内部组件可以划分为三个层次:核心调度框架、调度队列 和 调度缓存。每个组件在调度周期中承担不同的职责,其性能表现直接影响调度吞吐量。
- 调度框架(Scheduling Framework): 定义扩展点与插件生命周期,负责调度周期的编排。框架本身不执行具体调度逻辑,而是调用注册的插件。
- 调度队列(Scheduling Queue): 管理待调度的 Pod,支持优先级排序、重试、回退(Backoff)等机制。队列分为 activeQ、backoffQ 和 unschedulableQ 三个子队列。
- 调度缓存(Scheduler Cache): 缓存集群中 Node 和 Pod 的最新状态,减少对 API Server 的频繁查询。缓存包括 NodeInfo、PodInfo 等数据结构。
- 绑定器(Binder): 负责将调度决策写入 API Server,执行 Pod 与 Node 的绑定操作。
- 抢占器(Preemptor): 当 Pod 无法调度时,尝试抢占低优先级 Pod 的资源,为高优先级 Pod 腾出空间。
常见误区: 很多开发者认为调度器只做“过滤+打分”,忽略了调度队列和缓存对性能的影响。实际上,调度队列的锁竞争和缓存的一致性维护在高并发场景下同样会成为瓶颈。
1.4 调度器组件关系
下表总结了各组件之间的协作关系与数据流:
| 组件 | 输入 | 输出 | 与调度框架的关系 |
|---|---|---|---|
| 调度队列 | API Server 推送的 Pod 事件 | 排序后的 Pod 列表 | 框架从队列中 Pop Pod 开始调度周期 |
| 调度缓存 | API Server 推送的 Node/Pod 事件 | NodeInfo、PodInfo 快照 | 框架在过滤/打分阶段读取缓存,避免实时查询 |
| 调度框架 | Pod 与缓存快照 | 选定的 Node 名称 | 核心编排器,调用插件执行扩展点 |
| 绑定器 | Pod 与 Node 绑定信息 | API Server 绑定记录 | 框架在 Bind 扩展点调用绑定器 |
| 抢占器 | 无法调度的 Pod | 被抢占的 Pod 列表 | 框架在 PostFilter 扩展点触发抢占 |