前言
在互联网行业中,当新产品的一个个需求确立下来,开发同学不仅仅需要进行代码开发,在每个功能完善的同时,都需要重新发布测试环境,换而言之,开发同学还肩负着持续的部署工作。
为什么需要频繁部署?
因为产品时由多个功能点组合而成,所以一般会拆分为各个功能点划分给不同的开发同学协同合作推进产品成型,每一个功能点完成后,都需要发布到测试环境交由测试同学进行验证,若出现 Bug,则告知开发同学进行修复,因此,在一个功能点完成后,一个 Bug 修复后,都需要发布到测试环境。
开发同学是如何进行部署工作的呢?
开发同学一般是在功能点完成或 Bug 修复后,进行一系列以下操作:
- ① 将代码打包
- ② 上传到测试环境服务器
- ③ 删除(备份)旧包,kill 旧包进程,start 新包进程
这一系列人工操作,是重复且会花费开发同学一定时间的。
那么,以上操作能否自动化?降低开发同学的部署时间,提升团队的工作效率呢?
当然可以,这个时候就需要使用 CI/CD 工具了,并且它的作用远不止于此。
GitLab
GitLab 是由 GitLab Inc.开发的一款基于 Git 的完全集成的软件开发平台(fully 集成软件 development platform)。另外,GitLab 且具有 wiki 以及在线编辑、issue 跟踪功能、CI/CD 等功能。
CI/CD
GitLab CI/CD 是 GitLab 内置的一款工具,用于通过持续方法论 (页面存档备份,存于互联网档案馆)(continuous methodologies)的软件开发。
该持续方法论包含三个部分:
- 持续集成(Continuous Integration,即 CI):每次在上传代码块到基于 Git 仓库时,持续集成会运行脚本去构建、测试、校验代码,这些操作是在合并到默认分支之前进行的
- 持续交付(Continuous Delivery,即 CD):在持续集成之后(即合并到默认分支之后),持续交付将进行手动部署应用
- 持续部署(Continuous Deployment,即 CD):在持续集成之后(即合并到默认分支之后),持续部署将进行自动部署应用
原理
当开发者配置了 GitLab CI/CD,那么当开发者使用 git 提交(commit),就会触发 CI/CD 相关的一系列操作,这一系列操作由 GitLab Runner 执行,相关配置记载于.gitlab-ci.yml
文件中,执行的结果将在 Gitlab 页面中展示。
部署
RPM 方式
下载 RPM 包之后进行安装配置即可。
下载
1 | wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-12.9.0-ce.0.el7.x86_64.rpm |
安装
1 | rpm -ivh gitlab-ce-12.9.0-ce.0.el7.x86_64.rpm |
配置
1 | # 编辑站点地址,默认 80 端口 |
时区配置
时区设置为”Asia/Shanghai”:1
49 # gitlab_rails[‘time_zone’] = ‘UTC’ —> gitlab_rails[‘time_zone’] = ‘Asia/Shanghai’
git 仓库存储目录配置
git 仓库存储目录默认为/var/opt/gitlab/git-data
,由于存储数据一般比较多,所以最好专门指定存储目录。
修改git_data_dirs
的配置:1
2
3
4
5380 # git_data_dirs({
381 # "default" => {
382 # "path" => "/mnt/nfs-01/git-data"
383 # }
384 # })
修改为:1
2
3
4
5380 git_data_dirs({
381 "default" => {
382 "path" => "/data/softwares/gitlab/data"
383 }
384 })
配置后初次启动
1 | # 配置,若无报错则配置后启动,会在 /opt/gitlab/etc 下生成各应用服务配置文件,在 /var/log/gitlab/ 存放日志 |
初始的 Gitlab 默认管理员帐户的用户名为root
后续若有配置修改要求,修改配置文件后使用命令gitlab-ctl restart
重启所有组件服务即可启用新的配置。
相关命令
命令 | 说明 |
---|---|
gitlab-ctl start | 启动 |
gitlab-ctl restart | 重启 |
gitlab-ctl stop | 停止 |
gitlab-ctl status | 状态 |
Docker 方式
1 | vim docker-compose.yml |
1 | version: '3' |
1 | # 启动 |
成功后浏览器访问10.57.22.19:8180
即可访问 Gitlab。
外部域名
若要通过外部域名访问可以通过如下配置:
1 | version: '3' |
注意http://test.gitlab.com
得反向代理到安装 Gitalb 机器的 ip + 80 端口,即 http://test.gitlab.com
–> 10.55.22.9:80
。
使用
基础设置
GitLab 安装完成之后,第一次打开 UI 界面时可设置管理员帐号密码(密码要求八位数)。
若忘记执行上面的操作,初始密码也可通过下面的命令查看:1
2
3
4
5
6
7
8
9
10sudo cat /etc/gitlab/initial_root_password
# WARNING: This value is valid only in the following conditions
# 1. If provided manually (either via `GITLAB_ROOT_PASSWORD` environment variable or via `gitlab_rails['initial_root_password']` setting in `gitlab.rb`, it was provided before database was seeded for the first time (usually, the first reconfigure run).
# 2. Password hasn't been changed manually, either via UI or via command line.
#
# If the password shown here doesn't work, you must reset the admin password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.
Password: Qz4D/O0Gd2AhwEZsI3qOVDJtEuyCvMx1vHQQ33yO4=
# NOTE: This file will be automatically deleted in the first reconfigure run after 24 hours.
在设置好管理员帐号之后,选择 🔧 (Admin Area),点击Settings
,选择General
进行属性设置
Account and limit
:将Gravatar enabled
前的 ✅ 关闭,禁止获取用户头像(影响性能造成卡顿)Sign-up restrictions
:将其下的Sign-up enabled
前的 ✅ 关闭,禁止用户注册帐号
用户管理
在 🔧 (Admin Area)下Overview
下的Dashboard
下存在以下三个面包栏:
Projects
:项目Users
:用户Groups
:群组
点击Users
中的New user
进行用户创建:
Account
:Name
:帐号昵称Username
:登陆用户名Email
:登陆邮箱
Password
: 添加用户后可以修改密码,用户第一次登陆后会被强制要求修改密码Access
:Project limit
:允许此用户创建的项目数,默认 100000,可以设置的小一点,如 100Can create group
:是否允许当前用户创建用户组,默认开启,可以关闭Access level
: 用户权限等级,可选:Regular
: 普通用户,可以访问他们的项目和群组Regular
: 管理员,可以访问所有组,项目和用户,并且可以管理此安装的所有功能
群组
作为程序员,借助代码管理工具(如 GitLab)来管理代码是再正常不过的事情了。
程序员基本都服务于软件公司,公司产品线可能有多条,那么一般会存在不同的开发部门,比如团队 A 负责开发 X 产品,团队 B 负责开发 Z 产品。
通常而言,对于不同团队的代码,权限各自隔离,比如说:
- X 产品的代码应当只有 A 团队人员才能看到
- Z 产品的代码应当只有 B 团队人员才能看到
为了做到团队间的代码权限隔离,GitLab 引入群组的概念,不同团队开发时可以分别新建群组,然后在群组下组建各自团队的人员,进行协同开发工作。
在 GitLab 新建组时,可见行等级设置值存在三个:
Private
:此群组内部项目只有项目组内的成员可以看到Internal
:此群组内部项目可被登陆用户看到Public
:此群组内部项目可被任何授权用户看到
大部分情况下,创建项目组时,可见行等级使用Private
。
数据迁移
若要将某台 GitLab 的数据迁移到另一台服务器上,需要进行如下操作:
- ① 在原服务器备份数据
- ② 在新服务器还原数据
数据备份
通过下面的命令可以进行数据备份操作。1
sudo gitlab-rake gitlab:backup:create
此命令执行后,会在/var/opt/gitlab/backups
文件夹下生成一个名为[TIMESTAMP]_gitlab_backup.tar
的tar
文件,此文件会包含所有的数据库数据、所有的repo
数据,以及所有的附件。
TIMESTAMP是以秒为单位的时间戳,用来区分不同的备份文件,如1650948390_2022_04_26_14.0.2_gitlab_backup.tar
。
数据还原
若要进行数据还原工作,我们需要确保还原的的tar
文件在配置文件中指定的备份数据存放目录(默认为/var/opt/gitlab/backups
)下面。
因此,我们需要首先将相关文件上传后放置到此目录下:1
2
3
4sudo cp 1650948390_2022_04_26_14.0.2_gitlab_backup.tar /var/opt/gitlab/backups/
# 更改文件权限
sudo chown git /var/opt/gitlab/backups/1650948390_2022_04_26_14.0.2_gitlab_backup.tar
sudo chgrp git /var/opt/gitlab/backups/1650948390_2022_04_26_14.0.2_gitlab_backup.tar
之后,就可以通过命令来停止相关服务器,然后执行恢复操作了:1
2
3
4
5
6
7
8
9
10
11
12
13
14# 停止相关数据连接服务,从 GitLab 13.0 开始,Puma 代替 Unicorn 作为默认的 Web 服务器,请根据版本选择执行相关命令
# gitlab-ctl stop unicorn
sudo gitlab-ctl stop puma
sudo gitlab-ctl stop sidekiq
# 确认状态
sudo gitlab-ctl status
# 从相关备份文件中恢复数据,恢复过程中需要按照提示输入两次 yes 并回车
# 注意:这里不需要带 _gitlab_backup.tar 后缀
sudo gitlab-rake gitlab:backup:restore BACKUP=1650948390_2022_04_26_14.0.2
# 重启 gitlab
sudo gitlab-ctl restart
注意事项
Docker 日志文件过大
使用 Docker 部署时限制日志文件时,日志文件会越来越大,由于即使修改限制重启后已有 Docker 无法生效,此时可以使用另一种方式去定时清理指定镜像的日志文件(root 用户):1
0 2 * * * cat /dev/null > /var/lib/docker/containers/88f47da0443c28baedcdbc38cc5db26fd3e3b8abd6ce6678321784aee0d78f39/88f47da0443c28baedcdbc38cc5db26fd3e3b8abd6ce6678321784aee0d78f39-json.log
版本一致
备份操作对gitlab
的版本是严格要求一致的,这代表两台 GitLab 的服务器版本必须一致才可进行数据迁移工作,我们可以通过以下命令查看gitlab
版本:1
2cat /opt/gitlab/embedded/service/gitlab-rails/VERSION
14.0.2
还原会将原 Gitlab 的帐号密码同步导入新 Gitlab 中。
迁移到 Docker
直接将备份文件上传到 Docker Gitlab 映射目录,之后进入容器进行还原操作,最后重启容器即可。
1 | docker-compose exec gitlab /bin/bash |
部分文件无法还原(可以忽略通过其他手段重置)
注意迁移时以下文件不会还原:
/etc/gitlab/gitlab.rb
/etc/gitlab/gitlab-secrets.json
手动上述文件传到新机器上对应目录覆盖即可。
1 | sudo chown root:root gitlab* |
迁移后命令报错
Gitlab 执行部分命令时,爆以下错误:1
OpenSSL::Cipher::CipherError ():
通过执行以下命令修复即可:1
2
3
4
5sudo gitlab-rails c
settings = ApplicationSetting.last
settings.update_column(:runners_registration_token_encrypted, nil)
settings.update_column(:encrypted_ci_jwt_signing_key, nil)
settings.save!
迁移后 CI/CD 界面报错 500
通过执行以下命令后刷新页面即可:1
2
3
4
5
6
7gitlab-rails dbconsole
# 查询出指定项目
select name, runners_token_encrypted from projects where name = 'xxx';
# 清除 runners
update projects set runners_token_encrypted = null where name = 'xxx';
# 也可以直接清除所有项目的 runners
update projects set runners_token_encrypted = null;
定时备份(Docker 方式)
编写脚本
1 | cd /data/software/gitlab/ |
1 |
|
定时执行脚本
Linux 安装 crontab 工具(有可跳过):1
yum install -y crontab
创建定时备份任务:1
2
3
4
5
6
7
8# 添加定时任务
crontab -e
# 每天凌晨一点执行
00 1 * * * sh /data/software/gitlab/gitlab_backup.sh
# 查看定时任务
crontab -l
版本升级
Gitlab 进行版本升级时,过程需要按三步走:
- ① 确定当前运行版本
- ② 确定升级目标版本
- ③ 确定逐个升级的版本
- ④ 按升级过程中的版本依次升级即可
实践
当前运行版本为【14.0.2】,升级目标版本为【15.0.2】,根据其确定当前版本和升级路径(Gitlab 升级只能逐个版本升级,不能跨版本),升级路径在官网——升级说明查看参照:
目标版本 | 当前版本 | 升级路径 | 说明 |
---|---|---|---|
15.1.0 |
14.6.2 |
14.6.2 -> 14.9.5 -> 14.10.5 -> 15.0.2 -> 15.1.0 |
需要依次升级三个版本: 14.9 , 14.10 , and 15.0 . |
15.0.0 |
14.6.2 |
14.6.2 -> 14.9.5 -> 14.10.5 -> 15.0.2 |
需要依次升级两个版本: 14.9 and 14.10 . |
14.6.2 |
13.10.2 |
13.10.2 -> 13.12.15 -> 14.0.12 -> 14.3.6 => 14.6.2 |
需要依次升级三个版本: 13.12 , 14.0 , and 14.3 . |
注意,首先我们需要将14.0.2
升级到次要版本14.0.12
因此,我们从运行版本为【14.0.2】到升级目标版本【15.0.2】依次需要经过以下版本:
14.3.6
14.6.2
14.9.5
14.10.5
15.0.2
若为docker
方式部署,可以依次下载相关镜像:1
2
3
4
5docker pull gitlab/gitlab-ce:14.3.6-ce.0
docker pull gitlab/gitlab-ce:14.6.2-ce.0
docker pull gitlab/gitlab-ce:14.9.5-ce.0
docker pull gitlab/gitlab-ce:14.10.5-ce.0
docker pull gitlab/gitlab-ce:15.0.2-ce.0
扩展——强制修改帐号密码
若忘记了 root 密码,可以通过下面的操作强制修改密码:1
2
3
4
5
6
7
8
9
10
11
12
13# 进入相关控制台
sudo gitlab-rails console -e production
#
# 找到自己需要重置的用户 id 号,管理员账户通常 id 为 1
user=User.where(id:1).first
# 修改密码
user.password='Qz4D/O0Gd1hwEZsI7qOVD22CvMxncxvHQQNfyO4='
# 确认密码
user.password_confirmation='Qz4D/O0Gd1hwEZsI7qOVD22CvMxncxvHQQNfyO4='
# 保存密码
user.save!
# 退出
quit
Gitlab-Runner
简介
GitLab Runner 是一个开源项目,用于运行作业并将结果发送回 GitLab。它与 GitLab CI 结合使用,GitLab CI 是 GitLab 随附的用于协调作业的开源持续集成服务。
部署
环境要求
- GitLab Runner 版本应与 GitLab 版本同步,避免兼容性问题
GitLab Runner 依赖于 Git,若未安装建议 root 用户执行安装 Git
1
2
3
4
5
6
7
8sudo yum -y remove git
sudo yum -y remove git-*
sudo yum -y install https://packages.endpointdev.com/rhel/7/os/x86_64/endpoint-repo.x86_64.rpm
sudo yum install git
# 查看版本
git --version若要使用 Docker 请安装最新版本,GitLab Runner 需要最少的 Docker
v1.13.0
下载与安装
1 | # 下载 gitlab-runner 的 rpm 包 |
安装成功后,将自动创建一个gitlab-runner
用户,gitlab-ci
的执行 Runner 时的用户目录~
都将指向/home/gitlab-runner
目录。
Runner 的类型与状态
GitLabRunner 存在三种类型的 Runner 对象:
shared
: 可以运行整个平台项目的作业(gitlab)group
: 可以运行特定 group 下的所有项目的作业(group)specific
: 可以运行指定的项目作业(project)
Runner 对象存在以下两种状态:
locked
: 锁定状态,无法分配到其他项目的作业当中paused
: 暂停状态,不会运行任何新的作业
Runner 注册到 GitLab
安装成功后,就可以将 GitLab Runner 注册到 GitLab 的 Runners 中,让它们两者配合工作。
那么,如何将 GitLab Runner 注册到 GitLab 的 Runners 中呢?
这需要经历以下步骤:
- ① 输入
gitlab-runner register
命令,开始注册工作 - ② 填入需要注册到的 GitLab 的 url 地址
- ③ 填入对应 Runner 的 token
- ④ 填入当前 Runner 的描述信息
- ⑤ 填入 tag 说明
- ⑥ 选择执行器的种类(包括 shell、docker 等)
下面是以上步骤执行过程的日志:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26# 开始注册 Runner
$ gitlab-runner register
Runtime platform arch=amd64 os=linux pid=20303 revision=4c96e5ad version=12.9.0
WARNING: Running in user-mode.
WARNING: The user-mode requires you to manually start builds processing:
WARNING: $ gitlab-runner run
WARNING: Use sudo for system-mode:
WARNING: $ sudo gitlab-runner...
# 输入 GitLab CI 的 URL
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://10.211.55.23:8888/
# 输入 GitLab CI 的 Token
Please enter the gitlab-ci token for this runner:
bSBM4D8GaNEr4-DzZvT-
# 输入此 Runner 在 GitLab CI 中的描述说明
Please enter the gitlab-ci description for this runner:
[Gitlab-Runner]: test
# 输入此 Runner 的 Tag
Please enter the gitlab-ci tags for this runner (comma separated):
test
Registering runner... succeeded runner=bSBM4D8G
# 选择执行器的类型(这里我们选择 shell )
Please enter the executor: shell, ssh, virtualbox, docker+machine, custom, docker, docker-ssh+machine, kubernetes, docker-ssh, parallels:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
三种类型的 Runner 对象 token 的获取方式
shared 类型(全局)
进入系统设置 -> Runners
注册全局 Runner:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16[admin@centos7aids data]$ sudo gitlab-runner register
Runtime platform arch=amd64 os=linux pid=25438 revision=8925d9a0 version=14.1.0
Running in system-mode.
Enter the GitLab instance URL (for example, https://gitlab.com/):
http://xx.xx.xx.xx:8180/
Enter the registration token:
s52PGzxxxtX8S7Qjqmhj
Enter a description for the runner:
[centos7aids]: global
Enter tags for the runner (comma-separated):
global
Registering runner... succeeded runner=s52PGzwz
Enter an executor: custom, docker, docker-ssh, parallels, kubernetes, shell, ssh, virtualbox, docker+machine, docker-ssh+machine:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
group 类型(特定组)
进入group -> Settings -> CI/CD -> Runners -> Group Runners
specific 类型(特定项目)
进入具体的项目 -> Settings -> CI/CD -> Runners -> Specific Runners
命令
见下表说明:
命令 | 说明 |
---|---|
gitlab-runner start | 启动 |
gitlab-runner stop | 停止 |
gitlab-runner restart | 重启 |
gitlab-runner status | 状态 |
gitlab-runner run | 运行 |
gitlab-runner register | 注册 |
gitlab-runner verify | 检查注册的 Runner 是否可以连接,但不验证 GitLab 服务是否正在使用 |
gitlab-runner verify –delete | 检查注册的 Runner 是否可以连接,删除无法连接的 Runner |
gitlab-runner list | 列出所有运行的 Runner |
gitlab-runner unregister | 在 GitLab 注销已注册的某个 Runner |
gitlab-runner unregister –url http://gitlab.example.com/ –token b5kan | 在 GitLab 通过令牌注销已注册的 Runner |
gitlab-runner unregister –name test-runner | 在 GitLab 通过名称注销已注册的 Runner |
gitlab-runner unregister –all-runners | 在 GitLab 注销所有已注册的 Runner |
gitlab-runner uninstall | 停止运行 GitLab Runner 并将其卸载 |
建议执行以上命令时使用 root 用户操作,避免文件权限问题。
1 | sudo gitlab-runner install --working-directory /home/gitlab-runner --user root |
流水线作业
通过 Gitlab CI 进行 CI/CD 操作,只用在代码仓库里编辑和维护一个.gitlab-ci.yml
文件,将需要完成的 job(作业)拆分一一编写进.gitlab-ci.yml
,每当代码有更新,Gitlab CI 会读取.gitlab-ci.yml
里的内容,生成一条 Pipeline (管道)去执行文件中创建的各种 job(作业),进行 CI/CD 的操作。
语法
要想编写合适的.gitlab-ci.yml
使作业运行在流水线当中,需要熟悉相关命令的语法。
Keyword | Description |
---|---|
script | 运行的 Shell 命令或脚本 |
image | 使用 docker 映像 |
services | 使用 docker 服务映像 |
before_script | 在作业运行前运行脚本 |
after_script | 在作业运行后运行脚本 |
stages | 定义管道中的阶段,运行顺序 |
only | 限制创建作业的条件 |
except |
限制未创建作业的条件 |
rules |
条件列表,用于评估和确定作业的选定属性,以及是否创建该作业。不能only 与/ except 一起使用 |
tags |
用于选择 Runner 的标签列表 |
allow_failure |
允许作业失败,失败的 job 不会影响提交状态 |
when |
什么时候开始运行工作 |
environment |
作业部署到的环境的名称 |
cache |
在后续运行之间应缓存的文件列表 |
artifacts |
成功时附加到作业的文件和目录列表 |
dependencies |
通过提供要从中获取工件的作业列表,限制将哪些工件传递给特定作业 |
retry |
发生故障时可以自动重试作业的时间和次数 |
timeout |
定义自定义作业级别的超时,该超时优先于项目范围的设置 |
parallel |
多个作业并行运行 |
trigger |
定义下游管道触发 |
include | 允许此作业引用外部 YAML 文件 |
extends | 该作业将要继承的配置条目 |
pages | 上载作业结果以用于GitLab页面 |
variables | 在作业级别上定义作业变量 |
job——作业定义
在每个项目中,均可使用名为.gitlab-ci.yml
的 YAML 文件配置GitLab CI / CD Pipeline (管道)。
在 Pipeline 中,可以定义一个或多个 job(作业),对每个 job 而言:
- 必须具有唯一的名称(不能使用关键字)
- 是独立执行的
- 至少要包含一个 script
如下,我们在 Pipeline 中定义了两个作业,每个作业运行不同的命令。命令可以是shell或脚本。
1 | job1: |
script——作业执行的脚本
script
命令代表 job 中要执行的脚本。
script
命令使用时需要用单引号或双引号引起来。
举个例子,包含冒号的命令( :
)需要加引号,以便被包裹的 YAML 解析器将其作为一个字符串,而不是一个键值对,因此使用特殊字符时要特别小心,特殊字符包括: :
、 {
、 }
、 [
、 ]
、 ,
、 &
、 *
、 #
、 ?
、 |
、 -
、 <
、 >
、 =
、!
、%
、 @
.
before_script
若想在每个作业之前运行脚本,可以使用before_script
命令。
对此命令而言:
- 取值必须是一个数组
- 既可在全局定义,也可在 job 中定义,在 job 中定义则会覆盖全局
1 | before_script: |
after_script
若想在每个作业(包括失败的作业)之后运行脚本,可以使用after_script
命 对此命令而言:
- 取值必须是一个数组
- 既可在全局定义,也可在 job 中定义,在 job 中定义则会覆盖全局
1 | before_script: |
before_script VS after_script
before_script
和after_script
有什么区别呢?
对after_script
命令而言,其执行失败不会导致作业失败,但若before_script
命令执行失败,则会导致整个作业失败,那么其他作业将不再执行。
另外,若作业执行失败,是不会影响after_script
命令运行的(这类似 Java 的 finally)。
only & except——作业的创建条件
作业什么时候会被创建?
在.gitlab-ci.yml
中,通过only
和except
两个参数定义相关策略对 job 的创建进行限制:
only
:定义了作业需要执行的分支或者标签except
:定义了作业不会执行的分支或者标签
下面是策略规则:
only
和except
可以使用正则表达式。only
和except
允许指定用于过滤 forks 作业的存储库路径。only
和except
可同时使用,若在一个作业中同时定义了only
和except
,则同时only
except
进行过滤(注意,不是忽略except
条件) 。only
和except
中可以使用特殊的关键字,如branches
、tags
、api
、external
、pipelines
、pushes
、schedules
、triggers
、web
、merge_requests
、chats
等,说明见下表:
值 | 描述 |
---|---|
branches | 当一个分支被 push 上来 |
tags | 当一个打了 tag 的分支被 push 上来 |
api | 当一个 pipline 被 piplines api 所触发调起 |
external | 当使用了 GitLab 以外的 CI 服务 |
pipelines | 针对多项目触发器而言,当使用 CI_JOB_TOKEN 并使用 gitlab 所提供的 api 创建多个 pipelines 的时候 |
pushes | 当 pipeline 被用户的 git push 操作所触发时 |
schedules | 针对预定好的 pipline |
triggers | 用 token 创建 piplines 时 |
web | 在 GitLab 的 Pipelines 标签页下,用户点击run pipline按钮时 |
特定分支
下面的例子,job将会只在*issue-开头的分支下执行。
1 | job: |
在这个例子中,job 只会在打了 tag 的分支,或者被 api 所触发,或者每日构建任务上运行
1 | job: |
默认策略
- 当一个作业没有定义
only
规则时,其默认为only: ['branches', 'tags']
。 - 如果一个作业没有定义
except
规则时,则默认except
规则为空。
因此,下面这个两个例子是等价的:
1 | job: |
tags——绑定作业执行时的 Runner
tags
关键字用于指定 GitLab Runner
运行时中使用哪一个 Runner 去执行作业。
下面这个例子中,只有注册 Runner 时定义了 ruby
和 postgres
两个标签的 Runner 才能执行作业:
1 | job: |
stages——作业执行顺序
既然.gitlab-ci.yml
文件中可以定义各种各样的作业,那么如何确定这些作业的执行顺序呢?
这可以借助stages
,在其中可以定义一系列的stage
(阶段)后,后续将不同的stage
和作业进行绑定,那么作业就会按照stages
中定义的stage
先后顺序依次执行。
举个例子:
1 | stages: |
我们定义了两个阶段,创建了两个作业绑定不同的阶段,这样就会先执行测试的 job1,然后在执行打包的 job2
variables
在 .gitlab-ci.yml
配置文件中可通过 variables
关键字配置全局变量或作业级局部变量,变量特点如下:
- 可以在
variables
关键字中定义非敏感性配置 - 可以在 GitLab WEB 界面定义一些敏感性配置变量,或者可能变动的变量
- 当
variables
关键字使用在作业层级时,它会覆盖全局变量或预定义变量 - 全局变量可以在各个作业中作业,而作业级别的局部变量只能在该作业中使用
- 在
script
中使用export
可以导出当前可用的变量信息 - 作业内部修改全局变量只对当前作用生效,不会影响其他作业
- 可以使用赋值语句对全局变量或局部变量进行重新赋值
when——作业能否执行
when
参数用于对当前作业是否执行添加时机限制策略。
when
取值策略包括:
on_success
:只在前置执行过的所有作业都成功时才执行当前作业,默认值,因此有任何失败时管道流会停止执行后续任务on_failure
:只在前置执行过的作业中有一个失败的时候才执行always
:无论之前作业执行状态如何,总是执行manual
:在 GitLab UI 页面手动执行作业delayed
: 延迟执行作业(前面的作业结束时计时器马上开始计时),配合start_in
关键字一起作用,start_in
设置的值必须小于或等于 1 小时,start_in 值示例: 10 seconds 、 30 minutes 、 1 hour
artifacts
artifacts
用于指定在作业成功、失败、或者一直等待状态下时,将一系列的文件或文件夹附加到作业中。
artifacts
可以称为 工件或者归档文件- 作业完成后,工件被发送到 GitLab,可以在 GitLab Web 界面下载
- 默认情况下,只有成功的作业才会生成工件
- 并不是所有的
executor
执行器都支持工件 - 工件的详细介绍可参考 Introduction to job artifacts
paths
artifacts
中paths
参数可指定哪些文件或文件夹会被打包成工件(仅可使用当前项目工作空间内的文件)
- 要在不同作业间传递工件,需要额外使用
dependencies
参数
下面示例,将目录 binaries/
和文件 .config
打包成工件:
1 | artifacts: |
禁用工件传递
若要禁用工件传递,可使用空依赖关系定义作业:
1 | job: |
工件优化存储
可仅为打标记的release
发布版本创建工作,以避免临时构建产生大量的存储需求:1
2
3
4
5
6
7
8
9
10
11
12
13
14default-job:
script:
- mvn test -U
except:
- tags
release-job:
script:
- mvn package -U
artifacts:
paths:
- target/*.jar
only:
- tags
上面的示例中,default-job
作业不会在打标记的release发布版本中执行,而 release-job
只会在打标记的release发布版本执行,并且将 target/*.war
打包成工件以供下载。
name
工件的默认名称是 artifacts
,当下载时名称是 artifacts.zip
。
通过 artifacts:name
关键字可以自定义工件的归档名称,这样你可以为每个工件设置独一无二的名称,归档名称可以使用预定义的变量。
如果分支名称中包含斜杠(比如 feature/my-feature
),推荐使用 $CI_COMMIT_REF_SLUG
代替 $CI_COMMIT_REF_NAME
作为工件名称。
使用作业名称使用工件名称:
1 | job: |
使用当前分支或tag版本标签名作为工件名称:1
2
3
4
5job:
artifacts:
name: "$CI_COMMIT_REF_NAME"
paths:
- binaries/
同时使用当前作业名称以及当前分支或tag版本标签名作为工件名称:
1 | job: |
untracked(使用较少,了解即可)
untracked
可将未加入 git 版本库的文件作为工件文件。
artifacts:untracked
将会忽略配置文件.gitignore
。
将所有的未跟踪文件打包成工件:
1 | artifacts: |
将所有的未跟踪文件以及目录 binaries
中文件打包成工件:1
2
3
4artifacts:
untracked: true
paths:
- binaries/
when(使用较少,了解即可)
when
用于在作业失败时或者忽略失败时上传工件。
when
可以设置以下值:
on_success
:默认值,当作业成功上传工件on_failure
:当作业失败上传工件always
:无论作业是否成功一直上传工件
expire_in
expire_in
用于设置工件的过期时间。
- 你可以点击界面上的
Keep
保持按钮,永久保存工件 - 工件到期后,默认情况下每小时删除一次工件(通过 cron 作业),删除后不能再访问该工件
- 工件默认有效期为 30 天,可通过
Admin area
–>Settings
–>Continuous Integration and Deployment
设置默认有效期
下面示例中工件有效期为一小时:1
2
3job:
artifacts:
expire_in: 1h
reports
reports
用于收集测试报告,并在GitLab UI界面中显示出来。
- 无论作业是否成功,都会收集测试报告
- 可以通过设置工件的打包路径
artifacts:paths
添加测试的报告输出文件。 artifacts:reports:junit
可以用来收集单元测试的报告,查看 JUnit test reports 获取更详细的信息和示例
dependencies
dependencies
依赖关键字需要和 artifacts
工件关键字联合使用,允许你在不同作业间传递工件。
- 默认情况下,会传递所有本作业之前阶段的所有工件
- 需要在作业上下文中定义
dependencies
依赖关键字,并指出所有需要使用的前序工件的作业名称列表。 作业列表中不能使用该作业后的作业名称 。 - 定义空的依赖项,将下不会下载任何工件
- 使用依赖项不会考虑前面作业的运行状态
快速入门示例如下:
1 | # 在 build:osx 和 `build:linux` 两个作业中,都定义了工件 |
上面示例中,
parallel——相同作业并发执行
一种作业允许并行执行,通过parallel
参数指定并行执行的实例数,取值必须大于或等于 2 并且小于或等于 50。
携带parallel
参数的作业将创建 N 个并行运行的实例. 它们从job_name 1/N
到job_name N/N
依次命名。
1 | test: |
实战:Java 项目自动部署
一般 Java 项目会使用 Maven 工具打包,因此若想通过 GitLab-Runner 自动部署 Java 项目,需要在 GitLab-Runner 所在服务器安装 Maven 环境。
Maven 环境搭建
1 | yum install -y java-1.8.0-openjdk-devel.x86_64 |
1 | # 下载 maven,地址:https://maven.apache.org/download.cgi |
1 | # 修改 maven 配置文件 |
1 | # 赋予 gitlab-runner /data 目录访问权限 |
应用服务器通道建立
一般情况下,GitLab-Runner 服务和 Java 应用分别部署到两台不同的服务器上,因此 GitLab-Runner 自动部署应用时需要和 Java 应用服务器建立连接,连接可以使用以下两种方式:
- ①
sshpass
指定密码连接 - ②
ssh
配置密钥,免密登陆
这里我们使用常用的第二种方式,配置步骤如下:1
2
3
4# 生产密钥
ssh-keygen
# 复制公钥到指定服务器
ssh-copy-id -i ~/.ssh/id_rsa.pub user@xxx.xxx.xxx.xxx
脚本编写
在后端应用增加.gitlab-ci.yml
并配置脚本:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36variables:
package_path: target
package_name: gateway.jar
remote_server: admin@10.22.39.22
remote_post: 22
upload_path: /data/backend/gateway/tmp
start_path: /data/backend/gateway
stages:
- build-upload
- restart
maven-build-upload:
stage: build-upload
only:
- dev_1.0
tags:
- test
before_script:
- mvn clean install -Dmaven.test.skip=true
- echo "package success!!!"
script:
- scp -vr -P $remote_post ./$package_path/$package_name $remote_server:$upload_path
- echo "upload success!!!"
dependencies: []
retry: 2
restart:
stage: restart
only:
- dev_1.0
tags:
- test
script:
- ssh -p$remote_post $remote_server "cd ${start_path}; ./deploy.sh"
dependencies: []
注意
通过ssh
执行上面部分脚本时可能成功,如通过ssh
执行java -jar
启动应用时,发现找不到JAVA_HOME
。
研究后发现远程登录和直接登录执行的文件是不一样的:
/etc/profile
:当用户登录时,该文件被执行/etc/bashrc
:当bash shell
被打开时,该文件被执行
ssh
作为远程登录的方式进入,触发执行的是/etc/bashrc
文件,而不是/etc/profile
,所以会发生找不到JAVA_HOME
的问题,因此,需要将java
的配置信息配置到bashrc
的文件中去,配置步骤如下所示:
- ① 命令 vim ~/.bashrc 进入到文件;
- ② 文件末尾增加 Java 相关变量保存退出
- ③ 执行
source ~/.bashrc
命令更新
实战:前端项目自动部署
Node 环境搭建
1 | mkdir -p /data/softwares |
文件末尾增加:1
export PATH=$PATH:/data/softwares/node-v14.17.0/bin
刷新配置生效:1
source /etc/profile
测试是否成功:1
node -v
1 | # gitlab-runner 用户下 |
1 | # 赋予 gitlab-runner /data/softwares 目录访问权限 |
应用服务器通道建立
同上。
脚本编写
在前端应用增加.gitlab-ci.yml
并配置脚本:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52variables:
remote_server: admin@192.168.0.20
remote_post: 22
upload_path: /data/golden/frontend/tmp/system
front_path: /data/golden/frontend/system/
compress_file: dist.tar.gz
stages:
- install-build
- dist-upload
- deploy
#cache:
# key: ${CI_BUILD_REF_NAME}
# paths:
# - node_modules/
install-build:
stage: install-build
tags:
- global
only:
- test
# 执行脚本
script:
- npm install
- npm run build:test
artifacts:
expire_in: 48h
paths:
- dist/
after_script:
- "cd ${CI_PROJECT_DIR}/dist; tar -cvf ${compress_file} *"
# 上传压缩包
dist-upload:
stage: dist-upload
tags:
- global
only:
- test
script:
- scp -vr -P $remote_post ${CI_PROJECT_DIR}/dist/${compress_file} $remote_server:$upload_path
# 解压更新
deploy:
stage: deploy
tags:
- global
script:
- ssh $remote_server "mv ${upload_path}/${compress_file} ${front_path}"
- ssh $remote_server "cd ${front_path}; tar -xvf ${compress_file}"
参考
文章信息
时间 | 说明 |
---|---|
2022-03-23 | 初稿 |
2022-03-26 | 完稿 |
2022-06-19 | 新增数据迁移小节 |
2022-12-16 | 新增定时任务备份小节 |
2023-02-12 | 新增定 CI/CD 实战小节 |