Refactor deploy workflow to use SSH for k8s operations #2

Merged
geonhee merged 1 commits from add/kubernetes into main 2025-12-22 08:39:51 +00:00

View File

@@ -8,7 +8,7 @@
# 필수 Secrets (Repository Settings > Secrets):
# - HARBOR_USERNAME: Harbor 사용자명
# - HARBOR_PASSWORD: Harbor 비밀번호
# - KUBECONFIG: base64로 인코딩된 Kubernetes config
# - K8S_SSH_KEY: base64로 인코딩된 SSH 비밀키 (쿠버네티스 서버 접속용)
#
# Application Secrets:
# - k8s/vexplor-secret.yaml 파일에서 관리
@@ -31,10 +31,15 @@ on:
env:
GITEA_DOMAIN: g.wace.me
HARBOR_REGISTRY: localhost:5001
HARBOR_REGISTRY_K8S: 192.168.1.100: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"
@@ -74,12 +79,7 @@ jobs:
run: |
echo "필수 도구 설치 중..."
apt-get update -qq
apt-get install -y git curl ca-certificates gnupg
# kubectl 설치
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
mv kubectl /usr/local/bin/
apt-get install -y git curl ca-certificates gnupg openssh-client
# Docker 클라이언트 설치
install -m 0755 -d /etc/apt/keyrings
@@ -94,7 +94,7 @@ jobs:
echo "설치 완료:"
git --version
kubectl version --client
ssh -V
docker --version
export DOCKER_HOST=unix:///var/run/docker.sock
@@ -180,100 +180,121 @@ jobs:
docker push ${FRONTEND_FULL_IMAGE}:latest
echo "Frontend 푸시 완료"
# Kubernetes 설정
- name: Setup Kubernetes config
# SSH 키 설정 (쿠버네티스 서버 접속용)
- name: Setup SSH Key
env:
KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }}
SSH_KEY_CONTENT: ${{ secrets.K8S_SSH_KEY }}
run: |
echo "Kubernetes 설정..."
echo "SSH 키 설정..."
if [ -z "${KUBECONFIG_CONTENT}" ]; then
echo "KUBECONFIG secret이 설정되지 않았습니다!"
if [ -z "${SSH_KEY_CONTENT}" ]; then
echo "K8S_SSH_KEY secret이 설정되지 않았습니다!"
exit 1
fi
mkdir -p ~/.kube
echo "${KUBECONFIG_CONTENT}" | base64 -d > ~/.kube/config
chmod 600 ~/.kube/config
mkdir -p ~/.ssh
echo "${SSH_KEY_CONTENT}" | base64 -d > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
if [ ! -s ~/.kube/config ]; then
echo "kubeconfig 파일이 비어있습니다"
exit 1
fi
# known_hosts에 쿠버네티스 서버 추가
ssh-keyscan -p ${K8S_SSH_PORT} ${K8S_SSH_HOST} >> ~/.ssh/known_hosts 2>/dev/null
echo "kubeconfig 파일 생성 완료"
kubectl cluster-info > /dev/null 2>&1 && echo "Kubernetes 클러스터 연결 성공"
# SSH 연결 테스트
echo "SSH 연결 테스트..."
ssh -o StrictHostKeyChecking=no -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} "echo 'SSH 연결 성공'"
echo "SSH 키 설정 완료"
# Kubernetes 배포
- name: Deploy to Kubernetes
# k8s 매니페스트 파일을 쿠버네티스 서버로 전송
- name: Transfer k8s manifests
run: |
echo "Kubernetes 배포 시작..."
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
# ConfigMap 적용
echo "ConfigMap 적용..."
kubectl apply -f k8s/vexplor-config.yaml -n ${K8S_NAMESPACE}
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 ${K8S_NAMESPACE}
kubectl apply -f k8s/vexplor-secret.yaml -n vexplor
fi
# Harbor Registry Secret 생성 (없을 때만)
echo "네임스페이스 및 ConfigMap 적용 완료"
DEPLOY_SCRIPT
# Harbor Registry Secret 생성 (별도로 처리 - 환경변수 사용)
echo "Harbor Registry Secret 확인..."
if ! kubectl get secret harbor-registry -n ${K8S_NAMESPACE} > /dev/null 2>&1; then
echo "Harbor Registry Secret 생성 중..."
kubectl create secret docker-registry harbor-registry \
--docker-server=${HARBOR_REGISTRY_K8S} \
--docker-username=${{ secrets.HARBOR_USERNAME }} \
--docker-password=${{ secrets.HARBOR_PASSWORD }} \
-n ${K8S_NAMESPACE}
echo "Harbor Registry Secret 생성 완료"
else
echo "Harbor Registry Secret 이미 존재"
fi
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 배포..."
kubectl apply -f k8s/vexplor-backend-deployment.yaml -n ${K8S_NAMESPACE}
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
if kubectl get deployment ${BACKEND_DEPLOYMENT_NAME} -n ${K8S_NAMESPACE} > /dev/null 2>&1; then
echo "Backend 이미지 업데이트..."
kubectl set image deployment/${BACKEND_DEPLOYMENT_NAME} \
${BACKEND_CONTAINER_NAME}=${BACKEND_FULL_IMAGE_K8S}:latest \
-n ${K8S_NAMESPACE}
kubectl rollout restart deployment/${BACKEND_DEPLOYMENT_NAME} -n ${K8S_NAMESPACE}
fi
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 ${K8S_NAMESPACE} --timeout=5m
kubectl rollout status deployment/${BACKEND_DEPLOYMENT_NAME} -n vexplor --timeout=5m
echo "Backend 배포 완료"
BACKEND_DEPLOY
# Frontend 배포
echo "Frontend 배포..."
kubectl apply -f k8s/vexplor-frontend-deployment.yaml -n ${K8S_NAMESPACE}
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
if kubectl get deployment ${FRONTEND_DEPLOYMENT_NAME} -n ${K8S_NAMESPACE} > /dev/null 2>&1; then
echo "Frontend 이미지 업데이트..."
kubectl set image deployment/${FRONTEND_DEPLOYMENT_NAME} \
${FRONTEND_CONTAINER_NAME}=${FRONTEND_FULL_IMAGE_K8S}:latest \
-n ${K8S_NAMESPACE}
kubectl rollout restart deployment/${FRONTEND_DEPLOYMENT_NAME} -n ${K8S_NAMESPACE}
fi
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 ${K8S_NAMESPACE} --timeout=5m
kubectl rollout status deployment/${FRONTEND_DEPLOYMENT_NAME} -n vexplor --timeout=5m
echo "Frontend 배포 완료"
FRONTEND_DEPLOY
# Ingress 배포
echo "Ingress 배포..."
kubectl apply -f k8s/vexplor-ingress.yaml -n ${K8S_NAMESPACE}
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} "cd ~/vexplor-deploy && kubectl apply -f k8s/vexplor-ingress.yaml -n vexplor"
echo "전체 배포 완료!"
@@ -281,22 +302,24 @@ jobs:
- name: Verify deployment
run: |
echo "배포 검증..."
ssh -p ${K8S_SSH_PORT} ${K8S_SSH_USER}@${K8S_SSH_HOST} << 'VERIFY_SCRIPT'
echo ""
echo "Backend 상태:"
kubectl get deployment ${BACKEND_DEPLOYMENT_NAME} -n ${K8S_NAMESPACE}
kubectl get pods -l app=${BACKEND_DEPLOYMENT_NAME} -n ${K8S_NAMESPACE}
kubectl get deployment vexplor-backend -n vexplor
kubectl get pods -l app=vexplor-backend -n vexplor
echo ""
echo "Frontend 상태:"
kubectl get deployment ${FRONTEND_DEPLOYMENT_NAME} -n ${K8S_NAMESPACE}
kubectl get pods -l app=${FRONTEND_DEPLOYMENT_NAME} -n ${K8S_NAMESPACE}
kubectl get deployment vexplor-frontend -n vexplor
kubectl get pods -l app=vexplor-frontend -n vexplor
echo ""
echo "Services:"
kubectl get svc -n ${K8S_NAMESPACE}
kubectl get svc -n vexplor
echo ""
echo "Ingress:"
kubectl get ingress -n ${K8S_NAMESPACE}
kubectl get ingress -n vexplor
echo ""
echo "검증 완료"
VERIFY_SCRIPT
# 배포 요약
- name: Deployment summary
@@ -315,8 +338,8 @@ jobs:
if: failure()
run: |
echo "배포 실패! 이전 버전으로 롤백..."
kubectl rollout undo deployment/${BACKEND_DEPLOYMENT_NAME} -n ${K8S_NAMESPACE} || true
kubectl rollout undo deployment/${FRONTEND_DEPLOYMENT_NAME} -n ${K8S_NAMESPACE} || true
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