手当たり次第に書くんだ

飽きっぽいのは本能

Ubuntu 22.04 HAProxy ロードバランサー構築

目次に戻る

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 形式で生成されており、セキュリティを強化しています。
  • 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

目次に戻る
Ubuntu 22.04 HAProxy ロードバランサー構築

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る