Kueue 与 k8s 扩展点:Scheduling Gates

9 阅读5分钟

其实主要就是 Scheduling Gates: webhook 作用的也是 Scheduling Gates

你问的是 Kubernetes 的调度扩展机制。Kueue 利用的核心机制叫 Scheduling Gates(调度门控) 和 Dynamic Admission Control(动态准入控制)。


一、Kubernetes 调度扩展接口全景

Kubernetes 提供了多种调度扩展点,Kueue 主要用到了前两个:

扩展机制类型作用阶段Kueue 是否使用
Scheduling Gates内置 API 字段Pod 创建后、调度前✅ 核心机制
Admission Webhook动态准入控制资源创建时拦截✅ 用于注入 Scheduling Gates
Scheduler Extender调度器扩展调度决策时❌ 不用
Scheduler Framework调度插件调度流程内❌ 不用
PriorityClass + Preemption内置机制资源抢占✅ 辅助机制
ResourceQuota内置机制命名空间资源限制❌ 不用(自己实现)

二、核心机制:Scheduling Gates

1. 什么是 Scheduling Gates?

这是 Kubernetes 1.26+ 引入的原生字段,在 Pod spec 中:

apiVersion: v1
kind: Pod
metadata:
  name: my-gpu-job
spec:
  schedulingGates:          # ← 关键字段
  - name: kueue.x-k8s.io/admission  # ← 自定义的门控名称
  containers:
  - name: main
    image: nvidia/cuda:12.0
    resources:
      limits:
        nvidia.com/gpu: 4

2. Scheduling Gates 的工作机制

Pod 创建
   ↓
API Server 接受 Pod(status.phase = Pending)
   ↓
调度器看到 Pod 有 schedulingGates
   ↓
调度器拒绝调度(即使资源充足)
   ↓
Pod 一直保持 Pending 状态
   ↓
Kueue 控制器检查队列和配额
   ↓
资源满足 → Kueue 移除 schedulingGates
   ↓
调度器正常调度 Pod
   ↓
Pod 绑定到节点

关键点:Scheduling Gates 是调度器的硬性门槛,只要存在,调度器就不会调度这个 Pod。


三、Kueue 的完整工作流程

架构图

用户创建 Workload
    ↓
[Admission Webhook] → 拦截 Workload,注入 schedulingGates
    ↓
[Kueue Controller] → 将 Workload 加入 ClusterQueue
    ↓
[队列管理] → 检查配额(ResourceQuota)
    ↓
[准入决策] → 判断是否满足资源
    ↓
[移除 schedulingGates] → 允许调度
    ↓
[Kubernetes Scheduler] → 正常调度 Pod

详细步骤

Step 1:用户提交作业

apiVersion: kueue.x-k8s.io/v1beta1
kind: Workload
metadata:
  name: vllm-job
spec:
  podSets:
  - count: 2
    template:
      spec:
        containers:
        - name: vllm
          image: vllm/vllm-openai:latest
          resources:
            requests:
              cpu: "16"
              memory: "64Gi"
              nvidia.com/gpu: "4"

或者更常见的方式,用户创建普通的 Deployment/Job,Kueue 的 webhook 自动创建对应的 Workload。

Step 2:Webhook 注入 Scheduling Gates

Kueue 的 MutatingAdmissionWebhook 拦截 Pod 创建请求,自动添加:

spec:
  schedulingGates:
  - name: kueue.x-k8s.io/admission

Step 3:Kueue 控制器处理队列

apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: gpu-cluster-queue
spec:
  namespaceSelector: {}
  resourceGroups:
  - coveredResources: ["cpu", "memory", "nvidia.com/gpu"]
    flavors:
    - name: default-flavor
      resources:
      - name: "cpu"
        nominalQuota: 100
      - name: "memory"
        nominalQuota: 500Gi
      - name: "nvidia.com/gpu"
        nominalQuota: 16
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  name: team-a-queue
  namespace: team-a
spec:
  clusterQueue: gpu-cluster-queue

