- バックエンドエンジニア
- アナリスト
- 内部統制(J-SOX)
- Other occupations (8)
- Development
- Business
- Other
はじめに
こんにちは。ML・データ部MLOpsブロックの築山(@2kyym)です。
MLOpsブロックでは2022年の上期からArgo CDの導入に着手しました。本記事ではArgo CDの導入を検討した背景から導入のメリット、また導入における公式マニフェストへの変更点や、運用において必須である認証や権限管理など、具体的な手順についてご紹介します。少しでもArgo CDの導入を検討している方の助けになれば幸いです。
またArgo CDを導入するきっかけとなった、複数運用していたKubernetesクラスタを1つに集約するマルチテナントクラスタへの移行についても触れます。マルチテナントクラスタの設計や具体的な移行作業については述べると長くなってしまうため、詳細については改めて別の記事にてご紹介できればと思います。
Argo CDについては、昨年の計測SREブロックの記事でも触れられていますので是非こちらもご参照ください。
本記事ではArgo CD自体や導入のメリットについては簡単な紹介にとどめ、導入時の細かい作業や、導入後チーム運用に乗せるため必要な作業を中心として説明します。
また、本記事ではSSO(Single Sign-On)ログインと権限管理に弊社で利用しているAzure Active Directory(Azure AD)を使用することを前提とします。しかしArgo CDではAzure AD以外にもOktaなど別の認証基盤も数多くサポートしており、大まかな手順は変わらないはずです。また、出来る限りAzure ADに特化した記述を避けて説明します。
目次
- はじめに
- 目次
- 背景
- 従来の課題
- MLOpsマルチテナントクラスタについて
- Argo CDについて
- Argo CD導入によるデプロイフローの変化
- Argo CDの導入メリット
- 導入手順
- 公式マニフェストにパッチを当てる
- IAP認証とSSOログインについて
- IAP認証の導入
- SSOログインの導入
- きめ細かい権限管理について
- 補足: Secret管理のためのExternal Secrets Operatorの導入
- おわりに
背景
まずArgo CDについて述べる前に、背景としてMLOpsブロックにおけるインフラの運用課題と、それを解決するためのマルチテナントクラスタについて説明します。
なお前提として、MLOpsブロックではパブリッククラウドとしてGoogle Cloudを使用しており、インフラにはGoogle Kubernetes Engine(GKE)を使用しています。
従来の課題
MLOpsブロックでは、ZOZOTOWNやWEARに機械学習系の機能(推薦、検索、etc...)を提供するサービスを幅広く開発・運用しています。これらサービスのAPI群や一部のバッチは先述の通りGKEクラスタ上にデプロイされています。
また、これらのワークロードは従来、全て1つのクラスタにデプロイされていたわけではありません。推薦や検索、類似画像検索などといった大まかなくくりでGoogle Cloudプロジェクト自体が分かれており、そのため各プロジェクトごとのGKEクラスタへ別々にデプロイされていました。
特に類似画像検索とWEAR向けの機能はサービスあたり1つのGoogle Cloudプロジェクト、すなわちGKEクラスタで運用していました。そのため、サービス数が増えるにしたがってMLOpsブロックで管理するクラスタ数がどんどん増えていきました。
管理するGKEクラスタの増加に伴い、開発運用において次の課題が生まれました。
- 定期的に実施する必要があるKubernetesのバージョンアップ業務の工数が増加する
- 新規サービスのインフラを構築する際に、新規のGKEクラスタを構築しなければならない手間が発生する
- TerraformでGKE関連の冗長な記述が増加する、また共通の変更を加える際にはそれら全てに対して変更を加える手間が発生する
1点目については、GKE Autopilotなどのマネージドサービスを活用すればバージョンアップの自動化が可能ですが、MLOpsブロックでは安定性の観点からバージョンアップを手動で実施しています。そのため、クラスタの数が増加するとこちらの工数も単調増加してしまいます。
2点目については、上記の運用ですとサービスごとにGKEクラスタを分けているため、軽量なAPIが1つのみ必要な場合であっても新規のクラスタを構築する必要があります。 3点目については、我々はGoogle Cloud上のリソースを管理するためにTerraformを利用していますが、サービス別にクラスタを構築するとほぼ同じ内容のTerraformリソースが様々なリポジトリに記述されてしまっていました。
MLOpsマルチテナントクラスタについて
ここまで述べた開発運用における課題を解決するために、MLOpsブロックで管理するサービスのKubernetesワークロードを1つのGKEクラスタに集約する方針となりました。
マルチテナントクラスタの設計や移行の具体的な手順の検討については、詳細に説明するとそれだけで別の記事が書けてしまうボリュームとなるため、またの機会にぜひお伝えできればと思います。
ここでは簡単に触れるだけに留めますが、サービスごとにNamespaceとノードプールを分けて全てのサービスを1つのクラスタにデプロイするという点以外は、基本的に移行前と同じ構成で動作するように移行を進めました。
もちろん、開発運用・Staging環境・QA環境・本番環境はGoogle Cloudプロジェクト自体を分けて別のクラスタを用意しています。
このマルチテナントクラスタへの移行によって、先程述べた運用課題についてはある程度解決する見通しが立ちました。一方で、以前より感じていた次の運用課題は未だに残っていました。
- 運用しているサービスの数が非常に多く、監視は適切に行っているものの、それらのデプロイ状況やHealthyかどうかの状況を一覧する術がない
- 特定のサービスに紐づくKubernetesリソース(Deployment, Ingress, Service Account, Secretなど)の状況を確認する術がない
- GitHub Actions(GHA)のJob内でkubectl applyを実行することでデプロイを行っており、デプロイ状況がリポジトリのDesired Stateからズレた際に検知・修復できない
マルチテナントクラスタへの移行に着手するタイミングで、こういった課題を解決するためにMLOpsブロックではArgo CDの導入を検討することにしました。
以下の章では、Argo CDについてごく簡単な紹介をした後に、導入して感じたメリットと具体的な導入手順について述べます。また、Argo CDでのデプロイを運用に乗せるにあたって必須になるであろう認証と権限管理についても出来る限り具体的に説明します。
Argo CDについて
まずはArgo CDについて簡単にご紹介します。Argo CDはKubernetes向けのCD(Continuous Delivery)ツールです。
仕組みとしては、Kubernetesクラスタ上のArgo CDが管理対象のサービス(Argo CDではApplicationという単位で管理)のマニフェストが存在するリポジトリを監視します。そしてリポジトリにおいてマニフェストの変更を検知すると、その状態に合わせて自動で同期するようデプロイが行われます。
また、管理対象のApplicationごとに同期の対象(Desired State)とするリポジトリとブランチを設定できます。そのため、例えばStaging環境のArgo CDではmainブランチを、本番環境のArgo CDではreleaseブランチをターゲットとすることで環境ごとのデプロイが実施できます。
Argo CDの公式ドキュメントでは宣言的(declarative)であることがアピールされています。具体的には、Argo CD自体の設定はもちろん、Argo CDによって管理するアプリケーションの設定まで全てをKubernetesのカスタムリソースとしてマニフェストに記載できます。
以下に、Argo CDによるデプロイフローの簡単な概念図をCloud Native Computing Foundation(CNCF)のブログ記事より引用します。
Argo CD導入によるデプロイフローの変化
コマンドによってデプロイを行っていました。デプロイのタイミングはPull Requestがmain/qa/releaseブランチにマージされた際であり、それ以外のタイミングでは実施されません。
Argo CDの導入後は、クラスタ内部のArgo CD Controllerが同期の対象(Desired State)とするブランチを監視し、差分を検知したタイミングでデプロイが実施されます。例えばPull Requestがマージされた際はDesired Stateに差分が発生するのでデプロイが実施されます。後述する設定によって、何らかの問題や手動変更によってDesired Stateからズレた状態になってしまった際も自動デプロイを行うことが可能です。従来のGHAによるデプロイと比較して、Argo CDの導入によってデプロイフローがどう変化したか、ここで簡単に図を交えて説明します。図の左側は従来のGHAによるデプロイを、右側はArgo CDによるデプロイを示しています。
これまではGHAのJobから、つまりクラスタの外部から kubectl apply コマンドによってデプロイを行っていました。デプロイのタイミングはPull Requestがmain/qa/releaseブランチにマージされた際であり、それ以外のタイミングでは実施されません。
Argo CDの導入後は、クラスタ内部のArgo CD Controllerが同期の対象(Desired State)とするブランチを監視し、差分を検知したタイミングでデプロイが実施されます。例えばPull Requestがマージされた際はDesired Stateに差分が発生するのでデプロイが実施されます。後述する設定によって、何らかの問題や手動変更によってDesired Stateからズレた状態になってしまった際も自動デプロイを行うことが可能です。
Argo CDの導入メリット
導入のきっかけは前章で述べた通り、マルチテナントクラスタへ移行するのに合わせて、運用課題を解決するツールを導入できればタイミングが良いという部分が大きいです。それに加えて、動作検証にあたって感じたメリットを、前章で述べた運用課題の裏返しになりますが以下に列挙します。
- GUIが使いやすく、一覧性も高いため、数多の運用サービスのデプロイ状況やHealthyかどうかが簡単に確認できる
- 特定のサービス、すなわちApplicationに紐づくすべてのKubernetesリソースとその状況が簡単に確認できる
- 通知(Argo CD Notifications)や自動修復(Self Healing)機能によって、デプロイ状況がDesired Stateから乖離してしまった場合のアクションが取れる
- 自動カナリアリリースのためにArgo Rolloutsの導入を検討していたが、同じArgo FamilyであるArgo CDを導入することでスマートに管理できる
まず1点目と2点目についてですが、マルチテナントクラスタへ集約することで、GKEのコンソールやkubectlコマンドによるサービス状況の確認がそもそも以前よりも行いやすくなっていました。Argo CDを導入したことで、それに加えて運用する全てのサービス、すなわちApplicationのデプロイ状況と、それぞれに紐づくDeployment以外のKubernetesリソース状況も簡単に確認できるようになりました。
3点目については、GHAによるデプロイではカバーできなかったDesired Stateから乖離した場合の対応が可能となりました。開発過程での動作確認を頻繁に行わない本番環境においては、自動修復(Self Healing)機能を有効にしています。こうすることで定期的にデプロイ状況とDesired Stateを照合し、差分が生じた場合は自動で再同期を行えます。
最後に4点目について、今回の記事では深く触れませんが、自動カナリアリリース実現のために導入を検討していたArgo Rolloutsのカスタムリソースをスマートに取り扱えるという利点もありました。どちらもArgo Family内のツールであるため互換性が高く、例えば自動カナリアリリースにおける切り戻し(Abort)といったアクションがArgo CDのGUIやCLIを通して簡単に実施が可能です。
このような利点を踏まえて動作検証を進め、マルチテナントクラスタへの移行と同時にArgo CDの導入を実施することになりました。
導入手順
ここからは具体的なArgo CDの導入手順について説明します。
導入にあたって全ての事柄について説明すると記事が長くなってしまうため、公式ドキュメントを一見して分かりやすい部分に関しては説明を省きます。具体的にはApplicationやAppProjectといった基本的なカスタムリソースの概念やそのマニフェストの書き方については、特筆すべき点がないため本記事では述べません。本章では次の内容について述べます。
- マルチテナントクラスタに導入し、運用に乗せるにあたって公式マニフェストにパッチを当てた(カスタマイズした)内容
- セキュアかつ使いやすいArgo CD環境を用意するための認証とSSO(Single Sign-On)の導入について
- MLOpsブロック以外のチームのメンバーにArgo CDを使ってもらう際のきめ細かい権限管理について
次の節ではそれぞれの内容について、背景から導入手順までを実際のコードに則って説明します。
公式マニフェストにパッチを当てる
導入チームのインフラ運用次第ではありますが、公式マニフェストを導入しただけでは動作せず、一部マニフェストにパッチを当てる必要が出てくるケースが多いと考えます。今回の導入にあたっては公式マニフェストに幾つかパッチを当てる必要があったため、出来る限り実際のコードに則って説明を進めます。
我々の運用では、公式のマニフェストに含まれる次の3つのマニフェストにパッチを当てています。なお、IAP認証やSSOログイン、権限管理に関連したパッチについては後述します。
- Deployment, StatefulSet群が定義されている argocd-repo-server-deploy.yaml
- Argo CDのKubernetesワークロードが、マルチテナントクラスタのArgo CD専用のノードプールで起動するようにするためのパッチ
- 各ワークロードごとに適切なResource Limitsを設定するためのパッチ
- ConfigMap群が定義されているargocd-cm.yaml
- デプロイ(同期)の結果をSlackに通知するためのパッチ
- 本番環境のみ、事故防止のためにWeb UIの見た目をカスタマイズするためのパッチ
- デフォルトで有効になっている、管理者向けのIDとパスワードによるArgo CDへのログインを無効化するためのパッチ
- (後述)IAP認証、SSOログイン、権限管理に関連するパッチ
- Service群が定義されているargocd-server-service.yaml
- argocd-server をGoogle CloudのBackend Serviceと紐付けるためのパッチ
ここでは argocd-repo-server-deploy.yaml と argocd-cm.yaml にフォーカスし、実際のパッチの例を示しつつ説明します。
まず、 argocd-repo-server-deploy.yaml に対して適用するパッチを以下に示します。ここではマニフェストの例として argocd-applicationset-controller を挙げています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: argocd-applicationset-controller
spec:
template:
spec:
containers:
- name: argocd-applicationset-controller
resources:
requests:
cpu: 100m
memory: 150Mi
limits:
cpu: 500m
memory: 300Mi
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: cloud.google.com/gke-nodepool
operator: In
values:
- "argocd-xxxx-v1"
tolerations:
- key: "dedicated"
operator: "Equal"
value: "argocd-xxxx-v1"
effect: "NoSchedule"
リソースの割り当てに関しては特筆することはありませんが、ワークロードごとに適切な値を設定しています。
所望のノードへのスケジューリングに関しては、 nodeAffinity と tolerations の両方を設定しています。MLOpsブロックではサービスごとにノードプールを分けて運用しており、Argo CDに関しても専用のノードプールを設けています。また、各ノードプールには不要なワークロードがスケジューリングされないよう、 NoSchedule taintを付与しています。そのため、Argo CD向けのノードで起動させるために nodeAffinity だけでなくノードプール名をvalueに指定した tolerations が必要です。
次に、 argocd-cm.yaml に対して適用するパッチを以下に示します。こちらには argocd-cm , argocd-rbac-cm , argocd-notifications-cm といった複数のConfigMapマニフェストが定義されています。本来同じファイルに記載しますが、ここでは分かりやすさのため分けて記載します。
先述の通りIAP認証、SSOログイン、権限管理に関しては後述するため、ここでは該当する部分の記述を省いています。
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
data:
admin.enabled: "false"
ui.cssurl: "./custom/my-styles.css"
my-styles.css: |
.nav-bar {
background: red;
}
まずは argocd-cm です。admin.enabled をfalseに指定することで、デフォルトで発行される管理者向けのIDとパスワードによるログインが無効化されます。この設定によって、Argo CDのWeb UIにおけるログイン画面でもSSOによるログインしか表示されなくなります。
同じくカスタムCSSを使用するための設定も記述しています。本番環境のArgo CDを操作する際、本番環境だと認識せずに意図しない操作をすることを防ぐため、UI上のサイドバーを警告色にするようカスタマイズしています。
なお my-styles.css に関しては argocd-repo-server-deploy.yaml で別途 /shared/app/custom にVolumeをマウントしています。
次に示す画像は1枚目が開発環境のUIであり、2枚目が本番環境のUIです。
続きはこちら