kube-proxy と呼ばれる長期間有効なプロセスに Kubernetes の一部であるという問題があります。
問題は、接続が時々FIN_WAIT2状態のままになることです。
$ Sudo netstat -tpn | grep FIN_WAIT2
tcp6 0 0 10.244.0.1:33132 10.244.0.35:48936 FIN_WAIT2 14125/kube-proxy
tcp6 0 0 10.244.0.1:48340 10.244.0.35:56339 FIN_WAIT2 14125/kube-proxy
tcp6 0 0 10.244.0.1:52619 10.244.0.35:57859 FIN_WAIT2 14125/kube-proxy
tcp6 0 0 10.244.0.1:33132 10.244.0.50:36466 FIN_WAIT2 14125/kube-proxy
これらの接続は時間の経過とともにスタックし、プロセスの誤動作を引き起こします。私はすでに 問題を報告 をKubernetesバグトラッカーに報告しましたが、そのような接続がLinuxカーネルによって閉じられない理由を理解したいと思います。
その ドキュメント (tcp_fin_timeoutを検索)によると、FIN_WAIT2状態の接続は、X秒後にカーネルによって閉じられる必要があり、Xは/ procから読み取ることができます。私のマシンでは60に設定されています。
$ cat /proc/sys/net/ipv4/tcp_fin_timeout
60
だから私がそれを正しく理解すれば、そのような接続は60秒までに閉じられるべきです。しかし、これはそうではありません、彼らは何時間もそのような状態に置かれています。
私はFIN_WAIT2接続がかなり異常であることも理解していますが(ホストが接続のリモートエンドからのACKを待っていることを意味します)、これらの接続がシステムによって「閉じられない」理由がわかりません。
何かできることはありますか?
関連プロセスの再起動は最後の手段であることに注意してください。
カーネルタイムアウトは、接続が孤立している場合にのみ適用されます。接続がまだソケットに接続されている場合、そのソケットを所有するプログラムは、接続のシャットダウンのタイムアウトを担当します。おそらくshutdown
を呼び出し、接続が完全にシャットダウンするのを待っています。シャットダウンが完了するまで、アプリケーションは必要に応じて待機できます。
典型的なクリーンシャットダウンフローは次のようになります。
アプリケーションは接続をシャットダウンすることを決定し、接続の書き込み側をシャットダウンします。
アプリケーションは、相手側が接続の半分をシャットダウンするのを待ちます。
アプリケーションは、接続の相手側のシャットダウンを検出し、ソケットを閉じます。
アプリケーションは、必要なだけステップ2で待機できます。
アプリケーションにはタイムアウトが必要なようです。接続をシャットダウンすることを決定すると、妥当な時間の後に相手側が完全にシャットダウンするのを待つことをあきらめる必要があります。
ソケットがshutdown()であるが、まだclose()ではない場合、ソケットはFIN_WAIT2状態のままになります。そして、アプリケーションはまだファイル記述子を所有しているので、カーネルがクリーンアップを行う必要はありません。