2. Kubernetes 调度框架:核心组件、调度周期与扩展点

Kubernetes 调度器(kube-scheduler)是控制平面中负责将 Pod 绑定到合适 Node 的核心组件。本章深入解析调度框架的内部结构,包括调度队列、调度周期与绑定周期,以及两种扩展机制:传统的 Extender 和现代的 Scheduling Framework。

2.1 调度框架核心组件

调度器内部由多个协作组件构成,每个组件承担明确的职责:

组件 职责 关键特性
调度队列 管理待调度的 Pod,按优先级和调度重试策略排序 三种子队列:activeQ、backoffQ、unschedulableQ
调度周期 为 Pod 选择一个最优 Node(Filter + Score) 可插拔扩展点,支持自定义过滤和打分逻辑
绑定周期 将 Pod 与选定 Node 的绑定关系写入 API Server 支持异步绑定、预留(Reserve)和预绑定(PreBind)
缓存(Cache) 维护集群 Node 和 Pod 的实时快照 增量更新,减少 API Server 请求压力
调度策略 定义 Filter 和 Score 的规则集合 可通过配置或扩展点动态调整
架构要点: 调度队列、调度周期、绑定周期三者构成调度器的主循环。缓存组件为调度周期提供一致性的集群视图,避免调度过程中因数据不一致导致错误决策。

2.2 调度队列:三级队列模型

调度队列采用三级队列模型,确保高优先级 Pod 优先调度,同时为调度失败的 Pod 提供退避重试机制:

  • activeQ(活跃队列):存放等待调度的 Pod,按优先级排序。调度器每次从 activeQ 头部取出一个 Pod 进行调度。
  • backoffQ(退避队列):存放调度失败但仍在退避期内的 Pod。退避时间指数增长(如 1s、2s、4s…),退避结束后移回 activeQ。
  • unschedulableQ(不可调度队列):存放因资源不足、节点选择器不匹配等原因无法调度的 Pod。当集群发生变动(如新增 Node、资源释放)时,重新评估并移回 activeQ。
调度队列流转规则:
  1. 新 Pod 进入 activeQ,按优先级排序。
  2. 调度失败 → 进入 backoffQ(退避)或 unschedulableQ(不可调度)。
  3. 退避到期或集群事件触发 → 移回 activeQ 重新调度。
  4. 调度成功 → 从队列中移除,进入绑定周期。
调度队列三级模型 activeQ 活跃队列(按优先级排序) backoffQ 退避队列(指数退避) unschedulableQ 不可调度队列 取出 失败(可重试) 失败(不可调度) 退避到期 集群事件触发 说明:调度器每次从 activeQ 头部取出一个 Pod 执行调度周期;失败后根据原因进入 backoffQ 或 unschedulableQ。

2.3 调度周期与绑定周期

调度器为每个 Pod 执行两个主要阶段:调度周期(Scheduling Cycle)和绑定周期(Binding Cycle)。调度周期是同步的,绑定周期是异步的,两者通过扩展点实现可插拔。

调度周期(Scheduling Cycle)

调度周期为 Pod 选择一个最优 Node,包含以下步骤:

  1. PreFilter:预处理 Pod 和集群信息,检查 Pod 是否满足基本条件(如资源请求是否合法)。
  2. Filter:对所有 Node 执行过滤,排除不满足条件的 Node(如资源不足、端口冲突、节点选择器不匹配)。
  3. PostFilter:当所有 Node 都被过滤掉时,执行补救逻辑(如抢占低优先级 Pod)。
  4. PreScore:在打分前进行数据准备或运行检查。
  5. Score:对通过过滤的 Node 进行打分(0-100),分数越高越优。
  6. NormalizeScore:对分数进行归一化处理,确保不同打分插件的结果可比较。
  7. Reserve:在缓存中预留选定 Node 的资源,防止其他 Pod 同时占用。

绑定周期(Binding Cycle)

绑定周期将 Pod 与选定 Node 的绑定关系持久化到 API Server:

  1. PreBind:执行绑定前的准备工作(如创建存储卷、配置网络)。
  2. Bind:向 API Server 发送绑定请求(POST /api/v1/namespaces/{ns}/pods/{name}/binding)。
  3. PostBind:绑定成功后执行清理或通知操作。
