パケットはどうやって道を選ぶのか
一言でいうと
ホストは、宛先が自分のサブネット内なら直接、外ならデフォルトゲートウェイへ送ります。ルーティングテーブルはその判断ルールの一覧で、最も長いプレフィックスが勝ちます。
なぜ必要なのか
「pingは通るのにつながらない」「特定の範囲だけつながらない」といった報告は、たいていルーティングから出てきます。ところが、ルーティングテーブルの読み方を知らないと、何を見ればよいのかさえわかりません。
どう動くのか
ip route
# default via 192.168.219.1 dev eth0
# 10.244.0.0/16 dev cilium_host scope link
# 192.168.219.0/24 dev eth0 proto kernel scope link src 192.168.219.50
3行の意味は次のとおりです。
192.168.219.0/24 dev eth0: この範囲は直接つながっています。ARPで相手のMACを探して、すぐに送ります。10.244.0.0/16 dev cilium_host: Podの範囲はciliumインターフェースへ。default via 192.168.219.1: 残りはすべてゲートウェイに任せます。
宛先が複数の行に当てはまる場合は、最も長いプレフィックスが勝ちます。10.244.1.5はdefault(/0)と10.244.0.0/16の両方に合いますが、/16のほうが長いので勝ちます。これを最長プレフィックス一致(longest prefix match)といいます。
特定の宛先の実際の経路は、尋ねればわかります。
ip route get 8.8.8.8
ip route get 10.244.1.5
このコマンドは、カーネルに「このアドレスへ送るとどこから出るか」を直接尋ねます。テーブルを目で読んで推論するより正確です。
ルーティングを読む順序
ip routeの一覧を上から読んではいけません。カーネルは最も長いプレフィックス(most-specific)を先に選びます。同じ長さなら、metricが小さいものを使います。
10.0.5.0/24 dev eth1 ← /24. 10.0.5.7 은 여기로
10.0.0.0/8 via 10.0.0.1 dev eth0 ← /8. 10.0.5.7 도 여기 포함되지만 진다
default via 192.168.1.1 dev eth0 ← /0. 아무 데도 안 맞을 때
一覧を目で追う代わりに、カーネルに直接尋ねるほうが確実です。
ip route get 10.0.5.7
10.0.5.7 dev eth1 src 10.0.5.2 uid 1000
srcが重要です。出ていくインターフェースが決まると、送信元IPも一緒に決まり、そのアドレスが相手のファイアウォールで許可されていなければ、通信できません。「自分のIPは203.xなのに、なぜ10.xで出ていくのか」のような問題が、ここで見つかります。
ルール → テーブル → 経路
Linuxにはルーティングテーブルが複数あり、どれを見るかはip ruleが決めます。
ip rule show
0: from all lookup local ← 자기 주소. 건드리지 않는다
32766: from all lookup main ← ip route 가 기본으로 보여 주는 것
32767: from all lookup default
VPN・マルチ回線・ポリシールーティングでは、ここにルールが追加されます。
100: from 10.8.0.0/24 lookup vpn ← VPN 대역은 다른 테이블을 본다
この場合、ip route(mainテーブル)だけを見ると、「設定は合っているのに出ていかない」状態になります。ip route show table vpnで、そのテーブルを別に見る必要があります。ルールは番号が小さいものから評価され、最初に合ったルールのテーブルを使います。
ARPとネイバーキャッシュ
同じサブネット内なら、ルーターを経由せずにMACアドレスで直接送ります。その対応表がネイバーキャッシュです。
ip neigh show
10.0.5.1 dev eth1 lladdr 00:1a:2b:3c:4d:5e REACHABLE
10.0.5.9 dev eth1 FAILED ← 응답이 없다
FAILEDは、そのIPを持つ機器がない、または応答しないという意味です。ルーティングは合っているのに通信できないとき、ここを見ます。IPを移した直後は、古いMACがキャッシュに残って、数分間つながらないこともあります。ip neigh flush dev eth1で消します。
よくある勘違い
ゲートウェイは同じサブネットにある必要があります。デフォルトゲートウェイはARPで探す必要があるので、必ず直接つながっている範囲の中にある必要があります。別の範囲のアドレスをゲートウェイに入れると、Network is unreachableになります。
pingが通ればネットワークは正常だという勘違い。pingはICMPで、サービスはTCPです。ファイアウォールがICMPだけを開けていると、pingは通ってもつながりません。逆に、ICMPだけを塞いでいると、pingは通らないのにサービスは問題なく動きます。
実務で本当に大切なこと
コンテナの中でip routeを見ると、たいてい次のように単純です。
default via 10.244.1.1 dev eth0
10.244.1.0/24 dev eth0
Podは自分のノードのゲートウェイしか知りません。別のノードのPodへ行く道は、ノードが知っています。そのため、Pod間の通信ができないときは、Podの中ではなく、ノードのルーティングとCNIを見る必要があります。
Linuxにはテーブルが複数あり、ip ruleがどのテーブルを見るかを決めます。VPNやマルチ回線の環境で、「ルーティングテーブルは合っているのに出ていかない」なら、ip ruleを見る必要があります。