name: Build & Deploy to K8s on: push: branches: - main - gbpark-node env: REGISTRY: localhost:5000 PROJECT: invyone jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set commit SHA run: echo "SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_ENV # ---- Backend Spring ---- - name: Build backend-spring run: | docker build -t ${{ env.REGISTRY }}/${{ env.PROJECT }}/backend-spring:${{ env.SHORT_SHA }} \ -f docker/deploy/backend-spring.Dockerfile \ backend-spring/ # ---- Frontend ---- - name: Build frontend run: | docker build -t ${{ env.REGISTRY }}/${{ env.PROJECT }}/frontend:${{ env.SHORT_SHA }} \ --build-arg GIT_SHA=${{ env.SHORT_SHA }} \ -f docker/deploy/frontend.Dockerfile \ frontend/ # ---- Push to Registry ---- - name: Push images run: | docker push ${{ env.REGISTRY }}/${{ env.PROJECT }}/backend-spring:${{ env.SHORT_SHA }} docker push ${{ env.REGISTRY }}/${{ env.PROJECT }}/frontend:${{ env.SHORT_SHA }} # latest 태그 docker tag ${{ env.REGISTRY }}/${{ env.PROJECT }}/backend-spring:${{ env.SHORT_SHA }} ${{ env.REGISTRY }}/${{ env.PROJECT }}/backend-spring:latest docker tag ${{ env.REGISTRY }}/${{ env.PROJECT }}/frontend:${{ env.SHORT_SHA }} ${{ env.REGISTRY }}/${{ env.PROJECT }}/frontend:latest docker push ${{ env.REGISTRY }}/${{ env.PROJECT }}/backend-spring:latest docker push ${{ env.REGISTRY }}/${{ env.PROJECT }}/frontend:latest # ---- Deploy to K8s ---- - name: Deploy to Kubernetes run: | # kubectl은 act_runner가 실행되는 호스트에서 접근 가능 export KUBECONFIG=/home/chpark/.kube/config kubectl apply -f k8s/namespace.yaml kubectl apply -f k8s/configmap.yaml kubectl apply -f k8s/pvc.yaml kubectl apply -f k8s/backend-spring.yaml kubectl apply -f k8s/frontend.yaml kubectl apply -f k8s/networkpolicy.yaml # Rolling update with new image tag kubectl set image deployment/backend-spring \ backend-spring=${{ env.REGISTRY }}/${{ env.PROJECT }}/backend-spring:${{ env.SHORT_SHA }} \ -n invyone kubectl set image deployment/frontend \ frontend=${{ env.REGISTRY }}/${{ env.PROJECT }}/frontend:${{ env.SHORT_SHA }} \ -n invyone # Rollout 상태 확인 kubectl rollout status deployment/backend-spring -n invyone --timeout=180s kubectl rollout status deployment/frontend -n invyone --timeout=120s # ---- 실패 시 진단 (pod stdout / events 캡처) ---- - name: Diagnose on failure if: failure() run: | export KUBECONFIG=/home/chpark/.kube/config echo "============================================" echo "=== Pods (-n invyone) ===" echo "============================================" kubectl get pods -n invyone -o wide || true echo echo "============================================" echo "=== Deployment images (현재 어떤 tag 가 떠있는지) ===" echo "============================================" kubectl get deploy -n invyone -o jsonpath='{range .items[*]}{.metadata.name}{": "}{.spec.template.spec.containers[*].image}{"\n"}{end}' || true echo echo "============================================" echo "=== backend-spring describe ===" echo "============================================" kubectl describe deployment backend-spring -n invyone || true kubectl describe pods -n invyone -l app=backend-spring | tail -120 || true echo echo "============================================" echo "=== backend-spring ALL pod logs (per pod) ===" echo "============================================" # deployment/ selector 는 active ReplicaSet 한 개만 봐서 # 새로 뜨다 죽은 ReplicaSet 의 pod 를 놓침. # label selector 로 모든 backend-spring pod 순회. for p in $(kubectl get pods -n invyone -l app=backend-spring -o name 2>/dev/null); do echo "------------------------------" echo "--- $p (current, tail 500) ---" echo "------------------------------" kubectl logs -n invyone $p --all-containers=true --tail=500 2>&1 || true echo echo "--- $p (previous, if exists, tail 500) ---" kubectl logs -n invyone $p --all-containers=true --tail=500 --previous 2>&1 || true echo done echo echo "============================================" echo "=== frontend logs (참고, tail 200) ===" echo "============================================" kubectl logs -n invyone deployment/frontend --tail=200 --all-containers=true || true echo echo "============================================" echo "=== Recent Warning events ===" echo "============================================" kubectl get events -n invyone --sort-by='.lastTimestamp' --field-selector type=Warning 2>/dev/null | tail -30 || true