Skip to content

Instantly share code, notes, and snippets.

@yuya-takeyama
Last active January 14, 2023 11:15
Show Gist options
  • Save yuya-takeyama/1aa94cf1a72bff2faee1652517017ef7 to your computer and use it in GitHub Desktop.
Save yuya-takeyama/1aa94cf1a72bff2faee1652517017ef7 to your computer and use it in GitHub Desktop.
DevOps な組織で Monorepo から Argo CD を使って Kubernetes にデプロイする仕組みの草案

概要

image

前提条件

  • アプリケーションは Mono Repo 上にサブディレクトリとして数十ほど存在
  • 各アプリケーションは独立してリリース可能とする
    • そのためにリリースブランチ等には */release といった形でそのアプリケーションの名前を持つ
  • 開発チームは self-contained な DevOps チームへの変化を目指している
    • 開発チームはアプリケーションのコードはもちろん、Kubernetes の manifest にも ownership を持つ (持って欲しい)
    • そのため、アプリケーションコードも manifest も同一のリポジトリに保持する
    • アプリケーション用のディレクトリの中にサブディレクトリとして manifest をおく場所があり、環境ごとのバリエーションは kustomize の overlay として表現
  • GitHub の Pull Request を元に Mono Repo 内の全てのアプリケーションを単一の Kubernetes namespace にデプロイしている
    • Pull Request の ID を元に URL も発番される
    • そういった dynamic な環境は kustomize のみでの表現が難しいため、一部 envsubst による文字列置換も行なっている
  • その他、いくつかのブランチから特定の環境へのデプロイを行なっている
    • develop: デフォルトのブランチ。最新のコードが develop 環境にデプロイされる
    • */release: リリーステストの際、Jenkins からジョブをトリガーすることで develop からブランチが作成され、リリーステスト用の環境としてデプロイされる
    • */master: リリーステストで問題がなければ release ブランチからマージされ、本番環境へデプロイされる
  • manifest の変更とコードの変更は atomic に行いたい
    • コンテナの入れ替わり自体は Kubernetes の Deployment 等による rolling update となる
    • manifest が持つ各種パラメータと image tag が書き換わるタイミングは同時とする
    • Docker イメージのタグはデプロイごとにユニークにするっため、Git SHA1 を含んだもの
    • なので、manifest 中の image tag の書き換えを行うのは人間ではなく、ビルドパイプライン内で自動的にやらせたい

デプロイの流れ

1. アプリケーションコードの git push (または特定のブランチへのマージ)

フィーチャーブランチにおいては開発者が GitHub リポジトリに git push する。

develop, */release, */master に直接 git push することはなく、変更は全てPull Request へのマージにより行われるが、基本的に以降の流れは変わらない

2. Webhook で Image Builder に push イベントを通知

Image Builder が具体的にどこで動くかは未定。

CircleCI かもしれないし、Google Cloud Build のようなマネージド環境かもしれない。

単に docker build するだけなのであまりこだわらないが、ビルドが遅い時に金で殴ればとりあえず速くなる感じにはあって欲しい。

3. Image Builder が Mono Repo からチェックアウトして docker build

  • 元のブランチや Git SHA1 を元にタグが決まる
    • develop.<Git SHA1>: develop ブランチのもの
    • release.<Git SHA1>: */release ブランチのもの
    • production.<Git SHA1>: */master ブランチのもの
    • pr-123.<Git SHA1>: フィーチャーブランチのもの。数字の部分は Pull Request の ID

4. Image Builder から Manifest Reorganizer に image tag を通知

5. Manifest Reorganizer で manifest を書き換える

Manifest Reorganization は Mono Repo から持ってきた manifest に一手間加えて、GitOps Repo に push できる状態にする。

  • manifest 中の image tag を書き換える
  • ステージング環境であれば、envsubst で必要な置換を行う。
    • 主に、URL 中に含む Pull Request ID とか

これは CircleCI でいいかもしれないし、何か Serverless な実行環境でも良いかもしれない

6. GitOps Repo への git push

こちらは manifest だけで、アプリケーションコードは含まない。YAML だけを持つことになる。

ステージング環境においては、Pull Request の数だけサブディレクトリが作られて、その中に manifest が配置されるイメージ。

別で、Pull Request が close されたらそのディレクトリを削除して push するジョブも必要。

7. Argo CD による Kubernetes へのデプロイ

Argo CD が GitOps repo を watch して勝手にデプロイしてくれるので特別なことは無し。

その他

  • 説明的には Monorepo 関係ない感じになってしまった
    • 実際は変更が行われたサービスを検知し、変更のあったものだけ並列で docker build する
    • ステージング環境においては、変更がなかったサービスは develop のイメージを再利用する
  • CD だけで CI 関係なかった
    • 現行の全部 CircleCI でやってるやつだと、一つの workflow のなかでテストの実行と docker build が全部通ったら、それを待って最後に kubectl apply とかを行うシェルスクリプトでデプロイする仕組み
    • が、よく考えたら CI と CD とりあず関係を持たせる必要はなさそうな気がしてきた
    • */master へのマージ時は、 事前に */release ブランチでテストが通っていることを Pull Request 上の CI status で確認すれば、あとはマージ後に直接デプロイすれば良い
  • タコのキャラクターが多い
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment