TT Lab
はじめる
学ぶ 学習パス コース

ネットワークトラブルシューティング

繋がらないという報告を四層に割る

TT Labで続きを見る

一言でいうと

ネットワーク障害の診断の90%は、どの層で止まったのかを最初に決めることで片づきます。層を決めずにツールを起動しても、時間が過ぎるだけです。

なぜ必要なのか

「APIにつながらない」という報告を受けると、人はたいてい次のように動きます。pingを打ち、ファイアウォールのルールを開き、DNSを確認し、アプリケーションのログをあさります。順序がありません。そのため同じ場所を2回見て、見ていない場所を見ないままにします。

熟練者は違います。まず層を特定します。そして、その層に合ったツールを1つだけ使います。

どう動くのか

実務で使う層は、OSIの7階層ではなく4つあれば十分です。

層 問い 確認ツール 失敗したときの顔
名前 この名前がどのIPに解決されるか getent hosts, dig, resolvectl query Name or service not known
到達 そのIPまでパケットが届くか ping, traceroute -U, ip route Network is unreachable、応答なし
ポート そのIPのそのポートが開いているか nc -zv, ss -ltn, curl --connect-timeout Connection refused / timed out
応答 開いているのに応答がおかしいか curl -v, curl -w, アプリケーションのログ 5xx、遅い、誤った本文

ポイントは、層ごとに失敗の顔が異なることです。その顔を正確に読むだけで、層が決まります。

errno別の判別表を覚えておけば、報告の文面を見ただけで層が分かれます。

メッセージ errno 実際に起きたこと 最初に見る場所
Name or service not known EAI_NONAME 名前解決で失敗しました。ソケットを開くこともできませんでした nsswitch.conf、resolv.conf、/etc/hosts
Network is unreachable ENETUNREACH ルーティングテーブルに経路がありません ip route、特にIPv6の経路
No route to host EHOSTUNREACH ICMP unreachableを受信したか、ARPに応答がありません 宛先の電源、ARP、REJECTルール
Connection refused ECONNREFUSED 宛先がRSTを返しました 宛先ホストのプロセスとバインドアドレス
Connection timed out ETIMEDOUT SYNをすべて再送しても応答がありませんでした ファイアウォールのDROP、セキュリティグループ、acceptキュー

ここで最もよく間違えるのが、refusedをファイアウォールのせいにすることです。refusedはRSTを受け取ったという意味で、RSTを受け取ったなら、ルーティング・セキュリティグループ・NAT・ネットワークポリシーをすでにすべて通過した証拠です。実務のファイアウォールはほぼ常にDROPポリシーなので、塞がれたポートはtimeoutとして現れます。refusedを見てファイアウォールを調べるのは、すでに通過したゲートをもう一度確認することです。

時間も証拠です。Linuxのデフォルト値(net.ipv4.tcp_syn_retries=6)では、応答のない接続は1+2+4+8+16+32+64 = 127秒であきらめます。アプリケーションのタイムアウトが30秒と書かれているのに実際には127秒で失敗したなら、そのタイムアウト設定が適用されていないというサインです。

現場での姿

「ローカルでは動くのに、リモートからだけ動かない」。 十中八九、バインドアドレスの問題です。ss -ltnpで127.0.0.1:8080をリッスンしていると、Pod IPに来る接続はカーネルがRSTで拒否します。つまりrefusedです。逆にPod IPに対してもtimeoutになるなら、そこからネットワークポリシーを見ます。この1回の切り分けで、調査範囲が半分になります。

次にすること

最も下の層である名前解決から始めます。/etc/hostsとnsswitch.confがなぜdigより先なのか、そしてなぜdigはその両方をまったく見ないのかを、手で確認します。