wonho e7ffdcfe44 GitHub Actions CI/CD 파이프라인 및 Kustomize 다중 환경 배포 설정
- GitHub Actions workflow로 백엔드 서비스 자동 빌드/배포 구성
- Kustomize를 통한 dev/staging/prod 환경별 설정 관리
- 각 마이크로서비스별 Dockerfile 추가
- 배포 자동화 스크립트 및 환경 변수 설정
- CI/CD 가이드 문서 작성
2025-10-29 13:24:04 +09:00

15 KiB

KT Event Marketing - Backend CI/CD Guide

목차

  1. 개요
  2. 아키텍처
  3. 사전 요구사항
  4. GitHub Secrets 설정
  5. 배포 환경
  6. 파이프라인 구조
  7. 사용 방법
  8. 트러블슈팅

개요

이 문서는 KT Event Marketing 백엔드 마이크로서비스의 CI/CD 파이프라인 구축 및 운영 가이드입니다.

시스템 정보

  • 시스템명: kt-event-marketing
  • JDK 버전: 21
  • 빌드 도구: Gradle
  • 컨테이너 레지스트리: Azure Container Registry (ACR)
  • 배포 대상: Azure Kubernetes Service (AKS)

서비스 목록

  1. user-service (8081)
  2. event-service (8082)
  3. ai-service (8083)
  4. content-service (8084)
  5. distribution-service (8085)
  6. participation-service (8086)
  7. analytics-service (8087)

아키텍처

CI/CD 파이프라인 흐름

┌─────────────────┐
│  Code Push      │
│  (GitHub)       │
└────────┬────────┘
         │
         ▼
┌─────────────────────────────────────────────┐
│  GitHub Actions Workflow                    │
│                                              │
│  1. Detect Changed Services                 │
│  2. Build & Test (Gradle)                   │
│  3. Build Docker Image                      │
│  4. Push to ACR                             │
│  5. Deploy to AKS (Kustomize)               │
│  6. Verify Deployment                       │
└─────────────────────────────────────────────┘
         │
         ▼
┌─────────────────┐
│  AKS Cluster    │
│  (Running Pods) │
└─────────────────┘

Kustomize 디렉토리 구조

.github/
├── kustomize/
│   ├── base/                          # 기본 매니페스트
│   │   ├── kustomization.yaml
│   │   ├── cm-common.yaml
│   │   ├── secret-common.yaml
│   │   ├── ingress.yaml
│   │   └── *-service-*.yaml          # 각 서비스별 리소스
│   └── overlays/                      # 환경별 설정
│       ├── dev/
│       │   ├── kustomization.yaml
│       │   └── *-service-patch.yaml  # Dev 환경 패치
│       ├── staging/
│       │   ├── kustomization.yaml
│       │   └── *-service-patch.yaml  # Staging 환경 패치
│       └── prod/
│           ├── kustomization.yaml
│           └── *-service-patch.yaml  # Prod 환경 패치
├── workflows/
│   └── backend-cicd.yaml              # GitHub Actions 워크플로우
├── config/
│   ├── deploy_env_vars_dev           # Dev 환경 변수
│   ├── deploy_env_vars_staging       # Staging 환경 변수
│   └── deploy_env_vars_prod          # Prod 환경 변수
└── scripts/
    └── deploy.sh                      # 수동 배포 스크립트

사전 요구사항

1. Azure 리소스

  • Azure Container Registry (ACR)

    • 이름: acrdigitalgarage01
    • SKU: Standard 이상
  • Azure Kubernetes Service (AKS)

    • 클러스터명: aks-digitalgarage-01
    • 리소스그룹: rg-digitalgarage-01
    • Kubernetes 버전: 1.28 이상

2. GitHub Repository Secrets

다음 Secrets를 GitHub Repository에 등록해야 합니다:

  • ACR_USERNAME: ACR 사용자명
  • ACR_PASSWORD: ACR 패스워드
  • AZURE_CREDENTIALS: Azure Service Principal JSON

