インフラエンジニアをやっている井島です。
hinata の各プロダクト(Rental, Spot, Media)はGKEで稼働しており、GitOpsの考え方でデプロイを行っています。 今回はvivit で実際に使っている具体的なデプロイ構成についてご紹介したいと思います。
vivit では、開発環境は各人のローカルPC上とし、ステージング環境、本番環境はGKE上にあります。 開発環境で開発したものは、各々がステージング環境にデプロイして、最終的に本番環境にデプロイして、リリース完了、という開発の大きな流れになっています。
vivit では、1つのチームが1つのマイクロサービスの開発を行っているのではなく、基本的にプロダクト毎に開発チームが別れています。1つのチームが複数のマイクロサービスを扱っており、開発内容によってリリース範囲が変わってきます。
構成
GitHubレポジトリは基本的にモノレポ構成で、プログラムコードとk8sマニフェストも同じレポジトリに入っています。k8sへのデプロイにはArgoCDを使用しており、CIには主にCircleCIを使用しています。
開発者がコードをレポジトリにPushするとCircleCIでDocker build が実行され、コンテナがGCSにPushされます。
そして、開発者がGKE上の環境にデプロイしたい時は、git tag をレポジトリにPushして、デプロイをトリガーします。この時、CircleCIではデプロイ用の命名規則のgit tag 名だった場合にデプロイ処理を発火するように設定してあります。
このデプロイ処理は、k8sマニフェストでコンテナイメージのタグを更新し、レポジトリのmaster ブランチに対してPull Request を作成する処理です。
そして、開発者はCIによって作成されたPull Request を自分でApproveし、master にMergeすることで、一連の操作が完了です。
このPull RequestのMergeが、実際に環境へのデプロイ(Podの更新)処理開始のトリガーとなります。
ArgoCDはいずれの環境へもGitHubのmaster ブランチを参照するよう設定しており、ステージング環境であっても、master ブランチにあるマニフェストが正とすることを大切にしています。
詳細
この構成の欠点は、デプロイをトリガーする前に、GCR上にコンテナが出来上がっていることを事前に開発者が確認する必要があることです。
しかし、現在のvivit の開発チーム構成からデプロイの柔軟性を優先して、この構成にしています。
このデプロイ手順については以下の要求に対応できるよう設計しています。
1つのマイクロサービスだけリリースしたい
複数のマイクロサービスを同時にリリースしたい
チーム内で管理しているすべてのマイクロサービス(≒プロダクト)を同時にリリースしたい
特定のブランチ(で作成されたコンテナ)を特定の環境にデプロイしたい
ステージングや本番への各環境へのデプロイ手順に差異がないようにする
いま各環境にデプロイされているアプリケーションのバージョンなど(どのコンテナを使っているか)は、k8sマニフェストから追えるようにしたい
上記条件でデプロイを行うためにgit tag 作成でデプロイのトリガー、git tag の内容によって、どのブランチの、どのマイクロサービスを、どの環境にデプロイするかを制御しています。 具体的なgit tag の内容は以下です。
git tag 命名規則
<プロダクト名>/<環境名>/<年>/<月>/<日>/<時分>-<氏名>-<マイクロサービス(コンマ区切りで複数指定可)> 「ブランチ」の指定は、目的のブランチに移動してからgit tag を行う。
product1 の service1 とservice2 を production 環境にデプロイする時
product1/production/2020/09/29/1234-ijima-service1,service2
product1 のすべてのマイクロサービスをstaging 環境にデプロイする時
product1/staging/2020/09/29/1234-ijima
CircleCI では git tag 付与をトリガーとしてCIを実行できるので、その構成を行い、git tag のパース、指示されたデプロイ内容に基いたマニフェストの更新(コンテナイメージタグ部分)、Pull Request 作成などの処理を実装しています。
最後に
CircleCIなどの具体的なコードは割愛していますが、実際に使っている GitOpsなデプロイの具体的な構成の紹介でした。
デプロイ手順は、会社やチームによって、いろいろな要件が出てくるかと思います。なにかの参考になれば幸いです。