2. 调度器核心组件解析:kube-scheduler 二进制、调度框架 (Scheduling Framework)、调度队列

Kubernetes 调度器的核心职责是将待调度的 Pod 绑定到最合适的 Node 上。本章深入解析调度器的三大核心组件:kube-scheduler 二进制(进程入口与配置)、调度框架 (Scheduling Framework)(插件化调度流水线)以及调度队列(Pod 的排队与排序机制)。理解这三者是掌握调度器工作原理的基础。

2.1 kube-scheduler 二进制:进程入口与配置加载

kube-scheduler 是一个独立的 Go 二进制文件,作为 Kubernetes 控制平面的核心组件运行。它通过命令行参数、配置文件或 ConfigMap 来定义调度行为。

2.1.1 启动流程与配置方式

  • 命令行参数:传统方式,通过 --kubeconfig、--leader-elect、--config 等参数启动。
  • 配置文件 (KubeSchedulerConfiguration):推荐方式,通过 --config 指定 YAML/JSON 文件,支持更丰富的调度器配置,如插件启用、打分权重、扩展器配置等。
  • 多调度器支持:通过 --scheduler-name 参数可运行多个调度器实例,配合 Pod 的 schedulerName 字段实现自定义调度。
关键配置示例: 使用 KubeSchedulerConfiguration 配置文件启用自定义插件。
# scheduler-config.yaml
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
clientConnection:
  kubeconfig: "/etc/kubernetes/scheduler.conf"
profiles:
  - schedulerName: default-scheduler
    plugins:
      score:
        enabled:
          - name: MyCustomScorer  # 启用自定义打分插件
      filter:
        disabled:
          - name: NodeResourcesFit # 禁用内置资源过滤插件
    pluginConfig:
      - name: MyCustomScorer
        args:
          weight: 5

2.1.2 高可用与领导者选举

在生产环境中,通常部署多个 kube-scheduler 副本以实现高可用。通过 --leader-elect=true(默认开启)和 --leader-elect-resource-name 参数,多个副本通过 Endpoint 或 Lease 对象进行领导者选举,同一时刻只有一个活跃调度器执行调度决策。

参数 默认值 说明
--leader-elect true 是否启用领导者选举
--leader-elect-lease-duration 15s 租约有效期
--leader-elect-renew-deadline 10s 续租截止时间
--leader-elect-retry-period 2s 续租重试间隔

2.2 调度框架 (Scheduling Framework):插件化调度流水线

调度框架是 Kubernetes 1.19+ 引入的插件化架构,它将调度过程拆解为多个可扩展的扩展点 (Extension Points)。开发者可以编写自定义插件,注入到这些扩展点中,而无需修改调度器核心代码。

2.2.1 核心扩展点与执行顺序

调度框架定义了一套严格的扩展点执行顺序,每个扩展点负责调度周期中的一个特定阶段。

  1. QueueSort:对调度队列中的 Pod 进行排序,决定下一个调度的 Pod。
  2. PreFilter:预处理 Pod 信息,进行前置检查或数据准备。
  3. Filter:过滤节点,排除不满足 Pod 调度条件的节点(如资源不足、端口冲突、污点不匹配)。
  4. PostFilter:当 Filter 阶段无可用节点时执行,通常用于抢占式调度。
  5. PreScore:在打分前进行数据准备或运行前置任务。
  6. Score:对通过过滤的节点进行打分(0-100),分数越高越优先。
  7. NormalizeScore:对打分结果进行归一化处理,确保最终分数在合理范围内。
  8. Reserve:在绑定前预留节点资源,防止并发调度冲突。
  9. Permit:允许或拒绝调度决策,支持等待/超时机制。
  10. PreBind:在绑定前执行预处理,如挂载网络存储。
  11. Bind:将 Pod 绑定到选定节点,更新 API Server 中的 Pod 与 Node 关联。
  12. PostBind:绑定成功后执行清理或通知操作。
实践建议: 自定义插件通常只需实现 Filter 和 Score 扩展点即可满足大部分需求。复杂的调度逻辑(如资源预留、准入控制)可考虑 Reserve 和 Permit 扩展点。
调度框架扩展点流水线 调度框架扩展点执行流水线 QueueSort PreFilter Filter PostFilter PreScore Score Normalize Reserve Permit PreBind Bind PostBind 调度周期 (Scheduling Cycle) 绑定周期 (Binding Cycle)

2.3 调度队列:Pod 的排队与排序机制

调度队列负责管理待调度的 Pod。当一个新的 Pod 被创建后,它会被加入调度队列,等待调度器处理。调度队列的设计直接影响调度的公平性、优先级和效率。

2.3.1 队列结构与类型

调度器内部维护了三种队列,用于管理不同状态的 Pod:

队列名称 数据结构 存储内容 说明
ActiveQ 优先队列 (Heap) 等待调度的 Pod 按优先级排序,优先级高的 Pod 先被调度
BackoffQ 优先队列 (Heap) 调度失败的 Pod 失败后进入退避队列,等待重试,退避时间指数增长
UnschedulableQ Map + 集合 无法调度的 Pod 因资源不足、污点不匹配等原因无法调度,等待集群资源变化后重新入队

2.3.2 队列操作流程与 Pod 流转

Pod 在调度队列中的流转遵循以下核心逻辑:

  1. 入队 (Enqueue):新创建的 Pod 或经过重试的 Pod 被加入 ActiveQ。
  2. 出队 (Dequeue):调度器从 ActiveQ 中取出优先级最高的 Pod 进行调度。
  3. 调度失败:如果调度失败(如 Filter 阶段无可用节点),Pod 被移入 BackoffQ 或 UnschedulableQ。
  4. 退避重试:BackoffQ 中的 Pod 在退避时间结束后重新进入 ActiveQ。
  5. 重新入队:当集群资源发生变化(如新节点加入、已有节点资源释放),UnschedulableQ 中的 Pod 会被重新评估并移入 ActiveQ。
性能注意: 如果 UnschedulableQ 中的 Pod 数量持续增长,可能意味着集群资源严重不足或调度策略配置不当。建议监控 scheduler_queue_incoming_pods_total 和 scheduler_pod_scheduling_duration_seconds 指标。
调度队列 Pod 流转图 调度队列 Pod 流转与状态转换 新 Pod ActiveQ (优先队列) BackoffQ (退避队列) UnschedulableQ (不可调度队列) 调度器 入队 出队调度 调度失败 (可重试) 无法调度 退避结束 集群资源变化

2.4 核心组件协同工作流程

结合上述三个核心组件,一个完整的调度周期可以概括为以下步骤:

  1. Pod 入队:API Server 创建 Pod 后,调度器通过 Informer 机制感知到新 Pod,将其加入 ActiveQ。
  2. Pod 出队:调度器从 ActiveQ 中取出优先级最高的 Pod,进入调度框架的 调度周期。
  3. 过滤与打分:调度框架依次执行 Filter、Score 等扩展点,选出最优节点。
  4. 绑定:调度框架进入 绑定周期,执行 Reserve、Bind 等扩展点,将 Pod 绑定到节点。
  5. 结果处理:绑定成功则 Pod 进入运行状态;失败则根据失败原因将 Pod 移入 BackoffQ 或 UnschedulableQ。
核心要点: kube-scheduler 二进制是进程载体,调度框架是插件化调度逻辑的执行引擎,调度队列是 Pod 的排队与状态管理中枢。三者协同工作,构成了 Kubernetes 调度器的完整调度能力。