3. 로컬 개발 환경 (수동 배포 시)

  • Azure CLI 2.50 이상
  • kubectl 1.28 이상
  • kustomize 5.0 이상
  • JDK 21

GitHub Secrets 설정

1. Azure Service Principal 생성

# Azure 로그인
az login

# Service Principal 생성
az ad sp create-for-rbac \
  --name "github-actions-kt-event-marketing" \
  --role contributor \
  --scopes /subscriptions/{subscription-id}/resourceGroups/rg-digitalgarage-01 \
  --sdk-auth

# 출력된 JSON을 AZURE_CREDENTIALS Secret에 등록

2. ACR 자격증명 가져오기

# ACR 사용자명 확인
az acr credential show --name acrdigitalgarage01 --query username

# ACR 패스워드 확인
az acr credential show --name acrdigitalgarage01 --query passwords[0].value

3. GitHub Secrets 등록

GitHub Repository → Settings → Secrets and variables → Actions → New repository secret

Name: ACR_USERNAME
Value: [ACR 사용자명]

Name: ACR_PASSWORD
Value: [ACR 패스워드]

Name: AZURE_CREDENTIALS
Value: [Service Principal JSON]

배포 환경

Dev 환경

  • 브랜치: develop
  • 이미지 태그: dev
  • 네임스페이스: kt-event-marketing
  • 리소스:
    • Replicas: 1
    • CPU Request: 256m, Limit: 1024m
    • Memory Request: 256Mi, Limit: 1024Mi

Staging 환경

  • 브랜치: staging (Manual workflow dispatch)
  • 이미지 태그: staging
  • 네임스페이스: kt-event-marketing
  • 리소스:
    • Replicas: 2
    • CPU Request: 512m, Limit: 2048m
    • Memory Request: 512Mi, Limit: 2048Mi

Prod 환경

  • 브랜치: main
  • 이미지 태그: prod
  • 네임스페이스: kt-event-marketing
  • 리소스:
    • Replicas: 3
    • CPU Request: 1024m, Limit: 4096m
    • Memory Request: 1024Mi, Limit: 4096Mi

파이프라인 구조

Job 1: detect-changes

변경된 서비스를 감지하고 배포 환경을 결정합니다.

Output:

  • services: 배포할 서비스 목록 (JSON 배열)
  • environment: 배포 대상 환경 (dev/staging/prod)

로직:

  • Workflow dispatch: 사용자가 지정한 서비스와 환경
  • Push to main: 모든 서비스를 prod에 배포
  • Push to develop: 변경된 서비스를 dev에 배포

Job 2: build-and-push

각 서비스를 병렬로 빌드하고 ACR에 푸시합니다.

단계:

  1. 코드 체크아웃
  2. JDK 21 설정
  3. Gradle 빌드 (테스트 제외)
  4. 단위 테스트 실행
  5. bootJar 빌드
  6. ACR 로그인
  7. Docker 이미지 빌드 및 푸시

생성되는 이미지 태그:

  • {environment}: 환경별 태그 (dev/staging/prod)
  • {git-sha}: Git 커밋 해시
  • latest: 최신 이미지

Job 3: deploy

Kustomize를 사용하여 AKS에 배포합니다.

단계:

  1. Azure 로그인
  2. AKS 자격증명 가져오기
  3. Kustomize 설치
  4. 이미지 태그 업데이트
  5. Kustomize 빌드 및 적용
  6. Deployment 롤아웃 대기
  7. 배포 검증

Job 4: notify

배포 결과를 알립니다.


사용 방법

1. 자동 배포 (Push)

Dev 환경 배포

git checkout develop
git add .
git commit -m "feat: 새로운 기능 추가"
git push origin develop

Prod 환경 배포

git checkout main
git merge develop
git push origin main

2. 수동 배포 (Workflow Dispatch)

GitHub Actions 웹 UI에서:

  1. Actions 탭 클릭
  2. "Backend CI/CD Pipeline" 워크플로우 선택
  3. "Run workflow" 클릭
  4. 환경과 서비스 선택:
    • Environment: dev/staging/prod
    • Service: all 또는 특정 서비스명

