モノレポのCI/CDについて考える
情報収集のため
前提として、ここでのモノレポは単にstatelessなライブラリ群を管理するレポジトリを指すのではなく、apiサーバーやwebサーバーなどstateが存在するレポジトリを指す。前者はコンパイルの順番さえ守ればよいが、後者は依存を考慮したデプロイパイプラインを考える必要がある。
zozoのパターン
根底にある考え方
- 開発した機能はテストと手動チェックの後すぐに本番環境へ反映させたい
- trunkベース開発
- k8sを採用しているのでインフラは共通化されている。k8sのエコシステムを利用
流れ
- mainブランチにpush
- GitHub Actionで差分のあるディレクトリを検知
- 差分のあるマイクロサービスのみbuild&push
- 開発環境の自動更新? and 本番環境へ手動承認
- k8sのmanifestを自動変更
- k8sのインフラの更新
k8sを利用している場合
インフラは共通なのでデプロイパイプラインをk8sとそのエコシステムにまかせることができる。
IaaSを利用している場合
インフラはk8sほど共通化前提ではないので、デプロイパイプラインは環境×サービスごとに作成する必要がある。Buildパイプラインはある程度共通化できる。
k8sを利用していないパターン
- mainブランチにpush
- GitHub Actionで差分のあるディレクトリを検知
- 差分のあるサービスのみbuild&push
- 差分のあるサービスのみ開発環境のdeploy
- 本番環境へ手動承認
- 差分のあるサービスのみ本番環境のdeploy
モノレポにタグ運用は向いているのか
よくあるパターンとしてmainブランチにリリースし、リリースブランチorリリースタグで本番環境にリリースする方法がある。こうすることで、mainブランチのどのコミットをリリースするか決めることができ、またリリースバージョンの管理ができる。
これをモノレポに適用できるか?
レポジトリ全体にタグ付けすると、変更のないサービスのコードもそのタグで運用されてしまう。
そこで、GitHub Actionなどで差分のあるサービスのみbuildした際に、バージョンタグを更新することが考えられる。
そして、各サービスごとにリリースタグをつけることで、各サービスのデプロイパイプラインが立ち上がる。
- mainブランチにpush
- GitHub Actionで差分のあるディレクトリを検知
- 差分のあるサービスのみbuild&push gitのバージョンタグを更新し、イメージタグにバージョン情報を追加
- 差分のあるサービスのみ開発環境のdeploy
- 更新したい本番環境のタグにリリースタグをつける
- リリースタグのバージョン番号に応じて、イメージをpullしリビジョンを作成、デプロイ
ということで、モノレポでも従来のリリースタグによる運用は可能。
継続的デリバリー vs 手動デプロイ
zozoのようなbuildからそのまま本番環境へリリースするパイプラインが1本のものもあれば、
タグ運用によるリリースにように、リリースするコードを手動で選ぶこともできる。
これらの違いは、組織が継続的デリバリーを採用するかどうかだと思う。
継続的デリバリーとは、ソフトウェアをつねにリリースできる状態にもっていくことらしい
一般的に、DevOpsの界隈では価値を早く届けることがよしとされているので、継続的デリバリーを採用すべしと主張する。
しかし、継続的デリバリーを採用するのはかなり挑戦的だとも思う。
- mainブランチが信頼に足るものである
- バグがない
- 自動テストが充実している
- セキュリティに穴がない
- レビューが機能している
- 開発エンジニアのレベルが高い
- SecOpsが組み込まれている
- バグがない
- リスク管理
- いつでもロールバックできる仕組みがある
- サービスレベルが高すぎない
- 1つのバグが金銭的問題に発展しない
- 1つのバグが人命に影響しない