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 核心扩展点与执行顺序
调度框架定义了一套严格的扩展点执行顺序,每个扩展点负责调度周期中的一个特定阶段。
- QueueSort:对调度队列中的 Pod 进行排序,决定下一个调度的 Pod。
- PreFilter:预处理 Pod 信息,进行前置检查或数据准备。
- Filter:过滤节点,排除不满足 Pod 调度条件的节点(如资源不足、端口冲突、污点不匹配)。
- PostFilter:当 Filter 阶段无可用节点时执行,通常用于抢占式调度。
- PreScore:在打分前进行数据准备或运行前置任务。
- Score:对通过过滤的节点进行打分(0-100),分数越高越优先。
- NormalizeScore:对打分结果进行归一化处理,确保最终分数在合理范围内。
- Reserve:在绑定前预留节点资源,防止并发调度冲突。
- Permit:允许或拒绝调度决策,支持等待/超时机制。
- PreBind:在绑定前执行预处理,如挂载网络存储。
- Bind:将 Pod 绑定到选定节点,更新 API Server 中的 Pod 与 Node 关联。
- PostBind:绑定成功后执行清理或通知操作。
实践建议: 自定义插件通常只需实现
Filter 和 Score 扩展点即可满足大部分需求。复杂的调度逻辑(如资源预留、准入控制)可考虑 Reserve 和 Permit 扩展点。
2.3 调度队列:Pod 的排队与排序机制
调度队列负责管理待调度的 Pod。当一个新的 Pod 被创建后,它会被加入调度队列,等待调度器处理。调度队列的设计直接影响调度的公平性、优先级和效率。
2.3.1 队列结构与类型
调度器内部维护了三种队列,用于管理不同状态的 Pod:
| 队列名称 | 数据结构 | 存储内容 | 说明 |
|---|---|---|---|
| ActiveQ | 优先队列 (Heap) | 等待调度的 Pod | 按优先级排序,优先级高的 Pod 先被调度 |
| BackoffQ | 优先队列 (Heap) | 调度失败的 Pod | 失败后进入退避队列,等待重试,退避时间指数增长 |
| UnschedulableQ | Map + 集合 | 无法调度的 Pod | 因资源不足、污点不匹配等原因无法调度,等待集群资源变化后重新入队 |
2.3.2 队列操作流程与 Pod 流转
Pod 在调度队列中的流转遵循以下核心逻辑:
- 入队 (Enqueue):新创建的 Pod 或经过重试的 Pod 被加入 ActiveQ。
- 出队 (Dequeue):调度器从 ActiveQ 中取出优先级最高的 Pod 进行调度。
- 调度失败:如果调度失败(如 Filter 阶段无可用节点),Pod 被移入 BackoffQ 或 UnschedulableQ。
- 退避重试:BackoffQ 中的 Pod 在退避时间结束后重新进入 ActiveQ。
- 重新入队:当集群资源发生变化(如新节点加入、已有节点资源释放),UnschedulableQ 中的 Pod 会被重新评估并移入 ActiveQ。
性能注意: 如果 UnschedulableQ 中的 Pod 数量持续增长,可能意味着集群资源严重不足或调度策略配置不当。建议监控
scheduler_queue_incoming_pods_total 和 scheduler_pod_scheduling_duration_seconds 指标。
2.4 核心组件协同工作流程
结合上述三个核心组件,一个完整的调度周期可以概括为以下步骤:
- Pod 入队:API Server 创建 Pod 后,调度器通过 Informer 机制感知到新 Pod,将其加入 ActiveQ。
- Pod 出队:调度器从 ActiveQ 中取出优先级最高的 Pod,进入调度框架的 调度周期。
- 过滤与打分:调度框架依次执行 Filter、Score 等扩展点,选出最优节点。
- 绑定:调度框架进入 绑定周期,执行 Reserve、Bind 等扩展点,将 Pod 绑定到节点。
- 结果处理:绑定成功则 Pod 进入运行状态;失败则根据失败原因将 Pod 移入 BackoffQ 或 UnschedulableQ。
核心要点: kube-scheduler 二进制是进程载体,调度框架是插件化调度逻辑的执行引擎,调度队列是 Pod 的排队与状态管理中枢。三者协同工作,构成了 Kubernetes 调度器的完整调度能力。