3. 로컬에서 수동 배포

# Dev 환경에 모든 서비스 배포
./.github/scripts/deploy.sh dev

# Prod 환경에 특정 서비스만 배포
./.github/scripts/deploy.sh prod user-service

# 스크립트 도움말
./.github/scripts/deploy.sh

4. 단일 서비스 배포

특정 서비스만 배포하려면:

# GitHub Actions UI에서 Workflow Dispatch 사용
# 또는 로컬 스크립트 사용
./.github/scripts/deploy.sh dev user-service

배포 검증

1. Pod 상태 확인

kubectl get pods -n kt-event-marketing

모든 Pod가 Running 상태이고 READY 컬럼이 1/1이어야 합니다.

2. Service 확인

kubectl get svc -n kt-event-marketing

3. Ingress 확인

kubectl get ingress -n kt-event-marketing

4. 로그 확인

# 특정 Pod의 로그
kubectl logs -n kt-event-marketing <pod-name>

# 최근 로그 스트리밍
kubectl logs -n kt-event-marketing <pod-name> -f

# 이전 컨테이너 로그
kubectl logs -n kt-event-marketing <pod-name> --previous

5. 애플리케이션 헬스 체크

# Ingress를 통한 헬스 체크
curl http://kt-event-marketing-api.20.214.196.128.nip.io/api/v1/users/actuator/health

# 각 서비스별 엔드포인트
curl http://kt-event-marketing-api.20.214.196.128.nip.io/api/v1/events/actuator/health
curl http://kt-event-marketing-api.20.214.196.128.nip.io/api/v1/content/actuator/health
curl http://kt-event-marketing-api.20.214.196.128.nip.io/api/v1/ai-service/actuator/health
curl http://kt-event-marketing-api.20.214.196.128.nip.io/distribution/actuator/health
curl http://kt-event-marketing-api.20.214.196.128.nip.io/api/v1/participations/actuator/health

트러블슈팅

문제 1: ImagePullBackOff

증상:

kubectl get pods -n kt-event-marketing
NAME                           READY   STATUS             RESTARTS   AGE
user-service-xxx               0/1     ImagePullBackOff   0          2m

원인:

  • ACR 인증 실패
  • 이미지가 ACR에 존재하지 않음

해결:

# Secret 확인
kubectl get secret kt-event-marketing -n kt-event-marketing

# Secret 재생성
kubectl create secret docker-registry kt-event-marketing \
  --docker-server=acrdigitalgarage01.azurecr.io \
  --docker-username=<ACR_USERNAME> \
  --docker-password=<ACR_PASSWORD> \
  -n kt-event-marketing \
  --dry-run=client -o yaml | kubectl apply -f -

# ACR에 이미지 존재 확인
az acr repository list --name acrdigitalgarage01 --output table
az acr repository show-tags --name acrdigitalgarage01 --repository kt-event-marketing/user-service

문제 2: CrashLoopBackOff

증상:

kubectl get pods -n kt-event-marketing
NAME                           READY   STATUS             RESTARTS   AGE
user-service-xxx               0/1     CrashLoopBackOff   5          5m

원인:

  • 애플리케이션 시작 실패
  • 환경 변수 오류
  • 데이터베이스 연결 실패

해결:

# Pod 로그 확인
kubectl logs -n kt-event-marketing user-service-xxx

# 이전 컨테이너 로그 확인
kubectl logs -n kt-event-marketing user-service-xxx --previous

# ConfigMap 확인
kubectl get cm -n kt-event-marketing cm-common -o yaml
kubectl get cm -n kt-event-marketing cm-user-service -o yaml

# Secret 확인 (값은 base64 인코딩)
kubectl get secret -n kt-event-marketing secret-common -o yaml

# Pod describe로 상세 정보 확인
kubectl describe pod -n kt-event-marketing user-service-xxx

문제 3: Readiness Probe Failed

증상:

kubectl get pods -n kt-event-marketing
NAME                           READY   STATUS    RESTARTS   AGE
content-service-xxx            0/1     Running   0          3m

