找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1597

积分

0

好友

202

主题
发表于 2025-12-24 15:56:50 | 查看: 33| 回复: 0

RDMA in K8s

GPU 算力已经拉满,但网络却成了性能瓶颈?在大模型(LLM)的训练和推理场景中,传统 TCP/IP 网络固有的延迟和高昂的 CPU 开销,正严重制约着分布式计算集群的整体性能。RDMA 技术通过绕过内核、直接访问远程内存,能够显著降低网络延迟并释放 CPU 资源。本文将为你详细拆解在 Kubernetes 集群中启用 RDMA 能力的完整流程,从设备插件部署到性能基准测试,助力你的 AI 集群彻底释放硬件潜力。

1. 基本概念

RDMA (Remote Direct Memory Access) 是一种高性能网络通信技术,它允许网络中的一台计算机直接读取或写入另一台计算机的内存,而无需经过双方的操作系统内核或 CPU 干预。

1.1 核心特性

  • Zero Copy (零拷贝):应用程序能够直接将数据从用户空间传输到网络适配器,避免了内核空间与用户空间之间的数据复制。
  • Kernel Bypass (内核旁路):应用程序可以直接向网卡硬件提交命令,绕过操作系统内核协议栈,从而大幅降低通信延迟。
  • CPU Offload (CPU 卸载):网络传输的处理逻辑由智能网卡硬件承担,从而将宝贵的 CPU 资源归还给计算任务。

1.2 网络协议

RDMA 支持多种底层网络传输协议,主流的有以下三种:

  • InfiniBand (IB)
    • 专为高性能计算设计的网络标准。
    • 提供极高的吞吐量和极低的延迟。
    • 需要专用的 IB 交换机和网卡,成本较高,但性能最佳。
    • 采用基于信用的流控机制,确保无损传输。
  • RoCE (RDMA over Converged Ethernet)
    • 允许在标准的以太网上运行 RDMA 协议。
    • RoCE v1:基于以太网链路层(L2),只能在同一个二层广播域内通信,不可路由。
    • RoCE v2:基于 UDP/IP 协议(L3),可以跨三层网络路由,是目前数据中心的主流选择。需要交换机支持 PFC (优先级流控) 和 ECN (显式拥塞通知) 来保证无损传输。
  • iWARP (Internet Wide Area RDMA Protocol)
    • 基于 TCP/IP 协议栈实现 RDMA。
    • 利用 TCP 的可靠传输机制,对网络交换机要求较低(普通以太网交换机即可支持)。
    • 由于 TCP 协议栈本身的复杂性,其性能通常低于 IB 和 RoCE。

在 Kubernetes 环境中,我们的核心目标是将这些高性能网络能力安全、高效地暴露给 Pod 使用。

2. 背景与目标

随着大模型训练和推理需求的爆发式增长,分布式计算集群对网络带宽和延迟提出了前所未有的要求。在传统的 TCP/IP 网络架构中,数据传输需要经历操作系统内核的多次上下文切换和内存拷贝,这在 100Gbps 甚至更高带宽的场景下,会吞噬大量的 CPU 资源,并引入显著的延迟,最终成为 GPU 集群性能提升的瓶颈。

RDMA 技术正是为此而生。它允许应用直接访问远程节点的内存,完全绕开内核网络栈,从而实现高吞吐、低延迟和极低的 CPU 占用。然而,Kubernetes 原生并不直接支持 RDMA 设备的管理与调度。为了在 K8s 集群中充分利用 RDMA 硬件,我们需要解决以下几个关键问题:

  • 设备发现与管理:如何让 Kubernetes 调度器感知并管理物理节点上的 RDMA 设备(如 IB 卡、RoCE 网卡)。
  • Pod 资源配置:如何将 RDMA 设备挂载到 Pod 内部,使容器内的应用能够使用 IB Verbs API 进行通信。
  • 网络方案选择:在复杂的生产环境中,是否需要引入像 Multus CNI 这样的多网卡方案。
  • 性能验证:如何验证 RDMA 功能已正确启用,并测试其实际带宽与延迟是否达到预期。

