inductor's blog

nothing but self note :)

Googleが作った分散アプリケーション基盤、Borgの論文を読み解く -その5(最後の翻訳)-

このエントリーについて

このエントリーを書き始めた経緯は下記にあります。

blog.inductor.me

今回で翻訳は最後になります。前回のエントリーはこちらです。

blog.inductor.me

8. 教訓と今後の課題(Lessons and future work)

このセクションでは、10年以上にわたって本番環境でBorgを運用してきたことから学んだ定性的な教訓のいくつかを説明し、Kubernetesの設計でこれらの考察がどのように活かされているかを説明します[53]。

8.1 学び: 失敗談

まずは、「訓話」として話すのにちょうど良いBorgが持ついくつかの機能から始め、Kubernetesではこれを避けるためにどのように設計したかも合わせてご紹介します。

ジョブは、タスクの唯一のグループ化メカニズムとして制限されています。Borgには、マルチジョブサービス全体を単一のエンティティとして管理したり、サービスの関連インスタンス(カナリアトラックやプロダクショントラックなど)を参照したりするための"いい感じ"な方法がありません。代替策として、ユーザーはサービストポロジをジョブ名にエンコードすることによって、サービスディスカバリに必要な高レベルの管理ツールを構築する必要があります。対向側のサービスからはジョブの任意のサブセットを参照することはできません。これは、ローリングアップデートやジョブのサイズ変更において、柔軟性のないセマンティクスなどを始めとしたいくつかの問題につながります。

このような問題を避けるため、Kubernetesではジョブの概念をやめ、代わりにラベル(ユーザーがシステム内の任意のオブジェクトに付与できる任意のキーバリューの組み合わせ)を使用してスケジューリングユニット(Pod)を整理します。Borgジョブと同等の機能は、job:job名のようなラベルを一連のPodに添付することで実現できますが、該当サービスの種別、重要度、リリースタイプ(本番、ステージング、テストなど)といった他の有用なグループ化も表現できます。Kubernetesのオペレーションでは、オペレーションを適用するオブジェクトを選択するラベルクエリを使用してターゲットを識別します。このアプローチにより、ジョブの単一の固定グループ化よりも柔軟性が高まります。

マシンごとに1つのIPアドレスを使用すると、構成が複雑になります。Borgでは、マシン上のすべてのタスクがホストの単一のIPアドレスを使用するため、ホストのポート空間が共有されます。これにより多くの問題が発生します。Borgではポートをリソースとしてスケジュールする必要があります。Borgのタスクは、必要なポートの数を事前に宣言し、開始時にどのポートを使用するかを通知する必要があります。Borgletはポートの分離を強制する必要があります。また、名前解決のシステムとRPCシステムは、ポートとIPアドレスを処理する必要があります。

Linux名前空間、VM、IPv6、およびソフトウェア定義ネットワークの出現により、Kubernetesはこれらの複雑さを排除した、よりユーザーフレンドリーなアプローチをとることができます。すべてのPodとサービスが独自のIPアドレスを取得するため、開発者はポートを選択できるため、ソフトウェアをインフラストラクチャで選択されたポートに合わせる必要がなくなり、これらのインフラストラクチャがもたらす複雑さがなくなります。

Kubernetesではカジュアルなユーザーを犠牲にしてパワーユーザー向けに最適化が行われました。Borgは「パワーユーザー」を対象とした多数の機能セットを提供するため、プログラムの実行方法を微調整できます(BCL仕様には約230のパラメーターが記載されています)。最初の目的は、Google社内における最大のリソース消費者をサポートすることで、この利益が最も重要でした。残念なことに、このようなAPIの豊富さは、「カジュアル」なユーザーにとって物事を難しくし、その進化を制限します。私たちのソリューションは、Borg上で実行される自動化ツールとサービスを構築し、実験から適切な設定を決定することです。これらは、耐障害性アプリケーションによって提供される実験の自由から恩恵を受けます。自動化が失敗した場合、それは災害ではなく迷惑になります。

