콘텐츠로 이동

GitOps Basics

분류: Layer 5 - 플랫폼 엔지니어링 & 자동화 | 선수지식: CI/CD Basics, Kubernetes Basics

GitOps는 Git 저장소를 인프라와 애플리케이션의 단일 진실 공급원(Single Source of Truth)으로 사용해서, Git에 커밋하면 자동으로 클러스터에 배포되는 운영 방법론이다.

2026년 GitOps는 Kubernetes 클러스터 관리의 사실상 표준(de facto standard)이 되었다. 기존 CI/CD가 “빌드 → 푸시 → 배포 스크립트 실행”이라면, GitOps는 “Git에 원하는 상태를 선언하면 컨트롤러가 자동으로 클러스터를 맞춰준다”는 패러다임이다. 감사 추적(audit trail)이 자동으로 Git 히스토리에 남고, 롤백은 git revert 한 줄이다. 플랫폼 엔지니어링에서 “개발자가 PR만 올리면 배포되는” 셀프서비스 배포 파이프라인의 핵심 방법론이다.

2.5 GitOps 도입 적합/부적합 판단 기준

섹션 제목: “2.5 GitOps 도입 적합/부적합 판단 기준”

GitOps가 항상 정답은 아니다. 도입 전 아래 기준으로 적합성을 먼저 판단해야 한다.

기준권장주의부적합
Kubernetes 사용 여부이미 사용 중도입 검토 중사용 안 함 (VM/온프레미스 중심)
팀 규모5명 이상, DevOps/플랫폼팀 존재3~5명, Git 워크플로우 익숙1~2명, PR 리뷰 오버헤드 감당 불가
운영 성숙도IaC + CI/CD 운영 경험 있음CI/CD만 있고 IaC 미적용수동 배포가 표준, 선언적 사고 없음
배포 빈도일 1회 이상, 반복적 배포주 1~2회분기 1회 수준, 배포 자동화 ROI 낮음
변경 감사 요구규정상 감사 추적 필수 (금융/의료)권장 수준자유로운 핫픽스가 우선인 초기 스타트업
실시간 설정 변경배포 단위 변경 허용대부분 Git 경유 가능런타임 동적 설정(feature flag 실시간 토글)이 핵심인 시스템

실무 판단 기준: “Kubernetes 미사용 + 팀 2명 이하 + 분기 배포” 조합이면 GitOps 오버엔지니어링 위험. “K8s 운영 중 + DevOps팀 존재 + 멀티 환경 관리” 조합이면 GitOps 도입이 즉각 ROI를 낸다.

출처: GitOps Anti-Patterns — Oneuptime, GitOps Architecture Patterns — Platform Engineering

GitOps 4원칙

  1. 선언적(Declarative): 인프라/앱 상태를 YAML 등 선언적 코드로 정의
  2. 버전 관리(Versioned): Git에 저장 → 변경 이력 자동 추적
  3. 자동 적용(Automatically Applied): Git에 머지되면 에이전트가 자동으로 배포
  4. 자가 치유(Self-Healing): 실제 상태가 Git과 달라지면 자동으로 복원

Push vs Pull 모델 — 왜 Pull이 더 안전한가

기존 CI/CD(Push 모델)는 Jenkins나 GitHub Actions 같은 CI 서버가 kubectl apply를 직접 실행한다. 이 말은 CI 서버가 Kubernetes 클러스터에 접근할 수 있는 kubeconfig나 토큰을 가지고 있어야 한다는 뜻이다. CI 서버가 해킹당하면 클러스터 전체가 위험해진다.

GitOps Pull 모델은 반대다. 클러스터 에 에이전트(ArgoCD, Flux)가 떠 있고, 이 에이전트가 Git을 주기적으로 감시해서 변경이 생기면 스스로 적용한다. 외부에서 클러스터로 들어오는 접근이 없다 — 클러스터가 Git에서 읽기만 한다.

[Push 모델 — 기존 CI/CD]
개발자 → Git push → CI 서버가 kubectl apply 실행 → 클러스터
→ CI 서버에 클러스터 접근 권한이 필요 (보안 위험)
[Pull 모델 — GitOps]
개발자 → Git push → (대기)
클러스터 안의 Agent가 Git을 주기적으로 확인 → 차이 발견 → 자동 적용
→ 클러스터가 Git을 읽기만 함 (더 안전)

📖 더 보기: AWS Prescriptive Guidance - Argo CD and Flux use cases — Push vs Pull 보안 모델 차이와 AWS EKS 환경에서 각 도구를 언제 쓰는지 설명

ArgoCD 내부 아키텍처 — 왜 이렇게 동작하는가

ArgoCD는 단순한 도구가 아니라 여러 컴포넌트로 구성된 시스템이다:

ArgoCD 컴포넌트
├── API Server ← Web UI, CLI, 외부 시스템의 요청을 받음
├── Repo Server ← Git 저장소를 클론하고 YAML을 생성 (Helm 렌더링 등)
├── Application Controller ← 핵심! Git 상태 vs 실제 클러스터 상태를 비교하고 동기화
└── Redis ← 캐시 (반복 Git 클론 방지)

Reconciliation Loop (조정 루프) 상세 동작 원리

비유로 생각하면, ArgoCD의 Application Controller는 “항상 설계도(Git)와 실제 건물(클러스터)을 비교하는 감리사”다. 설계도가 바뀌거나 건물이 임의로 수정되면 즉시 감지해서 복원 명령을 내린다.

Application Controller는 기본적으로 3분마다(정확히는 120초 + 최대 60초의 랜덤 지터) Git과 클러스터를 비교한다. 지터(jitter)를 추가하는 이유는 Application이 많을 때 모든 앱이 동시에 Git을 조회해서 부하가 몰리는 것을 방지하기 위해서다.

Reconciliation 루프의 정확한 흐름:

  1. Observe: Repo Server가 Git에서 최신 매니페스트를 가져옴 (Helm이면 helm template 실행, Kustomize면 빌드)
  2. Diff: Application Controller가 Kubernetes API에서 현재 상태를 가져와서 비교
  3. Act: 차이가 있으면 “OutOfSync” 표시 → Auto-Sync 설정 시 kubectl apply 자동 실행

내부적으로 Application Controller는 두 개의 큐(queue)를 사용한다:

  • Status Processors (기본 20개): 애플리케이션 상태 확인 담당
  • Operation Processors (기본 10개): 실제 Sync 작업 담당

또한 Kubernetes Watch API를 활용해서 클러스터 상태 변화를 실시간으로 감지하는 경량 캐시를 유지한다. 이 덕분에 매번 Kubernetes API를 직접 조회하지 않아도 된다.

