2026年6月6日

2026年6月6日

HAProxy と Envoy の比較|設定の考え方・動的な構成変更・WordPress の前段にどちらを置くか

HAProxy と Envoy はどちらも高性能なプロキシ/ロードバランサーですが、得意な場面が違います。結論を先に言うと、数台の WordPress サーバーの前に置いて、設定ファイルで素直に運用したいなら HAProxy、Kubernetes やサービスメッシュのように構成が頻繁に変わる環境で、外部のコントロールプレーンから設定を配りたいなら Envoy が向いています。この記事では、設計思想・設定の書き方・構成変更の方法・観測性の違いを比べ、同じ構成を両方で書いた例も示すので、自分の環境でどちらを選ぶか判断できるようになります。

2つのプロキシの成り立ちと立ち位置

HAProxy は C 言語で書かれた、長い歴史を持つ TCP/HTTP ロードバランサーです。1つの設定ファイル(通常は /etc/haproxy/haproxy.cfg)に、受け口(frontend)と振り分け先(backend)を書いていくスタイルで、少ない資源で大量の接続をさばけることが評価されてきました。オープンソース版のほかに、商用サポートや追加機能のある Enterprise 版もあります。

Envoy は C++ で書かれたプロキシで、マイクロサービス間の通信を扱うために設計されました。CNCF(Cloud Native Computing Foundation)の卒業プロジェクトで、Istio などのサービスメッシュや、Kubernetes の Gateway API 実装(Envoy Gateway など)のデータプレーンとして広く使われています。最初から「設定は外部から API で配られるもの」という前提で作られている点が、HAProxy との大きな違いです。

どちらも活発に開発が続いており、HTTP/2、TLS 終端、ヘルスチェック、各種の負荷分散方式といった基本機能はそろっています(2026年10月現在)。違いが出るのは「機能の有無」よりも「設定と運用のしかた」です。

比較の要点

観点 HAProxy Envoy
設定形式 独自の設定ファイル(行単位の宣言) YAML / JSON(Protocol Buffers ベースの v3 API)
構成変更 設定の再読み込み、Runtime API、Data Plane API xDS API による動的配信、ホットリスタート
得意な規模 数台〜数十台の固定的な構成 頻繁に増減するサービス群、メッシュ
観測性 ログ・統計ページ・Prometheus 向け出力 詳細な統計、分散トレーシング連携
拡張 Lua、SPOE など HTTP フィルター、Lua、Wasm など
学習コスト 低め。設定が短く読みやすい 高め。設定が長く、概念が多い

表はおおまかな傾向です。たとえば HAProxy にも動的な構成変更の手段はありますし、Envoy も静的な設定ファイルだけで動かせます。どちらが「できない」かではなく、「どちらの運用が自然か」で見てください。

同じ構成を両方で書いてみる

2台の WordPress サーバー(10.0.0.11 と 10.0.0.12)にラウンドロビンで振り分け、/healthz.php でヘルスチェックする構成を、両方で書いてみます。/healthz.php は各サーバーに自分で用意する、200 を返すだけの軽いファイルを想定しています。

HAProxy の場合

global
    log /dev/log local0
    maxconn 4096

defaults
    mode http
    log global
    option httplog
    option forwardfor
    timeout connect 5s
    timeout client  30s
    timeout server  30s

frontend fe_http
    bind :80
    default_backend be_wordpress

backend be_wordpress
    balance roundrobin
    option httpchk GET /healthz.php
    http-check expect status 200
    server wp1 10.0.0.11:80 check
    server wp2 10.0.0.12:80 check

設定を変えたら、反映前に文法を確認します。

sudo haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl reload haproxy

Envoy の場合

static_resources:
  listeners:
  - name: listener_http
    address:
      socket_address: { address: 0.0.0.0, port_value: 80 }
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          use_remote_address: true
          route_config:
            name: local_route
            virtual_hosts:
            - name: wordpress
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route: { cluster: wordpress }
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
  - name: wordpress
    connect_timeout: 5s
    type: STATIC
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: wordpress
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address: { address: 10.0.0.11, port_value: 80 }
        - endpoint:
            address:
              socket_address: { address: 10.0.0.12, port_value: 80 }
    health_checks:
    - timeout: 2s
      interval: 5s
      unhealthy_threshold: 3
      healthy_threshold: 2
      http_health_check:
        path: /healthz.php

admin:
  address:
    socket_address: { address: 127.0.0.1, port_value: 9901 }

Envoy も起動前に設定を検証できます。

envoy --mode validate -c /etc/envoy/envoy.yaml

同じことをするのに、Envoy の設定は HAProxy の数倍の長さになります。Envoy では「リスナー → フィルターチェーン → HTTP 接続マネージャー → ルート → クラスター」という階層を明示的に書く必要があるためです。この階層は、のちに API から部分的に差し替えるための単位でもあります。管理用インターフェース(例では 9901 番)は統計や設定の確認に便利ですが、操作もできるため、例のように 127.0.0.1 だけで待ち受けて外部に公開しないでください。

