From e301c6869e1a9ea0ea7f38070c9fdda050e1b1a8 Mon Sep 17 00:00:00 2001 From: sljeff Date: Fri, 12 Aug 2022 15:46:36 +0800 Subject: [PATCH] feat: deploy --- .github/workflows/docker-build-push.yml | 99 +++++++++++++++++++++++++ apply.sh | 26 +++++++ deploy/prod/deploy.yaml | 57 ++++++++++++++ deploy/prod/hpa.yaml | 13 ++++ deploy/prod/route.yaml | 14 ++++ deploy/prod/secrets.yaml | 12 +++ deploy/prod/svc.yaml | 14 ++++ 7 files changed, 235 insertions(+) create mode 100644 .github/workflows/docker-build-push.yml create mode 100644 apply.sh create mode 100644 deploy/prod/deploy.yaml create mode 100644 deploy/prod/hpa.yaml create mode 100644 deploy/prod/route.yaml create mode 100644 deploy/prod/secrets.yaml create mode 100644 deploy/prod/svc.yaml diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml new file mode 100644 index 00000000..d948b801 --- /dev/null +++ b/.github/workflows/docker-build-push.yml @@ -0,0 +1,99 @@ +# build and push docker image to docker hub +name: Build & Deploy + +on: + push: + branches: + - 'dev' + - 'main' + - 'master' + tags: + - 'v*.*.*' + +env: + IMAGE_NAME: rss3/xlog + REGION_ID: us-east-1 + DEV_ACK_CLUSTER_ID: cd1d0ffc40b5242b39ddda1864e71e30d + PROD_ACK_CLUSTER_ID: cfc647c22fd6848b5a602ad4d7470632b + +jobs: + build: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.meta.outputs.version }} + steps: + - + name: Checkout + uses: actions/checkout@v2 + - name: docker meta + id: meta + uses: docker/metadata-action@v3 + with: + images: ${{ env.IMAGE_NAME }} + tags: | + type=sha + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - + name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v3 + with: + context: . + file: Dockerfile + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + +# deploy-dev: +# runs-on: ubuntu-latest +# needs: build +# steps: +# - name: Checkout +# uses: actions/checkout@v2 +# - name: Set K8s context +# uses: aliyun/ack-set-context@v1 +# with: +# access-key-id: "${{ secrets.ACCESS_KEY_ID }}" +# access-key-secret: "${{ secrets.ACCESS_KEY_SECRET }}" +# cluster-id: "${{ env.DEV_ACK_CLUSTER_ID }}" +# - run: | +# wget https://github.com/mikefarah/yq/releases/download/v4.25.1/yq_linux_amd64.tar.gz -O - | tar xz && mv yq_linux_amd64 /usr/local/bin/yq +# curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.22.10/bin/linux/amd64/kubectl && chmod +x kubectl && mv kubectl /usr/local/bin/kubectl +# - uses: sljeff/secrets2env@main +# with: +# secrets-json: ${{ toJson(secrets) }} +# - env: +# IMAGE_TAG_RELEASE: ${{ env.IMAGE_NAME }}:${{ needs.build.outputs.version }} +# run: | +# sh apply.sh deploy/dev/* + + deploy-prod: + # if: startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + needs: [build] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set K8s context + uses: aliyun/ack-set-context@v1 + with: + access-key-id: "${{ secrets.ACCESS_KEY_ID }}" + access-key-secret: "${{ secrets.ACCESS_KEY_SECRET }}" + cluster-id: "${{ env.PROD_ACK_CLUSTER_ID }}" + - run: | + wget https://github.com/mikefarah/yq/releases/download/v4.25.1/yq_linux_amd64.tar.gz -O - | tar xz && mv yq_linux_amd64 /usr/local/bin/yq + curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.22.10/bin/linux/amd64/kubectl && chmod +x kubectl && mv kubectl /usr/local/bin/kubectl + - uses: sljeff/secrets2env@main + with: + secrets-json: ${{ toJson(secrets) }} + - run: | + sh apply.sh deploy/prod/* + env: + IMAGE_TAG_RELEASE: ${{ env.IMAGE_NAME }}:${{ needs.build.outputs.version }} diff --git a/apply.sh b/apply.sh new file mode 100644 index 00000000..c5169553 --- /dev/null +++ b/apply.sh @@ -0,0 +1,26 @@ +set -e # exit on error +set -x # show command before execute + +apply_one() { + envsubst < $1 > temp.yaml && mv temp.yaml $1 + + kubectl apply -f $1 +} + +apply() { + for filename in $@; do + apply_one $filename + done + + # rollout status / annotation + for filename in $@; do + yaml_kind=$(yq '.kind' $filename) + if [ "$yaml_kind" = "Deployment" ]; then + ns=$(yq '.metadata.namespace' $filename) + name=$(yq '.metadata.name' $filename) + kubectl -n $ns rollout status -w deploy.apps/$name + fi + done +} + +apply $@ diff --git a/deploy/prod/deploy.yaml b/deploy/prod/deploy.yaml new file mode 100644 index 00000000..76f9535a --- /dev/null +++ b/deploy/prod/deploy.yaml @@ -0,0 +1,57 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: xlog + namespace: crossbell +spec: + progressDeadlineSeconds: 600 + replicas: 4 + revisionHistoryLimit: 5 + selector: + matchLabels: + app: xlog + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + labels: + app: xlog + spec: + enableServiceLinks: false + containers: + - image: $IMAGE_TAG_RELEASE + imagePullPolicy: Always + name: xlog + envFrom: + - secretRef: + name: xlog + ports: + - containerPort: 3000 + protocol: TCP + resources: + requests: + memory: '200Mi' + cpu: '150m' + limits: + memory: '500Mi' + cpu: '500m' + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + readinessProbe: + tcpSocket: + port: 3000 + initialDelaySeconds: 40 + periodSeconds: 10 + livenessProbe: + tcpSocket: + port: 3000 + initialDelaySeconds: 40 + periodSeconds: 20 + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 diff --git a/deploy/prod/hpa.yaml b/deploy/prod/hpa.yaml new file mode 100644 index 00000000..233ecdfc --- /dev/null +++ b/deploy/prod/hpa.yaml @@ -0,0 +1,13 @@ +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: xlog + namespace: crossbell +spec: + maxReplicas: 8 + minReplicas: 4 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: xlog + targetCPUUtilizationPercentage: 70 diff --git a/deploy/prod/route.yaml b/deploy/prod/route.yaml new file mode 100644 index 00000000..966964b6 --- /dev/null +++ b/deploy/prod/route.yaml @@ -0,0 +1,14 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: xlog + namespace: crossbell +spec: + entryPoints: + - web + routes: + - kind: Rule + match: "HostRegexp(`{subdomain:.*}.xlog.app`)" + services: + - name: xlog + port: 3000 diff --git a/deploy/prod/secrets.yaml b/deploy/prod/secrets.yaml new file mode 100644 index 00000000..73611690 --- /dev/null +++ b/deploy/prod/secrets.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +stringData: + NEXT_PUBLIC_APP_NAME: xlog + NEXT_PUBLIC_OUR_DOMAIN: xlog.app + NEXT_PUBLIC_DISCORD_LINK: "https://discord.gg/9XscSqJEq4" + NEXT_PUBLIC_GITHUB_LINK: "https://github.com/Crossbell-Box/xlog" + REDIS_URL: ${REDIS_URL} +kind: Secret +metadata: + name: xlog + namespace: corssbell +type: Opaque diff --git a/deploy/prod/svc.yaml b/deploy/prod/svc.yaml new file mode 100644 index 00000000..1b634e74 --- /dev/null +++ b/deploy/prod/svc.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: xlog + namespace: crossbell +spec: + type: ClusterIP + selector: + app: xlog + ports: + - name: http + protocol: TCP + port: 3000 + targetPort: 3000