# ArgoCD 동작 흐름 요약
Git repo (원하는 상태)
↓ Repo Server가 클론 + 렌더링 (Helm template / Kustomize build)
Application Controller 비교 (Watch API 캐시 활용)
↓ 차이 발견 (OutOfSync)
Kubernetes API로 Apply
클러스터 상태 = Git 상태 (Synced)
↓ 3분 후 다시 Reconciliation Loop 시작

📖 더 보기: ArgoCD Reconciliation 최적화 공식 문서 — Reconciliation 간격 조정, 성능 튜닝 파라미터 상세 설명

Reconciliation Loop 크로스 도메인 매핑 — 같은 패턴, 다른 도메인

Observe → Diff → Act 패턴은 GitOps에만 존재하지 않는다. 이 사고 모델을 다른 도메인에서 인식하면, 낯선 시스템을 만나도 “이것도 결국 Reconciliation이구나”로 빠르게 이해할 수 있다.

도메인Observe (현재 상태 관찰)Diff (차이 계산)Act (상태 수렴)수렴 실패 시
ArgoCDKubernetes API에서 리소스 조회Git 매니페스트 vs 클러스터 상태 비교kubectl apply로 동기화OutOfSync 경고 → 사람 개입
Terraformterraform state 원격 백엔드 조회.tf 선언 vs 실제 클라우드 리소스 비교terraform apply로 프로비저닝plan 결과 확인 후 수동 승인
Kubernetes Controlleretcd Watch API로 리소스 변화 감지spec(원하는 상태) vs status(실제 상태) 비교CRUD API로 하위 리소스 생성/수정/삭제error backoff + retry
DB Replication 감지replica lag 지표(초) 실시간 수집primary LSN vs replica LSN 차이 계산replica 따라잡기 대기 또는 재동기화lag 임계치 초과 → 읽기 라우팅 제외

전이 가치: Reconciliation Loop를 이해하면 Terraform, Kubernetes Operator, CDC(Change Data Capture) 시스템을 처음 볼 때도 “Observe → Diff → Act” 축으로 빠르게 분해할 수 있다. 모두 같은 제어 이론(Control Theory)의 파생이다.

출처: The Principle of Reconciliation — Chainguard, How Flux CD Reconciliation Loop Works — Oneuptime

대표 도구: ArgoCD vs FluxCD

항목ArgoCDFluxCD
설계중앙 집중형, 내장 Web UI분산형, CLI 중심, 모듈러
강점시각적 대시보드, 멀티테넌트, 직관적가벼움, Kubernetes 네이티브, 보안
적합 환경중앙 플랫폼팀이 여러 팀에 서비스 제공자율적 팀이 각자 클러스터 관리
CNCF 상태Graduated (졸업)Graduated (졸업)

ArgoCD vs FluxCD 정량 선택 기준

“어떤 도구를 써야 하나”는 주관적 선호가 아니라 아래 3가지 정량 기준으로 판단할 수 있다:

기준ArgoCD 선택FluxCD 선택
관리 클러스터 수 NN ≥ 3 (중앙 컨트롤 플레인 1개로 모든 클러스터 관리)N ≤ 5, 클러스터별 독립 운영 선호 (각 클러스터에 Flux 설치)
팀 구조중앙집중형 (플랫폼팀이 여러 앱팀에 서비스 제공, 멀티테넌트 필요)분산형 (앱팀이 각자 클러스터 운영, 플랫폼팀 없음)
UI 요구 여부필요 (비개발자 포함 팀, 배포 시각화 필수, RBAC 기반 접근 제어)불필요 (터미널 중심 운영, kubectl + flux CLI로 충분)

추가 고려사항:

  • 2024년 Weaveworks 폐사 이후 FluxCD는 CNCF 단독 관리로 전환. 상업적 지원은 없으나 CNCF 졸업 프로젝트로 지속 유지 중.
  • 신규 프로젝트라면 ArgoCD가 더 안전한 선택 (커뮤니티 크기, 엔터프라이즈 채택률 우세).
  • 기존 FluxCD 운영 중이라면 마이그레이션 비용 대비 이점을 먼저 검토.

출처: ArgoCD vs FluxCD in 2025 — DEV Community, ArgoCD vs FluxCD in 2026 — Oneuptime

Kustomize base/overlay 패턴 — 환경별 매니페스트 관리

ArgoCD와 FluxCD 모두 Kustomize를 네이티브로 지원한다. Kustomize는 Helm처럼 템플릿 언어 없이, 순수 YAML을 base(공통 기반)와 overlay(환경별 패치)로 분리해 관리한다. 별도 도구 설치 없이 kubectl에 내장되어 있다.

k8s/
├── base/ ← 모든 환경 공통 리소스 (Deployment, Service 등)
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
└── overlays/
├── dev/ ← dev 환경: 레플리카 1개, 낮은 리소스
│ ├── kustomization.yaml # base를 참조 + 패치 목록 지정
│ └── replica-patch.yaml # replicas: 1 오버라이드
└── prod/ ← prod 환경: 레플리카 3개, 높은 리소스
├── kustomization.yaml
└── replica-patch.yaml # replicas: 3 오버라이드

ArgoCD에서는 Application의 pathoverlays/prod로 지정하면 base를 자동으로 병합해서 렌더링한다. FluxCD에서는 Kustomization CR이 같은 역할을 한다. 이 패턴을 쓰면 환경마다 YAML을 복사할 필요 없이 차이점만 패치로 관리할 수 있다.

FluxCD 내부 아키텍처 — Kubernetes 네이티브 설계

FluxCD는 ArgoCD와 달리 단일 컨트롤러가 아니라 여러 독립적인 컨트롤러(Controller)가 각자 역할을 담당하는 모듈러 구조다. 각 컨트롤러는 Kubernetes CRD(Custom Resource Definition)로 동작하며, 서로 느슨하게 결합되어 있어 필요한 기능만 선택해서 사용할 수 있다.

FluxCD 컴포넌트 (각각 독립적인 Kubernetes Controller)
├── Source Controller ← Git/Helm/OCI 저장소를 감시하고 Artifact 생성
├── Kustomize Controller ← Kustomize 기반 Kubernetes 매니페스트 적용
├── Helm Controller ← Helm Chart 릴리즈 관리 (helm install/upgrade 자동화)
├── Notification Controller ← Slack/Teams/PagerDuty 등에 이벤트 알림
└── Image Automation Controller ← 새 이미지 태그 감지 → Git에 자동 커밋 (선택 설치)

비유: ArgoCD가 “한 명의 총괄 관리자”라면, FluxCD는 “각 분야 전문가 팀”이다. Source 전문가가 Git을 추적하고, Kustomize 전문가가 YAML을 처리하고, Helm 전문가가 차트를 관리한다.

FluxCD 설정 예시 — GitRepository + Kustomization으로 NestJS API 배포

