CTC 教育サービス
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes
みなさん、こんにちは! グーグルでCloud Solutions Architectとして活動させていただいている中井です。グーグルは古くから、自社サービスの提供に独自のソフトウェア技術を活用してきました。これらの技術の中には、グーグルに所属する研究者の手によって開発されたものもありますが、実は、「Research at Google」というWebサイトでは、これらの研究者が執筆した論文が公開されています。つまり、これらの論文を通して、グーグルの技術が勉強できてしまいます。これはスゴイ!
―― とは言うものの、いきなり論文を読めといわれても、敷居が高くて困ってしまうのも事実です。そこで、この連載では、これらの論文の内容をやさしく解説しながら、「地球規模」とも言われるインフラを支えるために開発された技術を紹介していきます。前提知識から説明を進めていきますので、インフラ技術を基礎から勉強し直したい方にも役立つものと思います。現在、グーグルが提供するクラウドサービスである「GCP(Google Cloud Platform)」でも、グーグルのインフラ技術が活用されています。本連載を通して、大規模分散処理の仕組みを理解すれば、GCPをより深く使いこなすこともできるでしょう。
記念すべき最初のテーマは、「ロードバランサー」です。2016年に公開された論文「Maglev: A Fast and Reliable Software Network Load Balancer」では、一千台以上のバックエンドサーバーにパケットを分散するために開発された、「Maglev」という分散処理方式のロードバランサーが紹介されています。今回は、Maglevの仕組みを理解する前提として、一般的なロードバランサーのアーキテクチャーと、ロードバランサーの処理を分散化するためのポイントとなる技術要素を押さえておきたいと思います。
多数のクライアントからのアクセスを複数のサーバーに振り分けるロードバランサーの役割は、みなさんご存知のことと思います。しかしながら、全世界からアクセスされる「地球規模」のアプリケーションとなると、アクセスを分散するにも複数の段階があります。図1は、2箇所のデータセンターに配置された、典型的なWebアプリケーションシステムの構成例です。
図1 複数データセンターを利用したWebアプリケーションの構成例
ここでは、GCPのクラウドを想定して、環境を構築しています(*1)。まず、GCPの「Cloud Load Balancing」を利用すると、1つのグローバルIPアドレス(VIP: Virtual IP)を用いて、地球上のすべてのリージョンにアクセスを分散することができます。インターネットとGCPの内部ネットワークを接続するPoP(Point of Presence)と呼ばれる施設が世界の複数箇所にあり、クライアントから送信されたパケットは、どれか1つのPoPを経由して、内部ネットワークに入ります。この後、内部ネットワークに配置されたロードバランサーによって、特定のリージョンのWebサーバーへとパケットが転送されます。当然ながら、アクセス元のユーザーの地域に応じて、最適なPoPを経由して、最適なリージョンへと転送されるようになっています。そして、一般的なWeb3層アプリケーションであれば、Webサーバーの背後には、複数のアプリケーションサーバーがあり、Webサーバーからアプリケーションサーバーへのアクセスについても負荷分散が行われます。
今回のテーマである、Maglevは、VIP宛のパケットを受け取って、複数のWebサーバーにパケットを転送する部分の役割を担います。これは、フロントエンドロードバランサーと呼ばれるもので、一般には、ハードウェアアプライアンスがよく利用されます。しかしながら、それでは、1台のアプライアンスの性能限界を超えることができません。複数のLinuxサーバーを用いて、ロードバランサーの処理を並列に実施することがMaglevの目的です。
Maglevの仕組みそのものは、次回に詳しく解説することにして、ここでは、Maglevを実現する上でポイントなる、ロードバランサーの機能を説明しておきます。コネクショントラッキングとDSR(Direct Server Return)です。
まず、コネクショントラッキングは、クライアントから見た時に、1つのセッションに伴うパケットを同じWebサーバーに転送する機能です。たとえば、ブラウザーからWebサーバー上の画像ファイルにアクセスした場合、ブラウザーとWebサーバーの間では、複数のパケットがやりとりされます。この時、ブラウザーから送信された最初のパケットとその次のパケットが異なるWebサーバーに転送されてしまうと、画像のダウンロードはうまくいきません。ロードバランサーで複数のWebサーバーにパケットを振り分けるとはいえ、1つの処理に伴う一連のパケットは、同じWebサーバーに転送する仕組みが必要です。
これは通常、5-tuple(5つ組)と呼ばれる情報を用いて実現されます。5-tupleは、IPパケットのヘッダーに含まれる「プロトコル番号(TCP/UDP/ICMPなど)、送信元IP、送信元ポート番号、宛先IP、宛先ポート番号」の事で、これらを用いて、「1つの処理に伴うパケット」を判別します。つまり、5-tupleが同じパケットは、すべて同じWebサーバーに転送するという仕組みを実装します。
この時、ロードバランサーが1台だけであれば、ある5-tupleのパケットをどのWebサーバーに転送するかは、ロードバランサー内部で自由に決めることができます。しかしながら、ロードバランサーが複数ある場合は、そういうわけには行きません。詳しくは次回に説明しますが、場合によっては、同じクライアントからのパケットが異なるMaglevサーバーに到達することがあります。このような場合でも、これらのパケットは同じWebサーバーに転送される必要があります。複数のMaglevサーバーで情報を共有することなく、間違いなく同じWebサーバーを選択するようなことは可能なのでしょうか? これが1つのポイントです。
もう一つのDSRは、Webサーバーから返送されるパケットは、ロードバランサーを経由せずに、クライアントに直接送る仕組みです。一般に、Webサーバーとの通信は、下り方向(Webサーバーからクライアントの方向)の通信量が多くなるので、この方向はロードバランサーを経由しないことで、通信性能を向上することができます(図2)。
図2 DSRを用いた際のパケット転送経路
これは、ロードバランサーからWebサーバーにパケットを転送する際に、ヘッダーに含まれる5-tupleの情報を書き換えずに、そのままWebサーバーに送ることで実現します。これにより、Webサーバーは、ヘッダーに含まれる送信元IPアドレス、すなわち、クライアントのIPアドレスに直接にパケットを返送することになります。
それでは、ロードバランサーは、WebサーバーのIPアドレスを指定することなく、どうやって目的のWebサーバーにパケットを転送するのでしょうか? これは、L2レイヤーでパケットを転送することで実現します。ロードバランサーとWebサーバーが同一のサブネットに属していて、L2スイッチで直結された状態であれば、宛先MACアドレスとして、WebサーバーのMACアドレスを指定することで、パケットの転送が行われます。Webサーバーの側では、ループバックデバイスのIPアドレスとして、VIPを設定しておくことにより、これを自分宛てのパケットして受け取ることが可能です(図3)。
図3 L2レイヤーによるパケットの転送
ただし、Maglevは、一千台以上のサーバーにパケットを転送する想定のため、これらをすべて同じサブネットに接続するのは現実的ではありません。場合によっては、他のデータセンターにあるWebサーバーを含めて負荷分散する場合もあります。L3レイヤーで接続されたWebサーバーに対してDSRを実現するには、少し工夫が必要です。
なお、ロードバランサーとWebサーバーに同じVIPを設定して、問題がおきないか心配になるかもしれません。Webサーバーでは、ループバックデバイスのIPアドレスついては、ARPリクエストに応答しないように設定しておきます。これにより、外部からは、ロードバランサーだけがVIPを持っているように見えるので問題にはなりません。(GCPでCloud Load Balancingを使用する場合、このようなWebサーバー側で必要な設定は、ゲストOSで稼働するエージェントが自動的に行います。)
今回は、分散型のロードバランサーを実現する「Maglev」について、これを理解するための前提知識を整理しました。コネクショントラッキングとDSRは、ロードバランサーの基本ですので、まずは、これらの仕組みを押さえてください。次回は、これらに関わる課題をMgalevがどのようにして解決しているのか、その仕組みを説明していきたいと思います。
*1 この構成の詳細は、「OpenStackユーザーのためのGoogle Cloud Platform入門(パート4)」を参考にしてください。
Disclaimer:この記事は個人的なものです。ここで述べられていることは私の個人的な意見に基づくものであり、私の雇用者には関係はありません。
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes