From f3a3f88b2770d74a522dc1c1e85a49677d50dc4a Mon Sep 17 00:00:00 2001 From: zyc <1439655764@qq.com> Date: Mon, 20 Apr 2026 10:11:48 +0800 Subject: [PATCH] ci: migrate deployment to Volcano Engine CR/K3s Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitea/workflows/deploy.yaml | 157 +++++++++++++++++++++++------------ k8s/backend-deployment.yaml | 2 +- k8s/web-deployment.yaml | 2 +- 3 files changed, 107 insertions(+), 54 deletions(-) diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml index 78b1d23..05964ca 100644 --- a/.gitea/workflows/deploy.yaml +++ b/.gitea/workflows/deploy.yaml @@ -3,84 +3,128 @@ name: Build and Deploy on: push: branches: - - main - - master + - airlabs jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + run: | + git clone --depth=1 --branch=${{ github.ref_name }} https://gitea.airlabs.art/${{ github.repository }}.git . - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - config-inline: | - [registry."docker.io"] - mirrors = ["https://docker.m.daocloud.io", "https://docker.1panel.live", "https://hub.rat.dev"] + - name: Set environment by branch + run: | + SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7) + BUILD_DATE=$(date +%Y%m%d) - - name: Login to Huawei Cloud SWR - uses: docker/login-action@v2 - with: - registry: ${{ secrets.SWR_SERVER }} - username: ${{ secrets.SWR_USERNAME }} - password: ${{ secrets.SWR_PASSWORD }} + echo "IMAGE_TAG=internal-${BUILD_DATE}-${SHORT_SHA}" >> $GITHUB_ENV + echo "CR_SERVER_ACTIVE=${{ secrets.CR_SERVER }}" >> $GITHUB_ENV + echo "CR_USERNAME_ACTIVE=${{ secrets.CR_USERNAME }}" >> $GITHUB_ENV + echo "CR_PASSWORD_ACTIVE=${{ secrets.CR_PASSWORD }}" >> $GITHUB_ENV + echo "CR_ORG=internal" >> $GITHUB_ENV + echo "DEPLOY_ENV=internal" >> $GITHUB_ENV + echo "DOMAIN_WEB=airgate.airlabs.art" >> $GITHUB_ENV + echo "DOMAIN_API=airgate-api.airlabs.art" >> $GITHUB_ENV + + - name: Login to Volcano Engine CR + run: | + echo "${{ env.CR_PASSWORD_ACTIVE }}" | docker login --username "${{ env.CR_USERNAME_ACTIVE }}" --password-stdin ${{ env.CR_SERVER_ACTIVE }} - name: Build and Push Backend id: build_backend run: | set -o pipefail - docker buildx build \ - --push \ - --provenance=false \ - --tag ${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/airgate-backend:latest \ - ./backend 2>&1 | tee /tmp/build.log + for attempt in 1 2 3; do + echo "Build backend attempt $attempt/3..." + DOCKER_BUILDKIT=0 docker build \ + --tag ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airgate-backend:${{ env.IMAGE_TAG }} \ + --tag ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airgate-backend:latest \ + ./backend 2>&1 | tee /tmp/build.log && break + echo "Attempt $attempt failed, retrying in 10s..." && sleep 10 + done + for attempt in 1 2 3; do + docker push ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airgate-backend:${{ env.IMAGE_TAG }} && \ + docker push ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airgate-backend:latest && break + echo "Push attempt $attempt failed, retrying in 10s..." && sleep 10 + done - name: Build and Push Web id: build_web run: | set -o pipefail - docker buildx build \ - --push \ - --provenance=false \ - --tag ${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/airgate-web:latest \ - ./frontend 2>&1 | tee -a /tmp/build.log + for attempt in 1 2 3; do + echo "Build web attempt $attempt/3..." + DOCKER_BUILDKIT=0 docker build \ + --tag ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airgate-web:${{ env.IMAGE_TAG }} \ + --tag ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airgate-web:latest \ + ./frontend 2>&1 | tee -a /tmp/build.log && break + echo "Attempt $attempt failed, retrying in 10s..." && sleep 10 + done + for attempt in 1 2 3; do + docker push ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airgate-web:${{ env.IMAGE_TAG }} && \ + docker push ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airgate-web:latest && break + echo "Push attempt $attempt failed, retrying in 10s..." && sleep 10 + done - - name: Setup SSH + - name: Setup Kubectl run: | - mkdir -p ~/.ssh - echo "${{ secrets.K3S_SSH_KEY }}" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh-keyscan -H ${{ secrets.K3S_HOST }} >> ~/.ssh/known_hosts 2>/dev/null + if ! command -v kubectl &>/dev/null; then + for attempt in 1 2 3; do + curl -LO "https://files.m.daocloud.io/dl.k8s.io/release/v1.28.0/bin/linux/amd64/kubectl" && break + echo "Download attempt $attempt failed, retrying in 5s..." && sleep 5 + done + chmod +x kubectl && mv kubectl /usr/bin/kubectl + fi + kubectl version --client - - name: Deploy to K3s via SSH + - name: Set kubeconfig + run: | + mkdir -p $HOME/.kube + printf '%s\n' '${{ secrets.VOLCANO_INTERNAL_KUBE_CONFIG }}' > $HOME/.kube/config + chmod 600 $HOME/.kube/config + echo "kubeconfig lines: $(wc -l < $HOME/.kube/config)" + grep server $HOME/.kube/config || echo "WARNING: no server found in kubeconfig" + + - name: Deploy to K3s id: deploy run: | - SWR_IMAGE="${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}" + echo "Environment: ${{ env.DEPLOY_ENV }}" + CR_IMAGE="${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}" - # Replace image placeholders in yaml files - sed -i "s|\${CI_REGISTRY_IMAGE}/airgate-backend:latest|${SWR_IMAGE}/airgate-backend:latest|g" k8s/backend-deployment.yaml - sed -i "s|\${CI_REGISTRY_IMAGE}/airgate-web:latest|${SWR_IMAGE}/airgate-web:latest|g" k8s/web-deployment.yaml + # Replace image placeholders + sed -i "s|\${CI_REGISTRY_IMAGE}/airgate-backend:latest|${CR_IMAGE}/airgate-backend:${{ env.IMAGE_TAG }}|g" k8s/backend-deployment.yaml + sed -i "s|\${CI_REGISTRY_IMAGE}/airgate-web:latest|${CR_IMAGE}/airgate-web:${{ env.IMAGE_TAG }}|g" k8s/web-deployment.yaml - # Copy k8s manifests to server - scp -o StrictHostKeyChecking=no k8s/backend-deployment.yaml k8s/web-deployment.yaml k8s/ingress.yaml root@${{ secrets.K3S_HOST }}:/tmp/ + # Replace domain placeholders in ingress + sed -i "s|airgate.airlabs.art|${{ env.DOMAIN_WEB }}|g" k8s/ingress.yaml + sed -i "s|airgate-api.airlabs.art|${{ env.DOMAIN_API }}|g" k8s/ingress.yaml - # Create/update secrets and apply manifests on server - set -o pipefail - ssh -o StrictHostKeyChecking=no root@${{ secrets.K3S_HOST }} << ENDSSH - export KUBECONFIG=/etc/rancher/k3s/k3s.yaml + # Replace CORS origin + sed -i "s|https://airgate.airlabs.art|https://${{ env.DOMAIN_WEB }}|g" k8s/backend-deployment.yaml - kubectl apply -f /tmp/backend-deployment.yaml - kubectl apply -f /tmp/web-deployment.yaml - kubectl apply -f /tmp/ingress.yaml - kubectl rollout restart deployment/airgate-backend - kubectl rollout restart deployment/airgate-web + for attempt in 1 2 3; do + echo "Deploy attempt $attempt/3..." + { + # Create/update image pull secret + kubectl create secret docker-registry cr-pull-secret \ + --docker-server="${{ env.CR_SERVER_ACTIVE }}" \ + --docker-username="${{ env.CR_USERNAME_ACTIVE }}" \ + --docker-password="${{ env.CR_PASSWORD_ACTIVE }}" \ + --dry-run=client -o yaml | kubectl apply -f - - rm -f /tmp/backend-deployment.yaml /tmp/web-deployment.yaml /tmp/ingress.yaml - ENDSSH + # Apply manifests + kubectl apply -f k8s/backend-deployment.yaml + kubectl apply -f k8s/web-deployment.yaml + kubectl apply -f k8s/ingress.yaml + + kubectl rollout restart deployment/airgate-backend + kubectl rollout restart deployment/airgate-web + } 2>&1 | tee /tmp/deploy.log && break + echo "Attempt $attempt failed, retrying in 10s..." + sleep 10 + done - # ===== Log Center: failure reporting ===== - name: Report failure to Log Center if: failure() run: | @@ -117,11 +161,11 @@ jobs: -H "Content-Type: application/json" \ -d "{ \"project_id\": \"airgate\", - \"environment\": \"${{ github.ref_name }}\", + \"environment\": \"${{ env.DEPLOY_ENV }}\", \"level\": \"ERROR\", \"source\": \"${SOURCE}\", \"commit_hash\": \"${{ github.sha }}\", - \"repo_url\": \"${{ github.server_url }}/${{ github.repository }}\", + \"repo_url\": \"https://gitea.airlabs.art/${{ github.repository }}.git\", \"error\": { \"type\": \"${ERROR_TYPE}\", \"message\": \"[${FAILED_STEP}] Build and Deploy failed on branch ${{ github.ref_name }}\", @@ -135,6 +179,15 @@ jobs: \"branch\": \"${{ github.ref_name }}\", \"actor\": \"${{ github.actor }}\", \"commit\": \"${{ github.sha }}\", - \"run_url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}\" + \"run_url\": \"https://gitea.airlabs.art/${{ github.repository }}/actions/runs/${{ github.run_number }}\" } }" || true + + - name: Docker Cleanup + if: always() + run: | + docker container prune -f + docker image prune -f + docker builder prune -a -f + echo "Disk usage after cleanup:" + df -h / | tail -1 diff --git a/k8s/backend-deployment.yaml b/k8s/backend-deployment.yaml index fb85bfe..9ebff25 100644 --- a/k8s/backend-deployment.yaml +++ b/k8s/backend-deployment.yaml @@ -15,7 +15,7 @@ spec: app: airgate-backend spec: imagePullSecrets: - - name: swr-secret + - name: cr-pull-secret containers: - name: airgate-backend image: ${CI_REGISTRY_IMAGE}/airgate-backend:latest diff --git a/k8s/web-deployment.yaml b/k8s/web-deployment.yaml index ac0dd28..3352931 100644 --- a/k8s/web-deployment.yaml +++ b/k8s/web-deployment.yaml @@ -15,7 +15,7 @@ spec: app: airgate-web spec: imagePullSecrets: - - name: swr-secret + - name: cr-pull-secret containers: - name: airgate-web image: ${CI_REGISTRY_IMAGE}/airgate-web:latest