Flannel简介

Flannel也是一个CNI插件,它的功能跟Calico一样,为K8S集群中的Pod提供网络支撑。

Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务。

Flannel的设计目的就是为集群中的所有节点重新规划IP地址的使用规则,从而使得不同节点上的Pod能够获得“同属一个内网”且”不重复的”IP地址,并让属于不同节点上的Pod能够直接通过内网IP通信。简单来说,它的功能是让集群中的不同节点主机创建的Pod都具有全集群唯一的虚拟IP地址。

Flannel实质上是一种“覆盖网络(overlaynetwork)”,也就是将TCP数据包装在另一种网络包里面进行路由转发和通信,目前已经支持udp、vxlan、host-gw、aws-vpc、gce和alloc路由等数据转发方式。

核心关键点:

  • 网络配置:Flannel 配置存储在etcd中。Flannel节点会从etcd中读取这些配置信息,并根据配置创建和管理网络。
  • 子网分配:Flannel会为每个节点分配一个不重叠的子网,以便在节点上运行的Pod可以使用该子网内的IP。这样,集群内的每个Pod都将具有唯一的IP地址。
  • 数据包封装与转发:Flannel使用数据包封装技术(例如 VXLAN、UDP 等)将Pod之间的通信封装为跨节点的通信。当一个节点上的Pod 需要与另一个节点上的Pod通信时,源节点上的Flannel程序会将数据包封装,添加上目标子网信息,并将封装后的数据包发送到目标节点。目标节点上的Flannel程序会解封装数据包,并将其转发给目标Pod。
  • 兼容性:Flannel可以与k8s中的其他网络插件(如 Calico)一起使用,以实现更复杂的网络功能。这使得Flannel可以很好地适应不同的集群环境和需求。

Flannel架构

Flannel在底层实现上要比Calico简单。

Flannel 最主要的两个组件是flanneld跟 flannel.1:

  • flanneld:控制面,运行在用户态,负责为宿主机分配子网,并监听Etcd,维护宿主机的FDB/ARP跟路由表
  • flannel.1:数据面,运行在内核态,作为VTEP,VXLAN 数据包的封包跟解包

Flannel架构

Flannel工作模式

Flannel三种工作模式:

  • UDP 模式:使用设备 flannel.0 进行封包解包,不是内核原生支持,频繁地内核态用户态切换,性能非常差,目前官方不建议使用了;
  • VxLAN 模式:使用 flannel.1 进行封包解包,内核原生支持,性能较强;
  • host-gw 模式:无需 flannel.1 这样的中间设备,直接宿主机当作子网的下一跳地址,性能最强;

VxLAN模式

VxLAN的设计思想是: 在现有的三层网络之上,“覆盖”一层虚拟的、由内核VxLAN模块负责维护的二层网络,使得连接在这个VxLAN二层网络上的“主机”(虚拟机或容器都可以),可以像在同一个局域网(LAN)里那样自由通信。 为了能够在二层网络上打通“隧道”,VxLAN会在宿主机上设置一个特殊的网络设备作为“隧道”的两端,叫VTEP:VxLAN Tunnel End Point(虚拟隧道端点)

VXLAN是Flannel默认和推荐的模式。当我们使用默认配置安装Flannel时,它会为每个节点分配一个24位子网,并在每个节点上创建两张虚机网卡: cni0 和 flannel.1 。

  • cni0 是一个网桥设备,节点上所有的Pod都通过veth pair的形式与cni0相连。
  • flannel.1 则是一个VXLAN类型的设备,充当VTEP的角色,实现对VXLAN报文的封包解包。

同一个节点内的Pod之间通信,只需要通过cni0即可,而我们要讨论的重点是跨节点通信。

假设两个节点Node1和Node2,两个节点上分别有两个Pod:PodA和PodB,现在Node1上的PodA要和Node2上的PodB通信,通信过程如下:

fannel-1

fannel-2

大致概括一下整个过程:

  • 发送端:在PodA中发起 ping 10.244.1.21 ,ICMP 报文经过 cni0 网桥后交由 flannel.1 设备处理。 Flannel.1 设备是一个VXLAN类型的设备,负责VXLAN封包解包。 因此,在发送端,flannel.1 将原始L2报文封装成VXLAN UDP报文,然后从 eth0 发送。
  • 接收端:Node2收到UDP报文,发现是一个VXLAN类型报文,交由 flannel.1 进行解包。根据解包后得到的原始报文中的目的IP,将原始报文经由 cni0 网桥发送给PodB。

路由:

Flanneld 从 etcd 中可以获取所有节点的子网情况,以此为依据为各节点配置路由,将属于非本节点的子网IP都路由到 flannel.1 处理,本节点的子网路由到 cni0 网桥处理。

[root@Node1 ~]# ip route
10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1 # Node1子网为10.224.0.0/24 本机PodIP都交由cni0处理
10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink # Node2子网为10.224.1.0/24Node2的PodID都交由flannel.1处理

host-gw网络模式

跟VxLAN不同,host-gw模式下没有flannel.1虚拟网卡,无需建立VxLAN隧道。但它有个缺点,必须要保证各Node在同一个网段。

fannel-3

fannel-4

Flanneld 模式的工作原理,就是将每个Flannel子网的下一跳,设置成了该子网对应的宿主机的 IP 地址,也就是说,宿主机(host)充当了这条容器通信路径的“网关”(Gateway),这正是 host-gw 的含义。

所有的子网和主机的信息,都保存在 Etcd 中,flanneld 只需要 watch 这些数据的变化 ,实时更新路由表就行了。

核心是IP包在封装成桢的时候,使用路由表的“下一跳”设置上的MAC地址,这样可以经过二层网络到达目的宿主机

[root@Node1 ~]# ip r
...
10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1
10.244.1.0/24 via 192.168.50.3 dev eth0 # Node2子网的下一跳地址指向Node2的public ip

由于没有封包解包带来的消耗,host-gw是性能最好的。不过一般在云环境下,都不支持使用host-gw的模式,在私有化部署的场景下,可以考虑。