本文目录导读:

Flannel 是一个专为 Kubernetes 设计的简单易用的容器网络解决方案(CNI 插件),它的核心功能是为集群中的所有 Pod 分配一个唯一的、可路由的 IP 地址,并建立覆盖网络(Overlay Network),使得不同节点上的 Pod 可以像在同一个局域网内一样直接通信。
Flannel 实现覆盖网络主要有两种核心模式:VXLAN(最常用,默认)和 host-gw(高性能,但有限制)。
核心原理(以 VXLAN 为例)
VXLAN 是 Flannel 最常用的模式,它通过在现有物理网络(Underlay Network)之上,构建一个虚拟的二层网络。
关键角色:
- etcd:Flannel 的后端存储,它存储了整个集群的网络配置(如 Pod 网段)和每个节点的子网分配信息。
- flanneld:部署在每个节点上的守护进程,它负责从 etcd 获取本节点的子网信息,并管理 VXLAN 隧道。
具体工作流程:
假设有两个节点:
- Node A:IP 为 192.168.1.10,其上的 Pod A 的 IP 为 10.5.1.2。
- Node B:IP 为 192.168.1.20,其上的 Pod B 的 IP 为 10.5.2.3。
当 Pod A(10.5.1.2)尝试 Ping Pod B(10.5.2.3)时,发生了以下步骤:
-
Pod A 发送数据包:
- 数据包的目的 IP 是 Pod B 的 IP(10.5.2.3)。
- 源 IP 是 Pod A 的 IP(10.5.1.2)。
-
到达 Node A 的 Root Namespace:
- 数据包通过 Pod 的 veth 对到达宿主机的 Docker/Containerd 网桥(通常是
cni0或docker0)。 - 宿主机内核查找路由表,由于目标 IP 10.5.2.3 属于另一个节点(Node B)的子网,路由表会指向
flannel.1这个虚拟网卡(VXLAN 隧道的 VTEP 设备)。
- 数据包通过 Pod 的 veth 对到达宿主机的 Docker/Containerd 网桥(通常是
-
VXLAN 封装(关键步骤):
flannel.1接口将内核传过来的原始以太网帧进行 VXLAN 封装,封装过程包括:- 添加 VXLAN 头部:包含一个 VNI(VXLAN 网络标识符),用于区分不同的租户或网络,Flannel 默认的 VNI 是 1。
- 添加 UDP 头部:外层 UDP 的目标端口是 8472(Flannel 默认)。
- 添加外部 IP 头部:外层包的目标 IP 是目标宿主机的物理 IP(192.168.1.20),源 IP 是源宿主机的物理 IP(192.168.1.10)。
- 添加外部 MAC 头部:外层包的目标 MAC 地址是到达 Node B 的下一跳 MAC 地址。
- 简单理解:原本的 Pod 数据包(10.5.1.2 → 10.5.2.3)被“打包”进一个新的 UDP 数据包(192.168.1.10:8472 → 192.168.1.20:8472)中。
-
在物理网络中传输:
这个外层 UDP 数据包就像普通流量一样,通过公司的物理交换机、路由器等设备,从 Node A 传输到 Node B。
-
在 Node B 解封装:
- Node B 上的
flanneld进程监听着 UDP 端口 8472。 - 当收到这个外层 UDP 包时,flanneld 识别出这是 VXLAN 流量。
- 它剥离掉外层的 IP/UDP/VXLAN 头部,还原出原始的 Pod 数据包(10.5.1.2 → 10.5.2.3)。
- Node B 上的
-
交付给 Pod B:
- 还原后的数据包被插入到 Node B 的内核网络栈中。
- Node B 的路由表显示目标 IP(10.5.2.3)是本节点上某个 Pod 的 IP。
- 数据包通过本地的网桥(
cni0)和 veth 对,最终到达 Pod B 的eth0网卡。
整个过程对 Pod 是完全透明的,Pod A 认为自己在直接 Ping Pod B 的 IP,但实际上数据包在宿主内核中经历了“封装 → 物理传输 → 解封装 → 最终交付”的旅程。
Flannel 的其他覆盖模式
除了 VXLAN,Flannel 还支持其他模式,性能和适用场景不同:
| 模式 | 原理 | 优点 | 缺点 | 使用场景 |
|---|---|---|---|---|
| VXLAN | 封装在 UDP 中,在内核内完成。 | 跨网络能力极强(无需底层网络支持组播或路由),兼容性好,最常用。 | 有额外的包头开销(约50字节),性能略低于 host-gw。 | 几乎所有场景,尤其是公有云、复杂网络环境。 |
| host-gw | 不封包,直接在宿主机路由表中创建路由规则,将 Pod 子网指向对应宿主机物理 IP。 | 性能最高(无封装解封装损失),最接近原生网络性能。 | 要求所有宿主机在同一个二层网络(同一交换机下),不能跨 VLAN 或路由器。 | 自建机房或私有云,所有节点二层可达,追求极致性能且网络简单。 |
| UDP | 用户态封装(非内核),较早的实现。 | 兼容性高,即使内核版本低也能跑。 | 性能极差(数据需要在内核态和用户态之间来回拷贝),已基本弃用。 | 几乎不再使用。 |
| WireGuard | 使用 WireGuard 加密隧道。 | 支持加密传输,安全。 | 配置较复杂,需要宿主机支持 WireGuard 内核模块。 | 对数据安全性有极高要求(如跨公网集群)。 |
| IPIP | 简单的 IP 封装(IP in IP)。 | 比 VXLAN 开销小一点。 | 同样依赖宿主机网络支持。 | 某些特定网络场景,不如 VXLAN 通用。 |
- Flannel 本质上是一个“L2 over L3”的隧道方案。
- 默认使用 VXLAN,在内核态完成数据包的封装和解封装,通过在宿主机物理 IP 之上构建 UDP 隧道,让 Pod 的虚拟 IP 能够跨节点通信。
- 其核心架构依赖 etcd 来存储配置和分配子网。
- 简单、稳定、易部署是 Flannel 的最大优势,虽然性能不是最强,但其工作可靠性和广泛兼容性使其成为很多 Kubernetes 集群的首选网络方案之一。
如果你想直观理解 VXLAN 模式的数据包结构变化:
[Pod 数据包]
| MAC头 | IP头 (10.5.1.2 -> 10.5.2.3) | 负载 |
↓ 在宿主机 flannel.1 上,被外层包裹
[物理网络传输包]
| 外层MAC头 | 外层IP头 (192.168.1.10 -> 192.168.1.20) | UDP头 (src:随机, dst:8472) | VXLAN头 (VNI=1) | 原始Pod数据包 |
标签: Backend