Kubernetes · GPU 网络栈

Kubernetes 上跑大模型:
Multus-CNI、Calico、NCCL、RoCE 与 SGLang 的 GPU 网络栈详解

算力靠 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-CNIMeta CNI管「多网卡」:给 Pod 多挂一张 RDMA 专用网卡
RoCE网络协议管「无损」:在以太网上跑 RDMA,配合 PFC/ECN 不丢包
NCCL通信库管「集合通信」:AllReduce 原语 + 走 RoCE 的路径选择
GPU算力管「算」:Device Plugin/GPU Operator 接入调度,NVLink 卡间互联
SGLang推理引擎管「推理」:RadixAttention + 连续批处理 + 多节点 TP
分层总览

一、一条推理请求走过的六层栈

先把全景图摆在前面。一条多机推理请求从用户到 GPU,大致走这样一条链路:

  1. Ingress / 应用层:请求进入服务,命中某个推理 Pod
  2. SGLang 引擎:调度请求、做 Prefill/Decode、管理 KV Cache
  3. NCCL 通信:TP 切分下各卡交换激活值/KV,发起集合通信
  4. RoCE / RDMA 网卡:NCCL 把数据交给 RDMA 网卡,走无损以太网直达对端 GPU 显存
  5. Multus 附加网络:这张 RDMA 网卡由 Multus 通过 NetworkAttachmentDefinition 挂进 Pod
  6. Calico 主网络:默认 eth0 继续负责服务发现、健康检查、控制流量

一句话记住分工:Calico 是「门牌号」,Multus 是「第二根网线」,RoCE 是「高速公路」,NCCL 是「调度员」,SGLang 是「老司机」。

Multus-CNI

二、Multus-CNI:让一个 Pod 长出多张网卡

1. 为什么需要 Multus

Kubernetes 原生 CNI 规范里,一个 Pod 默认只有一张网卡(通常是 eth0,走集群默认 CNI)。但大模型场景需要「两张网」:

如果硬把 RDMA 流量和普通流量挤在同一张网卡上,控制流量会抢占、抖动会传导到集合通信,导致训练/推理性能雪崩。所以业界约定俗成:数据面(RDMA)和控制面(普通 IP)分离。

2. Multus 的实现机制

Multus 是一个 CNI meta-plugin(元插件),它本身不实现网络,而是「代理调用」其他 CNI 插件。核心三件套:

流程是:Pod 创建时,kubelet 调 Multus → Multus 先调默认 CNI(Calico)配 eth0 → 再按注解调附加 CNI 配第二张、第三张网卡。

3. 一个 NAD 示例(macvlan 挂物理 RDMA 网卡)

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(sriov CNI + SR-IOV Network Operator),它能给每个 Pod 切出独立的 VF 虚拟网卡,直接获得硬件级 RDMA 能力,性能接近物理网卡,且免去 macvlan 桥接的额外开销。

Calico

三、Calico:默认 CNI 与「控制面」担当

Calico 在这套栈里扮演默认网络的角色。Multus 挂附加网卡前,会先调 Calico 给 Pod 配好 eth0。它的职责边界很清楚:

Calico 走 BGP 或 VXLAN/IPIP overlay,性能对「普通流量」完全够用,但不适合 RDMA——overlay 封装会破坏 RoCE 的无损假设,且引入 CPU 开销。这也是为什么 RDMA 流量必须走 Multus 附加的「物理/直连」网卡,而不是 Calico。

一句话:Calico 负责「能连通」,RoCE 附加网负责「通得快」。两者通过 Multus 解耦,互不干扰。

RoCE / RDMA

四、RoCE / RDMA:在以太网上跑「零拷贝」直连

1. RDMA 是什么

RDMA(Remote Direct Memory Access,远程直接内存访问)让一台机器的网卡绕过 CPU 和内核,直接把数据写进对端机器的内存。好处是三个「低」:低延迟(微秒级)、低 CPU 占用、高吞吐(单口 100G/200G/400G)。

2. RoCEv2 与 InfiniBand 的区别

