2. Kubernetes 调度基础:调度器核心组件、调度队列与调度周期

Kubernetes 调度器(kube-scheduler)是控制平面中负责将 Pod 绑定到合适 Node 的核心组件。理解其内部架构、调度队列机制以及两阶段调度周期,是进行调度优化与故障排查的前提。本章将深入剖析调度器的三大核心模块:Scheduler Framework、调度队列与调度周期。

2.1 调度器核心组件与 Scheduler Framework

Kubernetes 从 v1.19 开始将调度器重构为可插拔的 Scheduler Framework 架构。该框架定义了一组扩展点(Extension Points),允许用户通过编写插件(Plugin)来定制调度行为,而无需修改核心代码。

Scheduler Framework 核心架构与扩展点 调度队列 调度周期(Scheduling Cycle) 绑定周期(Binding Cycle) PreFilter Filter PostFilter PreScore Score NormalizeScore Reserve Permit PreBind Bind PostBind 说明:Scheduler Framework 将调度过程拆分为多个扩展点,每个扩展点可注册多个插件。插件按顺序执行,任一插件失败则调度周期终止。

2.2 调度队列(Scheduling Queue)

调度队列是调度器的输入缓冲区,负责管理等待调度的 Pod。Kubernetes 使用优先级队列(Priority Queue)实现,Pod 按优先级排序,高优先级 Pod 优先出队。队列内部维护三个子队列:

子队列 存储内容 出队策略 典型场景
ActiveQ 等待首次调度的 Pod 按优先级排序,高优先级先出队 新创建的 Pod
BackoffQ 调度失败后进入退避的 Pod 退避时间到期后移回 ActiveQ 资源不足、节点污点不匹配
UnschedulableQ 因不可调度原因(如资源不足)失败的 Pod 集群拓扑变化(如新节点加入)时重新评估 持久性资源不足、节点选择器不匹配
排查提示:当 Pod 长时间处于 Pending 状态时,可通过 kubectl describe pod <pod-name> 查看 Events 字段。若事件显示 "0/3 nodes are available",说明 Pod 进入了 UnschedulableQ。此时应检查节点资源水位或污点配置。

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

调度器将每个 Pod 的调度过程拆分为两个独立的周期:调度周期和绑定周期。调度周期是串行的,绑定周期是并行的,这种设计显著提升了调度吞吐量。

2.3.1 调度周期(Scheduling Cycle)

调度周期是串行执行的,同一时间只有一个 Pod 处于调度周期中。它包含以下阶段:

  1. PreFilter:预处理 Pod 信息,检查 Pod 是否满足基本约束(如节点选择器、亲和性)。
  2. Filter:过滤节点,找出所有满足 Pod 资源请求和约束的候选节点。
  3. PostFilter:当 Filter 阶段没有找到可用节点时,执行干预逻辑(如抢占式调度)。
  4. PreScore:为 Score 阶段准备数据,如计算节点亲和性得分。
  5. Score:对候选节点进行打分,分数越高表示节点越适合运行该 Pod。
  6. NormalizeScore:对分数进行归一化处理,确保不同插件的分数在同一量级。
  7. Reserve:在调度器缓存中预留资源,防止并发调度导致资源冲突。
  8. Permit:允许或拒绝调度结果,支持等待/超时机制(如用于多调度器协调)。

2.3.2 绑定周期(Binding Cycle)

绑定周期是并行执行的,多个 Pod 可以同时处于绑定周期中。它包含以下阶段:

  • PreBind:执行绑定前的准备工作,如动态创建存储卷(PV)。
  • Bind:向 API Server 发送绑定请求,将 Pod 与 Node 关联。
  • PostBind:绑定完成后的清理或通知逻辑。
性能关键点:调度周期是串行的,因此 Filter 和 Score 阶段的插件执行效率直接影响调度吞吐量。在生产环境中,建议将耗时较长的插件(如外部资源检查)放在 PreFilter 或 PreScore 阶段,避免阻塞整个调度周期。

2.4 调度器工作流程总结

以下表格总结了调度器从 Pod 入队到绑定完成的完整流程:

步骤 组件/阶段 操作 输出
1 调度队列 Pod 进入 ActiveQ,按优先级排序 高优先级 Pod 出队
2 调度周期 执行 Filter → Score → Reserve → Permit 选定目标 Node
3 绑定周期 执行 PreBind → Bind → PostBind Pod 与 Node 绑定
4 调度队列 Pod 从队列中移除 调度完成
常见误区:调度周期中的 Reserve 阶段仅在调度器缓存中预留资源,并未实际写入 etcd。如果绑定周期失败,Reserve 阶段预留的资源会被释放。因此,不要将 Reserve 视为最终资源锁定。

2.5 调度器插件配置示例

以下是一个自定义调度器配置的 YAML 示例,展示了如何通过 Scheduler Framework 注册插件:

apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
  - schedulerName: custom-scheduler
    plugins:
      filter:
        enabled:
          - name: NodeResourcesFit
          - name: NodeName
        disabled:
          - name: NodeUnschedulable
      score:
        enabled:
          - name: NodeResourcesBalancedAllocation
            weight: 2
          - name: ImageLocality
            weight: 1
    pluginConfig:
      - name: NodeResourcesBalancedAllocation
        args:
          resources:
            - name: cpu
              weight: 1
            - name: memory
              weight: 1

该配置定义了一个名为 custom-scheduler 的调度器,启用了自定义的 Filter 和 Score 插件,并禁用了默认的 NodeUnschedulable 过滤器。