告别 TCP/IP 延迟:Kubernetes 中的 RDMA 高性能网络实战

RDMA in K8s

GPU 算力拉满了,网络却成了瓶颈?在大模型训练和推理场景中,传统 TCP/IP 网络的延迟和 CPU 开销正在严重制约集群性能。RDMA 技术通过绕过内核直接访问内存,降低网络延迟。本文将手把手教你在 Kubernetes 中启用 RDMA 能力,从 Device Plugin 部署到性能验证,让你的 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:基于以太网链路层协议,只能在同一个二层广播域内通信,不可路由。
    • RoCE v2:基于 UDP/IP 协议,可以跨三层网络路由,是目前数据中心的主流选择。需要交换机支持 PFC (Priority Flow Control) 和 ECN (Explicit Congestion Notification) 以保证无损传输。
  • iWARP (Internet Wide Area RDMA Protocol)
    • 基于 TCP/IP 协议栈实现 RDMA。
    • 利用 TCP 的可靠传输机制,对网络设备要求较低(普通以太网交换机即可)。
    • 由于 TCP 协议栈的复杂性,性能通常低于 IB 和 RoCE。

在 Kubernetes 环境中,我们通常关注如何将这些高性能网络能力暴露给 Pod 使用。

2. 背景与目标

随着大模型(LLM)训练和推理需求的爆发式增长,分布式计算集群对网络带宽和延迟提出了极高的要求。在传统的 TCP/IP 网络架构中,数据传输需要经过操作系统内核的多次上下文切换和内存拷贝,这在高带宽(如 100Gbps+)场景下会消耗大量的 CPU 资源,并引入不可忽视的延迟,成为制约 GPU 集群性能的瓶颈。

为了解决这一问题,RDMA (Remote Direct Memory Access) 技术被广泛应用。它允许应用程序直接访问远程节点的内存,绕过内核网络栈,从而实现高吞吐、低延迟和低 CPU 占用。

然而,Kubernetes 原生并不直接支持 RDMA 设备的管理和调度。为了在 Kubernetes 集群中充分利用 RDMA 硬件能力,我们需要解决以下关键问题:

  • 设备发现与管理:如何将物理节点的 RDMA 设备(如 IB 卡、RoCE 网卡)暴露给 Kubernetes 调度器。
  • Pod 配置:如何将 RDMA 设备挂载到 Pod 内部,使其能够使用 IB Verbs API 进行通信。
  • 网络方案选择:在复杂的网络环境中,是否需要引入 Multus CNI 等多网卡方案。
  • 性能验证:如何验证 RDMA 功能是否正常开启,并测试实际带宽是否达标。

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

3. 部署 device-plugin

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

3.1 驱动安装

确保节点已安装对应版本的 MOFED/OFED 驱动及用户态库(libibverbsrdmacm 等)。驱动安装方式本文不赘述。

3.2 获取部署模板

先 clone 项目:

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

3.3 部署 Device Plugin

1
2
cd deployment/k8s/base
kubectl apply -k .

部署成功后 kube-system 中会出现 rdma-shared-dp-ds DaemonSet,它会在每个节点挂载 RDMA 设备并注册可调度资源。

1
2
3
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
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 设备

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

4.2 关联网络接口

1
2
3
4
5
6
7
8
9
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)

这里可以看到 IB 卡对应的接口名称,例如 mlx5_0 的接口名称为 ibp3s0

这里可以获取到配置中需要的 ifNames 参数。

4.3 获取 PCI 信息

mst status -v 可以列出所有 UP 状态网卡及其 PCI ID:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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

ConnectX7(rev:0)        /dev/mst/mt4129_pciconf1      0002:03:00.0    mlx5_1          net-ibP2p3s0                            0

ConnectX7(rev:0)        /dev/mst/mt4129_pciconf2      0010:03:00.0    mlx5_4          net-ibP16p3s0                           1

ConnectX7(rev:0)        /dev/mst/mt4129_pciconf3      0012:03:00.0    mlx5_5          net-ibP18p3s0                           1

BlueField3(rev:1)       /dev/mst/mt41692_pciconf0     0006:03:00.0    mlx5_2          net-enP6p3s0f0np0                       0

