クラスター内に、syslogで大量の「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
では、カウントが最大値よりはるかに少ないのに、なぜパケットをドロップするのでしょうか。
しばらく前にSquidシステムで同じ問題が発生しました。
Conntrackのサイズを減らすために私が見つけた最も効果的な方法の1つは、カーネルのデフォルトの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カウントは数日にわたって着実に減少していました。
Conntrackテーブルのカウントと最大設定をどのように確認したかはわかりませんが、値を取得するためにsysctl netfilter.nf_conntrack_max
とsysctl net.netfilter.nf_conntrack_count
を使用しました。