# Kubernetes 배포 가이드 ## 1. 시스템 개요 - **시스템명**: kt-event-marketing - **네임스페이스**: kt-event-marketing - **ACR**: acrdigitalgarage01 - **AKS 클러스터**: aks-digitalgarage-01 - **Ingress External IP**: 20.214.196.128 - **파드 수**: 1 (각 서비스) - **리소스 할당**: CPU 256m/1024m, Memory 256Mi/1024Mi ## 2. 서비스 구성 | 서비스 | 포트 | 데이터베이스 | Redis DB | API Path | |--------|------|------------|----------|----------| | user-service | 8081 | user-postgresql | 0 | /api/v1/users | | content-service | 8084 | N/A | 1 | /api/v1/content | | event-service | 8080 | event-postgresql | 2 | /api/v1/events, /api/v1/jobs | | ai-service | 8083 | N/A | 3 | /api/v1/ai-service | | participation-service | 8084 | participation-postgresql | 4 | /api/v1/participations, /api/v1/winners | | analytics-service | 8086 | analytic-postgresql | 5 | /api/v1/events/.../analytics, /api/v1/users/.../analytics | ## 3. 사전 확인 ### 3.1 Azure 로그인 확인 ```bash az account show ``` **확인 사항**: 올바른 Azure 구독에 로그인되어 있는지 확인 ### 3.2 AKS Credential 확인 ```bash kubectl cluster-info ``` **확인 사항**: Kubernetes 클러스터에 정상적으로 연결되어 있는지 확인 ### 3.3 Namespace 존재 확인 ```bash kubectl get ns kt-event-marketing ``` **확인 사항**: kt-event-marketing 네임스페이스가 존재하는지 확인. 없으면 생성: ```bash kubectl create namespace kt-event-marketing ``` ### 3.4 필수 서비스 확인 #### Redis 서비스 확인 ```bash kubectl get svc | grep redis ``` **확인 결과**: ``` redis ClusterIP 10.0.69.101 6379/TCP,26379/TCP redis-external LoadBalancer 10.0.68.243 20.214.210.71 6379:30397/TCP,26379:32563/TCP redis-headless ClusterIP None 6379/TCP,26379/TCP ``` **사용할 서비스**: `redis` (ClusterIP) #### 데이터베이스 서비스 확인 ```bash kubectl get svc | grep postgresql ``` **확인 결과**: ``` user-postgresql ClusterIP 10.0.189.87 5432/TCP user-postgresql-external LoadBalancer 10.0.186.11 20.249.125.115 5432:30414/TCP event-postgresql ClusterIP 10.0.245.96 5432/TCP event-postgresql-external LoadBalancer 10.0.200.134 20.249.177.232 5432:31222/TCP ``` **사용할 서비스**: - user-service: `user-postgresql` (ClusterIP) - event-service: `event-postgresql` (ClusterIP) #### Ingress Controller 확인 ```bash kubectl get svc ingress-nginx-controller -n ingress-nginx ``` **확인 결과**: ``` NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) ingress-nginx-controller LoadBalancer 10.0.76.134 20.214.196.128 80:32094/TCP,443:30210/TCP ``` **Ingress Host**: `kt-event-marketing-api.20.214.196.128.nip.io` ## 4. 매니페스트 적용 ### 4.1 공통 리소스 배포 ```bash kubectl apply -f deployment/k8s/common/ ``` **생성되는 리소스**: - Secret: `kt-event-marketing` (ImagePullSecret) - ConfigMap: `cm-common` - Secret: `secret-common` - Ingress: `kt-event-marketing` ### 4.2 user-service 배포 ```bash kubectl apply -f deployment/k8s/user-service/ ``` **생성되는 리소스**: - ConfigMap: `cm-user-service` - Secret: `secret-user-service` - Service: `user-service` - Deployment: `user-service` ### 4.3 content-service 배포 ```bash kubectl apply -f deployment/k8s/content-service/ ``` **생성되는 리소스**: - ConfigMap: `cm-content-service` - Secret: `secret-content-service` - Service: `content-service` - Deployment: `content-service` ### 4.4 event-service 배포 ```bash kubectl apply -f deployment/k8s/event-service/ ``` **생성되는 리소스**: - ConfigMap: `cm-event-service` - Secret: `secret-event-service` - Service: `event-service` - Deployment: `event-service` ### 4.5 ai-service 배포 ```bash kubectl apply -f deployment/k8s/ai-service/ ``` **생성되는 리소스**: - ConfigMap: `cm-ai-service` - Secret: `secret-ai-service` - Service: `ai-service` - Deployment: `ai-service` ### 4.6 participation-service 배포 ```bash kubectl apply -f deployment/k8s/participation-service/ ``` **생성되는 리소스**: - ConfigMap: `cm-participation-service` - Secret: `secret-participation-service` - Service: `participation-service` - Deployment: `participation-service` ### 4.7 analytics-service 배포 ```bash kubectl apply -f deployment/k8s/analytics-service/ ``` **생성되는 리소스**: - ConfigMap: `cm-analytics-service` - Secret: `secret-analytics-service` - Service: `analytics-service` - Deployment: `analytics-service` ### 4.8 전체 한번에 배포 (권장) ```bash # 공통 리소스 먼저 배포 kubectl apply -f deployment/k8s/common/ # 모든 서비스 배포 kubectl apply -f deployment/k8s/user-service/ kubectl apply -f deployment/k8s/content-service/ kubectl apply -f deployment/k8s/event-service/ kubectl apply -f deployment/k8s/ai-service/ kubectl apply -f deployment/k8s/participation-service/ kubectl apply -f deployment/k8s/analytics-service/ ``` ## 5. 배포 확인 ### 5.1 ConfigMap 및 Secret 확인 ```bash kubectl get configmap -n kt-event-marketing kubectl get secret -n kt-event-marketing ``` **예상 출력**: ``` NAME DATA AGE cm-common 41 1m cm-user-service 18 1m cm-content-service 10 1m cm-event-service 11 1m cm-ai-service 39 1m NAME TYPE DATA AGE kt-event-marketing kubernetes.io/dockerconfigjson 1 1m secret-common Opaque 2 1m secret-user-service Opaque 2 1m secret-content-service Opaque 3 1m secret-event-service Opaque 1 1m secret-ai-service Opaque 1 1m ``` ### 5.2 Service 확인 ```bash kubectl get svc -n kt-event-marketing ``` **예상 출력**: ``` NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE user-service ClusterIP 10.0.x.x 80/TCP 1m content-service ClusterIP 10.0.x.x 80/TCP 1m event-service ClusterIP 10.0.x.x 80/TCP 1m ai-service ClusterIP 10.0.x.x 80/TCP 1m ``` ### 5.3 Deployment 확인 ```bash kubectl get deployment -n kt-event-marketing ``` **예상 출력**: ``` NAME READY UP-TO-DATE AVAILABLE AGE user-service 1/1 1 1 1m content-service 1/1 1 1 1m event-service 1/1 1 1 1m ai-service 1/1 1 1 1m ``` ### 5.4 Pod 확인 ```bash kubectl get pods -n kt-event-marketing ``` **예상 출력**: ``` NAME READY STATUS RESTARTS AGE user-service-xxxxxxxxxx-xxxxx 1/1 Running 0 1m content-service-xxxxxxxxxx-xxxxx 1/1 Running 0 1m event-service-xxxxxxxxxx-xxxxx 1/1 Running 0 1m ai-service-xxxxxxxxxx-xxxxx 1/1 Running 0 1m ``` ### 5.5 Ingress 확인 ```bash kubectl get ingress -n kt-event-marketing ``` **예상 출력**: ``` NAME CLASS HOSTS ADDRESS PORTS AGE kt-event-marketing nginx kt-event-marketing-api.20.214.196.128.nip.io 20.214.196.128 80 1m ``` ### 5.6 Pod 로그 확인 ```bash # user-service 로그 kubectl logs -f deployment/user-service -n kt-event-marketing # content-service 로그 kubectl logs -f deployment/content-service -n kt-event-marketing # event-service 로그 kubectl logs -f deployment/event-service -n kt-event-marketing # ai-service 로그 kubectl logs -f deployment/ai-service -n kt-event-marketing ``` ### 5.7 Pod 상세 정보 확인 ```bash kubectl describe pod -l app=user-service -n kt-event-marketing kubectl describe pod -l app=content-service -n kt-event-marketing kubectl describe pod -l app=event-service -n kt-event-marketing kubectl describe pod -l app=ai-service -n kt-event-marketing ``` ## 6. API 테스트 ### 6.1 Health Check ```bash # user-service curl http://kt-event-marketing-api.20.214.196.128.nip.io/api/v1/users/profile # content-service curl http://kt-event-marketing-api.20.214.196.128.nip.io/api/v1/content/images/jobs/test # event-service curl http://kt-event-marketing-api.20.214.196.128.nip.io/api/v1/events # ai-service curl http://kt-event-marketing-api.20.214.196.128.nip.io/api/v1/ai-service/health ``` ### 6.2 Actuator Health Check ```bash # ClusterIP를 통한 내부 접근 테스트 kubectl run curl-test --image=curlimages/curl -i --rm --restart=Never -n kt-event-marketing -- \ curl http://user-service/actuator/health kubectl run curl-test --image=curlimages/curl -i --rm --restart=Never -n kt-event-marketing -- \ curl http://content-service/actuator/health kubectl run curl-test --image=curlimages/curl -i --rm --restart=Never -n kt-event-marketing -- \ curl http://event-service/actuator/health kubectl run curl-test --image=curlimages/curl -i --rm --restart=Never -n kt-event-marketing -- \ curl http://ai-service/actuator/health ``` ## 7. 체크리스트 검증 결과 ### 7.1 객체 이름 네이밍 룰 준수 여부 ✅ **통과** - 공통 ConfigMap: `cm-common` - 공통 Secret: `secret-common` - 서비스별 ConfigMap: `cm-{서비스명}` (예: cm-user-service) - 서비스별 Secret: `secret-{서비스명}` (예: secret-user-service) - Ingress: `kt-event-marketing` - Service: `{서비스명}` (예: user-service) - Deployment: `{서비스명}` (예: user-service) ### 7.2 Redis Host명을 ClusterIP 타입의 Service 객체로 사용 ✅ **통과** - **사용 서비스**: `redis` (ClusterIP 타입) - **확인 명령**: `kubectl get svc | grep redis` - **설정 위치**: `deployment/k8s/common/cm-common.yaml`의 `REDIS_HOST: "redis"` ### 7.3 Database Host명을 ClusterIP 타입의 Service 객체로 사용 ✅ **통과** **user-service**: - **사용 서비스**: `user-postgresql` (ClusterIP) - **확인 명령**: `kubectl get svc | grep user-postgresql` - **설정 위치**: `deployment/k8s/user-service/cm-user-service.yaml`의 `DB_HOST: "user-postgresql"` **event-service**: - **사용 서비스**: `event-postgresql` (ClusterIP) - **확인 명령**: `kubectl get svc | grep event-postgresql` - **설정 위치**: `deployment/k8s/event-service/cm-event-service.yaml`의 `DB_HOST: "event-postgresql"` ### 7.4 Secret 매니페스트에서 'stringData' 사용 ✅ **통과** - 모든 Secret 매니페스트에서 `stringData` 사용 확인 - `data` 필드 대신 `stringData` 사용으로 Base64 인코딩 불필요 **확인 파일**: - `deployment/k8s/common/secret-common.yaml` - `deployment/k8s/common/secret-imagepull.yaml` - `deployment/k8s/user-service/secret-user-service.yaml` - `deployment/k8s/content-service/secret-content-service.yaml` - `deployment/k8s/event-service/secret-event-service.yaml` - `deployment/k8s/ai-service/secret-ai-service.yaml` ### 7.5 JWT_SECRET을 openssl 명령으로 생성 ✅ **통과** - **생성 명령**: `openssl rand -base64 32` - **생성된 값**: `QL0czzXckz18kHnxpaTDoWFkq+3qKO7VQXeNvf2bOoU=` - **설정 위치**: `deployment/k8s/common/secret-common.yaml`의 `JWT_SECRET` ### 7.6 매니페스트 파일에 환경변수 미사용, 실제 값 지정 ✅ **통과** - 모든 매니페스트에서 `${변수명}` 형태가 아닌 실제 값 사용 - Ingress host: `kt-event-marketing-api.20.214.196.128.nip.io` (실제 IP 사용) ### 7.7 Image Pull Secret에 실제 USERNAME과 PASSWORD 지정 ✅ **통과** - **USERNAME**: `acrdigitalgarage01` - **PASSWORD**: `+OY+rmOagorjWvQe/tTk6oqvnZI8SmNbY/Y2o5EDcY+ACRDCDbYk` - **확인 명령**: ```bash az acr credential show -n acrdigitalgarage01 --query "username" -o tsv az acr credential show -n acrdigitalgarage01 --query "passwords[0].value" -o tsv ``` - **설정 위치**: `deployment/k8s/common/secret-imagepull.yaml` ### 7.8 Image명 형식 확인 ✅ **통과** - **형식**: `{ACR명}.azurecr.io/{시스템명}/{서비스명}:latest` - **예시**: - `acrdigitalgarage01.azurecr.io/kt-event-marketing/user-service:latest` - `acrdigitalgarage01.azurecr.io/kt-event-marketing/content-service:latest` - `acrdigitalgarage01.azurecr.io/kt-event-marketing/event-service:latest` - `acrdigitalgarage01.azurecr.io/kt-event-marketing/ai-service:latest` ### 7.9 Ingress Controller External IP 확인 및 반영 ✅ **통과** - **확인 명령**: `kubectl get svc ingress-nginx-controller -n ingress-nginx` - **EXTERNAL-IP**: `20.214.196.128` - **Ingress host**: `kt-event-marketing-api.20.214.196.128.nip.io` - **설정 위치**: `deployment/k8s/common/ingress.yaml` ### 7.10 Ingress와 Service의 포트 일치 확인 ✅ **통과** - Ingress의 `backend.service.port.number`: **80** - Service의 `port`: **80** - 모든 서비스에서 일치 확인 ### 7.11 Ingress path가 Controller @RequestMapping과 일치 ✅ **통과** | 서비스 | Controller Path | Ingress Path | |--------|----------------|--------------| | user-service | @RequestMapping("/api/v1/users") | /api/v1/users | | content-service | @RequestMapping("/api/v1/content") | /api/v1/content | | event-service | @RequestMapping("/api/v1/events") | /api/v1/events | | ai-service | /api/v1/ai-service/health | /api/v1/ai-service | ### 7.12 보안 환경변수를 Secret으로 지정 ✅ **통과** **공통 Secret** (secret-common): - REDIS_PASSWORD - JWT_SECRET **서비스별 Secret**: - **user-service**: DB_PASSWORD, DB_URL - **content-service**: AZURE_STORAGE_CONNECTION_STRING, REPLICATE_API_TOKEN, HUGGINGFACE_API_TOKEN - **event-service**: DB_PASSWORD - **ai-service**: AI_CLAUDE_API_KEY ### 7.13 REDIS_DATABASE가 각 서비스마다 다르게 지정 ✅ **통과** | 서비스 | Redis Database | 설정 위치 | |--------|---------------|-----------| | user-service | 0 | cm-user-service | | content-service | 1 | cm-content-service | | event-service | 2 | cm-event-service | | ai-service | 3 | cm-ai-service | ### 7.14 ConfigMap과 Secret을 envFrom으로 사용 ✅ **통과** - 모든 Deployment에서 `env` 대신 `envFrom` 사용 - `configMapRef`와 `secretRef`로 ConfigMap과 Secret 참조 ## 8. 실행 프로파일 환경변수 매핑 테이블 ### 8.1 user-service 환경변수 매핑 | 환경변수명 | 값 | 지정 객체 | 비고 | |-----------|---|----------|------| | SERVER_PORT | 8081 | cm-user-service | | | DB_URL | jdbc:postgresql://user-postgresql:5432/userdb | cm-user-service | | | DB_DRIVER | org.postgresql.Driver | cm-user-service | | | DB_HOST | user-postgresql | cm-user-service | ClusterIP Service | | DB_PORT | 5432 | cm-user-service | | | DB_NAME | userdb | cm-user-service | | | DB_USERNAME | eventuser | cm-user-service | | | DB_PASSWORD | Hi5Jessica! | secret-user-service | Secret | | DB_KIND | postgresql | cm-user-service | | | DDL_AUTO | update | cm-common | | | SHOW_SQL | false | cm-common | | | JPA_DIALECT | org.hibernate.dialect.PostgreSQLDialect | cm-common | | | H2_CONSOLE_ENABLED | false | cm-common | | | REDIS_ENABLED | true | cm-common | | | REDIS_HOST | redis | cm-common | ClusterIP Service | | REDIS_PORT | 6379 | cm-common | | | REDIS_PASSWORD | Hi5Jessica! | secret-common | Secret | | REDIS_DATABASE | 0 | cm-user-service | | | EXCLUDE_REDIS | "" | cm-common | | | KAFKA_BOOTSTRAP_SERVERS | 20.249.182.13:9095,4.217.131.59:9095 | cm-common | | | KAFKA_CONSUMER_GROUP | user-service-consumers | cm-user-service | | | EXCLUDE_KAFKA | "" | cm-common | | | JWT_SECRET | QL0czzXckz18kHnxpaTDoWFkq+3qKO7VQXeNvf2bOoU= | secret-common | Secret (openssl) | | JWT_ACCESS_TOKEN_VALIDITY | 604800000 | cm-common | | | CORS_ALLOWED_ORIGINS | http://localhost:8081,...,http://kt-event-marketing.20.214.196.128.nip.io | cm-common | | | LOG_LEVEL_APP | INFO | cm-common | | | LOG_LEVEL_WEB | INFO | cm-common | | | LOG_LEVEL_SQL | WARN | cm-common | | | LOG_LEVEL_SQL_TYPE | WARN | cm-common | | | LOG_FILE_PATH | logs/user-service.log | cm-user-service | | | DB_POOL_MAX | 20 | cm-user-service | | | DB_POOL_MIN | 5 | cm-user-service | | | DB_CONN_TIMEOUT | 30000 | cm-user-service | | | DB_IDLE_TIMEOUT | 600000 | cm-user-service | | | DB_MAX_LIFETIME | 1800000 | cm-user-service | | | DB_LEAK_THRESHOLD | 60000 | cm-user-service | | ### 8.2 content-service 환경변수 매핑 | 환경변수명 | 값 | 지정 객체 | 비고 | |-----------|---|----------|------| | SERVER_PORT | 8084 | cm-content-service | | | REDIS_ENABLED | true | cm-common | | | REDIS_HOST | redis | cm-common | ClusterIP Service | | REDIS_PORT | 6379 | cm-common | | | REDIS_PASSWORD | Hi5Jessica! | secret-common | Secret | | REDIS_DATABASE | 1 | cm-content-service | | | JWT_SECRET | QL0czzXckz18kHnxpaTDoWFkq+3qKO7VQXeNvf2bOoU= | secret-common | Secret | | JWT_ACCESS_TOKEN_VALIDITY | 604800000 | cm-common | | | JWT_REFRESH_TOKEN_VALIDITY | 86400000 | cm-common | | | AZURE_STORAGE_CONNECTION_STRING | DefaultEndpointsProtocol=https;... | secret-content-service | Secret | | AZURE_CONTAINER_NAME | content-images | cm-content-service | | | REPLICATE_API_URL | https://api.replicate.com | cm-content-service | | | REPLICATE_API_TOKEN | "" | secret-content-service | Secret (empty) | | REPLICATE_MODEL_VERSION | stability-ai/sdxl:... | cm-content-service | | | HUGGINGFACE_API_URL | https://api-inference.huggingface.co | cm-content-service | | | HUGGINGFACE_API_TOKEN | "" | secret-content-service | Secret (empty) | | HUGGINGFACE_MODEL | runwayml/stable-diffusion-v1-5 | cm-content-service | | | CORS_ALLOWED_ORIGINS | http://localhost:8081,...,http://kt-event-marketing.20.214.196.128.nip.io | cm-common | | | LOG_LEVEL_APP | INFO | cm-common | | | LOG_LEVEL_WEB | INFO | cm-common | | | LOG_LEVEL_ROOT | INFO | cm-common | | | LOG_FILE_PATH | logs/content-service.log | cm-content-service | | | LOG_FILE_MAX_SIZE | 10MB | cm-common | | | LOG_FILE_MAX_HISTORY | 7 | cm-common | | | LOG_FILE_TOTAL_CAP | 100MB | cm-common | | ### 8.3 event-service 환경변수 매핑 | 환경변수명 | 값 | 지정 객체 | 비고 | |-----------|---|----------|------| | SERVER_PORT | 8080 | cm-event-service | | | DB_HOST | event-postgresql | cm-event-service | ClusterIP Service | | DB_PORT | 5432 | cm-event-service | | | DB_NAME | eventdb | cm-event-service | | | DB_USERNAME | eventuser | cm-event-service | | | DB_PASSWORD | Hi5Jessica! | secret-event-service | Secret | | DDL_AUTO | update | cm-common | | | REDIS_HOST | redis | cm-common | ClusterIP Service | | REDIS_PORT | 6379 | cm-common | | | REDIS_PASSWORD | Hi5Jessica! | secret-common | Secret | | REDIS_DATABASE | 2 | cm-event-service | | | KAFKA_BOOTSTRAP_SERVERS | 20.249.182.13:9095,4.217.131.59:9095 | cm-common | | | KAFKA_CONSUMER_GROUP | event-service-consumers | cm-event-service | | | CONTENT_SERVICE_URL | http://content-service | cm-event-service | | | DISTRIBUTION_SERVICE_URL | http://distribution-service | cm-event-service | | | JWT_SECRET | QL0czzXckz18kHnxpaTDoWFkq+3qKO7VQXeNvf2bOoU= | secret-common | Secret | | LOG_LEVEL | INFO | cm-event-service | | | SQL_LOG_LEVEL | WARN | cm-event-service | | | LOG_FILE | logs/event-service.log | cm-event-service | | ### 8.4 ai-service 환경변수 매핑 | 환경변수명 | 값 | 지정 객체 | 비고 | |-----------|---|----------|------| | SERVER_PORT | 8083 | cm-ai-service | | | REDIS_HOST | redis | cm-common | ClusterIP Service | | REDIS_PORT | 6379 | cm-common | | | REDIS_PASSWORD | Hi5Jessica! | secret-common | Secret | | REDIS_DATABASE | 3 | cm-ai-service | | | REDIS_TIMEOUT | 3000 | cm-ai-service | | | REDIS_POOL_MIN | 2 | cm-ai-service | | | KAFKA_BOOTSTRAP_SERVERS | 20.249.182.13:9095,4.217.131.59:9095 | cm-common | | | KAFKA_CONSUMER_GROUP | ai-service-consumers | cm-ai-service | | | KAFKA_TOPICS_AI_JOB | ai-event-generation-job | cm-ai-service | | | KAFKA_TOPICS_AI_JOB_DLQ | ai-event-generation-job-dlq | cm-ai-service | | | JWT_SECRET | QL0czzXckz18kHnxpaTDoWFkq+3qKO7VQXeNvf2bOoU= | secret-common | Secret | | JWT_ACCESS_TOKEN_VALIDITY | 604800000 | cm-common | | | JWT_REFRESH_TOKEN_VALIDITY | 86400000 | cm-common | | | CORS_ALLOWED_ORIGINS | http://localhost:8081,...,http://kt-event-marketing.20.214.196.128.nip.io | cm-common | | | CORS_ALLOWED_METHODS | GET,POST,PUT,DELETE,OPTIONS,PATCH | cm-common | | | CORS_ALLOWED_HEADERS | "*" | cm-common | | | CORS_ALLOW_CREDENTIALS | true | cm-common | | | CORS_MAX_AGE | 3600 | cm-common | | | AI_PROVIDER | CLAUDE | cm-ai-service | | | AI_CLAUDE_API_URL | https://api.anthropic.com/v1/messages | cm-ai-service | | | AI_CLAUDE_API_KEY | sk-ant-api03-mLtyNZ... | secret-ai-service | Secret | | AI_CLAUDE_ANTHROPIC_VERSION | 2023-06-01 | cm-ai-service | | | AI_CLAUDE_MODEL | claude-sonnet-4-5-20250929 | cm-ai-service | | | AI_CLAUDE_MAX_TOKENS | 4096 | cm-ai-service | | | AI_CLAUDE_TEMPERATURE | 0.7 | cm-ai-service | | | AI_CLAUDE_TIMEOUT | 300000 | cm-ai-service | | | RESILIENCE4J_CIRCUITBREAKER_FAILURE_RATE_THRESHOLD | 50 | cm-ai-service | | | RESILIENCE4J_CIRCUITBREAKER_SLOW_CALL_RATE_THRESHOLD | 50 | cm-ai-service | | | RESILIENCE4J_CIRCUITBREAKER_SLOW_CALL_DURATION_THRESHOLD | 60s | cm-ai-service | | | RESILIENCE4J_CIRCUITBREAKER_PERMITTED_CALLS_HALF_OPEN | 3 | cm-ai-service | | | RESILIENCE4J_CIRCUITBREAKER_SLIDING_WINDOW_SIZE | 10 | cm-ai-service | | | RESILIENCE4J_CIRCUITBREAKER_MINIMUM_CALLS | 5 | cm-ai-service | | | RESILIENCE4J_CIRCUITBREAKER_WAIT_DURATION_OPEN | 60s | cm-ai-service | | | RESILIENCE4J_TIMELIMITER_TIMEOUT_DURATION | 300s | cm-ai-service | | | CACHE_TTL_RECOMMENDATION | 86400 | cm-ai-service | | | CACHE_TTL_JOB_STATUS | 86400 | cm-ai-service | | | CACHE_TTL_TREND | 3600 | cm-ai-service | | | CACHE_TTL_FALLBACK | 604800 | cm-ai-service | | | LOG_LEVEL_ROOT | INFO | cm-ai-service | | | LOG_LEVEL_AI | DEBUG | cm-ai-service | | | LOG_LEVEL_KAFKA | INFO | cm-ai-service | | | LOG_LEVEL_REDIS | INFO | cm-ai-service | | | LOG_LEVEL_RESILIENCE4J | DEBUG | cm-ai-service | | | LOG_FILE_NAME | logs/ai-service.log | cm-ai-service | | | LOG_FILE_MAX_SIZE | 10MB | cm-ai-service | | | LOG_FILE_MAX_HISTORY | 7 | cm-ai-service | | | LOG_FILE_TOTAL_CAP | 100MB | cm-ai-service | | ## 9. 트러블슈팅 ### 9.1 Pod가 ImagePullBackOff 상태인 경우 ```bash # ImagePullSecret 확인 kubectl get secret kt-event-marketing -n kt-event-marketing -o yaml # Pod 이벤트 확인 kubectl describe pod -l app=user-service -n kt-event-marketing ``` **해결 방법**: 1. ACR 자격 증명 재확인 2. ImagePullSecret 재생성 3. Deployment 재배포 ### 9.2 Pod가 CrashLoopBackOff 상태인 경우 ```bash # Pod 로그 확인 kubectl logs -l app=user-service -n kt-event-marketing --tail=100 # 이전 컨테이너 로그 확인 kubectl logs -l app=user-service -n kt-event-marketing --previous ``` **일반적인 원인**: - 데이터베이스 연결 실패 - Redis 연결 실패 - 환경변수 설정 오류 - 애플리케이션 시작 오류 ### 9.3 Ingress를 통한 접근이 안되는 경우 ```bash # Ingress 상태 확인 kubectl describe ingress kt-event-marketing -n kt-event-marketing # Ingress Controller 로그 확인 kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx ``` **확인 사항**: 1. Ingress host가 올바른지 확인 2. Service가 정상적으로 동작하는지 확인 3. Service selector와 Pod label이 일치하는지 확인 ### 9.4 데이터베이스 연결 실패 ```bash # PostgreSQL 서비스 확인 kubectl get svc | grep postgresql # Pod 내부에서 데이터베이스 연결 테스트 kubectl exec -it deployment/user-service -n kt-event-marketing -- /bin/sh # 컨테이너 내부에서 nc -zv user-postgresql 5432 ``` ### 9.5 Redis 연결 실패 ```bash # Redis 서비스 확인 kubectl get svc | grep redis # Pod 내부에서 Redis 연결 테스트 kubectl exec -it deployment/user-service -n kt-event-marketing -- /bin/sh # 컨테이너 내부에서 nc -zv redis 6379 ``` ## 10. 삭제 및 재배포 ### 10.1 특정 서비스 삭제 ```bash # user-service 삭제 kubectl delete -f deployment/k8s/user-service/ # content-service 삭제 kubectl delete -f deployment/k8s/content-service/ # event-service 삭제 kubectl delete -f deployment/k8s/event-service/ # ai-service 삭제 kubectl delete -f deployment/k8s/ai-service/ ``` ### 10.2 전체 삭제 ```bash # 모든 서비스 삭제 kubectl delete -f deployment/k8s/user-service/ kubectl delete -f deployment/k8s/content-service/ kubectl delete -f deployment/k8s/event-service/ kubectl delete -f deployment/k8s/ai-service/ # 공통 리소스 삭제 kubectl delete -f deployment/k8s/common/ ``` ### 10.3 Namespace 전체 삭제 (주의!) ```bash # ⚠️ 주의: Namespace를 삭제하면 모든 리소스가 삭제됩니다 kubectl delete namespace kt-event-marketing ``` ## 11. 참고 사항 ### 11.1 리소스 제한 - **CPU 요청**: 256m (0.25 코어) - **CPU 제한**: 1024m (1 코어) - **메모리 요청**: 256Mi - **메모리 제한**: 1024Mi 필요에 따라 `deployment.yaml`의 `resources` 섹션을 수정하여 조정할 수 있습니다. ### 11.2 Probe 설정 - **StartupProbe**: 초기 시작 확인 (최대 300초) - **ReadinessProbe**: 트래픽 수신 준비 확인 - **LivenessProbe**: 컨테이너 생존 확인 ### 11.3 Auto Scaling (추후 적용) HPA (Horizontal Pod Autoscaler) 설정 예시: ```bash kubectl autoscale deployment user-service \ --cpu-percent=70 \ --min=1 \ --max=5 \ -n kt-event-marketing ``` ### 11.4 보안 강화 - Secret 암호화: Sealed Secrets 또는 External Secrets Operator 사용 권장 - Network Policy: Pod 간 통신 제어 - RBAC: 적절한 권한 설정 ## 12. 문의 및 지원 배포 중 문제가 발생하면 다음 정보를 포함하여 문의하세요: 1. Pod 상태: `kubectl get pods -n kt-event-marketing` 2. Pod 로그: `kubectl logs -n kt-event-marketing` 3. Pod 이벤트: `kubectl describe pod -n kt-event-marketing` 4. Ingress 상태: `kubectl describe ingress kt-event-marketing -n kt-event-marketing`