ArgoCD: App of Apps 패턴으로 Kubernetes 클러스터를 선언형으로 부트스트랩하는 법
ArgoCD
ArgoCD는 Kubernetes 환경에서 애플리케이션의 배포와 관리를 자동화해 주는 GitOps 도구입니다.
GitOps란 Git 저장소를 단일한 소스로 삼아, 애플리케이션의 인프라와 설정을 관리하는 방식입니다.
ArgoCD는 이러한 GitOps 방식을 바탕으로, Git에 정의된 상태와 실제 Kubernetes 클러스터의 상태를 비교하고 자동으로 동기화해주는 역할을 합니다.
기존에는 kubectl apply 명령어나 CI/CD 파이프라인을 통해 수동으로 배포를 진행하는 경우가 많았습니다.
하지만 ArgoCD를 사용하면 Git 저장소에 선언형 설정 파일만 업로드하면 되고, ArgoCD가 이를 감지하여 자동으로 배포를 진행합니다. 설정 변경 사항이 감지되면 자동으로 클러스터에 반영하거나, 수동 승인 후 동기화를 진행할 수도 있습니다.
ArgoCD와 Kubernetes의 선언형 철학
선언형(Declarative) 접근 방식이란?
선언형 접근 방식이란, 시스템이 어떤 상태가 되어야 하는지를 명시하고, 그 상태에 도달하는 방법은 시스템이 알아서 처리하도록 하는 방식입니다.
이는 명령형(Imperative) 방식과는 다릅니다. 명령형 방식은 “무엇을 할지”뿐 아니라 “어떻게 할지”도 함께 명령합니다.
예를 들어, Kubernetes에서는 아래와 같이 YAML 파일로 애플리케이션의 원하는 상태(예: 몇 개의 파드, 어떤 이미지, 어떤 포트 등)를 정의합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
...
ArgoCD의 역할: 선언형 배포 자동화
Kubernetes 자체가 선언형 기반으로 인프라를 생성할 수 있도록 설계되어 있습니다.
모든 리소스(Deployment, Service, ConfigMap 등)는 YAML 또는 JSON 형식의 선언적 설정 파일로 정의됩니다.
클러스터는 이 설정 파일을 바탕으로 리소스를 생성하고, 운영 중에도 정의된 상태와 실제 상태를 지속적으로 비교하여 차이를 조정합니다.
이러한 설계는 관리의 일관성과 안정성을 높여주며, 특히 코드 기반의 인프라 관리(Infrastructure as Code)와 호환성이 좋습니다.
ArgoCD는 이런 Kubernetes의 선언형 철학을 그대로 애플리케이션 배포에 확장한 도구입니다.
- ArgoCD는 Git에 저장된 YAML 설정 파일을 읽고, 이를 기준으로 쿠버네티스 클러스터 상태를 자동으로 동기화합니다.
- Git 저장소가 “단일 진실 공급원(Single Source of Truth)“ 가 되며, ArgoCD는 이를 기준으로 클러스터를 유지하려고 시도합니다.
- 사용자가 Git에 변경사항을 커밋하면, ArgoCD는 이를 감지하고 자동으로 클러스터 상태를 업데이트합니다. 이 과정은 Kubernetes의 컨트롤 루프(Control Loop) 개념과도 일맥상통합니다.
💡 Control Loop
쿠버네티스에서 Control Loop는 “지속적으로 현재 상태를 확인하고, 원하는 상태와 다르면 수정하는” 반복적인 제어 구조를 말합니다. 예를 들어, 사용자가 파드 개수를 3개로 정의하면, 컨트롤러는 실제 파드가 3개인지 확인하고, 부족하면 새로 생성합니다.
ArgoCD는 Kubernetes의 선언형 철학을 배포 자동화에 그대로 적용하여 GitOps 방식의 이상적인 배포 구현체 역할을 합니다.
GitOps와 Argo CD
GitOps는 "모든 인프라와 애플리케이션 배포 정의를 Git에서 관리" 하는 운영 방식입니다.
기존 CI/CD 방식보다 명확한 변경 이력, 높은 일관성, 강력한 자동화를 가능하게 합니다.
Git을 단순한 저장소가 아닌 싱글 소스 오브 트루스(Single Source of Truth)로 활용하여 쿠버네티스 리소스를 자동으로 구성합니다.
GitOps
프로젝트에 데브옵스를 적용하는 실천 방법 중 하나로 클라우드 네이티브 애플리케이션을 대상으로 한 지속적 배포(Continuous Deployment)에 초점을 맞춥니다.
이름에서 나타나듯 애플리케이션의 배포와 운영에 관련된 모든 요소를 코드화하여 깃(Git)에서 관리(Ops)하는 것이 깃옵스의 핵심입니다. 기본 개념은 코드를 이용하여 인프라를 프로비저닝 하고 관리하는 IaC(Infrastructure as Code)에서 나온 것으로 깃옵스는 이를 인프라에서 전체 애플리케이션 범위로 확장한 개념입니다.
깃옵스의 핵심적인 아이디어는 다음과 같습니다.
- 배포에 관련된 모든 것을 선언형 기술서(Declarative Descriptions) 형태로 작성하여 Config Repository(혹은 Environment Repository)에서 관리한다.
- Config Repository의 선언형 기술서와 운영 환경 간 상태 차이가 없도록 유지시켜 주는 자동화 시스템을 구성한다.
💡 단일 진실 공급원 (Single Source Of Truth, SSOT)
깃을 단일 진실 공급원으로 지정하고 오직 Git 에서만 변경되는 사항을 관리하도록 합니다.
단 하나의 진실된 공급원을 통해 사람 혹은 시스템 간의 혼선을 최소화할 수 있고, 시스템에 반영된 사항은 모두 깃에 정의된 내용임을 보장할 수 있습니다.
Argo CD 의 App of Apps 패턴
Argo CD에서 하나의 애플리케이션(Application)이 다른 여러 개의 Argo CD 애플리케이션을 정의하는 YAML 파일들을 관리하도록 구성하는 방식입니다.
해당 패턴을 사용해서 Argo CD를 구성하는 경우 Argo CD 애플리케이션들을 또 하나의 애플리케이션으로 감싸서 관리하는 구조로 사용합니다.
공식 문서에서는 해당 패턴을 Cluster bootstrapping의 대표적인 예시로 소개하고 있습니다.
cluster bootstrapping 이란 새로운 쿠버네티스 클러스터를 설정하는 경우 필요한 여러 애플리케이션을 한 번에 배포하는 것을 의미합니다.
Application 하나를 통해 여러 하위 Application 을 선언적으로 정의하고 app of apps패턴으로 관리하면, 클러스터를 빠르게 초기화할 수 있습니다. 동일한 구성을 여러 클러스터에 배포하여 동일한 리소스를 가지는 클러스터를 구축할 수 있습니다.
App of Apps 패턴 구현
예시 프로젝트 구조는 다음과 같습니다.
.
├── additional-values # 각 애플리케이션별 추가적으로 필요한 values
│ └── dev
│ ├── apache-dev-additional-values.yaml
│ └── nginx-dev-additional-values.yaml
├── applications # bootstrap root application 을 통해 배포되는 application
│ └── dev
│ ├── apache-dev.yaml
│ └── nginx-dev.yaml
├── chart-values # bootstrap root application 의 환경별 values 값
│ ├── dev.yaml
│ └── staging.yaml
├── charts # 최초 배포가 필요한 bootstrap root application
│ └── argocd-bootstrap
│ ├── Chart.yaml
│ ├── templates
│ │ └── root-app.yaml
│ └── values.yaml
├── image-values # 각 application 이 참조하는 하위 배포 이미지 버전
│ └── dev
│ ├── apache-dev-image-values.yaml
│ └── nginx-dev-image-values.yaml
배포해야하는 root application 은 helm으로 구성되어 있습니다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-{{ .Values.env.name }}
namespace: argocd
spec:
project: {{ .Values.env.project }}
source:
repoURL: {{ .Values.repoURL }}
targetRevision: main
path: applications/{{ .Values.env.name }}
destination:
server: <https://kubernetes.default.svc>
namespace: argocd
syncPolicy:
automated:
selfHeal: true
prune: true
syncPolicy와 그 하위 부분을 삭제하면 manual 하게 sync 하는 설정으로 application 이 배포됩니다.
bootstrap application 배포
위와 같은 구조에서 다음 커맨드를 통해 bootstrap application을 argocd에 배포하면 다음과 같은 구성이 자동으로 sync 됩니다.
해당 내용은 argo cd 가 k8s 클러스터에 설치되었다는 가정하에 수행합니다.
git clone https://github.com/hippo-an/argo_app_of_apps_arch.git && cd argo_app_of_apps_arch
helm upgrade --install argocd-bootstrap ./charts/argocd-bootstrap \
-f chart-values/dev.yaml \
-n argocd
bootstrapping 을 위한 root application 은 argocd namespace에 배포하였습니다.
아래와 같이 참조하는 value 파일을 변경하여 배포하면 stg, prod 용 application 에 따른 설정으로 배포할 수 있습니다.
helm upgrade --install argocd-bootstrap ./charts/argocd-bootstrap \
-f chart-values/staging.yaml \
-n argocd
bootstrap application 이 배포되면 sync Application CRD 에 구성된 내용을 바탕으로 아래와 같이 application 이 생성됩니다.
❯ k get deploy -n test-ns
NAME READY UP-TO-DATE AVAILABLE AGE
apache-dev 1/1 1 1 62s
nginx-dev 1/1 1 1 62s
삭제옵션
삭제 시 2가지 옵션이 있습니다. non cascade와 cascade입니다.
- cascade - application 삭제 시 application 에 연결된 쿠버네티스 리소스 전부 삭제
- non-cascade - application 삭제 시 쿠버네티스 리소스는 그대로 두고 application 만 삭제
cascade로 root-dev application을 삭제하는 경우 모든 application 이 함께 정리됩니다.
만약 argocd 의 finalizers 가 설정되어 있지 않는 경우에는 application 은 삭제되지만 쿠버네티스 리소스는 삭제되지 않을 수 있기 때문에 argo application의 finalizer 설정을 확인해 보고 적용해야 합니다.
예제에선 nginx-dev에 finalizers의 설정이 빠져있으며 apache-dev 에는 finalizers 설정이 되어 있습니다.
non-cascading으로 root-dev application을 삭제하는 경우 root application 만 삭제되고 root 가 배포한 application의 경우 삭제되지 않고 남아있는 걸 확인할 수 있습니다.