本文最后更新于 5 年前,文中所描述的信息可能已发生改变。
起因
事情的起因也是来自工作中跟我们日常密切相关,而又没有机会接触到的东西:CI。项目脚手架自带了 CI 脚本,只需要稍作修改就可以直接使用;GitLab 上的项目的 CI 配合也不需要我们管,直接使用Public Runner就行了。时间长了自然就对这方面比较感兴趣,想知道其中的原理。正好搭建了服务器,部署好了 GitLab,于是说干就干,开始着手做自己的 GitLab CI 配置。
过程
CI 脚本
已经知道了在项目上执行的东西,包括推代码、打 tag 都会导致 CI 的自动执行,而什么情况执行什么 CI 的 stage 就由项目根目录下的.gitlab-ci.yml 文件决定。因此找到一个项目的 CI 文件看看是怎么写的:
image: xxxxxx:maven-openjdk8-onbuild
stages:
- build
- release
test:
stage: build
script:
- rm -rf test_target/* && mkdir -p test_target && mvn -U clean package -Dmaven.test.skip=true -P test
- cp -a oms-web/target/oms-web.jar test_target/ROOT.jar
- chmod +x ./test_target/ROOT.jar
- cp -rf ./.dockerignore ./test_target && cp -rf ./Dockerfile ./test_target
environment: test
only:
- /^neo-java-test-.*$/
except:
- branches
artifacts:
paths:
- test_target/*
untracked: false
neo-image-upload:
stage: release
image: xxxxx:docker19.06-base-image
script:
- mi_env=$(echo $CI_COMMIT_TAG | awk -F '-' '{print $3}')
- cd ./$mi_env'_target'
- docker login hub.pf.xiaomi.com -u $HUBUSER -p $HUBPASS
- docker build . -t xxxxxx.xxx.xxx/$(echo $CI_COMMIT_TAG | awk -F '-' '{print $2"-"$3}'):$CI_COMMIT_TAG
- docker push xxxxxxxxx.xxx.xxx]、/$(echo $CI_COMMIT_TAG | awk -F '-' '{print $2"-"$3}'):$CI_COMMIT_TAG
environment:
name: neo
only:
- /^neo-.*$/
except:
- branches
...首先上来是先定义CI 需要的基本 docker 镜像,不管你 CI 的目的是什么,最终都是要执行一段代码,这部分代码一定需要个环境去执行的,这个环境就是来自于声明的镜像类型。下面是定义了 2 个执行阶段:build 和 release。在 gitlab 平台上 CI 的过程状态图可以知道:这里是定义了他们执行的先后顺序:需要先构建好项目的产出可执行包,再推送到指定的容器中供启动。下面 2 部分则是定义了具体的 stage 的条件和执行的内容。stage:指定为哪个执行阶段。image:指定该阶段使用的镜像。script:该阶段执行的代码,一般为 shell 脚本。only:指定该阶段执行的触发条件,一般为分支或 tag 名。
根据上面的 ci 脚本,我定义一个最简单的 CI 脚本:
image: docker:dind
stages:
- stage1
- stage2
stage-first:
stage: stage1
script:
- echo 'I am first executed!'
only:
- master
artifacts:
paths:
- prod_target/*
stage-second:
stage: stage2
script:
- echo 'I am second executed!'
only:
- master定义了 2 个阶段,分别打印字符串。
CI Runner
完成上面的 CI 脚本后我迫不及待的将分支合到 master 并推送到远程,期望他能立刻执行出结果。可是 GitLab 上显示的CI 状态为:Pending:No Runner available for pipeline。表明没有可以用来执行CI 的 Runner。那么就需要查找跟 Runner 相关的信息。得知:Runner 是支持多节点的独立部署的服务,在机器上启动 Runner 管理服务后注册一个新的 Runner,将其绑定到对应的 GitLab 上(可以绑定为一个 GitLab 库公用或者一个指定 repository 专用)就可以用来执行 CI 了。
安装 gitlab-runner
此时我就去找 Runner 的安装了。我直接运行:
sudo apt-get install gitlab-runner安装成功,但是此时执行再执行:
sudo gitlab-runner register想注册一个 Runner 并绑定到我的 GitLab 上发现总是失败。
Runner 的坑
经过一番搜索,知道了 GitLab 和 Runner 的版本有约束:8.X 版本的 GitLab 只支持 1.X 版本的 Runner 服务,而 apt 自动安装的为 13.X 版本的了,无法兼容。于是就需要开始搜索互联网上的 1.X 版本的 Runner 安装程序。
Runner 的 RELEASE:没有 1.X 版本。
Runner 的 Tag 列表:有 1.X 版本的 tag 但是没有 artifacts 产物。
各大镜像站:只有 10.X 开始版本的 Runner 安装程序。
看似已经山穷水尽了。忽然灵光一现:你虽然可以删除 RELEASE 的旧版本,但是你打版本 tag 的那次 CI 一定有输出到的路径,我就去追溯你那个生成 artifact 的路径不就可以了?果然,被我找到了导出到 AWS 的文件~

找到了安装文件后就是顺利的安装过程~直接用命令说明吧:
scp ~/Downloads/gitlab-ci-multi-runner_i386.deb haoxingxiao@XXX.XXX.XXX.XXX:~/
ssh XXX.XXX.XXX.XXX
sudo dpkg -i gitlab-ci-multi-runner_i386.deb
sudo gitlab-runner register
(gitlab url)
> http://XXXXXXXX.XXX.XXX/ci/ // 注意这里需要提供 /ci 路径
(token)
> XXXXXXXXXXXXXX
(runner name)
> tencent-cloud-runner
(tags)
> tencent,common
(allow untagged task?)
> true
(choose type:docker,shell & etc.?)
> docker执行 CI
配置好 Runner 后就可以在 GitLab 上看到创建成功的 Runner 了:

这里我已经把租的阿里云服务器和腾讯云的服务器都配置上去了,构成了多个节点的 Runner 集群,当 CI 任务进入后会自动寻找空闲的 Runner 去执行。其实同一个容器绑定多个 Runner 也可以,不过负载就都在一台容器上了。
而刚才 Pending 的 CI 也开始执行了。学习了一下 CI 脚本的语法和知识,最终运行的结果如下图:


最终达到了搭建自己的自动化 CI 的环境~也利用了开源免费的 badge 服务 给项目的 README 增加了一个构建 CI 状态的徽章:

方便直观在项目主页查看状态。
后续
经过搭建 GitLab 和搭建 GitLab CI 2 步之后,下一步有好几个想要做的东西:
- Git Talk 服务
- 创建 Feishu SDK 项目,部署飞书通知的服务,并接入 CI,实现主动推送构建结果到飞书客户端。
- 进一步配置 Blog,目前 Blog 弄的比较仓促,很多信息和配置还没加上去。
今天就先写这么多吧~难得有摸鱼的机会弄自己的东西,希望还能一直保持这种热情做下去!☀️