一句话总结
同节点 Pod 靠网桥就能通, 但跨节点时, Pod IP 在物理网络里"查无此路".
解决它有两条路线: Overlay 把 Pod 的包用 VXLAN 装进一个外层包"偷渡"过去(通用但有性能损耗), L3 路由直接让物理网络学会到各节点 Pod 网段的路由(高效但依赖网络环境).
前置回顾
第 01 篇我们用 namespace + veth + 网桥搭通了同节点容器网络, 也留了个问题: 如果两个 Pod 在不同主机上, 网桥这套就不灵了. 同时 K8s 网络模型要求"所有 Pod 扁平互通, 无 NAT"--这个要求在跨节点时最难满足.
本篇就是攻克它, 这也是各 CNI 插件(第 03 篇)真正拉开差异的地方.
跨节点为什么会断
把第 01 篇的场景搬到两台主机上, 问题立刻暴露:
|
根子在于: Pod IP(10.244.x.x)是 Kubernetes 虚构出来的一套地址, 物理网络设备对它一无所知. 物理交换机只会按物理 IP(192.168.1.x)转发. 怎么让一个"物理网络不认识的包"跨过物理网络到达对端? 两条思路, 泾渭分明.
Pod IP 像公司内部的工位号(3 楼 17 号), 物理网络像城市的邮政系统(只认街道门牌).
写"送到 3 楼 17 号"邮局根本不知道往哪送. 要么把内部信装进一个写了街道地址的大信封(Overlay), 要么让邮局也学会"3 楼 17 号 = XX 街 88 号"这套对应关系(路由).
路线一: Overlay -- 给包套个"信封"偷渡过去
Overlay(叠加网络) 的思路: 既然物理网络不认识 Pod IP, 那就把整个 Pod 的数据包(包括它的 Pod IP)当作"数据", 塞进一个新的, 用物理 IP 寻址的外层包里. 物理网络只看外层包, 正常转发; 到了对端节点再拆开外层, 取出原始 Pod 包送达. 这个"套信封"的动作叫封装(Encapsulation), 最常用的封装协议是 VXLAN.
|
| Overlay 的优点 | Overlay 的代价 |
|---|---|
| 对物理网络零要求: 只要节点间物理 IP 能通, Pod 网络就能跑--物理网络无需任何配置 | 封装开销: 每个包多一层头(VXLAN 约 50 字节), CPU 要做封装/解封装, 有性能损耗 |
| 部署简单, 可移植: 几乎任何环境(自建机房, 各家云)都能用 | 抓包难排查: 外层包了一层, 排查时要先解封装才看得到真实流量 |
| Pod 网络和物理网络解耦 | MTU 要留意(外层头吃掉一部分, 易出现分片问题) |
Flannel 的默认模式(VXLAN)就是典型 Overlay. 它胜在"无脑能用"--这也是它成为最简单 CNI 的原因.
路线二: L3 路由 -- 让物理网络学会 Pod 网段的路由
第二条路线根本不封装, 而是反过来让网络学会怎么找到 Pod IP: 在每个节点和(可选的)物理路由器上, 写好路由规则--"要去 10.244.1.0/24 这个网段, 下一跳是节点2(192.168.1.20)". 这样 Pod 包原封不动地在物理网络上传输, 靠路由表逐跳转发.
|
问题是: 节点很多, Pod 网段会变, 这些路由谁来维护, 怎么同步到所有节点甚至物理路由器? 答案是 BGP(边界网关协议)--互联网级别的动态路由协议. 每个节点跑一个 BGP 程序, 自动把"我这台节点负责哪个 Pod 网段"广播给其他节点和路由器, 大家动态学习, 自动更新路由表.
| L3 路由的优点 | L3 路由的代价 |
|---|---|
| 无封装开销: 包原样传输, 性能接近物理网络, CPU 不做封装 | 对物理网络有要求: 需要网络支持(尤其想让物理路由器也学路由时, 要 BGP 支持) |
| 易排查: 抓到的就是真实 Pod 包, 没有外层伪装 | 跨子网/跨可用区时可能受物理网络拓扑限制 |
| Pod IP 在物理网络里"真实可见可路由" | 配置和理解门槛比 Overlay 高 |
Calico 的标志性(原生)模式就是 BGP 路由(无封装), 跨子网时则用 IPIP/VXLAN 兜底. 它胜在"快且透明", 是性能敏感场景的常见选择.
两条路线的本质对立: 封装 vs 路由
把取舍浓缩成一句话: Overlay 用"封装"换"对物理网络零依赖"(牺牲性能换通用), L3 路由用"对物理网络的要求"换"原生性能"(牺牲通用换高效).
没有谁绝对更好--自建/异构/图省事 → Overlay; 性能敏感, 网络可控 → 路由. 这个"通用 vs 高效"的权衡, 在 CI/CD 和可观测性系列里见过无数次(Loki vs ES, 尾部采样的取舍), 它是基础设施选型的永恒主题.
还有一种折中: IPIP / 混合模式
现实中不是非黑即白. 比如 Calico 在"节点都在同一二层网络"时用纯 BGP 路由(零开销), 一旦跨子网(路由不通)就自动切换成 IPIP(一种比 VXLAN 更轻的封装)兜底--这叫 CrossSubnet 模式.
即"能路由就路由, 路由不了才封装", 兼顾性能与通用. 理解了封装和路由两条主线, 这类混合策略就一看就懂.
一张表看懂两条路线
| 维度 | Overlay(封装, 如 VXLAN) | L3 路由(如 BGP) |
|---|---|---|
| 跨节点怎么走 | 原始包装进外层包, 物理 IP 寻址 | 原始包按路由表逐跳转发 |
| 性能 | 有封装开销(略低) | 接近物理网络(高) |
| 对物理网络要求 | 几乎没有(物理 IP 通即可) | 较高(BGP / 路由可控) |
| 排查难度 | 高(要解封装) | 低(真实包) |
| 典型代表 | Flannel(VXLAN) | Calico(BGP) |
| 适合 | 自建/异构环境, 图省事 | 性能敏感, 网络可控 |
承上启下
到这里, 从单节点(第 01 篇)到跨节点(本篇)的 Pod 通信原理就完整了. 但有个一直回避的问题: 这些 namespace, veth, 网桥, VXLAN 隧道, BGP 路由, 在 Pod 创建的瞬间是谁, 怎么自动配好的? 以及--Flannel, Calico 这些名字反复出现, 它们到底是什么, K8s 怎么调用它们? 答案就是 CNI: Kubernetes 把"配置 Pod 网络"这件事定义成一个标准接口, 外包给可插拔的插件. 下一篇揭开它.
快速回顾
- 跨节点断在哪: Pod IP 是 K8s 虚构的, 物理网络只认物理 IP, 不知道怎么转发 Pod 包
- Overlay(封装): 把原始 Pod 包装进用物理 IP 寻址的外层包(VXLAN)偷渡过去; 优点是对物理网络零要求, 通用, 代价是封装开销和排查难; 代表 Flannel
- L3 路由: 不封装, 让节点/路由器学会"哪个 Pod 网段在哪个节点"的路由(常用 BGP 动态同步); 优点是原生性能, 易排查, 代价是对物理网络有要求; 代表 Calico
- 本质对立: 封装(通用换性能) vs 路由(性能换通用); 还有 IPIP/CrossSubnet 这类"能路由就路由, 不行才封装"的折中
- 选型: 自建/异构/图省事 → Overlay; 性能敏感/网络可控 → 路由
VXLAN 的封装开销到底有多大? 值得为它换成路由吗?
VXLAN 外层头约 50 字节, 加上封装/解封装的 CPU 开销, 通常带来个位数到百分之十几的吞吐损耗(取决于包大小和硬件, 小包影响更明显). 对绝大多数业务, 这点损耗完全可接受, Overlay 的"省心"更值钱.
只有在网络密集型, 对延迟/吞吐极敏感的场景(高频交易, 大数据传输), 才值得为路线二的复杂度买单. 别为了"听起来更快"就盲目上 BGP--多数团队 Flannel 足矣.
云厂商的托管 K8s(EKS/GKE/ACK)用的是哪条路线?
很多云厂商走了"第三条路"--直接用云自己的 VPC 网络给 Pod 分配真实的 VPC IP(如 AWS VPC CNI). 这样 Pod IP 就是 VPC 里真实可路由的 IP, 既没有 Overlay 封装开销, 又不用自己配 BGP, 因为云的 VPC 网络底层已经把路由这件事做好了.
这本质上是"L3 路由"路线的一种云原生实现--把路由的复杂度下沉给了云平台. 代价是 Pod IP 会消耗 VPC 的 IP 地址空间. 这也再次印证: 具体怎么实现, 取决于所处环境--而 CNI(下一篇)正是让能按环境换实现的那个接口.
动手练习
- 起多节点集群观察: 用 kind 或 k3d 起一个多节点集群(默认通常是 Flannel/类 Overlay), 把两个 Pod 调度到不同节点, 确认它们能互 ping
- 抓包看封装: 在节点上用
tcpdump抓物理网卡的包, 观察跨节点 Pod 流量是否带 VXLAN 外层头(UDP 8472 端口), 亲眼看到"封装" - 读路由表判断路线: 查看节点的路由表(
ip route), 找出"去往其他节点 Pod 网段"的路由条目--对照本篇两条路线, 判断集群走的是封装还是路由 - 对比 Calico 集群(进阶): 换成 Calico 起一个集群, 对比: 跨节点流量还有 VXLAN 外层吗? 路由表里多了什么? 用本篇的两条路线解释差异
- 结合实际选型: 思考: 实际的 K8s 跑在自建机房还是云上? 根据环境, Overlay 和路由哪条更合适? 为什么?