Gunosy Tech Blog

Gunosy Tech Blogは株式会社Gunosyのエンジニアが知見を共有する技術ブログです。

管理画面にGitOpsを導入しました 〜構成編〜

はじめに

こんにちは、広告技術部の fujishiro です。普段は広告配信の API や管理画面の開発に携わっています。

さて、今回はその管理画面で下記の課題があったのですが、 Argo CD の導入と GitHub のリポジトリ戦略、ブランチ戦略を変更することで一部解決ができたため、そちらについてご紹介しようと思います。

  • 遅い CI
    • RSpec の実行に 30 分近くかかる
    • ロールバック時は Revert PR を作成することで対応するが、緊急時は CI を待てないので権限のある人が強制的にマージしている
  • CircleCI からのデプロイの失敗
    • pod が多いタイミングでデプロイすると Cluster Autoscaler が走るために CircleCI の実行時間が延び、タイムアウトしたりする
  • 手動でのマイグレーション
    • 人的ミスがおこりやすい

課題の詳細と GitOps の概要については前回の記事に詳しく説明があるので、気になる方はそちらも読んでみてください。

前回の記事はこちら tech.gunosy.io

Argo CD とは

Argo CDKubernetes 環境向けに作られた GitOps パターンを用いた継続的なデプロイメント(continuous delivery)を実現するための CD ツールです。

Jenkins や CircleCI のような CI/CD ツールと異なる点として Argo CD 自体が Kubernetes クラスター上に存在し、Git リポジトリの Kubernetes マニフェストを監視して、変更があればその差分を Kubernetes クラスターに apply することで Kubernetes クラスターの状態を更新してくれます。

Argo CD が Kubernetes クラスター上から Git リポジトリを監視

また、 Argo CD は Kubernetes のリソース監視に関して、非常に高機能な GUI ダッシュボード も提供しており、容易にアプリケーションの pod の状態を確認できたり、手動での Kubernetes クラスターへの apply やマニフェストの編集等も GUI のダッシュボードからできたりもします。

今回は Pull 型*1の CD ツールとして Argo CD に Git リポジトリの監視、差分の反映を任せることにしました。

CD ツールが他にもある中で Argo CD を選択した理由は、情報が多く、ドキュメントも充実していること、高機能な GUI ダッシュボードを提供していること。さらに、我々が管理している広告配信の API には Argo Rollouts といった Argo 系のツールを導入しており、Argo CD も同じ Argo 系のツールということで比較的導入しやすいと思ったため、選択しています。

Argo CD を導入することで CircleCI からデプロイすることがなくなるため、CircleCI からのデプロイが失敗することについては考えなくて良くなりました。

リポジトリ戦略

我々が開発している管理画面は GitOps を導入する前はアプリケーションと Kubernetes マニフェストが同一リポジトリに存在していました。

しかし、それによりロールバック時に Revert PR を作成して対応する際にもアプリケーションの長い CI が走ってしまうという課題があったため、デプロイに関連する CI を短くするべく、新たに Kubernetes マニフェスト用のリポジトリを作成し、Kubernetes マニフェストに関しては全てそちらで管理するようにしました。

具体的には、管理画面のリポジトリを以下のように分割しました。

  • アプリケーションのリポジトリ
    • アプリケーションコードを管理、CircleCI でビルド、Docker イメージを作成
  • Kubernetes マニフェストのリポジトリ
    • Kubernetes マニフェストを管理、Argo CD で Kubernetes クラスターに apply

ここで問題となるのが、Kubernetes マニフェストリポジトリでの Docker Image のタグの更新方法です。方法として Argo CD Image Updater を使用する方法などもありますが、我々のチームでアプリケーションコードと Kubernetes マニフェストの両方を管理していることもあり、Kubernetes マニフェストリポジトリで作成される Pull Request の Body にアプリケーションリポジトリの機能開発の Pull Request のリンクを含めたいという理由があったため、アプリケーションリポジトリの CircleCI 上で Kubernetes マニフェストリポジトリに向けた Pull Request を作成するようにしました。

