在 AWS 上虚拟化任意 GPU:HAMi 实现自由显存隔离

摘要:本指南在 AWS EKS 集群中创建两个 GPU 节点组(T4 和 A10G),自动安装 HAMi,并部署三个 vLLM 服务,借助自由显存隔离让每个节点上的多个服务共享同一块物理 GPU。你将看到 GPU 维度的装箱(binpack)效果:当资源允许时,多个 Pod 会共置在同一块 GPU 上。


为何在 AWS 上使用 HAMi?

HAMi 为 Kubernetes 带来了与 GPU 型号无关的虚拟化能力,覆盖从消费级到数据中心级的 GPU。在 AWS 上,这意味着你可以利用常见的 NVIDIA 实例(例如搭载 T4 的 g4dn.12xlarge、搭载 A10G 的 g5.12xlarge),然后切分 GPU 显存,在无需修改应用的情况下,安全地将多个 Pod 打包到同一块显卡上。

本演示中

  • 两个节点:一个 T4 节点,一个 A10G 节点(每个节点有 4 块 GPU)。
  • HAMi 在 Terraform apply 阶段通过 Helm 自动安装。
  • vLLM 工作负载仅申请部分 GPU 显存,因此两个 Pod 可在一块 GPU 上运行。

一键部署

代码库github.com/dynamia-ai/hami-ecosystem-demo

0)前置条件

  • Terraform 或 OpenTofu
  • AWS CLI v2(且 aws sts get-caller-identity 能成功执行)
  • kubectl、jq

1)配置 AWS 并安装 HAMi

git clone https://github.com/dynamia-ai/hami-ecosystem-demo.git
cd infra/aws
terraform init
terraform apply -auto-approve

完成后,使用输出配置 kubectl:

terraform output -raw kubectl_config_command
# 示例:
# aws eks update-kubeconfig --region us-west-2 --name hami-demo-aws

2)验证集群与 HAMi

检查 HAMi 组件是否在运行:

kubectl get pods -n kube-system | grep -i hami

示例输出:

hami-device-plugin-mtkmg             2/2     Running   0          3h6m
hami-device-plugin-sg5wl             2/2     Running   0          3h6m
hami-scheduler-574cb577b9-p4xd9      2/2     Running   0          3h6m

列出每个节点上已注册的 GPU(HAMi 会为节点添加库存注解):

kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}\t{.metadata.annotations.hami\\.io/node-nvidia-register}\n{end}'

示例输出:

ip-10-0-38-240.us-west-2.compute.internal GPU-f8e75627-86ed-f202-cf2b-6363fb18d516,10,15360,100,NVIDIA-Tesla T4,0,true,0,hami-core:GPU-7f2003cf-a542-71cf-121f-0e489699bbcf,10,15360,100,NVIDIA-Tesla T4,0,true,1,hami-core:GPU-90e2e938-7ac3-3b5e-e9d2-94b0bd279cf2,10,15360,100,NVIDIA-Tesla T4,0,true,2,hami-core:GPU-2facdfa8-853c-e117-ed59-f0f55a4d536f,10,15360,100,NVIDIA-Tesla T4,0,true,3,hami-core:
ip-10-0-53-156.us-west-2.compute.internal GPU-bd5e2639-a535-7cba-f018-d41309048f4e,10,23028,100,NVIDIA-NVIDIA A10G,0,true,0,hami-core:GPU-06f444bc-af98-189a-09b1-d283556db9ef,10,23028,100,NVIDIA-NVIDIA A10G,0,true,1,hami-core:GPU-6385a85d-0ce2-34ea-040d-23c94299db3c,10,23028,100,NVIDIA-NVIDIA A10G,0,true,2,hami-core:GPU-d4acf062-3ba9-8454-2660-aae402f7a679,10,23028,100,NVIDIA-NVIDIA A10G,0,true,3,hami-core:

部署演示工作负载

应用清单(两个 A10G 服务,一个 T4 服务):

kubectl apply -f demo/workloads/a10g.yaml
kubectl apply -f demo/workloads/t4.yaml
kubectl get pods -o wide

示例输出:

NAME                                       READY   STATUS    RESTARTS   AGE    IP            NODE                                        NOMINATED NODE   READINESS GATES
vllm-a10g-mistral7b-awq-5f78b4c6b4-q84k7   1/1     Running   0          172m   10.0.50.145   ip-10-0-53-156.us-west-2.compute.internal   <none>           <none>
vllm-a10g-qwen25-7b-awq-6d5b5d94b-nxrbj    1/1     Running   0          172m   10.0.49.180   ip-10-0-53-156.us-west-2.compute.internal   <none>           <none>
vllm-t4-qwen25-1-5b-55f98dbcf4-mgw8d       1/1     Running   0          117m   10.0.44.2     ip-10-0-38-240.us-west-2.compute.internal   <none>           <none>
vllm-t4-qwen25-1-5b-55f98dbcf4-rn5m4       1/1     Running   0          117m   10.0.37.202   ip-10-0-38-240.us-west-2.compute.internal   <none>           <none>