关键区别: 调度周期是同步的,调度器必须等待所有 Filter 和 Score 插件执行完毕;绑定周期是异步的,调度器可以同时处理多个 Pod 的绑定请求,提高吞吐量。
调度周期与绑定周期流程 调度周期(同步) PreFilter Filter PostFilter(可选) Score + NormalizeScore Reserve 绑定周期(异步) PreBind Bind PostBind 选定 Node 说明:调度周期为同步执行,绑定周期为异步执行;Reserve 是调度周期与绑定周期的衔接点。

2.4 扩展点:Extender 与 Scheduling Framework

Kubernetes 提供两种扩展调度器行为的方式:传统的 Extender 和现代的 Scheduling Framework。两者在架构、灵活性和性能上存在显著差异。

特性 Extender Scheduling Framework
架构 外部 HTTP 服务,通过 Webhook 调用 内部插件,编译进调度器或通过动态加载
扩展点 仅支持 Filter、Prioritize、Bind 支持 PreFilter、Filter、PostFilter、PreScore、Score、NormalizeScore、Reserve、PreBind、Bind、PostBind 等
性能 网络调用开销大,不适合高频场景 本地调用,延迟低,吞吐量高
灵活性 只能扩展有限逻辑,无法干预调度队列 可自定义整个调度流程,包括队列排序、抢占逻辑
维护性 独立部署,版本兼容性需自行管理 与调度器同进程,版本由 Kubernetes 管理
推荐场景 遗留系统、快速原型、非核心调度逻辑 生产环境、高性能调度、复杂策略

Extender 的工作方式

Extender 通过 kube-scheduler 配置文件中的 extenders 字段注册。调度器在 Filter、Prioritize、Bind 阶段向 Extender 发送 HTTP 请求,Extender 返回结果。典型配置示例:

apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
extenders:
  - urlPrefix: "http://my-extender:8888/"
    filterVerb: "filter"
    prioritizeVerb: "prioritize"
    bindVerb: "bind"
    weight: 1
    nodeCacheCapable: false
    managedResources:
      - name: "example.com/resource"
        ignoredByScheduler: false

Scheduling Framework 的工作方式

Scheduling Framework 允许开发者编写 Go 插件,实现特定扩展点接口。插件通过 profile 配置注册,支持多 profile 实现不同调度策略。核心接口示例:

// FilterPlugin 接口定义
type FilterPlugin interface {
    Name() string
    Filter(ctx context.Context, state *CycleState, pod *v1.Pod, nodeInfo *NodeInfo) *Status
}

// ScorePlugin 接口定义
type ScorePlugin interface {
    Name() string
    Score(ctx context.Context, state *CycleState, pod *v1.Pod, nodeName string) (int64, *Status)
    ScoreExtensions() ScoreExtensions
}
实践建议: 对于网络拓扑感知调度,推荐使用 Scheduling Framework 实现自定义 Filter 和 Score 插件。例如,在 Filter 阶段排除跨拓扑域延迟过高的 Node,在 Score 阶段优先选择与 Pod 亲和性匹配的 Node。Extender 仅适合作为临时方案或与第三方系统集成。

2.5 调度框架扩展点全景图

下表汇总了 Scheduling Framework 的所有扩展点及其在调度周期/绑定周期中的位置:

扩展点 所属阶段 执行时机 典型用途
PreFilter 调度周期 Filter 之前 检查 Pod 合法性、预处理数据
Filter 调度周期 过滤 Node 资源检查、端口冲突、节点选择器
PostFilter 调度周期 Filter 之后(无可用 Node) 抢占、重新评估
PreScore 调度周期 Score 之前 数据准备、运行检查
Score 调度周期 打分 资源均衡、亲和性、拓扑感知
NormalizeScore 调度周期 Score 之后 分数归一化
Reserve 调度周期 选定 Node 后 预留资源,防止并发冲突
PreBind 绑定周期 Bind 之前 创建存储卷、配置网络
Bind 绑定周期 执行绑定 写入 API Server
PostBind 绑定周期 Bind 之后 清理、通知
扩展点选择策略: 网络拓扑感知调度主要使用 Filter(排除高延迟 Node)和 Score(优先选择拓扑域内 Node)。如果需要预留网络资源,可在 Reserve 扩展点实现。避免在 PreFilter 或 PostFilter 中执行复杂计算,以免影响调度性能。