今天我 devops 了一下

361次阅读  |  发布于3年以前

今天花了一天时间,优化了一下代码。

原来是这样的。

public int sum(int a, int b) {
    return b + a;
}

被我优化成了这样。

public int sum(int a, int b) {
    return a + b;
}

我满意地看着自己的成果,熟练地用 commit + push 推送到了远程仓库 gitee 上。

git commit -am "修改了底层的计算逻辑,提升了代码的可读性,同时对调用方保持兼容和透明"
git push

由于我提前在 gitee 开启了 devops 流水线

并且写好了流水线触发规则以及要做的事情,就在 deploy.yml 这个文件里。

name: pm-api-display
# 设置 master 分支在产生代码 push 时精确触发(PRECISE)构建
triggers:
  push:                                    
    - matchType: PRECISE
      branch: master
commitMessage: ''
# 构建阶段配置
stages:
  - stage:
      name: spring-boot-stage
      displayName: 'Spring Boot Stage'
      failFast: false
      # 构建步骤配置
      steps:
        # 第一步                               
        - step: mavenbuild@1
        ...
        # 第二步
        - step: agent-deploy@1
        ...

所以当我在 master 分支上提交代码时,这个流水线将会被执行。

执行分为两步,这也是我自己提前写好的。

第一步,maven 打包并上传到制品库 zhipinku。

- step: mavenbuild@1               # 采用 Maven 编译环境
  name: spring-boot-build-step     # 定义一个 ID 标识为 spring-boot-build-step ,名为「编译构建」的阶段
  displayName: '编译构建'
  inputs:                          # 构建输入参数设定
    jdkVersion: 8                  # 指定 JDK 环境版本为 1.8
    mavenVersion: 3.6              # 指定 Maven 环境版本为 3.6
    goals: |                       # 使用 mvnw 打包编译,并将构建的 Jar 包
      mvn clean package
      mkdir output-artifact
      cp target/*.jar output-artifact/
      cp target/start.sh output-artifact/
      cp target/Dockerfile output-artifact/
    uploadArtifact: true                    # 构建完成后是否将构建物作为制品产出,非必填项,与下方上传参数需同时定义
    uploadArtifactOptions:                  # 构建物上传参数,非必填项,与 `uploadArtifact` 参数需同时定义
      artifactPath: './output-artifact'     # 构建完成后要打包的构建物所在路径
      artifactRepository: 'zhipinku'         # 制品库名称,可以理解为一批构建物的集合
      artifactName: 'spring-boot-jar'        # 构建物打包后的制品名

制品库也是我提前创建好的,其实就是一个可以存放文件的地方。

第二步,将制品库的文件上传到目标服务器,用 docker 跑起来。

- step: agent-deploy@1                                # 定义通过 SA 部署插件
  name: deploy                                        # Step 唯一标识
  dependsOn: spring-boot-build-step
  displayName: '部署发布'                              # Step 显示名称
  inputs:                                             # Step 入参
    hostGroupID: 'aliyun'                       # 指定部署主机组ID
    minComplicating: 0                                # 允许的最小并发部署数量
    maxComplicating: 2                                # 允许的最大并发部署数量
    deployArtifact:                                   # 上传的制品项
      - name: 'compiled-artifact'                     # 上传部署的制品名(仅作为显示,无具体作用,允许重复)
        source: build@spring-boot-stage/spring-boot-build-step   # 部署制品文件引用自上游流水线 Stage/Step 的制品
        artifactRepository: 'compiled-artifact'       # 当制品引用自流水线,此参数可忽略
        artifactName: 'server'                        # 当制品引用自流水线,此参数可忽略
        target: /data                                 # 目标机器制品上传目录
        isForce: true                                 # 当目标存在时是否强制覆盖,默认为 true,可选
    script: |                                         # 部署脚本,到目标机器制品上传目录解压并启动构建程序,并通过curl检测
      cd /data
      ls
      tar -zxf spring-boot-jar.tar.gz
      cd output-artifact
      if test -z "$(docker ps -a -f NAME=pm-api -q)"; then echo "new docker run"; else docker rm -f $(docker ps -a -f NAME=pm-api -q); fi
      if test -z "$(docker images pm-api:0.1 -aq)"; then echo "new docker images"; else docker rmi -f $(docker images pm-api:0.1 -aq); fi
      docker build -t pm-api:0.1 .
      docker run -dit --name pm-api -p 8080:8080 pm-api:0.1
      echo "Deploy Success"
      sleep 10
      curl 127.0.0.1:8080

看,之前打包在制品库的文件 spring-boot-jar.tar.gz 会被上传到 aliyun 这个主机组。这个主机组也是我提前配置好的。 主机组下面有我添加的主机,是我自己购买的阿里云服务器。 当然,你可以自己再添加一个新主机。 按照它上面的说明,把命令复制到你的主机上执行一下,过一会下面就出现了可添加的主机了。

制品库文件上传到主机并解压后,随后执行的关键命令就是这两句。

docker build -t pm-api:0.1 .
docker run -dit --name pm-api -p 8080:8080 pm-api:0.1

这是首先用 docker build 构建一个镜像,然后用 docker run 启动这个镜像,生成一个 docker 容器。

当然更专业的方式是,提前将镜像上传到一个统一的镜像仓库,这里就直接把本地当做镜像仓库了。

这个 docker 容器对外暴露 8080 端口,并且和主机的 8080 端口绑定。浏览器访问 8080 端口,就可以看到最新的效果了。

从我 commit 代码并 push 到远程仓库后,我就没有做任何的事情,全部由各种自动执行并触发后续操作的流水线帮我们去做,省去了人工部署代码的麻烦。

整个过程也可以直观地看到,包括进度和失败与成功日志。

这就是 devops

结束得有点突兀,但 devops 就是这样,之后遇到什么需要手动处理的嫌麻烦的,都可以在流水线上不断加更加复杂和便捷的自动化脚本,其实是牺牲了配置流水线和维护流水线的时间,但方便了开发者除了写代码本身一切工作。

另外,现在的基础设施越来越强大了,就我上面实现的这个小 demo 产生的效果,在几年前可能是人们梦寐以求但不敢想象的,但现在几乎是点点点就能实现了。

springboot 一键搭建 web 应用,docker 搭建环境,各平台的 devops 集成工具也是越来越傻瓜式,还有无数云原生开发者以及爱好者在基础设施层自发贡献着力量,相信未来基础设施层会大有可为!

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8