两个关键注解的作用

在 Pod 模板中,你会看到:

metadata:
  annotations:
    nvidia.com/use-gputype: "A10G"   # T4 演示中为 "T4"
    hami.io/gpu-scheduler-policy: "binpack"
  • nvidia.com/use-gputype 会限制调度到指定的 GPU 型号(例如 A10G、T4)。
  • hami.io/gpu-scheduler-policy: binpack 告知 HAMi,当内存/核心限制允许时,将 Pod 共置在 同一块物理 GPU 上(GPU 维度的装箱)。

显存隔离的请求方式

每个容器通过 HAMi 资源名称设置 GPU 内存限制,以便多个 Pod 能安全共享一块显卡:

  • 在 T4 上:nvidia.com/gpumem: "7500"(MiB),且有 2 个副本 ⇒ 两者都能在 16 GB 的 T4 上运行。
  • 在 A10G 上:每个部署的 nvidia.com/gpumem-percentage: "45" ⇒ 两个 Pod 能在 24 GB 的 A10G 上运行。

HAMi 会在容器内部和主机上强制执行这些限制,因此 Pod 不会超出分配的 GPU 内存。

预期结果:GPU 装箱

  • T4 部署vllm-t4-qwen25-1-5b,副本数为 2):两个副本都调度到 T4 节点上的同一块 T4 GPU。
  • A10G 部署vllm-a10g-mistral7b-awqvllm-a10g-qwen25-7b-awq):两者都部署在 A10G 节点上的同一块 A10G GPU(45% + 45% < 100%)。

如何验证共置与内存限制

