CTC 教育サービス
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes
前回に続いて、2020年に公開された論文「Scalable Build Service System with Smart Scheduling Service(PDF)」を紹介します。この論文では、Google社内で利用されている「分散ビルドシステム」のアーキテクチャーが解説されています。今回は、このシステムの具体的なアーキテクチャーを説明します。
Google社内の分散ビルドシステムは、その名前の通り、独立したいくつかのシステムが連携する分散型のアーキテクチャーになっています。主要なサービスは、図1のようにまとめられます。
図1 分散ビルドシステムのアーキテクチャー概要(論文より抜粋)
まずは、開発者がクライアント(Client)を用いて、スケジューリングサービス(Scheduling Service)にビルドリクエストを送信するところから処理がはじまります。リクエストを受け付けたスケジューリングサービスは、ユニークな「ビルドID」を割り当てて、クライアントに返送します。実際のビルド処理は、その背後にあるBazel WorkerとExcecutor Clusterによって非同期に行われますが、ビルドの進捗状況は、イベントサービス(Event Service)に記録されます。クライアントは、ビルドIDを用いて、該当のビルドの実行状態をイベントサービスから取得することができます。
特に「WatchBuild API」を利用すると、ビルド実行中のログ出力をリアルタイムに取得することができます。前回の記事では、開発者がワークステーション端末でビルドコマンドを実行すると、ビルド実行中のログメッセージが端末画面にリアルタイムで表示されると説明しました。これは、内部的には、WatchBuild APIを用いて実装されています。
また、イベントサービスには、実行中のログメッセージに加えて、ビルド後に実行されるテストの実行結果などを含む、より詳細な情報も集められます。クライアントは、ワークステーション端末に表示するべき情報だけをフィルタリングして取得しますが、図1のOutput Storageは、すべての情報を取得してストレージに長期保存します。Output Storageは、専用のWeb UIを提供しており、開発者は過去に実行したビルドの詳細をここから検索することができます。
なお、クライアントが利用できるAPIの全体は、図2のようになります。ビルド処理の詳細は、Bazelのビルド仕様ファイルとして受け渡しますので、APIの構成自体はシンプルにできています。
図2 クライアントが利用可能なAPI(論文より抜粋)
実際のビルド処理の進捗を管理するのは、Bazel Worker内で稼働する「Workspace」の役割になります。複数あるBazel Workerのそれぞれが、さらに複数のWorkspaceを持つ形になります。スケジューリングサービスは、受け付けたビルドの優先順位に応じて、ビルドジョブをWorkspaceに振り分けていきます。ビルドジョブを割り当てられたWorkspaceは、ジョブの内容をさらに細かな複数の「アクション」へと分解して、それぞれのアクションの実行をExecutor Clusterに依頼します。ジョブに含まれる一連のアクションは、一定の実行順序に従う必要がありますが、並列に実行できるアクションについては、Executor Clusterの複数のノードで並列に実行します。
Executor Clusterに含まれるノードは、さまざまなアクションを実行していきますが、アクションの実行結果(実行して得られた生成物)をクラスター全体でのグローバルなキャッシュに格納します。Workspaceからアクションの実行を依頼されたExecutor Clusterは、はじめにキャッシュの内容を確認して、同一のアクションの実行結果が保存されている場合は、それを即座に返却します。クラスター内では膨大な数のアクションが実行されており、冒頭の論文によると、Workspaceから依頼されたアクションの99%はキャッシュから返却することができるそうです。特に、Googleのビルド環境では、共有ライブラリは使用せず、基本的には、すべてのモジュールをスタティックリンクしたシングルバイナリーを生成します。このため、頻繁にリンクされるモジュールなどは、キャッシュされている可能性が高いことが想像できます。
なお、同様のキャッシュ機能はWorkspaceにも実装されています。こちらは、個々のWorkspaceが個別にローカルキャッシュを持つ形になりますが、過去に実行した同一アクションの結果がローカルキャッシュに残っている場合は、Executor Clusterへの実行依頼そのものをスキップします。スケジューリングサービスは、Workspace内のキャッシュのヒット率が高くなるように、類似したビルド処理をできるだけ同じWorkspaceに割り当てるように動作します。
前回説明したように、この分散ビルドシステムは、複数のグループが共有して利用しており、グループごとに利用可能なリソースの上限(Quota)が設定されています。図1のQuota Governorは、グループごとのリソースの使用量とExecutor Clusterの稼働率を見ながら、稼働率ができるだけ高くなるように(稼働していない無駄なリソースが生じないように)、各グループのQuotaをダイナミックに調整します。前回紹介した「Proportional Integral Derivative Controller(PID)」は、Quota Governorに実装された仕組みになります。
また、スケジューリングサービスがWorkspaceにジョブを割り当てる際は、該当のジョブが使用するリソース量を事前に予測した上で、現在のリソース上限の範囲内でジョブが実行できるかどうかを確認します。この予測処理は、図1のML Serviceによって、機械学習モデルを用いて行われます。これらの機能の組み合わせにより、各グループのQuotaに応じた適切なリソースの割り当てと、Executor Clusterの効率的な利用が実現されています。
今回は、2020年に公開された論文「Scalable Build Service System with Smart Scheduling Service」に基づいて、Google社内の分散ビルドシステムについて、システム全体のアーキテクチャーを紹介しました。次回は、このシステムの実際の動作環境について、論文に掲載の性能データなどを含めて紹介したいと思います。
Disclaimer:この記事は個人的なものです。ここで述べられていることは私の個人的な意見に基づくものであり、私の雇用者には関係はありません。
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes