跳到主要内容

MT GPU Operator 使用指南

MT GPU Operator 是摩尔线程提供的 Kubernetes GPU 管理组件,用于在 Kubernetes 集群中管理和使用摩尔线程 GPU 设备。本文档介绍 GPU Operator 的基本操作、配置和维护方法。

在 Pod 中使用 GPU 或 sGPU

在 Pod 中使用 GPU

申请 GPU 资源时,只需在 Pod 的 resources.limits 中声明 mthreads.com/gpu 资源即可。以下示例创建一个使用普通 GPU 的 Pod:

$ cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: opencl-test
spec:
restartPolicy: OnFailure
nodeSelector:
kubernetes.io/arch: amd64
containers:
- name: opencl-test
image: "ubuntu:20.04"
imagePullPolicy: Always
command: ["sleep"]
args: ["3600"]
resources:
limits:
mthreads.com/gpu: 1
EOF

在 Pod 中使用 sGPU

要在 Kubernetes 中使用 sGPU,首先需要确保 GPU Operator 安装时已启用 sGPU 相关功能。通过开启 GPU scheduler 组件和 GPU Webhook 组件来支持 sGPU。

在 sGPU 上运行工作负载时,您需要在 Pod 规范中指定 sGPU 资源。以下是与普通 GPU 的资源配置差异:

spec:
containers:
- name: mtpytorch
image: ubuntu:20.04
command:
- "sleep"
args:
- "infinity"
resources:
limits:
- mthreads.com/gpu: 1
+ mthreads.com/sgpu-core: 1
+ mthreads.com/sgpu-memory: 2

sGPU 资源说明

sGPU 使用两种独立的资源类型,可以更精确地控制容器对 GPU 资源的使用。多个 sGPU 容器在共享 1 个 GPU 时,显存独占,但计算资源是根据权重分时复用,不做强隔离。

  • mthreads.com/sgpu-core:表示计算资源的时间片权重
  • mthreads.com/sgpu-memory:显存数量,以 512 MiB 为单位,设为 2 表示使用 1 GiB 显存

验证 GPU 是否可用

进入容器,安装 OpenCL 相关软件库,然后使用 mthreads-gmi 验证容器内是否可见 GPU:

$ kubectl exec -ti opencl-test bash
root@opencl-test:/# apt-get update && apt-get -y upgrade && apt-get install -y ocl-icd-libopencl1 opencl-headers clinfo
...
root@opencl-test:/# mthreads-gmi
Mon May 19 07:37:31 2025
---------------------------------------------------------------
mthreads-gmi:2.0.0 Driver Version:3.0.0
---------------------------------------------------------------
ID Name |PCIe |%GPU Mem
Device Type |Pcie Lane Width |Temp MPC Capable
| ECC Mode
+-------------------------------------------------------------+
0 MTT S4000 |00000000:01:00.0 |0% 7MiB(49152MiB)
Physical |16x(16x) |88C YES
| N/A
---------------------------------------------------------------

--------------------------------------------------------------
Processes:
ID PID Process name GPU Memory
Usage
+-------------------------------------------------------------+
No running processes found
--------------------------------------------------------------

检查组件

检查 ClusterPolicy 的状态是否就绪:

$ kubectl get clusterpolicy mt-gpu-cluster-policy -o yaml
...
status:
namespace: mt-gpu-operator
state: ready

如果 status 没有出现在 ClusterPolicy 中,这意味着一些组件还没有准备好,可检查 mt-controller-manager Pod 日志,或查询 Operator 各 Pod 的状态。

日志和命令输出会显示哪些组件还没有准备好,以下示例表明个别组件状态是有问题的:container-toolkit、operator-validator、gpu-feature-discovery、device-plugin 和 gpu-exporter。可以向支持人员报告以下结果和有问题的组件状态:

