Multus + SR-IOV + RDMA不是一个独立的网络插件,而是一组分层协作的组件。它在保留Pod默认管理网络的同时,把可调度的高速网卡功能分配给训练Pod,使NCCL等通信库能够使用InfiniBand或RoCE进行跨节点集合通信。
这套方案主要面向裸金属多节点训练集群。它解决的是训练数据面的带宽、时延和设备编排问题,不会加速模型计算、数据预处理、存储读取或普通HTTP/gRPC通信。
基本概念
Multus
Multus CNI是一个CNI元插件。它不实现新的交换或路由数据面,而是调用其他CNI插件,使一个Pod能够连接多个网络。
管理员通过NetworkAttachmentDefinition(简称NAD)定义附加网络,工作负载通过k8s.v1.cni.cncf.io/networks注解引用它。典型训练Pod会获得两张网卡:
eth0由默认CNI创建,承载DNS、服务发现、日志、监控和训练会合流量。net1由附加CNI创建,承载节点间的高速训练通信。
SR-IOV
SR-IOV(Single Root I/O Virtualization,单根I/O虚拟化)是PCI Express提供的设备虚拟化能力。一张支持SR-IOV的物理网卡可以提供一个PF和多个VF:
PF(Physical Function)由宿主机管理,用于创建、删除和配置VF。VF(Virtual Function)具有独立的PCI地址、队列和网络接口,可以分配给单个Pod。
训练流量通过VF直接进入网卡硬件队列,可以减少常见veth pair、软件网桥和Overlay封装带来的处理开销。VF仍共享PF对应的物理端口和链路带宽,因此它是设备级隔离和分配机制,不等同于独占物理网卡。
RDMA
RDMA(Remote Direct Memory Access,远程直接内存访问)允许网卡在已经注册的内存区域之间直接传输数据。应用通常通过libibverbs创建内存区域、队列对和完成队列,再提交发送、接收、读写等操作。
与传统TCP Socket路径相比,RDMA可以减少数据复制、系统调用和内核协议栈处理,从而降低通信时延和CPU开销。连接建立、内存注册、队列管理和异常恢复仍需要软件参与,所以不能把RDMA理解为完全没有CPU或内核开销。
训练集群常见的两种承载方式如下:
| 承载方式 | 网络形态 | 主要关注点 |
|---|---|---|
InfiniBand | 原生InfiniBand网卡与交换网络 | 子网管理、分区、路由和链路状态 |
RoCEv2 | 在以太网上通过UDP/IP承载RDMA | VLAN、MTU、PFC/ECN、拥塞控制和路由一致性 |
GPUDirect RDMA
普通RDMA通常在两端主机内存之间传输数据。GPUDirect RDMA允许网卡直接访问GPU显存,减少数据在GPU显存与主机内存之间的中转。
GPUDirect RDMA建立在RDMA之上,但两者不能画等号。它还要求GPU、网卡、驱动、CUDA、PCIe拓扑以及显存映射机制相互兼容,最终由NCCL等通信库根据运行环境选择是否使用。
四项技术的关系可以概括为:
| 技术 | 解决的问题 | 不负责的事情 |
|---|---|---|
Multus | 为Pod编排多个网络 | 不转发训练数据,不创建VF |
SR-IOV | 把物理网卡划分为可独立分配的VF | 不提供集合通信协议 |
RDMA | 提供低时延、低CPU开销的远程内存传输 | 不负责Kubernetes调度和网络编排 |
GPUDirect RDMA | 在符合条件时让网卡直接访问GPU显存 | 不会因为安装CNI而自动启用 |
大模型训练中的常见网络问题
集合通信成为扩展瓶颈
多节点数据并行、张量并行和流水线并行都需要跨节点交换张量。以DistributedDataParallel(DDP)为例,每轮反向传播都会触发梯度AllReduce;参数规模、节点数或通信频率上升后,训练进程等待集合通信的时间会增加。
同步训练还具有木桶效应:一个成员的网络拥塞或通信延迟会阻塞其他成员。链路带宽、尾时延和通信稳定性都会直接影响单步时间与集群扩展效率。
默认Pod网络与训练数据面目标不同
默认Pod网络主要服务于通用业务通信。根据具体CNI模式,数据可能经过veth、主机协议栈、路由、网络策略或隧道封装。它能够满足控制和服务流量需求,但不一定适合持续的大块张量传输。
大模型训练通常还会遇到以下问题:
- 训练流量与
DNS、日志、监控和存储流量共享接口,容易互相争用。 - 普通网络资源不会自动作为
Kubernetes扩展资源参与调度,调度器无法判断节点还剩多少可用高速网卡功能。 - 直接使用
hostNetwork或挂载宿主机全部RDMA设备,会失去清晰的设备配额和Pod级可见性边界。 - 使用普通
Socket路径时,主机内存复制和CPU协议栈处理可能成为额外瓶颈。
技术方案如何解决问题
方案的核心是把管理网络、训练网络、硬件调度和通信库分层处理:
| 训练问题 | 解决机制 | 参与组件 |
|---|---|---|
| 管理流量与训练流量争用 | 为Pod保留eth0,另外创建net1 | Multus、默认CNI、NAD |
| 高速网卡无法按数量调度 | 将VF注册为扩展资源 | SR-IOV Network Device Plugin |
| 通用容器网络路径开销较高 | 把指定VF网口交给训练Pod | SR-IOV CNI |
Pod无法隔离使用RDMA设备 | 将关联的RDMA接口移入同一网络命名空间 | RDMA CNI |
跨节点张量通信占用CPU和主机内存路径 | 使用NCCL + RDMA,符合条件时使用GPUDirect RDMA | NCCL、libibverbs、网卡和GPU驱动 |
总体架构
Multus和各CNI只参与Pod网络的创建与删除。网络准备完成后,训练数据不会经过Multus进程,而是由NCCL、libibverbs、网卡驱动、网卡和交换网络传输。
Pod创建时的协作过程
- 训练
Pod通过资源请求申请GPU和VF,并通过网络注解引用NAD。 SR-IOV Network Device Plugin把可用VF上报为节点扩展资源,调度器据此选择节点。kubelet为容器分配具体VF,容器运行时随后调用Multus执行CNI ADD。Multus先调用默认CNI创建eth0,再读取NAD并把已经分配的deviceID传给附加插件链。SR-IOV CNI配置并迁移VF网口,RDMA CNI把关联的RDMA接口移入同一个Pod网络命名空间。- 训练进程启动后,
NCCL发现容器内的网络接口和RDMA设备,并选择实际通信路径。
只有默认网络和附加插件链都成功,Pod Sandbox才会进入网络就绪状态。删除Pod时,容器运行时会触发对应的CNI DEL调用,清理接口、地址和设备网络命名空间状态。
核心组件工作原理
SR-IOV Network Device Plugin
SR-IOV Network Device Plugin在每个训练节点发现符合选择条件的VF,并通过Kubernetes Device Plugin API把它们注册为扩展资源。调度器只处理资源数量,具体PCI deviceID由节点上的设备管理路径在Pod启动时分配。
它负责设备发现、健康检查、资源上报和分配,不负责创建VF,也不负责配置Pod中的网络接口。
Multus与NetworkAttachmentDefinition
Multus根据Pod网络注解读取对应NAD,再按配置顺序调用默认网络和附加网络插件。对于设备型网络,它还需要把设备插件已经分配的deviceID传给SR-IOV CNI和RDMA CNI。
设备资源池、NAD和Pod必须使用相同的扩展资源名:
| 配置位置 | 示例值 |
|---|---|
| 设备插件资源池 | resourcePrefix: example.com和resourceName: sriov_rdma |
NAD注解 | k8s.v1.cni.cncf.io/resourceName: example.com/sriov_rdma |
Pod资源申请 | example.com/sriov_rdma: "1" |
如果三处名称不一致,网络注解就无法关联到已经分配的VF。
SR-IOV CNI
SR-IOV CNI根据deviceID找到目标VF,通过PF设置所需的MAC、VLAN等属性,再把VF对应的网口移入Pod网络命名空间。对于使用内核驱动的网口,它还会调用IPAM结果配置IP和路由。
SR-IOV CNI只配置已经分配的设备,不负责设备发现、资源调度或VF生命周期管理。
RDMA CNI
RDMA CNI作为链式插件运行在SR-IOV CNI之后。它使用插件链的网络结果和Multus注入的deviceID找到关联的RDMA接口,并将其移入同一个网络命名空间,实现Pod级RDMA设备可见性。
RDMA CNI不把普通网络程序转换为RDMA程序。应用必须通过NCCL、UCX、libfabric或libibverbs等支持RDMA的通信栈发起传输。
IPAM
附加网络仍需要地址管理。多节点共享同一训练子网时,应使用具备跨节点地址协调能力的IPAM,例如Whereabouts,或者使用集群已经统一管理的地址分配方案。
训练网通常不设置默认路由,避免DNS、镜像访问和其他控制流量意外进入net1。
NCCL与GPUDirect RDMA
NCCL实现AllReduce、AllGather、ReduceScatter等GPU集合通信。它会根据可见的网络接口、RDMA HCA和拓扑选择传输方式。NCCL_SOCKET_IFNAME筛选IP接口,NCCL_IB_HCA筛选verbs设备,两者不是同一个对象。
当硬件、驱动和拓扑满足条件时,NCCL可以使用GPUDirect RDMA直接在网卡与GPU显存之间传输;否则仍可能使用主机内存中转。是否启用必须通过NCCL日志、拓扑信息和实际测试确认。
分布式训练示例
我们使用一个人脸识别训练任务作为示例,说明如何在两个训练节点上部署多GPU训练Pod,并使用Multus + SR-IOV + RDMA实现跨节点集合通信。
架构设计
明确需要加速的通信
人脸任务是否使用RDMA取决于应用通信方式,而不是任务名称:
| 场景 | 主要通信 | 与本方案的关系 |
|---|---|---|
人脸检测或表征模型的多节点DDP训练 | 梯度集合通信 | NCCL可以使用InfiniBand/RoCE |
在线人脸识别服务之间的HTTP/gRPC | 图片、请求和向量 | 默认仍使用TCP/IP,不会自动变成RDMA |
| 向量数据库查询 | 特征向量请求 | 是否使用RDMA取决于数据库及客户端实现 |
下面以两个训练节点、每个节点一个多GPU训练Pod为例。节点内通信由NVLink或PCIe承担,节点间梯度同步使用NCCL + RoCEv2。
双网络拓扑
流量划分如下:
eth0保留默认路由,用于torchrun会合、DNS、监控和日志。net1连接独立训练子网,NCCL通过其关联的RDMA HCA传输梯度和参数。NCCL_SOCKET_IFNAME可以限制NCCL使用的IP接口;容器只看到一个目标HCA时,通常不需要硬编码NCCL_IB_HCA。- 数据集读取、图像增强、前向计算和在线推理不会因为添加
net1而自动加速。
组件安装
安装前提
| 层级 | 需要满足的条件 |
|---|---|
| 硬件 | 训练节点网卡支持SR-IOV与RDMA,并已按规划创建VF |
| 主机 | PF/VF驱动和rdma-core正常,RDMA子系统处于exclusive网络命名空间模式 |
| 网络 | 训练节点之间的VLAN、MTU、路由和RoCE拥塞控制配置一致 |
| 集群 | 默认CNI正常,并已安装Multus、SR-IOV CNI、设备插件、RDMA CNI和所需IPAM |
| 镜像 | 包含匹配的CUDA、NCCL、libibverbs、网卡用户态库和训练框架 |
| 拓扑 | GPU与网卡的PCIe/NUMA位置符合预期;使用GPUDirect RDMA时满足厂商兼容要求 |
VF应由节点初始化系统或网络Operator统一创建和持久化。CNI负责把已经存在的VF交给Pod,不会代替节点侧的固件、驱动和VF生命周期管理。
需要安装的组件
| 部署位置 | 组件与安装说明 | 要求 | 作用 |
|---|---|---|---|
| 训练节点主机 | 网卡驱动、RDMA内核模块和rdma-core;rdma-core构建说明 | 必需 | 提供PF/VF驱动、RDMA verbs及诊断工具 |
| 所有工作节点 | 默认CNI;Kubernetes网络插件说明 | 必需 | 创建eth0,承载集群管理与通用业务流量 |
| 集群与工作节点 | Multus CNI和NAD CRD;快速安装 | 必需 | 解析网络注解并编排默认网络与附加网络 |
| 训练节点 | SR-IOV Network Device Plugin;快速安装 | 必需 | 发现VF并将其注册为可调度扩展资源 |
| 训练节点 | SR-IOV CNI;Kubernetes快速安装 | 必需 | 配置已分配的VF并创建net1 |
| 训练节点 | RDMA CNI;部署说明 | 必需 | 将VF关联的RDMA接口移入Pod网络命名空间 |
| 集群与训练节点 | Whereabouts或其他跨节点IPAM;Whereabouts安装说明 | 按地址方案选择 | 为附加训练网络分配不冲突的IP地址 |
| 训练节点 | GPU驱动和Kubernetes GPU Device Plugin;GPU Operator安装说明或NVIDIA Device Plugin快速安装 | GPU训练必需 | 将GPU注册为可调度资源,并为容器提供所需的驱动和运行时 |
| 训练镜像 | CUDA、NCCL、libibverbs及网卡用户态库;CUDA安装说明、NCCL安装说明 | GPU训练必需 | 让训练进程使用GPU和RDMA HCA执行集合通信 |
Multus、SR-IOV CNI、RDMA CNI和所选IPAM的可执行文件必须安装到容器运行时使用的CNI bin目录;对应的DaemonSet通常负责把二进制复制到宿主机。SR-IOV Network Device Plugin应只调度到具备目标网卡的训练节点。
当前独占VF方案不需要安装rdma-shared-dev-plugin。该插件对应共享HCA资源模型,不是对SR-IOV VF方案的额外增强。
推荐安装顺序
- 在训练节点完成固件、驱动、
RDMA内核模块、rdma-core和VF配置,并将RDMA子系统设置为exclusive模式。 - 安装并验证默认
CNI,确保普通Pod的eth0、DNS和跨节点通信正常。 - 安装
Multus CNI及NAD CRD,确认附加网络注解能够被识别。 - 在训练节点安装
SR-IOV CNI、RDMA CNI以及选定的跨节点IPAM。 - 配置并部署
SR-IOV Network Device Plugin,确认目标VF已经出现在节点allocatable资源中。 - 创建
NAD和最小测试Pod,先验证net1与RDMA HCA,再部署正式训练作业。
生产环境应通过发行版、网络Operator或经过审查的部署清单统一安装,并固定容器镜像摘要。不同来源的清单可能使用不同的宿主机目录、权限和DaemonSet名称,安装前必须与集群的容器运行时和节点操作系统对齐。
Kubernetes落地配置
配置SR-IOV RDMA资源池
下面的设备插件配置把指定PF下具备RDMA能力的VF注册为example.com/sriov_rdma。网卡名和厂商标识必须按实际环境修改。
apiVersion: v1
kind: ConfigMap
metadata:
name: sriovdp-config
namespace: kube-system
data:
config.json: |
{
"resourceList": [
{
"resourcePrefix": "example.com",
"resourceName": "sriov_rdma",
"selectors": [
{
"vendors": ["15b3"],
"pfNames": ["enp65s0f0np0"],
"isRdma": true
}
]
}
]
}
部署设备插件后,节点的status.allocatable中应出现example.com/sriov_rdma,其数量对应当前可分配的健康VF。
创建附加训练网络
下面的NAD先调用SR-IOV CNI创建net1,再调用RDMA CNI处理关联的RDMA接口。示例使用Whereabouts协调跨节点地址,并且不为训练网设置默认路由。
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
name: face-training-rdma
namespace: ai-training
annotations:
k8s.v1.cni.cncf.io/resourceName: example.com/sriov_rdma
spec:
config: |
{
"cniVersion": "0.3.1",
"name": "face-training-rdma",
"plugins": [
{
"type": "sriov",
"vlan": 200,
"spoofchk": "on",
"trust": "off",
"ipam": {
"type": "whereabouts",
"range": "10.60.0.0/16",
"exclude": ["10.60.0.0/24"]
}
},
{
"type": "rdma"
}
]
}
这里不能静态填写deviceID。具体VF由设备插件分配,再由Multus在运行时注入插件链。VLAN、地址段和安全属性必须与物理网络规划一致。
让训练Pod申请高速网络
训练工作负载必须同时引用NAD并申请对应的扩展资源。下面只保留与双网络和NCCL有关的关键字段,镜像、存储、资源数量及调度策略需要按训练平台补充。
apiVersion: v1
kind: Service
metadata:
name: face-rdzv
namespace: ai-training
spec:
clusterIP: None
publishNotReadyAddresses: true
selector:
app: face-trainer
ports:
- name: torch-rdzv
port: 29400
---
apiVersion: batch/v1
kind: Job
metadata:
name: face-trainer
namespace: ai-training
spec:
completions: 2
parallelism: 2
completionMode: Indexed
template:
metadata:
labels:
app: face-trainer
annotations:
k8s.v1.cni.cncf.io/networks: |
[{"name": "face-training-rdma", "interface": "net1"}]
spec:
subdomain: face-rdzv
restartPolicy: Never
containers:
- name: trainer
image: registry.example.com/ai/face-training:<validated-tag>
env:
- name: MASTER_ADDR
value: face-trainer-0.face-rdzv.ai-training.svc.cluster.local
- name: MASTER_PORT
value: "29400"
- name: NCCL_SOCKET_IFNAME
value: "=net1"
command:
- /bin/bash
- -ceu
- |
exec torchrun \
--nnodes=2 \
--nproc-per-node=8 \
--node-rank="${JOB_COMPLETION_INDEX}" \
--master-addr="${MASTER_ADDR}" \
--master-port="${MASTER_PORT}" \
/workspace/train_face.py
resources:
requests:
nvidia.com/gpu: "8"
example.com/sriov_rdma: "1"
limits:
nvidia.com/gpu: "8"
example.com/sriov_rdma: "1"
示例中的无头Service和subdomain为训练成员提供管理网会合地址。GPU数量、镜像和域名必须按集群实际情况修改。两个训练副本应调度到不同节点;需要同时启动所有成员时,应由训练Operator或支持成组调度的调度器完成资源准入。
NCCL_SOCKET_IFNAME只筛选IP接口。如果容器中存在多个RDMA HCA,再根据ibdev2netdev结果设置NCCL_IB_HCA;不要复制其他节点的设备名或GID index。
验证通信路径
验证应按资源、网络、RDMA、集合通信和真实训练逐层进行。ping成功只能证明IP连通,不能证明NCCL已经使用RDMA或GPUDirect RDMA。
| 验证层级 | 关键检查 |
|---|---|
| 资源 | 节点存在example.com/sriov_rdma可分配量,训练Pod成功申请一个VF |
| 网络 | network-status包含face-training-rdma,Pod中存在net1且默认路由仍在eth0 |
RDMA | rdma link、ibv_devinfo和ibdev2netdev显示HCA与net1关联且端口可用 |
| 点对点性能 | 两个训练Pod之间的ib_write_bw或ib_send_bw达到链路预期 |
| 集合通信 | NCCL日志选择NET/IB,nccl-tests结果优于Socket基线 |
| 真实训练 | 固定模型与批量大小后,比较单步时间、吞吐量、通信占比和多节点扩展效率 |
常用检查命令如下:
kubectl get nodes \
-o custom-columns='NAME:.metadata.name,RDMA-VF:.status.allocatable.example\.com/sriov_rdma'
kubectl -n ai-training get pod <pod-name> \
-o jsonpath='{.metadata.annotations.k8s\.v1\.cni\.cncf\.io/network-status}'
kubectl -n ai-training exec <pod-name> -- ip -br address
kubectl -n ai-training exec <pod-name> -- ip route
kubectl -n ai-training exec <pod-name> -- rdma link show
kubectl -n ai-training exec <pod-name> -- ibv_devinfo
kubectl -n ai-training exec <pod-name> -- ibdev2netdev
测试时可以临时启用NCCL_DEBUG=INFO观察传输选择,并使用NCCL_IB_DISABLE=1建立Socket基线。最终判断应以相同训练条件下的NCCL基准和真实训练结果为准,不能根据接口存在或单次带宽测试推断整体收益。
独占VF与共享HCA方案对比
本文采用的是Multus + SR-IOV Network Device Plugin + SR-IOV CNI + RDMA CNI组合,每个训练Pod申请一个独立VF。此外,常见的rdma-shared-dev-plugin组件采用不同思路:把同一个RDMA HCA注册为多个逻辑资源配额,让多个Pod共享该设备,网络接口通常由Macvlan、IPoIB或其他CNI创建。
| 对比维度 | 独占SR-IOV VF方案 | rdma-shared-dev-plugin共享方案 |
|---|---|---|
| 资源粒度 | 每个Pod分配一个或多个真实VF | 多个Pod共享同一个物理HCA |
| 调度资源 | 可分配数量受健康VF数量限制 | 通过rdmaHcaMax发布逻辑配额 |
| 网络接口 | SR-IOV CNI把VF网口移入Pod | 使用Macvlan、IPoIB等方式创建接口 |
| 隔离能力 | 具有独立PCI功能、网口和RDMA命名空间 | 共享HCA、端口、队列资源与链路故障域 |
| 性能确定性 | 较高,但多个VF仍共享PF物理带宽 | 较易受到其他共享Pod的流量与队列竞争影响 |
| 工作负载密度 | 受网卡可创建VF数量限制 | 较高,适合大量并发的小型RDMA任务 |
| 运维复杂度 | 需要管理VF生命周期、资源池和链式CNI | 配置较简单,但需要控制共享数量和资源争用 |
独占VF方案的优势是设备归属明确、调度数量对应真实硬件功能、性能更容易预测,也更适合多租户和长时间运行的大规模训练。缺点是组件较多,需要维护PF/VF、驱动、资源池和网络命名空间模式,可运行的Pod数量还会受到VF上限约束。
共享HCA方案的优势是资源密度高,不需要为每个Pod准备一个VF,适合实验环境、小规模任务或大量低带宽RDMA工作负载。缺点是rdmaHcaMax只是调度层逻辑容量,不会形成硬件带宽、队列或故障隔离;一个Pod产生拥塞时,其他共享者更容易受到影响。
对于需要稳定NCCL吞吐、明确资源配额和较强隔离的大模型训练集群,优先选择独占SR-IOV VF方案。只有在任务通信量较小、允许共享干扰并且更关注部署密度时,才适合采用rdma-shared-dev-plugin方案。除非已经按不同物理端口或设备集合划分资源,否则不应让两类设备插件同时管理同一组HCA/VF,以免重复上报和形成不一致的资源模型。