每个公司内部都有自己的DevOps平台,来规范需求创建、开发编译、部署、测试、上线等等流程。Beetle是转转内部的DevOps平台,很好地加强了产品的开发效率及发布质量。其中为了实现通用性,Beetle对持续集成(CI)部分的构建命令,做了一定的强制规范。但是魔方项目(内部低代码搭建平台)的构建比较复杂,不能完全符合规范及其他原因,造成这个平台不能接入,导致在开发编译部署上线阶段还经常出现问题。最后,我们尝试用Gitlab的CI/CD来先行解决这些问题。
1、仓库根目录增加.gitlab-ci.yml
文件
2、监听.gitlab-ci.yml
文件内配置的触发时机
3、触发(例如push)并执行配置的job
通常情况,每个仓库下都需要配置.gitlab-ci.yml
文件。
但是因为业务关系,我们并不在每个仓库下都放置一个配置文件,我这里新建了一个仓库,这个仓库用来集成所有魔方项目的构建部署工作。
这种设计并非常规设计,只是提供一种思路,大家慎重使用。
以下为详细设计思路:
1、创建一个CI/CD仓库,添加.gitlab-ci.yml
文件
2、分别创建多个仓库项目的JOB,并且将具体逻辑放到子yml文件中
3、每个JOB的触发时机为,正则匹配特定分支
或变量
的push
4、特定分支或变量规则:需要部署的项目名+是否需要安装依赖+部署分支
5、以上操作都通过api传入变量来触发
大致流程图如下:
仅以Linux环境为例:
1、在项目编译的物理机上安装gitlab-runner
https://mp.weixin.qq.com/s/qG3XhYB1zbYKZztJcWtkcw
2、授权
sudo chmod +x /usr/local/bin/gitlab-runner
3、创建一个gitlab-ci用户
sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
4、安装,并作为服务启动
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start
5、注册
sudo gitlab-runner register
命令展示:
注册需要的信息获取路径:
Project → Setting → CI/CD → Runner → Expand
如图:
配置信息:
注册后状态(待激活):
6、激活
sudo gitlab-runner verify
激活后:
创建仓库并创建.gitlab-ci.yml
文件,因为我们部署多个项目,所以配置比较多,我们对这些任务进行拆分。其中用到include
关键字来实现拆分,最后我们的仓库结构如下图:
.gitlab-ci.yml 文件
stages:
- module-publish
- install
- build
variables:
NODE_VERSION: "12.22.4"
# 以下为接口传入的参数
# $TRIGGER_JOB_NAME # api触发的job名
include:
- '.gitlab-ci.install.yml'
.gitlab-ci.install.yml文件
.script-common-install: &script-common-install
- |
nvm use $NODE_VERSION
dev-install-package-common:
stage: install
resource_group: dev-install-package-common
script:
- *script-common-install
- echo "通用依赖安装完成"
only:
refs:
- /^.*\+module\+.*$/
variables:
- $TRIGGER_JOB_NAME =~ /^.*magic-common-component.*$/
tags:
- magic-work
简单描述一下:
1、定义这个Pipeline执行阶段及相应的全局变量,并引入外部YAML文件。
2、监听当包含+module+
的分支名发生push,或者trigger中变量包含magic-common-component
时,执行名为dev-install-package-common的JOB,先检查其他Pipeline中是否已经存在dev-install-package-common任务,如果有,则进入pending,如果没有则,在相应的stage阶段,在magic-work
这个runner中执行这个job中的script。
描述:用于定义JOB的执行组,并且JOB将在定义的stage阶段运行。
如果stages未在.gitlab-ci.yml文件中定义,则默认管道阶段为:
.pre → build → test → deploy → .post
特点:
同一阶段的作业并行运行。
下一阶段的作业在上一阶段的作业成功完成后运行。
我定义了三个阶段:
1、组件publish到npm库
2、安装依赖
3、编译代码
描述:定义变量,可以在全局和JOB中使用。
特点:
如果在全局进行了定义,则在创建管道时,每个变量都会复制到每个JOB配置中。
如果JOB已经定义了该变量,则作业级变量优先。
描述:模块化,引入外部 YAML 文件
特点:
与.gitlab-ci.yml
文件中的内容合并
无论include位置在哪里,都会先进行合并
最多嵌套100个
.gitlab-ci.yml
会覆盖include引入的相同关键字
include的文件类型包括以下几种:
include:local
include:file
include:remote
include:template
描述:Pipeline配置都是从JOB开始的, 其中JOB是.gitlab-ci.yml
最基本的元素
特性:
1、相同stage中的job会并行执行 2、相同stage中的job都执行成功时,stage才会成功 3、任何一个job失败,该 stage 失败,pipeline也会失败 4、可定义的数量不受限制
描述:定义作业在哪个阶段运行
特点:
如果stage未定义,则默认在test阶段执行
如果JOB在不同的runner上运行,它们可以并行运行(我试了下好像不太行,可能打开方式不对...)
如果在一个runner运行,想并行运行,则需要设置concurrent
来实现
描述:用于resource_group创建资源组,以确保同一项目的不同管道之间的作业互斥。
例如,如果属于同一资源组的多个作业同时排队,则只有一个作业启动。其他作业等到resource_group空闲为止。
描述:在单个管道中并行运行作业多次,并行作业从job_name 1/N到依次命名job_name N/N。
这个属性很有用,我们可以将一个大的任务,拆分成多个小任务并行执行,来节约执行时间
描述:指定运行器要执行的命令,我们这里用的shell
特点:
可执行单行命令
可输入多行命令,借助- |
来实现
支持YAML锚点:通过&
来定义复用script,通过*
来引入复用的script。
描述:使用only来控制何时将作业添加到管道
支持类型:
only:refs
only:variables
only:changes
only:kubernetes
我们这里用了ref(分支)和variables(变量)
当匹配到的分支被push时触发或当匹配到传入的变量时被触发
条件支持:正则表达式和一些条件判断方法
描述:选择特定运行器来执行script,即在注册runner时定义的tag
我们已经定义完我们的配置,我们这里通过push
分支来触发,接下来看下我们执行的Pipeline
Project → CI/CD → Pipelines
如图:
上图我们发现,有两个任务,但是第二个任务一直处于pending状态,要等到第一个任务完成后,才会执行第二个任务。
这是我们无法接受的,这会严重影响我们的效率。
前边提到JOB应该是并行执行的,那为什么还会一直pending呢?
其实默认情况下,gitlab-runner每次运行的job数量是1,我们这里需要修改一下,路径:
vi /etc/gitlab-runner/config.toml
修改执行数值
concurrent=20
再次运行,则并行处理
通过以上我们实现,通过分支push来触发JOB,但是还是需要一些操作成本的,为了更易用,我们决定通过api来触发。
获取Token
开启后,我们就可以通过接口来触发Pipeline了
主要分为4种:
1、Use cURL
curl -X POST \
-F token=TOKEN \
-F ref=REF_NAME \
http://gitlab.xxx.com/api/v4/projects/id/trigger/pipeline
2、Use .gitlab-ci.yml
trigger_build:
stage: deploy
script:
- "curl -X POST -F token=TOKEN -F ref=REF_NAME http://gitlab.xxx.com/api/v4/projects/id/trigger/pipeline"
3、Use webhook
http://gitlab.xxx.com/api/v4/projects/id/ref/REF_NAME/trigger/pipeline?token=TOKEN
4、Pass job variables 传入变量
curl -X POST \
-F token=TOKEN \
-F "ref=REF_NAME" \
-F "variables[RUN_NIGHTLY_BUILD]=true" \
http://gitlab.xxx.com/api/v4/projects/id/trigger/pipeline
之前我们一直都是通过不同分支名push来触发的,现在我们就可以通过api传入不同变量,来触发不同的JOB,分别执行不同的项目部署了。
以上为我们实现的基本原理,还有一些很强大的功能文中没有提到,例如cache、Kubernetes及更全面的api等等功能。如果大家感兴趣,可以进一步查看官方文档,写的很详细。
通过持续集成帮助我们减少大量重复工作,减少风险,快速构建等等优点,大家也快快用起来吧。就先写到这里,不对的地方也希望大家多多指正,一起进步~
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8