Skip to content
Published on

ArgoCD GitOps 完全ガイド: ApplicationSet·Sync Waves·Hookで実現するKubernetes宣言的デプロイ

Authors
  • Name
    Twitter
ArgoCD GitOps 完全ガイド

はじめに

GitOpsはGitをSingle Source of Truthとして使用し、インフラとアプリケーションの望ましい状態を宣言的に管理する運用パラダイムです。ArgoCDはKubernetes環境でGitOpsを実現する最も広く使用されているツールで、CNCF Graduatedプロジェクトとしてプロダクションでの検証が完了しています。

本記事ではArgoCDの核心機能であるApplicationSetを通じたマルチクラスター/環境デプロイ、Sync WavesとHookを通じたデプロイ順序制御、RBACとシークレット管理までプロダクション環境で必要な全設定を実践コードと共に解説します。

ArgoCD アーキテクチャ概要

ArgoCDは以下の主要コンポーネントで構成されています。

コンポーネント役割主な機能
API ServerWeb UI、CLI、CI/CD連携gRPC/REST API提供、RBAC処理
Repo ServerGitリポジトリ管理マニフェスト生成(Helm、Kustomize、Plain YAML)
Application Controllerコア調整ループクラスター状態監視、同期実行
ApplicationSet Controller複数Application生成テンプレートベース自動Application作成
Redisキャッシュマニフェストキャッシング、クラスター状態キャッシング
Dex認証SSO、OIDC、LDAP等の外部認証連携

ArgoCD インストール

# Namespace作成とArgoCDインストール
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# またはHelmでインストール(プロダクション推奨)
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update

helm install argocd argo/argo-cd \
  --namespace argocd \
  --create-namespace \
  --set server.service.type=LoadBalancer \
  --set configs.params."server\.insecure"=true \
  --set controller.replicas=2 \
  --set repoServer.replicas=2 \
  --set redis-ha.enabled=true

# 初期adminパスワード確認
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath='{.data.password}' | base64 -d

Application リソース基本構成

Application スペック詳細

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-application
  namespace: argocd
  # Finalizer: Application削除時にクラスターリソースも一緒に削除
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: production
  source:
    repoURL: https://github.com/myorg/k8s-manifests.git
    targetRevision: main
    path: apps/my-app/overlays/production
    # Kustomizeオプション
    kustomize:
      namePrefix: prod-
      commonLabels:
        env: production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true # Gitから削除されたリソースをクラスターからも削除
      selfHeal: true # 手動変更時に自動復旧
      allowEmpty: false # 空マニフェストのデプロイ防止
    syncOptions:
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
      - PruneLast=true
      - ServerSideApply=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m
  ignoreDifferences:
    - group: apps
      kind: Deployment
      jsonPointers:
        - /spec/replicas # HPA管理対象のため無視

Helm ソース設定

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prometheus-stack
  namespace: argocd
spec:
  project: monitoring
  source:
    repoURL: https://prometheus-community.github.io/helm-charts
    chart: kube-prometheus-stack
    targetRevision: 65.1.0
    helm:
      releaseName: prometheus
      valuesObject:
        grafana:
          enabled: true
          adminPassword: vault:secret/grafana#password
        prometheus:
          prometheusSpec:
            retention: 30d
            storageSpec:
              volumeClaimTemplate:
                spec:
                  storageClassName: gp3
                  resources:
                    requests:
                      storage: 100Gi
  destination:
    server: https://kubernetes.default.svc
    namespace: monitoring

AppProjectによるRBAC実装

プロジェクト定義

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: production
  namespace: argocd
