单节点 Kubernetes 部署 HAMi,并基于 8G 显卡测试 vGPU 切分
一、环境说明
这次测试环境是一套单节点 Kubernetes 集群,节点上有一张 NVIDIA GPU,显存 8G 左右。部署目标是使用 HAMi 对单张 GPU 做 vGPU 共享,让多个 Pod 可以共享同一张物理 GPU。
HAMi 原名 k8s-vGPU-scheduler,现在是 Kubernetes 上的异构算力虚拟化中间件,主要用于 GPU、NPU 等异构设备的共享、隔离和调度。对于 NVIDIA GPU 来说,HAMi 可以让 Pod 按显存、GPU core 等维度申请资源,从而避免一个小任务独占整张 GPU。HAMi 官方文档中也说明,它支持多种异构 AI 计算设备,并且支持多个容器或工作负载共享设备资源。
本文主要测试以下内容:
1. 部署前检查 NVIDIA Driver 和 NVIDIA Container Toolkit
2. 使用 Helm 部署 HAMi
3. 验证 HAMi 组件是否正常
4. 测试一张 8G GPU 被两个 Pod 共享
5. 测试 nvidia.com/gpumem 显存切分
6. 测试 nvidia.com/gpumem-percentage 显存百分比切分
7. 测试 nvidia.com/gpucores 算力比例限制
8. 测试指定 GPU 型号
9. 测试指定 GPU UUID
10. 说明 nvidia.com/gpu: 2 这个容易误解的点
二、部署 HAMi 前需要准备什么
在 Kubernetes 上使用 NVIDIA GPU,大体要先解决三件事:
1. 宿主机能识别 GPU
2. 容器能使用 GPU
3. Kubernetes 能调度 GPU 资源
HAMi 官方 Helm 部署文档中提到,部署前需要在 GPU 节点上准备 NVIDIA Driver 和 NVIDIA Container Toolkit,并且假设 nvidia-container-runtime 已经配置为默认的底层运行时。也就是说,HAMi 本身不是用来安装显卡驱动的,驱动和容器运行时环境需要提前准备好。
这里有一点需要注意:
在 HAMi 场景下,通常不需要再单独部署 NVIDIA 官方 k8s-device-plugin。
原因是 HAMi 安装后会部署自己的 hami-device-plugin,由它负责把 HAMi 管理的 GPU 资源注册给 kubelet。HAMi 官方 FAQ 也说明,HAMi Device Plugin、Volcano vGPU Device Plugin、NVIDIA 官方 Device Plugin 都会管理 GPU 资源,同一个节点上建议只使用一种 GPU 管理插件,避免资源冲突。
如果你的集群里已经通过 GPU Operator 部署了 NVIDIA 官方 device-plugin,需要注意不要让两个 device-plugin 同时管理同一种 nvidia.com/gpu 资源,否则很容易出现资源显示、调度行为和实际设备分配对不上的问题。
三、检查宿主机和容器 GPU 环境
3.1 检查宿主机 GPU 是否正常
先在宿主机上执行:
nvidia-smi
正常情况下应该能看到显卡信息,例如:
NVIDIA GeForce RTX 3070 Ti Laptop GPU
Memory-Usage: 0MiB / 8192MiB
查看 GPU 型号:
nvidia-smi --query-gpu=name --format=csv,noheader
查看 GPU UUID:
nvidia-smi --query-gpu=index,name,uuid,memory.total --format=csv,noheader
示例输出:
0, NVIDIA GeForce RTX 3070 Ti Laptop GPU, GPU-998864a7-78d9-dbab-e122-4c37842ce7cf, 8192 MiB
后面测试 nvidia.com/use-gputype 和 nvidia.com/use-gpuuuid 时会用到这两个值。
3.2 检查 Docker 容器是否能使用 GPU
如果你的机器上使用 Docker,可以先用 Docker 跑一个容器测试 GPU 是否能被容器识别。
docker run --rm --gpus all nvidia/cuda:11.0.3-base-ubuntu18.04 nvidia-smi
如果这里不能正常输出 GPU 信息,就不要急着安装 HAMi,应该先处理 NVIDIA Driver、NVIDIA Container Toolkit 或 Docker runtime 配置。
3.3 注意 Docker 和 containerd 的区别
这里要特别注意:
Docker 测试成功,不代表 Kubernetes Pod 一定能使用 GPU。
原因是现在很多 Kubernetes 集群默认使用的是 containerd,而不是 Docker。HAMi 官方部署文档里 Docker 和 containerd 的 NVIDIA runtime 配置是分开的:如果 Kubernetes 使用 Docker,需要把 nvidia-container-runtime 配成 Docker 的默认 runtime;如果 Kubernetes 使用 containerd,需要在 containerd 配置中把 NVIDIA runtime 配成默认 runtime。
可以通过下面命令查看节点使用的容器运行时:
kubectl get node -o wide
如果显示的是 containerd,可以使用 NVIDIA 官方推荐的方式配置:
sudo nvidia-ctk runtime configure --runtime=containerd
sudo systemctl restart containerd
NVIDIA 官方文档也说明,Kubernetes 使用 containerd 时,可以通过 nvidia-ctk runtime configure --runtime=containerd 配置,然后重启 containerd。
如果是 Docker,则可以使用:
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
本文后面的 Pod YAML 没有显式配置:
runtimeClassName: nvidia
前提是 NVIDIA runtime 已经被配置为默认容器运行时。如果你的集群不是默认使用 NVIDIA runtime,而是通过 RuntimeClass 暴露 nvidia runtime,那么需要根据实际环境给 Pod 增加:
runtimeClassName: nvidia
四、安装 HAMi
4.1 给 GPU 节点打标签
HAMi 默认只管理带有 gpu=on 标签的 GPU 节点。官方文档说明,需要给 GPU 节点打 gpu=on 标签,没有这个标签的节点不能被 HAMi scheduler 管理。先查看节点名称:
kubectl get node
给节点打标签:
kubectl label nodes master-01 gpu=on --overwrite
确认标签:
kubectl get node master-01 --show-labels | grep gpu=on
如果你发现 hami-scheduler 正常,但是 hami-device-plugin 没有起来,优先检查这个标签是否存在。
4.2 添加 HAMi Helm 仓库
先查看 Kubernetes Server 版本:
kubectl version
添加 HAMi Helm 仓库:
helm repo add hami-charts https://project-hami.github.io/HAMi/
helm repo update
4.3 安装 HAMi
安装时需要设置 kube-scheduler 镜像版本和 Kubernetes Server 版本匹配。HAMi 官方安装文档中也明确写到,scheduler.kubeScheduler.imageTag 需要和 Kubernetes Server 版本保持一致。
例如 Kubernetes Server 版本是 v1.29.0,安装命令如下:
helm install hami hami-charts/hami \
--set scheduler.kubeScheduler.imageTag=v1.29.0 \
-n kube-system
这里的 v1.29.0 要替换成你自己集群的 Kubernetes Server 版本。
如果你的版本是 v1.27.9,那就写成:
helm install hami hami-charts/hami \
--set scheduler.kubeScheduler.imageTag=v1.27.9 \
-n kube-system
五、验证 HAMi 组件是否正常
执行:
kubectl -n kube-system get pod | grep -E "hami|vgpu"
新版本一般能看到类似:
hami-device-plugin-xxxxx 2/2 Running
hami-scheduler-xxxxx 2/2 Running
老版本可能叫:
vgpu-device-plugin-xxxxx Running
vgpu-scheduler-xxxxx Running
HAMi 官方文档中也说明,如果 hami-device-plugin 和 hami-scheduler 都是 Running,说明安装成功。查看节点资源:
kubectl describe node master-01
重点看 Capacity 和 Allocatable:
Capacity:
nvidia.com/gpu: 10
Allocatable:
nvidia.com/gpu: 10
这里有个容易误解的点:
nvidia.com/gpu: 10
这不是说机器上有 10 张物理 GPU,而是 HAMi 把一张物理 GPU 按默认配置注册成了多个可分配的 vGPU 份额。HAMi 配置中 nvidia.deviceSplitCount 默认值是 10,含义是单张 GPU 默认最多允许分配给 10 个任务。所以在单卡 8G 的机器上看到 nvidia.com/gpu: 10 是正常现象。
六、HAMi 常用资源字段说明
HAMi 在 Pod 里主要通过下面几个资源字段控制 GPU 申请:
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 3000
nvidia.com/gpucores: 30
字段含义如下:
nvidia.com/gpu
表示申请 GPU/vGPU 设备分配实例。安装 HAMi 后,节点上看到的 nvidia.com/gpu 数量通常来自 HAMi 的 deviceSplitCount 配置。例如单卡默认可能显示为 10,但这个 10 不是 10 张物理 GPU,也不表示单个 Pod 可以从同一张物理 GPU 上申请多个 vGPU。
nvidia.com/gpumem
表示申请多少 GPU 显存。官方示例中 nvidia.com/gpumem: 3000 表示每个 vGPU 申请 3G 左右显存。
nvidia.com/gpumem-percentage
表示按百分比申请显存。例如 10 表示申请这张 GPU 约 10% 的显存。
nvidia.com/gpucores
表示申请 GPU core 的比例。例如 30 可以理解为申请约 30% 的 GPU 算力。
这里注意一点:
nvidia.com/gpumem 和 nvidia.com/gpumem-percentage 不要同时写在同一个容器里。
前者表示按固定显存大小申请,后者表示按百分比申请,二者选择一种即可。HAMi 官方显存示例中也明确说明,nvidia.com/gpumem 不能和 nvidia.com/gpumem-percentage 一起使用。
Kubernetes 里 GPU 这类扩展资源一般写在 limits 下。如果只写 limits,Kubernetes 会默认把 limit 当作 request 使用。Kubernetes 官方文档也说明,GPU 可以只写 limits;如果同时写 requests 和 limits,两者必须相等;不能只写 GPU requests 而不写 limits。
七、容易误解的点:nvidia.com/gpu: 2 不是从一张卡里拿 2 份 vGPU
前面在查看节点资源时,可以看到类似下面的结果:
Capacity:
nvidia.com/gpu: 10
Allocatable:
nvidia.com/gpu: 10
如果是单卡环境,这里很容易产生一个误解:
既然节点上显示 nvidia.com/gpu: 10,
是不是说明这一张物理 GPU 被切成了 10 份,
所以单个 Pod 写 nvidia.com/gpu: 2,
就是从这一张物理 GPU 里拿 2 份 vGPU?
这个理解是不对的。
HAMi 官方 FAQ 对这个问题有明确说明:deviceSplitCount: 10 表示一张物理 GPU 最多可以同时服务 10 个任务,但它并不表示一个任务可以从同一张物理 GPU 上申请多个 vGPU。当一个任务申请 nvidia.com/gpu: 2 时,HAMi 会把它解释为需要两个物理 GPU,而不是从同一张 GPU 上申请两个 vGPU。也就是说,下面这种写法:
resources:
limits:
nvidia.com/gpu: 2
可以简单理解为:
这个 Pod 需要 2 个 GPU/vGPU 设备分配实例,并且这 2 个实例不能来自同一张物理 GPU。
对于我的单卡环境来说,可以简单理解为这个 Pod 需要 2 张物理 GPU,所以无法调度成功。
而不是:
这个 Pod 需要从 1 张 GPU 里拿 2 个 vGPU 份额。
所以在单节点、单张 8G GPU 环境里,如果创建下面这个 Pod:
apiVersion: v1
kind: Pod
metadata:
name: hami-gpu-2-test
spec:
restartPolicy: Never
containers:
- name: cuda
image: nvidia/cuda:11.0.3-base-ubuntu18.04
command: ["bash", "-lc", "nvidia-smi && sleep 3600"]
resources:
limits:
nvidia.com/gpu: 2
nvidia.com/gpumem: 2000
nvidia.com/gpucores: 30
这个 Pod 无法调度成功。因为当前节点只有一张物理 GPU,而 Pod 申请的是 2 个 GPU/vGPU 设备分配实例。创建后查看 Pod:
kubectl get pod hami-gpu-2-test
一般会看到它处于 Pending 状态:
NAME READY STATUS RESTARTS AGE
hami-gpu-2-test 0/1 Pending 0 1m
继续查看事件:
kubectl describe pod hami-gpu-2-test
可以看到调度失败相关信息。这里要把两个概念分清楚:
deviceSplitCount
表示一张物理 GPU 最多允许多少个任务共享。
nvidia.com/gpu
表示这个 Pod 申请几个 GPU/vGPU 设备分配实例。
当单个 Pod 写成 nvidia.com/gpu: 2 时,HAMi 会按需要 2 个 GPU/vGPU 设备实例处理。
在单卡环境下,它无法从同一张物理 GPU 上拿到两个 vGPU。
HAMi FAQ 里也说明,vGPU 的设计目标是让多个任务共享同一张 GPU,而不是让一个任务在同一张 GPU 上绑定多个 vGPU。deviceSplitCount: 10 只是允许最多 10 个任务共享该 GPU,并不会增加真实的物理 GPU 资源。
所以,如果目标是:
一张 8G GPU 同时跑两个 Pod
正确做法不是创建一个 Pod 并写:
nvidia.com/gpu: 2
而是创建两个 Pod,每个 Pod 都申请:
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 3000
nvidia.com/gpucores: 30
也就是:
Pod A 申请 1 个 vGPU,3000MB 显存,30% GPU core。
Pod B 申请 1 个 vGPU,3000MB 显存,30% GPU core。
这样两个 Pod 才能共享同一张物理 GPU。
八、测试 1:运行一个基础 HAMi GPU Pod
先验证 HAMi 调度链路和容器内 GPU 可见性。
apiVersion: v1
kind: Pod
metadata:
name: hami-basic
spec:
restartPolicy: Never
containers:
- name: cuda
image: nvidia/cuda:11.0.3-base-ubuntu18.04
command: ["bash", "-lc", "nvidia-smi && sleep 3600"]
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 2000
nvidia.com/gpucores: 30
进入容器验证:
kubectl exec -it hami-basic -- nvidia-smi
如果正常,会看到类似下面的输出:
[HAMI-core Msg(...): Initializing.....]
Memory-Usage:
0MiB / 2000MiB
重点看容器里显示的总显存是否变成了你申请的值。例如这里申请的是 2000,那么容器内看到的显存上限应该接近 2000MiB。
九、测试 2:一张 8G 卡切给两个 Pod,每个 Pod 申请 3G 显存
测试目的:
验证两个 Pod 是否可以共享同一张 8G 物理 GPU。
每个 Pod 申请 3000MB 显存。
两个 Pod 总共申请 6000MB,小于 8G,所以理论上可以同时 Running。
YAML 如下:
apiVersion: v1
kind: Pod
metadata:
name: hami-gpumem-3000-1
spec:
restartPolicy: Never
containers:
- name: cuda
image: nvidia/cuda:11.0.3-base-ubuntu18.04
command: ["bash", "-lc", "nvidia-smi && sleep 3600"]
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 3000
nvidia.com/gpucores: 30
---
apiVersion: v1
kind: Pod
metadata:
name: hami-gpumem-3000-2
spec:
restartPolicy: Never
containers:
- name: cuda
image: nvidia/cuda:11.0.3-base-ubuntu18.04
command: ["bash", "-lc", "nvidia-smi && sleep 3600"]
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 3000
nvidia.com/gpucores: 30
分别进入两个 Pod:
kubectl exec -it hami-gpumem-3000-1 -- nvidia-smi
kubectl exec -it hami-gpumem-3000-2 -- nvidia-smi
预期结果:
两个 Pod 都能 Running。
两个 Pod 内执行 nvidia-smi 都能看到 GPU。
每个 Pod 内看到的 GPU 总显存大约是 3000MiB。
如果这两个 Pod 都能正常运行,说明 HAMi 已经可以把一张物理 GPU 按显存维度切给多个 Pod 使用。
十、测试 3:按显存百分比切分
除了直接写 nvidia.com/gpumem,HAMi 也支持通过 nvidia.com/gpumem-percentage 按百分比申请显存。例如 8G 显存的 GPU,申请 10%:
apiVersion: v1
kind: Pod
metadata:
name: hami-gpumem-percent-10
spec:
restartPolicy: Never
containers:
- name: cuda
image: nvidia/cuda:11.0.3-base-ubuntu18.04
command: ["bash", "-lc", "nvidia-smi && sleep 3600"]
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem-percentage: 10
nvidia.com/gpucores: 10
验证:
kubectl exec -it hami-gpumem-percent-10 -- nvidia-smi
预期结果:
容器内看到的总显存约等于整卡显存的 10%。
如果物理卡是 8192MiB,那么 10% 大约就是 819MiB。
这里建议 Pod 名字和百分比保持一致。比如资源里写的是 nvidia.com/gpumem-percentage: 10,Pod 名称就叫 hami-gpumem-percent-10,避免后面排查时看乱。
十一、测试 4:按 GPU core 百分比限制
nvidia.com/gpucores 可以理解为 HAMi 里用于申请 GPU 算力比例的字段。比如:
nvidia.com/gpucores: 30
可以简单理解为申请约 30% GPU core 算力。这里的 30 不是指 30 个物理 CUDA Core,而是 HAMi 定义的 GPU core 使用比例。测试 YAML:
apiVersion: v1
kind: Pod
metadata:
name: hami-gpucores-30
spec:
restartPolicy: Never
containers:
- name: cuda
image: nvidia/cuda:11.0.3-base-ubuntu18.04
command: ["bash", "-lc", "nvidia-smi && sleep 3600"]
env:
- name: GPU_CORE_UTILIZATION_POLICY
value: "force"
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 2000
nvidia.com/gpucores: 30
查看:
kubectl get pod hami-gpucores-30
kubectl exec -it hami-gpucores-30 -- nvidia-smi
这里要注意:
nvidia-smi 只能证明容器能看到 GPU,以及显存视图是否被限制。
如果要验证 gpucores 的算力限制,需要运行 CUDA 压测程序观察 GPU-Util,而不是只看 nvidia-smi。
HAMi 官方文档说明,nvidia.com/gpucores 是通过 time-slice 方式实现的,所以通过 nvidia-smi 查询 core utilization 时可能会有波动,不一定稳定卡在某一个固定数值。
十二、GPU_CORE_UTILIZATION_POLICY=force 是什么
在测试 HAMi 的 GPU core 限制时,经常会看到下面这个环境变量:
env:
- name: GPU_CORE_UTILIZATION_POLICY
value: "force"
这个配置不是 Kubernetes 原生字段,而是 HAMi 容器侧配置项,主要给容器里的 HAMi-core 使用。HAMi 官方配置文档把 GPU_CORE_UTILIZATION_POLICY 放在 Container Configs: Env 下面,也就是说它属于容器运行时侧的环境变量,不是 Kubernetes 原生资源字段。
要理解这个参数,关键是要把 HAMi 的两个阶段分开看:
第一阶段:调度阶段
HAMi scheduler 根据 Pod 里申请的 nvidia.com/gpu、nvidia.com/gpumem、nvidia.com/gpucores 判断当前节点、当前 GPU 是否还有足够资源。
第二阶段:容器运行阶段
Pod 启动以后,容器里的 CUDA/NVML 调用会受到 HAMi-core 的影响,从而让容器看到被分配后的 GPU 资源视图,并对显存、GPU core 等资源进行运行时控制。
先看 Pod 资源申请:
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 2000
nvidia.com/gpucores: 30
这几个字段首先会进入 HAMi 的调度逻辑。它表达的是:
这个 Pod 需要 1 个 GPU/vGPU 设备分配实例;
这个 Pod 需要 2000MB 左右显存;
这个 Pod 需要 30% GPU core 配额。
所以在调度阶段,HAMi scheduler 会根据这些资源申请去判断:
这张 GPU 的剩余显存是否足够;
这张 GPU 的剩余 core 配额是否足够;
这个 Pod 是否可以放到这张 GPU 上。
举个例子,假设一张 GPU 上已经有一个 Pod 申请了:
nvidia.com/gpumem: 3000
nvidia.com/gpucores: 70
这时候再来一个 Pod 申请:
nvidia.com/gpumem: 3000
nvidia.com/gpucores: 40
即使显存还够,也可能因为 GPU core 配额不够而无法调度。这个阶段的重点是:
nvidia.com/gpucores 用于调度层面的资源计算。
HAMi scheduler 会根据它判断这张 GPU 还能不能继续放这个 Pod。
但是,调度成功不代表容器运行时一定会强制把 GPU 利用率压到 30% 以下。因为调度器只负责“把 Pod 放到哪里”,Pod 真正运行起来以后,就进入了 HAMi-core 的运行时控制阶段。
也就是说:
nvidia.com/gpucores: 30
首先表示:调度时我申请 30% GPU core 配额。
GPU_CORE_UTILIZATION_POLICY=force
表示:容器运行起来以后,HAMi-core 也要强制按照 nvidia.com/gpucores 的值去限制 GPU core utilization。
这才是 GPU_CORE_UTILIZATION_POLICY=force 的重点。
12.1 不加 GPU_CORE_UTILIZATION_POLICY=force 时
如果只写:
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 2000
nvidia.com/gpucores: 30
而不写:
env:
- name: GPU_CORE_UTILIZATION_POLICY
value: "force"
那么 nvidia.com/gpucores: 30 仍然会参与 HAMi 的调度计算。HAMi scheduler 仍然会认为这个 Pod 申请了 30% GPU core,并用这个值判断当前 GPU 是否还有足够的 core 配额。
但是容器真正运行 CUDA 程序时,是否强制把 GPU core utilization 限制在 30% 以下,就取决于 HAMi-core 的默认策略。
不加 GPU_CORE_UTILIZATION_POLICY=force 时,
nvidia.com/gpucores 主要体现为调度层面的 core 配额申请。
HAMi scheduler 会用它判断资源够不够,
但容器运行阶段不一定适合用来强验证 core 限制效果。
12.2 加上 GPU_CORE_UTILIZATION_POLICY=force 时
如果写成:
env:
- name: GPU_CORE_UTILIZATION_POLICY
value: "force"
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 2000
nvidia.com/gpucores: 30
它的含义就是:
调度阶段:
HAMi scheduler 按照 30% GPU core 计算这个 Pod 是否可以调度。
运行阶段:
Pod 启动后,HAMi-core 也会根据 nvidia.com/gpucores 的值,对容器内 GPU core utilization 做限制。
HAMi 官方配置文档中对 force 的说明是:限制 core utilization 低于 nvidia.com/gpucores。
所以如果只是为了让 HAMi scheduler 做资源计算,写 nvidia.com/gpucores 就可以。
但如果是为了测试运行时 GPU core 限制效果,建议同时加上:
env:
- name: GPU_CORE_UTILIZATION_POLICY
value: "force"
这样测试目标更明确:
既验证调度层面的 GPU core 配额计算;
也验证容器运行时 HAMi-core 对 GPU core utilization 的限制。
12.3 default、force、disable 三种策略怎么理解
HAMi 官方配置中,GPU_CORE_UTILIZATION_POLICY 有三个常见取值:
default
默认策略。
force
强制限制 core utilization,使其低于 nvidia.com/gpucores。
disable
任务执行期间忽略 nvidia.com/gpucores 设置的利用率限制。
可以这样理解:
| 策略 | 调度阶段 | 容器运行阶段 |
|---|---|---|
default |
nvidia.com/gpucores 仍然参与调度计算 |
使用 HAMi-core 默认策略 |
force |
nvidia.com/gpucores 参与调度计算 |
HAMi-core 强制限制 core utilization |
disable |
nvidia.com/gpucores 仍然可能参与调度计算 |
运行时忽略 nvidia.com/gpucores 的利用率限制 |
这里最容易混淆的是 disable。如果写成:
env:
- name: GPU_CORE_UTILIZATION_POLICY
value: "disable"
它主要影响的是容器运行时阶段,意思是运行任务时忽略 nvidia.com/gpucores 设置的利用率限制。但是不要简单理解成:
disable 后调度阶段也完全不看 nvidia.com/gpucores。
调度阶段是否能放下这个 Pod,仍然取决于 HAMi scheduler 对 Pod 资源申请的计算。GPU_CORE_UTILIZATION_POLICY 这个环境变量重点影响的是容器运行时 HAMi-core 的行为。
十三、测试 5:指定 GPU 型号
HAMi 支持通过 Pod annotation 指定要使用的 GPU 型号。官方配置文档中 nvidia.com/use-gputype 的含义是:如果设置了这个 annotation,那么 Pod 分配到的设备类型必须是这里指定的类型。先查看本机 GPU 型号:
nvidia-smi --query-gpu=name --format=csv,noheader
示例:
NVIDIA GeForce RTX 3070 Ti Laptop GPU
然后写 YAML:
apiVersion: v1
kind: Pod
metadata:
name: hami-use-gputype-3070
annotations:
nvidia.com/use-gputype: "NVIDIA GeForce RTX 3070 Ti Laptop GPU"
spec:
restartPolicy: Never
containers:
- name: cuda
image: nvidia/cuda:11.0.3-base-ubuntu18.04
command: ["bash", "-lc", "nvidia-smi && sleep 3600"]
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 2000
nvidia.com/gpucores: 30
查看:
kubectl get pod hami-use-gputype-3070
kubectl exec -it hami-use-gputype-3070 -- nvidia-smi
预期结果:
如果 annotation 里的 GPU 型号和 nvidia-smi 查出来的型号一致,Pod 可以 Running。
十四、测试 6:指定 GPU UUID
HAMi 也支持通过 nvidia.com/use-gpuuuid 指定 GPU UUID。官方配置文档中说明,如果设置了 nvidia.com/use-gpuuuid,Pod 分配到的设备必须属于指定 UUID 列表。先查看 UUID:
nvidia-smi --query-gpu=index,name,uuid,memory.total --format=csv,noheader
示例:
0, NVIDIA GeForce RTX 3070 Ti Laptop GPU, GPU-998864a7-78d9-dbab-e122-4c37842ce7cf, 8192 MiB
把 UUID 写进 Pod annotation:
apiVersion: v1
kind: Pod
metadata:
name: hami-use-gpuuuid
annotations:
nvidia.com/use-gpuuuid: "GPU-998864a7-78d9-dbab-e122-4c37842ce7cf"
spec:
restartPolicy: Never
containers:
- name: cuda
image: nvidia/cuda:11.0.3-base-ubuntu18.04
command: ["bash", "-lc", "nvidia-smi && sleep 3600"]
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 2000
nvidia.com/gpucores: 30
验证:
kubectl get pod hami-use-gpuuuid
kubectl exec -it hami-use-gpuuuid -- nvidia-smi
在单卡环境里,指定正确 UUID 的意义主要是验证 annotation 是否生效。如果是多卡机器,这个功能更有用,可以指定任务只能跑到某一张或某几张 GPU 上。
十五、总结
这次在单节点 Kubernetes 环境中部署了 HAMi,并基于一张 8G NVIDIA GPU 做了几个基础测试。
整体来看,HAMi 的核心作用就是让 GPU 不再只能以整卡方式分配给一个 Pod,而是可以按显存、core、设备型号、设备 UUID 等维度进行更细粒度的调度和限制。
本次测试中需要重点记住几件事:
1. 部署 HAMi 前,宿主机必须先能正常执行 nvidia-smi。
2. 容器运行时必须配置 NVIDIA Container Toolkit。
3. HAMi 节点需要打 gpu=on 标签。
4. scheduler.kubeScheduler.imageTag 要和 Kubernetes Server 版本匹配。
5. 单卡环境下看到 nvidia.com/gpu: 10 是 HAMi 默认切分数量,不是 10 张物理卡。
6. nvidia.com/gpumem 可以按固定显存大小申请 GPU。
7. nvidia.com/gpumem-percentage 可以按百分比申请显存。
8. nvidia.com/gpumem 和 nvidia.com/gpumem-percentage 不要同时使用。
9. nvidia.com/gpucores 表示申请 GPU core 比例,不是 CUDA Core 数量。
10. GPU_CORE_UTILIZATION_POLICY=force 更适合用来测试 GPU core 运行时限制效果。
11. nvidia.com/use-gputype 和 nvidia.com/use-gpuuuid 可以用来做指定型号或指定卡调度。
12. 单个 Pod 写 nvidia.com/gpu: 2,不是从一张卡里拿 2 份 vGPU;在单卡环境里会无法调度。
对于单卡实验环境来说,HAMi 的价值很明显:一张 8G GPU 可以被多个测试 Pod 共享,不再因为一个小任务就独占整张卡。
更多推荐



所有评论(0)