k8s的CNI网络方案选择,Flannel 和Calico 的分析对比?
问题来自@Samponiar 某航空 系统运维工程师,下文来自twt社区众多同行实践经验分享,欢迎大家参与交流,各抒己见。
@youki2008 广东溢达 系统架构师:Calico 作为老牌网络解决方案,可圈可点,已被 github 等公司用于生产。
Flannel 配置简单,性能弱低于 Calico,Redis 测试中稍占上风。大并发下稳定性稍低。
@zhuqibs Mcd 软件开发工程师:
Flannel:
(1)引入了多个网络组件,在网络通信时需要转到flannel0网络接口,再转到用户态的flanneld程序,到对端后还需要走这个过程的反过程,所以也会引入一些网络的时延损耗。
(2)Flannel模型默认采用了UDP作为底层传输协议,UDP本身是非可靠协议,虽然两端的TCP实现了可靠传输,但在大流量、高并发的应用场景下还建议多次测试。
Calico:
(1)节点组网时可以直接利用数据中心的网络结构(L2或者L3),不需要额外的NAT、隧道或者Overlay Network,没有额外的封包解包,能够节约CPU运算,提高网络效率。
(2) 在小规模集群中可以直接互联,在大规模集群中可以通过额外的BGP route reflector来完成。
(3) 基于iptables或ipvs还提供了丰富的网络策略,实现了Kubernetes的Network Policy策略,提供容器间网络可达性限制的功能。
@Garyy 某保险 系统工程师:
Calico:
IPIP/BGP 2 个方案都有不错的表现,其中 IPIP 的方案在 big meg size 上的表现更好,但在 128 字节的时候表现异常,多次测试依然一样。BGP 方案比较稳定, CPU 消耗并没有 IPIP 大,当然带宽表现也稍微差点。不过整体上来说,无论是 BGP 还是 IPIP Tunnel , Calico 这套 Overlay SDN 的解决方案成熟度和可用性都是相当不错的,是上云首选。
优势:性能好,可控性高,隔离性好。
劣势:操作起来比较复杂,对 Iptables 有依赖。
Flannel:
IPIP/BGP 2 个方案表现一般,其中 VXLAN 方案是因为没法开 UDP Offload 导致性能偏低,其他的测试报告看来,一旦让网卡自行解 UDP 包拿到 MAC 地址,性能基本上可以达到无损,同时 CPU 占用率相当好。UDP 方案受限于 USER Space 的解包,仅仅比 weave ( UDP )要好一点。
优势:部署简单,性能一般。
劣势:没办法实现固定 IP 的容器漂移,没法做子网隔离,对上层设计依赖程度高,没有 IPAM , IP 地址浪费,对 Docker 启动方法有绑定。
@wanggeng 某银行 系统运维工程师 :
在资源管理中,网络的管理是比较复杂的。对于容器平台可能的网络方案,基本上分为以下几类:
原生NAT方案
隧道方案(Overlay),代表性的方案有Flannel、Docker Overlay、OVS等
路由方案,代表性的方案有Calico、MacVlan
自定义网络方案
隧道方案,也就是Overlay方案,借助容器宿主机网络,构建出一个对于容器来说三层路由可达虚拟网络。具体做法是通过把容器网络数据包整体封装放进宿主机网络报文,由宿主机网络转发到目标容器所在的宿主机,再由目标容器所在的宿主机对报文进行拆解得到容器网络数据包,交给容器网桥,由容器网桥再转发到目标容器。隧道方案的好处是没有NAT方案的端口冲突问题、不消耗额外的骨干网络IP、与现有网络技术不产生冲突因此灵活性大、通过构建不同的VLAN虚拟网络很容易实现网络隔离、网络性能损失比原生NAT方案小,在满足银行业务功能和安全监管要求的同时,对性能也有一定的照顾。因此隧道(Overlay)方案目前是应用比较多的选择,在技术上的可选择性也最大,方案成熟度也比较高,所以相对其他的方案,隧道方案的实施、定制化、维护的成本比较低。不过事情都有两面,如果选择隧道方案,您还是有一些不可回避问题需要考虑解决:
如果容器平台中运行业务与其它平台上运行业务需要通信,则需要配置从容器外部访问容器的路由,否则容器的地址从容器平台外部不能直接路由访问。由于容器动态变化和跨主机迁移的特点,配置从外部访问容器的路由是一个比较复杂的问题,不仅需要在外部路由器、宿主机路由表中进行配置,还需要将这些配置动作和容器的启停联动起来,这需要复杂的SDN能力;
由于容器网络数据包在底层网络上传输时被封装在宿主机网络报文中,因此对普通防火墙来说,容器网络数据包的地址不可见。如果需要对容器数据包进行精确的防火墙规则设置,代价很大,几乎不可行;变通的方法可以考虑把需要进行网络隔离的容器,在启动时指定所在的VLAN,通过不同的VLAN来实现隔离;
由于容器网络数据包需要被封装在底层宿主机网络报文中,因此会增加底层网络数据包的长度,当您的底层网络也是Overlay网络,或者Overlay的层数较多时,会影响网络数据包承载数据的效率,并且封装和拆解数据包的次数也会显著影响网络的传输效率,对于性能关键的场景,这个问题也需要引起重视。
路由方案通过路由技术从三层或者二层实现跨主机容器互通,没有NAT,没有Overlay方案需要的数据包封装和拆解,每一个容器具有路由可达的IP地址,且可以做到从容器平台外部路由可达。这种网络方案的好处是性能损失小、外部路由可达、传统的防火墙仍然能正常发挥作用等。但缺点是:
IP地址消耗大,如果容器数量规模大,特别是采用微服务架构后,大量的容器IP资源被消耗,且可能出现大量IP冲击到路由表里,导致路由效率降低等问题;
容器平台外部对容器网络中网络实体的变化仍不能感知,例如新的容器创建或发生跨主机迁移时,以Calico方案为例,Felix和BGP client模块可以保证容器网络内的路由策略更新,但由于容器平台外界不能感知容器的变化,外部到此新创建容器的路由则没办法被自动创建,仍然需要额外的路由更新工作补充。
@Steven99 软件架构设计师:
容器虚拟化网络方案,总体分为2种截然不同的发展路线:基于隧道、基于路由。下面分别说一下这两种思路的原理,以及和flannel、calico的关系。
基于隧道
隧道方案最具普适性,在任何网络环境下都可以正常工作,这与它的原理密不可分。
最常见的隧道方案是flannel vxlan模式,以及calico的ipip模式,其核心原理包含了2个部分。
分配网段
每台宿主机上都有网络插件的agent进程,它们连接到etcd集中式存储,从虚拟IP池中申请一个IP段占位己有。宿主机上每个容器则从IP段中分配得到1个虚拟IP。
封装/解封
当不同宿主机上的容器互相访问时,数据包的源IP和目标IP都是容器IP。
数据包经过宿主机的agent进程进行封装后,新数据包的源IP和目标IP则变成了两端宿主机的物理IP。
数据包送到目标宿主机后,经过agent解封后得到原始数据包,并将数据包送入容器中处理,这就给两端容器营造了一种互通的感觉。
因为物理IP属于3层网络,可以在互联网中经过中间路由设备互相送达,所以隧道方案对宿主机之间的网络环境没有特殊要求,因此隧道方案具备普适性。
优势就是对物理网络环境没有特殊要求,只要宿主机IP层可以路由互通即可。
劣势就是性能差,这需要从2方面看:
封包和解包耗费CPU性能。
额外的封装导致带宽浪费,大约有30%左右的带宽损耗 flannel vxlan和calico ipip模式都是隧道方案,但是calico的封装协议IPIP的header更小,所以性能比flannel vxlan要好一点点。
基于路由
路由方案性能最好,原因是该方案不需要封包和解包,所以没有隧道方案的劣势,网络性能很好。
常见的路由方案包括了flannel的host-gw模式,以及calico的bgp模式。
下面以calico bpg模式为例,分析基于路由的方案原理,其包含了3个部分。
分配网段
每台宿主机也有agent,会从etcd中的虚拟IP池分配到一个IP子网段。宿主机上每个容器则从该IP段中分配得到1个虚拟IP。
本地路由
假设我们在宿主机A上新建了一个容器,则该容器分配了一个虚拟IP,我们假设它是值是k。
agent会在本机配置一条路由规则,即:如果数据包的目标地址等于k,那么把数据包送到容器的虚拟网卡上。
另外一台宿主机B上的一个容器,其IP是m,向k容器发数据包,则数据包的目标地址是k,原地址是m。
既然路由方案是不使用隧道封包为物理IP在网络中流通的,那么该数据包又该如何送达到虚拟IP k呢?
广播路由
路由方案会采用如下的手段,搞定m到k的虚拟IP互通问题。
即宿主机A会通过某种方式(比如BGP广播协议)把自己的虚拟IP网段广播给宿主机B。
在宿主机B收到广播后,会给本机配置一条路由规则:如果数据包的目标地址属于宿主机A的虚拟IP网段,则把该数据包发给宿主机A的物理IP。
这条路由规则相当于为宿主机A的虚拟IP网段配置了转发网关,而这个网关就是宿主机A的物理IP。
这就要求,宿主机B和宿主机A在2层网络是互通的,也就是它们在一个交换机下面,可以基于MAC地址直接互通。
一旦该数据包被送往宿主机A的物理IP,则宿主机A就可以应用刚才讲过的” 本地路由 “规则了,即:数据包的目标IP是k,直接送给对应容器的虚拟网卡。
我们发现,整个过程中从m发往k的数据包采用的都是虚拟容器IP,没有经过任何封装和解封,而仅仅是通过宿主机A的本地路由+宿主机B收到的广播路由,就 实现了在2层网络互通环境下的高效通讯 。
优势就是没有封包和解包过程,完全基于两端宿主机的路由表进行转发。
劣势包含2方面:
要求宿主机处于同一个2层网络下,也就是连在一台交换机上,这样才能基于MAC通讯,而不需要在IP上动封包/解包的手脚。
路由表膨胀导致性能降低,因为宿主机上每个容器需要在本机添加一条路由规则,而不同宿主机之间需要广播自己的网段路由规则。
@花花世界 小太阳 系统架构师:
Flannel:
由CoreOS开发的项目Flannel,可能是最直接和最受欢迎的CNI插件。它是容器编排系统中最成熟的网络结构示例之一,旨在实现更好的容器间和主机间网络。随着CNI概念的兴起,Flannel CNI插件算是早期的入门。
与其他方案相比,Flannel相对容易安装和配置。它被打包为单个二进制文件FlannelD,许多常见的Kubernetes集群部署工具和许多Kubernetes发行版都可以默认安装Flannel。Flannel可以使用Kubernetes集群的现有etcd集群来使用API存储其状态信息,因此不需要专用的数据存储。
Flannel配置第3层IPv4 Overlay网络。它会创建一个大型内部网络,跨越集群中每个节点。在此Overlay网络中,每个节点都有一个子网,用于在内部分配IP地址。在配置Pod时,每个节点上的Docker桥接口都会为每个新容器分配一个地址。同一主机中的Pod可以使用Docker桥接进行通信,而不同主机上的pod会使用flanneld将其流量封装在UDP数据包中,以便路由到适当的目标。
Flannel有几种不同类型的后端可用于封装和路由。默认和推荐的方法是使用VXLAN,因为VXLAN性能更良好并且需要的手动干预更少。
总的来说,Flannel是大多数用户的不错选择。从管理角度来看,它提供了一个简单的网络模型,用户只需要一些基础知识,就可以设置适合大多数用例的环境。一般来说,在初期使用Flannel是一个稳妥安全的选择,直到你开始需要一些它无法提供的东西。
Calico:
Calico是Kubernetes生态系统中另一种流行的网络选择。虽然Flannel被公认为是最简单的选择,但Calico以其性能、灵活性而闻名。Calico的功能更为全面,不仅提供主机和pod之间的网络连接,还涉及网络安全和管理。Calico CNI插件在CNI框架内封装了Calico的功能。
在满足系统要求的新配置的Kubernetes集群上,用户可以通过应用单个manifest文件快速部署Calico。如果您对Calico的可选网络策略功能感兴趣,可以向集群应用其他manifest,来启用这些功能。
尽管部署Calico所需的操作看起来相当简单,但它创建的网络环境同时具有简单和复杂的属性。与Flannel不同,Calico不使用overlay网络。相反,Calico配置第3层网络,该网络使用BGP路由协议在主机之间路由数据包。这意味着在主机之间移动时,不需要将数据包包装在额外的封装层中。BGP路由机制可以本地引导数据包,而无需额外在流量层中打包流量。
除了性能优势之外,在出现网络问题时,用户还可以用更常规的方法进行故障排除。虽然使用VXLAN等技术进行封装也是一个不错的解决方案,但该过程处理数据包的方式同场难以追踪。使用Calico,标准调试工具可以访问与简单环境中相同的信息,从而使更多开发人员和管理员更容易理解行为。
除了网络连接外,C���,����alico还以其先进的网络功能而闻名。网络策略是其最受追捧的功能之一。此外,Calico还可以与服务网格Istio集成,以便在服务网格层和网络基础架构层中解释和实施集群内工作负载的策略。这意味着用户可以配置强大的规则,描述Pod应如何发送和接受流量,提高安全性并控制网络环境。
如果对你的环境而言,支持网络策略是非常重要的一点,而且你对其他性能和功能也有需求,那么Calico会是一个理想的选择。