大規模環境でレイヤー4ロードバランシングが重要な理由
多くの開発者はHAProxyやNginxから使い始めます。これらはレイヤー7(HTTP)のロジックには優れていますが、ユーザースペースで動作します。そのため、すべてのパケットがネットワークカードからカーネルを経由し、アプリケーションに到達して、また戻るというプロセスを辿る必要があります。毎秒1万リクエスト程度であれば、このコンテキストスイッチは許容範囲内です。しかし、同時接続数が10万を超えたり、10Gbpsの回線を使い切るような状況では、そのオーバーヘッドがCPUの大きなボトルネックとなります。
Linux Virtual Server (LVS) は、ipvsモジュールを介してカーネル内で動作することで、この問題を解決します。LVSはレイヤー4で動作し、HTTPヘッダーやクッキーの中身を確認することなくTCP/UDPパケットを処理します。カーネル内に留まることで、LVSはワイヤスピードに近い速度でパケットを転送できます。筆者の本番環境では、同じトラフィック量において、ユーザースペースのプロキシからLVSに切り替えたことで、CPU負荷が40%近く削減されました。
LVS NATモードの設定
LVS NAT(ネットワークアドレス変換)は、最もシンプルな構成です。ロードバランサーがゲートウェイとして機能します。リクエストを受け取り、宛先IPをバックエンドサーバーに書き換え、戻りのトラフィックも処理します。構成は簡単ですが、ロードバランサーの帯域幅がインバウンドとアウトバウンド両方のデータ制限になる点に注意が必要です。
1. 管理ツールのインストール
カーネルのIPVSテーブルを管理するには、ipvsadmが必要です。UbuntuやDebianでは、次のコマンドでインストールできます。
sudo apt update && sudo apt install ipvsadm -y
2. IPフォワーディングの有効化
ロードバランサーはネットワーク間でパケットをルーティングする必要があります。直ちにカーネルでこれを有効にします。
sudo sysctl -w net.ipv4.ip_forward=1
3. バーチャルサービスの設定
ロードバランサー(VIP)を192.168.1.10、バックエンドを10.0.0.101および10.0.0.102と仮定します。
# 既存のルールを消去
sudo ipvsadm -C
# ラウンドロビン(-s rr)を使用して、ポート80にVIPを定義
sudo ipvsadm -A -t 192.168.1.10:80 -s rr
# NATモード(-m)を使用してリアルサーバーをマッピング
sudo ipvsadm -a -t 192.168.1.10:80 -r 10.0.0.101:80 -m
sudo ipvsadm -a -t 192.168.1.10:80 -r 10.0.0.102:80 -m
sudo ipvsadm -lnを実行して確認します。これで、カーネルレベルで動作する高速なトラフィック配信システムが構築されました。
真の威力:ダイレクトルーティング(DR)モード
NATモードには弱点があります。ロードバランサーがレスポンスのボトルネックになることです。多くのWebアプリでは、レスポンス(2MBの画像など)はリクエスト(1KBのGET)よりもはるかに大きくなります。ダイレクトルーティング(DR)は、バックエンドサーバーがクライアントに直接返信できるようにすることで、この問題を解決します。
DRモードでは、ロードバランサーはパケットのMACアドレスのみを書き換えてネットワークに戻します. バックエンドサーバーはパケットを受け取って処理し、レスポンスをユーザーに直接送信します。これにより、1つのLVSノードで巨大なクラスターを管理できます。重い戻りトラフィックを処理する必要がないからです。
究極のパフォーマンスを実現するLVS-DRの実装
DRを動作させるには、すべてのサーバーが同じレイヤー2セグメント(同じスイッチまたはVLAN)を共有している必要があります。これは、高性能なデータセンターアーキテクチャの標準的な構成です。
ステップ1:ロードバランサーの設定
# より適切な分散のために、重み付き最小接続(-s wlc)を使用
sudo ipvsadm -A -t 192.168.1.50:80 -s wlc
# DRモード(-g)でサーバーを追加
sudo ipvsadm -a -t 192.168.1.50:80 -r 192.168.1.101:80 -g
sudo ipvsadm -a -t 192.168.1.50:80 -r 192.168.1.102:80 -g
ステップ2:バックエンドでの「ARP問題」の解決
各バックエンドは、トラフィックを受け入れるためにループバックインターフェースにVIPを設定する必要があります。ただし、そのVIPに対するARPリクエストに応答してはいけません。さもないと、IPを巡ってロードバランサーと競合してしまいます。ループバックにVIPを追加します。
sudo ip addr add 192.168.1.50/32 dev lo
次に、ネットワーク上でこのIPについて応答しないようカーネルに設定します。
sudo sysctl -w net.ipv4.conf.all.arp_ignore=1
sudo sysctl -w net.ipv4.conf.all.arp_announce=2
sudo sysctl -w net.ipv4.conf.lo.arp_ignore=1
sudo sysctl -w net.ipv4.conf.lo.arp_announce=2
本番環境に向けた強化のヒント
1. Keepalivedによるヘルスチェックの自動化
ipvsadm単体では「無頓着」です。サーバーがダウンしてもトラフィックを送り続けてしまいます。Keepalivedを使用してバックエンドを監視しましょう。Keepalivedは定期的なヘルスチェック(TCP接続やHTTP GETなど)を実行し、ノードが故障した場合は自動的にipvsテーブルを更新します。
2. 適切なアルゴリズムの選択
- rr (Round Robin): すべてのバックエンドが同一のハードウェアである場合に最適です。
- wlc (Weighted Least Connections): 推奨されるデフォルト設定です。アクティブなジョブが少ないサーバーにトラフィックを送信します。
- sh (Source Hashing): クライアントのIPアドレスに基づいたセッション維持が必要な場合に不可欠です。
3. リアルタイム統計の監視
統計フラグを使用して、スループットの問題や設定ミスを特定します。
sudo ipvsadm -ln --stats
「OutPkts」列を確認してください。DRモードでこの数値がロードバランサー上でゼロであれば、設定は正しく機能しています。バックエンドが自ら送信トラフィックを処理していることを意味します。
4. ファイアウォールの注意点
LVSは、多くのiptablesチェーンよりも前にカーネルにフックします。問題が発生した場合は、一時的にufwやfirewalldを無効にして、ルーティングロジックが機能するか確認してください。確認後、VIPとリアルサーバーのポートへの通信を許可する特定のルールを追加します。
ロードバランシングをLVSでカーネルに移行することで、レイテンシを削減し、アプリケーションのためのCPUリソースを節約できます。Linux上で大規模かつ安定したスループットを必要とするインフラにとって、LVSは依然として不可欠なツールです。

