算力靠 GPU,吞吐靠带宽——六层分工讲清:Calico 管连通、Multus 管多网卡、RoCE 管无损、NCCL 管通信、SGLang 管推理
很多团队把大模型推理部署到 Kubernetes 后,发现一个尴尬现象:单机跑得飞起,一上多机分布式,吞吐反而腰斩。排查到最后,问题几乎都出在网络——不是 GPU 不够快,而是 GPU 之间的数据「运不过来」。
大模型从单机走向多机,本质上是把一次计算切给几十上百张卡并行完成,卡与卡之间要频繁交换激活值、梯度、KV Cache。以张量并行(TP)为例,每层都要做一次 AllReduce / AllGather,通信量动辄 GB 级且对延迟极度敏感。此时普通以太网根本喂不饱,必须上 RDMA 无损网络(RoCE 或 InfiniBand)。
而要把「GPU + RDMA 网卡 + 集合通信库 + 推理引擎」这套栈在声明式的 Kubernetes 里跑起来,需要几个关键组件各司其职:
| 组件 | 角色 | 一句话定位 |
|---|---|---|
| Calico | 默认 CNI | 管「控制面」:Pod 之间、Pod 到 Service 的普通 IP 网络 |
| Multus-CNI | Meta CNI | 管「多网卡」:给 Pod 多挂一张 RDMA 专用网卡 |
| RoCE | 网络协议 | 管「无损」:在以太网上跑 RDMA,配合 PFC/ECN 不丢包 |
| NCCL | 通信库 | 管「集合通信」:AllReduce 原语 + 走 RoCE 的路径选择 |
| GPU | 算力 | 管「算」:Device Plugin/GPU Operator 接入调度,NVLink 卡间互联 |
| SGLang | 推理引擎 | 管「推理」:RadixAttention + 连续批处理 + 多节点 TP |
先把全景图摆在前面。一条多机推理请求从用户到 GPU,大致走这样一条链路:
一句话记住分工:Calico 是「门牌号」,Multus 是「第二根网线」,RoCE 是「高速公路」,NCCL 是「调度员」,SGLang 是「老司机」。
Kubernetes 原生 CNI 规范里,一个 Pod 默认只有一张网卡(通常是 eth0,走集群默认 CNI)。但大模型场景需要「两张网」:
如果硬把 RDMA 流量和普通流量挤在同一张网卡上,控制流量会抢占、抖动会传导到集合通信,导致训练/推理性能雪崩。所以业界约定俗成:数据面(RDMA)和控制面(普通 IP)分离。
Multus 是一个 CNI meta-plugin(元插件),它本身不实现网络,而是「代理调用」其他 CNI 插件。核心三件套:
multus-cni 二进制和配置文件k8s.v1.cni.cncf.io/networks 指定要给 Pod 挂哪些附加网络流程是:Pod 创建时,kubelet 调 Multus → Multus 先调默认 CNI(Calico)配 eth0 → 再按注解调附加 CNI 配第二张、第三张网卡。
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
name: roce-net
namespace: default
spec:
config: '{
"cniVersion": "0.3.1",
"type": "macvlan",
"master": "ens2f0",
"mode": "bridge",
"ipam": {
"type": "host-local",
"ranges": [[{ "subnet": "192.168.100.0/24" }]]
}
}'
Pod 里这样挂载:
apiVersion: v1
kind: Pod
metadata:
name: sglang-worker-0
annotations:
k8s.v1.cni.cncf.io/networks: roce-net
spec:
containers:
- name: sglang
image: lmsysorg/sglang:latest
resources:
limits:
nvidia.com/gpu: "8"
rdma/rdma_shared_device_a: "1"
生产上 RDMA 网卡更推荐 SR-IOV(
sriovCNI + SR-IOV Network Operator),它能给每个 Pod 切出独立的 VF 虚拟网卡,直接获得硬件级 RDMA 能力,性能接近物理网卡,且免去 macvlan 桥接的额外开销。
Calico 在这套栈里扮演默认网络的角色。Multus 挂附加网卡前,会先调 Calico 给 Pod 配好 eth0。它的职责边界很清楚:
Calico 走 BGP 或 VXLAN/IPIP overlay,性能对「普通流量」完全够用,但不适合 RDMA——overlay 封装会破坏 RoCE 的无损假设,且引入 CPU 开销。这也是为什么 RDMA 流量必须走 Multus 附加的「物理/直连」网卡,而不是 Calico。
一句话:Calico 负责「能连通」,RoCE 附加网负责「通得快」。两者通过 Multus 解耦,互不干扰。
RDMA(Remote Direct Memory Access,远程直接内存访问)让一台机器的网卡绕过 CPU 和内核,直接把数据写进对端机器的内存。好处是三个「低」:低延迟(微秒级)、低 CPU 占用、高吞吐(单口 100G/200G/400G)。
| 维度 | InfiniBand(IB) | RoCEv2 |
|---|---|---|
| 物理网络 | 专用 IB 交换机和线缆 | 标准以太网交换机 |
| 原生无损 | 天生具备端到端流控 | 需靠 PFC/ECN 构造无损以太网 |
| 成本 | 高(专用硬件生态) | 低(复用以太网,性价比高) |
| 部署 | 独立组网 | 与现有以太网融合,适合 K8s 云原生 |
多数 GPU 云和自建 K8s 集群选 RoCEv2,因为成本低、易扩展,性能在配置得当后接近 IB。
RoCEv2 最怕丢包——一旦丢包,RDMA 要重传并做拥塞控制,性能出现「悬崖式」下跌。所以必须构造无损以太网:
两者配合:PFC 兜底「硬不丢包」,ECN 提前「软减速」,避免触发 PFC 的级联暂停。
NCCL_IB_GID_INDEX 指定用哪个 GID 通信,查法:show_gids 命令。NCCL(NVIDIA Collective Communications Library)是 NVIDIA 为多 GPU、多节点设计的集合通信库,实现 AllReduce、AllGather、Broadcast、ReduceScatter、All2All 等原语,是 PyTorch、DeepSpeed、SGLang、vLLM 等框架分布式通信的底层底座。
NCCL 的通信路径有一套「就近原则」自动选择:单机内优先 NVLink/NVSwitch(P2P)→ 跨机走 IB/RoCE(RDMA)→ 兜底走 TCP socket。生产上通常通过环境变量显式指定,避免它「选错路」。
export NCCL_IB_DISABLE=0 # 0=启用 IB/RoCE 走 RDMA 路径
export NCCL_SOCKET_IFNAME=eth0 # TCP socket 用的网卡(控制面)
export NCCL_IB_HCA=mlx5_0 # 指定 RDMA 网卡(ibv_devices 查到的名字)
export NCCL_IB_GID_INDEX=3 # RoCEv2 的 GID 索引(show_gids 查)
export NCCL_IB_TIMEOUT=22 # IB 超时,网络繁忙时调大减少误判
export NCCL_IB_RETRY_CNT=7 # 失败重试次数
export NCCL_P2P_LEVEL=NVL # 单机内优先 NVLink 点对点
export NCCL_NET_GDR_LEVEL=5 # 启用 GPUDirect RDMA(值越高越激进)
NCCL_IB_GID_INDEX是最容易踩坑的一个:容器里 RoCE 网卡的 GID 索引往往与宿主机不一致(Multus/SR-IOV 会动态分配),配错直接导致通信失败。进容器先跑show_gids确认再填。
GPU 要成为 K8s 里「可调度、可分配、可隔离」的资源,需要跨四道关卡:
nvidia-container-runtime)把驱动、libcuda 挂进容器nvidia-device-plugin DaemonSet 向 kubelet 注册 nvidia.com/gpu 资源limits: nvidia.com/gpu: 8 分配 GPUnvidia-device-plugin DaemonSet单机 8 卡之间不靠 RoCE,靠 NVLink + NVSwitch 做点对点全互联(如 H100 8 卡 NVLink 全互联),带宽高达 TB/s 级且延迟极低。所以「跨机用 RoCE、机内用 NVLink」是标准分层——NCCL 的 NCCL_P2P_LEVEL 就是为此设计的。
网络和 GPU 都就位后,最后一环是推理引擎如何高效调度。SGLang(由 LMSYS 与 UC Berkeley 等团队研发)是目前与 vLLM 并驾齐驱的两大开源推理引擎之一,核心创新在于:
SGLang 在 vLLM 的 PagedAttention 基础上,进一步用 Radix Tree(基数树) 结构组织所有请求的 KV Cache。共享相同前缀的请求(如 RAG 的公共上下文、多轮对话的历史、Agent 的系统提示词)自动复用同一段 KV,省下大量重复计算与显存。这是它在前缀共享型负载上显著领先 vLLM 的根源。
与传统「等一个 batch 跑完再放下一批」不同,连续批处理每完成一个 token 就动态接纳新请求、踢掉完成请求,把 GPU 的每个「空位」都填满,最大化吞吐。
大模型单卡放不下时,SGLang 支持 张量并行(TP) 与 流水线并行(PP) 切分。跨节点的 TP 通信正是走前面铺好的 RoCE + NCCL 通道——所以「网络栈搭得好,SGLang 的分布式才能快」。
| 维度 | SGLang | vLLM |
|---|---|---|
| KV 缓存机制 | RadixAttention(基数树,前缀共享强) | PagedAttention(分页管理) |
| 前缀共享/RAG/多轮对话 | 优势显著 | 有前缀缓存,粒度更粗 |
| 吞吐(特定基准) | 部分基准高约 29% | 通用场景稳定 |
| 硬件/模型兼容 | 主要 NVIDIA,覆盖主流架构 | 更广(NVIDIA/AMD/TPU/Gaudi,400+ 架构) |
| 结构化输出 | 原生支持好 | 需配合约束解码 |
把上面的组件串起来,一个多机 SGLang 推理 Pod 的关键配置长这样(示意):
apiVersion: v1
kind: Pod
metadata:
name: sglang-0
annotations:
k8s.v1.cni.cncf.io/networks: sriov-roce-net # Multus 挂 RDMA VF 网卡
spec:
containers:
- name: sglang
image: lmsysorg/sglang:latest
resources:
limits:
nvidia.com/gpu: "8"
env:
- name: NCCL_SOCKET_IFNAME
value: "eth0" # 控制面走默认网卡
- name: NCCL_IB_DISABLE
value: "0" # 启用 RoCE RDMA
- name: NCCL_IB_HCA
value: "mlx5_0" # RDMA 网卡名
- name: NCCL_IB_GID_INDEX
value: "3" # 容器内 show_gids 确认
- name: NCCL_NET_GDR_LEVEL
value: "5" # 开启 GPUDirect RDMA
command: ["python", "-m", "sglang.launch_server"]
args:
- "--model", "Qwen/Qwen2.5-72B-Instruct"
- "--tp", "16" # 跨 2 节点 × 8 卡张量并行
- "--trust-remote-code"
启动后,跨节点的 TP 激活值/KV 交换会通过 mlx5_0 这张 RDMA 网卡走 RoCEv2 + GPUDirect RDMA,直连对端 GPU 显存;而服务发现、健康检查、模型下载仍走 Calico 的 eth0,两网互不干扰。
NCCL_IB_GID_INDEX 别照搬宿主机值,容器内 show_gids 为准NCCL_NET_GDR_LEVEL=5 让数据直达显存,多机大模型收益明显NCCL_P2P_LEVEL 控制机内路径,别让机内流量绕去网络在 Kubernetes 上跑大模型,很多人只盯着「GPU 多少张、显存多少 G」,却忽略了真正决定分布式吞吐的那根「隐形水管」。把这套栈捋顺,你会发现每一层都有明确的分工:
网络栈搭不好,买再多的 H100 也跑不出应有的吞吐。下次你的多机推理吞吐腰斩时,别急着加卡——先 show_gids 看一眼 GID 索引,再 ib_write_bw 压一下 RDMA 带宽,往往问题就藏在「第二根网线」上。
GPU 集群、RoCE 网络、分布式推理调优,都是持续的基础设施工程。向量云(南京)科技有限公司依托字节跳动火山方舟官方授权,专注大模型应用落地:
| 向量云能力 | 说明 |
|---|---|
| 官方授权接入 | 火山方舟官方 API 与官方 Key 直连 |
| 低折扣 Token | 专属折扣价,用量越大越划算 |
| 独享接入点 | 独立接入点,缓存与配额不被公共池挤占 |
| 缓存隔离降本 | 上下文缓存红利稳定落袋 |
| 计费灵活 | 按量计费、即用即扣、注册充值 10 元起 |
| 协议兼容 | OpenAI 兼容协议,业务代码几乎零改动 |
接入方式:注册后获取官方 API Key,把 base_url 指向向量云接入点即可直接调用火山方舟官方模型。
获取 API Key:https://ark.tokenrize.cn/ · 火山方舟官方 API 与 Key 直连,注册即用
一句话总结:算力靠 GPU,吞吐靠带宽——Calico 管连通、Multus 管多网卡、RoCE 管无损、NCCL 管通信、SGLang 管推理,六层各司其职才能喂饱大模型。
面向大模型应用落地的技术服务型企业,依托字节跳动火山方舟能力,为合作方提供低折扣模型 Token、可独立部署的运营支撑平台及全链路运营支持。
火山方舟官方 API 与官方 Key 直连 · 向量云 · Kubernetes GPU 网络栈(Multus-CNI / Calico / NCCL / RoCE / SGLang)
A. Kubernetes 原生一个 Pod 默认只有一张网卡(eth0)。大模型场景需要「控制面 + 数据面」分离:普通 TCP 走默认网卡,RDMA 大流量走独立网卡。Multus 是一个 CNI 元插件,它代理调用其他 CNI 插件,通过 NetworkAttachmentDefinition(NAD)CRD 定义附加网络,再通过 Pod 注解 k8s.v1.cni.cncf.io/networks 把第二张网卡挂进 Pod,实现多网卡。
A. Calico 是集群默认 CNI,负责 Pod 到 Pod、Pod 到 Service 的普通 IP 网络与 NetworkPolicy;Multus 是 meta-plugin,创建 Pod 时先调 Calico 配好 eth0,再按注解调附加 CNI 配第二张网卡。两者通过 Multus 解耦:Calico 负责「能连通」,RDMA 附加网卡负责「通得快」,互不干扰。
A. InfiniBand 用专用交换机和线缆、天生无损但成本高;RoCEv2 在标准以太网上跑 RDMA、成本低易扩展。RoCEv2 强依赖无损以太网:需要 PFC(基于优先级的流控)兜底「硬不丢包」,ECN(显式拥塞通知)+ DCQCN 提前「软减速」,否则一旦丢包,RDMA 重传会导致性能悬崖式下跌。
A. 常用:NCCL_IB_DISABLE=0(启用 RDMA)、NCCL_SOCKET_IFNAME=eth0(控制面网卡)、NCCL_IB_HCA=mlx5_0(RDMA 网卡)、NCCL_IB_GID_INDEX(RoCEv2 的 GID 索引,容器内 show_gids 确认)、NCCL_IB_TIMEOUT、NCCL_P2P_LEVEL=NVL(机内 NVLink)、NCCL_NET_GDR_LEVEL=5(GPUDirect RDMA)。其中 GID 索引最容易配错,容器内外不一致会直接导致通信失败。
A. GPUDirect RDMA(GDR)让 RDMA 网卡直接读写 GPU 显存,数据从对端 GPU 显存直达本端 GPU 显存,全程不经过 CPU 和主机内存,显著降低延迟与 CPU 占用,是多机大模型集合通信的关键加速项,通过 NCCL_NET_GDR_LEVEL 启用。
A. SGLang 的核心是 RadixAttention——用基数树(Radix Tree)组织 KV 缓存,共享相同前缀的请求(RAG 公共上下文、多轮对话历史、Agent 系统提示)自动复用同一段 KV,省下大量重复计算与显存;配合连续批处理,在前缀共享型负载下吞吐显著领先,部分基准高约 29%,结构化输出支持也更好。vLLM 的优势则在更广的硬件与模型兼容性。
A. 用 Multus 给推理 Pod 挂一张 RDMA 网卡(SR-IOV VF 或 macvlan),配置 NCCL 环境变量(NCCL_IB_HCA、NCCL_IB_GID_INDEX、NCCL_NET_GDR_LEVEL 等),SGLang 以 --tp 做跨节点张量并行,跨节点 TP 的激活值/KV 交换就会通过这张 RDMA 网卡走 RoCEv2 + GPUDirect RDMA 直达对端 GPU 显存;服务发现、模型下载等控制流量仍走 Calico 的 eth0。