4. 调度器扩展机制:调度器扩展点(Scheduling Framework)与插件化架构

Kubernetes 调度器从 v1.19 开始全面转向 Scheduling Framework,将调度流程拆解为多个明确定义的扩展点(Extension Points),并通过插件(Plugin)机制实现可插拔的调度逻辑。这种架构使得用户无需修改调度器核心代码,即可注入自定义调度策略、资源评分规则甚至抢占逻辑。

4.1 调度器扩展点总览

Scheduling Framework 将一次 Pod 调度决策划分为两个阶段:Scheduling Cycle(调度周期)和 Binding Cycle(绑定周期)。每个周期内包含若干扩展点,插件可以注册到这些扩展点上执行特定逻辑。

阶段 扩展点 执行时机 典型插件用途
Scheduling Cycle QueueSort 对调度队列中的 Pod 排序 自定义 Pod 优先级排序策略
PreFilter 过滤前预处理或校验 Pod 信息 检查 Pod 是否满足资源预留条件
Filter 过滤不满足条件的节点 节点污点容忍、端口冲突检查
PostFilter 过滤后无可用节点时的处理 抢占(Preemption)逻辑
PreScore / Score / NormalizeScore 对通过过滤的节点进行评分 资源均衡、亲和性打分
Binding Cycle Reserve 在绑定前预留节点资源 确保资源不被其他 Pod 抢占
Permit 批准或延迟绑定 外部准入控制、多调度器协调
PreBind / Bind / PostBind 执行绑定及绑定后处理 自定义绑定逻辑、绑定后清理
关键理解: Filter 扩展点决定节点“能不能用”,Score 扩展点决定节点“好不好用”。OPA Gatekeeper 策略通常作用于 Filter 扩展点,而调度器参数(如资源权重)作用于 Score 扩展点。

4.2 插件化架构与注册机制

调度器插件以 Go 接口方式实现,通过 scheduler-config.yaml 配置文件注册到对应扩展点。每个插件可以同时实现多个扩展点接口。

# scheduler-config.yaml 示例
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
  - schedulerName: custom-scheduler
    plugins:
      filter:
        enabled:
          - name: "NodeResourcesFit"
          - name: "MyCustomFilter"   # 自定义过滤插件
        disabled:
          - name: "NodeUnschedulable"
      score:
        enabled:
          - name: "NodeResourcesBalancedAllocation"
            weight: 2
          - name: "MyCustomScorer"
            weight: 5
    pluginConfig:
      - name: "MyCustomFilter"
        args:
          forbiddenLabels: ["spot-instance"]
实践提示: 调度器配置支持多 Profile,每个 Profile 可以绑定不同的插件组合和权重。结合 OPA Gatekeeper 的命名空间标签,可以实现“不同租户使用不同调度器 Profile”的隔离策略。

4.3 调度框架核心流程 SVG 图

下图展示了 Scheduling Framework 中主要扩展点的执行顺序,以及插件如何挂载到这些扩展点上:

Kubernetes Scheduling Framework 扩展点与插件挂载流程 Scheduling Framework 扩展点与插件挂载流程 Scheduling Cycle Binding Cycle QueueSort PreFilter Filter PostFilter PreScore / Score Reserve Permit PreBind / Bind PostBind 调度结果传递 插件挂载示例 NodeResourcesFit → Filter + Score MyCustomFilter → Filter(OPA Gatekeeper 集成点)

4.4 插件生命周期与状态管理

调度器插件在运行时遵循明确的生命周期管理,确保状态一致性和并发安全:

  • 注册阶段: 调度器启动时读取配置,实例化所有启用的插件,并注册到对应扩展点。
  • 调度阶段: 每个 Pod 调度周期内,插件按扩展点顺序依次执行。Filter 插件返回 Success、Unschedulable 或 Error;Score 插件返回 0-100 的整数分数。
  • 状态清理: 绑定完成后,调度器调用 PostBind 插件清理临时状态。如果绑定失败,Unreserve 插件负责释放预留资源。
避坑指南: 自定义插件必须实现 Name() 方法返回唯一名称,且不能与内置插件重名。插件状态(如缓存)需要自行管理并发锁,调度器不提供状态隔离。

4.5 调度器参数与插件协同配置

调度器参数(如 percentageOfNodesToScore、bindTimeoutSeconds)与插件配置共同决定调度行为。下表列出关键协同参数:

参数名称 默认值 影响范围 与插件协同说明
percentageOfNodesToScore 50% Filter / Score 控制参与评分的节点比例,影响 Filter 插件的执行范围
bindTimeoutSeconds 100 Bind 自定义 Bind 插件超时时间,避免长时间阻塞
podInitialBackoffSeconds 1 QueueSort Pod 调度失败后的重试退避,影响 QueueSort 排序
profiles[].plugins.score[].weight 1 Score 每个 Score 插件的权重,决定最终评分占比

4.6 插件化架构与 OPA Gatekeeper 集成点

OPA Gatekeeper 策略可以通过以下两种方式与调度器插件协同:

  1. Filter 扩展点集成: 在自定义 Filter 插件中调用 OPA 的 REST API,将 Pod 和节点信息作为输入,根据 Gatekeeper 策略返回 Success 或 Unschedulable。
  2. PreScore 扩展点集成: 在评分前通过 OPA 策略调整节点候选集,例如剔除不符合安全策略的节点。
架构优势: 调度器插件化架构使得 OPA 策略可以“无侵入”地嵌入调度流程,无需修改调度器核心代码。策略变更只需更新插件配置或 OPA 规则,调度器热加载即可生效。

4.7 插件化架构分层 SVG 图

下图展示了调度器插件化架构的分层关系,从核心调度器到扩展点、插件层,再到外部策略引擎(如 OPA):

调度器插件化架构分层图 调度器插件化架构分层 核心调度器(Scheduler Core) 扩展点层(QueueSort / Filter / Score / Bind ...) 插件层(Plugin Layer) NodeResourcesFit | InterPodAffinity | MyCustomFilter | MyCustomScorer 外部策略引擎(OPA Gatekeeper / 自定义 Webhook)
实战要点: 在 Filter 扩展点集成 OPA 时,建议将 OPA 查询结果缓存到插件本地,避免每个 Pod 调度都发起 HTTP 调用。缓存 TTL 可根据策略变更频率设置,通常 5-10 秒即可。