問題の説明
ECSインスタンス上のアプリケーションに接続すると、パケット損失が発生することがあります。 ECSインスタンスの周辺ネットワークは、期待どおりに実行されます。 ただし、dmesgコマンドを実行してカーネルログを照会すると、「kernel: nf_conntrack: table full, dropping packet
」というエラーメッセージが表示されます。 問題が発生したECSインスタンスは、次の条件を満たしています。
画像:
aliyun-2.1903-x64-20G-alibase-20190327.vhd
以降カーネル:
Kernel-4.19.24-9.al7
以降
原因
nf_conntrackは、Linuxオペレーティングシステムの接続エントリを追跡するNATモジュールです。 nf_conntrackモジュールは、ハッシュテーブルを使用して、確立されたTCP接続を記録します。 ハッシュテーブル内のエントリが使い果たされると、新しいTCP接続の確立により、モジュールは「nf_conntrack: table full, dropping packet
」エラーを報告する。 nf_conntrackモジュールの次のパラメーターに注意してください。
nf_conntrack_buckets
: ハッシュテーブルのサイズ。 このパラメーターは、モジュールのロード時に指定したり、sysctl
コマンドを実行してパラメーターを変更したりできます。 システムメモリの容量が4 GB以上の場合、デフォルト値は65536です。nf_conntrack_max
: ハッシュテーブル内のノードの最大数。nf_conntrackモジュールでサポートされている接続の最大数です。 システムメモリの容量が4 GB以上の場合、デフォルト値は262144です。 多数の接続を処理するサーバーの場合は、ビジネス要件に基づいて値を増やすことができます。nf_conntrack_tcp_timeout_time_wait
: TCP接続がTIME_WAIT状態のままである期間で、nf_conntrackモジュールに保存されます。 デフォルト値は120です。 単位は秒です。
解決策
ビジネスシナリオに基づいて、次のいずれかのソリューションを使用します。
解決策1: sysctlインターフェイスを使用してnf_conntrackモジュールのパラメーター値を変更する
アプリケーションに必要なnf_conntrack_maxの値を事前に見積もり、sysctlコマンドを実行してnf_conntrackモジュールのパラメーター値を変更します。 サンプルコマンド:
sysctl -w net.netfilter.nf_conntrack_max=1503232
sysctl -w net.netfilter.nf_conntrack_buckets=375808 # This option cannot be modified during runtime if the kernel version is not 4.19.
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=60
コマンドのパラメータ値は、参照用にのみ提供されます。 ビジネス要件に基づいて値を変更します。 パラメーター値を変更する前に、ECSインスタンスのスナップショットを作成するか、重要なファイルをバックアップしてデータのセキュリティを確保することを推奨します。
パラメータ値を変更する方法に関する提案:
アプリケーションに多数の同時短期接続が含まれる場合は、パラメーター値を変更するときに次の提案に従います。nf_conntrackハッシュテーブルのエントリが過剰に接続されないようにするには、
nf_conntrack_max
およびnf_conntrack_buckets
パラメーターの値を増やすことを推奨します。 ほとんどの場合、nf_conntrack_max
パラメーターの値はnf_conntrack_buckets
パラメーターの値の4倍にすることを推奨します。nf_conntrack_buckets
パラメーターとnf_conntrack_max
パラメーターの値を一緒に変更することを推奨します。nf_conntrack_max
パラメーターの値のみを変更すると、ハッシュテーブルのリンクリストが長くなり、クエリの効率が低下する可能性があります。nf_conntrack_buckets
パラメーターの値のみを変更した場合、前述のパケット廃棄の問題は引き続き発生します。nf_conntrack_tcp_timeout_time_wait
パラメーターの値を変更する前に、パラメーターの動作とパラメーター値の変更の影響を理解してください。 次に、アプリケーションシナリオとパフォーマンスモニタリングデータに基づいてパラメーター値を変更するように注意してください。 パラメータ値を変更するためのいくつかの提案は次のとおりです。webサーバーなど、短期間で多数の短期間の接続を処理する並行性の高いアプリケーションの場合、
nf_conntrack_tcp_timeout_time_wait
パラメーターを30や60などの小さな値に設定することを推奨します。 これにより、ポートリソースをより迅速に再利用でき、より多くの新しい接続がサポートされます。 ただし、アプリケーションが少量のデータまたは遅延の潜在的な再送信を許容できることを確認する必要があります。金融取引システムなど、アプリケーションに送信されるデータの整合性に関する厳しい要件がある場合は、
nf_conntrack_tcp_timeout_time_wait
パラメーターのデフォルト値を受け入れるか、デフォルト値に近い値にパラメーターを設定します。 これにより、すべてのデータパケットが期待どおりに送信されます。レイテンシが高い、または不安定なネットワークでは、
nf_conntrack_tcp_timeout_time_wait
パラメーターの値が小さいと、データ損失のリスクが高くなり、より大きな値が必要になる場合があります。
解決策2: Iptablesユーティリティを使用して、追跡する必要のない接続を除外
次のコマンドを実行して、-j NOTRACKパラメーターをIptablesルールに追加し、追跡する必要のない接続を除外します。 このメソッドは、追跡する必要のない接続のレコードをハッシュテーブルから削除し、過剰な接続が「kernel: nf_conntrack: table full、dropping packet」エラーを引き起こすのを防ぎます。
sudo iptables -t raw -A PREROUTING -p udp -j NOTRACK
sudo iptables -t raw -A PREROUTING -p tcp --dport 22 -j NOTRACK
上記のコマンドは参照用にのみ提供されています。 これらは、nf_conntrackモジュールがポート22を介してUDP接続およびTCP接続を追跡するのを防ぐために実行されます。 ビジネス要件に基づいてコマンドを変更できます。