Kubernetes网络插件详解 - Flannel篇
Kubernetes本身并没有自己实现容器网络,而是借助CNI标准,通过插件化的方式来集成各种网络插件,实现集群内部网络相互通信。Kubernetes集群设计了Cluster IP、Node IP、Pod IP三种类型的通信IP:Cluster IP是Service对象的IP地址,实现Pod服务的负载均衡,外部网络无法ping通,只在集群内部可以访问使用,是一个虚拟的IP;Node IP是集群节点Node的IP地址,可以是物理机的IP(也可能是虚拟机IP);Pod IP是容器组Pod的IP地址,是在容器组初始化过程由Pause容器申请的IP地址。其中Pod IP是容器网络接口CNI与具体的网络插件来实现IP的申请及数据包的转发。
Flannel是CoreOS开源的,Overlay模式的CNI网络插件,Flannel在每个集群节点上运行一个flanneld的代理守护服务,为每个集群节点(HOST)分配一个子网(SUBNET),同时为节点上的容器组(POD)分配IP,在整个集群节点间构建一个虚拟的网络,实现集群内部跨节点通信。Flannel的数据包在集群节点间转发是由backend实现的,目前,已经支持核心官方推荐的模式有UDP、VXLAN、HOST-GW,以及扩展试用实验的模式有IPIP,AWS VPC、GCE、Ali VPC、Tencent VPC等路由,其中VXLAN模式在实际的生产中使用最多。
核心模式
UDP模式
UDP模式简单来说,就是数据报文在发送实际物理网络之前,通过flanneld进行一层UDP封装,将数据报文作为payload发送给对端,对端收到UDP报文之后,flanneld通过解包得到真正的数据报文后,再转发至最终的服务端,如图一所示。
UDP模式的核心点是虚拟网络设备tun/tap,该设备一端连接协议栈,另外一端连接用户程序,允许用户程序像读写文件一样进行收发数据包。tun/tap工作原理基本一致,tun模拟是三层网络设备,收发的是IP层数据包;tap模拟是二层网络设备,收发以太网数据帧。
在UDP模式,Flannel通过DaemonSet控制器,在每个节点启动一个kube-flannel的Pod,同时会创建两个虚拟网络设备,cni0与flannel0,如图二所示,其中cni0是linux bridge设备,而flannel0则是Tun设备。
在同一个Kubernetes集群中,Pod通信有同节点Pod通信及跨节点Pod通信两种场景,其中同节点Pod通信,由于cni0是类二层转发设备,可以直接实现数据包的转发,所以同节点的Pod间通信,直接通过Linux bridge cni0来实现。跨节点Pod通信则是三层虚拟网络设备Tun,也就是flannel0。当Pod数据包通过路由发送到flannel0上,节点主机上的flanneld进程就会收到IP包,并将IP包封装在一个UDP包,通过物理网络发送给目的宿主机。同理目的主机就会有UDP解包及转发至Pod服务。
UDP模式比较简单,但是由于flanneld运行在用户态,而数据的交互和传递则在内核态完成,会经历两次的内核态和用户态数据拷贝,性能损耗巨大,所以UDP模式已经逐渐废弃。如图四所示,是一个完成UDP模式数据包转发过程及路由表。
VXLAN模式
VXLAN (Virtual Extensible LAN)是一种网络虚拟化技术,它使用一种隧道协议将二层以太网帧封装在四层UDP报文中,通过三层网络传输,组成一个虚拟大二层网络。VXLAN使用VTEP(VXLAN Tunnel Endpoint)来进行封包和解包:在发送端,源VTEP将原始报文封装成VXLAN报文,通过UDP发送到对端VTEP;在接收端,VTEP将解开VXLAN报文,将原始的二层数据帧转发给目的的接收方。VTEP可以是独立的网络设备,例如交换机,也可以是部署在服务器上的虚拟设备。例如使用置顶交换机(TOR)作为VTEP时,VXLAN的网络模型如下图:
Flannel默认和推荐的模式就是VXLAN,当使用默认配置安装Flannel时,会为每个节点分配一个24位子网,并在每个节点上创建两张虚机网卡cni0和flannel.1:其中cni0是一个网桥设备,节点上所有的Pod都通过veth pair的形式与cni0相连;而flannel.1则是一个VXLAN类型的设备,充当VTEP的角色实现对VXLAN报文的封包解包。
同节点Pod通信,与UDP模式一样,通过cni0网桥完成,不涉及VXLAN报文的封包解包操作;跨节点Pod通信则是通过静态配置路由表,ARP(address resolution protocol 地址解析协议)表和FDB表(Forwarding database二层设备中MAC地址和端口的关联关系)的信息,通过VXLAN虚拟网卡flannel.1,实现了集群内所有Pod在同一个大二层网络相互通信。还有VXLAN模式支持DirectRouting配置,DirectRouting=true是支持在相同子网情况下数据包直接通过路由转发,与HOST-GW模式相同。
UDP模式和VXLAN模式都是属于隧道方式,也就是在UDP的基础之上,构建虚拟网络,VXLAN模式只是将UDP模式的flanneld进程换成了VTEP设备,通过VTEP设备完成封包和解包的过程;另外一个关键点是VXLAN模式全过程全部在内核态完成,flannel.1充当网桥的角色,进行UDP数据包的转发,所以性能要比UDP模式好很多。
HOST-GW模式
与UDP模式和VXLAN模式不同,HOST-GW模式属于路由的方式,无需经过任何封包和解包,纯路由机制实现,因此性能比较高。但是HOST-GW模式只支持宿主机之间二层连接,要求集群中所以节点必须处于同一个网络中。如果不在一个网络中,三层设备路由器缺少Pod 网络的路由规则,无法转发数据包。
HOST-GW模式将目的主机当作网关,直接路由原始的数据包。flanneld会在集群节点上创建并维护路由表,当数据包到达集群节点的时,就会根据路由表直接发送到下一跳,也就是同网段的节点IP,直接通过二层网络将数据转发到目的节点上;目的节点再根据路由表规则转发到cni网桥,网桥根据路由规则转发到容器里面。
HOST-GW模式通过路由转发实现高性能网络通信,但是这种模式局限性很大,节点之间都要相互有点对点的路由覆盖,每个节点上有n-1个路由,而n个节点共有n(n-1)/2个路由,才能保证flannel的flat网络能力。
扩展模式
IPIP模式
IPIP模式是一种简单隧道方式,通过内核IPIP封装数据包,开销低但只能封装ipv4单播通信,因此无法设置OSPF、RIP或任何其他基于多播的协议。
在IPIP模式,会有两个IPIP隧道设备tunl0和flannel.ipip,其中tunl0由ipip的内核模块,在modprobe ipip模块的网络命名空间(network namespace)自动创建,是命名空间默认IPIP设备,包含local=any和remote=any属性,flannel.ipip是由flannel创建的一对多ipip设备。当接收到IPIP协议数据包时,内核在local/remote属性中存在精确匹配src/dst的IP地址,就会解包转到内部服务,否则会将数据包转发到tunl0备用设备。同样,还有IPIP模式也支持DirectRouting配置,DirectRouting=true是支持在相同子网情况下数据包直接通过路由转发,与HOST-GW模式相同。
Cloud VPC
Kubernetes容器很多情况下都是部署在公有云之上,容器集群的网络需要云其他产品互联互通,Flannel支持公有云Cloud VPC模式,在AWS VPC,AliVPC,TencentCloud VPC运行容器集群,就可以直接使用VPC的路由表,将容器内部IP实时同步到路由表中,这样容器内部IP与其他云产品相互通信,比如ELB就可以直接配置路由到容器内部,不过有的公有云要路由条数有限制,或者需要额外收费。
总结
总的来说,Kubernetes网络比较复杂,主要是涉及到容器运行时CRI,容器网络标准CNI,以及容器网络插件三个方面配合及协调,同时在灵活易用及性能优化上持续演进。Flannel作为使用最广网络插件,主要具备两大优势:首先从UDP,VXLAN,HOST-GW到IPIP,不仅是场景覆盖与性能的权衡演进,还有对底层操作核心能力的快速支持,社区一直保持活跃。其次开放与云平台的集成,容器大部分运行环境都是在云平台之上,与云平台的集成直接使用底层云能力实现网络能力,提供开箱即用且高效网络方案,将云的能力最大化,始终贯彻云原生的理念。
模式 | 底层网络要求 | 实现模式 | 封包/解包 | overlay网络 | 转发效率 |
Flannel UDP | 三层互通 | overlay | 用户态 | 三层 | 低 |
Flannel VXLAN | 三层互通 | overlay | 内核态 | 二层 | 中 |
Flannel host-gw | 二层互通 | 路由 | 无 | 三层 | 高 |
IPIP模式 | 三层互通 | overlay | 内核态 | 三层 | 高 |
Cloud VPC | 三层互通 | 路由 | 无 | 三层 | 高 |