Microsoft Azure の負荷分散サービス


このポストは、4 月 8 日に投稿された Microsoft Azure Load Balancing Services の翻訳です。

Microsoft Azure では、Microsoft Azure クラウドでホストされている仮想マシン (IaaS) およびクラウド サービス (PaaS) に対して負荷分散サービスを提供しています。負荷分散によるメリットにはさまざまなものがありますが、その中でも、アプリケーションのスケーリングが可能になる、またアプリケーションで不具合が発生したときに柔軟に回復できるというメリットがあります。

負荷分散サービスへのアクセスは、Microsoft Azure ポータル、またはアプリケーションのサービス モデルからお客様のサービスの入力エンドポイントを指定すると可能になります。1 つまたは複数の入力エンドポイントを持つホスト対象のサービスが Microsoft Azure にデプロイされると、Microsoft Azure プラットフォームで提供される負荷分散サービスが自動的に構成されます。回復性と冗長性が得られるというサービスのメリットを活用するには、同一エンドポイントに対して少なくとも 2 つの仮想マシンがサービスを提供している必要があります。

次の図は、Microsoft Azure でホストされているアプリケーションが、負荷分散サービスを使用して、受信トラフィック (IP アドレスとポート番号の組み合わせは 1.2.3.4:80) を 3 つの仮想マシン (すべて 80 番ポートでリッスン) に転送する場合を示したものです。

ここからは、Microsoft Azure の負荷分散サービスの主な機能について説明します。

PaaS および IaaS のサポート

Microsoft Azure の負荷分散サービスは、あらゆる種類のテナント (IaaS または PaaS)、およびあらゆる種類の OS (Windows またはサポートされている Linux ベースの各 OS) で使用可能です。

PaaS テナントの構成は、サービス モデルで行います。IaaS テナントの構成 (英語) は、管理ポータルまたは PowerShell で行います。

レイヤー 4 のロード バランサー、および Hash に基づく配分

Microsoft Azure ロード バランサーはレイヤー 4 型です。トラフィックを受信した入力エンドポイントに応じてハッシュ関数を計算し、使用可能なサーバー (仮想マシン) 群に負荷を配分します。このハッシュ関数は、同一接続 (TCP または UDP) のすべてのパケットが同一のサーバーに届くように計算されます。Microsoft Azure ロード バランサーでは、使用可能なサーバーにトラフィックをマッピングする際に利用するハッシュの計算に、5 つのタプル (送信元の IP、送信元のポート番号、送信先の IP、送信先のポート番号、プロトコルの種類) を使います。ハッシュ関数は、サーバーへの接続の配分が均等になるように無作為に選択されます。ただし、トラフィックのパターンによっては、異なる接続を同一のサーバーにマッピングすることもできます (ただし、サーバーへの接続の分配はラウンドロビン方式ではなく、また要求をキューに入れて待機することもありませんので、注意が必要です。一部の記事やブログで書かれていることは誤りです)。ハッシュ関数を利用する場合の基本的な前提として、多数の異なるクライアントから多数の要求が送信されることを想定しています。こうした場合に、各サーバーに対する要求の配分がうまく行われます。

複数のプロトコルのサポート

Microsoft Azure の負荷分散サービスでは、TCP および UDP の各プロトコルがサポートされます。サービス モデル、PowerShell、管理ポータルのいずれかで入力エンドポイントを指定するときに、プロトコルを指定できます。

複数のエンドポイントのサポート

ホスト対象のサービスでは、入力エンドポイントを複数指定できます。またこの場合、自動的に負荷分散サービスが構成されます。

現時点では、ポート番号とプロトコルが同一のエンドポイントを複数指定することはできません。また、ホスト対象のサービス 1 つに対して指定可能なエンドポイントの数は、現時点では 150 個に制限されています。

内部エンドポイントのサポート

各サービスで最大 25 個の内部エンドポイントを指定できます。これは、ロード バランサーに公開されず、サービス ロール間での通信に使用されます。