spec:
  description: 'Production environment project'
  # 許可されたソースリポジトリ
  sourceRepos:
    - 'https://github.com/myorg/k8s-manifests.git'
    - 'https://github.com/myorg/helm-charts.git'
  # 許可されたデプロイ先
  destinations:
    - namespace: 'production'
      server: 'https://kubernetes.default.svc'
    - namespace: 'production-*'
      server: 'https://kubernetes.default.svc'
  # 許可されたクラスターリソース
  clusterResourceWhitelist:
    - group: ''
      kind: Namespace
    - group: 'rbac.authorization.k8s.io'
      kind: ClusterRole
    - group: 'rbac.authorization.k8s.io'
      kind: ClusterRoleBinding
  # ブロックされたネームスペースリソース
  namespaceResourceBlacklist:
    - group: ''
      kind: ResourceQuota
    - group: ''
      kind: LimitRange
  # RBACロール定義
  roles:
    - name: deployer
      description: 'Can sync and manage applications'
      policies:
        - p, proj:production:deployer, applications, get, production/*, allow
        - p, proj:production:deployer, applications, sync, production/*, allow
        - p, proj:production:deployer, applications, action/*, production/*, allow
      groups:
        - platform-team
    - name: viewer
      description: 'Read-only access'
      policies:
        - p, proj:production:viewer, applications, get, production/*, allow
      groups:
        - dev-team

ApplicationSet ジェネレーター

Git Directoryジェネレーター

Gitリポジトリのディレクトリ構造に基づいてApplicationを自動生成します。

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: app-of-apps
  namespace: argocd
spec:
  goTemplate: true
  goTemplateOptions: ['missingkey=error']
  generators:
    - git:
        repoURL: https://github.com/myorg/k8s-manifests.git
        revision: main
        directories:
          - path: 'apps/*/overlays/production'
          - path: 'apps/deprecated-*'
            exclude: true
  template:
    metadata:
      name: '{{.path.basename}}'
      namespace: argocd
      labels:
        app.kubernetes.io/managed-by: applicationset
    spec:
      project: production
      source:
        repoURL: https://github.com/myorg/k8s-manifests.git
        targetRevision: main
        path: '{{.path.path}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{.path.basename}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

Clusterジェネレーター

登録されたクラスターに基づいてマルチクラスターデプロイを自動化します。

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: multi-cluster-apps
  namespace: argocd
spec:
  goTemplate: true
  goTemplateOptions: ['missingkey=error']
  generators:
    - clusters:
        selector:
          matchLabels:
            env: production
          matchExpressions:
            - key: region
              operator: In
              values:
                - ap-northeast-2
                - us-west-2
                - eu-west-1
  template:
    metadata:
      name: 'app-{{.name}}'
      namespace: argocd
    spec:
      project: production
      source:
        repoURL: https://github.com/myorg/k8s-manifests.git
        targetRevision: main
        path: 'apps/my-app/overlays/{{.metadata.labels.env}}'
        kustomize:
          commonLabels:
            cluster: '{{.name}}'
            region: '{{.metadata.labels.region}}'
      destination:
        server: '{{.server}}'
        namespace: production

Matrixジェネレーター(複合組み合わせ)

2つのジェネレーターを組み合わせて全組み合わせを生成します。

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: matrix-deployment
  namespace: argocd
spec:
  goTemplate: true
  goTemplateOptions: ['missingkey=error']
  generators:
    - matrix:
        generators:
          # ジェネレーター1: クラスターリスト
          - clusters:
              selector:
                matchLabels:
                  env: production
          # ジェネレーター2: Gitディレクトリからアプリリスト
          - git:
              repoURL: https://github.com/myorg/k8s-manifests.git
              revision: main
              directories:
                - path: 'apps/*'
  template:
    metadata:
      name: '{{.path.basename}}-{{.name}}'
      namespace: argocd
    spec:
      project: production
      source:
        repoURL: https://github.com/myorg/k8s-manifests.git
        targetRevision: main
        path: '{{.path.path}}/overlays/production'
      destination:
        server: '{{.server}}'
        namespace: '{{.path.basename}}'

Listジェネレーター

静的な値リストに基づいてApplicationを生成します。

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: environment-apps
  namespace: argocd
spec:
  goTemplate: true
  goTemplateOptions: ['missingkey=error']
  generators:
    - list:
        elements:
          - env: dev
            cluster: https://dev-k8s.example.com
            revision: develop
            replicas: '1'
          - env: staging
            cluster: https://staging-k8s.example.com
            revision: release/v2.5
            replicas: '2'
          - env: production
            cluster: https://kubernetes.default.svc
            revision: main
            replicas: '3'
  template:
    metadata:
      name: 'my-app-{{.env}}'
      namespace: argocd
    spec:
      project: '{{.env}}'
      source:
        repoURL: https://github.com/myorg/k8s-manifests.git
        targetRevision: '{{.revision}}'
        path: 'apps/my-app/overlays/{{.env}}'
      destination:
        server: '{{.cluster}}'
        namespace: 'my-app-{{.env}}'

Sync Wavesによるデプロイ順序制御

Sync Wave基本概念

Sync Waveはargocd.argoproj.io/sync-waveアノテーションで定義し、整数値を使用して低い値から順次デプロイします。デフォルト値は0です。

# Wave -2: NamespaceとRBAC(前提条件)
apiVersion: v1
kind: Namespace
metadata:
  name: production
  annotations:
    argocd.argoproj.io/sync-wave: '-2'
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-service-account
  namespace: production
  annotations:
    argocd.argoproj.io/sync-wave: '-2'
