2. Kubernetes 调度框架基础:Scheduler Framework 架构与扩展点概览

Kubernetes 调度器从传统的“硬编码”调度器演进为可插拔的 Scheduler Framework。该框架将调度流程拆解为多个独立的扩展点,允许开发者通过插件机制注入自定义逻辑。理解这一架构是开发网络拓扑感知调度插件的前提。

2.1 调度框架整体架构

Scheduler Framework 采用“调度周期 + 绑定周期”的双阶段模型。调度周期负责为 Pod 选择一个合适的 Node,绑定周期负责将决策持久化到 API Server。整个流程通过一个核心调度循环(Scheduling Cycle)串联多个扩展点。

核心设计原则: 每个扩展点只负责一个明确的调度子问题,插件可以注册到多个扩展点,但每个扩展点的职责单一。
Scheduler Framework 架构与扩展点流程 Scheduler Framework 架构与扩展点流程 调度周期(Scheduling Cycle) QueueSort PreFilter Filter PostFilter PreScore Score NormalizeScore Reserve Permit 绑定周期(Binding Cycle) PreBind Bind PostBind Permit 通过 Unreserve 说明: • 调度周期为每个 Pod 选择一个最优 Node;绑定周期将决策写入 etcd。 • 插件可注册到多个扩展点,框架按注册顺序依次调用。

2.2 核心扩展点详解

Scheduler Framework 定义了 11 个标准扩展点,按执行顺序分为调度周期和绑定周期两大类。下表列出每个扩展点的职责、调用时机和典型应用场景。

扩展点 所属周期 调用时机 核心职责 典型应用
QueueSort 调度周期 调度队列排序时 对调度队列中的 Pod 进行排序 优先级调度、QoS 排序
PreFilter 调度周期 Filter 之前 预处理 Pod 信息,校验前置条件 网络拓扑预检查、资源预留校验
Filter 调度周期 遍历所有 Node 时 过滤不满足条件的 Node 节点选择器、端口冲突、网络可达性过滤
PostFilter 调度周期 Filter 后无可用 Node 时 处理调度失败,尝试替代方案 抢占调度、备用节点推荐
PreScore 调度周期 Score 之前 为打分阶段准备数据 网络延迟预计算、拓扑数据预加载
Score 调度周期 对每个过滤后的 Node 打分 为 Node 分配分数(0-100) 网络带宽评分、节点亲和性评分
NormalizeScore 调度周期 所有 Score 完成后 归一化多个插件的打分结果 权重调整、分数标准化
Reserve 调度周期 选定 Node 后 预留资源,防止并发冲突 网络带宽预留、IP 地址预留
Permit 调度周期 Reserve 之后 批准或延迟调度决策 网络拓扑一致性校验、等待依赖 Pod
PreBind 绑定周期 Bind 之前 执行绑定前准备工作 网络策略注入、CNI 配置下发
Bind 绑定周期 最终绑定 将 Pod 绑定到 Node 默认绑定、自定义绑定逻辑
PostBind 绑定周期 Bind 成功后 执行绑定后清理或通知 网络拓扑状态更新、监控指标上报
Unreserve 异常处理 绑定失败或 Permit 拒绝时 释放之前 Reserve 的资源 网络资源回滚、IP 地址释放
开发提示: 网络拓扑感知插件最常注册的扩展点是 Filter(过滤不可达节点)和 Score(为低延迟节点打高分)。如果涉及资源预留,还需要实现 Reserve 和 Unreserve。

2.3 插件生命周期与注册机制

每个插件必须实现 framework.Plugin 接口(至少包含 Name() 方法),然后按需实现一个或多个扩展点接口。框架通过插件注册表管理所有插件,调度器启动时加载配置文件中指定的插件列表。

// 插件注册示例:网络拓扑感知插件
type TopologyAwarePlugin struct {
    handle framework.Handle
}

// 必须实现 Plugin 接口
func (pl *TopologyAwarePlugin) Name() string {
    return "TopologyAware"
}

// 注册到 Filter 扩展点
func (pl *TopologyAwarePlugin) Filter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeInfo *framework.NodeInfo) *framework.Status {
    // 检查节点是否满足网络拓扑约束
    if !pl.isNodeReachable(nodeInfo.Node(), pod) {
        return framework.NewStatus(framework.Unschedulable, "node not reachable from pod's network zone")
    }
    return framework.NewStatus(framework.Success, "")
}

// 注册到 Score 扩展点
func (pl *TopologyAwarePlugin) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) {
    latency := pl.getNetworkLatency(nodeName, pod)
    // 延迟越低,分数越高
    score := int64(max(0, 100 - latency/10))
    return score, framework.NewStatus(framework.Success, "")
}

2.4 扩展点调用顺序与数据传递

框架通过 framework.CycleState 对象在扩展点之间传递数据。插件可以在 PreFilter 阶段写入计算结果,在 Filter 或 Score 阶段读取使用。这种机制避免了重复计算,是网络拓扑感知插件常用的优化手段。

扩展点调用顺序与 CycleState 数据流 扩展点调用顺序与 CycleState 数据流 PreFilter Filter PreScore Score NormalizeScore framework.CycleState(跨扩展点共享数据) 存储:网络拓扑快照 | 预计算延迟矩阵 | 节点可达性缓存 关键设计模式: PreFilter 中计算网络拓扑数据 → 写入 CycleState → Filter/Score 从 CycleState 读取,避免重复查询 API Server。

2.5 扩展点选择策略

开发网络拓扑感知插件时,应根据功能需求选择合适的扩展点。下表总结了不同场景下的推荐扩展点组合。

功能需求 推荐扩展点 说明
过滤不可达节点 Filter 直接返回 Unschedulable 状态,阻止调度到不满足网络拓扑约束的节点
优先选择低延迟节点 Score 根据网络延迟或带宽打分,分数越高优先级越高
预计算拓扑数据 PreFilter + CycleState 在 PreFilter 中一次性获取拓扑信息,后续扩展点复用
预留网络资源 Reserve + Unreserve 在 Reserve 中分配带宽或 IP,Unreserve 中释放
绑定前注入网络配置 PreBind 在绑定前将网络策略或 CNI 配置写入 Node 或 Pod 注解
拓扑一致性校验 Permit 在 Permit 中检查所有依赖 Pod 是否已就绪,延迟调度直到条件满足
注意事项: 不要在一个扩展点中做过多工作。Filter 应保持轻量,只做快速过滤;复杂的计算逻辑放在 PreFilter 或 PreScore 中,并通过 CycleState 传递结果。避免在 Score 中发起网络请求,这会严重拖慢调度周期。

2.6 框架配置与插件加载

调度器通过 KubeSchedulerConfiguration 配置文件声明启用的插件及其执行顺序。网络拓扑感知插件需要在此配置中注册,并指定在哪些扩展点生效。

# 调度器配置示例(YAML)
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
  - schedulerName: topology-aware-scheduler
    plugins:
      filter:
        enabled:
          - name: "TopologyAware"   # 启用网络拓扑过滤
        disabled:
          - name: "NodeUnschedulable"  # 可选:禁用默认插件
      score:
        enabled:
          - name: "TopologyAware"   # 启用网络拓扑打分
          - name: "NodeResourcesFit"  # 保留资源打分
        disabled:
          - name: "NodeAffinity"    # 可选:禁用默认插件
    pluginConfig:
      - name: "TopologyAware"
        args:
          latencyThresholdMs: 50    # 自定义参数:延迟阈值
          topologyCacheTTLSeconds: 300

通过这种配置方式,网络拓扑感知插件可以无缝集成到现有调度器中,与其他插件协同工作,而无需修改调度器核心代码。