Compare commits
3 Commits
70fea2e477
...
1e257d7093
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e257d7093 | |||
|
|
03cccb685e | ||
|
|
24e9e369b2 |
@@ -1,19 +1,16 @@
|
||||
# Gitea Actions Workflow - vexplor 자동 배포
|
||||
# Gitea Actions Workflow - vexplor 이미지 빌드 & Harbor Push
|
||||
#
|
||||
# 환경 변수:
|
||||
# - GITEA_DOMAIN: g.wace.me
|
||||
# - HARBOR_REGISTRY: harbor.wace.me
|
||||
# - K8S_NAMESPACE: vexplor
|
||||
# 동작 방식:
|
||||
# 1. main 브랜치에 push 시 자동 실행
|
||||
# 2. Docker 이미지 빌드 (Backend, Frontend)
|
||||
# 3. Harbor 레지스트리에 Push
|
||||
# 4. 공장 서버의 Watchtower가 새 이미지 감지 후 자동 업데이트
|
||||
#
|
||||
# 필수 Secrets (Repository Settings > Secrets):
|
||||
# - HARBOR_USERNAME: Harbor 사용자명
|
||||
# - HARBOR_PASSWORD: Harbor 비밀번호
|
||||
# - K8S_SSH_KEY: base64로 인코딩된 SSH 비밀키 (쿠버네티스 서버 접속용)
|
||||
#
|
||||
# Application Secrets:
|
||||
# - k8s/vexplor-secret.yaml 파일에서 관리
|
||||
|
||||
name: Deploy vexplor
|
||||
name: Build and Push Images
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -24,44 +21,35 @@ on:
|
||||
- "backend-node/**"
|
||||
- "frontend/**"
|
||||
- "docker/**"
|
||||
- "k8s/**"
|
||||
- ".gitea/workflows/deploy.yml"
|
||||
workflow_dispatch:
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- "deploy/**"
|
||||
- "k8s/**"
|
||||
workflow_dispatch: # 수동 실행도 가능
|
||||
|
||||
env:
|
||||
GITEA_DOMAIN: g.wace.me
|
||||
HARBOR_REGISTRY: localhost:5001
|
||||
HARBOR_REGISTRY_K8S: harbor.wace.me
|
||||
HARBOR_REGISTRY_EXTERNAL: harbor.wace.me
|
||||
HARBOR_PROJECT: speefox_vexplor
|
||||
K8S_NAMESPACE: vexplor
|
||||
|
||||
# 쿠버네티스 서버 SSH 접속 정보
|
||||
K8S_SSH_HOST: 112.168.212.142
|
||||
K8S_SSH_PORT: 22
|
||||
K8S_SSH_USER: wace
|
||||
|
||||
# Frontend 빌드 환경 변수
|
||||
NEXT_PUBLIC_API_URL: "https://api.vexplor.com/api"
|
||||
NEXT_PUBLIC_ENV: "production"
|
||||
INTERNAL_API_URL: "http://vexplor-backend-service:3001"
|
||||
|
||||
# Frontend 설정
|
||||
FRONTEND_IMAGE_NAME: vexplor-frontend
|
||||
FRONTEND_DEPLOYMENT_NAME: vexplor-frontend
|
||||
FRONTEND_CONTAINER_NAME: vexplor-frontend
|
||||
FRONTEND_BUILD_CONTEXT: frontend
|
||||
FRONTEND_DOCKERFILE_PATH: docker/deploy/frontend.Dockerfile
|
||||
|
||||
# Backend 설정
|
||||
BACKEND_IMAGE_NAME: vexplor-backend
|
||||
BACKEND_DEPLOYMENT_NAME: vexplor-backend
|
||||
BACKEND_CONTAINER_NAME: vexplor-backend
|
||||
BACKEND_BUILD_CONTEXT: backend-node
|
||||
BACKEND_DOCKERFILE_PATH: docker/deploy/backend.Dockerfile
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
@@ -79,7 +67,7 @@ jobs:
|
||||
run: |
|
||||
echo "필수 도구 설치 중..."
|
||||
apt-get update -qq
|
||||
apt-get install -y git curl ca-certificates gnupg openssh-client
|
||||
apt-get install -y git curl ca-certificates gnupg
|
||||
|
||||
# Docker 클라이언트 설치
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
@@ -94,7 +82,6 @@ jobs:
|
||||
|
||||
echo "설치 완료:"
|
||||
git --version
|
||||
ssh -V
|
||||
docker --version
|
||||
|
||||
export DOCKER_HOST=unix:///var/run/docker.sock
|
||||
@@ -120,13 +107,13 @@ jobs:
|
||||
|
||||
# Frontend 이미지
|
||||
echo "FRONTEND_FULL_IMAGE=${HARBOR_REGISTRY}/${HARBOR_PROJECT}/${FRONTEND_IMAGE_NAME}" >> $GITHUB_ENV
|
||||
echo "FRONTEND_FULL_IMAGE_K8S=${HARBOR_REGISTRY_K8S}/${HARBOR_PROJECT}/${FRONTEND_IMAGE_NAME}" >> $GITHUB_ENV
|
||||
|
||||
# Backend 이미지
|
||||
echo "BACKEND_FULL_IMAGE=${HARBOR_REGISTRY}/${HARBOR_PROJECT}/${BACKEND_IMAGE_NAME}" >> $GITHUB_ENV
|
||||
echo "BACKEND_FULL_IMAGE_K8S=${HARBOR_REGISTRY_K8S}/${HARBOR_PROJECT}/${BACKEND_IMAGE_NAME}" >> $GITHUB_ENV
|
||||
|
||||
echo "=========================================="
|
||||
echo "빌드 태그: ${IMAGE_TAG}"
|
||||
echo "=========================================="
|
||||
|
||||
# Harbor 로그인
|
||||
- name: Login to Harbor
|
||||
@@ -144,7 +131,9 @@ jobs:
|
||||
# Backend 빌드 및 푸시
|
||||
- name: Build and Push Backend image
|
||||
run: |
|
||||
echo "Backend 이미지 빌드 및 푸시..."
|
||||
echo "=========================================="
|
||||
echo "Backend 이미지 빌드 시작..."
|
||||
echo "=========================================="
|
||||
export DOCKER_HOST=unix:///var/run/docker.sock
|
||||
cd /workspace/source
|
||||
|
||||
@@ -154,14 +143,22 @@ jobs:
|
||||
-f ${BACKEND_DOCKERFILE_PATH} \
|
||||
${BACKEND_BUILD_CONTEXT}
|
||||
|
||||
echo "Backend 이미지 푸시..."
|
||||
docker push ${BACKEND_FULL_IMAGE}:${IMAGE_TAG}
|
||||
docker push ${BACKEND_FULL_IMAGE}:latest
|
||||
echo "Backend 푸시 완료"
|
||||
|
||||
echo "=========================================="
|
||||
echo "Backend 푸시 완료!"
|
||||
echo " - ${BACKEND_FULL_IMAGE}:${IMAGE_TAG}"
|
||||
echo " - ${BACKEND_FULL_IMAGE}:latest"
|
||||
echo "=========================================="
|
||||
|
||||
# Frontend 빌드 및 푸시
|
||||
- name: Build and Push Frontend image
|
||||
run: |
|
||||
echo "Frontend 이미지 빌드 및 푸시..."
|
||||
echo "=========================================="
|
||||
echo "Frontend 이미지 빌드 시작..."
|
||||
echo "=========================================="
|
||||
export DOCKER_HOST=unix:///var/run/docker.sock
|
||||
cd /workspace/source
|
||||
|
||||
@@ -176,175 +173,40 @@ jobs:
|
||||
--build-arg NEXT_PUBLIC_API_URL="${NEXT_PUBLIC_API_URL}" \
|
||||
${FRONTEND_BUILD_CONTEXT}
|
||||
|
||||
echo "Frontend 이미지 푸시..."
|
||||
docker push ${FRONTEND_FULL_IMAGE}:${IMAGE_TAG}
|
||||
docker push ${FRONTEND_FULL_IMAGE}:latest
|
||||
echo "Frontend 푸시 완료"
|
||||
|
||||
echo "=========================================="
|
||||
echo "Frontend 푸시 완료!"
|
||||
echo " - ${FRONTEND_FULL_IMAGE}:${IMAGE_TAG}"
|
||||
echo " - ${FRONTEND_FULL_IMAGE}:latest"
|
||||
echo "=========================================="
|
||||
|
||||
# SSH 키 설정 (쿠버네티스 서버 접속용)
|
||||
- name: Setup SSH Key
|
||||
env:
|
||||
SSH_KEY_CONTENT: ${{ secrets.K8S_SSH_KEY }}
|
||||
run: |
|
||||
echo "SSH 키 설정..."
|
||||
|
||||
if [ -z "${SSH_KEY_CONTENT}" ]; then
|
||||
echo "K8S_SSH_KEY secret이 설정되지 않았습니다!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p ~/.ssh
|
||||
echo "${SSH_KEY_CONTENT}" | base64 -d > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
|
||||
# known_hosts에 쿠버네티스 서버 추가
|
||||
ssh-keyscan -p ${K8S_SSH_PORT} ${K8S_SSH_HOST} >> ~/.ssh/known_hosts 2>/dev/null
|
||||
|
||||
# SSH 연결 테스트
|
||||
echo "SSH 연결 테스트..."
|
||||
ssh -o StrictHostKeyChecking=no -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} "echo 'SSH 연결 성공'"
|
||||
echo "SSH 키 설정 완료"
|
||||
|
||||
# k8s 매니페스트 파일을 쿠버네티스 서버로 전송
|
||||
- name: Transfer k8s manifests
|
||||
run: |
|
||||
echo "k8s 매니페스트 파일 전송..."
|
||||
cd /workspace/source
|
||||
|
||||
# 쿠버네티스 서버에 디렉토리 생성
|
||||
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} "mkdir -p ~/vexplor-deploy/k8s"
|
||||
|
||||
# k8s 파일 전송
|
||||
scp -P ${K8S_SSH_PORT} -r k8s/* ${K8S_SSH_USER}@${K8S_SSH_HOST}:~/vexplor-deploy/k8s/
|
||||
|
||||
echo "매니페스트 파일 전송 완료"
|
||||
|
||||
# Kubernetes 배포 (SSH를 통해 원격 실행)
|
||||
- name: Deploy to Kubernetes
|
||||
env:
|
||||
HARBOR_USER: ${{ secrets.HARBOR_USERNAME }}
|
||||
HARBOR_PASS: ${{ secrets.HARBOR_PASSWORD }}
|
||||
run: |
|
||||
echo "Kubernetes 배포 시작 (SSH 원격 실행)..."
|
||||
|
||||
# SSH를 통해 쿠버네티스 서버에서 kubectl 명령 실행
|
||||
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} << 'DEPLOY_SCRIPT'
|
||||
set -e
|
||||
cd ~/vexplor-deploy
|
||||
|
||||
echo "네임스페이스 확인..."
|
||||
kubectl apply -f k8s/namespace.yaml
|
||||
|
||||
echo "ConfigMap 적용..."
|
||||
kubectl apply -f k8s/vexplor-config.yaml -n vexplor
|
||||
|
||||
# Secret 적용 (존재하는 경우에만)
|
||||
if [ -f k8s/vexplor-secret.yaml ]; then
|
||||
echo "Secret 적용..."
|
||||
kubectl apply -f k8s/vexplor-secret.yaml -n vexplor
|
||||
fi
|
||||
|
||||
echo "네임스페이스 및 ConfigMap 적용 완료"
|
||||
DEPLOY_SCRIPT
|
||||
|
||||
# Harbor Registry Secret 생성 (별도로 처리 - 환경변수 사용)
|
||||
echo "Harbor Registry Secret 확인..."
|
||||
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} "kubectl get secret harbor-registry -n vexplor" > /dev/null 2>&1 || \
|
||||
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} "kubectl create secret docker-registry harbor-registry \
|
||||
--docker-server=${HARBOR_REGISTRY_K8S} \
|
||||
--docker-username=${HARBOR_USER} \
|
||||
--docker-password='${HARBOR_PASS}' \
|
||||
-n vexplor"
|
||||
echo "Harbor Registry Secret 확인 완료"
|
||||
|
||||
# Backend 배포
|
||||
echo "Backend 배포..."
|
||||
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} << BACKEND_DEPLOY
|
||||
set -e
|
||||
cd ~/vexplor-deploy
|
||||
kubectl apply -f k8s/vexplor-backend-deployment.yaml -n vexplor
|
||||
|
||||
echo "Backend 이미지 업데이트..."
|
||||
kubectl set image deployment/${BACKEND_DEPLOYMENT_NAME} \
|
||||
${BACKEND_CONTAINER_NAME}=${HARBOR_REGISTRY_K8S}/${HARBOR_PROJECT}/${BACKEND_IMAGE_NAME}:latest \
|
||||
-n vexplor || true
|
||||
kubectl rollout restart deployment/${BACKEND_DEPLOYMENT_NAME} -n vexplor
|
||||
|
||||
echo "Backend Rolling Update 진행 중..."
|
||||
kubectl rollout status deployment/${BACKEND_DEPLOYMENT_NAME} -n vexplor --timeout=5m
|
||||
echo "Backend 배포 완료"
|
||||
BACKEND_DEPLOY
|
||||
|
||||
# Frontend 배포
|
||||
echo "Frontend 배포..."
|
||||
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} << FRONTEND_DEPLOY
|
||||
set -e
|
||||
cd ~/vexplor-deploy
|
||||
kubectl apply -f k8s/vexplor-frontend-deployment.yaml -n vexplor
|
||||
|
||||
echo "Frontend 이미지 업데이트..."
|
||||
kubectl set image deployment/${FRONTEND_DEPLOYMENT_NAME} \
|
||||
${FRONTEND_CONTAINER_NAME}=${HARBOR_REGISTRY_K8S}/${HARBOR_PROJECT}/${FRONTEND_IMAGE_NAME}:latest \
|
||||
-n vexplor || true
|
||||
kubectl rollout restart deployment/${FRONTEND_DEPLOYMENT_NAME} -n vexplor
|
||||
|
||||
echo "Frontend Rolling Update 진행 중..."
|
||||
kubectl rollout status deployment/${FRONTEND_DEPLOYMENT_NAME} -n vexplor --timeout=5m
|
||||
echo "Frontend 배포 완료"
|
||||
FRONTEND_DEPLOY
|
||||
|
||||
# Ingress 배포
|
||||
echo "Ingress 배포..."
|
||||
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} "cd ~/vexplor-deploy && kubectl apply -f k8s/vexplor-ingress.yaml -n vexplor"
|
||||
|
||||
echo "전체 배포 완료!"
|
||||
|
||||
# 배포 검증
|
||||
- name: Verify deployment
|
||||
run: |
|
||||
echo "배포 검증..."
|
||||
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} << 'VERIFY_SCRIPT'
|
||||
echo ""
|
||||
echo "Backend 상태:"
|
||||
kubectl get deployment vexplor-backend -n vexplor
|
||||
kubectl get pods -l app=vexplor-backend -n vexplor
|
||||
echo ""
|
||||
echo "Frontend 상태:"
|
||||
kubectl get deployment vexplor-frontend -n vexplor
|
||||
kubectl get pods -l app=vexplor-frontend -n vexplor
|
||||
echo ""
|
||||
echo "Services:"
|
||||
kubectl get svc -n vexplor
|
||||
echo ""
|
||||
echo "Ingress:"
|
||||
kubectl get ingress -n vexplor
|
||||
echo ""
|
||||
echo "검증 완료"
|
||||
VERIFY_SCRIPT
|
||||
|
||||
# 배포 요약
|
||||
- name: Deployment summary
|
||||
# 빌드 완료 요약
|
||||
- name: Build summary
|
||||
if: success()
|
||||
run: |
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "배포가 성공적으로 완료되었습니다!"
|
||||
echo " 이미지 빌드 & Push 완료!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "빌드 버전: ${IMAGE_TAG}"
|
||||
echo "Frontend: https://v1.vexplor.com"
|
||||
echo "Backend API: https://api.vexplor.com"
|
||||
echo ""
|
||||
echo "푸시된 이미지:"
|
||||
echo " - Backend: ${HARBOR_REGISTRY_EXTERNAL}/${HARBOR_PROJECT}/${BACKEND_IMAGE_NAME}:latest"
|
||||
echo " - Frontend: ${HARBOR_REGISTRY_EXTERNAL}/${HARBOR_PROJECT}/${FRONTEND_IMAGE_NAME}:latest"
|
||||
echo ""
|
||||
echo "다음 단계:"
|
||||
echo " - 공장 서버의 Watchtower가 자동으로 새 이미지를 감지합니다"
|
||||
echo " - 또는 수동 업데이트: docker compose pull && docker compose up -d"
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
|
||||
# 실패 시 롤백
|
||||
- name: Rollback on failure
|
||||
if: failure()
|
||||
run: |
|
||||
echo "배포 실패! 이전 버전으로 롤백..."
|
||||
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} "kubectl rollout undo deployment/vexplor-backend -n vexplor" || true
|
||||
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} "kubectl rollout undo deployment/vexplor-frontend -n vexplor" || true
|
||||
|
||||
# Harbor 로그아웃
|
||||
- name: Logout from Harbor
|
||||
if: always()
|
||||
run: |
|
||||
export DOCKER_HOST=unix:///var/run/docker.sock
|
||||
docker logout ${HARBOR_REGISTRY} || true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user