---
# Wave -1: ConfigMapとSecret(設定)
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: production
  annotations:
    argocd.argoproj.io/sync-wave: '-1'
data:
  APP_ENV: production
  LOG_LEVEL: info
---
# Wave 0: コアアプリケーション(デフォルト)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
  annotations:
    argocd.argoproj.io/sync-wave: '0'
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      serviceAccountName: app-service-account
      containers:
        - name: app
          image: myorg/my-app:v2.5.0
          ports:
            - containerPort: 8080
          envFrom:
            - configMapRef:
                name: app-config
---
apiVersion: v1
kind: Service
metadata:
  name: my-app
  namespace: production
  annotations:
    argocd.argoproj.io/sync-wave: '0'
spec:
  selector:
    app: my-app
  ports:
    - port: 8080
      targetPort: 8080
---
# Wave 1: 依存リソース(Ingress、HPA)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
  namespace: production
  annotations:
    argocd.argoproj.io/sync-wave: '1'
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 3
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
---
# Wave 2: モニタリング
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: my-app-monitor
  namespace: production
  annotations:
    argocd.argoproj.io/sync-wave: '2'
spec:
  selector:
    matchLabels:
      app: my-app
  endpoints:
    - port: http
      interval: 15s

Sync Hookの活用

PreSync Hook: デプロイ前のデータベースマイグレーション

apiVersion: batch/v1
kind: Job
metadata:
  name: db-migration
  namespace: production
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
    argocd.argoproj.io/sync-wave: '-1'
spec:
  backoffLimit: 3
  template:
    spec:
      containers:
        - name: migrate
          image: myorg/db-migrator:v2.5.0
          command: ['./migrate', 'up']
          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: db-credentials
                  key: url
      restartPolicy: Never

PostSync Hook: デプロイ後の検証

apiVersion: batch/v1
kind: Job
metadata:
  name: smoke-test
  namespace: production
  annotations:
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
  backoffLimit: 1
  template:
    spec:
      containers:
        - name: smoke-test
          image: myorg/smoke-tester:latest
          command:
            - /bin/sh
            - -c
            - |
              echo "Running smoke tests..."
              curl -sf http://my-app.production.svc:8080/healthz || exit 1
              curl -sf http://my-app.production.svc:8080/api/v1/status || exit 1
              echo "All smoke tests passed!"
      restartPolicy: Never

SyncFail Hook: 同期失敗時の通知

apiVersion: batch/v1
kind: Job
metadata:
  name: sync-fail-notification
  namespace: production
  annotations:
    argocd.argoproj.io/hook: SyncFail
    argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
  backoffLimit: 1
  template:
    spec:
      containers:
        - name: notify
          image: curlimages/curl:latest
          command:
            - /bin/sh
            - -c
            - |
              curl -X POST "$SLACK_WEBHOOK_URL" \
                -H 'Content-Type: application/json' \
                -d '{"text":"ArgoCD Sync FAILED for my-app in production!"}'
          env:
            - name: SLACK_WEBHOOK_URL
              valueFrom:
                secretKeyRef:
                  name: slack-webhook
                  key: url
      restartPolicy: Never

シークレット管理

Sealed Secrets連携

# Sealed Secretsコントローラーインストール
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets \
  --namespace kube-system

# kubeseal CLIでシークレット暗号化
kubectl create secret generic db-credentials \
  --namespace production \
  --from-literal=url='postgresql://user:pass@db:5432/mydb' \
  --dry-run=client -o yaml | \
  kubeseal --format yaml > sealed-db-credentials.yaml
# Gitにコミット可能なSealedSecret
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: db-credentials
  namespace: production
  annotations:
    argocd.argoproj.io/sync-wave: '-2'
spec:
  encryptedData:
    url: AgA2X5N0Q...encrypted...base64==
  template:
    metadata:
      name: db-credentials
      namespace: production
    type: Opaque

External Secrets Operator連携

# ExternalSecret: AWS Secrets Managerからシークレット同期
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
  namespace: production
  annotations:
    argocd.argoproj.io/sync-wave: '-2'
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secretsmanager
    kind: ClusterSecretStore
  target:
    name: db-credentials
    creationPolicy: Owner
  data:
    - secretKey: url
      remoteRef:
        key: production/database
        property: connection_url
    - secretKey: password
      remoteRef:
        key: production/database
        property: password
---
# ClusterSecretStore定義
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: aws-secretsmanager
spec:
  provider:
    aws:
      service: SecretsManager
      region: ap-northeast-2
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets-sa
            namespace: external-secrets

