当前位置: 首页 > news >正文

Kueue 如何管理 DRA 模式下的 GPU 配额

环境准备分几段走:先创建 K8s 集群,再用 GPU Operator 把 GPU Driver / Container Runtime 准备好,最后装 Kueue 和 NVIDIA DRA Driver。

1.1 创建 Kubernetes 集群
集群使用 KubeClipper 创建。KubeClipper 1.6.0 默认支持 Kubernetes 1.36.1、containerd 2.2.4,和本文环境一致,详细步骤可以参考:KubeClipper 1.6.0 发布:kcctl 优化与 K8s 1.36 支持。

快速创建单节点集群的命令如下:

curl -sfL https://oss.kubeclipper.io/get-kubeclipper.sh | KC_REGION=cn bash -
kcctl deploy
kcctl create cluster --name demo --master <NODE_IP> --untaint-master
集群起来后确认版本:

$ kubectl get node -owide
NAME STATUS ROLES VERSION CONTAINER-RUNTIME
lixd-test-gpu Ready control-plane v1.36.1 containerd://2.2.4
1.2 GPU 环境准备(GPU Operator)
GPU Driver、NVIDIA Container Toolkit 等基础组件使用 GPU Operator 安装。完整说明可以参考之前这篇:GPU 环境搭建指南:使用 GPU Operator 加速 Kubernetes GPU 环境搭建。

本文后面会安装 NVIDIA DRA Driver,所以安装 GPU Operator 时需要关闭 DevicePlugin:

helm repo add nvidia https://helm.ngc.nvidia.com/nvidia && helm repo update

helm upgrade --install --wait gpu-operator
-n gpu-operator --create-namespace
nvidia/gpu-operator
–version=v26.3.1
–set driver.enabled=true
–set devicePlugin.enabled=false
–set devicePlugin.enabled=false:关闭 DevicePlugin,避免与后续安装的 DRA Driver 冲突。

安装完成后,确认 GPU Operator 组件正常运行:

$ kubectl get pods -n gpu-operator
NAME READY STATUS
gpu-operator-7bcbd487f5-h8dsd 1/1 Running
nvidia-container-toolkit-daemonset-zbpbv 1/1 Running
nvidia-operator-validator-8l2r5 1/1 Running
再确认节点能看到 GPU:

$ kubectl get node lixd-test-gpu -o jsonpath=‘{.metadata.labels.nvidia.com/gpu.product}{“\n”}’
Tesla-T4
1.3 安装 Kueue
Kueue 使用 0.18.1,安装方式和前两篇一样:

helm install kueue oci://registry.k8s.io/kueue/charts/kueue
–version=0.18.1
–namespace kueue-system
–create-namespace
–wait --timeout 300s
如果测试环境访问 registry.k8s.io 不稳定,也可以用 GitHub Release 里的 chart 包:

helm install kueue
https://github.com/kubernetes-sigs/kueue/releases/download/v0.18.1/kueue-0.18.1.tgz
–namespace kueue-system
–create-namespace
–wait --timeout 300s
1.4 接入 NVIDIA DRA Driver
最后安装 NVIDIA DRA Driver 25.12.0:

helm upgrade --install nvidia-dra-driver-gpu
nvidia/nvidia-dra-driver-gpu
–version 25.12.0
-n nvidia-dra-driver-gpu
–set gpuResourcesEnabledOverride=true
–create-namespace
–wait --timeout 300s
安装完成后,先看 DRA Driver 组件:

$ kubectl get pods -n nvidia-dra-driver-gpu
NAME READY STATUS
nvidia-dra-driver-gpu-controller-76864c66cb-s8tch 1/1 Running
nvidia-dra-driver-gpu-kubelet-plugin-grkbg 2/2 Running
再看 DeviceClass:

$ kubectl get deviceclass
NAME AGE
compute-domain-daemon.nvidia.com 2m47s
compute-domain-default-channel.nvidia.com 2m47s
gpu.nvidia.com 2m47s
mig.nvidia.com 2m47s
vfio.gpu.nvidia.com 2m47s
整卡调度用的是 gpu.nvidia.com。对应的 ResourceSlice 里能看到节点上的 T4:

$ kubectl get resourceslice
NAME NODE DRIVER POOL
lixd-test-gpu-gpu.nvidia.com-p8cdq lixd-test-gpu gpu.nvidia.com lixd-test-gpu
后面的 Job 会直接引用 gpu.nvidia.com 这个 DeviceClass,实际可分配设备则来自这些 ResourceSlice。

  1. Demo:使用 Kueue 调度 DRA 模式下的 GPU
    2.1 修改 Kueue DRA 配置
    DRA 和 Kueue 使用的资源名称并不是同一个。ResourceClaimTemplate 里写的是 deviceClassName: gpu.nvidia.com,而 ClusterQueue 里扣配额用的是资源名,所以这里需要做一次映射:

apiVersion: config.kueue.x-k8s.io/v1beta2
kind: Configuration
integrations:
frameworks:

  • batch/job
    resources:
    deviceClassMappings:
  • name: nvidia.com/gpu
    deviceClassNames:
    • gpu.nvidia.com
      这段配置的意思是:只要 Workload 通过 ResourceClaimTemplate 申请 gpu.nvidia.com 这个 DeviceClass,Kueue 就把它折算成 nvidia.com/gpu 这个逻辑资源来扣配额。

deviceClassMappings 将 DRA DeviceClass 映射为 Kueue 配额资源

修改 Kueue manager config 后,需要重启 kueue-controller-manager 让新配置生效。

2.2 创建队列
这次只用一个队列,GPU 配额只给 1 张 T4。这样后面再提交第二个 Job 时,Pending 状态会看得很清楚。

apiVersion: v1
kind: Namespace
metadata:
name: p3-dra-demo

apiVersion: kueue.x-k8s.io/v1beta2
kind: ResourceFlavor
metadata:
name: p3-t4
spec:
nodeLabels:
nvidia.com/gpu.product: Tesla-T4

apiVersion: kueue.x-k8s.io/v1beta2
kind: ClusterQueue
metadata:
name: p3-dra-cq
spec:
namespaceSelector: {}
resourceGroups:

  • coveredResources:
    • cpu
    • memory
    • nvidia.com/gpu
      flavors:
    • name: p3-t4
      resources:
      • name: cpu
        nominalQuota: “8”
      • name: memory
        nominalQuota: 16Gi
      • name: nvidia.com/gpu
        nominalQuota: 1

apiVersion: kueue.x-k8s.io/v1beta2
kind: LocalQueue
metadata:
name: p3-dra-queue
namespace: p3-dra-demo
spec:
clusterQueue: p3-dra-cq
注意这里的 coveredResources 里包含 nvidia.com/gpu。这是映射后的逻辑资源名,不是 Pod 里直接写的扩展资源。

2.3 用 ResourceClaimTemplate 申请整卡
使用 DRA 之后,Job 不再写 resources.limits.nvidia.com/gpu: 1,而是引用一个独立的 ResourceClaimTemplate。

这里 Kueue 做的事情很直接:读取 Workload 引用的 ResourceClaimTemplate,识别里面的 deviceClassName 和 count,再通过 deviceClassMappings 折算成 ClusterQueue 里的配额资源。

本文不展开 extended resource 路径,避免把两种 DRA 接入方式混在一起。

先创建 ResourceClaimTemplate:

apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: single-gpu
namespace: p3-dra-demo
spec:
spec:
devices:
requests:
- name: gpu
exactly:
deviceClassName: gpu.nvidia.com
allocationMode: ExactCount
count: 1
这里有两个细节容易混:

deviceClassName 是 gpu.nvidia.com,不是 nvidia.com/gpu
ExactCount + count: 1 表示申请 1 张整卡
再提交 Kueue 管理的 Job:

apiVersion: batch/v1
kind: Job
metadata:
name: kueue-dra-running-a
namespace: p3-dra-demo
labels:
kueue.x-k8s.io/queue-name: p3-dra-queue
spec:
parallelism: 1
completions: 1
suspend: true
template:
spec:
resourceClaims:
- name: gpu-claim
resourceClaimTemplateName: single-gpu
restartPolicy: Never
containers:
- name: cuda-test
image: nvcr.io/nvidia/cuda:12.6.0-base-ubuntu24.04
command: [“bash”, “-c”, “nvidia-smi -L && echo KUEUE_DRA_RUNNING_A && sleep 3600”]
resources:
claims:
- name: gpu-claim
Job 被 Kueue 准入后,会从 Suspended 变成 Running:

$ kubectl get job,pod,workload -n p3-dra-demo
NAME STATUS COMPLETIONS
job.batch/kueue-dra-running-a Running 0/1

NAME READY STATUS
pod/kueue-dra-running-a-kj7nw 1/1 Running

NAME QUEUE RESERVED IN ADMITTED
workload.kueue.x-k8s.io/job-kueue-dra-running-a-c3b3c p3-dra-queue p3-dra-cq True
ResourceClaim 已经分配:

$ kubectl get resourceclaim -n p3-dra-demo
NAME STATE
kueue-dra-running-a-kj7nw-gpu-claim-c6j4j allocated,reserved
容器里能看到 T4:

$ kubectl logs -n p3-dra-demo -l job-name=kueue-dra-running-a
GPU 0: Tesla T4 (UUID: GPU-6d8fdeb7-6247-e04e-81a7-7b42dc45180c)
KUEUE_DRA_RUNNING_A
2.4 看 Kueue 是否真的扣了 GPU 配额
直接看 Workload 的准入结果:

status:
admission:
clusterQueue: p3-dra-cq
podSetAssignments:
- count: 1
flavors:
nvidia.com/gpu: p3-t4
resourceUsage:
nvidia.com/gpu: “1”
这说明 deviceClassMappings 已经生效:用户写的是 ResourceClaimTemplate,Kueue 扣的是 nvidia.com/gpu 这个逻辑配额。

再看看 ClusterQueue,可以发现 GPU 配额已经被扣掉了:

status:
admittedWorkloads: 1
flavorsUsage:

  • name: p3-t4
    resources:
    • name: nvidia.com/gpu
      total: “1”
      2.5 第二个整卡 Job 会被 Kueue 卡住
      队列里只有 1 张 GPU 配额。如果再提交一个同样申请 single-gpu 的 Job:

kueue-dra-running-a:1 x gpu.nvidia.com
kueue-dra-pending-b:1 x gpu.nvidia.com
$ kubectl get job,workload -n p3-dra-demo
NAME STATUS
job.batch/kueue-dra-running-a Running
job.batch/kueue-dra-pending-b Suspended

NAME QUEUE RESERVED IN ADMITTED
workload.kueue.x-k8s.io/job-kueue-dra-running-a-c3b3c p3-dra-queue p3-dra-cq True
workload.kueue.x-k8s.io/job-kueue-dra-pending-b-494a3 p3-dra-queue
再看 Workload 状态,就能发现为什么第二个 Job 一直起不来:

status:
conditions:

  • reason: Pending
    message: ‘couldn’‘t assign flavors to pod set main: insufficient unused quota
    for nvidia.com/gpu in flavor p3-t4, 1 more needed’
    resourceRequests:
  • name: main
    resources:
    nvidia.com/gpu: “1”
  1. 几个容易踩坑的点
    DeviceClass 和配额资源不是同一个东西
    ResourceClaimTemplate 里写的是:

deviceClassName: gpu.nvidia.com
ClusterQueue 里写的是:

coveredResources:

  • nvidia.com/gpu
    两者靠 Kueue 配置里的 deviceClassMappings 关联起来。少了这段映射,Workload 会被标成 Inadmissible,原因类似:

DeviceClass gpu.nvidia.com is not mapped in DRA configuration
ResourceClaimTemplate 要单独创建
这两个名字最容易看混:

single-gpu:前面单独创建的 ResourceClaimTemplate,定义“我要 1 张 gpu.nvidia.com 整卡”。
gpu-claim:Pod 里的本地 claim 名字,后面容器通过它来使用 GPU。
Pod 里这段不是重新定义一个模板,而是引用已经存在的 single-gpu 模板:

resourceClaims:

  • name: gpu-claim
    resourceClaimTemplateName: single-gpu
    容器里再通过同一个 gpu-claim 关联到这次申请到的设备:

resources:
claims:

  • name: gpu-claim
    所以完整关系是:ResourceClaimTemplate(single-gpu) -> Pod resourceClaims(gpu-claim) -> container resources.claims(gpu-claim)。

Kueue 准入不等于设备已经分配
这里要注意一点:Kueue 只是负责“准入”,真正把 GPU 分配给 Pod 的还是 kube-scheduler 和 DRA Driver。

所以生产环境里建议同时关注 ResourceClaim 状态和 Pod 状态。如果希望 Workload 在 Pod 长时间起不来时释放 Kueue 配额,可以结合 waitForPodsReady 做保护。

  1. 小结
    到这里可以看到,Kueue 并没有直接参与 GPU 分配,而是站在 Job 准入这一层,通过 deviceClassMappings 把 DRA 的设备申请转换成队列里的配额资源。这样既保留了 DRA 的设备模型,也让 GPU 可以继续纳入 Kueue 的统一配额管理。

组件 负责什么
NVIDIA DRA Driver 把 GPU 作为 gpu.nvidia.com DeviceClass / ResourceSlice 发布出来
Kueue 通过 deviceClassMappings 把 DRA 设备折算成 nvidia.com/gpu 配额
kube-scheduler 在 Pod 调度阶段完成 ResourceClaim 的实际设备分配

http://www.cnnetsun.cn/news/3271432.html

相关文章:

  • Java Record 与 Lombok @Data 对比:5个维度剖析选择策略与性能影响
  • 基于TPS61170与PIC18F4455的高效DC-DC升压转换器设计
  • 304/316材质安平不锈钢丝网核心性能、报价、交付周期对比指南
  • 如何快速上手Light-Weight RefineNet:5分钟实现实时语义分割
  • CTPersistance CRUD操作指南:创建、读取、更新与删除完整教程
  • Git Worktree+Claude Code:一个人怎么“带“出多个AI程序员同时干活
  • Chispa与PySpark生态集成:最佳实践与常见问题解答
  • 我国实现铂族催化剂分钟级制备,绿色氢能材料研究取得新进展
  • React Native Map Clustering自定义聚类渲染指南:打造个性化地图标记样式
  • MembershipReboot性能优化:10个提升身份验证效率的技巧
  • Plonky3实战案例:基于Plonky3构建隐私保护投票系统的完整实现
  • SpringBoot 2.7 + MySQL 8.0 毕设项目实战:家庭理财系统从需求到部署的 5 个关键步骤
  • 开发者必读:NVIDIA-Nemotron-Labs-3-Puzzle-75B-A9B-BF16模型架构与代码实现详解
  • 成本效益分析:llama-nemotron-embed-vl-1b-v2在云服务和本地部署中的经济性对比
  • BI 看板加载优化:指标计算前推还是缓存预计算
  • 卡美德生物科普PDGFA(血小板衍生生长因子A)
  • LIExposeController高级用法:自定义Header/Footer与动画效果
  • eShopOnAbp测试策略:单元测试与集成测试完整指南
  • 只懂采购永远升不上总监!SCMP 项目补齐全链路短板,中研供应链实战课打破中层天花板
  • Cosmos3-Nano-Policy-DROID商业应用案例:制造业、物流、服务机器人的成功实践 [特殊字符]
  • 从零开始制作FOC轮腿机器人:开源DIY完整指南
  • NVIDIA-Nemotron-Labs-3-Puzzle-75B-A9B-NVFP4强化学习恢复:软件工程能力提升的终极指南
  • 如何构建基于NVIDIA-Nemotron-Labs-3-Puzzle-75B-A9B-NVFP4的RAG系统:完整指南
  • Honey Select 2汉化增强补丁:一站式解决方案让你的游戏体验全面提升
  • 为什么llama-nemotron-embed-vl-1b-v2在ViDoRe基准测试中表现卓越?深度技术解析
  • 如何快速部署MiniMax-M2.7-NVFP4:5分钟搭建高性能AI推理服务
  • 为什么越来越多的人开始使用ISP代理?
  • CANN/ops-math 偏置加法算子
  • NVIDIA-Nemotron-Labs-3-Puzzle-75B-A9B-BF16震撼发布:2倍吞吐量与1M长上下文的革命性AI模型
  • CANN/hixl C++通用编码规范