直接ポート エンドポイントのサポート (インスタンスの入力エンドポイント)

ホスト対象のサービスでは、特定のエンドポイントを指定して負荷分散の対象から除外し、サービスをホストしている仮想マシンに直接アクセスできるように指定できます。これにより、要求に負荷分散を適用せず、アプリケーションからのアクセスを特定のサーバー インスタンス (VM) に直接リダイレクトすることができます (要求に負荷分散が適用されて他のインスタンスに送られることを防止します)。

スケールの拡大/縮小の自動再構成、およびサービスの復旧と更新

負荷分散サービスでは、Microsoft Azure コンピューティング サービスと連携して、入力エンドポイントに指定されたサーバー インスタンス数の増減によりスケールの拡大および縮小が実行されます。これは Web ロールおよび Worker ロールのインスタンス数の増減、または同一負荷分散グループへの永続的な VM の追加および削除により実施されます。このとき、負荷分散サービスは自動的に増減したインスタンスに適合するように再構成されます。

また、負荷分散サービスは、Microsoft Azure ファブリック コントローラーによるサービスの復旧処理 (英語) を受けて、またはお客様がサービスを更新することにより、自身を透過的に再構成します。

サービスの監視

負荷分散サービスには、さまざまなサーバー インスタンスの正常性のプローブを行う機能や、異常なサーバー インスタンスをローテーションから除外する機能があります。サポートされているプローブには、ゲスト エージェント プローブ (PaaS の仮想マシンで使用可能)、HTTP カスタム プローブ、および TCP カスタム プローブがあります。ゲスト エージェント (英語) の場合、負荷分散サービスは仮想マシンのゲスト エージェントにクエリを発行し、サービスの状態を取得します。HTTP の場合は、負荷分散サービスは指定された URL をフェッチしてインスタンスの正常性を判断します。TCP の場合は、定義されたプローブのポートに対する TCP セッションが正常に確立されたかどうかで判断します。

送信元 NAT (SNAT)

サービスから送信されるすべてのトラフィックには、受信トラフィックと同じ VIP アドレスを使用するように送信元 NAT (SNAT) が適用されます。SNAT のしくみについては、今後の記事でご紹介します。

データ センター間のトラフィックの最適化

Microsoft Azure ロード バランサーは、同一リージョン内に存在する Microsoft Azure のデータ センター間のトラフィックを最適化します。これにより、同一リージョン内で VIP を使用して通信する Azure テナント間のトラフィックは、TCP/IP 接続の確立後、Microsoft Azure ロード バランサーを完全にバイパスします。

VIP スワップ

Microsoft Azure ロード バランサーでは、2 つのテナントの間で VIP を入れ替えることができます。これにより、テナントを「ステージング環境」と「本番環境」に相互に切り替えることが可能です。VIP スワップ操作を使用すると、新しいバージョンのサービスがデプロイされた後も、クライアントがサービスと通信するときに同じ VIP を使用できます。このため、新しいバージョンのサービスのデプロイやテストを、本番環境への影響がないようにステージング環境で実施することができます。この新しいバージョンのサービスは、必要なテストに合格した後、既存の本番環境のサービスと入れ替える形で本番環境に導入することができます。「古い」本番環境への既存の接続はそのまま変更されず、新しい接続は「新しい」本番環境にルーティングされます。

負荷分散サービスの例

ここからは、負荷分散サービスで提供される前述のサービスの大部分が、サンプルのクラウド サービスでどのように利用されるかを説明します。下の図は、この例で使用する PaaS テナントのモデルです。

このテナントにはフロントエンド (FE) ロールが 2 つ、バックエンド (BE) ロールが 1 つ存在します。FE ロールは、それぞれ、HTTP、TCP、UDP の各プロトコルを使用する 4 つのエンドポイントを、負荷分散対象として公開しています。また、エンドポイントの 1 つは、ロールの正常性をロード バランサーに通知するために使用されます。BE ロールは、HTTP、TCP、UDP の各プロトコルを使用する 3 つのエンドポイントを公開しています。FE ロールと BE ロールの両方で、対応するサービスのインスタンスに直接ポート エンドポイントを 1 つずつ公開しています。