Pod는 Running이지만 READY가 0/1입니다.

원인:

  • Actuator 엔드포인트 경로 오류
  • 애플리케이션 Context Path 설정 문제

해결:

# Pod 이벤트 확인
kubectl describe pod -n kt-event-marketing content-service-xxx

# 수동으로 헬스 체크 테스트
kubectl exec -n kt-event-marketing content-service-xxx -- \
  curl -f http://localhost:8084/api/v1/content/actuator/health

# Deployment의 probe 설정 확인 및 수정
kubectl edit deployment content-service -n kt-event-marketing

문제 4: Database Connection Failed

증상: 로그에서 데이터베이스 연결 오류 발생

해결:

# PostgreSQL Pod 확인
kubectl get pods -n kt-event-marketing | grep postgres

# PostgreSQL 연결 테스트
kubectl exec -it distribution-postgresql-0 -n kt-event-marketing -- \
  psql -U eventuser -d postgres -c "\l"

# 데이터베이스 생성
kubectl exec distribution-postgresql-0 -n kt-event-marketing -- \
  bash -c "PGPASSWORD=Hi5Jessica! psql -U eventuser -d postgres -c 'CREATE DATABASE analytics_db;'"

# ConfigMap과 Secret의 DB 설정 확인
kubectl get cm cm-analytics-service -n kt-event-marketing -o yaml
kubectl get secret secret-analytics-service -n kt-event-marketing -o yaml

문제 5: Workflow 실패

증상: GitHub Actions 워크플로우가 실패합니다.

해결:

  1. Build 단계 실패:
# 로컬에서 빌드 테스트
./gradlew clean build

# 특정 서비스만 빌드
./gradlew user-service:build
  1. Docker push 실패:
  • ACR_USERNAME, ACR_PASSWORD Secrets 확인
  • ACR에 로그인 권한 확인
  1. Deploy 단계 실패:
  • AZURE_CREDENTIALS Secret 확인
  • Service Principal 권한 확인
  • AKS 클러스터 접근 권한 확인

문제 6: Kustomize 빌드 실패

증상:

Error: unable to find one or more resources

해결:

# 로컬에서 Kustomize 빌드 테스트
cd .github/kustomize/overlays/dev
kustomize build .

# 리소스 파일 존재 확인
ls -la ../../base/

# kustomization.yaml의 resources 경로 확인
cat kustomization.yaml

모니터링 및 로깅

1. 실시간 로그 모니터링

# 모든 서비스 로그 스트리밍
kubectl logs -n kt-event-marketing -l app.kubernetes.io/part-of=kt-event-marketing -f

# 특정 서비스 로그
kubectl logs -n kt-event-marketing -l app=user-service -f

2. 리소스 사용량 모니터링

# Pod 리소스 사용량
kubectl top pods -n kt-event-marketing

# Node 리소스 사용량
kubectl top nodes

3. 이벤트 확인

# 네임스페이스 이벤트
kubectl get events -n kt-event-marketing --sort-by='.lastTimestamp'

# 특정 Pod 이벤트
kubectl describe pod -n kt-event-marketing user-service-xxx

롤백

1. Deployment 롤백

# 이전 버전으로 롤백
kubectl rollout undo deployment/user-service -n kt-event-marketing

# 특정 리비전으로 롤백
kubectl rollout history deployment/user-service -n kt-event-marketing
kubectl rollout undo deployment/user-service --to-revision=2 -n kt-event-marketing

2. 이미지 태그로 롤백

# 특정 이미지 버전으로 변경
kubectl set image deployment/user-service \
  user-service=acrdigitalgarage01.azurecr.io/kt-event-marketing/user-service:{previous-sha} \
  -n kt-event-marketing

# 롤아웃 상태 확인
kubectl rollout status deployment/user-service -n kt-event-marketing

참고 자료


변경 이력

날짜 버전 변경 내용 작성자
2025-10-29 1.0.0 초기 CI/CD 파이프라인 구축 DevOps Team