1. 调度器架构总览:核心组件、调度框架与扩展点
Kubernetes 调度器(kube-scheduler)是控制平面中负责将 Pod 绑定到合适 Node 的核心组件。其设计经历了从“硬编码调度策略”到“可插拔调度框架”的重大演进。本章将拆解调度器的内部架构、调度框架(Scheduling Framework)的插件化设计,以及关键的扩展点(Extension Points)。
1.1 调度器核心组件
调度器内部由多个协作模块构成,每个模块承担明确的职责。下表列出了核心组件及其功能:
| 组件 | 职责 | 说明 |
|---|---|---|
| 调度队列 | 管理待调度 Pod | 包含 activeQ、backoffQ、unschedulableQ 三个子队列,支持优先级排序与重试 |
| 调度框架 | 插件化调度流程 | 定义扩展点,允许用户注入自定义调度逻辑 |
| 调度缓存 | 缓存集群状态 | 维护 Node 和 Pod 的实时快照,避免频繁访问 API Server |
| 调度器主循环 | 驱动调度周期 | 从队列取出 Pod,依次执行过滤、打分、绑定等阶段 |
| 绑定器 | 写入绑定关系 | 将 Pod 与选定 Node 的绑定记录写入 API Server |
关键指标:调度延迟(Scheduling Latency)通常指 Pod 进入调度队列到完成绑定的时间。核心组件中,调度队列的排序效率和调度框架的插件执行时间是主要影响因素。
1.2 调度框架(Scheduling Framework)
调度框架是 Kubernetes 1.15+ 引入的插件化架构,它将调度周期拆解为多个独立的扩展点。每个扩展点可以注册一个或多个插件,插件按顺序执行,共同决定 Pod 的调度结果。
调度框架的核心设计原则:
- 可插拔:插件通过配置文件动态加载,无需重新编译调度器。
- 分层:调度周期分为 调度周期(Scheduling Cycle) 和 绑定周期(Binding Cycle),两者异步执行。
- 扩展点明确:每个扩展点有固定的输入输出和错误处理语义。
1.3 扩展点(Extension Points)详解
调度框架定义了 11 个标准扩展点,分布在调度周期和绑定周期中。每个扩展点有特定的语义和调用时机:
| 扩展点 | 所属周期 | 调用时机 | 典型用途 |
|---|---|---|---|
| PreFilter | 调度 | 过滤前预处理 | Pod 合法性检查、资源预计算 |
| Filter | 调度 | 过滤不满足条件的 Node | 节点选择器、资源不足、端口冲突 |
| PostFilter | 调度 | 过滤后无可用 Node 时触发 | 抢占、调度失败处理 |
| PreScore | 调度 | 打分前预处理 | 计算评分所需的数据 |
| Score | 调度 | 对通过过滤的 Node 打分 | 资源均衡、亲和性评分 |
| NormalizeScore | 调度 | 分数归一化 | 将多个插件的分数合并为最终分数 |
| Reserve | 调度 | 预留资源 | 在缓存中预留 Pod 资源,防止冲突 |
| Permit | 调度 | 批准或延迟绑定 | 实现准入控制、等待条件 |
| PreBind | 绑定 | 绑定前预处理 | 网络配置、存储挂载准备 |
| Bind | 绑定 | 执行绑定 | 写入绑定记录到 API Server |
| PostBind | 绑定 | 绑定后清理 | 日志记录、指标上报 |
优化提示:在多队列排序场景中,PreFilter 和 Filter 扩展点对调度延迟影响最大。如果插件执行时间过长,会阻塞整个调度周期。建议将耗时操作(如外部 API 调用)异步化或使用缓存。
1.4 调度队列与排序机制
调度队列是调度器的入口,负责管理所有待调度的 Pod。它包含三个子队列:
- activeQ:存放准备调度的 Pod,按优先级排序。
- backoffQ:存放调度失败但可重试的 Pod,按退避时间排序。
- unschedulableQ:存放因资源不足等原因无法调度的 Pod,等待集群状态变化后重新入队。
队列排序的核心逻辑由 LessFunc 决定,默认基于 Pod 优先级、创建时间等字段。自定义排序可以通过实现 QueueSortPlugin 扩展点注入。
1.5 调度器工作流程总结
一个完整的调度周期包含以下步骤:
- 入队:Pod 被创建或更新后,通过 Informer 机制加入调度队列。
- 出队:调度器主循环从 activeQ 取出优先级最高的 Pod。
- 过滤:执行 Filter 扩展点,筛选出满足条件的 Node 列表。
- 打分:执行 Score 扩展点,对候选 Node 进行评分。
- 选择:选择得分最高的 Node 作为绑定目标。
- 绑定:执行 Bind 扩展点,将 Pod 绑定到选定 Node。
- 后处理:执行 PostBind 扩展点,完成清理和指标上报。
延迟优化关注点:在多队列排序场景中,步骤 2(出队排序)和步骤 3-4(过滤/打分)是延迟瓶颈。队列排序的复杂度直接影响 Pod 等待时间,而过滤/打分插件的执行效率决定了调度周期的耗时。