K8s 基于 IB RDMA 网络加速大模型分布式训练的部署与测试指南

机器人
摘要
lomtom

环境说明

本文操作基于以下固定环境配置,执行前需确保集群环境与下述信息一致,或根据实际环境调整对应参数。

  • K8s 集群:版本为 v1.23.7,包含 1 个控制节点与 1 个工作节点,已提前安装 Node Feature Discovery(NFD)组件,用于节点硬件特性探测。
  • 操作系统:所有节点统一使用 Ubuntu 24.04 LTS 版本,确保系统内核与 IB 驱动兼容性。
  • 网络类型:采用 InfiniBand(IB)RDMA 网络,需提前完成物理网卡硬件部署与基础驱动安装。

安装k8s-device-plugin

k8s-device-plugin 用于实现 GPU 资源的容器化调度,需先配置容器运行时,再通过 Helm 部署插件,具体步骤如下。

安装 nvidia-container-toolkit

nvidia-container-toolkit 是 GPU 容器运行的基础依赖,需在所有节点执行安装命令(具体安装命令需参考 NVIDIA 官方文档,根据系统版本选择对应方式)。

配置 Container Runtime

  1. 执行命令配置 containerd 运行时,指定 nvidia 为 runtime 类型:
sudo nvidia-ctk runtime configure --runtime=containerd
  1. 编辑 containerd 配置文件,设置默认运行时为 nvidia:
sudo vi /etc/containerd/config.toml

在配置文件中找到以下层级,补充或修改 default_runtime_name 字段:

[plugins]
  [plugins."io.containerd.grpc.v1.cri"]
    [plugins."io.containerd.grpc.v1.cri".containerd]
      default_runtime_name = "nvidia"
  1. 重启 containerd 服务,使配置生效:
sudo systemctl restart containerd

配置 RuntimeClass

创建 RuntimeClass 资源,用于指定 GPU 容器的运行时,YAML 配置如下:

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: nvidia  # RuntimeClass 名称,后续 Pod 可通过此名称指定运行时
handler: nvidia  # 与 containerd 中配置的 runtime 名称对应

执行部署命令:kubectl apply -f runtimeclass-nvidia.yaml

安装 k8s-device-plugin

  1. 为节点添加 GPU 标识标签,便于插件识别 GPU 节点:
kubectl label nodes <节点名称> nvidia.com/gpu.present=true
  1. 添加 nvidia-device-plugin 的 Helm 仓库:
helm repo add nvdp https://nvidia.github.io/k8s-device-plugin
  1. 通过 Helm 安装插件,指定版本、镜像地址及关键参数:
helm install nvidia-device-plugin nvdp/nvidia-device-plugin \
  --version=0.17.4 \
  --namespace nvidia-device-plugin \
  --create-namespace \
  --set image.repository=swr.cn-east-3.myhuaweicloud.com/lomtom-common/k8s-device-plugin \
  --set compatWithCPUManager=true \  # 开启与 CPU Manager 的兼容性,优化资源调度
  --set migStrategy=mixed  # 支持 GPU MIG(多实例 GPU)模式,灵活分配 GPU 资源

IB RDMA 相关配置与部署

获取 IB 设备信息

在所有节点执行以下命令,获取 IB 网卡厂商 ID、设备 ID 及网卡名称,用于后续配置匹配。

  1. 查看 IB 网卡型号与 PCI 地址:
lspci | grep Mellanox

输出示例(本文环境使用 Mellanox ConnectX-6/7 系列网卡):

# lspci | grep Mellanox
19:00.0 Infiniband controller: Mellanox Technologies MT2910 Family [ConnectX-7]
3b:00.0 Infiniband controller: Mellanox Technologies MT2910 Family [ConnectX-7]
4c:00.0 Infiniband controller: Mellanox Technologies MT2910 Family [ConnectX-7]
5d:00.0 Infiniband controller: Mellanox Technologies MT2910 Family [ConnectX-7]
9b:00.0 Infiniband controller: Mellanox Technologies MT2910 Family [ConnectX-7]
a8:00.0 Infiniband controller: Mellanox Technologies MT28908 Family [ConnectX-6]
bb:00.0 Infiniband controller: Mellanox Technologies MT2910 Family [ConnectX-7]
cb:00.0 Infiniband controller: Mellanox Technologies MT2910 Family [ConnectX-7]
db:00.0 Infiniband controller: Mellanox Technologies MT2910 Family [ConnectX-7]
  1. 根据 PCI 地址(如 19:00.0)查询厂商 ID 与设备 ID:
lspci -n | grep 19:00.0

输出示例(需记录厂商 ID 15b3 与设备 ID 1021):

19:00.0 0302: 10de:2335 (rev a1)

创建 RDMA 设备配置 ConfigMap

通过 ConfigMap 定义 RDMA 资源的匹配规则,指定厂商 ID、设备 ID 及网卡名称,YAML 配置如下:

# 1. vendors 匹配 IB 网卡厂商 ID(需与 3.1 步骤获取结果一致)
# 2. deviceIDs 匹配 IB 网卡设备 ID(需与上一步骤获取结果一致)
# 3. ifNames 匹配节点上的 IB 网卡名称(需根据实际环境修改)
apiVersion: v1
kind: ConfigMap
metadata:
  name: rdma-devices
  namespace: kube-system
data:
  config.json: |
    {
        "periodicUpdateInterval": 300,
        "configList": [{
             "resourceName": "ib",
             "resourcePrefix": "rdma",
             "rdmaHcaMax": 1024,
             "selectors": {
               "vendors": ["15b3"],
               "deviceIDs": ["1021"],
               "ifNames": ["ibs11", "ibs13", "ibs15", "ibs17"]
             }
           }
        ]
    }

执行部署命令:kubectl apply -f rdma-devices-configmap.yaml

部署 RDMA 共享设备插件 DaemonSet

通过 DaemonSet 在所有节点部署 RDMA 设备插件,实现 RDMA 资源的探测与分配,YAML 配置如下:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: rdma-shared-dp-ds
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: rdma-shared-dp-ds
  template:
    metadata:
      labels:
        name: rdma-shared-dp-ds
    spec:
      hostNetwork: true
      priorityClassName: system-node-critical
      containers:
        - image: swr.cn-east-3.myhuaweicloud.com/lomtom-common/k8s-rdma-shared-dev-plugin:v1.3.2
          name: k8s-rdma-shared-dp-ds
          imagePullPolicy: IfNotPresent
          securityContext:
            privileged: true
          volumeMounts:
            - name: device-plugin
              mountPath: /var/lib/kubelet/device-plugins
              readOnly: false
            - name: plugins-registry
              mountPath: /var/lib/kubelet/plugins_registry
              readOnly: false
            - name: config
              mountPath: /k8s-rdma-shared-dev-plugin
            - name: devs
              mountPath: /dev/
      nodeSelector:
            nvidia.com/gpu.deploy.gpu-feature-discovery: "true"
      volumes:
        - name: device-plugin
          hostPath:
            path: /var/lib/kubelet/device-plugins
        - name: plugins-registry
          hostPath:
            path: /var/lib/kubelet/plugins_registry
        - name: config
          configMap:
            name: rdma-devices
            items:
            - key: config.json
              path: config.json
        - name: devs
          hostPath:
            path: /dev/

执行部署命令:kubectl apply -f rdma-shared-dp-daemonset.yaml

测试准备

部署测试 Pod(DaemonSet 方式)

通过 DaemonSet 在两个测试节点上创建 Pod,配置 IB 资源、权限及测试工具安装命令,YAML 配置如下:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-rdma
spec:
  selector:
    matchLabels:
        app: nginx
  template:
    spec:
      containers:
        - image: swr.cn-east-3.myhuaweicloud.com/lomtom-common/nginx:1.27
          name: nginx
          securityContext:
            capabilities:
              add: [ "IPC_LOCK" ]
          resources:
            limits:
              rdma/ib: "1"
          command:
            - sh
            - -c
            - |
              apt update && apt install -y ibverbs-utils perftest
              ls -l /dev/infiniband /sys/class/infiniband /sys/class/net
              sleep 100000

