mirror of
https://github.com/cna-bootcamp/phonebill.git
synced 2025-12-06 08:06:24 +00:00
Jenkins CI/CD 파이프라인 업데이트
- Jenkinsfile 개선: SonarQube 분석, Quality Gate 추가 - 환경별 설정 파일 업데이트 (dev/staging/prod) - Kustomize base 및 overlay 파일 정리 - prod 환경 overlay 파일 추가 - 배포 스크립트 및 검증 스크립트 업데이트 - 파이프라인 가이드 문서 업데이트 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
b467b84426
commit
0f054109bb
68
deployment/cicd/Jenkinsfile
vendored
68
deployment/cicd/Jenkinsfile
vendored
@ -59,6 +59,7 @@ podTemplate(
|
||||
],
|
||||
volumes: [
|
||||
emptyDirVolume(mountPath: '/home/gradle/.gradle', memory: false),
|
||||
emptyDirVolume(mountPath: '/root/.azure', memory: false),
|
||||
emptyDirVolume(mountPath: '/run/podman', memory: false)
|
||||
]
|
||||
) {
|
||||
@ -78,6 +79,7 @@ podTemplate(
|
||||
stage("Setup Kubernetes") {
|
||||
container('kubectl') {
|
||||
sh """
|
||||
kubectl config use-context ${props.context}
|
||||
kubectl create namespace ${props.namespace} --dry-run=client -o yaml | kubectl apply -f -
|
||||
"""
|
||||
}
|
||||
@ -92,25 +94,73 @@ podTemplate(
|
||||
}
|
||||
}
|
||||
|
||||
stage('SonarQube Analysis & Quality Gate') {
|
||||
if (skipSonarQube) {
|
||||
echo "⏭️ Skipping SonarQube Analysis (SKIP_SONARQUBE=${params.SKIP_SONARQUBE})"
|
||||
} else {
|
||||
container('gradle') {
|
||||
// 각 서비스별로 개별적으로 SonarQube 분석 및 Quality Gate 확인
|
||||
services.each { service ->
|
||||
withSonarQubeEnv('SonarQube') {
|
||||
echo "🔍 Starting SonarQube analysis for ${service}..."
|
||||
|
||||
// 서비스별 테스트 및 SonarQube 분석
|
||||
sh """
|
||||
./gradlew :${service}:test :${service}:jacocoTestReport :${service}:sonar \
|
||||
-Dsonar.projectKey=phonebill-${service}-${environment} \
|
||||
-Dsonar.projectName=phonebill-${service}-${environment} \
|
||||
-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/**
|
||||
"""
|
||||
|
||||
echo "✅ SonarQube analysis completed for ${service}"
|
||||
}
|
||||
|
||||
// 각 서비스별 Quality Gate 확인
|
||||
timeout(time: 5, unit: 'MINUTES') {
|
||||
echo "⏳ Waiting for Quality Gate result for ${service}..."
|
||||
def qg = waitForQualityGate()
|
||||
if (qg.status != 'OK') {
|
||||
error "❌ Quality Gate failed for ${service}: ${qg.status}"
|
||||
} else {
|
||||
echo "✅ Quality Gate passed for ${service}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "🎉 All services passed SonarQube Quality Gates!"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build & Push Images') {
|
||||
timeout(time: 30, unit: 'MINUTES') {
|
||||
container('podman') {
|
||||
withCredentials([
|
||||
usernamePassword(
|
||||
credentialsId: 'imagereg-credentials',
|
||||
usernameVariable: 'IMG_USERNAME',
|
||||
passwordVariable: 'IMG_PASSWORD'
|
||||
),
|
||||
usernamePassword(
|
||||
credentialsId: 'dockerhub-credentials',
|
||||
usernameVariable: 'DOCKERHUB_USERNAME',
|
||||
passwordVariable: 'DOCKERHUB_PASSWORD'
|
||||
)
|
||||
]) {
|
||||
// Docker Hub 로그인 (rate limit 해결)
|
||||
sh "podman login docker.io --username \$DOCKERHUB_USERNAME --password \$DOCKERHUB_PASSWORD"
|
||||
|
||||
// Image Registry 로그인
|
||||
sh "podman login docker.io --username \$IMG_USERNAME --password \$IMG_PASSWORD"
|
||||
|
||||
services.each { service ->
|
||||
sh """
|
||||
podman build \\
|
||||
--build-arg BUILD_LIB_DIR="${service}/build/libs" \\
|
||||
--build-arg ARTIFACTORY_FILE="${service}.jar" \\
|
||||
-f deployment/container/Dockerfile-backend \\
|
||||
podman build \
|
||||
--build-arg BUILD_LIB_DIR="${service}/build/libs" \
|
||||
--build-arg ARTIFACTORY_FILE="${service}.jar" \
|
||||
-f deployment/container/Dockerfile-backend \
|
||||
-t docker.io/hiondal/${service}:${environment}-${imageTag} .
|
||||
|
||||
podman push docker.io/hiondal/${service}:${environment}-${imageTag}
|
||||
@ -124,7 +174,7 @@ podTemplate(
|
||||
stage('Update Kustomize & Deploy') {
|
||||
container('kubectl') {
|
||||
sh """
|
||||
# Kustomize 설치
|
||||
# Kustomize 설치 (sudo 없이 사용자 디렉토리에 설치)
|
||||
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
|
||||
mkdir -p \$HOME/bin
|
||||
mv kustomize \$HOME/bin/
|
||||
@ -133,12 +183,12 @@ podTemplate(
|
||||
# 환경별 디렉토리로 이동
|
||||
cd deployment/cicd/kustomize/overlays/${environment}
|
||||
|
||||
# 서비스 목록 정의
|
||||
# 서비스 목록 정의 (공백으로 구분)
|
||||
services="api-gateway user-service bill-service product-service kos-mock"
|
||||
|
||||
# 이미지 태그 업데이트
|
||||
for service in \$services; do
|
||||
\$HOME/bin/kustomize edit set image docker.io/hiondal/\$service:${environment}-${imageTag}
|
||||
\$HOME/bin/kustomize edit set image docker.io/hiondal/\$service=docker.io/hiondal/\$service:${environment}-${imageTag}
|
||||
done
|
||||
|
||||
# 매니페스트 적용
|
||||
@ -147,15 +197,17 @@ podTemplate(
|
||||
# 배포 상태 확인
|
||||
echo "Waiting for deployments to be ready..."
|
||||
for service in \$services; do
|
||||
kubectl -n ${props.namespace} wait --for=condition=available deployment/\$service --timeout=300s || echo "Timeout waiting for \$service"
|
||||
kubectl -n ${props.namespace} wait --for=condition=available deployment/\$service --timeout=300s
|
||||
done
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
// 파이프라인 완료 로그 (Scripted Pipeline 방식)
|
||||
stage('Pipeline Complete') {
|
||||
echo "🧹 Pipeline completed. Pod cleanup handled by Jenkins Kubernetes Plugin."
|
||||
|
||||
// 성공/실패 여부 로깅
|
||||
if (currentBuild.result == null || currentBuild.result == 'SUCCESS') {
|
||||
echo "✅ Pipeline completed successfully!"
|
||||
} else {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
# Dev Environment Configuration
|
||||
# Minikube Remote 환경 설정
|
||||
k8s_context=minikube-remote
|
||||
# dev Environment Configuration
|
||||
context=minikube
|
||||
namespace=phonebill
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
# Production Environment Configuration
|
||||
# Minikube Remote 환경 설정
|
||||
k8s_context=minikube-remote
|
||||
namespace=phonebill-prod
|
||||
# prod Environment Configuration
|
||||
context=minikube-prod
|
||||
namespace=phonebill
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
# Staging Environment Configuration
|
||||
# Minikube Remote 환경 설정
|
||||
k8s_context=minikube-remote
|
||||
namespace=phonebill-staging
|
||||
# staging Environment Configuration
|
||||
context=minikube-staging
|
||||
namespace=phonebill
|
||||
|
||||
@ -1,175 +1,184 @@
|
||||
# Jenkins CI/CD 파이프라인 가이드
|
||||
# 백엔드 Jenkins CI/CD 파이프라인 가이드
|
||||
|
||||
## 개요
|
||||
이 문서는 Phonebill 프로젝트의 Jenkins 기반 CI/CD 파이프라인 구축 및 운영 가이드입니다.
|
||||
## 📋 개요
|
||||
|
||||
## 프로젝트 정보
|
||||
이 가이드는 phonebill 프로젝트의 Jenkins + Kustomize 기반 CI/CD 파이프라인 구축 및 운영 방법을 설명합니다.
|
||||
|
||||
## 🔧 사전 준비사항
|
||||
|
||||
### 프로젝트 정보
|
||||
| 항목 | 값 |
|
||||
|------|-----|
|
||||
| 시스템명 | phonebill |
|
||||
| 서비스 목록 | api-gateway, user-service, bill-service, product-service, kos-mock |
|
||||
| JDK 버전 | 21 |
|
||||
| Image Registry | docker.io |
|
||||
| Image Organization | hiondal |
|
||||
| K8s Context | minikube-remote |
|
||||
| Jenkins K8s Cloud Name | k8s |
|
||||
| K8s Context Prefix | minikube |
|
||||
| Namespace | phonebill |
|
||||
|
||||
### 서비스 목록
|
||||
- api-gateway (포트: 8080)
|
||||
- user-service (포트: 8081)
|
||||
- bill-service (포트: 8082)
|
||||
- product-service (포트: 8083)
|
||||
- kos-mock (포트: 8084)
|
||||
### Jenkins 서버 환경 구성
|
||||
|
||||
---
|
||||
|
||||
## 1. 사전 준비사항
|
||||
|
||||
### 1.1 Jenkins 필수 플러그인
|
||||
#### 1. 필수 플러그인 설치
|
||||
```
|
||||
- Kubernetes
|
||||
- Pipeline Utility Steps
|
||||
- Docker Pipeline
|
||||
- GitHub
|
||||
- SonarQube Scanner
|
||||
- Azure Credentials
|
||||
```
|
||||
|
||||
### 1.2 Jenkins Credentials 등록
|
||||
#### 2. Jenkins Credentials 등록
|
||||
|
||||
Jenkins 관리 > Credentials > Add Credentials에서 등록:
|
||||
|
||||
#### Docker Hub Credentials
|
||||
**Docker Hub Credentials (Rate Limit 해결용)**
|
||||
```
|
||||
- Kind: Username with password
|
||||
- ID: dockerhub-credentials
|
||||
- Username: {DOCKERHUB_USERNAME}
|
||||
- Password: {DOCKERHUB_PASSWORD}
|
||||
- 참고: Docker Hub 무료 계정 생성 (https://hub.docker.com)
|
||||
```
|
||||
|
||||
#### SonarQube Token (선택사항)
|
||||
**Image Registry Credentials**
|
||||
```
|
||||
- Kind: Username with password
|
||||
- ID: imagereg-credentials
|
||||
- Username: {REGISTRY_USERNAME}
|
||||
- Password: {REGISTRY_PASSWORD}
|
||||
```
|
||||
|
||||
**SonarQube Token (선택사항)**
|
||||
```
|
||||
- Kind: Secret text
|
||||
- ID: sonarqube-token
|
||||
- Secret: {SonarQube 토큰}
|
||||
- Secret: {SonarQube토큰}
|
||||
```
|
||||
|
||||
### 1.3 SonarQube 설정 (선택사항)
|
||||
Jenkins 관리 > Configure System > SonarQube servers:
|
||||
```
|
||||
- Name: SonarQube
|
||||
- Server URL: http://{SONARQUBE_URL}
|
||||
- Server authentication token: sonarqube-token (위에서 등록한 credential)
|
||||
```
|
||||
## 📁 디렉토리 구조
|
||||
|
||||
---
|
||||
|
||||
## 2. Kustomize 구조
|
||||
|
||||
### 2.1 디렉토리 구조
|
||||
```
|
||||
deployment/cicd/
|
||||
├── Jenkinsfile
|
||||
├── Jenkinsfile # Jenkins 파이프라인 정의
|
||||
├── jenkins-pipeline-guide.md # 이 가이드 문서
|
||||
├── config/
|
||||
│ ├── deploy_env_vars_dev
|
||||
│ ├── deploy_env_vars_staging
|
||||
│ └── deploy_env_vars_prod
|
||||
│ ├── deploy_env_vars_dev # dev 환경 설정
|
||||
│ ├── deploy_env_vars_staging # staging 환경 설정
|
||||
│ └── deploy_env_vars_prod # prod 환경 설정
|
||||
├── scripts/
|
||||
│ ├── deploy.sh
|
||||
│ └── validate-resources.sh
|
||||
│ ├── deploy.sh # 수동 배포 스크립트
|
||||
│ └── validate-resources.sh # 리소스 검증 스크립트
|
||||
└── kustomize/
|
||||
├── base/
|
||||
├── base/ # 기본 Kubernetes 매니페스트
|
||||
│ ├── kustomization.yaml
|
||||
│ ├── common/
|
||||
│ │ ├── cm-common.yaml
|
||||
│ │ ├── secret-common.yaml
|
||||
│ │ └── ingress.yaml
|
||||
│ ├── api-gateway/
|
||||
│ │ ├── deployment.yaml
|
||||
│ │ ├── service.yaml
|
||||
│ │ └── cm-api-gateway.yaml
|
||||
│ ├── user-service/
|
||||
│ │ ├── deployment.yaml
|
||||
│ │ ├── service.yaml
|
||||
│ │ ├── cm-user-service.yaml
|
||||
│ │ └── secret-user-service.yaml
|
||||
│ ├── bill-service/
|
||||
│ │ ├── deployment.yaml
|
||||
│ │ ├── service.yaml
|
||||
│ │ ├── cm-bill-service.yaml
|
||||
│ │ └── secret-bill-service.yaml
|
||||
│ ├── product-service/
|
||||
│ │ ├── deployment.yaml
|
||||
│ │ ├── service.yaml
|
||||
│ │ ├── cm-product-service.yaml
|
||||
│ │ └── secret-product-service.yaml
|
||||
│ └── kos-mock/
|
||||
│ ├── deployment.yaml
|
||||
│ ├── service.yaml
|
||||
│ └── cm-kos-mock.yaml
|
||||
└── overlays/
|
||||
├── dev/
|
||||
├── staging/
|
||||
└── prod/
|
||||
├── dev/ # 개발 환경 오버레이
|
||||
├── staging/ # 스테이징 환경 오버레이
|
||||
└── prod/ # 운영 환경 오버레이
|
||||
```
|
||||
|
||||
### 2.2 환경별 설정 차이
|
||||
## 🚀 Jenkins Pipeline Job 생성
|
||||
|
||||
| 항목 | dev | staging | prod |
|
||||
|------|-----|---------|------|
|
||||
| Namespace | phonebill | phonebill-staging | phonebill-prod |
|
||||
| Replicas | 1 | 2 | 3 |
|
||||
| CPU Requests | 256m | 512m | 1024m |
|
||||
| Memory Requests | 256Mi | 512Mi | 1024Mi |
|
||||
| CPU Limits | 1024m | 2048m | 4096m |
|
||||
| Memory Limits | 1024Mi | 2048Mi | 4096Mi |
|
||||
| DDL_AUTO | update | validate | validate |
|
||||
| SHOW_SQL | true | false | false |
|
||||
| SSL Redirect | false | true | true |
|
||||
### 1. Pipeline Job 생성
|
||||
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
|
||||
```
|
||||
|
||||
---
|
||||
### 2. Pipeline Parameters 설정
|
||||
| 파라미터 | 타입 | 값 | 설명 |
|
||||
|---------|------|-----|------|
|
||||
| ENVIRONMENT | Choice | dev, staging, prod | 배포 대상 환경 |
|
||||
| IMAGE_TAG | String | latest | 이미지 태그 (선택) |
|
||||
| SKIP_SONARQUBE | String | true | SonarQube 분석 건너뛰기 |
|
||||
|
||||
## 3. Jenkins Pipeline Job 생성
|
||||
## ⚙️ 환경별 설정
|
||||
|
||||
### 3.1 New Item > Pipeline 선택
|
||||
|
||||
### 3.2 Pipeline 설정
|
||||
```
|
||||
SCM: Git
|
||||
Repository URL: {Git 저장소 URL}
|
||||
Branch: main (또는 develop)
|
||||
Script Path: deployment/cicd/Jenkinsfile
|
||||
### DEV 환경
|
||||
```yaml
|
||||
# Replicas: 1
|
||||
# Resources:
|
||||
# requests: 256m CPU, 256Mi Memory
|
||||
# limits: 1024m CPU, 1024Mi Memory
|
||||
# DDL_AUTO: update
|
||||
# HTTPS: 비활성화
|
||||
```
|
||||
|
||||
### 3.3 Pipeline Parameters 설정
|
||||
| 파라미터 | 타입 | 기본값 | 설명 |
|
||||
|----------|------|--------|------|
|
||||
| ENVIRONMENT | Choice | dev | 배포 환경 (dev/staging/prod) |
|
||||
| SKIP_SONARQUBE | String | true | SonarQube 분석 건너뛰기 (true/false) |
|
||||
### STAGING 환경
|
||||
```yaml
|
||||
# Replicas: 2
|
||||
# Resources:
|
||||
# requests: 512m CPU, 512Mi Memory
|
||||
# limits: 2048m CPU, 2048Mi Memory
|
||||
# DDL_AUTO: validate
|
||||
# HTTPS: 활성화 (SSL 인증서 필요)
|
||||
```
|
||||
|
||||
---
|
||||
### PROD 환경
|
||||
```yaml
|
||||
# Replicas: 3
|
||||
# Resources:
|
||||
# requests: 1024m CPU, 1024Mi Memory
|
||||
# limits: 4096m CPU, 4096Mi Memory
|
||||
# DDL_AUTO: validate
|
||||
# HTTPS: 활성화 (SSL 인증서 필요)
|
||||
```
|
||||
|
||||
## 4. 파이프라인 스테이지
|
||||
## 📊 SonarQube 설정
|
||||
|
||||
### 4.1 Get Source
|
||||
- Git 저장소에서 소스 코드 체크아웃
|
||||
- 환경별 설정 파일 로드
|
||||
### Quality Gate 설정
|
||||
```
|
||||
Coverage: >= 80%
|
||||
Duplicated Lines: <= 3%
|
||||
Maintainability Rating: <= A
|
||||
Reliability Rating: <= A
|
||||
Security Rating: <= A
|
||||
```
|
||||
|
||||
### 4.2 Setup Kubernetes
|
||||
- Kubernetes 컨텍스트 설정
|
||||
- 네임스페이스 생성
|
||||
### 분석 제외 대상
|
||||
```
|
||||
**/config/**
|
||||
**/entity/**
|
||||
**/dto/**
|
||||
**/*Application.class
|
||||
**/exception/**
|
||||
```
|
||||
|
||||
### 4.3 Build
|
||||
- Gradle을 사용한 빌드 (테스트 제외)
|
||||
- `./gradlew build -x test`
|
||||
## 🔨 수동 배포
|
||||
|
||||
### 4.4 SonarQube Analysis & Quality Gate (선택사항)
|
||||
- SKIP_SONARQUBE=false일 때만 실행
|
||||
- 각 서비스별 테스트 및 코드 품질 분석
|
||||
- Quality Gate 통과 확인
|
||||
|
||||
### 4.5 Build & Push Images
|
||||
- Podman을 사용한 컨테이너 이미지 빌드
|
||||
- Docker Hub로 이미지 푸시
|
||||
- 이미지 태그: `{환경}-{타임스탬프}`
|
||||
|
||||
### 4.6 Update Kustomize & Deploy
|
||||
- Kustomize를 사용한 이미지 태그 업데이트
|
||||
- Kubernetes 매니페스트 적용
|
||||
- 배포 상태 확인
|
||||
|
||||
---
|
||||
|
||||
## 5. 배포 실행
|
||||
|
||||
### 5.1 Jenkins 파이프라인 실행
|
||||
1. Jenkins > phonebill > Build with Parameters
|
||||
2. ENVIRONMENT 선택 (dev/staging/prod)
|
||||
3. SKIP_SONARQUBE 입력 (true 또는 false)
|
||||
4. Build 클릭
|
||||
|
||||
### 5.2 수동 배포 (스크립트 사용)
|
||||
### 배포 스크립트 사용
|
||||
```bash
|
||||
# dev 환경 배포
|
||||
./deployment/cicd/scripts/deploy.sh dev latest
|
||||
@ -181,131 +190,100 @@ Script Path: deployment/cicd/Jenkinsfile
|
||||
./deployment/cicd/scripts/deploy.sh prod v1.0.0
|
||||
```
|
||||
|
||||
### 5.3 배포 상태 확인
|
||||
### 리소스 검증
|
||||
```bash
|
||||
# Pod 상태 확인
|
||||
# Kustomize 리소스 검증
|
||||
./deployment/cicd/scripts/validate-resources.sh
|
||||
```
|
||||
|
||||
## 🔄 배포 상태 확인
|
||||
|
||||
```bash
|
||||
# 파드 상태 확인
|
||||
kubectl get pods -n phonebill
|
||||
|
||||
# 서비스 상태 확인
|
||||
kubectl get services -n phonebill
|
||||
|
||||
# Ingress 상태 확인
|
||||
# 인그레스 확인
|
||||
kubectl get ingress -n phonebill
|
||||
|
||||
# 특정 Pod 로그 확인
|
||||
kubectl logs -f deployment/api-gateway -n phonebill
|
||||
# 배포 상태 상세 확인
|
||||
kubectl describe deployment api-gateway -n phonebill
|
||||
```
|
||||
|
||||
---
|
||||
## ⏪ 롤백 방법
|
||||
|
||||
## 6. 롤백
|
||||
|
||||
### 6.1 이전 버전으로 롤백
|
||||
### 이전 버전으로 롤백
|
||||
```bash
|
||||
# 특정 리비전으로 롤백
|
||||
kubectl rollout undo deployment/{서비스명} -n phonebill --to-revision=2
|
||||
|
||||
# 롤백 상태 확인
|
||||
kubectl rollout status deployment/{서비스명} -n phonebill
|
||||
|
||||
# 롤백 히스토리 확인
|
||||
kubectl rollout history deployment/{서비스명} -n phonebill
|
||||
```
|
||||
|
||||
### 6.2 이미지 태그 기반 롤백
|
||||
### 이미지 태그 기반 롤백
|
||||
```bash
|
||||
cd deployment/cicd/kustomize/overlays/{환경}
|
||||
|
||||
# 이전 안정 버전 이미지 태그로 업데이트
|
||||
kustomize edit set image docker.io/hiondal/{서비스명}:{환경}-{이전태그}
|
||||
|
||||
# 배포
|
||||
cd deployment/cicd/kustomize/overlays/{환경}
|
||||
kustomize edit set image docker.io/hiondal/{서비스명}=docker.io/hiondal/{서비스명}:{환경}-{이전태그}
|
||||
kubectl apply -k .
|
||||
```
|
||||
|
||||
---
|
||||
## 🔍 문제 해결
|
||||
|
||||
## 7. 리소스 검증
|
||||
### 일반적인 문제
|
||||
|
||||
### 7.1 검증 스크립트 실행
|
||||
#### 1. 이미지 풀 실패
|
||||
```bash
|
||||
# ImagePullBackOff 상태 확인
|
||||
kubectl describe pod {pod-name} -n phonebill
|
||||
|
||||
# Docker Hub 인증 확인
|
||||
kubectl get secret -n phonebill
|
||||
```
|
||||
|
||||
#### 2. 파드 시작 실패
|
||||
```bash
|
||||
# 로그 확인
|
||||
kubectl logs {pod-name} -n phonebill
|
||||
|
||||
# 이벤트 확인
|
||||
kubectl get events -n phonebill --sort-by='.lastTimestamp'
|
||||
```
|
||||
|
||||
#### 3. Kustomize 빌드 실패
|
||||
```bash
|
||||
# 검증 스크립트 실행
|
||||
./deployment/cicd/scripts/validate-resources.sh
|
||||
|
||||
# 직접 빌드 테스트
|
||||
kubectl kustomize deployment/cicd/kustomize/overlays/dev
|
||||
```
|
||||
|
||||
### 7.2 Kustomize 빌드 테스트
|
||||
```bash
|
||||
# Base 빌드 테스트
|
||||
kubectl kustomize deployment/cicd/kustomize/base/
|
||||
### Jenkins 파이프라인 문제
|
||||
|
||||
# 환경별 빌드 테스트
|
||||
kubectl kustomize deployment/cicd/kustomize/overlays/dev/
|
||||
kubectl kustomize deployment/cicd/kustomize/overlays/staging/
|
||||
kubectl kustomize deployment/cicd/kustomize/overlays/prod/
|
||||
```
|
||||
#### 1. Pod 정리가 안 되는 경우
|
||||
- `podRetention: never()` 설정 확인
|
||||
- `terminationGracePeriodSeconds: 3` 설정 확인
|
||||
- Jenkins Kubernetes Plugin 버전 확인
|
||||
|
||||
---
|
||||
#### 2. 변수 치환 오류
|
||||
- `${variable}` 사용 (Groovy 문자열 보간)
|
||||
- `\${variable}` 사용 금지 (bash 이스케이프)
|
||||
|
||||
## 8. SonarQube 설정 (선택사항)
|
||||
## 📝 체크리스트
|
||||
|
||||
### 8.1 Quality Gate 권장 설정
|
||||
```
|
||||
Coverage: >= 80%
|
||||
Duplicated Lines: <= 3%
|
||||
Maintainability Rating: <= A
|
||||
Reliability Rating: <= A
|
||||
Security Rating: <= A
|
||||
```
|
||||
|
||||
### 8.2 SonarQube 프로젝트 생성
|
||||
각 서비스별로 다음 형식의 프로젝트 키로 생성:
|
||||
- `phonebill-user-service-dev`
|
||||
- `phonebill-user-service-staging`
|
||||
- `phonebill-user-service-prod`
|
||||
|
||||
---
|
||||
|
||||
## 9. 트러블슈팅
|
||||
|
||||
### 9.1 이미지 푸시 실패
|
||||
- Docker Hub 인증 정보 확인
|
||||
- Rate Limit 확인 (무료 계정 제한)
|
||||
|
||||
### 9.2 배포 실패
|
||||
```bash
|
||||
# Pod 이벤트 확인
|
||||
kubectl describe pod {POD_NAME} -n phonebill
|
||||
|
||||
# Pod 로그 확인
|
||||
kubectl logs {POD_NAME} -n phonebill
|
||||
```
|
||||
|
||||
### 9.3 Kustomize 빌드 실패
|
||||
- 리소스 파일 존재 여부 확인
|
||||
- YAML 문법 검증
|
||||
- `kubectl kustomize` 명령으로 디버깅
|
||||
|
||||
### 9.4 SonarQube 연결 실패
|
||||
- SonarQube 서버 URL 확인
|
||||
- 인증 토큰 유효성 확인
|
||||
- 네트워크 연결 확인
|
||||
|
||||
---
|
||||
|
||||
## 10. 체크리스트
|
||||
|
||||
### 사전 준비
|
||||
- [ ] Jenkins 필수 플러그인 설치 완료
|
||||
- [ ] Docker Hub Credentials 등록 완료
|
||||
- [ ] SonarQube Token 등록 완료 (선택)
|
||||
### 배포 전 확인
|
||||
- [ ] 환경 변수 파일 설정 완료
|
||||
- [ ] Kubernetes 컨텍스트 설정 완료
|
||||
- [ ] 이미지 레지스트리 인증 설정
|
||||
- [ ] 네임스페이스 생성 완료
|
||||
- [ ] 백킹 서비스(DB, Redis) 준비 완료
|
||||
|
||||
### 배포 전
|
||||
- [ ] 리소스 검증 스크립트 실행 완료
|
||||
- [ ] 환경별 설정 파일 확인 완료
|
||||
- [ ] Kustomize 빌드 테스트 완료
|
||||
|
||||
### 배포 후
|
||||
- [ ] Pod 상태 확인 (Running)
|
||||
- [ ] 서비스 엔드포인트 확인
|
||||
- [ ] Ingress 접근 테스트
|
||||
- [ ] 로그 이상 여부 확인
|
||||
### 배포 후 확인
|
||||
- [ ] 모든 파드 Running 상태 확인
|
||||
- [ ] 서비스 엔드포인트 정상 응답
|
||||
- [ ] 로그에 에러 없음
|
||||
- [ ] 헬스체크 정상 통과
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: api-gateway-config
|
||||
|
||||
name: cm-api-gateway
|
||||
labels:
|
||||
app: api-gateway
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -2,7 +2,6 @@ apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: api-gateway
|
||||
|
||||
labels:
|
||||
app: api-gateway
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
@ -25,11 +24,11 @@ spec:
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: phonebill-common-config
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: api-gateway-config
|
||||
name: cm-api-gateway
|
||||
- secretRef:
|
||||
name: phonebill-common-secret
|
||||
name: secret-common
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
|
||||
@ -2,7 +2,6 @@ apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: api-gateway
|
||||
|
||||
labels:
|
||||
app: api-gateway
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: bill-service-config
|
||||
|
||||
name: cm-bill-service
|
||||
labels:
|
||||
app: bill-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -2,7 +2,6 @@ apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: bill-service
|
||||
|
||||
labels:
|
||||
app: bill-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
@ -25,13 +24,13 @@ spec:
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: phonebill-common-config
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: bill-service-config
|
||||
name: cm-bill-service
|
||||
- secretRef:
|
||||
name: phonebill-common-secret
|
||||
name: secret-common
|
||||
- secretRef:
|
||||
name: bill-service-db-secret
|
||||
name: secret-bill-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: bill-service-db-secret
|
||||
|
||||
name: secret-bill-service
|
||||
labels:
|
||||
app: bill-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -2,7 +2,6 @@ apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: bill-service
|
||||
|
||||
labels:
|
||||
app: bill-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: phonebill-common-config
|
||||
|
||||
name: cm-common
|
||||
labels:
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
data:
|
||||
|
||||
@ -2,7 +2,6 @@ apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: phonebill-ingress
|
||||
|
||||
labels:
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
annotations:
|
||||
@ -10,6 +9,7 @@ metadata:
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
|
||||
nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "false"
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
rules:
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: phonebill-common-secret
|
||||
|
||||
name: secret-common
|
||||
labels:
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
type: Opaque
|
||||
stringData:
|
||||
# JWT Secret (최소 256비트 이상, HS256 알고리즘용)
|
||||
JWT_SECRET: "EK1ZV7vROOXREXbYe/BCISdQq0Yklk9JtoA2v88ux1DBDc0bDGiRRxHeDSb7GHkDP9IUYHMVsBi4/1rS4OhfRg=="
|
||||
# Redis 비밀번호 (비밀번호 없는 경우 빈 값)
|
||||
REDIS_PASSWORD: "P@ssw0rd$"
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: kos-mock-config
|
||||
|
||||
name: cm-kos-mock
|
||||
labels:
|
||||
app: kos-mock
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -2,7 +2,6 @@ apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: kos-mock
|
||||
|
||||
labels:
|
||||
app: kos-mock
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
@ -25,11 +24,11 @@ spec:
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: phonebill-common-config
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: kos-mock-config
|
||||
name: cm-kos-mock
|
||||
- secretRef:
|
||||
name: phonebill-common-secret
|
||||
name: secret-common
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
|
||||
@ -2,7 +2,6 @@ apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: kos-mock
|
||||
|
||||
labels:
|
||||
app: kos-mock
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: product-service-config
|
||||
|
||||
name: cm-product-service
|
||||
labels:
|
||||
app: product-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -2,7 +2,6 @@ apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: product-service
|
||||
|
||||
labels:
|
||||
app: product-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
@ -25,13 +24,13 @@ spec:
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: phonebill-common-config
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: product-service-config
|
||||
name: cm-product-service
|
||||
- secretRef:
|
||||
name: phonebill-common-secret
|
||||
name: secret-common
|
||||
- secretRef:
|
||||
name: product-service-db-secret
|
||||
name: secret-product-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: product-service-db-secret
|
||||
|
||||
name: secret-product-service
|
||||
labels:
|
||||
app: product-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -2,7 +2,6 @@ apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: product-service
|
||||
|
||||
labels:
|
||||
app: product-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: user-service-config
|
||||
|
||||
name: cm-user-service
|
||||
labels:
|
||||
app: user-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -2,7 +2,6 @@ apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: user-service
|
||||
|
||||
labels:
|
||||
app: user-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
@ -25,13 +24,13 @@ spec:
|
||||
name: http
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: phonebill-common-config
|
||||
name: cm-common
|
||||
- configMapRef:
|
||||
name: user-service-config
|
||||
name: cm-user-service
|
||||
- secretRef:
|
||||
name: phonebill-common-secret
|
||||
name: secret-common
|
||||
- secretRef:
|
||||
name: user-service-db-secret
|
||||
name: secret-user-service
|
||||
resources:
|
||||
requests:
|
||||
cpu: "256m"
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: user-service-db-secret
|
||||
|
||||
name: secret-user-service
|
||||
labels:
|
||||
app: user-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -2,7 +2,6 @@ apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: user-service
|
||||
|
||||
labels:
|
||||
app: user-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: phonebill-common-config
|
||||
name: cm-common
|
||||
labels:
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
data:
|
||||
|
||||
@ -7,21 +7,18 @@ resources:
|
||||
- ../../base
|
||||
|
||||
patches:
|
||||
# Common patches
|
||||
- path: cm-common-patch.yaml
|
||||
target:
|
||||
kind: ConfigMap
|
||||
name: phonebill-common-config
|
||||
name: cm-common
|
||||
- path: secret-common-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: phonebill-common-secret
|
||||
name: secret-common
|
||||
- path: ingress-patch.yaml
|
||||
target:
|
||||
kind: Ingress
|
||||
name: phonebill-ingress
|
||||
|
||||
# Deployment patches
|
||||
- path: deployment-api-gateway-patch.yaml
|
||||
target:
|
||||
kind: Deployment
|
||||
@ -42,29 +39,27 @@ patches:
|
||||
target:
|
||||
kind: Deployment
|
||||
name: kos-mock
|
||||
|
||||
# Service Secret patches
|
||||
- path: secret-user-service-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: user-service-db-secret
|
||||
name: secret-user-service
|
||||
- path: secret-bill-service-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: bill-service-db-secret
|
||||
name: secret-bill-service
|
||||
- path: secret-product-service-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: product-service-db-secret
|
||||
name: secret-product-service
|
||||
|
||||
images:
|
||||
- name: docker.io/hiondal/api-gateway
|
||||
newTag: latest
|
||||
newTag: dev-latest
|
||||
- name: docker.io/hiondal/user-service
|
||||
newTag: latest
|
||||
newTag: dev-latest
|
||||
- name: docker.io/hiondal/bill-service
|
||||
newTag: latest
|
||||
newTag: dev-latest
|
||||
- name: docker.io/hiondal/product-service
|
||||
newTag: latest
|
||||
newTag: dev-latest
|
||||
- name: docker.io/hiondal/kos-mock
|
||||
newTag: latest
|
||||
newTag: dev-latest
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: bill-service-db-secret
|
||||
name: secret-bill-service
|
||||
labels:
|
||||
app: bill-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: phonebill-common-secret
|
||||
name: secret-common
|
||||
labels:
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
type: Opaque
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: product-service-db-secret
|
||||
name: secret-product-service
|
||||
labels:
|
||||
app: product-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: user-service-db-secret
|
||||
name: secret-user-service
|
||||
labels:
|
||||
app: user-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: phonebill-common-config
|
||||
name: cm-common
|
||||
labels:
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
data:
|
||||
|
||||
@ -16,7 +16,7 @@ spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- phonebill.example.com
|
||||
secretName: phonebill-prod-tls
|
||||
secretName: phonebill-tls
|
||||
rules:
|
||||
- host: phonebill.example.com
|
||||
http:
|
||||
|
||||
@ -1,27 +1,24 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: phonebill-prod
|
||||
namespace: phonebill
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
patches:
|
||||
# Common patches
|
||||
- path: cm-common-patch.yaml
|
||||
target:
|
||||
kind: ConfigMap
|
||||
name: phonebill-common-config
|
||||
name: cm-common
|
||||
- path: secret-common-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: phonebill-common-secret
|
||||
name: secret-common
|
||||
- path: ingress-patch.yaml
|
||||
target:
|
||||
kind: Ingress
|
||||
name: phonebill-ingress
|
||||
|
||||
# Deployment patches
|
||||
- path: deployment-api-gateway-patch.yaml
|
||||
target:
|
||||
kind: Deployment
|
||||
@ -42,29 +39,27 @@ patches:
|
||||
target:
|
||||
kind: Deployment
|
||||
name: kos-mock
|
||||
|
||||
# Service Secret patches
|
||||
- path: secret-user-service-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: user-service-db-secret
|
||||
name: secret-user-service
|
||||
- path: secret-bill-service-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: bill-service-db-secret
|
||||
name: secret-bill-service
|
||||
- path: secret-product-service-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: product-service-db-secret
|
||||
name: secret-product-service
|
||||
|
||||
images:
|
||||
- name: docker.io/hiondal/api-gateway
|
||||
newTag: latest
|
||||
newTag: prod-latest
|
||||
- name: docker.io/hiondal/user-service
|
||||
newTag: latest
|
||||
newTag: prod-latest
|
||||
- name: docker.io/hiondal/bill-service
|
||||
newTag: latest
|
||||
newTag: prod-latest
|
||||
- name: docker.io/hiondal/product-service
|
||||
newTag: latest
|
||||
newTag: prod-latest
|
||||
- name: docker.io/hiondal/kos-mock
|
||||
newTag: latest
|
||||
newTag: prod-latest
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: bill-service-db-secret
|
||||
name: secret-bill-service
|
||||
labels:
|
||||
app: bill-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_USERNAME: "unicorn"
|
||||
DB_PASSWORD: "PROD_DB_PASSWORD"
|
||||
DB_PASSWORD: "P@ssw0rd$"
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: phonebill-common-secret
|
||||
name: secret-common
|
||||
labels:
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
type: Opaque
|
||||
stringData:
|
||||
JWT_SECRET: "PROD_JWT_SECRET_REPLACE_WITH_SECURE_VALUE"
|
||||
REDIS_PASSWORD: "PROD_REDIS_PASSWORD"
|
||||
JWT_SECRET: "EK1ZV7vROOXREXbYe/BCISdQq0Yklk9JtoA2v88ux1DBDc0bDGiRRxHeDSb7GHkDP9IUYHMVsBi4/1rS4OhfRg=="
|
||||
REDIS_PASSWORD: "P@ssw0rd$"
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: product-service-db-secret
|
||||
name: secret-product-service
|
||||
labels:
|
||||
app: product-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_USERNAME: "unicorn"
|
||||
DB_PASSWORD: "PROD_DB_PASSWORD"
|
||||
DB_PASSWORD: "P@ssw0rd$"
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: user-service-db-secret
|
||||
name: secret-user-service
|
||||
labels:
|
||||
app: user-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_USERNAME: "unicorn"
|
||||
DB_PASSWORD: "PROD_DB_PASSWORD"
|
||||
DB_PASSWORD: "P@ssw0rd$"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: phonebill-common-config
|
||||
name: cm-common
|
||||
labels:
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
data:
|
||||
|
||||
@ -10,7 +10,7 @@ metadata:
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
|
||||
nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-staging"
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
tls:
|
||||
|
||||
@ -7,21 +7,18 @@ resources:
|
||||
- ../../base
|
||||
|
||||
patches:
|
||||
# Common patches
|
||||
- path: cm-common-patch.yaml
|
||||
target:
|
||||
kind: ConfigMap
|
||||
name: phonebill-common-config
|
||||
name: cm-common
|
||||
- path: secret-common-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: phonebill-common-secret
|
||||
name: secret-common
|
||||
- path: ingress-patch.yaml
|
||||
target:
|
||||
kind: Ingress
|
||||
name: phonebill-ingress
|
||||
|
||||
# Deployment patches
|
||||
- path: deployment-api-gateway-patch.yaml
|
||||
target:
|
||||
kind: Deployment
|
||||
@ -42,29 +39,27 @@ patches:
|
||||
target:
|
||||
kind: Deployment
|
||||
name: kos-mock
|
||||
|
||||
# Service Secret patches
|
||||
- path: secret-user-service-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: user-service-db-secret
|
||||
name: secret-user-service
|
||||
- path: secret-bill-service-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: bill-service-db-secret
|
||||
name: secret-bill-service
|
||||
- path: secret-product-service-patch.yaml
|
||||
target:
|
||||
kind: Secret
|
||||
name: product-service-db-secret
|
||||
name: secret-product-service
|
||||
|
||||
images:
|
||||
- name: docker.io/hiondal/api-gateway
|
||||
newTag: latest
|
||||
newTag: staging-latest
|
||||
- name: docker.io/hiondal/user-service
|
||||
newTag: latest
|
||||
newTag: staging-latest
|
||||
- name: docker.io/hiondal/bill-service
|
||||
newTag: latest
|
||||
newTag: staging-latest
|
||||
- name: docker.io/hiondal/product-service
|
||||
newTag: latest
|
||||
newTag: staging-latest
|
||||
- name: docker.io/hiondal/kos-mock
|
||||
newTag: latest
|
||||
newTag: staging-latest
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: bill-service-db-secret
|
||||
name: secret-bill-service
|
||||
labels:
|
||||
app: bill-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_USERNAME: "unicorn"
|
||||
DB_PASSWORD: "STAGING_DB_PASSWORD"
|
||||
DB_PASSWORD: "P@ssw0rd$"
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: phonebill-common-secret
|
||||
name: secret-common
|
||||
labels:
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
type: Opaque
|
||||
stringData:
|
||||
JWT_SECRET: "STAGING_JWT_SECRET_REPLACE_WITH_SECURE_VALUE"
|
||||
REDIS_PASSWORD: "STAGING_REDIS_PASSWORD"
|
||||
JWT_SECRET: "EK1ZV7vROOXREXbYe/BCISdQq0Yklk9JtoA2v88ux1DBDc0bDGiRRxHeDSb7GHkDP9IUYHMVsBi4/1rS4OhfRg=="
|
||||
REDIS_PASSWORD: "P@ssw0rd$"
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: product-service-db-secret
|
||||
name: secret-product-service
|
||||
labels:
|
||||
app: product-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_USERNAME: "unicorn"
|
||||
DB_PASSWORD: "STAGING_DB_PASSWORD"
|
||||
DB_PASSWORD: "P@ssw0rd$"
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: user-service-db-secret
|
||||
name: secret-user-service
|
||||
labels:
|
||||
app: user-service
|
||||
app.kubernetes.io/part-of: phonebill
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_USERNAME: "unicorn"
|
||||
DB_PASSWORD: "STAGING_DB_PASSWORD"
|
||||
DB_PASSWORD: "P@ssw0rd$"
|
||||
|
||||
@ -4,35 +4,32 @@ set -e
|
||||
ENVIRONMENT=${1:-dev}
|
||||
IMAGE_TAG=${2:-latest}
|
||||
|
||||
echo "🚀 Deploying to ${ENVIRONMENT} environment with tag ${IMAGE_TAG}..."
|
||||
|
||||
# 환경별 설정 파일 로드
|
||||
source "$(dirname "$0")/../config/deploy_env_vars_${ENVIRONMENT}"
|
||||
echo "🚀 Starting deployment to ${ENVIRONMENT} environment..."
|
||||
|
||||
# 환경별 이미지 태그 업데이트
|
||||
cd "$(dirname "$0")/../kustomize/overlays/${ENVIRONMENT}"
|
||||
cd deployment/cicd/kustomize/overlays/${ENVIRONMENT}
|
||||
|
||||
# 서비스 목록
|
||||
# 서비스 목록 (공백으로 구분)
|
||||
services="api-gateway user-service bill-service product-service kos-mock"
|
||||
|
||||
# 각 서비스 이미지 태그 업데이트
|
||||
for service in $services; do
|
||||
echo "📦 Updating image tag for ${service}..."
|
||||
kustomize edit set image docker.io/hiondal/$service:${ENVIRONMENT}-${IMAGE_TAG}
|
||||
kustomize edit set image docker.io/hiondal/$service=docker.io/hiondal/$service:${ENVIRONMENT}-${IMAGE_TAG}
|
||||
done
|
||||
|
||||
# 배포 실행
|
||||
echo "📋 Applying Kustomize manifests..."
|
||||
echo "📤 Applying Kubernetes manifests..."
|
||||
kubectl apply -k .
|
||||
|
||||
# 배포 상태 확인
|
||||
echo "⏳ Waiting for deployments to be ready..."
|
||||
for service in $services; do
|
||||
echo " Checking ${service}..."
|
||||
kubectl rollout status deployment/$service -n ${namespace} --timeout=300s || echo " ⚠️ Timeout waiting for ${service}"
|
||||
kubectl rollout status deployment/$service -n phonebill --timeout=300s
|
||||
done
|
||||
|
||||
echo "✅ Deployment completed successfully!"
|
||||
echo ""
|
||||
echo "📊 Current status:"
|
||||
kubectl get pods -n ${namespace}
|
||||
echo "📊 Current deployment status:"
|
||||
kubectl get pods -n phonebill
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
#!/bin/bash
|
||||
# Base 리소스 누락 검증 스크립트
|
||||
# Base 리소스 누락 검증 스크립트 (phonebill)
|
||||
|
||||
echo "🔍 Phonebill Base 리소스 누락 검증 시작..."
|
||||
echo "🔍 phonebill Base 리소스 누락 검증 시작..."
|
||||
|
||||
BASE_DIR="deployment/cicd/kustomize/base"
|
||||
MISSING_RESOURCES=0
|
||||
REQUIRED_FILES=("deployment.yaml" "service.yaml")
|
||||
OPTIONAL_FILES=("cm-" "secret-")
|
||||
|
||||
# 1. 각 서비스 디렉토리의 파일 확인
|
||||
echo ""
|
||||
@ -15,33 +17,24 @@ for dir in $BASE_DIR/*/; do
|
||||
echo "=== $service ==="
|
||||
|
||||
# 필수 파일 확인
|
||||
if [ -f "$dir/deployment.yaml" ]; then
|
||||
echo " ✅ deployment.yaml"
|
||||
else
|
||||
echo " ❌ MISSING REQUIRED: deployment.yaml"
|
||||
((MISSING_RESOURCES++))
|
||||
fi
|
||||
for required in "${REQUIRED_FILES[@]}"; do
|
||||
if [ -f "$dir$required" ]; then
|
||||
echo " ✅ $required"
|
||||
else
|
||||
echo " ❌ MISSING REQUIRED: $required"
|
||||
((MISSING_RESOURCES++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -f "$dir/service.yaml" ]; then
|
||||
echo " ✅ service.yaml"
|
||||
else
|
||||
echo " ❌ MISSING REQUIRED: service.yaml"
|
||||
((MISSING_RESOURCES++))
|
||||
fi
|
||||
|
||||
# ConfigMap 확인
|
||||
if ls "$dir"cm-*.yaml 1> /dev/null 2>&1; then
|
||||
for file in "$dir"cm-*.yaml; do
|
||||
echo " ✅ $(basename "$file")"
|
||||
done
|
||||
fi
|
||||
|
||||
# Secret 확인
|
||||
if ls "$dir"secret-*.yaml 1> /dev/null 2>&1; then
|
||||
for file in "$dir"secret-*.yaml; do
|
||||
echo " ✅ $(basename "$file")"
|
||||
done
|
||||
fi
|
||||
# 선택적 파일 확인
|
||||
for optional in "${OPTIONAL_FILES[@]}"; do
|
||||
files=($(ls "$dir"$optional*".yaml" 2>/dev/null))
|
||||
if [ ${#files[@]} -gt 0 ]; then
|
||||
for file in "${files[@]}"; do
|
||||
echo " ✅ $(basename "$file")"
|
||||
done
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
@ -50,11 +43,15 @@ done
|
||||
echo "2. Common 리소스 확인:"
|
||||
COMMON_DIR="$BASE_DIR/common"
|
||||
if [ -d "$COMMON_DIR" ]; then
|
||||
for file in "$COMMON_DIR"/*.yaml; do
|
||||
if [ -f "$file" ]; then
|
||||
common_files=($(ls "$COMMON_DIR"/*.yaml 2>/dev/null))
|
||||
if [ ${#common_files[@]} -gt 0 ]; then
|
||||
for file in "${common_files[@]}"; do
|
||||
echo " ✅ common/$(basename "$file")"
|
||||
fi
|
||||
done
|
||||
done
|
||||
else
|
||||
echo " ❌ Common 디렉토리에 YAML 파일이 없습니다"
|
||||
((MISSING_RESOURCES++))
|
||||
fi
|
||||
else
|
||||
echo " ❌ Common 디렉토리가 없습니다"
|
||||
((MISSING_RESOURCES++))
|
||||
@ -65,8 +62,9 @@ echo ""
|
||||
echo "3. kustomization.yaml 리소스 검증:"
|
||||
if [ -f "$BASE_DIR/kustomization.yaml" ]; then
|
||||
while IFS= read -r line; do
|
||||
# resources 섹션의 YAML 파일 경로 추출
|
||||
if [[ $line =~ ^[[:space:]]*-[[:space:]]*([^#]+\.yaml)[[:space:]]*$ ]]; then
|
||||
resource_path=$(echo "${BASH_REMATCH[1]}" | xargs)
|
||||
resource_path=$(echo "${BASH_REMATCH[1]}" | xargs) # 공백 제거
|
||||
full_path="$BASE_DIR/$resource_path"
|
||||
if [ -f "$full_path" ]; then
|
||||
echo " ✅ $resource_path"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user