4. 跨节点Pod通信与Overlay网络
在单节点内,Pod 之间通过 veth pair 接入网桥或 eBPF 程序即可完成二层转发;一旦 Pod 分布到不同节点,问题立刻变成:源节点如何知道目标 Pod 的 IP 归属哪个节点,以及数据包在物理网络之上如何被承载。Overlay 网络正是为解决这两个问题而存在——它用隧道封装把 Pod 网络“叠加”在节点网络之上,让每个节点只需与对端节点可达,而不要求物理交换机认识 Pod CIDR。
一、三种主流封装:VXLAN、IPIP、Geneve
VXLAN 是目前最普遍的方案。它把原始以太网帧整体作为载荷,外层加上 UDP 头(目的端口默认 4789)、8 字节 VXLAN 头(含 24 位 VNI)以及外层 IP 头。VNI 用于隔离不同租户或不同网络,24 位可提供约 1600 万个标识。由于封装的是二层帧,VXLAN 天然支持同一子网内 Pod 的 ARP 广播,这也是 Flannel 的 vxlan 模式、Calico 的 VXLAN 模式、Cilium 的隧道模式都采用它的原因。
IPIP 更轻量:它把原始 IP 包直接塞进一个新的 IP 包,外层协议号设为 4。没有 UDP 头,没有 VNI,开销固定为 20 字节(IPv4 外层)。代价是只能承载三层,无法在同一隧道内传递 ARP,因此通常配合节点上的路由表使用——每个节点为对端 Pod CIDR 配置一条经由隧道接口的路由。Flannel 的 ipip 模式、Calico 的 IPIP 模式即属此类。当外层 IP 头也使用 IPv4 时,IPIP 封装后总开销为 20 字节;若启用“IPIP always”,则所有跨节点流量都走隧道,否则仅在跨子网时封装。
Geneve 可以看作 VXLAN 的通用化版本。它同样基于 UDP,但头部长度可变,通过 TLV(Type-Length-Value)选项携带元数据,例如 Kubernetes 的 NetworkPolicy 标识、服务链信息或安全组 ID。默认端口 6081。Geneve 的灵活性使其在 OVN-Kubernetes、Antrea 等项目中成为首选,代价是头部解析比 VXLAN 稍复杂,且部分硬件卸载支持不如 VXLAN 成熟。
三者的共同点是:都在节点间建立点对点或点对多点的隧道,数据包在源节点被封装、在目标节点被解封装。区别在于承载层次(二层 vs 三层)、元数据能力(VNI vs TLV)和头部开销。
二、跨节点路由分发:谁告诉节点“目标 Pod 在哪”
封装只解决了“怎么送”,路由分发解决“送给谁”。以 Flannel 为例,它运行在每個节点上的 flanneld 会从集群的 etcd 或 Kubernetes API 中分配一个 Pod CIDR(例如 10.244.1.0/24),然后把“本节点 Pod CIDR ↔ 本节点 IP”的映射写入 etcd。其他节点的 flanneld 监听到变化后,在本机路由表中插入一条路由:目标为 10.244.1.0/24,下一跳为对端节点 IP,出接口为 flannel.1(VXLAN 接口)。这样,当本节点 Pod 访问 10.244.1.5 时,内核查表发现走 flannel.1,VXLAN 驱动再根据下一跳 IP 查到对端节点的 MAC,完成封装。
Calico 在 IPIP 模式下采用类似机制,但路由由 BGP 分发。每个节点作为 BGP Speaker,把本节点的 Pod CIDR 通过 BGP 宣告给其他节点或路由反射器。收到宣告的节点在路由表中写入“目标 Pod CIDR → 下一跳节点 IP → 隧道接口”。与 Flannel 的集中式 etcd 不同,BGP 是分布式的,规模更大时更稳健。Cilium 在隧道模式下则用 KVStore 或 CRD 同步节点与 Pod CIDR 的映射,并借助 eBPF 在数据路径上直接查表,绕过内核路由表的部分开销。
无论哪种方式,核心逻辑一致:每个节点必须掌握“哪个 Pod CIDR 在哪个节点”的映射,并据此建立隧道对端信息。 如果映射缺失或过期,典型症状是跨节点 Pod 不通、同节点正常,此时应检查路由表、隧道接口状态和对端节点可达性。
三、MTU:最容易被忽视的故障源
封装会额外增加头部,因此 Overlay 网络的 MTU 必须小于物理网卡 MTU。以 VXLAN 为例,外层 IP 头 20 字节 + UDP 头 8 字节 + VXLAN 头 8 字节 = 36 字节。若物理网卡 MTU 为 1500,则 Pod 网络 MTU 应设为 1500 - 36 = 1464。IPIP 开销为 20 字节,Pod MTU 应为 1480。Geneve 基础开销为 20 + 8 + 8 = 36 字节,若带 TLV 选项还会增加,通常也按 1464 或更小设置。
如果 MTU 设置错误,小包(如 ping、TCP 握手)正常,但大包(如 HTTP 响应、数据库查询结果)会被丢弃或分片,表现为“能连上但传不了数据”“curl 小文件正常、大文件卡死”。判断方法是:在 Pod 内执行 ping -M do -s 1472 <对端PodIP>(1472 + 28 = 1500),若不通则逐步减小 -s 值,找到能通过的最大值,再加 28 得到实际路径 MTU。若该值小于 Pod 网卡 MTU,说明 Overlay 开销未被正确扣除。
# 在 Pod 内探测到对端 Pod 的实际路径 MTU
ping -M do -s 1472 10.244.2.5 # 若失败
ping -M do -s 1440 10.244.2.5 # 逐步减小
# 假设 1440 成功,则路径 MTU = 1440 + 28 = 1468
# 若 Pod 网卡 MTU 为 1500,说明 VXLAN 开销未生效,需检查 CNI 配置
修正方式:在 CNI 配置中显式设置 mtu 字段,或通过 kubelet 的 --network-plugin-mtu 传递。Calico 可用 veth_mtu 环境变量,Cilium 用 --mtu 参数。修改后需重启 CNI 或重建 Pod 使新 MTU 生效。
四、性能影响与选型判断
封装带来的性能损耗主要来自三方面:头部开销降低有效载荷占比;封装/解封装消耗 CPU;隧道接口可能绕过部分硬件卸载。在 1500 MTU 下,VXLAN 的有效载荷占比约为 1464/1500 ≈ 97.6%,IPIP 约为 98.7%,差距不大。真正影响大的是是否启用硬件卸载:现代网卡支持 VXLAN 的 checksum、TSO、GRO 卸载时,吞吐可接近线速;若关闭卸载,单核可能只能达到几百 Mbps。
选型时可参考以下判断:若集群节点在同一二层网络、且希望最少开销,IPIP 更轻;若需要多租户隔离或跨三层网络,VXLAN 更通用;若需要携带策略元数据或与 OVN 集成,Geneve 更合适。无论选哪种,都必须验证 MTU 并观察 ip -s link show 中的 dropped/errors 计数,以及 ethtool -S 中的 tx_errors。跨节点通信的排查顺序建议为:先确认节点间 IP 可达,再确认路由表中存在对端 Pod CIDR,然后确认隧道接口 up,最后用不同大小包验证 MTU。
下面给出一份可直接用于排查的检查清单,按顺序执行即可定位大多数跨节点不通问题:
| 步骤 | 检查命令 | 预期结果与判断 |
|---|---|---|
| 1. 节点互通 | ping <对端节点IP> | 通,否则先修物理网络 |
| 2. 路由存在 | ip route | grep <对端PodCIDR> | 有路由,下一跳为对端节点IP或隧道接口 |
| 3. 隧道接口 | ip -d link show flannel.1 或 tunl0 | 状态 UP,VNI/本地IP/对端IP正确 |
| 4. 小包连通 | ping <对端PodIP> | 通,说明封装与路由基本正常 |
| 5. 大包 MTU | ping -M do -s 1440 <对端PodIP> | 通,且 1472 不通,说明 MTU 已扣除开销 |
| 6. 丢包计数 | ip -s link show <隧道接口> | dropped/errors 不持续增长 |
最后强调一个常见误区:Overlay 网络并不是“越封装越好”。如果节点本身就在同一子网,且 CNI 支持直接路由(如 Calico 的 BGP 非隧道模式、Cilium 的 native routing),那么不封装反而能获得更低延迟和更高吞吐,同时避免 MTU 问题。是否使用 Overlay,取决于物理网络是否允许节点间直接路由 Pod CIDR。理解封装原理与路由分发机制,才能在面试中准确回答“为什么跨节点 Pod 不通”以及“如何优化跨节点性能”这类问题。