【実務・中級編】 netstatによるルーティングテーブル(-r)とインター페이스統計の確認 – トラブルシューティング&ネットワーク運用監視実践ガイド

深夜のデータセンター、冷気混じりのサーバーラックの間で、何度「パケットの断末魔」を聞いてきただろうか。

「APIのレスポンスが返ってこない」「特定のサブネットにだけ通信が届かない」……。そんな絶望的な報告が飛び込んできたとき、我々シニアエンジニアが真っ先に叩くコマンドの一つが netstat だ。

最近は ip route や ss コマンドに取って代わられつつあるが、POSIX準拠のシステムであればどこにでも居てくれる、古き良き相棒だ。今回は、Web API開発者やインフラ担当者が「現場で生き抜く」ために必須となる、netstat を使ったルーティングとインターフェース統計の深掘り方法を伝授しよう。

—

1. ルーティングテーブルは「パケットの羅針盤」である

パケットがホストから旅立つとき、最初に見るのがカーネル内のルーティングテーブルだ。ここが狂っていれば、どんなに豪華なAPIを実装しても、パケットは虚空へと消えていく。

netstat -rn で現実を直視する

まずは、現在のルーティング状況を確認する基本の型だ。-r (routing) と -n (numeric:名前解決をせず数字で表示) を組み合わせるのが鉄則だ。

# ルーティングテーブルを表示する。-nを付けないとDNS逆引きで表示が遅れることがある。
$ netstat -rn

Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG        0 0          0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U         0 0          0 eth1
192.168.1.0     0.0.0.0         255.255.255.0   U         0 0          0 eth0

ここで注目すべきは Flags カラムだ。ここにはパケットの運命が記されている。

  • U (Up): ルートが有効である。
  • G (Gateway): ゲートウェイ(ルーター)を経由することを示す。0.0.0.0 の宛先(デフォルトゲートウェイ)には必ずこのフラグが立つ。
  • H (Host): 特定の1ホストへのルート。

現場のTips:
もしAPIの接続先が 10.0.0.5 なのに、ルーティングテーブルに 10.0.0.0/24 のエントリがなく、デフォルトゲートウェイ(0.0.0.0)に吸い込まれて外部ネットワークへ出ていこうとしていたら? そこで通信は遮断される。ルーティングの不整合は、コードを書く前の「土俵」の問題なのだ。

—

2. インターフェース統計から「ネットワークの悲鳴」を聴く

「通信は繋がっているが、なぜか時々遅い、パケットが落ちる」という微熱のような不具合。これを見抜くには netstat -i (interface) が不可欠だ。

# 全インターフェースの統計情報を確認
$ netstat -i

Kernel Interface table
Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0      1500   124502      0      0 0        105670      0      0      0 BMRU
lo       65536     2405      0      0 0          2405      0      0      0 LRU

統計値が語る真実

  • RX-ERR / TX-ERR: 受信・送信時のエラー数。ここが増えているなら、物理レイヤー(ケーブル不良、SFPモジュールの劣化)か、ドライバの不整合を疑え。
  • RX-DRP (Drop): カーネルの受信バッファが溢れたか、パケットフィルタリングで捨てられた数だ。APIへのバーストアクセスにシステムが耐えきれていない兆候かもしれない。

Web APIのパフォーマンスが出ないとき、アプリケーションのプロファイリングを始める前に、この RX-DRP が増えていないかチェックしてほしい。OSレベルでパケットを捌ききれていないなら、いくらPythonやGoのコードを最適化しても無意味だからだ。

—

3. 実務でのデバッグ・ワークフロー

ここからは、API開発者が遭遇しがちな「特定のマイクロサービスと通信できない」というケースを想定したデバッグ手順を示そう。

手順1: 通信経路の疎通確認

まずは curl での挙動を確認し、その後 netstat で足元を固める。

# タイムアウトを短く設定して接続確認
$ curl -v --connect-timeout 5 https://api.internal.service/v1/health

# 接続できない場合、そもそもどのインターフェースから出ようとしているか確認
$ netstat -rn

手順2: 宛先ネットワークへのルートが存在するか?

例えば、宛先が 172.16.50.10 なら、それを含むセグメントが Iface(例えば eth1)に紐付いているかを見る。もし無ければ、静的ルートの追加が必要になる。

# Linuxでの静的ルート追加例(一時的)
# 172.16.50.0/24 宛の通信は 192.168.1.254 を通れ、という指示
$ sudo ip route add 172.16.50.0/24 via 192.168.1.254 dev eth0

—

4. Pythonによるネットワーク監視の自動化

インフラ運用においては、手動でコマンドを叩くのは最初の一歩に過ぎない。重要なのは「異常の予兆」を検知することだ。psutil ライブラリを使えば、netstat -i 相当の情報をプログラムから容易に取得できる。

import psutil
import time

def monitor_interfaces():
    """
    インターフェースの統計情報を監視し、エラー率を算出する
    """
    # 初回取得
    old_stats = psutil.net_io_counters(pernic=True)
    
    while True:
        time.sleep(5)
        # 5秒後の統計取得
        new_stats = psutil.net_io_counters(pernic=True)
        
        for iface, stats in new_stats.items():
            drop_diff = stats.dropin - old_stats[iface].dropin
            err_diff = stats.errin - old_stats[iface].errin
            
            if drop_diff > 0 or err_diff > 0:
                print(f"[ALERT] Interface {iface}: Errors={err_diff}, Drops={drop_diff}")
                # ここでSlack通知やログ出力を行うのが現場流
            else:
                print(f"[INFO] Interface {iface}: Healthy")
                
        old_stats = new_stats

if __name__ == "__main__":
    monitor_interfaces()

—

結びに代えて:パケットの気持ちを理解する

RFC 791(IP)や RFC 793(TCP)を読み込むのも良い。しかし、トラブルの現場で最後にモノを言うのは、こうした泥臭いコマンドが吐き出す「生の数字」との対話だ。

netstat -r が示すのは、ホストが世界をどう見ているかという「地図」であり、netstat -i が示すのは、その地図を歩く足元の「健康状態」だ。

Web APIの設計者であっても、パケットが物理的なNICを通り、カーネルのルーティング判断を経て、インターネットの荒波へと消えていく一連のシーケンスを想像してほしい。その想像力こそが、堅牢なシステムを構築する最強の武器になるのだから。

次に画面が「Connection Timeout」を吐き出したとき、君が冷静に netstat -rn を叩けることを願っている。

コメント

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