EKS ArgoCD Capability 構築 — ApplicationSet で複数環境に自動デプロイする
目次
はじめに
前回の記事では、CodeCommit プライベートリポジトリから単一の Application をデプロイした。しかし実プロジェクトでは dev/staging/prod のように複数環境へのデプロイが求められる。環境ごとに Application を手動で作成すると、設定の同期漏れや管理コストが増える。
ArgoCD の ApplicationSet は、テンプレートとジェネレーターを組み合わせて複数の Application を自動生成する機能だ。Git Directory Generator を使えば、リポジトリ内のディレクトリ構造から環境ごとの Application を自動生成できる。ディレクトリを追加するだけで新環境の Application が生成される「ディレクトリ構造 = 環境構成」の GitOps パターンだ。
この記事では、前回構築した CodeCommit 直接統合の上に ApplicationSet を追加し、複数環境への自動デプロイを構築する。新環境追加の自動化と、個別環境変更の分離が両立することを実機で確認する。
前提条件:
- EKS クラスターに ArgoCD Capability が構築済み(シリーズ第1回参照)
- ターゲットクラスターが登録済み
- Capability Role に
codecommit:GitPullの設定経験がある(前回の記事参照。今回は新リポジトリ用に別途追加する) - AWS CLI、kubectl、git が設定済み
- 検証リージョン: ap-northeast-1
検証 1: Git Directory Generator で複数環境に自動デプロイする
CodeCommit リポジトリの準備
CodeCommit にリポジトリを作成し、環境ごとのディレクトリにマニフェストを配置する。
CodeCommit リポジトリの作成手順
aws codecommit create-repository \
--repository-name argocd-multi-env \
--repository-description "Multi-environment demo for ArgoCD ApplicationSet"git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/argocd-multi-env
cd argocd-multi-env
git config credential.helper '!aws codecommit credential-helper $@'
git config credential.UseHttpPath trueCapability Role に新リポジトリの権限を追加する。111122223333 は自分の AWS アカウント ID に置き換える。
aws iam put-role-policy \
--role-name ArgoCDCapabilityRole \
--policy-name CodeCommitGitPullMultiEnv \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "codecommit:GitPull",
"Resource": "arn:aws:codecommit:ap-northeast-1:111122223333:argocd-multi-env"
}
]
}'ディレクトリ構造は以下の通り。envs/ 配下に環境ごとのディレクトリを作成し、それぞれにマニフェストを配置する。
envs/
dev/
deployment.yaml # replicas: 1
prod/
deployment.yaml # replicas: 3マニフェストの内容(dev)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
env: dev
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
env: dev
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80prod は replicas: 3 と env: prod に変更したもの。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
env: prod
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
env: prod
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80git add . && git commit -m "Initial commit: dev and prod environments"
git push -u origin mainApplicationSet の作成
ApplicationSet を作成する。Git Directory Generator で envs/* にマッチするディレクトリごとに Application を自動生成する。
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: nginx-multi-env
namespace: argocd
spec:
generators:
- git:
repoURL: https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/argocd-multi-env
revision: main
directories:
- path: envs/*
template:
metadata:
name: 'nginx-{{path.basename}}'
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/argocd-multi-env
targetRevision: main
path: '{{path}}'
destination:
name: local-cluster
namespace: '{{path.basename}}'
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=trueポイントは {{path.basename}} の使い方だ。ApplicationSet は generators でパラメータを生成し、template に適用して Application を作成する。Git Directory Generator の場合、envs/* にマッチする各ディレクトリに対して path と path.basename が生成される。envs/dev の場合、path.basename は dev になる。これを Application 名(nginx-dev)とデプロイ先 namespace(dev)の両方に使っている。ディレクトリ名がそのまま環境名になる設計だ。
kubectl apply -f nginx-multi-env.yaml約1分後、2つの Application が自動生成された。
kubectl get application -n argocd -o wideNAME SYNC STATUS HEALTH STATUS REVISION PROJECT
nginx-dev Synced Healthy dbecbdf2e1d8610355b38bf8328a346d1d88ea53 default
nginx-prod Synced Healthy dbecbdf2e1d8610355b38bf8328a346d1d88ea53 default各環境の Pod 数も正しい。
=== dev ===
NAME READY STATUS RESTARTS AGE
nginx-c89f94576-4llrw 1/1 Running 0 53s
=== prod ===
NAME READY STATUS RESTARTS AGE
nginx-7bd6c6d75b-4qpxb 1/1 Running 0 54s
nginx-7bd6c6d75b-dnqcr 1/1 Running 0 54s
nginx-7bd6c6d75b-lcd8n 1/1 Running 0 54s1つの ApplicationSet から、ディレクトリ構造に基づいて2つの Application が自動生成された。 namespace も CreateNamespace=true により自動作成されている。
新環境の追加
staging 環境を追加する。envs/staging/ ディレクトリを作成してマニフェストを push するだけだ。ApplicationSet の定義は変更しない。
# envs/staging/deployment.yaml を作成(replicas: 2)
git add . && git commit -m "Add staging environment"
git pushstaging マニフェストの内容
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
env: staging
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
env: staging
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80ApplicationSet の Git Generator がリポジトリの変更を検知し、新しいディレクトリに対応する Application を自動生成するのを待つ。
# nginx-staging が生成されるまで30秒ごとに確認
while true; do
apps=$(kubectl get application -n argocd --no-headers 2>/dev/null | wc -l)
staging=$(kubectl get application nginx-staging -n argocd \
-o jsonpath='{.status.sync.status}' 2>/dev/null || echo "not found")
echo "$(date +%H:%M:%S) apps=$apps staging=$staging"
sleep 30
done今回の検証では、push から約8分後に nginx-staging が自動生成された。
NAME SYNC STATUS HEALTH STATUS REVISION PROJECT
nginx-dev Synced Healthy f6d2a1cc107ab6a13c9ac72831a4f8fe7bb5a6c2 default
nginx-prod Synced Healthy f6d2a1cc107ab6a13c9ac72831a4f8fe7bb5a6c2 default
nginx-staging Synced Healthy f6d2a1cc107ab6a13c9ac72831a4f8fe7bb5a6c2 defaultstaging の Pod も正しく 2 つ起動している。
=== staging ===
NAME READY STATUS RESTARTS AGE
nginx-d7dcb7974-4rdtl 1/1 Running 0 24s
nginx-d7dcb7974-6n6kp 1/1 Running 0 24sディレクトリを追加して push するだけで、ApplicationSet の定義を変更せずに新環境の Application が自動生成された。 ただし、Git Generator のポーリング間隔により、反映までに約8分かかった。前回の記事で単一 Application の自動同期が約5分だったことを考えると、ポーリングタイミングによっては同程度以上の待ち時間が発生する。
検証 2: 個別環境のマニフェスト変更が他環境に影響しないか
ApplicationSet では、テンプレートの変更は全環境の Application に反映され、個別のマニフェスト変更はその環境だけに反映されるとされている。後者の「個別環境の分離」を実機で確認する。
dev の replicas を 1 → 2 に変更して push した。
# envs/dev/deployment.yaml の replicas: 1 → 2 に変更
git commit -am "Scale dev to 2 replicas" && git pushポーリングを待つ代わりに、dev の Application に hard refresh を実行して即座に反映させた。
kubectl annotate application nginx-dev -n argocd \
argocd.argoproj.io/refresh=hard --overwrite結果を確認する。
kubectl get application -n argocd -o custom-columns=\
'NAME:.metadata.name,SYNC:.status.sync.status,HEALTH:.status.health.status'NAME SYNC HEALTH
nginx-dev Synced Healthy
nginx-prod Synced Healthy
nginx-staging Synced Healthy各環境の Pod 数を確認する。
for ns in dev staging prod; do
echo "=== $ns ==="
kubectl get pods -n $ns --no-headers | wc -l
done=== dev ===
2
=== staging ===
2
=== prod ===
3dev のみ Pod が 1 → 2 にスケールし、staging(2 Pod)と prod(3 Pod)は変化なし。 個別環境のマニフェスト変更は、その環境の Application だけに反映され、他環境には波及しない。
これは ApplicationSet の重要な特性だ。ディレクトリ構造で環境を分離しているため、envs/dev/ の変更は nginx-dev の Application だけがトラッキングする。envs/prod/ のマニフェストに変更がなければ、nginx-prod は同期済みのまま維持される。
まとめ
- ディレクトリ追加だけで新環境の Application が自動生成される — ApplicationSet の Git Directory Generator は
envs/*にマッチするディレクトリを監視し、新しいディレクトリが追加されると対応する Application を自動生成する。ApplicationSet の定義を変更する必要はない - 個別環境の変更は他環境に波及しない —
envs/dev/のマニフェスト変更はnginx-devだけに反映され、staging や prod には影響しない。ディレクトリ構造による環境分離が ApplicationSet でも正しく機能する - Git Generator のポーリング間隔に注意 — 今回の検証では、新環境追加の反映に約8分かかった。即座に反映したい場合は Application への hard refresh が有効だ
- ApplicationSet 削除時はカスケード削除に注意 — 公式ドキュメントによると、ApplicationSet を削除すると生成された全 Application が削除される。
prune: trueが設定されている場合、デプロイ済みリソースも削除される。リソースを残したい場合は preserveResourcesOnDeletion を設定する
クリーンアップ
# ApplicationSet の削除(生成された全 Application とリソースもカスケード削除される)
kubectl delete applicationset nginx-multi-env -n argocd
# namespace の削除
kubectl delete namespace dev staging prod
# IAM ポリシーの削除
aws iam delete-role-policy \
--role-name ArgoCDCapabilityRole \
--policy-name CodeCommitGitPullMultiEnv
# CodeCommit リポジトリの削除
aws codecommit delete-repository \
--repository-name argocd-multi-env \
--region ap-northeast-1