目录
Please enable Javascript to view the contents

K8s网络-多网卡方案详解(Multus + SR-IOV + ipvlan)

 ·  ☕ 7 分钟

系列导航

本系列从 Pod 网络连通入手,逐步展开到 K8s 网络全景。

① 概念 → ② Flannel → ③ Calico → ④ 流量路径 → ⑤ Cilium → ⑥ 对比 → ⑦ 排障 ‖ ⑧ 开发 → ⑨ 多网卡 → ⑩ AI 演进

顺序文章定位
概念与入门基础——主机网络、Docker 网络、CNI 标准、方案分类树
Flannel 详解CNI 实现——Overlay 封装(UDP/VXLAN/HostGW)与抓包
Calico 详解CNI 实现——三层路由(BGP/IPIP)+ NetworkPolicy
流量路径全解析全貌——Pod/Service/Ingress/Egress,揭示 CNI 的边界
Cilium 详解超越 CNI——eBPF 统一 Pod + Service + L7 + Hubble
插件对比与选型选型——5 插件横向对比 + 决策树
排障思路与常用命令运维——工具链 + 场景排查 + 性能
核心路径 ↑扩展展望 ↓
CNI 插件开发指南扩展——基于 CNI 规范开发自定义插件
本篇 - 多网卡方案详解进阶——Multus + SR-IOV/ipvlan 多网口实战
AI 时代网络演进展望——GPU 网络、eBPF 加速、未来方向

K8S 默认一个 Pod 一张网卡。GPU 训练、边缘计算、网络安全隔离等场景需要一个 Pod 同时接入多个网络。Multus 是 CNCF 的标准化多网卡调度器——将多个 CNI 插件串联,给 Pod 分配多张独立网卡。


1. 为什么需要多网卡

场景网卡1(管理面)网卡2(数据面)
GPU 分布式训练Cilium/Flannel(Pod 互通、DNS、Pull 镜像)SR-IOV VF(RDMA/RoCE,GPU all-reduce 通信)
边缘计算Calico(控制面、API 调用)ipvlan/macvlan(直通物理网络,低延迟数据采集)
安全隔离Cilium eBPF(策略管控、可观测)macvlan(直通 DMZ 网络,不经过集群路由)
NFV/SDNFlannel(管理)DPDK 用户态驱动(高性能包处理,绕过内核)

核心问题: 普通 Pod 只支持一个 CNI 插件。Kubelet 在创建 Pod 时调用一次 CNI ADD,分配一个 eth0。第二张网卡需要额外的 CNI 调用——Multus 负责这件事。


2. Multus 架构

Multus 本身不是网络插件——它是一个 CNI 调度器,位于 Kubelet 和其他 CNI 之间:

Kubelet
  │
  │ 调用 CNI ADD
  ▼
Multus (meta-plugin)
  │
  │ 遍历 NetworkAttachmentDefinition 列表
  │
  ├─► CNI #1 (Flannel/Cilium/Calico) → eth0
  ├─► CNI #2 (SR-IOV)                → net1
  └─► CNI #3 (ipvlan)                 → net2
  │
  ▼
Pod 拥有多张网卡

Multus 的本质:一个 meta-plugin,不做网络配置,只做调度——收到 Kubelet 的 CNI ADD 调用后,按 Pod 声明的 NAD 列表,依次委托各子 CNI 各自创建网卡、分配 IP。每个子 CNI 互不感知、独立工作,Multus 只负责"叫谁做、按什么顺序做"。最终 Pod 拥有 N 张独立网卡,各自的路由、策略、带宽由对应 CNI 管控。

统筹不同 CNI 搭配的关键:NAD 定义"用谁",Pod annotation 定义"要几个、叫什么"。Multus 不合并网络——网卡之间互不干扰,隔离性由各自 CNI 保证。

关键概念:

组件作用
NetworkAttachmentDefinition (NAD)CRD,定义"额外网卡"的属性——用什么 CNI 插件、配什么 IP 段、挂哪个物理网卡
k8s.v1.cni.cncf.io/networksPod annotation,指定本 Pod 需要哪些 NAD
multus-cniDaemonSet,每节点运行,负责按 NAD 列表依次调用各个 CNI 插件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# NetworkAttachmentDefinition 示例:SR-IOV 网卡
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: sriov-rdma
  namespace: default
spec:
  config: |
    {
      "type": "sriov",
      "ipam": {
        "type": "host-local",
        "subnet": "192.168.100.0/24",
        "rangeStart": "192.168.100.10",
        "rangeEnd": "192.168.100.200"
      }
    }    

3. 实战方案

3.1 Cilium(管理面) + SR-IOV(RDMA 高速面)

AI 训练的标准组合。Cilium 管 eth0(普通 Pod 互通 + Service + 策略),SR-IOV 管 net1(RDMA 直通,绕过内核)。

宿主机准备:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 1. 开启 SR-IOV,创建 VF
echo 8 > /sys/class/net/eth1/device/sriov_numvfs

# 2. 查看 VF 列表
ip link show eth1
# 输出:vf 0 MAC 00:00:00:00:00:00, spoof checking on ...

# 3. 创建 SriovNetworkNodePolicy(指定哪些 VF 可供 Pod 使用)
cat <<EOF | kubectl apply -f -
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: rdma-policy
spec:
  resourceName: mlx5_rdma
  deviceType: netdevice
  nicSelector:
    pfNames: ["eth1"]
  numVfs: 4
EOF

Pod 声明双网卡:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Pod
metadata:
  name: gpu-trainer
  annotations:
    k8s.v1.cni.cncf.io/networks: '[
      {"name": "sriov-rdma", "namespace": "default", "interface": "net1"}
    ]'
spec:
  containers:
  - name: training
    image: pytorch/pytorch:latest
    resources:
      limits:
        nvidia.com/gpu: 8
        intel.com/mlnx_rdma: "1"
    command: ["torchrun"]

验证双网卡是否就绪:

1
2
3
kubectl exec gpu-trainer -- ip a
# 3: eth0: <BROADCAST> inet 10.244.1.5/32    # Cilium 管理面
# 4: net1: <BROADCAST> inet 192.168.100.10/24 # SR-IOV RDMA 面

3.2 Flannel(管理面) + ipvlan(数据面)

ipvlan 比 macvlan 更适合容器场景——每个 Pod 的 MAC 地址与宿主机相同,交换机只看宿主机 MAC,避免 MAC 地址表溢出。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# ipvlan NAD 定义
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: ipvlan-datapath
spec:
  config: |
    {
      "type": "ipvlan",
      "master": "eth1",
      "mode": "l2",
      "ipam": {
        "type": "host-local",
        "subnet": "10.100.0.0/16"
      }
    }    
ipvlan 模式说明适用场景
L2同网段 Pod 二层互通,跨网段需外部路由同 VLAN 数据面
L3宿主机作为路由器,Pod 间走三层跨 VLAN,需宿主机关闭 rp_filter
L3S类似 L3,额外支持 iptables/Netfilter需要策略/SNAT 的场景

3.3 macvlan(Pod 直接暴露到物理网络)

macvlan 给每个 Pod 分配独立的 MAC 地址,Pod 直接接入物理二层网络,性能最高。适合需要 Pod 独立 IP 对外暴露的场景(如 DNS 服务器、负载均衡器)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: macvlan-external
spec:
  config: |
    {
      "type": "macvlan",
      "master": "eth1",
      "mode": "bridge",
      "ipam": {
        "type": "host-local",
        "subnet": "172.16.0.0/24"
      }
    }    
macvlan 模式说明注意
bridge同宿主机、同 VLAN 的 macvlan Pod 可以互通依赖外部交换机做 MAC 学习
privatePod 只能与外部通信,不能与同宿主机其他 macvlan Pod 通信最安全,适用 DMZ 场景
vepa内部流量也经外部交换机转发需交换机支持 VEPA(很少用)

注意: macvlan Pod 和宿主机之间默认无法直接通信——可以在宿主机额外创建 macvlan 子接口来解决:ip link add mac-host link eth1 type macvlan mode bridge


NVLink 和 NVSwitch 是 NVIDIA 的 GPU 互联技术。在 GB200 NVL72 这一代,它们已经跨节点了——一台机柜内 72 个 B200 GPU 通过 NVSwitch 无阻塞全互联,构成一个"超节点"。

