本站总访问量 Linux Conntrack为什么会崩溃并避免问题 - Jerry的小站

Jerry Gao

上帝就是真理,真理就是上帝

文章信息

作者:Alex Pollitt
原文https://www.tigera.io/blog/when-linux-conntrack-is-no-longer-your-friend/

连接跟踪(“conntrack”)是Linux内核网络堆栈的核心功能。它允许内核跟踪所有逻辑网络连接或流,从而识别构成每个流的所有数据包,以便可以一致的处理它们。

Conntrack是一个重要的内核特性,它支持一些关键的主线用例:

  • NAT依赖于连接跟踪信息,因此它可以以相同的方式转换流中的所有数据包。例如当pod访问kubernetes服务时,kube-proxy的负载均衡使用NAT将连接重定向到特定的后端pod。Conntrack记录对于特定连接,发往服务IP的数据包应该全部发送到同一个后端Pod,并且从后端pod返回的数据包未经NAT回到源pod。
  • 有状态的防火墙,例如Calico,依靠连接跟踪信息来精确将“响应”流量列入白名单。这允许您编写一个网络策略,上面写着“允许我的pod连接到任何远程IP”,而无需编写策略来明确允许响应流量。(否则,将不得不提娜佳更不安全的规则“允许任何IP到我的pod的数据包”)

此外conntrack通常会提高性能(减少CPU并减少数据包延迟),因为只有流中第一个数据包需要经过完整网络对战处理才能确定如何处理它。有关此操作的一个示例,请参阅“comparing kube-proxy modes”博客。

可是,conntrack有它自己的限制…

它在哪里崩溃

conntrack表有一个可配置的最大大小,如果它被填满,连接通常会开始拒绝或丢弃。对于大多数工作负载,表有足够的空间,这永远不会成为问题。但是在某些情况下,需要对conntrack表进行更多的考虑:

  • 最明显的情况是,服务器处理极高数量的同时活动的连接。例如,如果你的conntrack表配置为128k条目,但是有超过128k的同时连接,肯定会遇到问题。
  • 稍微不那么明显的情况是,服务器每秒处理非常多的连接数。即使连接是短暂的,Linux也会在很短的超时时间内(默认为120秒)继续跟踪链接。例如如果您的conntrack表配置为128k条目,并且您尝试每秒处理1100个连接,那么即使连接时间非常短暂(128k / 120s = 1092个连接/s)

有一些小众的工作负载属于这种类型。此外如果你出在一个敌对的环境中,那么用大量的半开放连接来淹没你的服务器,可以作为一种拒绝服务的攻击。在这里两种情况下,通过增加conntrack表的大小或减少conntrack超时,调整conntrack可能足以满足你的需求,但是如果你把调整弄错了,会导致很多痛苦。对于其他情况,你需要绕过conntrack来处理违规的流量。

一个真实的例子

与我们合作的一个大型Saas供应商有一组运行在裸机服务器上的memcached服务器(没有虚拟化或容器化),每个服务器每秒处理5万多个短时连接。这远远超过了标准Linux配置所能应付的范围。
他们曾尝试调整conntrack配置以增加表大小并减少超时,但调整很脆弱,增加的RAM使用是一个重大损失(想想GBytes),而且连接是如此的短暂,以至于conntrack没有提供其通常的性能优势(减少CPU或数据包延迟)。
相反,他们转向了Calico。Calico的网络策略允许绕过特定流量的conntrack(使用doNotTrack的标志)。为他们提供了所需的性能,以及Calico带来的额外安全优势。

绕过conntrack的取舍是什么?

  • 不跟踪网络策略通常是对称的。在saas提供商的案例中,他们的工作负载是内部的,因此使用网络策略,他们可以非常狭隘地将允许访问memcached服务的所有工作负载的往来流量列为白名单
  • 不跟踪策略对连接的方向是无视的。所以在memcached服务器被攻击的情况下,理论上可以尝试连接到任何memcached客户端,只要它使用正确的源端口。然而,假设你为你的memcached客户端正确定义了网络策略,那么这些链接尝试仍在客户端被拒绝。
  • 不跟踪网络策略适用于每个数据包,而正常的网络策略只适用于流中的第一个数据包。这可能会增加每个数据包的CPU成本,因为每个数据包都需要被网络策略处理。但是对于短暂的连接,这种额外的处理会被连通性处理的减少所抵消。例如,在saas供应上的案例中,每个连接中的数据包数量非常少,因此将策略应用于每个数据包的额外开销是一个合理的权衡。

进行测试

我们测试了单个memcached服务器pod和在远程节点上运行的多个客户端pod,因此我们可以每秒驱动非常高的连接。memcached服务器pod主机有8个内核和一个512k的conntrack表。我们测量了以下之间的性能差异:没有网络策略、Calico正常网络策略和Calico不跟踪网络策略。
在第一次测试中,我们将连接数限制在每秒4000个,这样我们就可以关注CPU的差异。没有策略和正常策略在性能上没有可衡量的差异,但不跟踪策略使得CPU使用率降低了约20%。

在第二个测试中,我们推送了我们的客户所能容纳的尽可能多的连接,并测量了memcached服务器每秒能够处理的最大连接数。正如预期那样,无策略和正常策略都在每秒4000多个连接数上达到conntrack表的限制(512k / 120s = 4396个连接/s)。有了不跟踪策略,我们的客户端每秒推送了60000个连接而没有遇到任何问题。我们相信我们可以通过吸引更多的客户来超越这个数字,但是我们觉得这些数字足以说明这篇博客的意义了。

结论

Conntrack是一个重要的内核特性。它做的很出色。许多主线用例都依赖它。然而对于某些小众的场景,conntrack的开销超过了它带来的正常好处。在这些场景中,Calico的网络策略可以用来有选择的绕过conntrack,同时仍然执行网络安全。对于所有的其他流量,conntrack仍然是你的朋友。

评论