パケットはどこへ消えた?Calicoの「トンネル」と「SNAT」の裏側を紐解く
こんにちは!クラウドインフラの深淵を覗き込み、時にその複雑さに頭を抱えながらも、パケットの旅路を追いかけるのが大好きなSREです。
Kubernetesを使い始めると、必ず一度はぶつかる壁が「ネットワーク」ですよね。特にCalicoのような強力なCNI(コンテナネットワークインターフェース)を使っていると、BGPだのIP-in-IPだの、急に難解な用語が飛び交い始めます。
今回は、そんなCalicoの「トンネリング」と「SNAT」という、一見すると地味だけど実は非常に重要な仕組みについて、郵便配達に例えながら優しく解説していこうと思います。
—
郵便配達で考える「トンネリング」
まずは、PodからPodへ手紙(パケット)を届けるシーンを想像してみてください。
通常、クラスター内のPodは、クラスター固有の「専用住所(Pod IP)」を持っています。しかし、AWSやGCPのようなクラウドのネットワーク基盤は、この「専用住所」を直接知りません。クラウドから見れば、Podは「ノードという名のマンション」の中に隠れた住民のようなものです。
ここで登場するのがIP-in-IP(トンネリング)です。
IP-in-IPは「封筒の中に封筒を入れる」こと
Pod AからPod Bへ手紙を送る時、Calicoはこんな工夫をします。
1. 内側の封筒: 本来の宛先である「Pod Bの住所」を書いた手紙を入れます。
2. 外側の封筒: 「Pod Bの住所」は外からは見えないので、代わりに「Pod Bが住んでいるマンション(ノード)の住所」を宛先に書きます。
こうして、郵便局(クラウドネットワーク)は、とりあえず「マンション」まで手紙を運びます。マンションの管理人(Calico)が外の封筒を開けると、中から「Pod Bに届けてくれ」という内側の封筒が出てくる。これがトンネリングの正体です。
—
なぜ「SNAT」が必要なのか?
次に、Podから「クラスターの外(インターネット)」へ通信する場合を考えてみましょう。
Podがインターネットに手紙を出すとき、宛先は「Webサイト」です。しかし、返信が届く時、Webサイト側は「Podの住所(プライベートIP)」を知らないので、返信の宛先を書くことができません。
そこでSNAT(送信元ネットワークアドレス変換)の出番です。
これは、「Podの住所を、ノード(マンション)の代表住所に書き換えてから外に出す」というテクニックです。これなら、外の世界からの返信は一度マンションの代表者に届き、代表者が「あ、これはあのPod宛てだね」と正しく転送してくれます。
—
注意!トンネリングとSNATの「排他関係」
ここで非常に重要なポイントがあります。「トンネリング(IP-in-IP/VXLAN)」と「SNAT」は、パケット処理の優先順位や役割において、時に食い合うことがあるということです。
Calicoでは、特定の通信に対して「この通信はトンネルを通すのか? それともSNATしてそのまま出すのか?」を制御できます。もし設定をミスすると、「パケットが二重に加工されて宛先に届かない」という悲劇が起こります。
Calicoの設定例:IPPoolを定義する
Calicoの設定(IPPool)では、どのようにトラフィックを扱うかを定義します。
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 192.168.0.0/16
# IPIPモードを有効にする(トンネルを使う)
ipipMode: Always
# NATを有効にする(クラスター外への通信を許可)
natOutgoing: true
ipipMode:Alwaysにすると、Pod間の通信にトンネルを使います。natOutgoing:trueにすると、外の世界への通信にSNATを適用します。
もし、クラウド環境のVPC内で直接ルーティングができる場合(AWSのTransit GatewayやVPC Nativeなど)、あえてipipModeをNeverにして、トンネルによるオーバーヘッド(封筒の二重化による無駄)を避けるのがモダンな構築の鉄則です。
—
トラブルシューティングの勘所
現場で「Podから外に出られない!」というトラブルに直面したとき、私はまず以下のことを確認します。
1. ルートを確認する: ip route コマンドで、パケットがトンネルインターフェース(tunl0など)に向かっているか確認します。
2. iptablesのSNATルールを見る: iptables -t nat -L POSTROUTING を叩いてみましょう。SNATが正しく適用されているか、あるいは意図せず書き換えられているかが見えてきます。
3. tcpdumpで覗き見する:
# 特定のノードでパケットがカプセル化されているか確認
tcpdump -i eth0 proto 4
proto 4 はIP-in-IPを表します。これでパケットが「封筒の中に封筒」状態で流れているか一目瞭然です。
—
最後に:ネットワークを「楽しむ」ために
ネットワークのトラブルは、時に非常に骨が折れます。しかし、パケットの気持ちになって「この封筒はどこで開けられるんだ?」「誰が宛先を書き換えたんだ?」と想像力を働かせると、少しずつ霧が晴れていくはずです。
最初は難しく感じるかもしれませんが、Calicoの設定一つひとつが「パケットという手紙を、正確に、速く届けるための工夫」だと思うと、少し愛着が湧いてきませんか?
ぜひ、手元のクラスターで calicoctl get ippool -o yaml を実行して、今のネットワークがどんな「配達ルール」で動いているのか、覗いてみてくださいね。
それでは、ハッピーなKubernetesライフを!
コメント