8.2 学び: 成功談

こうした一方で、Borgの多くの設計の特徴は非常に有益であり、時の試練に耐え、長く使われ続けてきました。

allocは便利です。Borgが持つallocの抽象化は、広く使用されているlogsaverパターン(§2.4)と、Webサーバーが使用するデータを単純なdata-loaderタスクが一定期間で更新するもう1つの一般的なパターンを生み出しました。allocとパッケージを使用すると、このようなヘルパーサービスを別のチームで開発できます。allocに相当するKubernetesはPodです。Podは、常に同じマシンにスケジュールされ、リソースを共有できる1つ以上のコンテナのリソース集合体です。Kubernetesにおいては、allocのタスクではなく同じPodのヘルパーコンテナを使用しますが、考え方は同じです。

クラスタ管理はタスク管理以上の仕事です。Borgの主な役割はタスクとマシンのライフサイクルを管理することですが、Borgで実行されるアプリケーションは、名前解決や負荷分散など、他の多くのクラスターサービスの恩恵を受けます。Kubernetesは、サービスの抽象化を使用した名前付けと負荷分散をサポートしています。サービスには、名前とラベルセレクターによって定義された動的なPodのセットがあります。クラスター内の任意のコンテナーは、サービス名を使用してサービスに接続できます。裏側では、Kubernetesはラベルセレクターに一致するPod間でサービスへの接続を自動的に負荷分散し、Podが実行されている場所を追跡します。

イントロスペクションは重要です。Borgはほとんどの場合「正常に動作」しますが、何か問題が発生した場合、根本原因を見つけるのは難しい場合があります。Borgにおける重要な設計上の決定は、デバッグ情報を非表示にするのではなく、すべてのユーザーに表示することでした。Borgには何千人ものユーザーがいるため、デバッグの最初のステップは「自己対応」でなければなりません。これにより、機能の廃止やユーザーが依存するようになる内部ポリシーの変更が難しくなりますが、それでもなおメリットが勝り、現実的な代替手段は見つかりませんでした。こうした膨大な量のデータを処理するために、複数レイヤでUIおよびデバッグツールを提供します。これにより、ユーザーはジョブに関連する異常なイベントをすばやく特定し、アプリケーションおよびインフラストラクチャ自体から詳細なイベントおよびエラーログにドリルダウンできます。

Kubernetesは、Borgのイントロスペクション手法の多くを再現することを目指しています。たとえば、リソース監視用のcAdvisor [15]、Elasticsearch / Kibana [30]およびFluentd [32]に基づくログ集約などのツールが同梱されています。マスターは、オブジェクトの状態のスナップショットを照会できます。Kubernetesには、すべてのコンポーネントがクライアントが利用できるイベント(たとえば、スケジュールされているPod、コンテナの障害)を記録するために使用できる統一されたメカニズムがあります。

マスターは、分散システムにおけるカーネルです。Borgmasterはもともとモノリシックシステムとして設計されましたが、時間が経つにつれて、ユーザージョブを管理するために協力するサービスのエコシステムの中心に位置するカーネルになりました。たとえば、スケジューラとプライマリUI(Sigma)を個別のプロセスに分割し、アドミッションコントロール、垂直および水平自動スケーリング、タスクの再パッキング、定期的なジョブ送信(cron)、ワークフロー管理のためのサービス、およびオフラインクエリのためのシステムアクションのアーカイブを追加しました これらを組み合わせることで、パフォーマンスや保守性を犠牲にすることなく、ワークロードと機能セットを拡張できます。

Kubernetesアーキテクチャはさらに進んでいます。コアにAPIサーバーがあり、リクエストの処理と、基礎となる状態オブジェクトの操作のみを担当します。クラスター管理ロジックは、障害が発生した場合にPodのレプリカを必要な数だけ保持するレプリケーションコントローラーやマシンのライフサイクルを管理するノードコントローラーなど、このAPIサーバーのクライアントである小さな構成可能なマイクロサービスとして構築されます。

8.3 結論