$ kubectl -n mt-gpu-operator get po -o wide
NAME READY STATUS RESTARTS AGE
kured-f94df 1/1 Running 0 62s
kured-k442c 1/1 Running 0 62s
kured-lgwt4 1/1 Running 0 62s
kured-xhd8d 1/1 Running 0 62s
mt-aiops-c988dc879-4pnst 1/1 Running 0 62s
mt-container-toolkit-daemonset-24w6f 1/1 Running 0 62s
mt-container-toolkit-daemonset-rtvr5 0/1 Init:Error 3 (43s ago) 62s
mt-controller-manager-7bbfbfc44c-zl9tr 2/2 Running 0 106s
mt-device-plugin-56hxn 0/1 Init:0/1 0 60s
mt-device-plugin-nqnnn 1/1 Running 0 61s
mt-driver-toolkit-89lsm 1/1 Running 0 62s
mt-driver-toolkit-nwv92 1/1 Running 0 62s
mt-gpu-exporter-fwqww 1/1 Running 0 60s
mt-gpu-exporter-jf26z 0/1 Init:0/1 0 60s
mt-gpu-feature-discovery-djh8g 0/1 Init:0/1 0 61s
mt-gpu-feature-discovery-p2csq 1/1 Running 0 61s
mt-gpu-webhook-5b58696885-2fqpg 1/1 Running 0 62s
mt-gpu-webhook-gen-secret-d9pl2 0/1 Completed 0 62s
mt-gpushare-scheduler-578d5595f9-h59rv 1/1 Running 0 62s
mt-operator-validator-mnlpt 0/1 Init:0/2 0 61s
mt-operator-validator-zzkgh 1/1 Running 0 61s
nfd-master-847694d746-5xw54 1/1 Running 0 63s
nfd-worker-bjg8v 1/1 Running 0 62s
nfd-worker-g8pdl 1/1 Running 0 62s
nfd-worker-vm2zx 1/1 Running 0 62s
nfd-worker-wl5j4 1/1 Running 0 62s
node-problem-detector-hq4lr 1/1 Running 0 62s
node-problem-detector-hztjz 1/1 Running 0 61s
node-problem-detector-j77rg 1/1 Running 0 61s
node-problem-detector-q7fmx 1/1 Running 0 62s

自定义 GPU 资源名

GPU 默认资源名为 mthreads.com/gpu,如用户有自定义需要,可通过以下步骤进行修改。

1. 确认旧资源已释放

确保没有 Pod 使用旧资源名:

mthreads.com/gpu

否则迁移可能无法完成。

2. 配置新资源名

执行:

kubectl edit clusterpolicy gpu-cluster-policy

spec.universalGPUDeviceController 下配置:

gpuResourceName: example.com/MTT-S5000-80G
gpuResourceNameMigration:
enabled: true
legacyResourceNames:
- mthreads.com/gpu
timeout: 30m

字段说明:

  • gpuResourceName:本轮期望注册给 kubelet 的整卡 GPU 资源名;为空时等价于 mthreads.com/gpu

  • legacyResourceNames:需要迁移和清理的旧整卡 GPU 资源名

  • enabled:启用旧整卡 GPU 资源名清理

  • timeout:资源名迁移的超时时间

资源名规则:

  • 格式:<DNS前缀>/<资源名称>,且只能包含一个 /

  • DNS 前缀:最长 253 字符,仅允许小写字母、数字、-.

  • 资源名称:最长 63 字符,允许大小写字母、数字、-_.

注意:不要在 args 中重复配置 --gpu-resource-name

3. 等待并确认迁移完成

迁移通常需要约 7 分钟

执行:

kubectl get clusterpolicy gpu-cluster-policy \
-o jsonpath='{.status.universalGPUDeviceController.gpuResourceNameMigration.phase}'

输出 Done 即表示迁移完成。

随后检查 Node,确认已注册新的 GPU 资源名:

kubectl describe node <node-name>

4. 更新业务 YAML

后续 GPU 工作负载统一使用新资源名:

resources:
requests:
example.com/MTT-S5000-80G: 1
limits:
example.com/MTT-S5000-80G: 1

注意:不要再提交使用 mthreads.com/gpu 的新工作负载。

5. 注意事项

  • 无需停止 kubelet

  • 不要手工删除 checkpoint 或 socket

  • 不要手动修改 Node Status

  • 首次迁移时,legacyResourceNames 填写原默认资源名 mthreads.com/gpu

驱动生命周期管理

用户可以通过配置 mthreads_v1alpha4_clusterconfig 文件(YAML 安装方式)或 mt-gpu-operator-custom-resources/values.yaml 文件(Helm 安装方式)来指定下载的驱动,该文件中承载的是 ClusterConfig CR。该 CR 的用途:

  • 指定需要安装哪些驱动程序。

  • 指定集群中 GPU 访问模式的比例。GPU 访问模式包括 GPU、sGPU、passthrough。

基本配置

您可以直接使用以下配置,无需修改。以下 ClusterConfig 对象表示集群中的节点需要安装 GPU 驱动(musa、libmtml.so)和 sGPU 驱动(sgpu),并为 100% 的 GPU 核心分配 sGPU 访问模式。