上記のサービスは、Azure のサービス モデルで次のように記述されます (わかりやすいようにスキーマの仕様を一部省略しています)。

<ServiceDefinition name="ProbeTenant">
  <LoadBalancerProbes>
    <LoadBalancerProbe name="MyProbeprotocol="httppath="Probe.aspxintervalInSeconds="5timeoutInSeconds="100" />
  </LoadBalancerProbes>
  
  <WorkerRole name="BERolevmsize="Small">
    <Endpoints>
      <InternalEndpoint name="BE_InternalEP_Tcpprotocol="tcp" />
      <InternalEndpoint name="BE_InternalEP_Udpprotocol="udp" />
      <InternalEndpoint name="BE_InternalEP_Httpprotocol="httpport="80" />

      <InstanceInputEndpoint name="InstanceEP_BEprotocol="tcplocalPort="80">
          <AllocatePublicPortFrom>
              <FixedPortRange min="10210max="10220"  />
          </AllocatePublicPortFrom>
      </InstanceInputEndpoint>
    </Endpoints>
  </WorkerRole>
  
  
  <WorkerRole name="FERolevmsize="Small">
    <Endpoints>
        <InputEndpoint name="FE_External_Httpprotocol="httpport="10000" />
        <InputEndpoint name="FE_External_Tcp"  protocol="tcp"  port="10001" />
        <InputEndpoint name="FE_External_Udp"  protocol="udp"  port="10002" />
      
        <InputEndpointname="HTTP_Probeprotocol="httpport="80loadBalancerProbe="MyProbe" />
      
        <InstanceInputEndpoint name="InstanceEPprotocol="tcplocalPort="80">
           <AllocatePublicPortFrom>
              <FixedPortRange min="10110max="10120"  />
           </AllocatePublicPortFrom>
        </InstanceInputEndpoint>

        <InternalEndpoint name="FE_InternalEP_Tcpprotocol="tcp" />
    </Endpoints>
  </WorkerRole>
</ServiceDefinition>

このサービス モデルについて、詳しく見ていきます。まず、ロード バランサーがサービスの正常性のクエリに使用する正常性プローブを定義します。

  <LoadBalancerProbes>
    <LoadBalancerProbe name="MyProbeprotocol="httppath="Probe.aspxintervalInSeconds="5timeoutInSeconds="100" />
  </LoadBalancerProbes>

これは、相対パス “Probe.aspx” という URL を使用する HTTP カスタム プローブを使用することを表しています。このプローブをエンドポイントの URL の最後に追加すると、クエリ先が完全に指定されます。

次に、FE ロールを Worker ロールとして定義します。これには、次に示すように、HTTP、TCP、UDP の各プロトコルを使用する複数のエンドポイントが含まれています。

        <InputEndpoint name="FE_External_Httpprotocol="httpport="10000" />
        <InputEndpoint name="FE_External_Tcp"  protocol="tcp"  port="10001" />
        <InputEndpoint name="FE_External_Udp"  protocol="udp"  port="10002" />

これらのエンドポイントにはカスタム プローブが割り当てられていないため、エンドポイントの正常性は仮想マシンのゲスト エージェントが管理しています。これは、StatusCheck イベントを使用すると変更できます。

次に、ポート番号 80 を使用する HTTP エンドポイントを追加で定義します。このエンドポイントでは、あらかじめ定義したカスタム プローブ (MyProbe) を使用します。

        <InputEndpoint name="HTTP_Probeprotocol="httpport="80loadBalancerProbe="MyProbe" />

ロード バランサーは、エンドポイントの情報とプローブの情報を組み合わせ、http://{VM の DIP}:80/Probe.aspx という形の URL を作成します。これは、サービスの正常性のクエリを発行する際に使用されます。サービスは、同一の IP で定期的にアクセスしていることを (おそらくログの形で) 通知します。これが、仮想マシンが実行されているノードのホストから送信される正常性プローブ要求です。

