ネットワークエンジニアの「魔の領域」:MTUとジャンボフレームが引き起こす隠れた悪夢
ネットワークエンジニアとして現場を渡り歩いていると、たまに「なぜか特定のAPIだけがタイムアウトする」「SSHは繋がるのに、巨大なレスポンスが返ってくると通信が止まる」といった不可解な現象に遭遇する。ログを見てもエラーが出ない。パケットキャプチャをしても、TCPの再送が繰り返されるばかりで原因が掴めない。
これ、十中八九「MTU(Maximum Transmission Unit)」が絡んでいる。今日は、初心者が陥りやすく、かつベテランでも油断できないこの厄介なテーマについて、実務的な観点から深掘りしていこう。
—
1. MTU 1500バイトという「呪縛」
イーサネットの標準MTUが 1500 バイトであることは、インフラ屋なら誰もが知っている事実だ。これは、イーサネットヘッダ(14バイト)とFCS(4バイト)を除いた、IPパケットが運べるデータサイズの上限を指す。
API設計やクラウドインフラを構築する際、この「1500」を意識することは少ない。なぜなら、OSやルーターが勝手にやってくれるからだ。しかし、ネットワークの境界(特にVPNやGREトンネル、あるいはクラウドのVPCピアリング)を越えるとき、この前提が崩れる。
なぜパケットは断片化(フラグメンテーション)するのか
送信側のMTUが 1500 で、経路上のどこかのMTUが 1400 だった場合、パケットはそこで分割される。IP層には「DF(Don’t Fragment)ビット」というフラグがあり、これが立っているとルーターは「分割不可」としてパケットを破棄し、送信元へICMPの Destination Unreachable を返す。
この「ICMPがどこかでフィルタリングされている」環境こそが、最もたちが悪い。通信がただ無言で死ぬ、いわゆる「ブラックホール問題」の完成だ。
—
2. ジャンボフレームという「諸刃の剣」
パフォーマンスを追求する現場では、MTUを 9000 バイトまで拡張する「ジャンボフレーム」が推奨されることがある。特にバックエンドのDB通信や、大量のログ転送を抱えるデータセンター内では、CPU負荷を劇的に下げられるため重宝される。
しかし、注意してほしい。ジャンボフレームは「エンド・ツー・エンド」で経路上の全機器が対応していなければならない。途中に1台でも 1500 のスイッチが混ざっていれば、そこでパケットはドロップされるか、最悪の場合、フラグメンテーションの嵐でネットワークが遅延の泥沼と化す。
—
3. 実践:Path MTU Discovery (PMTUD) を確認する術
APIの応答が重い、あるいは特定のクライアントだけ通信が通らないといった場合、まずはパケットの最大サイズをコマンドで特定する癖をつけよう。
pingによる探索(Linux環境)
ping コマンドで、DFビットを立てた状態でパケットサイズを徐々に大きくしていくのが最も原始的で確実な手法だ。
# パケットサイズ1472バイトを指定(IPヘッダー20 + ICMPヘッダー8 = 28バイトを引く)
# -M do は「断片化禁止」のフラグ
ping -M do -s 1472 192.168.1.1
# もし応答が返ってこなければ、サイズを下げていく
# 1464で通るなら、その経路のMTUは1492(1464+28)だと判断できる
Pythonで試すHTTPリクエストの確認
Web APIの場合、クライアントからサーバーへ巨大なリクエストを送る際にMTU問題が顕在化することがある。requests ライブラリ等でデバッグする際は、適宜タイムアウトとパケットサイズに気を配ろう。
import requests
# 巨大なPayloadを投げる際の注意点
# ヘッダーを含めて1500を超えると、フラグメント処理が走る可能性がある
data = {"payload": "A" * 2000}
try:
# タイムアウトを短めに設定してブラックホール問題を炙り出す
response = requests.post("https://api.example.com/upload", json=data, timeout=5)
print(f"Status: {response.status_code}")
except requests.exceptions.ConnectionError as e:
print(f"接続失敗: MTU問題の可能性あり -> {e}")
—
4. 現場で生き残るためのインフラTips
Web API設計者やSREがMTU問題に直面したとき、打てる手は以下の通りだ。
1. MSS Clampingの活用:
ルーターやロードバランサーの設定で、TCPの MSS(Maximum Segment Size) を強制的に小さく書き換える手法。経路のMTUを知らなくても、TCPのハンドシェイク中に通信サイズを制限できる。これが現場での「救世主」になることが多い。
- Cisco等のルーター設定例:
interface Tunnel0
ip tcp adjust-mss 1360 # VPN越しなら1360程度に絞るのが定石
2. OSレベルの調整:
ip link コマンドでインターフェースのMTUを調整する際は、慎重に行うこと。
# eth0のMTUを1400に変更
sudo ip link set dev eth0 mtu 1400
*注意: 設定を反映した瞬間に、SSH接続が切れて二度とログインできなくなるリスクがある。必ず tmux や screen 上で実行し、設定が誤っていても戻せる準備をしておくのがプロの流儀だ。*
—
まとめ:ネットワークは嘘をつかない
MTU問題は、高度なクラウド環境やコンテナネットワーク(Overlay Network)が普及した現代において、より複雑化している。仮想スイッチ(OVS)やVXLANなど、カプセル化技術を使うと、そのオーバーヘッド分だけMTUを削らなければならないからだ。
「なぜか動かない」という壁にぶつかったとき、OSのスタックよりも下の「パケットのサイズ」に目を向けてみてほしい。パケットが物理的な境界でどのような姿で運ばれているのかを想像できたとき、君はまた一つ、真のネットワークスペシャリストに近づいているはずだ。
次は、このMTU設定がKubernetesの Calico や Flannel でどう影響するかを話そうか。…続きが気になるなら、またこの場所で会おう。
コメント