マルチクラスターデプロイ

クラスター登録

# 対象クラスター登録(kubeconfigコンテキストベース)
argocd cluster add staging-cluster \
  --name staging \
  --label env=staging \
  --label region=ap-northeast-2

argocd cluster add production-cluster \
  --name production \
  --label env=production \
  --label region=ap-northeast-2

# 登録済みクラスター確認
argocd cluster list

クラスター別設定分離

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: platform-services
  namespace: argocd
spec:
  goTemplate: true
  goTemplateOptions: ['missingkey=error']
  generators:
    - matrix:
        generators:
          - clusters:
              selector:
                matchLabels:
                  env: production
          - list:
              elements:
                - app: cert-manager
                  namespace: cert-manager
                  chart: cert-manager
                  repoURL: https://charts.jetstack.io
                  targetRevision: v1.16.0
                - app: external-secrets
                  namespace: external-secrets
                  chart: external-secrets
                  repoURL: https://charts.external-secrets.io
                  targetRevision: 0.12.0
                - app: metrics-server
                  namespace: kube-system
                  chart: metrics-server
                  repoURL: https://kubernetes-sigs.github.io/metrics-server
                  targetRevision: 3.12.0
  template:
    metadata:
      name: '{{.app}}-{{.name}}'
      namespace: argocd
    spec:
      project: platform
      source:
        repoURL: '{{.repoURL}}'
        chart: '{{.chart}}'
        targetRevision: '{{.targetRevision}}'
        helm:
          releaseName: '{{.app}}'
      destination:
        server: '{{.server}}'
        namespace: '{{.namespace}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true

ロールバック戦略

自動ロールバック設定

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: production
  source:
    repoURL: https://github.com/myorg/k8s-manifests.git
    targetRevision: main
    path: apps/my-app/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    retry:
      limit: 3
      backoff:
        duration: 10s
        factor: 2
        maxDuration: 5m

CLIによる手動ロールバック

# デプロイ履歴確認
argocd app history my-app

# 特定リビジョンにロールバック
argocd app rollback my-app 5

# または特定Gitコミットに同期
argocd app sync my-app --revision abc123def

# 同期状態確認
argocd app get my-app
argocd app wait my-app --health

モニタリング構成

ArgoCD Prometheusメトリクス

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-metrics
  namespace: argocd
spec:
  selector:
    matchLabels:
      app.kubernetes.io/part-of: argocd
  endpoints:
    - port: metrics
      interval: 30s
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: argocd-alerts
  namespace: argocd
spec:
  groups:
    - name: argocd
      rules:
        - alert: ArgoCDAppOutOfSync
          expr: |
            argocd_app_info{sync_status="OutOfSync"} == 1
          for: 10m
          labels:
            severity: warning
          annotations:
            summary: 'Application {{ "{{" }} $labels.name {{ "}}" }} is OutOfSync for more than 10 minutes'
        - alert: ArgoCDAppDegraded
          expr: |
            argocd_app_info{health_status="Degraded"} == 1
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: 'Application {{ "{{" }} $labels.name {{ "}}" }} is Degraded'
        - alert: ArgoCDSyncFailed
          expr: |
            increase(argocd_app_sync_total{phase="Failed"}[10m]) > 0
          labels:
            severity: critical
          annotations:
            summary: 'ArgoCD sync failed for {{ "{{" }} $labels.name {{ "}}" }}'

Slack通知設定

# argocd-notifications-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.slack: |
    token: $slack-token
  trigger.on-sync-failed: |
    - when: app.status.operationState.phase in ['Error', 'Failed']
      send: [app-sync-failed]
  trigger.on-health-degraded: |
    - when: app.status.health.status == 'Degraded'
      send: [app-health-degraded]
  trigger.on-sync-succeeded: |
    - when: app.status.operationState.phase in ['Succeeded']
      oncePer: app.status.sync.revision
      send: [app-sync-succeeded]
  template.app-sync-failed: |
    slack:
      attachments: |
        [{
          "color": "#E96D76",
          "title": "Sync Failed: {{.app.metadata.name}}",
          "text": "Application {{.app.metadata.name}} sync failed.\nRevision: {{.app.status.sync.revision}}\nMessage: {{.app.status.operationState.message}}"
        }]
  template.app-health-degraded: |
    slack:
      attachments: |
        [{
          "color": "#f4c030",
          "title": "Health Degraded: {{.app.metadata.name}}",
          "text": "Application {{.app.metadata.name}} health is degraded."
        }]
  template.app-sync-succeeded: |
    slack:
      attachments: |
        [{
          "color": "#18BE52",
          "title": "Sync Succeeded: {{.app.metadata.name}}",
          "text": "Application {{.app.metadata.name}} synced successfully.\nRevision: {{.app.status.sync.revision}}"
        }]