执行部署命令:kubectl apply -f nginx-rdma-daemonset.yaml

验证 Pod 状态

部署完成后,通过命令查看 Pod 运行状态与网络信息,确保 Pod 正常启动且分配 IB 资源,并且记录 Pod IP,用于后续测试:

  ~ kubectl get pod -o wide        
NAME          READY   STATUS    RESTARTS   AGE     IP               
nginx-rdma    1/1     Running   0          4m58s   100.125.224.132
nginx-rdma1   1/1     Running   0          4m58s   100.101.169.137

并且每个 Pod日志都会输出相应的Ib信息:

/dev/infiniband:
total 0
crw------- 1 root root 231,  64 Oct 19 00:05 issm0
crw------- 1 root root 231,  65 Oct 19 00:05 issm1
crw------- 1 root root 231,  66 Oct 19 00:05 issm2
crw------- 1 root root 231,  67 Oct 19 00:05 issm3
crw------- 1 root root 231,  68 Oct 19 00:05 issm4
crw------- 1 root root 231,  70 Oct 19 00:05 issm6
crw------- 1 root root 231,  71 Oct 19 00:05 issm7
crw------- 1 root root 231,  72 Oct 19 00:05 issm8
crw-rw-rw- 1 root root  10, 118 Oct 19 00:05 rdma_cm
crw------- 1 root root 231,   0 Oct 19 00:05 umad0
crw------- 1 root root 231,   1 Oct 19 00:05 umad1
crw------- 1 root root 231,   2 Oct 19 00:05 umad2
crw------- 1 root root 231,   3 Oct 19 00:05 umad3
crw------- 1 root root 231,   4 Oct 19 00:05 umad4
crw------- 1 root root 231,   6 Oct 19 00:05 umad6
crw------- 1 root root 231,   7 Oct 19 00:05 umad7
crw------- 1 root root 231,   8 Oct 19 00:05 umad8
crw-rw-rw- 1 root root 231, 192 Oct 19 00:05 uverbs0
crw-rw-rw- 1 root root 231, 193 Oct 19 00:05 uverbs1
crw-rw-rw- 1 root root 231, 194 Oct 19 00:05 uverbs2
crw-rw-rw- 1 root root 231, 195 Oct 19 00:05 uverbs3
crw-rw-rw- 1 root root 231, 196 Oct 19 00:05 uverbs4
crw-rw-rw- 1 root root 231, 198 Oct 19 00:05 uverbs6
crw-rw-rw- 1 root root 231, 199 Oct 19 00:05 uverbs7
crw-rw-rw- 1 root root 231, 200 Oct 19 00:05 uverbs8

/sys/class/infiniband:
total 0
lrwxrwxrwx 1 root root 0 Oct 14 08:58 mlx5_0 -> ../../devices/pci0000:15/0000:15:01.0/0000:16:00.0/0000:17:01.0/0000:19:00.0/infiniband/mlx5_0
lrwxrwxrwx 1 root root 0 Oct 14 08:58 mlx5_1 -> ../../devices/pci0000:37/0000:37:01.0/0000:38:00.0/0000:39:01.0/0000:3b:00.0/infiniband/mlx5_1
lrwxrwxrwx 1 root root 0 Oct 14 08:58 mlx5_2 -> ../../devices/pci0000:48/0000:48:01.0/0000:49:00.0/0000:4a:01.0/0000:4c:00.0/infiniband/mlx5_2
lrwxrwxrwx 1 root root 0 Oct 14 08:58 mlx5_3 -> ../../devices/pci0000:59/0000:59:01.0/0000:5a:00.0/0000:5b:01.0/0000:5d:00.0/infiniband/mlx5_3
lrwxrwxrwx 1 root root 0 Oct 14 08:58 mlx5_4 -> ../../devices/pci0000:97/0000:97:01.0/0000:98:00.0/0000:99:01.0/0000:9b:00.0/infiniband/mlx5_4
lrwxrwxrwx 1 root root 0 Oct 14 08:58 mlx5_5 -> ../../devices/pci0000:a7/0000:a7:01.0/0000:a8:00.0/infiniband/mlx5_5
lrwxrwxrwx 1 root root 0 Oct 14 08:58 mlx5_6 -> ../../devices/pci0000:b7/0000:b7:01.0/0000:b8:00.0/0000:b9:01.0/0000:bb:00.0/infiniband/mlx5_6
lrwxrwxrwx 1 root root 0 Oct 14 08:58 mlx5_7 -> ../../devices/pci0000:c7/0000:c7:01.0/0000:c8:00.0/0000:c9:01.0/0000:cb:00.0/infiniband/mlx5_7
lrwxrwxrwx 1 root root 0 Oct 14 08:58 mlx5_8 -> ../../devices/pci0000:d7/0000:d7:01.0/0000:d8:00.0/0000:d9:01.0/0000:db:00.0/infiniband/mlx5_8

