
为什么你的 RDMA 在容器里突然变慢?
容器化如何悄悄打破算力网络的物理假设。
现象:一切都“看起来正常”
某天,你把训练任务从裸机迁移到 Kubernetes,结果出现:
- GPU 利用率从 95% 掉到 72%;
- NCCL 没有报错;
- 网络没有丢包;
- NIC 带宽也能打满;
- 延迟却明显增加。
更诡异的是:
在宿主机运行 RDMA benchmark 一切正常,换到容器里就变慢。
这就是典型的容器跨层问题。
容器里的网络和设备“可以使用”,并不意味着运行时仍然沿用了裸机上的最优物理路径。只要 CPU、GPU、NIC、PCIe、NUMA、CNI 或 cgroup 中有一层发生错位,最终都可能表现为 NCCL 变慢和 GPU 等待。
RDMA 本来依赖什么假设?
在裸机环境下,RDMA 的高性能依赖四个核心假设:
- GPU 与 NIC 之间的距离足够短;
- NUMA 绑定正确;
- NIC 资源完整;
- MTU 和优先级配置一致。
容器化后,这四个假设都可能被破坏。
问题在于,容器提供的是逻辑隔离,而 RDMA 性能依赖的是实际物理路径。Kubernetes 可以看到一个可分配的 GPU 和一个可分配的 VF,却不一定知道它们是否位于同一个 NUMA Node、同一个 PCIe Switch 或同一条 rail 上。
完整排查路径
遇到“裸机正常、容器变慢”时,可以按照下面的顺序检查:
RDMA 变慢
│
├── ① 是否跨 NUMA?
├── ② GPU ↔ NIC 是否仍在同一 PCIe 域?
├── ③ 是否使用 VF(SR-IOV)?
├── ④ MTU 是否被 CNI 改写?
├── ⑤ 是否启用了 hostNetwork?
├── ⑥ cgroup 是否限制 RDMA 资源?
└── ⑦ 多轨调度或 iptables / TC 是否产生干扰?
排查时不要只看“网络通不通”和“带宽能不能跑满”。容器场景里的问题经常不是硬故障,而是延迟增加、队列并行度下降、路径绕远或尾延迟抖动。
第一类问题:NUMA 亲和性被打破
裸机环境中,理想状态是:
GPU0 + NIC0 位于 NUMA0
训练进程绑定 NUMA0
进入容器后,可能出现:
- Pod 被调度到任意 CPU;
- 没有开启 Topology Manager;
- 没有设置 CPU pinning;
- CPU、GPU 和 NIC 的 NUMA 位置没有一起参与调度。
最终变成:
进程运行在 NUMA1
GPU / NIC 位于 NUMA0
这会带来:
- 跨 UPI 访问;
- PCIe 访问延迟增加;
ibv_post_send变慢;- 内存分配落在远端 NUMA Node;
- GPU、NIC 与 CPU 控制路径错位。
排查命令
在容器内检查进程 NUMA 策略:
numactl --show
检查 HCA 所属 NUMA Node:
cat /sys/class/infiniband/mlx5_0/device/numa_node
检查 GPU、NIC 与 CPU 之间的拓扑距离:
nvidia-smi topo -m
如果进程所在 NUMA Node 与 GPU、NIC 不一致,NUMA 错位就是第一嫌疑人。
第二类问题:GPU 与 NIC 拓扑被破坏
容器环境中常见的资源暴露方式是:
- 通过 Device Plugin 暴露 GPU;
- 通过 SR-IOV 暴露 VF。
但“GPU 可用”和“VF 可用”只代表资源已经分配给 Pod,并不代表两者物理距离最近。
裸机时可能是:
GPU0 --(PIX)-- NIC0
容器里却可能变成:
GPU0 --(SYS)-- VF3
PIX 通常表示设备间只经过单个 PCIe Bridge,而 SYS 往往意味着路径需要跨 NUMA Node 或 CPU 互连。此时 GPUDirect RDMA 的数据路径变长,延迟随之上升。
所以不能只验证 Pod 里“能看到 GPU”和“能看到 RDMA 设备”,还需要验证:
- GPU 与 VF 是否位于同一个 NUMA Node;
- GPU 与 VF 是否经过同一个 PCIe Switch;
- 分配给 Pod 的 VF 是否就是这张 GPU 的近端 NIC;
- Device Plugin 与 SR-IOV Network Device Plugin 是否使用一致的拓扑信息;
- 调度器是否把 GPU 和 NIC 当作一个拓扑组合来分配。
第三类问题:SR-IOV 切割 NIC 资源
SR-IOV 会把一个 Physical Function(PF)切成多个 Virtual Function(VF)。它提供了隔离能力,但不会自动提升性能。
切分后可能发生:
- QP 资源被切割;
- NIC SRAM 被重新分配;
- DCQCN 状态被隔离;
- 单个 VF 可用的队列和上下文资源减少。
可能的结果包括:
- 单 VF 可用 QP 减少;
- 拥塞控制精度下降;
- 瞬时突发更明显;
- NCCL 通信并行度受限;
- CNP 增多,延迟抖动加剧。
排查命令
查看 RDMA 设备及其能力:
ibv_devinfo
查看网卡侧 PFC 等统计:
ethtool -S ethX | grep -i pfc
同时确认容器内使用的是 PF 还是 VF,以及 VF 的资源上限是否满足当前 NCCL 通信规模。
第四类问题:MTU 被 CNI 改写
部分 CNI 或 Overlay 网络会把容器接口的 MTU 改成 1450,甚至更小,而 RoCE 网络仍然使用 9000 MTU。
这可能导致:
- 宿主机和容器的 MTU 不一致;
- 容器控制路径上的报文发生碎片化;
- 小包延迟明显上升;
- 数据面和控制面表现不一致;
- 问题只在容器网络命名空间里出现。
排查命令
查看容器内接口:
ip link show
查看指定接口 MTU:
cat /sys/class/net/ethX/mtu
需要同时对比宿主机和容器,而不是只检查物理 NIC 上的 MTU。
第五类问题:hostNetwork 与独立 netns
如果 Pod 没有启用 hostNetwork:
- 容器位于独立的 network namespace;
- iptables 规则可能不同;
- TC 可能插入额外队列;
- conntrack、mangle 或限速规则可能进入控制路径。
RoCEv2 使用 UDP 4791。不同的 CNI、netns 和策略配置,可能让相关流量经过额外处理。即使没有丢包,也可能增加 CPU 路径开销和尾延迟。
检查时应关注:
- Pod 是否使用
hostNetwork; - RDMA 数据接口是否真正绕开 Overlay;
- 容器 netns 内是否存在额外路由;
- iptables 是否包含 conntrack、mangle 或限速规则;
- TC 是否在接口上挂载 qdisc 或 filter;
- 数据面和管理面是否错误地共用同一条容器网络路径。
第六类问题:cgroup RDMA 限制
Linux 支持通过 cgroup 限制 RDMA 资源:
/sys/fs/cgroup/rdma/
如果 kubelet 或运行时启用了限制,每个 Pod 可使用的 QP、CQ 等资源可能受限。
结果可能是:
- NCCL 被迫复用 QP;
- 通信并行度下降;
- 大规模 rank 数下更容易触达资源上限;
- 小规模测试正常,大规模训练变慢;
- 性能下降却没有明显网络错误。
因此,除了确认设备已经挂载到容器,还要检查容器实际获得了多少 RDMA 资源。
第七类问题:多轨调度被打乱
在一台 8 NIC 服务器上,裸机环境可能按照下面的方式使用多轨网络:
channel0 → NIC0
channel1 → NIC1
channel2 → NIC2
...
容器化后,如果一个 Pod 只被分配到一个 VF,多 rail 的优势就会消失,通信带宽可能骤降。
即使 Pod 获得多个 VF,也需要继续确认:
- VF 是否来自不同 rail;
- VF 是否分别靠近对应 GPU;
- NCCL 是否识别并使用全部 HCA;
- 容器内的设备命名是否改变了 NCCL HCA 选择;
- 轨道之间是否出现流量不均;
- Pod 调度是否把所有 VF 集中到同一物理 NIC 或同一 Leaf。
多轨性能问题经常不是“少了一张网卡”这么简单,而是物理 rail、逻辑 VF 和 NCCL channel 三者的映射被打乱。
一个真实案例
场景:
- 16 个节点;
- 每个节点 8 张 GPU;
- 每节点使用 8 个 SR-IOV VF;
- 由 Kubernetes 调度。
现象:
- GPU 利用率只有 73%;
- 单机裸机测试可以达到 96%;
- 容器内 RDMA latency 增加 18%;
- NUMA 位置不一致;
- VF 不在 GPU 最近的 PCIe Switch 下。
修复动作:
- 启用 Topology Manager;
- 设置
single-numa-nodepolicy; - 手动对齐 GPU 与 VF。
修复后,GPU 利用率恢复到 92%。
这个案例说明,即使 NIC 带宽能够跑满、NCCL 也没有报错,错误的 NUMA 和 PCIe 路径仍然会让 GPU 在同步点等待。
容器化到底破坏了什么?
容器的本质,是把逻辑隔离叠加在物理资源之上;RDMA 则是一项极度依赖物理路径的技术。
当逻辑层忽略物理层时,性能就会悄悄下降:
- RDMA 的性能来自物理拓扑,而不是 API;
- 容器不会自动理解 PCIe 距离;
- NUMA 错位是容器算力集群中最常见的隐形问题之一;
- SR-IOV 是隔离工具,不是性能增强工具;
- 裸机正常,不代表容器正常。
因此,容器化 RDMA 的正确验收方式不能只是“设备能看到、网络能连通”。至少还要验证:
- CPU、GPU、NIC 是否位于一致的 NUMA 边界;
- GPU 与 VF 的 PCIe 距离是否符合预期;
- PF / VF 的 QP、CQ 等资源是否足够;
- 宿主机与容器 MTU、QoS 配置是否一致;
- netns、iptables 和 TC 是否引入额外路径;
- cgroup 是否限制 RDMA 资源;
- 多 rail 是否仍然被 NCCL 正确使用。
真正的问题往往不在某一个组件内部,而在 Kubernetes 调度、容器网络、PCIe 拓扑、NUMA、SR-IOV 和 NCCL 的交界处。