KUBERNETES /ドッキングウィンドウのネットワークのトラブルシューティング一度覚えておいてください
昨日、金曜日の夜、一時的な仕事、我々はユーザーに問題を報告したときに通常私たちは午後10時までの周りの17:30からフォローされている、私たちにヘルプを見てみましょう、比較的奇妙Kubernetesクラスタでネットワークにアクセスすることはできませんそう、ユーザーが問題を見つけることができるリモートコントロールのユーザーの場合は、リモートマシンにアクセスすることはできません。この問題は、私は個人的に、これらのコマンドとトラブルシューティングの調査に使用される方法のいくつかは、あなたと共有できることを感じて、かなり興味深いものですので、この記事を書きました。
問題の症状
マイクロ手紙のユーザーは、上記のサービスにアクセスすることができ、時には、時にはないアクセス、で、一定の確率があることを見出し、その後、ポッド調査を開く、彼らはKuberbnetes下のポッドに数百回あるいは数千を再起動されることがわかっていることを直接言いましたあなたはなぜ知らず、訪問することができません。そして、すべてではないポッドの問題はなく、1つまたは2つのポッド固有のネットワークアクセスが問題です。ユーザーは、このポッドは、ユーザーと、問題を除外するために、JavaのJavaプログラムを実行していると言う docker exec -it
も、同様の問題を発見したPythonのテストを開始し、直接SimpleHttpServerのコンテナにコマンド。
私たちは、おそらく、このバージョンのように、ユーザーのクラスタを知って、Kuberbnetes 1.7は、GWモード、ドッカーバージョン、未知のフランネルを使用したネットワークは、オペレーティングシステムのCentOS 7.4は、直接物理マシン上でドッキングウィンドウを実行している、物理的な構成が非常に高く、512ギガバイトのメモリ、いくつかありますCPUコア、ドッカーコンテナの何百もの上で実行されています。
問題のトラブルシューティング
問題の予備調査
クラスタ全体のネットワーク通信が正常であるので、まず第一に、私たちは、問題のフランネルを除外し、1つまたは2つのポッド固有の問題。そして、と telnet ip port
そこのコマンド手動テストネットワーク接続偉大な確率際に connection refused
、エラー、約1/4の確率、および例3/4が正しく接続されています。
受信されたその時、私たちはユーザーが参照するには、袋をつかむことができ、その後、ユーザーは、TCP接続の問題をキャッチしている SYN
、すぐに返さ、 RST, ACK
私は2人のIPユーザーが、知っている場所について尋ね10.233.14.129
市を docker0
、10.233.14.145
IPは、コンテナ内にあります。だから、基本的にドッカーのローカルネットワーク上の問題であり、すべての質問とkubernetsやフランネルを、除外です。
そのような物は直接リセットの場合で telnet
表示され connection refused
、私の個人的な経験のために、このエラーメッセージの SYN
完全な直接リターン RST, ACK
の条件は3つだけの事情があります。
- TCP接続は、接続を確立することができない理由は、本質的に完了することができない5タプルのTCPコネクション識別され、確立することができない、ほとんどの場合は、サーバのポート番号とは関係ありません。
- いくつか変更されたTCPパラメータ、特にこれらのパラメータは、デフォルトではオフになっているので、TCPのリンクが間違って構築され、それは、可能性があるため、不完全なTCPプロトコルにこれらのパラメータリードは。
- iptablesは含めて、設定をファイアウォール
REJECT
のルール。
赤色光は、私が感じたとき、彼女は、運転していたとき、NATネットワークサーバのようなビットが開いているため tcp_tw_recycle
と tcp_tw_reuse
病気の状態(「詳細を参照してくださいそれらのものTCP()には」)、そうしましょうユーザーが閲覧します我々は、質問TCPパラメータを除外してTCPパラメータには、我々が見つかりましたTCPパラメータのユーザーは、すべてのデフォルトを変更していません。
その後、私はコンテナ上iptablesの設定されます、そして、それは問題ではなく、良い時も悪いのは100%である場合とは思いません。だから、私は、コンテナのポート番号を聞いていないと思われるが、すぐに良い、これが問題のあるアプリケーションかもしれません。私はあそこに見えるように、ユーザーがアプリケーションのログを記録し、してみましょうする kublet describe
ような状況の実行を見て、見てのiptablesのホスト。
しかし、我々はすべての問題を見つけることができませんでした。この時、私たちは気持ちが上に行くことができない、すべての調査のリードを失った......
再ソート
今回は、自宅で、私たちは食べ終わって、電話を介してユーザは、より多くの重要な情報をユーザーに提供するために再カーディング、再び、この時間のすべての詳細は- 」でこの事を捕獲 docker0
缶に復帰へのコンテナ船を把握するために、しかし、キャッチ RST, ACK
「!しかし、私の知識によると、私が知っている docker0
と、コンテナ veth
カード上には、ネットワークデバイス間ではもはやありません(「参照ドッカー基本的な技術を:()でLINUX名前空間」)!
IPアドレスの競合 - だから我々は、ちょうど最後のケースにこの事を置きます!
LinuxのIPアドレスの競合を見てみると、単純な問題ではなく、ユーザーの生産環境では、いくつかの他のコマンドをインストールする方法はありません、我々は、この時間は、既存のコマンドを使用することができ、我々は、ユーザーのマシン上で発見した arping
、その後、私たちは、IPアドレスの衝突がない検出するために、このコマンドを使用します。次のコマンドを使用します。
1
2
|
$ arping -D -I docker0 -c 2 10.233.14.145
$
echo
$?
|
文書によると、-D
コマンドの退職状況がされている場合、パラメータは、IPアドレスの競合検出モードで 0
、その後矛盾があります。結果が返されます 1
。また、我々は使用 arping
異なるMACアドレスを見つからない場合はIPを。 今回は、手がかりの問題とは、壊れているようです。
顧客は我々が断続的例に働くので、いくつかの他のものに対処することが、まだですが、また、いくつかの作業を完了するために、ユーザーが必要なので、そのほとんど進展は遅いですが、私たちに考えるためにいくつかの時間を与えます。
ビスタ
今、私たちが知っている、IPの競合の可能性は非常に大きいですが、私たちが発見し、そのIP競合することはありません。そして、我々は一時的にこの問題を解決するために落ちたが、私たちはどのようにこの問題を知っていない場合は、このマシンを再起動する場合は、マシンを再起動することができますので、問題が出て解決しなければならないが、我々はこの問題を解決する方法はないことを感じていることを知っています起こり、その後、次の質問が再び来ます。そして、このコストが高すぎるオンラインマシンを再起動します。
だから、私たちの好奇心は、私たちは調査を続けています。私は、ユーザーせ kubectl delete
、すでにサービスがリブートし続けるので、2つの問題のポッドは、このように、削除する問題はありません。(1つのIP 2つのポッド後に削除 10.233.14.145
別です 10.233.14.137
)、私たちは他のマシン上のkubernetesは、2つのサービスの新しいインスタンスを再起動する、ことがわかりました。しかし、マシンの質問に、二人はIPアドレスは、実際に介して取得pingを実行することができます。
さて、問題はIPアドレスの競合を確認することができます。以来10.233.14.xxx
このセグメントドッキングウィンドウであるので、これは、このマシンのIPアドレスでなければなりません。そこで、我々は、すべてのネットワークの名前空間でのveth IPカードに表示したいと思います。
この問題に関連するコマンドはまた、非常に精通しているので、我々は、時間内にポイントを取ったので、私はGoogleのいくつかの時間を費やして、関連するマニュアルを見て。
- まず、我々はに行って
/var/run/netns
、何も見つからなかったシステムのネットワークの名前空間を、表示するディレクトリ。 - その後、我々はに行ってきました
/var/run/docker/netns
次のカタログドッカーの名前空間、より良い発見しました。 - したがって、我々はの場所を指定する方法でネットワークの名前空間ドッカーのIPアドレスを参照してください
これを使用するには nsenter
、コマンドを、このコマンドは、コマンドを実行するために、名前空間で入力することができます。そのようなものとして
1
|
$ nsenter --net=
/var/run/docker/netns/421bdb2accf1
ifconfig
-a
|
上記のコマンドへ var/run/docker/netns/421bdb2accf1
の実装におけるネットワークの名前空間 ifconfig -a
コマンド。だから我々は、すべてのネットワークの名前空間を横断する次のコマンドを使用することができます。
1
|
$
ls
/var/run/docker/netns
|
xargs
-I {} nsenter --net=
/var/run/docker/netns/
{} ip addr
|
その後、我々は比較的奇妙なことを発見しました。
10.233.14.145
私たちは、ドッキングウィンドウの名前空間だけでなく、IPの下で、このIP、説明を見つけました。10.233.14.137
このIPは、ネットワークの名前空間のドッキングウィンドウでは見られません。
漏れてあり、名前空間?私はバグドッキングウィンドウのを、インターネットをチェックし、見つけて-ドッキングウィンドウの削除で/何の適切なネットワークの名前空間がクリアされたときに、コンテナを停止していない、この問題があると報告されている #31597を発行 して固定し、その後 PR#31996、およびマージ17.05でのバージョンにドッカー。ユーザーのバージョンこの修正プログラムが含まれている必要があり、17.09です。それは、問題になることを感じ、他の場所に行くべきではありません。
しかし、 10.233.14.137
このIPのpingはIPが特定のネットワークカードに縛られ、ネットワークの名前空間の下に隠されていることを証明することによって得ることができます。
ここでは、すべてのネットワークの名前空間、最後のものだけの道を見て、それがすることです /proc/
すべてのPIDに入れディレクトリ、 /proc/<pid>/ns
網羅アウトするディレクトリ。幸いなことに、このことを行うことができ、より便利なコマンドがあります: lsns
だから私は、次のコマンドを書きました:
1
|
$ lsns -t net |
awk
‘{print $4}' |
xargs
-t -I {} nsenter -t {} -n ip addr |
grep
-C 4
"10.233.14.137"
|
説明してください。
lsns -t net
リストプロセスの開いているすべてのネットワークの名前空間を、そのPIDはプロセスであり、4- プロセスPIDアウトのすべてのネットワークの名前空間にオープンした、転送
xargs
コマンド xargs
コマンド今度はこれらのPIDを渡されたnsenter
コマンドを、xargs -t
それは私がPIDを知っているので、抜け出すために、関連するコマンドの実装を意味します。xargs -I {}
それは、関連するPIDを置き換えるためのプレースホルダを宣言することです
最後に、我々はものの、そのを見つけた /var/run/docker/netns
の下では見られない 10.233.14.137
が、 lsns
三つのプロセスを発見し、彼らが使用している10.233.14.137
このIP(競合あまり)、およびそのMACアドレスはすべて同じ!(不思議が見つかりませんARPを実行します)。することによりps
、コマンド、プロセスはこれら3で見つけることができ、2は、javaのものであり、1 /pause
(これはkubernetesサンドボックスでなければなりません)。
私たちはと、ホット追求で勝つために引き続きpstree
全体のプロセスツリーから抜け出すためのコマンド。私たちは、親プロセス3以上のプロセスが同じ呼び出しであることがわかった docker-contiane
プロセスで!
これはまだ明らかにドッキングウィンドウですが、中にdocker ps
道路が、適切な容器、どのような地獄を見つけることができませんでした!クイック崩壊......
プロセスツリーを見に進み、ことがわかった docker-contiane
親プロセスではありません dockerd
以下が、中に systemd
このスーパー親プロセスPID 1、私は頼ります!そして、我々は、このような野生プロセスの山を発見した(このフィールドプロセスまたはゾンビプロセスは、システムに有害であるか、彼らはまだリソースを占有しているため、少なくとも、サブの健康状態にシステムを作ります)。
docker-contiane
それはする必要があります dockerd
子プロセスがリンクしている pid 1
唯一の理由は、それが唯一の1時に養父のpidを見つけるために、親プロセス「飛ぶ」アウトです。このこのマシンに深刻ながあったことを示して dockerd
いるため、プロセスから撤退し、型破りな問題 systemd
の理由は、1 PIDになるために、それはすべてのプロセスの規制の子供や孫にあるが、それでも非常にことを示す、管理していませんでした問題の規制。(systemdにおよそ注、「参照LinuxのPID 1とにsystemdを 」、父と息子のプロセスについて何か、「プログラミング環境のUnixアドバンスド」ブックを参照してください)
次のステップは、見ている systemd
ため dockerd
(ただし、わずか3日間、3日間のログを記録......ログの記録dockerd
例外なし)
概要
今回の調査を通じて、我々はまとめることができ、
1)アンケート、知識の比較的強固な基盤については、問題の原因と程度を知っています。
2)あなたは慎重に細部を計量、手がかりのいくつかを詳しく見て振り返ってみると、再くしに、別の場所に行く場合。
3)をよりよく理解して診断ツールの様々な、それはあなたがより少ないと、より行うことができます。
4)プロセスまたは一部のごみシステムをゾンビ、これらのものは速やかに一掃されなければならないことが多いあなたはいくつかのものがあるかどうかを確認する必要があり、システムのメンテナンスとより類似したクリーニングを行います。
最後に、外観を言うために、多くの人々は、言う彼らは唯一のアカウントに運用および保守のコストをかけることなく、そのような512ギガバイトで数百のコンテナで起動し、アカウントにパフォーマンスのコストがかかるために実行するための物理マシン内ドッカーフィットが、これは、正確に右ではありませんゲームが再生され、これは大きな一つの本質であるので、それはあなたが重要なプロセスまたはマシンのいくつかを再起動する理由を持っているので、あなたの顔が巨大な影響力で、良いではありません。
-------- ---------更新2018年12月10日
問題の原因
自分の環境では二日、テストそれは、限り通じてことがわかっ systemctl start/stop docker
起動すると、停止コマンドなどドッカー、すべてのプロセスとリソースのすべてを取り除くことです。これは問題ありません。私は、ユーザの操作を再現することができます唯一の問題は、直接的である kill -9 <dockerd pid>
が、ユーザーはこのことを行うべきではありません。そして、することができますがドッカー衝突事象、systemdにあれば journalctl -u docker
、そのようなコマンドのシステムログを表示します。
だから、私はドッカーでの問題は、起動と停止を見つけるためにユーザーを探し、ユーザーが言うその実行 systemctl stop docker
このコマンドの時間は、このコマンドは発見に応答しない、押すことが可能である Ctrl +C
アップを!
これは、多数の原因でなければなりません docker-containe
にリンクされているプロセス PID 1
の次の原因。停止が時間を割いて、そのプロセスの木が非常に大きいので、私が思うに、単一の物理マシンのユーザーにコンテナの数百を実行し、前述したように、システムは、子プロセスへのすべてのドッキングウィンドウが髪を出て横断するでなければなりません信号は、このプロセスは非常に長くなることができます。装う死につながるオペレータコマンドが、プレス Ctrl + C
コンテナやプロセスの多くにつながるが、終了していません......
その他の事項
この記事では、私の書き込みがある理由のいくつかの学生が尋ね docker-containe
ていない containd
プロセス?これはある pstree
と、遮断する ps
コマンド全体、プロセス名の名前だけ見ることができる docker-
プレフィックスを。
ここで(異なるツリーインストールパッケージの2つのプロセス間の差である sleep
私が使用 buybox
ミラー活性化)は
1
2
3
4
5
6
|
systemd───dockerd─┬─docker-contained─┬─3*[docker-contained-shim─┬─
sleep
]
│ │ └─9*[{docker-containe}]]
│ ├─docker-contained-shim─┬─
sleep
│ │ └─10*[{docker-containe}]
│ └─14*[{docker-contained-shim}]
└─17*[{dockerd}]
|
1
2
3
4
5
6
|
systemd───dockerd─┬─containerd─┬─3*[containerd-shim─┬─
sleep
]
│ │ └─9*[{containerd-shim}]
│ ├─2*[containerd-shim─┬─
sleep
]
│ │ └─9*[{containerd-shim}]]
│ └─11*[{containerd}]
└─10*[{dockerd}]
|
ところで、ドッカー1.11バージョン以降、このモデルのようなドッカープロセスグループがトップを変更します。
dockerd
ドッカーEngineデーモン、ダイレクト・ツー・ユーザー操作があります。dockerd
あなたが起動したときにそれが開始されますcontainerd
彼らはRPCを介して通信する前に、子プロセスを。containerd
それはdockerd
とrunc
交換との間の中間部品。彼とdockerd
のデカップリングは、ドッカーは、より中立的になるようにすることです、そして標準OCIをサポートしています。containerd-shim
コンテナID、boundleディレクトリ(通常に位置コンテナ生成ディレクトリにcontainerdの対応、::実際にコンテナを実行するために使用され、各コンテナは、プロセスから新しいシムを開始します、それは主に3つのパラメータで指定されています/var/run/docker/libcontainerd/containerID
) 、と(デフォルトではコマンドを実行するrunc
コンテナを作成します)。docker-proxy
また、このプロセスは、ユーザーレベルのルーティングプロキシで、ドッカーの新バージョンでは、このプロセスを見ることができます。限り、あなたは使用してps -elf
、コマンドラインから抜け出すには、このコマンドを、あなたはそれがポートマッピングを行うことです見ることができます。あなたはこのプロキシを使用しない場合は、次のことができdockerd
、起動コマンドライン引数を追加します。--userland-proxy=false
このパラメータを。
詳細については、Googleが所有することができます。これは、二つの記事ことをお勧めします。