基本機能
このセクションでは、HAProxyが実装する機能をいくつか紹介します。現代のロードバランサーなら一般に備えていることが期待されるものもあれば、HAProxyのアーキテクチャーから直接得られる利点もあります。より高度な機能は、次のセクションで詳しく説明します。
3.3.1. 基本機能:プロキシ
プロキシ処理とは、独立した二つの接続を介して、クライアントとサーバーの間でデータを転送することです。プロキシ処理と接続管理について、HAProxyは次の基本機能をサポートします。
-
サーバーに正常な接続を提供し、クライアント側の不具合や攻撃から保護する。
-
複数のIPアドレスやポート、さらにはポート範囲でリッスンする。
-
透過的な受け付け:ローカルシステムに属していないものも含め、任意のIPアドレス宛てのトラフィックを捕捉する。
-
サーバーのポートはリッスンポートと対応する必要がなく、固定オフセットで変換することもできる(ポート範囲を使う場合に便利)。
-
透過的な接続:必要に応じて、サーバーへの接続時にクライアントのIPアドレス、または任意のIPアドレスを送信元として使う。
-
複数拠点のLBで、サーバーに信頼できる戻り先IPアドレスを提供する。
-
バッファーと、必要に応じて短時間の接続を使い、サーバーの同時接続数とメモリ使用量を減らして負荷を軽減する。
-
TCPスタック(SACKなど)と輻輳制御を最適化し、RTTの影響を減らす。
-
両側で異なるプロトコルファミリーをサポートする(IPv4/IPv6/Unixなど)。
-
タイムアウトの適用:接続の段階に応じた複数のタイムアウトをサポートし、停止したクライアントやサーバー、攻撃者が長時間リソースを占有できないようにする。
-
プロトコルの検証:HTTP、SSL、ペイロードを検査し、明示的に受け入れるよう指示されていない限り、不正なプロトコル要素を拒否する。
-
ポリシーの適用:許可されたものだけが転送されるようにする。
-
受信接続と送信接続の両方を特定のネットワーク名前空間に制限できる(Linuxのみ)。これにより、コンテナーをまたぐマルチテナントのロードバランサーを簡単に構築できる。
-
PROXYプロトコルにより、HTTP以外のトラフィックでもクライアントのIPアドレスをサーバーへ伝える。これはHAProxyの拡張機能で、現在では多くのサードパーティー製品に採用されている。執筆時点では、少なくとも次の製品が対応している。
- クライアント:haproxy、stud、stunnel、exaproxy、ELB、squid
- サーバー:haproxy、stud、postfix、exim、nginx、squid、node.js、varnish
3.3.2. 基本機能:SSL
HAProxyのSSLスタックは、Googleのエンジニアから、最も機能が豊富なものの一つと評価されています(http://istlsfastyet.com/ )。特に幅広い対応を支える、よく使われる機能は次のとおりです。
-
サイト数に制限がなく、性能を重視したSNIベースのマルチホスティング。それぞれの証明書を持つ50000ドメインを稼働させている導入例が、少なくとも一つ知られています。
-
ワイルドカード証明書をサポートし、多数の証明書を用意する必要性を減らします。
-
証明書によるクライアント認証。有効な証明書を提示できなかった場合のポリシーを設定できます。たとえば、クライアント証明書を再生成するための別のサーバーファームを提示できます。
-
バックエンドサーバーの認証により、接続先が中間者ではなく、本物のバックエンドサーバーであることを確認します。
-
バックエンドサーバーに対する認証により、接続しているのが期待されたhaproxyノードであることを、バックエンドサーバーへ証明します。
-
TLSのNPN拡張とALPN拡張により、SPDY/HTTP2接続を確実にオフロードし、平文でバックエンドサーバーへ渡せます。
-
OCSP staplingにより、クライアントがCertificate Status Requestを送った場合に、OCSPレスポンスを同時に渡し、最初のページの読み込み時間をさらに短縮します。
-
動的なレコードサイズ調整により、高性能と低レイテンシーを両立します。パケットがまだ転送中でもブラウザーが新しいオブジェクトの取得を始められるため、ページ読み込み時間を大きく短縮します。
-
ログ、アクセス制御、レポートなどのために、SSL/TLS層の関連情報へ常にアクセスできます。HTTPヘッダーやPROXYプロトコルの拡張にこれらの情報を埋め込むこともでき、オフロード先サーバーは、自身でSSLを終端した場合に得られたはずの情報をすべて取得できます。
-
OpenSSLの特定のバージョンに影響するHeartbleedのような既知の攻撃を、脆弱なSSLライブラリを使っている場合でも検出、記録、ブロックできます。
-
ステートレスなセッション再開をサポートします(RFC 5077のTLS Ticket拡張)。TLSチケットはCLIから更新できるため、頻繁にローテーションしてPerfect Forward Secrecyを実現できます。
3.3.3. 基本機能:監視
HAProxyは可用性を重視しています。そのため、サーバーの状態の確認と、自身の状態をほかのネットワークコンポーネントへ報告することに力を入れています。
-
サーバーごとのパラメーターで、その状態を継続的に監視します。これにより、通常のトラフィックが通るサーバーへの経路が機能していることを確認します。
-
ヘルスチェックには、稼働状態と停止状態への遷移それぞれにヒステリシスがあり、状態が頻繁に切り替わるのを防ぎます。
-
チェックは別のアドレス、ポート、プロトコルへ送れます。たとえば、HTTP+HTTPSサーバーのHTTPSポートのように、複数のサービスを代表すると見なせる単一のサービスを簡単にチェックできます。
-
サーバーはほかのサーバーの状態を追跡し、同時に停止状態へ移行できます。これにより、複数のサービスを提供するサーバーを一括して停止扱いにし、一部だけが故障したサーバーへ利用者を送らずに済みます。
-
サーバーにエージェントを配置して、負荷と健全性を監視できます。サーバー側から、ヘルスチェックでは見えない負荷、稼働状態、管理上の状態を報告したい場合があります。単純なエージェントを動かすことで、経路全体を検証するヘルスチェックに加え、サーバー自身が認識する健全性も判断に使えます。
-
TCP接続、HTTPリクエスト、SMTP hello、SSL hello、LDAP、SQL、Redis、send/expectスクリプトなど、さまざまなチェック方法を利用できます。すべてSSLの有無を選べます。
-
状態の変化は、障害の理由(検出時に受信したHTTPレスポンスなど)とともに、ログと統計ページに通知されます。変化が起きた際、設定したアドレスへメールを送ることもできます。
-
サーバーの状態は統計インターフェースにも表示され、ルーティングの判断に利用できます。サーバーファームの規模や健全性に応じて、別のファームへトラフィックを送れます(データセンター間リンクが失われた場合など)。
-
HAProxyはヘルスチェックリクエストを使い、サーバー名、重み、ファーム内のほかのサーバーの数などをサーバーへ伝えられます。サーバーは、その情報に基づいてレスポンスや判断を調整できます(利用可能なCPUを多く残すため、バックアップを延期するなど)。
-
サーバーはヘルスチェックで、単なる稼働・停止より詳しい状態を報告できます(停止したいため、新規訪問者の送信を止めてほしい、など)。
-
HAProxy自身も、ルーターやほかのロードバランサーなどの外部コンポーネントへ状態を報告でき、非常に充実した複数経路・複数層のインフラストラクチャーを構築できます。
3.3.4. 基本機能:高可用性
HAProxyは、本格的なロードバランサーと同様に、サービス全体をできるだけ継続させるため、可用性を非常に重視しています。
-
有効なサーバーだけを使い、それ以外は負荷分散先のファームから自動的に除外します。ただし、一定の条件では強制的に使うこともできます。
-
グレースフルシャットダウンをサポートし、接続に影響を与えずにサーバーをファームから外せます。
-
稼働系サーバーが停止すると、バックアップサーバーが自動的に代わりに使われ、可能な限りセッションが失われないようにします。同じサーバーへ到達する複数の経路(複数のインターフェースなど)も構築できます。
-
多数のサーバーが停止した場合、ファーム全体が障害状態であると報告できます。監視機能と組み合わせることで、上流のコンポーネントは、そのサービスに別のLBノードを選べます。
-
ステートレスな設計により、クラスターを簡単に構築できます。HAProxyは、障害時に失われる可能性のある情報を保存せず、サービスの継続性をできるだけ高めるよう設計されています。そのため、引き継ぎを可能な限り滑らかに行えます。
-
標準的なVRRPデーモンであるkeepalivedとよく連携します。HAProxyは自身の状態をkeepalivedへ簡単に伝えられ、フローティング仮想IPアドレスも適切に扱えます。注意:クラスター方式のソリューション(Heartbeatなど)ではなく、IP冗長化プロトコル(VRRP/CARP)だけを使ってください。最も速く、円滑で、信頼性の高いスイッチオーバーを実現するためです。
3.3.5. 基本機能:負荷分散
HAProxyは非常に充実した負荷分散機能を提供します。その多くは、残念ながら他の多くの負荷分散製品では利用できません。
-
10種類以上の負荷分散アルゴリズムをサポートします。入力データを使うものもあり、用途は無限に広がります。代表的なのは、round-robin(短い接続向け。各サーバーを順番に選ぶ)、leastconn(長い接続向け。接続数が最小のサーバー群のうち、最後に使われてから最も時間がたったものを選ぶ)、source(SSLやターミナルサーバーのファーム向け。クライアントの送信元アドレスでサーバーが直接決まる)、URI(HTTPキャッシュ向け。HTTP URIでサーバーが直接決まる)、hdr(特定のHTTPヘッダーフィールドの内容でサーバーが直接決まる)、first(短期間だけ稼働する仮想マシン向け。できるだけ少数のサーバーへ接続を集め、未使用のサーバーを停止できるようにする)です。
-
上記のすべてのアルゴリズムは、サーバーごとの重みをサポートします。ファーム内に世代の異なるサーバーを混在させたり、一部のトラフィックだけを特定のサーバー(デバッグモードや次期バージョンのソフトウェアを実行しているものなど)へ送ったりできます。
-
round-robin、leastconn、コンシステントハッシュでは、動的な重みをサポートします。CLIや、サーバーで動作するエージェントから、稼働中にサーバーの重みを変更できます。
-
動的な重みをサポートする場合は、常にslow-startも使えます。これにより、サーバーが受け持つトラフィックを段階的に増やせます。実行時にクラスをコンパイルする必要がある繊細なアプリケーションサーバーや、最大負荷をかける前にデータを蓄える必要のあるコールドキャッシュにとって、重要な機能です。
-
ハッシュには、クライアントの送信元アドレス、URLの要素、クエリー文字列の要素、ヘッダーフィールドの値、POSTパラメーター、RDP Cookieなど、さまざまな要素を使えます。
-
コンシステントハッシュは、ファームへのサーバー追加・削除時の大規模な再分配を防ぎます。大規模なキャッシュファームでは非常に重要で、slow-startを使ってコールドキャッシュにデータを蓄えられます。
-
サーバーごと・バックエンドごとの接続数、バックエンドの空き接続枠の数など、多数の内部メトリクスを使い、非常に高度な負荷分散方式を構築できます。
3.3.6. 基本機能:スティッキネス
スティッキネスがなければ、アプリケーションの負荷分散は役に立ちません。HAProxyは、サーバーの追加・削除、停止・復旧などが起きても、訪問者を同じサーバーに割り当て続けるための幅広い手段を提供します。一部の方式は複製を必要としないため、複数の負荷分散ノード間に距離があっても影響を受けにくい設計です。
-
必要に応じて、異なる場所からスティッキネス情報を個別に照合・学習できます。たとえば、JSESSIONID CookieをCookieとURLの両方で照合できます。最大8つの情報源を同時に学習でき、それぞれで異なるスティックテーブルを参照できます。
-
スティッキネス情報には、送信元アドレス、TCPペイロードのオフセットと長さ、HTTPクエリー文字列の要素、ヘッダーフィールドの値、Cookieなど、リクエストやレスポンス内で確認できるあらゆるものを使えます。
-
スティックテーブルは、マルチマスター方式ですべてのノード間に複製されます。
-
SSL-IDや、TSEファームで使うRDP Cookieなど、よく使われる要素には直接アクセスでき、簡単に操作できます。
-
すべてのスティッキー処理ルールには、ACLによる動的な条件を付けられます。
-
バックアップサーバーなど、特定のサーバーには固定しないようにできます。これにより、通常使うサーバーが復旧すると、自動的に負荷が戻ります。複数経路の環境でよく使われます。
-
HTTPでは、何も学習せずに、スティッキネス専用のCookieを操作する方式が好まれることがよくあります。Cookieを検出、書き換え、挿入したり、接頭辞を付けたりして、割り当てられたサーバーをクライアントに記憶させられます。
-
サーバーはログアウト時にスティッキネスCookieを変更・削除でき、離脱した訪問者は自動的にサーバーとの対応付けが解除されます。
-
ACLに基づくルールで、サーバーの状態にかかわらず、選択的にスティッキネスを無視したり強制したりできます。高度なヘルスチェックと組み合わせると、管理者は、導入中のサーバーが正常に動作することを一般公開前に確認できます。
-
Cookieに最大アイドル時間と有効期間を設定する独自の仕組みにより、スマートフォン、テレビ、家電など、閉じられることのない端末でも、永続ストレージに保存することなく、スティッキネスを円滑に終了できます。
-
複数のサーバーエントリーで同じスティッキネスキーを共有できます。複数経路の環境で一つの経路が停止しても、スティッキネスを維持できます。
-
ソフト停止では、スティッキネス情報を持つユーザーだけが割り当て済みのサーバーへ到達し続け、新しいユーザーはそこへ送られません。
3.3.7. 基本機能:ログ
ログは、ロードバランサーにとって極めて重要な機能です。第一に、ロードバランサーは単に表面化させた問題の原因として誤って疑われることがよくあります。第二に、インフラストラクチャーの重要な位置に置かれるため、正常・異常を問わずすべての動作を分析し、ほかのコンポーネントと突き合わせる必要があります。
HAProxyは非常に詳しいログを提供します。ミリ秒精度で、接続を受け付けた正確な時刻が含まれ、ファイアウォールのログで照合できます(NATとの対応付けなど)。デフォルトのTCPログとHTTPログは十分に詳細で、トラブルシューティングに必要な情報をすべて含みます。送信元IPアドレスとポート、フロントエンド、バックエンド、サーバー、タイマー(リクエスト受信時間、キュー待機時間、接続確立時間、レスポンスヘッダー受信時間、データ転送時間)、プロセス全体の状態、接続数、キューの状態、再試行回数、スティッキネス処理と切断理由の詳細、安全にエンコードされた取得ヘッダーなどです。この形式を拡張・置換して、任意のサンプルデータ、変数、取得値を含めることで、さらに詳しい情報を記録できます。たとえば、クライアントの累積リクエスト数や、訪問した異なるURLの数を記録できます。
標準のACLを使って、リクエストごとにログレベルを調整できます。不要なノイズと見なすログを自動的に抑え、その一方で、トラフィックの一部に異常な動作(特定の送信元アドレスのURL数やHTTPエラーが多すぎるなど)が見られた場合に警告を出せます。サーバーの停止や復旧などを知らせる管理ログも、独自のレベルで出力されます。
各フロントエンドとバックエンドは、複数の独立したログ出力先を持てるため、マルチテナント運用が容易になります。ログはUDPで送るのが望ましく、JSON形式でエンコードすることもできます。配送を保証するため、設定可能な行長で切り詰められます。stdout/stderr、任意のファイル記述子、またはクライアントが購読して取得できるリングバッファーへ送ることもできます。
3.3.8. 基本機能:統計
HAProxyは、認証、セキュリティレベル、スコープを備えたWebベースの統計表示インターフェースを提供します。ホスティングの顧客ごとに、その顧客のインスタンスだけを表示する専用ページを提供できます。通常のWebサイトの非公開URLに置けるため、新しいポートを開く必要はありません。ほかのHAProxyノードの稼働状況も表示でき、すべてが期待どおりに動作しているかを一目で確認できます。全体を簡潔に表示しながら、エラーの原因、最後のアクセスや変更からの経過時間など、多くの詳細にもアクセスできます。これらの情報はCSV表でも取得でき、ほかのツールに取り込んでグラフを作成できます。ページを自動更新して、大型ディスプレイ上の監視画面として使うこともできます。管理モードでは、保守作業を容易にするため、ページからサーバーの状態も変更できます。
Prometheusエクスポーターも用意されており、導入構成に応じて別の形式で統計を利用できます。