在 Azure Kubernetes Service 上安装 HAMi
本文介绍在 Linux NVIDIA GPU 节点池上安装经典 HAMi 所需的 AKS 配置:由 AKS 安装驱动,HAMi 是唯一的设备插件。需要 HAMi 2.10.0 或更高版本。本文不涉及 GPU Operator、Windows 节点池和 Node Auto Provisioning。
通用节点要求见安装前提条件。完成下文配置后,按通过 Helm 在线安装部署。CDI 配置见 NVIDIA CDI 支持。
AKS 会管理 HAMi webhook 的 namespaceSelector,并排除控制平面和 AKS 托管的命名空间,因此 HAMi 不会修改这些命名空间中的 Pod。本文设置 manageNamespaceSelector: false 以避免 Helm 所有权冲突(HAMi issue #2039),因此 Chart 的命名空间级 hami.io/webhook: ignore 标签和 whitelistNamespaces 不再生效。请改用 Pod 级的 hami.io/webhook: ignore 标签。
创建仅驱动的 GPU 节点池
AKS 将这种方式称为仅驱动(driver-only):AKS 安装 NVIDIA 驱动,Kubernetes 设备插件由你负责。请选择所在区域有配额且AKS 支持的 NVIDIA GPU 虚拟机规格。示例使用 Standard_NC4as_T4_v3。
完全托管 GPU 配置会安装一个声明 nvidia.com/gpu 的 NVIDIA 设备插件,与 HAMi 设备插件注册的资源相同,不能在同一批节点上同时运行。GPU 管理模式、驱动选择和 MIG 策略在节点池创建后无法修改。如果 gpuProfile.nvidia.managementMode 为 Managed,请创建新的仅驱动节点池替换。
请先使用较新的 Azure CLI,所需的 az 版本见准备工作。
创建专用的用户节点池。gpu=on 标签是 HAMi 的节点选择器,AKS 会在扩容、重置镜像和节点镜像升级创建的节点上重新应用:
az aks nodepool add \
--resource-group <resource-group> \
--cluster-name <aks-cluster> \
--name gpunp \
--mode User \
--node-count 1 \
--node-vm-size Standard_NC4as_T4_v3 \
--os-sku Ubuntu \
--node-osdisk-type Managed \
--labels gpu=on \
--node-taints sku=gpu:NoSchedule \
--gpu-driver Install \
--enable-managed-gpu=false
--gpu-driver Install 和 --enable-managed-gpu=false 选择仅驱动配置。请只把 gpu=on 标签用于 HAMi 管理的节点池。较旧的 Azure CLI 版本可能在 az aks nodepool show 中省略 managementMode,因此请从 ARM 响应中读取该配置:
az rest --method get \
--url "https://management.azure.com$(az aks nodepool show \
--resource-group <resource-group> --cluster-name <aks-cluster> \
--name gpunp --query id --output tsv)?api-version=2026-01-02-preview" \
--query properties.gpuProfile --output yaml
驱动必须为 Install,managementMode 必须为空或 Unmanaged。
确认没有其他插件管理该节点,下面两个值都必须为空:
kubectl get node <gpu-node> \
-o jsonpath='{.status.allocatable.nvidia\.com/gpu}{"\n"}{.metadata.labels.kubernetes\.azure\.com/dcgm-exporter}{"\n"}'
第一行有值,说明已有设备插件在声明 nvidia.com/gpu。第二行为 enabled,说明启用了完全托管栈。AKS 托管插件可能不会出现在 kubectl get daemonsets 中,因此不要只依赖该检查。
配置 HAMi Helm 值
将以下内容保存为 aks-values.yaml:
scheduler:
admissionWebhook:
manageNamespaceSelector: false
devicePlugin:
nvidiaDriverRoot: "/"
nvidiaNodeSelector:
kubernetes.azure.com/agentpool: gpunp
tolerations:
- key: sku
operator: Equal
value: gpu
effect: NoSchedule
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
manageNamespaceSelector: false让 AKS 管理 webhook 的namespaceSelector,避免 Helm server-side apply 冲突。见上文的限制说明。nvidiaDriverRoot: "/"使用节点主机上安装的驱动。nvidiaNodeSelector将 HAMi 设备插件限制在专用节点池。tolerations会替换 Chart 的默认值:该默认值在 Chart v2.10.0 中为空,在尚未发布的 v2.11.0 中仅包含nvidia.com/gpu:NoSchedule。该列表覆盖 AKS 的sku=gpu污点,以及部分节点镜像使用的nvidia.com/gpu污点。
使用该文件安装 Chart,之后每次 helm upgrade 也使用同一个文件:
helm repo add hami-charts https://project-hami.github.io/HAMi/
helm repo update hami-charts
helm upgrade --install hami hami-charts/hami \
--namespace kube-system \
--version 2.10.0 \
--values aks-values.yaml \
--wait
验证安装
确认 HAMi 已注册 GPU 并声明逻辑槽位。默认每个 GPU 对应 10 个 vGPU 时,单 GPU 节点会报告 10 个 nvidia.com/gpu 槽位。该配置项在已发布的 Chart v2.10.0 中为 devicePlugin.deviceSplitCount,在尚未发布的 Chart v2.11.0 中为 devices.nvidia.deviceSplitCount(见升级指南):
kubectl get node <gpu-node> \
-o jsonpath='{.metadata.annotations.hami\.io/node-nvidia-register}{"\n"}{.status.allocatable.nvidia\.com/gpu}{"\n"}'
AKS 会向 webhook 的 namespaceSelector 添加排除规则,使其跳过控制平面使用的命名空间,以及由 AKS 管理的命名空间。HAMi 的 webhook 不会修改这些命名空间中的 Pod。请先用以下命令查看集群中实际生效的选择条件,再选择符合条件的业务命名空间部署 HAMi 工作负载:
kubectl get mutatingwebhookconfiguration hami-webhook \
-o jsonpath='{.webhooks[0].namespaceSelector}{"\n"}'
运行一个申请 2048 MiB GPU 显存并容忍节点池污点的 Pod:
apiVersion: v1
kind: Pod
metadata:
name: hami-vgpu-test
namespace: <app-namespace>
spec:
restartPolicy: Never
nodeSelector:
kubernetes.azure.com/agentpool: gpunp
tolerations:
- key: sku
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: cuda
image: nvcr.io/nvidia/cuda:12.4.1-base-ubuntu22.04
command: ["sleep", "3600"]
resources:
limits:
nvidia.com/gpu: 1
nvidia.com/gpumem: 2048
nvidia.com/gpucores: 20
kubectl get pod hami-vgpu-test -n <app-namespace> -o jsonpath='{.spec.schedulerName}' 必须输出 hami-scheduler,kubectl exec -n <app-namespace> hami-vgpu-test -- nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 必须报告 2048 MiB,而不是物理显存。Pod 处于 Running 并不足以证明成功:webhook 的失败策略是 Ignore,webhook 连接失败时 Pod 会在没有 HAMi 调度器的情况下被创建。完整的显存限制测试见验证 HAMi 部署与 vGPU 行为。完成后删除测试 Pod。
HAMi-core 提供 CUDA 和 NVML 层面的软件隔离。它不是 MIG 那样的硬件边界,不应用于隔离互不信任的租户。
节点生命周期
AKS 会在扩容、重置镜像、修复和节点镜像升级时替换节点,因此不要通过 SSH 安装软件包或手动修改 containerd。每次节点池生命周期操作之后,请确认池中每个节点都处于 Ready,运行着 hami-device-plugin Pod,并且 hami.io/node-nvidia-register 注解非空,然后再接受工作负载。
自动扩缩容
请使用固定大小的节点池。HAMi 的 nvidia.com/gpu 是逻辑槽位数,nvidia.com/gpumem 和 nvidia.com/gpucores 不会发布到节点的 Capacity 或 Allocatable,上游 Cluster Autoscaler 在模拟扩容时也不会调用 HAMi 的调度器扩展。请手动规划 HAMi GPU 节点池的大小,或在生产使用前验证针对具体工作负载的方案。
GPU Operator、MIG 和 DRA
- GPU Operator: 上述流程不使用它。如果需要,请在使用
--gpu-driver None --labels gpu=on创建的单独节点池上,按 AKS GPU Operator 指南操作,在 Operator 的 values 中设置devicePlugin.enabled=false,并让其组件容忍sku=gpu污点。HAMi 设备插件只会运行在匹配devicePlugin.nvidiaNodeSelector的节点上,因此要让 HAMi 服务该节点池,请把选择器设为两个节点池共有的gpu: "on"标签,而不是节点池名称。请在创建节点池时用--labels设置该标签:AKS 会在新节点上重新应用,而用kubectl label添加的标签在节点被替换后会丢失。否则该节点池没有设备插件,也不会发布nvidia.com/gpu槽位。Operator 默认启用 CDI,因此还需参阅 NVIDIA CDI 支持,并在实际节点上确认驱动根目录和nvidia-ctk路径。 - MIG: AKS 托管 MIG 在创建节点池时设置配置和资源发布。除非已经验证过该组合,否则不要与 HAMi 动态 MIG 同时使用。
- DRA: HAMi-DRA 是独立的模型,不要与经典 HAMi 安装在同一批 GPU 上。见 HAMi-DRA 安装。
故障排查
HAMi 设备插件 Pod 处于 Pending
节点必须带有 kubernetes.azure.com/agentpool=<node-pool> 标签,其中 <node-pool> 应替换为实际节点池名称(本文为 gpunp)。同时,应在 Helm values 中为设备插件 Pod 配置对 sku=gpu:NoSchedule 污点的容忍。可通过 kubectl describe node <gpu-node> 查看节点标签和污点。
创建节点池时报告 OverconstrainedAllocationRequest
Azure 无法分配同时满足指定区域、虚拟机规格、磁盘类型和网络要求的资源。这不是 HAMi 导致的错误。上述命令使用 --node-osdisk-type Managed,避免临时 OS 磁盘的容量要求进一步限制资源分配。可以改用其他 AKS 支持的 GPU 虚拟机规格,或选择其他区域,并确认相应配额和可用容量充足。
设备插件无法发现 NVML 设备
用 kubectl logs -n kube-system -l app.kubernetes.io/component=hami-device-plugin --all-containers 查看设备插件日志。对于这种仅驱动路径,请保持 nvidiaDriverRoot: "/",不要把 GPU Operator 的路径复制进来。
Helm 升级报告 namespaceSelector 所有权冲突
请使用 HAMi 2.10.0 或更高版本,并设置 scheduler.admissionWebhook.manageNamespaceSelector: false。用 helm get values hami -n kube-system 确认已应用的值。
存在多个设备插件
相互竞争的插件不能共用节点。请找出来源:AKS 完全托管配置(managementMode 为 Managed,需要替换节点池)、GPU Operator(禁用其 devicePlugin 组件)或手动创建的 DaemonSet。
卸载
先删除或迁移 GPU 工作负载,再按卸载指南移除 HAMi:
helm uninstall hami --namespace kube-system
移除 HAMi 后,仅驱动节点池没有设备插件。在保留的节点池上运行 GPU 工作负载之前,请先安装标准 NVIDIA 设备插件,或删除该节点池:
az aks nodepool delete \
--resource-group <resource-group> \
--cluster-name <aks-cluster> \
--name gpunp