BlueField3(rev:1)       /dev/mst/mt41692_pciconf0.1   0006:03:00.1    mlx5_3          net-bond0                               0

BlueField3(rev:1)       /dev/mst/mt41692_pciconf1     0016:03:00.0    mlx5_6          net-enP22p3s0f0np0                      1

BlueField3(rev:1)       /dev/mst/mt41692_pciconf1.1   0016:03:00.1    mlx5_7          net-bond0                               1

GB100(rev:0)            /dev/mst/mt10561_pciconf0     0008:01:00.0                                            0

GB100(rev:0)            /dev/mst/mt10561_pci_cr0      0008:01:00.0                                            0

GB100(rev:0)            /dev/mst/mt10561_pciconf1     0009:01:00.0                                            0

GB100(rev:0)            /dev/mst/mt10561_pci_cr1      0009:01:00.0                                            0

GB100(rev:0)            /dev/mst/mt10561_pciconf2     0018:01:00.0                                            1

GB100(rev:0)            /dev/mst/mt10561_pci_cr2      0018:01:00.0                                            1

GB100(rev:0)            /dev/mst/mt10561_pciconf3     0019:01:00.0                                            1

GB100(rev:0)            /dev/mst/mt10561_pci_cr3      0019:01:00.0                                            1

示例中 mlx5_0 的 PCI ID 为 0000:03:00.0

4.4 查询厂商/设备 ID

根据上一步获取到的 PCI ID 查询:

1
2
lspci -n | grep 0000:03:00.0
0000:03:00.0 0207: 15b3:1021
  • 15b3:Mellanox/NVIDIA 厂商 ID
  • 1021:具体设备 ID

这里可以获取到配置中需要的 vendors、deviceIDs 参数。

4.5 生成 selectors

汇总以上信息即可写出 selectors,示例如下(可配置多块网卡):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
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:

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

5. 验证

5.1 Node 资源验证

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

已经能在 Node 上看到 rdma/hca_shared_devices_a 资源了。

5.2 构建测试镜像

基于 Ubuntu 安装 ibv_devicesibv_devinfoibstatibstatus 等工具构建一个用于测试的镜像。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
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"]

构建镜像:

1
docker build -t rdma-test:v1 .

已经推送到 dockerhub:lixd96/rdma-test:latest

5.3 Pod 申请资源

启动一个 Pod 申请 RDMA 资源:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
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 查看 IB 卡信息:

1
2
ibv_devices
ibv_devinfo

可以看到 Pod 内已经识别到 mlx5_0 等 RDMA 设备。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
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)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
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 状态:

1
2
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

进入 Pod,使用 ibv_devicesibv_devinfo 查看 IB 卡信息:

1
2
ibv_devices
ibv_devinfo

可以看到 Pod 内已经识别到 mlx5_0 等 RDMA 设备。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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.1 带宽测试

使用 ib_write_bw 工具测试 RDMA 带宽性能。

进入 rdma-server 启动 server:

1
ib_write_bw -d mlx5_0 -i 1

进入 rdma-client 启动 Client:

1
2
# 其中 172.25.114.16 为 rdma-server 的 IP
ib_write_bw -d mlx5_0 -i 1 172.25.114.16

结果如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
root@rdma-server:/# ib_write_bw -d mlx5_0 -i 1

************************************
* Waiting for client to connect... *
************************************
---------------------------------------------------------------------------------------
                    RDMA_Write BW Test
 Dual-port       : OFF		Device         : mlx5_0
 Number of qps   : 1		Transport type : IB
 Connection type : RC		Using SRQ      : OFF
 PCIe relax order: ON
 ibv_wr* API     : ON
 CQ Moderation   : 1
 Mtu             : 4096[B]
 Link type       : IB
 Max inline data : 0[B]
 rdma_cm QPs	 : OFF
 Data ex. method : Ethernet
---------------------------------------------------------------------------------------
 local address: LID 0x538 QPN 0x0171 PSN 0x7ef7d8 RKey 0x1fff00 VAddr 0x00aaaaaab00000
 remote address: LID 0x451 QPN 0x0165 PSN 0xac1c4 RKey 0x1fff00 VAddr 0x00aaaaaab80000
