跳转到文档内容
版本:v2.10.0

在腾讯云容器服务 TKE 上安装 HAMi

本文介绍在腾讯云容器服务(TKE)的 NVIDIA GPU 节点上安装 HAMi 所需的 TKE 配置。其他通用步骤见安装前提条件和通过 Helm 在线安装。

以下步骤已在如下环境中验证:

组件版本
节点类型TKE 原生节点(GN7.2XLARGE32,1 × Tesla T4)
操作系统TencentOS Server 3.1
Kubernetesv1.34.1-tke.8
容器运行时containerd 1.6.9-tke.9
NVIDIA 驱动580.126.20,CUDA 13.0.2,由 TKE 安装
HAMi2.10.0

准备 GPU 节点池​

创建节点池时,选择 GPU 机型和 GPU 驱动版本。TKE 会在节点上安装 NVIDIA 驱动和 NVIDIA Container Toolkit,因此无需部署 GPU Operator。保持 qGPU 共享处于关闭状态,本文在关闭该选项的情况下验证。

TKE 还会将 containerd 默认 runc 运行时的可执行文件设置为 nvidia-container-runtime。所有容器都会使用 NVIDIA 运行时,HAMi 无需配置 RuntimeClass。可在 GPU 节点上运行以下命令确认:

grep -A1 'runtimes.runc.options' /etc/containerd/config.toml

输出应包含:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
BinaryName = "nvidia-container-runtime"

由于 TKE 已将驱动直接安装在宿主机上(nvidia-smi 位于 /usr/bin,驱动库位于 /usr/lib64),因此需要将 HAMi 的 devicePlugin.nvidiaDriverRoot 设置为 /。配置方法见准备 HAMi values 文件。

禁用 TKE 自带的 NVIDIA Device Plugin​

TKE 会部署自带的 NVIDIA Device Plugin,即 DaemonSet kube-system/nvidia-device-plugin-daemonset。它运行在带有 nvidia-device-enable=enable 标签的节点上,TKE 会为 GPU 节点自动添加该标签。它与 HAMi 通过同一个 kubelet socket 注册 nvidia.com/gpu,因此同一节点上只能有一个生效。两者同时运行的后果见 Pod 能看到整张 GPU。

在 TKE 控制台编辑 GPU 节点池,设置以下 Labels:

键值作用
nvidia-device-enabledisable停止节点上 TKE 自带的 Device Plugin
gpuon让 HAMi 的 Device Plugin 选中该节点

勾选 对存量节点应用本次Label/Annotation/Taint更新,使节点池中已有的节点也生效。

也可以使用 kubectl 为单个节点设置标签:

kubectl label node <node-name> nvidia-device-enable=disable gpu=on --overwrite

检查节点标签,并确认 TKE 的 DaemonSet 不再调度到该节点:

kubectl get nodes -L gpu,nvidia-device-enable
kubectl -n kube-system get ds nvidia-device-plugin-daemonset
NAME STATUS ROLES AGE VERSION GPU NVIDIA-DEVICE-ENABLE
10.100.0.13 Ready <none> 59m v1.34.1-tke.8 on disable

NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
nvidia-device-plugin-daemonset 0 0 0 0 0 nvidia-device-enable=enable 66m

准备 HAMi values 文件​

TKE 节点默认没有公网 IP,除非 VPC 配置了 NAT 网关,否则只能从腾讯云内网拉取镜像。docker.io/projecthami/hami 不受影响,因为 TKE 已将 mirror.ccs.tencentyun.com 配置为 containerd 的 docker.io 镜像源;但 Chart 默认的 kube-scheduler 镜像来自 registry.cn-hangzhou.aliyuncs.com,这类节点无法访问该地址,hami-scheduler Pod 会报类似以下错误:

Failed to pull image "registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.34.1": ... dial tcp 120.55.105.209:443: i/o timeout

改用 TKE 的 ccr.ccs.tencentyun.com/tkeimages/hyperkube 镜像。该镜像包含 kube-scheduler 可执行文件,镜像 tag 与 TKE 的 Kubernetes 版本一致。在以下命令输出的 VERSION 列中查看集群版本:

kubectl get nodes

将以下内容保存为 hami-tke-values.yaml,并将 tag 替换为集群版本:

scheduler:
kubeScheduler:
image:
registry: ccr.ccs.tencentyun.com
repository: tkeimages/hyperkube
tag: v1.34.1-tke.8
devicePlugin:
nvidiaDriverRoot: /

安装 HAMi​

按通过 Helm 在线安装部署,并在安装命令中传入 values 文件:

helm install hami hami-charts/hami -n kube-system -f hami-tke-values.yaml

hami-device-plugin 和 hami-scheduler 运行后,确认 HAMi 已注册 GPU。devicePlugin.deviceSplitCount 默认为 10,因此一张 T4 会上报 10 个 nvidia.com/gpu:

kubectl get node <node-name> -o jsonpath='{.status.allocatable.nvidia\.com/gpu}{"\n"}'
10

故障排查​

Pod 能看到整张 GPU​

如果节点上 TKE 自带的 Device Plugin 与 HAMi 同时运行,最后注册的插件会接管 nvidia.com/gpu。当 TKE 的插件接管后,节点的 nvidia.com/gpu allocatable 会从 HAMi 上报的值(例如 10)降为物理 GPU 数量。新建的 Pod 可以正常启动,不会报错,但 HAMi 的限制不再生效。

恢复步骤:

  1. 按禁用 TKE 自带的 NVIDIA Device Plugin为节点设置 nvidia-device-enable=disable,等待该节点上的 nvidia-device-plugin-daemonset Pod 被删除。

  2. 重启 HAMi 的 Device Plugin,使其重新注册:

    kubectl -n kube-system rollout restart ds/hami-device-plugin
    kubectl -n kube-system rollout status ds/hami-device-plugin
  3. 确认节点的 nvidia.com/gpu allocatable 恢复为 HAMi 上报的值。

  4. 重建在 TKE 插件生效期间启动的 Pod。

Device Plugin 日志中出现 NUMA 错误​

在验证用的 T4 实例上,hami-device-plugin 每次注册设备时都会输出以下错误:

E0916 16:14:55.021458 83601 register.go:168] "failed to get numa information from sysfs" idx=0
I0916 16:14:55.021480 83601 register.go:204] Registered device id=0, memory=15360MB, type=NVIDIA-Tesla T4, numa=0, health=true

HAMi 从 /sys/bus/pci/devices/<bus-id>/numa_node 读取 GPU 所属的 NUMA 节点。当固件没有为该设备提供邻近域信息(ACPI _PXM)时,内核会把这个文件写成 -1,本文使用的这类单 NUMA 节点虚拟机实例正属于这种情况。HAMi 无法确定节点,于是输出这条错误并回退为 numa=0。可在 GPU 节点上运行以下命令查看:

nvidia-smi --query-gpu=pci.bus_id --format=csv,noheader |
tr 'A-F' 'a-f' | sed 's/^0000//' |
while read -r id; do echo "$id $(cat /sys/bus/pci/devices/$id/numa_node)"; done
0000:00:08.0 -1

该实例只有一个 NUMA 节点 node0,回退值与实际拓扑一致。设备仍以 health=true 注册成功,GPU 负载运行正常。在单 NUMA 节点的实例上可以忽略这条错误。

CNCFHAMi 是 CNCF 孵化项目