实验 3: 使用 HAMi 进行 GPU 分区
本实验在 实验 1 的基础上继续。你有一块拥有 15360 MiB 显存的物理 Tesla T4。在本实验中,你将在这一张卡上运行多个 Pod,每个 Pod 都有独立的显存和算力上限,并验证隔离的真实性:当一个 Pod 尝试分配超出其配额的显存时,会触发 CUDA OOM,而相邻 Pod 不受影响继续运行。
本实验中的每条命令和输出均来自使用实验 1 搭建的实际集群(HAMi v2.9.0、GPU Operator v25.3.0、Kubernetes v1.34)。
你将学到什么
- HAMi 为 Kubernetes 添加的 vGPU 资源类型
- 在一张物理 GPU 上运行多个 Pod
- HAMi 如何在容器内部强制执行显存上限
- 通过 OOM 测试验证显存隔离
- 使用
gpucores限制算力及两种利用率策略 - 在哪里查看 HAMi 调度器的决策
实验概览
前提条件
- 已完成 实验 1: 在线安装 的集群:HAMi 已安装,GPU 节点已标记
gpu=on - 来自
tutorials/labs/examples/03-gpu-partitioning/的清单文件
步骤 1: 了解 HAMi 资源类型
HAMi 通过自定义 GPU 资源扩展 Kubernetes。Pod 组合使用这些资源来描述其所需的 GPU 切片:
| 资源 | 含义 |
|---|---|
nvidia.com/gpu | 容器请求的 vGPU 数量 |
nvidia.com/gpumem | 每个 vGPU 的显存,单位 MiB |
nvidia.com/gpumem-percentage | 每个 vGPU 的显存占整卡的百分比(gpumem 的替代方案) |
nvidia.com/gpucores | 每个 vGPU 的算力,占显卡 SM 的百分比 |
查看节点提供的资源:
NODE_NAME=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')
kubectl get node ${NODE_NAME} -o jsonpath='{.status.allocatable.nvidia\.com/gpu}'
10
一张物理 T4 被注册为 10 个可调度的 vGPU(即你在实验 1 中验证过的注册注解中的
count字段)。每个 vGPU 可以携带独立的gpumem和gpucores限制。
步骤 2: 两个 Pod 共享一张 GPU
部署两个 Pod,每个请求 1 个 vGPU 和 4000 MiB 显存切片。先看清单文件:
apiVersion: v1
kind: Pod
metadata:
name: gpumem-pod-a
spec:
restartPolicy: Never
containers:
- name: app
image: nvidia/cuda:12.4.1-base-ubuntu22.04
command: ["sleep", "infinity"]
resources:
limits:
nvidia.com/gpu: 1 # 请求 1 个 vGPU
nvidia.com/gpumem: 4000 # 限制此 Pod 的显存为 4000 MiB
gpumem-pod-b.yaml 除了名称不同外完全相同。部署两个 Pod:
kubectl apply -f tutorials/labs/examples/03-gpu-partitioning/gpumem-pod-a.yaml -f tutorials/labs/examples/03-gpu-partitioning/gpumem-pod-b.yaml
kubectl get pods gpumem-pod-a gpumem-pod-b -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
gpumem-pod-a 1/1 Running 0 27s 10.244.218.156 hami-workshop <none> <none>
gpumem-pod-b 1/1 Running 0 27s 10.244.218.157 hami-workshop <none> <none>
两个 Pod 都在只有一张物理 GPU 的节点上运行。通过读取 HAMi 调度器写入每个 Pod 的分配注解,验证它们确实运行在同一张卡上:
kubectl get pod gpumem-pod-a -o jsonpath='{.metadata.annotations.hami\.io/vgpu-devices-allocated}'; echo
kubectl get pod gpumem-pod-b -o jsonpath='{.metadata.annotations.hami\.io/vgpu-devices-allocated}'; echo
GPU-859b872c-0ba2-97b0-10b4-8b7185c55039,NVIDIA,4000,0:;
GPU-859b872c-0ba2-97b0-10b4-8b7185c55039,NVIDIA,4000,0:;
相同的设备 UUID,各 4000 MiB。两个 Pod,一张物理 T4。注解格式为
{UUID},{厂商},{显存 MiB},{算力 %}。
步骤 3: 显存上限
关键问题:从 Pod 内部看,GPU 是什么样的?
kubectl exec gpumem-pod-a -- nvidia-smi
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.124.06 Driver Version: 570.124.06 CUDA Version: 12.8 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
|=========================================+========================+======================|
| 0 Tesla T4 On | 00000000:00:04.0 Off | 0 |
| N/A 57C P8 16W / 70W | 0MiB / 4000MiB | 0% Default |
+-----------------------------------------+------------------------+----------------------+
0MiB / 4000MiB:容器看到的是一块 4000 MiB 的 GPU,而不是物理的 15360 MiB。这是 HAMi-core 的核心能力:一个通过LD_PRELOAD注入到容器中的库,它拦截 CUDA 和 NVML 调用并重写内存数值。另一个 Pod 在同一张物理卡上看到的是独立的 4000 MiB 上限。