Study
9 min read
GitOps와 CI/CD — GitHub Actions에서 Kubernetes까지 자동화 배포 파이프라인
지금까지 Docker, Kubernetes, AWS, 배포 전략을 배웠다. 이제 마지막 퍼즐: 자동화. 코드를 push하는 순간 테스트·빌드·배포가 자동으로 일어난다면? GitHub Actions로 CI/CD 파이프라인을 구성하고, GitOps 원칙으로 선언형 배포를 관리하자.
Series
배포 환경 이해하기- 1Container와 Docker 기초 — 왜 필요하고 어떻게 작동하는가
- 2Kubernetes 핵심 — Pod, Service, Deployment가 하는 일
- 3AWS 핵심 서비스 — EC2, S3, RDS, VPC로 클라우드 인프라 구성하기
- 4배포 전략 — Blue-Green, Canary, Rolling Deployment 무중단 배포의 기술
- 5GitOps와 CI/CD — GitHub Actions에서 Kubernetes까지 자동화 배포 파이프라인
- 6모니터링·로깅 — Prometheus, Grafana, ELK Stack으로 운영 환경 관찰하기
💡
한 줄 요약 — CI/CD는 코드 push → 자동 테스트 → 자동 빌드 → 자동 배포의 파이프라인이고, GitOps는 Git을 진실의 원천(source of truth)으로 삼아 선언형 배포를 자동화하는 방식이다.
지금까지 배운 것들을 다시 정리하면:
1. Docker: 앱을 Container로 만들기
2. Kubernetes: Container를 자동으로 관리
3. AWS: 클라우드 인프라 제공
4. 배포 전략: Blue-Green, Canary, Rolling
하지만 현실에서 매일 이 모든 걸 수동으로 하려면:
$ docker build -t myapp:v1.1 .
$ docker push myapp:v1.1
$ kubectl set image deployment/myapp myapp=myapp:v1.1
$ kubectl rollout status deployment/myapp
# ... 손으로 여러 번 타이핑이걸 매번 하려면? 자동화가 필수다.
CI/CD란?
CI (Continuous Integration) — 지속적 통합
git push (코드 변경)
↓
GitHub 웹훅 감지
↓
자동으로 테스트 실행
├─ 단위 테스트 ✅
├─ 통합 테스트 ✅
└─ 린트 검사 ✅
↓
테스트 통과 → Merge 가능 (PR 승인)
테스트 실패 → Merge 불가 (고쳐야 함)
목표: 코드 품질 자동 검증. 문제를 빨리 발견.
CD (Continuous Deployment) — 지속적 배포
테스트 통과 → main 브랜치 merge
↓
자동으로 Docker 이미지 빌드
↓
이미지를 Registry (Docker Hub, ECR)에 푸시
↓
Kubernetes 클러스터에 자동 배포
↓
사용자가 새 버전 사용 (수동 개입 0)
목표: 검증된 코드를 자동으로 본환경에 배포. 배포 속도 극대화.
GitHub Actions로 CI/CD 구현
1단계: 테스트 자동화 (CI)
# .github/workflows/test.yml
name: CI - Test
on:
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
run: |
python -m pytest tests/
- name: Run linter
run: |
flake8 app/동작:
- PR 생성 → 자동으로 워크플로우 실행
- 테스트 통과 → "✅ All checks passed" (merge 가능)
- 테스트 실패 → "❌ Tests failed" (merge 불가)
2단계: 빌드 및 배포 (CD)
# .github/workflows/deploy.yml
name: CD - Deploy to Kubernetes
on:
push:
branches: [main] # main 브랜치에만
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker image
run: |
docker build -t myapp:${{ github.sha }} .
docker build -t myapp:latest .
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Push to Docker Hub
run: |
docker push myapp:${{ github.sha }}
docker push myapp:latest
- name: Deploy to Kubernetes
run: |
# kubectl 설정 (kubeconfig 복원)
mkdir -p $HOME/.kube
echo "${{ secrets.KUBECONFIG }}" | base64 -d > $HOME/.kube/config
# 이미지 업데이트 (Rolling 배포 시작)
kubectl set image deployment/myapp \
myapp=myapp:${{ github.sha }} \
--record
# 배포 상태 확인
kubectl rollout status deployment/myapp --timeout=5m
- name: Notify Slack
if: always()
run: |
STATUS="${{ job.status }}"
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-d "{\"text\":\"Deploy $STATUS: myapp:${{ github.sha }}\"}"동작 흐름:
git push main
↓
GitHub Actions 트리거
↓
1. Docker 이미지 빌드 (myapp:abc123)
↓
2. Docker Hub에 푸시
↓
3. kubectl set image 명령 실행
↓
4. Kubernetes가 자동으로 롤링 배포 시작
↓
5. 배포 완료 → Slack 알림
3단계: Secrets 관리
워크플로우에서 민감 정보 사용:
# .github/workflows/deploy.yml에서 사용
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
kubeconfig: ${{ secrets.KUBECONFIG }}
slack_webhook: ${{ secrets.SLACK_WEBHOOK }}설정 방법:
GitHub Repository
→ Settings
→ Secrets and variables
→ Actions
→ New repository secret
- DOCKER_USERNAME: seongyeon
- DOCKER_PASSWORD: (access token)
- KUBECONFIG: (base64 인코딩된 kubeconfig)
- SLACK_WEBHOOK: https://hooks.slack.com/...
GitOps 패턴
정의
Git을 진실의 원천(source of truth)으로 삼아, Git의 상태가 곧 본환경의 상태가 되도록 관리하는 방식.
전통 (Imperative)
# 개발자가 직접 명령
$ kubectl apply -f deployment.yaml
$ kubectl set image deployment/myapp myapp=myapp:v1.1
$ kubectl scale deployment/myapp --replicas=10
# Git과 실제 상태가 불일치할 수 있음 ❌GitOps (Declarative)
Git Repository
└─ kubernetes/
├─ deployment.yaml
├─ service.yaml
└─ configmap.yaml
Kubernetes Cluster
└─ GitOps 에이전트 (ArgoCD, Flux)
└─ 계속 Git을 감시
└─ Git과 클러스터 상태 동기화
변경 과정:
1. deployment.yaml 에서 replicas: 5 → 10 변경
2. git push
3. GitOps 에이전트가 감지
4. 자동으로 kubectl apply 실행
5. Pod 10개로 확장
장점
- ✅ 진실의 원천: Git = 현재 상태 (항상 일치)
- ✅ 감시 기능: 누군가 수동으로 kubectl 변경해도 자동으로 Git 상태로 복구
- ✅ 버전 관리: 배포 히스토리가 Git에 기록됨 (audit trail)
- ✅ Rollback:
git revert한 줄로 이전 버전 복구
실전: 이 블로그의 CI/CD
이 블로그의 배포 파이프라인을 예로 들어보자:
# .github/workflows/deploy.yml
name: Deploy Blog
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install dependencies
run: npm install
- name: Build static site
run: npm run build
# Next.js가 HTML/CSS/JS 생성
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./out
# out 디렉토리를 gh-pages 브랜치에 푸시결과:
Markdown 파일 작성
↓ git push
GitHub Actions 트리거
↓
Next.js 빌드 (Markdown → HTML)
↓
정적 파일을 gh-pages 브랜치에 푸시
↓
GitHub Pages가 자동 배포
↓
블로그 업데이트 완료 (수동 개입 0)
이것이 CI/CD의 진정한 가치: 코드 → 배포까지 자동화.
ArgoCD로 GitOps 구현
더 정교한 Kubernetes 배포를 위해 ArgoCD 사용:
# kubernetes/argocd-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/me/myapp-config
targetRevision: main
path: kubernetes/
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true # Git에서 삭제된 리소스도 제거
selfHeal: true # 수동 변경도 자동으로 복구
syncOptions:
- CreateNamespace=true동작:
- Git 저장소의
kubernetes/폴더를 감시 deployment.yaml수정 → git push- ArgoCD가 자동으로 감지 (또는 수동 sync)
kubectl apply자동 실행- 클러스터 상태 = Git 상태
CI/CD 체크리스트
프로덕션 환경의 CI/CD 파이프라인:
- [ ] 테스트 자동화 (단위, 통합, E2E)
- [ ] 코드 품질 검사 (linter, SAST)
- [ ] 보안 스캔 (의존성 취약점, 이미지 스캔)
- [ ] Docker 이미지 빌드 및 서명
- [ ] 이미지 Registry에 푸시
- [ ] Kubernetes 배포 자동화
- [ ] 배포 후 스모크 테스트 (health check)
- [ ] Slack/이메일 알림
- [ ] 자동 롤백 (실패 시)
- [ ] 배포 승인 프로세스 (선택적)핵심 정리
| 단계 | 도구 | 역할 |
|---|---|---|
| CI | GitHub Actions | 테스트, 린트, 빌드 |
| Registry | Docker Hub / ECR | 이미지 저장 |
| CD | GitHub Actions / ArgoCD | 배포 자동화 |
| GitOps | ArgoCD / Flux | Git 상태 동기화 |
다음 글 예고
- 모니터링·로깅: Prometheus, Grafana, ELK... 운영 환경 관찰하기