Calicoの深淵:IP-in-IPとSNATの排他制御が握る、クラスター境界のパフォーマンスとセキュリティ
Kubernetesのネットワークを語る際、多くのエンジニアが「魔法のように繋がるオーバーレイネットワーク」としてCalicoを導入する。しかし、その内部でパケットがどのようにカプセル化され、どのタイミングで SNAT(Masquerading)が発生するのかを理解している者は驚くほど少ない。
特に、パブリッククラウドのVPC環境で「IP-in-IP」を選択した瞬間に発生するオーバーヘッドと、トラフィックの出口(Egress)におけるルーティングのジレンマは、大規模システムを運用するインフラアーキテクトにとって避けては通れない関門だ。今回は、Calicoのルーティングモードがもたらすパケットレベルの挙動と、パフォーマンスを最大化するためのチューニングについて深掘りする。
—
1. カプセル化の代償:IP-in-IP vs BGP
Calicoの標準的な振る舞いとして、IP-in-IPはパケット全体を別のIPパケットで包み込む。これにより、レイヤー3のルーティングを維持したまま、Pod間通信をアンダーレイネットワーク(VPC)上で透過的に転送できる。
しかし、ここで忘れてはならないのはMTUの損失だ。IP-in-IPヘッダー(20バイト)が付与されることで、実質的なデータ転送効率(Goodput)は低下する。クラウド環境において、パケットがフラグメンテーションを起こせば、その瞬間にCPUコストが急増し、TCPの再送制御が足かせとなる。
パフォーマンス最適化のためのチューニング
もし、物理ネットワーク(VPC)がPodのIPアドレス範囲を直接ルーティングできるなら、迷わず BGP モードを選択し、カプセル化を無効化すべきだ。それが最も低レイテンシかつ、パケットヘッダーの解析コストを最小化する選択となる。
# CalicoのIPPool設定例
# カプセル化を無効化し、直接ルーティングを行う設定
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 192.168.0.0/16
ipipMode: Never # IP-in-IPを無効化
vxlanMode: Never # VXLANも無効化
natOutgoing: true # クラスター外へのSNATは許可
—
2. SNAT(Masquerading)の闇と排他制御
natOutgoing: true を設定すると、Podからクラスター外への通信に対し、ノードのIPアドレスで SNAT が行われる。これが有効な場合、パケットは以下の経路を辿る。
1. Pod内: 送信元Pod IPでパケット生成。
2. ノード内: iptables / nftables の MASQUERADE ルールにヒット。
3. ノード外: ノードのPrimary IPに書き換えられ、VPCのNATゲートウェイへと向かう。
ここで問題になるのが、「カプセル化とSNATの二重適用」によるCPU負荷と、コネクション追跡(conntrack)テーブルの枯渇だ。特にTCPハンドシェイクにおいて、conntrackのテーブルサイズが小さいと、高負荷時にパケットドロップが頻発する。
カーネルパラメーターの最適化
大規模クラスターにおいて conntrack の限界を感じたら、以下のsysctl設定をノードに投入せよ。
# conntrackテーブルの最大数を引き上げ、タイムアウトを短縮する
# 突発的なトラフィックバーストに対処するための必須設定
sysctl -w net.netfilter.nf_conntrack_max=1048576
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=86400
—
3. TCPバッファとRTT削減の戦術
インターネット越しの通信であれば、TCPの Window Scale オプションとバッファサイズの調整が、アプリケーションのパフォーマンスを劇的に左右する。
IP-in-IP のようなオーバーレイを使用する場合、アンダーレイのVPCネットワークとオーバーレイのMTU差による「不均一なパケット到達」が発生しやすい。これを解消するために、MSS Clamping を活用する。
# iptablesでMSSを強制的にクランプし、パケット分割を防ぐ
# 1460バイト(MTU 1500 - 20(IP) - 20(TCP))からカプセル分を引くのが鉄則
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1360
これにより、TCPのハンドシェイク時にクライアントとサーバー間で適切な最大セグメントサイズがネゴシエートされ、無駄なパケットの断片化を未然に防ぐことができる。
—
4. セキュリティ専門家への提言:脆弱性の回避
最後に、ネットワーク設計における「重大な見落とし」について触れておく。SNAT を広範に許可することは、セキュリティ境界を曖昧にする。Podから外部への通信を許可する場合、すべてのPodを一律にNATするのではなく、Calico Egress Gateway を活用して特定のノードにトラフィックを集約させ、固定IPで外部サービス(API GWやDB)と通信させるアーキテクチャが最も堅牢だ。
結論として、以下の指針を提唱する。
- カプセル化の排除: VPCルーティングが可能な環境では
IP-in-IPを捨て、BGPに移行せよ。 - conntrackの監視:
conntrackのエントリ数を常に監視し、枯渇の予兆があれば即座にテーブルを拡張せよ。 - MTUの最適化: ネットワークのパスMTUディスカバリーに頼らず、明示的な
MSS Clampingで通信品質を担保せよ。
ネットワークは「繋がって当たり前」ではない。パケットがカーネルを通過する一瞬の挙動を理解し、ボトルネックを潰し続けること。それこそが、SREとしてサービスを守るための唯一の道である。
コメント