web-dev-qa-db-ja.com

CoreOS:tcpdumpは不思議なことにネットワークの問題を解決します(過剰な数のソケットが使用されます)

今日はあなたにミステリーがあります。 AzureでCoreOS(2023.5.0/Linux 4.19.25-coreos)に基づく小さな3ノードのElasticsearchクラスターを実行します。 Elasticsearchは、ホストネットワークモードのDockerコンテナー内で実行されます。ほぼ完全にメンテナンスフリーで1年以上実行した後、マシンが非常に興味深い状態になるのを目にしてきました。

更新

この問題は、 Linuxカーネル のドライバーを修正することで解決しました。以下の回答を参照してください。

症状

基本的に、影響を受けるマシンと他の2つのノード間のネットワークが停止します。すべてが同じ仮想ネットワークと同じサブネット内にあり、通常、他のネットワークと通信できます。影響を受けるノードには、他のサブネット(sshで接続できます)および別のピアリングされた仮想ネットワークから到達できます。マシンはインターネットに(非常にむらがある)接続もありますが、ほとんどの要求はタイムアウトします。

影響を受けるノードでは、_/proc/net/sockstat_によって報告される「使用されるソケット」の数が非常に多いことがわかりました(正常なノードでは約300ではなく約4.5k)。監視は、この数がノードが利用できなくなった瞬間から急速に増加することを示しています。

面白いのは、これらの使用済みソケットのソースを特定できないように見えることです。

_# cat /proc/net/sockstat
sockets: used 4566
TCP: inuse 2 Orphan 0 tw 2 alloc 98 mem 4
UDP: inuse 1 mem 0
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

# cat /proc/net/sockstat6
TCP6: inuse 98
UDP6: inuse 1
UDPLITE6: inuse 0
RAW6: inuse 1
FRAG6: inuse 0 memory 0
_

それ以外はマシンは問題ないようです。疑わしいプロセスは実行されておらず、CPU使用率は最小限であり、使用可能なメモリが十分にあります。

「到達不能」にpingを送信するVMが同じサブネット内にある場合、EAGAINへのrecvmsg応答がいくつか発生し、次にENOBUFSに戻るfrom sendmsgstrace ping output here

(システムに変更を加える前に)追加の出力をいくつか収集し、このGistに投稿しました: https://Gist.github.com/privatwolke/e7e2e7eb0272787765f5d3726f37107c

分析

最初に容疑者はelasticsearchで、サーバー上で考えられるすべてのものをシャットダウンしようとしました。ただし、elasticsearchコンテナーをシャットダウンしても、使用済みのソケットは解放されません。すべてのCoreOS関連のプロセス(update-engine、locksmithdなど)、あるいはDockerランタイム全体またはAzure固有のものについても同様です。何も助けにならなかったようです。

しかし、今ではさらに奇妙になっています。何が起こっているのかを確認するために、マシンでtcpdumpを実行しようとしました。そして見よ:問題は自然に解決し、接続が回復した。私たちの理論は、tcpdumpがそれを解決するある種のシステムコールを行うというものでした。 gdbでtcpdumpを実行し、すべてのシステムコールにブレークポイントを設定しました。ブレークポイントの負荷をステップスルーした後、キャプチャソケット(特に libpcapのこの行 )で無差別モードを設定する動作が、使用されているソケットをリセットし、通常の状態に戻すものであることがわかりました状態。

追加の調査結果

  • _-p/--no-promiscuous-mode_フラグを使用してtcpdumpを実行しても、ソケット使用カウンタがクリアされず、マシンが使用可能な状態に戻らないことが確認されています。
  • _ifconfig eth0 txqueuelen 1001_を実行すると、sockets usedカウンターがリセットされますが、接続はnotに復元されます。
  • _ip link set eth0 promisc on_を使用して手動で無差別モードを設定しても、接続は復元されません。
    • _net.ipv4.xfrm4_gc_thresh_は32768に設定されており、少し増やしても問題は解決しません。

sockets used

私たちは、これと同じくらい困惑しているAzureと連絡を取ってきました。これは問題ではなく、単なる症状であることを理解しています。しかし、それは私がこれまでに見つけた唯一の具体的なものです。症状を理解することで、根本的な原因に近づくことができることを願っています。 Azureのネットワークインターフェイスは this network driver で実行されます。

たぶん、CoreOS /カーネルのせいですか?

タイムラインの観点から、問題はCoreOSが最新バージョンに自動更新した日である2019-03-11に始まりました。 リリースノートによる 、この更新には 4.15.23から4.19.25へのカーネル更新が含まれていました。変更ログを調べて、問題があるかどうかを確認しています。これまでのところ、hypervネットワークドライバーが ここ数か月の間にかなりの数の更新を受け取った であることを発見しましたが、そのすべてが4.19.25の一部であるとは限りません。 CoreOSが4.19.25に適用したパッチセットはそれほど印象的ではありません ですが、偽のnf_conntrack_ipv4モジュールを導入するパッチは新しいものです。

更新: カーネルに関連する可能性のあるパッチ?

助けて!

これまでのところ、私たちが持っている質問は次のとおりです。

  • この「使用されたソケット」メトリックが急上昇する原因は何ですか?私は kernel sources を読み、このメトリックは just a counter のようです。実際にどのような種類のソケットであるか、それらを作成したものは参照していません。

  • 数が約4.5kでフラットラインになるのはなぜですか?これを引き起こしているのはどの制限ですか?

  • カーネル4.14.96と4.19.25の間で何か重要な変更はありましたか?

  • Libpcapのsetsockopt()呼び出しが状態をリセットするのはなぜですか?

関連するCoreOSのバグ: https://github.com/coreos/bugs/issues/2572

14
Stephan Klein

これは、Linuxカーネルのhv_netsvcドライバーのバグが原因でした。これをマイクロソフトの開発者と解決し、上流で修正を適用することができました。

ここではコミットメッセージを引用します。問題を非常によくまとめています。

RX完了メッセージが原因でリングバッファがほぼいっぱいになると、TXパケットが「最低水準点」に到達し、キューが停止することがあります。 TX完了がキュー停止よりも早く到着した場合、ウェイクアップが失敗する可能性があります。

このパッチは、最後の保留パケットのチェックを移動して、EAGAINと成功の両方のケースをカバーするため、必要なときにキューが確実にウェイクアップされます。

今後の参考のために、これを修正するコミットは https://github.com/torvalds/linux/commit/6d9cfab853ca60b2f77b5e4c40443216988cba1f です。

0
Stephan Klein

まず、非常によく書かれた質問をありがとう!

あなたが説明した詳細レベルは非常に高く、あなたはすでにgdbレベルにいるので、私の答えはあまり役に立たないと思います。とにかく、ここで試してみます:

  • おそらく、すでにss -aeおよびlsof -n
  • これが発生した場合、dmesgは興味深いものを返しますか?
  • サーバーでiptablesを使用していますか?
  • Tcpdump以外の方法でプロミスキャスモードを設定した場合(たとえば、ip link set [interface] promisc on)、これも問題を解決しますか?
  • 疑わしいプロセス、ファイル、またはその他の奇妙なアクティビティをチェックしましたか?いくつかの招かれざる厄介なプロセスが自分自身を隠す影に潜んでいて、無差別モードが設定されているときはいつでも沈黙していると考えているだけですか?
  • Tcpdumpをバックグラウンドで実行したままにすると、この問題は再発しますか?

これがお役に立てば幸いです。

4