---------------------------------------------------------------------------------------
 #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,理论带宽为 50GB/s,该结果已经接近 IB 带宽上限,说明 RDMA 已能正常使用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
root@rdma-server:/# ibstat
CA 'mlx5_0'
	CA type: MT4129
	Number of ports: 1
	Firmware version: 28.44.2524
	Hardware version: 0
	Node GUID: 0x7c8c090300c3a7ae
	System image GUID: 0x7c8c090300c3a7ae
	Port 1:
		State: Active
		Physical state: LinkUp
		Rate: 400
		Base lid: 1105
		LMC: 0
		SM lid: 1
		Capability mask: 0xa751e848
		Port GUID: 0x7c8c090300c3a7ae
		Link layer: InfiniBand

5.4.2 延迟测试

除了带宽,延迟也是 RDMA 的重要性能指标。使用 ib_write_lat 测试延迟:

在 rdma-server 中启动:

1
ib_write_lat -d mlx5_0 -i 1

在 rdma-client 中连接:

1
ib_write_lat -d mlx5_0 -i 1 172.25.114.16

测试结果示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
---------------------------------------------------------------------------------------
                    RDMA_Write Latency Test
 Dual-port       : OFF		Device         : mlx5_0
 Number of qps   : 1		Transport type : IB
 Connection type : RC		Using SRQ      : OFF
 PCIe relax order: OFF
 ibv_wr* API     : ON
 TX depth        : 1
 Mtu             : 4096[B]
 Link type       : IB
 Max inline data : 220[B]
 rdma_cm QPs	 : OFF
 Data ex. method : Ethernet
---------------------------------------------------------------------------------------
 local address: LID 0x451 QPN 0x0167 PSN 0xca7dd8 RKey 0x1ffbba VAddr 0x00aaaaaab00000
 remote address: LID 0x538 QPN 0x0173 PSN 0x66403f RKey 0x1fecab VAddr 0x00aaaaaab00000
---------------------------------------------------------------------------------------
 #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 微秒,相比传统 TCP/IP 网络(通常 50-100 微秒),延迟降低了 20-40 倍。同时标准差仅为 0.04 微秒,说明延迟非常稳定,充分体现了 RDMA 的低延迟优势。

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 沿用 Host 网络的部分特性。

在这种模式下,Pod 依然使用默认 CNI(如 Calico、Flannel)分配的 IP 进行常规通信,同时拥有了访问 RDMA 硬件的能力。这是最简单、维护成本最低的方案。

6.2 需要 Multus CNI 的场景

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

  1. 网络隔离:需要将 RDMA 流量与 Kubernetes 管理/业务流量完全物理隔离。
  2. 独立 IP 地址:需要为 RDMA 网卡分配独立的 IP 地址(例如使用 IPoIB 或 RoCEv2 路由模式),以便应用通过特定 IP 进行绑定。
  3. SR-IOV 场景:如果使用 sriov-cni 将物理网卡虚拟化为 VF 直接透传给 Pod,通常需要 Multus 来管理这个额外的网络接口。

6.3 结论

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

7. 小结

本文系统性地梳理了在 Kubernetes 集群中落地 RDMA 技术的完整路径。从基础概念的认知,到硬件环境的准备,再到 Device Plugin 的部署与配置,最后通过实际的性能压测验证了 RDMA 性能的优越性。

核心要点回顾:

  1. 技术价值:RDMA 通过零拷贝和内核旁路技术,解决了 TCP/IP 网络在高带宽场景下的 CPU 瓶颈和延迟问题,是释放 GPU 集群算力的关键基础设施。
  2. 部署策略:对于大多数 AI 推理和训练场景,使用 k8s-rdma-shared-dev-plugin 配合 Shared 模式是最轻量级的方案。它无需复杂的网络改造,即可让 Pod 获得原生 RDMA 能力。
  3. 架构决策:在引入 Multus CNI 之前应审慎评估。如果不需要物理隔离或独立 IP,直接复用 Host 网络栈(通过 Device Plugin 暴露设备)往往能带来更低的操作复杂度和更高的稳定性。

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

0%