3、容器网络基础:veth pair与bridge的工作原理及数据包转发流程

容器网络是容器运行时进程网络IO的底层基础设施。理解 veth pair(虚拟以太网对)与 bridge(网桥)的工作原理,是分析网络IO瓶颈、设计高性能容器网络方案的先决条件。本章从这两个核心虚拟网络设备入手,拆解数据包从容器进程到宿主机外部的完整转发路径。

3.1 veth pair:容器与宿主机之间的虚拟网线

veth pair 是一对虚拟网卡,总是成对出现。它模拟一根“网线”:一端发送的数据,另一端立即接收。在容器网络中,veth pair 的一端放入容器网络命名空间(Network Namespace),另一端连接到宿主机上的 bridge 或根命名空间。

特性 说明
设备类型 虚拟以太网设备,成对创建
数据传递 一端发送的数据帧直接出现在另一端,无中间拷贝
命名空间 两端可分别位于不同网络命名空间
典型用途 连接容器 netns 与宿主机 root netns
MTU 影响 默认 1500,可调整;MTU 不匹配会导致分片或丢包
性能要点: veth pair 本身是纯软件设备,数据传递不经过物理网卡。但在高并发场景下,veth 的 tx/rx 队列深度和 NAPI 轮询机制可能成为瓶颈。监控 ethtool -S vethX 可查看丢包与队列溢出计数。

3.2 bridge:虚拟二层交换机

Linux bridge 工作在数据链路层(L2),行为与物理交换机一致。它维护一个 MAC 地址表,根据目标 MAC 地址决定转发端口。在容器网络中,bridge 将多个容器的 veth 端连接在同一广播域内,实现容器间直接通信。

功能 对应物理设备 容器网络中的作用
MAC 学习 交换机 CAM 表 记录每个端口连接的容器 MAC
帧转发 交换机背板 根据 MAC 表将帧转发到目标端口
广播/洪泛 交换机广播域 未知单播、ARP 请求在 bridge 内广播
STP 生成树协议 防止环路,默认开启
iptables 交互 无 bridge 数据流可被 netfilter 规则处理(需 br_netfilter 模块)

3.3 数据包转发流程:从容器进程到外部网络

以下流程图展示了一个容器内进程发送数据包到宿主机外部的完整路径。图中包含 容器 netns、veth pair、bridge、宿主机路由、iptables 和 物理网卡 六个关键节点。

容器数据包转发流程:veth pair + bridge 容器数据包转发流程(veth pair + bridge) 容器网络命名空间 eth0@ifN (veth端) IP: 10.0.0.2/24 MAC: 02:42:0a:00:00:02 进程发送数据包 目标: 8.8.8.8:80 veth pair 宿主机根网络命名空间 vethXXXX (对端) 连接到 bridge (docker0) Linux Bridge (docker0) MAC表: 02:42:0a:00:00:02 → vethXXXX IP: 10.0.0.1/24 (bridge 接口) 路由决策 路由与iptables 路由表: 0.0.0.0/0 → eth0 MASQUERADE (SNAT) FORWARD 规则检查 源IP: 10.0.0.2 → 宿主机IP 物理出口 物理网卡 eth0 发送到外部网络 外部网络 关键路径: 容器进程 → veth pair → bridge → 路由/iptables → 物理网卡 → 外部

3.4 数据包转发详细步骤

以容器内进程访问 8.8.8.8:80 为例,数据包经过以下 8 个步骤:

  1. 容器进程发送数据:进程通过 socket 发送数据,内核协议栈封装为 IP 包,目标 IP 8.8.8.8,源 IP 10.0.0.2。
  2. 路由查找:容器 netns 内路由表发现目标不在本地子网,默认网关为 10.0.0.1(bridge 接口)。
  3. ARP 解析:容器发送 ARP 请求获取 10.0.0.1 的 MAC 地址;bridge 代答或转发 ARP。
  4. 帧进入 veth:数据帧从容器 eth0 发出,立即出现在宿主机 vethXXXX 端。
  5. bridge 转发:bridge 根据 MAC 表或洪泛规则,将帧转发到 bridge 自身接口(docker0)。
  6. 宿主机路由:宿主机协议栈收到 IP 包,路由表匹配 0.0.0.0/0 经 eth0 发出。
  7. iptables SNAT:POSTROUTING 链执行 MASQUERADE,源 IP 替换为宿主机 eth0 IP。
  8. 物理网卡发送:数据包经物理网卡发送到外部网络。
瓶颈观察点: 步骤 4-5 中,veth pair 的 单队列 特性在大量小包场景下容易产生 锁竞争;步骤 7 的 iptables SNAT 会占用 conntrack 表项,高并发时可能触发 conntrack 表满 导致丢包。使用 conntrack -S 可查看 conntrack 统计信息。

3.5 容器间通信:同 bridge 下的直接转发

当两个容器位于同一 bridge 时,数据包无需经过宿主机路由和 iptables,直接在 bridge 内完成 L2 转发。下图展示容器 A 访问容器 B 的路径:

同 bridge 容器间通信流程 同 bridge 容器间通信(L2 直接转发) 容器 A eth0: 10.0.0.2 MAC: 02:42:0a:00:00:02 → 目标: 10.0.0.3 vethA Linux Bridge (docker0) MAC表: 02:42:0a:00:00:02 → vethA 02:42:0a:00:00:03 → vethB vethB 容器 B eth0: 10.0.0.3 MAC: 02:42:0a:00:00:03 ← 接收数据 关键特征: • 数据包不经过宿主机路由和 iptables,延迟低、吞吐高 • bridge 直接根据 MAC 表将帧从 vethA 转发到 vethB,无需三层处理

3.6 常见瓶颈与优化方向

瓶颈点 原因 优化手段
veth 单队列 默认单 tx/rx 队列,多核竞争锁 启用多队列 veth(需内核支持);使用 ethtool -L 调整
bridge MAC 表洪泛 未知 MAC 导致广播洪泛,消耗 CPU 使用 bridge fdb 静态配置;减少广播域规模
iptables conntrack 满 SNAT 占用 conntrack 表,高并发溢出 增大 nf_conntrack_max;使用无状态 NAT 或 eBPF
MTU 不匹配 veth/bridge/物理网卡 MTU 不一致导致分片 统一 MTU 值;容器网络插件自动对齐
br_netfilter 开销 bridge 流量经过 iptables,增加延迟 关闭 net.bridge.bridge-nf-call-iptables=0(需评估安全影响)
生产建议: 在 Kubernetes 环境中,CNI 插件(如 Calico、Flannel)会创建额外的网络设备(如 tunl0、cni0),但底层仍依赖 veth pair 和 bridge。监控 /proc/net/dev 和 ethtool -S 的丢包计数,是定位容器网络 IO 瓶颈的第一步。