Gitlab-CI初识

in DevOps with 0 comment

GitLab CI (Continuous Integration)是GitLab内置的进行持续集成的工具。基于特征分支开发后,需要发起Merge Requests合并共享代码库。Merge Requests总是频繁发生,合并请求过来后,可以触发流水线自动去构建、测试、验证新代码功能,及早发现错误,减少集成问题。我们也总是希望在任何时候都能发布稳定版本的软件,自动推送功能变更到演示环境,甚至是生产环境,完成持续地交付(Continuous Delivery)和部署(Continuous Deployment),以减少部署带来的风险和及时得到客户的反馈。通过Gitlab CI减少了人为错误的机会和跨团队沟通成本,提高整个团队的效率。

cicd_pipeline_infograph

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:SharedGroupSpecific

Shared Runners适用于所有应用,且只有系统管理员能够创建
Create a group Runner项目组下的所有应用,具有组权限的人才能创建
Specific Runners特定项目使用

我们可以用管理员账号登录,注册Shared Runner

image-20200813163435694

安装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 RunnerRunner executor等等。非容器化项目,Executor这里选Shell,如果想将项目部署到容器,可以选择相应的Docker、Kubernetes执行器。而利用Tags可以指定项目运行的Gitlab-Runner。URL和Token可以在Gitlab上分配,以Specitic Runner为例

image-20200813154011388

注册成功后,运行Gitlab-Runner

gitlab-runner run

当出现绿色实心圈则表示Gitlab-Runner注册成功,而且正在运行。这时,只要在项目下编写.gitlab-ci.yaml文件就可以啦

image-20200813155020665

编写.gitlab-ci.yml

GitLab CI使用YAML文件(.gitlab-ci.yml)来管理项目配置。默认存放于项目仓库的根目录,它包含了项目如何被编译的描述语句。YAML文件使用一系列约束定义了Job启动时所要做的事情。

如果.gitlab-ci.yml未指定Runner的tag,可能一直处于Pending状态,这时,可以编辑Runner配置,勾上Run untagged jobs

image-20200813161014290

Pipelines是整个Gitlab CI最顶层的组件,是一个分成不同阶段(Stage)的作业(Job)的集合。每个推送到 Gitlab 的提交都会产生一个与该提交关联的Pipeline,若一次推送包含了多个提交,则Pipeline与最后那个提交相关联。我们很容易利用每个Pipeline的ID标识做资源隔离,或者作为镜像的版本等等。根据配置可以展现出不同类型的Pipeline,可能是有向无环图(DAG)的,可能是父子结构的等等。

Java Maven Jar项目为例,通常包含package、test、deploy这三个步骤。先上效果图:

image-20200813170713024

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间是串行的,同个StageJob间是并行的。

image-20200813182442502

我们可以先看下deploy Job的描述片段:

deploy:
  stage: deploy
  script:
    - mvn $MAVEN_CLI_OPTS deploy
  only:
    - master

Job包含script,一段由Runner执行的shell脚本。在script中,对于直接定义|>等管道和重定向的shell复合命令,有可能会出现莫名问题,需要甄别。我们可以定义before_scriptafter_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的信息,或者某一类代码的变化,或者希望手动触发,或者定时触发,甚至是自定义触发规则等等。这时我们可以利用onlyexcept定义怎么触发Pipeline

  only:
    refs:
      - branches
    variables:
      - $ENABLE_VERIFY == "true"
    changes:
      - "**/*.java"

在编辑.gitlab-ci.yaml文件中可以使用预置的变量,如:$CI_PIPELINE_ID表示正在构建的PipelineID,可以在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

需要调整允许上传附件的最大大小

clip_image001

修改/etc/gitlab/gitlab.rbGitlab配置,将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

image-20200813182226498

值得注意的是,Gitlab RunnerPipeline拉取代码到仓库构建目录,存在一定规则:

/$RUNNER_TOKEN_KEY/$CONCURRENT_ID/$NAMESPACE/$PROJECT_NAME

我们也很容易从Pipeline的日志里看出端倪:/etc/profile.d/builds/53GgNRQd/0/wenqy/simple-maven-dep

image-20200813181255935

配置邮箱后,构建失败会发起邮箱通知:

image-20200814141455180

此外YAML格式文件编写还是易出错的,Gitlab嵌入了校验.gitlab-ci.yml内容格式的调试工具,还是比较人性化的。

image-20200813180659907

总之,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