十分钟漫谈容器网络方案01—Flannel
在《Docker和Kubernetes的前世今生(下)》中我们介绍了作为目前主流的容器编排系统,Kubernetes支持的功能和为容器集群业务带来的便利。而为了设计并保障编排系统运作,Kubernetes对容器集群进行了这样的要求:任何pods之间的通信都可以在不使用NAT的情况下进行,即设定集群内所有容器都是连通的。但Docker容器通过Namespace隔离,无法直接相互通信,默认可以通过共用宿主机的Network Namespace的方式,凭借宿主机的网络栈进行通讯。这样的方式也导致了一系列问题,比如征用宿主机端口时使端口资源很快不足使得通信规模受限,以及容器与宿主机共享的网络会暴露宿主机信息,致使网络传输存在安全隐患。
— 为什么需要Overlay Network —
为了不影响隔离性并实现容器间的网络通信,Docker通过虚拟网桥“连接”容器,使容器得以像物理节点一样经过“交换机”通讯。Docker在宿主机上创建名为docker0的虚拟网桥,对于每一个创建的容器均创建一对虚拟网卡设备,其中一端在docker0,另一端映射到容器内的eth0,并对容器内网卡分配一个容器网络IP。通过这一对虚拟网卡,容器就相当于“连接”到网桥上,虚拟网卡接在网桥上时只负责接受数据包,不再调用网络协议栈进行处理,因此只具有类似端口的作用。当容器A要访问容器B时,只需要广播ARP协议,通过docker0转发请求到对应”端口”,就实现了数据的转发。
然而,虽然虚拟网桥解决了同一宿主机下的容器间通信问题,以及容器与外部世界之间的通信,但是跨节点的容器通信依然存在问题。集群中每个节点的docker0都是独立的,不同节点分配的容器IP之间存在冲突的可能,因此需要有一个具有全局视角的上层网络以实现跨节点的容器网络,这便是Overlay Network解决方案的由来。
Flannel的框架包含以下组件:每个节点上的代理服务flanneld,负责为每个主机分配和管理子网;全局的网络配f置存储etcd(或K8S API)负责存储主机和容器子网的映射关系;多种网络转发功能的后端实现。本文主要介绍三种最常见的模式:UDP、VXLAN和Host-gateway(以下简称host-gw)。
Flannel在Kubernetes集群中的架构图
— Flannel数据转发模式之UDP —
UDP是与Docker网桥模式最相似的实现模式。不同的是,UDP模式在虚拟网桥基础上引入了TUN设备(flannel0)。TUN设备的特殊性在于它可以把数据包转给创建它的用户空间进程,从而实现内核到用户空间的拷贝。在Flannel中,flannel0由flanneld进程创建,因此会把容器的数据包转到flanneld,然后由flanneld封包转给宿主机发向外部网络。
UDP转发的过程为:Node1的container-1发起的IP包(目的地址为Node2的container-2)通过容器网关发到docker0,宿主机根据本地路由表将该包转到flannel0,接着发给flanneld。Flanneld根据目的容器容器子网与宿主机地址的关系(由etcd维护)获得目的宿主机地址,然后进行UDP封包,转给宿主机网卡通过物理网络传送到目标节点。在UDP数据包到达目标节点后,根据对称过程进行解包,将数据传递给目标容器。
UDP模式工作模式图
UDP模式数据包的传递过程
如果要进行性能优化,就需要减少用户态与内核态之间的数据拷贝,这就是VXLAN模式解决的问题。VXLAN的核心在于在三层网络的基础上构建了二层网络,使分布在不同节点上的所有容器在这个虚拟二层网络下自由通信。二层虚拟网络通过VXLAN在宿主机上创建的VTEP设备(flannel.1)实现,flannel.1和flanneld一样负责封包解包工作,不同的是flannel.1的封解包对象是二层数据帧,在内核中完成。
VXLAN的转发过程为:Node1的容器container-1发出的数据包经过docker0,路由给VTEP设备。每个在flannel网络中的节点,都会由flanneld维护一张路由表,指明发往目标容器网段的包应该经过的VTEP设备IP地址。Node1的VTEP会获得数据包应该发向Node2的VTEP设备的IP,并通过本地的ARP表知道目的VTEP设备的MAC地址,然后封装在数据包头部构成二层数据帧并再加上VXLAN头,标识是由VTEP设备处理的数据帧。另外,flannel会维护转发数据库FDB,记录目标VTEP的MAC地址应该发往的宿主机(也就是Node2),宿主机网卡将封装为外部网络传输的包转发到Node2。数据帧在Node2上解封后,宿主机会识别VXLAN头部,直接在内核拆包,然后转发到目标VTEP设备并转到对应容器。
作为Flannel中最被普遍采用的方案,VXLAN采用的是内置在Linux内核里的标准协议,因此虽然封包结构比UDP模式复杂,但装包和解包过程均在内核中完成,实际的传输速度要比UDP模式快许多。较快的传输速度和对底层网络的可兼容性也使得VXLAN适用性较其他模式更高,成为业务环境下的主流选择。
— Flannel数据转发模式之Host-gw —
除去上述两种模式外,Flannel还提供了一种纯三层网络模式host-gw。顾名思义,host-gw是一种主机网关模式,每个主机会维护一张路由表,记录发往某目标容器子网的数据包的下一跳IP地址(也就是子网所在宿主机的IP)。宿主机将下一跳目的主机的MAC地址作为目的地址,通过二层网络把包发往目的主机。目的主机收到后,会直接转发给对应容器。所以host-gw模式下,数据包直接以容器IP包的形式在网络中传递,每个宿主机就是通信链路中的网关。
Host-Gateway模式工作模式图
https://www.cnblogs.com/chenqionghe/p/11718365.html
和其他两种模式相比,host-gw模式少了额外的封包和拆包过程,效率与虚拟机直接的通信相差无几。但是,该模式要求所有节点都在物理二层网络中联通,且每个主机都需要维护路由表,节点规模较大时有较大的维护压力,因此不适用复杂网络。
— 基于星环TCOS的Flannel性能测试 —
目前UDP模式由于其性能问题已基本被弃用,因此对于三层物理网络首选VXLAN模式,而二层网络VXLAN和host-gw均可选用。为了测试VXLAN和host-gw在二层网络下性能,我们在实验子网内对两种模式进行了性能对比,以便更好的根据场景选择模式。我们从带宽和转发吞吐量两个方面考察性能,选择了IPerf和netperf两种网络性能测试工具。
两种模式在不同TCP window大小下的传输速率比较
两种模式不同数据负载下的吞吐量比较
根据上面两张测试数据可以得出:1、在TCP数据接收窗口相同的情况下,host-gw平均传输速度更快,比VXLAN快约20%,实验环境下最终趋于相近的速率;2、host-gw的平均吞吐量较VXLAN模式高出约5%。由此可见,对于小规模集群、二层网络下的通信,可以优先选择host-gw;而大规模集群、三层网络下的通信更适合走VXLAN模式。
和市场上很多云服务商一样,星环TCOS云操作系统的容器网络方案也兼容了Flannel。TCOS默认使用VXLAN模式,以满足复杂网络场景如跨子网通信、异地数据中心互联等,更加适合私有云部署的复杂场景。另外,TCOS也保留了host-gw模式,为小规模企业的扁平化网络提供通信方案,或者网络拓扑较简单的公有云环境下使用。
TCOS还对Flannel进行了二次开发,在自行维护了多网络和网络防火墙功能的同时,引入Flannel并不具备的Network Policy,以对Pod、Service和 NameSpace进行精细化的防火墙管理。在TCOS网络方案下,不同租户可以根据需要创建网络,彼此之间互不影响,满足了多租户网络管理隔离。
— Flannel出现后网络编排方案的发展 —
Flannel作为最早的跨网络通信解决方案,提供了自动化简单的策略,可以满足一般情况下的跨节点容器通信。市场上的云服务商如CDK Global、Ranchor、Platform9等都选择在支持其他方案的基础上保留了Flannel,足以见其在容器网络通信的适用性。作为容器网络解决方案的先驱者,Flannel和其他企业级开源解决方案如Calico、Weave等一同驱动了网络方案发展。
然而,虽然Flannel是最早为Kubernetes集群设计的自动化网络方案,但其功能并不完善,如不支持Kubernetes的Network Policy,对于有容器隔离需求的业务有着很大局限性。基于Flannel存在的问题和缺陷,也衍生出一批支持Network Policy、具备负载均衡功能等改良集群网络方案。这些方案从某种意义上来说可以被看做是Fannel的改进版,为Kubernetes的容器集群网络通信提供了更多的选择,网络编排方案开始进入百花争鸣的时代。