使用HAMi 实现的容器环境 GPU 分割方案
由于项目需要,现有硬件宿主机搭载一块Ada6000 的显卡需要分给 20 个Kubernetes Pod 使用,使用方向是带有 GPU 加速的无头 Xorg,互相隔离,Xorg 开在 Pod 内部。
应用需求是 Pod 里面开的是 Unity RenderStreaming 云渲染,因此必须要有实际画面才可以。
关键问题在于,物理 GPU 仅有一块。已经尝试过但是失败的方案:
- 使用宿主机开机 Xorg,共享到所有 Pod,每个 Pod 开启自己的 Screen 作为隔离(失败,非当前活跃屏会黑屏)
- 将物理 GPU 投射到所有 Pod 中开启 Xorg(失败,一个 GPU 实例只能开启一个 Xorg 会话)
- 使用GPU-Operator 配置时间切片time-slicing,模拟有 20 个GPU 分配到 Pod(失败,time-slicing 开启的 GPU 启动 Xorg 会提示找不到设备)
- 使用vGPU 或MIG 技术(失败,卡不是数据中心卡不支持 MIG,vGPU 需要授权,暂时没有那个预算)
所以,在经过一番折磨后找到了Project-HAMi。
https://github.com/Project-HAMi/HAMi/
HAMi 的前身就是k8s-vgpu-scheduler,来自国内上市公司第四范式,一个专门做云原生的公司。
官方 README 的描述是:
HAMi(前身为 'k8s-vGPU-scheduler')是一个面向 Kubernetes 的异构设备管理中间件。它可以管理不同类型的异构设备(如 GPU、NPU、MLU、DCU 等),实现异构设备在 Pod 之间的共享,并基于设备拓扑和调度策略做出更优的调度决策。
HAMi 旨在消除不同异构设备之间的差异,为用户提供统一的管理接口,无需对应用程序进行任何修改。截至 2024 年 12 月,HAMi 除了在互联网、公有云、私有云等领域外,在金融、证券、能源、运营商、教育、制造业等垂直领域,也得到了广泛采纳。超过 40 家企业和机构不仅是最终用户,同时也是活跃的贡献者。
HAMi 支持软件级别的vGPU,提供设备资源共享、隔离的能力,并且不光支持NVIDIA GPU。官方 README 写的支持列表:
支持的设备 NVIDIA GPU 寒武纪 MLU 海光 DCU 天数智芯 GPU 摩尔线程 GPU 昇腾 NPU 沐曦 GPU
还是比较强力的。最关键的一点就是,软件级别的 vGPU 是不需要 NVIDIA 授权的。
在我的需求之中,我只需要把显卡分成 20 份,互相隔离不干扰地启动 Xorg 并使用 GPU 加速。这可以说是完美符合我的需求了。
部署HAMi
TipHAMi 仍然使用nvidia-device-plugin 作为容器与物理 GPU 的桥梁,所以建议先安装好GPU-Operator 后再安装 HAMi。
运行 NVIDIA 设备插件的前置条件如下:
- NVIDIA 驱动 >= 440
- nvidia-docker 版本 > 2.0
- containerd/docker/cri-o 容器运行时的默认运行时配置为 nvidia
- Kubernetes 版本 >= 1.18
- glibc >= 2.17 & glibc < 2.30
- 内核版本 >= 3.10
- helm > 3.0
接下来可以直接跟着官方的说明进行安装:
给所用的节点添加gpu=on 标记:
kubectl label nodes {nodeid} gpu=on
在 helm 中添加HAMi的仓库
helm repo add hami-charts https://project-hami.github.io/HAMi/
使用以下命令进行部署:
helm install hami hami-charts/hami -n kube-system
验证安装:
kubectl get pods -n kube-system
如果 vgpu-device-plugin 和 vgpu-scheduler pod 都处于 Running 状态,则安装成功。
Tip启动需要时间,必要可以多等会,五分钟左右
(以上摘自官方README)
安装整个过程没有任何其他操作,稍等片刻便能看到两个 Pod 处于正常运行状态了。
Warning请确保原本的device-plugin 是可以正常运行的,如果发现找不到 sock 等问题(尤其是 K3s 安装的),请先通过 values 解决绑定 sock 的问题。
默认情况下,GPU 会被分为10 个vGPU,并且使用
- nvidia.com/gpu 选定要分配的 vGPU 数量
- nvidia.com/gpumem 选定要分配的显存数量(M) 等。
Warning
- 如果提升 pod 权限,会导致分配失效,请勿设置securityContext
- vGPU 不能超过物理机实际 GPU 数量,但是可以通过仅设置显存和gpucores 的方式来要求分配 GPU,并且互相可以正确隔离。
修改配置
目前是默认分配 10 个vGPU,而笔者的需求是 20 个,因此需要修改一次设置。使用 helm 自带的滚动升级功能可以执行这个操作,并且在出问题时及时回滚。
helm upgrade hami hami-chart/hami \
-n kube-system \
--reuse-values \
--set devicePlugin.deviceSplitCount=20
(其他参数可以参考这里进行修改)
随后稍等片刻,就能从kubectl describe node 节点
方式看到新的 GPU 数量。