/sys/class/net:
total 0
-rw-r--r-- 1 root root 4096 Oct 14 08:58 bonding_masters
lrwxrwxrwx 1 root root    0 Oct 14 08:58 eth0 -> ../../devices/virtual/net/eth0
lrwxrwxrwx 1 root root    0 Oct 14 08:58 lo -> ../../devices/virtual/net/lo
lrwxrwxrwx 1 root root    0 Oct 14 08:58 tunl0 -> ../../devices/virtual/net/tunl0

测试步骤

IB RDMA 读取速度测试(ib_read_bw)

  1. 服务端操作:打开终端 1,进入 IP 为 100.125.224.132 的 Pod(nginx-rdma),执行服务端命令,指定 IB 设备为 mlx5_0,启用所有端口并以 Gb/s 显示结果:
ib_read_bw -a -d mlx5_0 --report_gbits
  1. 客户端操作:打开终端 2,进入 IP 为 100.101.169.137 的 Pod(nginx-rdma1),执行客户端命令,连接服务端 IP 并保持参数一致:
ib_read_bw -d mlx5_0 --all --report_gbits 100.125.224.132
  1. 结果查看:待测试完成后,查看服务端输出的 “BW peak [Gb/sec]” 字段,记录读取速度峰值。

IB RDMA 写入速度测试(ib_write_bw)

测试步骤与读取速度测试一致,仅替换测试命令为 ib_write_bw:

  1. 服务端命令ib_write_bw -a -d mlx5_0 --report_gbits
  2. 客户端命令ib_write_bw -d mlx5_0 --all --report_gbits 100.125.224.132
  3. 结果查看:查看服务端输出的 “BW peak [Gb/sec]” 字段,记录写入速度峰值。

IB RDMA 读时延测试(ib_read_lat)

  1. 服务端操作:打开终端 1,进入 nginx-rdma Pod,执行服务端命令:
ib_read_lat -a -d mlx5_0
  1. 客户端操作:打开终端 2,进入 nginx-rdma1 Pod,执行客户端命令连接服务端:
ib_read_lat -a -d mlx5_0 100.125.224.132
  1. 结果查看:查看客户端输出的 “t_avg [usec]” 字段,记录平均读时延。

IB RDMA 写时延测试(ib_write_lat)

测试步骤与读时延测试一致,仅替换测试命令为 ib_write_lat:

  1. 服务端命令ib_write_lat -a -d mlx5_0
  2. 客户端命令ib_write_lat -a -d mlx5_0 100.125.224.132
  3. 结果查看:查看客户端输出的 “t_avg [usec]” 字段,记录平均写时延。

性能测试结果

测试项测试结果指令
IB RDMA 读取速度BW peak[355.37Gb/s]ib_read_bw
IB RDMA 写入速度BW peak[377.32Gb/s]ib_write_bw
IB RDMA 读时延测试t_avg[195.17 usec]ib_read_lat
IB RDMA 写时延测试t_avg[184.67 usec]ib_write_lat
  1. k8s-device-plugin官方仓库 🔗
  2. k8s-rdma-shared-dev-plugin官方仓库 🔗

标题:K8s 基于 IB RDMA 网络加速大模型分布式训练的部署与测试指南

作者:lomtom

链接:https://lomtom.cn/bk67xx0uta0io