在K8S中,flannel的作用?
Flannel 是 Kubernetes 中最经典、最广泛使用的 CNI(Container Network Interface)网络插件之一。它的核心作用是为 Kubernetes 集群提供一个简单、可靠的 Overlay 网络(覆盖网络),确保集群中所有 Pod 能够跨节点相互通信,无论这些 Pod 被调度到哪个节点上。这是 Kubernetes 网络模型的基本要求之一。
以下是 Flannel 的主要作用、工作原理和关键特性:
核心作用
-
提供 Pod 跨节点网络互通:
- 这是 Flannel 最根本的任务。它确保:
- 每个 Pod 获得一个唯一的、集群范围内有效的 IP 地址。
- 一个节点上的 Pod 可以直接通过 IP 地址访问另一个节点上的 Pod,无需进行 NAT(网络地址转换)。
- 解决了 Kubernetes 集群节点间 Pod 通信的基础需求。
- 这是 Flannel 最根本的任务。它确保:
-
实现 Kubernetes 网络模型:
- Kubernetes 要求:
- 所有 Pod 都可以在不使用 NAT 的情况下与其他所有 Pod 通信。
- 所有节点都可以在不使用 NAT 的情况下与所有 Pod 通信。
- Pod 自身看到的 IP 地址就是其他 Pod/节点看到的 IP 地址(IP-per-Pod)。
- Flannel 的设计目标就是满足这些要求。
- Kubernetes 要求:
工作原理 (以最常用的 VXLAN 后端为例)
-
网络规划:
- Flannel 会从管理员配置的一个大的 CIDR 地址块(例如
10.244.0.0/16
)中,为每个 Kubernetes 节点分配一个独立的、互不重叠的子网(例如10.244.1.0/24
给 Node1,10.244.2.0/24
给 Node2)。 - 每个节点上的 Pod 的 IP 地址都从这个节点的子网中分配。例如,Node1 上的 Pod 地址可能是
10.244.1.2
,10.244.1.3
等。
- Flannel 会从管理员配置的一个大的 CIDR 地址块(例如
-
本地网络 (节点内 Pod 通信):
- 当一个 Pod 被创建时,Flannel 的 CNI 插件(通常与
containerd
或CRI-O
集成)会:- 在节点上创建一个 Linux 网桥(通常叫
cni0
)。 - 为 Pod 创建一对 veth pair:一端放在 Pod 的网络命名空间内(命名为
eth0
),另一端连接到cni0
网桥上。 - 从分配给该节点的子网中为 Pod 的
eth0
分配一个 IP 地址,并设置 Pod 内的路由规则(默认网关指向cni0
的 IP)。
- 在节点上创建一个 Linux 网桥(通常叫
- 同一个节点上的 Pod 通信:数据包通过
eth0
-> veth pair ->cni0
网桥 -> 目标 Pod 的 veth pair -> 目标 Pod 的eth0
。这个过程在二层完成,不经过内核路由栈。
- 当一个 Pod 被创建时,Flannel 的 CNI 插件(通常与
-
跨节点网络通信 (关键):
- 当一个节点(Node1)上的 Pod(Pod A:
10.244.1.2
)需要访问另一个节点(Node2)上的 Pod(Pod B:10.244.2.3
)时:- 源节点 (Node1):
- Pod A 发出目标地址为
10.244.2.3
的数据包。 - 数据包到达
cni0
网桥。 - Node1 的内核路由表知道目标地址
10.244.2.3
属于子网10.244.2.0/24
,而这个子网属于 Node2。 - Flannel 守护进程
flanneld
会在每个节点上创建一个特殊的网络接口,通常是flannel.1
(VXLAN 接口)。 - 路由表指示:去往
10.244.2.0/24
的数据包,下一跳是flannel.1
接口(或更具体地说,需要通过 VXLAN 隧道发送到 Node2)。
- Pod A 发出目标地址为
- 封装 (VXLAN):
- 内核的 VXLAN 模块将原始的 Pod-to-Pod 数据包(内层包:源 IP=
10.244.1.2
, 目标 IP=10.244.2.3
)封装在一个新的 UDP 数据包中(外层包)。 - 外层 UDP 头: 源端口是动态的,目标端口是标准的 VXLAN 端口(通常是
8472
)。 - 外层 IP 头: 源 IP = Node1 的 IP 地址,目标 IP = Node2 的 IP 地址。
- VXLAN 头: 包含一个 VNI(VXLAN Network Identifier),用于标识不同的覆盖网络(Flannel 默认使用 VNI=1)。
- 内核的 VXLAN 模块将原始的 Pod-to-Pod 数据包(内层包:源 IP=
- 传输:
- 这个封装后的 UDP 数据包通过 Node1 的物理网络接口发送出去。
- 底层网络(交换机、路由器)只看到 Node1 到 Node2 的普通 IP/UDP 流量,并根据它们的 IP 地址进行路由,将数据包送达 Node2。
- 解封装 (Node2):
- Node2 的物理接口收到 UDP 数据包,发现目标端口是
8472
(VXLAN),于是将其交给内核的 VXLAN 模块处理。 - VXLAN 模块解封装数据包,剥离外层 UDP/IP 头,露出原始的 Pod-to-Pod 数据包(内层包:源 IP=
10.244.1.2
, 目标 IP=10.244.2.3
)。
- Node2 的物理接口收到 UDP 数据包,发现目标端口是
- 目标节点 (Node2) 内部转发:
- 解封装后的原始数据包被送到 Node2 的
flannel.1
接口。 - Node2 的内核路由表查询目标地址
10.244.2.3
,发现它属于本机的cni0
网桥管理的子网。 - 数据包被转发到
cni0
网桥。 cni0
网桥根据 MAC 地址表将数据包转发到连接目标 Pod B 的 veth 接口。- 数据包最终到达 Pod B 的
eth0
。
- 解封装后的原始数据包被送到 Node2 的
- 源节点 (Node1):
- 当一个节点(Node1)上的 Pod(Pod A:
关键特性与后端
-
多种后端 (Backend): Flannel 支持不同的封装/传输技术来实现跨节点通信,性能、复杂性和依赖不同:
vxlan
(默认且最常用): 如上述原理所示。提供良好的兼容性,能穿越大多数网络。有封装开销(~50字节)。host-gw
(Host Gateway):- 性能最好(接近裸金属网络),无封装开销。
- 原理:在路由表中为每个其他节点的 Pod 子网添加一条路由规则,指明下一跳就是目标节点的 IP 地址(
10.244.2.0/24 via <Node2_IP> dev eth0
)。 - 要求:节点间必须在同一个二层网络(L2 可达)。如果节点间需要经过路由器,路由器必须配置静态路由指向节点子网(不现实)。适合云环境或扁平数据中心。
udp
(已弃用): 最早的、纯用户空间实现的后端。性能差,仅用于没有内核 VXLAN 支持的旧系统。强烈不建议使用。ipsec
,wireguard
: 提供传输层加密,增强安全性。会引入额外的性能开销。ali-vpc
,gce
,aws-vpc
: 利用云提供商特定的路由功能(如 AWS VPC 路由表、GCE 路由、阿里云 VPC 路由),通常类似host-gw
但由云平台自动管理路由。性能好,依赖云平台。alloc
/ipvlan
/portmap
: 主要用于特定场景(如 IPv6、多网络接口、端口映射)。
-
简单轻量:
- 架构简单:一个在每个节点上运行的 DaemonSet (
kube-flannel-ds
)。 - 配置简单:通常只需要一个
ConfigMap
(kube-flannel-cfg
) 定义网络 CIDR 和后端。 - 资源消耗低。
- 架构简单:一个在每个节点上运行的 DaemonSet (
-
成熟稳定: 作为最早的 CNI 插件之一,经过长期生产环境验证,非常稳定。
-
专注于连通性:
- Flannel 不提供高级的网络策略功能(如防火墙规则、Pod 间 ACL)。它专注于解决最基础的 Pod 跨节点通信问题。
- 如果需要网络策略,通常需要额外安装一个网络策略提供者(如 Calico 的
kube-controllers
和calico/node
仅用于策略,或者 Cilium、Weave Net 等自带策略的插件)。
总结
Flannel 在 Kubernetes 中的核心作用是:为整个集群构建一个统一的 Overlay 虚拟网络,确保所有 Pod 无论部署在哪个节点上,都能通过唯一的 IP 地址直接相互通信。它通过简单的架构(通常是 VXLAN 封装)实现了 Kubernetes 网络模型的基本要求。
- 优点: 简单易部署、轻量、成熟稳定、社区支持好。
- 缺点: 默认 VXLAN 有封装开销(
host-gw
性能好但有网络拓扑限制)、不提供内置网络策略功能。 - 适用场景: 需要快速搭建基础网络的中小型集群、测试开发环境、对高级网络功能要求不高的场景。当需要高性能(且满足
host-gw
要求)或需要网络策略时,可能需要考虑其他方案或与策略组件结合。