mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 07:56:24 +00:00
add ci/cd
This commit is contained in:
parent
decc4de180
commit
9adcab2048
254
.github/workflows/backend-cicd_ArgoCD.yaml
vendored
Normal file
254
.github/workflows/backend-cicd_ArgoCD.yaml
vendored
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
name: Backend Services CI/CD
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main, develop ]
|
||||||
|
paths:
|
||||||
|
- 'user/**'
|
||||||
|
- 'meeting/**'
|
||||||
|
- 'stt/**'
|
||||||
|
- 'ai/**'
|
||||||
|
- 'notification/**'
|
||||||
|
- 'common/**'
|
||||||
|
- '.github/**'
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
ENVIRONMENT:
|
||||||
|
description: 'Target environment'
|
||||||
|
required: true
|
||||||
|
default: 'dev'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- dev
|
||||||
|
- staging
|
||||||
|
- prod
|
||||||
|
SKIP_SONARQUBE:
|
||||||
|
description: 'Skip SonarQube Analysis'
|
||||||
|
required: false
|
||||||
|
default: 'true'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- 'true'
|
||||||
|
- 'false'
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: acrdigitalgarage02.azurecr.io
|
||||||
|
IMAGE_ORG: hgzero
|
||||||
|
RESOURCE_GROUP: rg-digitalgarage-02
|
||||||
|
AKS_CLUSTER: aks-digitalgarage-02
|
||||||
|
NAMESPACE: hgzero
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build and Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
image_tag: ${{ steps.set_outputs.outputs.image_tag }}
|
||||||
|
environment: ${{ steps.set_outputs.outputs.environment }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up JDK 21
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '21'
|
||||||
|
distribution: 'temurin'
|
||||||
|
cache: 'gradle'
|
||||||
|
|
||||||
|
- name: Determine environment
|
||||||
|
id: determine_env
|
||||||
|
run: |
|
||||||
|
# Use input parameter or default to 'dev'
|
||||||
|
ENVIRONMENT="${{ github.event.inputs.ENVIRONMENT || 'dev' }}"
|
||||||
|
echo "environment=$ENVIRONMENT" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Load environment variables
|
||||||
|
id: env_vars
|
||||||
|
run: |
|
||||||
|
ENV=${{ steps.determine_env.outputs.environment }}
|
||||||
|
|
||||||
|
# Initialize variables with defaults
|
||||||
|
REGISTRY="acrdigitalgarage02.azurecr.io"
|
||||||
|
IMAGE_ORG="hgzero"
|
||||||
|
RESOURCE_GROUP="rg-digitalgarage-02"
|
||||||
|
AKS_CLUSTER="aks-digitalgarage-02"
|
||||||
|
NAMESPACE="hgzero"
|
||||||
|
|
||||||
|
# Read environment variables from .github/config file
|
||||||
|
if [[ -f ".github/config/deploy_env_vars_${ENV}" ]]; then
|
||||||
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||||
|
# Skip comments and empty lines
|
||||||
|
[[ "$line" =~ ^#.*$ ]] && continue
|
||||||
|
[[ -z "$line" ]] && continue
|
||||||
|
|
||||||
|
# Extract key-value pairs
|
||||||
|
key=$(echo "$line" | cut -d '=' -f1)
|
||||||
|
value=$(echo "$line" | cut -d '=' -f2-)
|
||||||
|
|
||||||
|
# Override defaults if found in config
|
||||||
|
case "$key" in
|
||||||
|
"resource_group") RESOURCE_GROUP="$value" ;;
|
||||||
|
"cluster_name") AKS_CLUSTER="$value" ;;
|
||||||
|
esac
|
||||||
|
done < ".github/config/deploy_env_vars_${ENV}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Export for other jobs
|
||||||
|
echo "REGISTRY=$REGISTRY" >> $GITHUB_ENV
|
||||||
|
echo "IMAGE_ORG=$IMAGE_ORG" >> $GITHUB_ENV
|
||||||
|
echo "RESOURCE_GROUP=$RESOURCE_GROUP" >> $GITHUB_ENV
|
||||||
|
echo "AKS_CLUSTER=$AKS_CLUSTER" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Grant execute permission for gradlew
|
||||||
|
run: chmod +x gradlew
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: |
|
||||||
|
./gradlew build -x test
|
||||||
|
|
||||||
|
- name: SonarQube Analysis & Quality Gate
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
|
||||||
|
run: |
|
||||||
|
# Check if SonarQube should be skipped
|
||||||
|
SKIP_SONARQUBE="${{ github.event.inputs.SKIP_SONARQUBE || 'true' }}"
|
||||||
|
|
||||||
|
if [[ "$SKIP_SONARQUBE" == "true" ]]; then
|
||||||
|
echo "⏭️ Skipping SonarQube Analysis (SKIP_SONARQUBE=$SKIP_SONARQUBE)"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Define services array
|
||||||
|
services=(user meeting stt ai notification)
|
||||||
|
|
||||||
|
# Run tests, coverage reports, and SonarQube analysis for each service
|
||||||
|
for service in "${services[@]}"; do
|
||||||
|
./gradlew :$service:test :$service:jacocoTestReport :$service:sonar \
|
||||||
|
-Dsonar.projectKey=hgzero-$service-${{ steps.determine_env.outputs.environment }} \
|
||||||
|
-Dsonar.projectName=hgzero-$service-${{ steps.determine_env.outputs.environment }} \
|
||||||
|
-Dsonar.host.url=$SONAR_HOST_URL \
|
||||||
|
-Dsonar.token=$SONAR_TOKEN \
|
||||||
|
-Dsonar.java.binaries=build/classes/java/main \
|
||||||
|
-Dsonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml \
|
||||||
|
-Dsonar.exclusions=**/config/**,**/entity/**,**/dto/**,**/*Application.class,**/exception/**
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: app-builds
|
||||||
|
path: |
|
||||||
|
user/build/libs/*.jar
|
||||||
|
meeting/build/libs/*.jar
|
||||||
|
stt/build/libs/*.jar
|
||||||
|
ai/build/libs/*.jar
|
||||||
|
notification/build/libs/*.jar
|
||||||
|
|
||||||
|
- name: Set outputs
|
||||||
|
id: set_outputs
|
||||||
|
run: |
|
||||||
|
# Generate timestamp for image tag
|
||||||
|
IMAGE_TAG=$(date +%Y%m%d%H%M%S)
|
||||||
|
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
|
||||||
|
echo "environment=${{ steps.determine_env.outputs.environment }}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
release:
|
||||||
|
name: Build and Push Docker Images
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Download build artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: app-builds
|
||||||
|
|
||||||
|
- name: Set environment variables from build job
|
||||||
|
run: |
|
||||||
|
echo "REGISTRY=${{ env.REGISTRY }}" >> $GITHUB_ENV
|
||||||
|
echo "IMAGE_ORG=${{ env.IMAGE_ORG }}" >> $GITHUB_ENV
|
||||||
|
echo "ENVIRONMENT=${{ needs.build.outputs.environment }}" >> $GITHUB_ENV
|
||||||
|
echo "IMAGE_TAG=${{ needs.build.outputs.image_tag }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to Docker Hub (prevent rate limit)
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Login to Azure Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ secrets.ACR_USERNAME }}
|
||||||
|
password: ${{ secrets.ACR_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and push Docker images for all services
|
||||||
|
run: |
|
||||||
|
# Define services array
|
||||||
|
services=(user meeting stt ai notification)
|
||||||
|
|
||||||
|
# Build and push each service image
|
||||||
|
for service in "${services[@]}"; do
|
||||||
|
echo "Building and pushing $service..."
|
||||||
|
docker build \
|
||||||
|
--build-arg BUILD_LIB_DIR="$service/build/libs" \
|
||||||
|
--build-arg ARTIFACTORY_FILE="$service.jar" \
|
||||||
|
-f deployment/container/Dockerfile-backend \
|
||||||
|
-t ${{ env.REGISTRY }}/${{ env.IMAGE_ORG }}/$service:${{ needs.build.outputs.environment }}-${{ needs.build.outputs.image_tag }} .
|
||||||
|
|
||||||
|
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_ORG }}/$service:${{ needs.build.outputs.environment }}-${{ needs.build.outputs.image_tag }}
|
||||||
|
done
|
||||||
|
|
||||||
|
update-manifest:
|
||||||
|
name: Update Manifest Repository
|
||||||
|
needs: [build, release]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Set image tag environment variable
|
||||||
|
run: |
|
||||||
|
echo "IMAGE_TAG=${{ needs.build.outputs.image_tag }}" >> $GITHUB_ENV
|
||||||
|
echo "ENVIRONMENT=${{ needs.build.outputs.environment }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Update Manifest Repository
|
||||||
|
run: |
|
||||||
|
# 매니페스트 레포지토리 클론
|
||||||
|
REPO_URL=$(echo "https://github.com/hjmoons/hgzero-manifest.git" | sed 's|https://||')
|
||||||
|
git clone https://${{ secrets.GIT_USERNAME }}:${{ secrets.GIT_PASSWORD }}@${REPO_URL} manifest-repo
|
||||||
|
cd manifest-repo
|
||||||
|
|
||||||
|
# Kustomize 설치
|
||||||
|
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
|
||||||
|
sudo mv kustomize /usr/local/bin/
|
||||||
|
|
||||||
|
# 매니페스트 업데이트
|
||||||
|
cd hgzero/kustomize/overlays/${{ env.ENVIRONMENT }}
|
||||||
|
|
||||||
|
# 각 서비스별 이미지 태그 업데이트
|
||||||
|
services="user meeting stt ai notification"
|
||||||
|
for service in $services; do
|
||||||
|
kustomize edit set image acrdigitalgarage02.azurecr.io/hgzero/$service:${{ env.ENVIRONMENT }}-${{ env.IMAGE_TAG }}
|
||||||
|
done
|
||||||
|
|
||||||
|
# Git 설정 및 푸시
|
||||||
|
cd ../../../..
|
||||||
|
git config user.name "GitHub Actions"
|
||||||
|
git config user.email "actions@github.com"
|
||||||
|
git add .
|
||||||
|
git commit -m "🚀 Update hgzero ${{ env.ENVIRONMENT }} images to ${{ env.ENVIRONMENT }}-${{ env.IMAGE_TAG }}"
|
||||||
|
git push origin main
|
||||||
|
|
||||||
|
echo "✅ 매니페스트 업데이트 완료. ArgoCD가 자동으로 배포합니다."
|
||||||
420
deploy/k8s/backend/README.md
Normal file
420
deploy/k8s/backend/README.md
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
# HGZero 백엔드 서비스 Kubernetes 배포 가이드
|
||||||
|
|
||||||
|
## 개요
|
||||||
|
|
||||||
|
이 가이드는 HGZero 백엔드 서비스(User, Meeting, Notification)를 Azure Kubernetes Service(AKS)에 배포하는 방법을 설명합니다.
|
||||||
|
|
||||||
|
## 배포 환경
|
||||||
|
|
||||||
|
- **ACR(Azure Container Registry)**: acrdigitalgarage02
|
||||||
|
- **AKS(Azure Kubernetes Service)**: aks-digitalgarage-02
|
||||||
|
- **네임스페이스**: hgzero
|
||||||
|
- **리소스 그룹**: rg-digitalgarage-02
|
||||||
|
|
||||||
|
## 서비스 구성
|
||||||
|
|
||||||
|
### 1. User Service
|
||||||
|
- **포트**: 8080
|
||||||
|
- **이미지**: acrdigitalgarage02.azurecr.io/hgzero/user-service:latest
|
||||||
|
- **기능**: 사용자 인증 및 관리, LDAP 연동
|
||||||
|
|
||||||
|
### 2. Meeting Service
|
||||||
|
- **포트**: 8081 (HTTP), 8082 (WebSocket)
|
||||||
|
- **이미지**: acrdigitalgarage02.azurecr.io/hgzero/meeting-service:latest
|
||||||
|
- **기능**: 회의 관리, WebSocket 통신
|
||||||
|
|
||||||
|
### 3. Notification Service
|
||||||
|
- **포트**: 8082
|
||||||
|
- **이미지**: acrdigitalgarage02.azurecr.io/hgzero/notification-service:latest
|
||||||
|
- **기능**: 알림 전송, 이메일 발송
|
||||||
|
|
||||||
|
## 리소스 할당
|
||||||
|
|
||||||
|
각 서비스는 다음과 같은 리소스를 사용합니다:
|
||||||
|
|
||||||
|
- **Requests**:
|
||||||
|
- CPU: 256m
|
||||||
|
- Memory: 256Mi
|
||||||
|
- **Limits**:
|
||||||
|
- CPU: 1024m
|
||||||
|
- Memory: 1024Mi
|
||||||
|
- **Replicas**: 1 (각 서비스)
|
||||||
|
|
||||||
|
## 사전 요구사항
|
||||||
|
|
||||||
|
1. **Azure CLI 설치**
|
||||||
|
```bash
|
||||||
|
# macOS
|
||||||
|
brew install azure-cli
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
# Download from https://aka.ms/installazurecliwindows
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **kubectl 설치**
|
||||||
|
```bash
|
||||||
|
# macOS
|
||||||
|
brew install kubectl
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
# Download from https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
|
||||||
|
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Azure 로그인**
|
||||||
|
```bash
|
||||||
|
az login
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **ACR 로그인**
|
||||||
|
```bash
|
||||||
|
az acr login --name acrdigitalgarage02
|
||||||
|
```
|
||||||
|
|
||||||
|
## 배포 파일 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
deploy/k8s/backend/
|
||||||
|
├── namespace.yaml # 네임스페이스 정의
|
||||||
|
├── configmap.yaml # ConfigMap (Redis, Mail 설정)
|
||||||
|
├── secret-template.yaml # Secret 템플릿 (민감 정보)
|
||||||
|
├── user-service.yaml # User Service 배포 매니페스트
|
||||||
|
├── meeting-service.yaml # Meeting Service 배포 매니페스트
|
||||||
|
├── notification-service.yaml # Notification Service 배포 매니페스트
|
||||||
|
├── deploy.sh # 배포 스크립트
|
||||||
|
├── undeploy.sh # 배포 해제 스크립트
|
||||||
|
├── create-secrets.sh # Secret 생성 스크립트
|
||||||
|
└── README.md # 이 문서
|
||||||
|
```
|
||||||
|
|
||||||
|
## 배포 절차
|
||||||
|
|
||||||
|
### 1단계: AKS 클러스터 접근 설정
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# AKS credentials 가져오기
|
||||||
|
az aks get-credentials \
|
||||||
|
--resource-group rg-digitalgarage-02 \
|
||||||
|
--name aks-digitalgarage-02 \
|
||||||
|
--overwrite-existing
|
||||||
|
|
||||||
|
# 클러스터 연결 확인
|
||||||
|
kubectl cluster-info
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2단계: 네임스페이스 생성
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3단계: ConfigMap 생성
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f configmap.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4단계: Secret 생성
|
||||||
|
|
||||||
|
옵션 A: 대화형 스크립트 사용 (권장)
|
||||||
|
```bash
|
||||||
|
./create-secrets.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
옵션 B: 직접 생성
|
||||||
|
```bash
|
||||||
|
# Database Secret
|
||||||
|
kubectl create secret generic db-secret \
|
||||||
|
--from-literal=host=<DB_HOST> \
|
||||||
|
--from-literal=username=<DB_USERNAME> \
|
||||||
|
--from-literal=password=<DB_PASSWORD> \
|
||||||
|
--namespace=hgzero
|
||||||
|
|
||||||
|
# Azure Secret
|
||||||
|
kubectl create secret generic azure-secret \
|
||||||
|
--from-literal=eventhub-connection-string=<EVENTHUB_CONN> \
|
||||||
|
--from-literal=blob-connection-string=<BLOB_CONN> \
|
||||||
|
--namespace=hgzero
|
||||||
|
|
||||||
|
# Mail Secret
|
||||||
|
kubectl create secret generic mail-secret \
|
||||||
|
--from-literal=username=<MAIL_USERNAME> \
|
||||||
|
--from-literal=password=<MAIL_PASSWORD> \
|
||||||
|
--namespace=hgzero
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5단계: 서비스 배포
|
||||||
|
|
||||||
|
옵션 A: 자동 배포 스크립트 사용 (권장)
|
||||||
|
```bash
|
||||||
|
./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
옵션 B: 수동 배포
|
||||||
|
```bash
|
||||||
|
# ACR 연동 설정
|
||||||
|
az aks update \
|
||||||
|
-n aks-digitalgarage-02 \
|
||||||
|
-g rg-digitalgarage-02 \
|
||||||
|
--attach-acr acrdigitalgarage02
|
||||||
|
|
||||||
|
# 서비스 배포
|
||||||
|
kubectl apply -f user-service.yaml
|
||||||
|
kubectl apply -f notification-service.yaml
|
||||||
|
kubectl apply -f meeting-service.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6단계: 배포 상태 확인
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deployment 상태 확인
|
||||||
|
kubectl get deployments -n hgzero
|
||||||
|
|
||||||
|
# Pod 상태 확인
|
||||||
|
kubectl get pods -n hgzero
|
||||||
|
|
||||||
|
# Service 확인
|
||||||
|
kubectl get services -n hgzero
|
||||||
|
|
||||||
|
# 상세 정보 확인
|
||||||
|
kubectl describe deployment user-service -n hgzero
|
||||||
|
```
|
||||||
|
|
||||||
|
## 배포 확인 및 테스트
|
||||||
|
|
||||||
|
### Pod 로그 확인
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# User Service 로그
|
||||||
|
kubectl logs -f deployment/user-service -n hgzero
|
||||||
|
|
||||||
|
# Meeting Service 로그
|
||||||
|
kubectl logs -f deployment/meeting-service -n hgzero
|
||||||
|
|
||||||
|
# Notification Service 로그
|
||||||
|
kubectl logs -f deployment/notification-service -n hgzero
|
||||||
|
```
|
||||||
|
|
||||||
|
### Health Check
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# User Service health check
|
||||||
|
kubectl port-forward svc/user-service 8080:8080 -n hgzero
|
||||||
|
curl http://localhost:8080/actuator/health
|
||||||
|
|
||||||
|
# Meeting Service health check
|
||||||
|
kubectl port-forward svc/meeting-service 8081:8081 -n hgzero
|
||||||
|
curl http://localhost:8081/actuator/health
|
||||||
|
|
||||||
|
# Notification Service health check
|
||||||
|
kubectl port-forward svc/notification-service 8082:8082 -n hgzero
|
||||||
|
curl http://localhost:8082/actuator/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pod 내부 접속
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pod 내부로 접속하여 디버깅
|
||||||
|
kubectl exec -it deployment/user-service -n hgzero -- /bin/sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 배포 해제
|
||||||
|
|
||||||
|
### 전체 서비스 삭제
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./undeploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 개별 서비스 삭제
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl delete -f user-service.yaml
|
||||||
|
kubectl delete -f meeting-service.yaml
|
||||||
|
kubectl delete -f notification-service.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Secret 및 ConfigMap 삭제
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl delete configmap redis-config mail-config -n hgzero
|
||||||
|
kubectl delete secret db-secret azure-secret mail-secret -n hgzero
|
||||||
|
```
|
||||||
|
|
||||||
|
### 네임스페이스 삭제
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl delete namespace hgzero
|
||||||
|
```
|
||||||
|
|
||||||
|
## 트러블슈팅
|
||||||
|
|
||||||
|
### Pod가 시작되지 않는 경우
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pod 상태 확인
|
||||||
|
kubectl get pods -n hgzero
|
||||||
|
|
||||||
|
# Pod 상세 정보 확인
|
||||||
|
kubectl describe pod <pod-name> -n hgzero
|
||||||
|
|
||||||
|
# Pod 로그 확인
|
||||||
|
kubectl logs <pod-name> -n hgzero
|
||||||
|
|
||||||
|
# 이전 컨테이너 로그 확인 (재시작된 경우)
|
||||||
|
kubectl logs <pod-name> -n hgzero --previous
|
||||||
|
```
|
||||||
|
|
||||||
|
### 이미지 Pull 오류
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ACR 연동 상태 확인
|
||||||
|
az aks show -n aks-digitalgarage-02 -g rg-digitalgarage-02 --query "servicePrincipalProfile"
|
||||||
|
|
||||||
|
# ACR 재연동
|
||||||
|
az aks update -n aks-digitalgarage-02 -g rg-digitalgarage-02 --attach-acr acrdigitalgarage02
|
||||||
|
|
||||||
|
# ImagePullSecret 확인
|
||||||
|
kubectl get serviceaccount default -n hgzero -o yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Secret 관련 오류
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Secret 존재 확인
|
||||||
|
kubectl get secrets -n hgzero
|
||||||
|
|
||||||
|
# Secret 내용 확인
|
||||||
|
kubectl get secret db-secret -n hgzero -o yaml
|
||||||
|
|
||||||
|
# Secret 재생성
|
||||||
|
kubectl delete secret db-secret -n hgzero
|
||||||
|
./create-secrets.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 네트워크 연결 문제
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Service Endpoint 확인
|
||||||
|
kubectl get endpoints -n hgzero
|
||||||
|
|
||||||
|
# DNS 확인
|
||||||
|
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup user-service.hgzero.svc.cluster.local
|
||||||
|
|
||||||
|
# 네트워크 정책 확인
|
||||||
|
kubectl get networkpolicies -n hgzero
|
||||||
|
```
|
||||||
|
|
||||||
|
### 리소스 부족 문제
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 노드 리소스 사용량 확인
|
||||||
|
kubectl top nodes
|
||||||
|
|
||||||
|
# Pod 리소스 사용량 확인
|
||||||
|
kubectl top pods -n hgzero
|
||||||
|
|
||||||
|
# 리소스 제한 조정 (필요 시)
|
||||||
|
kubectl edit deployment user-service -n hgzero
|
||||||
|
```
|
||||||
|
|
||||||
|
## 업데이트 및 롤링 배포
|
||||||
|
|
||||||
|
### 이미지 업데이트
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 새 이미지 태그로 업데이트
|
||||||
|
kubectl set image deployment/user-service \
|
||||||
|
user-service=acrdigitalgarage02.azurecr.io/hgzero/user-service:v2.0.0 \
|
||||||
|
-n hgzero
|
||||||
|
|
||||||
|
# 롤아웃 상태 확인
|
||||||
|
kubectl rollout status deployment/user-service -n hgzero
|
||||||
|
|
||||||
|
# 롤아웃 히스토리 확인
|
||||||
|
kubectl rollout history deployment/user-service -n hgzero
|
||||||
|
```
|
||||||
|
|
||||||
|
### 롤백
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 이전 버전으로 롤백
|
||||||
|
kubectl rollout undo deployment/user-service -n hgzero
|
||||||
|
|
||||||
|
# 특정 revision으로 롤백
|
||||||
|
kubectl rollout undo deployment/user-service --to-revision=2 -n hgzero
|
||||||
|
```
|
||||||
|
|
||||||
|
## 모니터링
|
||||||
|
|
||||||
|
### Kubernetes Dashboard
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Dashboard 접근
|
||||||
|
az aks browse -n aks-digitalgarage-02 -g rg-digitalgarage-02
|
||||||
|
```
|
||||||
|
|
||||||
|
### 리소스 모니터링
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 실시간 리소스 사용량 모니터링
|
||||||
|
watch kubectl top pods -n hgzero
|
||||||
|
|
||||||
|
# 이벤트 모니터링
|
||||||
|
kubectl get events -n hgzero --sort-by='.lastTimestamp'
|
||||||
|
```
|
||||||
|
|
||||||
|
## 보안 권장사항
|
||||||
|
|
||||||
|
1. **Secret 관리**
|
||||||
|
- Secret은 절대 Git에 커밋하지 마세요
|
||||||
|
- Azure Key Vault 통합을 고려하세요
|
||||||
|
- Secret rotation 정책을 수립하세요
|
||||||
|
|
||||||
|
2. **네트워크 보안**
|
||||||
|
- Network Policy를 활용하여 Pod 간 통신을 제한하세요
|
||||||
|
- Service Mesh 도입을 고려하세요
|
||||||
|
|
||||||
|
3. **이미지 보안**
|
||||||
|
- 정기적으로 이미지 스캔을 수행하세요
|
||||||
|
- 최소 권한 원칙을 적용하세요
|
||||||
|
|
||||||
|
## 성능 최적화
|
||||||
|
|
||||||
|
1. **Auto Scaling 설정**
|
||||||
|
```bash
|
||||||
|
kubectl autoscale deployment user-service \
|
||||||
|
--cpu-percent=70 \
|
||||||
|
--min=1 \
|
||||||
|
--max=5 \
|
||||||
|
-n hgzero
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **리소스 조정**
|
||||||
|
- 실제 사용량에 따라 requests/limits를 조정하세요
|
||||||
|
- HPA(Horizontal Pod Autoscaler) 설정을 고려하세요
|
||||||
|
|
||||||
|
## 참고 자료
|
||||||
|
|
||||||
|
- [Azure Kubernetes Service 문서](https://docs.microsoft.com/azure/aks/)
|
||||||
|
- [Kubernetes 공식 문서](https://kubernetes.io/docs/)
|
||||||
|
- [kubectl 치트시트](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)
|
||||||
|
|
||||||
|
## 지원 및 문의
|
||||||
|
|
||||||
|
문제 발생 시 다음 정보를 수집하여 보고해주세요:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 진단 정보 수집
|
||||||
|
kubectl get all -n hgzero > hgzero-resources.txt
|
||||||
|
kubectl describe pods -n hgzero > hgzero-pods-detail.txt
|
||||||
|
kubectl logs deployment/user-service -n hgzero > user-service.log
|
||||||
|
kubectl logs deployment/meeting-service -n hgzero > meeting-service.log
|
||||||
|
kubectl logs deployment/notification-service -n hgzero > notification-service.log
|
||||||
|
```
|
||||||
20
deploy/k8s/backend/configmap.yaml
Normal file
20
deploy/k8s/backend/configmap.yaml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
# Redis Configuration
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: redis-config
|
||||||
|
namespace: hgzero
|
||||||
|
data:
|
||||||
|
host: "redis-service.hgzero.svc.cluster.local"
|
||||||
|
port: "6379"
|
||||||
|
---
|
||||||
|
# Mail Configuration
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: mail-config
|
||||||
|
namespace: hgzero
|
||||||
|
data:
|
||||||
|
host: "smtp.gmail.com"
|
||||||
|
port: "587"
|
||||||
103
deploy/k8s/backend/create-secrets.sh
Executable file
103
deploy/k8s/backend/create-secrets.sh
Executable file
@ -0,0 +1,103 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# HGZero Backend Services Secrets Creation Script
|
||||||
|
# This script helps create Kubernetes secrets for the backend services
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Color codes for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
NAMESPACE="hgzero"
|
||||||
|
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
|
echo -e "${GREEN}HGZero Secrets Creation${NC}"
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
|
|
||||||
|
# Check if kubectl is installed
|
||||||
|
if ! command -v kubectl &> /dev/null; then
|
||||||
|
echo -e "${RED}Error: kubectl is not installed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify connection to cluster
|
||||||
|
echo -e "${YELLOW}Verifying connection to Kubernetes cluster...${NC}"
|
||||||
|
if ! kubectl cluster-info &> /dev/null; then
|
||||||
|
echo -e "${RED}Error: Cannot connect to Kubernetes cluster${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if namespace exists
|
||||||
|
if ! kubectl get namespace ${NAMESPACE} &> /dev/null; then
|
||||||
|
echo -e "${RED}Error: Namespace '${NAMESPACE}' does not exist${NC}"
|
||||||
|
echo -e "${YELLOW}Please run deploy.sh first to create the namespace${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Function to prompt for secret value
|
||||||
|
prompt_secret() {
|
||||||
|
local prompt_text=$1
|
||||||
|
local secret_value
|
||||||
|
echo -n -e "${YELLOW}${prompt_text}: ${NC}"
|
||||||
|
read -s secret_value
|
||||||
|
echo ""
|
||||||
|
echo -n "$secret_value"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create Database Secret
|
||||||
|
echo -e "${GREEN}Creating Database Secret...${NC}"
|
||||||
|
DB_HOST=$(prompt_secret "Enter Database Host")
|
||||||
|
DB_USERNAME=$(prompt_secret "Enter Database Username")
|
||||||
|
DB_PASSWORD=$(prompt_secret "Enter Database Password")
|
||||||
|
|
||||||
|
kubectl create secret generic db-secret \
|
||||||
|
--from-literal=host="${DB_HOST}" \
|
||||||
|
--from-literal=username="${DB_USERNAME}" \
|
||||||
|
--from-literal=password="${DB_PASSWORD}" \
|
||||||
|
--namespace=${NAMESPACE} \
|
||||||
|
--dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
echo -e "${GREEN}✓ Database secret created${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create Azure Secret
|
||||||
|
echo -e "${GREEN}Creating Azure Secret...${NC}"
|
||||||
|
EVENTHUB_CONN=$(prompt_secret "Enter EventHub Connection String")
|
||||||
|
BLOB_CONN=$(prompt_secret "Enter Blob Storage Connection String")
|
||||||
|
|
||||||
|
kubectl create secret generic azure-secret \
|
||||||
|
--from-literal=eventhub-connection-string="${EVENTHUB_CONN}" \
|
||||||
|
--from-literal=blob-connection-string="${BLOB_CONN}" \
|
||||||
|
--namespace=${NAMESPACE} \
|
||||||
|
--dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
echo -e "${GREEN}✓ Azure secret created${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create Mail Secret
|
||||||
|
echo -e "${GREEN}Creating Mail Secret...${NC}"
|
||||||
|
MAIL_USERNAME=$(prompt_secret "Enter Mail Username")
|
||||||
|
MAIL_PASSWORD=$(prompt_secret "Enter Mail Password")
|
||||||
|
|
||||||
|
kubectl create secret generic mail-secret \
|
||||||
|
--from-literal=username="${MAIL_USERNAME}" \
|
||||||
|
--from-literal=password="${MAIL_PASSWORD}" \
|
||||||
|
--namespace=${NAMESPACE} \
|
||||||
|
--dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
echo -e "${GREEN}✓ Mail secret created${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Verify secrets
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
|
echo -e "${GREEN}Secrets Created Successfully${NC}"
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
|
kubectl get secrets -n ${NAMESPACE}
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Note: Secrets are stored in Kubernetes and can be viewed with:${NC}"
|
||||||
|
echo -e " kubectl get secret <secret-name> -n ${NAMESPACE} -o yaml"
|
||||||
133
deploy/k8s/backend/deploy.sh
Executable file
133
deploy/k8s/backend/deploy.sh
Executable file
@ -0,0 +1,133 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# HGZero Backend Services Kubernetes Deployment Script
|
||||||
|
# Azure Container Registry: acrdigitalgarage02
|
||||||
|
# Azure Kubernetes Service: aks-digitalgarage-02
|
||||||
|
# Namespace: hgzero
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Color codes for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
ACR_NAME="acrdigitalgarage02"
|
||||||
|
AKS_NAME="aks-digitalgarage-02"
|
||||||
|
RESOURCE_GROUP="rg-digitalgarage-02"
|
||||||
|
NAMESPACE="hgzero"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
|
echo -e "${GREEN}HGZero Backend Services Deployment${NC}"
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
|
|
||||||
|
# Check if kubectl is installed
|
||||||
|
if ! command -v kubectl &> /dev/null; then
|
||||||
|
echo -e "${RED}Error: kubectl is not installed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if Azure CLI is installed
|
||||||
|
if ! command -v az &> /dev/null; then
|
||||||
|
echo -e "${RED}Error: Azure CLI is not installed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Login to Azure (if not already logged in)
|
||||||
|
echo -e "${YELLOW}Checking Azure login status...${NC}"
|
||||||
|
if ! az account show &> /dev/null; then
|
||||||
|
echo -e "${YELLOW}Please login to Azure...${NC}"
|
||||||
|
az login
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get AKS credentials
|
||||||
|
echo -e "${YELLOW}Getting AKS credentials...${NC}"
|
||||||
|
az aks get-credentials --resource-group ${RESOURCE_GROUP} --name ${AKS_NAME} --overwrite-existing
|
||||||
|
|
||||||
|
# Verify connection to cluster
|
||||||
|
echo -e "${YELLOW}Verifying connection to Kubernetes cluster...${NC}"
|
||||||
|
if ! kubectl cluster-info &> /dev/null; then
|
||||||
|
echo -e "${RED}Error: Cannot connect to Kubernetes cluster${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Successfully connected to ${AKS_NAME}${NC}"
|
||||||
|
|
||||||
|
# Create namespace if it doesn't exist
|
||||||
|
echo -e "${YELLOW}Creating namespace '${NAMESPACE}'...${NC}"
|
||||||
|
kubectl apply -f ${SCRIPT_DIR}/namespace.yaml
|
||||||
|
echo -e "${GREEN}✓ Namespace created/verified${NC}"
|
||||||
|
|
||||||
|
# Apply ConfigMaps
|
||||||
|
echo -e "${YELLOW}Applying ConfigMaps...${NC}"
|
||||||
|
kubectl apply -f ${SCRIPT_DIR}/configmap.yaml
|
||||||
|
echo -e "${GREEN}✓ ConfigMaps applied${NC}"
|
||||||
|
|
||||||
|
# Check if secrets exist
|
||||||
|
echo -e "${YELLOW}Checking for secrets...${NC}"
|
||||||
|
if ! kubectl get secret db-secret -n ${NAMESPACE} &> /dev/null || \
|
||||||
|
! kubectl get secret azure-secret -n ${NAMESPACE} &> /dev/null || \
|
||||||
|
! kubectl get secret mail-secret -n ${NAMESPACE} &> /dev/null; then
|
||||||
|
echo -e "${RED}Warning: One or more secrets are missing!${NC}"
|
||||||
|
echo -e "${YELLOW}Please create secrets using secret-template.yaml as reference${NC}"
|
||||||
|
echo -e "${YELLOW}Example:${NC}"
|
||||||
|
echo -e " kubectl create secret generic db-secret -n ${NAMESPACE} \\"
|
||||||
|
echo -e " --from-literal=host=<DB_HOST> \\"
|
||||||
|
echo -e " --from-literal=username=<DB_USERNAME> \\"
|
||||||
|
echo -e " --from-literal=password=<DB_PASSWORD>"
|
||||||
|
echo ""
|
||||||
|
read -p "Do you want to continue without secrets? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo -e "${RED}Deployment cancelled${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configure ACR integration
|
||||||
|
echo -e "${YELLOW}Configuring ACR integration...${NC}"
|
||||||
|
az aks update -n ${AKS_NAME} -g ${RESOURCE_GROUP} --attach-acr ${ACR_NAME}
|
||||||
|
echo -e "${GREEN}✓ ACR integration configured${NC}"
|
||||||
|
|
||||||
|
# Deploy services
|
||||||
|
echo -e "${YELLOW}Deploying User Service...${NC}"
|
||||||
|
kubectl apply -f ${SCRIPT_DIR}/user-service.yaml
|
||||||
|
echo -e "${GREEN}✓ User Service deployed${NC}"
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Deploying Notification Service...${NC}"
|
||||||
|
kubectl apply -f ${SCRIPT_DIR}/notification-service.yaml
|
||||||
|
echo -e "${GREEN}✓ Notification Service deployed${NC}"
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Deploying Meeting Service...${NC}"
|
||||||
|
kubectl apply -f ${SCRIPT_DIR}/meeting-service.yaml
|
||||||
|
echo -e "${GREEN}✓ Meeting Service deployed${NC}"
|
||||||
|
|
||||||
|
# Wait for deployments to be ready
|
||||||
|
echo -e "${YELLOW}Waiting for deployments to be ready...${NC}"
|
||||||
|
kubectl wait --for=condition=available --timeout=300s \
|
||||||
|
deployment/user-service \
|
||||||
|
deployment/notification-service \
|
||||||
|
deployment/meeting-service \
|
||||||
|
-n ${NAMESPACE}
|
||||||
|
|
||||||
|
# Show deployment status
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
|
echo -e "${GREEN}Deployment Status${NC}"
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
|
kubectl get deployments -n ${NAMESPACE}
|
||||||
|
echo ""
|
||||||
|
kubectl get pods -n ${NAMESPACE}
|
||||||
|
echo ""
|
||||||
|
kubectl get services -n ${NAMESPACE}
|
||||||
|
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
|
echo -e "${GREEN}Deployment Completed Successfully!${NC}"
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Useful commands:${NC}"
|
||||||
|
echo -e " View logs: kubectl logs -f deployment/<service-name> -n ${NAMESPACE}"
|
||||||
|
echo -e " View pods: kubectl get pods -n ${NAMESPACE}"
|
||||||
|
echo -e " Describe pod: kubectl describe pod <pod-name> -n ${NAMESPACE}"
|
||||||
|
echo -e " Port forward: kubectl port-forward svc/<service-name> <local-port>:<service-port> -n ${NAMESPACE}"
|
||||||
112
deploy/k8s/backend/meeting-service.yaml
Normal file
112
deploy/k8s/backend/meeting-service.yaml
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
---
|
||||||
|
# Meeting Service Deployment
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: meeting-service
|
||||||
|
namespace: hgzero
|
||||||
|
labels:
|
||||||
|
app: meeting-service
|
||||||
|
tier: backend
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: meeting-service
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: meeting-service
|
||||||
|
tier: backend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: meeting-service
|
||||||
|
image: acrdigitalgarage02.azurecr.io/hgzero/meeting-service:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 8081
|
||||||
|
name: http
|
||||||
|
- containerPort: 8082
|
||||||
|
name: websocket
|
||||||
|
env:
|
||||||
|
- name: SPRING_PROFILES_ACTIVE
|
||||||
|
value: "prod"
|
||||||
|
- name: SERVER_PORT
|
||||||
|
value: "8081"
|
||||||
|
- name: DB_HOST
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: db-secret
|
||||||
|
key: host
|
||||||
|
- name: DB_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: db-secret
|
||||||
|
key: username
|
||||||
|
- name: DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: db-secret
|
||||||
|
key: password
|
||||||
|
- name: REDIS_HOST
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: redis-config
|
||||||
|
key: host
|
||||||
|
- name: REDIS_PORT
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: redis-config
|
||||||
|
key: port
|
||||||
|
- name: AZURE_EVENTHUB_CONNECTION_STRING
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: azure-secret
|
||||||
|
key: eventhub-connection-string
|
||||||
|
- name: NOTIFICATION_SERVICE_URL
|
||||||
|
value: "http://notification-service:8082"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 256m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1024m
|
||||||
|
memory: 1024Mi
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/liveness
|
||||||
|
port: 8081
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/readiness
|
||||||
|
port: 8081
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 3
|
||||||
|
---
|
||||||
|
# Meeting Service Service
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: meeting-service
|
||||||
|
namespace: hgzero
|
||||||
|
labels:
|
||||||
|
app: meeting-service
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 8081
|
||||||
|
targetPort: 8081
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
- port: 8082
|
||||||
|
targetPort: 8082
|
||||||
|
protocol: TCP
|
||||||
|
name: websocket
|
||||||
|
selector:
|
||||||
|
app: meeting-service
|
||||||
9
deploy/k8s/backend/namespace.yaml
Normal file
9
deploy/k8s/backend/namespace.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
# Namespace for HGZero application
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: hgzero
|
||||||
|
labels:
|
||||||
|
name: hgzero
|
||||||
|
environment: production
|
||||||
129
deploy/k8s/backend/notification-service.yaml
Normal file
129
deploy/k8s/backend/notification-service.yaml
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
---
|
||||||
|
# Notification Service Deployment
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: notification-service
|
||||||
|
namespace: hgzero
|
||||||
|
labels:
|
||||||
|
app: notification-service
|
||||||
|
tier: backend
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: notification-service
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: notification-service
|
||||||
|
tier: backend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: notification-service
|
||||||
|
image: acrdigitalgarage02.azurecr.io/hgzero/notification-service:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 8082
|
||||||
|
name: http
|
||||||
|
env:
|
||||||
|
- name: SPRING_PROFILES_ACTIVE
|
||||||
|
value: "prod"
|
||||||
|
- name: SERVER_PORT
|
||||||
|
value: "8082"
|
||||||
|
- name: DB_HOST
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: db-secret
|
||||||
|
key: host
|
||||||
|
- name: DB_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: db-secret
|
||||||
|
key: username
|
||||||
|
- name: DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: db-secret
|
||||||
|
key: password
|
||||||
|
- name: REDIS_HOST
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: redis-config
|
||||||
|
key: host
|
||||||
|
- name: REDIS_PORT
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: redis-config
|
||||||
|
key: port
|
||||||
|
- name: AZURE_EVENTHUB_CONNECTION_STRING
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: azure-secret
|
||||||
|
key: eventhub-connection-string
|
||||||
|
- name: AZURE_BLOB_CONNECTION_STRING
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: azure-secret
|
||||||
|
key: blob-connection-string
|
||||||
|
- name: MAIL_HOST
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: mail-config
|
||||||
|
key: host
|
||||||
|
- name: MAIL_PORT
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: mail-config
|
||||||
|
key: port
|
||||||
|
- name: MAIL_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: mail-secret
|
||||||
|
key: username
|
||||||
|
- name: MAIL_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: mail-secret
|
||||||
|
key: password
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 256m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1024m
|
||||||
|
memory: 1024Mi
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/liveness
|
||||||
|
port: 8082
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/readiness
|
||||||
|
port: 8082
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 3
|
||||||
|
---
|
||||||
|
# Notification Service Service
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: notification-service
|
||||||
|
namespace: hgzero
|
||||||
|
labels:
|
||||||
|
app: notification-service
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 8082
|
||||||
|
targetPort: 8082
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: notification-service
|
||||||
36
deploy/k8s/backend/secret-template.yaml
Normal file
36
deploy/k8s/backend/secret-template.yaml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
# Database Secret Template
|
||||||
|
# Note: Replace base64 encoded values with your actual credentials
|
||||||
|
# To encode: echo -n 'your-value' | base64
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: db-secret
|
||||||
|
namespace: hgzero
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
host: <BASE64_ENCODED_DB_HOST>
|
||||||
|
username: <BASE64_ENCODED_DB_USERNAME>
|
||||||
|
password: <BASE64_ENCODED_DB_PASSWORD>
|
||||||
|
---
|
||||||
|
# Azure Secret Template
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: azure-secret
|
||||||
|
namespace: hgzero
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
eventhub-connection-string: <BASE64_ENCODED_EVENTHUB_CONNECTION_STRING>
|
||||||
|
blob-connection-string: <BASE64_ENCODED_BLOB_CONNECTION_STRING>
|
||||||
|
---
|
||||||
|
# Mail Secret Template
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: mail-secret
|
||||||
|
namespace: hgzero
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
username: <BASE64_ENCODED_MAIL_USERNAME>
|
||||||
|
password: <BASE64_ENCODED_MAIL_PASSWORD>
|
||||||
89
deploy/k8s/backend/undeploy.sh
Executable file
89
deploy/k8s/backend/undeploy.sh
Executable file
@ -0,0 +1,89 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# HGZero Backend Services Kubernetes Undeployment Script
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Color codes for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
NAMESPACE="hgzero"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
echo -e "${YELLOW}======================================${NC}"
|
||||||
|
echo -e "${YELLOW}HGZero Backend Services Undeployment${NC}"
|
||||||
|
echo -e "${YELLOW}======================================${NC}"
|
||||||
|
|
||||||
|
# Check if kubectl is installed
|
||||||
|
if ! command -v kubectl &> /dev/null; then
|
||||||
|
echo -e "${RED}Error: kubectl is not installed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify connection to cluster
|
||||||
|
echo -e "${YELLOW}Verifying connection to Kubernetes cluster...${NC}"
|
||||||
|
if ! kubectl cluster-info &> /dev/null; then
|
||||||
|
echo -e "${RED}Error: Cannot connect to Kubernetes cluster${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if namespace exists
|
||||||
|
if ! kubectl get namespace ${NAMESPACE} &> /dev/null; then
|
||||||
|
echo -e "${YELLOW}Namespace '${NAMESPACE}' does not exist. Nothing to undeploy.${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}This will delete all services in namespace '${NAMESPACE}'${NC}"
|
||||||
|
read -p "Are you sure you want to continue? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo -e "${YELLOW}Undeployment cancelled${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Delete services
|
||||||
|
echo -e "${YELLOW}Deleting Meeting Service...${NC}"
|
||||||
|
kubectl delete -f ${SCRIPT_DIR}/meeting-service.yaml --ignore-not-found=true
|
||||||
|
echo -e "${GREEN}✓ Meeting Service deleted${NC}"
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Deleting Notification Service...${NC}"
|
||||||
|
kubectl delete -f ${SCRIPT_DIR}/notification-service.yaml --ignore-not-found=true
|
||||||
|
echo -e "${GREEN}✓ Notification Service deleted${NC}"
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Deleting User Service...${NC}"
|
||||||
|
kubectl delete -f ${SCRIPT_DIR}/user-service.yaml --ignore-not-found=true
|
||||||
|
echo -e "${GREEN}✓ User Service deleted${NC}"
|
||||||
|
|
||||||
|
# Delete ConfigMaps
|
||||||
|
echo -e "${YELLOW}Deleting ConfigMaps...${NC}"
|
||||||
|
kubectl delete -f ${SCRIPT_DIR}/configmap.yaml --ignore-not-found=true
|
||||||
|
echo -e "${GREEN}✓ ConfigMaps deleted${NC}"
|
||||||
|
|
||||||
|
# Ask about secrets deletion
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Do you want to delete secrets as well?${NC}"
|
||||||
|
echo -e "${RED}Warning: This will delete all database and Azure credentials${NC}"
|
||||||
|
read -p "Delete secrets? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
kubectl delete secret db-secret azure-secret mail-secret -n ${NAMESPACE} --ignore-not-found=true
|
||||||
|
echo -e "${GREEN}✓ Secrets deleted${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ask about namespace deletion
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Do you want to delete the namespace '${NAMESPACE}'?${NC}"
|
||||||
|
read -p "Delete namespace? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
kubectl delete namespace ${NAMESPACE}
|
||||||
|
echo -e "${GREEN}✓ Namespace deleted${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
|
echo -e "${GREEN}Undeployment Completed${NC}"
|
||||||
|
echo -e "${GREEN}======================================${NC}"
|
||||||
102
deploy/k8s/backend/user-service.yaml
Normal file
102
deploy/k8s/backend/user-service.yaml
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
---
|
||||||
|
# User Service Deployment
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: user-service
|
||||||
|
namespace: hgzero
|
||||||
|
labels:
|
||||||
|
app: user-service
|
||||||
|
tier: backend
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: user-service
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: user-service
|
||||||
|
tier: backend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: user-service
|
||||||
|
image: acrdigitalgarage02.azurecr.io/hgzero/user-service:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
env:
|
||||||
|
- name: SPRING_PROFILES_ACTIVE
|
||||||
|
value: "prod"
|
||||||
|
- name: DB_HOST
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: db-secret
|
||||||
|
key: host
|
||||||
|
- name: DB_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: db-secret
|
||||||
|
key: username
|
||||||
|
- name: DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: db-secret
|
||||||
|
key: password
|
||||||
|
- name: REDIS_HOST
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: redis-config
|
||||||
|
key: host
|
||||||
|
- name: REDIS_PORT
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: redis-config
|
||||||
|
key: port
|
||||||
|
- name: AZURE_EVENTHUB_CONNECTION_STRING
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: azure-secret
|
||||||
|
key: eventhub-connection-string
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 256m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1024m
|
||||||
|
memory: 1024Mi
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/liveness
|
||||||
|
port: 8080
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /actuator/health/readiness
|
||||||
|
port: 8080
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 3
|
||||||
|
---
|
||||||
|
# User Service Service
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: user-service
|
||||||
|
namespace: hgzero
|
||||||
|
labels:
|
||||||
|
app: user-service
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
targetPort: 8080
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: user-service
|
||||||
Loading…
x
Reference in New Issue
Block a user