リポジトリを分割した構成

これにより、アプリケーションリポジトリからデプロイすることがなくなり、デプロイは Kubernetes マニフェストリポジトリで行うことができるため、CI と CD を分離することができ、ロールバック時も Kubernetes マニフェストリポジトリで Revert PR を作成することでアプリケーションの長い CI は実行されないようになります。

一方で Kubernetes マニフェストリポジトリだけを Revert しても、ビルドされた Docker Image にはまだ機能が含まれ続けているので、アプリケーションリポジトリも同様に Revert PR を作成する手間は発生します。

ブランチ戦略

GitOps 導入以前はアプリケーションリポジトリに master ブランチと develop ブランチがあり、master ブランチは本番環境、develop ブランチはステージング環境に CircleCI からデプロイしていたのですが、上のリポジトリ戦略を導入したことでアプリケーションリポジトリからデプロイがされなくなったため、アプリケーションリポジトリではデプロイ先の環境ごとにブランチを分ける必要がなくなりました。

そのため、アプリケーションリポジトリは develop ブランチは削除して master ブランチのみを使用するようにし、代わりに Kubernetes マニフェストリポジトリでデプロイ先の環境ごとにブランチを分けるようにする必要が出てきます。

Argo CD では、環境ごとに監視するターゲットのリポジトリのブランチを設定することができるので、今回は Kubernetes マニフェストリポジトリに main ブランチと staging ブランチを作成し、本番環境では main ブランチに、ステージング環境では staging ブランチにターゲットを設定しました。

そして、アプリケーションリポジトリの master に変更がマージされると、CircleCI でマニフェストリポジトリの staging ブランチへの Pull Request を作成するようにし、staging ブランチにマージすることで Argo CD が差分を検知し、ステージング環境のクラスターに反映、またそれと同時に CircleCI で main ブランチへのリリース PR を作成、リリース PR をマージすることで本番環境のクラスターに反映するようにしています。

ブランチごとに Argo CD の監視ターゲットを設定した構成

課題の解決

今回のリポジトリ戦略とブランチ戦略の変更、そして Argo CD の導入によって、以下の課題を解決することができました。

  • 遅い CI
    • RSpec の実行に 30 分近くかかる
    • ロールバック時は Revert PR を作成することで対応するが、緊急時は CircleCI を待てないので権限のある人が強制的にマージしている
  • CircleCI からのデプロイの失敗
    • pod が多いタイミングでデプロイすると Cluster Autoscaler が走るために CircleCI の実行時間が延び、タイムアウトしたりする

遅い CI の課題に関しては、リポジトリを分割し、デプロイを Kubernetes マニフェストリポジトリで行うことでアプリケーションの遅い CI を待たずに反映することができるようになりました。

また、CircleCI からのデプロイの失敗に関しては、Argo CD を導入することで CircleCI からデプロイすることがなくなったため、タイムアウトの問題も解決しました。

一方で今回の内容では手動でのマイグレーションの課題は解決できていません。

  • 手動でのマイグレーション
    • 人的ミスがおこりやすい

こちらに関しては Argo CD の Hooks を利用して解決をしています。(次回以降にご紹介します)

まとめ

いかがだったでしょうか。この記事では、Argo CD と GitOps 導入時のリポジトリ戦略、そしてブランチ戦略についてご紹介しました。

今回の導入で デプロイに関して管理画面の運用を大きく改善することができました。 また、我々のチームはアプリケーションとマニフェストの両方を管理していますが、別チームでアプリケーションとマニフェストを分けて管理している場合は今回ご紹介したリポジトリ戦略を導入することで各チームが管理すべきファイルがリポジトリではっきりと分かれてくれるため、作業がしやすくなるかと思います。

*1:Kubernetes クラスターから Git リポジトリの変更を検知して変更内容をデプロイする手法で Argo CD や Flux がこれにあたります