HAProxyによるL4負荷分散実装
お伝えしたいこと
Linuxにインストール可能なオープンソースソフトウェアのロードバランサーであるHAProxyについて、以下のトピックをご紹介します。
- 概要
- インストール手順
- L4ロードバランスの実装手順
- お伝えしたいこと
- HAProxyとは
- (参考) HAProxyの有償版について
- (参考) えんでぃ目線のHAProxyの使い方
- HAProxyの構成
- (参考) Keepalivedの概要
- HAProxyのセットアップ手順サンプル
- (参考) Keepalivedのステータス確認
- (参考) HAProxyのステータス確認
- 参考URL
HAProxyとは
HAProxyにはざっくりOSS版と商用版があります。 本記事では、単にHAProxyと記載した場合はOSS版を指すものとします。
HAProxyはTCP, HTTP, HTTPSをサポートするロードバランサーです。 つまりHAProxyは対象の通信を一度受信し、配下のサーバ群に対して負荷が分散するよう通信を転送するネットワーク機器です。
HAProxyがサポートする機能を一部のみ抜粋します。
BIG-IP用語でいうとtcp/http/client-ssl/server-ssl profileとsnatに近い機能を持ちます。
(HAProxy 3.1 Starter Guide - #What HAProxy is and isn't)
- TCP (L4) ロードバランシング (UDPのロードバランシング機能はない)
- HTTP/HTTPS (L7) ロードバランシング
- SSL/TLS オフロード/イニシエイト (HTTPS通信を受信・復号してHTTPで転送したり、再暗号化してHTTPSで転送したりできる)
- ヘッダ情報に応じた通信制御 (例: URLによる負荷分散先の切り替え)
- 透過型フォワードプロキシ
- 負荷分散時の送信元NAT (デフォルト有効。無効化することも可能)
一方で、サポートしない機能は以下の通りです。
- UDPロードバランシング (代替選択肢: Keepalivedなど、Linux Virtual Serverベースのロードバランサー)
- 明示型フォワードプロキシ (代替選択肢:
squid) - DSR (Direct Server Return)
ここに記載した情報は全量ではないので、詳細が気になる方は上記リンク先の公式情報を参照してください。
(参考) HAProxyの有償版について
HAProxy Technologies, LLCは、OSS版のHAProxyをベースとした製品をいくつか販売しています。
製品の1つであるHAProxy EnterpriseはHAProxyの有償版とも言うべきソフトウェアロードバランサーで、OSS版よりも多くの機能をサポートしています。 追加機能にはUDPロードバランシングも含まれます。
詳細はFeature comparison tableの比較表をご覧ください。
(参考) えんでぃ目線のHAProxyの使い方
あくまで私の場合ですが、「KubernetesでControl-plane Nodesを冗長化したい」など、非クラウドのローカル検証環境にて簡易的なロードバランサーが欲しくなったときにHAProxyを使いました。 このユースケースであれば、本記事で紹介するHAProxyのL4負荷分散機能で十分にカバーできます。
HAProxyの構成
簡易構成図と用語説明
今回はHTTPクライアント 1台、HAProxyロードバランサー (LB) 1台、HTTPサーバ 2台の構成でTCPロードバランシングを実装してみます。

構成上のポイントは2つあります。 2のこだわりポイントを実現するために、今回はHAProxyに加えてKeepalivedという別ソフトも併せてインストールします。
- 全てのホストを同一ネットワークに構築した (設計・実装の難易度を下げるため)
- LB VIP (front_endの待ち受けIP) をfloating IPで構成した。つまりLinuxレイヤーでインターフェースに設定していないIPをLB VIPとして使える (こだわりポイント)
Keepalivedとの組み合わせ
多くのLinuxにおいて、デフォルトではOSレイヤーに設定済みのIPアドレスしかVIPとして使えません。
例えば、192.168.0.10/24というIPアドレスを持つLinuxにHAProxyをインストールしたとします。
このLinuxに192.168.0.11:80というTCPソケットをbind (利用登録) し、LB VIPとして使うことはデフォルトではできないことが多いです。
一方で192.168.0.10:80のように、OSレイヤーで持っているIPアドレスであればLB VIPとして使うことが可能です。
LBの設計によっては、NICに設定していないIPアドレスもLB VIPとして設定し、floating VIPを構成したいケースもあると思います。
そんなときに役立つのが以下2つの設定です。
(※) 私はまだ検証していませんが、VRRPでLBを冗長化することも可能です
sysctlによりnet.ipv4.ip_nonlocal_bind=1というkernel parameterを設定することで、NICに設定していないIPを含むソケットのbindを許可する- KeepalivedによりVRRPを構成することで、VRRP VIPを生成する。1の設定と合わせることで、このVRRP VIPをHAProxy側でLB VIPとして設定できる
なお、上記2つの設定なしでもNIC上に複数のIPアドレスを設定することでもHAProxyに複数IPのLB VIPを設定することが可能です。 LB冗長化に対応しない簡易的な設定方法ですが、既存のネットワークの制約でVRRPを使いたくないときなどに役立つかもしれません。
(参考) Keepalivedの概要
Keepalivedは大きく分けて2つの機能を持ちます。
1と2の機能はそれぞれ独立して実装できます。 例えば1に関連する情報だけを設定ファイルに記述した場合はVRRPのみ動作し、L4ロードバランシングは動作しません。
今回のケースでは、KeepalivedのVRRP機能のみが必要です。 したがって、設定ファイルにもVRRPに関連する設定のみ記述します。
なお2のL4ロードバランシングについては、全体的にHAProxyと比較すると簡易的な機能です。 ヘルスチェックと負荷分散は可能なので、簡易的な負荷分散のみを実装するのであればKeepalivedだけで完結できます。 特に (無償版の) HAProxyはUDPの負荷分散に対応していないので、UDPの負荷分散がどうしても必要な場合はKeepalivedの利用を検討すると良さそうです。
HAProxyのセットアップ手順サンプル
では、実際のセットアップ手順のサンプルを示したいと思います。 今回実装する構成を再掲します。

全てのホストがCentOS Stream 9である前提で手順を紹介します。
Linuxの基本設定
本手順はLBとWEBサーバに対して実行します (lb1, web1, web2)。以下の流れで作業します。
私の環境は以下の構成になっています。 環境の前提が異なる方は必要に応じて読み替えてください。
ens3インターフェースを使う192.168.0.1がデフォルトゲートウェイかつDNSサーバである- デフォルトゲートウェイからインターネットに出られる
- シリアルコンソール接続して操作している (
nmcli deleteでネットワーク疎通が切れる手順になっています。困る方はアレンジしてください)
以下はLBの手順です。 2台のWEBサーバについても、ホスト名とIPアドレスを読み替えつつ同様に設定します。
sudo hostnamectl set-hostname lb1.test sudo nmcli connection delete ens3 sudo nmcli connection add autoconnect yes type ethernet ifname ens3 con-name ens3 ipv4.method manual ipv4.addresses 192.168.0.10/24 ipv4.gateway 192.168.0.1 ipv4.dns 192.168.0.1 sudo nmcli connection up ens3 sudo firewall-cmd --add-port 80/tcp --permanent sudo firewall-cmd --reload
以降の手順は各LinuxサーバにSSHログインして実行できます。
Keepalivedのセットアップ
本手順はLBに対してのみ実行します (lb)。
以下の流れで作業します。
- Keepalivedのインストール
- Keepalived設定ファイルの更新 (VRRP VIP
192.168.0.100の作成) - Keepalivedサービスの起動
# 1 # sudo firewall-cmd --add-protocol vrrp --permanent # sudo firewall-cmd --reload # 2 sudo dnf -y install keepalived # 3-1 sudo mv -i /etc/keepalived/keepalived.conf{,.orig} sudo mkdir /etc/keepalived/conf.d cat << EOF | sudo tee /etc/keepalived/keepalived.conf > /dev/null vrrp_track_process haproxy { process haproxy quorum 1 weight 0 } include /etc/keepalived/conf.d/*.conf EOF # 3-2 cat << EOF | sudo tee /etc/keepalived/conf.d/10_vrrp_web.conf > /dev/null vrrp_instance web { virtual_router_id 2 state MASTER interface ens3 virtual_ipaddress { 192.168.0.100 } priority 255 track_process { haproxy } } EOF # keepalived -t ; echo $? # 4 sudo systemctl enable keepalived.service --now # 5 journalctl -eu keepalived.service -g state
コメント行に書かれた番号は、本セクションの冒頭に記載した「手順の流れ」の項番と対応しています。
以下、参考情報としていくつかの操作内容について補足します。
# 1
# 3-1
- デフォルトの
/etc/keepalived/keepalived.confには不要な設定が多数あるので、一旦退避した - VRRP VIPが増えた場合も設定ファイルの見通しを良くするため、用途に応じてファイルを分割する構成とした (->
include) - Keepalived全体に影響を与えるようなグローバル設定のみ本ファイルに直接記述した
グローバル設定としては、以下の内容を実装した。
- 「Keepalivedは同じLinux上で動作する
haproxyプロセスを監視し、haproxyが起動していなかった場合にVRRPステータスをFAULTに遷移する」設定を追加した - この設定がなくてもVRRPとしては最低限動作する
vrrp_track_processブロック配下の設定の意味は、それぞれ以下のとおりです。
| オプション | 意味 |
|---|---|
process <str> |
指定した名前のプロセスが起動しているか否かを監視する |
quorum <int> |
指定した数のプロセス数が起動していたら監視成功。 そうでなければ失敗 |
weight <int> |
整数値を指定する。 正の数を指定すると、監視成功時にpriorityが加算される。 負の数を指定すると監視失敗時にpriorityを減算する。 0を指定すると監視失敗時にVRRPインスタンスが失敗する。0 reverseを指定すると監視成功時にVRRPインスタンスが失敗する。デフォルトは 1 |
# 3-2
- VRRPインスタンス設定を投入する
- VRRP ID、VRRP VIP、Priorityなど、一般的なVRRP設定を一通り指定する
# 2-1で設定したtrack設定を紐付けることで、trackの成否をVRRP状態と連動させる
vrrp_instanceブロック配下の設定の意味は、それぞれ以下のとおりです。
| オプション | 意味 |
|---|---|
virtual_router_id <int> |
VRRP ID (1〜255) の指定。 VRRP冗長化する2インスタンス間では値を揃える。 詳細はVRRPの標準仕様を調べること |
state <str> |
VRRPのステータス初期値。MASTER: priorityが255の場合に即時MASTERに昇格する。BACKUP: BACKUPで起動し、3秒間のネゴシエーションの末MASTERに昇格。今回はシングル構成なのでVIP起動を早めるため state MASTERかつpriority 255とした。冗長化する場合は起動時のIP重複を避けるため priority 150など即昇格を避けるべきかも |
interface <str> |
VRRPを動作させるインターフェース名を指定する |
virtual_ipaddress {...} |
VRRP VIP (Virtual IP) を指定する。 CIDR形式で記述できるが、Prefix長を省略してホストIPとするのが一般的 (参考) |
priority <int> |
VRRP Priority。 値が大きいほど優先的に MASTERに昇格しやすくなる。nopreempt設定と密に関係する |
track_process {...} |
# 2-2で設定したvrrp_track_process設定名を指定。指定したtrack設定を有効化する。 有効化により、trackの成否が priorityやstateが連動するようになる |
nopreempt |
preemptを無効化する設定。 デフォルトはpreempt有効。 preemptが有効の場合、既存の MASTERよりも自身のpriorityが大きいときにMASTERを交代する。preemptが無効の場合は既存の MASTERを維持する。preemptを言い換えると自動フェイルバック設定 |
設定値の詳細はman keepalived.confを参照してください。
最後にコメントアウトされた以下のコマンドは、確認用です。
keepalived -tはconfig testを意味しており、keepalivedを起動せず設定ファイルの確認のみ行います。
Exit statusが0であれば正常で、それ以外の値であれば設定ファイルにエラーが存在します。
echo $?は、直前のkeepalived -tのExit statusを表示するコマンドです。
keepalived -t ; echo $?
HAProxyのセットアップ
本手順はLBに対してのみ実行します (lb1)。
以下の流れで作業します。
- HAProxyのインストール
net.ipv4.ip_nonlocal_bind = 1のsysctl設定を追加し、VRRP VIPをLB VIPとして使えるようにする- (必要に応じて) SELinuxの許可設定を有効化する
- HAProxyの設定ファイル更新
- HAProxyのサービス起動
LB VIPが待ち受けているTCP 80ポートは、すでに#Linuxの基本設定で通信許可されています。
# 1 sudo dnf -y install haproxy # 2 cat << EOF | sudo tee /etc/sysctl.d/50_haproxy.conf net.ipv4.ip_nonlocal_bind = 1 EOF sudo sysctl --system # sysctl net.ipv4.ip_nonlocal_bind # 3 # sudo dnf -y install setools-console # sesearch -A -ds -s haproxy_t -p name_bind # seinfo --portcon | grep -P ':(commplex_main_port_t|http_cache_port_t|http_port_t):' | awk '{print $2, $3}' # getsebool haproxy_connect_any # seinfo -x -a port_type # for PORT_T in $(seinfo -x -a port_type | grep -Po '\S+_t$') ; do seinfo --portcon | grep -P ":${PORT_T}:" | awk '{print $2, $3}'; done sudo setsebool -P haproxy_connect_any=True # getsebool haproxy_connect_any # 4 sudo cp -pi /etc/haproxy/haproxy.cfg{,.orig} cat << EOF | sudo tee /etc/haproxy/haproxy.cfg > /dev/null global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon # turn on stats unix socket stats socket /var/lib/haproxy/stats stats timeout 2m # utilize system-wide crypto-policies ssl-default-bind-ciphers PROFILE=SYSTEM ssl-default-server-ciphers PROFILE=SYSTEM defaults tcp mode tcp log global maxconn 3000 option dontlognull retries 3 timeout check 10s timeout client 1m timeout connect 10s timeout queue 1m timeout server 1m defaults http from tcp mode http option httplog option http-server-close option forwardfor except 127.0.0.0/8 option redispatch timeout http-request 10s timeout http-keep-alive 10s EOF cat << EOF | sudo tee /etc/haproxy/conf.d/web.cfg > /dev/null frontend web_http from tcp description Web Servers (HTTP) bind 192.168.0.100:80 default_backend web_http backend web_http from tcp description Web Servers (HTTP) server web1 192.168.0.11:80 check server web2 192.168.0.12:80 check EOF # haproxy -c -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d # 5 systemctl enable haproxy.service --now
以下、詳細を補足します。
# 3
この手順では、SELinuxの許可設定を追加しています。 今回の構成では不要なのですが、LB VIPに割り当てるポート番号によっては必要となります。
また、そもそもSELinuxをpermissiveモードに変更するなどしてSELinuxの防御を無効化している場合には、この設定は不要です。
(参考) SELinuxのステータス
前半のコメントアウト部分は、全て現状のSELinuxルールを確認するための確認コマンドです。
最初は以下の操作を実施しています。
最後のseinfoコマンドで出力されたポート番号は、HAProxyがデフォルトでLB VIPとして設定可能なポート番号です。
今回はtcp 80のLB VIPを作れれば良いので、デフォルト構成のままでも動作します。
- SELinuxの確認コマンドを実行するため、必要なrpmパッケージをインストールする (
setools-console) haproxyプロセスがbind可能なポート番号を調査する (sesearch,seinfo)
sudo dnf -y install setools-console sesearch -A -ds -s haproxy_t -p name_bind # allow haproxy_t commplex_main_port_t:tcp_socket { name_bind name_connect }; # allow haproxy_t http_cache_port_t:tcp_socket { name_bind name_connect }; # allow haproxy_t http_port_t:tcp_socket { name_bind name_connect }; # allow haproxy_t port_type:tcp_socket name_bind; [ haproxy_connect_any ]:True getsebool haproxy_connect_any # haproxy_connect_any --> off seinfo --portcon | grep -P ':(commplex_main_port_t|http_cache_port_t|http_port_t):' | awk '{print $2, $3}' # tcp 10001-10010 # tcp 443 # tcp 488 # tcp 5000 # tcp 80 # tcp 8008 # tcp 8009 # tcp 8080 # tcp 81 # tcp 8118 # tcp 8123 # tcp 8443 # tcp 9000 # udp 3130 # udp 5000
上記以外のポート番号をbindする要件がある場合は、以下のコマンドを実行してください。
追加で許可できるポート番号がfor文で表示されます。
seinfo -x -a port_type # # Type Attributes: 1 # attribute port_type; # afs3_callback_port_t # afs_bos_port_t # 以下略 for PORT_T in $(seinfo -x -a port_type | grep -Po '\S+_t$') ; do seinfo --portcon | grep -P ":${PORT_T}:" | awk '{print $2, $3}'; done # tcp 7001 # udp 7001 # udp 7007 # 以下略 sudo setsebool -P haproxy_connect_any=True getsebool haproxy_connect_any # haproxy_connect_any --> on
一連のSELinux操作についてもっと詳しく理解したい方は、以下の記事をご覧ください。
SELinuxの実践
今回扱った操作に関連する部分だけ拾い読みするなら、Boolean有無の確認と(参考) SELinuxの確認コマンドをご確認ください。
# 4
本手順では、まずオリジナルの/etc/haproxy/haproxy.cfgをベースにして以下のように書き換えています。
まずはglobalセクションです。
globalセクションにはHAProxy全体の基本設定が入っています。
globalセクションの設定はほぼ書き換えていません。
ただ唯一、stats timeout 2mという設定のみ書き換えました。
HAProxyの対話プロンプトを開いてステータス確認などを行う際のセッションタイムアウトをデフォルトの5秒から2分に延長するための便利設定です。
詳しくは#(参考) HAProxyのステータス確認で扱います。
globalセクション配下の各設定について、詳細はHAProxy 3.1 Configuration Manual - Global parametersを参照してください。
続いてdefaultsセクションです。
defaultsセクションには、後続のfrontendセクションやbackendセクションのデフォルト値を指定します。
frontend xxx from yyy、backend xxx from yyyのようにfrom yyyの形式でdefaultsセクション名を指定することで、yyyセクションの設定をデフォルト値として参照するようになります。
HAProxyの負荷分散設定はざっくりL4ロードバランシング (mode tcp) とL7ロードバランシング (mode http) の2種類が存在することを想定し、今回もtcpとhttpという2種類のdefaultsセクションを定義しました。
インストール時に初期設定されていたdefaults設定はmode httpを想定した設定でしたが、今回はその設定をtcpとhttpの2つに分割しました。
そしてdefaults tcpセクションにはTCPの設定のみを指定し、defaults http from tcpセクションにはHTTPの設定のみを指定しました。
defaults http from tcpセクションはdefaults tcpセクションの設定を踏襲するので、結果としてオリジナルのdefaultsセクションと全く同じ設定値になります。
(BIG-IP用語でいうと、デフォルトのtcp profileとhttp profileの作成に相当します)
本件のハンズオンではdefaults tcpセクションしか使わないものの、将来的にはdefaults http from tcpセクションが役立つときが来るかもしれません。
TLSオフロード/TLSイニシエイトを実装したくなった場合は、新たにdefaults https from httpセクションを作成して設定を拡張できる想定です。
続いて/etc/haproxy/conf.d/web.cfgという設定ファイルですが、ここには今回のハンズオンで使用する負荷分散設定を実装しました。
frontendセクションにはLB VIPの設定を指定します。
(BIG-IP用語ではVirtual Serverに相当します)
frontendセクションで使ったオプションは以下の通りです。
HAProxy 3.1 Configuration Manual - Proxy keywords matrix
| オプション | 意味 |
|---|---|
| description | 説明文。 任意の文字列を指定可能 |
| bind | LB VIPの設定 (待ち受けIPアドレスとポート番号) |
| default_backend | frontendと紐付けるbackend名を指定。結果として負荷分散先のサーバが決まる |
backendセクションには負荷分散先のサーバへの転送設定を指定します。
(BIG-IP用語ではpoolに相当します)
backendセクションで使ったオプションは以下の通りです。
HAProxy 3.1 Configuration Manual - Proxy keywords matrix
HAProxy 3.1 Configuration Manual - Server and default-server options
| オプション | 意味 |
|---|---|
| description | 説明文。 任意の文字列を指定可能 |
| server | 負荷分散先サーバの転送先IPアドレスとポート番号。 checkを指定するとヘルスチェックが有効になる (デフォルト無効)。 デフォルトでは tcpかtlsによるヘルスチェックとなる |
| source | backendに転送する際の送信元IP指定。 デフォルトではLBのIPアドレスに送信元NATされる。 デフォルトの送信元ポート番号はEphemeral Portとなる。 ヘルスチェックもデフォルトで同様の挙動。 送信元IP/ポート番号変換を無効化することも可能 |
Webサーバのセットアップ
本手順はWEBサーバ (web1, web2) に対してのみ実行します。
以下の流れで作業します。
http通信のためのTCP 80ポートは、すでに#Linuxの基本設定で通信許可されています。
# 1 sudo dnf -y install httpd # 2 sudo systemctl enable httpd.service --now # 3 echo "${HOSTNAME}" | sudo tee /var/www/html/index.html > /dev/null # curl localhost
最後のcurl localhostを実行すると、index.htmlに記述されたホスト名が返ってくる想定です。
疎通確認
では、最後にクライアントPCから疎通確認してみましょう。
今回はcurlを使っていますが、環境によってはブラウザアクセスでご確認いただいても結構です。
複数回アクセスすると、負荷分散によりweb1とweb2に対して交互に転送されていることがわかります。
curl 192.168.0.100 # web1.test curl 192.168.0.100 # web2.test
(参考) Keepalivedのステータス確認
以下のようにstateキーワードでログを検索することで、VRRPのステータス遷移を確認できます。
journalctl -eu keepalived.service -g state # Apr 03 00:24:16 lb1.test Keepalived_vrrp[1546]: (web) Entering FAULT STATE # Apr 03 00:24:16 lb1.test Keepalived_vrrp[1546]: (web) Entering BACKUP STATE # Apr 03 00:24:19 lb1.test Keepalived_vrrp[1546]: (web) Entering MASTER STATE # Apr 03 00:24:36 lb1.test Keepalived_vrrp[1567]: (web) Entering MASTER STATE
ちなみに4行のログは、それぞれ以下のコマンドにより発生しました。
sudo systemctl restart haproxy.serviceを実行したことで、Keepalivedがhaproxyプロセスの障害を検知してFAULT > BACKUP > MASTERと遷移 (FAULTに遷移した場合は、state MASTERかつpriority 255に設定していても一度BACKUPになるようです)sudo systemctl restart keepalived.serviceを実行したことで、MASTER > (停止) > MASTERと遷移。サービス起動直後にMASTERに遷移するのはstate MASTERかつpriority 255に設定したため
sedコマンドでより簡潔な形に整形することもできます。
journalctl -eu keepalived.service -g state | sed -Ee 's/(.{15}).* \((\S+)\) entering (\S+) state(.*)/\1 | \2 -> \3\4/i' # Apr 03 00:24:16 | web -> FAULT # Apr 03 00:24:16 | web -> BACKUP # Apr 03 00:24:19 | web -> MASTER # Apr 03 00:24:36 | web -> MASTER
また、ipコマンドでもVRRPのステータスをうかがい知ることができます。
VRRP MASTERのときしかVRRP VIPが表示されないことから、VRRPの状態を察知できます。
以下のように、haproxyサービスを停止することで意図的にVRRPインスタンスをFAULT状態に遷移させると、VRRP VIP (192.168.0.100/24) が見えなくなることがわかります。
sudo systemctl stop haproxy.service ip -br address show # lo UNKNOWN 127.0.0.1/8 ::1/128 # ens3 UP 192.168.0.10/24 fe80::b4e3:96cd:51f2:6fb7/64 # ens4 DOWN # ens5 DOWN sudo systemctl start haproxy.service ip -br address show # lo UNKNOWN 127.0.0.1/8 ::1/128 # ens3 UP 192.168.0.10/24 192.168.0.100/24 fe80::b4e3:96cd:51f2:6fb7/64 # ens4 DOWN # ens5 DOWN
(参考) HAProxyのステータス確認
CLIによるステータス確認
HAProxy 3.1 Configuration Manual - stats socket
/etc/haproxy/haproxy.cfgにstats socket /var/lib/haproxy/statsという設定行があります。
この設定により、HAProxyはUNIXソケットファイルを生成します。 UNIXソケットファイルに接続することで、ネットワーク機器に対して専用コマンドを実行するかのように設定変更やステータス確認コマンドを実行できます。
HAProxy 3.1 Management Guide - Unix Socket commands
UNIXソケットファイルに接続してステータスを確認してみましょう。 手順は以下のとおりです。
sudo dnf -y install socat socat /var/lib/haproxy/stats readline prompt show backend # web_http show servers state web_http # 3 web_http 1 web1 192.168.0.11 2 0 1 1 277 6 3 4 6 0 0 0 - 80 - 0 0 - - 0 # 3 web_http 2 web2 192.168.0.12 2 0 1 1 277 6 3 4 6 0 0 0 - 80 - 0 0 - - 0
使ったコマンドは以下のとおりです。
| コマンド | 意味 |
|---|---|
| prompt | 対話モード・非対話モードを切り替える。 とりあえず最初に実行する |
| show backend | backend名を一覧表示する |
| show servers state | backendのステータス表示。 6列目がステータスで、 2が起動状態を表す。0は停止状態、1は起動中、3は停止中 |
このままだと少々見づらいので、Linuxコマンドで整形しましょう。
まず基礎知識として、以下のようにsocatでstdioと接続することで、非対話形式でコマンドを実行できます。
echo 'show servers state web_http' | socat /var/lib/haproxy/stats stdio # 3 web_http 1 web1 192.168.0.11 2 0 1 1 769 6 3 4 6 0 0 0 - 80 - 0 0 - - 0 # 3 web_http 2 web2 192.168.0.12 2 0 1 1 769 6 3 4 6 0 0 0 - 80 - 0 0 - - 0
この形式であれば整形できますね。cutコマンドで1〜6列目のみを取り出しつつ、column -tで列の間隔を揃えて表示します。
echo 'show servers state web_http' | socat /var/lib/haproxy/stats stdio | sed 's/^# /#/' | cut -d' ' -f 1-6 | column -t # #be_id be_name srv_id srv_name srv_addr srv_op_state # 4 web_http 1 web1 192.168.0.11 2 # 4 web_http 2 web2 192.168.0.12 2
だいぶ見やすくなりましたね。
srv_op_stateが2なので、負荷分散先のサーバへのヘルスチェックは成功しており、通信可能であることがわかります。
GUIによるステータス確認
(参考元: Exploring the HAProxy Stats Page (What You Should Know))
先ほどのCLI手順でも登場したHAProxyのStatsを、今度はWEB画面で確認する手順を紹介します。
ポート番号は80にしていますが、別の番号にしたい場合は8080や8008などでも良いかもしれません。
これらのポート番号であればデフォルトのSELinuxポリシーで許可されますが、80以外を使う場合はfirewalldの穴あけが必要です。
今回の設定ではstats admin if TRUEによってGUIアクセス時にHAProxyの操作権限が付与されます。
つまりGUI上で負荷分散先Serverの無効化 (BIG-IP風に言えばPool member無効化) などの操作が行なえます。
stats admin if TRUEをstats admin if LOCALHOSTに置き換えることで、リモートログイン時には特権なしにできますので、お好みでアレンジしてください。
cat << EOF | sudo tee /etc/haproxy/conf.d/stat.cfg > /dev/null frontend stats mode http bind *:80 stats enable stats uri / stats admin if TRUE # stats refresh 10s EOF # sudo firewall-cmd --add-port 80/tcp --permanent # sudo firewall-cmd --reload systemctl restart haproxy.service
上記設定を入れた上で、HAProxyのIPアドレス (LB VIPではありません。今回の場合はhttp://192.168.0.10) にクライアントPCのブラウザからHTTPアクセスすると、GUIダッシュボードを確認できます。
ピンク色の枠で囲んだように、緑色のセルから直感的にサーバがUpしていることがわかりますし、Status列からも同様な情報を確認できます。 検証においては便利だと思います。

以上でHAProxy + Keepalived構成のデモは終わりです。 お疲れ様でした。
参考URL
- さくらのナレッジ - 多機能なロードバランサとして使える多機能プロクシサーバー「HAProxy」入門
- とてもわかりやすい
- HAProxyの概要とL7 (HTTP) ロードバランシングの設定例の説明
- さくらのナレッジ - 多機能プロクシサーバー「HAProxy」のさまざまな設定例
- YouTube - The Essentials of an HAProxy Configuration File | Easy to Follow Tutorial
- HAProxy公式動画
- 動画で学習したい方に (英語)
- HAProxy Documentation
- HAProxyの公式ドキュメント。3種類のドキュメントがある
- Starter Guide: HAProxyの機能一覧。具体的な操作手順は書かれていない。セクション2の "Quick Introduction" は一般知識のため、読み飛ばしても問題ない
- Configuration Manual: 設定ファイルの仕様が全て書かれている。セクション1の "Quick reminder" は読み飛ばしても問題ない
- Management Guide: 拾い読み推奨。Configuration Manualでもカバーされていないような詳細仕様やトラブルシューティング情報が書かれている
- Keepalived User Guide
- Keepalivedの公式ドキュメント