
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 驱动及用户态库(如 libibverbs、rdmacm 等)。驱动安装的具体步骤此处不赘述。
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)。
这里我们得到了配置所需的 vendors 和 deviceIDs 参数。
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_devices 和 ibv_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 写带宽测试。
- 在
rdma-server Pod 中启动服务端:
ib_write_bw -d mlx5_0 -i 1
- 在
rdma-client Pod 中启动客户端(其中 172.25.114.16 为 rdma-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 写操作的延迟。
- 在
rdma-server Pod 中启动服务端:
ib_write_lat -d mlx5_0 -i 1
- 在
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:
- 仅需 IB Verbs API:应用(如 vLLM、NCCL)直接调用 RDMA 接口进行数据面通信,不依赖或仅少量依赖 IP 协议(可能仅用于控制面)。
- 使用 Shared Device Plugin:如本文所述,
k8s-rdma-shared-dev-plugin 可以在不改变 Pod 网络命名空间结构的前提下,将 RDMA 设备文件(/dev/infiniband/*)安全地暴露给 Pod。
- 扁平网络架构:RDMA 网卡与 Kubernetes 集群的管理/业务网卡处于同一网络平面,或者可以接受 Pod 沿用宿主机的部分网络特性。
在这种模式下,Pod 依然通过默认 CNI(如 Calico、Flannel)获得 IP 地址进行常规通信,同时通过 Device Plugin 获得了访问底层 RDMA 硬件的能力。这是最简单、运维成本最低的方案。
6.2 需要 Multus CNI 的场景
如果存在以下需求,则建议引入 Multus CNI:
- 网络流量隔离:需要将 RDMA 数据流量与 Kubernetes 管理流量或其它业务流量进行严格的物理或逻辑隔离。
- 独立 IP 地址:需要为 RDMA 网卡分配独立的 IP 地址(例如在使用 IPoIB 或 RoCEv2 路由模式时),以便应用通过特定的 IP 进行绑定和通信。
- 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 的卓越性能。
核心要点回顾:
- 技术价值:RDMA 通过零拷贝和内核旁路技术,从根本上解决了 TCP/IP 网络在高带宽场景下的 CPU 瓶颈与高延迟问题,是释放现代 GPU 集群算力潜力的关键云原生基础设施。
- 部署策略:对于常见的 AI 负载,使用
k8s-rdma-shared-dev-plugin 的共享模式是最为轻量、高效的方案。它无需对现有网络架构进行复杂改造,即可让 Pod 获得近乎原生的 RDMA 能力。
- 架构决策:在决定引入 Multus CNI 等高级网络方案前应进行审慎评估。若无强制性的网络隔离或独立 IP 需求,复用宿主机的网络栈并通过 Device Plugin 暴露设备,往往能在复杂性与性能之间取得最佳平衡。
随着云原生 AI 的持续演进,底层网络设施的性能优化变得愈发关键。熟练掌握 RDMA 在 Kubernetes 中的配置与管理,已成为构建高性能、低延迟 AI 计算平台的必备技能。未来,可以进一步探索 GPUDirect RDMA、SR-IOV 硬件虚拟化等更进阶的技术,以应对更大规模、更严苛延迟要求的计算挑战。