# 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 <pod-name>

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

# 이전 컨테이너 로그
kubectl logs -n kt-event-marketing <pod-name> --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=<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
```

**원인**:
- 애플리케이션 시작 실패
- 환경 변수 오류
- 데이터베이스 연결 실패

**해결**:
```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 |
