比较kube-proxy模式 iptables或IPVS? - tigera
2020-07-12 tech network linux 11 mins 8 图 4116 字
这是calico母公司的一篇分享博客。讲得挺好,转载过来。机翻警告⚠️
kube-proxy 是 Kubernetes部署的关键组件。它的作用是使发往service 的流量(通过群集IP和节点端口)负载均衡到正确的后端 Pod。Kube-proxy可以三种模式之一运行,每种模式都使用不同的数据平面技术实现: userspace, iptables或 IPVS。
userspace非常陈旧,缓慢,不建议使用!但是,如何权衡使用iptables还是IPVS模式呢?在本文中,我们将比较两者,评估它们在真正的微服务环境中的性能,并解释何时选择一个与另一个。
首先,我们将从两种模式的背景知识入手,然后深入了解下面的测试和结果…
背景:iptables代理模式
iptables是一种Linux内核功能,旨在成为高效的防火墙,并具有足够的灵活性来处理各种常见的数据包操作和过滤需求。它允许将灵活的规则序列附加到内核的数据包处理管道中的各种钩子上。在iptables模式下,kube-proxy 将规则附加到“ NAT pre-routing” 钩子上以实现 NAT和负载平衡功能。它的工作原理很简单,并且与其他也使用 iptables 进行过滤的程序(例如Calico!)一同运行而不互相影响。
但是,kube-proxy 下增加的iptables条目空间复杂度是 O(n),条目数在 service的数量和每个 service 背后的 Pod的数量增长而成比例地增长。
背景:IPVS代理模式
IPVS是专门用于负载平衡的Linux内核功能。在IPVS模式下,kube-proxy 对IPVS负载均衡器进行编程,而不是使用iptables。IPVS 专 为负载均衡大量服务而设计;它优化了API和查找目标的方式,而不是顺序查找。
IPVS模式下的kube-proxy的连接处理的计算复杂度为O(1)。换句话说,在大多数情况下,其连接处理性能将保持恒定,与群集大小无关。
此外,作为专用的负载平衡器,IPVS拥有多种不同的调度算法,例如循环调度,最短期望延迟,最少连接和各种哈希方法。iptables 中的 kube-proxy 只能使用随机等价选择算法。
IPVS的一个潜在缺点是,与正常情况下的数据包相比,由IPVS处理的数据包通过iptables filter hooks的路径非常不同。如果您打算将IPVS与其他使用iptables的程序一起使用,则需要研究它们是否可以一起正常工作。
性能比较
名义上kube-proxy在iptables模式下的连接处理为O(n),在IPVS模式下为O(1)。但是,在微服务场景中的实际表现怎么样呢?
在大多数情况下,在应用程序和微服务的上下文中,当涉及到kube-proxy的性能时,您可能会关心两个关键属性:
- 对往返响应时间的影响。 当一个微服务对另一个微服务进行API调用时,第一个微服务平均向第二个微服务发送请求并从第二个微服务接收响应的时间为多长时间?
- 对总CPU使用率的影响。 在支持微服务(包括kube-proxy)所需的所有进程中,运行微服务时主机的总CPU使用量是多少,包括用户空间和内核/系统使用情况?
为了说明这一点,我们在专用节点上运行一个专门用来发请求的pod,它每秒生成1000个请求,所有的请求打到一个service上,这个service后边挂着10个pod。然后,我们在iptables和IPVS模式下,使用若干个的Kubernetes service(每个服务有10个Pod支持),最多10,000个service(带有100,000个endpoints)来测量客户端节点上的性能。对于微服务,我们使用了用golang编写的简单测试工具作为客户端微服务,并用标准NGINX作为服务器微服务的后端容器。
往返响应时间
考虑往返响应时间时,了解连接和请求之间的区别很重要。通常,大多数微服务将使用持久性或“ keepalive”连接,这意味着每个连接可在多个请求中重用,而不是每个请求都需要一个新的连接。这很重要,因为大多数新连接都需要通过网络进行三向TCP握手(这需要时间),Linux网络堆栈中的更多处理(这需要更多时间和CPU)。
为了说明这些差异,我们在有和没有保持连接的情况下进行了测试。对于保持连接,我们使用了NGINX的默认配置,该配置使每个连接保持活动状态,最多可重复使用100个请求。请参见下图,请注意,响应时间越短越好。
图表显示了两个关键事项:
- 在获得超过1,000个服务(10,000个后端Pod)之前,iptables和IPVS之间的平均往返响应时间的差异微不足道。
- 仅当不使用keepalive连接时,才能确定平均往返响应时间的差异。即当为每个请求使用新连接时。
对于iptables和IPVS模式,kube-proxy的响应时间开销与建立连接相关,而不是与您在这些连接上发送的数据包或请求的数量有关。这是因为Linux使用的连接跟踪(conntrack)能够非常有效地将数据包与现有连接进行匹配。如果数据包在conntrack中匹配,则无需通过kube-proxy的iptables或IPVS规则来确定如何处理它。Linux conntrack是您的朋友! (几乎所有时间……。请关注我们的下一篇博客文章“当Linux conntrack不是您的朋友时!”)
值得注意的是,在此示例中,对于“服务器”微服务,我们使用NGINX Pod服务于一个小的静态响应主体。许多微服务需要做的工作远远超过此,这将导致相应的响应时间更长,这意味着与该图表相比,用于kube-proxy处理的增量将占响应时间的百分比较小。
最后有一个奇怪的解释:如果IPVS中新连接的处理是O(1)复杂性,为什么在10,000个服务上IPVS的非Keepalive响应时间会变慢?我们需要做更多的挖掘工作才能真正深入了解此问题,但其中一个因素是,由于主机上CPU使用率的增加,整个系统的运行速度会变慢。这使我们很好地讨论了下一个主题。
总CPU
为了说明总的CPU使用率,下表重点介绍了不使用持久/ keepalive连接的最坏情况,在这种情况下,kube-proxy连接的处理开销影响最大。
图表显示了两个关键事项:
- iptables和IPVS之间的CPU使用率差异不明显,直到获得超过1,000个服务(带有10,000个后端Pod)为止。
- 在10,000个服务(具有100,000个后端pod)的情况下,使用iptables的CPU的增加量约为内核的35%,而使用IPVS的CPU的增加量约为内核的8%。
影响此CPU使用模式的主要因素有两个。
第一个贡献者是默认情况下,kube-proxy以30秒的间隔对所有服务进行内核重新编程。这解释了为什么IPVS模式在CPU上会略有增加,即使IPVS对新连接的处理名义上的复杂度为O(1)。此外,在较旧内核版本中对iptables进行重新编程的API比现在慢得多。因此,如果您在iptables模式下使用带有kube-proxy的较旧内核,则CPU增长将比该图表还要高。
第二个原因是kube-proxy使用iptables或IPVS处理新连接所花费的时间。对于iptables,名义上是O(n)。在大量服务中,这极大地影响了CPU使用率。例如,在10,000个服务(带有100,000个后端Pod)上,iptables为每个新连接执行约20,000个规则。请记住,尽管在此图表中,我们显示的是微服务的最坏情况,该微服务针对每个请求使用新的连接。如果我们使用NGINX的默认keepalive(每个连接100个请求),那么kube-proxy的iptables规则执行的频率将减少100倍,从而大大减少了使用iptables而不是IPVS可能对CPU造成的影响,降低到接近内核的2%。
值得注意的是,本示例中使用的“客户端”微服务只是丢弃了从“服务器”微服务收到的每个响应。真正的微服务将需要做的工作远不止于此,这将增加此图表中的基本CPU使用率,但不会改变与服务数量相关的CPU绝对增加量。
结论
kube-proxy的IPVS模式可扩展到超过1,000个服务,可以提供一些不错的性能改进。您的工作量可能会有所不同,但是作为一般指南,对于使用持久性“ keepalive”风格连接且在现代内核上运行的微服务,其收益可能相对较小。对于不使用持久连接的微服务,或者在较旧的内核上运行时,将kube-proxy切换到IPVS模式将是一个不错的选择。
与性能无关,如果您需要比kube-proxy的iptables模式随机负载平衡更复杂的负载平衡调度算法,则还应该考虑使用IPVS模式。
如果不确定IPVS是否会为您取胜,请在iptables模式下坚持使用kube-proxy。它在生产中进行了更多的强化,尽管它并不完美,但您可以说这是默认设置,这是有原因的。
后记:比较kube-proxy和Calico对iptables的使用
在本文中,我们已经看到kube-proxy对iptables的使用会如何在非常大的范围内导致性能影响。有时我会被问到为什么Calico没有同样的挑战。答案是,Calico对iptables的使用与kube-proxy的显着不同。Kube-proxy使用非常长的规则链,该规则链与群集大小大致成比例增长,而Calico使用非常短的优化规则链并广泛使用ipset,ipset的查找与大小无关。
为了更好地理解这一点,下表显示了kube-proxy与Calico每次连接执行的iptables规则的平均数量,假设集群中的节点平均托管30个Pod,集群中的每个Pod平均拥有3个网络策略适用于它。
即使在具有10,000个服务和100,000个后端Pod的完全扩展集群中运行时,Calico每个连接也只能执行与kube-proxy在200个后端Pod上执行20个服务时大致相同数量的iptables规则。换句话说,Calico对iptables的使用规模!