4、默认调度器(kube-scheduler)架构:核心组件、工作流与配置方式

Kubernetes 默认调度器(kube-scheduler)是控制平面中负责将 Pod 绑定到合适 Node 的核心组件。它并非一个黑盒,而是由多个职责清晰的模块构成,遵循“过滤 → 打分 → 绑定”的线性工作流。理解其内部架构是进行调度器扩展、性能调优以及实现拓扑感知调度的前提。

4.1 核心组件架构

kube-scheduler 以事件驱动的方式运行,内部主要分为调度队列、调度框架(Scheduling Framework)和缓存三个逻辑层。下图展示了其核心组件及数据流关系:

kube-scheduler 核心组件架构图 kube-scheduler 核心组件架构 调度队列 (SchedulingQueue) 调度框架 (Scheduling Framework) 调度器缓存 (SchedulerCache) Pop 读/写 调度框架内部扩展点 PreFilter Filter Score Reserve Permit 缓存内容 Node 信息 Pod 状态 资源配额 绑定 API Server 绑定请求 调度器通过 Informer 机制 监听 API Server 变化更新缓存
核心组件职责速览:
  • 调度队列(SchedulingQueue): 负责接收待调度的 Pod,支持优先级排序、重试和背压机制。默认实现为 PriorityQueue。
  • 调度框架(Scheduling Framework): 定义了一组扩展点(Extension Points),调度器通过插件(Plugin)在这些扩展点中执行具体的调度逻辑。
  • 调度器缓存(SchedulerCache): 维护集群中 Node 和 Pod 的实时快照,避免每次调度都从 API Server 全量拉取,是调度性能的关键。

4.2 调度工作流:从入队到绑定

一个 Pod 从创建到被调度到 Node 上,经历以下标准工作流。该流程由调度框架的扩展点驱动,每个扩展点可以注册多个插件。

阶段 扩展点 核心行为 典型插件示例
1. 入队 — Pod 进入调度队列,按优先级排序。Unschedulable 的 Pod 会被放入重试队列。 PrioritySort
2. 预过滤 PreFilter 预处理 Pod 信息,检查 Pod 是否满足基本条件(如资源请求是否合法)。 NodeResourcesFit
3. 过滤 Filter 遍历所有 Node,剔除不满足 Pod 调度约束的节点(如端口冲突、污点容忍、资源不足)。 NodePorts、TaintToleration
4. 预打分 PreScore 在打分前进行信息准备,如计算跨拓扑分布的统计信息。 —
5. 打分 Score 对过滤后的 Node 进行评分(0-100),分数越高越优先。支持多维度加权。 NodeResourcesBalancedAllocation
6. 正常排序 NormalizeScore 对分数进行归一化处理,确保不同打分插件的分数在同一量级。 —
7. 预留 Reserve 在缓存中为 Pod 预留资源,防止并发调度时的资源竞争。 VolumeBinding
8. 许可 Permit 允许或拒绝调度结果。支持等待(Wait)和拒绝(Deny)语义,常用于实现 Gang Scheduling。 —
9. 绑定 PreBind / Bind 执行绑定前的准备工作(如挂载卷),然后向 API Server 发送绑定请求。 VolumeBinding
调度性能关键点: 过滤阶段(Filter)是性能瓶颈的高发区。默认调度器会并行执行所有 Filter 插件,但每个 Node 的过滤是串行的。当集群规模超过 5000 Node 时,过滤阶段的耗时占比会显著上升,此时需要引入“调度器扩展”或“拓扑感知剪枝”来减少候选 Node 数量。

4.3 配置方式:Scheduler Configuration API

kube-scheduler 的配置已经从命令行参数迁移到基于 YAML 的配置文件(Scheduler Configuration API,v1beta3 / v1)。配置的核心是定义调度器使用的插件列表及其在每个扩展点上的启用/禁用状态,以及打分插件的权重。

以下是一个典型的调度器配置文件片段,展示了如何自定义插件链:

apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
  - schedulerName: default-scheduler
    plugins:
      # 在 Filter 阶段启用自定义插件,并禁用默认的 NodeUnschedulable 插件
      filter:
        enabled:
          - name: "MyCustomFilter"
        disabled:
          - name: "NodeUnschedulable"
      # 在 Score 阶段启用自定义打分插件,权重为 5
      score:
        enabled:
          - name: "MyCustomScorer"
            weight: 5
    # 配置打分插件的权重(仅对 Score 插件生效)
    pluginConfig:
      - name: "NodeResourcesFit"
        args:
          scoringStrategy:
            type: "LeastAllocated"  # 使用最少资源分配策略
配置变更风险提示: 修改调度器配置(如禁用默认插件或调整权重)会直接影响 Pod 的调度行为。建议在测试环境中充分验证,并使用 kube-scheduler --config /path/to/config.yaml 启动调度器。生产环境中推荐使用多个调度器 Profile 来隔离不同工作负载的调度策略。

4.4 调度器扩展机制:从 In-tree 到 Out-of-tree

Kubernetes 调度器支持两种扩展方式,以适应不同的定制需求:

  • In-tree 插件: 将插件代码直接编译进 kube-scheduler 二进制文件。优点是性能高、部署简单;缺点是扩展性差,需要修改调度器源码并重新编译。
  • Out-of-tree 插件(Scheduler Extender / Framework): 通过 HTTP 或 gRPC 协议将调度决策委托给外部进程。Scheduler Extender 是旧版机制,仅支持 Filter 和 Score 扩展点;Scheduler Framework 是新一代机制,支持所有扩展点,且性能更优。

对于容器网络拓扑感知调度,推荐使用 Scheduler Framework 的 Out-of-tree 方式,在 Filter 和 Score 扩展点中注入拓扑距离计算逻辑,而无需修改调度器核心代码。

In-tree 与 Out-of-tree 扩展对比 In-tree 与 Out-of-tree 扩展对比 In-tree 插件 kube-scheduler 二进制 插件代码编译进二进制 优点:性能高,部署简单 缺点:扩展性差,需重新编译 Out-of-tree 插件 kube-scheduler 二进制 (无修改) 外部插件进程 (gRPC/HTTP) 优点:扩展灵活,独立部署 缺点:网络延迟,运维复杂
选择建议: 对于容器网络拓扑感知调度,由于需要频繁查询网络拓扑距离(可能涉及外部系统),推荐使用 Out-of-tree Scheduler Framework 插件。这样可以将拓扑感知逻辑与核心调度器解耦,便于独立迭代和灰度发布。