diff --git a/.gitea/workflows/deploy-backend.yaml b/.gitea/workflows/deploy-backend.yaml index 5422bcf..e58a826 100644 --- a/.gitea/workflows/deploy-backend.yaml +++ b/.gitea/workflows/deploy-backend.yaml @@ -3,57 +3,175 @@ name: Build and Deploy Backend on: push: branches: - - main - master + - dev 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 }} + if [[ "${{ github.ref_name }}" == "master" ]]; then + echo "IMAGE_TAG=prod-${BUILD_DATE}-${SHORT_SHA}" >> $GITHUB_ENV + echo "CR_SERVER_ACTIVE=${{ secrets.CR_PROD_SERVER }}" >> $GITHUB_ENV + echo "CR_USERNAME_ACTIVE=${{ secrets.CR_PROD_USERNAME }}" >> $GITHUB_ENV + echo "CR_PASSWORD_ACTIVE=${{ secrets.CR_PROD_PASSWORD }}" >> $GITHUB_ENV + echo "CR_ORG=${{ secrets.CR_PROD_ORG }}" >> $GITHUB_ENV + echo "DEPLOY_ENV=production" >> $GITHUB_ENV + elif [[ "${{ github.ref_name }}" == "dev" ]]; then + echo "IMAGE_TAG=dev-${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=${{ secrets.CR_ORG }}" >> $GITHUB_ENV + echo "DEPLOY_ENV=development" >> $GITHUB_ENV + fi + + - name: Login to Container Registry + run: | + echo "${{ env.CR_PASSWORD_ACTIVE }}" | docker login --username "${{ env.CR_USERNAME_ACTIVE }}" --password-stdin ${{ env.CR_SERVER_ACTIVE }} - name: Build and Push Backend - uses: docker/build-push-action@v4 - with: - context: ./backend - push: true - provenance: false - tags: ${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/airlabs-manage-backend:latest + id: build_backend + run: | + set -o pipefail + 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 }}/airlabs-manage-backend:${{ env.IMAGE_TAG }} \ + --tag ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airlabs-manage-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 }}/airlabs-manage-backend:${{ env.IMAGE_TAG }} && \ + docker push ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airlabs-manage-backend:latest && break + echo "Push attempt $attempt failed, retrying in 10s..." && sleep 10 + done - name: Setup Kubectl run: | - curl -LO "https://files.m.daocloud.io/dl.k8s.io/release/v1.28.2/bin/linux/amd64/kubectl" - chmod +x kubectl - mv kubectl /usr/local/bin/ + 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: Set kubeconfig + run: | + mkdir -p $HOME/.kube + if [[ "${{ github.ref_name }}" == "master" ]]; then + printf '%s\n' '${{ secrets.KUBE_CONFIG_PROD }}' > $HOME/.kube/config + elif [[ "${{ github.ref_name }}" == "dev" ]]; then + printf '%s\n' '${{ secrets.KUBE_CONFIG }}' > $HOME/.kube/config + fi + 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 - uses: Azure/k8s-set-context@v3 - with: - method: kubeconfig - kubeconfig: ${{ secrets.KUBE_CONFIG }} - - - name: Update K8s Manifests + id: deploy run: | - # 替换镜像地址 - sed -i "s|\${CI_REGISTRY_IMAGE}/backend:latest|${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/airlabs-manage-backend:latest|g" k8s/backend-deployment-prod.yaml + echo "Environment: ${{ env.DEPLOY_ENV }}" + CR_IMAGE="${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}" - # 应用配置 - kubectl apply -f k8s/backend-deployment-prod.yaml - kubectl apply -f k8s/backend-ingress.yaml + # Replace image placeholders + sed -i "s|\${CI_REGISTRY_IMAGE}/backend:latest|${CR_IMAGE}/airlabs-manage-backend:${{ env.IMAGE_TAG }}|g" k8s/backend-deployment-prod.yaml - kubectl rollout restart deployment/airlabs-manage-backend + 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 - + + kubectl apply -f k8s/cert-manager-issuer.yaml + kubectl apply -f k8s/backend-deployment-prod.yaml + kubectl apply -f k8s/backend-ingress.yaml + + kubectl rollout restart deployment/airlabs-manage-backend + } 2>&1 | tee /tmp/deploy.log && break + echo "Attempt $attempt failed, retrying in 10s..." + sleep 10 + done + + - name: Report failure to Log Center + if: failure() + run: | + BUILD_LOG="" + DEPLOY_LOG="" + FAILED_STEP="unknown" + + if [[ "${{ steps.build_backend.outcome }}" == "failure" ]]; then + FAILED_STEP="build" + if [ -f /tmp/build.log ]; then + BUILD_LOG=$(tail -50 /tmp/build.log | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g') + fi + elif [[ "${{ steps.deploy.outcome }}" == "failure" ]]; then + FAILED_STEP="deploy" + if [ -f /tmp/deploy.log ]; then + DEPLOY_LOG=$(tail -50 /tmp/deploy.log | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g') + fi + fi + + ERROR_LOG="${BUILD_LOG}${DEPLOY_LOG}" + if [ -z "$ERROR_LOG" ]; then + ERROR_LOG="No captured output. Check Gitea Actions UI for details." + fi + + if [[ "$FAILED_STEP" == "deploy" ]]; then + SOURCE="deployment" + ERROR_TYPE="DeployError" + else + SOURCE="cicd" + ERROR_TYPE="DockerBuildError" + fi + + curl -s -X POST "https://qiyuan-log-center-api.airlabs.art/api/v1/logs/report" \ + -H "Content-Type: application/json" \ + -d "{ + \"project_id\": \"airlabs_manage_backend\", + \"environment\": \"${{ env.DEPLOY_ENV }}\", + \"level\": \"ERROR\", + \"source\": \"${SOURCE}\", + \"commit_hash\": \"${{ github.sha }}\", + \"repo_url\": \"https://gitea.airlabs.art/${{ github.repository }}.git\", + \"error\": { + \"type\": \"${ERROR_TYPE}\", + \"message\": \"[${FAILED_STEP}] Build and Deploy Backend failed on branch ${{ github.ref_name }}\", + \"stack_trace\": [\"${ERROR_LOG}\"] + }, + \"context\": { + \"job_name\": \"build-and-deploy\", + \"step_name\": \"${FAILED_STEP}\", + \"workflow\": \"${{ github.workflow }}\", + \"run_id\": \"${{ github.run_number }}\", + \"branch\": \"${{ github.ref_name }}\", + \"actor\": \"${{ github.actor }}\", + \"commit\": \"${{ github.sha }}\", + \"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/.gitea/workflows/deploy-web.yaml b/.gitea/workflows/deploy-web.yaml index f8fd68e..f95cdb2 100644 --- a/.gitea/workflows/deploy-web.yaml +++ b/.gitea/workflows/deploy-web.yaml @@ -3,57 +3,175 @@ name: Build and Deploy Web on: push: branches: - - main - master + - dev 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 }} + if [[ "${{ github.ref_name }}" == "master" ]]; then + echo "IMAGE_TAG=prod-${BUILD_DATE}-${SHORT_SHA}" >> $GITHUB_ENV + echo "CR_SERVER_ACTIVE=${{ secrets.CR_PROD_SERVER }}" >> $GITHUB_ENV + echo "CR_USERNAME_ACTIVE=${{ secrets.CR_PROD_USERNAME }}" >> $GITHUB_ENV + echo "CR_PASSWORD_ACTIVE=${{ secrets.CR_PROD_PASSWORD }}" >> $GITHUB_ENV + echo "CR_ORG=${{ secrets.CR_PROD_ORG }}" >> $GITHUB_ENV + echo "DEPLOY_ENV=production" >> $GITHUB_ENV + elif [[ "${{ github.ref_name }}" == "dev" ]]; then + echo "IMAGE_TAG=dev-${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=${{ secrets.CR_ORG }}" >> $GITHUB_ENV + echo "DEPLOY_ENV=development" >> $GITHUB_ENV + fi + + - name: Login to Container Registry + run: | + echo "${{ env.CR_PASSWORD_ACTIVE }}" | docker login --username "${{ env.CR_USERNAME_ACTIVE }}" --password-stdin ${{ env.CR_SERVER_ACTIVE }} - name: Build and Push Web - uses: docker/build-push-action@v4 - with: - context: ./frontend - push: true - provenance: false - tags: ${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/airlabs-manage-web:latest + id: build_web + run: | + set -o pipefail + 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 }}/airlabs-manage-web:${{ env.IMAGE_TAG }} \ + --tag ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airlabs-manage-web:latest \ + ./frontend 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 }}/airlabs-manage-web:${{ env.IMAGE_TAG }} && \ + docker push ${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}/airlabs-manage-web:latest && break + echo "Push attempt $attempt failed, retrying in 10s..." && sleep 10 + done - name: Setup Kubectl run: | - curl -LO "https://files.m.daocloud.io/dl.k8s.io/release/v1.28.2/bin/linux/amd64/kubectl" - chmod +x kubectl - mv kubectl /usr/local/bin/ + 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: Set kubeconfig + run: | + mkdir -p $HOME/.kube + if [[ "${{ github.ref_name }}" == "master" ]]; then + printf '%s\n' '${{ secrets.KUBE_CONFIG_PROD }}' > $HOME/.kube/config + elif [[ "${{ github.ref_name }}" == "dev" ]]; then + printf '%s\n' '${{ secrets.KUBE_CONFIG }}' > $HOME/.kube/config + fi + 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 - uses: Azure/k8s-set-context@v3 - with: - method: kubeconfig - kubeconfig: ${{ secrets.KUBE_CONFIG }} - - - name: Update K8s Manifests + id: deploy run: | - # 替换镜像地址 - sed -i "s|\${CI_REGISTRY_IMAGE}/web:latest|${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/airlabs-manage-web:latest|g" k8s/web-deployment-prod.yaml + echo "Environment: ${{ env.DEPLOY_ENV }}" + CR_IMAGE="${{ env.CR_SERVER_ACTIVE }}/${{ env.CR_ORG }}" - # 应用配置 - kubectl apply -f k8s/web-deployment-prod.yaml - kubectl apply -f k8s/web-ingress.yaml + # Replace image placeholders + sed -i "s|\${CI_REGISTRY_IMAGE}/web:latest|${CR_IMAGE}/airlabs-manage-web:${{ env.IMAGE_TAG }}|g" k8s/web-deployment-prod.yaml - kubectl rollout restart deployment/airlabs-manage-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 - + + kubectl apply -f k8s/cert-manager-issuer.yaml + kubectl apply -f k8s/web-deployment-prod.yaml + kubectl apply -f k8s/web-ingress.yaml + + kubectl rollout restart deployment/airlabs-manage-web + } 2>&1 | tee /tmp/deploy.log && break + echo "Attempt $attempt failed, retrying in 10s..." + sleep 10 + done + + - name: Report failure to Log Center + if: failure() + run: | + BUILD_LOG="" + DEPLOY_LOG="" + FAILED_STEP="unknown" + + if [[ "${{ steps.build_web.outcome }}" == "failure" ]]; then + FAILED_STEP="build" + if [ -f /tmp/build.log ]; then + BUILD_LOG=$(tail -50 /tmp/build.log | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g') + fi + elif [[ "${{ steps.deploy.outcome }}" == "failure" ]]; then + FAILED_STEP="deploy" + if [ -f /tmp/deploy.log ]; then + DEPLOY_LOG=$(tail -50 /tmp/deploy.log | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g') + fi + fi + + ERROR_LOG="${BUILD_LOG}${DEPLOY_LOG}" + if [ -z "$ERROR_LOG" ]; then + ERROR_LOG="No captured output. Check Gitea Actions UI for details." + fi + + if [[ "$FAILED_STEP" == "deploy" ]]; then + SOURCE="deployment" + ERROR_TYPE="DeployError" + else + SOURCE="cicd" + ERROR_TYPE="DockerBuildError" + fi + + curl -s -X POST "https://qiyuan-log-center-api.airlabs.art/api/v1/logs/report" \ + -H "Content-Type: application/json" \ + -d "{ + \"project_id\": \"airlabs_manage_web\", + \"environment\": \"${{ env.DEPLOY_ENV }}\", + \"level\": \"ERROR\", + \"source\": \"${SOURCE}\", + \"commit_hash\": \"${{ github.sha }}\", + \"repo_url\": \"https://gitea.airlabs.art/${{ github.repository }}.git\", + \"error\": { + \"type\": \"${ERROR_TYPE}\", + \"message\": \"[${FAILED_STEP}] Build and Deploy Web failed on branch ${{ github.ref_name }}\", + \"stack_trace\": [\"${ERROR_LOG}\"] + }, + \"context\": { + \"job_name\": \"build-and-deploy\", + \"step_name\": \"${FAILED_STEP}\", + \"workflow\": \"${{ github.workflow }}\", + \"run_id\": \"${{ github.run_number }}\", + \"branch\": \"${{ github.ref_name }}\", + \"actor\": \"${{ github.actor }}\", + \"commit\": \"${{ github.sha }}\", + \"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/backend/.env b/backend/.env index 1f20f1b..08e557f 100644 --- a/backend/.env +++ b/backend/.env @@ -1,9 +1,9 @@ -# MySQL 数据库 -DB_HOST=rm-7xv1uaw910558p1788o.mysql.rds.aliyuncs.com -DB_USER=airlabs_manage -DB_PASSWORD=Airlabs-manage123 +# MySQL 数据库 (火山云测试环境) +DB_HOST=mysql-8351f937d637-public.rds.volces.com +DB_USER=zyc +DB_PASSWORD=Zyc188208 DB_PORT=3306 -DB_NAME=airlabs-manage +DB_NAME=airlabs_manage # 豆包模型配置 (火山引擎 ARK) ARK_API_KEY=846b6981-9954-4c58-bb39-63079393bdb8 diff --git a/k8s/backend-deployment-prod.yaml b/k8s/backend-deployment-prod.yaml index 25e9a1d..4d9f80f 100644 --- a/k8s/backend-deployment-prod.yaml +++ b/k8s/backend-deployment-prod.yaml @@ -14,6 +14,8 @@ spec: labels: app: airlabs-manage-backend spec: + imagePullSecrets: + - name: cr-pull-secret containers: - name: airlabs-manage-backend image: ${CI_REGISTRY_IMAGE}/backend:latest @@ -21,30 +23,52 @@ spec: ports: - containerPort: 8000 env: - # Database (阿里云 RDS MySQL) + # Database - name: DB_HOST - value: "rm-7xv1uaw910558p1788o.mysql.rds.aliyuncs.com" + value: "mysql8351f937d637.rds.ivolces.com" - name: DB_NAME - value: "airlabs-manage" - - name: DB_USER value: "airlabs_manage" + - name: DB_USER + value: "zyc" - name: DB_PASSWORD - value: "Airlabs-manage123" + value: "Zyc188208" - name: DB_PORT value: "3306" - # 生产环境 JWT 密钥 + # JWT 密钥 - name: SECRET_KEY value: "Ui5-xEvtAhKRDtlXKzDfd7TElsVZFUhakff0qcjn8jU" # CORS 允许的域名 - name: CORS_ORIGINS value: "https://airlabs-manage-web.airlabs.art" + livenessProbe: + httpGet: + path: /api/health/ + port: 8000 + httpHeaders: + - name: Host + value: localhost + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /api/health/ + port: 8000 + httpHeaders: + - name: Host + value: localhost + initialDelaySeconds: 15 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 resources: requests: - memory: "128Mi" - cpu: "100m" + memory: "256Mi" + cpu: "250m" limits: - memory: "512Mi" - cpu: "500m" + memory: "1024Mi" + cpu: "1000m" --- apiVersion: v1 kind: Service diff --git a/k8s/cert-manager-issuer.yaml b/k8s/cert-manager-issuer.yaml new file mode 100644 index 0000000..f0b2af8 --- /dev/null +++ b/k8s/cert-manager-issuer.yaml @@ -0,0 +1,14 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: airlabsv001@gmail.com + privateKeySecretRef: + name: letsencrypt-prod-key + solvers: + - http01: + ingress: + class: traefik diff --git a/k8s/web-deployment-prod.yaml b/k8s/web-deployment-prod.yaml index 06001f8..ab0eb42 100644 --- a/k8s/web-deployment-prod.yaml +++ b/k8s/web-deployment-prod.yaml @@ -14,19 +14,37 @@ spec: labels: app: airlabs-manage-web spec: + imagePullSecrets: + - name: cr-pull-secret containers: - name: airlabs-manage-web image: ${CI_REGISTRY_IMAGE}/web:latest imagePullPolicy: Always ports: - containerPort: 80 + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 3 + failureThreshold: 3 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 resources: requests: memory: "64Mi" - cpu: "100m" + cpu: "50m" limits: - memory: "512Mi" - cpu: "500m" + memory: "256Mi" + cpu: "250m" --- apiVersion: v1 kind: Service