apiVersion: mthreads.com/v1alpha4
kind: ClusterConfig
metadata:
name: gpu-cluster-config
spec:
upgradePolicy:
autoUpgrade: false
allocateStrategy: all
drain:
deleteEmptyDir: false
enable: false
force: false
timeoutSeconds: 300
maxParallelUpgrades: 1
podDeletion:
deleteEmptyDir: false
force: false
timeoutSeconds: 300
waitForCompletion:
timeoutSeconds: 0
podSelector: ""
nodes:
- nodePoolName: node-pool-1
drivers:
- kind: musa
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: product-release
objectName: develop/20230607/musa_2023.06.07-D+4358+dkms+glvnd+Ubuntu_amd64.deb
md5sum: string
- kind: libmtml.so
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: release-ci
objectName: mtml/release_1.5/a9d889431_mtml_1.5.0-linux-R_amd64.deb
md5sum: string
- kind: sgpu
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: release-ci
objectName: cloud/sgpu/master/20230607/sgpu-dkms_1.1.1_amd64.deb
md5sum: string
clusterGpuTargetRatio:
sgpu: 100%
workspaceDir: /tmp
sgpuSpec:
"max_inst": "16"
"policy": "0"
"overcommit_ratio": "1.1"
"time_slice": "1"

驱动升级策略

在 mt-driver-toolkit 升级驱动过程中,需要考虑到每次驱动容器重启时,都必须卸载驱动内核模块,然后再次加载。因此,升级驱动程序时需要执行具体操作,包括以下步骤:

  • 如果 mtgpu 模块处于活动状态(/sys/module/mtgpu/refcnt 的值不为 0),则只能通过重新启动节点来卸载驱动程序。
  • 如果 mtgpu 模块未使用,driver-toolkit 会卸载旧的 mtgpu 驱动程序内核模块,这将禁止所有客户端使用 GPU 驱动程序。
  • 加载更新的 mtgpu 驱动程序内核模块。
  • Container-toolkit 将设置节点容器运行时。
  • 启用 GPU 驱动程序的客户端。

驱动升级配置选项

ClusterConfig 中的以下字段可用于配置 clusterconfig 控制器:

  • autoUpgrade 负责启用或禁用驱动程序升级策略。默认值为 false。当设置为 false 时,将忽略所有其他选项,并且即使更新了 ClusterConfig 对象中的 driversclusterGpuTargetRatioselector 字段,也不会启动升级过程。

  • maxParallelUpgrades 是可以并行升级的节点数。0 表示无限。默认值为 1。

  • allocateStrategy 指定哪个操作会触发为节点重新分配 GPU 角色,这个重新分配操作也会导致节点上的驱动重新安装:

    • all:指示当字段(clusterGpuTargetRatiodriversselectorsgpuSpecvgpuMedvWeight)更改时将采取的重新分配操作。
    • onClusterGpuTargetRatioUpdate 表示只有 clusterGpuTargetRatio 字段发生变化时才会触发重新分配。
    • onDriverUpdate 表示只有当 drivers 字段下的内容发生变化时才会触发重新分配。
    • onSelectorUpdate 表示只有当 selector 字段发生变化时才会触发重新分配。
    • onSgpuSpecUpdate 表示只有当 sgpuSpec 字段发生变化时才会触发重新分配。
    • onVgpuMdevWeightUpdated 表示只有当 vgpuMdevWeight 字段发生变化时才会触发重新分配。
  • drain 提供了用于驱逐节点的选项(类似于 kubectl drain)。驱逐仅在启用时使用,并且 podDeletion 无法删除所有正在使用 GPU 的 pod:

    • enable 负责在升级过程中启用和禁用节点耗尽。默认值为 false。
    • force 用于强制删除 pod,即使它们不受控制器(例如 ReplicationController、ReplicaSet、Job、DaemonSet 和 StatefulSet)管理。默认值为 false
    • timeoutSeconds 指定驱逐的最大等待时长。0 表示无穷大。当超时时,GPU Pod 将被强制删除。默认值为 300。
    • podSelector 用于过滤节点上的 pod。如果未设置,操作员将清空所有 Pod。
    • deleteEmptyDir 用于指定是否删除使用 emptyDir 卷的 pod。当 deleteEmptyDir 设置为 true 时,存储在 emptyDir 卷中的任何本地数据都将与 pod 一起删除。默认值为 false。
  • podDeletion 提供用于驱逐分配了 GPU 的 pod:

    • force 用于强制删除 pod,即使它们不受控制器(例如 ReplicationController、ReplicaSet、Job、DaemonSet 和 StatefulSet)管理。默认值为 false
    • timeoutSeconds 指定驱逐的最大等待时长。0 表示无穷大。当超时时,GPU Pod 将被强制删除。默认值为 300。
    • podSelector 用于过滤节点上的 pod。如果未设置,操作员将清空所有 Pod。
    • deleteEmptyDir 用于指定是否删除使用 emptyDir 卷的 pod。当 deleteEmptyDir 设置为 true 时,存储在 emptyDir 卷中的任何本地数据都将与 pod 一起删除。默认值为 false。
  • waitForCompletion 提供用于在升级节点上的驱动程序之前等待用户定义的 pod 组完成的选项:

    • timeoutSeconds 指定驱逐的最大等待时长。0 表示无穷大。当超时时,GPU Pod 将被强制删除。默认值为 300。
    • podSelector 指定选择器选中的 pod,如果 pod 处于 running 状态,则等待 timeoutSeconds 时间,超时后进入 podDeletion 阶段。

常用配置如下:

upgradePolicy:
autoUpgrade: false
maxParallelUpgrades: 1
allocateStrategy: all
drain:
enable: false
force: false
timeoutSeconds: 300
podSelector: ""
deleteEmptyDir: false
podDeletion:
force: false
timeoutSeconds: 300
deleteEmptyDir: false
waitForCompletion:
timeoutSeconds: 300
podSelector: ""

暂停驱动程序升级

如果要暂停集群中的自动驱动程序升级,请在 clusterconfig CR 中将 spec.upgradePolicy.autoUpgrade 设置为 false。通过这样做,整个调谐器将暂停升级。当然,也可以通过设置 spec.upgradePolicy.autoUpgradetrue 来恢复驱动升级。

跳过驱动程序升级

如果要跳过节点驱动升级,请使用 mthreads.com/driver-upgrade.skip=true 来标记 NodeConfig 对象(与节点同名)。

停止节点上的驱动程序安装

如果在驱动安装过程中节点出现环境问题,即使已经开始安装也可能无法成功。驱动程序安装过程包括以下步骤:

  • 验证节点上的驱动程序和 GPU 访问模式。
  • 清除节点的 GPU 访问模式。
  • 卸载所有旧驱动程序。
  • 下载新的驱动程序包。
  • 安装新驱动程序。
  • 执行 GPU 访问模式的 post install 步骤。

要在节点上检测到问题时暂时停止安装过程,您可以通过 mthreads.com/driver-install.stop=true 来标记 NodeConfig 对象(与节点同名)。问题解决后,您可以删除此标签,安装过程将自动恢复。

升级驱动相关的指标和事件

GPU Operator 生成多个指标,Prometheus 在升级过程中可以抓取这些指标。这些指标包括:

  • gpu_operator_driver_auto_upgrade_enabled: 是否启用驱动程序自动升级。如果启用则值为 1,如果未启用则值为 0。
  • gpu_operator_nodes_upgrades_in_progress: 当前正在升级的节点总数。
  • gpu_operator_nodes_upgrades_done: 已成功完成节点驱动程序升级的节点总数。
  • gpu_operator_nodes_upgrades_failed: 升级失败的节点总数。
  • gpu_operator_nodes_upgrades_available: 当前满足升级条件的节点总数。
  • gpu_operator_nodes_upgrades_pending: 待升级的节点总数。

在升级过程中,MT GPU Operator 将产生各种事件来报告状态或故障。以下示例是为升级单个 NodeConfig 对象而生成的一组事件。

