1、介绍
Flannel 是一个轻量级、易于配置的网络插件,旨在简化 Kubernetes 集群中 Pod 网络的管理。Flannel 的核心功能是提供一个虚拟的网络,允许每个 Pod 获取一个独立的 IP 地址,并实现不同节点间的 Pod 之间的通信
2、原理
2.1 基本概念
CNI (Container Network Interface): CNI 是一种标准接口,允许不同的网络插件与容器运行时进行交互。Flannel 就是一个实现了 CNI 规范的网络插件。
Backend: Flannel 支持多种后端实现方式,包括 VXLAN、host-gw(直接路由)、UDP 等等
2.2 原理
Flannel 首先从给定的更大地址池中为集群中的每个节点分配一个小的子网。然后,它会负责维护这些子网和对应节点之间的映射关系。当数据包需要从一个节点传输到另一个节点时,Flannel 根据其配置的 backend 来决定如何转发这些数据包。
2.3 flannel CNI工作流程
总结flannel-cni的工作流程如下:
-
Pod创建与网络命名空间准备:当Kubernetes的kubelet创建一个Pod时,首先会创建一个pause容器,并使用该容器的网络命名空间作为参数(例如通过
/var/run/docker/netns/xxxx获取)。这个命名空间将被用于后续CNI插件的调用。 -
CNI配置文件:在
/etc/cni/net.d/目录下存在名为10-flannel.conflist的配置文件,该文件由kube-flannel组件启动时生成。它定义了CNI插件链,首先是flannel类型,其次是portmap,用于支持端口映射功能。 -
Flannel插件执行:根据配置,kubelet调用
/opt/cni/bin/flannel执行。Flannel首先读取/run/flannel/subnet.env文件以获取当前节点的子网信息(如网络范围、MTU等),这些信息也是由kube-flannel在启动时写入的。 -
动态配置生成:基于从
subnet.env中读取的信息,Flannel生成符合CNI标准的配置文件,其中包含了bridge类型的网络配置以及host-local IP地址管理器的设置。 -
Bridge插件调用:接着,Flannel按照上述配置调用
/opt/cni/bin/bridge插件。此过程涉及:- 创建Linux bridge
cni0并绑定子网的第一个IP地址作为默认网关。 - 在主机上添加路由规则,确保节点到本节点所有Pod的流量都通过
cni0。 - 为新Pod创建veth对,并将其一端连接到Pod的网络命名空间,另一端连接到
cni0。 - 为Pod内的veth接口分配IP地址,并设置默认网关。
- 创建Linux bridge
-
跨节点通信:尽管flannel-cni主要负责同一节点上的Pod间通信,跨节点的Pod通信则由kube-flannel组件处理,包括设置适当的MTU值和选择合适的跨节点通信方案(如vxlan或host-gw)。
-
IP地址管理:
host-local插件负责管理IP地址的分配情况,通过在本地文件系统中记录已分配的IP及其对应的容器ID来避免IP冲突。这通常发生在/var/lib/cni/network/host-local/目录下。
这样,通过一系列的步骤和组件协作,flannel-cni成功地为每个Pod设置了网络环境,实现了在同一节点上的Pod间通信。
3、网络模式
-
vxlan(默认):基于 VXLAN(Virtual Extensible LAN)隧道协议,通过隧道将不同主机上的 Pod 网络连接起来。适合大部分场景,特别是在跨节点的环境下。
-
host-gw:这种模式依赖于主机间的路由表,而不需要额外的隧道。它适合于节点之间有直通路由的环境,例如同一数据中心内的节点。
| 特性 | vxlan(默认) | host-gw |
|---|---|---|
| 原理 | 基于 VXLAN 隧道协议,将 Pod 流量封装在 VXLAN 数据包内,跨节点传输数据 | 利用节点的路由表,通过主机间的直接路由进行通信 |
| 优点 | 1、支持跨数据中心部署。 2、 网络封装灵活 | 1、性能高,无需额外开销 2、维护简单 |
| 缺点 | 1、性能开销较大,特别是对于大规模集群 2、配置和故障排查较复杂 | 不适用于复杂网络环境或跨数据中心部署 |
| 适用场景 | 跨数据中心或不同网络环境的集群,适用于没有直接路由的网络。 | 节点间网络有直接路由的环境(例如同一数据中心内) |
3、原理详细
3.1 vxlan
同节点pod之间通讯
假设有两个 Pod(Pod A 和 Pod B)运行在同一节点上,IP 分别为 10.244.1.2 和 10.244.1.3,子网由 Flannel 分配为 10.244.1.0/24。
- Pod A 发起通信:
Pod A 需要向 Pod B 发送数据包(目标 IP 为 10.244.1.3)。
数据包从 Pod A 的虚拟网络接口(veth pair)发出,进入其网络命名空间。 - 进入宿主机网络:
Pod A 的 veth pair 的一端连接到宿主机的网桥(通常是 Flannel 创建的 cni0 网桥)。
数据包通过 veth pair 传递到 cni0 网桥。 - 网桥转发:
cni0 网桥是一个二层设备,会根据目标 MAC 地址进行转发。
因为 Pod B 的 IP(10.244.1.3)也在同一子网内,网桥通过 ARP 解析获取 Pod B 的 MAC 地址。
网桥发现 Pod B 的 veth pair 也连接到自己,因此直接将数据包转发到 Pod B 的 veth pair。 - Pod B 接收数据:
数据包通过 Pod B 的 veth pair 进入其网络命名空间。
Pod B 的网络栈处理数据包,最终到达目标应用程序。
跨节点pod之间通讯

发送端:pod A的数据包会通过虚拟网卡转发到(cni0)容器虚拟网桥上,然后交由 flannel.1 设备处理,进行VXLAN封包解包,然后从 eth0 发送。
接收端:Node2收到报文后,发现是一个VXLAN类型报文,交由 flannel.1 进行解包。根据解包后得到的原始报文中的目的IP,将原始报文经由 cni0 网桥发送给目标Pod。
3.2 host-gw

- 发送端(Pod A,节点 1):
1、Pod A(10.244.1.2)发出数据包到 Pod B(10.244.2.3),从 veth pair 送到节点 1 的 cni0 网桥。
2、cni0 查路由表,发现目标是 10.244.2.0/24,转给 flannel.1。
3、flannel.1 把数据包封装成 VXLAN(外层 IP: 192.168.1.10 → 192.168.1.11),通过 eth0 发送到节点 2。 - 接收端(Pod B,节点 2):
1、节点 2 的 eth0 收到 VXLAN 数据包,转给 flannel.1。
2、flannel.1 解封装,恢复原始数据包(10.244.1.2 → 10.244.2.3)。
3、数据包送到 cni0 网桥,用 ARP 找到 Pod B 的 MAC,转给 Pod B 的 veth pair。
4、Pod B 收到数据,交给应用处理
2万+






