예제로 배우는 Argo CD
2장. Argo CD 시작하기
Helm 으로 Argo CD 를 설치 및 실행하고, Helm nginx bitnami legacy 프로젝트를 서비스로 등록하여 UI 환경에서 어떤 식으로 노출되는지 살펴본다.
Argo CD 개념과 용어
Argo CD 는 지정된 Git 저장소의 파일을 지속적으로 모니터링하며, 변경 사항을 동기화한다.
이 과정에서 Argo CD 는 Git 저장소에 있는 헬름 차트를 쿠버네티스 YAML 로 렌더링하고, 클러스터와 상태를 비교하게 된다.
만약, Argo CD 는 상태가 다르다고 판단하면 자동으로 적용하거나 혹은 수동으로 kubectl API 를 통해 템플릿화된 파일로 변경한다.
용어
- 애플리케이션: App 하나를 배포하게 되면 Application 이라는 CR(Custom Resource)를 만든다.
- 애플리케이션 소스 타입: Helm, Kustomize, Jsonnet 과 같이 애플리케이션을 구축하는 데 필요한 도구
- 타깃 상태: Git 저장소에 등록된 원천 소스
- 현재 상태: 쿠버네티스 클러스터에 배포된 상태
- 동기화 상태: 현재 상태와 타깃 상태가 일치하는지 확인한다
- 동기화 동작 상태: 동기화 단계에서 작업의 성공 여부
Argo CD 아키텍처
Argo CD 의 핵심 요소들은 쿠버네티스 컨트롤러로 구성되어 있으며, 각 구성 요소가 어떤 동작을 하는지 살펴본다.
쿠버네티스 컨트롤러가 작동하는 방식
쿠버네티스 컨트롤러는 클러스터의 상태를 체크하고 변경 사항을 적용하거나 요청한다.

- API 서버: 쿠버네티스와 비슷하게 API 서버가 있으며, UI, CLI, Event, CI/CD 시스템이 다른 시스템과 통신하기 위한 서버 역할을 하며, 대표적으로 애플리케이션 관리 및 상태 보고, 트리거 작업, 깃 저장소와 클러스터 관리 등이 있다.
- 리포지토리 서버: 애플리케이션 매니페스트를 보관하는 깃 저장소의 로컬 캐시를 유지하는 역할을 한다. Argo CD 는 헬름 차트에서 YAML 매니페스트로 렌더링한다고 했는데, 이 렌더링된 파일을 보관하며 다른 컴포넌트가 매니페스트 정보를 얻기 위해 요청하는 곳이다.
- 애플리케이션 컨트롤러: 지속적으로 애플리케이션의 현재 상태를 확인하고, 깃 저장소의 변경 사항과 비교하는 역할을 한다. 만약, 동기화가 되지 않는 경우 해당 컨트롤러에서 상태를 맞추려고 한다.
동기화 원리
Argo CD 에서 동기화는 쿠버네티스 클러스터에 변경 내용을 적용하여 타깃 상태로 변경하는 것이다.
리소스 훅
Argo CD 의 동기화 과정에서 여러 동기화 단계를 거쳐 실행되는데 이를 리소스 훅이라고 부른다.
동기화 단계는 아래와 같다.
- Pre Sync: 동기화 전에 완료되어야 하는 작업을 수행할 때 사용한다. 일반적으로 DB 마이그레이션 같은 경우가 이에 속한다.
- Skip: Argo CD 애플리케이션 매니페스트가 적용되지 않고 넘어가려고 할 때 사용한다.
- Sync: 블루-그린, 카나리 배포와 같은 롤링 업데이트 전략보다 더 복잡한 배포를 하는 데 사용한다.
- Post Sync: 배포 후 통합 및 상태 확인 하는 데 주로 사용한다.
- SyncFail: 동기화 작업이 실패했을 경우 로직을 정리하거나 종료시킬 때 사용한다.
리소스 훅은 쿠버네티스 매니페스트에 적용되어, YAML 파일에 어노테이션으로 선언해야 한다.
apiVersion: batch/v1
...
metadata:
annotations:
argocd.argoproj.io/hook: PreSync
동기화 웨이브
위에서 살펴본 동기화 단계 내에서 후속 리소스가 동기화되기 전에 특정 리소스가 정상인지 확인할 수 있는 웨이브를 설정할 수 있다. 웨이브는 양수와 음수 값을 모두 가질 수 있으며, 기본값으로 0을 갖는다.
즉, 웨이브에 값을 설정하여 동기화 작업을 시작할 때 실행 순서를 재배치할 수 있다.
...
metadata:
annotations:
argocd.argoproj.io/sync-wave: "5"
3장. Argo CD 운영
Argo CD 의 고가용성 설정에 필요한 옵션은 무엇인지 살펴보고, 운영 환경에서 알림을 전송하는 과정을 설명한다.
Argo CD 모니터링 주기
Argo CD 는 기본값으로 3분마다 리포지토리를 모니터링하는 폴링 방식을 사용하여 새로운 커밋이 있는지 확인한다. 이때, 변경 사항이 감지되면 매니페스트를 다시 확인하고 클러스터에 변경 사항을 적용하는데, 이러한 이유로 Argo CD 가 자기 자신을 관리할 수 있는 매커니즘(app-of-apps 패턴)이 된다.
고가용성
API 서버
외부 통신을 담당하는 서버로, 클라이언트를 생성하거나 할 때 API 로 통신하게 되며 고가용성 매니페스트에서 2개로 설정된다.
API 는 상태를 갖지 않으므로 부하에 따라 확장하거나 축소하는 데 자유롭다.
리포지토리 서버
클러스터에 적용할 최종 매니페스트 파일을 생성하는 역할을 하며, 고가용성 매니페스트에서 2개의 레플리카로 설정된다.
리포지토리 서버는 깃 리포지터리의 내용을 가져와 헬름, 커스터마이즈 등 템플릿 엔진을 무엇을 사용할지 판단하고, 최종 형태의 매니페스트를 생성한다.
이 리포지토리 서버는 많은 일을 수행하는데, 이 과정에서 메모리 부족이나 CPU 스로틀링으로 인해 컨테이너가 종료되지 않도록 충분한 리소스를 제공해줘야 한다.
리포지토리 서버 성능 이야기
헬름 v2 → 헬름 v3 로 마이그레이션 했을 때, 매니페스트 생성 시간이 크게 단축된다.
애플리케이션 컨트롤러
작업에 의해 코드 변경 사항이 감지되면 애플리케이션 동기화를 발생시키고, 고가용성 매니페스트에서는 하나의 컨트롤러로 설정된다.
컨트롤러의 개수를 늘리는 것이 고가용성 설치에 필수적인 요소는 아니지만, 분명 도움이 되는데 그 이유는 하나의 컨트롤러에 문제가 생기면 오직 그 클러스터에만 영향이 가고, 전체 클러스터가 멈추지 않기 때문이다.
--operation-processors, --status-processors, --kubectl-parallelism-limit 플래그를 확인하고 이 값들을 높게 설정해 인스턴스가 더 많은 애플리케이션을 처리할 수 있도록 최적화해야 한다.
레디스 캐시
매니페스트 생성이 무거운 작업이기 때문에 레디스에 매니페스트를 저장해두며, 고가용성 설정에서는 HAProxy 디플로이먼트와 레디스 레플리카를 3개로 설정한다.
레디스가 없다면 매 동기화 요청마다 매니페스트를 다시 만들어야 한다.
고가용성 설치는 레디스용 레플리카 3개를 가진 StatefulSet 으로 구성하고, 레디스 앞에 HAProxy 디플로이먼트를 두는 것이다.
- 마스터 레디스에 장애가 난 경우 슬레이브 중 하나가 새로운 마스터로 승격되고,
HAProxy는 이 내용을 클라이언트 애플리케이션에게 전달한다.
프로메테우스로 관찰하기
Argo CD 를 관측하기 위해서 애플리케이션 컨트롤러, API 서버, 리포지토리 서버의 지표를 스크랩해야 한다.
가장 중요하게 모니터링해야 할 대상
Argo CD 는 동기화를 수행하기 위해 리포지터리 서버와 컨트롤러를 사용하는데, 이 둘이 가장 중요하게 모니터링해야 할 대상이 된다.
OOM Killed
노드 운영체제에서 컨테이너가 너무 많은 리소스를 사용하려고 할 때 발생하는 것이 메모리 부족 현상이다.
컨테이너에 요청 리소스만큼 사용하다가 최대 리소스를 사용하려고 할 때 노드에 가용 자원이 부족한 경우 발생한다.
- 리포지토리 서버: 동시에 너무 많은 매니페스트가 생성되는 경우
- 애플리케이션 컨트롤러: 동시에 너무 많은 매니페스트가 적용되는 경우
sum by (pod, container, namespace)
(kube_pod_container_status_last_terminated_reason{reason="OOMKilled"}) *
on (pod, container) group_left sum by (pod, container)
(changes(kube_pod_container_status_restarts_total[5m])) > 0
이 쿼리는 지난 5분 동안 컨테이너가 다시 시작됐거나 마지막으로 종료된 이유가 OOMKilled 인지 조회하는 쿼리이다.
만약, 해당 쿼리를 통해 일주일에 한두 번 정도 알람을 받는다면 아직 지켜봐도 괜찮은 단계이고 하루에 두 번 이상 발생한다면 조치를 취해야 하는 수준이다.
조치 방법
- Deployment, StatefulSet 은 replicas 숫자를 증가시켜, 리소스를 많이 사용할 때 분산 처리할 수 있도록 유도한다.
- 컨테이너의 CPU 와 메모리 리소스를 더 높게 할당한다.
- 리포지토리 서버의
--parallelismlimit, 컨트롤러의--kubectl-parallelism-limit매개변수 값을 줄인다.
시스템 부하 메트릭
리포지토리 서버는 깃 리포지토리에서 컨텐츠를 가져온 다음 사용된 템플릿 엔진(Helm, Kustomize)을 기반으로 매니페스트를 생성한다.
최종 매니페스트를 생성한 후 애플리케이션 컨트롤러로 전달하는데, 수많은 매니페스트가 동시에 적용될 때 OOM 이슈가 발생된다.
깃 리포지터리의 컨텐츠를 가져오는 요청이 많은 경우는 어떨까?
이 경우, 컨텐츠를 가져오기 위해 대기 중인 요청 수에 따라 변동되는 옵션인 argocd_repo_pending_request_total 을 통해 현재 리포지토리 인스턴스가 얼만큼의 작업 부하를 처리할 수 있는지 나타낸다.
다음으로는 애플리케이션 컨트롤러에서 시스템 부하를 나타내는 메트릭인 argocd_kubectl_exec_pending 값이 있으며, 이 값은 클러스터에서 실행 대기 중인 상태의 apply 와 auth 명령의 수를 나타낸다.
마이크로서비스 팀을 위한 메트릭
- 애플리케이션의 동기화 상태: 깃허브의 변경 이력과 Argo CD 애플리케이션의 매니페스트와 일치하는지를 확인하며, 새로운 버전의 도커 이미지나 매니페스트에 변경 사항이 생겼을 때 동기화가 실패하는 경우 알림 발송
- 애플리케이션 헬스 상태: Argo CD 애플리케이션이 정상적으로 동작하고 있는지에 대한 상태이며, Degraded 상태는 제대로 동작하지 않을 때 발생한다.