GitOps Workflow Design: Kubernetes CI/CD 자동화 가이드
GitOps 원칙을 기반으로 Kubernetes 환경에서 CI/CD 파이프라인을 설계하고 자동화하는 방법을 상세히 안내합니다. Docker, Argo CD, Helm을 활용한 효율적인 인프라 관리 전략을 다룹니다.
GitOps Workflow Design: Kubernetes CI/CD 자동화 가이드
현대 소프트웨어 개발에서 빠르고 안정적인 배포는 비즈니스 성공의 핵심 요소입니다. 특히 마이크로서비스 아키텍처와 컨테이너 기반 환경이 보편화되면서, Kubernetes와 같은 컨테이너 오케스트레이션 시스템의 복잡성을 효과적으로 관리하는 것이 중요해졌습니다. 이러한 배경 속에서 GitOps는 인프라 및 애플리케이션 배포를 자동화하고 관리하는 강력한 방법론으로 자리 잡고 있습니다.
이 글에서는 GitOps의 기본 개념부터 시작하여, Kubernetes 환경에서 CI/CD 파이프라인을 설계하고 구축하는 실질적인 방법을 심층적으로 다룹니다. Docker, Argo CD, Helm과 같은 핵심 도구들을 활용하여 어떻게 효율적이고 안정적인 GitOps 워크플로우를 구현할 수 있는지 함께 살펴보겠습니다.
GitOps란 무엇이며 왜 필요한가?
GitOps는 Git을 "진실의 원천(Single Source of Truth)"으로 삼아 인프라와 애플리케이션 배포를 관리하는 운영 프레임워크입니다. 즉, Git 리포지토리에 저장된 선언적(declarative) 명세(manifest)가 실제 시스템의 상태를 정의하고, 이 명세와 실제 시스템 상태 간의 차이를 지속적으로 감지하고 자동으로 동기화하는 것을 목표로 합니다.
GitOps의 핵심 원칙은 다음과 같습니다.
- 선언적 명세(Declarative Configuration): 모든 시스템의 상태는 YAML 파일과 같은 선언적인 방식으로 Git에 저장됩니다.
- 버전 관리 및 감사(Versioned and Auditable): Git의 모든 변경 이력은 버전으로 관리되며, 누가, 언제, 무엇을 변경했는지 명확하게 추적할 수 있습니다.
- 자동화된 동기화(Automated Synchronization): Git에 정의된 상태와 실제 클러스터의 상태를 비교하여 불일치(drift)가 발생하면 자동으로 클러스터의 상태를 Git에 정의된 상태로 동기화합니다.
- Pull-based 메커니즘(Pull Request based): 클러스터 내부의 에이전트(예: Argo CD)가 Git 리포지토리를 지속적으로 모니터링하고 변경 사항을 감지하여 클러스터에 적용합니다. 이는 기존의 Push-based CI/CD 방식과 대조됩니다.
GitOps를 도입하면 다음과 같은 이점을 얻을 수 있습니다.
- 일관성 및 신뢰성: Git에 정의된 상태가 항상 클러스터에 반영되므로, 수동 작업으로 인한 오류를 줄이고 배포의 일관성을 보장합니다.
- 빠른 배포 및 복구: Git 변경 이력을 통해 빠르고 안정적인 롤백이 가능하며, 새로운 기능 배포 시간을 단축합니다.
- 감사 및 규정 준수: 모든 변경 사항이 Git에 기록되므로, 변경 이력을 쉽게 추적하고 감사 요구사항을 충족할 수 있습니다.
- 보안 강화: 클러스터 접근 권한을 최소화하고, 모든 변경 사항을 Git을 통해 검토하고 승인하는 워크플로우를 강제하여 보안을 강화합니다.
GitOps 워크플로우의 핵심 구성 요소
효율적인 GitOps 워크플로우를 설계하기 위해서는 여러 구성 요소들이 유기적으로 결합되어야 합니다. 주요 구성 요소들은 다음과 같습니다.
- Git Repository (진실의 원천): 애플리케이션 소스 코드와 Kubernetes 배포 명세(manifests)를 저장하는 곳입니다. 일반적으로 애플리케이션 코드 리포지토리와 인프라/배포 명세 리포지토리를 분리하여 관리하는 것이 일반적입니다.
- CI Pipeline: 애플리케이션 소스 코드를 빌드하고 테스트하며, Docker 이미지를 생성하여 컨테이너 레지스트리에 푸시하는 과정을 자동화합니다.
- Container Registry: 빌드된 Docker 이미지를 저장하는 곳입니다. Docker Hub, GitLab Container Registry, AWS ECR, Google Container Registry 등이 있습니다.
- CD Pipeline (GitOps Operator): Git 리포지토리에 정의된 배포 명세를 지속적으로 모니터링하고, 변경 사항이 발생하면 자동으로 Kubernetes 클러스터에 동기화하는 역할을 합니다. Argo CD, Flux CD 등이 대표적인 GitOps Operator입니다.
- Kubernetes Cluster: 컨테이너화된 애플리케이션을 배포하고 관리하는 대상 환경입니다.
- Configuration Management Tool: Kubernetes 배포 명세의 복잡성을 관리하고 환경별 차이를 쉽게 적용할 수 있도록 돕는 도구입니다. Helm, Kustomize 등이 주로 사용됩니다.
이러한 구성 요소들이 상호 작용하며, 개발자가 Git에 변경 사항을 커밋하는 것만으로 애플리케이션이 빌드되고 Kubernetes 클러스터에 배포되는 완전 자동화된 워크플로우를 구현할 수 있습니다.
GitOps를 위한 Git Repository 구조 설계
GitOps의 핵심은 Git 리포지토리를 진실의 원천으로 활용하는 것입니다. 효과적인 GitOps 워크플로우를 위해서는 Git 리포지토리의 구조를 신중하게 설계해야 합니다. 일반적으로 애플리케이션 소스 코드와 Kubernetes 배포 명세를 별도의 리포지토리로 분리하는 "모노레포(Monorepo)" 또는 "폴리레포(Polyrepo)" 전략 중 하나를 선택합니다. 여기서는 두 개의 리포지토리를 사용하는 폴리레포 전략을 기준으로 설명하겠습니다.
- 애플리케이션 리포지토리 (Application Repository):
- 애플리케이션의 소스 코드,
Dockerfile, CI(Continuous Integration) 설정 파일(.gitlab-ci.yml,.github/workflows/ci.yml등)을 포함합니다. - 개발자는 이 리포지토리에 코드를 커밋하고 푸시합니다.
- 애플리케이션의 소스 코드,
- 설정 리포지토리 (Configuration Repository 또는 Manifest Repository):
- Kubernetes 배포에 필요한 모든 명세 파일(Deployment, Service, Ingress 등), Helm 차트, Kustomize 파일 등을 포함합니다.
- 이 리포토리가 실제 Kubernetes 클러스터의 상태를 정의하는 "진실의 원천"이 됩니다.
다음은 일반적인 설정 리포지토리의 구조 예시입니다.
infra-repo/
├── applications/
│ ├── my-app/
│ │ ├── Chart.yaml # Helm Chart 정의
│ │ ├── values.yaml # Helm Chart 기본 값
│ │ └── templates/ # Helm Chart 템플릿 파일
│ ├── another-app/
│ │ └── ...
│ └── ...
├── environments/
│ ├── dev/
│ │ ├── my-app-release.yaml # Argo CD Application manifest (dev 환경)
│ │ ├── another-app-release.yaml
│ │ └── ...
│ ├── prod/
│ │ ├── my-app-release.yaml # Argo CD Application manifest (prod 환경)
│ │ └── ...
│ └── ...
└── base/
├── namespace.yaml # 공통 네임스페이스 정의
└── cluster-roles.yaml # 공통 RBAC 정의
-
applications/: 각 애플리케이션의 배포 명세를 Helm 차트 형태로 관리합니다.values.yaml파일은 애플리케이션별 기본 설정을 담고 있으며, CI 파이프라인에서 Docker 이미지 태그를 업데이트하는 주요 대상이 됩니다. -
environments/: 개발(dev), 운영(prod)과 같은 환경별 설정을 관리합니다. 각 환경 디렉토리 내에는 해당 환경에 배포될 Argo CDApplication리소스 명세가 포함됩니다. 이Application리소스는applications/경로의 Helm 차트를 참조하고, 환경별values.yaml오버라이드 파일을 지정할 수 있습니다. -
base/: 모든 환경에서 공통으로 사용되는 Kubernetes 리소스(예: 네임스페이스, RBAC 정의)를 포함합니다.
이러한 구조는 각 애플리케이션의 배포 명세와 환경별 설정을 명확하게 분리하여 관리의 복잡성을 줄이고, 여러 환경에 걸친 일관된 배포를 가능하게 합니다.
CI 파이프라인 구축: Docker 이미지 빌드 및 푸시
GitOps 워크플로우에서 CI(Continuous Integration) 파이프라인은 애플리케이션 소스 코드를 빌드하고, 테스트를 실행하며, 최종적으로 Docker 이미지를 생성하여 컨테이너 레지스트리에 푸시하는 역할을 담당합니다. 이 과정에서 가장 중요한 단계는 새로 빌드된 Docker 이미지의 태그를 GitOps 설정 리포지토리에 업데이트하여 CD 파이프라인을 트리거하는 것입니다.
다음은 GitLab CI를 예시로 한 CI 파이프라인 설정의 핵심 부분입니다. GitHub Actions, Jenkins, CircleCI 등 다른 CI/CD 도구에서도 유사한 방식으로 구현할 수 있습니다.
# .gitlab-ci.yml (애플리케이션 리포지토리 내)
stages:
- build_image
- update_gitops_repo
variables:
DOCKER_IMAGE_NAME: my-app # Docker 이미지 이름
KUBERNETES_VALUES_PATH: applications/my-app/values.yaml # GitOps 설정 리포지토리 내 values.yaml 경로
build_and_push_image:
stage: build_image
image: docker:latest
services:
- docker:dind
script:
- echo "로그인 정보로 Docker 레지스트리에 로그인합니다."
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- echo "Docker 이미지를 빌드합니다. 태그는 커밋 SHA를 사용합니다."
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- echo "빌드된 이미지를 컨테이너 레지스트리에 푸시합니다."
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
only:
- main # main 브랜치에 푸시될 때만 실행
update_gitops_repo:
stage: update_gitops_repo
image: alpine/git:latest # Git 명령어를 사용할 수 있는 이미지
script:
- echo "Git 설정 및 GitOps 리포지토리 클론"
- git config --global user.email "ci@example.com"
- git config --global user.name "GitLab CI"
- git clone https://oauth2:$GIT_OPS_REPO_TOKEN@gitlab.com/your-org/infra-repo.git
- cd infra-repo
- echo "Helm values.yaml 파일에서 Docker 이미지 태그를 업데이트합니다."
# sed 명령어를 사용하여 values.yaml 파일 내 image.tag 값을 업데이트
# 예: image:
# repository: your-registry/my-app
# tag: old-tag -> tag: new-tag (CI_COMMIT_SHORT_SHA)
- sed -i "s|tag: .*|tag: \"$CI_COMMIT_SHORT_SHA\"|" $KUBERNETES_VALUES_PATH
- echo "변경 사항을 커밋하고 GitOps 리포지토리에 푸시합니다."
- git add $KUBERNETES_VALUES_PATH
- git commit -m "Update $DOCKER_IMAGE_NAME image to $CI_COMMIT_SHORT_SHA [skip ci]"
- git push origin HEAD:main # main 브랜치에 푸시
only:
- main
needs: ["build_and_push_image"] # 이미지 빌드 및 푸시가 성공한 후에만 실행위 예시에서 build_and_push_image 단계는 애플리케이션 소스 코드를 기반으로 Docker 이미지를 빌드하고, Git 커밋의 짧은 SHA 값을 태그로 사용하여 컨테이너 레지스트리에 푸시합니다. 이 태그는 특정 커밋에 대한 고유한 이미지를 식별하는 데 사용됩니다.
핵심은 update_gitops_repo 단계입니다. 이 단계에서는 GitOps 설정 리포지토리를 클론하고, sed 명령어를 사용하여 values.yaml 파일 내의 image.tag 값을 새로 빌드된 이미지의 태그($CI_COMMIT_SHORT_SHA)로 업데이트합니다. 그리고 이 변경 사항을 커밋하고 설정 리포지토리에 푸시합니다. 이 푸시 작업이 GitOps Operator(예: Argo CD)가 변경 사항을 감지하고 Kubernetes 클러스터에 배포를 시작하는 트리거 역할을 합니다. [skip ci]는 GitOps 리포지토리의 CI 파이프라인이 불필요하게 실행되는 것을 방지합니다.
$GIT_OPS_REPO_TOKEN은 GitOps 설정 리포지토리에 접근할 수 있는 개인 액세스 토큰(Personal Access Token) 또는 배포 키(Deploy Key)여야 합니다. 이 토큰은 CI/CD 환경 변수로 안전하게 관리해야 합니다.
CD 파이프라인 구축: Argo CD를 이용한 Kubernetes 배포 자동화
CD(Continuous Delivery) 파이프라인은 GitOps 워크플로우의 핵심이자, Git에 정의된 상태를 Kubernetes 클러스터에 자동으로 동기화하는 역할을 합니다. 여기서는 대표적인 GitOps Operator인 Argo CD를 활용한 배포 자동화 방법을 살펴보겠습니다.
Argo CD 설치 및 구성
먼저 Kubernetes 클러스터에 Argo CD를 설치해야 합니다. 다음은 간단한 설치 명령어입니다.
# Argo CD 네임스페이스 생성
kubectl create namespace argocd
# Argo CD 설치
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Argo CD CLI 설치 (선택 사항)
# macOS (Homebrew): brew install argocd
# Linux: curl -sSL https://raw.githubusercontent.com/argoproj/argo-cd/stable/hack/install_cli.sh | bash
# 초기 관리자 비밀번호 확인
# 기본적으로 admin 사용자 비밀번호는 Argo CD Pod의 이름으로 설정됩니다.
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
# Argo CD UI 접속을 위한 포트 포워딩
kubectl port-forward svc/argocd-server -n argocd 8080:443
설치 후 localhost:8080으로 접속하여 웹 UI를 확인할 수 있습니다.
Argo CD Application 리소스 정의
Argo CD는 Application이라는 CRD(Custom Resource Definition)를 사용하여 Git 리포지토리의 특정 경로를 모니터링하고, 이를 Kubernetes 클러스터의 특정 네임스페이스에 동기화합니다. 이 Application 리소스는 GitOps 설정 리포지토리 내 environments/ 경로에 정의됩니다.
다음은 my-app 애플리케이션을 dev 환경에 배포하기 위한 Argo CD Application 리소스 예시입니다.
# infra-repo/environments/dev/my-app-release.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-dev # Argo CD 애플리케이션 이름 (환경별로 고유하게)
namespace: argocd # Argo CD가 설치된 네임스페이스
finalizers:
- resources-finalizer.argocd.argoproj.io # 애플리케이션 삭제 시 관련 리소스도 삭제
spec:
project: default # Argo CD 프로젝트 (기본값)
source:
repoURL: https://github.com/your-org/infra-repo.git # GitOps 설정 리포지토리 URL
targetRevision: HEAD # 모니터링할 Git 브랜치 또는 태그 (예: main)
path: applications/my-app # 설정 리포지토리 내 Helm 차트 또는 Kustomize 경로
helm: # Helm 차트를 사용하는 경우
valueFiles:
- values.yaml # 기본 values.yaml 파일
# parameters를 사용하여 CI에서 업데이트된 이미지 태그를 오버라이드할 수 있습니다.
# 이 예시에서는 values.yaml 파일을 직접 수정하는 방식을 사용했으므로,
# 여기서는 추가적인 image.tag 오버라이드는 필요 없습니다.
# 만약 환경별로 다른 values.yaml 파일을 사용한다면,
# valueFiles에 환경별 파일을 추가할 수 있습니다.
# ex: valueFiles: ["values.yaml", "environments/dev-values.yaml"]
destination:
server: https://kubernetes.default.svc # 배포 대상 Kubernetes 클러스터 (현재 클러스터)
namespace: my-app-dev # 애플리케이션이 배포될 Kubernetes 네임스페이스
syncPolicy:
automated: # 자동 동기화 설정
prune: true # Git에 없는 리소스를 클러스터에서 삭제
selfHeal: true # 클러스터에서 변경된 리소스를 Git 상태로 복구
syncOptions:
- CreateNamespace=true # 대상 네임스페이스가 없으면 생성
이 Application 리소스를 GitOps 설정 리포지토리에 커밋하고 푸시하면, Argo CD는 이를 감지하고 다음 작업을 수행합니다.
-
repoURL과path에 지정된 GitOps 설정 리포지토리의 특정 경로를 모니터링합니다. - 해당 경로의 명세(여기서는 Helm 차트)를 기반으로 Kubernetes 리소스를 렌더링합니다.
-
destination에 지정된 Kubernetes 클러스터와 네임스페이스에 렌더링된 리소스를 배포합니다. -
syncPolicy.automated설정에 따라 Git 리포지토리의 상태와 클러스터의 실제 상태를 지속적으로 비교하고, 불일치(drift)가 발생하면 자동으로 동기화합니다.
따라서 CI 파이프라인에서 infra-repo/applications/my-app/values.yaml 파일 내의 image.tag를 업데이트하고 푸시하면, Argo CD가 이 변경 사항을 감지하여 my-app-dev 애플리케이션을 새로운 Docker 이미지로 자동으로 업데이트합니다.
GitOps 워크플로우의 고급 전략 및 고려사항
GitOps 워크플로우를 더욱 견고하고 유연하게 만들기 위한 몇 가지 고급 전략과 고려사항이 있습니다.
1. 환경별 관리 (Multi-environment Management)
개발(Dev), 스테이징(Staging), 운영(Prod)과 같은 여러 환경에 애플리케이션을 배포해야 하는 경우, 각 환경의 설정을 효율적으로 관리하는 것이 중요합니다.
- 디렉토리 분리:
environments/dev/,environments/prod/와 같이 별도의 디렉토리를 사용하여 환경별 Argo CDApplication리소스 및values.yaml파일을 관리할 수 있습니다. - Helm Value Overrides: Helm 차트의
values.yaml파일을 환경별로 오버라이드하여 사용할 수 있습니다. 예를 들어,helm install -f values.yaml -f environments/prod-values.yaml my-app .와 같이-f옵션으로 여러values.yaml파일을 지정하여 병합할 수 있습니다. Argo CD Application 리소스에서도source.helm.valueFiles에 여러 파일을 지정할 수 있습니다. - Kustomize Overlays: Kustomize를 사용하면
base명세를 정의하고,overlays를 통해 환경별로 특정 필드만 수정하는 방식으로 관리가 가능합니다.
2. Secret Management
민감한 정보(데이터베이스 비밀번호, API 키 등)는 절대로 Git 리포지토리에 평문으로 저장해서는 안 됩니다. GitOps 환경에서 시크릿을 안전하게 관리하기 위한 방법은 다음과 같습니다.
- Sealed Secrets: Bitnami에서 제공하는 Sealed Secrets는 Kubernetes 클러스터의 컨트롤러와 함께 작동하여 암호화된 시크릿을 Git에 저장할 수 있게 합니다. 이 시크릿은 특정 클러스터에서만 복호화될 수 있습니다.
- External Secrets Operator: AWS Secrets Manager, Google Secret Manager, HashiCorp Vault와 같은 외부 시크릿 관리 시스템과 Kubernetes를 연동하는 Operator를 사용합니다. Kubernetes
Secret리소스를 생성하는 대신, 외부 시스템에서 시크릿을 가져와서 애플리케이션에 주입합니다. - Vault: HashiCorp Vault는 시크릿 관리, 암호화, 접근 제어를 위한 중앙 집중식 솔루션입니다. Kubernetes와 통합하여 동적으로 시크릿을 생성하고 관리할 수 있습니다.
3. 롤백 (Rollback) 전략
GitOps의 가장 큰 장점 중 하나는 쉬운 롤백입니다. 문제가 발생했을 때, 단순히 Git 리포지토리에서 이전 커밋으로 되돌리는 git revert 명령어를 실행하면 됩니다. Argo CD는 이 변경 사항을 감지하여 자동으로 클러스터의 상태를 이전 버전으로 되돌립니다.
# Git 리포지토리에서 이전 커밋으로 되돌리기
git revert <problematic_commit_sha>
git push origin main
이 과정은 빠르고 신뢰할 수 있으며, 모든 롤백 이력이 Git에 기록되어 투명성을 제공합니다.
4. 관측 가능성 (Observability)
GitOps 환경에서는 클러스터의 상태와 Argo CD의 작동 상태를 지속적으로 모니터링하는 것이 중요합니다.
- Argo CD UI/CLI: Argo CD는 웹 UI와 CLI를 통해 애플리케이션의 동기화 상태, 배포 이력, 리소스 헬스 등을 시각적으로 확인할 수 있습니다.
- Prometheus & Grafana: Prometheus를 사용하여 Argo CD 및 Kubernetes 클러스터의 메트릭을 수집하고, Grafana 대시보드를 통해 시각화하여 시스템 상태를 한눈에 파악할 수 있습니다.
- 로그 관리: Fluentd, Loki, Elasticsearch, Kibana 등을 활용하여 애플리케이션 로그와 클러스터 이벤트를 중앙 집중식으로 수집하고 분석합니다.
5. 보안 (Security)
GitOps는 보안 측면에서 여러 이점을 제공하지만, 몇 가지 고려사항이 있습니다.
- Git Repository 보안: Git 리포지토리에 대한 접근 제어(RBAC), 2단계 인증, 코드 리뷰 강제 등을 통해 리포지토리 자체의 보안을 강화해야 합니다.
- Argo CD RBAC: Argo CD는 자체적인 RBAC 시스템을 제공하여, 특정 사용자나 그룹이 어떤
Application을 보고 동기화할 수 있는지 세밀하게 제어할 수 있습니다. - Kubernetes RBAC: Argo CD가 Kubernetes 클러스터에 리소스를 배포하기 위해 필요한 최소한의 권한만 부여하도록 Kubernetes RBAC를 구성해야 합니다.
마무리
GitOps는 Git을 중심으로 인프라와 애플리케이션 배포를 자동화하고 관리하는 강력한 방법론입니다. 이 글에서 살펴본 GitOps 워크플로우 설계 가이드를 통해 Docker, Kubernetes, Argo CD, Helm 등의 도구를 활용하여 효율적이고 안정적인 CI/CD 파이프라인을 구축하는 방법을 이해하셨기를 바랍니다.
GitOps를 도입함으로써 개발 팀은 더욱 빠르게 기능을 배포하고, 운영 팀은 인프라의 일관성과 신뢰성을 확보하며, 전체 DevOps 프로세스의 투명성과 감사 가능성을 크게 향상시킬 수 있습니다. GitOps는 단순한 도구의 집합이 아니라, 소프트웨어 배포 및 인프라 관리에 대한 사고방식의 전환을 의미합니다. 지금 바로 GitOps를 여러분의 DevOps 여정에 통합하여, 더욱 견고하고 자동화된 시스템을 구축해 보시길 권장합니다.
관련 게시글
ArgoCD를 활용한 Kubernetes Continuous Delivery 심층 가이드
ArgoCD를 이용한 Kubernetes 환경에서의 GitOps 기반 지속적 배포(Continuous Delivery) 전략을 심층적으로 다룹니다. 설치부터 Application 관리, 고급 기능 및 DevOps 베스트 프랙티스까지, 자동화된 인프라 배포를 위한 가이드입니다.
Kubernetes Pod Service Deployment 심층 가이드
Kubernetes의 핵심 구성 요소인 Pod, Service, Deployment를 DevOps 관점에서 심층 분석하고, 실제 예시와 CLI 명령어를 통해 컨테이너 오케스트레이션의 기본기를 다집니다.
Nginx Reverse Proxy 설정 완벽 가이드: Docker, Kubernetes 환경 최적화
Nginx Reverse Proxy의 핵심 개념부터 Docker 및 Kubernetes 환경에서의 고급 설정까지, DevOps 엔지니어를 위한 상세 가이드를 제공합니다. 로드 밸런싱, SSL/TLS, 캐싱 등 실제 예시로 배우는 Nginx 활용법.