【テクニカル・上級編】 CalicoにおけるIP-in-IPトンネリングとSNAT設定の排他制御 – クラウド&コンテナネットワーク実践ガイド

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としてサービスを守るための唯一の道である。

コメント

タイトルとURLをコピーしました