部门决定从SVN迁移到GIT之初,我们暂定的是使用Jenkins作为CI/CD的实现,不过秉承实用的思想我们最终决定直接启用GitLab内置的GitLab-CI作为我们目前的CI/CD实现。
1. 概述
GitLab-CI 即为 GitLab Continuous Integration,也就是GitLab自带的持续集成工具。其思想就是每次用户push代码到gitlab上时触发执行
.gitlab-ci.yml
脚本,脚本的内容包括了测试,编译,部署等一系列自定义的内容。
与 Jenkins Pipeline 相比,GitLab-CI 更轻,更方便。它直接通过简单 yaml 文件定义 pipeline,相比与 jenkins 复杂的 groovy 语法,GitLab-CI 更简单。正如官方宣传的"Don’t let your tools slow you down"。
2. 配置GitLab-Runner
想要使用GitLab-CI,我们需要安装一些额外的组件GitLab-Runner。GitLab服务本身只负责任务的派发,具体的执行还是得交给Runner,这也符合最基本的设计准则——调度中心和执行分开,避免相互影响,方便迭代更新,也方便扩容。
GitLab Runner可以跑在一个单独的机子上。只需要这个机器需要能够访问GitLab服务本身。不过笔者建议进行单独安装,避免搅和在一起相互影响。软件开发是一个整体,前期偷的那点懒,之后会成倍地还回来。
这里以CentOS为例:
######## 准备工作
# 操作系统版本
$ rpm -q centos-release
centos-release-7-7.1908.0.el7.centos.x86_64
# 更改hostname, 让CI执行日志更有辨识度
$ sudo hostname 252Server
######## 安装
# 下载可执行包
wget -O /usr/local/bin/gitlab-runner https://gitlab-ci-multi-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-ci-multi-runner-linux-amd64
# 赋予执行权限
chmod +x /usr/local/bin/gitlab-runner
# 创建runner用户
useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
######## 注册Runner (目的是实现GitLab-Runner与GitLab-CI之间的信息互注册。Runner知道了自己需要操作哪个项目,CI也知道了该runner的存在。刷新Runners settings就可以看到新注册的Runner了。)
# 注意以下输入项大部分是可以在之后进行界面化修改的, 所以不用过分担心.
$ gitlab-runner register
Running in system-mode.
# 以下URL, TOKEN的来源参见下方截图
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://XXX.XXX.XXX.XXX/ # 注意这里使用默认端口80, 笔者经过尝试发现这里即使你特意配置了端口, 之后Runner拉取代码的时候依然是使用默认的80端口. 即使配置了clone_url也无效; 有知道的同学非常欢迎留言, 不甚感激.
Please enter the gitlab-ci token for this runner:
XXXXXXXXXXXXXXXX
Please enter the gitlab-ci description for this runner:
[localhost.localdomain]: XxxGoodName # 取个好名字, 方便自己, 也方便他人.
Please enter the gitlab-ci tags for this runner (comma separated):
pioneer,maven # 使用逗号分割.
Whether to run untagged builds [true/false]: # 默认值为false。这句话的意思是:是否在没有标记tag的job上运行,如果选择默认值false,那没有标记tag的代码提交是不会触发gitlab runner的,如果做测试,最好填true。
[false]: false
Whether to lock Runner to current project [true/false]:
[false]: false
Registering runner... succeeded runner=ZXxxxx
Please enter the executor: docker, shell, virtualbox, docker+machine, docker-ssh+machine, docker-ssh, parallels, ssh, kubernetes:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
######## 安装Runner并作为服务运行
gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
gitlab-runner start
# 查看服务状态
service gitlab-runner status
2.1 获取配置项URL和TOKEN
Runner大体分为两类:
- Shared Runner(所有项目共用的)
- Specific Runner(针对特定的项目)
2.2 GitLab中的Runner信息
- GitLab知晓的Runner配置信息。
- 归属于特定Project的Runner
2.3 几个关键路径
- 配置文件路径
/etc/gitlab-runner/config.toml on *nix systems when GitLab Runner is executed as root (this is also path for service configuration) ~/.gitlab-runner/config.toml on *nix systems when GitLab Runner is executed as non-root ./config.toml on other systems
- 工作目录
/home/gitlab-runner/
/home/gitlab-runner/ .bash_history .bash_logout .bash_profile .bashrc builds cache .m2 .oracle_jre_usage .ssh
3. 配置 .gitlab-ci.yml
.gitlab-ci.yml
这里直接给一个测试成功的SpringBoot应用编译, 打包, 部署的配置模板。
# 缓存服务, 如果有文件需要多个stages共用,例如jar/war包
cache:
paths:
- target/
variables:
USERNAME: "Xxxx"
PASSWORD: "Xxxx"
IP: "xx.xx.xx.xx"
# 本次构建的阶段:build package deploy
stages:
- build
- package
- deploy
# 构建 Job
build:
stage: build
tags:
- maven
script:
- echo "=============== 开始编译构建任务 ==============="
- mvn clean compile
# 打包
package:
stage: package
tags:
- maven # 这里和上面我们在注册Runner时候输入的maven tag对应
script:
- echo "=============== 开始打包任务 ==============="
# 这里的 ./ 路径指代项目根目录, 即: /home/gitlab-runner/builds/a9240569/0/root/projectName/
- mvn package -Dmaven.test.skip=true -P product -Dbuild.assemblySavePath=./target/
# 部署
deploy:
stage: deploy
tags:
- maven
script:
- echo "=============== 开始部署任务 ==============="
# 测试,是否能够通过 ssh 连通远程服务器
- sshpass -p $PASSWORD ssh -o StrictHostKeychecking=no [email protected]$IP
- echo "=============== 将 war 包部署到远程服务器上 ==============="
- sshpass -p $PASSWORD scp -o StrictHostKeychecking=no target/projectName-bin.zip [email protected]$IP:/root/projectName-bin.zip
- echo "=============== 开始执行 ==============="
# 执行shell脚本的时候必须要用命令:source xx.sh,如果只是单纯的执行命令./xx.sh,则切换目录命令cd不会被执行
- sshpass -p $PASSWORD ssh -o StrictHostKeychecking=no [email protected]$IP "cd /root && source ./deploy.sh"
4. 效果
单个Pipeline内部:
5. 关闭CI功能
- 参见 Office Site - enable_or_disable_ci,实现在项目级别管理CI功能:
- 全局范围内,依然是参见上述官方文档,这里就不展开了。
6. 概念解释
我们有必要对GitLab中的一些组件进行了解。
6.1 GitLab-CI
- GitLab-CI是GitLab Continuous Integration(Gitlab持续集成)的简称,是GitLab自带的一套持续集成工具。
- 从Gitlab的8.0版本开始,gitlab就全面集成了Gitlab-CI,并且对所有项目默认开启。(jenkins+webhook 也可以实现持续集成)
- 只要在项目仓库的根目录添加.gitlab-ci.yml文件,并且配置了Runner(运行器),那么每一次合并请求(MR)或者push都会触发CI pipeline。
6.2 .gitlab-ci.yml
这个是在git项目的根目录下的一个文件,记录了一系列的阶段和执行规则,包含一系列的执行脚本和指定的runner名称。GitLab-CI在push后会解析它,根据里面的内容调用runner来运行。
6.3 GitLab-Runner
GitLab-Runner是
.gitlab-ci.yml
脚本的运行器,Gitlab-Runner是基于Gitlab-CI的API进行构建的相互隔离的机器(或虚拟机)。GitLab Runner 不需要和Gitlab安装在同一台机器上,但是考虑到GitLab Runner的资源消耗问题和安全问题,也不建议这两者安装在同一台机器上。
可以分类两种类型:Shared Runner和Specific Runner。
- Shared Runner:所有工程都能够用的。只有系统管理员能够创建Shared Runner。
- Specific Runner:只能为指定的工程服务。拥有该工程权限的人都能够为该工程创建Shared Runner。
6.4 Pipelines
Pipelines是定义于
.gitlab-ci.yml
中的不同阶段的不同任务。
我们把Pipelines理解为流水线,流水线包含有多个阶段(stages),每个阶段包含有一个或多个工序(jobs),比如先购料、组装、测试、包装再上线销售,每一次push或者MR都要经过流水线之后才可以合格出厂。而
.gitlab-ci.yml
正是定义了这条流水线有哪些阶段,每个阶段要做什么事。
任何提交或者merge request的合并都可以触发pipeline。
stages
stages表示构建阶段。一次pipeline可以定义多个stages,他们特点如下:
- 所有stages会按照顺序运行。
- 所有stages完成后,该构建任务(pipeline)才会成功。
- 任何一个stage失败,后面的stages不会执行。
job
jobs表示构建工作,表示某个stage里面执行的工作。我们可以在stages里面定义多个jobs,这些jobs会有以下特点:
- 同一个stage中的的job会并行执行。
- 同一个stage中的全部jobs都成功时候,该stage才会成功。
- 如果任何一个job失败,那么该stage失败,即该构建任务失败。
6.5 Badges(徽章)
当Pipelines执行完成,会生成徽章,你可以将这些徽章加入到你的README.md文件或者你的网站。
7. Links
- gitlab-runner实现Spring Boot项目CI/CD
- 持续集成 Gitlab-CI 【Maven】
- Office SIte - CI - Introduction