- Authors
- Name
- はじめに
- ArgoCDアーキテクチャとコアコンポーネント
- マルチクラスター登録とシークレット管理
- ApplicationSet Controllerとジェネレーターパターン
- App of Appsパターン設計
- Sync WaveとHookによるデプロイ順序制御
- ArgoCD vs Flux vs Jenkins GitOps 比較
- 障害シナリオと復旧
- 運用自動化のベストプラクティス
- おわりに
- 参考資料

はじめに
マルチクラスターKubernetes環境を運用する組織が増えるにつれて、一貫したデプロイパイプラインの重要性が高まっています。各クラスターに手動でkubectl applyを実行していた時代は終わりました。GitOpsはGitリポジトリをSingle Source of Truth(唯一の信頼できる情報源)として、宣言的にインフラとアプリケーションの状態を管理する運用パラダイムです。
ArgoCDはCNCF Graduatedプロジェクトであり、KubernetesネイティブGitOpsツールの事実上の標準です。本記事では、ArgoCDを活用したマルチクラスターデプロイのアーキテクチャ設計からApplicationSet、App of Appsパターン、Sync Wave、セキュリティ、障害復旧まで、実運用に必要なすべてを解説します。
ArgoCDアーキテクチャとコアコンポーネント
アーキテクチャ概要
ArgoCDは以下のコアコンポーネントで構成されます:
┌─────────────────────────────────────────────────┐
│ ArgoCD Server │
│ ┌──────────┐ ┌───────────┐ ┌──────────────┐ │
│ │ API Server│ │ Repo Server│ │ App Controller│ │
│ └──────────┘ └───────────┘ └──────────────┘ │
│ ┌──────────────────┐ ┌─────────────────────┐ │
│ │ ApplicationSet │ │ Notification │ │
│ │ Controller │ │ Controller │ │
│ └──────────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────┘
│ │
┌────┴────┐ ┌───┴────┐
│ Git Repo │ │ K8s │
│ (Source) │ │Clusters│
└─────────┘ └────────┘
- API Server:UIとCLIのリクエスト処理、認証・認可
- Repo Server:Gitリポジトリからマニフェストを取得してレンダリング(Helm、Kustomize、Jsonnetなど)
- Application Controller:実際のクラスター状態とGitの状態を比較して同期
- ApplicationSet Controller:テンプレートベースで複数のApplicationを自動生成
- Notification Controller:Sync状態の変化をSlack、Teams、Webhookなどに通知
マルチクラスターにおけるArgoCDデプロイモデル
マルチクラスター環境では、ArgoCD自体をどこにどのようにデプロイするかが最初の設計判断です。
| モデル | 構造 | メリット | デメリット |
|---|---|---|---|
| Hub-Spoke | 管理クラスターにArgoCD 1つ、ワーカークラスターにデプロイ | 集中管理、一貫したポリシー | SPOF、ネットワーク依存 |
| Standalone | 各クラスターにArgoCDをインストール | 独立性、ネットワーク分離 | 管理オーバーヘッド、設定の不一致 |
| Hybrid | Hubで共通インフラ、各クラスターでアプリデプロイ | バランスの取れたアプローチ | アーキテクチャの複雑さ |
ほとんどの組織ではHub-Spokeモデルを採用しています。このモデルでは、管理(Management)クラスターにArgoCDをインストールし、リモートクラスターを登録してデプロイします。
マルチクラスター登録とシークレット管理
クラスター登録
ArgoCD CLIを使用してリモートクラスターを登録します:
# kubeconfigコンテキストの確認
kubectl config get-contexts
# クラスター追加(ArgoCDがServiceAccountを自動作成)
argocd cluster add staging-cluster \
--name staging \
--label env=staging \
--label region=ap-northeast-2
argocd cluster add production-apne2 \
--name production-apne2 \
--label env=production \
--label region=ap-northeast-2
argocd cluster add production-use1 \
--name production-use1 \
--label env=production \
--label region=us-east-1
内部的に、ArgoCDは各クラスター情報をSecretリソースとして保存します。宣言的に管理するには、次のようにSecretを直接作成します:
apiVersion: v1
kind: Secret
metadata:
name: production-apne2-cluster
namespace: argocd
labels:
argocd.argoproj.io/secret-type: cluster
env: production
region: ap-northeast-2
type: Opaque
stringData:
name: production-apne2
server: 'https://kubernetes.production-apne2.internal:6443'
config: |
{
"bearerToken": "<service-account-token>",
"tlsClientConfig": {
"insecure": false,
"caData": "<base64-encoded-ca-cert>"
}
}
シークレット管理戦略
マルチクラスター環境でシークレットをGitに平文で保存すると、セキュリティインシデントが発生します。以下のツールをArgoCDと組み合わせます:
- Sealed Secrets:公開鍵で暗号化してGitに保存、クラスターで復号化
- External Secrets Operator (ESO):AWS Secrets Manager、HashiCorp Vaultなどからシークレットを同期
- SOPS + age/KMS:ファイル単位の暗号化
ESOをArgoCDと組み合わせるパターンが最も広く使用されています:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: database-credentials
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: database-credentials
creationPolicy: Owner
data:
- secretKey: DB_HOST
remoteRef:
key: production/database
property: host
- secretKey: DB_PASSWORD
remoteRef:
key: production/database
property: password
ApplicationSet Controllerとジェネレーターパターン
ApplicationSetはマルチクラスターデプロイの中核ツールです。1つのApplicationSetで数十のクラスターに同一のアプリケーションを自動デプロイできます。
Cluster Generator
ArgoCDに登録されたクラスター情報に基づいてApplicationを生成します:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: prometheus-stack
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ['missingkey=error']
generators:
- clusters:
selector:
matchLabels:
env: production
values:
helmReleaseName: kube-prometheus
template:
metadata:
name: 'prometheus-{{.name}}'
spec:
project: infrastructure
source:
repoURL: 'https://github.com/org/k8s-infrastructure.git'
targetRevision: main
path: 'clusters/{{.metadata.labels.region}}/prometheus'
helm:
releaseName: '{{.values.helmReleaseName}}'
valueFiles:
- 'values.yaml'
- 'values-{{.metadata.labels.env}}.yaml'
destination:
server: '{{.server}}'
namespace: monitoring
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
この設定は、env=productionラベルを持つすべてのクラスターにPrometheusスタックをデプロイします。新しいクラスターを追加して同じラベルを付けると、自動的にApplicationが作成されます。
Matrix Generator - クラスター x サービスの組み合わせ
複数のクラスターに複数のサービスをデプロイする場合、Matrix Generatorが有用です:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: microservices
namespace: argocd
spec:
goTemplate: true
generators:
- matrix:
generators:
- clusters:
selector:
matchLabels:
env: production
- list:
elements:
- service: order-service
replicas: '3'
memory: '512Mi'
- service: payment-service
replicas: '2'
memory: '1Gi'
- service: notification-service
replicas: '2'
memory: '256Mi'
template:
metadata:
name: '{{.service}}-{{.name}}'
annotations:
notifications.argoproj.io/subscribe.on-sync-failed.slack: deploy-alerts
spec:
project: applications
source:
repoURL: 'https://github.com/org/k8s-apps.git'
targetRevision: main
path: 'apps/{{.service}}'
helm:
parameters:
- name: replicaCount
value: '{{.replicas}}'
- name: resources.requests.memory
value: '{{.memory}}'
destination:
server: '{{.server}}'
namespace: '{{.service}}'
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Matrix Generatorは、クラスター3つ x サービス3つ = 9つのApplicationを自動生成します。これがApplicationSetの最も強力な点です。
App of Appsパターン設計
App of Appsパターンは、ArgoCD Applicationを管理するApplicationを作成する階層的アプローチです。GitリポジトリにApplicationマニフェストを保存し、ルートApplicationがそれらを参照します。
ディレクトリ構造
k8s-gitops/
├── root-apps/
│ ├── infrastructure.yaml # インフラApp of Apps
│ ├── platform.yaml # プラットフォームApp of Apps
│ └── applications.yaml # ビジネスアプリApp of Apps
├── infrastructure/
│ ├── cert-manager.yaml
│ ├── external-secrets.yaml
│ ├── ingress-nginx.yaml
│ └── prometheus-stack.yaml
├── platform/
│ ├── istio.yaml
│ ├── kafka.yaml
│ └── redis.yaml
└── applications/
├── order-service.yaml
├── payment-service.yaml
└── notification-service.yaml
ルートApplication設定
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-infrastructure
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: '-2'
spec:
project: default
source:
repoURL: 'https://github.com/org/k8s-gitops.git'
targetRevision: main
path: infrastructure
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-platform
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: '-1'
spec:
project: default
source:
repoURL: 'https://github.com/org/k8s-gitops.git'
targetRevision: main
path: platform
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-applications
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: '0'
spec:
project: default
source:
repoURL: 'https://github.com/org/k8s-gitops.git'
targetRevision: main
path: applications
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
Sync WaveとHookによるデプロイ順序制御
Sync Waveの基本概念
Sync Waveはargocd.argoproj.io/sync-waveアノテーションでリソースのデプロイ順序を定義します。小さい数値から順にデプロイされ、同じWave内では並列処理されます。
# Wave -1: NamespaceとRBACを先に作成
apiVersion: v1
kind: Namespace
metadata:
name: payment-service
annotations:
argocd.argoproj.io/sync-wave: '-1'
---
# Wave 0: ConfigMapとSecret
apiVersion: v1
kind: ConfigMap
metadata:
name: payment-config
namespace: payment-service
annotations:
argocd.argoproj.io/sync-wave: '0'
data:
DATABASE_URL: 'postgresql://db.internal:5432/payments'
KAFKA_BROKERS: 'kafka-0.kafka:9092'
---
# Wave 1: メインDeployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
namespace: payment-service
annotations:
argocd.argoproj.io/sync-wave: '1'
spec:
replicas: 3
selector:
matchLabels:
app: payment-service
template:
metadata:
labels:
app: payment-service
spec:
containers:
- name: payment
image: registry.internal/payment-service:v2.3.1
envFrom:
- configMapRef:
name: payment-config
---
# Wave 2: Serviceの公開
apiVersion: v1
kind: Service
metadata:
name: payment-service
namespace: payment-service
annotations:
argocd.argoproj.io/sync-wave: '2'
spec:
selector:
app: payment-service
ports:
- port: 8080
targetPort: 8080
Sync Hookの活用
Hookは、Syncライフサイクルの特定のタイミングで実行されるリソース(主にJob)です:
# PreSync Hook: デプロイ前のデータベースマイグレーション
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
namespace: payment-service
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
argocd.argoproj.io/sync-wave: '-1'
spec:
template:
spec:
containers:
- name: migrate
image: registry.internal/payment-service:v2.3.1
command: ['python', 'manage.py', 'migrate']
envFrom:
- secretRef:
name: database-credentials
restartPolicy: Never
backoffLimit: 3
---
# PostSync Hook: デプロイ後のスモークテスト
apiVersion: batch/v1
kind: Job
metadata:
name: smoke-test
namespace: payment-service
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: smoke-test
image: registry.internal/smoke-tester:latest
command: ['./run-tests.sh']
env:
- name: TARGET_URL
value: 'http://payment-service.payment-service:8080'
- name: TEST_SUITE
value: 'smoke'
restartPolicy: Never
backoffLimit: 1
Hookの種類と実行タイミング:
| Hook | 実行タイミング | 使用例 |
|---|---|---|
| PreSync | マニフェスト同期前 | DBマイグレーション、バックアップ |
| Sync | マニフェスト同期と同時 | 特殊な順序でのデプロイ |
| PostSync | すべてのリソースがHealthy後 | スモークテスト、通知 |
| SyncFail | Sync失敗時 | ロールバック、アラート通知 |
| Skip | 同期から除外 | 手動管理リソース |
ArgoCD vs Flux vs Jenkins GitOps 比較
| 項目 | ArgoCD | Flux v2 | Jenkins + GitOps |
|---|---|---|---|
| CNCFステータス | Graduated | Graduated | 該当なし |
| UIダッシュボード | 内蔵(豊富) | Weave GitOps(別途) | Jenkins内蔵 |
| マルチクラスター | Hub-Spokeネイティブ | クラスター毎インストール推奨 | 別途構成が必要 |
| ApplicationSet | ネイティブ対応 | Kustomizationで類似 | 未対応 |
| Helmサポート | ネイティブ | HelmRelease CRD | プラグイン |
| イメージ自動更新 | Image Updater(別途) | ネイティブ対応 | パイプライントリガー |
| RBAC | プロジェクトベースの細分化 | Kubernetes RBAC | Jenkins独自のRBAC |
| Sync Wave/Hook | ネイティブ対応 | Health Checkベース | パイプラインステージ |
| 通知 | Notification Controller | Alert Provider | プラグイン |
| 学習コスト | 中程度 | 中~高 | 高(Groovyが必要) |
| コミュニティ規模 | 非常に活発(17k+ Stars) | 活発(6k+ Stars) | 非常に活発 |
ArgoCDはUIの直感性、ApplicationSetの強力なテンプレート機能、そしてHub-Spokeマルチクラスター対応で優位性を示しています。Fluxはイメージの自動更新とKubernetesネイティブな設計思想が強みです。
障害シナリオと復旧
シナリオ1:Syncがスタック状態になる
症状:ApplicationがSyncing状態で止まり、進行しない
# Applicationの状態確認
argocd app get payment-service --show-operation
# Sync操作の強制終了
argocd app terminate-op payment-service
# Syncのリトライ
argocd app sync payment-service --retry-limit 3 --retry-backoff-duration 10s
原因:PreSync Hook Jobの失敗、またはリソースがHealthy状態に到達できない場合
シナリオ2:Gitリポジトリにアクセスできない
症状:すべてのApplicationがUnknown状態で表示される
# Repo Serverのログ確認
kubectl logs -n argocd deployment/argocd-repo-server --tail=100
# Git接続テスト
argocd repo list
# リポジトリの再登録
argocd repo add https://github.com/org/k8s-gitops.git \
--username deploy-bot \
--password "$GITHUB_TOKEN"
復旧:ArgoCDは最後に成功したマニフェストをキャッシュしているため、Gitが一時的にアクセスできなくても既存のデプロイ状態は維持されます。ただし、新しいデプロイは実行できません。
シナリオ3:リモートクラスターとの接続切断
# クラスターの状態確認
argocd cluster list
# 特定クラスターのすべてのアプリ状態
argocd app list --dest-server https://kubernetes.production-apne2.internal:6443
# クラスター認証情報の更新
argocd cluster set production-apne2 \
--server https://kubernetes.production-apne2.internal:6443 \
--bearer-token "new-token-here"
シナリオ4:誤ったデプロイのロールバック
# Applicationの履歴確認
argocd app history payment-service
# 特定リビジョンへのロールバック
argocd app rollback payment-service 42
# またはGit revert後に自動Sync
git revert HEAD
git push origin main
GitOpsで推奨されるロールバック方法は、argocd app rollbackよりもGit revertです。Gitが真実の情報源であるため、ロールバックの記録はGit履歴に残すべきです。
運用自動化のベストプラクティス
通知設定
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
trigger.on-sync-failed: |
- description: Application sync has failed
send:
- slack-deploy-alert
when: app.status.operationState.phase in ['Error', 'Failed']
trigger.on-health-degraded: |
- description: Application health has degraded
send:
- slack-deploy-alert
when: app.status.health.status == 'Degraded'
template.slack-deploy-alert: |
message: |
Application *{{.app.metadata.name}}* sync {{.app.status.operationState.phase}}.
Revision: {{.app.status.sync.revision}}
Cluster: {{.app.spec.destination.server}}
slack:
attachments: |
[{
"color": "#E96D76",
"title": "{{.app.metadata.name}}",
"title_link": "https://argocd.internal/applications/{{.app.metadata.name}}",
"fields": [
{"title": "Sync Status", "value": "{{.app.status.sync.status}}", "short": true},
{"title": "Health", "value": "{{.app.status.health.status}}", "short": true}
]
}]
service.slack: |
token: $slack-token
username: ArgoCD
icon: ":argocd:"
RBACによるプロジェクト分離
# argocd-rbac-cm ConfigMapのpolicy.csv
p, role:platform-team, applications, *, infrastructure/*, allow
p, role:platform-team, clusters, get, *, allow
p, role:dev-team-order, applications, get, applications/order-*, allow
p, role:dev-team-order, applications, sync, applications/order-*, allow
p, role:dev-team-order, applications, action/*, applications/order-*, allow
p, role:dev-team-payment, applications, get, applications/payment-*, allow
p, role:dev-team-payment, applications, sync, applications/payment-*, allow
g, platform-admins, role:platform-team
g, order-team, role:dev-team-order
g, payment-team, role:dev-team-payment
おわりに
ArgoCDを活用したマルチクラスターGitOpsは、単にツールをインストールすることではなく、組織のデプロイ文化を変えることです。ApplicationSetでクラスターを動的に管理し、App of Appsパターンで階層的な構造を作り、Sync WaveとHookでデプロイ順序を制御します。そして、すべての変更はGit PRを通じてレビューされ、自動的に同期されます。
最も重要な原則はGitが真実の情報源であるということです。緊急時にkubectl editで直接修正したくなる誘惑がありますが、ArgoCDのselfHeal機能がそれを元の状態に戻します。Gitを通じた変更のみが永続的であり、追跡可能であり、ロールバック可能です。
参考資料
- ArgoCD公式ドキュメント - Declarative Setup
- ArgoCD ApplicationSet - Generators
- ArgoCD Sync Waves and Hooks
- Codefresh - ArgoCD ApplicationSet Multi-Cluster Deployment
- Red Hat - How to Automate Multi-Cluster Deployments Using Argo CD
- ArgoCD Notifications Documentation
- DigitalOcean - Manage Multi-Cluster Deployments with ArgoCD