目录
Please enable Javascript to view the contents

K8s 调度扩展——Scheduler Framework 详解

 ·  ☕ 3 分钟

重要

Kubernetes 默认调度器 kube-scheduler 按 CPU/内存请求 + 节点亲和性做 Pod 放置。当需要 GPU 拓扑感知、成本优先、实时性优先等自定义调度策略时,通过 Scheduler Framework 插入自定义逻辑。

Scheduler Framework 将调度拆成多个扩展点,每个扩展点可以注册多个插件,插件之间按权重协作。

环境说明

  • Kubernetes v1.26+

1.简介

Kube-scheduler 的每一个调度决策可以拆成两阶段:

阶段操作关键扩展点
调度周期(Scheduling Cycle)为 Pod 选定一个 NodeQueueSort → Filter → Score → Reserve
绑定周期(Binding Cycle)将 Pod 绑定到选定的 NodePermit → Bind → PostBind

调度周期是同步串行的(一次只处理一个 Pod),绑定周期是异步并行的。

2.说明

2.1 架构总览

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Pod 进入调度队列
QueueSort       →  决定 Pod 出队顺序(如按优先级排列)
PreFilter       →  预处理 Pod Spec,计算调度周期内不变的信息
Filter          →  过滤不满足条件的 Node(遍历所有 Node,每次调用一个插件)
PostFilter      →  Filter 全部失败后的补救(如抢占)
PreScore        →  Score 阶段的前置处理
Score           →  对每个通过 Filter 的 Node 打分
NormalizeScore  →  分数归一化(0~100)
Reserve         →  资源预占(避免并发调度冲突)
Permit          →  放行 / 阻塞 / 拒绝
PreBind         →  绑定前的准备(如挂载 Volume)
Bind            →  执行 bind 操作(写 Pod.Spec.NodeName)
PostBind        →  绑定后的清理或通知

每个扩展点可以注册多个插件,调度器在每个阶段依次调用,Score 阶段各插件分数加权求和。

2.2 关键扩展点

扩展点输入输出用途
QueueSort待调度 Pods 列表排序后的队列优先级调度
FilterPod + Node 信息Success or Unschedulable硬件筛选(GPU 型号)、拓扑约束
ScorePod + Node 信息0~100 分成本优选、装箱率优选
ReservePod + 选定 NodeReserve / UnreserveGPU 拓扑感知预留
PermitPod + 选定 NodeApprove / Deny / Wait等待外部条件(如 license)
BindPod + 选定 Node绑定结果自定义绑定逻辑

2.3 插件注册

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package myplugin

import (
    "k8s.io/kubernetes/pkg/scheduler/framework"
)

type MyScorePlugin struct{}

func (p *MyScorePlugin) Name() string {
    return "MyScorePlugin"
}

func (p *MyScorePlugin) Score(ctx context.Context, state *framework.CycleState,
    pod *v1.Pod, nodeName string) (int64, *framework.Status) {
    // 优先选择标签中有 "cost=low" 的节点
    node := state.NodeInfo.Node()
    if node.Labels["cost"] == "low" {
        return 100, nil
    }
    return 0, nil
}

注册插件——在 main() 中用 runtime.Registry 注册:

1
2
3
4
5
6
func main() {
    command := app.NewSchedulerCommand(
        app.WithPlugin("MyScorePlugin", &MyScorePlugin{}),
    )
    command.Execute()
}

2.4 配置示例

通过 KubeSchedulerConfiguration 启用自定义插件并配置权重:

1
2
3
4
5
6
7
8
9
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
  - schedulerName: custom-scheduler
    plugins:
      score:
        enabled:
          - name: MyScorePlugin
            weight: 10
配置项说明
schedulerName使用此 Profile 的 Pod 需声明 schedulerName: custom-scheduler
enabled启用插件,disabled 可禁用默认插件
weightScore 阶段权重,最终得分加权求和决定选中 Node
pluginConfig向插件传入自定义参数

2.5 多 Profile

一个 kube-scheduler 实例可以加载多个 Profile,每个 Profile 有自己的一套启用插件 + 配置。不同业务通过 Pod 的 schedulerName 字段路由到不同 Profile。

1
2
3
4
profiles:
  - schedulerName: default-scheduler     # 默认
  - schedulerName: gpu-scheduler         # GPU 任务专用,启用拓扑感知插件
  - schedulerName: batch-scheduler       # 批处理任务,启用成本优先插件

3.总结

  1. Scheduler Framework 是 K8s 调度层的扩展接口,将调度拆成多个扩展点;
  2. Filter 做裁剪,Score 做优选,Permit 做阻塞控制——三者覆盖大部分自定义调度需求;
  3. 多 Profile 让同一集群内不同业务使用不同调度策略,无需部署多个调度器实例。

4.参考

分享

Hex
作者
Hex
CloudNative Developer