構成変更のしかたの違い

運用で差が大きいのが、サーバーの追加・削除をどう反映するかです。

HAProxy は、設定ファイルを書き換えて再読み込みするのが基本です。再読み込みでは新しいプロセスが接続を引き継ぎ、古いプロセスは処理中の接続を終えてから終了するため、通常は通信を落とさずに反映できます。加えて、Runtime API(stats socket)でサーバーの有効化・無効化や重みの変更をその場で行えますし、DNS を使ってバックエンドの増減を自動で拾う仕組みもあります。より本格的に API で管理したい場合は Data Plane API という別コンポーネントを使います。

Envoy は、xDS と総称される API(リスナー用、クラスター用、エンドポイント用などに分かれています)で、外部のコントロールプレーンから設定を受け取るのが本来の使い方です。サービスの増減が多い環境では、Kubernetes や Istio などのコントロールプレーンが自動で設定を配るため、人が設定ファイルを書き換える場面はほとんどありません。逆に言えば、コントロールプレーンを持たない小規模な構成では、Envoy の強みが生きにくくなります。

観測性とデバッグ

HAProxy は、アクセスログに振り分け先のサーバー名や各段階の処理時間、終了理由(タイムアウトや接続拒否など)を記録できます。トラブル時は、ログの終了理由コードを見ると「クライアント側で切れたのか、バックエンドが遅いのか」を切り分けやすいのが利点です。統計ページや Prometheus 向けの出力も用意されています。

Envoy は、クラスターごと・リスナーごとに非常に細かい統計を出し、分散トレーシング(OpenTelemetry など)との連携も前提に作られています。複数のサービスをまたぐリクエストの遅延を追いたい場合に有利です。一方で、統計項目が多いぶん、どの値を見ればよいかを把握するまでに時間がかかります。

WordPress の前段に置くときの判断基準

WordPress を複数台で動かす前段として選ぶなら、次のように考えると迷いにくくなります。

  • サーバーは数台で、増減は手作業かたまに行う程度 → HAProxy。設定が短く、障害時に読み解きやすい
  • すでに Kubernetes 上で動かしていて、Ingress や Gateway として Envoy 系の製品を使っている → Envoy に寄せると運用がそろう
  • サービスメッシュでマイクロサービス間の通信も管理したい → Envoy
  • 運用担当者が少なく、設定をレビューしやすくしたい → HAProxy

どちらを選んでも、WordPress 側の対応は共通です。プロキシで HTTPS を終端すると、WordPress からはすべての接続が HTTP に見えるため、X-Forwarded-Proto ヘッダーを見て HTTPS と判定させる設定を wp-config.php に入れます。

// プロキシ経由のときだけ HTTPS と判定する(プロキシ以外から直接届かない構成が前提)
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
    $_SERVER['HTTPS'] = 'on';
}

このヘッダーはクライアントが自由に付けられるため、バックエンドのサーバーにはプロキシからしか接続できないよう、ファイアウォールで制限しておくことが前提です。クライアントの IP アドレスも同様で、プロキシが付ける X-Forwarded-For は、信頼できるプロキシからの接続に限って使います。また、アップロードファイルの共有、オブジェクトキャッシュ、WP-Cron の実行場所など、複数台構成そのものの課題はプロキシの種類に関係なく残ります。

移行や併用のときの注意

既存の HAProxy から Envoy へ、またはその逆に移す場合は、設定を機械的に置き換えるのではなく、タイムアウト値、ヘルスチェックの判定条件、再試行の挙動を一つずつ対応づけて確認してください。デフォルト値が両者で異なるため、同じ設定のつもりでも挙動が変わることがあります。切り替えは、本番と同じ構成のステージング環境で負荷をかけて試し、DNS や前段のロードバランサーで一部の通信だけを新しいプロキシに流してから全体を移すと安全です。作業前には既存の設定ファイルをバックアップしておきます。

まとめ

  • HAProxy は設定ファイル中心で読みやすく、固定的な構成のロードバランサーとして扱いやすい
  • Envoy は API による動的な設定配信が前提で、Kubernetes やサービスメッシュとの相性がよい
  • 同じ構成でも Envoy の設定は長くなるが、その階層が動的な差し替えの単位になっている
  • WordPress の前段としては、数台規模なら HAProxy、Kubernetes 環境なら Envoy 系が選びやすい
  • どちらでも HTTPS 判定とクライアント IP の扱いは WordPress 側で調整し、バックエンドへの直接接続は閉じる
  • 機能やデフォルト値はバージョンで変わるため、公式ドキュメントで確認し、ステージングで試してから切り替える

お気軽にご相談ください

お見積りへ お問い合わせへ
▲