序章

高可用性プロキシの略であるHAProxyは、Linux、macOS、およびFreeBSDで実行できる人気のあるオープンソースソフトウェアTCP/HTTPロードバランサーおよびプロキシソリューションです。 その最も一般的な用途は、ワークロードを複数のサーバーに分散することにより、サーバー環境のパフォーマンスと信頼性を向上させることです(例: Web、アプリケーション、データベース)。 GitHub、Imgur、Instagram、Twitterなど、多くの注目を集める環境で使用されています。

このガイドでは、HAProxyとは何かの概要を説明し、負荷分散の用語を確認し、HAProxyを使用して独自のサーバー環境のパフォーマンスと信頼性を向上させる方法の例を示します。

HAProxyの用語

ロードバランシングとプロキシについて説明するときに重要な用語と概念はたくさんあります。 次のサブセクションでは、一般的に使用される用語について説明します。

基本的なタイプの負荷分散に入る前に、ACL、バックエンド、およびフロントエンドの確認から始める必要があります。

アクセス制御リスト(ACL)

負荷分散に関連して、ACLはいくつかの条件をテストし、アクションを実行するために使用されます(例: テスト結果に基づいてサーバーを選択するか、リクエストをブロックします)。 ACLを使用すると、パターンマッチングやバックエンドへの接続数など、さまざまな要因に基づいた柔軟なネットワークトラフィック転送が可能になります。

ACLの例:

acl url_blog path_beg /blog

このACLは、ユーザーのリクエストのパスが/blogで始まる場合に一致します。 これは、たとえばhttp://yourdomain.com/blog/blog-entry-1のリクエストと一致します。

ACLの使用法の詳細については、HAProxy構成マニュアルを参照してください。

バックエンド

バックエンドは、転送されたリクエストを受信するサーバーのセットです。 バックエンドは、HAProxy設定のbackendセクションで定義されます。 最も基本的な形式では、バックエンドは次のように定義できます。

  • 使用する負荷分散アルゴリズム
  • サーバーとポートのリスト

バックエンドには、1つまたは複数のサーバーを含めることができます。 一般的に、バックエンドにサーバーを追加すると、負荷が複数のサーバーに分散されるため、潜在的な負荷容量が増加します。 一部のバックエンドサーバーが使用できなくなった場合に備えて、この方法によって信頼性も向上します。

次に、2つのバックエンド構成web-backendblog-backendの例を示します。それぞれに2つのWebサーバーがあり、ポート80でリッスンしています。

backend web-backend
   balance roundrobin
   server web1 web1.yourdomain.com:80 check
   server web2 web2.yourdomain.com:80 check
   
backend blog-backend
   balance roundrobin
   mode http
   server blog1 blog1.yourdomain.com:80 check
   server blog1 blog1.yourdomain.com:80 check

balance roundrobin行は、負荷分散アルゴリズムを指定します。これについては、負荷分散アルゴリズムセクションで詳しく説明しています。

mode httpは、レイヤー7プロキシが使用されることを指定します。これについては、負荷分散のタイプセクションで説明されています。

serverディレクティブの最後にあるcheckオプションは、これらのバックエンドサーバーでヘルスチェックを実行する必要があることを指定します。

フロントエンド

フロントエンドは、リクエストをバックエンドに転送する方法を定義します。 フロントエンドは、HAProxy設定のfrontendセクションで定義されています。 それらの定義は、次のコンポーネントで構成されています。

  • IPアドレスとポートのセット(例: 10.1.1.7:80、*:443など)
  • ACL
  • 一致するACL条件に応じて使用するバックエンドを定義するuse_backendルール、および/または他のすべてのケースを処理するdefault_backendルール

次のセクションで説明するように、フロントエンドはさまざまなタイプのネットワークトラフィックに合わせて構成できます。

負荷分散の種類

ロードバランシングで使用される基本的なコンポーネントを理解したので、ロードバランシングの基本的なタイプに移ることができます。

