Mellanox -- 性能调优
你的推导在“单 Pod 独占整个 NUMA 节点”的极端假设下是成立的,但在实际的 Kubernetes 生产环境中,这个结论并不完全准确。
这里存在一个核心概念的误区:K8s Topology Manager 的 single-numa-node 策略是针对“单个 Pod”内部的资源对齐,而不是针对“整个节点”的资源独占。
让我们详细拆解一下实际情况:
核心机制澄清:Pod 级对齐 vs 节点级独占
你的假设:如果强制绑核(Topology Manager single-numa-node),那么整个 Node 上所有 Pod 的 CPU 总和不能超过 NUMA 3 的 32 核。
实际机制:
对齐范围:single-numa-node 策略只保证同一个 Pod 内申请的所有资源(CPU、GPU、RDMA)必须落在同一个 NUMA 节点上。
多 Pod 共存:它允许 Node 上同时运行多个 Pod,只要它们各自内部是对齐的即可。
Pod A 可以绑定在 NUMA 3 (使用 4 核 + GPU0 + RDMA0)。
Pod B 也可以绑定在 NUMA 3 (使用 4 核 + GPU1 + RDMA1,如果有多个设备)。
Pod C 可以绑定在 NUMA 0 (使用 4 核 + ...,如果该 Pod 不需要 RDMA 或者 RDMA 也在 NUMA 0)。
关键限制点在于 RDMA 网卡的数量和位置:
如果你的节点上只有 mlx5_0 和 mlx5_1 这两张卡,且它们都在 NUMA 3 上:
需要 RDMA 的 Pod:任何请求了 RDMA 资源的 Pod,必须调度到 NUMA 3 上的 CPU 核。
在这种情况下,所有消耗 RDMA 资源的 Pod 的 CPU 总和确实不能超过 NUMA 3 的可用核数(32 核 - 系统预留)。
如果你试图启动第 N 个需要 RDMA 的 Pod,而 NUMA 3 的剩余 CPU 不足,该 Pod 将调度失败(Pending),即使 NUMA 0/1/2 上有大量空闲 CPU。
不需要 RDMA 的 Pod:普通的 CPU 密集型 Pod(不请求 RDMA 资源)不受此限制。它们可以被调度到 NUMA 0, 1, 2 的任何空闲核上。
场景推演
假设节点配置:
CPU: 4 NUMA 节点 (0, 1, 2, 3),每个 32 核,共 128 核。
RDMA: 2 张卡 (mlx5_0, mlx5_1),都在 NUMA 3。
策略: Kubelet --topology-manager-policy=single-numa-node。
Pod 需求: 每个训练 Pod 需要 4 CPU + 1 RDMA VF。
情况 A:所有 Pod 都需要 RDMA
Pod 1: 占用 NUMA 3 的 4 核 + mlx5_0_VF1。
Pod 2: 占用 NUMA 3 的 4 核 + mlx5_0_VF2。
...
Pod 8: 占用 NUMA 3 的 4 核 + mlx5_1_VF1。
总计: 最多只能运行 32 / 4 = 8 个这样的 Pod。
结果: 此时 NUMA 0, 1, 2 的 96 个核全部空闲,但无法再调度任何需要 RDMA 的 Pod。
结论: 是的,在这种特定场景下(所有业务都强依赖位于单一 NUMA 的 RDMA 设备),该 NUMA 节点的 CPU 核数成为了瓶颈。
情况 B:混合负载 (部分 Pod 不需要 RDMA)
上述 8 个 RDMA Pod 跑在 NUMA 3。
另外启动 20 个纯 CPU 推理 Pod (不需要 RDMA)。
结果: 这 20 个 Pod 会被调度到 NUMA 0, 1, 2。
结论: 节点总 CPU 利用率可以远超 32 核,只有RDMA 相关任务受限于 NUMA 3。
如何解决这个瓶颈?
如果业务确实需要超过 32 个并发 RDMA 任务(即超过单个 NUMA 的 CPU 承载能力),通常有以下几种优化方案:
方案一:超分 CPU (Overcommit) - 最常见
RDMA 传输主要依赖网卡硬件卸载,CPU 主要用于发起指令和处理少量中断。对于大模型训练或高性能存储,CPU 并不需要 100% 独占。
操作: 调整 Kubelet 参数 --cpu-manager-policy=static 的同时,配合 CPU Quota 或在 Pod 中设置 requests < limits。
效果: 允许在 NUMA 3 的 32 个物理核上运行超过 32 个 vCPU 的 RDMA Pod(例如运行 16 个 Pod,每个配 4 vCPU,总共 64 vCPU,通过时间片轮转共享物理核)。
风险: 可能会增加延迟,但对于吞吐型任务(如训练)通常可接受。
方案二:调整拓扑策略为 best-effort 或 restricted
如果不强制 single-numa-node,可以使用较弱的策略。
restricted: 尝试对齐,如果无法对齐(例如 CPU 不够了),则允许跨 NUMA 调度。
后果: Pod 可以调度成功,利用 NUMA 0 的 CPU 和 NUMA 3 的 RDMA。
性能影响: 会产生 QPI/UPI 跨 socket 流量,导致 RDMA 延迟增加、带宽轻微下降。对于极度敏感的业务不可取,但对于一般业务可能是性价比最高的方案。
方案三:硬件层面优化 (根本解决)
BIOS 设置: 检查 BIOS 是否开启了 "NUMA Node Per Socket" (NPS) 选项。有些服务器默认是 NPS=1 (整个 Socket 一个大 NUMA),可以改为 NPS=4 (将一个大 Socket 切分成 4 个小 NUMA)。
如果 mlx5 网卡物理连接在 PCIe Switch 上,而该 Switch 连接到 CPU 的特定 Lane,修改 NPS 可能无法改变网卡的物理 NUMA 归属,但能细化 CPU 的粒度。
网卡插槽: 在采购或装机时,确保多张 RDMA 网卡分散在不同的 NUMA 节点上(例如 mlx5_0 在 NUMA 3, mlx5_1 在 NUMA 2)。这样可以将 RDMA 任务的 CPU 瓶颈分散到两个 NUMA 节点,容量翻倍。
方案四:使用 Volcano 进行更细粒度的调度
如前所述,使用 Volcano 可以编写自定义策略。例如,定义一个策略:
优先满足 NUMA 亲和性。
当 NUMA 3 CPU 耗尽时,允许新 Pod 跨 NUMA 调度(自动降级为性能稍差的模式),而不是直接 Pending。
总结
你的担忧是部分正确的:
对于强依赖 RDMA 且要求严格 NUMA 亲和性的任务,其并发度确实受限于RDMA 网卡所在 NUMA 节点的 CPU 核数(本例中为 32 核)。
但这并不意味着整个节点只能跑 32 个 CPU,其他不依赖该 RDMA 设备的任务依然可以使用其他 NUMA 的 CPU。
建议操作:
评估业务特性:确认你的 RDMA 任务是否真的需要独占 CPU,还是可以通过超分(Overcommit)来突破 32 核限制。
检查硬件分布:确认是否所有高速网卡都挤在同一个 NUMA 上,未来规划时尽量分散。
灵活配置策略:在生产环境中,很少全程开启 single-numa-node。通常做法是:
关键训练任务:使用 single-numa-node 保证极致性能。
普通推理/预处理任务:使用 best-effort 或利用 Volcano 动态决策,允许跨 NUMA 以换取更高的资源利用率。

浙公网安备 33010602011771号