サービスは、ロード バランサーに 200 の HTTP ステータス コードを返して、サービスが正常であることを示す必要があります。他の HTTP ステータス コード (503 など) が返されると、該当する VM はローテーションから除外されます。

プローブの定義では、プローブの頻度も制御します。上の例では、ロード バランサーは 15 秒ごとにエンドポイントのプローブを実行します。正常な応答が 30 秒間 (プローブ間隔 2 回分) なかった場合、プローブはサービスが停止していると判断し、その VM はローテーションから除外されます。同様に、ローテーションから除外されているサービスから正常な応答が返されると、該当するサービスはただちにローテーションに復帰します。サービスの状態が正常と異常とで激しく変化する場合、ロード バランサーは、該当するサービスがプローブの正常な応答を一定回数返すまで、ローテーションへの復帰を遅延させることができます。

FE のサービスは直接ポートを各インスタンスにつき 1 つずつ公開しています (インスタンスの入力エンドポイント)。これは、下のコードで指定されているポートの FE インスタンスへの直接接続に使用されます。

      <InstanceInputEndpoint name="InstanceEPprotocol="tcplocalPort="80">
          <AllocatePublicPortFrom>
              <FixedPortRange min="10110max="10120"  />
          </AllocatePublicPortFrom>
      </InstanceInputEndpoint>

上の定義の場合、10110、10111、… の各 TCP ポートから、各 FE ロールの VM インスタンスの 80 番ポートに接続されます。この機能は、さまざまな場合に利用できます。

a) 特定のインスタンスに対する直接アクセスを確立して、該当するインスタンスのみに対するアクションを実行する。

b) 負荷分散対象のエンドポイントを通過した後にユーザーのアプリケーションを特定のインスタンスにリダイレクトする。これにより、特定のインスタンスに対する「固定された」セッションを使用できます。ただし、該当するインスタンスでオーバーロードが発生する可能性があることと、冗長性がなくなることに注意する必要があります。

最後に、FE ロールが内部エンドポイントを公開します。これは、FE ロールと BE ロールの間の通信で使用されます。

        <InternalEndpoint name="FE_InternalEP_Tcpprotocol="tcp" />

各ロールは、自身が公開しているエンドポイント、および他のロールが RoleEnvironment クラスを使用して公開しているエンドポイントを検出できます。

BE ロールは、Worker ロールとしてもモデル化されます。

BE ロールは負荷分散の対象となるエンドポイントは公開せず、HTTP、TCP、および UDP を使用する内部エンドポイントのみを公開します。

      <InternalEndpoint name="BE_InternalEP_Tcpprotocol="tcp" />
      <InternalEndpoint name="BE_InternalEP_Udpprotocol="udp" />
      <InternalEndpoint name="BE_InternalEP_Httpprotocol="httpport="80" />

上の定義の場合、10210、10211、… の各 TCP ポートから、各 BE ロールの VM インスタンスの 80 番ポートに接続されます。

      <InstanceInputEndpoint name="InstanceEP_BEprotocol="tcplocalPort="80">
          <AllocatePublicPortFrom>
              <FixedPortRange min="10210max="10220"  />
          </AllocatePublicPortFrom>
      </InstanceInputEndpoint>

ここまでの説明で、すべての負荷分散機能がサービスのモデル化で使用される様子をおわかりいただけたでしょうか。

今後の記事では、このテナントの実際の動作について説明し、サンプル コードをご紹介する予定です。次の項目の詳細についてもお伝えします。

a) SNAT のしくみ

b) カスタム プローブ

c) 仮想ネットワーク

また、皆様が詳細な説明をご希望される項目がありましたらお知らせください。

Microsoft Azure ネットワーキング チームへ

Marios Zikos

Comments (0)

Skip to main content