
쿠버네티스 환경에서 애플리케이션을 운영하다 보면 개발, 스테이징, 프로덕션 등 여러 환경 간의 구성이 달라지는 '구성 드리프트(Configuration Drift)' 문제를 겪게 된다. 이를 해결하기 위해 등장한 GitOps 와 이를 쿠버네티스에서 효과적으로 구현해주는 도구인 Argo CD에 대해 알아본다.
GitOps는 버전 제어 시스템(Git)과 CI/CD를 인프라 자동화에 적용하는 방법론이다. 간단히 말해, Git Repository를 단일 진실 공급원(Single Source of Truth)으로 삼고, Pull Request를 통해 인프라와 애플리케이션 배포를 관리하는 운영 모델이다.
GitOps는 다음과 같은 네 가지 핵심 원칙을 기반으로 동작한다.
선언적 구성 (Declarative Configuration)
시스템이 '어떻게' 동작해야 하는지에 대한 구체적인 명령이 아닌, '무엇을' 원하는지에 대한 의도된 상태(Desired State)를 선언적으로 명시한다.
예를 들어, "컨테이너를 3개 만들어라"라고 명령하는 것이 아니라, "컨테이너의 개수는 3개여야 한다"라고 선언하면, 소프트웨어 에이전트가 현재 상태를 파악하고 3개로 맞춰주는 방식이다.
버전이 제어되는 불변적 저장소 (Version Controlled & Immutable)
자동화된 배포 (Automated Deployment)
소프트웨어 에이전트 (Software Agents)
쿠버네티스는 그 자체로 선언적 API를 기반으로 설계되었기 때문에 GitOps와 매우 잘 맞는다. 쿠버네티스는 모든 리소스의 상태를 데이터베이스(etcd)에 저장하고, REST API를 통해 이 상태를 관리한다. 사용자가 YAML 파일에 원하는 상태를 선언하여 API 서버에 전달하면, 컨트롤러가 현재 상태와 비교하여 원하는 상태로 맞춰준다. 이는 GitOps의 원칙과 정확히 일치한다.
명령형(Imperative) API: '어떻게' 할 것인지 직접 명령한다.
kubectl create namespace test-namespace: test-namespace를 생성하라는 직접적인 명령이다.
kubectl create -f namespace.yaml: 구성 파일을 사용하더라도, '생성'이라는 행위를 직접 명령한다.
선언형(Declarative) API: '무엇을' 원하는지 상태를 선언한다.
kubectl apply -f namespace.yaml: 구성 파일에 정의된 상태를 클러스터에 적용한다. 쿠버네티스는 이전 상태와 비교하여 변경된 내용만 지능적으로 적용하므로, 반복적으로 실행해도 안전하다. Argo CD는 바로 이 apply 방식을 사용한다.Argo CD는 쿠버네티스를 위한 선언적인 GitOps 지속적 배포(CD) 도구이다. Git Repository를 단일 진실 공급원으로 사용하여 애플리케이션의 배포 및 라이프사이클 관리를 자동화한다.
Argo CD의 애플리케이션 컨트롤러는 운영 중인 애플리케이션의 현재 상태(Live State)와 Git Repository에 정의된 목표 상태(Target State)를 지속적으로 비교한다. 만약 두 상태가 일치하지 않으면, Git Repository의 내용을 기준으로 클러스터의 상태를 자동으로 동기화하여 드리프트를 방지한다.
주요 사용 사례
배포 자동화: Git Commit, Pull Request Merge, CI 파이프라인 완료 등 다양한 트리거를 통해 배포를 자동화한다.
관찰 가능성: UI와 CLI를 통해 애플리케이션의 동기화 상태와 운영 상태를 쉽게 파악할 수 있다. Argo CD Notification 엔진을 통해 변경 사항에 대한 알림을 받을 수 있다.
멀티테넌시: RBAC 정책을 통해 여러 팀과 여러 클러스터를 안전하게 관리하고 배포할 수 있다.
Argo Project 도구들
Argo CD: GitOps 기반의 지속적 배포 도구
Argo Rollouts: 카나리, 블루그린 등 점진적 배포 전략을 제공하는 컨트롤러
Argo Events: 이벤트 기반의 워크플로우 자동화 프레임워크
Argo Workflows: 쿠버네티스 네이티브 컨테이너 워크플로우 엔진
Application: 배포할 쿠버네티스 리소스들의 논리적인 그룹.
Source: 애플리케이션의 목표 상태가 정의된 위치 (예: Git Repository). Helm, Kustomize 등 다양한 타입을 지원한다.
Target State: 애플리케이션이 도달해야 할 의도된 상태. 즉, Git Repository에 정의된 상태를 의미한다.
Live State: 현재 쿠버네티스 클러스터에 배포되어 운영 중인 애플리케이션의 실제 상태.
Sync Status: Target State와 Live State가 일치하는지 여부를 나타내는 상태 (Synced / OutOfSync).
Sync: Live State를 Target State와 일치시키는 과정. kubectl apply를 통해 변경 사항을 클러스터에 적용한다.
Refresh: Git Repository의 최신 코드를 가져와 Target State와 Live State의 차이점을 다시 비교하는 과정.
API Server: 웹 UI, CLI, CI/CD 시스템 등 외부 시스템과의 상호작용을 위한 gRPC/REST API를 제공한다.
Repository Server: Git Repository의 로컬 캐시를 유지하며, Helm/Kustomize와 같은 매니페스트를 쿠버네티스 YAML로 렌더링하는 역할을 한다.
Application Controller: 애플리케이션의 상태를 지속적으로 모니터링하고, Live State와 Target State를 비교하여 Sync Status를 결정한다. 동기화가 필요할 경우 Sync 작업을 실행한다.
Argo CD는 자체적인 CRD(Custom Resource Definition)를 사용하여 GitOps 파이프라인을 정의한다.
Application: 배포할 애플리케이션의 인스턴스를 정의한다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/argoproj/argocd-example-apps.git
targetRevision: HEAD
path: guestbook
destination:
server: https://kubernetes.default.svc
namespace: guestbook
AppProject: 애플리케이션을 논리적으로 그룹화하고, 배포 가능한 Repository, 클러스터, 네임스페이스 등을 제한하여 멀티테넌시 환경을 구축하는 데 사용된다.
Repository & Cluster Credentials: Private Repository나 외부 클러스터에 접근하기 위한 자격 증명은 쿠버네티스 Secret을 통해 관리된다.
1. Argo CD Helm 저장소 추가 및 설치
# Helm 저장소 추가
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
# argocd 네임스페이스 생성
kubectl create namespace argocd
# Helm으로 설치
helm install argocd argo/argo-cd -n argocd
2. Argo CD UI 접속
기본적으로 ClusterIP 타입의 서비스로 생성되므로, 외부 접속을 위해 타입을 변경하거나 포트포워딩을 사용한다.
# 서비스를 NodePort 타입으로 변경 (EC2 환경 등)
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "NodePort"}}'
# 또는 포트포워딩 사용
# kubectl port-forward svc/argocd-server -n argocd 8080:443
3. 초기 비밀번호 확인
admin 계정의 초기 비밀번호는 시크릿에 저장되어 있다.
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
4. Nginx 애플리케이션 배포 (YAML 방식)
아래 내용으로 nginx-app.yaml 파일을 생성한다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nginx
namespace: argocd
spec:
project: default
source:
repoURL: https://charts.bitnami.com/bitnami
chart: nginx
targetRevision: 15.4.2 # 예시 버전
destination:
server: https://kubernetes.default.svc
namespace: nginx
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
# YAML 파일로 애플리케이션 배포
kubectl apply -f nginx-app.yaml
5. Nginx 애플리케이션 배포 (CLI 방식)
# Argo CD 서버에 로그인
argocd login <ARGO_CD_SERVER_IP:PORT>
# CLI 명령어로 애플리케이션 생성
argocd app create nginx \
--repo https://charts.bitnami.com/bitnami \
--helm-chart nginx \
--revision 15.4.2 \
--dest-server https://kubernetes.default.svc \
--dest-namespace nginx
실제 운영 환경에서는 Argo CD 자체의 안정성과 확장성을 확보하는 것이 중요하다.
Argo CD가 다른 애플리케이션을 관리하듯, 자기 자신도 Git Repository를 통해 관리(Self-Managed)할 수 있다. 이를 위해 Kustomize 를 사용한다.
1. Git Repository 구성
GitHub에 Argo CD 설정을 관리할 Repository를 생성한다.
kustomize-argocd/
├── resources/
│ └── namespace.yaml
└── kustomization.yaml
2. Kustomize 파일 작성
kustomization.yaml에 Argo CD 공식 매니페스트를 base로 지정하고, 커스텀 설정을 추가한다.
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: argocd
bases:
- github.com/argoproj/argo-cd/manifests/ha/cluster-install?ref=v2.8.4 # 버전 명시
resources:
- resources/namespace.yaml
3. 설정 변경 (Reconciliation 주기 조정)
Argo CD가 Git 변경을 확인하는 주기는 기본 180초이다. 이 값을 변경하려면 ConfigMap 패치를 사용한다.
patches/argocd-cm.yaml 파일 생성
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
data:
timeout.reconciliation: 300s
kustomization.yaml 에 패치 추가
# kustomization.yaml
...
patchesStrategicMerge:
- patches/argocd-cm.yaml
대규모 환경에서는 각 컴포넌트의 복제본(replica) 수를 늘려 고가용성을 확보해야 한다.
API Server: 상태를 갖지 않으므로 replicas 수를 늘려 부하를 분산한다.
Repository Server: Git에서 매니페스트를 렌더링하는 역할을 하므로, 많은 애플리케이션을 관리할수록 리소스와 복제본 수가 많이 필요하다. ARGOCD_EXEC_TIMEOUT 환경 변수로 템플릿 생성 시간 초과를 조절할 수 있다.
Application Controller: 여러 클러스터를 관리할 경우, 샤딩(sharding)을 통해 각 컨트롤러가 특정 클러스터를 담당하도록 부하를 분산한다.
Kustomize 패치를 통해 각 Deployment/StatefulSet의 replicas를 3개 이상으로 설정하여 HA를 구성할 수 있다.
# patches/argocd-server-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: argocd-server
spec:
replicas: 3
Redis Cache: Redis는 생성된 매니페스트를 캐싱하여 성능을 향상시킨다. 필수는 아니지만 운영 환경에서는 성능 저하를 막기 위해 고가용성 구성으로 사용하는 것을 강력히 권장한다.
Prometheus를 사용하여 Argo CD의 주요 메트릭을 수집하고 모니터링할 수 있다.
ServiceMonitor 리소스를 생성하여 Prometheus가 Application Controller, API Server, Repository Server의 메트릭 엔드포인트를 수집하도록 설정한다.주요 모니터링 메트릭
운영팀: OOMKilled (메모리 부족), 시스템 부하, 각 컴포넌트의 리소스 사용량 등
마이크로서비스팀: 애플리케이션 동기화 상태 (argocd_app_info), 운영 상태(argocd_app_health_status) 등
Argo CD Notifications를 설치하면 애플리케이션 상태 변경(예: 동기화 성공/실패)에 대한 알림을 이메일, Slack 등 다양한 채널로 받을 수 있다.