维度InfiniBand(IB)RoCEv2
物理网络专用 IB 交换机和线缆标准以太网交换机
原生无损天生具备端到端流控需靠 PFC/ECN 构造无损以太网
成本高(专用硬件生态)低(复用以太网,性价比高)
部署独立组网与现有以太网融合,适合 K8s 云原生

多数 GPU 云和自建 K8s 集群选 RoCEv2,因为成本低、易扩展,性能在配置得当后接近 IB。

3. 无损以太网的两个关键:PFC 与 ECN

RoCEv2 最怕丢包——一旦丢包,RDMA 要重传并做拥塞控制,性能出现「悬崖式」下跌。所以必须构造无损以太网:

两者配合:PFC 兜底「硬不丢包」,ECN 提前「软减速」,避免触发 PFC 的级联暂停。

4. GID 与 GPUDirect RDMA

NCCL

五、NCCL:GPU 集合通信的「调度员」

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

六、GPU:从硬件到 K8s 可调度资源

GPU 要成为 K8s 里「可调度、可分配、可隔离」的资源,需要跨四道关卡:

  1. 驱动层:宿主机装好 NVIDIA 驱动 + CUDA
  2. 容器运行时:NVIDIA Container Toolkit(nvidia-container-runtime)把驱动、libcuda 挂进容器
  3. 设备插件:nvidia-device-plugin DaemonSet 向 kubelet 注册 nvidia.com/gpu 资源
  4. 调度层:调度器按 limits: nvidia.com/gpu: 8 分配 GPU

Device Plugin 与 GPU Operator

单机多卡的「另一张网」:NVLink / NVSwitch

单机 8 卡之间不靠 RoCE,靠 NVLink + NVSwitch 做点对点全互联(如 H100 8 卡 NVLink 全互联),带宽高达 TB/s 级且延迟极低。所以「跨机用 RoCE、机内用 NVLink」是标准分层——NCCL 的 NCCL_P2P_LEVEL 就是为此设计的。

SGLang

七、SGLang:把 GPU 与带宽「用满」的推理引擎

网络和 GPU 都就位后,最后一环是推理引擎如何高效调度。SGLang(由 LMSYS 与 UC Berkeley 等团队研发)是目前与 vLLM 并驾齐驱的两大开源推理引擎之一,核心创新在于:

1. RadixAttention:前缀共享的「基数树 KV 缓存」

SGLang 在 vLLM 的 PagedAttention 基础上,进一步用 Radix Tree(基数树) 结构组织所有请求的 KV Cache。共享相同前缀的请求(如 RAG 的公共上下文、多轮对话的历史、Agent 的系统提示词)自动复用同一段 KV,省下大量重复计算与显存。这是它在前缀共享型负载上显著领先 vLLM 的根源。

2. Continuous Batching(连续批处理)

与传统「等一个 batch 跑完再放下一批」不同,连续批处理每完成一个 token 就动态接纳新请求、踢掉完成请求,把 GPU 的每个「空位」都填满,最大化吞吐。

3. 多节点分布式:TP/PP + RoCE/NCCL

大模型单卡放不下时,SGLang 支持 张量并行(TP) 与 流水线并行(PP) 切分。跨节点的 TP 通信正是走前面铺好的 RoCE + NCCL 通道——所以「网络栈搭得好,SGLang 的分布式才能快」。

4. 与 vLLM 的对比

维度SGLangvLLM
KV 缓存机制RadixAttention(基数树,前缀共享强)PagedAttention(分页管理)
前缀共享/RAG/多轮对话优势显著有前缀缓存,粒度更粗
吞吐(特定基准)部分基准高约 29%通用场景稳定
硬件/模型兼容主要 NVIDIA,覆盖主流架构更广(NVIDIA/AMD/TPU/Gaudi,400+ 架构)
结构化输出原生支持好需配合约束解码
端到端配置

八、端到端配置示例:Multus + SR-IOV + NCCL + SGLang

把上面的组件串起来,一个多机 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,两网互不干扰。

落地要点

