ハードウェアの限界を突破するレイヤー4負荷分散:LinuxにおけるIPVSとipvsadmの構築

Network tutorial - IT technology blog
Network tutorial - IT technology blog

入口でシステムがダウン:HAProxyが物理的限界に達する時

私はかつて、約50万件の同時接続を支えるAPIクラスターを扱ったことがあります。皮肉なことに、バックエンドノードはCPU使用率20%で「手持ち無沙汰」な状態である一方、HAProxyを実行しているサーバーは95〜98%という限界状態で悲鳴を上げていました。レイテンシ(遅延)は10msから一気に500msまで跳ね上がりました。問題は設定ミスではなく、ユーザ空間(userspace)のアーキテクチャにありました。パケットがカーネルとアプリケーション層の間で何度もコピーされるため、頻繁なコンテキストスイッチが発生し、帯域幅が埋まる前にCPUが過負荷になっていたのです。

もし、毎秒数百万パケット(PPS)を処理するスピードを持つレイヤー4(TCP/UDP)のトラフィック制御が必要なら、IPVS (IP Virtual Server)こそが求めていた「武器」です。面倒なインストールは不要で、IPVSは実際にはLinuxカーネルに組み込まれているモジュールであり、サーバーを高性能なロードバランサーに変えることができます。

IPVSの圧倒的な速さの秘密

IPVSの最大の強みは、カーネルのNetfilter内部で直接動作することです。NginxやHAProxyのようにパケットをアプリケーション層まで「段階的に引き上げる」のではなく、IPVSはネットワーク層でパケットをインターセプトし、即座にリダイレクトします。

このモデルでは、サーバーはDirector(ディレクター)としての役割を果たします。ハッシュテーブルをO(1)の速度で検索し、パケットをほぼ瞬時に転送します。その結果、10Gbpsのデータフローを処理しても, CPU負荷は非常に低いまま維持されます。

注意すべき3つの動作モードがあります:

  • NAT (Network Address Translation): Directorが宛先IPを書き換えてReal Serverに転送します。設定は簡単ですが、往路と復路の両方を処理するため、Directorがボトルネックになりやすいのが難点です。
  • DR (Direct Routing): これが最も「神」に近いモードです。DirectorはMACアドレスのみを書き換えます。Real Serverはパケットを受け取り、復路ではDirectorを介さずクライアントに直接レスポンスを返します。パフォーマンスにおいてこれに勝るものはありません。
  • TUN (IP Tunneling): Real Serverが異なるネットワークセグメントにあり、VPNやインターネット経由で接続されている場合に使用します。

ipvsadmを使用したIPVS構築の実践

IPVSを制御するには、ipvsadmというツールを使用します。シンプルなWebサーバークラスターに対してNATモードを設定してみましょう。

1. ネットワーク構成の計画

以下のパラメータを準備します:

  • Load Balancer (Director): 192.168.1.10
  • Backend 1 & 2: 192.168.1.21 および 192.168.1.22
  • Virtual IP (VIP): 10.0.0.100 (クライアントがアクセスするアドレス)

大規模なクラスターのIP範囲を設計する場合、手動でのサブネット計算はミスが発生しやすいものです。私はいつも toolcraft.app/ja/tools/developer/ip-subnet-calculator を使用して、/27や/28のCIDR範囲を素早く計算し、最初から正確なバックエンド用の固定IPを計画しています。

2. インストールとカーネルの設定

Ubuntuに管理ツールをインストールします:

sudo apt-get update && sudo apt-get install ipvsadm -y

パケット転送機能を有効にするのを忘れないでください。これを忘れるとNATモードが動作しません:

echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

3. 負荷分散ルールの設定

ラウンドロビン(rr)アルゴリズムを使用して、ポート80で動作する仮想サービスを作成します:

sudo ipvsadm -A -t 10.0.0.100:80 -s rr

-m パラメータ(NATモード)を使用して、2台のバックエンドサーバーをリストに追加します:

sudo ipvsadm -a -t 10.0.0.100:80 -r 192.168.1.21:80 -m
sudo ipvsadm -a -t 10.0.0.100:80 -r 192.168.1.22:80 -m

4. 成果の確認

次のコマンドを入力して、リアルタイムの転送テーブルを確認します:

sudo ipvsadm -L -n --stats

システムを流れるパケットの送受信数(Packet In/Out)とバイト数が透過的に表示されます。

HAProxyの代わりにIPVSを使うべきタイミングは?

最強のツールを選ぶことよりも、適切なツールを選ぶことの方が重要です。処理する層(レイヤー)に基づいて検討してください:

  • HAProxyを選ぶ場合: ヘッダーの読み取り、Cookieの確認、SQLインジェクションの遮断、またはSSLの復号化(レイヤー7)が必要な場合です。IPVSはIPとポートしか見ないため、そこまで「スマート」ではありません。
  • IPVSを選ぶ場合: 生のTCP/UDPを極めて高いスループットで転送するだけでよい場合です。IPVSは非常に安定しており、ユーザ空間で複雑な状態を維持しないため、メモリ不足(OOM)エラーが発生することはほとんどありません。

WikipediaやGitHubのような大手サイトでは、よく両方を組み合わせています。IPVSを最前面に置いて数百万PPSの負荷を受け止め、その後段にHAProxyクラスターを配置してアプリケーションロジックを処理させています。

実運用に向けて:Keepalivedを忘れずに

ipvsadm コマンドを叩くのは第一歩に過ぎません。本番環境で、唯一のDirectorノードがダウンすれば、システム全体が「行方不明」になってしまいます。

IPVSをKeepalivedと組み合わせることをお勧めします。Keepalivedは、Directorのペアを作成し、マスター・バックアップ構成を実現します。マスターに障害が発生した場合、バックアップが数秒以内に自動的にVIPを引き継ぎます。同時に、KeepalivedはReal Serverのヘルスチェック(Health Check)を自動的に行い、故障中のサーバーにパケットが送られないように保証します。

結論として、もしロードバランサーが「息切れ」しているなら、それをカーネル層に落とし込んでください。それが、ハードウェアのアップグレードに一銭もかけずにパフォーマンスを最適化する最も賢い方法です。

Share: