Kubernetes GPU 调度实战:从 Device Plugin 到共享 GPU
摘要: K8s 原生不认 GPU——它只把 GPU 当"一个可分配的整数资源"。真正让它认识 GPU 的是 Device Plugin,而让 GPU 用得更高效的是共享/切分方案。本文讲清楚:Device Plugin 怎么工作、共享 GPU 三方案怎么选、监控配额怎么配,以及"K8s 和 Slurm 谁管谁"的定位。
0. 实验目标
- 理解 Device Plugin 机制:K8s 如何把 GPU 暴露为可调度资源
- 掌握共享 GPU 三条路线:时间片(Time-Slice)/ MIG / MPS
- 用 Prometheus + DCGM 监控 GPU 使用与配额
- 明确 K8s 与 Slurm 的协同边界
1. Device Plugin:K8s 认识 GPU 的关键
原理讲解:
- K8s 调度器只认
resources.requests/limits里的整数资源(cpu/memory)。要让 GPU 可调度,需要一个 Device Plugin(K8s 官方机制)做三件事:- 向 Kubelet 汇报本节点有几张 GPU(
ListAndWatch) - 收到 Pod 调度后分配/初始化对应 GPU 设备(
Allocate,注入环境变量CUDA_VISIBLE_DEVICES) - 监控 GPU 健康状态
- 向 Kubelet 汇报本节点有几张 GPU(
yaml
# 使用 GPU 的 Pod(标准写法)
apiVersion: v1
kind: Pod
metadata:
name: gpu-infer
spec:
containers:
- name: infer
image: my-llm:latest
resources:
limits:
nvidia.com/gpu: 1 # 申请 1 张 GPU(Device Plugin 暴露的资源名)
env:
- name: NVIDIA_VISIBLE_DEVICES
value: all # 容器内由 plugin 注入实际可见 GPU 编号工程启示:
- NVIDIA Device Plugin 是事实标准(DaemonSet 部署),社区版 + 官方版二选一,按节点 GPU 型号配置。
- Pod 里
nvidia.com/gpu: N申请整数张 GPU;默认不支持"半个 GPU"——要切分得用下面的共享方案。 - 裸奔风险:如果节点装了驱动但没装 Device Plugin,GPU 对 K8s 不可见(
nvidia.com/gpu资源为 0),调度直接失败。
2. 共享 GPU 三方案:时间片 / MIG / MPS
| 方案 | 原理 | 隔离级别 | 适合场景 | K8s 支持 |
|---|---|---|---|---|
| 时间片(Time-Slice) | 多 Pod 轮流用同一 GPU | 最弱(无显存隔离) | 低负载推理、开发测试 | NVIDIA 官方 plugin 支持 |
| MIG | 硬件切分 SM/显存 | 强(实例隔离) | 多租户、强隔离 | plugin 支持 MIG 实例 |
| MPS | 多进程共享 context | 中(软件共享) | 小任务并发提吞吐 | 需自定义调度扩展 |
逐段拆解:
- 时间片:最简单,
nvidia.com/gpu按"份额"暴露(如 0.5 张 = 时间片轮转)。风险:显存不隔离,一个吃显存的 Pod 可能把同卡其他 Pod 挤 OOM——只适合可控环境。 - MIG:A100/H100 硬件切分(7 个实例),K8s 里每个 MIG 实例作为独立资源调度。隔离最强但配置固定(实例规格不可动态变),详见 MIG 分区 篇。
- MPS:软件共享,小任务并发吞吐最优(详见 CUDA MPS 篇);K8s 集成需要把 MPS 管道目录挂进 Pod 并注入环境变量。
选型速记:时间片给开发,MIG 给租户,MPS 给吞吐。
3. GPU 监控与配额
bash
# DCGM(NVIDIA Data Center GPU Manager)导出 Prometheus 指标
# 部署 nvidia-dcgm-exporter DaemonSet 后,接入 Prometheus/Grafana
curl -s localhost:9400/metrics | grep -E "DCGM_FI_DEV_GPU_UTIL|DCGM_FI_DEV_MEM_COPY_UTIL|DCGM_FI_DEV_GPU_TEMP" | head -5关键指标(告警建议):
| 指标 | 含义 | 建议告警 |
|---|---|---|
DCGM_FI_DEV_GPU_UTIL | GPU 利用率 | 长期 <20% 提示闲置浪费 |
DCGM_FI_DEV_MEM_COPY_UTIL | 显存带宽利用率 | >90% 提示瓶颈 |
DCGM_FI_DEV_GPU_TEMP | 温度 | >85°C 告警 |
DCGM_FI_DEV_ECC_... | ECC 错误 | >0 立即告警(硬件问题) |
配额管理:K8s 原生 ResourceQuota + LimitRange 限制命名空间 GPU 总量;多租户强隔离用 MIG + 命名空间配额组合。
4. K8s 与 Slurm:协同定位
原理讲解:
- Slurm 管 HPC 批作业:MPI、科学计算、固定资源的长期训练作业——排队、抢占、拓扑感知调度成熟。
- K8s 管云原生服务:在线推理 API、微服务、弹性扩缩容、滚动更新——K8s 的强项。
- 协同架构(常见):
- 分区共用 GPU 池:Slurm 节点与 K8s 节点物理分离,各管各的(简单可靠)
- K8s 里跑 Slurm(Slurm-on-K8s):用 K8s 管理裸金属/虚机节点,Slurm 负责作业调度(高级)
- 事件驱动联动:推理高峰 K8s 扩 GPU Pod,训练作业排 Slurm——通过 Autoscaler/Webhook 联动
工程启示:
- 在线推理走 K8s(弹性 + 滚动更新),批训练走 Slurm(排队 + 拓扑),各用所长。
- GPU 池物理分离最稳:避免 K8s 弹性扩容把 Slurm 节点抢走导致作业排队雪崩。
- 共享 GPU 按场景选:开发/测试用时间片,生产推理 MPS 提吞吐,多租户 MIG 强隔离。
- DCGM 指标接入监控:GPU 利用率/温度/ECC 全量纳管,别等用户报障。
- Device Plugin 是前置条件:新节点上线 checklist 必含"
kubectl describe node | grep nvidia.com/gpu"。 - 配额先行:多团队共享集群前先定 ResourceQuota,避免"抢 GPU"纠纷。
5. 工程启示汇总
- Device Plugin = GPU 调度的地基:没装 = GPU 对 K8s 不可见。
- 整数资源限制:
nvidia.com/gpu: 1只能申请整卡;切分靠时间片/MIG/MPS。 - 时间片给开发、MIG 给租户、MPS 给吞吐。
- 时间片不隔离显存:生产慎用,OOM 风险高。
- DCGM 全量纳管:利用率/温度/ECC 进 Prometheus。
- K8s 管在线、Slurm 管批处理:GPU 池分离,协同不抢资源。
- 配额先行:ResourceQuota + MIG 组合做多租户治理。