九、落地设计要点(八条)

  1. 控制面与数据面分离:RDMA 流量绝不过 Calico overlay,必须走 Multus 附加的物理/直连网卡
  2. 优先 SR-IOV,其次 macvlan:生产 RDMA 用 SR-IOV Network Operator 切 VF,性能与隔离更好
  3. 无损以太网是前提:PFC + ECN 配错,RoCE 一丢包性能就雪崩,交换机端要逐跳验证
  4. GID 索引进容器再确认:NCCL_IB_GID_INDEX 别照搬宿主机值,容器内 show_gids 为准
  5. 开启 GPUDirect RDMA:NCCL_NET_GDR_LEVEL=5 让数据直达显存,多机大模型收益明显
  6. 单机用 NVLink、跨机用 RoCE:NCCL_P2P_LEVEL 控制机内路径,别让机内流量绕去网络
  7. 驱动与运行时对齐:NVIDIA 驱动、Container Toolkit、Device Plugin、NCCL 版本要匹配,否则通信静默降级到 TCP
  8. 推理框架选型看负载:大量前缀共享(RAG/多轮/Agent)选 SGLang,追求极广硬件兼容选 vLLM
总结

十、写在最后

在 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 独享接入点 缓存隔离降本 低折扣 Token 即用即扣 · 不设账期

常见问题(FAQ)

火山方舟官方 API 与官方 Key 直连 · 向量云 · Kubernetes GPU 网络栈(Multus-CNI / Calico / NCCL / RoCE / SGLang)

Q1. Multus-CNI 是什么?为什么 Kubernetes 需要它?

A. Kubernetes 原生一个 Pod 默认只有一张网卡(eth0)。大模型场景需要「控制面 + 数据面」分离:普通 TCP 走默认网卡,RDMA 大流量走独立网卡。Multus 是一个 CNI 元插件,它代理调用其他 CNI 插件,通过 NetworkAttachmentDefinition(NAD)CRD 定义附加网络,再通过 Pod 注解 k8s.v1.cni.cncf.io/networks 把第二张网卡挂进 Pod,实现多网卡。

Q2. Calico 和 Multus 是什么关系?

A. Calico 是集群默认 CNI,负责 Pod 到 Pod、Pod 到 Service 的普通 IP 网络与 NetworkPolicy;Multus 是 meta-plugin,创建 Pod 时先调 Calico 配好 eth0,再按注解调附加 CNI 配第二张网卡。两者通过 Multus 解耦:Calico 负责「能连通」,RDMA 附加网卡负责「通得快」,互不干扰。

Q3. RoCE 和 InfiniBand 有什么区别?RoCEv2 需要什么网络条件?

A. InfiniBand 用专用交换机和线缆、天生无损但成本高;RoCEv2 在标准以太网上跑 RDMA、成本低易扩展。RoCEv2 强依赖无损以太网:需要 PFC(基于优先级的流控)兜底「硬不丢包」,ECN(显式拥塞通知)+ DCQCN 提前「软减速」,否则一旦丢包,RDMA 重传会导致性能悬崖式下跌。

Q4. NCCL 在 RoCE 网络下需要配置哪些环境变量?

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 索引最容易配错,容器内外不一致会直接导致通信失败。

Q5. 什么是 GPUDirect RDMA?

A. GPUDirect RDMA(GDR)让 RDMA 网卡直接读写 GPU 显存,数据从对端 GPU 显存直达本端 GPU 显存,全程不经过 CPU 和主机内存,显著降低延迟与 CPU 占用,是多机大模型集合通信的关键加速项,通过 NCCL_NET_GDR_LEVEL 启用。

Q6. SGLang 相比 vLLM 有什么优势?

A. SGLang 的核心是 RadixAttention——用基数树(Radix Tree)组织 KV 缓存,共享相同前缀的请求(RAG 公共上下文、多轮对话历史、Agent 系统提示)自动复用同一段 KV,省下大量重复计算与显存;配合连续批处理,在前缀共享型负载下吞吐显著领先,部分基准高约 29%,结构化输出支持也更好。vLLM 的优势则在更广的硬件与模型兼容性。

Q7. 多节点 SGLang 推理怎么走 RoCE 网络?

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。