LIVESENSE ENGINEER BLOG

リブセンスエンジニアの活動や注目していることを発信しています

Kubernetes manifests を単一リポジトリで集中管理する運用設計

Data Platform グループのリーダーの田中です。データ分析基盤 Livesense Analytics と機械学習基盤 Livesense Brain のプロジェクトマネジメント/アーキテクチャリングをしています。

今回は Livesense Brain における Kubernetes (k8s) manifest の管理方式と運用設計について紹介します。

2種類の管理方式: 個別管理と集中管理

k8sクラスタで複数のシステムを運用しmanifestをGit管理するとき、その管理方式は大きく次の2種類に分けられます。

  • 個別管理: 各システムの実装を管理するGitリポジトリにmanifestを一緒に含める
  • 集中管理: 各システムのリポジトリと別に、全manifestを管理する単一のリポジトリをおく

個別管理の場合、各システムのリポジトリで開発〜運用にかかわるすべてのコードを管理できるため、リポジトリをまたいで考えることが少ないという長所があります。

逆に集中管理の場合、複数システム間でCI/CDフローを統一できるなど、各システムごとに必要な運用知識の差分を少なくできるという長所があります。

網羅的に調べたわけではありませんが、Skaffoldを始めとして最近人気のあるmanifest管理ツールは主に個別管理を意識してつくられているように感じます。ただ私自身は、2つの方式のどちらかがより優れているというわけではなく、チームのニーズに応じて選択すればよいと考えています。

Livesense Brain の選択: 集中管理

リブセンスの全社横断的な機械学習基盤である Livsense Brain はGKEを中心に構築されており、単一のGKEクラスタ上で Webアプリ・バッチ処理・ストリーミング処理 のような様々な形態の十数個のシステムが稼働しています。下記にシステムの一例を示します。

  • アルバイト求人メディア「マッハバイト」のレコメンドデータ生成システム(バッチ処理)
  • 全社共通のレコメンドデータ配信・A/Bテスト用システム(Webアプリ + バッチ処理)
  • MLジョブの途中経過や精度指標のログを収集・通知するシステム(ストリーミング処理)

Livesnse Brain ではこれらを含む全システムのmanifestを単一リポジトリで集中管理しています。

すなわち、上記のようなシステムの実装リポジトリと別に、manifest専用のリポジトリをひとつ用意し、Webアプリを構成する Deployment, Service, Ingress やバッチ処理を構成する CronJob, Workflow (Argo) などリソースのYAML定義を全てこのリポジトリで管理しています。

集中管理を選択している理由はいくつかありますが、主には「常任メンバーが少なくても運用負荷を抑えやすい」こと、「リリースフローをビルドとデプロイに分割できる」ことが挙げられます。以下でそれぞれの理由をもう少し詳しく説明します。

理由1: 常任メンバーが少なくても運用負荷を抑えやすい

Livesense Brain 上で稼働しているシステムは十数個あり、各システムは少なくともひとつのWebアプリやバッチ処理からなります。Deployment, CronJob などのワークロードリソースの総数は数十個程度です。

基盤全体と各システムの開発・運用に携わる常任メンバーは現在4名です。後述のように常任メンバー以外にも多くの人が開発に関わりますが、そうした人々は特定のシステムの実装の一部を担当することが多く、manifestの管理やワークロードの監視などの運用面は基本的に常任メンバーのみで担っています。

仮にシステムごとのmanifestを個別管理すると、各々のmanifestの書き方やデプロイフローなどの運用設計に差異が生じやすくなり、それら全てを把握する必要がある常任メンバーの1人あたりの運用負荷が相対的に高まることが懸念されます。 厳格なルールを設ければそのような事態を防ぐこともできそうですが、すると今度は運用設計やルール自体を全体的に変更したいときに全リポジトリに手を入れることが必要になり、気軽に仕組みを変えるのが難しくなります。

集中管理であれば、運用設計を単一のmanifest管理リポジトリの中にコード化できるため、システムごとの差分が生じにくく変更も容易になり、常任メンバーの運用負荷を抑えられると考えています。

理由2: リリースフローをビルドとデプロイに分割できる

集中管理ではシステムの変更をリリースするまでに、システム実装リポジトリとmanifest管理リポジトリという2つのリポジトリに対する変更 (=プルリクのマージ) が必要です。これは一見手間がかかるように思えますが、 Livesense Brain ではこの特性を活かしていくつかの運用課題を解決しています。

リリースフローにおいて、これら2つのリポジトリへの変更は次のように位置づけられます。

  1. システム実装リポジトリへの変更 = ビルドステップ
  2. manifest管理リポジトリへの変更 = デプロイステップ

ビルドステップでは、プルリクマージ時にコンテナイメージをビルドし、できたイメージをコンテナレジストリにpushするところまでが自動化されています。イメージはプルリク単位でバージョニングされており、レジストリは本番・開発環境で共通です。

ビルドステップではシステムの実行環境への変更は一切行われないため、いわば気楽にプルリクをマージできます。経験値の浅いメンバーからのプルリクや、dependabotが自動作成したプルリクであっても、CIによるテストさえ通っていれば「とりあえずマージしてうまく動かなかったらrevertしよう」という判断がしやすくなります。 Livesense Brain では常任メンバー以外に、MLアルゴリズムの開発を担うデータサイエンティスト、事業部から一時的に開発に参加するエンジニア、学生インターンの研究・開発アシスタントなど様々な人がプルリクを作成するため、それらを迅速かつ安全にマージできることは生産性に直結します。

デプロイステップでは、DeploymentのイメージバージョンやConfigMapの値などの変更をプルリクとして作成し、プルリクマージ時にmanifestが本番環境に適用されるようになっています。また作成中のプルリクのコミットにtagを付与してpushすると、未マージのプルリクを開発環境にデプロイして動作確認を行うこともできます。

デプロイステップの実行後に問題が発生した場合、切り戻し作業はmanifestの変更内容をrevertするプルリクを作成してマージするだけです。これによって問題の影響を最小限に抑え、根本原因を調査する時間を確保することができます。

f:id:yubessy:20211202111119p:plain
リリースフローをビルドステップとデプロイステップに分割する

おわりに

k8s manifest を単一リポジトリで集中管理することについて、 Livesense Brain での背景をもとに説明しました。このような運用設計が適しているかどうかはもちろんチームの規模や役割によって変わりますが、同じような課題に取り組んでいるチームの参考になれば幸いです。