はじめに
はじめまして、スリーシェイクのSreake事業部インターン生の上田です。
私は、SRE技術の調査と研究を行う目的で2024年8月19日~8月30日に開催された2週間のインターンに参加しました。
私はCI/CDパイプラインに興味があったため、Argo CDついての調査をする方向性でテーマを考え、Argo CD を活用して、Kubernetes クラスタ上でマルチテナントを実現するための構成検討、検証、および各構成のメリット/デメリットを整理をしました。
以降、その成果を記述します。
自己紹介
上田
インターン生の上田です。クラウドネイティブ領域に興味があり、SREやインフラ領域のスキル向上になると思い、本インターンに参加しました。
Kubernetesとマルチテナント
組織規模や体制によってマルチテナントを採用する組織は多いのではないかと思います。
マルチテナントとは
マルチテナントとは、Kubernetes クラスタ内で複数の異なるチームやプロジェクトが Kubernetes リソースを共有しつつ、それぞれを独立して管理することを指します。
マルチテナントの課題
- デプロイの制御
- リソースの権限管理
- セキュリティとアクセス制御
などが挙げられます。
今回の研究テーマでは、上記課題における「デプロイの制御」と「リソースの権限管理」に対し、GitOpsを用いてどのように課題に対処できるかを検討/検証してみました。
GitOpsとは
Gitリポジトリを唯一の情報源とし、インフラやアプリケーションの状態をコードとして管理します。
GitOpsが提供するもの
- アプリケーション開発のための標準的なワークフロー
- Git による可視化とバージョン管理で信頼性を向上
- あらゆるクラスタ、クラウド、オンプレミス環境における一貫性
- PRによる承認フロー
主なCDツールとして、
- GitHub Actions
- Argo CD
- Flux
- Jenkins X
などのツールが代表に挙げられます。その中でも今回はArgo CDにスコープを絞って調査しました。
Argo CD とは
Argo CDとは、
Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.
と公式サイトに書いてある通り GitOpsを実現するためのKubernetes用のCDツールです。
定期的にApplication単位でGitリポジトリを覗きに行き差分があった場合 Git リポジトリと Kubernetes クラスタの同期を行ってくれます。
- 使いやすいUI
GUIでの操作にも対応しており、Kubernetesに詳しくない開発者でも扱いやすく、デプロイの規模が大きくなっても見通しがよくなっています。 - マルチクラスタのサポート
ArgoCDがインストールされているクラスタだけでなく、API経由で複数のクラスタへのデプロイもサポートしています。 - あらゆるマニフェストの形式をサポート
helmやkustomizeなどのマニフェスト管理ツールにも対応しています。 - 認証
dexによりGitHubを筆頭にKeyCloakなどでSSOを実装することもできるため、エンタープライズなシーンでの利用もできます。
Argo CDを用いたマルチテナントのデプロイ管理方法の検証
マルチテナントの前提事項
実際に検証を行ったマルチテナント構成の前提事項を整理します。
今回の調査では、3つのテナント数を想定し、それぞれ tenant-1
tenant-2
tenant-3
としました。 それらのテナントは単一のKubernetesクラスタを利用します。 また、テナント毎にリポジトリが用意されており、クラスタ管理を担う管理者用のリポジトリも別途存在する前提とします。
環境
GKE | 1.29.7-gke.1104000 |
Argo CD | v2.12.3 |
Terraform | v1.9.5-dev |
Argo CDの構成について
今回はテナント毎にArgo CDを占有するパターンと、テナント全体でArgo CDを共有するパターンを検討しました。
占有型 (Argo CD : テナント = 1 : 1)
※インターン期間中に占有型の動作検証まで実施できなかったため、占有型に関する評価は机上の整理結果となります。
構成図
占有型では、各テナント毎にArgoCDをデプロイしており、それぞれの管理は基盤となるArgoCDが管理しています。
共有型 (Argo CD : テナント = 1 : n)
構成図
共有型ではクラスタにおいて単一のArgo CDリソースで複数のテナントを管理するため、管理者は各テナントのユーザからAppProjectまで一元で管理しています。
リポジトリ構成説明
今回検証で使うリポジトリの一覧は下記の通りです。
リポジトリ | 用途 |
---|---|
infra | 管理者用リポジトリ |
tenant-1 | テナント1 |
tenant-2 | テナント2 |
tenant-3 | テナント3 |
管理者用リポジトリ
https://github.com/multi-tenant-example-org/infra
.
├── infra
│ └── studio
│ ├── dev
│ │ └── main.tf
│ └── module
│ ├── gar/
│ ├── gke/
│ ├── network/
│ └── subnet/
└── manifest
└── argocd
└── argocd
├── base
│ ├── app-project-tenant-1.yaml
│ ├── app-project-tenant-2.yaml
│ ├── app-project-tenant-3.yaml
│ ├── argocd-cm.yaml
│ ├── argocd.yaml
│ ├── kustomization.yaml
│ ├── tenant-1.yaml
│ ├── tenant-2.yaml
│ └── tenant-3.yaml
└── overlays
└── dev
├── app-project-tenant-1.yaml
├── app-project-tenant-2.yaml
├── app-project-tenant-3.yaml
├── argocd-rbac-cm.yaml
├── argocd.yaml
├── kustomization.yaml
├── tenant-1.yaml
├── tenant-2.yaml
└── tenant-3.yaml
infraには環境毎のインフラを定義するterraformがあります。
manifestには、マルチテナント間のデプロイ制御、および権限制御を行うためのマニフェストを管理しています。
今回はKustomizeを利用しているため、baseには基礎とoverlaysには環境毎の差分を入れるようにしています。
其々の役割です。
- app-project-tenant-*.yaml
其々のテナントのAppProjectを定義しています。 - argocd-cm.yaml
Argo CD上のローカルユーザやDexの定義をしています ※インターン期間内にDexの検証までは実施できませんでした - argocd-rbac-cm.yaml
各ユーザのRBACを定義しています。 - argocd.yaml
Argo CD の Applicationを定義しています。 - tenant-*.yaml
各テナントが利用するリポジトリにあるApplicationを管理するApplicationを管理しています。
各テナントのリポジトリ
.
└── manifests
├── argocd
│ └── application
│ ├── base
│ │ ├── kustomization.yaml
│ │ └── sample-app.yaml
│ └── overlays
│ └── dev
│ ├── kustomization.yaml
│ └── sample-app.yaml
└── tenant-1
└── sample-app
├── base
│ ├── deployment.yaml
│ ├── kustomization.yaml
│ └── service.yaml
└── overlays
└── dev
├── deployment.yaml
└── kustomization.yaml
manifestsの中には、各アプリケーションをデプロイするためのマニフェストとそれらを管理するArgo CD Applicationマニフェストを用意しています。
こちらもkustomizeを利用しているので管理者用リポジトリ同様にbase/overlaysの構成になっています。
https://github.com/multi-tenant-example-org
に詳細な実装を載せています。
検証
アカウントの作成
今回の検証ではArgo CDのローカルアカウントを使用して検証を行います。
# manifest/argocd/argocd/base/argocd-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
labels:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
data:
accounts.root: login
accounts.guest: login
accounts.kin: login # tenant-1
accounts.gin: login # tenant-2
accounts.dou: login # tenant-3
AppProjectの作成
# manifest/argocd/argocd/base/app-project-tenant-1.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: tenant-1
namespace: argocd
spec:
clusterResourceWhitelist:
- group: '*'
kind: '*'
destinations:
- namespace: 'tenant-1'
server: '*'
- namespace: 'tenant-1-*'
server: '*'
sourceRepos:
- https://github.com/multi-tenant-example-org/tenant-1
roles:
- name: guest
description: "guest role"
policies:
- p, proj:tenant-1:guest, applications, get, tenant-1/*, allow
- name: developer
description: "developer role"
policies:
- p, proj:tenant-1:developer, applications, create, tenant-1/*, allow
- p, proj:tenant-1:developer, applications, get, tenant-1/*, allow
- p, proj:tenant-1:developer, applications, update, tenant-1/*, allow
- p, proj:tenant-1:developer, applications, delete, tenant-1/*, allow
- p, proj:tenant-1:developer, applications, sync, tenant-1/*, allow
- name: operator
description: "operator role"
policies:
- p, proj:tenant-1:operator, applications, create, */*, allow
- p, proj:tenant-1:operator, applications, get, */*, allow
- p, proj:tenant-1:operator, applications, update, */*, allow
- p, proj:tenant-1:operator, applications, delete, */*, allow
- p, proj:tenant-1:operator, applications, sync, */*, allow
AppProjectには .spec.destinationsという項目があり、この項目ではnamesapceやクラスタなどのスコープを限定することができます。
この場合は、すべてのクラスタにおいて、tenant-1 もしくは tenant-1-* にマッチする場所でのみこのAppProjectはアプリケーションをデプロイできます。
また、sourceReposを設定することにより、テナントが管理するリポジトリなど、限定的なリポジトリのみを許可することができます。
これらの設定を使い、開発者が間違ったリポジトリにアクセスしたり、間違ったnamespaceに対してデプロイすることを防いでいます。
RBACの設定
# manifest/argocd/argocd/overlays/dev/argocd-rbac-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
#policy.default: role:readonly
policy.csv: |
g, guest, proj:tenant-1:guest
g, guest, proj:tenant-2:guest
g, guest, proj:tenant-3:guest
g, kin, proj:tenant-1:developer
g, gin, proj:tenant-2:developer
g, dou, proj:tenant-3:developer
g, root, proj:tenant-1:operator
g, root, proj:tenant-2:operator
g, root, proj:tenant-3:operator
また、RBACでは、rootに全テナントに対する全権限を付与し、それぞれのアカウントにはデベロッパー権限、ゲストには閲覧のみの権限を与えています。
動作確認
rootユーザ
ルートユーザでログインした場合では、すべてのテナントと管理者チームが管理しているArgoCD Applicationが閲覧・操作ができます
tenant-1に属するアカウント
tenant-1のアカウントではtenant-1のアプリケーションしか見れません。
ゲストアカウント
ゲストアカウントでは、すべてのテナントのアプリケーションを閲覧できますが、syncなどの操作は受け付けません。
占有型と共有型のメリット、デメリット、および想定するユースケース
非機能要求グレード | 共有型 | 占有型 |
---|---|---|
可用性 | △ Argo CDで障害が起こるとテナント全体に影響が出る | 〇 あるテナントのArgo CDで障害が起きても、他のテナントには影響しない |
性能 拡張性 | 〇 テナントが増えてもAppProject、ユーザ、およびRBACを追加するだけで対応できる | △ テナントが増えるとArgo CDを追加する必要がある。(Argo CD自体がArgo CDによって管理されている場合は負担が多少軽減される) |
運用 保守性 | △ バージョンアップ運用は1つのArgo CDのみで済む。ただし、ユーザのRBACを管理するcsvファイルは肥大化していく | △ 複数のArgo CDに対してバージョンアップする必要がある。1テナントでユーザ管理が完結する |
共有型では、AppProject単位でテナントを分割する為、容易にテナントを増やすことが可能です。
また、ユーザーも一元管理ができることから、自社基盤などのユースケースで利用するのが適していると考えます。
特にSRE(プラットフォーム)チームが独立しており、開発者がほとんどインフラに関する設定を行わない体制であるならばより一層適していると思います。
まとめ
今回、Argo CDを用いたマルチテナント構成を検討・検証してみて、普段の個人開発時には気にしなかった考慮事項を検討できたのはよかったです。
今回のインターンでは単一のKubernetesクラスタかつArgo CDをスコープとしたマルチテナント構成でしたが、クラスタ構成からの検討や、Argo CD以外のリソースをどうコントロールすべきかなど、追加で調査・検討してみたいと思いました。