運用時の注意事項

1. ApplicationSetセキュリティ

ApplicationSetのprojectフィールドがテンプレート化されている場合、開発者が過剰な権限を持つプロジェクトにApplicationを作成できる可能性があります。常に管理者が制御するソースからのみプロジェクトフィールドを参照するよう設定してください。

2. 自動同期の注意点

automated.prune: trueはGitから削除されたリソースをクラスターから削除します。誤ってマニフェストを削除するとプロダクションリソースが即座に削除される可能性があるため、重要リソースにはargocd.argoproj.io/sync-options: Prune=falseアノテーションを追加することを推奨します。

3. Webhookセキュリティ

ArgoCDが公開的にアクセス可能な場合、必ずWebhookシークレットを設定してDDoS攻撃を防止してください。

4. Repo Serverリソース

大規模リポジトリやHelmチャートの処理時にRepo Serverのメモリ使用量が急増する可能性があります。適切なリソース制限とレプリカ数を設定してください。

5. 抽象化レイヤー制限

Application of Applicationsパターン使用時、3階層以上の抽象化を避けてください。4-5階層のネストはデバッグを極めて困難にします。

障害事例と復旧手順

事例1: Sync無限ループ

# 症状: ApplicationがSyncing状態を繰り返す
# 原因: ignoreDifferences未設定によるドリフト検知

# 診断
argocd app diff my-app
argocd app get my-app --show-operation

# 復旧: ignoreDifferencesを追加
kubectl patch application my-app -n argocd --type merge -p '{
  "spec": {
    "ignoreDifferences": [
      {
        "group": "apps",
        "kind": "Deployment",
        "jsonPointers": ["/spec/replicas"]
      }
    ]
  }
}'

事例2: Repo Server OOM

# 症状: ApplicationがUnknown状態、マニフェスト生成失敗
# 診断
kubectl logs -n argocd deploy/argocd-repo-server --previous
kubectl top pods -n argocd

# 復旧: リソース制限を増加
kubectl patch deployment argocd-repo-server -n argocd --type json -p '[
  {
    "op": "replace",
    "path": "/spec/template/spec/containers/0/resources/limits/memory",
    "value": "4Gi"
  }
]'

# Repo Server再起動
kubectl rollout restart deployment/argocd-repo-server -n argocd

事例3: シークレット同期失敗(External Secrets)

# 症状: ApplicationはHealthyだがPodがCrashLoopBackOff
# 原因: ExternalSecretがまだ同期されていない

# 診断
kubectl get externalsecret -n production
kubectl describe externalsecret db-credentials -n production

# 復旧: ExternalSecret強制同期
kubectl annotate externalsecret db-credentials \
  -n production \
  force-sync=$(date +%s) --overwrite

# またはSync Waveで順序を保証
# ExternalSecret: sync-wave=-2, Deployment: sync-wave=0

事例4: ApplicationSet意図しない削除

# 症状: ApplicationSet修正後に既存Applicationが削除される
# 原因: ジェネレーター設定エラーでマッチ項目が減少

# 予防: preserveResourcesOnDeletion設定
kubectl patch applicationset my-appset -n argocd --type merge -p '{
  "spec": {
    "syncPolicy": {
      "preserveResourcesOnDeletion": true
    }
  }
}'

# 復旧: Git履歴から以前のApplicationSet設定を復元
git log --oneline -- applicationsets/my-appset.yaml
git checkout HEAD~1 -- applicationsets/my-appset.yaml
git commit -m "Revert ApplicationSet to restore applications"
git push

まとめ

ArgoCDはGitOpsの核心ツールとして、ApplicationSetを通じたマルチクラスター自動化、Sync WavesとHookを通じた精密なデプロイ順序制御、そしてRBACとシークレット管理を通じたセキュリティ強化まで、プロダクション環境で必要な全機能を提供します。

重要なのはGitをSingle Source of Truthとして維持しながら、適切な自動化レベルを設定することです。全環境に自動同期を適用するのではなく、開発/ステージングには自動同期を、プロダクションには手動同期を適用する段階的なアプローチを推奨します。モニタリングとアラートを必ず併せて構成し、同期失敗やヘルスチェック異常を迅速に検知して対応できるようにしてください。

参考資料