本文主要介紹ECS執行個體中的應用偶爾出現丟包現象並且核心日誌(dmesg)存在“kernel: nf_conntrack: table full, dropping packet”報錯資訊的原因以及解決方案。
問題描述
串連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協議“established connection”記錄,當這個雜湊表滿之後,新的串連會引發“nf_conntrack: table full, dropping packet
”錯誤。關於nf_conntrack模組中的重要參數,可參考如下資訊。
nf_conntrack_buckets
:雜湊表的大小,可在模組載入時指定參數,也可以通過sysctl
命令修改。當系統記憶體大於等於4GB時,它的預設值是“65536”。nf_conntrack_max
:雜湊表的最大節點個數,即nf_conntrack模組支援的最大串連數。當系統記憶體大於等於4G時,它的預設值是“262144”。對於處理大量已連線的服務器來說,該預設值相對較小。nf_conntrack_tcp_timeout_time_wait
:nf_conntrack模組中儲存time_wait狀態的TCP連線時間,預設值為“120s”。
解決方案
請您結合現場實際情況,從如下兩種解決方案中選擇最適合您業務情境的方法。
方案一:通過sysctl介面調整nf_conntrack模組中的參數值
業務側應提前自行確認應用程式可能使用的nf_conntrack最大串連數,並參考如下命令,通過sysctl介面調整nf_conntrack模組中的參數值。
如果您的業務本身符合“並發串連數較高,其中主要是短串連”的特性。建議增大nf_conntrack_max
和nf_conntrack_buckets
的參數值,以確保不會由於串連數過多導致nf_conntrack的雜湊表滿。一般建議nf_conntrack_max
參數值為nf_conntrack_buckets
參數值的4倍 。
sudo sysctl -w net.netfilter.nf_conntrack_max=1503232
sudo sysctl -w net.netfilter.nf_conntrack_buckets=375808 # 如果使用非4.19核心,該選項可能無法在運行時修改
sudo sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=60
命令中的參數值僅供參考,現場請結合實際業務情況進行調整。在調整前,建議提前建立快照或備份重要檔案,確保資料安全。
建議一起調整
nf_conntrack_buckets
和nf_conntrack_max
參數。如果只改動nf_conntrack_max
參數值,可能會導致雜湊表上的鏈表過長,查詢效率低。如果只改動nf_conntrack_buckets
參數值,不能解決該問題。
方案二:通過iptables過濾不需要追蹤的串連
參考如下命令,在iptables規則中增加“-j notrack”的動作 ,即過濾不需要追蹤(track)的串連。該方式的好處是治本,可以將不需要追蹤的串連直接進行notrack處理,將不會佔用雜湊表的空間,也就不會引發報錯。
sudo iptables -t raw -A PREROUTING -p udp -j NOTRACK
sudo iptables -t raw -A PREROUTING -p tcp --dport 22 -j NOTRACK
此處的命令表示不追蹤UDP和22連接埠的TCP串連,僅供參考。現場以實際情況為準。