kubernetes网络模型flannel和calico解析和对比
有段时间没写技术文章了,一直忙着找工作,刷力扣,看书。也没有找时间好好沉淀下。现在补上。
本文探讨kubernetes常见的网络模型flannel和calico,会介绍两种网络模型的各种模式以及通信原理,然后对比相同点和不同点以及优缺点。网上也有很多参考资料,也是参考了这些资料整理出来的。
首先,我们需要了解下kubernetes的网络模型的基本要求。
每个Pod都拥有一个独立的IP地址,并假定所有Pod都在一个可以直接连通的、扁平的网络空间中。
具体要求有3点
(1)所有容器都可以在不用NAT的方式下同别的容器通信。
(2)所有节点都可以在不用NAT的方式下同所有容器通信,反之亦然。
(3)容器的地址和别人看到的地址是同一个地址。
主要就是两个工作
1、网络模型需要分配和管理pod的ip,保证ip不冲突。
2、网络模型需要将这些信息通过各种方式同步给所有节点
不管是flannel和calico就是实现了这两个工作。
现在来探讨下flannel和calico如何实现这两个工作。
flannel
flannel是通过flanneld进程分配ip,并通过etcd进行持久化存储。根据不同模型采用不同方式将信息同步给其他节点。
模式一:udp
在udp模式下,flannel会创建一个tun设备flannel0(TUN设备是工作在三层的虚拟网络设备,在操作系统内核和用户程序之间传递ip包),这个设备由flanneld创建。一端是绑定到docker0,作为docker0默认网关。一端是flanneld。如果flannel0收到数据,会将其发送给创建其的进程即flanneld。
为了描述方便,我将flannel分配给pod的ip称为私网ip,将宿主机的ip称为宿主机ip
flanneld会根据接收方私网ip地址,查询本地缓存或者去etcd查询。得到接收方宿主机ip。然后再封装一层ip报文,其接收方ip即刚才查询到的接收方宿主机ip,目的端口是自己监听的端口。然后传递给宿主机的网卡。宿主机网卡根据ip发送给接收方宿主机。由于目标端口是flanneld监听端口,所以接收方宿主机收到报文后会将其发送给宿主机上的flanneld,其会将报文拆开,然后发送给docker0。docker0发送给对应的pod。
总结下:
flannel在启动时会创建一个flanneld进程,其会创建一个tun设备flannel0,作为docker0默认网关。并且flanneld会根据当前集群节点给每个节点分配一个私有网段(会预留一部分供后续增加节点使用),并保存到etcd中,然后修改docker0启动参数,加上--bip=分配的私有网段。这样docker0在给pod分配ip的时候就只会使用这个私网网段的ip,这样ip就不会冲突了。到这里第一个工作就做完了。
相同节点下的pod通信,直接通过docker0进行通信。
不同节点下的pod通信,会通过docker0传递给flannel0,然后由flanneld封包,发送给宿主机网卡。并由其发送给接收方宿主机。然后传递给接收方宿主机flanneld,解包,通过flannel0经由docker0传给对端pod。
流程如下
pod1->docker0->flannel0(flanneld封包)->(发送方网卡)->(中间路由器)->(接收方网卡)->flannel0(flannel解包)->docker0->pod2
流程很复杂很长。而且由于flanneld是用户进程,封包和解包需要上下文切换等操作。性能非常差。一般仅测试使用。
模式二:VxLan
VXLAN,即Virtual Extensible LAN(虚拟可扩展局域网),是Linux本身支持的一网种网络虚拟化技术。VXLAN可以完全在内核态实现封装和解封装工作,从而通过“隧道”机制,构建出覆盖网络(Overlay Network)
为了能够在二层网络上打通“隧道”,VXLAN会在宿主机上设置一个特殊的网络设备作为“隧道”的两端,叫VTEP:VXLAN Tunnel End Point(虚拟隧道端点)
在该模式下,前面的ip分配工作不变(flannel0改成flannel.1),需要在发送方宿主机和接收方宿主机建立VXLAN隧道,即要创建VTEP。由其进行内核态的封装和解封装操作,并且其是二层封装,即封装mac地址,而非udp的ip地址。
总结下:
docker0会将非本机的ip数据包发送给flannel.1,flannel.1找到目标主机的VTEP设备(通过本地缓存或者etcd查询),设备信息由flanneld进程维护。找到设备信息后,封装mac报文。然后发送给目标VTEP设备。目标VTEP设备收到后,进行拆包,然后经由docker0发送给对端pod。
流程如下
pod1->docker0->flannel.1->VTEP1->(发送方网卡)->(中间路由器)->(接收方网卡)->VTEP2->flannel.1->docker0->pod2
流程还是很长,但是由于封包和解包操作由内核执行,所以效率相较udp更高。
模式三:host-GW
该模式下前面的ip分配和管理工作不变(不需要flannel0和flannel.1),还是由flanneld管理。其直接将etcd中保存的私网ip和宿主机ip信息转化为路由信息下发给每个宿主机。将宿主机充当网关。flanneld只需要watch监听etcd中信息变化做对应的修改。
流程如下
pod1->docker0->(发送方网卡)->(接收方网卡)->docker0->pod2
流程变短很多,但是由于需要将宿主机充当网关使用,所以要求,两台机器在同一个子网中。其效率也很高,但是当集群节点变多,路由信息不好维护。
Calico
Calico是采用三层的方案,其通过felix分配和管理ip,并通过bgp协议通告路由信息。
felix主要是负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等,可以类比成flanneld。由其来分配和管理ip,并且也是通过etcd进行持久化存储。
通过bird进行bgp协议广播。默认情况下两两节点需要互联,可以使用Route Reflector(RR)模式,选择一个节点作为RR节点,其他节点与该节点互联,由RR节点同步其他节点的路由信息。
Calico两种工作模式
IPIP模式
IPIP网络就是将IP网络封装在IP网络里。IPIP网络的特点是所有pod的数据流量都从隧道tunl0发送,并且在tunl0这增加了一层传输层的封包。
类似flannel的vxlan模式,区别是ipip是三层,vxlan是二层隧道。
BGP模式
通过felix管理ip和路由,通过bird广播bgp协议,通告路由信息。
类似flannel的host-Gw模式,区别是不需要在同一个子网中。
如果节点数量不多,那么flannel和calico都可以,如果节点数量较多,最好使用calico
除开Calico的bgp模式,理论上性能排序
flannel vxlan>calico ipip > flannel udp
理由是vxlan和ipip虽然都是内核态封包和解包,但是vxlan是二层包,ipip是三层包,vxlan报文头更短,一般来说层级更低,效率会更高。
至于ipip大于udp是因为一个是内核态一个是用户态,当然内核态性能更好。
以上个人属于个人观点,有不同意见欢迎交流