# KT Event Marketing - Backend CI/CD Guide ## 목차 1. [개요](#개요) 2. [아키텍처](#아키텍처) 3. [사전 요구사항](#사전-요구사항) 4. [GitHub Secrets 설정](#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 생성 ```bash # 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 자격증명 가져오기 ```bash # 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 환경 배포 ```bash git checkout develop git add . git commit -m "feat: 새로운 기능 추가" git push origin develop ``` #### Prod 환경 배포 ```bash 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. 로컬에서 수동 배포 ```bash # Dev 환경에 모든 서비스 배포 ./.github/scripts/deploy.sh dev # Prod 환경에 특정 서비스만 배포 ./.github/scripts/deploy.sh prod user-service # 스크립트 도움말 ./.github/scripts/deploy.sh ``` ### 4. 단일 서비스 배포 특정 서비스만 배포하려면: ```bash # GitHub Actions UI에서 Workflow Dispatch 사용 # 또는 로컬 스크립트 사용 ./.github/scripts/deploy.sh dev user-service ``` --- ## 배포 검증 ### 1. Pod 상태 확인 ```bash kubectl get pods -n kt-event-marketing ``` 모든 Pod가 `Running` 상태이고 `READY` 컬럼이 `1/1`이어야 합니다. ### 2. Service 확인 ```bash kubectl get svc -n kt-event-marketing ``` ### 3. Ingress 확인 ```bash kubectl get ingress -n kt-event-marketing ``` ### 4. 로그 확인 ```bash # 특정 Pod의 로그 kubectl logs -n kt-event-marketing # 최근 로그 스트리밍 kubectl logs -n kt-event-marketing -f # 이전 컨테이너 로그 kubectl logs -n kt-event-marketing --previous ``` ### 5. 애플리케이션 헬스 체크 ```bash # 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에 존재하지 않음 **해결**: ```bash # 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= \ --docker-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 ``` **원인**: - 애플리케이션 시작 실패 - 환경 변수 오류 - 데이터베이스 연결 실패 **해결**: ```bash # 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 설정 문제 **해결**: ```bash # 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 **증상**: 로그에서 데이터베이스 연결 오류 발생 **해결**: ```bash # 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 단계 실패**: ```bash # 로컬에서 빌드 테스트 ./gradlew clean build # 특정 서비스만 빌드 ./gradlew user-service:build ``` 2. **Docker push 실패**: - ACR_USERNAME, ACR_PASSWORD Secrets 확인 - ACR에 로그인 권한 확인 3. **Deploy 단계 실패**: - AZURE_CREDENTIALS Secret 확인 - Service Principal 권한 확인 - AKS 클러스터 접근 권한 확인 ### 문제 6: Kustomize 빌드 실패 **증상**: ``` Error: unable to find one or more resources ``` **해결**: ```bash # 로컬에서 Kustomize 빌드 테스트 cd .github/kustomize/overlays/dev kustomize build . # 리소스 파일 존재 확인 ls -la ../../base/ # kustomization.yaml의 resources 경로 확인 cat kustomization.yaml ``` --- ## 모니터링 및 로깅 ### 1. 실시간 로그 모니터링 ```bash # 모든 서비스 로그 스트리밍 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. 리소스 사용량 모니터링 ```bash # Pod 리소스 사용량 kubectl top pods -n kt-event-marketing # Node 리소스 사용량 kubectl top nodes ``` ### 3. 이벤트 확인 ```bash # 네임스페이스 이벤트 kubectl get events -n kt-event-marketing --sort-by='.lastTimestamp' # 특정 Pod 이벤트 kubectl describe pod -n kt-event-marketing user-service-xxx ``` --- ## 롤백 ### 1. Deployment 롤백 ```bash # 이전 버전으로 롤백 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. 이미지 태그로 롤백 ```bash # 특정 이미지 버전으로 변경 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 ``` --- ## 참고 자료 - [GitHub Actions 공식 문서](https://docs.github.com/en/actions) - [Kustomize 공식 문서](https://kustomize.io/) - [Azure AKS 공식 문서](https://docs.microsoft.com/en-us/azure/aks/) - [Kubernetes 공식 문서](https://kubernetes.io/docs/) --- ## 변경 이력 | 날짜 | 버전 | 변경 내용 | 작성자 | |------|------|-----------|--------| | 2025-10-29 | 1.0.0 | 초기 CI/CD 파이프라인 구축 | DevOps Team |