技术是什么通信范围由谁管理
NVLinkGPU 间直连总线,双向带宽 900GB/s(H100)→ 1.8TB/s(B200)传统:单节点内 / NVL72:跨节点(机柜内)NVIDIA 驱动 + NVLink Fabric Manager
NVSwitch无阻塞交换芯片,连接多个 GPU单节点 8 GPU(H100)→ NVL72 机柜 72 GPU(B200)NVLink Fabric Manager(不是 CNI)
InfiniBand跨机柜 RDMA 网络,延迟 < 2μs跨机柜、跨集群SR-IOV CNI + IB 子网管理器
RoCE v2融合以太网跑 RDMA跨机柜SR-IOV CNI + 交换机 PFC/ECN

三层通信结构:

┌─ NVLink Switch 域(机柜内,72 GPU 全互联)───────┐
  │  GPU0 ←→ GPU1 ←→ ... ←→ GPU71                     │
  │  通过 NVSwitch 交换,不经过任何网络设备               │
  └────────────────────────────────────────────────────┘
         │
         │ GPU Direct RDMA
         ▼
  ┌─ InfiniBand / RoCE 网络(跨机柜)─────────────────┐
  │  SR-IOV VF → IB Switch → ... → 远端 SR-IOV VF     │
  │  CNI 管理:分配 VF + 分配 IP + 保证可达            │
  └────────────────────────────────────────────────────┘
         │
         ▼
  ┌─ 以太网(管理面)─────────────────────────────────┐
  │  eth0:Cilium/Flannel(DNS、API、Pull 镜像)      │
  └────────────────────────────────────────────────────┘

NVLink Switch 域内通信用什么? 不走任何 CNI——GPU 之间通过 NVSwitch 直接做内存访问(load/store 语义),不经过 IP 协议栈。它不是"网络",是"总线扩展"。

跨 NVSwitch 域(机柜之间)通信用什么? InfiniBand 或 RoCE。CNI 的任务是:把 SR-IOV VF 正确分配给 Pod,保证 VF 的 IP 可达、RDMA 链路畅通。GPU Direct RDMA 让 GPU 显存直接 DMA 到 VF,不经过 CPU。

NVIDIA 的"超节点"策略是把尽可能多的 GPU 放进一个 NVSwitch 域(省去昂贵的 IB 网络),域外用 CNI 管理的 RDMA 连接。


5. 多网卡排障

5.1 Pod 只有 eth0,额外网卡未出现

1
2
3
4
5
6
7
8
9
# 1. 检查 NAD 是否存在
kubectl get network-attachment-definitions -A

# 2. 检查 Pod annotation 格式
kubectl get pod <name> -o jsonpath='{.metadata.annotations}'
# annotation key 必须是 k8s.v1.cni.cncf.io/networks(拼写错误最常见)

# 3. 检查 Multus DaemonSet 日志
kubectl logs -n kube-system ds/kube-multus-ds

5.2 额外网卡存在但无 IP

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 1. 检查 IPAM 是否耗尽
kubectl exec <pod> -- ip a | grep net1
# 如果只有 MAC 没有 IP → IPAM 池不足

# 2. 检查 SriovNetworkNodePolicy 的 VF 已分配
kubectl get sriovnetworknodestates -A -o yaml | grep -A5 allocatable

# 3. 查看 Multus 调用 CNI 的错误
kubectl describe pod <name> | grep -A10 Events
# 常见:sriov 插件找不到 VF、ipvlan 的 master 接口 down

5.3 多网卡路由冲突

Pod 有双网卡时,默认路由只能走一张网卡。需要手动指定目标网段走哪张卡:

1
2
3
# Pod 内添加策略路由(确保 RDMA 流量走 net1,管理流量走 eth0)
kubectl exec gpu-trainer -- ip route add 192.168.100.0/24 dev net1
kubectl exec gpu-trainer -- ip route add 10.244.0.0/16 dev eth0

6. 总结

维度macvlanipvlanSR-IOV
MAC 地址每个 Pod 独立 MAC共享宿主机 MACVF 独立 MAC
性能高(直通物理网络)最高(硬件直通)
交换机负载MAC 表项随 Pod 数增长仅宿主机 MACVF MAC 数增长
RDMA 支持不支持不支持支持
宿主机→Pod 通信需额外子接口原生支持不支持(VF 特性)
典型场景独立 IP 对外暴露同网段数据面GPU 训练 RDMA 面

Multus 是多网卡的第一步——定义网卡类型、调度 IPAM、绑定到 Pod。后续的带宽、延迟、策略管控,由各 CNI 插件各自负责。

参考链接

分享

Hex
作者
Hex
CloudNative Developer