k8s day11 vuejs+docker+kubernates+github actions实现自动部署

641 阅读3分钟

打算把个人博客部署在k8s上面,记录下过程。

博客是由vuepress搭建的

目前的部署方式见CD

简单说就是执行npm run build把生成的静态资源扔到我自己服务器的nginx站点目录中

我们要实现的是 每次提交到master分支,打包一个docker镜像 -> 推到docker hub -> 登录 google cloud 的k8s集群简称(GKE) -> 每个节点拉镜像实现分布式

  1. 首先项目根目录添加Dockerfile.dockerignore

Dockerfile

# build stage
FROM node:lts-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/docs/.vuepress/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

.dockerignore

node_modules
.git
  1. 打包docker镜像并推到docker hub仓库
docker build . --file Dockerfile -t finleyma/blog-vuepres
docker push

打开 hub.docker.com/r/finleyma/… 更新时间变了,搞定了第一步

  1. 项目根目录创建kubernates.yaml

注意:我们已经提前在google cloud上建立好了包含3个工作节点的k8s集群

其中Deployment的replicas为3,因为我们的k8s集群有三个工作节点

Service的类型为LoadBalancer,这样google cloud会自动帮我们创建负载均衡器并分配IP

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-blog-vuepress
  labels:
    app: blog-vuepress
spec:
  replicas: 3
  selector:
    matchLabels:
      app: blog-vuepress
  template:
    metadata:
      labels:
        app: blog-vuepress
    spec:
      containers:
        - name: blog-vuepress
          image: finleyma/blog-vuepress:latest
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: service-blog-vuepress
spec:
  type: LoadBalancer
  selector:
    app: blog-vuepress
  ports:
    # 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。
    - protocol: TCP
      ## service暴露在cluster ip上的端口
      port: 80
      ## targetPort是pod上的端口,Dockerfile中指定了80
      targetPort: 80
  1. 稍等片刻,查看刚刚创建的service kubectl describe svc service-blog-vuepress

image.png

注意LoadBalancer Ingress就是暴露出来的可以外部访问的IP啦,浏览器打开这个IP就是我们的网站了

以上基本功能已经完成,接下来我们实现自动化

  1. 提交代码后自动创建镜像 项目根目录创建.github/workflows/cloud.yaml 注意:这个文件目前在完善中,不保证是最新的
# This is a basic workflow to help you get started with Actions
name: CI

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
  push:
    branches: [ master ]

env:
  CI: true
  NODE: 14.x
  # google cloud kubernates cluser (GKE)
  PROJECT_ID: ivory-strategy-313903
  GKE_CLUSTER: cluster-1    # Add your cluster name here.
  GKE_ZONE: asia-east1-a  # Add your cluster zone here.
  DEPLOYMENT_NAME: deployment-blog-vuepress # Add your deployment name here.
  IMAGE: finleyma/blog-vuepress
  IMAGE_TAG: $GITHUB_SHA


# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:

    - uses: actions/checkout@v2
    - name: Install Node.js
      uses: actions/setup-node@v1
      with:
        node-version: "${{ env.NODE }}"

    # calculate some variables that are used later
    - name: github branch
      run: |
        BRANCH=${GITHUB_REF##*/}
        if [ "$BRANCH" == "master" ]; then
          TAGS="latest,$(date +'%Y%m%d')"
        else
          TAGS="$BRANCH"
        fi
        TAGS="${TAGS},${BRANCH}-${{ github.run_number }},${GITHUB_SHA:0:7}"
        echo "TAGS=${TAGS}" >> $GITHUB_ENV
        echo "GITHUB_BRANCH=${BRANCH}" >> $GITHUB_ENV

    - name: Install npm dependencies
      run: npm ci

    - name: Run build task
      run: npm run build --if-present

    - name: Build the Docker image
      run: docker build --file Dockerfile .

    - name: publish docker image to dockerhub
      uses: elgohr/Publish-Docker-Github-Action@master
      with:
        name: ${{ env.IMAGE }}
        username: finleyma
        password: ${{ secrets.DOCKER_HUB_PASSWORD }}
        tags: ${{ env.TAGS }}

#    - name: Deploy to Server Cloud 2
#      uses: easingthemes/ssh-deploy@v2.1.5
#      env:
#        SSH_PRIVATE_KEY: ${{ secrets.PRIVATE_KEY2 }}
#        ARGS: "-rltgoDzvO --delete"
#        SOURCE: "docs/.vuepress/dist/"
#        REMOTE_PORT : ${{ secrets.PORT2 }}
#        REMOTE_HOST: ${{ secrets.HOST2 }}
#        REMOTE_USER: ${{ secrets.USERNAME }}
#        TARGET: "/home/ubuntu/blog"

      # Setup gcloud CLI
    - uses: google-github-actions/setup-gcloud@94337306dda8180d967a56932ceb4ddcf01edae7
      with:
        service_account_key: ${{ secrets.GKE_SA_KEY }}
        project_id: ${{ env.PROJECT_ID }}

      # Configure docker to use the gcloud command-line tool as a credential helper
    - run: |-
        gcloud --quiet auth configure-docker

      # Get the GKE credentials so we can deploy to the cluster
    - uses: google-github-actions/get-gke-credentials@fb08709ba27618c31c09e014e1d8364b02e5042e
      with:
        cluster_name: ${{ env.GKE_CLUSTER }}
        location: ${{ env.GKE_ZONE }}
        credentials: ${{ secrets.GKE_SA_KEY }}

      # Deploy the Docker image to the GKE cluster
      # kubectl set image deployment deployment-blog-vuepress blog-vuepress=finleyma/blog-vuepress:master-87 --record
      #        ./kustomize edit set image gcr.io/PROJECT_ID/IMAGE:TAG=gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA
      #        ./kustomize build . | kubectl apply -f -
    - name: Deploy
      run: |-
        kubectl get services -o wide
        kubectl set image deployment deployment-blog-vuepress blog-vuepress=finleyma/blog-vuepress:${GITHUB_SHA:0:7} --record
        kubectl rollout history deployment deployment-blog-vuepress

      # Slack Notification
    - name: Slack Notification
      uses: 8398a7/action-slack@v3
      with:
        status: ${{ job.status }}
        fields: repo,message,commit,author,action,eventName,ref,workflow,job,took # selectable (default: repo,message)
      env:
        # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # optional
        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} # required
      if: always() # Pick up events even if the job fails or is canceled.
  1. google cloud部分可以参考

github.com/actions/sta…