# 1단계: GitRepository — Flux가 감시할 Git 저장소 등록
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: k8s-manifests
namespace: flux-system
spec:
interval: 1m # 1분마다 Git 변경 확인
url: https://github.com/my-team/k8s-manifests
ref:
branch: main
secretRef:
name: github-token # Private 저장소라면 인증 정보
---
# 2단계: Kustomization — GitRepository에서 어떤 경로를 어디에 배포할지 정의
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: nestjs-api
namespace: flux-system
spec:
interval: 10m # 10분마다 클러스터 상태와 비교 (Drift 감지)
path: ./apps/nestjs-api/production
prune: true # Git에서 삭제된 리소스를 클러스터에서도 삭제
sourceRef:
kind: GitRepository
name: k8s-manifests
healthChecks: # 배포 완료 기준 — Deployment가 Ready일 때
- apiVersion: apps/v1
kind: Deployment
name: nestjs-api
namespace: production
# Flux 상태 확인
$ flux get kustomizations
NAME REVISION SUSPENDED READY MESSAGE
nestjs-api main/a3c1f20 False True Applied revision: main/a3c1f20
# Git push 후 자동 동기화 확인
$ flux reconcile kustomization nestjs-api --with-source
► annotating GitRepository k8s-manifests in flux-system
✔ GitRepository annotated
◎ waiting for GitRepository reconciliation
✔ fetched revision: main/b5d2e31
► annotating Kustomization nestjs-api in flux-system
✔ Kustomization annotated
◎ waiting for Kustomization reconciliation
✔ applied revision: main/b5d2e31

📖 더 보기: FluxCD Getting Started (공식 문서) — Flux CLI 설치부터 첫 GitRepository + Kustomization 배포까지 단계별 가이드

Argo Rollouts — Progressive Delivery (점진적 배포)

기본 Kubernetes Rolling Update는 새 버전을 “한 번에 전체 교체”한다. Argo Rollouts는 카나리 배포(Canary)블루-그린 배포(Blue-Green) 를 지원해서 새 버전에 트래픽을 점진적으로 늘리면서 문제 없으면 전체 전환, 문제 있으면 즉시 롤백할 수 있게 한다.

비유: 식당 메뉴를 바꿀 때 “전체 손님에게 바로 새 메뉴”가 아니라 “10% 손님에게 먼저 제공 → 반응 좋으면 50% → 전체 전환”하는 방식이다.

# Argo Rollouts — Canary 배포 예시 (NestJS API)
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: nestjs-api
spec:
replicas: 10
selector:
matchLabels:
app: nestjs-api
template:
metadata:
labels:
app: nestjs-api
spec:
containers:
- name: api
image: my-ecr/nestjs-api:v2.0.0 # 새 버전
strategy:
canary:
steps:
- setWeight: 10 # 1단계: 트래픽의 10%를 새 버전으로
- pause: { duration: 5m } # 5분 대기 (메트릭 확인)
- setWeight: 30 # 2단계: 30%로 증가
- pause: { duration: 10m } # 10분 대기
- setWeight: 60 # 3단계: 60%로 증가
- pause: {} # 수동 승인 대기 (무한 pause)
# → 팀원이 승인하면 100%로 전환
analysis: # 자동 메트릭 검증
templates:
- templateName: success-rate # 성공률이 95% 미만이면 자동 롤백
startingStep: 1
# Argo Rollouts 진행 상황 확인 (kubectl plugin)
$ kubectl argo rollouts get rollout nestjs-api --watch
Name: nestjs-api
Namespace: production
Status: ॥ Paused
Message: CanaryPauseStep
Strategy: Canary
Step: 2/6
SetWeight: 10
ActualWeight: 10
NAME KIND STATUS AGE INFO
⟳ nestjs-api Rollout ॥ Paused 2m
├──# revision:2 Canary
│ └──⧉ nestjs-api-xxx (1 replica) RS ✔ Healthy 45s canary
└──# revision:1 Stable
└──⧉ nestjs-api-yyy (9 replicas) RS ✔ Healthy 5d stable
# 카나리 10%에서 문제 없으면 다음 단계로 수동 진행
$ kubectl argo rollouts promote nestjs-api
rollout 'nestjs-api' promoted
# 문제 발생 시 즉시 롤백
$ kubectl argo rollouts abort nestjs-api
rollout 'nestjs-api' aborted

📖 더 보기: Argo Rollouts 공식 문서 — Canary/Blue-Green 전략 설정, Analysis Template으로 자동 메트릭 기반 프로모션/롤백 구성

ArgoCD Application 리소스 예시

ArgoCD에서 “어떤 Git repo의 어떤 경로를 어떤 클러스터에 배포할지”를 Application 리소스로 정의한다:

# ArgoCD Application 리소스 예시
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nestjs-api
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/my-team/k8s-manifests
targetRevision: main
path: apps/nestjs-api # 이 경로의 YAML을 배포
destination:
server: https://kubernetes.default.svc # 현재 클러스터
namespace: production
syncPolicy:
automated: # 자동 동기화
prune: true # Git에서 삭제된 리소스도 클러스터에서 삭제
selfHeal: true # kubectl edit 등으로 직접 수정하면 자동 복원
# ArgoCD CLI로 상태 확인 예상 출력
$ argocd app get nestjs-api
Name: argocd/nestjs-api
Project: default
Server: https://kubernetes.default.svc
Namespace: production
URL: https://argocd.example.com/applications/nestjs-api
Repo: https://github.com/my-team/k8s-manifests
Target: main
Path: apps/nestjs-api
SyncWindow: Sync Allowed
Sync Policy: Automated (Prune)
Sync Status: Synced to main (a3c1f20)
Health Status: Healthy
GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
apps Deployment production nestjs-api Synced Healthy deployment.apps/nestjs-api configured
Service production nestjs-api Synced Healthy service/nestjs-api configured

App of Apps 패턴 — 멀티 환경 관리의 표준

실제 운영 환경에서는 애플리케이션이 수십 개다. 각각 ArgoCD Application을 직접 만들면 관리가 어려워진다. App of Apps 패턴은 하나의 부모 Application이 여러 자식 Application을 관리하는 구조다.

비유: App of Apps는 “목차가 있는 책”이다. 목차(부모 App)가 각 챕터(자식 App)를 가리키고, ArgoCD는 목차만 바라보면서 전체 내용을 관리한다.

# 멀티 환경 Git 저장소 구조 (권장 패턴)
k8s-manifests/
├── app-of-apps/
│ └── parent-app.yaml ← 부모 Application (이것만 ArgoCD에 직접 등록)
├── apps/
│ ├── nestjs-api/
│ │ ├── values-dev.yaml
│ │ ├── values-staging.yaml
│ │ └── values-prod.yaml
│ └── postgres/
│ └── ...
└── environments/
├── dev/
├── staging/
└── prod/
# 부모 Application 예시 — 자식 Applications를 자동으로 생성
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: app-of-apps
namespace: argocd
spec:
source:
repoURL: https://github.com/my-team/k8s-manifests
path: app-of-apps
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true

📖 더 보기: App of Apps 패턴 - AWS EKS Workshop — AWS EKS 환경에서 App of Apps 패턴을 실습하는 단계별 가이드

ApplicationSet — 멀티 클러스터 대규모 배포 자동화

App of Apps가 단일 클러스터에서 앱을 관리하는 패턴이라면, ApplicationSet은 여러 클러스터와 여러 앱을 조합해서 대규모로 배포를 자동화하는 리소스다. 예를 들어 앱 20개 × 클러스터 5개 = 100개 조합을 ApplicationSet 파일 하나로 자동 생성할 수 있다.

ApplicationSet의 핵심은 **Generator(생성기)**다. Generator는 ApplicationSet이 자동으로 Application을 만들 때 사용하는 “규칙”이다:

  • Cluster Generator: ArgoCD에 등록된 클러스터 목록을 기반으로 자동 생성. 새 클러스터가 등록되면 자동으로 Application이 생성됨
  • Git Generator: Git 저장소의 디렉토리 구조나 JSON 파일을 기반으로 Application 생성
  • Matrix Generator: 두 Generator를 조합. 예: 클러스터 목록 × 앱 목록 = 전체 배포 조합
# ApplicationSet 예시 — dev/staging/prod 클러스터에 nestjs-api 자동 배포
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: nestjs-api-multienv
namespace: argocd
spec:
generators:
- list:
elements:
- cluster: dev
url: https://dev-cluster.example.com
- cluster: staging
url: https://staging-cluster.example.com
- cluster: prod
url: https://prod-cluster.example.com
template:
metadata:
name: "nestjs-api-{{cluster}}"
spec:
project: default
source:
repoURL: https://github.com/my-team/k8s-manifests
targetRevision: main
path: "apps/nestjs-api/{{cluster}}"
destination:
server: "{{url}}"
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
# ApplicationSet 적용 후 자동 생성된 Application 확인
$ argocd app list
NAME CLUSTER NAMESPACE PROJECT STATUS HEALTH
nestjs-api-dev https://dev-cluster.example.com production default Synced Healthy
nestjs-api-staging https://staging-cluster.example.com production default Synced Healthy
nestjs-api-prod https://prod-cluster.example.com production default Synced Healthy
# → 파일 하나로 3개 클러스터에 Application이 자동 생성됨

📖 더 보기: ArgoCD ApplicationSet 공식 문서 — Generator 종류별 설명과 Matrix Generator 사용법 상세 안내

AWS EKS Capability for ArgoCD (2025 출시) — 관리형 ArgoCD

2025년 AWS가 EKS Capabilities의 일부로 관리형 ArgoCD를 출시했다. 기존에는 ArgoCD를 직접 클러스터에 설치하고 운영(스케일링, 업그레이드, 장애 대응)해야 했다. EKS Capability for ArgoCD는 ArgoCD 소프트웨어를 AWS 컨트롤 플레인에서 실행하므로 워커 노드를 소비하지 않고, AWS가 스케일링과 업그레이드를 자동으로 처리한다.

주요 특징:

  • Git 저장소 접근을 AWS 계정 레벨에서 처리 (워커 노드가 Git에 직접 접근 불필요)
  • AWS Secrets Manager, ECR, CodeCommit과 네이티브 통합
  • IAM 역할로 권한 관리 → 별도 ArgoCD RBAC 설정 최소화
# EKS Capability for ArgoCD 활성화 흐름 (AWS CLI)
1. IAM Capability Role 생성 (ArgoCD가 소스/클러스터에 접근할 권한)
2. EKS 클러스터에 ArgoCD Capability 리소스 등록 (콘솔 또는 CLI)
3. Git 저장소 연결 설정
4. Application 리소스 생성 → 배포 자동화 시작
$ aws eks create-addon \
--cluster-name my-nestjs-cluster \
--addon-name argocd \
--addon-version v2.11.0-eksbuild.1

📖 더 보기: AWS Deep Dive - EKS Capability for ArgoCD — 관리형 ArgoCD의 아키텍처와 설정 방법 상세 설명

ArgoCD v3.x 주요 변화 — 2025년 업그레이드 필수

2025년 4월 ArgoCD v3.0이 출시되었고, v2.14는 2025년 11월 4일 공식 EOL이 되었다. v2.x를 운영 중이라면 v3.x 마이그레이션이 필수다.

핵심 변경사항 3가지:

  1. RBAC 정교화(v3.0): AppProject 단위 RBAC 분리가 권장 패턴으로 자리잡음. 멀티테넌트 환경에서 전역 RBAC 복잡도 문제를 해결한다.
  2. Source Hydrator(v3.0): “Dry Repo(템플릿) → Wet Repo(렌더링 결과)” 패턴을 네이티브로 지원. 대규모 Helm 환경에서 Repo Server 부하를 줄인다.
  3. PreDelete Hooks(v3.3): Application 삭제 시 클린업 Job을 먼저 실행하고 완료 후 리소스를 삭제. DB 마이그레이션 롤백 등 안전한 삭제가 가능하다. 추가로 OCI Registry 네이티브 지원(v3.1)으로 ECR에 저장한 Helm Chart를 ArgoCD에서 직접 참조할 수 있다.

📖 더 보기: ArgoCD 3.3 Release — InfoQ — v3.3의 PreDelete Hooks, Source Hydrator 개선, KEDA 통합 등 주요 변경사항 상세 설명

Sync Waves와 Hooks — 배포 순서를 정밀하게 제어하는 방법

실제 애플리케이션을 배포할 때는 “DB 마이그레이션 → 앱 배포 → 스모크 테스트” 같은 순서가 중요하다. ArgoCD의 Sync Waves와 Hooks가 이 순서를 제어한다.

비유: 건물 공사에서 “기초(wave -1) → 골조(wave 0) → 내장(wave 1) → 준공 검사(PostSync hook)” 순서로 진행하는 것과 같다. 이전 단계가 완료되어야 다음 단계가 시작된다.

Sync Wave: 리소스에 argocd.argoproj.io/sync-wave 어노테이션으로 숫자를 부여하면, 작은 숫자부터 순서대로 적용된다. 기본값은 0이고, 음수도 가능하다. 같은 wave 안에서는 병렬로 적용된다.

Sync Hooks: 배포의 특정 시점에 실행되는 리소스(보통 Job)이다:

  • PreSync: Sync 전에 실행 (DB 마이그레이션, 스키마 변경)
  • Sync: 일반 리소스와 함께 적용 (기본)
  • PostSync: Sync 완료 후 실행 (스모크 테스트, 알림 발송)
  • SyncFail: Sync 실패 시 실행 (장애 알림)
  • PreDelete: Application 삭제 전 실행 (클린업, ArgoCD v3.3+)
# Sync Wave + Hook 조합 예시 — DB 마이그레이션 → 앱 배포 → 테스트
---
# Wave -1: Namespace와 ConfigMap 먼저 생성
apiVersion: v1
kind: ConfigMap
metadata:
name: nestjs-api-config
annotations:
argocd.argoproj.io/sync-wave: "-1"
data:
DB_HOST: postgres.database.svc.cluster.local
---
# PreSync Hook: DB 마이그레이션 Job (앱 배포 전에 실행)
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: my-ecr/nestjs-api:latest
command: ["npx", "typeorm", "migration:run"]
restartPolicy: Never
---
# Wave 0: 메인 애플리케이션 Deployment (기본값)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nestjs-api
# sync-wave 미지정 → 기본값 0
spec:
replicas: 3
# ... (Deployment spec)
---
# PostSync Hook: 스모크 테스트 (배포 완료 후 실행)
apiVersion: batch/v1
kind: Job
metadata:
name: smoke-test
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: test
image: curlimages/curl
command: ["curl", "-f", "http://nestjs-api/health"]
restartPolicy: Never
# Sync Wave 실행 순서 시각화
Phase: PreSync
→ db-migration Job 실행 → 완료 대기
Phase: Sync
→ Wave -1: ConfigMap 생성
→ Wave 0: Deployment, Service 적용
Phase: PostSync
→ smoke-test Job 실행 → 성공 확인

📖 더 보기: ArgoCD Sync Waves and Hooks 공식 문서 — Wave 숫자 규칙, Hook 종류별 동작, hook-delete-policy 옵션 상세 설명

시크릿 관리 패턴 — Git에 평문 저장 없이 GitOps를 유지하는 방법

GitOps의 원칙은 “모든 것을 Git에 저장”이지만 비밀번호, API Key 같은 시크릿은 예외다. 시크릿을 Git에 평문으로 저장하면 저장소에 접근할 수 있는 모든 사람이 볼 수 있어 보안 위험이 크다. 이 문제를 해결하는 두 가지 주요 패턴이 있다:

패턴 1 — Sealed Secrets: Git에 암호화된 시크릿을 저장한다. 클러스터 안의 Sealed Secrets Controller가 복호화해서 일반 Kubernetes Secret으로 변환한다.

# Sealed Secrets 흐름
1. kubeseal CLI로 Secret을 암호화 → SealedSecret 리소스 생성
2. SealedSecret YAML을 Git에 커밋 (암호화된 상태)
3. ArgoCD가 SealedSecret을 클러스터에 적용
4. Sealed Secrets Controller가 복호화 → 일반 Secret 생성
5. Pod가 Secret을 환경변수나 볼륨으로 마운트해서 사용

패턴 2 — External Secrets Operator (ESO): AWS Secrets Manager, HashiCorp Vault 같은 외부 시크릿 저장소의 값을 Kubernetes Secret으로 자동 동기화한다. AWS 환경에서는 이 패턴이 가장 많이 사용된다.

# External Secrets Operator 예시 — AWS Secrets Manager 연동
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: nestjs-api-secrets
spec:
refreshInterval: 1h # 1시간마다 AWS에서 최신 값 가져오기
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: nestjs-api-secrets # 생성될 Kubernetes Secret 이름
data:
- secretKey: DB_PASSWORD
remoteRef:
key: prod/nestjs-api/db # AWS Secrets Manager의 시크릿 이름
property: password
- secretKey: REDIS_PASSWORD
remoteRef:
key: prod/nestjs-api/redis
property: password
# ESO가 자동으로 생성한 Kubernetes Secret 확인
$ kubectl get externalsecret nestjs-api-secrets
NAME STORE REFRESH STATUS
nestjs-api-secrets aws-secrets-manager 1h SecretSynced
$ kubectl get secret nestjs-api-secrets -o jsonpath='{.data.DB_PASSWORD}' | base64 -d
my-secret-password
# → AWS Secrets Manager의 값이 Kubernetes Secret으로 자동 동기화됨

📖 더 보기: External Secrets Operator 공식 문서 — AWS, GCP, Vault 등 Provider별 설정 방법과 SecretStore 구성 가이드

⚠️ ArgoCD + Helm 주의사항 — helm install이 아니다

ArgoCD가 Helm Chart를 처리할 때 helm install이나 helm upgrade를 실행하지 않는다. 내부적으로 helm template을 실행해서 YAML을 생성한 뒤, 그 결과를 kubectl apply한다. 이 차이가 중요한 이유:

  • Helm Hooks의 동작이 달라진다: pre-install, pre-upgrade 훅이 매번 Sync할 때마다 실행된다. 훅이 멱등(idempotent)하지 않으면 DB 마이그레이션이 중복 실행되는 등 문제가 생긴다.
  • Helm Release 히스토리가 없다: helm history로 배포 이력을 볼 수 없다. 이력은 Git에만 있다.
  • 따라서 ArgoCD + Helm 환경에서는 Helm Hooks 대신 Kubernetes Job이나 ArgoCD Sync Waves/Hooks를 사용하는 것이 권장된다.

ArgoCD HA(High Availability) 프로덕션 설정 — 단일 Pod는 프로덕션 부적합

ArgoCD를 EKS 프로덕션에 직접 설치할 때는 반드시 HA 매니페스트를 사용해야 한다. 기본 설치(non-HA)는 각 컴포넌트가 Pod 1개로 동작하므로, 한 Pod가 재시작되는 순간 전체 배포 파이프라인이 멈춘다.

HA 설치의 핵심은 세 가지다:

  • Application Controller: StatefulSet으로 샤딩(sharding) 지원. 앱이 많아지면 여러 Controller 인스턴스가 각각 일부 앱을 담당
  • Repo Server: 여러 복제본이 Git 클론 + Helm 렌더링 병렬 처리
  • Redis HA: Redis Sentinel로 자동 페일오버. Redis가 죽으면 캐시 손실 → 모든 앱 상태를 Git에서 다시 읽어야 하므로 API Server 과부하 발생
# ArgoCD HA 설치 (EKS 프로덕션용 권장 설정)
# 설치: kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/ha/install.yaml
# 추가 튜닝 — argocd-cmd-params-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cmd-params-cm
namespace: argocd
data:
# Application Controller 샤딩 — 앱 100개 이상일 때 활성화
controller.sharding.algorithm: "consistent-hashing" # 샤드 간 앱 분배 방식
# Repo Server 캐시 만료 시간 (기본 24시간)
reposerver.parallelism.limit: "10" # 동시 Helm 렌더링 최대 10개
# HA 설치 후 컴포넌트 확인
$ kubectl get pods -n argocd
NAME READY STATUS RESTARTS
argocd-application-controller-0 1/1 Running 0 ← StatefulSet (샤드 0)
argocd-application-controller-1 1/1 Running 0 ← StatefulSet (샤드 1)
argocd-repo-server-6d8f5b7c9-abc12 1/1 Running 0
argocd-repo-server-6d8f5b7c9-def34 1/1 Running 0 ← 2개 복제본
argocd-redis-ha-haproxy-xxx 1/1 Running 0 ← Redis HA + HAProxy
argocd-server-7d9f4b8c4-ghijk 1/1 Running 0
argocd-server-7d9f4b8c4-lmnop 1/1 Running 0 ← 2개 복제본
# → 각 컴포넌트가 여러 Pod로 동작 → 단일 Pod 장애에도 배포 파이프라인 유지

📖 더 보기: ArgoCD HA 구성 방법 - Oneuptime Blog — HA 설치 단계별 가이드, Redis Sentinel 구성, 컴포넌트별 replicas 설정

ArgoCD + EKS Pod Identity — IRSA 없이 Git 저장소 접근

기존 ArgoCD가 Private Git 저장소나 ECR에 접근할 때 SSH Key나 IRSA를 설정해야 했다. 2025년부터 EKS Pod Identity와 ArgoCD를 결합하면 OIDC 설정 없이 IAM Role만으로 접근 권한을 부여할 수 있다.

# Terraform으로 ArgoCD Service Account에 Pod Identity 연결
resource "aws_eks_pod_identity_association" "argocd_repo_server" {
cluster_name = module.eks.cluster_name
namespace = "argocd"
service_account = "argocd-repo-server"
role_arn = aws_iam_role.argocd_ecr_access.arn
}
# ArgoCD Repo Server에 ECR 읽기 권한 부여
resource "aws_iam_role_policy_attachment" "argocd_ecr" {
role = aws_iam_role.argocd_ecr_access.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
}
# Pod Identity 적용 후 ArgoCD가 ECR에서 이미지 정보를 가져올 수 있는지 확인
$ argocd app sync nestjs-api
...
SYNC apps Deployment production nestjs-api Synced
# → 별도 Docker credentials 없이 ECR 이미지 정보 접근 성공

Drift Detection (상태 드리프트 감지)

누군가 kubectl edit으로 클러스터를 직접 수정하면, ArgoCD가 이를 감지하고 “OutOfSync” 경고를 표시한다. Self-Healing 설정이 켜져 있으면 자동으로 Git 상태로 되돌린다.

⚠️ Git에 시크릿을 직접 저장하면 안 된다

GitOps에서 모든 것을 Git에 저장하지만, 비밀번호/API Key는 예외다. Sealed Secrets, External Secrets Operator, AWS Secrets Manager 연동 등으로 시크릿을 별도 관리해야 한다.

  • Kubernetes 클러스터에 애플리케이션 자동 배포
  • 인프라 변경의 PR 기반 리뷰 → 머지 → 자동 적용
  • 멀티 클러스터 환경(dev/staging/prod) 관리
  • 롤백: git revert → 자동으로 이전 상태 복원
  • 감사 추적: “누가 언제 무엇을 배포했는지” Git 이력으로 확인
  • App of Apps 패턴으로 수십 개 애플리케이션을 일관되게 관리
  • ApplicationSet으로 수십 개 클러스터 × 수십 개 앱 조합을 파일 하나로 관리
  • CI/CD 파이프라인 고도화 시 GitOps 패턴 도입 검토
  • “배포 히스토리를 추적하고 싶다” → GitOps의 핵심 가치
  • 플랫폼 엔지니어링에서 “개발자가 PR만 올리면 배포되는” 워크플로 구축
  • 여러 환경(dev/staging/prod)을 일관되게 관리하는 표준 방법
  • AWS EKS Capabilities(2025 출시)가 ArgoCD를 네이티브로 통합 → EKS에서 GitOps 진입 장벽 대폭 낮아짐
  • ApplicationSet으로 멀티 클러스터를 운영하는 경우 단일 파일로 전체 배포 상태를 코드화할 수 있음
개념 A개념 B차이점
GitOpsCI/CDCI/CD는 빌드+배포 자동화, GitOps는 Git을 진실 공급원으로 사용하는 배포 방법론
Push 배포Pull 배포 (GitOps)Push는 CI가 클러스터에 직접 적용, Pull은 클러스터 에이전트가 Git에서 가져옴
ArgoCDFluxCDArgoCD는 UI+중앙집중, Flux는 CLI+분산형 (둘 다 CNCF 졸업)
GitOpsIaCIaC는 인프라를 코드로 정의하는 것, GitOps는 그 코드를 Git 기반으로 자동 적용하는 것
helm installArgoCD + HelmArgoCD는 helm template으로 YAML 생성 후 kubectl apply, helm 히스토리 없음
App of AppsApplicationSetApp of Apps는 단일 클러스터 다수 앱 관리, ApplicationSet은 멀티 클러스터 자동화

🔧 ComparisonError: failed to load live state — ArgoCD가 클러스터 상태를 못 읽음

섹션 제목: “🔧 ComparisonError: failed to load live state — ArgoCD가 클러스터 상태를 못 읽음”

증상: ArgoCD 대시보드에서 Application이 Unknown 상태로 표시되고 “failed to load live state” 에러

원인: ArgoCD가 Kubernetes API에 접근하는 ServiceAccount에 필요한 RBAC 권한이 없거나, 클러스터 연결 자체가 끊긴 경우

해결:

  1. argocd cluster list로 연결된 클러스터 상태 확인
  2. kubectl get pods -n argocdapplication-controller Pod가 Running인지 확인
  3. ArgoCD ServiceAccount의 ClusterRole 바인딩 확인: kubectl get clusterrolebinding | grep argocd
  4. 외부 클러스터라면 argocd cluster add <context-name>으로 다시 등록

🔧 Application이 계속 OutOfSync로 돌아옴 — Self-Heal 루프

섹션 제목: “🔧 Application이 계속 OutOfSync로 돌아옴 — Self-Heal 루프”

증상: Sync를 눌러서 Synced가 됐는데 몇 분 후 다시 OutOfSync로 돌아오는 현상이 반복됨

원인: Kubernetes가 리소스를 생성할 때 자동으로 추가하는 필드(defaultMode, managedFields 등)가 Git의 원본 YAML에는 없어서 항상 “차이”로 감지됨. 또는 다른 컨트롤러(예: Helm Operator)가 ArgoCD 관리 리소스를 계속 수정하는 경우

해결:

  1. argocd app diff nestjs-api로 정확히 어떤 필드가 다른지 확인
  2. 무시해도 되는 필드라면 Application spec에 ignoreDifferences 추가:
spec:
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/template/spec/containers/0/resources
  1. 다른 컨트롤러와 충돌이면 관리 주체를 하나로 통일

🔧 rpc error: repository not accessible — Git 저장소 접근 불가

섹션 제목: “🔧 rpc error: repository not accessible — Git 저장소 접근 불가”

증상: ArgoCD Application을 생성하거나 Sync할 때 “repository not accessible” 또는 “authentication required” 에러

원인: Private Git 저장소에 등록된 SSH Key 또는 HTTPS 토큰이 만료되거나 잘못 설정된 경우

해결:

  1. ArgoCD UI → Settings → Repositories에서 해당 저장소의 연결 상태 확인
  2. SSH Key 방식이면 argocd repo add git@github.com:my-team/k8s-manifests.git --ssh-private-key-path ~/.ssh/id_rsa로 재등록
  3. HTTPS 방식이면 Personal Access Token 만료 여부 확인 후 재발급 및 재등록
  4. argocd repo list로 등록된 저장소 목록과 상태 재확인

🔧 ArgoCD + Helm Hooks가 매번 Sync마다 실행됨

섹션 제목: “🔧 ArgoCD + Helm Hooks가 매번 Sync마다 실행됨”

증상: DB 마이그레이션이나 초기화 Job이 ArgoCD Sync할 때마다 중복 실행됨

원인: ArgoCD는 helm install/helm upgrade가 아닌 helm template으로 YAML을 생성하기 때문에 Helm의 pre-install/pre-upgrade 훅이 Sync할 때마다 트리거됨

해결:

  1. Helm Hook 대신 ArgoCD의 argocd.argoproj.io/hook 어노테이션 사용:
    metadata:
    annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
  2. Job이 멱등(idempotent)하게 설계: 이미 완료된 상태면 다시 실행해도 부작용 없도록
  3. DB 마이그레이션은 ArgoCD Sync Wave로 실행 순서를 제어

🔧 ApplicationSet으로 생성된 Application이 의도치 않게 삭제됨

섹션 제목: “🔧 ApplicationSet으로 생성된 Application이 의도치 않게 삭제됨”

증상: ApplicationSet에서 클러스터 또는 디렉토리 항목을 제거했더니 해당 클러스터의 Application과 실제 배포된 리소스까지 삭제됨

원인: ApplicationSet의 기본 동작은 Generator에서 항목이 사라지면 해당 Application을 자동으로 삭제(prune)한다. Application의 syncPolicy.automated.prune: true와 함께 사용하면 클러스터의 리소스까지 연쇄 삭제된다

해결:

  1. deletionPolicyRetain으로 설정하면 ApplicationSet이 삭제되어도 Application은 유지됨:
    spec:
    syncPolicy:
    preserveResourcesOnDeletion: true # ArgoCD 2.7+
  2. Generator 항목을 제거하기 전에 반드시 해당 Application을 수동으로 확인하고 삭제 여부를 결정
  3. 프로덕션 환경의 ApplicationSet에는 automated.prune: false로 시작해서 안전성 확인 후 전환

🔧 ArgoCD Repo Server OOM — 대규모 Helm Chart 렌더링 시 메모리 부족

섹션 제목: “🔧 ArgoCD Repo Server OOM — 대규모 Helm Chart 렌더링 시 메모리 부족”

증상: kubectl get pods -n argocd에서 argocd-repo-server Pod가 주기적으로 OOMKilled로 재시작됨. Sync 버튼을 누를 때마다 Repo Server가 죽어서 배포가 실패함

원인: Helm Chart가 크거나 values 파일이 많을 때 helm template 실행 시 Repo Server 메모리 사용량이 급증한다. 기본 Repo Server의 메모리 limit(256Mi~512Mi)이 너무 낮은 경우, 또는 여러 앱이 동시에 Sync 요청할 때 병렬 렌더링이 메모리를 모두 소비하는 경우

해결:

  1. Repo Server 메모리 limits 증가:
    # argocd-repo-server Deployment 패치
    containers:
    - name: argocd-repo-server
    resources:
    requests:
    memory: "256Mi"
    cpu: "100m"
    limits:
    memory: "1Gi" # 기본값 512Mi → 1Gi로 증가
    cpu: "500m"
  2. 동시 렌더링 수 제한 (argocd-cmd-params-cm ConfigMap):
    data:
    reposerver.parallelism.limit: "5" # 동시 helm template 최대 5개 (기본값 제한 없음)
  3. Helm Chart 크기 문제라면 ArgoCD v3.x의 Source Hydrator 도입 검토 — Repo Server 부하를 분산
# OOMKilled 확인 및 메모리 사용량 모니터링
$ kubectl describe pod argocd-repo-server-xxx -n argocd | grep -A 3 "Last State"
Last State: Terminated
Reason: OOMKilled
Exit Code: 137
$ kubectl top pods -n argocd -l app.kubernetes.io/component=repo-server
NAME CPU(cores) MEMORY(bytes)
argocd-repo-server-6d8f5b7c9 340m 498Mi ← limits 512Mi에 근접
# → limits를 1Gi로 올린 후 재배포

🔧 멀티 클러스터 환경에서 일부 클러스터만 Sync 실패

섹션 제목: “🔧 멀티 클러스터 환경에서 일부 클러스터만 Sync 실패”

증상: 여러 클러스터 중 특정 클러스터의 Application만 Degraded 또는 SyncError 상태

원인: 클러스터별로 Kubernetes 버전이 다르거나, 특정 클러스터에 필요한 CRD(Custom Resource Definition)가 설치되어 있지 않은 경우. 또는 해당 클러스터의 네트워크 단절

해결:

  1. argocd cluster list로 문제 클러스터의 연결 상태 확인
  2. argocd app logs <app-name> 또는 argocd app sync <app-name> --dry-run으로 에러 내용 파악
  3. 클러스터 버전 차이가 원인이면 Kustomize의 components를 사용해서 클러스터별 오버레이 적용
  4. CRD 누락이 원인이면 해당 CRD를 먼저 설치한 뒤 Sync Waves로 순서 제어
  • GitOps의 4원칙을 설명할 수 있다
  • Push 모델(기존 CI/CD)과 Pull 모델(GitOps)의 차이를 설명할 수 있다
  • ArgoCD와 FluxCD의 차이를 설명할 수 있다
  • Drift Detection이 뭔지, 왜 중요한지 설명할 수 있다
  • GitOps에서 시크릿을 어떻게 관리하는지 설명할 수 있다
  • App of Apps 패턴이 왜 필요한지 설명할 수 있다
  • ArgoCD + Helm 조합에서 helm template 방식의 차이를 설명할 수 있다
  • ApplicationSet과 App of Apps의 차이를 설명할 수 있다
  • AWS EKS Capability for ArgoCD가 기존 자체 설치 방식과 어떻게 다른지 설명할 수 있다
  • Sync Waves와 Hooks를 사용해서 배포 순서를 제어하는 방법을 설명할 수 있다
  • External Secrets Operator가 어떻게 GitOps에서 시크릿 문제를 해결하는지 설명할 수 있다
  • FluxCD의 GitRepository + Kustomization 조합이 ArgoCD Application과 어떻게 대응되는지 설명할 수 있다
  • Argo Rollouts의 Canary 배포가 기본 Rolling Update와 무엇이 다른지 설명할 수 있다
  • Progressive Delivery에서 자동 롤백이 어떤 조건으로 트리거되는지 설명할 수 있다

ArgoCD ApplicationSet, Helm + ArgoCD, Kustomize, Sealed Secrets, External Secrets Operator, Progressive Delivery, Argo Rollouts, Flux Image Automation, App of Apps, ArgoCD Sync Waves, EKS Capability for ArgoCD, Matrix Generator, Cluster Generator

  • minikube 클러스터에 ArgoCD 설치: kubectl create namespace argocd && kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

    # 예상 출력
    customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io created
    customresourcedefinition.apiextensions.k8s.io/applicationsets.argoproj.io created
    ...
    deployment.apps/argocd-server created
  • ArgoCD Web UI에 접속해서 대시보드 구조 파악

    # admin 초기 비밀번호 확인
    $ kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
    xK9mN3pQ2wR8vT4s
  • 간단한 Git repo에 Deployment YAML 저장 → ArgoCD Application으로 연결 → Sync 확인

    # Sync 완료 후 상태
    $ argocd app get nestjs-api
    Sync Status: Synced to main (a3c1f20)
    Health Status: Healthy
  • Git에서 replicas 수를 변경하고 push → ArgoCD가 자동으로 감지하는지 확인

    # git push 후 3분 이내 OutOfSync 감지
    $ argocd app get nestjs-api
    Sync Status: OutOfSync (1 resource(s) need update)
    # Auto-Sync 켜져 있으면 자동으로 Synced로 돌아옴
  • argocd app diff nestjs-api로 Git과 클러스터의 차이를 직접 확인

    $ argocd app diff nestjs-api
    ===== apps/Deployment production/nestjs-api ======
    3c3
    < replicas: 3
    ---
    > replicas: 5
    # Git은 3개, 클러스터는 5개 → OutOfSync 원인 파악 가능
  • ApplicationSet을 이용해서 dev/prod 두 환경에 동시에 Application을 자동 생성해보기

    $ kubectl apply -f applicationset.yaml -n argocd
    applicationset.argoproj.io/nestjs-api-multienv created
    $ argocd app list
    NAME CLUSTER NAMESPACE STATUS HEALTH
    nestjs-api-dev dev-cluster production Synced Healthy
    nestjs-api-prod prod-cluster production Synced Healthy
    # → ApplicationSet 하나로 두 환경 Application이 자동 생성됨
  1. GitOps는 Git을 인프라/앱의 단일 진실 공급원으로 사용하는 운영 방법론이다
  2. Pull 모델: 클러스터 에이전트가 Git을 감시하고 자동으로 상태를 맞춘다 (3분 주기 Reconciliation)
  3. 감사 추적(Git 이력)과 롤백(git revert)이 자연스럽게 내장된다
  4. ArgoCD v3.x(2025~)가 표준으로 자리잡음 — v2.14는 EOL, PreDelete Hooks·KEDA 통합 등 운영 편의성 강화
  5. AWS EKS Capability for ArgoCD(2025 출시)로 클러스터 외부에서 관리형 GitOps가 가능해졌다
Git (선언적 상태 저장)
└── ArgoCD Repo Server (Helm template / Kustomize build)
└── Application Controller (Reconciliation Loop, 3분 주기)
├── OutOfSync 감지 → Auto-Sync → kubectl apply
└── Drift 감지 → Self-Heal (kubectl edit 등 직접 수정 자동 복원)
배포 구조 패턴
├── App of Apps: 단일 클러스터 내 다수 앱 관리 (목차 + 챕터 구조)
└── ApplicationSet: 멀티 클러스터 × 멀티 앱 자동화 (Generator로 조합 생성)
배포 순서 제어
├── Sync Waves: 숫자 어노테이션으로 리소스 적용 순서 결정 (-1 → 0 → 1)
└── Sync Hooks: PreSync(DB 마이그레이션) → Sync → PostSync(스모크 테스트)
시크릿 관리 (Git에 평문 저장 금지)
├── Sealed Secrets: Git에 암호화된 시크릿 저장 → 클러스터에서 복호화
└── External Secrets Operator: AWS Secrets Manager 값을 Kubernetes Secret으로 자동 동기화 (AWS 환경 권장)
  • “GitOps와 기존 CI/CD의 차이?” → Push vs Pull 모델. CI서버가 클러스터에 접근하느냐, 클러스터 에이전트가 Git을 당겨오느냐의 차이. Pull이 보안상 더 안전
  • “Drift Detection이란?” → 누군가 kubectl edit로 클러스터를 직접 수정하면 ArgoCD가 Git과의 차이를 감지해서 OutOfSync 표시. Self-Heal 켜면 자동 복원
  • “App of Apps vs ApplicationSet 차이?” → App of Apps는 단일 클러스터에서 앱 관리, ApplicationSet은 멀티 클러스터까지 Generator로 자동화
  • “ArgoCD + Helm의 주의점?” → ArgoCD는 helm install이 아닌 helm template 실행. Helm Hooks가 매 Sync마다 실행되어 DB 마이그레이션 중복 실행 위험
  • ArgoCD를 HA 모드(High Availability)로 설치했는가? (단일 Pod는 프로덕션 부적합)
  • 소스 코드 저장소와 매니페스트(GitOps) 저장소를 분리했는가?
  • 브랜치 분기 대신 폴더(environments/dev, /staging, /prod)로 환경을 분리했는가?
  • 시크릿을 Git에 평문으로 저장하지 않고 Sealed Secrets 또는 External Secrets를 쓰는가?
  • 프로덕션 Application에 selfHeal: trueprune: true를 적용하기 전 충분히 검증했는가?
  • ApplicationSet에 preserveResourcesOnDeletion: true로 실수 삭제를 방지했는가?
  • ArgoCD 버전이 v3.x인가? (v2.14는 2025년 11월 EOL)

최종 수정: 2026-04-01