2 HAProxyを使用したロード・バランシングの設定

この章では、HAProxyを使用してロード・バランシングを構成する方法について説明します。この章には、構成のシナリオと例も含まれています。

HAProxyのインストールと構成

HAProxyを使用してロード・バランシングを設定する前に、最初に機能をインストールして構成する必要があります。

  1. 各フロントエンド・サーバーにhaproxyパッケージをインストールします。

    sudo dnf install haproxy
  2. /etc/haproxy/haproxy.cfgファイルを編集して、各サーバーでHAProxyを構成します。

    HAProxy構成ディレクティブを参照してください。

  3. HAProxyにより処理するサービスまたはポートへのアクセスを有効にします。

    ポート80で受信TCPリクエストを受け入れるには、次のコマンドを使用します。

    sudo firewall-cmd --zone=zone --add-port=80/tcp
    sudo firewall-cmd --permanent --zone=zone --add-port=80/tcp
  4. 各サーバーでhaproxyサービスを有効にし、起動します。

    sudo systemctl enable --now haproxy

    HAProxy構成を変更した場合は、haproxyサービスを再ロードします。

    sudo systemctl reload haproxy

HAProxy構成ディレクティブ

/etc/haproxy/haproxy.cfg構成ファイルは、次の各セクションに分かれています。

global

syslog機能などのグローバル設定と、ロギングに使用するレベル、許可される最大同時接続数、およびデーモン・モードで開始するプロセス数を定義します。

defaults

その他のセクションのデフォルト設定を定義します。

listen

完全プロキシを定義します。これには、frontendおよびbackendコンポーネントが暗黙的に含まれています。

frontend

クライアント接続を受け入れるポートを定義します。

backend

プロキシがクライアント接続を転送する先のサーバーを定義します。

HAProxyを使用したラウンド・ロビン・ロード・バランシングの構成

次の例では、HAProxyを使用して、受信リクエストを2つのバックエンドWebサーバー間で分散し、さらにバックエンド・サーバーでサービス停止も処理するフロントエンド・サーバーを実装します。

次の図は、外部公開ネットワーク(10.0.0.0/24)および内部ネットワーク(192.168.1.0/24)に接続されたHAProxyサーバー(10.0.0.10)を示しています。内部ネットワークでは、2つのWebサーバーwebsrv1 (192.168.1.71)およびwebsrv2 (192.168.1.72)にアクセス可能です。IPアドレス10.0.0.10がプライベート・アドレス範囲10.0.0.0/24内にあるため、インターネット上でルーティングできません。アップストリーム・ネットワーク・アドレス変換(NAT)ゲートウェイまたはプロキシ・サーバーが、インターネットとの間のアクセスを提供します。

図2-1 ロード・バランシングのためのHAProxy構成の例


この図は、外部公開ネットワーク(10.0.0.0/24)および内部ネットワーク(192.168.1.0/24)に接続されたHAProxyサーバー(10.0.0.10)を示しています。内部ネットワークでは、2つのWebサーバーwebsrv1 (192.168.1.71)およびwebsrv2 (192.168.1.72)にアクセス可能です。IPアドレス10.0.0.10はプライベート・アドレス範囲10.0.0.0/24内にあり、インターネット上でルーティングできません。アップストリームNATゲートウェイまたはプロキシ・サーバーが、インターネットとの間のアクセスを提供します。

次に、サーバー上の/etc/haproxy/haproxy.cfgの構成例を示します。

global
    daemon
    log 127.0.0.1 local0 debug
    maxconn 50000
    nbproc 1

defaults
    mode http
    timeout connect 5s
    timeout client 25s
    timeout server 25s
    timeout queue 10s

# Handle Incoming HTTP Connection Requests
listen  http-incoming
    mode http
    bind 10.0.0.10:80
# Use each server in turn, according to its weight value
    balance roundrobin
# Verify that service is available
    option httpchk HEAD / HTTP/1.1\r\nHost:\ www
# Insert X-Forwarded-For header
    option forwardfor
# Define the back-end servers, which can handle up to 512 concurrent connections each
    server websrv1 192.168.1.71:80 maxconn 512 check
    server websrv2 192.168.1.72:80 maxconn 512 check

この構成では、HTTPトラフィックが2つのバックエンドWebサーバー(websrv1およびwebsrv2)の間で分散され、これらのサーバーのファイアウォールは、ポート80で受信TCPリクエストを受け入れるように構成されています。トラフィックはサーバー間で均等に分散され、各サーバーは最大512個の同時接続を処理できます。ヘルス・チェックも構成され、これにより、各バックエンド・サーバーのWebルートに対するリクエストでHTTPヘッダーに対するリクエストが実行されます。

Webサーバーに基本的な/var/www/html/index.htmlファイルを実装し、curlを使用して接続をテストした後は、次の出力に、HAProxyがどのようにトラフィックをこれらのサーバー間で分散し、どのようにwebsrv1でのhttpdサービス停止を処理するかが示されます。

