web-dev-qa-db-ja.com

FIN_WAIT2状態の接続がLinuxカーネルによって閉じられないのはなぜですか?

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を待っていることを意味します)、これらの接続がシステムによって「閉じられない」理由がわかりません。

何かできることはありますか?

関連プロセスの再起動は最後の手段であることに注意してください。

11
Adam Romanek

カーネルタイムアウトは、接続が孤立している場合にのみ適用されます。接続がまだソケットに接続されている場合、そのソケットを所有するプログラムは、接続のシャットダウンのタイムアウトを担当します。おそらくshutdownを呼び出し、接続が完全にシャットダウンするのを待っています。シャットダウンが完了するまで、アプリケーションは必要に応じて待機できます。

典型的なクリーンシャットダウンフローは次のようになります。

  1. アプリケーションは接続をシャットダウンすることを決定し、接続の書き込み側をシャットダウンします。

  2. アプリケーションは、相手側が接続の半分をシャットダウンするのを待ちます。

  3. アプリケーションは、接続の相手側のシャットダウンを検出し、ソケットを閉じます。

アプリケーションは、必要なだけステップ2で待機できます。

アプリケーションにはタイムアウトが必要なようです。接続をシャットダウンすることを決定すると、妥当な時間の後に相手側が完全にシャットダウンするのを待つことをあきらめる必要があります。

14
David Schwartz

ソケットがshutdown()であるが、まだclose()ではない場合、ソケットはFIN_WAIT2状態のままになります。そして、アプリケーションはまだファイル記述子を所有しているので、カーネルがクリーンアップを行う必要はありません。

2
L. Yan