今天花了一天时间,优化了一下代码。
原来是这样的。
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