RDMA 这组词,高性能计算圈子里几乎人人都听过,但要在云平台上把 RDMA 高性能网络真正落地,让租户像使用普通云主机一样拿到低延迟、高带宽的网络能力,中间隔着的不是一层窗户纸,而是整整一套从底层硬件到上层调度的复杂工程。这个项目我前前后后做了三轮迭代,踩过不少坑,也沉淀下来一套可复用的搭建思路。这篇文章不谈概念,只讲实操路径、关键决策和避坑经验,适合正在规划 RDMA 云平台网络、或者准备把 RDMA 能力开放给内部业务的同学参考。
1. 项目背景与需求拆解
1.1 云平台为什么突然需要 RDMA
很多内部云平台刚起步时,业务跑在千兆或万兆以太网上,依赖 TCP/IP 协议栈做数据交换。但一旦涉及分布式训练、海量日志分析、高性能存储这类场景,问题立刻暴露:CPU 频繁被网络中断打断,进程上下文切换开销巨大,十几 Gbps 的吞吐就把单核 CPU 占满。业务侧反馈“网络太慢”,实际上不是链路带宽不够,而是数据从网卡到内存再到应用程序的路径太长,内核协议栈成了瓶颈。
RDMA 的核心价值就是把数据搬运这件事从 CPU 手里接管过来,网卡直接读写远端内存,绕过内核,减少拷贝次数,从而把延迟压到微秒级,把带宽跑到线速。对于云平台来说,如果能把 RDMA 能力以租户可用的方式提供出去,就相当于让所有计算节点共享一个“超级网络”,这对存储集群、AI 训练池的收益是肉眼可见的。
1.2 我们当时的核心诉求
我这个项目启动时,需求其实非常聚焦:
- 支持至少两个独立业务部门同时使用 RDMA 网络,彼此之间要强隔离。
- 租户的虚拟机能直接拿到 RDMA 网卡能力,不需要改代码。
- 网络拓扑变更时不能影响存量业务。
- 整体改造成本要可控,不能一上来就全量替换网络硬件。
这些需求直接决定了我后面的技术选型。如果只是搭一条物理机之间的 RDMA 链路,问题会简单很多,但因为要让虚拟化环境里的虚拟机也能用,牵扯到虚拟化层如何透传网卡、怎么隔离、怎么运维,复杂度立刻上升了一个量级。
1.3 技术选型:为什么最终选了 RoCE v2
当时摆在面前的无非三条路:InfiniBand、RoCE、iWARP。
InfiniBand 性能最稳,端到端无损,但它的交换设备和网卡成本高,而且和云平台里普遍的以太网络管理栈不兼容,等于要单独维护一套物理网络。iWARP 虽然跑在 TCP 上,部署方便,但性能受限于 TCP 处理,低延迟场景下优势不明显,生态也相对冷门。
最后我选了 RoCE v2。理由很实际:它跑在标准以太网上,复用现有交换机和网卡,成本低;RoCE v2 报文可以承载在 IP 层,具备一定的路由能力,相比只能跑在二层网络的 RoCE v1,更适合云平台这种多子网环境;生态上也够成熟,主流 RDMA 网卡和驱动都支持。唯一的问题是它需要无损网络支撑,而这个“无损”恰恰是实施中最考验耐心的地方。
提示:如果你的预算充足、业务对延迟极其敏感,而且有专人维护专用网络,用 InfiniBand 也能走通。但云平台这种多租户、多业务复用场景,RoCE v2 的性价比和灵活性更合适。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 方案设计与网络架构
2.1 整体物理拓扑怎么画
我采用的是“存储和计算共用一套 RoCE 网络,但通过独立 VLAN 和子网进行租户隔离”的架构。每个计算节点插一块双端口 RDMA 网卡,双上行分别接到两台万兆交换机上,交换机之间做堆叠或使用 MLAG 提供冗余。存储节点也接入同一套 RoCE 网络,这样虚拟机发起的 RDMA 流量不需要绕行管理网络。
这里有一个容易被忽略的细节:RoCE v2 使用 UDP 报文承载数据,默认目的端口是 4791。如果你在网络里做了流量监控或安全策略,千万记得放通这段协议,否则链路看似通,但 RDMA 连接就是建立不起来。
2.2 虚拟化层的 RDMA 能力怎么给到虚拟机
这一步是云平台改造的关键。虚拟机要用 RDMA,最直接的办法是把物理网卡的 PCI 设备透传给虚拟机,也就是 PCI Passthrough。但这种方案一台物理机上只能给少量虚拟机分配整卡,灵活性太差。更实用的做法是用 SR-IOV 先把物理网卡切出多个虚拟功能(VF),再把 VF 直通给不同的虚拟机。
SR-IOV 的好处是每个 VF 都有自己的队列和中断资源,虚拟机的 RDMA 流量可以直接从 VF 进出,绕开宿主机的虚拟交换层,性能损耗非常小。虚拟化平台只需要保证宿主机开启了 VT-d/IOMMU,然后把 VF 绑定到虚拟机即可。对于云平台来说,可以把 VF 看作一种可分配的网络资源,做成租户可选的带宽类型。
当时的实现里,我做了两层映射:底层的物理网卡、PF、VF 资源统一由宿主机管理;上层的云平台通过调度逻辑决定每个 VF 分配给哪台虚拟机,并且给每个 VF 打上租户标签。这个设计让后续做计费和 ACL 控制变得顺手很多。
2.3 租户隔离与网络打通
多租户意味着不能因为一个租户的 RDMA 广播风暴影响到另一个租户。RoCE 网络里既有普通 TCP/IP 流量,又有 RDMA 流量,我要求所有 RDMA 网卡只走专门的 VLAN,并把不同租户分配到不同子网。在交换机上用基于 VLAN 的 ACL 隔离租户间流量,物理层再把 PFC 优先级队列独立划分给 RDMA 流量,这样即使某个租户疯狂发流量,也只是把它自己那一类队列填满,不会拖垮整个网络。
值得强调的是,RDMA 连接本质上是点对点五元组通信,不像普通虚拟机之间需要依赖网关转发。因此租户之间的隔离,除了 IP 层 ACL 之外,我还限制了每个租户的 VF 数量,避免一个租户申请大量 VF 导致宿主机资源耗尽。
2.4 网络设备需要具备的能力
构建 RoCE 云平台,交换机不是随便一台万兆交换机能搞定的。它必须支持:
- PFC(优先级流控):为 RDMA 流量单独划分 buffer 并做无损控制。
- ECN(显式拥塞通知):在拥塞时给报文打上标记,让网卡端做拥塞控制。
- 大缓冲区或足够的队列缓存:否则瞬时突发流量容易直接丢包。
- 支持基于 VXLAN 或 VLAN 的隔离:便于云平台网络自动化。
如果交换机不支持 PFC,RoCE v2 在高负载下几乎必现丢包,性能断崖。我建议在采购前先和测试环境做一轮 PFC 压测,确认交换机参数可调,而不是只能固定几个优先级。
3. 核心实施步骤与配置
3.1 宿主机 RDMA 网卡初始化
先把硬件能力验证好。新到的网卡先升级固件,然后装对应版本的 RDMA 驱动。驱动装完之后,检查内核是否加载了必要的模块:
bash复制lsmod | grep rdma
ls /dev/infiniband/
能看到 uverbs0、umad0 这类设备节点,说明核心模块正常。接着用 ibstat 查看端口状态,默认必须是 Active,状态为 InfiniBand 或 Ethernet 取决于网卡模式。RoCE 模式下我们一般把网卡切成 Ethernet 模式,再在上面配置 IP。
实操心得:我踩过一次固件和驱动版本不匹配的坑,网卡能识别,但创建 QP 时直接报参数错误。后来统一用官方固件配套的推荐驱动版本,问题消失。版本管理最好从项目开始就纳入配置管理库,别靠“上次装的那个”.
给宿主机配置 IP 时,要确认 IP 和路由是通的。RoCE 场景下还可以通过把 GID 索引和 IP 关联,确认 ibv_devinfo 里能看到针对 RoCE v2 的 GID 条目。我通常会写一个小脚本,批量检查所有宿主机上的 GID 和端口速率,确保前期基础状态可控。
3.2 交换机无损配置
这一步是决定 RDMA 表现的核心,也是最多人翻车的地方。我以常见的两台万兆交换机为例,需要做的配置整理成三层:
第一层,开启 PFC。把 RDMA 流量用的优先级队列拉出来,我一般用优先级 3 或 4。在该队列上开启流控,同时关闭为普通 TCP/IP 流量服务的队列的 PFC 能力,避免因为 TCP 重传把 RDMA buffer 占满。
第二层,配置 ECN 阈值。RoCE v2 常用的拥塞控制机制是 DCQCN,网卡根据收到的 ECN 标记来降速。交换机上要设置 WRED 的 min 和 max 阈值,让队列在接近拥塞时开始标 ECN,而不是直接丢包。阈值的经验值通常是队列深度的一半到四分之一,具体得通过压测微调。
第三层,禁止交换机对 RoCE 报文做泛洪或广播学习。RoCE 流量和普通 TCP/UDP 不同,如果交换机把它当普通大流量 UDP 去处理,可能会触发 MAC 地址老化或流表溢出。我把 RDMA 流量涉及的 VLAN 作为静态配置,不依赖动态 MAC 学习,减少异常断流概率。
3.3 虚拟机的 VF 透传与配置
宿主机上先创建 VF:
bash复制echo 4 > /sys/class/net/<pf_pci>/device/sriov_numvfs
比如你想从物理网卡分出 4 个 VF,就把 sriov_numvfs 设为 4。创建后,用 lspci 或 ip link show 确认出现的虚拟设备。然后需要把 VF 解绑宿主机驱动,改绑定到 vfio-pci:
bash复制modprobe vfio-pci
echo vfio-pci > /sys/bus/pci/devices/<vf_pci>/driver_override
echo <vf_pci> > /sys/bus/pci/drivers/vfio-pci/bind
这些操作之后,云平台调度就可以把该 VF 对应的 PCI 设备挂到虚拟机 XML 配置里。虚拟机系统起来后,同样需要安装 RDMA 驱动,加载 ib_uverbs 模块,在虚拟机内部执行:
bash复制ibv_devinfo
如果能看到设备,说明透传成功。
注意:虚拟机内部的驱动必须和宿主机物理网卡匹配。因为 VF 是物理 PF 的分身,驱动版本错配会导致虚拟机内设备无法正常工作。这也是云平台镜像里必须内置统一 RDMA 驱动版本的原因。
3.4 测试 RDMA 读写性能
等基础配置完成后,马上做一轮性能验证。我常用 perftest 工具做的两个测试是 ib_write_bw 和 ib_read_lat。
先跑到一台机器上起服务端:
bash复制ib_write_bw -d <device> -x 3 --report_gbits
这是监听端,跑在接收方。然后在另一台机器上执行:
bash复制ib_write_bw -d <device> -x 3 --report_gbits <服务端IP>
如果网络正常,很快能看到吞吐结果。我习惯先用单 QP 测,再开多个 QP 打满压力。验证延迟的话:
bash复制ib_read_lat -d <device> <服务端IP>
正常情况下,万兆 RoCE 网络的 ping 延迟相对无意义,但 RDMA 读写延迟应该在几十微秒以内。如果读到几百微秒甚至毫秒,说明配置有问题,别急着调应用。
3.5 云平台调度模块的改造
物理链路通了,还剩最后一步:让云平台能够自助创建带 RDMA 能力的虚拟机。我的做法是扩展云平台的 flavor 和网络模型,新增一个“rdma:true”的规格标签。调度器在创建虚拟机时,先检查宿主机是否有剩余 VF,再检查租户配额,最后根据 PCI 设备所在的 NUMA 节点尽量做亲和性绑定。
亲和性绑定这一点尤其重要。如果 VF 挂在 NUMA node 0,虚拟机 vCPU 却跑在 node 1 上,跨 NUMA 访问会增加延迟。虽然功能不会出错,但性能会损失不少。我们的策略是在宿主机 agent 里记录每个 VF 的位置,虚拟机创建时优先把 vCPU 和内存分配到同一个 NUMA 节点。
3.6 配置快照与自动化
整个配置过程如果全靠手工敲命令,后续运维会非常痛苦。我从第一轮迭代就开始用配置管理工具管理网卡驱动、固件版本、网络配置和交换机预检命令。宿主机 agent 启动时会执行一套脚本,自动检查模块、设备节点、GID、链路速率,如果不满足预期就在监控里上报。
这让我后面扩展新宿主机非常省事:新机器接进来,agent 自动完成大部分初始化,只有分配 VF 这类资源操作留给云平台调度。自动化脚本里我特意加了幂等判断,确保可重复执行而不会重复创建 VF 或重复挂载驱动。
4. 性能调优与问题排查盛宴
4.1 第一轮压测:被 PFC 死锁按在地上摩擦
第一次拿 10 台宿主机做压力测试,吞吐刚到一半就开始剧烈抖动,严重时 RDMA 连接直接超时。后来查交换机计数,发现 RDMA 优先级队列出现了大量 PFC 暂停帧,而且暂停帧没有正常恢复,形成了事实上的死锁。
原因也很经典:PFC 的 buffer 被一个方向的流量占满,反向流量不仅不能走,还因 buffer 占死而暂停,最后造成环路式阻塞。解决方法是调整了交换机上的 buffer 分配,把 RDMA 队列的 buffer 加大到足以吸收瞬时突发,同时开启了 PFC watchdog 机制,持续异常时自动禁用该队列的 PFC,避免影响全网。
4.2 ECN 阈值调参:从一刀切到动态微调
另一个性能杀手是 ECN 阈值设得太低,网卡动不动就收到拥塞标记,频繁降速,最终结果比不用拥塞控制还差。当时对比了两组阈值,一组是队列深度 50%,一组是 20%,前者在强突发流量下表现更稳,后者在持续高负载下更优。后来我针对不同业务类型做了两套模板:存储业务偏吞吐,ECN 阈值调高;AI 训练偏低延迟,ECN 阈值调低,让端到端快速反馈拥塞信号。
4.3 虚拟机内的多队列中断配置
宿主机上直通的 VF 进了虚拟机后,虚拟机内部默认可能只用一个 CPU 核心处理收发。需要手工打开多队列和 RSS,并让中断 CPU 与设备所在 NUMA 节点对齐。我们在虚拟机镜像里内置了一个初始化脚本,开机后自动把网络队列的 CPU 亲和性设置好,同时把 busy_poll 相关参数打开到合理值。
如果不做这一步,虚拟机里的 RDMA 性能会受限于单个 vCPU 的处理能力,遇到大报文时尤其明显。这个坑隐蔽在性能测试初期不容易发现,要到高并发多连接时才会暴露。
4.4 常见问题速查表
| 现象 | 可能原因 | 排查与解决 |
|---|---|---|
| RDMA 设备在虚拟机内看不到 | VF 未成功 bind 到 vfio-pci | 检查宿主机 driver_override 和 IOMMU 映射 |
| 带宽远低于预期 | PFC 未生效或 ECN 阈值过小 | 检查交换机队列计数、PFC 暂停帧数量 |
| 延迟出现周期性尖刺 | NUMA 亲和性未设置 | 调整虚拟机 vCPU 内存到 VF 所在 NUMA 节点 |
| 连接能建立但数据吞吐极低 | GID 索引错误或 RoCE 模式不匹配 | 用 ibv_devinfo 检查 GID 类型是否为 RoCE v2 |
| 多租户干扰严重 | 交换机 ACL 未配置或共享 buffer 不足 | 确认 VLAN 隔离,调整 buffer 分配策略 |
| 宿主机 CPU 占用异常高 | VF 中断未卸载或驱动默认参数不合理 | 启用多队列,调整中断合并参数 |
4.5 压测工具与指标基线
除了 perftest,我还用了第三方压测工具模拟真实业务流。先跑 5 分钟纯带宽测试,观察是否达到线速、衰减幅度、丢包数;再跑 10 分钟随机小包压力测试,观察延迟 P99 曲线。如果 PFC 暂停帧占比高或者 ECN 标记率过高,就必须调参,而不是试图用测例绕过。
我的参考基线是:万兆 RoCE v2 单流写带宽达到 9.5Gbps 以上,8 条流并发时尽量保持 9Gbps 以上;单边写延迟 P50 低于 20 微秒,P99 低于 40 微秒。如果实际数据离这个基线差得远,回归检查网络配置永远是第一步。
5. 踩坑记录与扩展经验
5.1 虚拟机热迁移在 RDMA 场景就是个伪需求
第一次设计云平台方案时,理所当然地想把热迁移特性也保留下来。但 RDMA VF 是物理网卡切出来的直通设备,虚拟机一迁移,VF 就要重新挂载,原有的 RDMA 连接瞬间断开,应用无法自动恢复。我后来和业务部门确认,发现他们能接受“裸金属节点故障时重新调度虚拟机”的方式,只要状态数据落到分布式存储里,重建耗时控制在分钟级即可。于是热迁移在 RDMA 网络池里直接禁用,换来的是大幅简化的调度逻辑。
如果你的业务确实需要热迁移,那就得走网卡虚拟化共享方案,例如在宿主机上用软件模拟 RDMA 语义再把流量代理转发出去,但那种方案性能损耗不小,而且实现复杂度远超我这里的水平。建议在业务需求评审阶段就确认清楚:是不是真的要迁移正在运行的训练任务。
5.2 安全组的配置不能套用普通网络策略
云平台上普通虚拟机的安全组一般基于 IP 和端口。RDMA 流量如果被安全组拦截,连接会异常。我当时做了一版策略:允许租户自定义安全组规则,但必须放通底层 RDMA 所需的 UDP 4791 端口,同时禁止租户修改 RDMA 子网内的网关配置。这个限制起初业务方有点抵触,但实际运行下来并没有影响他们的正常使用,反而减少了很多“网络不通”的工单。
5.3 监控必须能看到物理层指标
云平台本来就希望上层监控“白盒化”,但在 RDMA 网络里,只有虚拟机的指标是远远不够的。我在宿主机上采集网卡计数器,包括 PFC 暂停帧、ECN 标记数、丢包数、链路速率、RDMA QP 数,统一写入监控系统。这样租户报障时,我能先看物理链路有没有异常,再判断是否需要联系交换机侧。
后来有一次凌晨业务降速,看了一圈虚拟机指标没有异常,最后是宿主机网卡的温度过高降速了。如果当时没有采集物理链路速率,这个问题很难定位到硬件层。所以给 RDMA 网络单独做一层物理指标监控,优先级和时间成本都非常值得。
5.4 后续扩展:从万兆到 100G
随着业务数据量增长,万兆的 RoCE 方案很快会看到天花板。如果后续要升级到 100G,硬件和交换机都要换,而且网络调参经验大体类似,但 buffer 要求更苛刻。我的建议是前期部署虚拟化时,尽量预留物理 PCIe 通道带宽和足够的 CPU 核资源,别等升级时发现服务器本身支撑不住。
我个人在实际操作中最大的体会是:RDMA 网络的搭建并不神秘,难点全在“细节”二字。很多人一上来就调参数,反而忽略了最基础的 PFC 链路是否真实生效。每次排查问题我都先看物理计数器的变化,再动的参数,这个顺序能省掉一半的折腾时间。如果你做这个项目,切记把每一步的基础验证做扎实,尤其是在交换机配置完成后,先单独验证 PFC 和 ECN 是否如预期工作,再接入云平台调度,否则后续的变量太多,出了问题根本分不清是网络问题还是平台问题。
