--- id: devops-argocd-apps-deep title: ArgoCD Applications β€” App-of-Apps / ApplicationSet category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [devops, argocd, gitops, vibe-coding] tech_stack: { language: "YAML", applicable_to: ["DevOps"] } applied_in: [] aliases: [ArgoCD, Application, ApplicationSet, App-of-Apps, GitOps, declarative deploy] --- # ArgoCD Applications Deep > K8s GitOps 의 ν‘œμ€€. **Application + ApplicationSet + App-of-Apps**. Declarative, drift detect, rollback. ## πŸ“– 핡심 κ°œλ… - Git = source of truth. - ArgoCD κ°€ sync to cluster. - Drift detect + reconcile. - Multi-cluster + multi-tenant. ## πŸ’» μ½”λ“œ νŒ¨ν„΄ ### Application ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: my-app namespace: argocd spec: project: default source: repoURL: https://github.com/me/my-app targetRevision: HEAD path: kubernetes destination: server: https://kubernetes.default.svc namespace: production syncPolicy: automated: prune: true selfHeal: true syncOptions: - CreateNamespace=true ``` β†’ Git path 의 manifest κ°€ cluster. ### Sync wave (order) ```yaml metadata: annotations: argocd.argoproj.io/sync-wave: '-1' # λ¨Όμ € ``` β†’ "Database λ¨Όμ €, app λ‹€μŒ" 식. ### Hook (pre/post sync) ```yaml metadata: annotations: argocd.argoproj.io/hook: PreSync argocd.argoproj.io/hook-delete-policy: HookSucceeded ``` β†’ DB migration κ°€ sync μ „. ### App-of-Apps ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: root spec: source: path: apps/ # λ§€ file κ°€ Application destination: { ... } ``` ```yaml # apps/users.yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: users-service spec: ... # apps/orders.yaml ... ``` β†’ 1 root Application κ°€ λͺ¨λ“  λ‹€λ₯Έ Application 관리. ### ApplicationSet (generator) ```yaml apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: per-cluster spec: generators: - clusters: {} # λ§€ cluster 의 Application template: metadata: name: '{{name}}-app' spec: source: repoURL: ... path: 'manifests/{{name}}' destination: server: '{{server}}' ``` β†’ λ§€ cluster / branch / file κ°€ μžλ™ Application. ### Generator types ``` - List: explicit list. - Cluster: matrix (λͺ¨λ“  cluster). - Git directory: λ§€ dir = Application. - Git file: λ§€ file. - Pull request: λ§€ PR κ°€ preview env. - Matrix: combine. - Merge: combine + override. ``` ### PR preview environment ```yaml generators: - pullRequest: github: owner: me repo: my-app labels: ['preview'] template: metadata: name: 'preview-{{number}}' spec: source: targetRevision: '{{branch}}' path: kubernetes destination: namespace: 'preview-{{number}}' ``` β†’ λ§€ PR 의 own preview namespace. ### Multi-cluster ```yaml generators: - clusters: selector: matchLabels: environment: production template: spec: destination: server: '{{server}}' ``` β†’ λ§€ prod cluster 에 μžλ™ deploy. ### Sync options ```yaml syncPolicy: automated: { prune: true, selfHeal: true } syncOptions: - CreateNamespace=true - ServerSideApply=true - ApplyOutOfSyncOnly=true - RespectIgnoreDifferences=true ``` ### Ignore differences ```yaml ignoreDifferences: - group: apps kind: Deployment jsonPointers: - /spec/replicas # HPA κ°€ manage ``` β†’ Replica drift λ¬΄μ‹œ. ### Health check ```yaml # Custom resource metadata: annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true ``` ```yaml # Or custom health Lua script data: resource.customizations: | redis.io/Redis: health.lua: | if obj.status ~= nil then if obj.status.phase == 'Ready' then return { status = 'Healthy' } end end ``` ### Helm + ArgoCD ```yaml spec: source: repoURL: https://charts.example.com chart: my-chart targetRevision: 1.2.3 helm: values: | replicaCount: 3 image: ... ``` ### Kustomize + ArgoCD ```yaml spec: source: path: overlays/production kustomize: images: - my-app:v1.2.3 ``` ### Notification ```yaml # argocd-notifications-cm data: service.slack: | token: $slack-token template.app-deployed: | message: 'App {{.app.metadata.name}} deployed.' trigger.on-deployed: | when: app.status.operationState.phase == 'Succeeded' send: [app-deployed] subscriptions: | - recipients: [slack:deployments] triggers: [on-deployed] ``` ### RBAC ```yaml data: policy.csv: | p, role:dev, applications, sync, default/*, allow p, role:dev, applications, get, default/*, allow g, dev-team, role:dev ``` β†’ Team 별 access. ### Project (multi-tenant) ```yaml apiVersion: argoproj.io/v1alpha1 kind: AppProject metadata: name: my-team spec: sourceRepos: - https://github.com/me/team-repo destinations: - namespace: 'team-*' server: '*' clusterResourceWhitelist: - group: '*' kind: '*' ``` ### vs Flux ``` ArgoCD: UI μΉœν™”, 큰 ecosystem. Flux: simple, GitOps Toolkit. β†’ ArgoCD κ°€ 더 popular. ``` ### vs Argo Rollouts (닀름) ``` ArgoCD: app deploy. Argo Rollouts: progressive delivery (canary, blue-green). β†’ λ‘˜ λ‹€ 같이 μ‚¬μš©. ``` β†’ [[DevOps_Argo_Rollouts]]. ### Production patterns ``` 1. Git monorepo 의 λ§€ app folder. 2. ApplicationSet κ°€ μžλ™ Application 생성. 3. PR preview κ°€ λ§€ feature. 4. Notification κ°€ Slack. 5. Project 별 RBAC. 6. Argo Rollouts κ°€ progressive deploy. ``` ### Disaster recovery ``` ArgoCD 자체 κ°€ down: - Cluster 의 manifest μœ μ§€ (κΈ°μ‘΄ deploy). - μƒˆ deploy μ•ˆ 됨. - Restore from backup (etcd). β†’ ArgoCD κ°€ second cluster 의 backup. ``` ### Cost ``` ArgoCD: 무료 (open source). Cluster compute: ArgoCD κ°€ μž‘μ€ (μž‘μ€ deployment). β†’ Self-host κ°€ cheap. ``` ### Real-world - **Intuit** (creator). - **Adobe**: 큰 user. - **Red Hat OpenShift**: native integration. - **Tetrate / SAP**: 큰 deployment. ### 함정 ``` - Auto-sync κ°€ λͺ¨λ“  λ³€κ²½ μ¦‰μ‹œ: μœ„ν—˜. - No project / RBAC: λ§€ user κ°€ λͺ¨λ“ . - Manifest drift (manual kubectl): self-heal κ°€ fight. - Big repo (10k+ Application): 느린. - Helm value secret in git: μ•ˆ 됨 (External Secrets). ``` ### Best practice ``` 1. App-of-Apps λ˜λŠ” ApplicationSet (DRY). 2. Self-heal + auto-sync (production). 3. Pre-sync hook 의 migration. 4. Notification (Slack). 5. RBAC + Project. 6. Argo Rollouts κ°€ progressive. 7. Secret management (External Secrets / Sealed Secrets). ``` ## πŸ€” μ˜μ‚¬κ²°μ • κΈ°μ€€ | μž‘μ—… | μΆ”μ²œ | |---|---| | K8s GitOps | ArgoCD | | Simple GitOps | Flux | | Multi-cluster | ApplicationSet | | Preview env | PR generator | | Helm | Helm + ArgoCD | | Kustomize | Kustomize + ArgoCD | | Progressive deploy | Argo Rollouts | ## ❌ μ•ˆν‹°νŒ¨ν„΄ - **Manual kubectl**: drift. - **No project**: shared cluster + λ§€ user. - **Big mono Application**: slow sync. - **Secret in git**: leak. - **No notification**: silent failure. - **No backup**: lost. ## πŸ€– LLM ν™œμš© 힌트 - ArgoCD = K8s GitOps standard. - ApplicationSet κ°€ multi-cluster / multi-app. - App-of-Apps κ°€ hierarchy. - Argo Rollouts 와 ν•¨κ»˜ progressive. ## πŸ”— κ΄€λ ¨ λ¬Έμ„œ - [[DevOps_ArgoCD_GitOps]] - [[DevOps_Argo_Rollouts]] - [[DevOps_K8s_Operators]]