项目代码:基于v2.8.0分支源码分析
HAMi Webhook 架构与流程说明
本文基于 pkg/scheduler/webhook.go 的当前实现,对 HAMi Webhook 的处理范围、准入流程和关键变更点进行整理。
1. Webhook 处理范围
HAMi Webhook 并不会处理所有 Pod,而是优先处理以下几类对象:
spec.schedulerName为空的 Podspec.schedulerName已设置为 HAMi 调度器的 Podspec.schedulerName为default-scheduler,且ForceOverwriteDefaultScheduler=true的 Pod
对于已经指定为其他调度器的 Pod,Webhook 会直接放行,不再继续执行 HAMi 相关变更逻辑。
2. Webhook 工作时序图

3. 以 NVIDIA 设备为例的变更点
以 NVIDIA 设备实现为例,MutateAdmission 不只是检查资源是否存在,还可能直接修改 Pod / Container 内容,
go
func (dev *NvidiaGPUDevices) MutateAdmission(ctr *corev1.Container, p *corev1.Pod) (bool, error) {
/*gpu related */
priority, ok := ctr.Resources.Limits[corev1.ResourceName(dev.config.ResourcePriority)]
if ok {
ctr.Env = append(ctr.Env, corev1.EnvVar{
Name: util.TaskPriority,
Value: fmt.Sprint(priority.Value()),
})
}
if dev.config.GPUCorePolicy != "" &&
dev.config.GPUCorePolicy != DefaultCorePolicy {
ctr.Env = append(ctr.Env, corev1.EnvVar{
Name: util.CoreLimitSwitch,
Value: string(dev.config.GPUCorePolicy),
})
}
hasResource := dev.mutateContainerResource(ctr)
if dev.defaultExclusiveCoreIfNeeded(ctr) {
hasResource = true
}
if hasResource {
// Set runtime class name if it is not set by user and the runtime class name is configured
if p.Spec.RuntimeClassName == nil && dev.config.RuntimeClassName != "" {
p.Spec.RuntimeClassName = &dev.config.RuntimeClassName
}
}
if !hasResource && dev.config.OverwriteEnv {
ctr.Env = append(ctr.Env, corev1.EnvVar{
Name: "NVIDIA_VISIBLE_DEVICES",
Value: "none",
})
}
return hasResource, nil
}
主要包括:
- 注入任务优先级环境变量
- 根据
GPUCorePolicy注入核心策略环境变量 - 当容器只声明
core/memory/memoryPercentage、未声明 GPU 数量时,可能自动补充ResourceCountName - 当识别到使用了 GPU 资源,且用户未设置
RuntimeClassName时,自动补充RuntimeClassName - 当未使用该设备资源且开启
OverwriteEnv时,注入NVIDIA_VISIBLE_DEVICES=none

4. 思考
4.1 特权容器不会直接导致整个 Pod 被拒绝
当前实现中,特权容器的处理方式是"跳过该容器的设备变更逻辑",而不是"直接拒绝整个 Pod"。
因此更准确的说法是:
- 特权容器不会执行设备注入和相关修改
- Pod 不会仅因为某个容器是特权模式就被立即拒绝
4.2 未识别到 HAMI 设备资源的 Pod 通常会放行
当所有设备实现都没有识别到该 Pod 使用了 HAMI 设备资源时:
- Webhook 不会将其改写为 HAMi 调度器
- Webhook 也不会因为"未使用 vGPU"而直接拒绝该 Pod
4.3 nodeName 拒绝是有前提条件的
只有在以下条件同时满足时,Webhook 才会因为 nodeName 已设置而拒绝 Pod:
hasResource = true- 配置了 HAMi 的
SchedulerName
也就是说,并不是所有设置了 nodeName 的 Pod 都会被拒绝。
4.4 配额校验当前主要针对 NVIDIA
fitResourceQuota() 当前实现中带有"Only supports NVIDIA"的限制,因此这里的资源配额检查目前主要面向 NVIDIA 资源,而不是所有设备统一校验。
5. Webhook 功能总结
HAMi Webhook 在 Pod 创建阶段介入准入流程,识别 Pod 是否申请了 HAMi 管理的设备资源,并按需补充资源字段、注入环境变量、设置 RuntimeClassName,以及将需要由 HAMi 接管调度的 Pod 改写为 HAMi 调度器处理。
对于已指定其他调度器的 Pod,Webhook 会直接放行;
对于已经使用 HAMi 设备资源但又显式指定了 nodeName 的 Pod,Webhook 会直接拒绝,以避免绕过 HAMi 的调度决策。
资源配额检查通过后,Webhook 返回 Patch 给 apiserver,随后进入后续调度流程。