$ kubectl describe nodeconfig yuzhou-system-product-name
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal DriverUpgrade 4m30s mt-gpu-operator Successfully updated nodeconfig state label to ValidateNode
Normal DriverUpgrade 3m30s (x2 over 3m30s) mt-gpu-operator Successfully updated nodeconfig state label to CordonRequired
Normal DriverUpgrade 3m28s mt-gpu-operator Successfully updated nodeconfig state label to WaitForJobsRequired
Normal DriverUpgrade 3m28s mt-gpu-operator Successfully updated nodeconfig state label to OperatorPodDisableRequired
Normal DriverUpgrade 3m27s mt-gpu-operator disable mt-gpu-operator deploy label successfully, node: yuzhou-system-product-name
Normal DriverUpgrade 3m26s mt-gpu-operator Successfully updated nodeconfig state label to DrainNodeRequired
Normal DriverUpgrade 2m49s (x3 over 2m49s) mt-gpu-operator Successfully drained the node
Normal DriverUpgrade 2m49s (x3 over 2m49s) mt-gpu-operator Successfully updated nodeconfig state label to UninstallRequired
Warning DriverUpgrade 2m39s mt-gpu-operator Failed to update nodeconfig state label to UploadDevicesRequired err: timed out waiting for the condition
Normal DriverUpgrade 2m29s (x2 over 2m49s) mt-gpu-operator Successfully updated nodeconfig state label to ClearRoleRequired
Normal DriverUpgrade 89s (x2 over 2m8s) mt-gpu-operator (combined from similar events): Successfully updated nodeconfig state label to TryInstallRequired
Normal DriverUpgrade 23s mt-gpu-operator Successfully updated nodeconfig annotation to [mthreads.com/driver-upgrade-wait-for-pod-completion-start-time null]=%!s(MISSING)
Normal DriverUpgrade 23s mt-gpu-operator Successfully updated nodeconfig state label to InstallRequired
Normal DriverUpgrade 22s mt-gpu-operator Successfully updated nodeconfig state label to ValidateNode
Warning DriverUpgrade 13s mt-gpu-operator Failed to update nodeconfig state label to UpgradeFailed err: timed out waiting for the condition

指定驱动

在 ClusterConfig CR 中,spec.nodes[0].drivers 是一个数组,用于配置节点上的驱动程序。以下 ClusterConfig 对象表示将在每个节点上安装 DEB 包和 sGPU 模块。

apiVersion: mthreads.com/v1alpha4
kind: ClusterConfig
metadata:
name: gpu-cluster-config
namespace: mt-gpu-operator
spec:
upgradePolicy:
...
nodes:
- nodePoolName: node-pool-1
specification: balanced-gpu
workspaceDir: /tmp
drivers:
- kind: musa
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: product-release
objectPrefix: develop/20221208
- kind: sgpu
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: release-ci
objectPrefix: cloud/sgpu/latest

驱动器种类

每个软件都有一个 kind 属性,kind 的值包括 musasgpulibmtml.somthreads-gmimt_peermem。支持的封装类型说明如下:

  • musa: 您可以指定 musa DEB 包,例如 musa_2022.08.22-M643.Ubuntu_amd64.deb
  • sgpu: 您可以指定一个包,例如 sgpu_km.ko 或 sgpu-dkms_1.1.1_amd64.deb。
  • libmtml.so: 您可以指定 libmtml.so 或 a9d889431_mtml_1.5.0-linux-R_amd64.deb 等软件包。
  • mthreads-gmi: 可以指定 mthreads-gmi 等包。
  • mt_peermem: 您可以指定 mt_peermem.ko 等文件。

驱动源

驱动源包括 OSS 服务器、HTTP 服务器、本地目录。以下各节分别介绍如何从这些来源获取包。

从 OSS 获取包

使用以下结构指定 OSS 上的包。

oss:
endpoint: oss.mthreads.com # oss domain or ip
id: string # oss user name
secret: string # oss password
useSSL: false # need ssl authentication or not
bucketName: product-release # bucket on oss
objectPrefix: master/20220810 # prefix under bucket
objectName: master/20220810/musa_2022.08.10-M397.Kylin_arm64.deb # objectName under bucket
md5sum: string # used to verify file

以下配置从 OSS 上的 product-release 存储桶中获取 master/20220810 前缀目录下的 DEB 包。

drivers:
- kind: musa
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: product-release
objectPrefix: master/20220810

上述配置没有指定 DEB 包。前缀文件夹(在本示例中为 master/20220810)可能包含不同体系结构和格式的多个 DEB 包,如下例所示。

$ mc ls oss/product-release/master/20220810
[2022-08-10 23:29:21 CST] 119B STANDARD musa_2022.08.10-M-B397_info.txt
[2022-08-10 23:29:22 CST] 32MiB STANDARD musa_2022.08.10-M397.Kylin_arm64.deb
[2022-08-10 23:29:23 CST] 34MiB STANDARD musa_2022.08.10-M397.Ubuntu_amd64.deb
[2022-08-10 23:29:23 CST] 34MiB STANDARD musa_2022.08.10-M397.Ubuntu_amd64.rpm
[2022-08-10 23:29:23 CST] 122MiB STANDARD musa_2022.08.10-M397.uos_arm64.deb

