diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 286cc4d..2be91c8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -19,11 +19,12 @@ jobs: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-2 - - - name: Get current IAM user + + - name: Verify AWS Configuration run: | + echo "πŸ” AWS μ„€μ • 확인..." aws sts get-caller-identity - echo "μœ„ 결과의 'Arn' 값을 EKS μ•‘μ„ΈμŠ€ ν•­λͺ©μ— μž…λ ₯ν•˜μ„Έμš”" + aws eks describe-cluster --name nestjs-cluster --region ap-northeast-2 --query 'cluster.status' - name: Install eksctl run: | @@ -39,35 +40,49 @@ jobs: sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl kubectl version --client + - name: Update kubeconfig and verify connection + run: | + echo "πŸ”§ EKS kubeconfig μ„€μ •..." + aws eks update-kubeconfig --region ap-northeast-2 --name nestjs-cluster + + echo "πŸ” ν΄λŸ¬μŠ€ν„° μ—°κ²° ν…ŒμŠ€νŠΈ..." + kubectl cluster-info + kubectl get nodes -o wide + + echo "πŸ” ν˜„μž¬ context 확인..." + kubectl config current-context + - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 + - name: Verify ECR Repository + run: | + echo "πŸ” ECR 리포지토리 확인..." + aws ecr describe-repositories --repository-names nestjs-app --region ap-northeast-2 || { + echo "❌ ECR 리포지토리가 μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μƒμ„±ν•©λ‹ˆλ‹€..." + aws ecr create-repository --repository-name nestjs-app --region ap-northeast-2 + } + - name: Build, tag, and push image to Amazon ECR env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY: nestjs-app IMAGE_TAG: ${{ github.sha }} run: | + echo "πŸ—οΈ Docker 이미지 λΉŒλ“œ 및 ν‘Έμ‹œ..." docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest - - - name: Update kubeconfig - run: | - # EKS ν΄λŸ¬μŠ€ν„° kubeconfig μ„€μ • - aws eks update-kubeconfig --region ap-northeast-2 --name nestjs-cluster - # μ—°κ²° ν…ŒμŠ€νŠΈ - kubectl cluster-info - kubectl get nodes + echo "βœ… 이미지 ν‘Έμ‹œ μ™„λ£Œ: $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" - name: Install AWS Load Balancer Controller (if not exists) run: | - # Check if AWS Load Balancer Controller exists + echo "πŸ” AWS Load Balancer Controller 확인..." if ! kubectl get deployment -n kube-system aws-load-balancer-controller > /dev/null 2>&1; then - echo "Installing AWS Load Balancer Controller..." + echo "πŸ“¦ AWS Load Balancer Controller μ„€μΉ˜ 쀑..." # Download IAM policy curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.2/docs/install/iam_policy.json @@ -75,7 +90,7 @@ jobs: # Create IAM policy (ignore if exists) aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ - --policy-document file://iam_policy.json || true + --policy-document file://iam_policy.json || echo "IAM 정책이 이미 μ‘΄μž¬ν•©λ‹ˆλ‹€" # Create service account with eksctl eksctl create iamserviceaccount \ @@ -85,7 +100,7 @@ jobs: --role-name AmazonEKSLoadBalancerControllerRole \ --attach-policy-arn=arn:aws:iam::863518449560:policy/AWSLoadBalancerControllerIAMPolicy \ --approve \ - --region=ap-northeast-2 || true + --region=ap-northeast-2 || echo "μ„œλΉ„μŠ€ 계정이 이미 μ‘΄μž¬ν•©λ‹ˆλ‹€" # Install cert-manager kubectl apply \ @@ -93,7 +108,7 @@ jobs: -f https://github.com/jetstack/cert-manager/releases/download/v1.13.0/cert-manager.yaml # Wait for cert-manager - echo "Waiting for cert-manager to be ready..." + echo "⏳ cert-manager μ€€λΉ„ λŒ€κΈ° 쀑..." kubectl wait --for=condition=ready pod -l app.kubernetes.io/instance=cert-manager -n cert-manager --timeout=300s # Download and apply AWS Load Balancer Controller @@ -102,10 +117,10 @@ jobs: kubectl apply -f v2_7_2_full.yaml # Wait for controller to be ready - echo "Waiting for AWS Load Balancer Controller to be ready..." + echo "⏳ AWS Load Balancer Controller μ€€λΉ„ λŒ€κΈ° 쀑..." kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=aws-load-balancer-controller -n kube-system --timeout=300s else - echo "AWS Load Balancer Controller already exists" + echo "βœ… AWS Load Balancer Controllerκ°€ 이미 μ„€μΉ˜λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€" fi - name: Deploy to EKS @@ -114,10 +129,14 @@ jobs: ECR_REPOSITORY: nestjs-app IMAGE_TAG: ${{ github.sha }} run: | + echo "πŸš€ EKS 배포 μ‹œμž‘..." + # Create namespace + echo "πŸ“ λ„€μž„μŠ€νŽ˜μ΄μŠ€ 생성..." kubectl apply -f k8s/namespace.yaml # Create or update secrets + echo "πŸ” μ‹œν¬λ¦Ώ 생성/μ—…λ°μ΄νŠΈ..." kubectl create secret generic app-secrets \ --from-literal=database-url="${{ secrets.DATABASE_URL }}" \ --from-literal=redis-url="${{ secrets.REDIS_URL }}" \ @@ -125,18 +144,115 @@ jobs: --dry-run=client -o yaml | kubectl apply -f - # Update deployment image + echo "πŸ”„ 배포 이미지 μ—…λ°μ΄νŠΈ..." sed -i "s|863518449560.dkr.ecr.ap-northeast-2.amazonaws.com/nestjs-app:latest|$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG|g" k8s/deployment.yaml # Deploy application + echo "πŸ“¦ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 배포..." kubectl apply -f k8s/deployment.yaml kubectl apply -f k8s/service.yaml kubectl apply -f k8s/hpa.yaml kubectl apply -f k8s/ingress.yaml - # Check deployment status - kubectl rollout status deployment/nestjs-app -n nestjs-app + echo "βœ… λ¦¬μ†ŒμŠ€ 배포 μ™„λ£Œ" + + - name: Monitor Deployment Progress + run: | + echo "πŸ” 배포 μ§„ν–‰ 상황 λͺ¨λ‹ˆν„°λ§..." + + # Start rollout status check in background + kubectl rollout status deployment/nestjs-app -n nestjs-app --timeout=600s & + ROLLOUT_PID=$! + + # Monitor pods and logs in real-time + echo "πŸ“Š μ‹€μ‹œκ°„ λͺ¨λ‹ˆν„°λ§ μ‹œμž‘..." + for i in {1..30}; do + echo "--- 체크 #$i ($(date '+%H:%M:%S')) ---" + + echo "Pod μƒνƒœ:" + kubectl get pods -n nestjs-app -l app=nestjs-app -o wide + + echo "ReplicaSet μƒνƒœ:" + kubectl get rs -n nestjs-app -l app=nestjs-app -o wide + + echo "졜근 이벀트:" + kubectl get events -n nestjs-app --field-selector involvedObject.kind=Pod --sort-by='.lastTimestamp' | tail -3 + + # Get logs from any running pods + PODS=$(kubectl get pods -n nestjs-app -l app=nestjs-app -o jsonpath='{.items[*].metadata.name}') + if [ ! -z "$PODS" ]; then + echo "ν˜„μž¬ Pod 둜그:" + for pod in $PODS; do + echo "--- $pod 둜그 ---" + kubectl logs $pod -n nestjs-app --tail=5 --since=30s 2>/dev/null || echo "둜그 μ—†μŒ" + done + fi + + # Check if rollout is still running + if ! kill -0 $ROLLOUT_PID 2>/dev/null; then + echo "βœ… 둀아웃 μ™„λ£Œ!" + break + fi + + echo "⏳ 20초 ν›„ λ‹€μ‹œ 확인..." + sleep 20 + done + + # Wait for rollout to complete + wait $ROLLOUT_PID + + - name: Debug Deployment Issues + if: failure() + run: | + echo "πŸ” ===== 배포 μ‹€νŒ¨ 디버깅 =====" + + echo "πŸ“Š Deployment 상세 정보:" + kubectl describe deployment nestjs-app -n nestjs-app + + echo "" + echo "πŸ“Š ReplicaSet μƒνƒœ:" + kubectl describe rs -n nestjs-app -l app=nestjs-app + + echo "" + echo "🚨 μ‹€νŒ¨ν•œ Pod 상세 정보:" + kubectl get pods -n nestjs-app -l app=nestjs-app -o wide + + # 각 Pod의 상세 정보와 둜그 좜λ ₯ + PODS=$(kubectl get pods -n nestjs-app -l app=nestjs-app -o jsonpath='{.items[*].metadata.name}') + for pod in $PODS; do + echo "" + echo "--- Pod: $pod 상세 정보 ---" + kubectl describe pod $pod -n nestjs-app + + echo "" + echo "--- Pod: $pod ν˜„μž¬ 둜그 ---" + kubectl logs $pod -n nestjs-app --tail=50 || echo "ν˜„μž¬ 둜그 μ—†μŒ" + + echo "" + echo "--- Pod: $pod 이전 둜그 ---" + kubectl logs $pod -n nestjs-app --previous --tail=50 || echo "이전 둜그 μ—†μŒ" + done + + echo "" + echo "πŸ” 졜근 이벀트 (상세):" + kubectl get events -n nestjs-app --sort-by='.lastTimestamp' | tail -20 + + echo "" + echo "πŸ” ν΄λŸ¬μŠ€ν„° λ¦¬μ†ŒμŠ€ μƒνƒœ:" + kubectl top nodes || echo "λ©”νŠΈλ¦­ μ„œλ²„ μ‚¬μš© λΆˆκ°€" + kubectl describe nodes | grep -A 10 "Allocated resources" || echo "λ…Έλ“œ λ¦¬μ†ŒμŠ€ 정보 μ—†μŒ" + + echo "" + echo "πŸ” λ„€μž„μŠ€νŽ˜μ΄μŠ€ λ¦¬μ†ŒμŠ€:" + kubectl get all -n nestjs-app + + echo "" + echo "πŸ” Secret 및 ConfigMap μƒνƒœ:" + kubectl get secrets -n nestjs-app + kubectl get configmaps -n nestjs-app - name: Post-Deployment Verification + if: success() run: | echo "πŸš€ ===== 배포 μ™„λ£Œ 확인 ====="