while true; do curl http://10.0.0.10; sleep 1; done
This is HTTP server websrv1 (192.168.1.71).
This is HTTP server websrv2 (192.168.1.72).
This is HTTP server websrv1 (192.168.1.71).
This is HTTP server websrv2 (192.168.1.72).
...
This is HTTP server websrv2 (192.168.1.72).
<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>
This is HTTP server websrv2 (192.168.1.72).
This is HTTP server websrv2 (192.168.1.72).
This is HTTP server websrv2 (192.168.1.72).
...
This is HTTP server websrv2 (192.168.1.72).
This is HTTP server websrv2 (192.168.1.72).
This is HTTP server websrv2 (192.168.1.72).
This is HTTP server websrv1 (192.168.1.71).
This is HTTP server websrv2 (192.168.1.72).
This is HTTP server websrv1 (192.168.1.71).
...

この例では、websrv1httpdサービスが再起動され、websrv2に加えてこのサーバーも再び使用し始めたことが、HAProxyによって検出されました。

HAProxyのロード・バランシング機能をKeepalivedの高可用性機能と組み合せることにより、プライマリ・ロード・バランサが失敗した場合にサービスを継続できるようにバックアップ・ロード・バランサを構成できます。この構成を拡張する方法の詳細は、HAProxyでのKeepalivedを使用したロード・バランシングの拡張を参照してください。

重み付けラウンド・ロビン・ロード・バランシングとHAProxyの使用

重み付けラウンド・ロビン・アルゴリズムを使用してトラフィックを分散するようにHAProxyを構成することもできます。このアルゴリズムは、重みに従ってサーバーを順番に選択し、サーバー応答時間などの特定の要因を実装せずにサーバーの負荷を分散します。重み付けラウンド・ロビンを使用すると、サーバーの処理能力とサーバーで使用可能なリソースに基づいて、サーバー間のトラフィックを比例的に分散できます。

重み付けラウンド・ロビンを実装するには、構成内の各サーバーに重みの値を追加します。たとえば、トラフィックの量の2倍をwebsrv1に分散するには、次のように、それぞれの重み率が含まれるように構成を変更します。

server websrv1 192.168.1.71:80 weight 2 maxconn 512 check
server websrv2 192.168.1.72:80 weight 1 maxconn 512 check

HAProxyのセッション永続性の追加

HAProxyには、多数のロード・バランシング・アルゴリズムがあり、その一部では、Webセッションが同じバックエンド・サーバーへの永続的な接続を保持することを自動的に保証する機能が用意されています。hdrrdp-cookiesourceuriまたはurl_paramなどのbalanceアルゴリズムを構成して、セッション中の特定の受信接続に対してトラフィックが常に同じWebサーバーにルーティングされるようにできます。たとえば、sourceアルゴリズムは、ソースIPアドレスのハッシュを作成し、それを特定のバックエンド・サーバーにマップします。rdp-cookieまたはurl_paramアルゴリズムを使用する場合は、これらのメカニズムを効率的に実行するために、バックエンドWebサーバーまたはWebアプリケーションを構成することが必要な場合があります。

実装でleastconnroundrobinまたはstatic-rrアルゴリズムを使用する必要がある場合は、サーバー依存Cookieを使用してセッションの永続性を実現できます。

1つのWebサーバーですべてのページのセッションの永続性を有効にするには、cookieディレクティブを使用して、挿入するCookieの名前を定義し、cookieオプションとサーバー名をserverの行に追加します。たとえば:

cookie WEBSVR insert
server websrv1 192.168.1.71:80 weight 1 maxconn 512 cookie 1 check
server websrv2 192.168.1.72:80 weight 1 maxconn 512 cookie 2 check

HAProxyは、Webサーバーを識別するSet-Cookie:ヘッダーをクライアントへの応答に含めます(たとえば: Set-Cookie: WEBSVR=N; path=page_path )。クライアントがリクエストでWEBSVR Cookieを指定すると、HAProxyは、server cookieの値がWEBSVRの値と一致するWebサーバーにリクエストを転送します。

Webサーバーで選択的に永続性を有効にするには、cookieディレクティブを使用して、指定したCookie (通常はセッションID Cookieまたはその他の既存のCookie)の前にserver cookie値および~デリミタが付くことをHAProxyが必要とすることを指定します。次に例を示します。

cookie SESSIONID prefix
server websrv1 192.168.1.71:80 weight 1 maxconn 512 cookie 1 check
server websrv2 192.168.1.72:80 weight 1 maxconn 512 cookie 2 check

SESSIONIDの値の前にserver cookie値を付けると(たとえば: Set-Cookie: SESSIONID=N~Session_ID;)、HAProxyは、SESSIONID Cookieから接頭辞とデリミタを取り除いてから、server cookie値がその接頭辞と一致するWebサーバーにリクエストを転送します。

次の例に、接頭辞付きのCookieを使用してセッションの永続性を構成する方法を示します。

while true; do curl http://10.0.0.10 cookie "SESSIONID=1~1234;"; sleep 1; done
This is HTTP server websrv1 (192.168.1.71).
This is HTTP server websrv1 (192.168.1.71).
This is HTTP server websrv1 (192.168.1.71).
...

実際のWebアプリケーションは通常、サーバー側にセッションIDを設定し、この場合、最初のHAProxyレスポンスでSet-Cookie:ヘッダーに接頭辞付きのCookieが含められます。