driver-toolkit 会根据所在节点的 Linux 发行版(Ubuntu 或 UOS)和架构来下载对应的 DEB 包。

或者,您也可以直接使用 objectName 指定要从 OSS 下载的 DEB 包。以下示例下载 master/20220810/musa_2022.08.10-M397.Ubuntu_amd64.deb。

drivers:
- kind: musa
oss:
bucketName: product-release
endpoint: oss.mthreads.com
id: string
secret: string
objectName: master/20220810/musa_2022.08.10-M397.Ubuntu_amd64.deb
useSSL: false
md5sum: string

如果要指定安装包的安装脚本,可以使用 installConfig 字段。在本例中,workspaceDir/tmp/tmp/umd+kmd/ 为下载文件解压后的文件夹:

workspaceDir: /tmp
drivers:
- kind: umd+kmd
oss:
id: string
secret: string
useSSL: false
bucketName: release-rc
objectPrefix: release_pkg/master
objectName: release_pkg/master/B1261_mtgpu_linux-x86-xorg-hw-release-kmd_e8aac23.tar.gz
md5sum: string
installConfig:
installCmd: /tmp/umd+kmd/mt_umd/x86_64-mtgpu_linux-xorg-release/install.sh
uninstallCmd: /tmp/umd+kmd/mt_umd/x86_64-mtgpu_linux-xorg-release/install.sh -u

从 HTTP 服务器获取包

以下配置从 HTTP 服务器下载 DEB 包。

drivers:
- kind: musa
http:
url: http://oss.mthreads.com/product-release/master/20220711/musa_2022.07.11-M215.Ubuntu_amd64.deb
md5sum: string

本地获取包

用户需要将该文件放在主机上的 /usr/data 目录下,然后配置 clusterconfig 对象,以下配置从本地的 /usr/data/mtgpu_linux-xorg-hw-20220707.tar.gz 获取包文件。

drivers:
- kind: musa
local:
filePath: /usr/data/mtgpu_linux-xorg-hw-20220707.tar.gz
md5sum: string

Selector 配置

Selector 用来指定需要安装驱动程序的节点。以下配置在标签为 kubernetes.io/hostname 键值为 k8s-masteruser-ubuntu 的节点上安装 drivers 字段中指定的驱动程序。

apiVersion: mthreads.com/v1alpha4
kind: ClusterConfig
metadata:
name: clustergpuconfig-sample
namespace: mt-gpu-operator
spec:
upgradePolicy:
...
nodes:
- nodePoolName: test
clusterGpuTargetRatio:
gpu: 80%
passthrough: 20%
workspaceDir: /tmp
drivers:
- kind: musa
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: product-release
objectPrefix: master/20220910
selector:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-master
- user-ubuntu

selector 字段是可选的。没有设置 selector 的 ClusterConfig 对象可能如下所示:

apiVersion: mthreads.com/v1alpha4
kind: ClusterConfig
metadata:
name: clustergpuconfig-sample
namespace: mt-gpu-operator
spec:
nodes:
- clusterGpuTargetRatio:
gpu: 80%
passthrough: 20%
workspaceDir: /tmp
drivers:
- kind: musa
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: product-release
objectPrefix: master/20220910

以上示例表示所有节点都可以安装在 product-release 存储桶的 master/20220910 前缀文件夹下的 musa 包。

节点打上用户指定的标签

在驱动安装完成后,用户可以使用 nodeDriverLabels 字段给节点打上指定标签。

apiVersion: mthreads.com/v1alpha4
kind: ClusterConfig
metadata:
name: clustergpuconfig-sample
namespace: mt-gpu-operator
spec:
nodes:
- clusterGpuTargetRatio:
...
nodeDriverLabels:
"musa-driver-version": "2.0.1"
"sGPU-version": "1.2.1"

分配 GPU 核心

分配 GPU 核心的意思是节点可能有多张卡,每张卡可能有 1-2 个核心,每个核心可以配置成普通 GPU 或 sGPU 设备,而 clusterconfig 对象中有字段可以控制集群中这些设备角色的比例。

方法一:指定 clusterGpuTargetRatio

您可以使用 clusterGpuTargetRatio 字段指定如何在集群中分配 GPU 核心。