容器内验证(nvidia-smi

# A10G 组
for p in $(kubectl get pods -l app=vllm-a10g-mistral7b-awq -o name; \
           kubectl get pods -l app=vllm-a10g-qwen25-7b-awq -o name); do
  echo "== $p =="
  # 显示 GPU UUID(共置检查)
  kubectl exec ${p#pod/} -- nvidia-smi --query-gpu=uuid --format=csv,noheader
  # 显示容器内的内存限制(总量)和当前使用情况
  kubectl exec ${p#pod/} -- nvidia-smi --query-gpu=name,memory.total,memory.used --format=csv,noheader
  echo
done

预期

  • 两个 A10G Pod 会打印 相同的 GPU UUID → 确认 共置在同一块物理 A10G 上。
  • 每个容器内的 memory.total 约为 A10G 显存的 45% (由于驱动/开销会略少,例如 约 10,3xx MiB),且 memory.used 保持在该限制以下。

示例输出:

== pod/vllm-a10g-mistral7b-awq-5f78b4c6b4-q84k7 ==
GPU-d4acf062-3ba9-8454-2660-aae402f7a679
NVIDIA A10G, 10362 MiB, 7241 MiB

== pod/vllm-a10g-qwen25-7b-awq-6d5b5d94b-nxrbj ==
GPU-d4acf062-3ba9-8454-2660-aae402f7a679
NVIDIA A10G, 10362 MiB, 7355 MiB
# T4 组(同一部署的 2 个副本)
for p in $(kubectl get pods -l app=vllm-t4-qwen25-1-5b -o name); do
  echo "== $p =="
    kubectl exec ${p#pod/} -- nvidia-smi --query-gpu=uuid --format=csv,noheader
    kubectl exec ${p#pod/} -- nvidia-smi --query-gpu=name,memory.total,memory.used --format=csv,noheader
  echo
done

预期

  • 两个副本会打印 相同的 T4 GPU UUID → 确认 共置在同一块 T4 上。
  • memory.total = 7500 MiB(来自 nvidia.com/gpumem: "7500"),且 memory.used 保持在其以下。

示例输出:

== pod/vllm-t4-qwen25-1-5b-55f98dbcf4-mgw8d ==
GPU-f8e75627-86ed-f202-cf2b-6363fb18d516
Tesla T4, 7500 MiB, 5111 MiB

== pod/vllm-t4-qwen25-1-5b-55f98dbcf4-rn5m4 ==
GPU-f8e75627-86ed-f202-cf2b-6363fb18d516
Tesla T4, 7500 MiB, 5045 MiB

快速推理检查

在本地端口转发每个服务并发送一个小请求。

T4 / Qwen2.5‑1.5B

kubectl port-forward svc/vllm-t4-qwen25-1-5b 8001:8000
curl -s http://127.0.0.1:8001/v1/chat/completions \
  -H 'Content-Type: application/json' \
  --data-binary @- <<'JSON' | jq -r '.choices[0].message.content'
{
  "model": "Qwen/Qwen2.5-1.5B-Instruct",
  "temperature": 0.2,
  "messages": [
    {
      "role": "user",
      "content": "用 2 个要点总结这封邮件,并草拟一句回复:\n\n主题:续费报价和单点登录\n\n嗨,团队,我们需要续费报价,倾向于月度账单,而且我们需要在本月底前完成单点登录。你们能确认时间安排吗?\n\n——亚历克斯"
    }
  ]
}
JSON

示例输出:

总结:
- 要求提供续费报价,倾向于月度账单。
- 需要在本月底前完成单点登录(SSO)。

回复:
谢谢你,亚历克斯。我会确保续费报价和单点登录请求都能及时处理。我们的目标是在本月底前准备好一切。

A10G / Mistral‑7B‑AWQ

kubectl port-forward svc/vllm-a10g-mistral7b-awq 8002:8000
curl -s http://127.0.0.1:8002/v1/chat/completions \
  -H 'Content-Type: application/json' \
  --data-binary @- <<'JSON' | jq -r '.choices[0].message.content'
{
  "model": "solidrust/Mistral-7B-Instruct-v0.3-AWQ",
  "temperature": 0.3,
  "messages": [
    {
      "role": "user",
      "content": "写一段 3 句话的每周更新,内容是关于借助内存限制改进 EKS 上的 GPU 共享。受众:非技术高管。"
    }
  ]
}
JSON

示例输出:

在我们持续优化云资源的过程中,很高兴地宣布,在增强 Amazon Elastic Kubernetes Service(EKS)上的 GPU 共享方面取得了重大进展。通过实施内存限制,我们确保 EKS 上每个支持 GPU 的 Pod 都被分配了一定量的内存,防止过度使用,提高了整体系统效率。此次更新将为我们的 GPU 密集型应用降低成本并提升性能,最终增强我们在市场上的竞争优势。

A10G / Qwen2.5‑7B‑AWQ

kubectl port-forward svc/vllm-a10g-qwen25-7b-awq 8003:8000
curl -s http://127.0.0.1:8012/v1/chat/completions \
  -H 'Content-Type: application/json' \
  --data-binary @- <<'JSON' | jq -r '.choices[0].message.content'
{
  "model": "Qwen/Qwen2.5-7B-Instruct-AWQ",
  "temperature": 0.2,
  "messages": [
    {
      "role": "user",
      "content": "你是一家电子商务商店的客户支持助理。\n\n任务:\n1) 阅读工单。\n2) 仅返回包含以下字段的有效 JSON:intent(意图)、sentiment(情绪)、order_id(订单号)、item(商品)、eligibility(资格)、next_steps(后续步骤)、customer_reply(客户回复)。\n3) 回复需友好、简洁且注重行动性。\n\n工单:\n\"订单 #A1234 — 你好,我26天前买了一双跑鞋。鞋太小了。可以换成10码吗?我下周末前需要用到。如有差价,我愿意支付。——杰米\""
    }
  ]
}
JSON

示例输出:

{
  "intent": "请求换货",
  "sentiment": "中性",
  "order_id": "A1234",
  "item": "跑鞋",
  "eligibility": "30 天内可换货",
  "next_steps": "我们可以为你更换 10 码的鞋子。请寄回当前的鞋子,我们会寄出新的。",
  "customer_reply": "谢谢!能请你确认一下邮寄详情吗?"
}

清理环境

cd infra/aws
terraform destroy -auto-approve

后续内容(系列短文)

  • 深入调度:GPU 与节点 装箱/分散、反亲和性、NUMA 感知NVLink 感知部署、UUID 固定。
  • 容器级监控:简单可复现的分配与使用情况检查;可共享的仪表盘。
  • 底层原理:HAMi 调度流程与 HAMi 核心的内存/计算限制(简明深入解析)。
  • DRA:社区积极开发中的功能;我们将介绍支持进展与计划
  • 生态演示:Kubeflow、vLLM 生产栈、Volcano、Xinference、JupyterHub。(vLLM 生产栈、VolcanoXinference已具备原生集成。)

HAMi 是异构 AI 计算虚拟化中间件(Heterogeneous AI Computing Virtualization Middleware)的缩写,是一种“一站式”架构,旨在管理 Kubernetes 集群中的异构 AI 计算设备,为异构 AI 设备提供共享能力和任务级资源隔离。HAMi 致力于提高 Kubernetes 集群中异构计算设备的利用率,为不同类型的异构设备提供统一的复用接口。目前,它是 CNCF 沙箱项目,并已被纳入 CNCF CNAI 类别技术图谱。

HAMi 异构计算支持架构图
图1: HAMi 异构计算支持架构图

Dynamia 以 CNCF HAMi 为核心基础,提供灵活、可靠、按需、弹性的 GPU 虚拟化和异构计算调度及统一管理全球解决方案。它可以以插件化、轻量级、非侵入的方式部署在任何公有云、私有云或混合云环境中,并支持 NVIDIA、昇腾、沐曦、寒武纪、海光、摩尔线程、壁仞等异构芯片。

网站:https://dynamia.ai
邮箱:info@dynamia.ai

分享这篇文章