本文将基于 NVIDIA Mellanox 官方维护的 k8s-rdma-shared-dev-plugin,详细介绍在 Kubernetes 中启用原生 RDMA 支持的完整流程与最佳实践。

3. 部署 device-plugin

推荐使用由 Mellanox 官方维护的 Device Plugin:k8s-rdma-shared-device-plugin

3.1 驱动安装

确保各个节点已安装对应版本的 MOFED/OFED 驱动及用户态库(如 libibverbsrdmacm 等)。驱动安装的具体步骤此处不赘述。

3.2 获取部署模板

首先克隆项目仓库:

git clone https://github.com/Mellanox/k8s-rdma-shared-dev-plugin.git

3.3 部署 Device Plugin

cd deployment/k8s/base
kubectl apply -k .

部署成功后,在 kube-system 命名空间中会出现名为 rdma-shared-dp-ds 的 DaemonSet。它会在每个节点上运行,负责挂载 RDMA 设备并向 API Server 注册可供调度的资源。

root@GB200-POD2-F06-Node05:~# kubectl -n kube-system get po|grep rdma
rdma-shared-dp-ds-vrswv                 1/1     Running   1 (27h ago)     31h
rdma-shared-dp-ds-zg242                 1/1     Running   1 (27h ago)     31h

3.4 配置

Device Plugin 的核心配置是一个 ConfigMap。默认配置可参考:configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: rdma-devices
  namespace: kube-system
data:
  config.json: |
    {
        "periodicUpdateInterval": 300,
        "configList": [
          {
             "resourceName": "hca_shared_devices_a",
             "rdmaHcaMax": 1000,
             "selectors": {
               "vendors": ["15b3"],
               "deviceIDs": ["1021"],
               "ifNames": ["ibp3s0"]
             }
           }
        ]
    }

关键字段说明:

  • resourceName:Pod 申请资源时使用的名称,建议自定义,例如 rdma/ib
  • rdmaHcaMax:单块物理网卡允许共享的 Pod 数量上限,默认为 1000。
  • selectors:定义由该 Device Plugin 接管的物理网卡筛选条件,是配置的核心。
    • vendors:设备厂商 ID,例如 Mellanox 为 15b3
    • deviceIDs:设备 ID,与具体 IB 卡型号相关,例如 ConnectX-7 为 1021
    • ifNames:网络接口名称。

接下来,我们详细介绍如何收集这些配置所需的信息。

4. 采集 RDMA 设备信息

4.1 列出 IB 设备

ls /sys/class/infiniband
mlx5_0  mlx5_1  mlx5_2  mlx5_3  mlx5_4  mlx5_5  mlx5_6  mlx5_7

4.2 关联网络接口

使用 ibdev2netdev 命令查看 IB 设备与网络接口的映射关系:

ibdev2netdev
mlx5_0 port 1 ==> ibp3s0 (Up)
mlx5_1 port 1 ==> ibP2p3s0 (Up)
mlx5_2 port 1 ==> enP6p3s0f0np0 (Up)
mlx5_3 port 1 ==> bond0 (Up)
mlx5_4 port 1 ==> ibP16p3s0 (Up)
mlx5_5 port 1 ==> ibP18p3s0 (Up)
mlx5_6 port 1 ==> enP22p3s0f0np0 (Up)
mlx5_7 port 1 ==> bond0 (Up)

从这里我们可以获取到配置中需要的 ifNames 参数,例如 mlx5_0 对应的接口名为 ibp3s0

4.3 获取 PCI 信息

使用 mst status -v 命令可以列出所有处于 UP 状态的网卡及其 PCI ID:

root@GB200-POD2-F06-Node05:~/lixd/rdma# mst status -v
MST modules:
------------
    MST PCI module loaded
    MST PCI configuration module loaded