apiVersion: mthreads.com/v1alpha4
kind: ClusterConfig
metadata:
name: clustergpuconfig-sample
namespace: mt-gpu-operator
spec:
upgradePolicy:
...
nodes:
- nodePoolName: node-pool-1
clusterGpuTargetRatio:
gpu: 80%
sgpu: 20%
workspaceDir: /tmp
drivers:
- kind: musa
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: product-release
objectPrefix: master/20220910

上述 ClusterConfig 对象表示 80% 的 GPU 核心分配给普通 GPU 容器,20% 分配为 sGPU 使用。

clusterGpuTargetRatio 结构如下:

clusterGpuTargetRatio:
gpu: string
passthrough: string
sgpu: string

注意:

  • 比例的格式必须满足 ^(100|[1-9]?\d(.)?)%$|0$/ 正则表达式。另外,比率之和必须等于 100%。

  • 在当前版本的 mt-gpu-operator 中,clusterGpuTargetRatio.passthrough 只能设置为低于 100% 的值。

  • clusterGPUTargetRatio 表示预期值。实际值取决于集群节点的状态。

  • 要将 GPU 核心分配为直通设备供虚拟机使用,您需要在 BIOS 中启用虚拟化扩展和 I/O 内存管理单元 (IOMMU) 扩展。

    对于 Intel:引导计算机并将 intel_iommu=on 附加到 grub 配置文件中 GRUB_CMDLINE_LINUX 行的末尾。

# vi /etc/default/grub
...
GRUB_CMDLINE_LINUX="nofb splash=quiet console=tty0 ... intel_iommu=on
...
# grub-mkconfig -o /boot/grub/grub.cfg
# reboot

对于 AMD:引导计算机,并将 amd_iommu=on 附加到 grub 配置文件中 GRUB_CMDLINE_LINUX 行的末尾。

# vi /etc/default/grub
...
GRUB_CMDLINE_LINUX="nofb splash=quiet console=tty0 ... amd_iommu=on
...
# grub-mkconfig -o /boot/grub/grub.cfg
# reboot

方法二:指定规格

为了便于配置比例,您可以指定 specification 而不是 clusterGpuTargetRatio,如下所示。

apiVersion: mthreads.com/v1alpha4
kind: ClusterConfig
metadata:
name: gpu-cluster-config
namespace: mt-gpu-operator
spec:
upgradePolicy:
...
nodes:
- nodePoolName: node-pool-1
drivers:
- kind: musa
oss:
bucketName: product-release
endpoint: oss.mthreads.com
id: string
objectPrefix: develop/20221208
secret: string
useSSL: false
- kind: sgpu
oss:
bucketName: release-ci
endpoint: oss.mthreads.com
id: string
objectPrefix: cloud/sgpu/latest
secret: string
useSSL: false
specification: balanced-gpu
workspaceDir: /tmp

上例中 specification 设置为 balanced-gpu,与下面的配置效果相同。

clusterGpuTargetRatio:
gpu: "33%"
sgpu: "33%"
passthrough: "34%"

specification 的有效值包括 gpu-onlysgpu-onlypassthrough-onlybalanced-gpu

指定 sgpuSpec

sgpuSpec 定义节点 sGPU 配置的 sGPU 参数。sGPU 有这些参数可以配置:max_instpolicytime_sliceovercommit_ratio。有关更多信息,请参阅 sGPU 文档。

sgpuSpec:
"max_inst": "16"
"policy": "0"
"overcommit_ratio": "1.1"
"time_slice": "1"

常见场景

ClusterConfig 对象主要用于以下场景:

  • 在所有节点上安装相同的驱动程序。
  • 在不同节点上安装不同的驱动程序。
  • 按比例分配 GPU 核心。

在所有节点上安装相同的驱动程序

Helm chart 中有一个 values.yaml 文件,用于安装 GPU 驱动。gpu-cluster-config 在 mtGpuClusterConfigClusterconfig.spec 中配置如下。

nodes:
- nodePoolName: test
drivers:
- kind: musa
oss:
bucketName: product-release
endpoint: oss.mthreads.com
id: string
objectPrefix: develop/20221208
secret: string
useSSL: false
- kind: sgpu
oss:
bucketName: release-ci
endpoint: oss.mthreads.com
id: string
objectPrefix: cloud/sgpu/latest
secret: string
useSSL: false
specification: balanced-gpu
workspaceDir: /tmp

在不同的节点上安装不同的驱动

使用 selector 选择应安装驱动程序的节点:

