我们集群中有一个节点,它在系统日志中收到大量“nf_conntrack:表已满,丢弃数据包”消息。我检查了 nf_conntrack_count,发现它正好达到 nf_conntrack_max。查看表格后,我发现大多数条目都是 DNS 请求,因此我将这些规则添加到“原始”netfilter 表中。
$ sudo iptables -t raw -vnL
Chain PREROUTING (policy ACCEPT 146M packets, 19G bytes)
pkts bytes target prot opt in out source destination
33M 4144M CT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53 CT notrack
33M 2805M CT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 CT notrack
Chain OUTPUT (policy ACCEPT 73M packets, 8311M bytes)
pkts bytes target prot opt in out source destination
10785 882K CT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 CT notrack
0 0 CT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53 CT notrack
这使得计数徘徊在 13000 左右,并且 nf_conntrack_max 设置为 65535。但是我仍然不断收到丢弃数据包的消息。其余大部分数据包都是 UDP,我将 nf_conntrack_udp_timeout 设置为 1 秒,使 nf_conntrack_count 保持在 1000 左右。但是我仍然收到丢弃数据包的消息。
从这里开始,如果我提高最大值,它将停止丢弃数据包消息,但是我不明白为什么这是必要的。
我正在运行 docker,并且有一个 elasticsearch 容器(这个问题似乎发生在运行 elasticsearch 的任何节点上)。不确定这是否相关,但该节点有 48 个核心。
$ uname -a
Linux qtausc-pphd0128 3.19.0-26-generic #28~14.04.1-Ubuntu SMP Wed Aug 12 14:09:17 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
那么为什么当数量远小于最大值时会丢弃数据包?
答案1
不久前我在 Squid 系统上遇到了同样的问题。
我发现减少 conntrack 大小的最有效方法之一是减少内核中的默认 TCP 超时。
默认设置net.netfilter.nf_conntrack_tcp_timeout_established
为 432000。没错...也就是 5 天。
要设置该值,您可以发出以下命令;
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=X
如果您希望该更改持久化,则需要将该行添加到/etc/sysctl.conf
。
将该值降低到 600 后,conntrack 数量在几天内稳步下降。
我使用sysctl net.netfilter.nf_conntrack_max
和sysctl net.netfilter.nf_conntrack_count
来获取值。