◀ 5.

HAProxy とは frontend/backend と設定例 | ネットワーク入門

▶

このページはHAProxyの入口・送り先・監視を分ける入門です。旧設定は保存用で本番利用不可。先に隔離例と検証範囲を読んでください。追加例の対象はHAProxy 3.2 LTSで、実行時のパッチ版はhaproxy -vvで確認します。

apiのパス境界、HTTP readiness、loopbackと認証で分離した統計経路

先に試す隔離用の完成設定(HAProxy 3.2)

以下は実在サービスへ接続しない教材です。新規の専用コンテナをnetwork none・ホスト公開ポートなしで起動し、その中の127.0.0.1だけを使います。haproxy.cfgとfixtures.cfgの2ファイルを読み取り専用で同じディレクトリに置き、両方を-fで指定します。fixtures.cfgはHAProxy自身が返す合成API/Webで、実アプリではありません。既存の設定ファイルを上書きしないでください。

statsのlab:public-lab-onlyは公開済みの合成資格情報で、本番には使用不可。loopbackでも同一ホスト内の別プロセスは接続可能です。実運用では管理経路の到達制限、固有の秘密値、TLS等の通信保護を設計します。Basic認証だけでは平文HTTPの盗聴対策になりません。stats adminは有効にしません。

haproxy.cfg:受け口・HTTP検査・統計

# HAProxy 3.2: isolated loopback lab, NOT a production configuration.
global
    maxconn 128

defaults
    mode http
    timeout connect 1s
    timeout client 5s
    timeout server 5s
    timeout check 1s

frontend lab_in
    bind 127.0.0.1:8080
    # Direct clients only: discard their claimed forwarding identity.
    http-request del-header Forwarded
    http-request del-header X-Real-IP
    http-request del-header X-Forwarded-Host
    http-request del-header X-Forwarded-Port
    http-request del-header X-Forwarded-Prefix
    http-request set-header X-Forwarded-Proto http
    http-request set-header X-Forwarded-For %[src]
    acl api_exact path /api
    acl api_child path_beg /api/
    use_backend api_servers if api_exact or api_child
    default_backend web_servers

backend api_servers
    option httpchk
    http-check send meth GET uri /readyz ver HTTP/1.1 hdr Host lab.invalid
    http-check expect status 200
    server api1 127.0.0.1:9101 check inter 200ms fall 2 rise 2

backend web_servers
    option httpchk
    http-check send meth GET uri /readyz ver HTTP/1.1 hdr Host lab.invalid
    http-check expect status 200
    server web1 127.0.0.1:9102 check inter 200ms fall 2 rise 2

listen lab_stats
    bind 127.0.0.1:8404
    stats enable
    stats uri /stats
    stats hide-version
    # PUBLIC synthetic lab values, never reuse as production credentials.
    stats auth lab:public-lab-only

fixtures.cfg:同じ隔離プロセス内の合成応答

# Synthetic servers in this same isolated process; no external upstreams.
frontend mock_api
    bind 127.0.0.1:9101
    http-request return status 200 content-type text/plain string ready if { path /readyz }
    http-request return status 200 content-type text/plain lf-string "api xff=%[req.hdr(X-Forwarded-For)] forwarded=%[req.hdr(Forwarded)] real=%[req.hdr(X-Real-IP)] proto=%[req.hdr(X-Forwarded-Proto)] host=%[req.hdr(X-Forwarded-Host)] port=%[req.hdr(X-Forwarded-Port)] prefix=%[req.hdr(X-Forwarded-Prefix)]"

frontend mock_web
    bind 127.0.0.1:9102
    http-request return status 200 content-type text/plain string ready if { path /readyz }
    http-request return status 200 content-type text/plain string web

frontend mock_redirect
    bind 127.0.0.1:9103
    http-request return status 302 hdr Location /login

frontend mock_unready
    bind 127.0.0.1:9104
    http-request return status 503 content-type text/plain string not-ready

backend default_http_redirect
    option httpchk GET /readyz
    server redirect 127.0.0.1:9103 check inter 200ms fall 2 rise 2

backend strict_http_redirect
    option httpchk GET /readyz
    http-check expect status 200
    server redirect 127.0.0.1:9103 check inter 200ms fall 2 rise 2

backend tcp_unready
    server unready 127.0.0.1:9104 check inter 200ms fall 2 rise 2

