ArgoCD를 활용한 Kubernetes GitOps 기반 CD 구현 가이드: Docker, CI/CD 자동화
GitOps 원칙을 따르는 ArgoCD를 사용하여 Kubernetes 환경에서 효율적인 지속적 배포(CD)를 구현하는 방법을 소개합니다. Docker 이미지 빌드부터 배포 자동화까지 DevOps 엔지니어링 관점에서 상세히 설명합니다.
ArgoCD를 활용한 Kubernetes GitOps 기반 CD 구현 가이드: Docker, CI/CD 자동화
현대의 클라우드 네이티브 환경에서 애플리케이션을 안정적이고 효율적으로 배포하는 것은 DevOps 엔지니어링의 핵심 과제입니다. 특히 Kubernetes를 기반으로 하는 환경에서는 복잡한 배포 프로세스를 자동화하고 관리하기 위한 효과적인 전략이 필수적입니다. 이 글에서는 GitOps 원칙을 따르는 강력한 지속적 배포(CD) 도구인 ArgoCD를 활용하여 Kubernetes 환경에서 배포를 자동화하는 방법에 대해 심층적으로 다루고자 합니다.
GitOps와 ArgoCD의 등장 배경
전통적인 CI/CD 파이프라인은 빌드, 테스트, 배포 단계를 거치며, 배포 단계에서는 스크립트나 명령어를 통해 직접 Kubernetes 클러스터에 변경 사항을 적용하는 경우가 많았습니다. 이러한 방식은 배포 이력 관리가 어렵고, 수동 작업으로 인한 휴먼 에러 발생 가능성이 높으며, 클러스터의 실제 상태와 코드 저장소의 상태 간 불일치(Drift)를 파악하기 어렵다는 단점이 있었습니다.
이러한 문제점을 해결하기 위해 등장한 개념이 바로 GitOps입니다. GitOps는 Git 저장소를 "진실의 원천(Single Source of Truth)"으로 삼아 인프라와 애플리케이션의 선언적 상태를 관리하는 운영 모델입니다. 모든 변경 사항은 Git을 통해 이루어지며, 자동화된 에이전트가 Git 저장소의 상태와 클러스터의 실제 상태를 지속적으로 동기화합니다.
ArgoCD는 이러한 GitOps 원칙을 Kubernetes 환경에서 구현하기 위한 대표적인 오픈소스 CD 도구입니다. ArgoCD는 다음과 같은 주요 특징을 통해 GitOps 기반의 효율적인 배포를 가능하게 합니다.
- 선언적(Declarative): Kubernetes manifests, Helm charts, Kustomize 파일 등 Git 저장소에 정의된 선언적 상태를 기반으로 배포합니다.
- 자동 동기화(Automated Synchronization): Git 저장소의 변경 사항을 감지하고 Kubernetes 클러스터에 자동으로 동기화하여 배포를 자동화합니다.
- 드리프트 감지(Drift Detection): 클러스터의 실제 상태가 Git 저장소에 정의된 상태와 다를 경우 이를 감지하고 시각적으로 보여줍니다.
- 롤백(Rollback): Git 커밋 이력을 기반으로 쉽고 빠르게 이전 상태로 롤백할 수 있습니다.
- 직관적인 UI: 배포 상태, 동기화 이력, 리소스 상태 등을 한눈에 파악할 수 있는 웹 UI를 제공합니다.
ArgoCD 설치 및 기본 설정
ArgoCD를 Kubernetes 클러스터에 설치하는 과정은 매우 간단합니다. 다음 단계를 따라 ArgoCD를 설치하고 초기 설정을 완료할 수 있습니다.
1. ArgoCD CLI 설치
ArgoCD를 관리하기 위한 argocd CLI 도구를 설치합니다. Linux 환경에서는 다음과 같이 설치할 수 있습니다.
# Linux
curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argocd/releases/latest/download/argocd-linux-amd64
chmod +x /usr/local/bin/argocd
# macOS (Homebrew 사용)
brew install argocd
2. ArgoCD 서버 배포
ArgoCD는 자체 컨트롤러와 API 서버를 포함하는 여러 Kubernetes 리소스들로 구성됩니다. 이를 배포하기 위해 install.yaml 파일을 kubectl로 적용합니다.
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argocd/stable/manifests/install.yaml
배포가 완료되면 argocd 네임스페이스에 ArgoCD 관련 파드들이 실행되는 것을 확인할 수 있습니다.
kubectl get pods -n argocd
3. ArgoCD UI 접속
ArgoCD UI에 접속하기 위한 방법은 여러 가지가 있지만, 가장 간단한 방법은 kubectl port-forward를 사용하는 것입니다.
kubectl port-forward svc/argocd-server -n argocd 8080:443
이제 웹 브라우저에서 https://localhost:8080으로 접속할 수 있습니다. 초기 로그인 시 사용자명은 admin이며, 초기 비밀번호는 argocd-initial-admin-secret 시크릿에 저장되어 있습니다.
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
초기 로그인 후에는 보안을 위해 비밀번호를 변경하는 것이 좋습니다.
argocd login localhost:8080
argocd account update-password
Application 생성 및 Git Repository 연동
ArgoCD에서 배포 단위는 Application입니다. Application은 Git 저장소의 특정 경로에 있는 Kubernetes manifests(혹은 Helm chart, Kustomize 파일)를 Kubernetes 클러스터의 특정 대상으로 배포하도록 정의합니다.
1. Git Repository 등록
ArgoCD에 배포할 Kubernetes manifests가 저장된 Git repository를 등록해야 합니다.
argocd repo add https://github.com/your-org/your-repo.git --username <username> --password <password>
# 또는 SSH 키 사용
# argocd repo add git@github.com:your-org/your-repo.git --ssh-private-key-path ~/.ssh/id_rsa
2. 샘플 애플리케이션 Manifest 준비
예를 들어, guestbook이라는 간단한 Nginx 애플리케이션을 배포한다고 가정하고, 다음과 같은 manifest 파일을 Git 저장소에 준비합니다.
# my-app/guestbook/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: guestbook-ui
spec:
selector:
matchLabels:
app: guestbook-ui
replicas: 1
template:
metadata:
labels:
app: guestbook-ui
spec:
containers:
- name: guestbook-ui
image: gcr.io/google-samples/node-hello:1.0
ports:
- containerPort: 80
# my-app/guestbook/service.yaml
apiVersion: v1
kind: Service
metadata:
name: guestbook-ui
spec:
ports:
- port: 80
targetPort: 80
selector:
app: guestbook-ui
type: LoadBalancer
이 파일들을 Git 저장소의 my-app/guestbook 경로에 커밋하고 푸시합니다.
3. ArgoCD Application 생성
이제 ArgoCD UI 또는 argocd CLI를 사용하여 Application을 생성합니다. CLI를 사용하는 예시는 다음과 같습니다.
argocd app create guestbook-app \
--repo https://github.com/your-org/your-repo.git \
--path my-app/guestbook \
--dest-server https://kubernetes.default.svc \
--dest-namespace default \
--sync-policy automated \
--self-heal \
--prune
-
--repo: Git 저장소 URL -
--path: Git 저장소 내 Kubernetes manifests 경로 -
--dest-server: 배포할 Kubernetes 클러스터의 API 서버 URL (인클러스터 배포 시https://kubernetes.default.svc) -
--dest-namespace: 배포할 네임스페이스 -
--sync-policy automated: 자동 동기화 활성화 -
--self-heal: 클러스터의 실제 상태가 Git 상태와 다를 경우 자동으로 복구 -
--prune: Git에 없는 리소스를 클러스터에서 삭제
Application이 생성되면 ArgoCD UI에서 guestbook-app이 Healthy하고 Synced 상태로 전환되는 것을 확인할 수 있습니다.
자동 동기화 (Automated Synchronization) 및 드리프트 감지
ArgoCD의 핵심 기능 중 하나는 Git 저장소와 Kubernetes 클러스터 간의 지속적인 상태 동기화입니다. Application 생성 시 sync-policy를 설정하여 이 동작을 제어할 수 있습니다.
Sync Policy 옵션
spec.syncPolicy 필드를 통해 다음과 같은 동기화 옵션을 설정할 수 있습니다.
-
automated: Git 저장소에 변경 사항이 푸시되면 ArgoCD가 이를 감지하고 자동으로 클러스터에 동기화합니다.-
prune: true: Git 저장소에 더 이상 존재하지 않는 리소스를 클러스터에서 자동으로 삭제합니다. -
selfHeal: true: 클러스터의 실제 상태가 Git 저장소의 선언적 상태와 다를 경우, ArgoCD가 자동으로 Git 상태로 복구합니다. 이는 무단 변경이나 장애로 인한 드리프트를 자동으로 해결하는 데 유용합니다.
-
-
manual: Git 저장소에 변경 사항이 있어도 자동으로 동기화되지 않고, 사용자가 직접 UI 또는 CLI를 통해 동기화를 시작해야 합니다.
예시 Application YAML 정의:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook-app
namespace: argocd
spec:
destination:
namespace: default
server: https://kubernetes.default.svc
project: default
source:
path: my-app/guestbook
repoURL: https://github.com/your-org/your-repo.git
targetRevision: HEAD
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true # 대상 네임스페이스가 없으면 생성
드리프트 감지 (Drift Detection)
ArgoCD는 Git 저장소의 선언적 상태와 Kubernetes 클러스터의 실제 상태를 지속적으로 비교하여 불일치(Drift)를 감지합니다. 예를 들어, kubectl edit 명령어를 사용하여 guestbook-ui Deployment의 replicas 수를 1에서 2로 변경하면, ArgoCD UI에서 guestbook-app이 OutOfSync 상태로 변경되고, 어떤 리소스가 어떤 부분에서 드리프트가 발생했는지 상세하게 보여줍니다.
selfHeal: true로 설정되어 있다면, ArgoCD는 일정 시간 후 자동으로 replicas 수를 다시 1로 되돌려 Git 저장소의 상태와 일치시킵니다. 이는 클러스터의 무결성을 유지하는 데 매우 중요한 기능입니다.
Helm Charts 및 Kustomize 연동
실제 운영 환경에서는 단순한 YAML manifest 파일보다는 Helm Charts나 Kustomize와 같은 템플릿/설정 관리 도구를 사용하는 경우가 많습니다. ArgoCD는 이들 도구와 완벽하게 통합됩니다.
Helm Charts 연동
Helm chart를 사용하는 Application을 생성할 때는 source 필드에 chart와 targetRevision (chart 버전), 그리고 필요한 경우 helm.values를 지정합니다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-helm-app
namespace: argocd
spec:
destination:
namespace: my-namespace
server: https://kubernetes.default.svc
project: default
source:
repoURL: https://charts.bitnami.com/bitnami # 또는 Git 저장소 URL
chart: nginx
targetRevision: 13.2.14
helm:
values: |
service:
type: ClusterIP
ingress:
enabled: false
syncPolicy:
automated:
prune: true
selfHeal: true
Git 저장소에 직접 Helm chart를 포함시키고 배포할 수도 있습니다. 이 경우 source.repoURL은 Git 저장소 URL이 되고, source.path는 Git 저장소 내 Helm chart 디렉토리가 됩니다.
Kustomize 연동
Kustomize는 Kubernetes manifest를 템플릿화하지 않고 'overlay' 방식으로 커스터마이징하는 도구입니다. ArgoCD는 Kustomize도 지원합니다. source 필드에 kustomize 섹션을 추가하면 됩니다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-kustomize-app
namespace: argocd
spec:
destination:
namespace: my-namespace
server: https://kubernetes.default.svc
project: default
source:
repoURL: https://github.com/your-org/your-repo.git
path: my-app/kustomize-base/overlays/production # Kustomize base와 overlay 경로
targetRevision: HEAD
syncPolicy:
automated:
prune: true
selfHeal: true
Git 저장소 구조는 다음과 같을 수 있습니다.
your-repo/
├── my-app/
│ └── kustomize-base/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
│ └── kustomize-base/overlays/
│ ├── production/
│ │ └── kustomization.yaml
│ └── staging/
│ └── kustomization.yaml
이처럼 ArgoCD는 다양한 Kubernetes 설정 관리 도구와 유연하게 통합되어 복잡한 배포 시나리오를 지원합니다.
CI 파이프라인과 ArgoCD 통합 (Docker 이미지 업데이트)
ArgoCD는 CD(Continuous Delivery/Deployment) 도구이며, CI(Continuous Integration) 파이프라인과는 역할이 분리됩니다. CI 파이프라인은 코드 빌드, 테스트, Docker 이미지 생성 및 이미지 레지스트리 푸시를 담당하고, ArgoCD는 CI 파이프라인의 결과물(새로운 Docker 이미지 태그)이 반영된 Git 저장소의 Kubernetes manifests를 감지하여 배포를 수행합니다.
일반적인 CI/CD 워크플로우는 다음과 같습니다.
- 개발자 코드 커밋: 개발자가 애플리케이션 코드를 Git 저장소(예: GitHub, GitLab)에 커밋합니다.
- CI 파이프라인 트리거: Git 커밋 이벤트가 Jenkins, GitHub Actions, GitLab CI 등의 CI 파이프라인을 트리거합니다.
- 코드 빌드 및 테스트: CI 파이프라인은 코드를 빌드하고 유닛/통합 테스트를 실행합니다.
- Docker 이미지 빌드: 테스트를 통과하면 애플리케이션의 Docker 이미지를 빌드합니다.
- Docker 이미지 푸시: 빌드된 Docker 이미지를 Docker Hub, GCR, ECR 등의 컨테이너 이미지 레지스트리에 푸시합니다. 이때 이미지 태그는
latest대신git-commit-sha또는버전등 고유한 값으로 지정하는 것이 좋습니다. - Kubernetes Manifest 업데이트: CI 파이프라인은 배포에 사용될 Kubernetes manifests가 저장된 별도의 GitOps 저장소를 클론하고, 여기에 새로운 Docker 이미지 태그를 반영하여 manifest 파일을 업데이트한 후 다시 GitOps 저장소에 커밋하고 푸시합니다.
- Kustomize를 사용하면 이미지 태그 업데이트가 매우 간편합니다.
- ArgoCD 감지 및 배포: ArgoCD는 GitOps 저장소의 변경 사항(새로운 이미지 태그가 반영된 manifest)을 감지하고, 이를 Kubernetes 클러스터에 자동으로 동기화하여 새로운 버전의 애플리케이션을 배포합니다.
Kustomize를 이용한 Docker 이미지 태그 업데이트 예시
GitOps 저장소에 다음과 같은 Kustomize 설정이 있다고 가정합니다.
# gitops-repo/environments/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
images:
- name: my-app-image # base/deployment.yaml에 정의된 이미지 이름
newTag: v1.0.0 # CI 파이프라인이 업데이트할 태그
base 디렉토리에는 my-app-image를 사용하는 deployment.yaml이 있습니다.
# gitops-repo/base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-image # Kustomize images 필드에서 참조하는 이름
image: your-registry/my-app:latest # 초기 이미지, Kustomize가 newTag로 변경
ports:
- containerPort: 8080
CI 파이프라인에서 Docker 이미지를 빌드하고 v1.0.1 태그로 푸시한 후, gitops-repo/environments/production/kustomization.yaml 파일을 다음과 같이 업데이트하고 커밋합니다.
# CI 파이프라인 스크립트 예시
NEW_IMAGE_TAG="v1.0.1" # CI 빌드 결과로 얻은 태그
GIT_OPS_REPO_PATH="/tmp/gitops-repo" # GitOps 저장소를 클론한 경로
git clone git@github.com:your-org/gitops-repo.git $GIT_OPS_REPO_PATH
cd $GIT_OPS_REPO_PATH
# Kustomize 설정 파일 업데이트
yq e '.images[0].newTag = "'$NEW_IMAGE_TAG'"' -i environments/production/kustomization.yaml
git add environments/production/kustomization.yaml
git commit -m "Update my-app image to $NEW_IMAGE_TAG"
git push origin main
이 커밋이 GitOps 저장소에 푸시되면, ArgoCD는 이를 감지하고 my-app Application을 v1.0.1 이미지로 자동으로 업데이트합니다. 이로써 CI와 CD가 Git을 통해 완벽하게 분리되고 자동화된 워크플로우가 구축됩니다.
ArgoCD 고급 기능 및 고려사항
1. Multi-cluster 배포
ArgoCD는 여러 Kubernetes 클러스터에 애플리케이션을 배포할 수 있도록 지원합니다. ArgoCD에 다른 클러스터들을 등록하고, 각 Application이 배포될 dest-server를 해당 클러스터의 API 서버 URL로 지정하면 됩니다.
argocd cluster add <CONTEXT_NAME> --name <CLUSTER_NAME>
# 예: argocd cluster add dev-cluster --name dev
2. 리소스 훅 (Resource Hooks)
배포 전/중/후에 특정 작업을 수행해야 할 때 ArgoCD 리소스 훅을 사용할 수 있습니다. 예를 들어, 데이터베이스 마이그레이션 작업을 배포 전에 실행하거나, 배포 후 캐시를 비우는 작업을 수행할 수 있습니다.
apiVersion: batch/v1
kind: Job
metadata:
name: database-migration
annotations:
argocd.argoproj.io/hook: PreSync # PreSync 훅으로 지정
argocd.argoproj.io/hook-delete-policy: HookSucceeded # 성공 시 Job 삭제
spec:
template:
spec:
containers:
- name: migration
image: my-app-migrator:latest
restartPolicy: Never
3. Role-Based Access Control (RBAC)
ArgoCD는 자체 RBAC 시스템을 제공하여, 누가 어떤 Application에 접근하고 어떤 작업을 수행할 수 있는지 세밀하게 제어할 수 있습니다. argocd-cm ConfigMap을 수정하여 사용자 역할을 정의하고, Kubernetes RBAC과 연동하여 통합 인증을 구성할 수 있습니다.
4. 보안 고려사항
- 시크릿 관리: 민감한 정보(예: 데이터베이스 비밀번호)는 Kubernetes Secret을 사용하고, Git 저장소에는 직접 노출하지 않도록 합니다. Git 저장소에 Secret을 관리해야 한다면 SOPS (Secrets OPerationS)와 같은 도구를 사용하여 암호화하는 것을 고려할 수 있습니다.
- 권한 최소화: ArgoCD 컨트롤러에 필요한 Kubernetes 클러스터 권한을 최소화합니다.
- Git Webhook 보안: Git 저장소에서 ArgoCD로의 Webhook 통신 시 시크릿 토큰을 사용하여 요청을 검증합니다.
마무리
ArgoCD는 GitOps 철학을 Kubernetes 환경에서 완벽하게 구현할 수 있도록 돕는 강력한 지속적 배포 도구입니다. Git을 진실의 원천으로 삼아 인프라와 애플리케이션의 상태를 선언적으로 관리하고, 자동 동기화 및 드리프트 감지 기능을 통해 배포의 안정성과 신뢰성을 크게 향상시킬 수 있습니다. Docker 이미지 빌드부터 CI 파이프라인과의 연동, 그리고 최종 Kubernetes 클러스터 배포에 이르는 모든 과정을 Git 중심의 자동화된 방식으로 전환함으로써, DevOps 엔지니어링 팀은 더욱 효율적이고 견고한 배포 시스템을 구축할 수 있을 것입니다.
관련 게시글
GitOps Workflow 설계 가이드: Kubernetes와 CI/CD를 활용한 자동화
GitOps는 선언적 인프라 및 애플리케이션 관리를 위한 강력한 패러다임입니다. 이 가이드에서는 Git을 Single Source of Truth로 활용하여 Kubernetes 환경에서 안정적이고 효율적인 GitOps 워크플로우를 설계하는 방법을 Docker, CI/CD 자동화 예시와 함께 상세히 설명합니다.
GitHub Actions Advanced Workflows: Docker, Kubernetes CI/CD
GitHub Actions를 활용한 Docker, Kubernetes 기반 CI/CD 파이프라인 구축 심화 가이드. DevOps 엔지니어링 관점에서 자동화 전략을 탐구합니다.
Terraform Infrastructure Automation: DevOps 엔지니어링 가이드
Terraform을 활용한 인프라 자동화의 핵심 개념부터 실제 AWS 환경에서의 배포 예시까지, DevOps 엔지니어링 관점에서 자세히 알아봅니다. IaC, Docker, Kubernetes, CI/CD 파이프라인 통합 전략을 다룹니다.