GitLab CI (Continuous Integration)是GitLab内置的进行持续集成的工具。基于特征分支开发后,需要发起Merge Requests
合并共享代码库。Merge Requests
总是频繁发生,合并请求过来后,可以触发流水线自动去构建、测试、验证新代码功能,及早发现错误,减少集成问题。我们也总是希望在任何时候都能发布稳定版本的软件,自动推送功能变更到演示环境,甚至是生产环境,完成持续地交付(Continuous Delivery)和部署(Continuous Deployment),以减少部署带来的风险和及时得到客户的反馈。通过Gitlab CI减少了人为错误的机会和跨团队沟通成本,提高整个团队的效率。
GitLab CI/CD作为Gitlab整个DevOps生命周期的重要组成部分,对应用的构建、测试、部署和监控都起到重要作用。对于Docker、Kubernetes等容器化技术有着天然的集成,简直就是为云原生而生。
对于Gitlab项目集成CI/CD很容易上手,像之前【Gitlab概览】提到过的那样,只需两个步骤:1、安装Gitlab-Runner
及配置,2、工程目录下创建和编写.gitlab-ci.yaml
文件。
Gitlab-Runner
GitLab-Runner
是一个Go语言编写的开源项目,用于运行Job并将结果发送回GitLab,它与GitLab CI/CD一起,协调持续集成服务。它能部署到任何一个地方、任何一个平台,只要它能ping通Gitlab。多个项目可以使用同一个Gitlab-Runner
,一个项目也可以使用多个Gitlab-Runner
,而Gitlab-Runner
还可以并发地执行多个Job,它是灵活的,减轻了Gitlab构建项目的负担。Gitlab-Runner
对Docker、Kubernetes的等天然支持,使得项目与容器云服务有很好的集成。
Gitlab-Runner类型
主要有三种类型的Runner:Shared、Group 、Specific。
Shared Runners | 适用于所有应用,且只有系统管理员能够创建 |
---|---|
Create a group Runner | 项目组下的所有应用,具有组权限的人才能创建 |
Specific Runners | 特定项目使用 |
我们可以用管理员账号登录,注册Shared Runner
安装Gitlab-Runner
安装Gitlab-Runner
的版本要注意与Gitlab的版本一致。可能由于新版本引入新功能特性或者Bug,存在版本差异,版本不一致可能造成无法预知的后果。
以CentOS7,Shell
执行器为例,可以利用官方的一键脚本安装最新版本的Gitlab-Runner
# For RHEL/CentOS/Fedora
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash
也可以使用软件源,安装特定版本,注意修改软件源
# For RHEL/CentOS/Fedora
sudo yum install gitlab-runner
# for RPM based systems
yum list gitlab-runner --showduplicates | sort -r
sudo yum install gitlab-runner-10.0.0-1
安装时会自动创建Gitlab-Runner
的用户,并用这个用户账号运行CI任务。需要注意权限问题。对应Linux root用户,Runner使用的默认配置路径/etc/gitlab-runner/config.toml
,对于修改配置,如,并发数参数等,大多数选项,可以不需要重启。默认每5分钟检查一次文件,自动获取所有更改。
Gitlab-Runner注册
Gitlab-Runner
拉取Gitlab代码需要授权,这时需要注册URL和Token。以CentOS7,Shell
执行器为例,键入命令
#sudo gitlab-ci-multi-runner register
sudo gitlab-runner register
按步骤,交互式访问需要依次输入GitLab URL、Gitlab token、Description for the Runner、Tags associated with the Runner、Runner executor等等。非容器化项目,Executor这里选Shell
,如果想将项目部署到容器,可以选择相应的Docker、Kubernetes执行器。而利用Tags
可以指定项目运行的Gitlab-Runner
。URL和Token可以在Gitlab上分配,以Specitic Runner
为例
注册成功后,运行Gitlab-Runner
gitlab-runner run
当出现绿色实心圈则表示Gitlab-Runner
注册成功,而且正在运行。这时,只要在项目下编写.gitlab-ci.yaml
文件就可以啦
编写.gitlab-ci.yml
GitLab CI使用YAML
文件(.gitlab-ci.yml
)来管理项目配置。默认存放于项目仓库的根目录,它包含了项目如何被编译的描述语句。YAML
文件使用一系列约束定义了Job启动时所要做的事情。
如果.gitlab-ci.yml
未指定Runner的tag
,可能一直处于Pending
状态,这时,可以编辑Runner配置,勾上Run untagged jobs
。
Pipelines
是整个Gitlab CI最顶层的组件,是一个分成不同阶段(Stage
)的作业(Job
)的集合。每个推送到 Gitlab 的提交都会产生一个与该提交关联的Pipeline
,若一次推送包含了多个提交,则Pipeline
与最后那个提交相关联。我们很容易利用每个Pipeline
的ID标识做资源隔离,或者作为镜像的版本等等。根据配置可以展现出不同类型的Pipeline
,可能是有向无环图(DAG)的,可能是父子结构的等等。
以Java Maven Jar
项目为例,通常包含package、test、deploy这三个步骤。先上效果图:
Gitlab CI Pipeline定义了Stage
这个阶段概念,对批量的作业进行了一个逻辑上划分。多个Stage
间是顺序执行的,一个 Stage
失败,后续的 Stage
不会被执行,整个 CI 过程会被认为失败。
stages:
- build
- test
- deploy
上述Maven样例中整个 CI 环节包含三个Stage
:build、test 和deploy。分别对应maven的打包、测试、部署阶段。其中一个阶段失败,都会导致后面的阶段不可用。
Job
是Runner要执行的指令集合,Job
可以被关联到一个Stage
,一个Stage
可能包含多个Job
。当一个Stage
执行的时候,与其关联的所有Job
都会被执行。同一个Stage
下的Job
是可以并发执行的,至于并发能力,这取决于Runner配置的并发数和服务器并行能力。
从官网截了一个图出来,比较直观,Stage
间是串行的,同个Stage
下Job
间是并行的。
我们可以先看下deploy Job的描述片段:
deploy:
stage: deploy
script:
- mvn $MAVEN_CLI_OPTS deploy
only:
- master
Job
包含script
,一段由Runner执行的shell脚本。在script中,对于直接定义|
、>
等管道和重定向的shell复合命令,有可能会出现莫名问题,需要甄别。我们可以定义before_script
,after_script
来辅助Job
执行script
前后需要准备或者收尾的事情。
#定义全局 before_script:
default:
before_script:
- global before script
#覆盖全局before_script
job:
before_script:
- execute this instead of global before script
script:
- my command
after_script:
- execute this after my script
对于多个Job,有些步骤可能是重复的,如Maven的打包和测试阶段都需要寻找依赖,这时,可以利用缓存机制,将依赖缓存下来,加快Job的执行时间。
variables:
MAVEN_CLI_OPTS: "-s ci_settings.xml --batch-mode"
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
cache:
paths:
- .m2/repository/
- target/
很多时候我们并不希望每次push都触发Pipeline
,希望定义触发规则还触发Pipeline
,我们可能希望指定某个分支,或者以分支名正则关联,或者排除某些分支,或者某个变量的值,或者某个commit
的信息,或者某一类代码的变化,或者希望手动触发,或者定时触发,甚至是自定义触发规则等等。这时我们可以利用only
和except
定义怎么触发Pipeline
。
only:
refs:
- branches
variables:
- $ENABLE_VERIFY == "true"
changes:
- "**/*.java"
在编辑.gitlab-ci.yaml
文件中可以使用预置的变量,如:$CI_PIPELINE_ID
表示正在构建的Pipeline
ID,可以在script
中使用这个变量。将预置变量CI_DEBUG_TRACE
值设为true,则进入debug模式,将打印更多的CI日志。
variables:
CI_DEBUG_TRACE: "true"
我们有可能需要Gitlab-Runner
生成的结果回传给Gitlab,提供下载。
artifacts:
#expire_in: 1 week
paths:
- target/*.jar
如果上传打包太大会报错:
ERROR: Uploading artifacts to coordinator... too large archive id=407 responseStatus=413 Request Entity Too Large status=413 Request Entity Too Large token=EQ-TLvUS
FATAL: too large
需要调整允许上传附件的最大大小
修改/etc/gitlab/gitlab.rb
Gitlab配置,将client_max_body_size
值设为0,表示不限制大小
nginx['client_max_body_size'] = 0
我们有可能引入手动,以便更好的控制部署,有时候会只希望负责人手动批准,触发任务部署。
when: mannual
allow_failure: false
对于微服务这种项目,我们可能还要打通上下游项目,需要触发多项目的Pipeline
。而且多个项目间权限不同,有可能还需要引入批准步骤等等,这些高级特性还有待挖掘。语法中还有模板的功能,这些就详见官方文档了。
以Shell
为执行器的Gitlab Runner
服务器,在运行Maven Job时,需要提前准备JDK\Maven环境。万事俱备之后,Push代码后,直接自动触发Pipeline
。
值得注意的是,Gitlab Runner
跑Pipeline
拉取代码到仓库构建目录,存在一定规则:
/$RUNNER_TOKEN_KEY/$CONCURRENT_ID/$NAMESPACE/$PROJECT_NAME
我们也很容易从Pipeline
的日志里看出端倪:/etc/profile.d/builds/53GgNRQd/0/wenqy/simple-maven-dep
配置邮箱后,构建失败会发起邮箱通知:
此外YAML
格式文件编写还是易出错的,Gitlab嵌入了校验.gitlab-ci.yml
内容格式的调试工具,还是比较人性化的。
总之,Gitlab项目要启用CI/CD还是相当容易,.gitlab-c.yaml
文件提供了很大的灵活度,可以根据具体项目的需要定制属于自己团队特殊的CI/CD,Gitlab CI/CD无疑为团队的整个效益提供一大助力,为敏捷开发提供了支持。
参考
https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/
https://docs.gitlab.com/ee/ci/quick_start/
https://docs.gitlab.com/runner/install/linux-repository.html
https://docs.gitlab.com/runner/install/kubernetes.html
https://docs.gitlab.com/runner/commands/README.html
https://docs.gitlab.com/ee/ci/runners/#using-tags
https://docs.gitlab.com/ee/ci/yaml/README.html
https://docs.gitlab.com/ee/ci/examples/artifactory_and_gitlab/
https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
https://gitlab.com/gitlab-org/gitlab/-/pipelines/177402875
本文由 wenqy 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Nov 4,2020