跳转到文档内容
版本:下一个

在华为云云容器引擎 CCE 上安装 HAMi

本文介绍在华为云云容器引擎(CCE)的 NVIDIA GPU 节点上安装 HAMi 所需的 CCE 配置。其他通用步骤见安装前提条件和通过 Helm 在线安装。

准备 GPU 节点池​

创建 GPU 节点池之前,先安装 CCE AI 套件(NVIDIA GPU)插件,并保留默认驱动。无需部署 GPU Operator。保持 GPU 虚拟化关闭。

CCE AI 套件会在每个 GPU 节点上将 NVIDIA 驱动安装到 /usr/local/nvidia,并安装 NVIDIA Container Toolkit。它还会在 containerd 中添加 nvidia 运行时,但默认运行时仍为 runc。因此 HAMi 需要一个指向 nvidia 运行时的 RuntimeClass。可在 GPU 节点上运行以下命令确认:

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

输出应包含:

default_runtime_name = 'runc'
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.nvidia.options]
BinaryName = '/usr/bin/nvidia-container-runtime'

集群默认没有 RuntimeClass,由 HAMi Chart 创建。配置方法见准备 HAMi values 文件。

禁用 CCE 自带的 NVIDIA Device Plugin​

CCE AI 套件会在 GPU 节点上运行 Device Plugin,即 DaemonSet kube-system/nvidia-gpu-device-plugin。它与 HAMi 的 Device Plugin 通过同一个 kubelet socket 注册 nvidia.com/gpu,因此同一节点上只能有一个生效。两者同时运行的后果见 Pod 能看到整张 GPU。

CCE AI 套件会同时部署 Device Plugin(nvidia-gpu-device-plugin)和驱动安装组件(nvidia-driver-installer),控制台和 YAML 参数中都没有单独关闭 Device Plugin 的选项。这两个组件的 DaemonSet 都通过 accelerator 标签选择节点,CCE 会为 GPU 节点自动添加该标签,删除该标签会同时停止驱动安装。为 Device Plugin 的 DaemonSet 添加一条规则,跳过带有 gpu=on 标签的节点:

kubectl -n kube-system patch ds nvidia-gpu-device-plugin --type=json -p='[{"op":"add","path":"/spec/template/spec/affinity/nodeAffinity/requiredDuringSchedulingIgnoredDuringExecution/nodeSelectorTerms/0/matchExpressions/-","value":{"key":"gpu","operator":"NotIn","values":["on"]}}]'

然后为 GPU 节点添加标签。HAMi 的 Device Plugin 也通过该标签选择节点:

kubectl label node <node-name> gpu=on

如需为节点池中的所有节点(包括之后新增的节点)添加标签,可在 CCE 控制台的节点池配置中添加 Kubernetes 标签 gpu=on。

检查节点标签,并确认 Device Plugin 不再运行在该节点上,而驱动安装仍在运行:

kubectl get nodes -L accelerator,gpu
kubectl -n kube-system get ds nvidia-gpu-device-plugin ubuntu22-nvidia-driver-installer
NAME STATUS ROLES AGE VERSION ACCELERATOR GPU
192.168.0.3 Ready <none> 60m v1.36.2-r10-36.0.2.3 nvidia-t4 on

NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
nvidia-gpu-device-plugin 0 0 0 0 0 <none> 65m
ubuntu22-nvidia-driver-installer 1 1 1 1 1 <none> 65m

驱动安装 DaemonSet 的名称取决于节点的操作系统。

将 HAMi 镜像复制到 SWR​

HAMi Chart 会从 Docker Hub 和 registry.cn-hangzhou.aliyuncs.com 拉取镜像,无法访问公网的节点拉取不到。将这三个镜像复制到与集群同地域的容器镜像服务(SWR)中。

先创建组织,然后在一台能访问 Docker Hub 和 registry.k8s.io 的机器上,按推送镜像到镜像仓库在 SWR 控制台生成登录指令,并将其中的 docker login 换成 skopeo login 运行。

Chart 会将 kube-scheduler 镜像的 tag 设置为集群的 Kubernetes 版本。例如 kubectl version 显示 Server Version 为 v1.36.2-r0-36.0.13.6 时,tag 为 v1.36.2。

复制镜像,将 <地域> 替换为地域 ID(例如西南-贵阳一为 cn-southwest-2),并将 v1.36.2 替换为集群对应的 tag。--all 会复制镜像的所有平台:

skopeo copy --all docker://docker.io/projecthami/hami:v2.10.0 \
docker://swr.<地域>.myhuaweicloud.com/<组织名称>/hami:v2.10.0
skopeo copy --all docker://docker.io/liangjw/kube-webhook-certgen:v1.1.1 \
docker://swr.<地域>.myhuaweicloud.com/<组织名称>/kube-webhook-certgen:v1.1.1
skopeo copy --all docker://registry.k8s.io/kube-scheduler:v1.36.2 \
docker://swr.<地域>.myhuaweicloud.com/<组织名称>/kube-scheduler:v1.36.2

准备 HAMi values 文件​

将以下内容保存为 hami-cce-values.yaml,并替换 <地域> 和 <组织名称>:

global:
imagePullSecrets:
- default-secret
scheduler:
kubeScheduler:
image:
registry: swr.<地域>.myhuaweicloud.com
repository: <组织名称>/kube-scheduler
extender:
image:
registry: swr.<地域>.myhuaweicloud.com
repository: <组织名称>/hami
patch:
imageNew:
registry: swr.<地域>.myhuaweicloud.com
repository: <组织名称>/kube-webhook-certgen
devicePlugin:
runtimeClassName: nvidia
createRuntimeClass: true
image:
registry: swr.<地域>.myhuaweicloud.com
repository: <组织名称>/hami
monitor:
image:
registry: swr.<地域>.myhuaweicloud.com
repository: <组织名称>/hami

global.imagePullSecrets 使用 default-secret 拉取镜像。CCE 会在每个命名空间下创建该 Secret,其中包含从 SWR 拉取镜像的凭证,因此镜像仓库可以保持私有。见集群系统密钥说明。devicePlugin.runtimeClassName 和 devicePlugin.createRuntimeClass 会创建 nvidia RuntimeClass,并将其用于 HAMi 的 Device Plugin。HAMi 也会为申请 vGPU 资源的 Pod 设置该 RuntimeClass。

安装 HAMi​

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

helm install hami hami-charts/hami -n kube-system --version 2.10.0 -f hami-cce-values.yaml

hami-device-plugin 和 hami-scheduler 运行后,确认 RuntimeClass 已创建,并且 HAMi 调度器已持有选主租约:

kubectl get runtimeclass
kubectl -n kube-system get lease hami-scheduler
NAME HANDLER AGE
nvidia nvidia 29s

NAME HOLDER AGE
hami-scheduler hami-scheduler-57478c9db5-ttlrj_845424a5-33aa-4881-a744-9baa9090c26c 26s

然后确认 HAMi 已注册 GPU。devicePlugin.deviceSplitCount 默认为 10,因此一张 GPU 会上报 10 个 nvidia.com/gpu:

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

故障排查​

Pod 能看到整张 GPU​

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

恢复步骤:

  1. 按禁用 CCE 自带的 NVIDIA Device Plugin重新为该 DaemonSet 添加规则,等待该节点上的 nvidia-gpu-device-plugin 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. 重建在 CCE 的 Device Plugin 生效期间启动的 Pod。

HAMi 的 Device Plugin 反复重启​

如果 hami-device-plugin 处于 CrashLoopBackOff 状态,并且其 device-plugin 容器输出以下错误,说明没有设置 RuntimeClass:

E1011 04:44:38.399747 44144 factory.go:135] Incompatible strategy detected auto
E1011 04:44:38.399767 44144 factory.go:136] If this is a GPU node, did you configure the NVIDIA Container Toolkit?

此时容器使用默认的 runc 运行时,找不到 NVIDIA 驱动。按准备 HAMi values 文件设置 devicePlugin.runtimeClassName 和 devicePlugin.createRuntimeClass。

Device Plugin 日志中出现 NUMA 错误​

在只有一个 NUMA 节点的 g6.xlarge.4 实例上,hami-device-plugin 每次注册设备时都会输出以下错误:

E1011 05:13:54.908058 55835 register.go:168] "failed to get numa information from sysfs" idx=0
I1011 05:13:54.908089 55835 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 节点。在该实例上,内核为 GPU 上报 -1。HAMi 无法确定 NUMA 节点,于是输出这条错误并回退为 numa=0,与实际拓扑一致。设备仍以 health=true 注册成功,GPU 负载运行正常。在单 NUMA 节点的实例上可以忽略这条错误。

CNCFHAMi 是 CNCF 孵化项目