upgradePolicy:
allocateStrategy: all
autoUpgrade: false
drain:
deleteEmptyDir: false
enable: false
force: false
timeoutSeconds: 300
maxParallelUpgrades: 1
podDeletion:
deleteEmptyDir: false
force: false
timeoutSeconds: 300
waitForCompletion:
timeoutSeconds: 300
nodes:
- nodePoolName: node-pool-1
clusterGpuTargetRatio:
sgpu: 50%
passthrough: 50%
workspaceDir: /tmp
drivers:
- kind: musa
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: product-release
objectPrefix: master/20221101
- kind: sgpu
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: release-ci
objectPrefix: cloud/sgpu/latest
selector:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- nodename_1
- nodename_2
- nodePoolName: node-pool-2
clusterGpuTargetRatio:
gpu: 100%
workspaceDir: /tmp
drivers:
- kind: musa
oss:
endpoint: oss.mthreads.com
id: string
secret: string
useSSL: false
bucketName: product-release
objectPrefix: master/20221101
selector:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- nodename_3
- nodename_4

驱动基本运维

查询基本状态

如果驱动安装/升级失败,你可以通过以下命令查看驱动当前安装的状态:

$ kubectl get nodeconfig
NAME DRIVER UPGRADE STATE NODE POOL INSTALLATION TIMEOUT
node-1 InstallDone default
node-2 InstallDone default
node-3 InstallDone default

当驱动安装失败后,可以查看驱动升级的相关事件:

$ kubectl get events --sort-by='.lastTimestamp' | grep DriverUpgrade
...
5m28s Normal DriverUpgrade nodeconfig/node-1 (combined from similar events): Successfully updated nodeconfig state label to ValidateNode
5m19s Warning DriverUpgrade nodeconfig/node-1 Failed to update nodeconfig state label to UpgradeFailed err: timed out waiting for the condition
4m28s Normal DriverUpgrade nodeconfig/node-1 Successfully updated nodeconfig state label to WaitForJobsRequired
79s Normal DriverUpgrade nodeconfig/node-1 Successfully updated nodeconfig state label to InstallDone
29s Normal DriverUpgrade nodeconfig/node-2 Successfully updated nodeconfig state label to InstallDone
...

你也可以单独查看某一个节点上驱动安装事件:

$ kubectl describe nodeconfig <node-name>
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning DriverUpgrade 12s mt-gpu-operator 2024-01-19 03:29:06: failed reason: timed out waiting for the condition
Normal DriverUpgrade 12s mt-gpu-operator 2024-01-19 03:29:06: disable mt-gpu-operator deploy label successfully, node: yuzhou-system-product-name
Normal DriverUpgrade 12s mt-gpu-operator 2024-01-19 03:29:06: Successfully drained the node
Normal DriverInstall 12s mt-gpu-operator 2024-01-19 03:29:06: Success to clear gpu

升级失败

用户可以通过查看 mt-controller-manager 日志来定位问题:

kubectl logs mt-controller-manager-xxx-xxx | grep controllers.NodeConfig

在解决升级失败问题后,可以通过将 NodeConfig 标签设置为升级所需的状态来继续升级过程。

$ kubectl label node <node-name> mthreads.com/gpu-driver-upgrade-state=UpgradeRequired --overwrite

节点卡在 RebootNodeRequired 状态

如果节点长时间卡在 RebootNodeRequired 状态:

$ kubectl get nodeconfig
node-1 RebootNodeRequired

可能是由 Kured 导致的问题。在重启节点之前,Kured 会尝试驱逐节点上的负载,但这一步骤可能会失败。用户可以通过查看节点上的注解和标签来确定 Kured 是否卡在驱逐阶段:

$ kubectl describe node <node-name> | grep reboot
mthreads.com/node-need-reboot=true
weave.works/kured-most-recent-reboot-needed: 2024-01-18T04:58:47Z
weave.works/kured-reboot-in-progress: 2024-01-18T04:58:47Z

这些标签和注解是由 Kured 创建的:

  • mthreads.com/node-need-reboot=true:表示节点需要重启。
  • weave.works/kured-most-recent-reboot-needed: 2024-01-18T04:58:47Z:表示上一次由 Kured 触发节点重启的时间。
  • weave.works/kured-reboot-in-progress: 2024-01-18T04:58:47Z:表示当前 Kured 正在处理节点,可能正在驱逐节点上的负载。

若希望在 Kured 驱逐失败时强制重启节点,在 ClusterPolicy 中添加 Kured 强制重启的参数:

kured:
enabled: true
args:
...
- --force-reboot=true