一张GPU卡跑两个AI任务:HAMi在Kubernetes上实现GPU虚拟化共享
【免费下载链接】HAMiHeterogeneous GPU Sharing on Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ha/HAMi
HAMi(Heterogeneous AI Computing Virtualization Middleware)是 Kubernetes 上的 GPU 虚拟化共享与异构加速器调度项目:多个 Pod 按显存和算力份额共用同一张卡,彼此隔离互不干扰。
🎬 从一个场景说起:小任务为什么独占整张卡
想象一台装着 4 张 V100(每张 32G)的节点。用户 A 的小训练任务每张卡只要 10G 显存,却得按整卡申请;用户 B 的推理服务每张卡要 20G,同样只能整卡占。传统整卡分配下,4 张卡全被两个任务拿走,每张卡还有一半显存闲着——集群利用率卡在 50%。
接入 HAMi 后,卡被按显存和算力份额切开:同样的负载只占 2 张卡,另外 2 张完整释放给新任务。应用不用改一行代码,GPU 利用率直接从 50% 翻到 100%。
🗺️ 一张图看懂HAMi:四个角色各管一摊
HAMi 的定位一句话:夹在 Kubernetes 调度生态和异构加速器之间的虚拟化层,提供虚拟化、共享、隔离、调度四种能力。
把四个组件想成四个角色,新手很快能建立直觉:
- Mutating Webhook 是门卫:Pod 提交时拦截请求,把设备参数写进 Pod;
- 调度器扩展器是裁判:做设备感知的过滤、评分与绑定,决定 Pod 上哪个节点、哪张卡;
- 设备插件是管家:执行 Allocate(),配置容器运行时看到的设备;
- 监控系统是保安:持续采集 vGPU 显存、核心利用率,喂给监控看板。
核心代码在 cmd/,调度器与设备插件分两个进程交付。
🔍 它是怎么干活的:一个Pod的完整旅程
现在你提交一个推理 Pod。kubectl apply 之后,请求先经过 Mutating Webhook 被"做上标记";接着 HAMi 调度器以每张卡当前的显存、核心占用为输入做过滤和评分,绑定后把分配结果写进 Pod 注解。节点上的设备插件监听到注解,调用 Allocate(),再借助容器内虚拟化组件(lib/ 下的 preload 库)接管进程的设备访问——容器里看到的是一块被限额的"虚拟 GPU",谁也抢不走别人的份额。最后监控系统把这个 vGPU 的用量采回指标系统,链路闭环。
共享显存怎么申请?资源声明里加几行就够了:
resources: limits: nvidia.com/gpu: 1 nvidia.com/gpumem: 3000 nvidia.com/gpucores: 30含义是占 1 张物理卡,但只给 Pod 3000MB 显存和 30% 的算力。完整写法见 examples/nvidia/default_use.yaml。
🛠️ 从零到一键装好:Helm部署五步走
动手前确认环境:NVIDIA 驱动 ≥ 440、容器运行时已把 nvidia 设为默认 runtime、Kubernetes ≥ 1.23、glibc ≥ 2.17、内核 ≥ 3.10、Helm > 3.0。
第一步给节点打标,随后添加仓库并安装:
kubectl label nodes <node-name> gpu=on helm repo add hami-charts https://project-hami.github.io/HAMi/ helm repo update helm install hami hami-charts/hami -n kube-system确认 hami-scheduler 和 hami-device-plugin 都 Running,再跑一个示例负载验证:
kubectl get pods -n kube-system kubectl apply -f examples/nvidia/default_use.yamlPod 起来、容器里能看到 GPU,说明全链路通了。Chart 在 charts/hami/,可按需调整 values。
🧩 进阶能力:调度策略怎么选,监控能看什么
策略实现在 pkg/scheduler/policy/,按你的目标选:
- binpack:把任务尽量塞进少数卡、少数节点,腾出空闲资源,适合追求利用率与降本;
- spread:把任务摊开、减少互相干扰,适合多租户要公平的场景;
- 拓扑感知:在支持的硬件上按 GPU 拓扑组合设备,降低跨 NUMA 通信开销,适合多卡训练;
- 动态 MIG:为支持的 NVIDIA 卡动态创建、缓存、回收 MIG 实例(见 docs/develop/dynamic-mig-lifecycle.md),适合不能被噪声干扰的稳定切片。
装完监控即默认开启,调度器默认在 31993 端口暴露指标,Prometheus 可直接抓取:
看板上能看到每个 vGPU 的显存、核心实时利用率与分配趋势。HAMi 还配了独立 WebUI:
资源概览、节点性能 Top5、GPU 类型分布都在这里,还能按 1 小时、1 天等时间窗回看使用率。排障时先看这两张图,多数"玄学"资源问题能直接定位。
📡 它适合谁:设备家族与三类典型场景
支持的加速器后端都在 pkg/device/ 下,覆盖 NVIDIA GPU、华为昇腾 NPU、寒武纪 MLU、海光 DCU、摩尔线程 GPU、沐曦 MetaX、天数智芯、昆仑芯、燧原 GCU、壁仞、AMD、AWS Neuron 等,异构集群可以用同一套调度分配流程管理。
三类适配场景:
- 私有云 AI 平台:把多类加速卡池化,按配额共享,统一入口、公平分配;
- 多租户服务:Notebook、训练、vLLM 推理跑在同一张卡池上,按显存与算力互相隔离;
- 科研与批量计算:与 Volcano、Kueue 等调度生态配合,支撑队列式批量 AI 负载。
🚑 常见坑与解法
设备插件起不来:hami-device-plugin 反复重启时,先查节点 gpu=on 标签是否打上,再确认容器运行时已把 nvidia 设为默认 runtime,Pod 日志里通常有明确原因。
调度不生效:Pod 能起但显存请求"没被认出来",多半是 hami-scheduler 没 Running 或 Webhook 没拦住请求,确认两者状态,并检查 YAML 是否正确声明了 gpumem / gpucores。
性能不达预期:先上看板判断是不是显存限额太小导致频繁抖动,再调整 limits 或在 binpack / spread 之间切换,同时确认驱动版本达标。
✍️ 写在最后
HAMi 做的事,本质是把"卡"变成"容量":加速器被切成可调度、可隔离的份额,小任务不再独占整卡,异构卡说同一种调度语言。它已是 CNCF 孵化项目,与 Volcano、Kueue、Prometheus 等生态工具可以顺畅搭配。想深入实现细节,把仓库拉下来从源码读起:
git clone https://gitcode.com/GitHub_Trending/ha/HAMi【免费下载链接】HAMiHeterogeneous GPU Sharing on Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ha/HAMi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考