負荷分散なし

負荷分散のない単純なWebアプリケーション環境は、次のようになります。

No Load Balancing

この例では、ユーザーはyourdomain.comでWebサーバーに直接接続し、負荷分散は行われません。 単一のWebサーバーがダウンすると、ユーザーはWebサーバーにアクセスできなくなります。 さらに、多くのユーザーが同時にサーバーにアクセスしようとしていて、サーバーが負荷を処理できない場合、ユーザーのエクスペリエンスが遅いか、まったく接続できない可能性があります。

レイヤー4の負荷分散

ネットワークトラフィックを複数のサーバーに負荷分散する最も簡単な方法は、レイヤー4(トランスポート層)の負荷分散を使用することです。 この方法で負荷分散を行うと、IP範囲とポートに基づいてユーザートラフィックが転送されます(つまり、 http://yourdomain.com/anythingに対するリクエストが着信した場合、トラフィックはport 80上のyourdomain.comに対するすべてのリクエストを処理するバックエンドに転送されます。 レイヤー4の詳細については、ネットワーク入門TCPサブセクションを確認してください。

レイヤー4の負荷分散の簡単な例を次に示します。

Layer 4 Load Balancing

ユーザーはロードバランサーにアクセスします。ロードバランサーは、ユーザーのリクエストをバックエンドサーバーのweb-backendグループに転送します。 どちらのバックエンドサーバーが選択されても、ユーザーの要求に直接応答します。 通常、 web-backend 内のすべてのサーバーは同一のコンテンツを提供する必要があります。そうしないと、ユーザーが一貫性のないコンテンツを受け取る可能性があります。 両方のWebサーバーが同じデータベースサーバーに接続していることに注意してください。

レイヤー7の負荷分散

ネットワークトラフィックを負荷分散するもう1つのより複雑な方法は、レイヤー7(アプリケーション層)の負荷分散を使用することです。 レイヤー7を使用すると、ロードバランサーは、ユーザーのリクエストの内容に基づいて、リクエストをさまざまなバックエンドサーバーに転送できます。 この負荷分散モードでは、同じドメインとポートで複数のWebアプリケーションサーバーを実行できます。 レイヤー7の詳細については、ネットワーク入門HTTPサブセクションをご覧ください。

レイヤー7の負荷分散の簡単な例を次に示します。

Layer 7 Load Balancing

この例では、ユーザーがyourdomain.com/blogをリクエストすると、ブログアプリケーションを実行するサーバーのセットであるblogバックエンドに転送されます。 他のリクエストはweb-backendに転送され、別のアプリケーションを実行している可能性があります。 この例では、両方のバックエンドが同じデータベースサーバーを使用しています。

フロントエンド構成の例のスニペットは次のようになります。

frontend http
  bind *:80
  mode http

  acl url_blog path_beg /blog
  use_backend blog-backend if url_blog
 
  default_backend web-backend

これにより、httpという名前のフロントエンドが構成され、ポート80ですべての着信トラフィックが処理されます。

acl url_blog path_beg /blogは、ユーザーのリクエストのパスが/blogで始まる場合、リクエストに一致します。

use_backend blog-backend if url_blogは、ACLを使用してトラフィックをblog-backendにプロキシします。

default_backend web-backendは、他のすべてのトラフィックがweb-backendに転送されることを指定します。

負荷分散アルゴリズム

使用される負荷分散アルゴリズムは、負荷分散時にバックエンドで選択されるサーバーを決定します。 HAProxyは、アルゴリズムにいくつかのオプションを提供します。 負荷分散アルゴリズムに加えて、サーバーに weight パラメーターを割り当てて、他のサーバーと比較してサーバーが選択される頻度を操作できます。

一般的に使用されるアルゴリズムのいくつかは次のとおりです。

ラウンドロビン

ラウンドロビンはサーバーを順番に選択します。 これがデフォルトのアルゴリズムです。

最小の接続

接続数が最も少ないサーバーを選択します。 これは、より長いセッションに推奨されます。 同じバックエンド内のサーバーもラウンドロビン方式でローテーションされます。

ソース

これにより、ユーザーがリクエストを行っている送信元IPアドレスのハッシュに基づいて使用するサーバーが選択されます。 この方法により、同じユーザーが同じサーバーに接続することが保証されます。

スティッキーセッション

一部のアプリケーションでは、ユーザーが同じバックエンドサーバーに接続し続ける必要があります。 これは、スティッキーセッションを介して、それを必要とするバックエンドのappsessionパラメーターを使用して実現できます。

健康診断

HAProxyはヘルスチェックを使用して、バックエンドサーバーがリクエストの処理に使用できるかどうかを判断します。 これにより、サーバーが使用できなくなった場合にサーバーをバックエンドから手動で削除する必要がなくなります。 デフォルトのヘルスチェックは、サーバーへのTCP接続の確立を試みることです。

サーバーがヘルスチェックに失敗したためにリクエストを処理できない場合、サーバーはバックエンドで自動的に無効になり、サーバーが再び正常になるまでトラフィックはサーバーに転送されません。 バックエンド内のすべてのサーバーに障害が発生した場合、それらのバックエンドサーバーの少なくとも1つが再び正常になるまで、サービスは使用できなくなります。

データベースサーバーなどの特定の種類のバックエンドの場合、デフォルトのヘルスチェックでは、サーバーがまだ正常であるかどうかを判断する必要はありません。

Nginx Webサーバーは、スタンドアロンのプロキシサーバーまたはロードバランサーとしても使用でき、キャッシュおよび圧縮機能のためにHAProxyと組み合わせて使用されることがよくあります。

高可用性

このチュートリアルで説明するレイヤー4と7の負荷分散のセットアップは、どちらもロードバランサーを使用して、トラフィックを多くのバックエンドサーバーの1つに転送します。 ただし、これらのセットアップでは、ロードバランサーが単一障害点になります。 ダウンしたり、リクエストに圧倒されたりすると、サービスの遅延やダウンタイムが長くなる可能性があります。

高可用性(HA)セットアップは、単一障害点のないインフラストラクチャとして広く定義されています。 アーキテクチャのすべてのレイヤーに冗長性を追加することで、単一サーバーの障害がダウンタイムイベントになるのを防ぎます。 ロードバランサーはバックエンドレイヤー(Web /アプリサーバー)の冗長性を促進しますが、真の高可用性セットアップには、冗長ロードバランサーも必要です。

高可用性セットアップの図を次に示します。

HA Setup

この例では、あるサーバーから別のサーバーに再マッピングできる静的IPアドレスの背後に複数のロードバランサー(1つはアクティブで1つ以上のパッシブ)があります。 ユーザーがWebサイトにアクセスすると、要求は外部IPアドレスを介してアクティブなロードバランサーに送信されます。 そのロードバランサーに障害が発生した場合、フェイルオーバーメカニズムがそれを検出し、パッシブサーバーの1つにIPアドレスを自動的に再割り当てします。 アクティブ/パッシブHAセットアップを実装する方法はいくつかあります。 詳細については、フローティングIPの使用方法を参照してください。

結論

負荷分散について理解し、HAProxyの使用方法を理解したので、独自のサーバー環境のパフォーマンスと信頼性の向上を開始するための強固な基盤が得られました。

後で表示するためにHAProxyの出力を保存することに興味がある場合は、CentOS8でRsyslogを使用してHAProxyログを構成する方法[クイックスタート]を確認してください。

問題の解決を検討している場合は、一般的なHAProxyエラーを確認してください。 さらにトラブルシューティングが必要な場合は、一般的なHAProxyエラーのトラブルシューティング方法を参照してください。