Kueue 控制器:

  • 监控所有带 schedulingGates 的 Pod
  • 根据 Pod 的 namespace 找到对应的 LocalQueue → ClusterQueue
  • 将 Workload 放入队列

Step 4:准入决策

Kueue 定期检查:

当前集群资源使用情况:
  GPU 已用:12/16
  CPU 已用:80/100
  内存已用:400/500Gi

新 Workload 需求:
  GPU:4
  CPU:16
  内存:64Gi

判断:4 + 12 ≤ 16 ✅
     16 + 80 ≤ 100 ✅
     64 + 400 ≤ 500Gi ✅

决策:准入!

Step 5:移除 Scheduling Gates

Kueue 更新 Pod:

spec:
  schedulingGates: []  # 移除

Step 6:Kubernetes 调度器接管

调度器看到 schedulingGates 已空,开始正常调度:

  • 过滤节点
  • 打分
  • 绑定

四、为什么不用 Scheduler Extender 或 Framework?

Scheduler Extender 的问题

# kube-scheduler 配置
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
extenders:
- urlPrefix: "http://kueue-scheduler:8080/scheduler"
  filterVerb: "filter"
  prioritizeVerb: "prioritize"

缺点:

  • 每个节点都要 HTTP 调用,性能差
  • 只能影响单个 Pod 的调度决策,无法全局排队
  • 需要在调度器配置中添加,侵入性强

Scheduler Framework 的问题

需要修改 kube-scheduler 代码或使用自定义调度器:

// 需要编写 Go 插件
type KueuePlugin struct {
    // 实现 QueueSort、Filter、Reserve 等接口
}

缺点:

  • 需要重新编译调度器
  • 升级 Kubernetes 需要同步升级插件
  • 无法与默认调度器共存

Scheduling Gates 的优势

优势说明
原生支持Kubernetes 1.26+ 内置,无需改代码
解耦Kueue 和调度器完全独立
全局视角可以在所有 Pod 之间做全局排队
简单可靠只是 Pod 的一个字段,无性能开销
兼容性好与任何调度器兼容

五、Kubernetes 调度扩展机制全景

完整的调度流程和扩展点

Pod 创建
  ↓
[1. Admission Webhooks]      ← 可以修改 Pod spec,注入 schedulingGates
  ↓
[2. Scheduling Gates]        ← 硬性门槛,阻止调度
  ↓
[3. Scheduler Queue]         ← 队列排序插件
  ↓
[4. Filter Phase]            ← 过滤插件(资源、亲和性等)
  ↓
[5. Score Phase]             ← 打分插件
  ↓
[6. Reserve Phase]           ← 预留资源
  ↓
[7. Permit Phase]            ← 可以等待其他条件
  ↓
[8. Bind Phase]              ← 绑定到节点
  ↓
[9. Post-bind]               ← 绑定后处理

各扩展机制的位置

扩展点机制谁能用典型场景
1Admission Webhook所有用户注入 sidecar、修改配置、注入 schedulingGates
2Scheduling Gates控制器Kueue、Volcano 的队列
3-8Scheduler Framework调度器开发者自定义调度算法
3-8Scheduler Extender外部服务简单的自定义调度逻辑
7Permit调度器插件Gang scheduling

六、Kueue vs 其他方案

方案机制特点
KueueScheduling Gates + Webhook通用队列,支持多种作业类型
Volcano自定义调度器 + Framework专注 HPC/AI 工作负载
Yunikorn自定义调度器大数据场景
KoordinatorFramework + Webhook混部、QoS

七、总结

Kueue 使用的核心扩展机制是:

  1. Scheduling Gates(调度门控):Kubernetes 1.26+ 的原生 Pod 字段,阻止调度器调度 Pod
  2. Admission Webhook(准入控制器):自动注入 schedulingGates 到 Pod
  3. Controller Pattern(控制器模式):Kueue 作为控制器,监控和管理队列

设计哲学:Kubernetes 提供了"卡住"Pod 的能力(schedulingGates),Kueue 利用这个能力实现队列,而不是修改调度器本身。这种设计让 Kueue 与 Kubernetes 解耦,升级和维护都更简单。