Table of contents
- 첫 번째 앱 등록 전에
- 샘플 매니페스트 준비
- CLI로 Application 등록
- Application CRD 구조
- Application 싱크 흐름
- 수동 싱크 vs 자동 싱크
- 싱크와 헬스 체크
- UI에서 확인
- Diff 확인과 롤백
첫 번째 앱 등록 전에
2편에서 ArgoCD를 설치하고 빈 대시보드까지 확인했다. 이제 여기에 실제 애플리케이션을 등록해볼 차례다.
ArgoCD에서 “Application”이란 하나의 Git 리포(또는 그 안의 특정 경로)와 하나의 클러스터 네임스페이스를 연결하는 단위다. “이 Git 경로에 있는 매니페스트를 저 네임스페이스에 배포해라”라고 알려주는 것과 같다.
실습을 위해 간단한 Nginx Deployment와 Service를 담은 Git 리포를 준비하자. 본인의 GitHub에 리포를 하나 만들어도 좋고, ArgoCD 공식 예제 리포를 써도 된다.
샘플 매니페스트 준비
실습용 Git 리포에 아래 두 파일을 만든다.
먼저 Deployment다. Nginx 컨테이너를 2개의 레플리카로 띄우는 단순한 구성이다.
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-demo
labels:
app: nginx-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-demo
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
다음은 Service다. Deployment의 Pod으로 트래픽을 라우팅해준다.
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-demo
spec:
selector:
app: nginx-demo
ports:
- port: 80
targetPort: 80
이 파일들을 Git 리포의 k8s/ 디렉토리에 커밋하고 푸시한다.
CLI로 Application 등록
가장 빠른 방법은 CLI다. 한 줄이면 된다.
argocd app create nginx-demo \
--repo https://github.com/<your-username>/argocd-example.git \
--path k8s \
--dest-server https://kubernetes.default.svc \
--dest-namespace default
각 플래그의 의미는 이렇다.
--repo: 매니페스트가 있는 Git 리포 URL--path: 리포 안에서 매니페스트가 위치한 디렉토리--dest-server: 배포 대상 클러스터 (in-cluster라면https://kubernetes.default.svc)--dest-namespace: 배포할 네임스페이스
등록만 했을 뿐 아직 배포는 안 됐다. ArgoCD는 기본적으로 수동 싱크 모드로 Application을 생성하기 때문에, 명시적으로 싱크를 해줘야 한다.
Application CRD 구조
CLI가 편하긴 하지만, 실무에서는 Application을 YAML로 정의하고 Git에 저장하는 것이 GitOps 철학에 맞다. Application 자체도 Kubernetes Custom Resource이기 때문이다.
아래가 위의 CLI 명령과 동일한 Application CRD다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nginx-demo
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/<your-username>/argocd-example.git
targetRevision: HEAD
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
각 필드를 뜯어보자.
metadata
name: Application 이름. ArgoCD UI와 CLI에서 이 이름으로 식별된다namespace: Application CRD 자체가 위치할 네임스페이스.argocd여야 한다
spec.project
- ArgoCD의 프로젝트. 리포/클러스터 접근 권한을 묶는 단위인데, 기본값인
default는 모든 리포와 클러스터를 허용한다
spec.source
repoURL: Git 리포 주소targetRevision: 추적할 브랜치, 태그, 또는 커밋 해시.HEAD는 기본 브랜치의 최신 커밋을 의미한다path: 리포 안에서 매니페스트 디렉토리 경로
spec.destination
server: 대상 클러스터의 API 서버 주소namespace: 리소스가 배포될 네임스페이스
spec.syncPolicy
- 이 부분이 수동 싱크와 자동 싱크를 결정하는 핵심이다. 바로 다음 섹션에서 자세히 다룬다
이 YAML을 kubectl apply로 적용하면 Application이 등록된다.
kubectl apply -f application.yaml
Application 싱크 흐름
Application이 등록되면 ArgoCD 내부에서 어떤 순서로 싱크가 일어나는지 흐름을 한눈에 보자.
sequenceDiagram
participant Git as Git Repository
participant Repo as Repo Server
participant Controller as Application Controller
participant K8s as Kubernetes Cluster
Git->>Repo: 1. Git clone / pull
Repo->>Repo: 2. 매니페스트 렌더링 (Helm, Kustomize 등)
Repo->>Controller: 3. 렌더링된 매니페스트 전달
Controller->>K8s: 4. 클러스터 현재 상태 조회
Controller->>Controller: 5. Desired vs Live 상태 비교
alt OutOfSync 감지
Controller->>K8s: 6. kubectl apply (매니페스트 적용)
K8s-->>Controller: 7. 적용 결과 반환
Controller->>Controller: 8. Health Check 수행
end
Git에서 출발해 Repo Server가 매니페스트를 준비하고, Application Controller가 클러스터 상태와 비교한 뒤 차이가 있으면 싱크를 수행한다. 이 흐름을 이해하면 수동 싱크와 자동 싱크의 차이도 자연스럽게 따라온다.
수동 싱크 vs 자동 싱크
Application을 등록할 때 syncPolicy를 어떻게 설정하느냐에 따라 동작이 완전히 달라진다.
수동 싱크
syncPolicy를 아예 빼거나 비워두면 수동 싱크 모드가 된다. Git에 변경이 생겨도 ArgoCD는 “OutOfSync” 상태만 표시하고, 실제 배포는 하지 않는다.
사용자가 직접 싱크를 트리거해야 한다.
argocd app sync nginx-demo
또는 웹 UI에서 SYNC 버튼을 누르면 된다. 프로덕션 환경에서 배포 전에 변경 내용을 확인하고 싶다면 수동 싱크가 적합하다.
자동 싱크
syncPolicy.automated를 설정하면 Git에 변경이 감지되는 즉시 자동으로 싱크한다.
syncPolicy:
automated:
prune: true
selfHeal: true
두 가지 중요한 옵션이 있다.
- prune: Git에서 삭제된 리소스를 클러스터에서도 삭제할지 여부.
false면 Git에서 매니페스트를 지워도 클러스터에 리소스가 남는다. 실무에서는true로 놓는 게 깔끔하다 - selfHeal: 누군가
kubectl edit으로 직접 수정했을 때, ArgoCD가 Git 상태로 되돌릴지 여부. GitOps의 핵심이 “Git이 진실의 원천”이니까, 이것도true가 일반적이다
자동 싱크는 개발 환경에서 특히 유용하다. 커밋만 하면 몇 초 안에 클러스터에 반영되니까 피드백 루프가 짧아진다. 프로덕션에서는 수동 싱크로 두거나, 자동 싱크에 PR 승인 게이트를 추가하는 방식을 쓰기도 한다.
싱크와 헬스 체크
싱크를 실행하면 ArgoCD가 매니페스트를 클러스터에 적용하고, 이후 헬스 체크를 수행한다.
argocd app get nginx-demo
이 명령으로 Application의 현재 상태를 확인할 수 있다. 출력에서 주목할 두 가지 상태값이 있다.
Sync Status — Git과 클러스터의 일치 여부
Synced: Git과 클러스터가 일치OutOfSync: 차이가 있음
Health Status — 리소스의 실제 동작 상태
Healthy: 모든 리소스가 정상 동작 중Progressing: 배포가 진행 중 (예: 롤링 업데이트)Degraded: 일부 리소스에 문제 발생Missing: 리소스가 클러스터에 없음
이상적인 상태는 Synced + Healthy다. Synced이지만 Degraded면 매니페스트는 적용됐지만 Pod이 제대로 뜨지 못하는 상황이니, Pod 로그를 확인해야 한다.
argocd app get nginx-demo --show-operation
--show-operation 플래그를 추가하면 마지막 싱크 작업의 상세 결과도 볼 수 있어서 디버깅에 도움이 된다.
UI에서 확인

출처: ArgoCD 공식 리포 — Apache 2.0 License
웹 UI에서 보면 훨씬 직관적이다. Application 카드를 클릭하면 리소스 트리가 나온다.
Application: nginx-demo
├── Service: nginx-demo
└── Deployment: nginx-demo
└── ReplicaSet: nginx-demo-xxx
├── Pod: nginx-demo-xxx-abc
└── Pod: nginx-demo-xxx-def
각 노드마다 싱크 상태와 헬스 상태가 색상으로 표시된다. 초록색이면 정상, 노란색이면 진행 중, 빨간색이면 문제가 있다는 뜻이다.
개별 리소스를 클릭하면 YAML 매니페스트를 볼 수 있고, Pod을 클릭하면 로그까지 확인 가능하다. kubectl을 쓰지 않고도 대부분의 디버깅을 UI에서 할 수 있다는 게 ArgoCD의 큰 장점이다.
Diff 확인과 롤백
싱크하기 전에 어떤 변경이 적용될지 미리 보고 싶다면 diff를 확인할 수 있다.
argocd app diff nginx-demo
Git의 매니페스트와 클러스터의 현재 상태를 비교해서 차이점을 보여준다. 수동 싱크 모드에서 배포 전 리뷰 용도로 유용하다.
문제가 생겨서 이전 상태로 되돌려야 할 때는 롤백을 쓴다.
argocd app history nginx-demo
이 명령으로 싱크 히스토리를 확인하고, 특정 리비전으로 롤백할 수 있다.
argocd app rollback nginx-demo <REVISION_NUMBER>
물론 GitOps 방식에서 가장 깔끔한 롤백은 Git에서 revert 커밋을 만드는 것이다. 그러면 ArgoCD가 자동으로 이전 상태로 싱크해주니까. 하지만 긴급 상황에서는 CLI 롤백이 더 빠르다.
여기까지 ArgoCD에 Application을 등록하고 싱크하는 전체 과정을 다뤘다. 다음 편에서는 실무에서 거의 필수적으로 쓰이는 Kustomize와 Helm을 ArgoCD와 함께 사용하는 방법을 살펴본다. 환경별로 매니페스트를 어떻게 분리하고 관리하는지가 핵심이다.
Loading comments...