GitOps Workflow Design Guide: Docker, Kubernetes CI/CD Automation
GitOps는 Git을 진실의 원천으로 삼아 Kubernetes 환경에 애플리케이션을 배포하고 인프라를 관리하는 강력한 방법론입니다. 이 가이드에서는 GitOps의 핵심 원칙부터 Docker, Kubernetes 기반의 CI/CD 자동화 워크플로우 설계 및 구현 전략을 심층적으로 다룹니다.
GitOps Workflow Design Guide: Docker, Kubernetes CI/CD Automation
현대 소프트웨어 개발에서 빠르고 안정적인 배포는 필수적인 요소입니다. GitOps는 Git Repository를 인프라와 애플리케이션의 "단일 진실 원천(Single Source of Truth)"으로 활용하여, Kubernetes 환경에서 CI/CD 파이프라인을 자동화하고 인프라를 코드(IaC)로 관리하는 강력한 방법론입니다. 이 글에서는 GitOps의 핵심 원칙을 이해하고, Docker와 Kubernetes를 기반으로 견고한 GitOps 워크플로우를 설계하는 구체적인 가이드라인과 실제 예시를 제공합니다.
GitOps란 무엇이며 왜 필요한가요?
GitOps는 Git을 통해 인프라와 애플리케이션 배포를 관리하는 운영 프레임워크입니다. 모든 인프라 구성, 애플리케이션 배포 상태, 환경 설정 등이 Git Repository에 선언적으로 정의되며, 변경 사항은 Git Pull Request를 통해 검토되고 병합됩니다. GitOps Operator(예: ArgoCD, FluxCD)는 Git Repository의 상태와 실제 클러스터의 상태를 지속적으로 비교하고, 차이가 발생하면 Git의 상태를 따르도록 클러스터를 동기화합니다.
GitOps의 필요성
GitOps는 기존의 명령형(Imperative) 방식의 배포 및 관리 방식이 가진 한계를 극복하고, 다음과 같은 이점을 제공하여 현대 클라우드 네이티브 환경에 필수적인 방법론으로 자리 잡고 있습니다.
- 생산성 향상: 개발자가 직접 클러스터를 조작할 필요 없이 Git을 통해 배포를 관리하여 개발 및 운영 효율성을 높일 수 있습니다.
- 안정성 및 신뢰성: 모든 변경 이력이 Git에 기록되어 언제든지 이전 상태로 롤백할 수 있으며, 코드 리뷰를 통해 오류를 줄이고 배포의 안정성을 확보합니다.
- 일관성: Git Repository가 단일 진실 원천이 되어 개발, 스테이징, 프로덕션 등 모든 환경의 일관성을 보장합니다.
- 보안 강화: 직접적인 클러스터 접근을 최소화하고, Git의 접근 제어 및 감사 기능을 활용하여 보안을 강화합니다.
- 관찰 가능성(Observability): Git 커밋 히스토리를 통해 누가, 언제, 무엇을 변경했는지 명확하게 파악할 수 있으며, 이는 문제 발생 시 빠른 진단과 해결에 도움을 줍니다.
GitOps 핵심 원칙
GitOps는 다음 네 가지 핵심 원칙을 기반으로 합니다.
- 선언적(Declarative) 방식: 모든 시스템 상태는 선언적으로 기술되어 Git Repository에 저장됩니다. 이는 Kubernetes YAML Manifest와 같이 "최종 상태"를 명시하는 방식으로, 시스템이 어떻게 동작해야 하는지를 기술합니다.
- Git을 진실의 원천으로: Git Repository는 시스템의 모든 상태를 담고 있는 단일 진실 원천입니다. 모든 변경 사항은 Git을 통해서만 이루어져야 합니다.
- 자동화된 동기화: GitOps Operator는 선언된 상태와 실제 클러스터 상태를 지속적으로 비교하여 불일치 시 자동으로 클러스터를 Git의 상태로 동기화합니다.
- 지속적인 동기화: 상태 불일치 감지 및 동기화는 일회성이 아닌 지속적인 과정으로 이루어져, 클러스터 상태가 항상 Git Repository와 일치하도록 유지합니다.
GitOps 워크플로우 구성 요소
효과적인 GitOps 워크플로우를 설계하기 위해서는 다음 핵심 구성 요소들을 이해하고 적절히 활용해야 합니다.
- Git Repository:
- Application Repository: 애플리케이션 소스 코드, Dockerfile, CI/CD 파이프라인 정의 등을 포함합니다. 개발자들이 일상적으로 작업하는 코드 저장소입니다.
- Configuration Repository (Manifest Repository): Kubernetes Manifest 파일, Helm 차트, Kustomize 설정 등 클러스터에 배포될 선언적 구성 파일을 포함합니다. 일반적으로 애플리케이션 Repository와 분리하여 관리하는 것이 GitOps의 철학에 더 부합합니다.
- CI/CD 파이프라인:
- CI (Continuous Integration): 소스 코드 빌드, 단위 및 통합 테스트, Docker 이미지 생성 및 Container Registry 푸시를 담당합니다.
- CD (Continuous Delivery/Deployment): CI에서 생성된 Docker 이미지 태그를 사용하여 Configuration Repository의 Kubernetes Manifest를 업데이트하고, 해당 변경 사항을 Git에 커밋하는 역할을 합니다.
- Container Registry: Docker 이미지를 저장하고 관리하는 중앙 저장소입니다. (예: Docker Hub, AWS ECR, Google GCR)
- Kubernetes 클러스터: 애플리케이션이 배포되고 실행될 대상 환경입니다.
- GitOps Operator: Kubernetes 클러스터 내에서 실행되며, Configuration Repository를 지속적으로 모니터링하고 클러스터의 실제 상태를 Git의 선언된 상태와 일치시킵니다. 대표적인 도구로는 ArgoCD와 FluxCD가 있습니다.
GitOps 워크플로우 설계: CI 파이프라인
CI 파이프라인은 개발자가 코드를 Git에 푸시할 때마다 자동으로 트리거되어, 애플리케이션을 빌드하고 Docker 이미지를 생성하며, 이를 Container Registry에 푸시하는 역할을 합니다. 또한, GitOps 워크플로우에서는 CI 파이프라인의 마지막 단계에서 Configuration Repository의 Kubernetes Manifest 파일을 업데이트하고 커밋하는 것이 핵심입니다.
Dockerfile 예시
Node.js 기반 애플리케이션의 Dockerfile 예시입니다. 멀티-스테이지 빌드를 통해 최종 이미지 크기를 최적화합니다.
# syntax=docker/dockerfile:1
# Builder stage: 애플리케이션 빌드 및 의존성 설치
FROM public.ecr.aws/bitnami/node:16-prod AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage: 빌드된 결과물만 포함
FROM public.ecr.aws/bitnami/node:16-prod
WORKDIR /app
COPY --from=builder /app/build ./build
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
EXPOSE 3000
CMD ["npm", "start"]
CI 파이프라인 정의 (GitHub Actions 예시)
이 GitHub Actions 워크플로우는 main 브랜치에 코드가 푸시될 때마다 트리거됩니다. 애플리케이션 코드를 빌드하고, Docker 이미지를 생성하여 AWS ECR에 푸시한 다음, 최종적으로 Configuration Repository의 Kubernetes Manifest 파일 내 이미지 태그를 업데이트하고 커밋합니다.
# .github/workflows/ci.yaml (Application Repository에 위치)
name: CI Pipeline for Application
on:
push:
branches:
- main
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout Application Repository
uses: actions/checkout@v3
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-2
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build and Push Docker Image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: my-webapp
IMAGE_TAG: ${{ github.sha }} # Git 커밋 SHA를 이미지 태그로 사용
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "ECR_IMAGE=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_ENV # 다음 스텝에서 사용하기 위해 환경 변수 설정
- name: Checkout Configuration Repository
uses: actions/checkout@v3
with:
repository: your-org/kubernetes-config # Configuration Repository URL
token: ${{ secrets.GH_PAT }} # Configuration Repository에 커밋하기 위한 Personal Access Token
path: kubernetes-config # 특정 경로로 체크아웃
- name: Update Kubernetes Manifest and Push
run: |
cd kubernetes-config
# sed 명령어를 사용하여 deployment.yaml 파일의 이미지 태그를 업데이트합니다.
# 예시: image: your-ecr-registry/my-webapp:old-tag -> image: your-ecr-registry/my-webapp:new-tag
sed -i "s|image: .*/my-webapp:.*|image: ${{ env.ECR_IMAGE }}|g" k8s/production/deployment.yaml
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .
git commit -m "chore(k8s): Update my-webapp image to ${{ env.ECR_IMAGE }}" || echo "No changes to commit"
git push
working-directory: kubernetes-config
이 파이프라인은 애플리케이션 이미지를 빌드하고 ECR에 푸시한 후, kubernetes-config Repository의 k8s/production/deployment.yaml 파일에 있는 이미지 태그를 최신 이미지로 업데이트하고 Git에 커밋합니다. 이 커밋이 GitOps Operator의 트리거가 됩니다.
GitOps 워크플로우 설계: CD 파이프라인과 GitOps Operator
GitOps에서 CD 파이프라인은 CI 파이프라인이 Configuration Repository를 업데이트하는 것으로 완료됩니다. 실제 배포는 GitOps Operator가 담당합니다. GitOps Operator는 Configuration Repository를 지속적으로 모니터링하며, 변경 사항이 감지되면 자동으로 Kubernetes 클러스터에 적용합니다.
Kubernetes Manifest 예시 (deployment.yaml)
Configuration Repository에 저장될 Kubernetes Manifest 파일의 예시입니다. CI 파이프라인에서 이 파일의 image 필드가 최신 Docker 이미지 태그로 업데이트됩니다.
# kubernetes-config/k8s/production/deployment.yaml (Configuration Repository에 위치)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-webapp-deployment
labels:
app: my-webapp
spec:
replicas: 3
selector:
matchLabels:
app: my-webapp
template:
metadata:
labels:
app: my-webapp
spec:
containers:
- name: my-webapp
image: your-ecr-registry/my-webapp:latest # 이 부분이 CI에서 업데이트됩니다.
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
GitOps Operator의 역할 (ArgoCD 예시)
ArgoCD는 Kubernetes 클러스터 내에 설치되어 Configuration Repository를 주기적으로 폴링하고, Git의 선언된 상태와 클러스터의 실제 상태를 비교합니다. 불일치가 발견되면 ArgoCD는 Git의 상태를 따르도록 클러스터를 동기화합니다.
# ArgoCD 설치 (예시)
# 먼저 ArgoCD 네임스페이스를 생성합니다.
kubectl create namespace argocd
# ArgoCD 매니페스트를 적용하여 설치합니다.
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# ArgoCD CLI 설치 (macOS 기준)
brew install argocd
# ArgoCD Application 생성 예시
# 이 명령어는 ArgoCD에게 Configuration Repository를 모니터링하도록 지시합니다.
argocd app create my-webapp-prod \
--repo https://github.com/your-org/kubernetes-config.git \
--path k8s/production \
--dest-server https://kubernetes.default.svc \
--dest-namespace default \
--sync-policy automated \
--self-heal \
--revision HEAD
위 argocd app create 명령어는 kubernetes-config Repository의 k8s/production 경로를 모니터링하고, default 네임스페이스에 자동으로 동기화하도록 ArgoCD Application을 생성합니다.
-
--sync-policy automated: Git Repository에 변경 사항이 감지되면 자동으로 동기화를 시작합니다. -
--self-heal: 클러스터에서 수동으로 변경된 사항이 Git의 상태와 다를 경우, 자동으로 Git의 상태로 되돌리는 역할을 합니다. -
--revision HEAD: 최신 커밋을 기준으로 동기화합니다. 특정 브랜치(main) 또는 태그를 지정할 수도 있습니다.
실제 GitOps 워크플로우 시나리오
개발자가 애플리케이션 코드를 변경하고 main 브랜치에 푸시하면 다음과 같은 GitOps 워크플로우가 진행됩니다.
- 코드 변경 및 푸시: 개발자가 애플리케이션 코드를 수정하고, Git Repository(
application-repo)의main브랜치에 푸시합니다. - **CI 파이프라인 트리거
관련 게시글
GitOps Workflow Design: Kubernetes CI/CD 자동화 가이드
GitOps 원칙을 기반으로 Kubernetes 환경에서 CI/CD 파이프라인을 설계하고 자동화하는 방법을 상세히 안내합니다. Docker, Argo CD, Helm을 활용한 효율적인 인프라 관리 전략을 다룹니다.
ArgoCD를 활용한 Kubernetes Continuous Delivery 심층 가이드
ArgoCD를 이용한 Kubernetes 환경에서의 GitOps 기반 지속적 배포(Continuous Delivery) 전략을 심층적으로 다룹니다. 설치부터 Application 관리, 고급 기능 및 DevOps 베스트 프랙티스까지, 자동화된 인프라 배포를 위한 가이드입니다.
Kubernetes Pod Service Deployment 심층 가이드
Kubernetes의 핵심 구성 요소인 Pod, Service, Deployment를 DevOps 관점에서 심층 분석하고, 실제 예시와 CLI 명령어를 통해 컨테이너 오케스트레이션의 기본기를 다집니다.