GitOps란 무엇인가 — 4가지 핵심 원칙
"Git이 곧 배포다"라는 발상의 전환
GitOps는 인프라와 애플리케이션의 원하는 상태(desired state)를 Git 저장소에 선언적으로 기록하고, 에이전트가 그 선언을 클러스터에 자동으로 반영하게 하는 운영 방식이다. 사람이 클러스터에 직접 명령을 내리는 대신, Git에 커밋(또는 PR 머지)하는 것만으로 배포가 일어난다. 모든 변경이 커밋 히스토리로 남기 때문에 감사(audit)와 롤백이 git revert 한 줄로 끝난다.
CNCF GitOps 워킹그룹이 정리한 OpenGitOps의 4가지 원칙은 다음과 같다.
- Declarative(선언적): 시스템의 원하는 상태를 "어떻게"가 아니라 "무엇"으로 선언한다.
- Versioned and Immutable(버전 관리·불변): 원하는 상태는 Git처럼 버전과 전체 이력이 남고, 불변성이 보장되는 저장소에 둔다.
- Pulled Automatically(자동 풀): 소프트웨어 에이전트가 저장소의 선언을 자동으로 가져온다(push가 아닌 pull 모델).
- Continuously Reconciled(지속적 동기화): 에이전트가 실제 상태와 선언된 상태를 끊임없이 비교하고, 차이(drift)가 생기면 자동으로 교정한다.
Argo CD가 하는 일
Argo CD는 위 원칙을 Kubernetes에서 구현한 대표적인 GitOps 컨트롤러다. Git 저장소에 있는 매니페스트(plain YAML / Helm / Kustomize)를 주기적으로 풀하고, 클러스터의 실제 상태와 비교해 OutOfSync면 자동 또는 수동으로 동기화한다. 누군가 클러스터를 손으로 건드려도 Argo CD가 drift를 감지하고 Git 기준으로 되돌릴 수 있다(self-heal). 웹 UI에서 리소스 트리와 동기화 상태를 한눈에 볼 수 있는 것도 큰 장점이다.
Argo CD 설치와 첫 Application 등록
설치 — 버전을 고정하라
설치는 네임스페이스를 만들고 릴리스 매니페스트를 적용하면 끝이다. stable 대신 구체적인 버전 태그를 쓰는 것이 재현성 측면에서 안전하다(2026년 6월 기준 최신 안정 버전은 3.4 계열).
kubectl create namespace argocd
kubectl apply -n argocd -f \
https://raw.githubusercontent.com/argoproj/argo-cd/v3.4.3/manifests/install.yaml
# 초기 admin 비밀번호 확인
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
# UI/CLI 접속용 포트포워딩
kubectl port-forward svc/argocd-server -n argocd 8080:443
첫 Application 선언하기
Argo CD의 배포 단위는 Application 커스텀 리소스다. "어느 Git 저장소의, 어느 경로를, 어느 클러스터/네임스페이스에 배포할지"를 선언한다. 아래는 자동 동기화와 self-heal까지 켠 실제 동작하는 예시다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/k8s-manifests.git
targetRevision: main
path: apps/guestbook
destination:
server: https://kubernetes.default.svc
namespace: guestbook
syncPolicy:
automated:
prune: true # Git에서 지운 리소스는 클러스터에서도 삭제
selfHeal: true # 수동 변경(drift) 발생 시 Git 기준으로 자동 복구
syncOptions:
- CreateNamespace=true
이 한 파일을 kubectl apply -n argocd -f application.yaml로 등록하면, 이후 배포는 매니페스트 저장소에 커밋하는 것만으로 자동 반영된다. App of Apps 패턴(루트 Application이 하위 Application들을 관리)으로 확장하면 수십 개 서비스도 Git 한 곳에서 통제할 수 있다.
Helm·Kustomize·OCI 레지스트리 연동
Helm 차트를 Application으로
Argo CD는 Helm 차트를 별도 Tiller 없이 helm template으로 렌더링한 뒤 적용한다. source.helm.values에 인라인 값을 넣거나 valueFiles로 환경별 values 파일을 지정한다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: ingress-nginx
namespace: argocd
spec:
project: default
source:
repoURL: https://kubernetes.github.io/ingress-nginx
chart: ingress-nginx # Helm repo의 차트 이름
targetRevision: 4.11.3 # 차트 버전 고정
helm:
valueFiles:
- values-prod.yaml
destination:
server: https://kubernetes.default.svc
namespace: ingress-nginx
syncPolicy:
automated: { prune: true, selfHeal: true }
syncOptions: [ CreateNamespace=true ]
OCI 레지스트리를 차트 소스로
최신 Argo CD는 Helm 차트를 OCI 아티팩트로 끌어올 수 있다. 즉 GHCR, AWS ECR, Google Artifact Registry 같은 컨테이너 레지스트리를 별도 Helm 차트 저장소 없이 그대로 차트 소스로 쓸 수 있다. repoURL을 oci://로 지정하고 chart 필드를 함께 주면 Argo CD가 OCI 소스로 인식한다.
spec:
source:
repoURL: oci://ghcr.io/myorg/charts
chart: backend-api
targetRevision: 1.4.0
helm:
valueFiles:
- values-prod.yaml
Kustomize, 그리고 Helm+Kustomize 조합
Kustomize는 kustomization.yaml이 있는 경로를 가리키기만 하면 Argo CD가 자동 인식한다. base/overlays 구조로 dev/staging/prod 차이를 패치로 관리하는 방식이 GitOps와 특히 잘 맞는다. Helm 차트를 Kustomize로 한 번 더 후처리하고 싶다면 --enable-helm을 켠 Kustomize 빌드를 사용하면 된다.
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- path: replica-patch.yaml # prod에서만 replicas 상향
images:
- name: myorg/backend-api
newTag: "1.4.0" # latest 금지, 버전 고정
ApplicationSet과 Argo Rollouts 점진적 배포
ApplicationSet — 템플릿으로 수십 개 앱 찍어내기
ApplicationSet 컨트롤러는 이제 Argo CD 코어에 통합되어 있다. 하나의 템플릿과 제너레이터(generator)로 수십~수백 개의 Application을 자동 생성한다. 멀티 클러스터, 멀티 환경, 모노레포 디렉터리별 배포에 특히 강력하다. 아래는 Git 디렉터리 제너레이터로 apps/ 아래 각 폴더를 자동으로 Application화하는 예시다.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: all-apps
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/myorg/k8s-manifests.git
revision: main
directories:
- path: apps/*
template:
metadata:
name: '{{path.basename}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/k8s-manifests.git
targetRevision: main
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{path.basename}}'
syncPolicy:
automated: { prune: true, selfHeal: true }
syncOptions: [ CreateNamespace=true ]
Argo Rollouts — 카나리·블루그린 자동화
기본 Deployment의 롤링 업데이트만으로는 트래픽 비율을 세밀하게 제어하거나 지표 기반으로 자동 승격/중단을 하기 어렵다. Argo Rollouts는 Deployment를 대체하는 Rollout CRD를 제공해 카나리와 블루그린 같은 점진적 배포(progressive delivery)를 선언적으로 구현한다. Prometheus·Datadog 등 지표 분석(AnalysisTemplate)과 연동하면 시간이 아니라 데이터 기반으로 승격을 결정한다.
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: backend-api
spec:
replicas: 5
selector:
matchLabels: { app: backend-api }
template:
metadata:
labels: { app: backend-api }
spec:
containers:
- name: backend-api
image: ghcr.io/myorg/backend-api:1.4.0
strategy:
canary: # 단계별로 트래픽을 점진 확대
steps:
- setWeight: 20
- pause: { duration: 5m }
- setWeight: 50
- pause: { duration: 5m }
- setWeight: 100
블루그린이 필요하면 strategy.blueGreen으로 바꿔 active/preview 두 ReplicaSet을 운영하고, 검증 후 promote 한 번으로 전환한다. Rollout 매니페스트 역시 Git에 두면 Argo CD가 관리하므로 GitOps와 자연스럽게 결합된다.
장단점 비교표와 실전 팁
| 구분 | 장점 | 단점 |
|---|---|---|
| 추적성 | 모든 배포가 Git 커밋으로 남아 감사·롤백이 git revert로 끝남 | 긴급 핫픽스도 커밋을 거쳐야 해 절차가 늘어남 |
| 안정성 | drift 자동 감지·self-heal, 클러스터를 손으로 못 건드리게 강제 | self-heal이 의도한 수동 변경까지 되돌려 혼란을 줄 수 있음 |
| 확장성 | ApplicationSet으로 멀티 클러스터·수백 앱을 템플릿화 | 제너레이터·App of Apps 구조 설계에 학습이 필요 |
| 배포 전략 | Argo Rollouts로 카나리·블루그린·지표 기반 승격 | Deployment를 Rollout CRD로 바꿔야 하는 전환 비용 |
| 생태계 | Helm·Kustomize·OCI 레지스트리, Prometheus 분석 연동 풍부 | 도구 조합이 많아 초기 선택 피로도 발생 |
현장에서 검증된 실전 팁
앱 코드와 매니페스트 저장소를 분리하라. 애플리케이션 리포와 별도로 "배포 매니페스트 전용 리포"를 두면, CI가 이미지 태그만 매니페스트 리포에 커밋하고 Argo CD가 그걸 풀하는 깔끔한 흐름이 된다.
버전은 무조건 고정하라. Argo CD 설치 매니페스트, Helm 차트, 컨테이너 이미지 모두 stable/latest 대신 구체 버전을 쓴다. GitOps의 핵심인 재현성이 여기서 갈린다.
Secret을 평문으로 Git에 올리지 마라. Sealed Secrets, External Secrets Operator, SOPS 중 하나를 반드시 끼운다. GitOps라고 비밀번호를 Git에 그대로 커밋하면 사고로 직결된다.
selfHeal과 prune은 환경별로 신중하게. prod는 켜서 drift를 막되, 처음 도입하는 클러스터에서는 수동 동기화로 며칠 관찰한 뒤 자동화를 켜는 것이 안전하다.
지원 버전 안에 머물러라. Argo CD는 분기마다 마이너 릴리스가 나오고 최신 3개 마이너만 패치를 받는다(2026년 6월 기준 3.4/3.3/3.2). EOL 버전은 보안 패치가 끊기므로 업그레이드 주기를 캘린더에 박아두자.
마무리: 누구에게 GitOps를 추천하는가
- 배포 이력 추적과 빠른 롤백이 중요한 프로덕션 Kubernetes 운영팀
- 여러 클러스터·여러 환경을 일관되게 관리해야 하는 플랫폼 엔지니어링 조직
- 수동
kubectl작업으로 인한 drift와 휴먼 에러에 시달려 본 DevOps 엔지니어 - 카나리·블루그린 같은 안전한 점진적 배포를 표준화하고 싶은 팀
- 변경에 대한 감사·승인(PR 리뷰) 절차를 배포 파이프라인에 강제하고 싶은 조직
반대로 단일 노드에서 컨테이너 한두 개만 굴리거나 팀이 1~2명이라면, GitOps의 운영 오버헤드가 이득보다 클 수 있다. 그럴 땐 단순한 CI 배포부터 시작해도 충분하다.
GitOps는 "배포를 사람이 하는 일"에서 "Git에 선언하면 시스템이 맞춰주는 일"로 바꾼다. Argo CD로 Application 하나를 자동 동기화해 보는 것에서 시작해, ApplicationSet과 Argo Rollouts로 확장해 나가면 배포가 훨씬 예측 가능하고 안전해진다. 이 글이 그 출발점이 되길 바란다.

