通过技术手段保证gitlab中项目某个版本的可用性,当我想发布新版本时随实可以tag出一个可用的版本。与github配套的是travis,使用非常简单,只需要将github账户与travis绑定就可以选择保护的项目及版本,但是要在gitlab上实现类似的功能就只能靠自己来搭建了,今天就来介绍下gitlab-runner是如何工作的。
1 Maintainer职责是最重要的,负责代码的review、approve merge、关心test结果,是master代码质量的第一负责人。
2 通过gitlab-runner运行pipeline,可以根据自己的需要编写复杂度不同的pipeline,初期只用在单元测试即可,fork版中的测试环节是非必需的,master版本中的测试环节是必须的。
Runner分为共享型(Shared Runner)和特享型(Specific Runner),因为gitlab项目语言种类和运行环境复杂多样,我们选用Specific Runner型。
项目中添加.gitlab-ci文件定义runner要做的事情,tag决定哪个runner来执行。
在centos7上安装最新版本gitlab,我的版本是GitLab Enterprise Edition 11.3.4-ee
#安装依赖:
sudo yum install postfix
sudo systemctl enable postfix
sudo systemctl start postfix
#安装企业版gitlab
sudo yum -y install gitlab-ee
#修改gitlab访问地址和端口号(external_url)
sudo vi /etc/gitlab/gitlab.rb
#配置修改生效
sudo gitlab-ctl reconfigure
按照自己配置的external_url去访问gitlab,首次登陆需要设置administrator的密码
Runner分为共享型(Shared Runner)和特享型(Specific Runner)两种,共享型可以被gitlab上所有project公用;特享型绑定project只被指定使用。
由于我的业务java、php、python各种语言都有,每条产品线运行环境也存在差异,所以倾向采用Specific Runner
Runner可以安装在独立的vm内,也可以安装在容器内,这里的Specifig Runner我们运行在docker中。
注意:runner不要与gitlab安装在一起,注册发现会有问题。
docker的安装以前博文有介绍过,这里不再详解,重点是获取gitlab/gitlab-runner这个image。
sudo docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
先在gitlab的CI/CD页面找到url和token,如图
#进入容器
sudo docker exec -it gitlab-runner /bin/bash
#容器中完成注册
gitlab-runner register \
--non-interactive \
--url "http://10.100.129.113:8090" \
--registration-token "S1Erstg39-nh1xQVMtBN" \
--executor "docker" \
--docker-image maven:latest \
--description "193runner " \
--tag-list "193" \
--run-untagged \
--locked="false"
重要参数说明:
url和token参考上图,在runner需要对接的gitlab中获得;
executor是runner中pipeline以什么方式运行,这里选择的是docker方式,其实还支持shell等其它方式。
docker-image是runner中pipelne以哪个image为基础来执行executor。
tag-list是runner的tag,在gitlab的project中关于ci的配置文件中会引用得到。
Runner注册成功后就会在gitlab的CI/CD页面看到下图中的红框内容:
如果出现灰色的runner说明runner虽然注册上来但是不可用,当gitlab与runner安装在同一台机器时就会出现这种情况,所以请尽量分开。
在项目根目录下添加.gitlab-ci.yml文件,gitlab-ci很强大,本质就是以yml的格式定义了一个pipeline,与jenkins存在功能重叠的部分,由于我们只是利用runner做项目master版本的单元测试,所以只需要在gitlab-ci中执行maven test。
.gitlab-ci.yml内容如下:
image: maven:latest
stages:
- test
job_test:
stage: test
script:
- mvn test
tags:
- '193'
限制只有maintainers才可以push和merge项目的master版本
项目准备 maven-jdk1.8-Junit,可以在我的GitHub中直接下载:https://github.com/yejingtao/runproject.git
验证步骤:
以maintainers用户直接push,成功,同时触发pipeline。
5.2.1 模拟直接提交
用developer用户clone出runproject项目,直接push,因权限不足失败。
5.2.2 fork 提交push到自己
Developer用户从runproject项目中fork出自己版本,直接push可以成功,因为他是自己版本的maintainer
5.2.3 发起PR
Developer修改代码并push到自己fork项目后,发起PR
5.2.4 maintainer用户mergePR
Maintainer登陆gitlab后会看到RP通知,有两种merge方式:
下拉列表第一种是Developer自己的fork版本通过pipeline测试后再merge进master版本;第二种是直接merge进master版本。无论选择哪一种,都会触发master版本的一次pipeline。
因为我们的目的只是保证master版本的可用性,所以推荐第二种。
5.2.5 master revert本次操作
如果merge一次PR后pipeline没有通过或者其他形式发现代码不可用,可以在PR页面找到当此PR,执行Revert。
Revert的本质其实就是以老版本重新发起一次PR,所以Revert后也会触发一次pipeline。
1 .gitignore中记得要把.gitlab-ci.yml添加进去,不要被随意修改。
2 如果要通过mvn test来做单元测试需要严格按照框架的命名规则,例如Junit默认测试Test结尾的类。
3 Executor Image的选择要给予自己项目的场景,对于Specific Runner由研发自定义docker的image,可以提高执行效率。
每次pipeline利用maven做单元测试时都会重新拉取代码的依赖包,如果有办法利用volume等手段缓存依赖的话可以提高测试效率。
理解了前面的原理,缓存的设置需要做两部份工作:1如何在docker中通过volume让maven的仓库可以直接在宿主机上挂载;2如何在gitlab-ci中进行配置。
修改/srv/gitlab-runner/config/config.toml文件,我们从前面docker命令-v就可以看得出修改这里其实就是在修改runner容器中注册的问题件,修改如下:
[[runners]]
name = "193runner"
url = "http://10.100.129.113:8090"
token = "327781c1630cef378aa4c62441a4e4"
executor = "docker"
[runners.docker]
tls_verify = false
image = "maven:latest"
privileged = false
disable_cache = false
volumes = ["/var/runcache:/cache:rw"]
shm_size = 0
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
volumes这一行是关键,把宿主机的/var/runcache目录挂在到maven executor容器的/cache盘符下,并赋予读写权限。
在.gitlab-ci.yml中添加如下几行:
variables:
MAVEN_OPTS: "-Djava.awt.headless=true -Dmaven.repo.local=./.m2/repository"
cache:
paths:
- ./.m2/repository
优化前:
优化后:
可以看到效率得到明显的提高,再让我们看下宿主机的/var/runcache中到底有什么:
可以看到/var/runcache/${gitlab_username}/${project_name}/default目录下有个cache压缩文件,解压后里面就是.m2仓库文件了,里面就是项目缓存的依赖包了。
你可以修改项目的pom.xml添加新的依赖,再来这个cache中看下就可以确定自己的猜测了。
gitlab与runner的版本需要匹配使用,如果版本不匹配会出现runner无法注册、runner注册后无法连接、runner无法运行executor等一系列莫名其妙的错误。
例如我公司由于历史包袱的原因,现在使用的gitlab是企业版8.1,我就在搭建这套环境中吃够了苦头。
1 gitlab-runner是9.0以后的产品,它的前身是gitlab-ci-multi-runner,所以用gitlab-runner是无法注册成为gitlab的runner的,像我的gitlab8.1版本的gitlab-ci-multi-runner对应的是1.8.5版本,下载地址:https://packages.gitlab.com/runner/gitlab-ci-multi-runner/packages/fedora/21/gitlab-ci-multi-runner-1.8.5-1.x86_64.rpm
2 .gitlab-ci.yml中的cache是gitlab8.2版本添加的属性,所以在我公司的版本中会报无法识别的错误,需要去掉。如果你想多个maven的executor之间共享local repository,可以修改config.toml中的volume,把宿主机的一个目录挂到executor的容器中去,然后在config.toml的variables中指定maven的本地仓库,例如:MAVEN_OPTS: "-Djava.awt.headless=true -Dmaven.repo.local=/root/.m2/repository"