Googleのクラスターワークロードのほぼすべてが、過去10年間でBorgを使用するように切り替わりました。私たちはそれを進化させ続け、それから学んだ教訓をKubernetesに適用しました。

謝辞(Acknowledgments)

この論文の著者は評価を行い、論文を執筆しましたが、Borgのコンポーネントとエコシステムを設計、実装、および保守した数十人のエンジニアが成功の鍵です。ここでは、BorgmasterとBorgletsの設計、実装、および運用に最も直接参加した人だけをリストします(誰かを見逃していた場合は謝罪します)。

初期のBorgmasterは、主にJeremy DionとMark VandevoordeがBen Smith、Ken Ashcraft、Maricia Scott、Ming-Yee Iu、およびMonika Henzingerとともに設計および実装しました。最初のBorgletは、主にPaul Menageによって設計および実装されました。

その後の貢献者には、Abhishek Rai、Abhishek Verma、Andy Zheng、Ashwin Kumar、Beng-Hong Lim、Bin Zhang、Bolu Szewczyk、Brian Budge、Brian Grant、Brian Wickman、Chengdu Huang、Cynthia Wong、Daniel Smith、Dave Bort、David Oppenheimer、David Wall、Dawn Chen、Eric Haugen、Eric Tune、Ethan Solomita、Gaurav Dhiman、Geeta Chaudhry、Greg Roelofs、Grzegorz Czajkowski、James Eady、Jarek Kusmierek、Jaroslaw Przybylowicz、Jason Hickey、Javier Kohen、Jeremy Lau、Jerzy Szczepkowski、John Wilkes、Jonathan Wilson、Joso Eterovic、Jutta Degener、Kai Backman、Kamil Yurtsever、Kenji Kaneda、Kevan Miller、Kurt Steinkraus、Leo Landa、Liza Fireman、Madhukar Korupolu、Mark Logan、Markus Gutschke、Matt Sparks、Maya Haridasan、Michael Abd-El-Malek、Michael Kenniston、Mukesh Kumar、Nate Calvin、Onufry Wojtaszczyk、Patrick Johnson、Pedro Valenzuela、Piotr Witusowski、Praveen Kallakuri、Rafal Sokolowski、Richard Gooch、Rishi Gosalia、Rob Radez、Robert Hagmann、Robert Jardine、Robert Kennedy、Rohit Jnagal、Roy Bryant、Rune Dahl、Scott Garriss、Scott Johnson、Sean Howarth、Sheena Madan、Smeeta Jalan、Stan Chesnutt、Temo Arobelidze、Tim Hockin、Todd Wang、Tomasz Blaszczyk、Tomasz Wozniak、Tomek Zielonka、Victor Marmol、Vish Kannan、Vrigo Gokhale、Walfredo Cirne、Walt Drummond、Weiran Liu、Xiaopan Zhang、Xiao Zhang、Ye Zhao、Zohaib Mayaがいます。

BorgのSREチームも重要であり、Adam Rogoyski、Alex Milivojevic、Anil Das、Cody Smith、Cooper Bethea、Folke Behrens、Matt Liggett、James Sanford、John Millikin、Matt Brown、Miki Habryn、Peter Dahl、Robert van Gent、Seppi Wilhelmi、Seth Hettich、Torsten Marek、Viraj Alankarが含まれています。Borg構成言語(BCL)およびborgcfgツールは、元々Marcel van LohuizenとRobert Griesemerによって開発されました。

この論文に対するフィードバックをいただいたレビュアー(特にEric Brewer、Malte Schwarzkopf、Tom Rodeheffer)と、我々の”羊飼い”であるChristos Kozyrakisに感謝します。


最後の最後まで非常に勉強になりました。

特に、Borgが抱えた課題とKubernetesが解決したアプローチの部分や、Kubernetesの根幹をなすマイクロサービスたちがどのような経緯で形作られていったかが何となく見えるような感じがして非常に面白いですね。

引き続き、折を見て全体の振り返りと考察について書いていきたいと思います。