深色模式
GPU 资源池化与调度
摘要:本文面向需要把昂贵的 GPU 变成"可池化、可切分、可配额、可抢占"的共享资源的平台工程师。讲解 NVIDIA GPU Operator 体系、MIG 与 time-slicing 两种切分、拓扑感知调度、以及 Kueue/Volcano 的队列与 gang 调度。适用版本:NVIDIA GPU Operator 24.x([版本相关:以 NVIDIA 发布为准]),Kubernetes v1.28+(DRA 在 1.31+ 引入,GA 说法存疑,见下 [未实测])。
适用版本与前提
- Kubernetes:v1.28+(推荐 1.31+ 以试用 DRA,[版本相关])
- 节点已带 NVIDIA GPU(A100/H100 支持 MIG;T4/L4/老卡仅支持 time-slicing)
- 有 Helm 访问权限以安装 GPU Operator
核心概念:从"一块整卡"到"资源池"
GPU 调度要解决四件事:发现(device plugin)、切分(MIG/time-slicing)、放置(拓扑感知)、配额(队列/抢占)。
| 机制 | 隔离性 | 适用 |
|---|---|---|
整卡 nvidia.com/gpu: 1 | 强 | 训练、大推理 |
| MIG(A100/H100) | 硬件级内存+算力隔离 | 多租户推理、稳定 SLA |
| time-slicing | 仅时间片,无内存隔离 | dev/轻推理、延迟不敏感 |
| DRA(Dynamic Resource Allocation) | 细粒度设备分配 | 多卡组合、异构设备([未实测,版本相关]) |
生产实践 1:安装 GPU Operator
bash
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
helm install gpu-operator nvidia/gpu-operator \
--namespace gpu-operator --create-namespace \
--set operator.defaultRuntime=containerd
# 等待所有 DaemonSet/Pod Ready
kubectl get pods -n gpu-operator
# 期望: gpu-operator-, nvidia-driver-daemonset, nvidia-device-plugin-daemonset 等 Running1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
验证 GPU 可见
bash
kubectl get nodes -o json | jq '.items[].status.allocatable' | grep nvidia.com/gpu
# 期望节点 allocatable 含 "nvidia.com/gpu": "8"(8 卡节点)1
2
2
生产实践 2:MIG 切分(推荐用于推理隔离)
MIG 把一张 A100/H100 切成多个带独立内存与算力的实例,是唯一有硬件隔离的共享方式。先用 ConfigMap 定义切分方案,再让 GPU Operator 启用 migManager:
yaml
# mig-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mig-config
namespace: gpu-operator
data:
config.yaml: |
version: v1
mig-configs:
all-disabled:
- devices: [0,1,2,3,4,5,6,7]
mig-enabled: false
mixed-config:
- devices: [0,1]
mig-enabled: true
mig-devices:
1g.5gb: 2
2g.10gb: 1
- devices: [2,3,4,5,6,7]
mig-enabled: false1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bash
kubectl apply -f mig-config.yaml
kubectl patch clusterpolicies.nvidia.com/cluster-policy -n gpu-operator --type merge \
--patch '{"spec":{"migManager":{"config":{"name":"mig-config","default":"all-disabled"}}}}'1
2
3
2
3
工作负载直接请求 MIG 切片资源(资源名随 profile 变化):
yaml
# mig-workload.yaml
apiVersion: v1
kind: Pod
metadata:
name: mig-inference
spec:
restartPolicy: Never
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
nodeSelector:
nvidia.com/mig.config: mixed-config
containers:
- name: infer
image: nvcr.io/nvidia/tritonserver:24.01-py3 # [版本相关]
resources:
limits:
nvidia.com/mig-1g.5gb: 1 # 请求一个 1g.5gb 切片
memory: 8Gi1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
生产实践 3:Time-Slicing(dev/轻推理)
time-slicing 无内存隔离,适合延迟不敏感负载。通过 ConfigMap + 给设备插件指定配置启用:
yaml
# time-slicing-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: time-slicing-config
namespace: gpu-operator
data:
any: |
version: v1
flags:
migStrategy: none
sharing:
timeSlicing:
resources:
- name: nvidia.com/gpu
replicas: 4 # 每张物理 GPU 虚拟为 4 份1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bash
kubectl apply -f time-slicing-config.yaml
kubectl patch clusterpolicies.nvidia.com/cluster-policy -n gpu-operator --type merge \
--patch '{"spec":{"devicePlugin":{"config":{"name":"time-slicing-config"}}}}'1
2
3
2
3
两种切分怎么选
MIG 有内存/算力硬隔离,推理 SLA 稳定,优先用于多租户推理;time-slicing 只是时间片复用,两个 Pod 共享同一显存,一方 OOM 会拖累同卡其他 Pod,仅适合 dev/轻负载。不要对延迟敏感的生产推理用 time-slicing。
生产实践 4:Kueue 队列与 gang 调度(多租户配额)
yaml
# kueue-resourceflavor + clusterqueue(示意)
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
name: h100
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
name: team-a
spec:
resourceGroups:
- coveredResources: ["nvidia.com/gpu"]
flavors:
- name: h100
resources:
- name: nvidia.com/gpu
nominalQuota: 8 # team-a 最多用 8 张 H100
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
name: team-a-queue
namespace: team-a
spec:
clusterQueue: team-a1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
分布式训练 Job 用 PodGroup 声明需同时拿到的 GPU 数,否则会死锁:
yaml
# 在训练 Job 上挂 kueue.x-k8s.io/queue-name: team-a-queue
# 并声明 podGroups: [{name: ..., minResources: {nvidia.com/gpu: 8}}]1
2
2
验证
bash
# 确认节点暴露 GPU 资源
kubectl describe node <gpu-node> | grep -A3 Allocatable | grep nvidia
# MIG 节点应出现 nvidia.com/mig-1g.5gb 等
kubectl get node <gpu-node> -o json | jq '.metadata.labels | keys[] | select(.|contains("mig"))'
# 跑一个 GPU 校验 Pod
kubectl run gpu-test --rm -it --image=nvidia/cuda:12.4.0-base-ubuntu22.04 --restart=Never \
--limits=nvidia.com/gpu=1 -- nvidia-smi -L
# 期望列出 GPU 设备(示意):
# GPU 0: NVIDIA A100-SXM4-80GB ...1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
回滚与清理
bash
# 关闭 MIG 改回整卡:把 default 改成 all-disabled 并 drain 节点
kubectl patch clusterpolicies.nvidia.com/cluster-policy -n gpu-operator --type merge \
--patch '{"spec":{"migManager":{"config":{"default":"all-disabled"}}}}'
# 卸载 GPU Operator(会移除驱动 DaemonSet,谨慎)
helm uninstall gpu-operator -n gpu-operator1
2
3
4
5
6
2
3
4
5
6
切分变更需 drain 节点
MIG 的切分模式改变(mixed <-> none)通常需要排空(cordon+drain)相关 GPU 节点才能生效,过程中该节点上 GPU 负载会中断。务必在低峰、确认可迁移后操作。
故障排查
| 现象 | 原因 | 排查 |
|---|---|---|
Pod Insufficient nvidia.com/gpu | 整卡被占满,无 MIG/切片 | 查 kubectl describe node 已分配;考虑 MIG/time-slicing |
| MIG 资源名不存在 | migManager 未启用/配置未生效 | 查 nvidia-mig-manager 日志与节点 label |
| time-slicing 后 OOM 互相影响 | 无内存隔离所致 | 改用 MIG 或降低并发 |
| 多卡训练死锁 | 未 gang 调度,部分卡长期拿不到 | 用 Kueue/Volcano PodGroup 同时申请 |
| 拓扑错配训练慢 | GPU 非 NVLink 互联 | 用 GPU Feature Discovery 标签做亲和 |
安全与合规
GPU 是多租户越权与成本失控的高危资源
- taint + 配额:GPU 节点打
nvidia.com/gpu: NoScheduletaint,仅授权负载容忍;用 Kueue ClusterQueue 限制每团队卡数,防单团队吃满整池(变相"越权占用")。 - 隔离边界:多租户推理优先 MIG 而非 time-slicing,避免显存越界影响他人;跨租户共卡需配合 PSA
restricted。 - 驱动/固件一致性:节点间驱动版本错配会导致 CUDA 兼容性故障;锁定驱动版本并在升级前在灰度节点验证。
- egress 收敛:GPU 节点上的训练/推理 Pod 收敛出网,防止权重或数据经 GPU 节点外泄(与 model-repo.md、kserve.md 安全章节呼应)。
成本与性能
- 成本主导项:GPU 单价远高于 CPU。示例([价格随云厂商/时点变化,未实测]):H100 约 2–3 USD/GPU·小时,8 卡节点满载单月约 11,500–17,300 USD。MIG 把开发/小推理切到 1g.5gb 切片,第三方经验称开发环境 GPU 需求可降约 50%([未实测])。
- 利用率即省钱:第三方经验称合理的池化 + 优先级抢占 + 缩容到零,可把整体吞吐提升 20–40%([未实测,取决于负载画像]);30% 的利用率提升在 20 万美元/月的 GPU 预算上意味着约 6 万美元/月节省(第三方估算,[未实测])。
- 拓扑收益:通信密集训练若 GPU 经 NVLink 而非 PCIe 互联,带宽差一个数量级(NVLink 数百 GB/s vs PCIe ~32GB/s),错误放置可使训练慢 3–8 倍([未实测])。务必拓扑感知调度。
DRA 成熟度
Kubernetes Dynamic Resource Allocation(DRA)用于更细粒度的 GPU/异构设备分配,在 1.31+ 引入;其 GA 状态与 KServe/KubeRay 的 DRA 集成仍在演进,本文以"特性存在、按需评估"表述,不保证当前为 GA,请以 Kubernetes 官方 release notes 与你集群版本为准([未实测])。