其实主要就是 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] ← 绑定后处理
各扩展机制的位置
| 扩展点 | 机制 | 谁能用 | 典型场景 |
|---|---|---|---|
| 1 | Admission Webhook | 所有用户 | 注入 sidecar、修改配置、注入 schedulingGates |
| 2 | Scheduling Gates | 控制器 | Kueue、Volcano 的队列 |
| 3-8 | Scheduler Framework | 调度器开发者 | 自定义调度算法 |
| 3-8 | Scheduler Extender | 外部服务 | 简单的自定义调度逻辑 |
| 7 | Permit | 调度器插件 | Gang scheduling |
六、Kueue vs 其他方案
| 方案 | 机制 | 特点 |
|---|---|---|
| Kueue | Scheduling Gates + Webhook | 通用队列,支持多种作业类型 |
| Volcano | 自定义调度器 + Framework | 专注 HPC/AI 工作负载 |
| Yunikorn | 自定义调度器 | 大数据场景 |
| Koordinator | Framework + Webhook | 混部、QoS |
七、总结
Kueue 使用的核心扩展机制是:
- Scheduling Gates(调度门控):Kubernetes 1.26+ 的原生 Pod 字段,阻止调度器调度 Pod
- Admission Webhook(准入控制器):自动注入 schedulingGates 到 Pod
- Controller Pattern(控制器模式):Kueue 作为控制器,监控和管理队列
设计哲学:Kubernetes 提供了"卡住"Pod 的能力(schedulingGates),Kueue 利用这个能力实现队列,而不是修改调度器本身。这种设计让 Kueue 与 Kubernetes 解耦,升级和维护都更简单。