Contents
Overview
HAProxy を使用してロードバランサーを構築します。HAProxy は、無料で非常に高速かつ信頼性の高いリバースプロキシであり、高可用性、ロードバランシング、そして TCP および HTTP ベースのアプリケーションプロキシを提供します。HAProxy は事実上の標準オープンソースロードバランサーです。現在ではほとんどの主流の Linux ディストリビューションに同梱されており、クラウドプラットフォームにおいてもデフォルトで展開されることが多くなっています。
前提条件
- こちらを参考に基本設定が完了していること。
- DualStack (IPv4/IPv6) に対応しています。
- 統計情報 (stats) を HTTPS で有効化しています。オプションとして、iptables を使用して stats へのアクセスを制限することも検討できます。
- HAProxy 自体を冗長構成にするには Keepalived が必要ですが、本稿では取り上げていません。
インストール
haproxy
, apache2-utils
をインストールします。apache2-utils は htpasswd
コマンドを使用するためにインストールしています。
myadmin@ubuntu-22-04:~$ sudo apt -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold install haproxy apache2-utils
パスワードハッシュの生成
htpasswd
コマンドを使用してパスワードハッシュを生成します。本稿の例では、password
を指定していますが、実際は強固なパスワードを使用してください。ここで生成したハッシュは haproxy.cfg で使用します。
myadmin@ubuntu-22-04:~$ htpasswd -nB admin
-n
: このオプションは、結果を標準出力に表示するためのものです。通常、htpasswd
コマンドはパスワードをファイルに保存しますが、-n
オプションを使うと、生成されたパスワードハッシュが標準出力に表示されます。-B
: このオプションは bcrypt 暗号化方式を指定します。bcryptはセキュリティが高く、推奨されるパスワードハッシュ方式です。
/etc/haproxy/haproxy.cfg
/etc/haproxy/haproxy.cfg
を編集します。
デフォルト値
デフォルト値は下記の通りです。
myadmin@ubuntu-22-04:~$ grep -v -e '^\s*#' -e '^\s*$' /etc/haproxy/haproxy.cfg | expand | tr -s [:space:] | sed 's/^\s/ /g'
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
global
:log /dev/log local0
: HAProxy のログを Syslog に送る設定です。local0
はログファシリティの一つで、どのログチャネルに送るかを指定します。log /dev/log local1 notice
: こちらも Syslog にログを送りますが、local1
を使い、ログの重要度をnotice
レベルに設定しています。chroot /var/lib/haproxy
: セキュリティを向上させるために、HAProxy プロセスを/var/lib/haproxy
ディレクトリに閉じ込めます。このディレクトリ以外へのアクセスを制限します。stats socket ...
:HAProxy の統計情報を取得するためのソケットを設定します。mode 660
でパーミッションを設定し、level admin
で管理者レベルのアクセスを提供します。stats timeout ...
: 統計情報のソケット接続のタイムアウトを 30 秒に設定します。user haproxy
: HAProxy を実行するユーザーをhaproxy
に設定します。group haproxy
: HAProxy を実行するグループをhaproxy
に設定します。daemon
: HAProxy をデーモンモードで実行します。バックグラウンドで実行されるようにします。ca-base /etc/ssl/certs
: CA 証明書のベースディレクトリを指定します。SSL/TLS の設定に使用されます。crt-base /etc/ssl/private
: SSL/TLS 証明書のベースディレクトリを指定します。ssl-default-bind-ciphers
: デフォルトの SSL/TLS バインドで使用する暗号スイートを指定します。これにより、セキュアな通信を確保します。ssl-default-bind-ciphersuites
: TLS 1.3 で使用する暗号スイートを指定します。ssl-default-bind-options
: デフォルトの SSL/TLS バインドオプションを設定します。最低 TLS バージョンを 1.2 に設定し、セッションチケットを無効にします。
defaults
:log global
: global セクションで設定したログオプションを継承します。mode http
: デフォルトの動作モードを HTTP に設定します。option httplog
: HTTP ログオプションを有効にします。HTTP リクエストとレスポンスの詳細をログに記録します。option dontlognull
: 空の HTTP リクエストをログに記録しません。timeout connect 5000
: 接続タイムアウトを 5 秒に設定します。timeout client 50000
: クライアント側のタイムアウトを 50 秒に設定します。timeout server 50000
: サーバー側のタイムアウトを 50 秒に設定します。errorfile
: 各エラー時に表示するカスタムエラーページを指定します。
設定値
設定値は以下の通りです。この設定は Kubernetes のマスターノードのバランシングを想定しており、これによりマスターノードに冗長性を持たせます。この例では、s00-int-k8s-master-v001
のみを backend
として指定しており、1 台でも動作しますが、Kubernetes の推奨は 3 台です。利用する台数に応じて行を追加してください。
myadmin@ubuntu-22-04:~$ sudo cp -ai /etc/haproxy/haproxy.cfg{,.orig}
myadmin@ubuntu-22-04:~$ sudo tee /etc/haproxy/haproxy.cfg <<"EOF"
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
ca-base /etc/ssl/certs
crt-base /etc/my-ssl/private
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
listen stats
bind 10.1.0.124:50000 ssl crt /etc/my-ssl/private/si1230.com.pem
bind [fd00::a01:7c]:50000 ssl crt /etc/my-ssl/private/si1230.com.pem
mode http
stats enable
stats uri /haproxy?stats
stats refresh 30s
acl AuthOkay http_auth(StatsAuth)
http-request auth realm HAProxy\ Statistics if !AuthOkay
stats admin if TRUE
http-request deny if !AuthOkay
userlist StatsAuth
user admin password $2y$05$lxbI83Bmc6/2gJICgJ2I1us7erN396AMZmJnZJdsWeeuTgfr0fR96
frontend k8s-api-frontend
bind 10.1.0.125:6443
bind [fd00::a01:7d]:6443
option tcplog
mode tcp
default_backend k8s-api-backend
backend k8s-api-backend
mode tcp
balance roundrobin
option ssl-hello-chk
server s00-int-k8s-master-v001 s00-int-k8s-master-v001.si1230.com:6443
EOF
- backend server の指定には、管理性の面から FQDN を推奨します。FQDN を使用する場合、HAProxy は名前解決ができないと起動できません。
global
:crt-base
: 証明書を配置するディレクトリを変更しています。本稿における証明書の設定はこちらを参照してください。
listen stats
: listen セクションは、特定のプロキシを設定するためのもので、フロントエンドとバックエンドの両方の機能を持ちます。このセクションでは、HAProxy の統計情報を提供するための設定が行われています。bind …
: 特定の IPv4/IPv6 アドレスでポート 50000 にバインドし、指定された PEM ファイル(TLS 証明書と秘密鍵を含む)を使用して SSL/TLS を有効にします。これにより、統計ページが HTTPS 経由で提供されます。mode http
: このセクションでのトラフィックを HTTP モードで処理します。HTTP モードは、HTTP プロトコルに特化した設定とオプションを有効にします。stats enable
: 統計ページを有効にします。これにより、HAProxy の統計情報を閲覧できる WebUI が提供されます。stats uri
: 統計ページにアクセスするための URI を設定します。例として、http://your-haproxy-server:50000/haproxy?stats
でアクセスできます。stats refresh
: 統計ページを 30 秒ごとに自動的にリフレッシュします。これにより、リアルタイムで更新された情報を確認できます。stats auth
: ベーシック認証を設定し、統計ページにアクセスするためのユーザー名とパスワードを指定します。ここでは、ユーザー名が admin、パスワードが password です。この認証情報はセキュリティ上の理由から強固なものに変更することを推奨します。- acl AuthOkay: HTTP 認証をチェックするアクセス制御リスト (ACL) を定義します。
StatsAuth
というユーザーリストに対する認証が成功した場合にAuthOkay
を設定します。 http-request auth
: 認証が成功しなかった場合に、HAProxy Statistics
という領域で HTTP 認証を要求します。stats admin
: 統計ページでの管理機能(例:サーバの状態変更や停止など)を有効にします。このオプションを設定することで、管理者としての操作が可能になります。http-request
: 認証が成功しなかった場合にアクセスを拒否します。
userlist StatsAuth
: 認証情報を定義するユーザーリストです。ここではStatsAuth
という名前でリストを作成しています。- user admin password: ユーザー
admin
のハッシュ化されたパスワードを設定します。このハッシュはbcrypt
形式で生成されており、セキュリティを強化しています。
- user admin password: ユーザー
frontend
:frontend k8s-api-frontend
: フロントエンドの名前を k8s-api-frontend に設定します。bind...
: 特定の IPv4/IPv6 アドレスでポート 6443 にバインドします。Kubernetes API サーバーへのリクエストを受け付けます。option tcplog
: TCP ログオプションを有効にします。TCP 接続の詳細をログに記録します。mode tcp
: フロントエンドを TCP モードで動作させます。default_backend k8s-api-backend
: デフォルトのバックエンドを k8s-api-backend に設定します。
backend
:backend k8s-api-backend
: バックエンドの名前を k8s-api-backend に設定します。mode tcp
: バックエンドを TCP モードで動作させます。balance roundrobin
: ロードバランシングの方式をラウンドロビンに設定します。リクエストを順番に各サーバーに分配します。option ssl-hello-chk
: バックエンドサーバーが SSL/TLS で動作している場合に、そのサーバーが応答可能かどうかを確認するための SSL ハンドシェイクを行うオプションです。この設定がなくても基本的な TCP レベルの確認は行われ、問題なく動作しますが、SSL/TLS レイヤーの問題を見逃してしまう可能性があります。server ...
: バックエンドサーバーとしてs00-int-k8s-master-v001.si1230.com:6443
を指定します。
設定ファイルに認証情報を含むため、パーミッションを 600 に変更しています。
myadmin@ubuntu-22-04:~$ sudo chmod 600 /etc/haproxy/haproxy.cfg
設定値(参考)
以下は OpenShift 用の設定のサンプルです。OpenShift はクラスターの展開時点で多くのサービスチェックを行うため、設定量も多くなっています。
myadmin@ubuntu-22-04:~$ sudo cp -ai /etc/haproxy/haproxy.cfg{,.orig}
myadmin@ubuntu-22-04:~$ sudo tee /etc/haproxy/haproxy.cfg <<"EOF"
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
# ingress-http
frontend ingress-http
bind *:80
option tcplog
mode tcp
default_backend ingress-http-pool
backend ingress-http-pool
mode tcp
balance roundrobin
server node0 node0.test.si1230.com:80 check
server node1 node1.test.si1230.com:80 check
server node2 node2.test.si1230.com:80 check
server bs bs.test.si1230.com:80 check
# ingress-https
frontend ingress-https
bind *:443
option tcplog
mode tcp
default_backend ingress-https-pool
backend ingress-https-pool
mode tcp
balance roundrobin
option ssl-hello-chk
server node0 node0.test.si1230.com:443 check
server node1 node1.test.si1230.com:443 check
server node2 node2.test.si1230.com:443 check
server bs bs.test.si1230.com:443 check
# k8s-api
frontend k8s-api
bind *:6443
option tcplog
mode tcp
default_backend k8s-api-pool
backend k8s-api-pool
mode tcp
balance roundrobin
option ssl-hello-chk
server node0 node0.test.si1230.com:6443 check
server node1 node1.test.si1230.com:6443 check
server node2 node2.test.si1230.com:6443 check
server bs bs.test.si1230.com:6443 check
# config
frontend config
bind *:22623
option tcplog
mode tcp
default_backend config-pool
backend config-pool
mode tcp
balance roundrobin
option ssl-hello-chk
server node0 node0.test.si1230.com:22623 check
server node1 node1.test.si1230.com:22623 check
server node2 node2.test.si1230.com:22623 check
server bs bs.test.si1230.com:22623 check
EOF
設定の有効化
設定を有効化します。
myadmin@ubuntu-22-04:~$ sudo systemctl restart haproxy.service && systemctl status haproxy.service
参考
全てのインターフェイスでデュアルスタックにするには以下のようになります。
listen stats
bind :::50000 v4v6 ssl crt /etc/my-ssl/private/si1230.com.pem
frontend k8s-api-frontend
bind :::6443 v4v6