diff --git a/deployment/cicd/Jenkinsfile b/deployment/cicd/Jenkinsfile index b1bc636..3f053fe 100644 --- a/deployment/cicd/Jenkinsfile +++ b/deployment/cicd/Jenkinsfile @@ -11,8 +11,22 @@ podTemplate( serviceAccount: 'jenkins', containers: [ containerTemplate(name: 'podman', image: "mgoltzsche/podman", ttyEnabled: true, command: 'cat', privileged: true), - containerTemplate(name: 'gradle', image: 'gradle:jdk17', ttyEnabled: true, command: 'cat'), - containerTemplate(name: 'azure-cli', image: 'hiondal/azure-kubectl:latest', command: 'cat', ttyEnabled: true) + containerTemplate(name: 'gradle', + image: 'gradle:jdk17', + ttyEnabled: true, + command: 'cat', + envVars: [ + envVar(key: 'DOCKER_HOST', value: 'unix:///run/podman/podman.sock'), + envVar(key: 'TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE', value: '/run/podman/podman.sock'), + envVar(key: 'TESTCONTAINERS_RYUK_DISABLED', value: 'true') + ]), + containerTemplate(name: 'azure-cli', image: 'hiondal/azure-kubectl:latest', command: 'cat', ttyEnabled: true), + containerTemplate(name: 'envsubst', image: "hiondal/envsubst", command: 'sleep', args: '1h') + ], + volumes: [ + emptyDirVolume(mountPath: '/home/gradle/.gradle', memory: false), + emptyDirVolume(mountPath: '/root/.azure', memory: false), + emptyDirVolume(mountPath: '/run/podman', memory: false) ] ) { node(PIPELINE_ID) { @@ -48,23 +62,38 @@ podTemplate( # 각 서비스별 테스트 및 분석 ./gradlew :api-gateway:test :api-gateway:jacocoTestReport :api-gateway:sonar \\ -Dsonar.projectKey=phonebill-api-gateway-\${environment} \\ - -Dsonar.projectName=phonebill-api-gateway - + -Dsonar.projectName=phonebill-api-gateway \\ + -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/** + ./gradlew :user-service:test :user-service:jacocoTestReport :user-service:sonar \\ -Dsonar.projectKey=phonebill-user-service-\${environment} \\ - -Dsonar.projectName=phonebill-user-service + -Dsonar.projectName=phonebill-user-service \\ + -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/** ./gradlew :bill-service:test :bill-service:jacocoTestReport :bill-service:sonar \\ -Dsonar.projectKey=phonebill-bill-service-\${environment} \\ - -Dsonar.projectName=phonebill-bill-service + -Dsonar.projectName=phonebill-bill-service \\ + -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/** ./gradlew :product-service:test :product-service:jacocoTestReport :product-service:sonar \\ -Dsonar.projectKey=phonebill-product-service-\${environment} \\ - -Dsonar.projectName=phonebill-product-service + -Dsonar.projectName=phonebill-product-service \\ + -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/** ./gradlew :kos-mock:test :kos-mock:jacocoTestReport :kos-mock:sonar \\ -Dsonar.projectKey=phonebill-kos-mock-\${environment} \\ - -Dsonar.projectName=phonebill-kos-mock + -Dsonar.projectName=phonebill-kos-mock \\ + -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/** """ } } @@ -93,7 +122,7 @@ podTemplate( podman build \\ --build-arg BUILD_LIB_DIR="\${service}/build/libs" \\ --build-arg ARTIFACTORY_FILE="\${service}.jar" \\ - -f deployment/container/Dockerfile \\ + -f deployment/container/Dockerfile-backend \\ -t acrdigitalgarage01.azurecr.io/phonebill/\${service}:\${environment}-\${imageTag} . podman push acrdigitalgarage01.azurecr.io/phonebill/\${service}:\${environment}-\${imageTag} @@ -132,19 +161,5 @@ podTemplate( """ } } - - stage('Health Check') { - container('azure-cli') { - sh """ - echo "🔍 Health Check starting..." - - # API Gateway Health Check - GATEWAY_POD=\$(kubectl get pod -n phonebill-\${environment} -l app=api-gateway -o jsonpath='{.items[0].metadata.name}') - kubectl -n phonebill-\${environment} exec \$GATEWAY_POD -- curl -f http://localhost:8080/actuator/health || exit 1 - - echo "✅ All services are healthy!" - """ - } - } } } \ No newline at end of file diff --git a/deployment/cicd/config/deploy_env_vars_dev b/deployment/cicd/config/deploy_env_vars_dev index d2b1855..5a49197 100644 --- a/deployment/cicd/config/deploy_env_vars_dev +++ b/deployment/cicd/config/deploy_env_vars_dev @@ -1,3 +1,3 @@ -# DEV Environment Configuration +# dev Environment Configuration resource_group=rg-digitalgarage-01 cluster_name=aks-digitalgarage-01 \ No newline at end of file diff --git a/deployment/cicd/config/deploy_env_vars_prod b/deployment/cicd/config/deploy_env_vars_prod index f0c04c4..53ee4a0 100644 --- a/deployment/cicd/config/deploy_env_vars_prod +++ b/deployment/cicd/config/deploy_env_vars_prod @@ -1,3 +1,3 @@ -# PROD Environment Configuration +# prod Environment Configuration resource_group=rg-digitalgarage-01 cluster_name=aks-digitalgarage-01 \ No newline at end of file diff --git a/deployment/cicd/config/deploy_env_vars_staging b/deployment/cicd/config/deploy_env_vars_staging index 21423e5..5873b90 100644 --- a/deployment/cicd/config/deploy_env_vars_staging +++ b/deployment/cicd/config/deploy_env_vars_staging @@ -1,3 +1,3 @@ -# STAGING Environment Configuration +# staging Environment Configuration resource_group=rg-digitalgarage-01 cluster_name=aks-digitalgarage-01 \ No newline at end of file diff --git a/deployment/cicd/jenkins-pipeline-guide.md b/deployment/cicd/jenkins-pipeline-guide.md index a8ee796..a81ec19 100644 --- a/deployment/cicd/jenkins-pipeline-guide.md +++ b/deployment/cicd/jenkins-pipeline-guide.md @@ -2,43 +2,62 @@ ## 📋 개요 -이 가이드는 통신요금 관리 서비스(phonebill)를 위한 Jenkins + Kustomize 기반 CI/CD 파이프라인 구축 방법을 제공합니다. +이 가이드는 통신요금 관리 서비스(phonebill)를 위한 Jenkins 기반 CI/CD 파이프라인 구축 방법을 안내합니다. -### 🎯 주요 특징 -- **환경별 배포**: dev, staging, prod 환경 분리 관리 -- **Kustomize 기반**: 환경별 매니페스트 관리 및 배포 -- **SonarQube 연동**: 코드 품질 분석 및 Quality Gate 적용 -- **Azure 통합**: ACR, AKS와 완전 통합 -- **Health Check**: 배포 후 서비스 상태 자동 확인 +**주요 특징:** +- Jenkins + Kustomize 기반 CI/CD 파이프라인 +- 환경별(dev/staging/prod) 매니페스트 관리 +- SonarQube 코드 품질 분석과 Quality Gate +- Azure Container Registry(ACR) 연동 +- AKS(Azure Kubernetes Service) 자동 배포 ---- +## 🏗 아키텍처 구성 -## 🏗️ 시스템 아키텍처 +``` +Jenkins Pipeline + ↓ +┌─── Build & Test (Gradle) ─────┐ +│ - 소스코드 빌드 │ +│ - 단위 테스트 실행 │ +│ - SonarQube 품질 분석 │ +│ - Quality Gate 검증 │ +└─────────────────────────────┘ + ↓ +┌─── Container Build ───────────┐ +│ - 서비스별 이미지 빌드 │ +│ - ACR에 이미지 푸시 │ +│ - 환경별 태그 관리 │ +└─────────────────────────────┘ + ↓ +┌─── Deploy to AKS ─────────────┐ +│ - Kustomize 매니페스트 적용 │ +│ - 환경별 설정 적용 │ +│ - 배포 상태 확인 │ +└─────────────────────────────┘ +``` + +## 🛠 사전 준비사항 + +### 실행 환경 정보 +- **ACR명**: acrdigitalgarage01 +- **리소스 그룹**: rg-digitalgarage-01 +- **AKS 클러스터**: aks-digitalgarage-01 ### 서비스 구성 - **시스템명**: phonebill -- **서비스 목록**: - - api-gateway (API 게이트웨이) - - user-service (사용자 서비스) - - bill-service (요금 조회 서비스) - - product-service (상품 변경 서비스) - - kos-mock (KOS Mock 서비스) +- **서비스목록**: + - api-gateway + - user-service + - bill-service + - product-service + - kos-mock -### Azure 리소스 정보 -- **ACR**: acrdigitalgarage01.azurecr.io -- **리소스 그룹**: rg-digitalgarage-01 -- **AKS 클러스터**: aks-digitalgarage-01 +## 🔧 Jenkins 환경 구성 ---- +### 1. Jenkins 필수 플러그인 설치 -## 🛠️ Jenkins 서버 환경 구성 - -### 1. 필수 플러그인 설치 - -Jenkins 관리 > 플러그인 관리에서 다음 플러그인들을 설치하세요: - -``` -📦 필수 플러그인 목록: +```bash +# Jenkins 관리 > 플러그인 관리에서 다음 플러그인 설치 - Kubernetes - Pipeline Utility Steps - Docker Pipeline @@ -49,183 +68,141 @@ Jenkins 관리 > 플러그인 관리에서 다음 플러그인들을 설치하 ### 2. Jenkins Credentials 등록 -Manage Jenkins > Credentials > Add Credentials에서 다음 정보들을 등록하세요: - -#### Azure Service Principal -```yaml -Kind: Microsoft Azure Service Principal -ID: azure-credentials -Subscription ID: {구독ID} -Client ID: {클라이언트ID} -Client Secret: {클라이언트시크릿} -Tenant ID: {테넌트ID} -Azure Environment: Azure +**Azure Service Principal 등록:** +``` +Manage Jenkins > Credentials > Add Credentials +- Kind: Microsoft Azure Service Principal +- ID: azure-credentials +- Subscription ID: {구독ID} +- Client ID: {클라이언트ID} +- Client Secret: {클라이언트시크릿} +- Tenant ID: {테넌트ID} +- Azure Environment: Azure ``` -#### ACR Credentials -```yaml -Kind: Username with password -ID: acr-credentials -Username: acrdigitalgarage01 -Password: {ACR패스워드} +**ACR Credentials 등록:** +``` +- Kind: Username with password +- ID: acr-credentials +- Username: acrdigitalgarage01 +- Password: {ACR패스워드} ``` -#### SonarQube Token -```yaml -Kind: Secret text -ID: sonarqube-token -Secret: {SonarQube토큰} +**SonarQube Token 등록:** +``` +- Kind: Secret text +- ID: sonarqube-token +- Secret: {SonarQube토큰} ``` - ---- ## 📂 Kustomize 구조 -### 디렉토리 구조 +프로젝트에 다음과 같은 Kustomize 구조가 생성되었습니다: + ``` deployment/cicd/ ├── kustomize/ -│ ├── base/ # 기본 매니페스트 -│ │ ├── common/ # 공통 리소스 -│ │ ├── api-gateway/ # API Gateway 리소스 -│ │ ├── user-service/ # User Service 리소스 -│ │ ├── bill-service/ # Bill Service 리소스 -│ │ ├── product-service/ # Product Service 리소스 -│ │ ├── kos-mock/ # KOS Mock 리소스 -│ │ └── kustomization.yaml # Base Kustomization -│ └── overlays/ # 환경별 오버레이 -│ ├── dev/ # 개발 환경 -│ ├── staging/ # 스테이징 환경 -│ └── prod/ # 운영 환경 -├── config/ # 환경별 설정 -├── scripts/ # 배포 스크립트 -└── Jenkinsfile # Jenkins 파이프라인 +│ ├── base/ +│ │ ├── kustomization.yaml +│ │ ├── namespace.yaml +│ │ ├── common/ +│ │ │ ├── cm-common.yaml +│ │ │ ├── secret-common.yaml +│ │ │ ├── secret-imagepull.yaml +│ │ │ └── ingress.yaml +│ │ └── [각 서비스별 매니페스트] +│ └── overlays/ +│ ├── dev/ +│ ├── staging/ +│ └── prod/ +├── config/ +│ ├── deploy_env_vars_dev +│ ├── deploy_env_vars_staging +│ └── deploy_env_vars_prod +├── scripts/ +│ └── deploy.sh +└── Jenkinsfile ``` -### 환경별 특성 +## 🚀 Jenkins Pipeline 설정 -#### 🔧 DEV 환경 -- **네임스페이스**: phonebill-dev -- **도메인**: phonebill-api.20.214.196.128.nip.io (HTTP) -- **프로파일**: dev -- **DDL**: update (테이블 자동 생성/수정) -- **JWT 토큰**: 5시간 유효 -- **Replica**: 모든 서비스 1개 -- **리소스**: requests(256m CPU, 256Mi Memory), limits(1024m CPU, 1024Mi Memory) +### 1. Pipeline Job 생성 -#### 🔄 STAGING 환경 -- **네임스페이스**: phonebill-staging -- **도메인**: phonebill-staging.20.214.196.128.nip.io (HTTPS) -- **프로파일**: staging -- **DDL**: validate (스키마 검증만) -- **JWT 토큰**: 5시간 유효 -- **Replica**: 모든 서비스 2개 -- **리소스**: requests(512m CPU, 512Mi Memory), limits(2048m CPU, 2048Mi Memory) +1. Jenkins 웹 UI에서 **New Item > Pipeline** 선택 +2. **Pipeline script from SCM** 설정: + ``` + SCM: Git + Repository URL: {Git저장소URL} + Branch: main (또는 develop) + Script Path: deployment/cicd/Jenkinsfile + ``` -#### 🚀 PROD 환경 -- **네임스페이스**: phonebill-prod -- **도메인**: phonebill.20.214.196.128.nip.io (HTTPS + SSL 강화) -- **프로파일**: prod -- **DDL**: validate (스키마 검증만) -- **JWT 토큰**: 1시간 유효 (보안 강화) -- **Replica**: 모든 서비스 3개 -- **리소스**: requests(1024m CPU, 1024Mi Memory), limits(4096m CPU, 4096Mi Memory) +3. **Pipeline Parameters** 설정: + ``` + ENVIRONMENT: Choice Parameter (dev, staging, prod) + IMAGE_TAG: String Parameter (default: latest) + ``` ---- +### 2. Pipeline 단계별 설명 -## 🔄 CI/CD 파이프라인 단계 +**Stage 1: Get Source** +- Git 저장소에서 소스코드 체크아웃 +- 환경별 설정 파일 로드 -### Pipeline 단계 설명 +**Stage 2: Setup AKS** +- Azure 서비스 프린시팔로 로그인 +- AKS 클러스터 연결 설정 +- 네임스페이스 생성 -1. **Get Source** 📥 - - Git 소스 코드 체크아웃 - - 환경별 설정 파일 로딩 +**Stage 3: Build & SonarQube Analysis** +- Gradle 빌드 및 테스트 실행 +- 각 서비스별 SonarQube 분석 +- 코드 커버리지 리포트 생성 -2. **Setup AKS** ⚙️ - - Azure Service Principal로 로그인 - - AKS 클러스터 연결 설정 - - 네임스페이스 생성 +**Stage 4: Quality Gate** +- SonarQube Quality Gate 결과 대기 +- 품질 기준 미달 시 파이프라인 중단 -3. **Build & SonarQube Analysis** 🔍 - - Gradle 빌드 실행 - - 각 서비스별 단위 테스트 - - SonarQube 코드 품질 분석 - - 테스트 커버리지 리포트 생성 +**Stage 5: Build & Push Images** +- 서비스별 컨테이너 이미지 빌드 +- ACR에 이미지 푸시 +- 환경별 태그 적용 -4. **Quality Gate** 🚪 - - SonarQube Quality Gate 검증 - - 품질 기준 미달 시 파이프라인 중단 +**Stage 6: Update Kustomize & Deploy** +- 이미지 태그 업데이트 +- Kustomize를 통한 매니페스트 적용 +- 배포 완료 대기 -5. **Build & Push Images** 🐳 - - 각 서비스별 컨테이너 이미지 빌드 - - ACR에 이미지 푸시 - - 환경별 이미지 태그 적용 - -6. **Update Kustomize & Deploy** 🚀 - - Kustomize를 통한 매니페스트 생성 - - 이미지 태그 업데이트 - - Kubernetes 클러스터에 배포 - - 배포 완료 대기 - -7. **Health Check** 🔍 - - API Gateway Health Check - - 서비스 정상 동작 확인 - -### SonarQube Quality Gate 기준 +## ⚙ SonarQube 설정 +### Quality Gate 규칙 ```yaml -품질 기준: -- Coverage: >= 80% -- Duplicated Lines: <= 3% -- Maintainability Rating: <= A -- Reliability Rating: <= A -- Security Rating: <= A +Coverage: >= 80% +Duplicated Lines: <= 3% +Maintainability Rating: <= A +Reliability Rating: <= A +Security Rating: <= A ``` ---- - -## 🚀 Jenkins Pipeline Job 생성 - -### 1. 새 Pipeline Job 생성 - -1. Jenkins 웹 UI에서 **New Item** 클릭 -2. **Pipeline** 선택 후 프로젝트명 입력 -3. **OK** 클릭 - -### 2. Pipeline 설정 - -#### Source Code Management -```yaml -SCM: Git -Repository URL: {Git저장소URL} -Branch: main (또는 develop) -Script Path: deployment/cicd/Jenkinsfile +### 프로젝트별 분석 제외 항목 +``` +**/config/** +**/entity/** +**/dto/** +**/*Application.class +**/exception/** ``` -#### Pipeline Parameters -```yaml -ENVIRONMENT: - - Type: Choice Parameter - - Choices: dev, staging, prod - - Default: dev +## 🎯 배포 실행 방법 -IMAGE_TAG: - - Type: String Parameter - - Default: latest -``` +### 1. Jenkins 파이프라인 실행 ---- - -## 📦 배포 실행 방법 - -### 1. Jenkins UI를 통한 배포 - -1. Jenkins > {프로젝트명} > **Build with Parameters** 클릭 +1. Jenkins > {프로젝트명} > **Build with Parameters** 2. **ENVIRONMENT** 선택 (dev/staging/prod) -3. **IMAGE_TAG** 입력 (선택사항, 기본값: latest) +3. **IMAGE_TAG** 입력 (선택사항) 4. **Build** 클릭 -### 2. 수동 배포 스크립트 사용 +### 2. 수동 배포 스크립트 실행 ```bash # 개발 환경 배포 @@ -249,22 +226,14 @@ kubectl get services -n phonebill-{환경} # Ingress 상태 확인 kubectl get ingress -n phonebill-{환경} - -# 로그 확인 -kubectl logs -n phonebill-{환경} deployment/{환경}-api-gateway ``` ---- - ## 🔄 롤백 방법 -### 1. Kubernetes 기본 롤백 +### 1. Kubernetes 롤백 ```bash -# 이전 버전으로 롤백 -kubectl rollout undo deployment/{환경}-{서비스명} -n phonebill-{환경} - -# 특정 리비전으로 롤백 +# 특정 버전으로 롤백 kubectl rollout undo deployment/{환경}-{서비스명} -n phonebill-{환경} --to-revision=2 # 롤백 상태 확인 @@ -274,151 +243,102 @@ kubectl rollout status deployment/{환경}-{서비스명} -n phonebill-{환경} ### 2. 이미지 태그 기반 롤백 ```bash -# 안정 버전 태그로 수동 배포 -./deployment/cicd/scripts/deploy.sh prod {이전안정버전태그} +# 이전 안정 버전 이미지 태그로 업데이트 +cd deployment/cicd/kustomize/overlays/{환경} +kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/{서비스명}:{환경}-{이전태그} +kubectl apply -k . ``` ---- +## 🏷 환경별 설정 차이점 -## 🔧 트러블슈팅 +### DEV 환경 +- **Replicas**: 1개 +- **Resources**: requests(256m/256Mi), limits(1024m/1024Mi) +- **Domain**: phonebill-api.20.214.196.128.nip.io +- **SSL**: 비활성화 +- **DDL**: update -### 일반적인 문제 해결 +### STAGING 환경 +- **Replicas**: 2개 +- **Resources**: requests(512m/512Mi), limits(2048m/2048Mi) +- **Domain**: phonebill-staging.example.com +- **SSL**: 활성화 (Let's Encrypt) +- **DDL**: validate -#### 1. 파이프라인 실패 시 +### PROD 환경 +- **Replicas**: 3개 +- **Resources**: requests(1024m/1024Mi), limits(4096m/4096Mi) +- **Domain**: phonebill-prod.example.com +- **SSL**: 활성화 (Let's Encrypt) +- **DDL**: validate +- **JWT**: 보안 강화 (짧은 유효시간) + +## 📋 체크리스트 + +### 사전 준비 +- [ ] settings.gradle에서 시스템명과 서비스명 확인 +- [ ] Azure 환경 정보 확인 (ACR, 리소스 그룹, AKS 클러스터) +- [ ] Jenkins 플러그인 설치 완료 +- [ ] Jenkins Credentials 등록 완료 + +### Kustomize 구성 +- [ ] Base 매니페스트 복사 및 설정 완료 +- [ ] 환경별 Overlay 구성 완료 +- [ ] Patch 파일 작성 완료 (replicas, resources 포함) +- [ ] 환경별 설정 파일 생성 완료 + +### Jenkins Pipeline +- [ ] Jenkinsfile 작성 완료 +- [ ] Pipeline Job 생성 및 설정 완료 +- [ ] SonarQube 연동 설정 완료 +- [ ] 배포 스크립트 생성 및 권한 설정 완료 + +### 배포 테스트 +- [ ] DEV 환경 배포 테스트 완료 +- [ ] STAGING 환경 배포 테스트 완료 +- [ ] PROD 환경 배포 테스트 완료 +- [ ] 롤백 테스트 완료 + +## 🚨 트러블슈팅 + +### 일반적인 문제들 + +**1. Quality Gate 실패** ```bash -# Jenkins 콘솔 로그 확인 -# SonarQube Quality Gate 상태 확인 -# Kubernetes 이벤트 확인 -kubectl get events -n phonebill-{환경} --sort-by='.lastTimestamp' +# 해결방법: SonarQube 분석 결과 확인 및 코드 개선 +./gradlew sonar ``` -#### 2. 배포 실패 시 +**2. 이미지 빌드 실패** ```bash -# Pod 상태 및 로그 확인 -kubectl describe pod {pod-name} -n phonebill-{환경} -kubectl logs {pod-name} -n phonebill-{환경} - -# ConfigMap/Secret 확인 -kubectl get configmap -n phonebill-{환경} -kubectl get secret -n phonebill-{환경} +# 해결방법: Dockerfile 및 빌드 컨텍스트 확인 +podman build --no-cache -f deployment/container/Dockerfile-backend . ``` -#### 3. 네트워크 연결 문제 +**3. 배포 타임아웃** ```bash -# Service와 Endpoint 확인 -kubectl get svc,endpoints -n phonebill-{환경} - -# Ingress 설정 확인 -kubectl describe ingress -n phonebill-{환경} +# 해결방법: 리소스 사용량 및 노드 상태 확인 +kubectl describe pods -n phonebill-{환경} +kubectl top nodes ``` ---- - -## 📝 체크리스트 - -### 📋 Kustomize 구성 체크리스트 - -#### 📂 기본 구조 검증 -- [ ] 디렉토리 구조: `deployment/cicd/kustomize/{base,overlays/{dev,staging,prod}}` -- [ ] 서비스별 base 디렉토리: `base/{common,api-gateway,user-service,bill-service,product-service,kos-mock}` -- [ ] Base kustomization.yaml 파일 생성 완료 - -#### 🔧 환경별 Overlay 검증 -**각 환경(dev/staging/prod)별로 다음 파일들이 모두 생성되어야 함:** - -**필수 파일 목록:** -- [ ] `kustomization.yaml` - 환경 설정 및 patch 파일 참조 -- [ ] `configmap-common-patch.yaml` - 환경별 공통 설정 (프로파일, DDL, JWT 설정) -- [ ] `secret-common-patch.yaml` - 환경별 공통 시크릿 (JWT Secret, Redis 정보) -- [ ] `ingress-patch.yaml` - 환경별 도메인 및 보안 설정 -- [ ] **`deployment-patch.yaml`** - **환경별 replicas AND resources 설정** ⚠️ -- [ ] `secret-user-service-patch.yaml` - User Service DB 정보 -- [ ] `secret-bill-service-patch.yaml` - Bill Service DB 정보 -- [ ] `secret-product-service-patch.yaml` - Product Service DB 정보 - -**⚠️ deployment-patch.yaml 필수 검증 사항:** -- [ ] **파일명이 정확한지**: `deployment-patch.yaml` (❌ `replica-patch.yaml` 아님) -- [ ] **Strategic Merge Patch 형식 사용**: YAML 형식, JSON Patch 아님 -- [ ] **replicas 설정**: dev(1), staging(2), prod(3) -- [ ] **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) -- [ ] **모든 서비스 포함**: api-gateway, user-service, bill-service, product-service, kos-mock - -#### 🔍 호환성 검증 -- [ ] base 매니페스트에 없는 항목을 patch에 추가하지 않음 -- [ ] base 매니페스트와 patch 필드 구조 일치 -- [ ] Secret 매니페스트에 'data' 대신 'stringData' 사용 - -### 📋 배포 전 체크리스트 - -- [ ] Jenkins 필수 플러그인 설치 완료 -- [ ] Credentials 등록 완료 (Azure, ACR, SonarQube) -- [ ] SonarQube 프로젝트 설정 완료 -- [ ] 환경별 Database/Redis 준비 완료 -- [ ] 네트워크 및 도메인 설정 완료 - -### 🚀 배포 후 체크리스트 - -- [ ] 모든 Pod가 Running 상태 -- [ ] Health Check 통과 -- [ ] Ingress로 외부 접근 가능 -- [ ] 로그에 오류 없음 -- [ ] 기능 테스트 완료 - -### 💡 일반적인 실수 방지 가이드 - -**❌ 자주 발생하는 실수들:** -1. **파일명 실수**: `replica-patch.yaml` 생성 → 정답: `deployment-patch.yaml` -2. **내용 누락**: replicas만 설정하고 resources 누락 → 정답: 둘 다 설정 -3. **형식 실수**: JSON Patch 사용 → 정답: Strategic Merge Patch 사용 -4. **환경별 차이 없음**: 모든 환경 동일 설정 → 정답: 환경별 차등 설정 - -**✅ 올바른 deployment-patch.yaml 예시:** -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: api-gateway -spec: - replicas: 1 # 환경별 차등 적용 - template: - spec: - containers: - - name: api-gateway - resources: # 반드시 포함 - requests: - cpu: 256m # 환경별 차등 적용 - memory: 256Mi # 환경별 차등 적용 - limits: - cpu: 1024m # 환경별 차등 적용 - memory: 1024Mi # 환경별 차등 적용 +**4. 네임스페이스 관련 오류** +```bash +# 해결방법: 네임스페이스 수동 생성 +kubectl create namespace phonebill-{환경} ``` ---- +## 📞 지원 및 문의 -## 📞 지원 정보 +Jenkins CI/CD 파이프라인 운영 중 문제가 발생하면 다음을 확인해 주세요: -### 환경 정보 -- **시스템**: phonebill (통신요금 관리 서비스) -- **Git 저장소**: [Repository URL] -- **Jenkins**: [Jenkins URL] -- **SonarQube**: [SonarQube URL] - -### 연락처 -- **DevOps 팀**: 최운영 (데옵스) -- **백엔드 팀**: 이개발 (백엔더) -- **QA 팀**: 정테스트 (QA매니저) +1. Jenkins 빌드 로그 확인 +2. SonarQube Quality Gate 결과 확인 +3. Kubernetes 클러스터 상태 확인 +4. Azure Container Registry 연결 상태 확인 --- -## 📚 추가 리소스 +**데옵스**: Jenkins CI/CD 파이프라인이 성공적으로 구축되었습니다! 🎉 -- [Kustomize 공식 문서](https://kustomize.io/) -- [Jenkins Pipeline 문법](https://www.jenkins.io/doc/book/pipeline/syntax/) -- [Azure DevOps 가이드](https://docs.microsoft.com/en-us/azure/devops/) - ---- - -*이 가이드는 phonebill 프로젝트의 CI/CD 파이프라인 구축을 위한 완전한 가이드입니다. 추가 질문이나 지원이 필요하시면 DevOps 팀에 문의하세요.* \ No newline at end of file +이제 각 환경별로 자동화된 빌드, 테스트, 배포가 가능합니다. SonarQube를 통한 코드 품질 관리와 Kustomize를 통한 환경별 설정 관리로 안정적인 DevOps 환경을 구축했습니다. \ No newline at end of file diff --git a/deployment/cicd/kustomize/base/kustomization.yaml b/deployment/cicd/kustomize/base/kustomization.yaml index 184c099..9b334a1 100644 --- a/deployment/cicd/kustomize/base/kustomization.yaml +++ b/deployment/cicd/kustomize/base/kustomization.yaml @@ -5,6 +5,9 @@ metadata: name: phonebill-base resources: + # Namespace + - namespace.yaml + # Common resources - common/cm-common.yaml - common/secret-common.yaml @@ -28,7 +31,7 @@ resources: - bill-service/cm-bill-service.yaml - bill-service/secret-bill-service.yaml - # Product Service + # Product Service - product-service/deployment.yaml - product-service/service.yaml - product-service/cm-product-service.yaml @@ -47,7 +50,7 @@ images: - name: acrdigitalgarage01.azurecr.io/phonebill/api-gateway newTag: latest - name: acrdigitalgarage01.azurecr.io/phonebill/user-service - newTag: latest + newTag: latest - name: acrdigitalgarage01.azurecr.io/phonebill/bill-service newTag: latest - name: acrdigitalgarage01.azurecr.io/phonebill/product-service diff --git a/deployment/cicd/kustomize/base/namespace.yaml b/deployment/cicd/kustomize/base/namespace.yaml new file mode 100644 index 0000000..e0edb58 --- /dev/null +++ b/deployment/cicd/kustomize/base/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: phonebill + labels: + name: phonebill \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/dev/configmap-common-patch.yaml b/deployment/cicd/kustomize/overlays/dev/configmap-common-patch.yaml index a707506..0511102 100644 --- a/deployment/cicd/kustomize/overlays/dev/configmap-common-patch.yaml +++ b/deployment/cicd/kustomize/overlays/dev/configmap-common-patch.yaml @@ -4,8 +4,8 @@ metadata: name: cm-common data: CORS_ALLOWED_ORIGINS: "http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://phonebill.20.214.196.128.nip.io" - JWT_ACCESS_TOKEN_VALIDITY: "18000000" # 5시간 + JWT_ACCESS_TOKEN_VALIDITY: "18000000" JWT_REFRESH_TOKEN_VALIDITY: "86400000" REDIS_PORT: "6379" SPRING_PROFILES_ACTIVE: "dev" - DDL_AUTO: "update" + DDL_AUTO: "update" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/dev/deployment-patch.yaml b/deployment/cicd/kustomize/overlays/dev/deployment-patch.yaml index dd57639..3c1c53b 100644 --- a/deployment/cicd/kustomize/overlays/dev/deployment-patch.yaml +++ b/deployment/cicd/kustomize/overlays/dev/deployment-patch.yaml @@ -10,11 +10,11 @@ spec: - name: api-gateway resources: requests: - cpu: 256m - memory: 256Mi + memory: "256Mi" + cpu: "256m" limits: - cpu: 1024m - memory: 1024Mi + memory: "1024Mi" + cpu: "1024m" --- apiVersion: apps/v1 kind: Deployment @@ -28,11 +28,11 @@ spec: - name: user-service resources: requests: - cpu: 256m - memory: 256Mi + memory: "256Mi" + cpu: "256m" limits: - cpu: 1024m - memory: 1024Mi + memory: "1024Mi" + cpu: "1024m" --- apiVersion: apps/v1 kind: Deployment @@ -46,11 +46,11 @@ spec: - name: bill-service resources: requests: - cpu: 256m - memory: 256Mi + memory: "256Mi" + cpu: "256m" limits: - cpu: 1024m - memory: 1024Mi + memory: "1024Mi" + cpu: "1024m" --- apiVersion: apps/v1 kind: Deployment @@ -64,11 +64,11 @@ spec: - name: product-service resources: requests: - cpu: 256m - memory: 256Mi + memory: "256Mi" + cpu: "256m" limits: - cpu: 1024m - memory: 1024Mi + memory: "1024Mi" + cpu: "1024m" --- apiVersion: apps/v1 kind: Deployment @@ -82,8 +82,8 @@ spec: - name: kos-mock resources: requests: - cpu: 256m - memory: 256Mi + memory: "256Mi" + cpu: "256m" limits: - cpu: 1024m - memory: 1024Mi \ No newline at end of file + memory: "1024Mi" + cpu: "1024m" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/dev/ingress-patch.yaml b/deployment/cicd/kustomize/overlays/dev/ingress-patch.yaml index 542a5d9..3c5cec7 100644 --- a/deployment/cicd/kustomize/overlays/dev/ingress-patch.yaml +++ b/deployment/cicd/kustomize/overlays/dev/ingress-patch.yaml @@ -45,4 +45,4 @@ spec: service: name: kos-mock port: - number: 80 + number: 80 \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/dev/secret-bill-service-patch.yaml b/deployment/cicd/kustomize/overlays/dev/secret-bill-service-patch.yaml index 40b58fe..72b5ee6 100644 --- a/deployment/cicd/kustomize/overlays/dev/secret-bill-service-patch.yaml +++ b/deployment/cicd/kustomize/overlays/dev/secret-bill-service-patch.yaml @@ -7,4 +7,4 @@ stringData: DB_HOST: "bill-inquiry-postgres-dev-postgresql" DB_NAME: "bill_inquiry_db" DB_USERNAME: "bill_inquiry_user" - DB_PASSWORD: "BillUser2025!" + DB_PASSWORD: "BillUser2025!" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/dev/secret-common-patch.yaml b/deployment/cicd/kustomize/overlays/dev/secret-common-patch.yaml index f32a832..b641d81 100644 --- a/deployment/cicd/kustomize/overlays/dev/secret-common-patch.yaml +++ b/deployment/cicd/kustomize/overlays/dev/secret-common-patch.yaml @@ -6,4 +6,4 @@ type: Opaque stringData: JWT_SECRET: "nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==" REDIS_HOST: "redis-cache-dev-master" - REDIS_PASSWORD: "Redis2025Dev!" + REDIS_PASSWORD: "Redis2025Dev!" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/dev/secret-product-service-patch.yaml b/deployment/cicd/kustomize/overlays/dev/secret-product-service-patch.yaml index e651e74..73c1619 100644 --- a/deployment/cicd/kustomize/overlays/dev/secret-product-service-patch.yaml +++ b/deployment/cicd/kustomize/overlays/dev/secret-product-service-patch.yaml @@ -7,4 +7,4 @@ stringData: DB_HOST: "product-change-postgres-dev-postgresql" DB_NAME: "product_change_db" DB_USERNAME: "product_change_user" - DB_PASSWORD: "ProductUser2025!" + DB_PASSWORD: "ProductUser2025!" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/dev/secret-user-service-patch.yaml b/deployment/cicd/kustomize/overlays/dev/secret-user-service-patch.yaml index 91a2a16..a0e6d7a 100644 --- a/deployment/cicd/kustomize/overlays/dev/secret-user-service-patch.yaml +++ b/deployment/cicd/kustomize/overlays/dev/secret-user-service-patch.yaml @@ -7,4 +7,4 @@ stringData: DB_HOST: "auth-postgres-dev-postgresql" DB_NAME: "phonebill_auth" DB_USERNAME: "auth_user" - DB_PASSWORD: "AuthUser2025!" + DB_PASSWORD: "AuthUser2025!" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/prod/configmap-common-patch.yaml b/deployment/cicd/kustomize/overlays/prod/configmap-common-patch.yaml index 8ebe568..abc4521 100644 --- a/deployment/cicd/kustomize/overlays/prod/configmap-common-patch.yaml +++ b/deployment/cicd/kustomize/overlays/prod/configmap-common-patch.yaml @@ -3,9 +3,9 @@ kind: ConfigMap metadata: name: cm-common data: - CORS_ALLOWED_ORIGINS: "https://phonebill.20.214.196.128.nip.io" - JWT_ACCESS_TOKEN_VALIDITY: "3600000" # 1시간 - JWT_REFRESH_TOKEN_VALIDITY: "86400000" + CORS_ALLOWED_ORIGINS: "https://phonebill-prod.example.com" + JWT_ACCESS_TOKEN_VALIDITY: "3600000" + JWT_REFRESH_TOKEN_VALIDITY: "43200000" REDIS_PORT: "6379" SPRING_PROFILES_ACTIVE: "prod" - DDL_AUTO: "validate" + DDL_AUTO: "validate" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/prod/deployment-patch.yaml b/deployment/cicd/kustomize/overlays/prod/deployment-patch.yaml index eacf315..32d790c 100644 --- a/deployment/cicd/kustomize/overlays/prod/deployment-patch.yaml +++ b/deployment/cicd/kustomize/overlays/prod/deployment-patch.yaml @@ -10,11 +10,11 @@ spec: - name: api-gateway resources: requests: - cpu: 1024m - memory: 1024Mi + memory: "1024Mi" + cpu: "1024m" limits: - cpu: 4096m - memory: 4096Mi + memory: "4096Mi" + cpu: "4096m" --- apiVersion: apps/v1 kind: Deployment @@ -28,11 +28,11 @@ spec: - name: user-service resources: requests: - cpu: 1024m - memory: 1024Mi + memory: "1024Mi" + cpu: "1024m" limits: - cpu: 4096m - memory: 4096Mi + memory: "4096Mi" + cpu: "4096m" --- apiVersion: apps/v1 kind: Deployment @@ -46,11 +46,11 @@ spec: - name: bill-service resources: requests: - cpu: 1024m - memory: 1024Mi + memory: "1024Mi" + cpu: "1024m" limits: - cpu: 4096m - memory: 4096Mi + memory: "4096Mi" + cpu: "4096m" --- apiVersion: apps/v1 kind: Deployment @@ -64,11 +64,11 @@ spec: - name: product-service resources: requests: - cpu: 1024m - memory: 1024Mi + memory: "1024Mi" + cpu: "1024m" limits: - cpu: 4096m - memory: 4096Mi + memory: "4096Mi" + cpu: "4096m" --- apiVersion: apps/v1 kind: Deployment @@ -82,8 +82,8 @@ spec: - name: kos-mock resources: requests: - cpu: 1024m - memory: 1024Mi + memory: "1024Mi" + cpu: "1024m" limits: - cpu: 4096m - memory: 4096Mi \ No newline at end of file + memory: "4096Mi" + cpu: "4096m" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/prod/ingress-patch.yaml b/deployment/cicd/kustomize/overlays/prod/ingress-patch.yaml index 554fae8..8a20553 100644 --- a/deployment/cicd/kustomize/overlays/prod/ingress-patch.yaml +++ b/deployment/cicd/kustomize/overlays/prod/ingress-patch.yaml @@ -7,16 +7,14 @@ metadata: nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" cert-manager.io/cluster-issuer: "letsencrypt-prod" - nginx.ingress.kubernetes.io/ssl-protocols: "TLSv1.2 TLSv1.3" - nginx.ingress.kubernetes.io/ssl-ciphers: "ECDHE-RSA-AES128-GCM-SHA256,ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-AES256-GCM-SHA384" spec: ingressClassName: nginx tls: - hosts: - - phonebill.20.214.196.128.nip.io + - phonebill-prod.example.com secretName: phonebill-prod-tls rules: - - host: phonebill.20.214.196.128.nip.io + - host: phonebill-prod.example.com http: paths: - path: /api/v1/auth @@ -53,4 +51,4 @@ spec: service: name: kos-mock port: - number: 80 + number: 80 \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/prod/secret-bill-service-patch.yaml b/deployment/cicd/kustomize/overlays/prod/secret-bill-service-patch.yaml index 52c87e1..6fb37b9 100644 --- a/deployment/cicd/kustomize/overlays/prod/secret-bill-service-patch.yaml +++ b/deployment/cicd/kustomize/overlays/prod/secret-bill-service-patch.yaml @@ -7,4 +7,4 @@ stringData: DB_HOST: "bill-inquiry-postgres-prod-postgresql" DB_NAME: "bill_inquiry_db" DB_USERNAME: "bill_inquiry_user" - DB_PASSWORD: "BillUser2025Prod!" + DB_PASSWORD: "BillUser2025Prod!SecurePassword" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/prod/secret-common-patch.yaml b/deployment/cicd/kustomize/overlays/prod/secret-common-patch.yaml index 13f59ad..8545abb 100644 --- a/deployment/cicd/kustomize/overlays/prod/secret-common-patch.yaml +++ b/deployment/cicd/kustomize/overlays/prod/secret-common-patch.yaml @@ -4,6 +4,6 @@ metadata: name: secret-common type: Opaque stringData: - JWT_SECRET: "prod7Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/prod" + JWT_SECRET: "nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==" REDIS_HOST: "redis-cache-prod-master" - REDIS_PASSWORD: "Redis2025Prod!" + REDIS_PASSWORD: "Redis2025Prod!SecurePassword" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/prod/secret-product-service-patch.yaml b/deployment/cicd/kustomize/overlays/prod/secret-product-service-patch.yaml index 4f3907c..f6ffda9 100644 --- a/deployment/cicd/kustomize/overlays/prod/secret-product-service-patch.yaml +++ b/deployment/cicd/kustomize/overlays/prod/secret-product-service-patch.yaml @@ -7,4 +7,4 @@ stringData: DB_HOST: "product-change-postgres-prod-postgresql" DB_NAME: "product_change_db" DB_USERNAME: "product_change_user" - DB_PASSWORD: "ProductUser2025Prod!" + DB_PASSWORD: "ProductUser2025Prod!SecurePassword" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/prod/secret-user-service-patch.yaml b/deployment/cicd/kustomize/overlays/prod/secret-user-service-patch.yaml index 71a6aff..06135f5 100644 --- a/deployment/cicd/kustomize/overlays/prod/secret-user-service-patch.yaml +++ b/deployment/cicd/kustomize/overlays/prod/secret-user-service-patch.yaml @@ -7,4 +7,4 @@ stringData: DB_HOST: "auth-postgres-prod-postgresql" DB_NAME: "phonebill_auth" DB_USERNAME: "auth_user" - DB_PASSWORD: "AuthUser2025Prod!" + DB_PASSWORD: "AuthUser2025Prod!SecurePassword" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/staging/configmap-common-patch.yaml b/deployment/cicd/kustomize/overlays/staging/configmap-common-patch.yaml index 7098d5c..7f720b5 100644 --- a/deployment/cicd/kustomize/overlays/staging/configmap-common-patch.yaml +++ b/deployment/cicd/kustomize/overlays/staging/configmap-common-patch.yaml @@ -3,9 +3,9 @@ kind: ConfigMap metadata: name: cm-common data: - CORS_ALLOWED_ORIGINS: "https://phonebill-staging.20.214.196.128.nip.io" - JWT_ACCESS_TOKEN_VALIDITY: "18000000" # 5시간 + CORS_ALLOWED_ORIGINS: "https://phonebill-staging.example.com" + JWT_ACCESS_TOKEN_VALIDITY: "18000000" JWT_REFRESH_TOKEN_VALIDITY: "86400000" REDIS_PORT: "6379" SPRING_PROFILES_ACTIVE: "staging" - DDL_AUTO: "validate" + DDL_AUTO: "validate" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/staging/deployment-patch.yaml b/deployment/cicd/kustomize/overlays/staging/deployment-patch.yaml index 0ebeb97..dd3ceb4 100644 --- a/deployment/cicd/kustomize/overlays/staging/deployment-patch.yaml +++ b/deployment/cicd/kustomize/overlays/staging/deployment-patch.yaml @@ -10,11 +10,11 @@ spec: - name: api-gateway resources: requests: - cpu: 512m - memory: 512Mi + memory: "512Mi" + cpu: "512m" limits: - cpu: 2048m - memory: 2048Mi + memory: "2048Mi" + cpu: "2048m" --- apiVersion: apps/v1 kind: Deployment @@ -28,11 +28,11 @@ spec: - name: user-service resources: requests: - cpu: 512m - memory: 512Mi + memory: "512Mi" + cpu: "512m" limits: - cpu: 2048m - memory: 2048Mi + memory: "2048Mi" + cpu: "2048m" --- apiVersion: apps/v1 kind: Deployment @@ -46,11 +46,11 @@ spec: - name: bill-service resources: requests: - cpu: 512m - memory: 512Mi + memory: "512Mi" + cpu: "512m" limits: - cpu: 2048m - memory: 2048Mi + memory: "2048Mi" + cpu: "2048m" --- apiVersion: apps/v1 kind: Deployment @@ -64,11 +64,11 @@ spec: - name: product-service resources: requests: - cpu: 512m - memory: 512Mi + memory: "512Mi" + cpu: "512m" limits: - cpu: 2048m - memory: 2048Mi + memory: "2048Mi" + cpu: "2048m" --- apiVersion: apps/v1 kind: Deployment @@ -82,8 +82,8 @@ spec: - name: kos-mock resources: requests: - cpu: 512m - memory: 512Mi + memory: "512Mi" + cpu: "512m" limits: - cpu: 2048m - memory: 2048Mi \ No newline at end of file + memory: "2048Mi" + cpu: "2048m" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/staging/ingress-patch.yaml b/deployment/cicd/kustomize/overlays/staging/ingress-patch.yaml index 354aca2..e8592f9 100644 --- a/deployment/cicd/kustomize/overlays/staging/ingress-patch.yaml +++ b/deployment/cicd/kustomize/overlays/staging/ingress-patch.yaml @@ -5,15 +5,16 @@ metadata: annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: ingressClassName: nginx tls: - hosts: - - phonebill-staging.20.214.196.128.nip.io + - phonebill-staging.example.com secretName: phonebill-staging-tls rules: - - host: phonebill-staging.20.214.196.128.nip.io + - host: phonebill-staging.example.com http: paths: - path: /api/v1/auth @@ -50,4 +51,4 @@ spec: service: name: kos-mock port: - number: 80 + number: 80 \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/staging/secret-bill-service-patch.yaml b/deployment/cicd/kustomize/overlays/staging/secret-bill-service-patch.yaml index 03241fe..6fe86a5 100644 --- a/deployment/cicd/kustomize/overlays/staging/secret-bill-service-patch.yaml +++ b/deployment/cicd/kustomize/overlays/staging/secret-bill-service-patch.yaml @@ -7,4 +7,4 @@ stringData: DB_HOST: "bill-inquiry-postgres-staging-postgresql" DB_NAME: "bill_inquiry_db" DB_USERNAME: "bill_inquiry_user" - DB_PASSWORD: "BillUser2025Staging!" + DB_PASSWORD: "BillUser2025Staging!" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/staging/secret-common-patch.yaml b/deployment/cicd/kustomize/overlays/staging/secret-common-patch.yaml index d6abb77..951d3b4 100644 --- a/deployment/cicd/kustomize/overlays/staging/secret-common-patch.yaml +++ b/deployment/cicd/kustomize/overlays/staging/secret-common-patch.yaml @@ -4,6 +4,6 @@ metadata: name: secret-common type: Opaque stringData: - JWT_SECRET: "staging5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/staging" + JWT_SECRET: "nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==" REDIS_HOST: "redis-cache-staging-master" - REDIS_PASSWORD: "Redis2025Staging!" + REDIS_PASSWORD: "Redis2025Staging!" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/staging/secret-product-service-patch.yaml b/deployment/cicd/kustomize/overlays/staging/secret-product-service-patch.yaml index 249d077..e54ac69 100644 --- a/deployment/cicd/kustomize/overlays/staging/secret-product-service-patch.yaml +++ b/deployment/cicd/kustomize/overlays/staging/secret-product-service-patch.yaml @@ -7,4 +7,4 @@ stringData: DB_HOST: "product-change-postgres-staging-postgresql" DB_NAME: "product_change_db" DB_USERNAME: "product_change_user" - DB_PASSWORD: "ProductUser2025Staging!" + DB_PASSWORD: "ProductUser2025Staging!" \ No newline at end of file diff --git a/deployment/cicd/kustomize/overlays/staging/secret-user-service-patch.yaml b/deployment/cicd/kustomize/overlays/staging/secret-user-service-patch.yaml index b1bd753..33c2eb3 100644 --- a/deployment/cicd/kustomize/overlays/staging/secret-user-service-patch.yaml +++ b/deployment/cicd/kustomize/overlays/staging/secret-user-service-patch.yaml @@ -7,4 +7,4 @@ stringData: DB_HOST: "auth-postgres-staging-postgresql" DB_NAME: "phonebill_auth" DB_USERNAME: "auth_user" - DB_PASSWORD: "AuthUser2025Staging!" + DB_PASSWORD: "AuthUser2025Staging!" \ No newline at end of file diff --git a/deployment/cicd/scripts/deploy.sh b/deployment/cicd/scripts/deploy.sh index c55550d..8aa7ab2 100755 --- a/deployment/cicd/scripts/deploy.sh +++ b/deployment/cicd/scripts/deploy.sh @@ -4,37 +4,12 @@ set -e ENVIRONMENT=${1:-dev} IMAGE_TAG=${2:-latest} -echo "🚀 Starting deployment to ${ENVIRONMENT} environment with image tag: ${IMAGE_TAG}" +echo "🚀 Starting deployment for environment: $ENVIRONMENT with image tag: $IMAGE_TAG" -# 환경 검증 -if [[ ! "$ENVIRONMENT" =~ ^(dev|staging|prod)$ ]]; then - echo "❌ Error: Invalid environment. Use dev, staging, or prod" - exit 1 -fi - -# Kustomize 설치 확인 -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 - -# kubectl 연결 확인 -if ! kubectl cluster-info &> /dev/null; then - echo "❌ Error: Unable to connect to Kubernetes cluster" - echo "Please ensure kubectl is configured properly" - exit 1 -fi - -# 네임스페이스 생성 -echo "🔧 Creating namespace phonebill-${ENVIRONMENT} if not exists..." -kubectl create namespace phonebill-${ENVIRONMENT} --dry-run=client -o yaml | kubectl apply -f - - -# 환경별 디렉토리로 이동 +# 환경별 이미지 태그 업데이트 cd deployment/cicd/kustomize/overlays/${ENVIRONMENT} -echo "🏷️ Updating image tags..." - +echo "📝 Updating image tags..." # 각 서비스 이미지 태그 업데이트 kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/api-gateway:${ENVIRONMENT}-${IMAGE_TAG} kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/user-service:${ENVIRONMENT}-${IMAGE_TAG} @@ -42,41 +17,21 @@ kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/bill-service:${ kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/product-service:${ENVIRONMENT}-${IMAGE_TAG} kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/kos-mock:${ENVIRONMENT}-${IMAGE_TAG} -echo "📋 Applying Kubernetes manifests..." - +echo "📦 Applying manifests to Kubernetes..." # 배포 실행 kubectl apply -k . echo "⏳ Waiting for deployments to be ready..." - # 배포 상태 확인 -kubectl rollout status deployment/${ENVIRONMENT}-api-gateway -n phonebill-${ENVIRONMENT} --timeout=300s -kubectl rollout status deployment/${ENVIRONMENT}-user-service -n phonebill-${ENVIRONMENT} --timeout=300s -kubectl rollout status deployment/${ENVIRONMENT}-bill-service -n phonebill-${ENVIRONMENT} --timeout=300s -kubectl rollout status deployment/${ENVIRONMENT}-product-service -n phonebill-${ENVIRONMENT} --timeout=300s -kubectl rollout status deployment/${ENVIRONMENT}-kos-mock -n phonebill-${ENVIRONMENT} --timeout=300s +kubectl rollout status deployment/${ENVIRONMENT}-api-gateway -n phonebill-${ENVIRONMENT} +kubectl rollout status deployment/${ENVIRONMENT}-user-service -n phonebill-${ENVIRONMENT} +kubectl rollout status deployment/${ENVIRONMENT}-bill-service -n phonebill-${ENVIRONMENT} +kubectl rollout status deployment/${ENVIRONMENT}-product-service -n phonebill-${ENVIRONMENT} +kubectl rollout status deployment/${ENVIRONMENT}-kos-mock -n phonebill-${ENVIRONMENT} -echo "🔍 Health Check..." - -# API Gateway Health Check -GATEWAY_POD=$(kubectl get pod -n phonebill-${ENVIRONMENT} -l app=api-gateway -o jsonpath='{.items[0].metadata.name}') -if kubectl -n phonebill-${ENVIRONMENT} exec $GATEWAY_POD -- curl -f http://localhost:8080/actuator/health > /dev/null 2>&1; then - echo "✅ API Gateway is healthy!" -else - echo "⚠️ API Gateway health check failed, but deployment completed" -fi - -echo "" -echo "✅ Deployment completed successfully!" -echo "" -echo "📊 Deployment Status:" -kubectl get pods -n phonebill-${ENVIRONMENT} -l app=phonebill -echo "" -echo "🌐 Services:" +echo "🔍 Checking deployment status..." +kubectl get pods -n phonebill-${ENVIRONMENT} kubectl get services -n phonebill-${ENVIRONMENT} -echo "" -echo "🔗 Ingress:" kubectl get ingress -n phonebill-${ENVIRONMENT} -echo "" -echo "🎯 Environment: ${ENVIRONMENT}" -echo "🏷️ Image Tag: ${ENVIRONMENT}-${IMAGE_TAG}" \ No newline at end of file + +echo "✅ Deployment completed successfully!" \ No newline at end of file