PCI devices:
------------
DEVICE_TYPE             MST                           PCI              RDMA            NET                                                         NUMA
ConnectX7(rev:0)        /dev/mst/mt4129_pciconf0      0000:03:00.0    mlx5_0          net-ibp3s0                                                    0
...(其余输出省略)...

例如,mlx5_0 对应的 PCI ID 为 0000:03:00.0

4.4 查询厂商/设备 ID

根据上一步获取的 PCI ID,查询其详细的厂商和设备 ID:

lspci -n | grep 0000:03:00.0
0000:03:00.0 0207: 15b3:1021
  • 15b3:Mellanox/NVIDIA 的厂商 ID。
  • 1021:具体设备 ID(此处为 ConnectX-7)。

这里我们得到了配置所需的 vendorsdeviceIDs 参数。

4.5 生成 selectors

汇总以上信息,即可编写出完整的 selectors 配置。以下是一个配置多块网卡的示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: rdma-devices
  namespace: kube-system
data:
  config.json: |
    {
        "periodicUpdateInterval": 300,
        "configList": [
          {
             "resourceName": "hca_shared_devices_a",
             "rdmaHcaMax": 1000,
             "selectors": {
               "vendors": ["15b3"],
               "deviceIDs": ["1021"],
               "ifNames": ["ibp3s0"]
             }
           }
        ]
    }

更新 ConfigMap 后,需要重启 Device Plugin 的 DaemonSet 以使配置生效:

kubectl -n kube-system rollout restart ds rdma-shared-dp-ds

5. 验证

5.1 Node 资源验证

查看节点资源容量,确认 RDMA 资源已被成功注册:

kk describe node gb200-pod2-f06-node05 | grep Capacity -A 9

此时应该能在 Node 的描述信息中看到 rdma/hca_shared_devices_a 资源。

5.2 构建测试镜像

为了验证功能,我们需要一个包含 RDMA 测试工具的容器镜像。以下是一个基于 Ubuntu 的 Dockerfile 示例:

FROM ubuntu:22.04

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        perftest \
        ibverbs-utils \
        ibverbs-providers \
        libibumad3 \
        libibverbs1 \
        librdmacm1 \
        infiniband-diags \
        iproute2 && \
    rm -rf /var/lib/apt/lists/*

ENTRYPOINT ["sleep","infinity"]

构建并推送镜像:

docker build -t rdma-test:v1 .

也可直接使用已构建好的镜像:lixd96/rdma-test:latest

5.3 Pod 申请资源

创建一个 Pod,申请我们配置的 RDMA 资源:

apiVersion: v1
kind: Pod
metadata:
  name: mofed-test-pod
spec:
  restartPolicy: OnFailure
  containers:
  - image: rdma-test:v1
    name: mofed-test-ctr
    securityContext:
      capabilities:
        add: ["IPC_LOCK"]
    resources:
      limits:
        rdma/hca_shared_devices_a: 1
    command:
    - sh
    - -c
    - |
      ls -l /dev/infiniband /sys/class/infiniband /sys/class/net
      sleep 1000000

进入该 Pod,使用 ibv_devicesibv_devinfo 命令查看 RDMA 设备信息:

ibv_devices
ibv_devinfo

如果配置正确,Pod 内应该能识别到 mlx5_0 等 RDMA 设备。例如:

root@mofed-test-pod:/# ibv_devices
    device              node GUID
    ------              ----------------
    mlx5_0              7c8c090300c3cfee

root@mofed-test-pod:/# ibv_devinfo
hca_id: mlx5_0
    transport:          InfiniBand (0)
    fw_ver:             28.44.2524
    node_guid:          7c8c:0903:00c3:cfee
    sys_image_guid:     7c8c:0903:00c3:cfee
    vendor_id:          0x02c9
    vendor_part_id:     4129
    hw_ver:             0x0
    board_id:           NVD0000000054
    phys_port_cnt:      1
        port:   1
            state:          PORT_ACTIVE (4)
            max_mtu:        4096 (5)
            active_mtu:     4096 (5)
            sm_lid:         1
            port_lid:       1336
            port_lmc:       0x00
            link_layer:     InfiniBand

5.4 性能验证

为了全面评估 RDMA 性能,我们需要启动两个 Pod 进行点对点的带宽和延迟测试。

Pod 1 (Server):

apiVersion: v1
kind: Pod
metadata:
  name: rdma-server
spec:
  restartPolicy: OnFailure
  containers:
  - image: rdma-test:v1
    name: mofed-test-ctr
    securityContext:
      capabilities:
        add: ["IPC_LOCK"]
    resources:
      limits:
        rdma/hca_shared_devices_a: 1
    command:
    - sh
    - -c
    - |
      ls -l /dev/infiniband /sys/class/infiniband /sys/class/net
      sleep 1000000

Pod 2 (Client):

apiVersion: v1
kind: Pod
metadata:
  name: rdma-client
spec:
  restartPolicy: OnFailure
  containers:
  - image: rdma-test:v1
    name: mofed-test-ctr
    securityContext:
      capabilities:
        add: ["IPC_LOCK"]
    resources:
      limits:
        rdma/hca_shared_devices_a: 1
    command:
    - sh
    - -c
    - |
      ls -l /dev/infiniband /sys/class/infiniband /sys/class/net
      sleep 1000000

部署后查看 Pod 状态,确认它们运行在同一个节点上(或跨节点但 RDMA 网络可达):

rdma-server   1/1     Running   0          7m18s   172.25.114.16   gb200-pod2-f06-node05
rdma-client   1/1     Running   0          5m24s   172.25.114.38   gb200-pod2-f06-node05

5.4.1 带宽测试

使用 ib_write_bw 工具进行 RDMA 写带宽测试。

  1. rdma-server Pod 中启动服务端:
    ib_write_bw -d mlx5_0 -i 1
  2. rdma-client Pod 中启动客户端(其中 172.25.114.16rdma-server 的 IP):
    ib_write_bw -d mlx5_0 -i 1 172.25.114.16

    测试结果示例如下:

    ---------------------------------------------------------------------------------------
                    RDMA_Write BW Test
    Dual-port       : OFF          Device         : mlx5_0
    ...(输出省略)...
    ---------------------------------------------------------------------------------------
    #bytes     #iterations    BW peak[MB/sec]    BW average[MB/sec]   MsgRate[Mpps]
    65536      5000             46711.55            45733.81        0.731741
    ---------------------------------------------------------------------------------------

    测试结果显示带宽达到约 46 GB/s。假设使用的 IB 网卡为 400Gb/s(理论带宽约 50 GB/s),则该结果已接近硬件上限,证明 RDMA 已正常启用并发挥高性能。

5.4.2 延迟测试

使用 ib_write_lat 工具测试 RDMA 写操作的延迟。

  1. rdma-server Pod 中启动服务端:
    ib_write_lat -d mlx5_0 -i 1
  2. rdma-client Pod 中启动客户端:
    ib_write_lat -d mlx5_0 -i 1 172.25.114.16

    测试结果示例如下:

    ---------------------------------------------------------------------------------------
                    RDMA_Write Latency Test
    Dual-port       : OFF          Device         : mlx5_0
    ...(输出省略)...
    ---------------------------------------------------------------------------------------
    #bytes #iterations    t_min[usec]    t_max[usec]  t_typical[usec]    t_avg[usec]    t_stdev[usec]
    2       100          2.62           3.84         2.74               2.73           0.04

    测试结果显示,RDMA 的单向延迟约为 2.73 微秒,且标准差极小(0.04 微秒)。相比传统 TCP/IP 网络通常 50-100 微秒的延迟,RDMA 将延迟降低了 20-40 倍,充分体现了其在低延迟场景下的巨大优势。这对于追求极致性能的人工智能与高性能计算应用至关重要。

6. 是否需要 Multus CNI?

在 Kubernetes 中实施 RDMA 方案时,是否需要引入 Multus CNI 取决于具体的应用场景和网络架构需求。

6.1 不需要 Multus CNI 的场景

如果你的应用满足以下条件,通常不需要部署 Multus CNI:

  1. 仅需 IB Verbs API:应用(如 vLLM、NCCL)直接调用 RDMA 接口进行数据面通信,不依赖或仅少量依赖 IP 协议(可能仅用于控制面)。
  2. 使用 Shared Device Plugin:如本文所述,k8s-rdma-shared-dev-plugin 可以在不改变 Pod 网络命名空间结构的前提下,将 RDMA 设备文件(/dev/infiniband/*)安全地暴露给 Pod。
  3. 扁平网络架构:RDMA 网卡与 Kubernetes 集群的管理/业务网卡处于同一网络平面,或者可以接受 Pod 沿用宿主机的部分网络特性。

在这种模式下,Pod 依然通过默认 CNI(如 Calico、Flannel)获得 IP 地址进行常规通信,同时通过 Device Plugin 获得了访问底层 RDMA 硬件的能力。这是最简单、运维成本最低的方案。

6.2 需要 Multus CNI 的场景

如果存在以下需求,则建议引入 Multus CNI:

  1. 网络流量隔离:需要将 RDMA 数据流量与 Kubernetes 管理流量或其它业务流量进行严格的物理或逻辑隔离。
  2. 独立 IP 地址:需要为 RDMA 网卡分配独立的 IP 地址(例如在使用 IPoIB 或 RoCEv2 路由模式时),以便应用通过特定的 IP 进行绑定和通信。
  3. SR-IOV 场景:如果使用 SR-IOV 技术将物理网卡虚拟化为多个 VF(虚拟功能),并希望通过 sriov-cni 将 VF 直接透传给 Pod,那么通常需要 Multus CNI 来管理这个额外的网络接口。

6.3 结论

对于大多数基于 k8s-rdma-shared-dev-plugin 的 AI 分布式训练和推理任务,不需要额外部署 Multus CNI。直接通过 Device Plugin 暴露设备,配合应用层的 RDMA 库(如 NCCL)即可实现高性能通信。引入 Multus 会显著增加网络与系统配置的复杂性,应仅在确有强隔离、独立 IP 或 SR-IOV 透传需求时使用。

7. 小结

本文系统性地梳理了在 Kubernetes 集群中集成 RDMA 高性能网络的完整路径。从技术原理认知、硬件与驱动准备,到 Device Plugin 的部署、配置与验证,最后通过实际的性能压测数据证实了 RDMA 的卓越性能。

核心要点回顾:

  1. 技术价值:RDMA 通过零拷贝和内核旁路技术,从根本上解决了 TCP/IP 网络在高带宽场景下的 CPU 瓶颈与高延迟问题,是释放现代 GPU 集群算力潜力的关键云原生基础设施。
  2. 部署策略:对于常见的 AI 负载,使用 k8s-rdma-shared-dev-plugin 的共享模式是最为轻量、高效的方案。它无需对现有网络架构进行复杂改造,即可让 Pod 获得近乎原生的 RDMA 能力。
  3. 架构决策:在决定引入 Multus CNI 等高级网络方案前应进行审慎评估。若无强制性的网络隔离或独立 IP 需求,复用宿主机的网络栈并通过 Device Plugin 暴露设备,往往能在复杂性与性能之间取得最佳平衡。

随着云原生 AI 的持续演进,底层网络设施的性能优化变得愈发关键。熟练掌握 RDMA 在 Kubernetes 中的配置与管理,已成为构建高性能、低延迟 AI 计算平台的必备技能。未来,可以进一步探索 GPUDirect RDMA、SR-IOV 硬件虚拟化等更进阶的技术,以应对更大规模、更严苛延迟要求的计算挑战。




上一篇:Windows 10下VSCode配置C++开发环境详细教程
下一篇:2025年Google PMax广告投放复盘:智能化趋势下的消耗、ROAS与投放策略观察
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-12 02:46 , Processed in 0.230829 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表