backend http_unready
    option httpchk GET /readyz
    http-check expect status 200
    server unready 127.0.0.1:9104 check inter 200ms fall 2 rise 2

構文確認と機能確認を分ける

コンテナ内の設定配置先を/labとした場合の読取検査です。-cは設定を検査して終了し、通常の待受起動はしません。成功してもバックエンドへの接続・TLS・実トラフィックの動作保証にはなりません。

# Read-only validation inside the dedicated lab container; no service reload.
haproxy -vv
haproxy -c -f /lab/haproxy.cfg -f /lab/fixtures.cfg

次も同じ専用コンテナ内だけで実行する機能確認です。BusyBoxのsh/wget/grep/base64を使い、実サーバーや公開IPへは接続しません。設定検査とは別に、起動後の応答を検査します。

# Run only INSIDE the dedicated network-none lab after both config files load.
set -eu
base=http://127.0.0.1:8080
auth="Authorization: Basic $(printf '%s' 'lab:public-lab-only' | base64)"
attempt=0
until wget -q -O - "$base/api" | grep -q '^api xff=127.0.0.1'; do
    attempt=$((attempt + 1))
    test "$attempt" -lt 20
    sleep 1
done
for path in /api /api/ /api/users '/api?x=1'; do
    wget -q -O - "$base$path" | grep -q '^api xff=127.0.0.1'
done
for path in / /apix /apiary /API; do
    test "$(wget -q -O - "$base$path")" = web
done
body=$(wget -q -O - --header 'X-Forwarded-For: 203.0.113.77' \
    --header 'Forwarded: for=203.0.113.77' \
    --header 'X-Real-IP: 203.0.113.77' \
    --header 'X-Forwarded-Host: evil.invalid' \
    --header 'X-Forwarded-Port: 9' \
    --header 'X-Forwarded-Prefix: /evil' \
    --header 'X-Forwarded-Proto: https' "$base/api")
