mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 16:06:24 +00:00
Merge branch 'develop' into feature/analytics
This commit is contained in:
commit
108ee10293
186
.github/README.md
vendored
Normal file
186
.github/README.md
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
# KT Event Marketing - CI/CD Infrastructure
|
||||
|
||||
이 디렉토리는 KT Event Marketing 백엔드 서비스의 CI/CD 인프라를 포함합니다.
|
||||
|
||||
## 디렉토리 구조
|
||||
|
||||
```
|
||||
.github/
|
||||
├── README.md # 이 파일
|
||||
├── workflows/
|
||||
│ └── backend-cicd.yaml # GitHub Actions 워크플로우
|
||||
├── kustomize/ # Kubernetes 매니페스트 관리
|
||||
│ ├── base/ # 기본 리소스 정의
|
||||
│ │ ├── kustomization.yaml
|
||||
│ │ ├── cm-common.yaml
|
||||
│ │ ├── secret-common.yaml
|
||||
│ │ ├── secret-imagepull.yaml
|
||||
│ │ ├── ingress.yaml
|
||||
│ │ └── {service}-*.yaml # 각 서비스별 리소스
|
||||
│ └── overlays/ # 환경별 설정
|
||||
│ ├── dev/
|
||||
│ │ ├── kustomization.yaml
|
||||
│ │ └── *-patch.yaml # 1 replica, 256Mi-1024Mi
|
||||
│ ├── staging/
|
||||
│ │ ├── kustomization.yaml
|
||||
│ │ └── *-patch.yaml # 2 replicas, 512Mi-2048Mi
|
||||
│ └── prod/
|
||||
│ ├── kustomization.yaml
|
||||
│ └── *-patch.yaml # 3 replicas, 1024Mi-4096Mi
|
||||
├── config/
|
||||
│ ├── deploy_env_vars_dev # Dev 환경 변수
|
||||
│ ├── deploy_env_vars_staging # Staging 환경 변수
|
||||
│ └── deploy_env_vars_prod # Prod 환경 변수
|
||||
└── scripts/
|
||||
├── deploy.sh # 수동 배포 스크립트
|
||||
├── generate-patches.sh # 패치 파일 생성 스크립트
|
||||
└── copy-manifests-to-base.py # 매니페스트 복사 스크립트
|
||||
```
|
||||
|
||||
## 주요 파일 설명
|
||||
|
||||
### workflows/backend-cicd.yaml
|
||||
GitHub Actions 워크플로우 정의 파일입니다.
|
||||
|
||||
**트리거**:
|
||||
- develop 브랜치 push → dev 환경 배포
|
||||
- main 브랜치 push → prod 환경 배포
|
||||
- Manual workflow dispatch → 원하는 환경과 서비스 선택
|
||||
|
||||
**Jobs**:
|
||||
1. `detect-changes`: 변경된 서비스 감지
|
||||
2. `build-and-push`: 서비스 빌드 및 ACR 푸시
|
||||
3. `deploy`: AKS에 배포
|
||||
4. `notify`: 배포 결과 알림
|
||||
|
||||
### kustomize/base/kustomization.yaml
|
||||
모든 환경에서 공통으로 사용하는 기본 리소스를 정의합니다.
|
||||
|
||||
**포함 리소스**:
|
||||
- Common ConfigMaps and Secrets
|
||||
- Ingress
|
||||
- 7개 서비스의 Deployment, Service, ConfigMap, Secret
|
||||
|
||||
### kustomize/overlays/{env}/kustomization.yaml
|
||||
환경별 설정을 오버라이드합니다.
|
||||
|
||||
**주요 차이점**:
|
||||
- 이미지 태그 (dev/staging/prod)
|
||||
- Replica 수 (1/2/3)
|
||||
- 리소스 할당량 (작음/중간/큼)
|
||||
|
||||
### scripts/deploy.sh
|
||||
로컬에서 수동 배포를 위한 스크립트입니다.
|
||||
|
||||
**사용법**:
|
||||
```bash
|
||||
# 모든 서비스를 dev 환경에 배포
|
||||
./scripts/deploy.sh dev
|
||||
|
||||
# 특정 서비스만 prod 환경에 배포
|
||||
./scripts/deploy.sh prod user-service
|
||||
```
|
||||
|
||||
## 배포 프로세스
|
||||
|
||||
### 자동 배포 (GitHub Actions)
|
||||
|
||||
1. **Dev 환경**:
|
||||
```bash
|
||||
git checkout develop
|
||||
git push origin develop
|
||||
```
|
||||
|
||||
2. **Prod 환경**:
|
||||
```bash
|
||||
git checkout main
|
||||
git merge develop
|
||||
git push origin main
|
||||
```
|
||||
|
||||
3. **수동 배포**:
|
||||
- GitHub Actions UI → Run workflow
|
||||
- Environment 선택 (dev/staging/prod)
|
||||
- Service 선택 (all 또는 특정 서비스)
|
||||
|
||||
### 수동 배포 (로컬)
|
||||
|
||||
```bash
|
||||
# 사전 요구사항: Azure CLI, kubectl, kustomize 설치
|
||||
# Azure 로그인 필요
|
||||
|
||||
# Dev 환경에 모든 서비스 배포
|
||||
./.github/scripts/deploy.sh dev
|
||||
|
||||
# Prod 환경에 user-service만 배포
|
||||
./.github/scripts/deploy.sh prod user-service
|
||||
```
|
||||
|
||||
## 환경별 설정
|
||||
|
||||
| 환경 | 브랜치 | 이미지 태그 | Replicas | CPU Request | Memory Request |
|
||||
|------|--------|-------------|----------|-------------|----------------|
|
||||
| Dev | develop | dev | 1 | 256m | 256Mi |
|
||||
| Staging | manual | staging | 2 | 512m | 512Mi |
|
||||
| Prod | main | prod | 3 | 1024m | 1024Mi |
|
||||
|
||||
## 서비스 목록
|
||||
|
||||
1. **user-service** (8081) - 사용자 관리
|
||||
2. **event-service** (8082) - 이벤트 관리
|
||||
3. **ai-service** (8083) - AI 기반 콘텐츠 생성
|
||||
4. **content-service** (8084) - 콘텐츠 관리
|
||||
5. **distribution-service** (8085) - 경품 배포
|
||||
6. **participation-service** (8086) - 이벤트 참여
|
||||
7. **analytics-service** (8087) - 분석 및 통계
|
||||
|
||||
## 모니터링
|
||||
|
||||
### Pod 상태 확인
|
||||
```bash
|
||||
kubectl get pods -n kt-event-marketing
|
||||
```
|
||||
|
||||
### 로그 확인
|
||||
```bash
|
||||
# 실시간 로그
|
||||
kubectl logs -n kt-event-marketing -l app=user-service -f
|
||||
|
||||
# 이전 컨테이너 로그
|
||||
kubectl logs -n kt-event-marketing <pod-name> --previous
|
||||
```
|
||||
|
||||
### 리소스 사용량
|
||||
```bash
|
||||
# Pod 리소스
|
||||
kubectl top pods -n kt-event-marketing
|
||||
|
||||
# Node 리소스
|
||||
kubectl top nodes
|
||||
```
|
||||
|
||||
## 트러블슈팅
|
||||
|
||||
상세한 트러블슈팅 가이드는 [deployment/cicd/CICD-GUIDE.md](../../deployment/cicd/CICD-GUIDE.md)를 참조하세요.
|
||||
|
||||
**주요 문제 해결**:
|
||||
- ImagePullBackOff → ACR Secret 확인
|
||||
- CrashLoopBackOff → 로그 확인 및 환경 변수 검증
|
||||
- Readiness Probe Failed → Context Path 및 Actuator 경로 확인
|
||||
|
||||
## 롤백
|
||||
|
||||
```bash
|
||||
# 이전 버전으로 롤백
|
||||
kubectl rollout undo deployment/user-service -n kt-event-marketing
|
||||
|
||||
# 특정 리비전으로 롤백
|
||||
kubectl rollout undo deployment/user-service --to-revision=2 -n kt-event-marketing
|
||||
```
|
||||
|
||||
## 참고 자료
|
||||
|
||||
- [CI/CD 가이드 (한글)](../../deployment/cicd/CICD-GUIDE.md)
|
||||
- [GitHub Actions 공식 문서](https://docs.github.com/en/actions)
|
||||
- [Kustomize 공식 문서](https://kustomize.io/)
|
||||
- [Azure AKS 공식 문서](https://docs.microsoft.com/en-us/azure/aks/)
|
||||
11
.github/config/deploy_env_vars_dev
vendored
Normal file
11
.github/config/deploy_env_vars_dev
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# Development Environment Variables
|
||||
ENVIRONMENT=dev
|
||||
ACR_NAME=acrdigitalgarage01
|
||||
RESOURCE_GROUP=rg-digitalgarage-01
|
||||
AKS_CLUSTER=aks-digitalgarage-01
|
||||
NAMESPACE=kt-event-marketing
|
||||
REPLICAS=1
|
||||
CPU_REQUEST=256m
|
||||
MEMORY_REQUEST=256Mi
|
||||
CPU_LIMIT=1024m
|
||||
MEMORY_LIMIT=1024Mi
|
||||
11
.github/config/deploy_env_vars_prod
vendored
Normal file
11
.github/config/deploy_env_vars_prod
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# Production Environment Variables
|
||||
ENVIRONMENT=prod
|
||||
ACR_NAME=acrdigitalgarage01
|
||||
RESOURCE_GROUP=rg-digitalgarage-01
|
||||
AKS_CLUSTER=aks-digitalgarage-01
|
||||
NAMESPACE=kt-event-marketing
|
||||
REPLICAS=3
|
||||
CPU_REQUEST=1024m
|
||||
MEMORY_REQUEST=1024Mi
|
||||
CPU_LIMIT=4096m
|
||||
MEMORY_LIMIT=4096Mi
|
||||
11
.github/config/deploy_env_vars_staging
vendored
Normal file
11
.github/config/deploy_env_vars_staging
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# Staging Environment Variables
|
||||
ENVIRONMENT=staging
|
||||
ACR_NAME=acrdigitalgarage01
|
||||
RESOURCE_GROUP=rg-digitalgarage-01
|
||||
AKS_CLUSTER=aks-digitalgarage-01
|
||||
NAMESPACE=kt-event-marketing
|
||||
REPLICAS=2
|
||||
CPU_REQUEST=512m
|
||||
MEMORY_REQUEST=512Mi
|
||||
CPU_LIMIT=2048m
|
||||
MEMORY_LIMIT=2048Mi
|
||||
55
.github/kustomize/base/ai-service-cm-ai-service.yaml
vendored
Normal file
55
.github/kustomize/base/ai-service-cm-ai-service.yaml
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm-ai-service
|
||||
data:
|
||||
# Server Configuration
|
||||
SERVER_PORT: "8083"
|
||||
|
||||
# Redis Configuration (service-specific)
|
||||
REDIS_DATABASE: "3"
|
||||
REDIS_TIMEOUT: "3000"
|
||||
REDIS_POOL_MIN: "2"
|
||||
|
||||
# Kafka Configuration (service-specific)
|
||||
KAFKA_CONSUMER_GROUP: "ai-service-consumers"
|
||||
|
||||
# Kafka Topics Configuration
|
||||
KAFKA_TOPICS_AI_JOB: "ai-event-generation-job"
|
||||
KAFKA_TOPICS_AI_JOB_DLQ: "ai-event-generation-job-dlq"
|
||||
|
||||
# AI Provider Configuration
|
||||
AI_PROVIDER: "CLAUDE"
|
||||
AI_CLAUDE_API_URL: "https://api.anthropic.com/v1/messages"
|
||||
AI_CLAUDE_ANTHROPIC_VERSION: "2023-06-01"
|
||||
AI_CLAUDE_MODEL: "claude-sonnet-4-5-20250929"
|
||||
AI_CLAUDE_MAX_TOKENS: "4096"
|
||||
AI_CLAUDE_TEMPERATURE: "0.7"
|
||||
AI_CLAUDE_TIMEOUT: "300000"
|
||||
|
||||
# Circuit Breaker Configuration
|
||||
RESILIENCE4J_CIRCUITBREAKER_FAILURE_RATE_THRESHOLD: "50"
|
||||
RESILIENCE4J_CIRCUITBREAKER_SLOW_CALL_RATE_THRESHOLD: "50"
|
||||
RESILIENCE4J_CIRCUITBREAKER_SLOW_CALL_DURATION_THRESHOLD: "60s"
|
||||
RESILIENCE4J_CIRCUITBREAKER_PERMITTED_CALLS_HALF_OPEN: "3"
|
||||
RESILIENCE4J_CIRCUITBREAKER_SLIDING_WINDOW_SIZE: "10"
|
||||
RESILIENCE4J_CIRCUITBREAKER_MINIMUM_CALLS: "5"
|
||||
RESILIENCE4J_CIRCUITBREAKER_WAIT_DURATION_OPEN: "60s"
|
||||
RESILIENCE4J_TIMELIMITER_TIMEOUT_DURATION: "300s"
|
||||
|
||||
# Redis Cache TTL Configuration (seconds)
|
||||
CACHE_TTL_RECOMMENDATION: "86400"
|
||||
CACHE_TTL_JOB_STATUS: "86400"
|
||||
CACHE_TTL_TREND: "3600"
|
||||
CACHE_TTL_FALLBACK: "604800"
|
||||
|
||||
# Logging Configuration
|
||||
LOG_LEVEL_ROOT: "INFO"
|
||||
LOG_LEVEL_AI: "DEBUG"
|
||||
LOG_LEVEL_KAFKA: "INFO"
|
||||
LOG_LEVEL_REDIS: "INFO"
|
||||
LOG_LEVEL_RESILIENCE4J: "DEBUG"
|
||||
LOG_FILE_NAME: "logs/ai-service.log"
|
||||
LOG_FILE_MAX_SIZE: "10MB"
|
||||
LOG_FILE_MAX_HISTORY: "7"
|
||||
LOG_FILE_TOTAL_CAP: "100MB"
|
||||
62
.github/kustomize/base/ai-service-deployment.yaml
vendored
Normal file
62
.github/kustomize/base/ai-service-deployment.yaml
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ai-service
|
||||
labels:
|
||||
app: ai-service
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: ai-service
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: ai-service
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: kt-event-marketing
|
||||
containers:
|
||||
- name: ai-service
|
||||
image: acrdigitalgarage01.azurecr.io/kt-event-marketing/ai-service:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8083
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: cm-ai-service
|
||||
- secretRef:
|
||||
name: secret-common
|
||||
- secretRef:
|
||||
name: secret-ai-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
port: 8083
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
port: 8083
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
failureThreshold: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
port: 8083
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
8
.github/kustomize/base/ai-service-secret-ai-service.yaml
vendored
Normal file
8
.github/kustomize/base/ai-service-secret-ai-service.yaml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret-ai-service
|
||||
type: Opaque
|
||||
stringData:
|
||||
# Claude API Key
|
||||
AI_CLAUDE_API_KEY: "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"
|
||||
15
.github/kustomize/base/ai-service-service.yaml
vendored
Normal file
15
.github/kustomize/base/ai-service-service.yaml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ai-service
|
||||
labels:
|
||||
app: ai-service
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8083
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: ai-service
|
||||
37
.github/kustomize/base/analytics-service-cm-analytics-service.yaml
vendored
Normal file
37
.github/kustomize/base/analytics-service-cm-analytics-service.yaml
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm-analytics-service
|
||||
data:
|
||||
# Server Configuration
|
||||
SERVER_PORT: "8086"
|
||||
|
||||
# Database Configuration
|
||||
DB_HOST: "analytic-postgresql"
|
||||
DB_PORT: "5432"
|
||||
DB_NAME: "analytics_db"
|
||||
DB_USERNAME: "eventuser"
|
||||
|
||||
# Redis Configuration (service-specific)
|
||||
REDIS_DATABASE: "5"
|
||||
|
||||
# Kafka Configuration (service-specific)
|
||||
KAFKA_ENABLED: "true"
|
||||
KAFKA_CONSUMER_GROUP_ID: "analytics-service"
|
||||
|
||||
# Sample Data Configuration (MVP only)
|
||||
SAMPLE_DATA_ENABLED: "true"
|
||||
|
||||
# Batch Scheduler Configuration
|
||||
BATCH_REFRESH_INTERVAL: "300000" # 5분 (밀리초)
|
||||
BATCH_INITIAL_DELAY: "30000" # 30초 (밀리초)
|
||||
BATCH_ENABLED: "true"
|
||||
|
||||
# Logging Configuration
|
||||
LOG_LEVEL_APP: "INFO"
|
||||
LOG_LEVEL_WEB: "INFO"
|
||||
LOG_LEVEL_SQL: "WARN"
|
||||
LOG_LEVEL_SQL_TYPE: "WARN"
|
||||
SHOW_SQL: "false"
|
||||
DDL_AUTO: "update"
|
||||
LOG_FILE: "logs/analytics-service.log"
|
||||
62
.github/kustomize/base/analytics-service-deployment.yaml
vendored
Normal file
62
.github/kustomize/base/analytics-service-deployment.yaml
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: analytics-service
|
||||
labels:
|
||||
app: analytics-service
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: analytics-service
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: analytics-service
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: kt-event-marketing
|
||||
containers:
|
||||
- name: analytics-service
|
||||
image: acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8086
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: cm-analytics-service
|
||||
- secretRef:
|
||||
name: secret-common
|
||||
- secretRef:
|
||||
name: secret-analytics-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
port: 8086
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
port: 8086
|
||||
initialDelaySeconds: 0
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
port: 8086
|
||||
initialDelaySeconds: 0
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
7
.github/kustomize/base/analytics-service-secret-analytics-service.yaml
vendored
Normal file
7
.github/kustomize/base/analytics-service-secret-analytics-service.yaml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret-analytics-service
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_PASSWORD: "Hi5Jessica!"
|
||||
15
.github/kustomize/base/analytics-service-service.yaml
vendored
Normal file
15
.github/kustomize/base/analytics-service-service.yaml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: analytics-service
|
||||
labels:
|
||||
app: analytics-service
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8086
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: analytics-service
|
||||
46
.github/kustomize/base/cm-common.yaml
vendored
Normal file
46
.github/kustomize/base/cm-common.yaml
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm-common
|
||||
data:
|
||||
# Redis Configuration
|
||||
REDIS_ENABLED: "true"
|
||||
REDIS_HOST: "redis"
|
||||
REDIS_PORT: "6379"
|
||||
REDIS_TIMEOUT: "2000ms"
|
||||
REDIS_POOL_MAX: "8"
|
||||
REDIS_POOL_IDLE: "8"
|
||||
REDIS_POOL_MIN: "0"
|
||||
REDIS_POOL_WAIT: "-1ms"
|
||||
|
||||
# Kafka Configuration
|
||||
KAFKA_BOOTSTRAP_SERVERS: "20.249.182.13:9095,4.217.131.59:9095"
|
||||
EXCLUDE_KAFKA: ""
|
||||
EXCLUDE_REDIS: ""
|
||||
|
||||
# CORS Configuration
|
||||
CORS_ALLOWED_ORIGINS: "http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://kt-event-marketing.20.214.196.128.nip.io"
|
||||
CORS_ALLOWED_METHODS: "GET,POST,PUT,DELETE,OPTIONS,PATCH"
|
||||
CORS_ALLOWED_HEADERS: "*"
|
||||
CORS_ALLOW_CREDENTIALS: "true"
|
||||
CORS_MAX_AGE: "3600"
|
||||
|
||||
# JWT Configuration
|
||||
JWT_ACCESS_TOKEN_VALIDITY: "604800000"
|
||||
JWT_REFRESH_TOKEN_VALIDITY: "86400000"
|
||||
|
||||
# JPA Configuration
|
||||
DDL_AUTO: "update"
|
||||
SHOW_SQL: "false"
|
||||
JPA_DIALECT: "org.hibernate.dialect.PostgreSQLDialect"
|
||||
H2_CONSOLE_ENABLED: "false"
|
||||
|
||||
# Logging Configuration
|
||||
LOG_LEVEL_APP: "INFO"
|
||||
LOG_LEVEL_WEB: "INFO"
|
||||
LOG_LEVEL_SQL: "WARN"
|
||||
LOG_LEVEL_SQL_TYPE: "WARN"
|
||||
LOG_LEVEL_ROOT: "INFO"
|
||||
LOG_FILE_MAX_SIZE: "10MB"
|
||||
LOG_FILE_MAX_HISTORY: "7"
|
||||
LOG_FILE_TOTAL_CAP: "100MB"
|
||||
24
.github/kustomize/base/content-service-cm-content-service.yaml
vendored
Normal file
24
.github/kustomize/base/content-service-cm-content-service.yaml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm-content-service
|
||||
data:
|
||||
# Server Configuration
|
||||
SERVER_PORT: "8084"
|
||||
|
||||
# Redis Configuration (service-specific)
|
||||
REDIS_DATABASE: "1"
|
||||
|
||||
# Replicate API Configuration (Stable Diffusion)
|
||||
REPLICATE_API_URL: "https://api.replicate.com"
|
||||
REPLICATE_MODEL_VERSION: "stability-ai/sdxl:39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b"
|
||||
|
||||
# HuggingFace API Configuration
|
||||
HUGGINGFACE_API_URL: "https://api-inference.huggingface.co"
|
||||
HUGGINGFACE_MODEL: "runwayml/stable-diffusion-v1-5"
|
||||
|
||||
# Azure Blob Storage Configuration
|
||||
AZURE_CONTAINER_NAME: "content-images"
|
||||
|
||||
# Logging Configuration
|
||||
LOG_FILE_PATH: "logs/content-service.log"
|
||||
62
.github/kustomize/base/content-service-deployment.yaml
vendored
Normal file
62
.github/kustomize/base/content-service-deployment.yaml
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: content-service
|
||||
labels:
|
||||
app: content-service
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: content-service
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: content-service
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: kt-event-marketing
|
||||
containers:
|
||||
- name: content-service
|
||||
image: acrdigitalgarage01.azurecr.io/kt-event-marketing/content-service:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8084
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: cm-content-service
|
||||
- secretRef:
|
||||
name: secret-common
|
||||
- secretRef:
|
||||
name: secret-content-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /api/v1/content/actuator/health
|
||||
port: 8084
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/v1/content/actuator/health/readiness
|
||||
port: 8084
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
failureThreshold: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/v1/content/actuator/health/liveness
|
||||
port: 8084
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
14
.github/kustomize/base/content-service-secret-content-service.yaml
vendored
Normal file
14
.github/kustomize/base/content-service-secret-content-service.yaml
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret-content-service
|
||||
type: Opaque
|
||||
stringData:
|
||||
# Azure Blob Storage Connection String
|
||||
AZURE_STORAGE_CONNECTION_STRING: "DefaultEndpointsProtocol=https;AccountName=blobkteventstorage;AccountKey=tcBN7mAfojbl0uGsOpU7RNuKNhHnzmwDiWjN31liSMVSrWaEK+HHnYKZrjBXXAC6ZPsuxUDlsf8x+AStd++QYg==;EndpointSuffix=core.windows.net"
|
||||
|
||||
# Replicate API Token
|
||||
REPLICATE_API_TOKEN: ""
|
||||
|
||||
# HuggingFace API Token
|
||||
HUGGINGFACE_API_TOKEN: ""
|
||||
15
.github/kustomize/base/content-service-service.yaml
vendored
Normal file
15
.github/kustomize/base/content-service-service.yaml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: content-service
|
||||
labels:
|
||||
app: content-service
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8084
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: content-service
|
||||
28
.github/kustomize/base/distribution-service-cm-distribution-service.yaml
vendored
Normal file
28
.github/kustomize/base/distribution-service-cm-distribution-service.yaml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm-distribution-service
|
||||
data:
|
||||
# Server Configuration
|
||||
SERVER_PORT: "8085"
|
||||
|
||||
# Database Configuration
|
||||
DB_HOST: "distribution-postgresql"
|
||||
DB_PORT: "5432"
|
||||
DB_NAME: "distributiondb"
|
||||
DB_USERNAME: "eventuser"
|
||||
|
||||
# Kafka Configuration
|
||||
KAFKA_ENABLED: "true"
|
||||
KAFKA_CONSUMER_GROUP: "distribution-service"
|
||||
|
||||
# External Channel APIs
|
||||
URIDONGNETV_API_URL: "http://localhost:9001/api/uridongnetv"
|
||||
RINGOBIZ_API_URL: "http://localhost:9002/api/ringobiz"
|
||||
GINITV_API_URL: "http://localhost:9003/api/ginitv"
|
||||
INSTAGRAM_API_URL: "http://localhost:9004/api/instagram"
|
||||
NAVER_API_URL: "http://localhost:9005/api/naver"
|
||||
KAKAO_API_URL: "http://localhost:9006/api/kakao"
|
||||
|
||||
# Logging Configuration
|
||||
LOG_FILE: "logs/distribution-service.log"
|
||||
62
.github/kustomize/base/distribution-service-deployment.yaml
vendored
Normal file
62
.github/kustomize/base/distribution-service-deployment.yaml
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: distribution-service
|
||||
labels:
|
||||
app: distribution-service
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: distribution-service
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: distribution-service
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: kt-event-marketing
|
||||
containers:
|
||||
- name: distribution-service
|
||||
image: acrdigitalgarage01.azurecr.io/kt-event-marketing/distribution-service:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8085
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: cm-distribution-service
|
||||
- secretRef:
|
||||
name: secret-common
|
||||
- secretRef:
|
||||
name: secret-distribution-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /api/v1/distribution/actuator/health
|
||||
port: 8085
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/v1/distribution/actuator/health/readiness
|
||||
port: 8085
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
failureThreshold: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/v1/distribution/actuator/health/liveness
|
||||
port: 8085
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
7
.github/kustomize/base/distribution-service-secret-distribution-service.yaml
vendored
Normal file
7
.github/kustomize/base/distribution-service-secret-distribution-service.yaml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret-distribution-service
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_PASSWORD: "Hi5Jessica!"
|
||||
15
.github/kustomize/base/distribution-service-service.yaml
vendored
Normal file
15
.github/kustomize/base/distribution-service-service.yaml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: distribution-service
|
||||
labels:
|
||||
app: distribution-service
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: distribution-service
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 8085
|
||||
protocol: TCP
|
||||
28
.github/kustomize/base/event-service-cm-event-service.yaml
vendored
Normal file
28
.github/kustomize/base/event-service-cm-event-service.yaml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm-event-service
|
||||
data:
|
||||
# Server Configuration
|
||||
SERVER_PORT: "8080"
|
||||
|
||||
# Database Configuration
|
||||
DB_HOST: "event-postgresql"
|
||||
DB_PORT: "5432"
|
||||
DB_NAME: "eventdb"
|
||||
DB_USERNAME: "eventuser"
|
||||
|
||||
# Redis Configuration (service-specific)
|
||||
REDIS_DATABASE: "2"
|
||||
|
||||
# Kafka Configuration (service-specific)
|
||||
KAFKA_CONSUMER_GROUP: "event-service-consumers"
|
||||
|
||||
# Service URLs
|
||||
CONTENT_SERVICE_URL: "http://content-service"
|
||||
DISTRIBUTION_SERVICE_URL: "http://distribution-service"
|
||||
|
||||
# Logging Configuration
|
||||
LOG_LEVEL: "INFO"
|
||||
SQL_LOG_LEVEL: "WARN"
|
||||
LOG_FILE: "logs/event-service.log"
|
||||
62
.github/kustomize/base/event-service-deployment.yaml
vendored
Normal file
62
.github/kustomize/base/event-service-deployment.yaml
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: event-service
|
||||
labels:
|
||||
app: event-service
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: event-service
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: event-service
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: kt-event-marketing
|
||||
containers:
|
||||
- name: event-service
|
||||
image: acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: cm-event-service
|
||||
- secretRef:
|
||||
name: secret-common
|
||||
- secretRef:
|
||||
name: secret-event-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
failureThreshold: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
8
.github/kustomize/base/event-service-secret-event-service.yaml
vendored
Normal file
8
.github/kustomize/base/event-service-secret-event-service.yaml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret-event-service
|
||||
type: Opaque
|
||||
stringData:
|
||||
# Database Password
|
||||
DB_PASSWORD: "Hi5Jessica!"
|
||||
15
.github/kustomize/base/event-service-service.yaml
vendored
Normal file
15
.github/kustomize/base/event-service-service.yaml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: event-service
|
||||
labels:
|
||||
app: event-service
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: event-service
|
||||
116
.github/kustomize/base/ingress.yaml
vendored
Normal file
116
.github/kustomize/base/ingress.yaml
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: kt-event-marketing
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "false"
|
||||
nginx.ingress.kubernetes.io/use-regex: "true"
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
rules:
|
||||
- host: kt-event-marketing-api.20.214.196.128.nip.io
|
||||
http:
|
||||
paths:
|
||||
# User Service
|
||||
- path: /api/v1/users
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: user-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# Content Service
|
||||
- path: /api/v1/content
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: content-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# Event Service
|
||||
- path: /api/v1/events
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: event-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
- path: /api/v1/jobs
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: event-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
- path: /api/v1/redis-test
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: event-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# AI Service
|
||||
- path: /api/v1/ai-service
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: ai-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# Participation Service
|
||||
- path: /api/v1/participations
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: participation-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
- path: /api/v1/winners
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: participation-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
- path: /debug
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: participation-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# Analytics Service - Event Analytics
|
||||
- path: /api/v1/events/([0-9]+)/analytics
|
||||
pathType: ImplementationSpecific
|
||||
backend:
|
||||
service:
|
||||
name: analytics-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# Analytics Service - User Analytics
|
||||
- path: /api/v1/users/([0-9]+)/analytics
|
||||
pathType: ImplementationSpecific
|
||||
backend:
|
||||
service:
|
||||
name: analytics-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# Distribution Service
|
||||
- path: /distribution
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: distribution-service
|
||||
port:
|
||||
number: 80
|
||||
76
.github/kustomize/base/kustomization.yaml
vendored
Normal file
76
.github/kustomize/base/kustomization.yaml
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
# Common resources
|
||||
resources:
|
||||
# Common ConfigMaps and Secrets
|
||||
- cm-common.yaml
|
||||
- secret-common.yaml
|
||||
- secret-imagepull.yaml
|
||||
|
||||
# Ingress
|
||||
- ingress.yaml
|
||||
|
||||
# user-service
|
||||
- user-service-deployment.yaml
|
||||
- user-service-service.yaml
|
||||
- user-service-cm-user-service.yaml
|
||||
- user-service-secret-user-service.yaml
|
||||
|
||||
# event-service
|
||||
- event-service-deployment.yaml
|
||||
- event-service-service.yaml
|
||||
- event-service-cm-event-service.yaml
|
||||
- event-service-secret-event-service.yaml
|
||||
|
||||
# ai-service
|
||||
- ai-service-deployment.yaml
|
||||
- ai-service-service.yaml
|
||||
- ai-service-cm-ai-service.yaml
|
||||
- ai-service-secret-ai-service.yaml
|
||||
|
||||
# content-service
|
||||
- content-service-deployment.yaml
|
||||
- content-service-service.yaml
|
||||
- content-service-cm-content-service.yaml
|
||||
- content-service-secret-content-service.yaml
|
||||
|
||||
# distribution-service
|
||||
- distribution-service-deployment.yaml
|
||||
- distribution-service-service.yaml
|
||||
- distribution-service-cm-distribution-service.yaml
|
||||
- distribution-service-secret-distribution-service.yaml
|
||||
|
||||
# participation-service
|
||||
- participation-service-deployment.yaml
|
||||
- participation-service-service.yaml
|
||||
- participation-service-cm-participation-service.yaml
|
||||
- participation-service-secret-participation-service.yaml
|
||||
|
||||
# analytics-service
|
||||
- analytics-service-deployment.yaml
|
||||
- analytics-service-service.yaml
|
||||
- analytics-service-cm-analytics-service.yaml
|
||||
- analytics-service-secret-analytics-service.yaml
|
||||
|
||||
# Common labels for all resources
|
||||
commonLabels:
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
app.kubernetes.io/part-of: kt-event-marketing
|
||||
|
||||
# Image tag replacement (will be overridden by overlays)
|
||||
images:
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/user-service
|
||||
newTag: latest
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service
|
||||
newTag: latest
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/ai-service
|
||||
newTag: latest
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/content-service
|
||||
newTag: latest
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/distribution-service
|
||||
newTag: latest
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/participation-service
|
||||
newTag: latest
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service
|
||||
newTag: latest
|
||||
24
.github/kustomize/base/participation-service-cm-participation-service.yaml
vendored
Normal file
24
.github/kustomize/base/participation-service-cm-participation-service.yaml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm-participation-service
|
||||
data:
|
||||
# Server Configuration
|
||||
SERVER_PORT: "8084"
|
||||
|
||||
# Database Configuration
|
||||
DB_HOST: "participation-postgresql"
|
||||
DB_PORT: "5432"
|
||||
DB_NAME: "participationdb"
|
||||
DB_USERNAME: "eventuser"
|
||||
|
||||
# Redis Configuration (service-specific)
|
||||
REDIS_DATABASE: "4"
|
||||
|
||||
# Kafka Configuration (service-specific)
|
||||
KAFKA_CONSUMER_GROUP: "participation-service-consumers"
|
||||
|
||||
# Logging Configuration
|
||||
LOG_LEVEL: "INFO"
|
||||
SHOW_SQL: "false"
|
||||
LOG_FILE: "logs/participation-service.log"
|
||||
62
.github/kustomize/base/participation-service-deployment.yaml
vendored
Normal file
62
.github/kustomize/base/participation-service-deployment.yaml
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: participation-service
|
||||
labels:
|
||||
app: participation-service
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: participation-service
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: participation-service
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: kt-event-marketing
|
||||
containers:
|
||||
- name: participation-service
|
||||
image: acrdigitalgarage01.azurecr.io/kt-event-marketing/participation-service:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8084
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: cm-participation-service
|
||||
- secretRef:
|
||||
name: secret-common
|
||||
- secretRef:
|
||||
name: secret-participation-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
port: 8084
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
port: 8084
|
||||
initialDelaySeconds: 0
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
port: 8084
|
||||
initialDelaySeconds: 0
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
7
.github/kustomize/base/participation-service-secret-participation-service.yaml
vendored
Normal file
7
.github/kustomize/base/participation-service-secret-participation-service.yaml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret-participation-service
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_PASSWORD: "Hi5Jessica!"
|
||||
15
.github/kustomize/base/participation-service-service.yaml
vendored
Normal file
15
.github/kustomize/base/participation-service-service.yaml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: participation-service
|
||||
labels:
|
||||
app: participation-service
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8084
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: participation-service
|
||||
11
.github/kustomize/base/secret-common.yaml
vendored
Normal file
11
.github/kustomize/base/secret-common.yaml
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret-common
|
||||
type: Opaque
|
||||
stringData:
|
||||
# Redis Password
|
||||
REDIS_PASSWORD: "Hi5Jessica!"
|
||||
|
||||
# JWT Secret
|
||||
JWT_SECRET: "QL0czzXckz18kHnxpaTDoWFkq+3qKO7VQXeNvf2bOoU="
|
||||
16
.github/kustomize/base/secret-imagepull.yaml
vendored
Normal file
16
.github/kustomize/base/secret-imagepull.yaml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: kt-event-marketing
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
stringData:
|
||||
.dockerconfigjson: |
|
||||
{
|
||||
"auths": {
|
||||
"acrdigitalgarage01.azurecr.io": {
|
||||
"username": "acrdigitalgarage01",
|
||||
"password": "+OY+rmOagorjWvQe/tTk6oqvnZI8SmNbY/Y2o5EDcY+ACRDCDbYk",
|
||||
"auth": "YWNyZGlnaXRhbGdhcmFnZTAxOitPWStybU9hZ29yald2UWUvdFRrNm9xdm5aSThTbU5iWS9ZMm81RURjWStBQ1JEQ0RiWWs="
|
||||
}
|
||||
}
|
||||
}
|
||||
31
.github/kustomize/base/user-service-cm-user-service.yaml
vendored
Normal file
31
.github/kustomize/base/user-service-cm-user-service.yaml
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm-user-service
|
||||
data:
|
||||
# Server Configuration
|
||||
SERVER_PORT: "8081"
|
||||
|
||||
# Database Configuration
|
||||
DB_URL: "jdbc:postgresql://user-postgresql:5432/userdb"
|
||||
DB_HOST: "user-postgresql"
|
||||
DB_PORT: "5432"
|
||||
DB_NAME: "userdb"
|
||||
DB_USERNAME: "eventuser"
|
||||
DB_DRIVER: "org.postgresql.Driver"
|
||||
DB_KIND: "postgresql"
|
||||
DB_POOL_MAX: "20"
|
||||
DB_POOL_MIN: "5"
|
||||
DB_CONN_TIMEOUT: "30000"
|
||||
DB_IDLE_TIMEOUT: "600000"
|
||||
DB_MAX_LIFETIME: "1800000"
|
||||
DB_LEAK_THRESHOLD: "60000"
|
||||
|
||||
# Redis Configuration (service-specific)
|
||||
REDIS_DATABASE: "0"
|
||||
|
||||
# Kafka Configuration (service-specific)
|
||||
KAFKA_CONSUMER_GROUP: "user-service-consumers"
|
||||
|
||||
# Logging Configuration
|
||||
LOG_FILE_PATH: "logs/user-service.log"
|
||||
62
.github/kustomize/base/user-service-deployment.yaml
vendored
Normal file
62
.github/kustomize/base/user-service-deployment.yaml
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: user-service
|
||||
labels:
|
||||
app: user-service
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: user-service
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: user-service
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: kt-event-marketing
|
||||
containers:
|
||||
- name: user-service
|
||||
image: acrdigitalgarage01.azurecr.io/kt-event-marketing/user-service:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8081
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: cm-user-service
|
||||
- secretRef:
|
||||
name: secret-common
|
||||
- secretRef:
|
||||
name: secret-user-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
port: 8081
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
port: 8081
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
failureThreshold: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
port: 8081
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
8
.github/kustomize/base/user-service-secret-user-service.yaml
vendored
Normal file
8
.github/kustomize/base/user-service-secret-user-service.yaml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret-user-service
|
||||
type: Opaque
|
||||
stringData:
|
||||
# Database Password
|
||||
DB_PASSWORD: "Hi5Jessica!"
|
||||
15
.github/kustomize/base/user-service-service.yaml
vendored
Normal file
15
.github/kustomize/base/user-service-service.yaml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: user-service
|
||||
labels:
|
||||
app: user-service
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8081
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: user-service
|
||||
17
.github/kustomize/overlays/dev/ai-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/dev/ai-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ai-service
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: ai-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
17
.github/kustomize/overlays/dev/analytics-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/dev/analytics-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: analytics-service
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: analytics-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
17
.github/kustomize/overlays/dev/content-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/dev/content-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: content-service
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: content-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
17
.github/kustomize/overlays/dev/distribution-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/dev/distribution-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: distribution-service
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: distribution-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
17
.github/kustomize/overlays/dev/event-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/dev/event-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: event-service
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: event-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
38
.github/kustomize/overlays/dev/kustomization.yaml
vendored
Normal file
38
.github/kustomize/overlays/dev/kustomization.yaml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: kt-event-marketing
|
||||
|
||||
bases:
|
||||
- ../../base
|
||||
|
||||
# Environment-specific labels
|
||||
commonLabels:
|
||||
environment: dev
|
||||
|
||||
# Environment-specific patches
|
||||
patchesStrategicMerge:
|
||||
- user-service-patch.yaml
|
||||
- event-service-patch.yaml
|
||||
- ai-service-patch.yaml
|
||||
- content-service-patch.yaml
|
||||
- distribution-service-patch.yaml
|
||||
- participation-service-patch.yaml
|
||||
- analytics-service-patch.yaml
|
||||
|
||||
# Override image tags for dev environment
|
||||
images:
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/user-service
|
||||
newTag: dev
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service
|
||||
newTag: dev
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/ai-service
|
||||
newTag: dev
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/content-service
|
||||
newTag: dev
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/distribution-service
|
||||
newTag: dev
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/participation-service
|
||||
newTag: dev
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service
|
||||
newTag: dev
|
||||
17
.github/kustomize/overlays/dev/participation-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/dev/participation-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: participation-service
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: participation-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
17
.github/kustomize/overlays/dev/user-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/dev/user-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: user-service
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: user-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
17
.github/kustomize/overlays/prod/ai-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/prod/ai-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ai-service
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: ai-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
limits:
|
||||
cpu: "4096m"
|
||||
memory: "4096Mi"
|
||||
17
.github/kustomize/overlays/prod/analytics-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/prod/analytics-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: analytics-service
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: analytics-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
limits:
|
||||
cpu: "4096m"
|
||||
memory: "4096Mi"
|
||||
17
.github/kustomize/overlays/prod/content-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/prod/content-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: content-service
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: content-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
limits:
|
||||
cpu: "4096m"
|
||||
memory: "4096Mi"
|
||||
17
.github/kustomize/overlays/prod/distribution-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/prod/distribution-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: distribution-service
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: distribution-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
limits:
|
||||
cpu: "4096m"
|
||||
memory: "4096Mi"
|
||||
17
.github/kustomize/overlays/prod/event-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/prod/event-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: event-service
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: event-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
limits:
|
||||
cpu: "4096m"
|
||||
memory: "4096Mi"
|
||||
38
.github/kustomize/overlays/prod/kustomization.yaml
vendored
Normal file
38
.github/kustomize/overlays/prod/kustomization.yaml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: kt-event-marketing
|
||||
|
||||
bases:
|
||||
- ../../base
|
||||
|
||||
# Environment-specific labels
|
||||
commonLabels:
|
||||
environment: prod
|
||||
|
||||
# Environment-specific patches
|
||||
patchesStrategicMerge:
|
||||
- user-service-patch.yaml
|
||||
- event-service-patch.yaml
|
||||
- ai-service-patch.yaml
|
||||
- content-service-patch.yaml
|
||||
- distribution-service-patch.yaml
|
||||
- participation-service-patch.yaml
|
||||
- analytics-service-patch.yaml
|
||||
|
||||
# Override image tags for prod environment
|
||||
images:
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/user-service
|
||||
newTag: prod
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service
|
||||
newTag: prod
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/ai-service
|
||||
newTag: prod
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/content-service
|
||||
newTag: prod
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/distribution-service
|
||||
newTag: prod
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/participation-service
|
||||
newTag: prod
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service
|
||||
newTag: prod
|
||||
17
.github/kustomize/overlays/prod/participation-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/prod/participation-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: participation-service
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: participation-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
limits:
|
||||
cpu: "4096m"
|
||||
memory: "4096Mi"
|
||||
17
.github/kustomize/overlays/prod/user-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/prod/user-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: user-service
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: user-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
limits:
|
||||
cpu: "4096m"
|
||||
memory: "4096Mi"
|
||||
17
.github/kustomize/overlays/staging/ai-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/staging/ai-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ai-service
|
||||
spec:
|
||||
replicas: 2
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: ai-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "512m"
|
||||
memory: "512Mi"
|
||||
limits:
|
||||
cpu: "2048m"
|
||||
memory: "2048Mi"
|
||||
17
.github/kustomize/overlays/staging/analytics-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/staging/analytics-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: analytics-service
|
||||
spec:
|
||||
replicas: 2
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: analytics-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "512m"
|
||||
memory: "512Mi"
|
||||
limits:
|
||||
cpu: "2048m"
|
||||
memory: "2048Mi"
|
||||
17
.github/kustomize/overlays/staging/content-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/staging/content-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: content-service
|
||||
spec:
|
||||
replicas: 2
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: content-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "512m"
|
||||
memory: "512Mi"
|
||||
limits:
|
||||
cpu: "2048m"
|
||||
memory: "2048Mi"
|
||||
17
.github/kustomize/overlays/staging/distribution-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/staging/distribution-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: distribution-service
|
||||
spec:
|
||||
replicas: 2
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: distribution-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "512m"
|
||||
memory: "512Mi"
|
||||
limits:
|
||||
cpu: "2048m"
|
||||
memory: "2048Mi"
|
||||
17
.github/kustomize/overlays/staging/event-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/staging/event-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: event-service
|
||||
spec:
|
||||
replicas: 2
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: event-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "512m"
|
||||
memory: "512Mi"
|
||||
limits:
|
||||
cpu: "2048m"
|
||||
memory: "2048Mi"
|
||||
38
.github/kustomize/overlays/staging/kustomization.yaml
vendored
Normal file
38
.github/kustomize/overlays/staging/kustomization.yaml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: kt-event-marketing
|
||||
|
||||
bases:
|
||||
- ../../base
|
||||
|
||||
# Environment-specific labels
|
||||
commonLabels:
|
||||
environment: staging
|
||||
|
||||
# Environment-specific patches
|
||||
patchesStrategicMerge:
|
||||
- user-service-patch.yaml
|
||||
- event-service-patch.yaml
|
||||
- ai-service-patch.yaml
|
||||
- content-service-patch.yaml
|
||||
- distribution-service-patch.yaml
|
||||
- participation-service-patch.yaml
|
||||
- analytics-service-patch.yaml
|
||||
|
||||
# Override image tags for staging environment
|
||||
images:
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/user-service
|
||||
newTag: staging
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service
|
||||
newTag: staging
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/ai-service
|
||||
newTag: staging
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/content-service
|
||||
newTag: staging
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/distribution-service
|
||||
newTag: staging
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/participation-service
|
||||
newTag: staging
|
||||
- name: acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service
|
||||
newTag: staging
|
||||
17
.github/kustomize/overlays/staging/participation-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/staging/participation-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: participation-service
|
||||
spec:
|
||||
replicas: 2
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: participation-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "512m"
|
||||
memory: "512Mi"
|
||||
limits:
|
||||
cpu: "2048m"
|
||||
memory: "2048Mi"
|
||||
17
.github/kustomize/overlays/staging/user-service-patch.yaml
vendored
Normal file
17
.github/kustomize/overlays/staging/user-service-patch.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: user-service
|
||||
spec:
|
||||
replicas: 2
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: user-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "512m"
|
||||
memory: "512Mi"
|
||||
limits:
|
||||
cpu: "2048m"
|
||||
memory: "2048Mi"
|
||||
79
.github/scripts/copy-manifests-to-base.py
vendored
Normal file
79
.github/scripts/copy-manifests-to-base.py
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Copy K8s manifests to Kustomize base directory and remove namespace declarations
|
||||
"""
|
||||
import os
|
||||
import shutil
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
|
||||
# Service names
|
||||
SERVICES = [
|
||||
'user-service',
|
||||
'event-service',
|
||||
'ai-service',
|
||||
'content-service',
|
||||
'distribution-service',
|
||||
'participation-service',
|
||||
'analytics-service'
|
||||
]
|
||||
|
||||
# Base directories
|
||||
SOURCE_DIR = Path('deployment/k8s')
|
||||
BASE_DIR = Path('.github/kustomize/base')
|
||||
|
||||
def remove_namespace_from_yaml(content):
|
||||
"""Remove namespace field from YAML content"""
|
||||
docs = list(yaml.safe_load_all(content))
|
||||
|
||||
for doc in docs:
|
||||
if doc and isinstance(doc, dict):
|
||||
if 'metadata' in doc and 'namespace' in doc['metadata']:
|
||||
del doc['metadata']['namespace']
|
||||
|
||||
return yaml.dump_all(docs, default_flow_style=False, sort_keys=False)
|
||||
|
||||
def copy_and_process_file(source_path, dest_path):
|
||||
"""Copy file and remove namespace declaration"""
|
||||
with open(source_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Remove namespace from YAML
|
||||
processed_content = remove_namespace_from_yaml(content)
|
||||
|
||||
# Write to destination
|
||||
dest_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(dest_path, 'w', encoding='utf-8') as f:
|
||||
f.write(processed_content)
|
||||
|
||||
print(f"✓ Copied and processed: {source_path} -> {dest_path}")
|
||||
|
||||
def main():
|
||||
print("Starting manifest copy to Kustomize base...")
|
||||
|
||||
# Copy common resources
|
||||
print("\n[Common Resources]")
|
||||
common_dir = SOURCE_DIR / 'common'
|
||||
for file in ['cm-common.yaml', 'secret-common.yaml', 'secret-imagepull.yaml', 'ingress.yaml']:
|
||||
source = common_dir / file
|
||||
if source.exists():
|
||||
dest = BASE_DIR / file
|
||||
copy_and_process_file(source, dest)
|
||||
|
||||
# Copy service-specific resources
|
||||
print("\n[Service Resources]")
|
||||
for service in SERVICES:
|
||||
service_dir = SOURCE_DIR / service
|
||||
if not service_dir.exists():
|
||||
print(f"⚠ Service directory not found: {service_dir}")
|
||||
continue
|
||||
|
||||
print(f"\nProcessing {service}...")
|
||||
for file in service_dir.glob('*.yaml'):
|
||||
dest = BASE_DIR / f"{service}-{file.name}"
|
||||
copy_and_process_file(file, dest)
|
||||
|
||||
print("\n✅ All manifests copied to base directory!")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
181
.github/scripts/deploy.sh
vendored
Normal file
181
.github/scripts/deploy.sh
vendored
Normal file
@ -0,0 +1,181 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
###############################################################################
|
||||
# Backend Services Deployment Script for AKS
|
||||
#
|
||||
# Usage:
|
||||
# ./deploy.sh <environment> [service-name]
|
||||
#
|
||||
# Arguments:
|
||||
# environment - Target environment (dev, staging, prod)
|
||||
# service-name - Specific service to deploy (optional, deploys all if not specified)
|
||||
#
|
||||
# Examples:
|
||||
# ./deploy.sh dev # Deploy all services to dev
|
||||
# ./deploy.sh prod user-service # Deploy only user-service to prod
|
||||
###############################################################################
|
||||
|
||||
# Color output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Functions
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Validate arguments
|
||||
if [ $# -lt 1 ]; then
|
||||
log_error "Usage: $0 <environment> [service-name]"
|
||||
log_error "Environment must be one of: dev, staging, prod"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ENVIRONMENT=$1
|
||||
SERVICE=${2:-all}
|
||||
|
||||
# Validate environment
|
||||
if [[ ! "$ENVIRONMENT" =~ ^(dev|staging|prod)$ ]]; then
|
||||
log_error "Invalid environment: $ENVIRONMENT"
|
||||
log_error "Must be one of: dev, staging, prod"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Load environment variables
|
||||
ENV_FILE=".github/config/deploy_env_vars_${ENVIRONMENT}"
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
log_error "Environment file not found: $ENV_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$ENV_FILE"
|
||||
log_info "Loaded environment configuration: $ENVIRONMENT"
|
||||
|
||||
# Service list
|
||||
SERVICES=(
|
||||
"user-service"
|
||||
"event-service"
|
||||
"ai-service"
|
||||
"content-service"
|
||||
"distribution-service"
|
||||
"participation-service"
|
||||
"analytics-service"
|
||||
)
|
||||
|
||||
# Validate service if specified
|
||||
if [ "$SERVICE" != "all" ]; then
|
||||
if [[ ! " ${SERVICES[@]} " =~ " ${SERVICE} " ]]; then
|
||||
log_error "Invalid service: $SERVICE"
|
||||
log_error "Must be one of: ${SERVICES[*]}"
|
||||
exit 1
|
||||
fi
|
||||
SERVICES=("$SERVICE")
|
||||
fi
|
||||
|
||||
log_info "Services to deploy: ${SERVICES[*]}"
|
||||
|
||||
# Check prerequisites
|
||||
log_info "Checking prerequisites..."
|
||||
|
||||
if ! command -v az &> /dev/null; then
|
||||
log_error "Azure CLI not found. Please install Azure CLI."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v kubectl &> /dev/null; then
|
||||
log_error "kubectl not found. Please install kubectl."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v kustomize &> /dev/null; then
|
||||
log_error "kustomize not found. Please install kustomize."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Azure login check
|
||||
log_info "Checking Azure authentication..."
|
||||
if ! az account show &> /dev/null; then
|
||||
log_error "Not logged in to Azure. Please run 'az login'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get AKS credentials
|
||||
log_info "Getting AKS credentials..."
|
||||
az aks get-credentials \
|
||||
--resource-group "$RESOURCE_GROUP" \
|
||||
--name "$AKS_CLUSTER" \
|
||||
--overwrite-existing
|
||||
|
||||
# Check namespace
|
||||
log_info "Checking namespace: $NAMESPACE"
|
||||
if ! kubectl get namespace "$NAMESPACE" &> /dev/null; then
|
||||
log_warn "Namespace $NAMESPACE does not exist. Creating..."
|
||||
kubectl create namespace "$NAMESPACE"
|
||||
fi
|
||||
|
||||
# Build and deploy with Kustomize
|
||||
OVERLAY_DIR=".github/kustomize/overlays/${ENVIRONMENT}"
|
||||
if [ ! -d "$OVERLAY_DIR" ]; then
|
||||
log_error "Kustomize overlay directory not found: $OVERLAY_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Building Kustomize manifests for $ENVIRONMENT..."
|
||||
cd "$OVERLAY_DIR"
|
||||
|
||||
# Update image tags
|
||||
log_info "Updating image tags to: $ENVIRONMENT"
|
||||
kustomize edit set image \
|
||||
${ACR_NAME}.azurecr.io/kt-event-marketing/user-service:${ENVIRONMENT} \
|
||||
${ACR_NAME}.azurecr.io/kt-event-marketing/event-service:${ENVIRONMENT} \
|
||||
${ACR_NAME}.azurecr.io/kt-event-marketing/ai-service:${ENVIRONMENT} \
|
||||
${ACR_NAME}.azurecr.io/kt-event-marketing/content-service:${ENVIRONMENT} \
|
||||
${ACR_NAME}.azurecr.io/kt-event-marketing/distribution-service:${ENVIRONMENT} \
|
||||
${ACR_NAME}.azurecr.io/kt-event-marketing/participation-service:${ENVIRONMENT} \
|
||||
${ACR_NAME}.azurecr.io/kt-event-marketing/analytics-service:${ENVIRONMENT}
|
||||
|
||||
# Apply manifests
|
||||
log_info "Applying manifests to AKS..."
|
||||
kustomize build . | kubectl apply -f -
|
||||
|
||||
cd - > /dev/null
|
||||
|
||||
# Wait for deployments
|
||||
log_info "Waiting for deployments to be ready..."
|
||||
for service in "${SERVICES[@]}"; do
|
||||
log_info "Waiting for $service deployment..."
|
||||
if ! kubectl rollout status deployment/"$service" -n "$NAMESPACE" --timeout=5m; then
|
||||
log_error "Deployment of $service failed!"
|
||||
exit 1
|
||||
fi
|
||||
log_info "✓ $service is ready"
|
||||
done
|
||||
|
||||
# Verify deployment
|
||||
log_info "Verifying deployment..."
|
||||
echo ""
|
||||
echo "=== Pods Status ==="
|
||||
kubectl get pods -n "$NAMESPACE" -l app.kubernetes.io/part-of=kt-event-marketing
|
||||
|
||||
echo ""
|
||||
echo "=== Services ==="
|
||||
kubectl get svc -n "$NAMESPACE"
|
||||
|
||||
echo ""
|
||||
echo "=== Ingress ==="
|
||||
kubectl get ingress -n "$NAMESPACE"
|
||||
|
||||
log_info "Deployment completed successfully!"
|
||||
log_info "Environment: $ENVIRONMENT"
|
||||
log_info "Services: ${SERVICES[*]}"
|
||||
51
.github/scripts/generate-patches.sh
vendored
Normal file
51
.github/scripts/generate-patches.sh
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
|
||||
SERVICES=(user-service event-service ai-service content-service distribution-service participation-service analytics-service)
|
||||
|
||||
# Staging patches (2 replicas, increased resources)
|
||||
for service in "${SERVICES[@]}"; do
|
||||
cat > ".github/kustomize/overlays/staging/${service}-patch.yaml" << YAML
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ${service}
|
||||
spec:
|
||||
replicas: 2
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: ${service}
|
||||
resources:
|
||||
requests:
|
||||
cpu: "512m"
|
||||
memory: "512Mi"
|
||||
limits:
|
||||
cpu: "2048m"
|
||||
memory: "2048Mi"
|
||||
YAML
|
||||
done
|
||||
|
||||
# Prod patches (3 replicas, maximum resources)
|
||||
for service in "${SERVICES[@]}"; do
|
||||
cat > ".github/kustomize/overlays/prod/${service}-patch.yaml" << YAML
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ${service}
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: ${service}
|
||||
resources:
|
||||
requests:
|
||||
cpu: "1024m"
|
||||
memory: "1024Mi"
|
||||
limits:
|
||||
cpu: "4096m"
|
||||
memory: "4096Mi"
|
||||
YAML
|
||||
done
|
||||
|
||||
echo "✅ Generated all patch files for staging and prod"
|
||||
207
.github/workflows/backend-cicd.yaml
vendored
Normal file
207
.github/workflows/backend-cicd.yaml
vendored
Normal file
@ -0,0 +1,207 @@
|
||||
name: Backend CI/CD Pipeline
|
||||
|
||||
on:
|
||||
# push:
|
||||
# branches:
|
||||
# - develop
|
||||
# - main
|
||||
# paths:
|
||||
# - '*-service/**'
|
||||
# - '.github/workflows/backend-cicd.yaml'
|
||||
# - '.github/kustomize/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- develop
|
||||
- main
|
||||
paths:
|
||||
- '*-service/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: 'Target environment'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- dev
|
||||
- staging
|
||||
- prod
|
||||
service:
|
||||
description: 'Service to deploy (all for all services)'
|
||||
required: true
|
||||
default: 'all'
|
||||
|
||||
env:
|
||||
ACR_NAME: acrdigitalgarage01
|
||||
RESOURCE_GROUP: rg-digitalgarage-01
|
||||
AKS_CLUSTER: aks-digitalgarage-01
|
||||
NAMESPACE: kt-event-marketing
|
||||
JDK_VERSION: '21'
|
||||
|
||||
jobs:
|
||||
detect-changes:
|
||||
name: Detect Changed Services
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
services: ${{ steps.detect.outputs.services }}
|
||||
environment: ${{ steps.env.outputs.environment }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Determine environment
|
||||
id: env
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
echo "environment=${{ github.event.inputs.environment }}" >> $GITHUB_OUTPUT
|
||||
elif [ "${{ github.ref }}" = "refs/heads/main" ]; then
|
||||
echo "environment=prod" >> $GITHUB_OUTPUT
|
||||
elif [ "${{ github.ref }}" = "refs/heads/develop" ]; then
|
||||
echo "environment=dev" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "environment=dev" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Detect changed services
|
||||
id: detect
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ github.event.inputs.service }}" != "all" ]; then
|
||||
echo "services=[\"${{ github.event.inputs.service }}\"]" >> $GITHUB_OUTPUT
|
||||
elif [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ github.event.inputs.service }}" = "all" ]; then
|
||||
echo "services=[\"user-service\",\"event-service\",\"ai-service\",\"content-service\",\"distribution-service\",\"participation-service\",\"analytics-service\"]" >> $GITHUB_OUTPUT
|
||||
else
|
||||
CHANGED_SERVICES=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} | \
|
||||
grep -E '^(user|event|ai|content|distribution|participation|analytics)-service/' | \
|
||||
cut -d'/' -f1 | sort -u | \
|
||||
jq -R -s -c 'split("\n") | map(select(length > 0))')
|
||||
|
||||
if [ "$CHANGED_SERVICES" = "[]" ] || [ -z "$CHANGED_SERVICES" ]; then
|
||||
echo "services=[\"user-service\",\"event-service\",\"ai-service\",\"content-service\",\"distribution-service\",\"participation-service\",\"analytics-service\"]" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "services=$CHANGED_SERVICES" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
fi
|
||||
|
||||
build-and-push:
|
||||
name: Build and Push - ${{ matrix.service }}
|
||||
needs: detect-changes
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
service: ${{ fromJson(needs.detect-changes.outputs.services) }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up JDK ${{ env.JDK_VERSION }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ env.JDK_VERSION }}
|
||||
distribution: 'temurin'
|
||||
cache: 'gradle'
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew ${{ matrix.service }}:build -x test
|
||||
|
||||
# - name: Run tests
|
||||
# run: ./gradlew ${{ matrix.service }}:test
|
||||
|
||||
- name: Build JAR
|
||||
run: ./gradlew ${{ matrix.service }}:bootJar
|
||||
|
||||
- name: Log in to Azure Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.ACR_NAME }}.azurecr.io
|
||||
username: ${{ secrets.ACR_USERNAME }}
|
||||
password: ${{ secrets.ACR_PASSWORD }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./${{ matrix.service }}
|
||||
file: ./${{ matrix.service }}/Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.ACR_NAME }}.azurecr.io/kt-event-marketing/${{ matrix.service }}:${{ needs.detect-changes.outputs.environment }}
|
||||
${{ env.ACR_NAME }}.azurecr.io/kt-event-marketing/${{ matrix.service }}:${{ github.sha }}
|
||||
${{ env.ACR_NAME }}.azurecr.io/kt-event-marketing/${{ matrix.service }}:latest
|
||||
|
||||
deploy:
|
||||
name: Deploy to AKS - ${{ needs.detect-changes.outputs.environment }}
|
||||
needs: [detect-changes, build-and-push]
|
||||
runs-on: ubuntu-latest
|
||||
environment: ${{ needs.detect-changes.outputs.environment }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Azure login
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
- name: Get AKS credentials
|
||||
run: |
|
||||
az aks get-credentials \
|
||||
--resource-group ${{ env.RESOURCE_GROUP }} \
|
||||
--name ${{ env.AKS_CLUSTER }} \
|
||||
--overwrite-existing
|
||||
|
||||
- name: Setup Kustomize
|
||||
uses: imranismail/setup-kustomize@v2
|
||||
|
||||
- name: Deploy with Kustomize
|
||||
run: |
|
||||
cd .github/kustomize/overlays/${{ needs.detect-changes.outputs.environment }}
|
||||
kustomize edit set image \
|
||||
acrdigitalgarage01.azurecr.io/kt-event-marketing/user-service:${{ needs.detect-changes.outputs.environment }} \
|
||||
acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service:${{ needs.detect-changes.outputs.environment }} \
|
||||
acrdigitalgarage01.azurecr.io/kt-event-marketing/ai-service:${{ needs.detect-changes.outputs.environment }} \
|
||||
acrdigitalgarage01.azurecr.io/kt-event-marketing/content-service:${{ needs.detect-changes.outputs.environment }} \
|
||||
acrdigitalgarage01.azurecr.io/kt-event-marketing/distribution-service:${{ needs.detect-changes.outputs.environment }} \
|
||||
acrdigitalgarage01.azurecr.io/kt-event-marketing/participation-service:${{ needs.detect-changes.outputs.environment }} \
|
||||
acrdigitalgarage01.azurecr.io/kt-event-marketing/analytics-service:${{ needs.detect-changes.outputs.environment }}
|
||||
|
||||
kustomize build . | kubectl apply -f -
|
||||
|
||||
- name: Wait for deployment rollout
|
||||
run: |
|
||||
for service in $(echo '${{ needs.detect-changes.outputs.services }}' | jq -r '.[]'); do
|
||||
echo "Waiting for ${service} deployment..."
|
||||
kubectl rollout status deployment/${service} -n ${{ env.NAMESPACE }} --timeout=5m
|
||||
done
|
||||
|
||||
- name: Verify deployment
|
||||
run: |
|
||||
echo "=== Pods Status ==="
|
||||
kubectl get pods -n ${{ env.NAMESPACE }} -l app.kubernetes.io/part-of=kt-event-marketing
|
||||
|
||||
echo "=== Services ==="
|
||||
kubectl get svc -n ${{ env.NAMESPACE }}
|
||||
|
||||
echo "=== Ingress ==="
|
||||
kubectl get ingress -n ${{ env.NAMESPACE }}
|
||||
|
||||
notify:
|
||||
name: Notify Deployment Result
|
||||
needs: [detect-changes, deploy]
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
steps:
|
||||
- name: Deployment Success
|
||||
if: needs.deploy.result == 'success'
|
||||
run: |
|
||||
echo "✅ Deployment to ${{ needs.detect-changes.outputs.environment }} succeeded!"
|
||||
echo "Services: ${{ needs.detect-changes.outputs.services }}"
|
||||
|
||||
- name: Deployment Failure
|
||||
if: needs.deploy.result == 'failure'
|
||||
run: |
|
||||
echo "❌ Deployment to ${{ needs.detect-changes.outputs.environment }} failed!"
|
||||
echo "Services: ${{ needs.detect-changes.outputs.services }}"
|
||||
exit 1
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
244
API-TEST-RESULT.md
Normal file
244
API-TEST-RESULT.md
Normal file
@ -0,0 +1,244 @@
|
||||
# API 연동 테스트 결과 보고서
|
||||
|
||||
**테스트 일시**: 2025-10-29
|
||||
**테스트 대상**: 프론트엔드(localhost:3000)와 event-service(localhost:8080) API 연동
|
||||
|
||||
---
|
||||
|
||||
## ✅ 테스트 결과 요약
|
||||
|
||||
### 1. 서비스 실행 상태
|
||||
- **프론트엔드**: ✅ Next.js 서버 (port 3000) 정상 실행
|
||||
- **백엔드**: ✅ Event-service (port 8080) 정상 실행
|
||||
- **데이터베이스**: ✅ PostgreSQL 연결 정상 (헬스체크 통과)
|
||||
|
||||
### 2. API 연동 테스트
|
||||
|
||||
#### 2.1 백엔드 API 직접 호출 테스트
|
||||
**테스트 명령어**:
|
||||
```bash
|
||||
curl -X GET "http://localhost:8080/api/v1/events?page=0&size=20" \
|
||||
-H "Authorization: Bearer <JWT_TOKEN>" \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
**결과**: ✅ **성공**
|
||||
- 응답 코드: 200 OK
|
||||
- 조회된 이벤트: 8개
|
||||
- 응답 형식: JSON (표준 API 응답 포맷)
|
||||
- 페이지네이션: 정상 작동
|
||||
|
||||
**샘플 응답 데이터**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"content": [
|
||||
{
|
||||
"eventId": "2a91c77c-9276-49d3-94d5-0ab8f0b3d343",
|
||||
"userId": "11111111-1111-1111-1111-111111111111",
|
||||
"storeId": "22222222-2222-2222-2222-222222222222",
|
||||
"objective": "awareness",
|
||||
"status": "DRAFT",
|
||||
"createdAt": "2025-10-29T11:08:38.556326"
|
||||
}
|
||||
// ... 7개 더
|
||||
],
|
||||
"page": 0,
|
||||
"size": 20,
|
||||
"totalElements": 8,
|
||||
"totalPages": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 인증 테스트
|
||||
**JWT 토큰**: ✅ 정상 작동
|
||||
- 토큰 생성 스크립트: `generate-test-token.py`
|
||||
- 유효 기간: 365일 (테스트용)
|
||||
- 알고리즘: HS256
|
||||
- Secret: 백엔드와 일치
|
||||
|
||||
#### 2.3 프론트엔드 설정
|
||||
**환경 변수 파일**: `.env.local` 생성 완료
|
||||
```env
|
||||
NEXT_PUBLIC_API_BASE_URL=http://localhost:8081
|
||||
NEXT_PUBLIC_EVENT_HOST=http://localhost:8080
|
||||
NEXT_PUBLIC_API_VERSION=v1
|
||||
```
|
||||
|
||||
**현재 상태**: ⚠️ **Mock 데이터 사용 중**
|
||||
- 파일: `src/app/(main)/events/page.tsx`
|
||||
- 이벤트 목록 페이지가 하드코딩된 Mock 데이터 표시
|
||||
- 실제 API 연동 코드 미구현 상태
|
||||
|
||||
---
|
||||
|
||||
## 📊 API 엔드포인트 정보
|
||||
|
||||
### Event Service (localhost:8080)
|
||||
|
||||
#### 1. 이벤트 목록 조회
|
||||
- **URL**: `GET /api/v1/events`
|
||||
- **인증**: Bearer Token 필수
|
||||
- **파라미터**:
|
||||
- `status`: EventStatus (optional) - DRAFT, PUBLISHED, ENDED
|
||||
- `search`: String (optional) - 검색어
|
||||
- `objective`: String (optional) - 목적 필터
|
||||
- `page`: int (default: 0)
|
||||
- `size`: int (default: 20)
|
||||
- `sort`: String (default: createdAt)
|
||||
- `order`: String (default: desc)
|
||||
|
||||
#### 2. 이벤트 상세 조회
|
||||
- **URL**: `GET /api/v1/events/{eventId}`
|
||||
- **인증**: Bearer Token 필수
|
||||
|
||||
#### 3. 이벤트 생성 (목적 선택)
|
||||
- **URL**: `POST /api/v1/events/objectives`
|
||||
- **인증**: Bearer Token 필수
|
||||
- **Request Body**:
|
||||
```json
|
||||
{
|
||||
"objective": "CUSTOMER_ACQUISITION"
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. 추가 엔드포인트
|
||||
- `DELETE /api/v1/events/{eventId}` - 이벤트 삭제
|
||||
- `POST /api/v1/events/{eventId}/publish` - 이벤트 배포
|
||||
- `POST /api/v1/events/{eventId}/end` - 이벤트 종료
|
||||
- `POST /api/v1/events/{eventId}/ai-recommendations` - AI 추천 요청
|
||||
- `POST /api/v1/events/{eventId}/images` - 이미지 생성 요청
|
||||
- `PUT /api/v1/events/{eventId}` - 이벤트 수정
|
||||
|
||||
---
|
||||
|
||||
## 🔍 발견 사항
|
||||
|
||||
### ✅ 정상 작동 항목
|
||||
1. **백엔드 서비스**
|
||||
- Event-service 정상 실행 (port 8080)
|
||||
- PostgreSQL 데이터베이스 연결 정상
|
||||
- API 엔드포인트 정상 응답
|
||||
- JWT 인증 시스템 작동
|
||||
|
||||
2. **프론트엔드 서비스**
|
||||
- Next.js 개발 서버 정상 실행 (port 3000)
|
||||
- 페이지 렌더링 정상
|
||||
- 환경 변수 설정 완료
|
||||
|
||||
### ⚠️ 개선 필요 항목
|
||||
|
||||
#### 1. 프론트엔드 API 연동 미구현
|
||||
**현재 상태**:
|
||||
- `src/app/(main)/events/page.tsx` 파일이 Mock 데이터 사용
|
||||
- 실제 API 호출 코드 없음
|
||||
|
||||
**권장 수정 사항**:
|
||||
```typescript
|
||||
// src/entities/event/api/eventApi.ts (신규 생성 필요)
|
||||
import { apiClient } from '@/shared/api';
|
||||
|
||||
export const eventApi = {
|
||||
getEvents: async (params) => {
|
||||
const response = await apiClient.get('/api/v1/events', { params });
|
||||
return response.data;
|
||||
},
|
||||
// ... 기타 메서드
|
||||
};
|
||||
```
|
||||
|
||||
#### 2. API 클라이언트 설정 개선
|
||||
**현재**:
|
||||
- `apiClient` 기본 URL이 user-service(8081)를 가리킴
|
||||
- Event API는 별도 서비스(8080)
|
||||
|
||||
**개선 방안**:
|
||||
```typescript
|
||||
// 서비스별 클라이언트 분리 또는
|
||||
// NEXT_PUBLIC_EVENT_HOST 환경 변수 활용
|
||||
const eventApiClient = axios.create({
|
||||
baseURL: process.env.NEXT_PUBLIC_EVENT_HOST || 'http://localhost:8080',
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 테스트 체크리스트
|
||||
|
||||
### 완료된 항목 ✅
|
||||
- [x] 백엔드 서비스 실행 상태 확인
|
||||
- [x] 프론트엔드 서비스 실행 상태 확인
|
||||
- [x] Event Service API 직접 호출 테스트
|
||||
- [x] JWT 인증 토큰 생성 및 테스트
|
||||
- [x] 환경 변수 설정 (`.env.local`)
|
||||
- [x] API 응답 형식 확인
|
||||
- [x] 페이지네이션 동작 확인
|
||||
- [x] 데이터베이스 연결 확인
|
||||
|
||||
### 추가 작업 필요 ⏳
|
||||
- [ ] 프론트엔드 API 연동 코드 작성
|
||||
- [ ] Event API 클라이언트 구현
|
||||
- [ ] React Query 또는 SWR 통합
|
||||
- [ ] 에러 핸들링 구현
|
||||
- [ ] 로딩 상태 UI 구현
|
||||
- [ ] 실제 데이터 렌더링 테스트
|
||||
- [ ] E2E 테스트 작성
|
||||
|
||||
---
|
||||
|
||||
## 🎯 다음 단계 권장사항
|
||||
|
||||
### 1단계: Event API 클라이언트 작성
|
||||
```bash
|
||||
# 파일 생성
|
||||
src/entities/event/api/eventApi.ts
|
||||
src/entities/event/model/types.ts
|
||||
```
|
||||
|
||||
### 2단계: React Query 설정
|
||||
```bash
|
||||
# useEvents 훅 작성
|
||||
src/entities/event/model/useEvents.ts
|
||||
```
|
||||
|
||||
### 3단계: 페이지 수정
|
||||
```bash
|
||||
# Mock 데이터를 실제 API 호출로 교체
|
||||
src/app/(main)/events/page.tsx
|
||||
```
|
||||
|
||||
### 4단계: 통합 테스트
|
||||
- 브라우저에서 실제 데이터 렌더링 확인
|
||||
- 필터링 및 검색 기능 테스트
|
||||
- 페이지네이션 동작 확인
|
||||
|
||||
---
|
||||
|
||||
## 📌 참고 정보
|
||||
|
||||
### 테스트 토큰 정보
|
||||
- User ID: `6db043d0-b303-4577-b9dd-6d366cc59fa0`
|
||||
- Store ID: `34000028-01fd-4ed1-975c-35f7c88b6547`
|
||||
- Email: `test@example.com`
|
||||
- 유효 기간: 2026-10-29까지
|
||||
|
||||
### 서비스 포트 매핑
|
||||
| 서비스 | 포트 | 상태 |
|
||||
|--------|------|------|
|
||||
| 프론트엔드 | 3000 | ✅ Running |
|
||||
| User Service | 8081 | ⚠️ 미확인 |
|
||||
| Event Service | 8080 | ✅ Running |
|
||||
| Content Service | 8082 | ⚠️ 미확인 |
|
||||
| AI Service | 8083 | ⚠️ 미확인 |
|
||||
| Participation Service | 8084 | ⚠️ 미확인 |
|
||||
|
||||
---
|
||||
|
||||
## ✨ 결론
|
||||
|
||||
**백엔드 API는 정상적으로 작동하고 있으며, 프론트엔드와의 연동을 위한 환경은 준비되었습니다.**
|
||||
|
||||
다음 작업은 프론트엔드에서 Mock 데이터를 실제 API 호출로 교체하는 것입니다.
|
||||
24
ai-service/Dockerfile
Normal file
24
ai-service/Dockerfile
Normal file
@ -0,0 +1,24 @@
|
||||
# Multi-stage build for Spring Boot application
|
||||
FROM eclipse-temurin:21-jre-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY build/libs/*.jar app.jar
|
||||
RUN java -Djarmode=layertools -jar app.jar extract
|
||||
|
||||
FROM eclipse-temurin:21-jre-alpine
|
||||
WORKDIR /app
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup -S spring && adduser -S spring -G spring
|
||||
USER spring:spring
|
||||
|
||||
# Copy layers from builder
|
||||
COPY --from=builder /app/dependencies/ ./
|
||||
COPY --from=builder /app/spring-boot-loader/ ./
|
||||
COPY --from=builder /app/snapshot-dependencies/ ./
|
||||
COPY --from=builder /app/application/ ./
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:8083/api/v1/ai-service/actuator/health || exit 1
|
||||
|
||||
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
|
||||
@ -37,7 +37,7 @@ spring:
|
||||
server:
|
||||
port: ${SERVER_PORT:8083}
|
||||
servlet:
|
||||
context-path: /
|
||||
context-path: /api/v1/ai-service
|
||||
encoding:
|
||||
charset: UTF-8
|
||||
enabled: true
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
<entry key="JWT_REFRESH_TOKEN_VALIDITY" value="86400" />
|
||||
|
||||
<!-- CORS Configuration -->
|
||||
<entry key="CORS_ALLOWED_ORIGINS" value="http://localhost:*" />
|
||||
<entry key="CORS_ALLOWED_ORIGINS" value="http://localhost:*,http://*.nip.io:*" />
|
||||
|
||||
<!-- Logging Configuration -->
|
||||
<entry key="LOG_FILE" value="logs/analytics-service.log" />
|
||||
|
||||
24
analytics-service/Dockerfile
Normal file
24
analytics-service/Dockerfile
Normal file
@ -0,0 +1,24 @@
|
||||
# Multi-stage build for Spring Boot application
|
||||
FROM eclipse-temurin:21-jre-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY build/libs/*.jar app.jar
|
||||
RUN java -Djarmode=layertools -jar app.jar extract
|
||||
|
||||
FROM eclipse-temurin:21-jre-alpine
|
||||
WORKDIR /app
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup -S spring && adduser -S spring -G spring
|
||||
USER spring:spring
|
||||
|
||||
# Copy layers from builder
|
||||
COPY --from=builder /app/dependencies/ ./
|
||||
COPY --from=builder /app/spring-boot-loader/ ./
|
||||
COPY --from=builder /app/snapshot-dependencies/ ./
|
||||
COPY --from=builder /app/application/ ./
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:8086/api/v1/analytics/actuator/health || exit 1
|
||||
|
||||
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
|
||||
@ -80,6 +80,7 @@ server:
|
||||
charset: UTF-8
|
||||
enabled: true
|
||||
force: true
|
||||
context-path: /api/v1/analytics
|
||||
|
||||
# JWT
|
||||
jwt:
|
||||
@ -89,7 +90,11 @@ jwt:
|
||||
|
||||
# CORS Configuration
|
||||
cors:
|
||||
allowed-origins: ${CORS_ALLOWED_ORIGINS:http://localhost:*}
|
||||
allowed-origins: ${CORS_ALLOWED_ORIGINS:http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://kt-event-marketing.20.214.196.128.nip.io}
|
||||
allowed-methods: ${CORS_ALLOWED_METHODS:GET,POST,PUT,DELETE,OPTIONS,PATCH}
|
||||
allowed-headers: ${CORS_ALLOWED_HEADERS:*}
|
||||
allow-credentials: ${CORS_ALLOW_CREDENTIALS:true}
|
||||
max-age: ${CORS_MAX_AGE:3600}
|
||||
|
||||
# Actuator
|
||||
management:
|
||||
|
||||
25
check-event-service.sh
Normal file
25
check-event-service.sh
Normal file
@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
echo "================================"
|
||||
echo "Event Service 시작 확인"
|
||||
echo "================================"
|
||||
echo ""
|
||||
|
||||
echo "1. 프로세스 확인..."
|
||||
jps -l | grep -i "EventServiceApplication" || echo "❌ 프로세스 없음"
|
||||
echo ""
|
||||
|
||||
echo "2. 포트 확인..."
|
||||
netstat -ano | findstr "LISTENING" | findstr ":8082" || echo "⚠️ 8082 포트 리스닝 없음"
|
||||
echo ""
|
||||
|
||||
echo "3. Health Check (8082 포트)..."
|
||||
curl -s http://localhost:8082/actuator/health 2>&1 | head -5
|
||||
echo ""
|
||||
|
||||
echo "4. 로그 확인 (최근 10줄)..."
|
||||
tail -10 logs/event-service.log
|
||||
echo ""
|
||||
|
||||
echo "================================"
|
||||
echo "확인 완료"
|
||||
echo "================================"
|
||||
68
claude/class-design.md
Normal file
68
claude/class-design.md
Normal file
@ -0,0 +1,68 @@
|
||||
# 클래스설계가이드
|
||||
|
||||
[요청사항]
|
||||
- <작성원칙>을 준용하여 설계
|
||||
- <작성순서>에 따라 설계
|
||||
- [결과파일] 안내에 따라 파일 작성
|
||||
|
||||
[가이드]
|
||||
<작성원칙>
|
||||
- **유저스토리와 매칭**되어야 함. **불필요한 추가 설계 금지**
|
||||
- API설계서와 일관성 있게 설계. Controller에 API를 누락하지 말고 모두 설계
|
||||
- Controller 클래스는 API로 정의하지 않은 메소드 생성 안함. 단, 필요한 Private 메소드는 추가함
|
||||
- {service-name}-simple.puml파일에 Note로 Controller 클래스 메소드와 API 매핑표 작성: {Methond}: {API Path} {API 제목}
|
||||
예) login: /login 로그인
|
||||
- 내부시퀀스설계서와 일관성 있게 설계
|
||||
- 각 서비스별 지정된 {설계 아키텍처 패턴}을 적용
|
||||
- Clean아키텍처 적용 시 Port/Adapter라는 용어 대신 Clean 아키텍처에 맞는 용어 사용
|
||||
- 클래스의 프라퍼티와 메소드를 모두 기술할 것. 단 "Getter/Setter 메소드"는 작성하지 않음
|
||||
- 클래스 간의 관계를 표현: Generalization, Realization, Dependency, Association, Aggregation, Composition
|
||||
|
||||
<작성순서>
|
||||
- **서브 에이전트를 활용한 병렬 작성 필수**
|
||||
- **3단계 하이브리드 접근법 적용**
|
||||
- **마이크로서비스 아키텍처 기반 설계**
|
||||
|
||||
- 1단계: 공통 컴포넌트 설계 (순차적)
|
||||
- 결과: design/backend/class/common-base.puml
|
||||
|
||||
- 2단계: 서비스별 병렬 설계 (병렬 실행)
|
||||
- 1단계 공통 컴포넌트 참조
|
||||
- '!include'는 사용하지 말고 필요한 인터페이스 직접 정의
|
||||
- 클래스 설계 후 프라퍼티와 메소드를 생략한 간단한 클래스설계서도 추가로 작성
|
||||
- 결과:
|
||||
- design/backend/class/{service-name}.puml
|
||||
- design/backend/class/{service-name}-simple.puml
|
||||
|
||||
- 병렬 처리 기준
|
||||
- 서비스 간 의존성이 없는 경우: 모든 서비스 동시 실행
|
||||
- 의존성이 있는 경우: 의존성 그룹별로 묶어서 실행
|
||||
- 예: A→B 의존 시, A 완료 후 B 실행
|
||||
- 독립 서비스 C,D는 A,B와 병렬 실행
|
||||
|
||||
- 3단계: 통합 및 검증 (순차적)
|
||||
- '패키지구조표준'의 예시를 참조하여 모든 클래스와 파일이 포함된 패키지 구조도를 작성
|
||||
(plantuml 스크립트가 아니라 트리구조 텍스트로 작성)
|
||||
- 인터페이스 일치성 검증
|
||||
- 명명 규칙 통일성 확인
|
||||
- 의존성 검증
|
||||
- 크로스 서비스 참조 검증
|
||||
- **PlantUML 스크립트 파일 검사 실행**: 'PlantUML문법검사가이드' 준용
|
||||
|
||||
[참고자료]
|
||||
- 유저스토리
|
||||
- API설계서
|
||||
- 내부시퀀스설계서
|
||||
- 패키지구조표준
|
||||
- PlantUML문법검사가이드
|
||||
|
||||
[예시]
|
||||
- 링크: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/samples/sample-클래스설계서.puml
|
||||
|
||||
[결과파일]
|
||||
- 패키지 구조도: design/backend/class/package-structure.md
|
||||
- 클래스설계서:
|
||||
- design/backend/class/common-base.puml
|
||||
- design/backend/class/{service-name}.puml
|
||||
- 클래스설계서(요약): design/backend/class/{service-name}-simple.puml
|
||||
- service-name은 영어로 작성 (예: profile, location, itinerary)
|
||||
55
claude/data-design.md
Normal file
55
claude/data-design.md
Normal file
@ -0,0 +1,55 @@
|
||||
# 데이터설계가이드
|
||||
|
||||
[요청사항]
|
||||
- <작성원칙>을 준용하여 설계
|
||||
- <작성순서>에 따라 설계
|
||||
- [결과파일] 안내에 따라 파일 작성
|
||||
|
||||
[가이드]
|
||||
<작성원칙>
|
||||
- **클래스설계서의 각 서비스별 Entity정의와 일치**해야 함. **불필요한 추가 설계 금지**
|
||||
- <데이터독립성원칙>에 따라 각 서비스마다 데이터베이스를 분리
|
||||
<작성순서>
|
||||
- 준비:
|
||||
- 유저스토리, API설계서, 외부시퀀스설계서, 내부시퀀스설계서, 패키지구조표준 분석 및 이해
|
||||
- 실행:
|
||||
- <병렬처리>안내에 따라 각 서비스별 병렬 수행
|
||||
- 데이터설계서 작성
|
||||
- 캐시 사용 시 캐시DB 설계 포함
|
||||
- 시작 부분에 '데이터설계 요약' 제공
|
||||
- 결과: {service-name}.md
|
||||
- ERD 작성
|
||||
- 결과: {service-name}-erd.puml
|
||||
- **PlantUML 스크립트 파일 생성 즉시 검사 실행**: 'PlantUML 문법 검사 가이드' 준용
|
||||
- 데이터베이스 스키마 스크립트 작성
|
||||
- 실행 가능한 SQL 스크립트 작성
|
||||
- 결과: {service-name}-schema.psql
|
||||
- 검토:
|
||||
- <작성원칙> 준수 검토
|
||||
- 스쿼드 팀원 리뷰: 누락 및 개선 사항 검토
|
||||
- 수정 사항 선택 및 반영
|
||||
|
||||
<병렬처리>
|
||||
Agent 1~N: 각 서비스별 데이터베이스 설계
|
||||
- 서비스별 독립적인 스키마 설계
|
||||
- Entity 클래스와 1:1 매핑
|
||||
- 서비스 간 데이터 공유 금지
|
||||
- FK 관계는 서비스 내부에서만 설정
|
||||
|
||||
<데이터독립성원칙>
|
||||
- **데이터 소유권**: 각 서비스가 자신의 데이터 완전 소유
|
||||
- **크로스 서비스 조인 금지**: 서비스 간 DB 조인 불가
|
||||
- **이벤트 기반 동기화**: 필요시 이벤트/메시지로 데이터 동기화
|
||||
- **캐시 활용**: 타 서비스 데이터는 캐시로만 참조
|
||||
|
||||
[참고자료]
|
||||
- 클래스설계서
|
||||
|
||||
[예시]
|
||||
- 링크: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/samples/sample-데이터설계서.puml
|
||||
|
||||
[결과파일]
|
||||
- design/backend/database/{service-name}.md
|
||||
- design/backend/database/{service-name}-erd.puml
|
||||
- design/backend/database/{service-name}-schema.psql
|
||||
- service-name은 영어로 작성
|
||||
770
claude/deploy-actions-cicd-back-guide.md
Normal file
770
claude/deploy-actions-cicd-back-guide.md
Normal file
@ -0,0 +1,770 @@
|
||||
# 백엔드 GitHub Actions 파이프라인 작성 가이드
|
||||
|
||||
[요청사항]
|
||||
- GitHub Actions 기반 CI/CD 파이프라인 구축 가이드 작성
|
||||
- 환경별(dev/staging/prod) Kustomize 매니페스트 관리 및 자동 배포 구현
|
||||
- SonarQube 코드 품질 분석과 Quality Gate 포함
|
||||
- Kustomize 매니페스트 생성부터 배포까지 전체 과정 안내
|
||||
- '[결과파일]'에 구축 방법 및 파이프라인 작성 가이드 생성
|
||||
- 아래 작업은 실제 수행하여 파일 생성
|
||||
- Kustomize 디렉토리 구조 생성
|
||||
- Base Kustomization 작성
|
||||
- 환경별 Overlay 작성
|
||||
- 환경별 Patch 파일 생성
|
||||
- GitHub Actions 워크플로우 파일 작성
|
||||
- 환경별 배포 변수 파일 작성
|
||||
- 수동 배포 스크립트 작성
|
||||
|
||||
[작업순서]
|
||||
- 사전 준비사항 확인
|
||||
프롬프트의 '[실행정보]'섹션에서 아래정보를 확인
|
||||
- {ACR_NAME}: Azure Container Registry 이름
|
||||
- {RESOURCE_GROUP}: Azure 리소스 그룹명
|
||||
- {AKS_CLUSTER}: AKS 클러스터명
|
||||
- {NAMESPACE}: Namespace명
|
||||
예시)
|
||||
```
|
||||
[실행정보]
|
||||
- ACR_NAME: acrdigitalgarage01
|
||||
- RESOURCE_GROUP: rg-digitalgarage-01
|
||||
- AKS_CLUSTER: aks-digitalgarage-01
|
||||
- NAMESPACE: phonebill-dg0500
|
||||
```
|
||||
|
||||
- 시스템명과 서비스명 확인
|
||||
settings.gradle에서 확인.
|
||||
- {SYSTEM_NAME}: rootProject.name
|
||||
- {SERVICE_NAMES}: include 'common'하위의 include문 뒤의 값임
|
||||
|
||||
예시) include 'common'하위의 서비스명들.
|
||||
```
|
||||
rootProject.name = 'phonebill'
|
||||
|
||||
include 'common'
|
||||
include 'api-gateway'
|
||||
include 'user-service'
|
||||
include 'order-service'
|
||||
include 'payment-service'
|
||||
```
|
||||
|
||||
- JDK버전 확인
|
||||
루트 build.gradle에서 JDK 버전 확인.
|
||||
{JDK_VERSION}: 'java' 섹션에서 JDK 버전 확인. 아래 예에서는 21임.
|
||||
```
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- GitHub 저장소 환경 구성 안내
|
||||
- GitHub Repository Secrets 설정
|
||||
- Azure 접근 인증정보 설정
|
||||
```
|
||||
# Azure Service Principal
|
||||
Repository Settings > Secrets and variables > Actions > Repository secrets에 등록
|
||||
|
||||
AZURE_CREDENTIALS:
|
||||
{
|
||||
"clientId": "{클라이언트ID}",
|
||||
"clientSecret": "{클라이언트시크릿}",
|
||||
"subscriptionId": "{구독ID}",
|
||||
"tenantId": "{테넌트ID}"
|
||||
}
|
||||
예시)
|
||||
{
|
||||
"clientId": "5e4b5b41-7208-48b7-b821-d6d5acf50ecf",
|
||||
"clientSecret": "ldu8Q~GQEzFYU.dJX7_QsahR7n7C2xqkIM6hqbV8",
|
||||
"subscriptionId": "2513dd36-7978-48e3-9a7c-b221d4874f66",
|
||||
"tenantId": "4f0a3bfd-1156-4cce-8dc2-a049a13dba23",
|
||||
}
|
||||
```
|
||||
|
||||
- ACR Credentials
|
||||
Credential 구하는 방법 안내
|
||||
az acr credential show --name {acr 이름}
|
||||
예) az acr credential show --name acrdigitalgarage01
|
||||
```
|
||||
ACR_USERNAME: {ACR_NAME}
|
||||
ACR_PASSWORD: {ACR패스워드}
|
||||
```
|
||||
- SonarQube URL과 인증 토큰
|
||||
SONAR_HOST_URL 구하는 방법과 SONAR_TOKEN 작성법 안내
|
||||
SONAR_HOST_URL: 아래 명령 수행 후 http://{External IP}를 지정
|
||||
k get svc -n sonarqube
|
||||
예) http://20.249.187.69
|
||||
|
||||
SONAR_TOKEN 값은 아래와 같이 작성
|
||||
- SonarQube 로그인 후 우측 상단 'Administrator' > My Account 클릭
|
||||
- Security 탭 선택 후 토큰 생성
|
||||
|
||||
```
|
||||
SONAR_TOKEN: {SonarQube토큰}
|
||||
SONAR_HOST_URL: {SonarQube서버URL}
|
||||
```
|
||||
|
||||
- Docker Hub (Rate Limit 해결용)
|
||||
Docker Hub 패스워드 작성 방법 안내
|
||||
- DockerHub(https://hub.docker.com)에 로그인
|
||||
- 우측 상단 프로필 아이콘 클릭 후 Account Settings를 선택
|
||||
- 좌측메뉴에서 'Personal Access Tokens' 클릭하여 생성
|
||||
```
|
||||
DOCKERHUB_USERNAME: {Docker Hub 사용자명}
|
||||
DOCKERHUB_PASSWORD: {Docker Hub 패스워드}
|
||||
```
|
||||
|
||||
- GitHub Repository Variables 설정
|
||||
```
|
||||
# Workflow 제어 변수
|
||||
Repository Settings > Secrets and variables > Actions > Variables > Repository variables에 등록
|
||||
|
||||
ENVIRONMENT: dev (기본값, 수동실행시 선택 가능: dev/staging/prod)
|
||||
SKIP_SONARQUBE: true (기본값, 수동실행시 선택 가능: true/false)
|
||||
```
|
||||
|
||||
**사용 방법:**
|
||||
- **자동 실행**: Push/PR 시 기본값 사용 (ENVIRONMENT=dev, SKIP_SONARQUBE=true)
|
||||
- **수동 실행**: Actions 탭 > "Backend Services CI/CD" > "Run workflow" 버튼 클릭
|
||||
- Environment: dev/staging/prod 선택
|
||||
- Skip SonarQube Analysis: true/false 선택
|
||||
|
||||
- Kustomize 디렉토리 구조 생성
|
||||
- GitHub Actions 전용 Kustomize 디렉토리 생성
|
||||
```bash
|
||||
mkdir -p .github/kustomize/{base,overlays/{dev,staging,prod}}
|
||||
mkdir -p .github/kustomize/base/{common,{서비스명1},{서비스명2},...}
|
||||
mkdir -p .github/{config,scripts}
|
||||
```
|
||||
- 기존 k8s 매니페스트를 base로 복사
|
||||
```bash
|
||||
# 기존 deployment/k8s/* 파일들을 base로 복사
|
||||
cp deployment/k8s/common/* .github/kustomize/base/common/
|
||||
cp deployment/k8s/{서비스명}/* .github/kustomize/base/{서비스명}/
|
||||
|
||||
# 네임스페이스 하드코딩 제거
|
||||
find .github/kustomize/base -name "*.yaml" -exec sed -i 's/namespace: .*//' {} \;
|
||||
```
|
||||
|
||||
- Base Kustomization 작성
|
||||
`.github/kustomize/base/kustomization.yaml` 파일 생성
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
metadata:
|
||||
name: {SYSTEM_NAME}-base
|
||||
|
||||
resources:
|
||||
# Common resources
|
||||
- common/configmap-common.yaml
|
||||
- common/secret-common.yaml
|
||||
- common/secret-imagepull.yaml
|
||||
- common/ingress.yaml
|
||||
|
||||
# 각 서비스별 리소스
|
||||
- {SERVICE_NAME}/deployment.yaml
|
||||
- {SERVICE_NAME}/service.yaml
|
||||
- {SERVICE_NAME}/configmap.yaml
|
||||
- {SERVICE_NAME}/secret.yaml
|
||||
|
||||
images:
|
||||
- name: {ACR_NAME}.azurecr.io/{SYSTEM_NAME}/{SERVICE_NAME}
|
||||
newTag: latest
|
||||
```
|
||||
|
||||
- 환경별 Patch 파일 생성
|
||||
각 환경별로 필요한 patch 파일들을 생성합니다.
|
||||
**중요원칙**:
|
||||
- **base 매니페스트에 없는 항목은 추가 안함**
|
||||
- **base 매니페스트와 항목이 일치해야 함**
|
||||
- Secret 매니페스트에 'data'가 아닌 'stringData'사용
|
||||
|
||||
**1. ConfigMap Common Patch 파일 생성**
|
||||
`.github/kustomize/overlays/{ENVIRONMENT}/cm-common-patch.yaml`
|
||||
|
||||
- base 매니페스트를 환경별로 복사
|
||||
```
|
||||
cp .github/kustomize/base/common/cm-common.yaml .github/kustomize/overlays/{ENVIRONMENT}/cm-common-patch.yaml
|
||||
```
|
||||
|
||||
- SPRING_PROFILES_ACTIVE를 환경에 맞게 설정 (dev/staging/prod)
|
||||
- DDL_AUTO 설정: dev는 "update", staging/prod는 "validate"
|
||||
- JWT 토큰 유효시간은 prod에서 보안을 위해 짧게 설정
|
||||
|
||||
**2. Secret Common Patch 파일 생성**
|
||||
`.github/kustomize/overlays/{ENVIRONMENT}/secret-common-patch.yaml`
|
||||
|
||||
- base 매니페스트를 환경별로 복사
|
||||
```
|
||||
cp .github/kustomize/base/common/secret-common.yaml .github/kustomize/overlays/{ENVIRONMENT}/secret-common-patch.yaml
|
||||
```
|
||||
|
||||
**3. Ingress Patch 파일 생성**
|
||||
`.github/kustomize/overlays/{ENVIRONMENT}/ingress-patch.yaml`
|
||||
- base의 ingress.yaml을 환경별로 오버라이드
|
||||
- **⚠️ 중요**: 개발환경 Ingress Host의 기본값은 base의 ingress.yaml과 **정확히 동일하게** 함
|
||||
- base에서 `host: {SYSTEM_NAME}-api.20.214.196.128.nip.io` 이면
|
||||
- dev에서도 `host: {SYSTEM_NAME}-api.20.214.196.128.nip.io` 로 동일하게 설정
|
||||
- **절대** `{SYSTEM_NAME}-dev-api.xxx` 처럼 변경하지 말 것
|
||||
- Staging/Prod 환경별 도메인 설정: {SYSTEM_NAME}.도메인 형식
|
||||
- service name을 '{서비스명}'으로 함.
|
||||
- Staging/prod 환경은 HTTPS 강제 적용 및 SSL 인증서 설정
|
||||
- staging/prod는 nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
- dev는 nginx.ingress.kubernetes.io/ssl-redirect: "false"
|
||||
|
||||
**4. deployment Patch 파일 생성** ⚠️ **중요**
|
||||
각 서비스별로 별도 파일 생성
|
||||
`.github/kustomize/overlays/{ENVIRONMENT}/deployment-{SERVICE_NAME}-patch.yaml`
|
||||
|
||||
**필수 포함 사항:**
|
||||
- ✅ **replicas 설정**: 각 서비스별 Deployment의 replica 수를 환경별로 설정
|
||||
- dev: 모든 서비스 1 replica (리소스 절약)
|
||||
- staging: 모든 서비스 2 replicas
|
||||
- prod: 모든 서비스 3 replicas
|
||||
- ✅ **resources 설정**: 각 서비스별 Deployment의 resources를 환경별로 설정
|
||||
- dev: requests(256m CPU, 256Mi Memory), limits(1024m CPU, 1024Mi Memory)
|
||||
- staging: requests(512m CPU, 512Mi Memory), limits(2048m CPU, 2048Mi Memory)
|
||||
- prod: requests(1024m CPU, 1024Mi Memory), limits(4096m CPU, 4096Mi Memory)
|
||||
|
||||
**5. Secret Service Patch 파일 생성**
|
||||
각 서비스별로 별도 파일 생성
|
||||
`.github/kustomize/overlays/{ENVIRONMENT}/secret-{SERVICE_NAME}-patch.yaml`
|
||||
|
||||
- base 매니페스트를 환경별로 복사
|
||||
```
|
||||
cp .github/kustomize/base/{SERVICE_NAME}/secret-{SERVICE_NAME}.yaml .github/kustomize/overlays/{ENVIRONMENT}/secret-{SERVICE_NAME}-patch.yaml
|
||||
```
|
||||
- 환경별 데이터베이스 연결 정보로 수정
|
||||
- **⚠️ 중요**: 패스워드 등 민감정보는 실제 환경 구축 시 별도 설정
|
||||
|
||||
- 환경별 Overlay 작성
|
||||
각 환경별로 `overlays/{환경}/kustomization.yaml` 생성
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: {NAMESPACE}
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
patches:
|
||||
- path: cm-common-patch.yaml
|
||||
target:
|
||||
kind: ConfigMap
|
||||
name: cm-common
|
||||
- path: deployment-{SERVICE_NAME}-patch.yaml
|
||||
target:
|
||||
kind: Deployment
|
||||
name: {SERVICE_NAME}
|
||||
- path: ingress-patch.yaml
|
||||
target:
|
||||
kind: Ingress
|
||||
name: {SYSTEM_NAME}
|
||||
- path: secret-common-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: secret-common
|
||||
- path: secret-{SERVICE_NAME}-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: secret-{SERVICE_NAME}
|
||||
|
||||
images:
|
||||
- name: {ACR_NAME}.azurecr.io/{SYSTEM_NAME}/{SERVICE_NAME}
|
||||
newTag: {ENVIRONMENT}-latest
|
||||
|
||||
```
|
||||
|
||||
- GitHub Actions 워크플로우 작성
|
||||
`.github/workflows/backend-cicd.yaml` 파일 생성 방법을 안내합니다.
|
||||
|
||||
주요 구성 요소:
|
||||
- **Build & Test**: Gradle 기반 빌드 및 단위 테스트
|
||||
- **SonarQube Analysis**: 코드 품질 분석 및 Quality Gate
|
||||
- **Container Build & Push**: 환경별 이미지 태그로 빌드 및 푸시
|
||||
- **Kustomize Deploy**: 환경별 매니페스트 적용
|
||||
|
||||
```yaml
|
||||
name: Backend Services CI/CD
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- '{서비스명1}/**'
|
||||
- '{서비스명2}/**'
|
||||
- '{서비스명3}/**'
|
||||
- '{서비스명N}/**'
|
||||
- 'common/**'
|
||||
- '.github/**'
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ENVIRONMENT:
|
||||
description: 'Target environment'
|
||||
required: true
|
||||
default: 'dev'
|
||||
type: choice
|
||||
options:
|
||||
- dev
|
||||
- staging
|
||||
- prod
|
||||
SKIP_SONARQUBE:
|
||||
description: 'Skip SonarQube Analysis'
|
||||
required: false
|
||||
default: 'true'
|
||||
type: choice
|
||||
options:
|
||||
- 'true'
|
||||
- 'false'
|
||||
|
||||
env:
|
||||
REGISTRY: ${{ secrets.REGISTRY }}
|
||||
IMAGE_ORG: ${{ secrets.IMAGE_ORG }}
|
||||
RESOURCE_GROUP: ${{ secrets.RESOURCE_GROUP }}
|
||||
AKS_CLUSTER: ${{ secrets.AKS_CLUSTER }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build and Test
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
image_tag: ${{ steps.set_outputs.outputs.image_tag }}
|
||||
environment: ${{ steps.set_outputs.outputs.environment }}
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up JDK {버전}
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '{JDK버전}'
|
||||
distribution: 'temurin'
|
||||
cache: 'gradle'
|
||||
|
||||
- name: Determine environment
|
||||
id: determine_env
|
||||
run: |
|
||||
# Use input parameter or default to 'dev'
|
||||
ENVIRONMENT="${{ github.event.inputs.ENVIRONMENT || 'dev' }}"
|
||||
echo "environment=$ENVIRONMENT" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Load environment variables
|
||||
id: env_vars
|
||||
run: |
|
||||
ENV=${{ steps.determine_env.outputs.environment }}
|
||||
|
||||
# Initialize variables with defaults
|
||||
REGISTRY="{ACR_NAME}.azurecr.io"
|
||||
IMAGE_ORG="{SYSTEM_NAME}"
|
||||
RESOURCE_GROUP="{RESOURCE_GROUP}"
|
||||
AKS_CLUSTER="{AKS_CLUSTER}"
|
||||
NAMESPACE="{NAMESPACE}"
|
||||
|
||||
# Read environment variables from .github/config file
|
||||
if [[ -f ".github/config/deploy_env_vars_${ENV}" ]]; then
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
# Skip comments and empty lines
|
||||
[[ "$line" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$line" ]] && continue
|
||||
|
||||
# Extract key-value pairs
|
||||
key=$(echo "$line" | cut -d '=' -f1)
|
||||
value=$(echo "$line" | cut -d '=' -f2-)
|
||||
|
||||
# Override defaults if found in config
|
||||
case "$key" in
|
||||
"resource_group") RESOURCE_GROUP="$value" ;;
|
||||
"cluster_name") AKS_CLUSTER="$value" ;;
|
||||
esac
|
||||
done < ".github/config/deploy_env_vars_${ENV}"
|
||||
fi
|
||||
|
||||
# Export for other jobs
|
||||
echo "REGISTRY=$REGISTRY" >> $GITHUB_ENV
|
||||
echo "IMAGE_ORG=$IMAGE_ORG" >> $GITHUB_ENV
|
||||
echo "RESOURCE_GROUP=$RESOURCE_GROUP" >> $GITHUB_ENV
|
||||
echo "AKS_CLUSTER=$AKS_CLUSTER" >> $GITHUB_ENV
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
./gradlew build -x test
|
||||
|
||||
- name: SonarQube Analysis & Quality Gate
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
|
||||
run: |
|
||||
# Check if SonarQube should be skipped
|
||||
SKIP_SONARQUBE="${{ github.event.inputs.SKIP_SONARQUBE || 'true' }}"
|
||||
|
||||
if [[ "$SKIP_SONARQUBE" == "true" ]]; then
|
||||
echo "⏭️ Skipping SonarQube Analysis (SKIP_SONARQUBE=$SKIP_SONARQUBE)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Define services array
|
||||
services=({SERVICE_NAME1} {SERVICE_NAME2} {SERVICE_NAME3} {SERVICE_NAMEN})
|
||||
|
||||
# Run tests, coverage reports, and SonarQube analysis for each service
|
||||
for service in "${services[@]}"; do
|
||||
./gradlew :$service:test :$service:jacocoTestReport :$service:sonar \
|
||||
-Dsonar.projectKey={SYSTEM_NAME}-$service-${{ steps.determine_env.outputs.environment }} \
|
||||
-Dsonar.projectName={SYSTEM_NAME}-$service-${{ steps.determine_env.outputs.environment }} \
|
||||
-Dsonar.host.url=$SONAR_HOST_URL \
|
||||
-Dsonar.token=$SONAR_TOKEN \
|
||||
-Dsonar.java.binaries=build/classes/java/main \
|
||||
-Dsonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml \
|
||||
-Dsonar.exclusions=**/config/**,**/entity/**,**/dto/**,**/*Application.class,**/exception/**
|
||||
done
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: app-builds
|
||||
path: |
|
||||
{SERVICE_NAME1}/build/libs/*.jar
|
||||
{SERVICE_NAME2}/build/libs/*.jar
|
||||
{SERVICE_NAME3}/build/libs/*.jar
|
||||
{SERVICE_NAMEN}/build/libs/*.jar
|
||||
|
||||
- name: Set outputs
|
||||
id: set_outputs
|
||||
run: |
|
||||
# Generate timestamp for image tag
|
||||
IMAGE_TAG=$(date +%Y%m%d%H%M%S)
|
||||
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
|
||||
echo "environment=${{ steps.determine_env.outputs.environment }}" >> $GITHUB_OUTPUT
|
||||
|
||||
release:
|
||||
name: Build and Push Docker Images
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: app-builds
|
||||
|
||||
- name: Set environment variables from build job
|
||||
run: |
|
||||
echo "REGISTRY=${{ needs.build.outputs.registry }}" >> $GITHUB_ENV
|
||||
echo "IMAGE_ORG=${{ needs.build.outputs.image_org }}" >> $GITHUB_ENV
|
||||
echo "ENVIRONMENT=${{ needs.build.outputs.environment }}" >> $GITHUB_ENV
|
||||
echo "IMAGE_TAG=${{ needs.build.outputs.image_tag }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub (prevent rate limit)
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Login to Azure Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.ACR_USERNAME }}
|
||||
password: ${{ secrets.ACR_PASSWORD }}
|
||||
|
||||
- name: Build and push Docker images for all services
|
||||
run: |
|
||||
# Define services array
|
||||
services=({SERVICE_NAME1} {SERVICE_NAME2} {SERVICE_NAME3} {SERVICE_NAMEN})
|
||||
|
||||
# Build and push each service image
|
||||
for service in "${services[@]}"; do
|
||||
echo "Building and pushing $service..."
|
||||
docker build \
|
||||
--build-arg BUILD_LIB_DIR="$service/build/libs" \
|
||||
--build-arg ARTIFACTORY_FILE="$service.jar" \
|
||||
-f deployment/container/Dockerfile-backend \
|
||||
-t ${{ env.REGISTRY }}/${{ env.IMAGE_ORG }}/$service:${{ needs.build.outputs.environment }}-${{ needs.build.outputs.image_tag }} .
|
||||
|
||||
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_ORG }}/$service:${{ needs.build.outputs.environment }}-${{ needs.build.outputs.image_tag }}
|
||||
done
|
||||
|
||||
deploy:
|
||||
name: Deploy to Kubernetes
|
||||
needs: [build, release]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set image tag environment variable
|
||||
run: |
|
||||
echo "IMAGE_TAG=${{ needs.build.outputs.image_tag }}" >> $GITHUB_ENV
|
||||
echo "ENVIRONMENT=${{ needs.build.outputs.environment }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Install Azure CLI
|
||||
run: |
|
||||
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
||||
|
||||
- name: Azure Login
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
- name: Setup kubectl
|
||||
uses: azure/setup-kubectl@v3
|
||||
|
||||
- name: Get AKS Credentials
|
||||
run: |
|
||||
az aks get-credentials --resource-group ${{ env.RESOURCE_GROUP }} --name ${{ env.AKS_CLUSTER }} --overwrite-existing
|
||||
|
||||
- name: Create namespace
|
||||
run: |
|
||||
kubectl create namespace ${{ env.NAMESPACE }} --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
- name: Install Kustomize
|
||||
run: |
|
||||
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
|
||||
sudo mv kustomize /usr/local/bin/
|
||||
|
||||
- name: Update Kustomize images and deploy
|
||||
run: |
|
||||
# 환경별 디렉토리로 이동
|
||||
cd deployment/cicd/kustomize/overlays/${{ env.ENVIRONMENT }}
|
||||
|
||||
# 각 서비스별 이미지 태그 업데이트
|
||||
kustomize edit set image ${{ env.REGISTRY }}/${{ env.IMAGE_ORG }}/api-gateway:${{ env.ENVIRONMENT }}-${{ env.IMAGE_TAG }}
|
||||
kustomize edit set image ${{ env.REGISTRY }}/${{ env.IMAGE_ORG }}/user-service:${{ env.ENVIRONMENT }}-${{ env.IMAGE_TAG }}
|
||||
kustomize edit set image ${{ env.REGISTRY }}/${{ env.IMAGE_ORG }}/bill-service:${{ env.ENVIRONMENT }}-${{ env.IMAGE_TAG }}
|
||||
kustomize edit set image ${{ env.REGISTRY }}/${{ env.IMAGE_ORG }}/product-service:${{ env.ENVIRONMENT }}-${{ env.IMAGE_TAG }}
|
||||
kustomize edit set image ${{ env.REGISTRY }}/${{ env.IMAGE_ORG }}/kos-mock:${{ env.ENVIRONMENT }}-${{ env.IMAGE_TAG }}
|
||||
|
||||
# 매니페스트 적용
|
||||
kubectl apply -k .
|
||||
|
||||
- name: Wait for deployments to be ready
|
||||
run: |
|
||||
echo "Waiting for deployments to be ready..."
|
||||
kubectl -n ${{ env.NAMESPACE }} wait --for=condition=available deployment/${{ env.ENVIRONMENT }}-api-gateway --timeout=300s
|
||||
kubectl -n ${{ env.NAMESPACE }} wait --for=condition=available deployment/${{ env.ENVIRONMENT }}-user-service --timeout=300s
|
||||
kubectl -n ${{ env.NAMESPACE }} wait --for=condition=available deployment/${{ env.ENVIRONMENT }}-bill-service --timeout=300s
|
||||
kubectl -n ${{ env.NAMESPACE }} wait --for=condition=available deployment/${{ env.ENVIRONMENT }}-product-service --timeout=300s
|
||||
kubectl -n ${{ env.NAMESPACE }} wait --for=condition=available deployment/${{ env.ENVIRONMENT }}-kos-mock --timeout=300s
|
||||
|
||||
```
|
||||
|
||||
- GitHub Actions 전용 환경별 설정 파일 작성
|
||||
`.github/config/deploy_env_vars_{환경}` 파일 생성 방법
|
||||
|
||||
**.github/config/deploy_env_vars_dev**
|
||||
```bash
|
||||
# dev Environment Configuration
|
||||
resource_group={RESOURCE_GROUP}
|
||||
cluster_name={AKS_CLUSTER}
|
||||
```
|
||||
|
||||
**.github/config/deploy_env_vars_staging**
|
||||
```bash
|
||||
# staging Environment Configuration
|
||||
resource_group={RESOURCE_GROUP}
|
||||
cluster_name={AKS_CLUSTER}
|
||||
```
|
||||
|
||||
**.github/config/deploy_env_vars_prod**
|
||||
```bash
|
||||
# prod Environment Configuration
|
||||
resource_group={RESOURCE_GROUP}
|
||||
cluster_name={AKS_CLUSTER}
|
||||
```
|
||||
|
||||
**참고**: Kustomize 방식에서는 namespace, replicas, resources 등은 kustomization.yaml과 patch 파일에서 관리됩니다.
|
||||
|
||||
- GitHub Actions 전용 수동 배포 스크립트 작성
|
||||
`.github/scripts/deploy-actions.sh` 파일 생성:
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
ENVIRONMENT=${1:-dev}
|
||||
IMAGE_TAG=${2:-latest}
|
||||
|
||||
echo "🚀 Manual deployment starting..."
|
||||
echo "Environment: $ENVIRONMENT"
|
||||
echo "Image Tag: $IMAGE_TAG"
|
||||
|
||||
# Check if kustomize is installed
|
||||
if ! command -v kustomize &> /dev/null; then
|
||||
echo "Installing Kustomize..."
|
||||
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
|
||||
sudo mv kustomize /usr/local/bin/
|
||||
fi
|
||||
|
||||
# Load environment variables from .github/config
|
||||
if [[ -f ".github/config/deploy_env_vars_${ENVIRONMENT}" ]]; then
|
||||
source ".github/config/deploy_env_vars_${ENVIRONMENT}"
|
||||
echo "✅ Environment variables loaded for $ENVIRONMENT"
|
||||
else
|
||||
echo "❌ Environment configuration file not found: .github/config/deploy_env_vars_${ENVIRONMENT}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create namespace
|
||||
echo "📝 Creating namespace {NAMESPACE}..."
|
||||
kubectl create namespace {NAMESPACE} --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# 환경별 이미지 태그 업데이트 (.github/kustomize 사용)
|
||||
cd .github/kustomize/overlays/${ENVIRONMENT}
|
||||
|
||||
echo "🔄 Updating image tags..."
|
||||
# 서비스 배열 정의
|
||||
services=({SERVICE_NAME1} {SERVICE_NAME2} {SERVICE_NAME3} {SERVICE_NAMEN})
|
||||
|
||||
# 각 서비스별 이미지 태그 업데이트
|
||||
for service in "${services[@]}"; do
|
||||
kustomize edit set image {ACR_NAME}.azurecr.io/{SYSTEM_NAME}/$service:${ENVIRONMENT}-${IMAGE_TAG}
|
||||
done
|
||||
|
||||
echo "🚀 Deploying to Kubernetes..."
|
||||
# 배포 실행
|
||||
kubectl apply -k .
|
||||
|
||||
echo "⏳ Waiting for deployments to be ready..."
|
||||
# 서비스별 배포 상태 확인
|
||||
for service in "${services[@]}"; do
|
||||
kubectl rollout status deployment/${ENVIRONMENT}-$service -n {NAMESPACE} --timeout=300s
|
||||
done
|
||||
|
||||
echo "🔍 Health check..."
|
||||
# API Gateway Health Check (첫 번째 서비스가 API Gateway라고 가정)
|
||||
GATEWAY_SERVICE=${services[0]}
|
||||
GATEWAY_POD=$(kubectl get pod -n {NAMESPACE} -l app.kubernetes.io/name=${ENVIRONMENT}-$GATEWAY_SERVICE -o jsonpath='{.items[0].metadata.name}')
|
||||
kubectl -n {NAMESPACE} exec $GATEWAY_POD -- curl -f http://localhost:8080/actuator/health || echo "Health check failed, but deployment completed"
|
||||
|
||||
echo "📋 Service Information:"
|
||||
kubectl get pods -n {NAMESPACE}
|
||||
kubectl get services -n {NAMESPACE}
|
||||
kubectl get ingress -n {NAMESPACE}
|
||||
|
||||
echo "✅ GitHub Actions deployment completed successfully!"
|
||||
```
|
||||
|
||||
- SonarQube 프로젝트 설정 방법 작성
|
||||
- SonarQube에서 각 서비스별 프로젝트 생성
|
||||
- Quality Gate 설정:
|
||||
```
|
||||
Coverage: >= 80%
|
||||
Duplicated Lines: <= 3%
|
||||
Maintainability Rating: <= A
|
||||
Reliability Rating: <= A
|
||||
Security Rating: <= A
|
||||
```
|
||||
|
||||
- 롤백 방법 작성
|
||||
- GitHub Actions에서 이전 버전으로 롤백:
|
||||
```bash
|
||||
# 이전 워크플로우 실행으로 롤백
|
||||
1. GitHub > Actions > 성공한 이전 워크플로우 선택
|
||||
2. Re-run all jobs 클릭
|
||||
```
|
||||
- kubectl을 이용한 롤백:
|
||||
```bash
|
||||
# 특정 버전으로 롤백
|
||||
kubectl rollout undo deployment/{환경}-{서비스명} -n {NAMESPACE} --to-revision=2
|
||||
|
||||
# 롤백 상태 확인
|
||||
kubectl rollout status deployment/{환경}-{서비스명} -n {NAMESPACE}
|
||||
```
|
||||
- 수동 스크립트를 이용한 롤백:
|
||||
```bash
|
||||
# 이전 안정 버전 이미지 태그로 배포
|
||||
./deployment/cicd/scripts/deploy-actions.sh {환경} {이전태그}
|
||||
```
|
||||
|
||||
[체크리스트]
|
||||
GitHub Actions CI/CD 파이프라인 구축 작업을 누락 없이 진행하기 위한 체크리스트입니다.
|
||||
|
||||
## 📋 사전 준비 체크리스트
|
||||
- [ ] settings.gradle에서 시스템명과 서비스명 확인 완료
|
||||
- [ ] 실행정보 섹션에서 ACR명, 리소스 그룹, AKS 클러스터명 확인 완료
|
||||
|
||||
## 📂 GitHub Actions 전용 Kustomize 구조 생성 체크리스트
|
||||
- [ ] 디렉토리 구조 생성: `.github/kustomize/{base,overlays/{dev,staging,prod}}`
|
||||
- [ ] 서비스별 base 디렉토리 생성: `.github/kustomize/base/{common,{서비스명들}}`
|
||||
- [ ] 기존 k8s 매니페스트를 base로 복사 완료
|
||||
- [ ] **리소스 누락 방지 검증 완료**:
|
||||
- [ ] `ls .github/kustomize/base/*/` 명령으로 모든 서비스 디렉토리의 파일 확인
|
||||
- [ ] 각 서비스별 필수 파일 존재 확인 (deployment.yaml, service.yaml 필수)
|
||||
- [ ] ConfigMap 파일 존재 시 `cm-{서비스명}.yaml` 명명 규칙 준수 확인
|
||||
- [ ] Secret 파일 존재 시 `secret-{서비스명}.yaml` 명명 규칙 준수 확인
|
||||
- [ ] Base kustomization.yaml 파일 생성 완료
|
||||
- [ ] 모든 서비스의 deployment.yaml, service.yaml 포함 확인
|
||||
- [ ] 존재하는 모든 ConfigMap 파일 포함 확인 (`cm-{서비스명}.yaml`)
|
||||
- [ ] 존재하는 모든 Secret 파일 포함 확인 (`secret-{서비스명}.yaml`)
|
||||
- [ ] **검증 명령어 실행 완료**:
|
||||
- [ ] `kubectl kustomize .github/kustomize/base/` 정상 실행 확인
|
||||
- [ ] 에러 메시지 없이 모든 리소스 출력 확인
|
||||
|
||||
## 🔧 GitHub Actions 전용 환경별 Overlay 구성 체크리스트
|
||||
### 중요 체크 사항
|
||||
- Base Kustomization에서 존재하지 않는 Secret 파일들 제거
|
||||
|
||||
### 공통 체크 사항
|
||||
- **base 매니페스트에 없는 항목을 추가하지 않았는지 체크**
|
||||
- **base 매니페스트와 항목이 일치 하는지 체크**
|
||||
- Secret 매니페스트에 'data'가 아닌 'stringData'사용했는지 체크
|
||||
- **⚠️ Kustomize patch 방법 변경**: `patchesStrategicMerge` → `patches` (target 명시)
|
||||
|
||||
### DEV 환경
|
||||
- [ ] `.github/kustomize/overlays/dev/kustomization.yaml` 생성 완료
|
||||
- [ ] `.github/kustomize/overlays/dev/cm-common-patch.yaml` 생성 완료 (dev 프로파일, update DDL)
|
||||
- [ ] `.github/kustomize/overlays/dev/secret-common-patch.yaml` 생성 완료
|
||||
- [ ] `.github/kustomize/overlays/dev/ingress-patch.yaml` 생성 완료 (**Host 기본값은 base의 ingress.yaml과 동일**)
|
||||
- [ ] `.github/kustomize/overlays/dev/deployment-{서비스명}-patch.yaml` 생성 완료 (replicas, resources 지정)
|
||||
- [ ] 각 서비스별 `.github/kustomize/overlays/dev/secret-{서비스명}-patch.yaml` 생성 완료
|
||||
|
||||
### STAGING 환경
|
||||
- [ ] `.github/kustomize/overlays/staging/kustomization.yaml` 생성 완료
|
||||
- [ ] `.github/kustomize/overlays/staging/cm-common-patch.yaml` 생성 완료 (staging 프로파일, validate DDL)
|
||||
- [ ] `.github/kustomize/overlays/staging/secret-common-patch.yaml` 생성 완료
|
||||
- [ ] `.github/kustomize/overlays/staging/ingress-patch.yaml` 생성 완료 (prod 도메인, HTTPS, SSL 인증서)
|
||||
- [ ] `.github/kustomize/overlays/staging/deployment-{서비스명}-patch.yaml` 생성 완료 (replicas, resources 지정)
|
||||
- [ ] 각 서비스별 `.github/kustomize/overlays/staging/secret-{서비스명}-patch.yaml` 생성 완료
|
||||
|
||||
### PROD 환경
|
||||
- [ ] `.github/kustomize/overlays/prod/kustomization.yaml` 생성 완료
|
||||
- [ ] `.github/kustomize/overlays/prod/cm-common-patch.yaml` 생성 완료 (prod 프로파일, validate DDL, 짧은 JWT)
|
||||
- [ ] `.github/kustomize/overlays/prod/secret-common-patch.yaml` 생성 완료
|
||||
- [ ] `.github/kustomize/overlays/prod/ingress-patch.yaml` 생성 완료 (prod 도메인, HTTPS, SSL 인증서)
|
||||
- [ ] `.github/kustomize/overlays/prod/deployment-{서비스명}-patch.yaml` 생성 완료 (replicas, resources 지정)
|
||||
- [ ] 각 서비스별 `.github/kustomize/overlays/prod/secret-{서비스명}-patch.yaml` 생성 완료
|
||||
|
||||
## ⚙️ GitHub Actions 설정 및 스크립트 체크리스트
|
||||
- [ ] 환경별 설정 파일 생성: `.github/config/deploy_env_vars_{dev,staging,prod}`
|
||||
- [ ] GitHub Actions 워크플로우 파일 `.github/workflows/backend-cicd.yaml` 생성 완료
|
||||
- [ ] 워크플로우 주요 내용 확인
|
||||
- Build, SonarQube, Docker Build & Push, Deploy 단계 포함
|
||||
- JDK 버전 확인: `java-version: '{JDK버전}'`
|
||||
- 변수 참조 문법 확인: `${{ needs.build.outputs.* }}` 사용
|
||||
- 모든 서비스명이 실제 프로젝트 서비스명으로 치환되었는지 확인
|
||||
- **환경 변수 SKIP_SONARQUBE 처리 확인**: 기본값 'true', 조건부 실행
|
||||
- **플레이스홀더 사용 확인**: {ACR_NAME}, {SYSTEM_NAME}, {SERVICE_NAME} 등
|
||||
|
||||
- [ ] 수동 배포 스크립트 `.github/scripts/deploy-actions.sh` 생성 완료
|
||||
- [ ] 스크립트 실행 권한 설정 완료 (`chmod +x .github/scripts/*.sh`)
|
||||
|
||||
[결과파일]
|
||||
- 가이드: .github/actions-pipeline-guide.md
|
||||
- GitHub Actions 워크플로우: .github/workflows/backend-cicd.yaml
|
||||
- GitHub Actions 전용 Kustomize 매니페스트: .github/kustomize/*
|
||||
- GitHub Actions 전용 환경별 설정 파일: .github/config/*
|
||||
- GitHub Actions 전용 수동배포 스크립트: .github/scripts/deploy-actions.sh
|
||||
425
claude/highlevel-architecture-template.md
Normal file
425
claude/highlevel-architecture-template.md
Normal file
@ -0,0 +1,425 @@
|
||||
# High Level 아키텍처 정의서
|
||||
|
||||
## 1. 개요 (Executive Summary)
|
||||
|
||||
### 1.1 프로젝트 개요
|
||||
- **비즈니스 목적**:
|
||||
- **핵심 기능**:
|
||||
- **대상 사용자**:
|
||||
- **예상 사용자 규모**:
|
||||
|
||||
### 1.2 아키텍처 범위 및 경계
|
||||
- **시스템 범위**:
|
||||
- **포함되는 시스템**:
|
||||
- **제외되는 시스템**:
|
||||
- **외부 시스템 연동**:
|
||||
|
||||
### 1.3 문서 구성
|
||||
이 문서는 4+1 뷰 모델을 기반으로 구성되며, 논리적/물리적/프로세스/개발 관점에서 아키텍처를 정의합니다.
|
||||
|
||||
---
|
||||
|
||||
## 2. 아키텍처 요구사항
|
||||
|
||||
### 2.1 기능 요구사항 요약
|
||||
| 영역 | 주요 기능 | 우선순위 |
|
||||
|------|-----------|----------|
|
||||
| | | |
|
||||
|
||||
### 2.2 비기능 요구사항 (NFRs)
|
||||
|
||||
#### 2.2.1 성능 요구사항
|
||||
- **응답시간**:
|
||||
- **처리량**:
|
||||
- **동시사용자**:
|
||||
- **데이터 처리량**:
|
||||
|
||||
#### 2.2.2 확장성 요구사항
|
||||
- **수평 확장**:
|
||||
- **수직 확장**:
|
||||
- **글로벌 확장**:
|
||||
|
||||
#### 2.2.3 가용성 요구사항
|
||||
- **목표 가용성**: 99.9% / 99.99% / 99.999%
|
||||
- **다운타임 허용**:
|
||||
- **재해복구 목표**: RTO/RPO
|
||||
|
||||
#### 2.2.4 보안 요구사항
|
||||
- **인증/인가**:
|
||||
- **데이터 암호화**:
|
||||
- **네트워크 보안**:
|
||||
- **컴플라이언스**:
|
||||
|
||||
### 2.3 아키텍처 제약사항
|
||||
- **기술적 제약**:
|
||||
- **비용 제약**:
|
||||
- **시간 제약**:
|
||||
- **조직적 제약**:
|
||||
|
||||
---
|
||||
|
||||
## 3. 아키텍처 설계 원칙
|
||||
|
||||
### 3.1 핵심 설계 원칙
|
||||
1. **확장성 우선**: 수평적 확장이 가능한 구조
|
||||
2. **장애 격리**: 단일 장애점 제거 및 Circuit Breaker 패턴
|
||||
3. **느슨한 결합**: 마이크로서비스 간 독립성 보장
|
||||
4. **관측 가능성**: 로깅, 모니터링, 추적 체계 구축
|
||||
5. **보안 바이 데자인**: 설계 단계부터 보안 고려
|
||||
|
||||
### 3.2 아키텍처 품질 속성 우선순위
|
||||
| 순위 | 품질 속성 | 중요도 | 전략 |
|
||||
|------|-----------|--------|------|
|
||||
| 1 | | High | |
|
||||
| 2 | | Medium | |
|
||||
| 3 | | Low | |
|
||||
|
||||
---
|
||||
|
||||
## 4. 논리 아키텍처 (Logical View)
|
||||
|
||||
### 4.1 시스템 컨텍스트 다이어그램
|
||||
```
|
||||
{논리아키텍처 경로}
|
||||
```
|
||||
|
||||
### 4.2 도메인 아키텍처
|
||||
#### 4.2.1 도메인 모델
|
||||
| 도메인 | 책임 | 주요 엔티티 |
|
||||
|--------|------|-------------|
|
||||
| | | |
|
||||
|
||||
#### 4.2.2 바운디드 컨텍스트
|
||||
```
|
||||
[도메인별 바운디드 컨텍스트 다이어그램]
|
||||
```
|
||||
|
||||
### 4.3 서비스 아키텍처
|
||||
#### 4.3.1 마이크로서비스 구성
|
||||
| 서비스명 | 책임 |
|
||||
|----------|------|
|
||||
| | |
|
||||
|
||||
#### 4.3.2 서비스 간 통신 패턴
|
||||
- **동기 통신**: REST API, GraphQL
|
||||
- **비동기 통신**: Event-driven, Message Queue
|
||||
- **데이터 일관성**: Saga Pattern, Event Sourcing
|
||||
|
||||
---
|
||||
|
||||
## 5. 프로세스 아키텍처 (Process View)
|
||||
|
||||
### 5.1 주요 비즈니스 프로세스
|
||||
#### 5.1.1 핵심 사용자 여정
|
||||
```
|
||||
[사용자 여정별 프로세스 플로우]
|
||||
```
|
||||
|
||||
#### 5.1.2 시스템 간 통합 프로세스
|
||||
```
|
||||
[시스템 통합 시퀀스 다이어그램]
|
||||
```
|
||||
|
||||
### 5.2 동시성 및 동기화
|
||||
- **동시성 처리 전략**:
|
||||
- **락 관리**:
|
||||
- **이벤트 순서 보장**:
|
||||
|
||||
---
|
||||
|
||||
## 6. 개발 아키텍처 (Development View)
|
||||
|
||||
### 6.1 개발 언어 및 프레임워크 선정
|
||||
#### 6.1.1 백엔드 기술스택
|
||||
| 서비스 | 언어 | 프레임워크 | 선정이유 |
|
||||
|----------|------|---------------|----------|
|
||||
|
||||
#### 6.1.2 프론트엔드 기술스택
|
||||
- **언어**:
|
||||
- **프레임워크**:
|
||||
- **선정 이유**:
|
||||
|
||||
### 6.2 서비스별 개발 아키텍처 패턴
|
||||
| 서비스 | 아키텍처 패턴 | 선정 이유 |
|
||||
|--------|---------------|-----------|
|
||||
| | Clean/Layered/Hexagonal | |
|
||||
|
||||
|
||||
### 6.3 개발 가이드라인
|
||||
- **코딩 표준**:
|
||||
- **테스트 전략**:
|
||||
|
||||
---
|
||||
|
||||
## 7. 물리 아키텍처 (Physical View)
|
||||
|
||||
### 7.1 클라우드 아키텍처 패턴
|
||||
#### 7.1.1 선정된 클라우드 패턴
|
||||
- **패턴명**:
|
||||
- **적용 이유**:
|
||||
- **예상 효과**:
|
||||
|
||||
#### 7.1.2 클라우드 제공자
|
||||
- **주 클라우드**: Azure/AWS/GCP
|
||||
- **멀티 클라우드 전략**:
|
||||
- **하이브리드 구성**:
|
||||
|
||||
### 7.2 인프라스트럭처 구성
|
||||
#### 7.2.1 컴퓨팅 리소스
|
||||
| 구성요소 | 사양 | 스케일링 전략 |
|
||||
|----------|------|---------------|
|
||||
| 웹서버 | | |
|
||||
| 앱서버 | | |
|
||||
| 데이터베이스 | | |
|
||||
|
||||
#### 7.2.2 네트워크 구성
|
||||
```
|
||||
[네트워크 토폴로지 다이어그램]
|
||||
```
|
||||
|
||||
#### 7.2.3 보안 구성
|
||||
- **방화벽**:
|
||||
- **WAF**:
|
||||
- **DDoS 방어**:
|
||||
- **VPN/Private Link**:
|
||||
|
||||
---
|
||||
|
||||
## 8. 기술 스택 아키텍처
|
||||
|
||||
### 8.1 API Gateway & Service Mesh
|
||||
#### 8.1.1 API Gateway
|
||||
- **제품**:
|
||||
- **주요 기능**: 인증, 라우팅, 레이트 리미팅, 모니터링
|
||||
- **설정 전략**:
|
||||
|
||||
#### 8.1.2 Service Mesh
|
||||
- **제품**: Istio/Linkerd/Consul Connect
|
||||
- **적용 범위**:
|
||||
- **트래픽 관리**:
|
||||
|
||||
### 8.2 데이터 아키텍처
|
||||
#### 8.2.1 데이터베이스 전략
|
||||
| 용도 | 데이터베이스 | 타입 | 특징 |
|
||||
|------|-------------|------|------|
|
||||
| 트랜잭션 | | RDBMS | |
|
||||
| 캐시 | | In-Memory | |
|
||||
| 검색 | | Search Engine | |
|
||||
| 분석 | | Data Warehouse | |
|
||||
|
||||
#### 8.2.2 데이터 파이프라인
|
||||
```
|
||||
[데이터 플로우 다이어그램]
|
||||
```
|
||||
|
||||
### 8.3 백킹 서비스 (Backing Services)
|
||||
#### 8.3.1 메시징 & 이벤트 스트리밍
|
||||
- **메시지 큐**:
|
||||
- **이벤트 스트리밍**:
|
||||
- **이벤트 스토어**:
|
||||
|
||||
#### 8.3.2 스토리지 서비스
|
||||
- **객체 스토리지**:
|
||||
- **블록 스토리지**:
|
||||
- **파일 스토리지**:
|
||||
|
||||
### 8.4 관측 가능성 (Observability)
|
||||
#### 8.4.1 로깅 전략
|
||||
- **로그 수집**:
|
||||
- **로그 저장**:
|
||||
- **로그 분석**:
|
||||
|
||||
#### 8.4.2 모니터링 & 알람
|
||||
- **메트릭 수집**:
|
||||
- **시각화**:
|
||||
- **알람 정책**:
|
||||
|
||||
#### 8.4.3 분산 추적
|
||||
- **추적 도구**:
|
||||
- **샘플링 전략**:
|
||||
- **성능 분석**:
|
||||
|
||||
---
|
||||
|
||||
## 9. AI/ML 아키텍처
|
||||
|
||||
### 9.1 AI API 통합 전략
|
||||
#### 9.1.1 AI 서비스/모델 매핑
|
||||
| 목적 | 서비스 | 모델 | Input 데이터 | Output 데이터 | SLA |
|
||||
|------|--------|-------|-------------|-------------|-----|
|
||||
| | | | | | |
|
||||
|
||||
#### 9.1.2 AI 파이프라인
|
||||
```
|
||||
[AI 데이터 처리 파이프라인]
|
||||
```
|
||||
|
||||
### 9.2 데이터 과학 플랫폼
|
||||
- **모델 개발 환경**:
|
||||
- **모델 배포 전략**:
|
||||
- **모델 모니터링**:
|
||||
|
||||
---
|
||||
|
||||
## 10. 개발 운영 (DevOps)
|
||||
|
||||
### 10.1 CI/CD 파이프라인
|
||||
#### 10.1.1 지속적 통합 (CI)
|
||||
- **도구**:
|
||||
- **빌드 전략**:
|
||||
- **테스트 자동화**:
|
||||
|
||||
#### 10.1.2 지속적 배포 (CD)
|
||||
- **배포 도구**:
|
||||
- **배포 전략**: Blue-Green/Canary/Rolling
|
||||
- **롤백 정책**:
|
||||
|
||||
### 10.2 컨테이너 오케스트레이션
|
||||
#### 10.2.1 Kubernetes 구성
|
||||
- **클러스터 전략**:
|
||||
- **네임스페이스 설계**:
|
||||
- **리소스 관리**:
|
||||
|
||||
#### 10.2.2 헬름 차트 관리
|
||||
- **차트 구조**:
|
||||
- **환경별 설정**:
|
||||
- **의존성 관리**:
|
||||
|
||||
---
|
||||
|
||||
## 11. 보안 아키텍처
|
||||
|
||||
### 11.1 보안 전략
|
||||
#### 11.1.1 보안 원칙
|
||||
- **Zero Trust**:
|
||||
- **Defense in Depth**:
|
||||
- **Least Privilege**:
|
||||
|
||||
#### 11.1.2 위협 모델링
|
||||
| 위협 | 영향도 | 대응 방안 |
|
||||
|------|--------|-----------|
|
||||
| | | |
|
||||
|
||||
### 11.2 보안 구현
|
||||
#### 11.2.1 인증 & 인가
|
||||
- **ID 제공자**:
|
||||
- **토큰 전략**: JWT/OAuth2/SAML
|
||||
- **권한 모델**: RBAC/ABAC
|
||||
|
||||
#### 11.2.2 데이터 보안
|
||||
- **암호화 전략**:
|
||||
- **키 관리**:
|
||||
- **데이터 마스킹**:
|
||||
|
||||
---
|
||||
|
||||
## 12. 품질 속성 구현 전략
|
||||
|
||||
### 12.1 성능 최적화
|
||||
#### 12.1.1 캐싱 전략
|
||||
| 계층 | 캐시 유형 | TTL | 무효화 전략 |
|
||||
|------|-----------|-----|-------------|
|
||||
| | | | |
|
||||
|
||||
#### 12.1.2 데이터베이스 최적화
|
||||
- **인덱싱 전략**:
|
||||
- **쿼리 최적화**:
|
||||
- **커넥션 풀링**:
|
||||
|
||||
### 12.2 확장성 구현
|
||||
#### 12.2.1 오토스케일링
|
||||
- **수평 확장**: HPA/VPA
|
||||
- **수직 확장**:
|
||||
- **예측적 스케일링**:
|
||||
|
||||
#### 12.2.2 부하 분산
|
||||
- **로드 밸런서**:
|
||||
- **트래픽 분산 정책**:
|
||||
- **헬스체크**:
|
||||
|
||||
### 12.3 가용성 및 복원력
|
||||
#### 12.3.1 장애 복구 전략
|
||||
- **Circuit Breaker**:
|
||||
- **Retry Pattern**:
|
||||
- **Bulkhead Pattern**:
|
||||
|
||||
#### 12.3.2 재해 복구
|
||||
- **백업 전략**:
|
||||
- **RTO/RPO**:
|
||||
- **DR 사이트**:
|
||||
|
||||
---
|
||||
|
||||
## 13. 아키텍처 의사결정 기록 (ADR)
|
||||
|
||||
### 13.1 주요 아키텍처 결정
|
||||
| ID | 결정 사항 | 결정 일자 | 상태 | 결정 이유 |
|
||||
|----|-----------|-----------|------|-----------|
|
||||
| ADR-001 | | | | |
|
||||
|
||||
### 13.2 트레이드오프 분석
|
||||
#### 13.2.1 성능 vs 확장성
|
||||
- **고려사항**:
|
||||
- **선택**:
|
||||
- **근거**:
|
||||
|
||||
#### 13.2.2 일관성 vs 가용성 (CAP 정리)
|
||||
- **고려사항**:
|
||||
- **선택**: AP/CP
|
||||
- **근거**:
|
||||
|
||||
---
|
||||
|
||||
## 14. 구현 로드맵
|
||||
|
||||
### 14.1 개발 단계
|
||||
| 단계 | 기간 | 주요 산출물 | 마일스톤 |
|
||||
|------|------|-------------|-----------|
|
||||
| Phase 1 | | | |
|
||||
| Phase 2 | | | |
|
||||
| Phase 3 | | | |
|
||||
|
||||
### 14.2 마이그레이션 전략 (레거시 시스템이 있는 경우)
|
||||
- **데이터 마이그레이션**:
|
||||
- **기능 마이그레이션**:
|
||||
- **병행 운영**:
|
||||
|
||||
---
|
||||
|
||||
## 15. 위험 관리
|
||||
|
||||
### 15.1 아키텍처 위험
|
||||
| 위험 | 영향도 | 확률 | 완화 방안 |
|
||||
|------|--------|------|-----------|
|
||||
| | | | |
|
||||
|
||||
### 15.2 기술 부채 관리
|
||||
- **식별된 기술 부채**:
|
||||
- **해결 우선순위**:
|
||||
- **해결 계획**:
|
||||
|
||||
---
|
||||
|
||||
## 16. 부록
|
||||
|
||||
### 16.1 참조 아키텍처
|
||||
- **업계 표준**:
|
||||
- **내부 표준**:
|
||||
- **외부 참조**:
|
||||
|
||||
### 16.2 용어집
|
||||
| 용어 | 정의 |
|
||||
|------|------|
|
||||
| | |
|
||||
|
||||
### 16.3 관련 문서
|
||||
- {문서명}: {파일 위치}
|
||||
- ...
|
||||
|
||||
---
|
||||
|
||||
## 문서 이력
|
||||
| 버전 | 일자 | 작성자 | 변경 내용 | 승인자 |
|
||||
|------|------|--------|-----------|-------|
|
||||
| v1.0 | | | 초기 작성 | |
|
||||
|
||||
230
claude/physical-architecture-design.md
Normal file
230
claude/physical-architecture-design.md
Normal file
@ -0,0 +1,230 @@
|
||||
# 물리아키텍처설계가이드
|
||||
|
||||
[요청사항]
|
||||
- <작성원칙>을 준용하여 설계
|
||||
- <작성순서>에 따라 설계
|
||||
- [결과파일] 안내에 따라 파일 작성
|
||||
- 완료 후 mermaid 스크립트 테스트 방법 안내
|
||||
- https://mermaid.live/edit 에 접근
|
||||
- 스크립트 내용을 붙여넣어 확인
|
||||
|
||||
[가이드]
|
||||
<작성원칙>
|
||||
- 클라우드 기반의 물리 아키텍처 설계
|
||||
- HighLevel아키텍처정의서와 일치해야 함
|
||||
- 백킹서비스설치방법에 있는 제품을 우선적으로 사용
|
||||
- 환경별 특성에 맞는 차별화 전략 적용
|
||||
- 비용 효율성과 운영 안정성의 균형 고려
|
||||
- 선정된 아키텍처 패턴 반영 및 최적화
|
||||
|
||||
<작성순서>
|
||||
- 준비:
|
||||
- 아키텍처패턴, 논리아키텍처, 외부시퀀스설계서, 데이터설계서, HighLevel아키텍처정의서 분석 및 이해
|
||||
|
||||
- 실행:
|
||||
- 물리아키텍처 다이어그램 작성
|
||||
- 서브에이전트로 병렬 수행
|
||||
- Mermaid 형식으로 작성
|
||||
- Mermaid 스크립트 파일 검사 실행
|
||||
- 개발환경 물리아키텍처 다이어그램
|
||||
- '<예시>의 '개발환경 물리아키텍처 다이어그램'의 내용을 읽어 참조
|
||||
- 사용자 → Ingress → 서비스 → 데이터베이스 플로우만 표시
|
||||
- 클라우드 서비스는 최소한으로만 포함
|
||||
- 부가 설명은 문서에만 기록, 다이어그램에서 제거
|
||||
- 네트워크, 보안, 운영 관련 아키텍처는 생략
|
||||
- 모니터링/로깅/보안과 관련된 제품/서비스 생략함
|
||||
- 운영환경 물리아키텍처 다이어그램
|
||||
- '<예시>의 '운영환경 물리아키텍처 다이어그램'의 내용을 읽어 참조
|
||||
- 결과:
|
||||
- 개발환경: physical-architecture-dev.mmd
|
||||
- 운영환경: physical-architecture-prod.mmd
|
||||
- 네트워크 아키텍처 다이어그램 작성
|
||||
- 서브에이전트로 병렬 수행
|
||||
- Mermaid 형식으로 작성
|
||||
- Mermaid 스크립트 파일 검사 실행
|
||||
- 개발환경 네트워크 다이어그램: '<예시>의 '개발환경 네트워크 다이어그램'의 내용을 읽어 참조
|
||||
- 운영환경 네트워크 다이어그램: '<예시>의 '운영환경 네트워크 다이어그램'의 내용을 읽어 참조
|
||||
- 결과:
|
||||
- 개발환경: network-dev.mmd
|
||||
- 운영환경: network-prod.mmd
|
||||
- 개발환경 물리아키텍처 설계서 작성
|
||||
- <개발환경가이드>의 항목별 작성
|
||||
- '<예시>의 '개발환경 물리아키텍처 설계서'의 내용을 읽어 참조
|
||||
- 비용 최적화 중심의 개발 친화적 환경 구성
|
||||
- 빠른 배포와 테스트를 위한 단순화된 아키텍처
|
||||
- Pod 기반 백킹서비스와 기본 보안 설정
|
||||
- 개발팀 규모와 워크플로우에 최적화
|
||||
- 제품/서비스 구성
|
||||
- Application Gateway: Kubernetes Ingress
|
||||
- Database: "백킹서비스설치방법"에 있는 오픈소스 DB사용
|
||||
- Message Queue: "백킹서비스설치방법"에 있는 {CLOUD}에서 제공하는 제품
|
||||
- CI/CD: 'HighLevel아키텍처정의서'에 있는 CI/CD 제품
|
||||
- 결과: physical-architecture-dev.md
|
||||
- 운영환경 물리아키텍처 설계서 작성
|
||||
- <운영환경가이드>의 항목별 작성
|
||||
- '<예시>의 '운영환경 물리아키텍처 설계서'의 내용을 읽어 참조
|
||||
- 고가용성과 확장성을 고려한 프로덕션 환경
|
||||
- 관리형 서비스 중심의 안정적인 구성
|
||||
- 엔터프라이즈급 보안과 모니터링 체계
|
||||
- 실사용자 규모에 따른 성능 최적화
|
||||
- 결과: physical-architecture-prod.md
|
||||
- 마스터 아키텍처 설계서 작성
|
||||
- <마스터가이드>의 항목별 작성
|
||||
- '<예시>의 '마스터 물리아키텍처 설계서'의 내용을 읽어 참조
|
||||
- 환경별 아키텍처 비교 및 통합 관리
|
||||
- 단계별 전환 전략과 확장 로드맵
|
||||
- 비용 분석과 운영 가이드라인
|
||||
- 전체 시스템 거버넌스 체계
|
||||
- 결과: physical-architecture.md
|
||||
- 검토:
|
||||
- <작성원칙> 준수 검토
|
||||
- 선정 아키텍처 패턴 적용 확인
|
||||
- 환경별 비용 효율성 검증
|
||||
- 확장성 및 성능 요구사항 충족 확인
|
||||
- 프로젝트 팀원 리뷰 및 피드백 반영
|
||||
- 수정 사항 선택 및 최종 반영
|
||||
|
||||
<개발환경가이드>
|
||||
```
|
||||
대분류|중분류|소분류|작성가이드
|
||||
---|---|---|---
|
||||
1. 개요|1.1 설계 목적||개발환경 물리 아키텍처의 설계 범위, 목적, 대상을 명확히 기술
|
||||
1. 개요|1.2 설계 원칙||개발환경에 적합한 핵심 설계 원칙 4가지 정의 (MVP 우선, 비용 최적화, 개발 편의성, 단순성)
|
||||
1. 개요|1.3 참조 아키텍처||관련 아키텍처 문서들의 연관관계와 참조 방법 명시
|
||||
2. 개발환경 아키텍처 개요|2.1 환경 특성||개발환경의 목적, 사용자 규모, 가용성 목표, 확장성, 보안 수준 등 특성 정의
|
||||
2. 개발환경 아키텍처 개요|2.2 전체 아키텍처||전체 시스템 구성도와 주요 컴포넌트 간 연결 관계 설명 및 다이어그램 링크
|
||||
3. 컴퓨팅 아키텍처|3.1 Kubernetes 클러스터 구성|3.1.1 클러스터 설정|Kubernetes 버전, 서비스 계층, 네트워크 플러그인, DNS 등 클러스터 기본 설정값 표 작성
|
||||
3. 컴퓨팅 아키텍처|3.1 Kubernetes 클러스터 구성|3.1.2 노드 풀 구성|인스턴스 크기, 노드 수, 스케일링 설정, 가용영역, 가격 정책 등 노드 풀 상세 설정 표 작성
|
||||
3. 컴퓨팅 아키텍처|3.2 서비스별 리소스 할당|3.2.1 애플리케이션 서비스|각 마이크로서비스별 CPU/Memory requests, limits, replicas 상세 리소스 할당 표 작성
|
||||
3. 컴퓨팅 아키텍처|3.2 서비스별 리소스 할당|3.2.2 백킹 서비스|데이터베이스, 캐시 등 백킹서비스 Pod의 리소스 할당 및 스토리지 설정 표 작성 (PVC 사용 시 클라우드 스토리지 클래스 지정: standard, premium-ssd 등)
|
||||
3. 컴퓨팅 아키텍처|3.2 서비스별 리소스 할당|3.2.3 스토리지 클래스 구성|클라우드 제공자별 스토리지 클래스 설정 (hostPath 사용 금지, 관리형 디스크만 사용)
|
||||
4. 네트워크 아키텍처|4.1 네트워크 구성|4.1.1 네트워크 토폴로지|네트워크 구성도 및 서브넷 구조 설명, 네트워크 다이어그램 링크 제공
|
||||
4. 네트워크 아키텍처|4.1 네트워크 구성|4.1.2 네트워크 보안|Network Policy 설정, 접근 제한 규칙, 보안 정책 표 작성
|
||||
4. 네트워크 아키텍처|4.2 서비스 디스커버리||각 서비스의 내부 DNS 주소, 포트, 용도를 정리한 서비스 디스커버리 표 작성
|
||||
5. 데이터 아키텍처|5.1 데이터베이스 구성|5.1.1 주 데이터베이스 Pod 구성|컨테이너 이미지, 리소스 설정, 스토리지 구성, 데이터베이스 설정값 상세 표 작성 (스토리지는 클라우드 제공자별 관리형 스토리지 사용: Azure Disk, AWS EBS, GCP Persistent Disk 등)
|
||||
5. 데이터 아키텍처|5.1 데이터베이스 구성|5.1.2 캐시 Pod 구성|캐시 컨테이너 이미지, 리소스, 메모리 설정, 캐시 정책 등 상세 설정 표 작성 (영구 저장이 필요한 경우 클라우드 스토리지 클래스 사용)
|
||||
5. 데이터 아키텍처|5.2 데이터 관리 전략|5.2.1 데이터 초기화|Kubernetes Job을 이용한 데이터 초기화 프로세스, 실행 절차, 검증 방법 상세 기술
|
||||
5. 데이터 아키텍처|5.2 데이터 관리 전략|5.2.2 백업 전략|백업 방법, 주기, 보존 전략, 복구 절차를 서비스별로 정리한 표 작성
|
||||
6. 메시징 아키텍처|6.1 Message Queue 구성|6.1.1 Basic Tier 설정|Message Queue 전체 설정값과 큐별 상세 설정을 표로 정리하여 작성
|
||||
6. 메시징 아키텍처|6.1 Message Queue 구성|6.1.2 연결 설정|인증 방식, 연결 풀링, 재시도 정책 등 연결 관련 설정 표 작성
|
||||
7. 보안 아키텍처|7.1 개발환경 보안 정책|7.1.1 기본 보안 설정|보안 계층별 설정값과 수준을 정리한 표와 관리 대상 시크릿 목록 작성
|
||||
7. 보안 아키텍처|7.1 개발환경 보안 정책|7.1.2 시크릿 관리|시크릿 관리 방식, 순환 정책, 저장소 등 시크릿 관리 전략 표 작성
|
||||
7. 보안 아키텍처|7.2 Network Policies|7.2.1 기본 정책|Network Policy 설정 상세 내용과 보안 정책 적용 범위 표 작성
|
||||
8. 모니터링 및 로깅|8.1 기본 모니터링|8.1.1 Kubernetes 기본 모니터링|모니터링 스택 구성과 기본 알림 설정 임계값을 표로 정리
|
||||
8. 모니터링 및 로깅|8.1 기본 모니터링|8.1.2 애플리케이션 모니터링|헬스체크 설정과 수집 메트릭 유형을 표로 정리하여 작성
|
||||
8. 모니터링 및 로깅|8.2 로깅|8.2.1 로그 수집|로그 수집 방식, 저장 방식, 보존 기간과 로그 레벨 설정을 표로 작성
|
||||
9. 배포 관련 컴포넌트|||CI/CD 파이프라인 구성 요소들과 각각의 역할을 표 형태로 정리
|
||||
10. 비용 최적화|10.1 개발환경 비용 구조|10.1.1 주요 비용 요소|구성요소별 사양과 월간 예상 비용, 절약 방안을 상세 표로 작성
|
||||
10. 비용 최적화|10.1 개발환경 비용 구조|10.1.2 비용 절약 전략|컴퓨팅, 스토리지, 네트워킹 영역별 절약 방안과 절약률을 표로 정리
|
||||
11. 개발환경 운영 가이드|11.1 일상 운영|11.1.1 환경 시작/종료|일상적인 환경 관리를 위한 kubectl 명령어와 절차를 코드 블록으로 제공
|
||||
11. 개발환경 운영 가이드|11.1 일상 운영|11.1.2 데이터 관리|데이터 초기화, 백업, 복원을 위한 구체적 명령어와 절차를 코드 블록으로 작성
|
||||
11. 개발환경 운영 가이드|11.2 트러블슈팅|11.2.1 일반적인 문제 해결|자주 발생하는 문제 유형별 원인과 해결방안, 예방법을 표로 정리
|
||||
12. 개발환경 특성 요약|||개발환경의 핵심 설계 원칙, 주요 제약사항, 최적화 목표를 요약하여 기술
|
||||
```
|
||||
|
||||
<운영환경가이드>
|
||||
```
|
||||
대분류|중분류|소분류|작성가이드
|
||||
---|---|---|---
|
||||
1. 개요|1.1 설계 목적||운영환경 물리 아키텍처의 설계 범위, 목적, 대상을 명확히 기술
|
||||
1. 개요|1.2 설계 원칙||고가용성, 확장성, 보안 우선, 관측 가능성, 재해복구 등 5대 핵심 원칙 정의
|
||||
1. 개요|1.3 참조 아키텍처||관련 아키텍처 문서들의 연관관계와 참조 방법 명시
|
||||
2. 운영환경 아키텍처 개요|2.1 환경 특성||운영환경의 목적, 사용자 규모, 가용성 목표, 확장성, 보안 수준 등 특성 정의
|
||||
2. 운영환경 아키텍처 개요|2.2 전체 아키텍처||전체 시스템 구성도와 주요 컴포넌트 간 연결 관계 설명 및 다이어그램 링크
|
||||
3. 컴퓨팅 아키텍처|3.1 Kubernetes 클러스터 구성|3.1.1 클러스터 설정|Kubernetes 버전, Standard 서비스 티어, CNI 플러그인, RBAC 등 클러스터 기본 설정값 표 작성
|
||||
3. 컴퓨팅 아키텍처|3.1 Kubernetes 클러스터 구성|3.1.2 노드 풀 구성|시스템 노드 풀과 애플리케이션 노드 풀의 인스턴스 크기, 노드 수, Multi-Zone 배포 설정 표 작성
|
||||
3. 컴퓨팅 아키텍처|3.2 고가용성 구성|3.2.1 Multi-Zone 배포|가용성 전략과 Pod Disruption Budget 설정을 표로 정리
|
||||
3. 컴퓨팅 아키텍처|3.3 서비스별 리소스 할당|3.3.1 애플리케이션 서비스|각 마이크로서비스별 CPU/Memory requests, limits, replicas, HPA 설정 상세 표 작성
|
||||
3. 컴퓨팅 아키텍처|3.3 서비스별 리소스 할당|3.3.2 HPA 구성|Horizontal Pod Autoscaler 설정을 YAML 코드 블록으로 상세 작성
|
||||
4. 네트워크 아키텍처|4.1 네트워크 토폴로지||네트워크 흐름도와 VNet 구성, 서브넷 세부 구성을 표로 정리하고 다이어그램 링크 제공
|
||||
4. 네트워크 아키텍처|4.1 네트워크 토폴로지|4.1.1 Virtual Network 구성|VPC/VNet 기본 설정과 서브넷별 주소 대역, 용도, 특별 설정을 상세 표로 작성
|
||||
4. 네트워크 아키텍처|4.1 네트워크 토폴로지|4.1.2 네트워크 보안 그룹|보안 그룹 규칙을 방향, 규칙 이름, 포트, 소스/대상별로 정리한 표 작성
|
||||
4. 네트워크 아키텍처|4.2 트래픽 라우팅|4.2.1 Application Gateway 구성|기본 설정, 프론트엔드 구성, 백엔드 및 라우팅 설정을 표로 정리
|
||||
4. 네트워크 아키텍처|4.2 트래픽 라우팅|4.2.2 WAF 구성|WAF 정책과 커스텀 규칙, 관리 규칙을 YAML 코드 블록으로 작성
|
||||
4. 네트워크 아키텍처|4.3 Network Policies|4.3.1 마이크로서비스 간 통신 제어|Network Policy 기본 설정과 Ingress/Egress 규칙을 표로 정리
|
||||
4. 네트워크 아키텍처|4.4 서비스 디스커버리||각 서비스의 내부 DNS 주소, 포트, 용도를 정리한 서비스 디스커버리 표 작성
|
||||
5. 데이터 아키텍처|5.1 관리형 주 데이터베이스|5.1.1 데이터베이스 구성|기본 설정, 고가용성, 백업 및 보안 설정을 표로 정리하여 작성 (클라우드 제공자의 관리형 데이터베이스 서비스 사용: Azure Database, AWS RDS, Google Cloud SQL 등)
|
||||
5. 데이터 아키텍처|5.1 관리형 주 데이터베이스|5.1.2 읽기 전용 복제본|읽기 복제본 구성을 YAML 코드 블록으로 상세 작성
|
||||
5. 데이터 아키텍처|5.2 관리형 캐시 서비스|5.2.1 캐시 클러스터 구성|기본 설정, 클러스터 구성, 지속성 및 보안 설정을 표로 정리 (관리형 캐시 서비스 사용: Azure Cache for Redis, AWS ElastiCache, Google Cloud Memorystore 등)
|
||||
5. 데이터 아키텍처|5.2 관리형 캐시 서비스|5.2.2 캐시 전략|운영 최적화된 캐시 전략과 패턴을 YAML 코드 블록으로 작성
|
||||
5. 데이터 아키텍처|5.3 데이터 백업 및 복구|5.3.1 자동 백업 전략|주 데이터베이스와 캐시의 자동 백업 전략을 YAML 코드 블록으로 상세 작성
|
||||
6. 메시징 아키텍처|6.1 관리형 Message Queue|6.1.1 Message Queue 구성|Premium 티어 설정과 네임스페이스, 보안 설정을 YAML 코드 블록으로 작성
|
||||
6. 메시징 아키텍처|6.1 관리형 Message Queue|6.1.2 큐 및 토픽 설계|큐와 토픽의 상세 설정을 YAML 코드 블록으로 작성
|
||||
7. 보안 아키텍처|7.1 다층 보안 아키텍처|7.1.1 보안 계층 구조|L1-L4 보안 계층별 구성 요소를 YAML 코드 블록으로 상세 작성
|
||||
7. 보안 아키텍처|7.2 인증 및 권한 관리|7.2.1 클라우드 Identity 통합|클라우드 Identity 구성과 애플리케이션 등록을 YAML 코드 블록으로 작성
|
||||
7. 보안 아키텍처|7.2 인증 및 권한 관리|7.2.2 RBAC 구성|클러스터 역할과 서비스 계정을 YAML 코드 블록으로 상세 작성
|
||||
7. 보안 아키텍처|7.3 네트워크 보안|7.3.1 Private Endpoints|각 서비스별 Private Endpoint 설정을 YAML 코드 블록으로 작성
|
||||
7. 보안 아키텍처|7.4 암호화 및 키 관리|7.4.1 관리형 Key Vault 구성|Key Vault 설정과 액세스 정책, 순환 정책을 YAML 코드 블록으로 작성
|
||||
8. 모니터링 및 관측 가능성|8.1 종합 모니터링 스택|8.1.1 클라우드 모니터링 통합|Log Analytics, Application Insights, Container Insights 설정을 YAML 코드 블록으로 작성
|
||||
8. 모니터링 및 관측 가능성|8.1 종합 모니터링 스택|8.1.2 메트릭 및 알림|중요 알림과 리소스 알림 설정을 YAML 코드 블록으로 상세 작성
|
||||
8. 모니터링 및 관측 가능성|8.2 로깅 및 추적|8.2.1 중앙집중식 로깅|로그 수집 설정과 중앙 로그 시스템 쿼리를 YAML 코드 블록으로 작성
|
||||
8. 모니터링 및 관측 가능성|8.2 로깅 및 추적|8.2.2 애플리케이션 성능 모니터링|APM 설정과 커스텀 메트릭을 YAML 코드 블록으로 작성
|
||||
9. 배포 관련 컴포넌트|||CI/CD 파이프라인 구성 요소들과 각각의 역할, 보안 스캔, 롤백 정책을 표 형태로 정리
|
||||
10. 재해복구 및 고가용성|10.1 재해복구 전략|10.1.1 백업 및 복구 목표|RTO, RPO와 백업 전략을 YAML 코드 블록으로 상세 작성
|
||||
10. 재해복구 및 고가용성|10.1 재해복구 전략|10.1.2 자동 장애조치|데이터베이스, 캐시, 애플리케이션별 장애조치 설정을 YAML 코드 블록으로 작성
|
||||
10. 재해복구 및 고가용성|10.2 비즈니스 연속성|10.2.1 운영 절차|인시던트 대응, 유지보수 윈도우, 변경 관리를 YAML 코드 블록으로 작성
|
||||
11. 비용 최적화|11.1 운영환경 비용 구조|11.1.1 월간 비용 분석|구성요소별 사양, 예상 비용, 최적화 방안을 상세 표로 작성
|
||||
11. 비용 최적화|11.1 운영환경 비용 구조|11.1.2 비용 최적화 전략|컴퓨팅, 스토리지, 네트워크 영역별 최적화 방안을 YAML 코드 블록으로 작성
|
||||
11. 비용 최적화|11.2 성능 대비 비용 효율성|11.2.1 Auto Scaling 최적화|예측 스케일링과 비용 인식 스케일링을 YAML 코드 블록으로 작성
|
||||
12. 운영 가이드|12.1 일상 운영 절차|12.1.1 정기 점검 항목|일일, 주간, 월간 운영 체크리스트를 YAML 코드 블록으로 작성
|
||||
12. 운영 가이드|12.2 인시던트 대응|12.2.1 장애 대응 절차|심각도별 대응 절차를 YAML 코드 블록으로 상세 작성
|
||||
12. 운영 가이드|12.2 인시던트 대응|12.2.2 자동 복구 메커니즘|Pod 재시작, 노드 교체, 트래픽 라우팅 등 자동 복구를 YAML 코드 블록으로 작성
|
||||
13. 확장 계획|13.1 단계별 확장 로드맵|13.1.1 Phase 1-3|각 단계별 목표, 대상, 결과물을 YAML 코드 블록으로 상세 작성
|
||||
13. 확장 계획|13.2 기술적 확장성|13.2.1 수평 확장 전략|애플리케이션, 데이터베이스, 캐시 티어별 확장 전략을 YAML 코드 블록으로 작성
|
||||
14. 운영환경 특성 요약|||운영환경의 핵심 설계 원칙, 주요 성과 목표, 최적화 목표를 요약하여 기술
|
||||
```
|
||||
|
||||
<마스터가이드>
|
||||
```
|
||||
대분류|중분류|소분류|작성가이드
|
||||
---|---|---|---
|
||||
1. 개요|1.1 설계 목적||전체 물리 아키텍처의 통합 관리 체계와 마스터 인덱스 역할 기술
|
||||
1. 개요|1.2 아키텍처 분리 원칙||개발환경과 운영환경 분리 원칙과 단계적 발전 전략 정의
|
||||
1. 개요|1.3 문서 구조||마스터 인덱스와 환경별 상세 문서 구조 및 참조 관계 명시
|
||||
1. 개요|1.4 참조 아키텍처||관련 아키텍처 문서들(HighLevel, 논리, 패턴, API)의 연관관계 명시
|
||||
2. 환경별 아키텍처 개요|2.1 환경별 특성 비교||목적, 가용성, 사용자, 확장성, 보안, 비용 등 환경별 특성을 비교 표로 작성
|
||||
2. 환경별 아키텍처 개요|2.2 환경별 세부 문서|2.2.1 개발환경 아키텍처|개발환경 문서 링크와 주요 특징, 핵심 구성을 요약하여 기술
|
||||
2. 환경별 아키텍처 개요|2.2 환경별 세부 문서|2.2.2 운영환경 아키텍처|운영환경 문서 링크와 주요 특징, 핵심 구성을 요약하여 기술
|
||||
2. 환경별 아키텍처 개요|2.3 핵심 아키텍처 결정사항|2.3.1 공통 아키텍처 원칙|서비스 메시 제거, 비동기 통신, 관리형 Identity, 다층 보안 등 공통 원칙 기술
|
||||
2. 환경별 아키텍처 개요|2.3 핵심 아키텍처 결정사항|2.3.2 환경별 차별화 전략|개발환경과 운영환경의 최적화 전략 차이점을 비교하여 기술
|
||||
3. 네트워크 아키텍처 비교|3.1 환경별 네트워크 전략|3.1.1 환경별 네트워크 전략 비교|인그레스, 네트워크, 보안, 접근 방식을 환경별로 비교한 표 작성
|
||||
3. 네트워크 아키텍처 비교|3.2 네트워크 보안 전략|3.2.1 공통 보안 원칙|Network Policies, 관리형 Identity, Private Endpoints, TLS 암호화 등 공통 보안 원칙 기술
|
||||
3. 네트워크 아키텍처 비교|3.2 네트워크 보안 전략|3.2.2 환경별 보안 수준|Network Policy, 시크릿 관리, 암호화, 웹 보안 수준을 환경별로 비교한 표 작성
|
||||
4. 데이터 아키텍처 비교|4.1 환경별 데이터 전략|4.1.1 환경별 데이터 구성 비교|주 데이터베이스와 캐시의 환경별 구성, 가용성, 비용을 비교한 상세 표 작성 (개발환경: Pod 기반 + 클라우드 스토리지, 운영환경: 관리형 서비스)
|
||||
4. 데이터 아키텍처 비교|4.2 캐시 전략 비교|4.2.1 다층 캐시 아키텍처|L1 애플리케이션 캐시와 L2 분산 캐시의 계층별 설정을 표로 정리
|
||||
4. 데이터 아키텍처 비교|4.2 캐시 전략 비교|4.2.2 환경별 캐시 특성 비교|캐시 구성, 데이터 지속성, 성능 특성을 환경별로 비교한 표 작성
|
||||
5. 보안 아키텍처 비교|5.1 다층 보안 아키텍처|5.1.1 공통 보안 계층|L1-L4 보안 계층의 보안 기술, 적용 범위, 보안 목적을 표로 정리
|
||||
5. 보안 아키텍처 비교|5.2 환경별 보안 수준|5.2.1 환경별 보안 수준 비교|인증, 네트워크, 시크릿, 암호화 영역별 보안 수준과 강화 방안을 비교한 표 작성
|
||||
6. 모니터링 및 운영|6.1 환경별 모니터링 전략|6.1.1 환경별 모니터링 도구 비교|모니터링 도구, 메트릭, 알림, 로그 수집 방식을 환경별로 비교한 표 작성
|
||||
6. 모니터링 및 운영|6.2 CI/CD 및 배포 전략|6.2.1 환경별 배포 방식 비교|배포 방식, 자동화, 테스트, 다운타임 허용도를 환경별로 비교한 표 작성
|
||||
7. 비용 분석|7.1 환경별 비용 구조|7.1.1 월간 비용 비교|구성요소별 개발환경과 운영환경 비용을 상세 비교한 표 작성
|
||||
7. 비용 분석|7.1 환경별 비용 구조|7.1.2 환경별 비용 최적화 전략 비교|컴퓨팅, 백킹서비스, 리소스 관리 최적화 방안을 환경별로 비교한 표 작성
|
||||
8. 전환 및 확장 계획|8.1 개발환경 → 운영환경 전환 체크리스트||데이터 마이그레이션, 설정 변경, 모니터링 등 전환 체크리스트를 카테고리별로 표 작성
|
||||
8. 전환 및 확장 계획|8.2 단계별 확장 로드맵||Phase 1-3 단계별 기간, 핵심 목표, 주요 작업, 사용자 지원, 가용성을 표로 정리
|
||||
9. 핵심 SLA 지표|9.1 환경별 서비스 수준 목표||가용성, 응답시간, 배포시간, 복구시간, 동시사용자, 월간비용을 환경별로 비교한 표 작성
|
||||
```
|
||||
|
||||
[참고자료]
|
||||
- 아키텍처패턴
|
||||
- 논리아키텍처
|
||||
- 외부시퀀스설계서
|
||||
- 데이터설계서
|
||||
- HighLevel아키텍처정의서
|
||||
|
||||
[예시]
|
||||
- 개발환경 물리아키텍처 설계서: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/samples/physical/sample-physical-architecture-dev.md
|
||||
- 운영환경 물리아키텍처 설계서: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/samples/physical/sample-physical-architecture-prod.md
|
||||
- 마스터 물리아키텍처 설계서: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/samples/physical/sample-physical-architecture.md
|
||||
- 개발환경 물리아키텍처 다이어그램: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/samples/physical/sample-physical-architecture-dev.mmd
|
||||
- 운영환경 물리아키텍처 다이어그램: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/samples/physical/sample-physical-architecture-prod.mmd
|
||||
- 개발환경 네트워크 다이어그램: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/samples/physical/sample-network-dev.mmd
|
||||
- 운영환경 네트워크 다이어그램: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/samples/physical/sample-network-prod.mmd
|
||||
|
||||
[결과파일]
|
||||
- design/backend/physical/physical-architecture.md
|
||||
- design/backend/physical/physical-architecture-dev.md
|
||||
- design/backend/physical/physical-architecture-prod.md
|
||||
- design/backend/physical/physical-architecture-dev.mmd
|
||||
- design/backend/physical/physical-architecture-prod.mmd
|
||||
- design/backend/physical/network-dev.mmd
|
||||
- design/backend/physical/network-prod.mmd
|
||||
138
claude/sample-network-dev.mmd
Normal file
138
claude/sample-network-dev.mmd
Normal file
@ -0,0 +1,138 @@
|
||||
graph TB
|
||||
%% 개발환경 네트워크 다이어그램
|
||||
%% AI 기반 여행 일정 생성 서비스 - 개발환경
|
||||
|
||||
%% 외부 영역
|
||||
subgraph Internet["🌐 인터넷"]
|
||||
Developer["👨💻 개발자"]
|
||||
QATester["🧪 QA팀"]
|
||||
end
|
||||
|
||||
%% Azure 클라우드 영역
|
||||
subgraph AzureCloud["☁️ Azure Cloud"]
|
||||
|
||||
%% Virtual Network
|
||||
subgraph VNet["🏢 Virtual Network (VNet)<br/>주소 공간: 10.0.0.0/16"]
|
||||
|
||||
%% AKS 서브넷
|
||||
subgraph AKSSubnet["🎯 AKS Subnet<br/>10.0.1.0/24"]
|
||||
|
||||
%% Kubernetes 클러스터
|
||||
subgraph AKSCluster["⚙️ AKS Cluster"]
|
||||
|
||||
%% Ingress Controller
|
||||
subgraph IngressController["🚪 NGINX Ingress Controller"]
|
||||
LoadBalancer["⚖️ LoadBalancer Service<br/>(External IP)"]
|
||||
IngressPod["📦 Ingress Controller Pod"]
|
||||
end
|
||||
|
||||
%% Application Tier
|
||||
subgraph AppTier["🚀 Application Tier"]
|
||||
UserService["👤 User Service<br/>Pod"]
|
||||
TripService["🗺️ Trip Service<br/>Pod"]
|
||||
AIService["🤖 AI Service<br/>Pod"]
|
||||
LocationService["📍 Location Service<br/>Pod"]
|
||||
end
|
||||
|
||||
%% Database Tier
|
||||
subgraph DBTier["🗄️ Database Tier"]
|
||||
PostgreSQL["🐘 PostgreSQL<br/>Pod"]
|
||||
PostgreSQLStorage["💾 hostPath Volume<br/>(/data/postgresql)"]
|
||||
end
|
||||
|
||||
%% Cache Tier
|
||||
subgraph CacheTier["⚡ Cache Tier"]
|
||||
Redis["🔴 Redis<br/>Pod"]
|
||||
end
|
||||
|
||||
%% Cluster Internal Services
|
||||
subgraph ClusterServices["🔗 ClusterIP Services"]
|
||||
UserServiceDNS["user-service:8080"]
|
||||
TripServiceDNS["trip-service:8080"]
|
||||
AIServiceDNS["ai-service:8080"]
|
||||
LocationServiceDNS["location-service:8080"]
|
||||
PostgreSQLDNS["postgresql:5432"]
|
||||
RedisDNS["redis:6379"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%% Service Bus 서브넷
|
||||
subgraph ServiceBusSubnet["📨 Service Bus Subnet<br/>10.0.2.0/24"]
|
||||
ServiceBus["📮 Azure Service Bus<br/>(Basic Tier)"]
|
||||
|
||||
subgraph Queues["📬 Message Queues"]
|
||||
AIQueue["🤖 ai-schedule-generation"]
|
||||
LocationQueue["📍 location-search"]
|
||||
NotificationQueue["🔔 notification"]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%% 네트워크 연결 관계
|
||||
|
||||
%% 외부에서 클러스터로의 접근
|
||||
Developer -->|"HTTPS:443<br/>(개발용 도메인)"| LoadBalancer
|
||||
QATester -->|"API 호출/테스트"| LoadBalancer
|
||||
|
||||
%% Ingress Controller 내부 흐름
|
||||
LoadBalancer -->|"트래픽 라우팅"| IngressPod
|
||||
|
||||
%% Ingress에서 Application Services로
|
||||
IngressPod -->|"/api/users/**"| UserServiceDNS
|
||||
IngressPod -->|"/api/trips/**"| TripServiceDNS
|
||||
IngressPod -->|"/api/ai/**"| AIServiceDNS
|
||||
IngressPod -->|"/api/locations/**"| LocationServiceDNS
|
||||
|
||||
%% ClusterIP Services에서 실제 Pod로
|
||||
UserServiceDNS -->|"내부 로드밸런싱"| UserService
|
||||
TripServiceDNS -->|"내부 로드밸런싱"| TripService
|
||||
AIServiceDNS -->|"내부 로드밸런싱"| AIService
|
||||
LocationServiceDNS -->|"내부 로드밸런싱"| LocationService
|
||||
|
||||
%% Application Services에서 Database로
|
||||
UserService -->|"DB 연결<br/>TCP:5432"| PostgreSQLDNS
|
||||
TripService -->|"DB 연결<br/>TCP:5432"| PostgreSQLDNS
|
||||
AIService -->|"DB 연결<br/>TCP:5432"| PostgreSQLDNS
|
||||
LocationService -->|"DB 연결<br/>TCP:5432"| PostgreSQLDNS
|
||||
|
||||
%% Application Services에서 Cache로
|
||||
UserService -->|"캐시 연결<br/>TCP:6379"| RedisDNS
|
||||
TripService -->|"캐시 연결<br/>TCP:6379"| RedisDNS
|
||||
AIService -->|"캐시 연결<br/>TCP:6379"| RedisDNS
|
||||
LocationService -->|"캐시 연결<br/>TCP:6379"| RedisDNS
|
||||
|
||||
%% ClusterIP Services에서 실제 Pod로 (Database/Cache)
|
||||
PostgreSQLDNS -->|"DB 요청 처리"| PostgreSQL
|
||||
RedisDNS -->|"캐시 요청 처리"| Redis
|
||||
|
||||
%% Storage 연결
|
||||
PostgreSQL -->|"데이터 영속화"| PostgreSQLStorage
|
||||
|
||||
%% Service Bus 연결
|
||||
AIService -->|"비동기 메시징<br/>HTTPS/AMQP"| ServiceBus
|
||||
LocationService -->|"비동기 메시징<br/>HTTPS/AMQP"| ServiceBus
|
||||
TripService -->|"알림 메시징<br/>HTTPS/AMQP"| ServiceBus
|
||||
|
||||
ServiceBus --> AIQueue
|
||||
ServiceBus --> LocationQueue
|
||||
ServiceBus --> NotificationQueue
|
||||
|
||||
%% 스타일 정의
|
||||
classDef azureStyle fill:#0078D4,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef k8sStyle fill:#326CE5,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef appStyle fill:#28A745,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef dbStyle fill:#DC3545,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef cacheStyle fill:#FF6B35,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef serviceStyle fill:#6610F2,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef queueStyle fill:#FD7E14,stroke:#fff,stroke-width:2px,color:#fff
|
||||
|
||||
%% 스타일 적용
|
||||
class AzureCloud,VNet azureStyle
|
||||
class AKSCluster,AKSSubnet,IngressController k8sStyle
|
||||
class AppTier,UserService,TripService,AIService,LocationService appStyle
|
||||
class DBTier,PostgreSQL,PostgreSQLStorage dbStyle
|
||||
class CacheTier,Redis cacheStyle
|
||||
class ClusterServices,UserServiceDNS,TripServiceDNS,AIServiceDNS,LocationServiceDNS,PostgreSQLDNS,RedisDNS serviceStyle
|
||||
class ServiceBus,ServiceBusSubnet,Queues,AIQueue,LocationQueue,NotificationQueue queueStyle
|
||||
190
claude/sample-network-prod.mmd
Normal file
190
claude/sample-network-prod.mmd
Normal file
@ -0,0 +1,190 @@
|
||||
graph TB
|
||||
%% 운영환경 네트워크 다이어그램
|
||||
%% AI 기반 여행 일정 생성 서비스 - 운영환경
|
||||
|
||||
%% 외부 영역
|
||||
subgraph Internet["🌐 인터넷"]
|
||||
Users["👥 실사용자<br/>(1만~10만 명)"]
|
||||
CDN["🌍 Azure Front Door<br/>+ CDN"]
|
||||
end
|
||||
|
||||
%% Azure 클라우드 영역
|
||||
subgraph AzureCloud["☁️ Azure Cloud (운영환경)"]
|
||||
|
||||
%% Virtual Network
|
||||
subgraph VNet["🏢 Virtual Network (VNet)<br/>주소 공간: 10.0.0.0/16"]
|
||||
|
||||
%% Gateway Subnet
|
||||
subgraph GatewaySubnet["🚪 Gateway Subnet<br/>10.0.4.0/24"]
|
||||
subgraph AppGateway["🛡️ Application Gateway + WAF"]
|
||||
PublicIP["📍 Public IP<br/>(고정)"]
|
||||
PrivateIP["📍 Private IP<br/>(10.0.4.10)"]
|
||||
WAF["🛡️ WAF<br/>(OWASP CRS 3.2)"]
|
||||
RateLimiter["⏱️ Rate Limiting<br/>(100 req/min/IP)"]
|
||||
end
|
||||
end
|
||||
|
||||
%% Application Subnet
|
||||
subgraph AppSubnet["🎯 Application Subnet<br/>10.0.1.0/24"]
|
||||
|
||||
%% AKS 클러스터
|
||||
subgraph AKSCluster["⚙️ AKS Premium Cluster<br/>(Multi-Zone)"]
|
||||
|
||||
%% System Node Pool
|
||||
subgraph SystemNodes["🔧 System Node Pool"]
|
||||
SystemNode1["📦 System Node 1<br/>(Zone 1)"]
|
||||
SystemNode2["📦 System Node 2<br/>(Zone 2)"]
|
||||
SystemNode3["📦 System Node 3<br/>(Zone 3)"]
|
||||
end
|
||||
|
||||
%% Application Node Pool
|
||||
subgraph AppNodes["🚀 Application Node Pool"]
|
||||
AppNode1["📦 App Node 1<br/>(Zone 1)"]
|
||||
AppNode2["📦 App Node 2<br/>(Zone 2)"]
|
||||
AppNode3["📦 App Node 3<br/>(Zone 3)"]
|
||||
end
|
||||
|
||||
%% Application Services (High Availability)
|
||||
subgraph AppServices["🚀 Application Services"]
|
||||
UserServiceHA["👤 User Service<br/>(3 replicas, HPA)"]
|
||||
TripServiceHA["🗺️ Trip Service<br/>(3 replicas, HPA)"]
|
||||
AIServiceHA["🤖 AI Service<br/>(2 replicas, HPA)"]
|
||||
LocationServiceHA["📍 Location Service<br/>(2 replicas, HPA)"]
|
||||
end
|
||||
|
||||
%% Internal Load Balancer
|
||||
subgraph InternalLB["⚖️ Internal Services"]
|
||||
UserServiceLB["user-service:8080"]
|
||||
TripServiceLB["trip-service:8080"]
|
||||
AIServiceLB["ai-service:8080"]
|
||||
LocationServiceLB["location-service:8080"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%% Database Subnet
|
||||
subgraph DBSubnet["🗄️ Database Subnet<br/>10.0.2.0/24"]
|
||||
subgraph AzurePostgreSQL["🐘 Azure PostgreSQL Flexible Server"]
|
||||
PGPrimary["📊 Primary Server<br/>(Zone 1)"]
|
||||
PGSecondary["📊 Read Replica<br/>(Zone 2)"]
|
||||
PGBackup["💾 Automated Backup<br/>(Point-in-time Recovery)"]
|
||||
end
|
||||
end
|
||||
|
||||
%% Cache Subnet
|
||||
subgraph CacheSubnet["⚡ Cache Subnet<br/>10.0.3.0/24"]
|
||||
subgraph AzureRedis["🔴 Azure Cache for Redis Premium"]
|
||||
RedisPrimary["⚡ Primary Cache<br/>(Zone 1)"]
|
||||
RedisSecondary["⚡ Secondary Cache<br/>(Zone 2)"]
|
||||
RedisCluster["🔗 Redis Cluster<br/>(High Availability)"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%% Service Bus (Premium)
|
||||
subgraph ServiceBus["📨 Azure Service Bus Premium"]
|
||||
ServiceBusHA["📮 Service Bus Namespace<br/>(sb-tripgen-prod)"]
|
||||
|
||||
subgraph QueuesHA["📬 Premium Message Queues"]
|
||||
AIQueueHA["🤖 ai-schedule-generation<br/>(Partitioned, 16GB)"]
|
||||
LocationQueueHA["📍 location-search<br/>(Partitioned, 16GB)"]
|
||||
NotificationQueueHA["🔔 notification<br/>(Partitioned, 16GB)"]
|
||||
end
|
||||
end
|
||||
|
||||
%% Private Endpoints
|
||||
subgraph PrivateEndpoints["🔒 Private Endpoints"]
|
||||
PGPrivateEndpoint["🔐 PostgreSQL<br/>Private Endpoint"]
|
||||
RedisPrivateEndpoint["🔐 Redis<br/>Private Endpoint"]
|
||||
ServiceBusPrivateEndpoint["🔐 Service Bus<br/>Private Endpoint"]
|
||||
end
|
||||
end
|
||||
|
||||
%% 네트워크 연결 관계
|
||||
|
||||
%% 외부에서 Azure로의 접근
|
||||
Users -->|"HTTPS 요청"| CDN
|
||||
CDN -->|"글로벌 가속"| PublicIP
|
||||
|
||||
%% Application Gateway 내부 흐름
|
||||
PublicIP --> WAF
|
||||
WAF --> RateLimiter
|
||||
RateLimiter --> PrivateIP
|
||||
|
||||
%% Application Gateway에서 AKS로
|
||||
PrivateIP -->|"/api/users/**<br/>NodePort 30080"| UserServiceLB
|
||||
PrivateIP -->|"/api/trips/**<br/>NodePort 30081"| TripServiceLB
|
||||
PrivateIP -->|"/api/ai/**<br/>NodePort 30082"| AIServiceLB
|
||||
PrivateIP -->|"/api/locations/**<br/>NodePort 30083"| LocationServiceLB
|
||||
|
||||
%% Load Balancer에서 실제 서비스로
|
||||
UserServiceLB -->|"고가용성 라우팅"| UserServiceHA
|
||||
TripServiceLB -->|"고가용성 라우팅"| TripServiceHA
|
||||
AIServiceLB -->|"고가용성 라우팅"| AIServiceHA
|
||||
LocationServiceLB -->|"고가용성 라우팅"| LocationServiceHA
|
||||
|
||||
%% 서비스 배치 (Multi-Zone)
|
||||
UserServiceHA -.-> AppNode1
|
||||
UserServiceHA -.-> AppNode2
|
||||
UserServiceHA -.-> AppNode3
|
||||
|
||||
TripServiceHA -.-> AppNode1
|
||||
TripServiceHA -.-> AppNode2
|
||||
TripServiceHA -.-> AppNode3
|
||||
|
||||
%% Application Services에서 Database로 (Private Endpoint)
|
||||
UserServiceHA -->|"Private Link<br/>TCP:5432"| PGPrivateEndpoint
|
||||
TripServiceHA -->|"Private Link<br/>TCP:5432"| PGPrivateEndpoint
|
||||
AIServiceHA -->|"Private Link<br/>TCP:5432"| PGPrivateEndpoint
|
||||
LocationServiceHA -->|"Private Link<br/>TCP:5432"| PGPrivateEndpoint
|
||||
|
||||
%% Private Endpoint에서 실제 서비스로
|
||||
PGPrivateEndpoint --> PGPrimary
|
||||
PGPrivateEndpoint --> PGSecondary
|
||||
|
||||
%% Application Services에서 Cache로 (Private Endpoint)
|
||||
UserServiceHA -->|"Private Link<br/>TCP:6379"| RedisPrivateEndpoint
|
||||
TripServiceHA -->|"Private Link<br/>TCP:6379"| RedisPrivateEndpoint
|
||||
AIServiceHA -->|"Private Link<br/>TCP:6379"| RedisPrivateEndpoint
|
||||
LocationServiceHA -->|"Private Link<br/>TCP:6379"| RedisPrivateEndpoint
|
||||
|
||||
%% Private Endpoint에서 Redis로
|
||||
RedisPrivateEndpoint --> RedisPrimary
|
||||
RedisPrivateEndpoint --> RedisSecondary
|
||||
|
||||
%% High Availability 연결
|
||||
PGPrimary -.->|"복제"| PGSecondary
|
||||
RedisPrimary -.->|"HA 동기화"| RedisSecondary
|
||||
PGPrimary -.->|"자동 백업"| PGBackup
|
||||
|
||||
%% Service Bus 연결 (Private Endpoint)
|
||||
AIServiceHA -->|"Private Link<br/>HTTPS/AMQP"| ServiceBusPrivateEndpoint
|
||||
LocationServiceHA -->|"Private Link<br/>HTTPS/AMQP"| ServiceBusPrivateEndpoint
|
||||
TripServiceHA -->|"Private Link<br/>HTTPS/AMQP"| ServiceBusPrivateEndpoint
|
||||
|
||||
ServiceBusPrivateEndpoint --> ServiceBusHA
|
||||
ServiceBusHA --> AIQueueHA
|
||||
ServiceBusHA --> LocationQueueHA
|
||||
ServiceBusHA --> NotificationQueueHA
|
||||
|
||||
%% 스타일 정의
|
||||
classDef azureStyle fill:#0078D4,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef k8sStyle fill:#326CE5,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef appStyle fill:#28A745,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef dbStyle fill:#DC3545,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef cacheStyle fill:#FF6B35,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef serviceStyle fill:#6610F2,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef queueStyle fill:#FD7E14,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef securityStyle fill:#E83E8C,stroke:#fff,stroke-width:2px,color:#fff
|
||||
classDef haStyle fill:#20C997,stroke:#fff,stroke-width:2px,color:#fff
|
||||
|
||||
%% 스타일 적용
|
||||
class AzureCloud,VNet azureStyle
|
||||
class AKSCluster,AppSubnet,SystemNodes,AppNodes k8sStyle
|
||||
class AppServices,UserServiceHA,TripServiceHA,AIServiceHA,LocationServiceHA appStyle
|
||||
class DBSubnet,AzurePostgreSQL,PGPrimary,PGSecondary,PGBackup dbStyle
|
||||
class CacheSubnet,AzureRedis,RedisPrimary,RedisSecondary,RedisCluster cacheStyle
|
||||
class InternalLB,UserServiceLB,TripServiceLB,AIServiceLB,LocationServiceLB serviceStyle
|
||||
class ServiceBus,ServiceBusHA,QueuesHA,AIQueueHA,LocationQueueHA,NotificationQueueHA queueStyle
|
||||
class AppGateway,WAF,RateLimiter,PrivateEndpoints,PGPrivateEndpoint,RedisPrivateEndpoint,ServiceBusPrivateEndpoint securityStyle
|
||||
class CDN,SystemNode1,SystemNode2,SystemNode3,AppNode1,AppNode2,AppNode3 haStyle
|
||||
49
claude/sample-physical-architecture-dev.mmd
Normal file
49
claude/sample-physical-architecture-dev.mmd
Normal file
@ -0,0 +1,49 @@
|
||||
graph TB
|
||||
%% Development Environment Physical Architecture
|
||||
%% Core Flow: Users → Ingress → Services → Database
|
||||
|
||||
Users[Mobile/Web Users] --> Ingress[Kubernetes Ingress Controller]
|
||||
|
||||
subgraph "Azure Kubernetes Service - Development"
|
||||
Ingress --> UserService[User Service Pod]
|
||||
Ingress --> TravelService[Travel Service Pod]
|
||||
Ingress --> ScheduleService[AI Service Pod]
|
||||
Ingress --> LocationService[Location Service Pod]
|
||||
|
||||
UserService --> PostgreSQL[PostgreSQL Pod<br/>16GB Storage]
|
||||
TravelService --> PostgreSQL
|
||||
ScheduleService --> PostgreSQL
|
||||
LocationService --> PostgreSQL
|
||||
|
||||
UserService --> Redis[Redis Pod<br/>Memory Cache]
|
||||
TravelService --> Redis
|
||||
ScheduleService --> Redis
|
||||
LocationService --> Redis
|
||||
|
||||
TravelService --> ServiceBus[Azure Service Bus<br/>Basic Tier]
|
||||
ScheduleService --> ServiceBus
|
||||
LocationService --> ServiceBus
|
||||
end
|
||||
|
||||
%% External APIs
|
||||
ExternalAPI[External APIs<br/>OpenAI, Maps, Weather] --> ScheduleService
|
||||
ExternalAPI --> LocationService
|
||||
|
||||
%% Essential Azure Services
|
||||
AKS --> ContainerRegistry[Azure Container Registry]
|
||||
|
||||
%% Node Configuration
|
||||
subgraph "Node Pool"
|
||||
NodePool[2x Standard B2s<br/>2 vCPU, 4GB RAM]
|
||||
end
|
||||
|
||||
%% Styling
|
||||
classDef azureService fill:#0078d4,stroke:#333,stroke-width:2px,color:#fff
|
||||
classDef microservice fill:#ff6b6b,stroke:#333,stroke-width:2px,color:#fff
|
||||
classDef database fill:#4ecdc4,stroke:#333,stroke-width:2px,color:#fff
|
||||
classDef external fill:#95e1d3,stroke:#333,stroke-width:2px,color:#333
|
||||
|
||||
class Ingress,ServiceBus,ContainerRegistry azureService
|
||||
class UserService,TravelService,ScheduleService,LocationService microservice
|
||||
class PostgreSQL,Redis database
|
||||
class Users,ExternalAPI external
|
||||
184
claude/sample-physical-architecture-prod.mmd
Normal file
184
claude/sample-physical-architecture-prod.mmd
Normal file
@ -0,0 +1,184 @@
|
||||
graph TB
|
||||
%% Production Environment Physical Architecture
|
||||
%% Enterprise-grade Azure Cloud Architecture
|
||||
|
||||
Users[Mobile/Web Users<br/>1만~10만 명] --> CDN[Azure Front Door<br/>+ CDN]
|
||||
|
||||
subgraph "Azure Cloud - Production Environment"
|
||||
CDN --> AppGateway[Application Gateway<br/>+ WAF v2<br/>Zone Redundant]
|
||||
|
||||
subgraph "VNet (10.0.0.0/16)"
|
||||
subgraph "Gateway Subnet (10.0.4.0/24)"
|
||||
AppGateway
|
||||
end
|
||||
|
||||
subgraph "Application Subnet (10.0.1.0/24)"
|
||||
subgraph "AKS Premium Cluster - Multi-Zone"
|
||||
direction TB
|
||||
|
||||
subgraph "System Node Pool"
|
||||
SystemNode1[System Node 1<br/>Zone 1<br/>D2s_v3]
|
||||
SystemNode2[System Node 2<br/>Zone 2<br/>D2s_v3]
|
||||
SystemNode3[System Node 3<br/>Zone 3<br/>D2s_v3]
|
||||
end
|
||||
|
||||
subgraph "Application Node Pool"
|
||||
AppNode1[App Node 1<br/>Zone 1<br/>D4s_v3]
|
||||
AppNode2[App Node 2<br/>Zone 2<br/>D4s_v3]
|
||||
AppNode3[App Node 3<br/>Zone 3<br/>D4s_v3]
|
||||
end
|
||||
|
||||
subgraph "Application Services"
|
||||
UserService[User Service<br/>3 replicas, HPA<br/>2-10 replicas]
|
||||
TripService[Trip Service<br/>3 replicas, HPA<br/>3-15 replicas]
|
||||
AIService[AI Service<br/>2 replicas, HPA<br/>2-8 replicas]
|
||||
LocationService[Location Service<br/>2 replicas, HPA<br/>2-10 replicas]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
AppGateway -->|NodePort 30080-30083| UserService
|
||||
AppGateway -->|NodePort 30080-30083| TripService
|
||||
AppGateway -->|NodePort 30080-30083| AIService
|
||||
AppGateway -->|NodePort 30080-30083| LocationService
|
||||
|
||||
subgraph "Database Subnet (10.0.2.0/24)"
|
||||
PostgreSQLPrimary[Azure PostgreSQL<br/>Flexible Server<br/>Primary - Zone 1<br/>GP_Standard_D4s_v3]
|
||||
PostgreSQLReplica[PostgreSQL<br/>Read Replica<br/>Zone 2]
|
||||
PostgreSQLBackup[Automated Backup<br/>Point-in-time Recovery<br/>35 days retention]
|
||||
end
|
||||
|
||||
subgraph "Cache Subnet (10.0.3.0/24)"
|
||||
RedisPrimary[Azure Redis Premium<br/>P2 - 6GB<br/>Primary - Zone 1]
|
||||
RedisSecondary[Redis Secondary<br/>Zone 2<br/>HA Enabled]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph "Service Bus Premium"
|
||||
ServiceBusPremium[Azure Service Bus<br/>Premium Tier<br/>sb-tripgen-prod]
|
||||
|
||||
subgraph "Message Queues"
|
||||
AIQueue[ai-schedule-generation<br/>Partitioned, 16GB]
|
||||
LocationQueue[location-search<br/>Partitioned, 16GB]
|
||||
NotificationQueue[notification<br/>Partitioned, 16GB]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph "Private Endpoints"
|
||||
PostgreSQLEndpoint[PostgreSQL<br/>Private Endpoint<br/>10.0.2.10]
|
||||
RedisEndpoint[Redis<br/>Private Endpoint<br/>10.0.3.10]
|
||||
ServiceBusEndpoint[Service Bus<br/>Private Endpoint<br/>10.0.5.10]
|
||||
KeyVaultEndpoint[Key Vault<br/>Private Endpoint<br/>10.0.6.10]
|
||||
end
|
||||
|
||||
subgraph "Security & Management"
|
||||
KeyVault[Azure Key Vault<br/>Premium<br/>HSM-backed]
|
||||
AAD[Azure Active Directory<br/>RBAC Integration]
|
||||
Monitor[Azure Monitor<br/>+ Application Insights<br/>Log Analytics]
|
||||
end
|
||||
|
||||
%% Private Link Connections
|
||||
UserService -->|Private Link| PostgreSQLEndpoint
|
||||
TripService -->|Private Link| PostgreSQLEndpoint
|
||||
AIService -->|Private Link| PostgreSQLEndpoint
|
||||
LocationService -->|Private Link| PostgreSQLEndpoint
|
||||
|
||||
PostgreSQLEndpoint --> PostgreSQLPrimary
|
||||
PostgreSQLEndpoint --> PostgreSQLReplica
|
||||
|
||||
UserService -->|Private Link| RedisEndpoint
|
||||
TripService -->|Private Link| RedisEndpoint
|
||||
AIService -->|Private Link| RedisEndpoint
|
||||
LocationService -->|Private Link| RedisEndpoint
|
||||
|
||||
RedisEndpoint --> RedisPrimary
|
||||
RedisEndpoint --> RedisSecondary
|
||||
|
||||
AIService -->|Private Link| ServiceBusEndpoint
|
||||
LocationService -->|Private Link| ServiceBusEndpoint
|
||||
TripService -->|Private Link| ServiceBusEndpoint
|
||||
|
||||
ServiceBusEndpoint --> ServiceBusPremium
|
||||
ServiceBusPremium --> AIQueue
|
||||
ServiceBusPremium --> LocationQueue
|
||||
ServiceBusPremium --> NotificationQueue
|
||||
|
||||
%% High Availability Connections
|
||||
PostgreSQLPrimary -.->|Replication| PostgreSQLReplica
|
||||
PostgreSQLPrimary -.->|Auto Backup| PostgreSQLBackup
|
||||
RedisPrimary -.->|HA Sync| RedisSecondary
|
||||
|
||||
%% Security Connections
|
||||
UserService -.->|Managed Identity| KeyVaultEndpoint
|
||||
TripService -.->|Managed Identity| KeyVaultEndpoint
|
||||
AIService -.->|Managed Identity| KeyVaultEndpoint
|
||||
LocationService -.->|Managed Identity| KeyVaultEndpoint
|
||||
|
||||
KeyVaultEndpoint --> KeyVault
|
||||
|
||||
UserService -.->|RBAC| AAD
|
||||
TripService -.->|RBAC| AAD
|
||||
AIService -.->|RBAC| AAD
|
||||
LocationService -.->|RBAC| AAD
|
||||
|
||||
%% Monitoring Connections
|
||||
UserService -.->|Telemetry| Monitor
|
||||
TripService -.->|Telemetry| Monitor
|
||||
AIService -.->|Telemetry| Monitor
|
||||
LocationService -.->|Telemetry| Monitor
|
||||
end
|
||||
|
||||
%% External Integrations
|
||||
subgraph "External Services"
|
||||
ExternalAPI[External APIs<br/>OpenAI GPT-4 Turbo<br/>Google Maps API<br/>OpenWeatherMap API]
|
||||
end
|
||||
|
||||
%% External Connections
|
||||
ExternalAPI -->|HTTPS/TLS 1.3| AIService
|
||||
ExternalAPI -->|HTTPS/TLS 1.3| LocationService
|
||||
|
||||
%% DevOps & CI/CD
|
||||
subgraph "DevOps Infrastructure"
|
||||
GitHubActions[GitHub Actions<br/>Enterprise CI/CD]
|
||||
ArgoCD[ArgoCD<br/>GitOps Deployment<br/>HA Mode]
|
||||
ContainerRegistry[Azure Container Registry<br/>Premium Tier<br/>Geo-replicated]
|
||||
end
|
||||
|
||||
%% DevOps Connections
|
||||
GitHubActions -->|Build & Push| ContainerRegistry
|
||||
ArgoCD -->|Deploy| UserService
|
||||
ArgoCD -->|Deploy| TripService
|
||||
ArgoCD -->|Deploy| AIService
|
||||
ArgoCD -->|Deploy| LocationService
|
||||
|
||||
%% Backup & DR
|
||||
subgraph "Backup & Disaster Recovery"
|
||||
BackupVault[Azure Backup Vault<br/>GRS - 99.999999999%]
|
||||
DRSite[DR Site<br/>Secondary Region<br/>Korea Central]
|
||||
end
|
||||
|
||||
PostgreSQLPrimary -.->|Automated Backup| BackupVault
|
||||
RedisPrimary -.->|Data Persistence| BackupVault
|
||||
ContainerRegistry -.->|Image Backup| BackupVault
|
||||
BackupVault -.->|Geo-replication| DRSite
|
||||
|
||||
%% Styling
|
||||
classDef azureService fill:#0078d4,stroke:#333,stroke-width:2px,color:#fff
|
||||
classDef microservice fill:#28a745,stroke:#333,stroke-width:2px,color:#fff
|
||||
classDef database fill:#dc3545,stroke:#333,stroke-width:2px,color:#fff
|
||||
classDef security fill:#ffc107,stroke:#333,stroke-width:2px,color:#333
|
||||
classDef external fill:#17a2b8,stroke:#333,stroke-width:2px,color:#fff
|
||||
classDef devops fill:#6f42c1,stroke:#333,stroke-width:2px,color:#fff
|
||||
classDef backup fill:#e83e8c,stroke:#333,stroke-width:2px,color:#fff
|
||||
classDef privateEndpoint fill:#fd7e14,stroke:#333,stroke-width:2px,color:#fff
|
||||
classDef nodePool fill:#20c997,stroke:#333,stroke-width:2px,color:#fff
|
||||
|
||||
class CDN,AppGateway,ServiceBusPremium,ContainerRegistry,Monitor,AAD azureService
|
||||
class UserService,TripService,AIService,LocationService microservice
|
||||
class PostgreSQLPrimary,PostgreSQLReplica,PostgreSQLBackup,RedisPrimary,RedisSecondary database
|
||||
class KeyVault,KeyVaultEndpoint security
|
||||
class Users,ExternalAPI external
|
||||
class GitHubActions,ArgoCD devops
|
||||
class BackupVault,DRSite backup
|
||||
class PostgreSQLEndpoint,RedisEndpoint,ServiceBusEndpoint privateEndpoint
|
||||
class SystemNode1,SystemNode2,SystemNode3,AppNode1,AppNode2,AppNode3 nodePool
|
||||
268
claude/sample-physical-architecture.md
Normal file
268
claude/sample-physical-architecture.md
Normal file
@ -0,0 +1,268 @@
|
||||
# 물리 아키텍처 설계서 - 마스터 인덱스
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 설계 목적
|
||||
- AI 기반 여행 일정 생성 서비스의 Azure Cloud 기반 물리 아키텍처 설계
|
||||
- 개발환경과 운영환경의 체계적인 아키텍처 분리 및 관리
|
||||
- 환경별 특화 구성과 단계적 확장 전략 제시
|
||||
|
||||
### 1.2 아키텍처 분리 원칙
|
||||
- **환경별 특화**: 개발환경과 운영환경의 목적에 맞는 최적화
|
||||
- **단계적 발전**: 개발→운영 단계적 아키텍처 진화
|
||||
- **비용 효율성**: 환경별 비용 최적화 전략
|
||||
- **운영 단순성**: 환경별 복잡도 적정 수준 유지
|
||||
|
||||
### 1.3 문서 구조
|
||||
```
|
||||
physical-architecture.md (마스터 인덱스)
|
||||
├── physical-architecture-dev.md (개발환경)
|
||||
└── physical-architecture-prod.md (운영환경)
|
||||
```
|
||||
|
||||
### 1.4 참조 아키텍처
|
||||
- HighLevel아키텍처정의서: design/high-level-architecture.md
|
||||
- 논리아키텍처: design/backend/logical/logical-architecture.md
|
||||
- 아키텍처패턴: design/pattern/아키텍처패턴.md
|
||||
- API설계서: design/backend/api/*.yaml
|
||||
|
||||
## 2. 환경별 아키텍처 개요
|
||||
|
||||
### 2.1 환경별 특성 비교
|
||||
|
||||
| 구분 | 개발환경 | 운영환경 |
|
||||
|------|----------|----------|
|
||||
| **목적** | MVP 개발/검증 | 실제 서비스 운영 |
|
||||
| **가용성** | 95% | 99.9% |
|
||||
| **사용자** | 개발팀(5명) | 실사용자(1만~10만) |
|
||||
| **확장성** | 고정 리소스 | 자동 스케일링 |
|
||||
| **보안** | 기본 수준 | 엔터프라이즈급 |
|
||||
| **비용** | 최소화($150/월) | 최적화($2,650/월) |
|
||||
| **복잡도** | 단순 | 고도화 |
|
||||
|
||||
### 2.2 환경별 세부 문서
|
||||
|
||||
#### 2.2.1 개발환경 아키텍처
|
||||
📄 **[물리 아키텍처 설계서 - 개발환경](./physical-architecture-dev.md)**
|
||||
|
||||
**주요 특징:**
|
||||
- **비용 최적화**: Spot Instance, 로컬 스토리지 활용
|
||||
- **개발 편의성**: 복잡한 설정 최소화, 빠른 배포
|
||||
- **단순한 보안**: 기본 Network Policy, JWT 검증
|
||||
- **Pod 기반 백킹서비스**: PostgreSQL, Redis Pod 배포
|
||||
|
||||
**핵심 구성:**
|
||||
📄 **[개발환경 물리 아키텍처 다이어그램](./physical-architecture-dev.mmd)**
|
||||
- NGINX Ingress → AKS Basic → Pod Services 구조
|
||||
- Application Pods, PostgreSQL Pod, Redis Pod 배치
|
||||
|
||||
#### 2.2.2 운영환경 아키텍처
|
||||
📄 **[물리 아키텍처 설계서 - 운영환경](./physical-architecture-prod.md)**
|
||||
|
||||
**주요 특징:**
|
||||
- **고가용성**: Multi-Zone 배포, 자동 장애조치
|
||||
- **확장성**: HPA 기반 자동 스케일링 (10배 확장)
|
||||
- **엔터프라이즈 보안**: 다층 보안, Private Endpoint
|
||||
- **관리형 서비스**: Azure Database, Cache for Redis
|
||||
|
||||
**핵심 구성:**
|
||||
📄 **[운영환경 물리 아키텍처 다이어그램](./physical-architecture-prod.mmd)**
|
||||
- Azure Front Door → App Gateway + WAF → AKS Premium 구조
|
||||
- Multi-Zone Apps, Azure PostgreSQL, Azure Redis Premium 배치
|
||||
|
||||
### 2.3 핵심 아키텍처 결정사항
|
||||
|
||||
#### 2.3.1 공통 아키텍처 원칙
|
||||
- **서비스 메시 제거**: Istio 대신 Kubernetes Network Policies 사용
|
||||
- **비동기 통신 중심**: 직접적인 서비스 간 호출 최소화
|
||||
- **Managed Identity**: 키 없는 인증으로 보안 강화
|
||||
- **다층 보안**: L1(Network) → L2(Gateway) → L3(Identity) → L4(Data)
|
||||
|
||||
#### 2.3.2 환경별 차별화 전략
|
||||
|
||||
**개발환경 최적화:**
|
||||
- 개발 속도와 비용 효율성 우선
|
||||
- 단순한 구성으로 운영 부담 최소화
|
||||
- Pod 기반 백킹서비스로 의존성 제거
|
||||
|
||||
**운영환경 최적화:**
|
||||
- 가용성과 확장성 우선
|
||||
- 관리형 서비스로 운영 안정성 확보
|
||||
- 엔터프라이즈급 보안 및 모니터링
|
||||
|
||||
## 3. 네트워크 아키텍처 비교
|
||||
|
||||
### 3.1 환경별 네트워크 전략
|
||||
|
||||
#### 3.1.1 환경별 네트워크 전략 비교
|
||||
|
||||
| 구성 요소 | 개발환경 | 운영환경 | 비교 |
|
||||
|-----------|----------|----------|------|
|
||||
| **인그레스** | NGINX Ingress Controller | Azure Application Gateway + WAF | 운영환경에서 WAF 보안 강화 |
|
||||
| **네트워크** | 단일 서브넷 구성 | 다중 서브넷 (Application/Database/Cache) | 운영환경에서 계층적 분리 |
|
||||
| **보안** | 기본 Network Policy | Private Endpoint, NSG 강화 | 운영환경에서 엔터프라이즈급 보안 |
|
||||
| **접근** | 인터넷 직접 접근 허용 | Private Link 기반 보안 접근 | 운영환경에서 보안 접근 제한 |
|
||||
|
||||
### 3.2 네트워크 보안 전략
|
||||
|
||||
#### 3.2.1 공통 보안 원칙
|
||||
- **Network Policies**: Pod 간 통신 제어
|
||||
- **Managed Identity**: 키 없는 인증
|
||||
- **Private Endpoints**: Azure 서비스 보안 접근
|
||||
- **TLS 암호화**: 모든 외부 통신
|
||||
|
||||
#### 3.2.2 환경별 보안 수준
|
||||
|
||||
| 보안 요소 | 개발환경 | 운영환경 | 보안 수준 |
|
||||
|-----------|----------|----------|----------|
|
||||
| **Network Policy** | 기본 (개발 편의성 고려) | 엄격한 적용 | 운영환경에서 강화 |
|
||||
| **시크릿 관리** | Kubernetes Secrets | Azure Key Vault | 운영환경에서 HSM 보안 |
|
||||
| **암호화** | HTTPS 인그레스 레벨 | End-to-End TLS 1.3 | 운영환경에서 완전 암호화 |
|
||||
| **웹 보안** | - | WAF + DDoS 보호 | 운영환경 전용 |
|
||||
|
||||
## 4. 데이터 아키텍처 비교
|
||||
|
||||
### 4.1 환경별 데이터 전략
|
||||
|
||||
#### 4.1.1 환경별 데이터 구성 비교
|
||||
|
||||
| 데이터 서비스 | 개발환경 | 운영환경 | 가용성 | 비용 |
|
||||
|-------------|----------|----------|---------|------|
|
||||
| **PostgreSQL** | Kubernetes Pod (hostPath) | Azure Database Flexible Server | 95% vs 99.9% | 무료 vs $450/월 |
|
||||
| **Redis** | Memory Only Pod | Azure Cache Premium (Cluster) | 단일 vs 클러스터 | 무료 vs $250/월 |
|
||||
| **백업** | 수동 (주 1회) | 자동 (35일 보존) | 로컬 vs 지역간 복제 | - |
|
||||
| **데이터 지속성** | 재시작 시 손실 가능 | Zone Redundant | - | - |
|
||||
|
||||
### 4.2 캐시 전략 비교
|
||||
|
||||
#### 4.2.1 다층 캐시 아키텍처
|
||||
| 캐시 계층 | 캐시 타입 | TTL | 개발환경 설정 | 운영환경 설정 | 용도 |
|
||||
|----------|----------|-----|-------------|-------------|------|
|
||||
| **L1_Application** | Caffeine Cache | 5분 | max_entries: 1000 | max_entries: 2000 | 애플리케이션 레벨 로컬 캐시 |
|
||||
| **L2_Distributed** | Redis | 30분 | cluster_mode: false | cluster_mode: true | 분산 캐시, eviction_policy: allkeys-lru |
|
||||
|
||||
#### 4.2.2 환경별 캐시 특성 비교
|
||||
|
||||
| 캐시 특성 | 개발환경 | 운영환경 | 비고 |
|
||||
|-----------|----------|----------|------|
|
||||
| **Redis 구성** | 단일 Pod | Premium 클러스터 | 운영환경에서 고가용성 |
|
||||
| **데이터 지속성** | 메모리 전용 | 지속성 백업 | 운영환경에서 데이터 보장 |
|
||||
| **성능** | 기본 성능 | 최적화된 성능 | 운영환경에서 향상된 처리 능력 |
|
||||
|
||||
## 5. 보안 아키텍처 비교
|
||||
|
||||
### 5.1 다층 보안 아키텍처
|
||||
|
||||
#### 5.1.1 공통 보안 계층
|
||||
| 보안 계층 | 보안 기술 | 적용 범위 | 보안 목적 |
|
||||
|----------|----------|----------|----------|
|
||||
| **L1_Network** | Kubernetes Network Policies | Pod-to-Pod 통신 제어 | 내부 네트워크 마이크로 세그먼테이션 |
|
||||
| **L2_Gateway** | API Gateway JWT 검증 | 외부 요청 인증/인가 | API 레벨 인증 및 인가 제어 |
|
||||
| **L3_Identity** | Azure Managed Identity | Azure 서비스 접근 | 클라우드 리소스 안전한 접근 |
|
||||
| **L4_Data** | Private Link + Key Vault | 데이터 암호화 및 비밀 관리 | 엔드투엔드 데이터 보호 |
|
||||
|
||||
### 5.2 환경별 보안 수준
|
||||
|
||||
#### 5.2.1 환경별 보안 수준 비교
|
||||
|
||||
| 보안 영역 | 개발환경 | 운영환경 | 보안 강화 |
|
||||
|-----------|----------|----------|----------|
|
||||
| **인증** | JWT (고정 시크릿) | Azure AD + Managed Identity | 운영환경에서 엔터프라이즈 인증 |
|
||||
| **네트워크** | 기본 Network Policy | 엄격한 Network Policy + Private Endpoint | 운영환경에서 네트워크 격리 강화 |
|
||||
| **시크릿** | Kubernetes Secrets | Azure Key Vault (HSM) | 운영환경에서 하드웨어 보안 모듈 |
|
||||
| **암호화** | HTTPS (인그레스 레벨) | End-to-End TLS 1.3 | 운영환경에서 전 구간 암호화 |
|
||||
|
||||
## 6. 모니터링 및 운영
|
||||
|
||||
### 6.1 환경별 모니터링 전략
|
||||
|
||||
#### 6.1.1 환경별 모니터링 도구 비교
|
||||
|
||||
| 모니터링 요소 | 개발환경 | 운영환경 | 기능 차이 |
|
||||
|-------------|----------|----------|----------|
|
||||
| **도구** | Kubernetes Dashboard, kubectl logs | Azure Monitor, Application Insights | 운영환경에서 전문 APM 도구 |
|
||||
| **메트릭** | 기본 Pod/Node 메트릭 | 포괄적 APM, 비즈니스 메트릭 | 운영환경에서 비즈니스 인사이트 |
|
||||
| **알림** | 기본 알림 (Pod 재시작) | 다단계 알림 (PagerDuty, Teams) | 운영환경에서 전문 알림 체계 |
|
||||
| **로그** | 로컬 파일시스템 (7일) | Log Analytics (90일) | 운영환경에서 장기 보존 |
|
||||
|
||||
### 6.2 CI/CD 및 배포 전략
|
||||
|
||||
#### 6.2.1 환별별 배포 방식
|
||||
|
||||
#### 6.2.1 환경별 배포 방식 비교
|
||||
|
||||
| 배포 요소 | 개발환경 | 운영환경 | 안정성 차이 |
|
||||
|-----------|----------|----------|----------|
|
||||
| **배포 방식** | Rolling Update | Blue-Green Deployment | 운영환경에서 무중단 배포 |
|
||||
| **자동화** | develop 브랜치 자동 | tag 생성 + 수동 승인 | 운영환경에서 더 신중한 배포 |
|
||||
| **테스트** | 기본 헬스체크 | 종합 품질 게이트 (80% 커버리지) | 운영환경에서 더 엄격한 테스트 |
|
||||
| **다운타임** | 허용 (1-2분) | Zero Downtime | 운영환경에서 서비스 연속성 보장 |
|
||||
|
||||
## 7. 비용 분석
|
||||
|
||||
### 7.1 환경별 비용 구조
|
||||
|
||||
#### 7.1.1 월간 비용 비교 (USD)
|
||||
|
||||
| 구성요소 | 개발환경 | 운영환경 | 차이 |
|
||||
|----------|----------|----------|------|
|
||||
| **컴퓨팅** | | | |
|
||||
| AKS 노드 | $120 (Spot) | $1,200 (Reserved) | 10배 |
|
||||
| **데이터** | | | |
|
||||
| PostgreSQL | $0 (Pod) | $450 (Managed) | 무제한 |
|
||||
| Redis | $0 (Pod) | $250 (Premium) | 무제한 |
|
||||
| **네트워킹** | | | |
|
||||
| Load Balancer | $20 | $150 | 7.5배 |
|
||||
| **기타** | | | |
|
||||
| Service Bus | $10 | $150 | 15배 |
|
||||
| 모니터링 | $0 | $100 | 무제한 |
|
||||
| **총합** | **$150** | **$2,650** | **17.7배** |
|
||||
|
||||
#### 7.1.2 비용 최적화 전략
|
||||
|
||||
#### 7.1.2 환경별 비용 최적화 전략 비교
|
||||
|
||||
| 최적화 영역 | 개발환경 | 운영환경 | 절약 효과 |
|
||||
|-------------|----------|----------|----------|
|
||||
| **컴퓨팅 비용** | Spot Instances 사용 | Reserved Instances | 70% vs 30% 절약 |
|
||||
| **백킹서비스** | Pod 기반 (무료) | 관리형 서비스 | 100% 절약 vs 안정성 |
|
||||
| **리소스 관리** | 비업무시간 자동 종료 | 자동 스케일링 | 시간 절약 vs 효율성 |
|
||||
| **사이징 전략** | 고정 리소스 | 성능 기반 적정 sizing | 단순 vs 최적화 |
|
||||
|
||||
## 8. 전환 및 확장 계획
|
||||
|
||||
### 8.1 개발환경 → 운영환경 전환 체크리스트
|
||||
|
||||
| 카테고리 | 체크 항목 | 상태 | 우선순위 | 비고 |
|
||||
|---------|-----------|------|----------|------|
|
||||
| **데이터 마이그레이션** | 개발 데이터 백업 | ☐ | 높음 | pg_dump 사용 |
|
||||
| **데이터 마이그레이션** | 스키마 마이그레이션 스크립트 | ☐ | 높음 | Flyway/Liquibase 고려 |
|
||||
| **데이터 마이그레이션** | Azure Database 프로비저닝 | ☐ | 높음 | Flexible Server 구성 |
|
||||
| **설정 변경** | 환경 변수 분리 | ☐ | 높음 | ConfigMap/Secret 분리 |
|
||||
| **설정 변경** | Azure Key Vault 설정 | ☐ | 높음 | HSM 보안 모듈 |
|
||||
| **설정 변경** | Managed Identity 구성 | ☐ | 높음 | 키 없는 인증 |
|
||||
| **모니터링** | Azure Monitor 설정 | ☐ | 중간 | Log Analytics 연동 |
|
||||
| **모니터링** | 알림 정책 수립 | ☐ | 중간 | PagerDuty/Teams 연동 |
|
||||
| **모니터링** | 대시보드 구축 | ☐ | 낮음 | Application Insights |
|
||||
|
||||
### 8.2 단계별 확장 로드맵
|
||||
|
||||
| 단계 | 기간 | 핵심 목표 | 주요 작업 | 사용자 지원 | 가용성 |
|
||||
|------|------|----------|----------|-------------|----------|
|
||||
| **Phase 1** | 현재-6개월 | 안정화 | 개발환경 → 운영환경 전환<br/>기본 모니터링 및 알림 구축 | 1만 사용자 | 99.9% |
|
||||
| **Phase 2** | 6-12개월 | 최적화 | 성능 최적화 및 비용 효율화<br/>고급 모니터링 (APM) 도입 | 10만 동시 사용자 | 99.9% |
|
||||
| **Phase 3** | 12-18개월 | 글로벌 확장 | 다중 리전 배포<br/>글로벌 CDN 및 로드 밸런싱 | 100만 사용자 | 99.95% |
|
||||
|
||||
## 9. 핵심 SLA 지표
|
||||
|
||||
### 9.1 환경별 서비스 수준 목표
|
||||
|
||||
| SLA 항목 | 개발환경 | 운영환경 | 글로벌환경 (Phase 3) |
|
||||
|---------|----------|----------|---------------------|
|
||||
| **가용성** | 95% | 99.9% | 99.95% |
|
||||
| **응답시간** | < 10초 | < 5초 | < 2초 |
|
||||
| **배포시간** | 30분 | 10분 | 5분 |
|
||||
| **복구시간** | 수동 복구 | < 5분 | < 2분 |
|
||||
| **동시사용자** | 개발팀 (5명) | 10만명 | 100만명 |
|
||||
| **월간비용** | $150 | $2,650 | $15,000+ |
|
||||
| **보안인시던트** | 모니터링 없음 | 0건 목표 | 0건 목표 |
|
||||
@ -12,6 +12,8 @@
|
||||
- UI/UX설계서의 '사용자 플로우'참조하여 설계
|
||||
- 마이크로서비스 내부의 처리 흐름을 표시
|
||||
- **각 서비스-시나리오별로 분리하여 각각 작성**
|
||||
- 요청/응답을 **한글로 표시**
|
||||
- Repository CRUD 처리를 한글로 설명하고 SQL은 사용하지 말것
|
||||
- 각 서비스별 주요 시나리오마다 독립적인 시퀀스 설계 수행
|
||||
- 프론트엔드와 백엔드 책임 분리: 프론트엔드에서 할 수 있는 것은 백엔드로 요청 안하게 함
|
||||
- 표현 요소
|
||||
|
||||
@ -40,7 +40,11 @@ replicate:
|
||||
|
||||
# CORS Configuration
|
||||
cors:
|
||||
allowed-origins: ${CORS_ALLOWED_ORIGINS:http://localhost:*}
|
||||
allowed-origins: ${CORS_ALLOWED_ORIGINS:http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://kt-event-marketing.20.214.196.128.nip.io}
|
||||
allowed-methods: ${CORS_ALLOWED_METHODS:GET,POST,PUT,DELETE,OPTIONS,PATCH}
|
||||
allowed-headers: ${CORS_ALLOWED_HEADERS:*}
|
||||
allow-credentials: ${CORS_ALLOW_CREDENTIALS:true}
|
||||
max-age: ${CORS_MAX_AGE:3600}
|
||||
|
||||
# Actuator
|
||||
management:
|
||||
|
||||
582
deployment/cicd/CICD-GUIDE.md
Normal file
582
deployment/cicd/CICD-GUIDE.md
Normal file
@ -0,0 +1,582 @@
|
||||
# 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 |
|
||||
288
deployment/cicd/SETUP-SUMMARY.md
Normal file
288
deployment/cicd/SETUP-SUMMARY.md
Normal file
@ -0,0 +1,288 @@
|
||||
# GitHub Actions CI/CD 파이프라인 구축 완료
|
||||
|
||||
## 작업 일시
|
||||
2025-10-29
|
||||
|
||||
## 작업 내용
|
||||
|
||||
### 1. Kustomize 디렉토리 구조 생성 ✅
|
||||
|
||||
```
|
||||
.github/kustomize/
|
||||
├── base/ # 기본 매니페스트 (35개 파일)
|
||||
│ ├── kustomization.yaml # 기본 리소스 정의
|
||||
│ ├── cm-common.yaml
|
||||
│ ├── secret-common.yaml
|
||||
│ ├── secret-imagepull.yaml
|
||||
│ ├── ingress.yaml
|
||||
│ └── {service}-*.yaml # 7개 서비스 × 4개 리소스
|
||||
└── overlays/ # 환경별 설정
|
||||
├── dev/ # Dev 환경 (9개 파일)
|
||||
│ ├── kustomization.yaml
|
||||
│ └── *-service-patch.yaml # 7개 서비스
|
||||
├── staging/ # Staging 환경 (9개 파일)
|
||||
│ ├── kustomization.yaml
|
||||
│ └── *-service-patch.yaml # 7개 서비스
|
||||
└── prod/ # Prod 환경 (9개 파일)
|
||||
├── kustomization.yaml
|
||||
└── *-service-patch.yaml # 7개 서비스
|
||||
```
|
||||
|
||||
**총 파일 수**: 62개
|
||||
|
||||
### 2. GitHub Actions 워크플로우 생성 ✅
|
||||
|
||||
**파일**: `.github/workflows/backend-cicd.yaml`
|
||||
|
||||
**주요 기능**:
|
||||
- 변경된 서비스 자동 감지
|
||||
- 병렬 빌드 및 테스트
|
||||
- ACR에 Docker 이미지 푸시
|
||||
- Kustomize를 사용한 AKS 배포
|
||||
- 배포 검증 및 알림
|
||||
|
||||
**트리거**:
|
||||
- develop 브랜치 push → dev 환경 자동 배포
|
||||
- main 브랜치 push → prod 환경 자동 배포
|
||||
- Manual workflow dispatch → 원하는 환경/서비스 선택 배포
|
||||
|
||||
**Jobs**:
|
||||
1. `detect-changes`: 변경된 서비스 및 환경 감지
|
||||
2. `build-and-push`: 서비스별 병렬 빌드 및 푸시
|
||||
3. `deploy`: Kustomize 기반 AKS 배포
|
||||
4. `notify`: 배포 결과 알림
|
||||
|
||||
### 3. 배포 스크립트 생성 ✅
|
||||
|
||||
**디렉토리**: `.github/scripts/`
|
||||
|
||||
1. **deploy.sh**
|
||||
- 로컬에서 수동 배포를 위한 메인 스크립트
|
||||
- 환경별 배포 설정 자동 적용
|
||||
- 사용법: `./deploy.sh <env> [service]`
|
||||
|
||||
2. **generate-patches.sh**
|
||||
- Staging과 Prod 환경의 패치 파일 자동 생성
|
||||
- 리소스 할당량을 환경에 맞게 설정
|
||||
|
||||
3. **copy-manifests-to-base.py**
|
||||
- 기존 K8s 매니페스트를 base 디렉토리로 복사
|
||||
- namespace 선언 자동 제거
|
||||
|
||||
### 4. 환경별 설정 파일 생성 ✅
|
||||
|
||||
**디렉토리**: `.github/config/`
|
||||
|
||||
1. **deploy_env_vars_dev**
|
||||
- Dev 환경 변수 정의
|
||||
- Replicas: 1, CPU: 256m-1024m, Memory: 256Mi-1024Mi
|
||||
|
||||
2. **deploy_env_vars_staging**
|
||||
- Staging 환경 변수 정의
|
||||
- Replicas: 2, CPU: 512m-2048m, Memory: 512Mi-2048Mi
|
||||
|
||||
3. **deploy_env_vars_prod**
|
||||
- Prod 환경 변수 정의
|
||||
- Replicas: 3, CPU: 1024m-4096m, Memory: 1024Mi-4096Mi
|
||||
|
||||
### 5. 문서화 완료 ✅
|
||||
|
||||
1. **deployment/cicd/CICD-GUIDE.md** (15KB)
|
||||
- 전체 CI/CD 파이프라인 가이드
|
||||
- 사전 요구사항 및 설정 방법
|
||||
- 상세한 트러블슈팅 가이드
|
||||
- 모니터링 및 롤백 방법
|
||||
|
||||
2. **.github/README.md** (6KB)
|
||||
- CI/CD 인프라 구조 설명
|
||||
- 배포 프로세스 가이드
|
||||
- 환경별 설정 요약
|
||||
|
||||
3. **deployment/cicd/SETUP-SUMMARY.md** (이 파일)
|
||||
- 구축 완료 요약
|
||||
|
||||
## 시스템 정보
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| 시스템명 | kt-event-marketing |
|
||||
| JDK 버전 | 21 |
|
||||
| 빌드 도구 | Gradle |
|
||||
| ACR | acrdigitalgarage01.azurecr.io |
|
||||
| AKS 클러스터 | aks-digitalgarage-01 |
|
||||
| 리소스 그룹 | rg-digitalgarage-01 |
|
||||
| 네임스페이스 | kt-event-marketing |
|
||||
| 서비스 수 | 7개 |
|
||||
|
||||
## 서비스 목록
|
||||
|
||||
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)
|
||||
|
||||
## 환경별 설정
|
||||
|
||||
| 환경 | 브랜치 | 이미지 태그 | Replicas | CPU Limit | Memory Limit |
|
||||
|------|--------|-------------|----------|-----------|--------------|
|
||||
| Dev | develop | dev | 1 | 1024m | 1024Mi |
|
||||
| Staging | manual | staging | 2 | 2048m | 2048Mi |
|
||||
| Prod | main | prod | 3 | 4096m | 4096Mi |
|
||||
|
||||
## 다음 단계 (Required)
|
||||
|
||||
### 1. GitHub Secrets 설정 필수
|
||||
|
||||
다음 Secrets를 GitHub Repository에 등록해야 합니다:
|
||||
|
||||
```bash
|
||||
# ACR 자격증명 확인
|
||||
az acr credential show --name acrdigitalgarage01
|
||||
|
||||
# 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
|
||||
```
|
||||
|
||||
**필수 Secrets**:
|
||||
1. `ACR_USERNAME` - ACR 사용자명
|
||||
2. `ACR_PASSWORD` - ACR 패스워드
|
||||
3. `AZURE_CREDENTIALS` - Service Principal JSON
|
||||
|
||||
**등록 경로**:
|
||||
GitHub Repository → Settings → Secrets and variables → Actions → New repository secret
|
||||
|
||||
### 2. 초기 배포 테스트
|
||||
|
||||
```bash
|
||||
# 로컬에서 Kustomize 빌드 테스트
|
||||
cd .github/kustomize/overlays/dev
|
||||
kustomize build .
|
||||
|
||||
# Azure 로그인
|
||||
az login
|
||||
|
||||
# AKS 자격증명 가져오기
|
||||
az aks get-credentials \
|
||||
--resource-group rg-digitalgarage-01 \
|
||||
--name aks-digitalgarage-01
|
||||
|
||||
# Dev 환경 배포 테스트
|
||||
./.github/scripts/deploy.sh dev
|
||||
```
|
||||
|
||||
### 3. GitHub Actions 워크플로우 테스트
|
||||
|
||||
```bash
|
||||
# develop 브랜치에 커밋하여 자동 배포 트리거
|
||||
git checkout develop
|
||||
git add .
|
||||
git commit -m "ci: Add GitHub Actions CI/CD pipeline"
|
||||
git push origin develop
|
||||
```
|
||||
|
||||
또는 GitHub Actions UI에서 Manual workflow dispatch 실행
|
||||
|
||||
## 주요 특징
|
||||
|
||||
### 1. Kustomize 기반 환경 관리
|
||||
- Base + Overlays 패턴으로 중복 최소화
|
||||
- 환경별 리소스 할당량 자동 적용
|
||||
- 이미지 태그 환경별 분리 (dev/staging/prod)
|
||||
|
||||
### 2. 자동 변경 감지
|
||||
- Git diff를 통한 변경된 서비스 자동 감지
|
||||
- 변경된 서비스만 빌드 및 배포하여 시간 절약
|
||||
- Manual trigger 시 전체 또는 특정 서비스 선택 가능
|
||||
|
||||
### 3. 병렬 처리
|
||||
- 7개 서비스를 병렬로 빌드하여 시간 단축
|
||||
- Matrix strategy를 사용한 효율적인 CI
|
||||
|
||||
### 4. 안전한 배포
|
||||
- Startup, Readiness, Liveness probe 설정
|
||||
- 롤아웃 상태 자동 확인
|
||||
- 배포 실패 시 자동 알림
|
||||
|
||||
### 5. 다단계 이미지 태깅
|
||||
- 환경별 태그: dev/staging/prod
|
||||
- Git SHA 태그: 추적성 확보
|
||||
- latest 태그: 최신 버전 유지
|
||||
|
||||
## 파일 통계
|
||||
|
||||
| 카테고리 | 파일 수 | 설명 |
|
||||
|----------|---------|------|
|
||||
| Kustomize Base | 35 | 기본 매니페스트 |
|
||||
| Kustomize Dev Overlay | 9 | Dev 환경 설정 |
|
||||
| Kustomize Staging Overlay | 9 | Staging 환경 설정 |
|
||||
| Kustomize Prod Overlay | 9 | Prod 환경 설정 |
|
||||
| Workflows | 1 | GitHub Actions 워크플로우 |
|
||||
| Scripts | 3 | 배포 및 유틸리티 스크립트 |
|
||||
| Config | 3 | 환경별 설정 파일 |
|
||||
| Documentation | 3 | 가이드 문서 |
|
||||
| **Total** | **72** | **전체 파일** |
|
||||
|
||||
## 기술 스택
|
||||
|
||||
- **CI/CD**: GitHub Actions
|
||||
- **Container Registry**: Azure Container Registry
|
||||
- **Orchestration**: Azure Kubernetes Service (AKS)
|
||||
- **Manifest Management**: Kustomize
|
||||
- **Build Tool**: Gradle
|
||||
- **Runtime**: OpenJDK 21
|
||||
- **Containerization**: Docker (multi-stage builds)
|
||||
|
||||
## 참고 사항
|
||||
|
||||
### 현재 AKS 배포 상태
|
||||
현재 7개 서비스가 모두 AKS에 배포되어 Running 상태입니다:
|
||||
- user-service: 1/1 Running
|
||||
- event-service: 1/1 Running
|
||||
- ai-service: 1/1 Running
|
||||
- content-service: 1/1 Running
|
||||
- distribution-service: 1/1 Running
|
||||
- participation-service: 1/1 Running
|
||||
- analytics-service: 1/1 Running
|
||||
|
||||
### 기존 배포 방식과의 호환성
|
||||
- 기존 K8s 매니페스트 (`deployment/k8s/`)는 그대로 유지
|
||||
- Kustomize는 별도 경로 (`.github/kustomize/`)에 구성
|
||||
- 두 방식 모두 사용 가능하나 CI/CD에서는 Kustomize 사용 권장
|
||||
|
||||
### 모니터링 및 로깅
|
||||
- Kubernetes 기본 모니터링 사용
|
||||
- Azure Monitor 통합 가능 (별도 설정 필요)
|
||||
- Application Insights 연동 가능 (별도 설정 필요)
|
||||
|
||||
## 문의 및 지원
|
||||
|
||||
- CI/CD 관련 문제: [deployment/cicd/CICD-GUIDE.md](./CICD-GUIDE.md) 참조
|
||||
- 인프라 구조: [.github/README.md](../../.github/README.md) 참조
|
||||
- 트러블슈팅: CICD-GUIDE.md의 트러블슈팅 섹션 참조
|
||||
|
||||
## 완료 체크리스트
|
||||
|
||||
- [x] Kustomize base 디렉토리 생성 및 매니페스트 복사
|
||||
- [x] 환경별 overlay 디렉토리 생성 (dev/staging/prod)
|
||||
- [x] 환경별 패치 파일 생성
|
||||
- [x] GitHub Actions 워크플로우 작성
|
||||
- [x] 배포 스크립트 작성
|
||||
- [x] 환경별 설정 파일 작성
|
||||
- [x] CI/CD 가이드 문서 작성
|
||||
- [x] README 문서 작성
|
||||
- [ ] GitHub Secrets 설정 (사용자 작업 필요)
|
||||
- [ ] 초기 배포 테스트 (사용자 작업 필요)
|
||||
- [ ] 워크플로우 동작 확인 (사용자 작업 필요)
|
||||
|
||||
---
|
||||
|
||||
**작성일**: 2025-10-29
|
||||
**작성자**: Claude (DevOps Assistant)
|
||||
**버전**: 1.0.0
|
||||
76
deployment/container/.env.event.example
Normal file
76
deployment/container/.env.event.example
Normal file
@ -0,0 +1,76 @@
|
||||
# Event Service 환경변수 설정 템플릿
|
||||
# 이 파일을 .env.event로 복사하고 실제 값으로 수정하세요
|
||||
# 사용법: docker-compose --env-file .env.event -f docker-compose-event.yml up -d
|
||||
|
||||
# =============================================================================
|
||||
# 서버 설정
|
||||
# =============================================================================
|
||||
SERVER_PORT=8082
|
||||
|
||||
# =============================================================================
|
||||
# PostgreSQL 데이터베이스 설정 (필수)
|
||||
# =============================================================================
|
||||
DB_HOST=your-postgresql-host
|
||||
DB_PORT=5432
|
||||
DB_NAME=eventdb
|
||||
DB_USERNAME=eventuser
|
||||
DB_PASSWORD=your-db-password
|
||||
DDL_AUTO=update
|
||||
|
||||
# 개발 환경 예시:
|
||||
# DB_HOST=localhost
|
||||
# DB_PORT=5432
|
||||
# DB_NAME=eventdb
|
||||
# DB_USERNAME=eventuser
|
||||
# DB_PASSWORD=eventpass123
|
||||
|
||||
# =============================================================================
|
||||
# Redis 설정 (필수)
|
||||
# =============================================================================
|
||||
REDIS_HOST=your-redis-host
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=your-redis-password
|
||||
|
||||
# 개발 환경 예시 (비밀번호 없음):
|
||||
# REDIS_HOST=localhost
|
||||
# REDIS_PORT=6379
|
||||
# REDIS_PASSWORD=
|
||||
|
||||
# =============================================================================
|
||||
# Kafka 설정 (필수)
|
||||
# =============================================================================
|
||||
KAFKA_BOOTSTRAP_SERVERS=your-kafka-host:9092
|
||||
|
||||
# 개발 환경 예시:
|
||||
# KAFKA_BOOTSTRAP_SERVERS=localhost:9092
|
||||
|
||||
# 운영 환경 예시 (다중 브로커):
|
||||
# KAFKA_BOOTSTRAP_SERVERS=kafka1:9092,kafka2:9092,kafka3:9092
|
||||
|
||||
# =============================================================================
|
||||
# JWT 설정 (필수 - 최소 32자)
|
||||
# =============================================================================
|
||||
JWT_SECRET=your-jwt-secret-key-minimum-32-characters-required
|
||||
|
||||
# 주의: 운영 환경에서는 반드시 강력한 시크릿 키를 사용하세요
|
||||
# 예시: JWT_SECRET=kt-event-marketing-prod-jwt-secret-2025-secure-random-key
|
||||
|
||||
# =============================================================================
|
||||
# 마이크로서비스 URL (선택)
|
||||
# =============================================================================
|
||||
CONTENT_SERVICE_URL=http://content-service:8083
|
||||
DISTRIBUTION_SERVICE_URL=http://distribution-service:8086
|
||||
|
||||
# Kubernetes 환경 예시:
|
||||
# CONTENT_SERVICE_URL=http://content-service.default.svc.cluster.local:8083
|
||||
# DISTRIBUTION_SERVICE_URL=http://distribution-service.default.svc.cluster.local:8086
|
||||
|
||||
# =============================================================================
|
||||
# 로깅 설정 (선택)
|
||||
# =============================================================================
|
||||
LOG_LEVEL=INFO
|
||||
SQL_LOG_LEVEL=WARN
|
||||
|
||||
# 개발 환경에서는 DEBUG로 설정 가능:
|
||||
# LOG_LEVEL=DEBUG
|
||||
# SQL_LOG_LEVEL=DEBUG
|
||||
291
deployment/container/EVENT-SERVICE-CONNECTION-GUIDE.md
Normal file
291
deployment/container/EVENT-SERVICE-CONNECTION-GUIDE.md
Normal file
@ -0,0 +1,291 @@
|
||||
# Event Service 외부 서비스 연결 가이드
|
||||
|
||||
## 📋 연결 설정 검토 결과
|
||||
|
||||
### ✅ 현재 설정 상태
|
||||
|
||||
Event Service는 다음 외부 서비스들과 연동됩니다:
|
||||
|
||||
1. **PostgreSQL** - 이벤트 데이터 저장
|
||||
2. **Redis** - AI 생성 결과 및 이미지 캐싱
|
||||
3. **Kafka** - 비동기 작업 큐 (AI 생성, 이미지 생성)
|
||||
4. **Content Service** - 콘텐츠 생성 서비스 (선택)
|
||||
5. **Distribution Service** - 배포 서비스 (선택)
|
||||
|
||||
### 📁 설정 파일
|
||||
|
||||
#### application.yml
|
||||
모든 연결 정보는 환경변수를 통해 주입되도록 설정되어 있습니다:
|
||||
|
||||
```yaml
|
||||
# PostgreSQL
|
||||
spring.datasource.url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:eventdb}
|
||||
spring.datasource.username: ${DB_USERNAME:eventuser}
|
||||
spring.datasource.password: ${DB_PASSWORD:eventpass}
|
||||
|
||||
# Redis
|
||||
spring.data.redis.host: ${REDIS_HOST:localhost}
|
||||
spring.data.redis.port: ${REDIS_PORT:6379}
|
||||
spring.data.redis.password: ${REDIS_PASSWORD:}
|
||||
|
||||
# Kafka
|
||||
spring.kafka.bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS:localhost:9092}
|
||||
|
||||
# JWT
|
||||
jwt.secret: ${JWT_SECRET:default-jwt-secret-key-for-development-minimum-32-bytes-required}
|
||||
```
|
||||
|
||||
## 🔧 필수 환경변수
|
||||
|
||||
### PostgreSQL (필수)
|
||||
```bash
|
||||
DB_HOST=your-postgresql-host # PostgreSQL 호스트
|
||||
DB_PORT=5432 # PostgreSQL 포트
|
||||
DB_NAME=eventdb # 데이터베이스 이름
|
||||
DB_USERNAME=eventuser # 데이터베이스 사용자
|
||||
DB_PASSWORD=your-password # 데이터베이스 비밀번호
|
||||
DDL_AUTO=update # Hibernate DDL 모드
|
||||
```
|
||||
|
||||
### Redis (필수)
|
||||
```bash
|
||||
REDIS_HOST=your-redis-host # Redis 호스트
|
||||
REDIS_PORT=6379 # Redis 포트
|
||||
REDIS_PASSWORD=your-password # Redis 비밀번호 (없으면 빈 문자열)
|
||||
```
|
||||
|
||||
### Kafka (필수)
|
||||
```bash
|
||||
KAFKA_BOOTSTRAP_SERVERS=kafka-host:9092 # Kafka 브로커 주소
|
||||
```
|
||||
|
||||
### JWT (필수)
|
||||
```bash
|
||||
JWT_SECRET=your-jwt-secret-key # 최소 32자 이상
|
||||
```
|
||||
|
||||
### 마이크로서비스 연동 (선택)
|
||||
```bash
|
||||
CONTENT_SERVICE_URL=http://content-service:8083
|
||||
DISTRIBUTION_SERVICE_URL=http://distribution-service:8086
|
||||
```
|
||||
|
||||
## 🚀 배포 방법
|
||||
|
||||
### 방법 1: Docker Run
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name event-service \
|
||||
-p 8082:8082 \
|
||||
-e DB_HOST=your-postgresql-host \
|
||||
-e DB_PORT=5432 \
|
||||
-e DB_NAME=eventdb \
|
||||
-e DB_USERNAME=eventuser \
|
||||
-e DB_PASSWORD=your-password \
|
||||
-e REDIS_HOST=your-redis-host \
|
||||
-e REDIS_PORT=6379 \
|
||||
-e REDIS_PASSWORD=your-redis-password \
|
||||
-e KAFKA_BOOTSTRAP_SERVERS=your-kafka:9092 \
|
||||
-e JWT_SECRET=your-jwt-secret-minimum-32-chars \
|
||||
acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service:latest
|
||||
```
|
||||
|
||||
### 방법 2: Docker Compose
|
||||
|
||||
1. **환경변수 파일 생성**:
|
||||
```bash
|
||||
cp .env.event.example .env.event
|
||||
vi .env.event # 실제 값으로 수정
|
||||
```
|
||||
|
||||
2. **컨테이너 실행**:
|
||||
```bash
|
||||
docker-compose --env-file .env.event -f docker-compose-event.yml up -d
|
||||
```
|
||||
|
||||
3. **로그 확인**:
|
||||
```bash
|
||||
docker-compose -f docker-compose-event.yml logs -f event-service
|
||||
```
|
||||
|
||||
### 방법 3: 스크립트 실행
|
||||
|
||||
```bash
|
||||
# run-event-service.sh 파일 수정 후 실행
|
||||
chmod +x run-event-service.sh
|
||||
./run-event-service.sh
|
||||
```
|
||||
|
||||
## 🔍 연결 상태 확인
|
||||
|
||||
### 헬스체크
|
||||
```bash
|
||||
curl http://localhost:8082/actuator/health
|
||||
```
|
||||
|
||||
**예상 응답**:
|
||||
```json
|
||||
{
|
||||
"status": "UP",
|
||||
"components": {
|
||||
"ping": {"status": "UP"},
|
||||
"db": {"status": "UP"},
|
||||
"redis": {"status": "UP"}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 개별 서비스 연결 확인
|
||||
|
||||
#### PostgreSQL 연결
|
||||
```bash
|
||||
docker logs event-service | grep -i "hikari"
|
||||
```
|
||||
성공 시: `HikariPool-1 - Start completed.`
|
||||
|
||||
#### Redis 연결
|
||||
```bash
|
||||
docker logs event-service | grep -i "redis"
|
||||
```
|
||||
성공 시: `Lettuce driver initialized`
|
||||
|
||||
#### Kafka 연결
|
||||
```bash
|
||||
docker logs event-service | grep -i "kafka"
|
||||
```
|
||||
성공 시: `Kafka version: ...`
|
||||
|
||||
## ⚠️ 주의사항
|
||||
|
||||
### 1. localhost 주의
|
||||
- Docker 컨테이너 내에서 `localhost`는 컨테이너 자신을 의미
|
||||
- 호스트 머신의 서비스에 접근하려면:
|
||||
- Linux/Mac: `host.docker.internal` 사용
|
||||
- 또는 호스트 IP 직접 사용
|
||||
|
||||
### 2. JWT Secret
|
||||
- 최소 32자 이상 필수
|
||||
- 운영 환경에서는 강력한 랜덤 키 사용
|
||||
- 예시: `kt-event-marketing-prod-jwt-secret-2025-secure-random-key`
|
||||
|
||||
### 3. DDL_AUTO 설정
|
||||
- 개발: `update` (스키마 자동 업데이트)
|
||||
- 운영: `validate` (스키마 검증만 수행)
|
||||
- 초기 설치: `create` (스키마 생성, 주의: 기존 데이터 삭제)
|
||||
|
||||
### 4. Kafka 토픽
|
||||
Event Service가 사용하는 토픽들이 미리 생성되어 있어야 합니다:
|
||||
- `ai-event-generation-job`
|
||||
- `image-generation-job`
|
||||
- `event-created`
|
||||
|
||||
### 5. Redis 캐시 키
|
||||
다음 키 프리픽스를 사용합니다:
|
||||
- `ai:recommendation:*` - AI 추천 결과 (TTL: 24시간)
|
||||
- `image:generation:*` - 이미지 생성 결과 (TTL: 7일)
|
||||
- `job:status:*` - 작업 상태
|
||||
|
||||
## 🐛 트러블슈팅
|
||||
|
||||
### PostgreSQL 연결 실패
|
||||
**증상**: `Connection refused` 또는 `Connection timeout`
|
||||
|
||||
**해결**:
|
||||
```bash
|
||||
# 1. PostgreSQL 서버 상태 확인
|
||||
psql -h $DB_HOST -U $DB_USERNAME -d $DB_NAME
|
||||
|
||||
# 2. 방화벽 확인
|
||||
telnet $DB_HOST 5432
|
||||
|
||||
# 3. 환경변수 확인
|
||||
docker exec event-service env | grep DB_
|
||||
```
|
||||
|
||||
### Redis 연결 실패
|
||||
**증상**: `Unable to connect to Redis`
|
||||
|
||||
**해결**:
|
||||
```bash
|
||||
# 1. Redis 서버 상태 확인
|
||||
redis-cli -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_PASSWORD ping
|
||||
|
||||
# 2. 환경변수 확인
|
||||
docker exec event-service env | grep REDIS_
|
||||
```
|
||||
|
||||
### Kafka 연결 실패
|
||||
**증상**: `Connection to node ... could not be established`
|
||||
|
||||
**해결**:
|
||||
```bash
|
||||
# 1. Kafka 서버 상태 확인
|
||||
kafka-topics.sh --bootstrap-server $KAFKA_BOOTSTRAP_SERVERS --list
|
||||
|
||||
# 2. 토픽 존재 확인
|
||||
kafka-topics.sh --bootstrap-server $KAFKA_BOOTSTRAP_SERVERS --describe --topic ai-event-generation-job
|
||||
|
||||
# 3. 환경변수 확인
|
||||
docker exec event-service env | grep KAFKA_
|
||||
```
|
||||
|
||||
### JWT 오류
|
||||
**증상**: `JWT secret key must be at least 32 characters`
|
||||
|
||||
**해결**:
|
||||
```bash
|
||||
# JWT_SECRET 길이 확인 (32자 이상이어야 함)
|
||||
docker exec event-service env | grep JWT_SECRET | awk -F'=' '{print length($2)}'
|
||||
```
|
||||
|
||||
## 📊 연결 풀 설정
|
||||
|
||||
### HikariCP (PostgreSQL)
|
||||
```yaml
|
||||
maximum-pool-size: 5 # 최대 연결 수
|
||||
minimum-idle: 2 # 최소 유휴 연결 수
|
||||
connection-timeout: 30000 # 연결 타임아웃 (30초)
|
||||
```
|
||||
|
||||
### Lettuce (Redis)
|
||||
```yaml
|
||||
max-active: 5 # 최대 활성 연결 수
|
||||
max-idle: 3 # 최대 유휴 연결 수
|
||||
min-idle: 1 # 최소 유휴 연결 수
|
||||
```
|
||||
|
||||
## 🔐 보안 권장사항
|
||||
|
||||
1. **환경변수 보안**
|
||||
- `.env` 파일은 `.gitignore`에 추가
|
||||
- 운영 환경에서는 Kubernetes Secrets 또는 AWS Secrets Manager 사용
|
||||
|
||||
2. **네트워크 보안**
|
||||
- 프로덕션 환경에서는 전용 네트워크 사용
|
||||
- 불필요한 포트 노출 금지
|
||||
|
||||
3. **인증 정보 관리**
|
||||
- 비밀번호 정기적 변경
|
||||
- 강력한 비밀번호 사용
|
||||
|
||||
## 📝 체크리스트
|
||||
|
||||
배포 전 확인 사항:
|
||||
|
||||
- [ ] PostgreSQL 서버 준비 및 데이터베이스 생성
|
||||
- [ ] Redis 서버 준비 및 연결 확인
|
||||
- [ ] Kafka 클러스터 준비 및 토픽 생성
|
||||
- [ ] JWT Secret 생성 (32자 이상)
|
||||
- [ ] 환경변수 파일 작성 및 검증
|
||||
- [ ] 네트워크 방화벽 설정 확인
|
||||
- [ ] Docker 이미지 pull 권한 확인
|
||||
- [ ] 헬스체크 엔드포인트 접근 가능 확인
|
||||
|
||||
## 📚 관련 문서
|
||||
|
||||
- [Event Service 컨테이너 이미지 빌드 가이드](build-image.md)
|
||||
- [Docker Compose 설정](docker-compose-event.yml)
|
||||
- [환경변수 템플릿](.env.event.example)
|
||||
- [실행 스크립트](run-event-service.sh)
|
||||
- [IntelliJ 실행 프로파일](../.run/EventServiceApplication.run.xml)
|
||||
@ -1,68 +1,57 @@
|
||||
# 백엔드 컨테이너 이미지 작성 결과
|
||||
# 백엔드 컨테이너 이미지 빌드 결과
|
||||
|
||||
## 작업 개요
|
||||
- **작업일시**: 2025-10-29
|
||||
- **작성자**: DevOps Engineer (송근정 "데브옵스 마스터")
|
||||
- **대상 서비스**: 6개 백엔드 마이크로서비스
|
||||
## 개요
|
||||
KT 이벤트 마케팅 서비스의 백엔드 마이크로서비스들에 대한 컨테이너 이미지를 생성하였습니다.
|
||||
|
||||
## 1. 서비스 확인
|
||||
## 작업 일시
|
||||
- 날짜: 2025-10-29
|
||||
- 빌드 환경: Windows (MINGW64_NT-10.0-19045)
|
||||
|
||||
### settings.gradle 분석
|
||||
```gradle
|
||||
## 서비스 목록 확인
|
||||
|
||||
settings.gradle에서 확인한 서비스 목록:
|
||||
```
|
||||
rootProject.name = 'kt-event-marketing'
|
||||
|
||||
// Common module
|
||||
include 'common'
|
||||
|
||||
// Microservices
|
||||
include 'user-service'
|
||||
include 'event-service'
|
||||
include 'ai-service'
|
||||
include 'content-service'
|
||||
include 'distribution-service'
|
||||
include 'participation-service'
|
||||
include 'analytics-service'
|
||||
```
|
||||
|
||||
### 빌드 가능한 서비스 (6개)
|
||||
Main Application 클래스가 존재하는 서비스:
|
||||
1. **user-service** - `UserServiceApplication.java`
|
||||
2. **event-service** - `EventServiceApplication.java`
|
||||
3. **ai-service** - `AiServiceApplication.java`
|
||||
4. **content-service** - `ContentApplication.java`
|
||||
5. **participation-service** - `ParticipationServiceApplication.java`
|
||||
6. **analytics-service** - `AnalyticsServiceApplication.java`
|
||||
**빌드 대상 서비스 (6개):**
|
||||
- user-service (Java/Spring Boot)
|
||||
- event-service (Java/Spring Boot)
|
||||
- ai-service (Java/Spring Boot)
|
||||
- distribution-service (Java/Spring Boot)
|
||||
- participation-service (Java/Spring Boot)
|
||||
- analytics-service (Java/Spring Boot)
|
||||
|
||||
### 제외된 서비스
|
||||
- **distribution-service**: 소스 코드 미구현 상태 (src/main/java 디렉토리 없음)
|
||||
**제외 대상:**
|
||||
- common: 공통 라이브러리 모듈 (독립 실행 서비스 아님)
|
||||
- content-service: Python 기반 서비스 (별도 빌드 필요)
|
||||
|
||||
## 2. bootJar 설정
|
||||
## bootJar 설정 확인
|
||||
|
||||
각 서비스의 `build.gradle`에 bootJar 설정 추가/수정:
|
||||
모든 Java 서비스의 build.gradle에 bootJar 설정이 올바르게 구성되어 있음을 확인:
|
||||
|
||||
### 설정 추가된 서비스 (5개)
|
||||
```gradle
|
||||
bootJar {
|
||||
archiveFileName = '{service-name}.jar'
|
||||
}
|
||||
```
|
||||
| 서비스명 | JAR 파일명 | 경로 |
|
||||
|---------|-----------|------|
|
||||
| user-service | user-service.jar | user-service/build/libs/user-service.jar |
|
||||
| event-service | event-service.jar | event-service/build/libs/event-service.jar |
|
||||
| ai-service | ai-service.jar | ai-service/build/libs/ai-service.jar |
|
||||
| distribution-service | distribution-service.jar | distribution-service/build/libs/distribution-service.jar |
|
||||
| participation-service | participation-service.jar | participation-service/build/libs/participation-service.jar |
|
||||
| analytics-service | analytics-service.jar | analytics-service/build/libs/analytics-service.jar |
|
||||
|
||||
- user-service/build.gradle
|
||||
- ai-service/build.gradle
|
||||
- distribution-service/build.gradle (향후 구현 대비)
|
||||
- participation-service/build.gradle
|
||||
- analytics-service/build.gradle
|
||||
## Dockerfile 생성
|
||||
|
||||
### 기존 설정 확인된 서비스 (2개)
|
||||
- event-service/build.gradle ✅
|
||||
- content-service/build.gradle ✅
|
||||
**파일 위치:** `deployment/container/Dockerfile-backend`
|
||||
|
||||
## 3. Dockerfile 생성
|
||||
|
||||
### 파일 경로
|
||||
`deployment/container/Dockerfile-backend`
|
||||
|
||||
### Dockerfile 내용
|
||||
**Dockerfile 구성:**
|
||||
```dockerfile
|
||||
# Build stage
|
||||
FROM openjdk:23-oraclelinux8 AS builder
|
||||
@ -91,58 +80,34 @@ ENTRYPOINT [ "sh", "-c" ]
|
||||
CMD ["java ${JAVA_OPTS} -jar app.jar"]
|
||||
```
|
||||
|
||||
### Dockerfile 특징
|
||||
- **Multi-stage build**: 빌드와 실행 스테이지 분리
|
||||
- **Non-root user**: 보안을 위한 k8s 사용자 실행
|
||||
- **플랫폼**: linux/amd64 (K8s 클러스터 호환)
|
||||
- **Java 버전**: OpenJDK 23
|
||||
**주요 특징:**
|
||||
- Multi-stage 빌드: 빌드 이미지와 런타임 이미지 분리
|
||||
- Base Image: openjdk:23-slim (경량화)
|
||||
- 보안: 비root 사용자(k8s)로 실행
|
||||
- 플랫폼: linux/amd64
|
||||
|
||||
## 4. JAR 파일 빌드
|
||||
## Gradle 빌드 실행
|
||||
|
||||
### 빌드 명령어
|
||||
**실행 명령:**
|
||||
```bash
|
||||
./gradlew user-service:bootJar ai-service:bootJar event-service:bootJar \
|
||||
content-service:bootJar participation-service:bootJar analytics-service:bootJar
|
||||
./gradlew clean build -x test
|
||||
```
|
||||
|
||||
### 빌드 결과
|
||||
```
|
||||
BUILD SUCCESSFUL in 27s
|
||||
33 actionable tasks: 15 executed, 18 up-to-date
|
||||
```
|
||||
**빌드 결과:**
|
||||
- 상태: ✅ BUILD SUCCESSFUL
|
||||
- 소요 시간: 33초
|
||||
- 실행된 태스크: 56개
|
||||
|
||||
### 생성된 JAR 파일
|
||||
```bash
|
||||
$ ls -lh */build/libs/*.jar
|
||||
## 컨테이너 이미지 빌드
|
||||
|
||||
-rw-r--r-- 1 KTDS 197121 94M 10월 29 09:49 ai-service/build/libs/ai-service.jar
|
||||
-rw-r--r-- 1 KTDS 197121 95M 10월 29 09:48 analytics-service/build/libs/analytics-service.jar
|
||||
-rw-r--r-- 1 KTDS 197121 78M 10월 29 09:49 content-service/build/libs/content-service.jar
|
||||
-rw-r--r-- 1 KTDS 197121 94M 10월 29 09:49 event-service/build/libs/event-service.jar
|
||||
-rw-r--r-- 1 KTDS 197121 85M 10월 29 09:49 participation-service/build/libs/participation-service.jar
|
||||
-rw-r--r-- 1 KTDS 197121 96M 10월 29 09:49 user-service/build/libs/user-service.jar
|
||||
```
|
||||
### 병렬 빌드 전략
|
||||
서브 에이전트를 활용하여 6개 서비스를 동시에 빌드하여 시간 단축
|
||||
|
||||
## 5. Docker 이미지 빌드
|
||||
### 1. user-service
|
||||
|
||||
### 사전 준비사항
|
||||
⚠️ **Docker Desktop이 실행 중이어야 합니다**
|
||||
|
||||
Docker Desktop 시작 확인:
|
||||
```bash
|
||||
# Docker 상태 확인
|
||||
docker version
|
||||
docker ps
|
||||
|
||||
# Docker Desktop이 정상 실행되면 위 명령들이 정상 동작합니다
|
||||
```
|
||||
|
||||
### 빌드 명령어
|
||||
|
||||
#### 5.1 user-service
|
||||
**빌드 명령:**
|
||||
```bash
|
||||
DOCKER_FILE=deployment/container/Dockerfile-backend
|
||||
|
||||
docker build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_LIB_DIR="user-service/build/libs" \
|
||||
@ -151,22 +116,17 @@ docker build \
|
||||
-t user-service:latest .
|
||||
```
|
||||
|
||||
#### 5.2 ai-service
|
||||
**결과:**
|
||||
- 상태: ✅ SUCCESS
|
||||
- 이미지 ID: fb07547604be
|
||||
- 이미지 크기: 1.09GB
|
||||
- Image SHA: sha256:fb07547604bee7e8ff69e56e8423299b7dec277e80d865ee5013ddd876a0b4c6
|
||||
|
||||
### 2. event-service
|
||||
|
||||
**빌드 명령:**
|
||||
```bash
|
||||
DOCKER_FILE=deployment/container/Dockerfile-backend
|
||||
|
||||
docker build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_LIB_DIR="ai-service/build/libs" \
|
||||
--build-arg ARTIFACTORY_FILE="ai-service.jar" \
|
||||
-f ${DOCKER_FILE} \
|
||||
-t ai-service:latest .
|
||||
```
|
||||
|
||||
#### 5.3 event-service
|
||||
```bash
|
||||
DOCKER_FILE=deployment/container/Dockerfile-backend
|
||||
|
||||
docker build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_LIB_DIR="event-service/build/libs" \
|
||||
@ -175,22 +135,56 @@ docker build \
|
||||
-t event-service:latest .
|
||||
```
|
||||
|
||||
#### 5.4 content-service
|
||||
**결과:**
|
||||
- 상태: ✅ SUCCESS
|
||||
- 이미지 ID: 191a9882a628
|
||||
- 이미지 크기: 1.08GB
|
||||
- 빌드 시간: ~20초
|
||||
|
||||
### 3. ai-service
|
||||
|
||||
**빌드 명령:**
|
||||
```bash
|
||||
DOCKER_FILE=deployment/container/Dockerfile-backend
|
||||
|
||||
docker build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_LIB_DIR="content-service/build/libs" \
|
||||
--build-arg ARTIFACTORY_FILE="content-service.jar" \
|
||||
--build-arg BUILD_LIB_DIR="ai-service/build/libs" \
|
||||
--build-arg ARTIFACTORY_FILE="ai-service.jar" \
|
||||
-f ${DOCKER_FILE} \
|
||||
-t content-service:latest .
|
||||
-t ai-service:latest .
|
||||
```
|
||||
|
||||
#### 5.5 participation-service
|
||||
**결과:**
|
||||
- 상태: ✅ SUCCESS
|
||||
- 이미지 ID: 498feb888dc5
|
||||
- 이미지 크기: 1.08GB
|
||||
- Image SHA: sha256:498feb888dc58a98715841c4e50f191bc8434eccd12baefa79e82b0e44a5bc40
|
||||
|
||||
### 4. distribution-service
|
||||
|
||||
**빌드 명령:**
|
||||
```bash
|
||||
DOCKER_FILE=deployment/container/Dockerfile-backend
|
||||
docker build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_LIB_DIR="distribution-service/build/libs" \
|
||||
--build-arg ARTIFACTORY_FILE="distribution-service.jar" \
|
||||
-f ${DOCKER_FILE} \
|
||||
-t distribution-service:latest .
|
||||
```
|
||||
|
||||
**결과:**
|
||||
- 상태: ✅ SUCCESS
|
||||
- 이미지 ID: e0ad31c51b63
|
||||
- 이미지 크기: 1.08GB
|
||||
- Image SHA: sha256:e0ad31c51b63b44d67f017cca8a729ae9cbb5e9e9503feddb308c09f19b70fba
|
||||
- 빌드 시간: ~60초
|
||||
|
||||
### 5. participation-service
|
||||
|
||||
**빌드 명령:**
|
||||
```bash
|
||||
DOCKER_FILE=deployment/container/Dockerfile-backend
|
||||
docker build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_LIB_DIR="participation-service/build/libs" \
|
||||
@ -199,10 +193,18 @@ docker build \
|
||||
-t participation-service:latest .
|
||||
```
|
||||
|
||||
#### 5.6 analytics-service
|
||||
**결과:**
|
||||
- 상태: ✅ SUCCESS
|
||||
- 이미지 ID: 9bd60358659b
|
||||
- 이미지 크기: 1.04GB
|
||||
- Image SHA: sha256:9bd60358659b528190edcab699152b5126dc906070e05d355310303ac292f02b
|
||||
- 빌드 시간: ~37초
|
||||
|
||||
### 6. analytics-service
|
||||
|
||||
**빌드 명령:**
|
||||
```bash
|
||||
DOCKER_FILE=deployment/container/Dockerfile-backend
|
||||
|
||||
docker build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_LIB_DIR="analytics-service/build/libs" \
|
||||
@ -211,186 +213,55 @@ docker build \
|
||||
-t analytics-service:latest .
|
||||
```
|
||||
|
||||
### 빌드 스크립트 (일괄 실행)
|
||||
**결과:**
|
||||
- 상태: ✅ SUCCESS
|
||||
- 이미지 ID: 33b53299ec16
|
||||
- 이미지 크기: 1.08GB
|
||||
- Image SHA: sha256:33b53299ec16e0021a9adca4fb32535708021073df03c30b8a0ea335348547de
|
||||
|
||||
## 생성된 이미지 확인
|
||||
|
||||
**확인 명령:**
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# build-all-images.sh
|
||||
|
||||
DOCKER_FILE=deployment/container/Dockerfile-backend
|
||||
|
||||
services=(
|
||||
"user-service"
|
||||
"ai-service"
|
||||
"event-service"
|
||||
"content-service"
|
||||
"participation-service"
|
||||
"analytics-service"
|
||||
)
|
||||
|
||||
for service in "${services[@]}"; do
|
||||
echo "Building ${service}..."
|
||||
docker build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg BUILD_LIB_DIR="${service}/build/libs" \
|
||||
--build-arg ARTIFACTORY_FILE="${service}.jar" \
|
||||
-f ${DOCKER_FILE} \
|
||||
-t ${service}:latest .
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ ${service} build successful"
|
||||
else
|
||||
echo "❌ ${service} build failed"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "🎉 All images built successfully!"
|
||||
docker images | grep -E "(user-service|event-service|ai-service|distribution-service|participation-service|analytics-service)" | grep latest
|
||||
```
|
||||
|
||||
## 6. 이미지 확인
|
||||
|
||||
### 생성된 이미지 확인 명령어
|
||||
```bash
|
||||
# 모든 서비스 이미지 확인
|
||||
docker images | grep -E "(user-service|ai-service|event-service|content-service|participation-service|analytics-service)"
|
||||
|
||||
# 개별 서비스 확인
|
||||
docker images user-service:latest
|
||||
docker images ai-service:latest
|
||||
docker images event-service:latest
|
||||
docker images content-service:latest
|
||||
docker images participation-service:latest
|
||||
docker images analytics-service:latest
|
||||
**확인 결과:**
|
||||
```
|
||||
event-service latest 191a9882a628 39 seconds ago 1.08GB
|
||||
ai-service latest 498feb888dc5 46 seconds ago 1.08GB
|
||||
analytics-service latest 33b53299ec16 46 seconds ago 1.08GB
|
||||
user-service latest fb07547604be 47 seconds ago 1.09GB
|
||||
participation-service latest 9bd60358659b 48 seconds ago 1.04GB
|
||||
distribution-service latest e0ad31c51b63 48 seconds ago 1.08GB
|
||||
```
|
||||
|
||||
### 빌드 결과 ✅
|
||||
```
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
user-service latest 91c511ef86bd About a minute ago 1.09GB
|
||||
ai-service latest 9477022fa493 About a minute ago 1.08GB
|
||||
event-service latest add81de69536 About a minute ago 1.08GB
|
||||
content-service latest aa9cc16ad041 About a minute ago 1.01GB
|
||||
participation-service latest 9b044a3854dd About a minute ago 1.04GB
|
||||
analytics-service latest ac569de42545 About a minute ago 1.08GB
|
||||
```
|
||||
## 빌드 결과 요약
|
||||
|
||||
**빌드 일시**: 2025-10-29 09:50 KST
|
||||
**빌드 소요 시간**: 약 13초 (병렬 빌드)
|
||||
**총 이미지 크기**: 6.48GB
|
||||
| 서비스명 | 이미지 태그 | 이미지 ID | 크기 | 상태 |
|
||||
|---------|-----------|----------|------|------|
|
||||
| user-service | user-service:latest | fb07547604be | 1.09GB | ✅ |
|
||||
| event-service | event-service:latest | 191a9882a628 | 1.08GB | ✅ |
|
||||
| ai-service | ai-service:latest | 498feb888dc5 | 1.08GB | ✅ |
|
||||
| distribution-service | distribution-service:latest | e0ad31c51b63 | 1.08GB | ✅ |
|
||||
| participation-service | participation-service:latest | 9bd60358659b | 1.04GB | ✅ |
|
||||
| analytics-service | analytics-service:latest | 33b53299ec16 | 1.08GB | ✅ |
|
||||
|
||||
## 7. 이미지 테스트
|
||||
**총 6개 서비스 이미지 빌드 성공**
|
||||
|
||||
### 로컬 실행 테스트 (예시: user-service)
|
||||
```bash
|
||||
# 컨테이너 실행
|
||||
docker run -d \
|
||||
--name user-service-test \
|
||||
-p 8080:8080 \
|
||||
-e SPRING_PROFILES_ACTIVE=dev \
|
||||
user-service:latest
|
||||
## 다음 단계
|
||||
|
||||
# 로그 확인
|
||||
docker logs -f user-service-test
|
||||
생성된 이미지를 사용하여 다음 작업을 진행할 수 있습니다:
|
||||
|
||||
# 헬스체크
|
||||
curl http://localhost:8080/actuator/health
|
||||
1. **로컬 테스트:** Docker Compose 또는 개별 컨테이너 실행
|
||||
2. **ACR 푸시:** Azure Container Registry에 이미지 업로드
|
||||
3. **AKS 배포:** Kubernetes 클러스터에 배포
|
||||
4. **CI/CD 통합:** GitHub Actions 또는 Jenkins 파이프라인 연동
|
||||
|
||||
# 정리
|
||||
docker stop user-service-test
|
||||
docker rm user-service-test
|
||||
```
|
||||
## 참고사항
|
||||
|
||||
## 8. 다음 단계
|
||||
|
||||
### 8.1 컨테이너 레지스트리 푸시
|
||||
```bash
|
||||
# Docker Hub 예시
|
||||
docker tag user-service:latest <your-registry>/user-service:latest
|
||||
docker push <your-registry>/user-service:latest
|
||||
|
||||
# Azure Container Registry 예시
|
||||
docker tag user-service:latest <acr-name>.azurecr.io/user-service:latest
|
||||
docker push <acr-name>.azurecr.io/user-service:latest
|
||||
```
|
||||
|
||||
### 8.2 Kubernetes 배포
|
||||
- Kubernetes Deployment 매니페스트 작성
|
||||
- Service 리소스 정의
|
||||
- ConfigMap/Secret 설정
|
||||
- Ingress 구성
|
||||
|
||||
### 8.3 CI/CD 파이프라인 구성
|
||||
- GitHub Actions 또는 Jenkins 파이프라인 작성
|
||||
- 자동 빌드 및 배포 설정
|
||||
- 이미지 태깅 전략 수립 (semantic versioning)
|
||||
|
||||
## 9. 트러블슈팅
|
||||
|
||||
### Issue 1: Docker Desktop 미실행
|
||||
**증상**:
|
||||
```
|
||||
ERROR: error during connect: open //./pipe/dockerDesktopLinuxEngine:
|
||||
The system cannot find the file specified.
|
||||
```
|
||||
|
||||
**해결**:
|
||||
1. Docker Desktop 애플리케이션 시작
|
||||
2. 시스템 트레이의 Docker 아이콘이 안정화될 때까지 대기
|
||||
3. `docker ps` 명령으로 정상 동작 확인
|
||||
|
||||
### Issue 2: JAR 파일 없음
|
||||
**증상**:
|
||||
```
|
||||
COPY failed: file not found in build context
|
||||
```
|
||||
|
||||
**해결**:
|
||||
```bash
|
||||
# JAR 파일 재빌드
|
||||
./gradlew {service-name}:clean {service-name}:bootJar
|
||||
|
||||
# 생성 확인
|
||||
ls -l {service-name}/build/libs/{service-name}.jar
|
||||
```
|
||||
|
||||
### Issue 3: 플랫폼 불일치
|
||||
**증상**: K8s 클러스터에서 실행 안됨
|
||||
|
||||
**해결**: `--platform linux/amd64` 옵션 사용 (이미 적용됨)
|
||||
|
||||
## 10. 요약
|
||||
|
||||
### ✅ 완료된 작업
|
||||
1. ✅ 6개 서비스의 bootJar 설정 완료
|
||||
2. ✅ Dockerfile-backend 생성 완료
|
||||
3. ✅ 6개 서비스 JAR 파일 빌드 완료 (총 542MB)
|
||||
4. ✅ 6개 서비스 Docker 이미지 빌드 완료 (총 6.48GB)
|
||||
|
||||
### 📊 최종 서비스 현황
|
||||
| 서비스 | JAR 빌드 | Docker 이미지 | 이미지 크기 | Image ID | 상태 |
|
||||
|--------|---------|--------------|-----------|----------|------|
|
||||
| user-service | ✅ 96MB | ✅ | 1.09GB | 91c511ef86bd | ✅ Ready |
|
||||
| ai-service | ✅ 94MB | ✅ | 1.08GB | 9477022fa493 | ✅ Ready |
|
||||
| event-service | ✅ 94MB | ✅ | 1.08GB | add81de69536 | ✅ Ready |
|
||||
| content-service | ✅ 78MB | ✅ | 1.01GB | aa9cc16ad041 | ✅ Ready |
|
||||
| participation-service | ✅ 85MB | ✅ | 1.04GB | 9b044a3854dd | ✅ Ready |
|
||||
| analytics-service | ✅ 95MB | ✅ | 1.08GB | ac569de42545 | ✅ Ready |
|
||||
| distribution-service | ❌ | ❌ | - | - | 소스 미구현 |
|
||||
|
||||
### 🎯 빌드 성능 메트릭
|
||||
- **JAR 빌드 시간**: 27초
|
||||
- **Docker 이미지 빌드**: 병렬 실행으로 약 13초
|
||||
- **총 소요 시간**: 약 40초
|
||||
- **빌드 성공률**: 100% (6/6 서비스)
|
||||
|
||||
### 🚀 다음 단계 권장사항
|
||||
1. **컨테이너 레지스트리 푸시** (예: Azure ACR, Docker Hub)
|
||||
2. **Kubernetes 배포 매니페스트 작성**
|
||||
3. **CI/CD 파이프라인 구성** (GitHub Actions 또는 Jenkins)
|
||||
4. **모니터링 및 로깅 설정**
|
||||
|
||||
---
|
||||
|
||||
**작성일**: 2025-10-29 09:50 KST
|
||||
**작성자**: DevOps Engineer (송근정 "데브옵스 마스터")
|
||||
**빌드 완료**: ✅ 모든 서비스 이미지 빌드 성공
|
||||
- 모든 이미지는 linux/amd64 플랫폼용으로 빌드됨
|
||||
- 보안을 위해 비root 사용자(k8s)로 실행 구성
|
||||
- Multi-stage 빌드로 이미지 크기 최적화
|
||||
- Java 23 (OpenJDK) 기반 런타임 사용
|
||||
- content-service(Python)는 별도의 Dockerfile로 빌드 필요
|
||||
|
||||
52
deployment/container/docker-compose-event.yml
Normal file
52
deployment/container/docker-compose-event.yml
Normal file
@ -0,0 +1,52 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
event-service:
|
||||
image: acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service:latest
|
||||
container_name: event-service
|
||||
ports:
|
||||
- "8082:8082"
|
||||
environment:
|
||||
# Server Configuration
|
||||
- SERVER_PORT=8082
|
||||
|
||||
# PostgreSQL Configuration (필수)
|
||||
- DB_HOST=${DB_HOST:-your-postgresql-host}
|
||||
- DB_PORT=${DB_PORT:-5432}
|
||||
- DB_NAME=${DB_NAME:-eventdb}
|
||||
- DB_USERNAME=${DB_USERNAME:-eventuser}
|
||||
- DB_PASSWORD=${DB_PASSWORD:-your-db-password}
|
||||
- DDL_AUTO=${DDL_AUTO:-update}
|
||||
|
||||
# Redis Configuration (필수)
|
||||
- REDIS_HOST=${REDIS_HOST:-your-redis-host}
|
||||
- REDIS_PORT=${REDIS_PORT:-6379}
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD:-your-redis-password}
|
||||
|
||||
# Kafka Configuration (필수)
|
||||
- KAFKA_BOOTSTRAP_SERVERS=${KAFKA_BOOTSTRAP_SERVERS:-your-kafka-host:9092}
|
||||
|
||||
# JWT Configuration (필수 - 최소 32자)
|
||||
- JWT_SECRET=${JWT_SECRET:-your-jwt-secret-key-minimum-32-characters-required}
|
||||
|
||||
# Microservice URLs (선택)
|
||||
- CONTENT_SERVICE_URL=${CONTENT_SERVICE_URL:-http://content-service:8083}
|
||||
- DISTRIBUTION_SERVICE_URL=${DISTRIBUTION_SERVICE_URL:-http://distribution-service:8086}
|
||||
|
||||
# Logging Configuration (선택)
|
||||
- LOG_LEVEL=${LOG_LEVEL:-INFO}
|
||||
- SQL_LOG_LEVEL=${SQL_LOG_LEVEL:-WARN}
|
||||
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8082/actuator/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
networks:
|
||||
- kt-event-network
|
||||
|
||||
networks:
|
||||
kt-event-network:
|
||||
driver: bridge
|
||||
46
deployment/container/run-event-service.sh
Normal file
46
deployment/container/run-event-service.sh
Normal file
@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Event Service Docker 실행 스크립트
|
||||
# 실제 환경에 맞게 환경변수 값을 수정하세요
|
||||
|
||||
docker run -d \
|
||||
--name event-service \
|
||||
-p 8082:8082 \
|
||||
--restart unless-stopped \
|
||||
\
|
||||
# 서버 설정
|
||||
-e SERVER_PORT=8082 \
|
||||
\
|
||||
# PostgreSQL 설정 (필수)
|
||||
-e DB_HOST=your-postgresql-host \
|
||||
-e DB_PORT=5432 \
|
||||
-e DB_NAME=eventdb \
|
||||
-e DB_USERNAME=eventuser \
|
||||
-e DB_PASSWORD=your-db-password \
|
||||
-e DDL_AUTO=update \
|
||||
\
|
||||
# Redis 설정 (필수)
|
||||
-e REDIS_HOST=your-redis-host \
|
||||
-e REDIS_PORT=6379 \
|
||||
-e REDIS_PASSWORD=your-redis-password \
|
||||
\
|
||||
# Kafka 설정 (필수)
|
||||
-e KAFKA_BOOTSTRAP_SERVERS=your-kafka-host:9092 \
|
||||
\
|
||||
# JWT 설정 (필수 - 최소 32자)
|
||||
-e JWT_SECRET=your-jwt-secret-key-minimum-32-characters-required \
|
||||
\
|
||||
# 마이크로서비스 연동 (선택)
|
||||
-e CONTENT_SERVICE_URL=http://content-service:8083 \
|
||||
-e DISTRIBUTION_SERVICE_URL=http://distribution-service:8086 \
|
||||
\
|
||||
# 로깅 설정 (선택)
|
||||
-e LOG_LEVEL=INFO \
|
||||
-e SQL_LOG_LEVEL=WARN \
|
||||
\
|
||||
# 이미지
|
||||
acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service:latest
|
||||
|
||||
echo "Event Service 컨테이너 시작됨"
|
||||
echo "헬스체크: curl http://localhost:8082/actuator/health"
|
||||
echo "로그 확인: docker logs -f event-service"
|
||||
@ -42,21 +42,21 @@ spec:
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
path: /api/v1/ai-service/actuator/health
|
||||
port: 8083
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
path: /api/v1/ai-service/actuator/health/readiness
|
||||
port: 8083
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
failureThreshold: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
path: /api/v1/ai-service/actuator/health/liveness
|
||||
port: 8083
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
|
||||
@ -42,21 +42,21 @@ spec:
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
path: /api/v1/analytics/actuator/health/liveness
|
||||
port: 8086
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
path: /api/v1/analytics/actuator/health/liveness
|
||||
port: 8086
|
||||
initialDelaySeconds: 0
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
path: /api/v1/analytics/actuator/health/readiness
|
||||
port: 8086
|
||||
initialDelaySeconds: 0
|
||||
periodSeconds: 10
|
||||
|
||||
@ -6,7 +6,7 @@ metadata:
|
||||
data:
|
||||
# Redis Configuration
|
||||
REDIS_ENABLED: "true"
|
||||
REDIS_HOST: "redis"
|
||||
REDIS_HOST: "redis-node-0.redis-headless"
|
||||
REDIS_PORT: "6379"
|
||||
REDIS_TIMEOUT: "2000ms"
|
||||
REDIS_POOL_MAX: "8"
|
||||
@ -20,7 +20,7 @@ data:
|
||||
EXCLUDE_REDIS: ""
|
||||
|
||||
# CORS Configuration
|
||||
CORS_ALLOWED_ORIGINS: "http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://kt-event-marketing.20.214.196.128.nip.io"
|
||||
CORS_ALLOWED_ORIGINS: "http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://kt-event-marketing.20.214.196.128.nip.io,http://kt-event-marketing-api.20.214.196.128.nip.io,http://*.20.214.196.128.nip.io,https://kt-event-marketing.20.214.196.128.nip.io,https://kt-event-marketing-api.20.214.196.128.nip.io,https://*.20.214.196.128.nip.io"
|
||||
CORS_ALLOWED_METHODS: "GET,POST,PUT,DELETE,OPTIONS,PATCH"
|
||||
CORS_ALLOWED_HEADERS: "*"
|
||||
CORS_ALLOW_CREDENTIALS: "true"
|
||||
|
||||
@ -89,18 +89,9 @@ spec:
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# Analytics Service - Event Analytics
|
||||
- path: /api/v1/events/([0-9]+)/analytics
|
||||
pathType: ImplementationSpecific
|
||||
backend:
|
||||
service:
|
||||
name: analytics-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# Analytics Service - User Analytics
|
||||
- path: /api/v1/users/([0-9]+)/analytics
|
||||
pathType: ImplementationSpecific
|
||||
# Analytics Service
|
||||
- path: /api/v1/analytics
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: analytics-service
|
||||
@ -108,7 +99,7 @@ spec:
|
||||
number: 80
|
||||
|
||||
# Distribution Service
|
||||
- path: /distribution
|
||||
- path: /api/v1/distribution
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
|
||||
@ -9,7 +9,7 @@ stringData:
|
||||
AZURE_STORAGE_CONNECTION_STRING: "DefaultEndpointsProtocol=https;AccountName=blobkteventstorage;AccountKey=tcBN7mAfojbl0uGsOpU7RNuKNhHnzmwDiWjN31liSMVSrWaEK+HHnYKZrjBXXAC6ZPsuxUDlsf8x+AStd++QYg==;EndpointSuffix=core.windows.net"
|
||||
|
||||
# Replicate API Token
|
||||
REPLICATE_API_TOKEN: ""
|
||||
REPLICATE_API_TOKEN: "r8_BsGCJtAg5U5kkMBXSe3pgMkPufSKnUR4NY9gJ"
|
||||
|
||||
# HuggingFace API Token
|
||||
HUGGINGFACE_API_TOKEN: ""
|
||||
|
||||
@ -42,21 +42,21 @@ spec:
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
path: /api/v1/distribution/actuator/health
|
||||
port: 8085
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
path: /api/v1/distribution/actuator/health/readiness
|
||||
port: 8085
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
failureThreshold: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
path: /api/v1/distribution/actuator/health/liveness
|
||||
port: 8085
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
|
||||
@ -42,21 +42,21 @@ spec:
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
path: /api/v1/events/actuator/health
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
path: /api/v1/events/actuator/health/readiness
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
failureThreshold: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
path: /api/v1/events/actuator/health/liveness
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
|
||||
@ -42,21 +42,21 @@ spec:
|
||||
memory: "1024Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
path: /api/v1/participations/actuator/health/liveness
|
||||
port: 8084
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
path: /api/v1/participations/actuator/health/liveness
|
||||
port: 8084
|
||||
initialDelaySeconds: 0
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
path: /api/v1/participations/actuator/health/readiness
|
||||
port: 8084
|
||||
initialDelaySeconds: 0
|
||||
periodSeconds: 10
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user