2026年6月5日

2026年6月5日

HAProxy を Auto Scaling と連携する方法|DNS検出・Runtime API・安全な縮退の手順

HAProxy を Auto Scaling と連携させるには、増減するバックエンドサーバーを HAProxy に自動で反映させる仕組みが必要です。代表的な方法は、DNS でサーバー一覧を引く server-template、稼働中に設定を変える Runtime API(または Data Plane API)、設定ファイルを生成して再読み込みする方式の3つです。この記事では、それぞれの仕組みと向いている場面を比べたうえで、DNS 方式の設定例、インスタンス削除時に通信を落とさない手順、WordPress を複数台で動かすときの注意点までを解説します。

なぜ「連携」が必要なのか

Auto Scaling(AWS の EC2 Auto Scaling など)は負荷に応じてサーバーを増減させますが、新しいサーバーの IP アドレスは起動するまで分かりません。HAProxy の設定ファイルに IP を固定で書いていると、増えたサーバーには振り分けられず、減ったサーバーにはリクエストを送り続けてエラーになります。

連携の目標は次の3つです。

  • 増えたサーバーを、準備ができてから振り分け対象に加える
  • 減るサーバーを、処理中のリクエストを終えてから外す
  • これらを人手を介さずに行う

なお、AWS 上で HAProxy 固有の機能(細かいルーティングや独自のヘルスチェック)が不要なら、Application Load Balancer のようにターゲットグループと Auto Scaling が直接連携するマネージドのロードバランサーを使うほうが運用は軽くなります。HAProxy を選ぶ理由がある前提で読み進めてください。

3つの連携方式の比較

方式 仕組み 向いている場面
DNS 検出(server-template) HAProxy が定期的に DNS を引き、返ってきたアドレスを空き枠に割り当てる サービス検出用の DNS(Consul、AWS Cloud Map など)がある
Runtime API / Data Plane API 外部のスクリプトや仕組みが、稼働中の HAProxy にサーバーの追加・状態変更を指示する Auto Scaling のイベントを受けて細かく制御したい
設定生成+再読み込み テンプレートから設定ファイルを作り直し、HAProxy を reload する 構成が単純で、変更頻度が低い

実際には、DNS 検出でサーバーの増減を拾い、削除時の縮退だけ Runtime API で制御する、という組み合わせがよく使われます。

方式1:DNS 検出で増減を自動反映する

HAProxy 1.8 以降では、resolvers セクションで DNS サーバーを定義し、server-template で「最大何台分の枠を用意するか」を指定できます。DNS が返すアドレスの数だけ枠が埋まり、返らなくなった枠は自動で無効になります。

前提として、Auto Scaling で起動したサーバーが自動的に DNS に登録される仕組みが必要です。AWS では Cloud Map(サービス検出)や Consul のエージェントを使う方法が一般的です。通常の Route 53 のレコードは、Auto Scaling と連動して自動更新されるわけではない点に注意してください。

以下は設定の例です。HAProxy のバージョンによって使える記法が異なるため、お使いのバージョンのドキュメントで確認してから適用してください。2.x 系以降を想定しています(2026年10月現在)。設定を変える前に現在の haproxy.cfg をバックアップし、ステージングで試してください。

resolvers vpcdns
    nameserver dns1 10.0.0.2:53        # VPC の DNS(VPC の CIDR の先頭 +2)
    accepted_payload_size 8192
    resolve_retries 3
    timeout resolve 1s
    timeout retry   1s
    hold valid    10s
    hold obsolete 30s

frontend fe_web
    bind :80
    default_backend be_wordpress

backend be_wordpress
    balance roundrobin
    option httpchk
    http-check send meth GET uri /healthz.php ver HTTP/1.1 hdr Host www.example.com
    http-check expect status 200
    default-server inter 3s fall 3 rise 2
    # 最大 20 台分の枠。web.internal.example の A レコードを使う
    server-template web 20 web.internal.example:80 check resolvers vpcdns init-addr none

ポイントは次のとおりです。

  • 枠の数: server-template の数は Auto Scaling の最大台数以上にします。足りないと、あふれたサーバーには振り分けられません。
  • **init-addr none**: 起動時に名前解決できなくても HAProxy を起動させるための指定です。これがないと、DNS が空の状態で起動に失敗することがあります。
  • ヘルスチェック: DNS に登録された直後のサーバーは、まだ PHP や Web サーバーの準備が終わっていない場合があります。rise の回数だけ成功してから振り分けが始まるので、準備前のサーバーにリクエストが流れるのを防げます。
  • SRV レコード: Consul や Cloud Map が SRV レコードを返す場合、server-template web 20 _http._tcp.web.service.consul resolvers ... のように書くと、ポート番号も DNS から取得できます。

方式2:Runtime API で状態を制御する

Runtime API は、HAProxy が待ち受ける管理用ソケットにコマンドを送って、稼働中の状態を変える仕組みです。設定ファイルの global セクションでソケットを有効にします。

global
    stats socket /run/haproxy/admin.sock mode 660 level admin
# サーバーの状態を一覧表示
echo "show servers state be_wordpress" | sudo socat stdio /run/haproxy/admin.sock

# 新しい接続を止め、既存の接続は処理させる(縮退)
echo "set server be_wordpress/web3 state drain" | sudo socat stdio /run/haproxy/admin.sock

# 振り分け対象に戻す
echo "set server be_wordpress/web3 state ready" | sudo socat stdio /run/haproxy/admin.sock

新しいバージョンでは add server / del server でサーバー自体を追加・削除することもできますが、導入されたバージョンや制約があるため、使う前にドキュメントで確認してください。HTTP 経由で同様の操作をしたい場合は、HAProxy の Data Plane API を使う方法もあります。

管理用ソケットは HAProxy を自由に操作できるため、ファイルの権限を絞り、ネットワーク越しに公開しないでください。

方式3:設定ファイルを生成して再読み込みする

consul-template などで、サービスの一覧から haproxy.cfg を生成し、変更があれば systemctl reload haproxy を実行する方式です。仕組みは分かりやすい一方、変更のたびに再読み込みが走ります。master-worker モード(多くのディストリビューションの systemd 設定で既定)であれば、再読み込みで既存の接続が切れにくくなりますが、長時間の接続が多い環境では古いプロセスが残り続けることがある点に注意します。再読み込みの前には haproxy -c -f /etc/haproxy/haproxy.cfg で構文を検査してください。

インスタンス削除時に通信を落とさない

スケールイン(台数の削減)で最も問題になるのは、処理中のリクエストが途中で切れることです。AWS の Auto Scaling では「ライフサイクルフック」を使うと、インスタンスを終了する前に待機時間を設けられます。

  1. Auto Scaling グループに、終了時(autoscaling:EC2_INSTANCE_TERMINATING)のライフサイクルフックを設定する
  2. フックの通知(EventBridge など)を受けた仕組みが、HAProxy の該当サーバーを drain にする
  3. 接続数が0になるか、決めた時間が過ぎるのを待つ
  4. ライフサイクルアクションを完了させ、終了を進める
aws autoscaling complete-lifecycle-action \
  --lifecycle-hook-name wp-terminate-hook \
  --auto-scaling-group-name wp-asg \
  --lifecycle-action-result CONTINUE \
  --instance-id i-0123456789abcdef0

DNS 検出だけで運用している場合でも、DNS の登録解除が先に行われれば HAProxy は次の名前解決でそのサーバーを外します。ただし、TTL や hold の設定の分だけ反映に時間がかかるため、その間にインスタンスが終了しないよう、待機時間を十分に取ってください。

WordPress を複数台で動かすときの注意点

ロードバランサーの連携ができても、WordPress 側が複数台を前提にしていないと不具合が起きます。

  • アップロードファイル: wp-content/uploads がサーバーごとに別だと、画像が表示されたりされなかったりします。共有ストレージ(EFS など)か、メディアをオブジェクトストレージへ置くプラグインを使います。
  • コードの同一性: プラグインやテーマの更新を管理画面から行うと、1台だけが更新されます。デプロイの仕組みで全台をそろえ、本番の管理画面からの更新は止める運用が安全です。
  • WP-Cron: 全台で WP-Cron が動くと処理が重複することがあります。wp-config.php で define( 'DISABLE_WP_CRON', true ); とし、1か所からだけ定期実行します。
  • HTTPS の判定: HAProxy で TLS を終端する場合、WordPress は HTTP で受け取るため、リダイレクトが繰り返されることがあります。HAProxy が X-Forwarded-Proto を付けていることを確認したうえで、信頼できるプロキシ経由のときだけ HTTPS と判定する処理を wp-config.php に入れます。
  • ヘルスチェック用のページ: トップページをヘルスチェックに使うと、負荷が高いときにチェック自体が失敗して全台が外れることがあります。軽い専用のエンドポイントを用意します。

HAProxy 自体の冗長化

バックエンドを自動で増減させても、HAProxy が1台だけだとそこが単一障害点になります。複数台の HAProxy を置き、仮想 IP の切り替え(Keepalived など)や、手前に別のロードバランサーを置く構成を検討してください。クラウドではマルチキャストが使えないなど、Keepalived の構成に制約があるため、利用するクラウドの推奨構成も確認します。

まとめ

  • Auto Scaling 連携の目的は、増えたサーバーを準備後に加え、減るサーバーを処理を終えてから外すこと
  • DNS 検出(resolvers と server-template)が基本で、枠の数は最大台数以上にする
  • 削除時は Runtime API の drain とライフサイクルフックを組み合わせて接続を落とさない
  • WordPress はアップロード・コード・WP-Cron・HTTPS 判定を複数台前提にそろえる
  • HAProxy 自体の冗長化と、マネージドのロードバランサーという選択肢も検討する

お気軽にご相談ください

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