test "$body" = 'api xff=127.0.0.1 forwarded= real= proto=http host= port= prefix='
denied=$(wget -S -O - http://127.0.0.1:8404/stats 2>&1 || true)
printf '%s' "$denied" | grep -q 'HTTP/1.1 401'
csv=$(wget -q -O - --header "$auth" 'http://127.0.0.1:8404/stats;csv')
printf '%s' "$csv" | grep -q '^# pxname,svname,'
test "$(wget -q -O - "$base/stats")" = web
printf '%s\n' 'PASS loopback routing, forwarded identity and stats authentication'

専用テストは同じ2設定で新規プロセスを起動し、コンテナ内のHTTPだけで以下を確認します。一般のHAProxyサービスを停止/再起動せず、検査後はテスト自身が作ったコンテナだけを除去します。

入力・観測この教材の期待結果
/api、/api/、/api/users、/api?x=1APIへ。pathはqueryを含まない
/apix、/apiary、/API、/Webへ。大文字小文字を区別する
偽のX-Forwarded-For / Forwarded / X-Real-IP申告値を除去し、直接の接続元127.0.0.1をX-Forwarded-Forへ上書き
/statsの未認証・誤認証 / 合成認証401 / 200。外部向けポートなし
HTTP検査の302 / expect status 200での302既定ではUP / 明示200ではDOWN
503を返すHTTPサーバへのTCP検査 / HTTPで200限定検査TCP接続だけならUP / HTTP検査ではDOWN

/api境界はここでは正規化していないpath文字列に対する判定です。%2F、連続スラッシュ、アプリ独自のURL正規化や認可まで安全と保証しません。前後の層でURL解釈を揃え、APIの認証・認可は別に実装します。

readinessと可用性の限界

checkだけは通常TCP接続検査で、HTTPが200を返すこととは異なります。option httpchkの既定の成功は2xxと3xxなので、認証画面への302でも正常扱いになり得ます。本例はGET /readyz・HTTP/1.1・Hostとexpect status 200を指定しています。実アプリではreadinessが何を確認するか、仮想HostやTLSの条件、検査の負荷とtimeoutを決めます。200でも依存DB・書込み・全機能の成功を意味するとは限りません。

fall/riseは連続失敗/成功による判定に関わります。DOWN検知には時間がかかり、既存接続や失敗した要求を必ず別サーバーでやり直せるわけではありません。再送は注文等の重複実行を招き得ます。本例は各backendが1台なので、故障時の代替先はなく503になり得ます。実LB冗長化・フェイルオーバー・無停止は未検証です。

転送元IPと運用変更の境界

IP以外の申告もそのまま信頼しません。このHTTP検体はX-Forwarded-Host / Port / Prefixを除去し、X-Forwarded-Protoを実際のhttpに固定します。Host自体の許可検査やアプリのURL生成規則は別に必要です。前段TLS終端やpath変換を追加する場合は、信頼する層と受渡すヘッダーの規約を再設計します。

新例はHAProxyへクライアントが直接接続する前提で、転送元ヘッダーを除去/上書きします。CDN等の前段がある場合、このままではCDNのIPになります。許可した中継元だけから受ける設計、ヘッダーの付与/解釈規約とアプリの信頼設定を合わせ、外部申告の左端IPを無条件に採用しません。TLSや認証を本例が自動付加するわけでもありません。

reloadは配布環境のunitやmaster-worker構成によって反映方法が異なり、restartと同義ではありません。対象ファイルの退避、同じ起動引数での構文検査、承認、反映後の応答/ログ/プロセス確認、切戻しを事前に計画します。この隔離試験では実サービスのreload/restartや旧版の公開statsへアクセスしていません。

比較表を読むとき

HAProxy 3.2にはhttp-request returnのstring/file等で固定応答を返す機能があります。「静的ファイルを一切返せない」とは言えません。ただし汎用Webサーバーの静的配信機能と同一ではありません。nginxとの優劣や固定の処理性能をこの小さな教材から推定しないでください。

公式資料と確認範囲(2026年10月26日)

HAProxy公式の保守ブランチ一覧で3.2 LTSを確認。対象ブランチのHTTP検査、成功条件、path、転送元ヘッダー、統計認証、固定応答、構文検査・プロセス管理を参照しました。検証は隔離した合成HTTPだけで、本番ネットワーク、OSのsystemd、TLS、実アプリのreadiness、性能の試験ではありません。

この記事の要点
  • HAProxy は TCP / HTTP の負荷分散・中継を行う。性能は負荷条件・設定・計測で確認する
  • 設定は frontend (受け口) と backend (振り分け先サーバ群) に分けて記述するのが基本構造
  • ACL (アクセス制御リスト) を使い、パスやヘッダの条件で backend を切り替える柔軟なルーティングができる
  • 各サーバのヘルスチェックを行い、ダウンしたサーバを自動的に振り分け対象から外す
  • 統計画面 (stats) でリアルタイムの接続数・サーバ状態・エラー率を可視化できるのが運用上の強み

概要

HAProxy (High Availability Proxy) は、TCP および HTTP に対応した高性能なロードバランサ兼リバースプロキシです。Webサービス等の入口で利用できますが、導入だけで処理性能や無停止を保証するものではありません。ロードバランサ としても リバースプロキシ としても機能し、L4 (TCP) と L7 (HTTP) の両方の振り分けに対応します。親項目は 負荷分散・プロキシ・CDN です。

nginx がリバースプロキシ + 静的配信に強いのに対し、HAProxy は負荷分散と振り分けに特化しており、ヘルスチェック・きめ細かい ACL・充実した統計画面など、ロードバランサとしての機能が豊富なのが特徴です。

仕組み

HAProxy の設定は、役割ごとに分かれたセクションで構成されます。中核となるのは frontend と backend です。

  • global: プロセス全体の設定 (最大接続数・ログ出力・実行ユーザなど)。
  • defaults: frontend/backend 共通の既定値 (タイムアウト・モードなど)。
  • frontend: クライアントからの受け口。どのアドレス:ポートで待ち受け、どの条件でどの backend へ渡すかを定義する。
  • backend: 振り分け先のサーバ群。分散アルゴリズム (roundrobin / leastconn 等) とヘルスチェックを定義する。

frontend では ACL (Access Control List) を使って「このパスなら」「このヘッダなら」という条件を定義し、条件に応じて送り先の backend を切り替えられます。server行のcheck等で検査を有効にした送り先は、設定した失敗/成功回数でDOWN/UPを判定します。検知前や処理途中の要求、残存容量、セッションやDBの状態によっては失敗が続きます。自動フェイルオーバーや無停止を保証する機能ではありません。

設定・実用例

次の旧設定は保存用で、本番へコピー・実行しないでください。bind *:8404 は全アドレス待受で認証もなく、統計情報を露出します。bind *:80 も無制限の待受です。path_beg /api は /apix や /apiary も一致し、/api とその配下だけという意図とは異なります。API側のHTTP検査は既定で2xx/3xxを許可し、Web側のcheckだけではTCP接続検査です。「先に試す隔離用の完成設定(HAProxy 3.2)」を参照し、旧アドレスへ接続しないでください。

global
    maxconn 20000
    log /dev/log local0

defaults
    mode    http
    timeout connect 5s
    timeout client  30s
    timeout server  30s

# 受け口
frontend http_in
    bind *:80

    # ACL: パスが /api で始まるか判定
    acl is_api path_beg /api

    # 条件に応じて backend を切り替え
    use_backend api_servers if is_api
    default_backend web_servers

# API サーバ群 (最小接続方式 + ヘルスチェック)
backend api_servers
    balance leastconn
    option httpchk GET /healthz
    server api1 10.0.0.31:8000 check
    server api2 10.0.0.32:8000 check

# Web サーバ群 (ラウンドロビン + 重み付け)
backend web_servers
    balance roundrobin
    server web1 10.0.0.41:80 check weight 3
    server web2 10.0.0.42:80 check weight 1

# 統計画面 (運用監視用)
listen stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 5s

次の旧コマンドも保存用で、そのまま本番実行しないでください。reloadはrestart(停止して起動)ではありません。実サービスのunit・起動引数・対象ファイルとreloadの実装を確認し、退避・構文検査・承認後の反映・新旧プロセス/実応答の確認・切戻しを分けます。構文成功だけでは到達性や無停止を証明できません。この教材ではsystemctlも本番reload/restartも実行しません。

# 設定ファイルの構文チェック
haproxy -c -f /etc/haproxy/haproxy.cfg

# 反映 (systemd 環境)
sudo systemctl reload haproxy

旧手順の http://<HAProxyのIP>:8404/stats は外部アクセス先として使用しません。統計は接続数・状態・累積エラーカウンタ等を示しますが、カウンタを時間で割らずにエラー率と読み替えないでください。

主な用途

  • 大規模な負荷分散: 複数バックエンドへ要求を分散する。実効性能はTLS・接続特性・アプリ等を含めて測定する。
  • TCP レベルの中継 (L4): HTTP 以外 (データベース接続・MQ など) も mode tcp で負荷分散できる。
  • 条件付きルーティング: ACL でパス・ホスト・ヘッダ別に backend を切り替える。
  • 高可用性: ヘルスチェックで故障機を自動切り離しし、サービス継続性を高める。
  • 運用監視: 統計画面で接続状況・サーバ状態を可視化し、障害の早期発見に使う。

nginx との比較

観点HAProxynginx
得意分野負荷分散・振り分けに特化リバプロ + 静的配信
対応レイヤL4 (TCP) / L7 (HTTP)主に L7 (HTTP) ※stream で L4 も可
ヘルスチェックTCP接続検査・HTTP検査等を設定で選ぶ版・module・Open Source/Plusで検査方式を確認
統計画面標準で stats 画面あり標準は簡易 (status のみ)
静的配信http-request returnで固定応答やfile指定が可能。汎用静的Webサーバとの用途・制限は別途比較得意

注意点

  • 統計画面の保護: /stats は内部情報を晒すため、認証・アクセス元制限を必ずかける。外部公開は厳禁。
  • タイムアウトの設定漏れ: timeout を適切に設定しないと、滞留したコネクションがリソースを食い潰す。
  • SSL 終端の負荷: HAProxy で TLS 終端する場合は CPU 負荷が上がる。証明書と暗号スイートの選定に注意する。
  • クライアント IP の引き継ぎ: option forwardfor はヘッダー付与であって送信元の真正性を保証しない。外部入力を信頼せず、信頼する中継元・上書きする層・アプリのtrusted proxyとバックエンドへの到達制限を合わせる。
  • 単一障害点: HAProxyが1台なら入口自体が単一障害点になり得る。複数LB、VIP/経路の切替、障害検知、残存容量、データとセッションの継続を別々に設計する。keepalived等を置くだけで切替成功や無停止を保証しない。

関連リンク

子ページ

子ページはありません

同階層のページ
  1. フォワードプロキシ
  2. リバースプロキシ
  3. ロードバランサ
  4. nginxリバースプロキシ設定
  5. HAProxy
  6. CDN