【CI/CD】详解如何配置gitlab-ci/cd

Gitlab CI/CD 简介

  • gitlab:一个基于git的、开源的代码仓库管理平台,类似的平台还有github、gitee这些。

  • CI:Continuous Integration 持续集成,对代码进行构建、编译、打包,得到产物 output.zip

  • CD:Continuous Delivery 持续交付,将产物 output.zip部署到测试服务器(服务端及web端)、推送到内部的移动app安装平台(移动端),以供测试、验收。

  • CD:Continuous Deployment 持续部署,将产物使用k8s部署到容器,上线预发布、正式环境。

个人理解:CI/CD是一种软件持续性开发的方法论。gitlab-ci是基于该方法论实现的一个工具,它使得软件工程师可以不断的对新代码进行构建、测试和部署。这样可以有助于提前发现问题,减少基于错误或失败的版本进行开发新代码的可能性,尤其是对于多人协同开发的大型项目,CI/CD显得尤为重要。使用这种方法,从新代码开发到部署,可以减少人工干预甚至不用干预。

关于gitlab ci/cd的一些基本概念,可以参考官网 Get started with GitLab CI/CD | GitLab

本文介绍的主要是如何配置gitlab ci/cd,以达到自动构建、自动部署的目的

配置Gitlab CI/CD

配置之前,你需要创建一个仓库,如果是对已有仓库配置则需要有该仓库的 Maintainer或者Owner 权限。

gitlab runner

gitlab runner指的是用来执行构建编译的机器,类似于Jenkins的node节点。可以是Linux机器或者windows机器。

runner可以在项目 => setting => CI/CD中查看。

runner 分为共享型(所有项目都可以用)、指定型(当前项目可以用)。

如果还没有配置好的runner机器,可以用自己本地电脑作为runner机进行测试。

  1. Install GitLab Runner and ensure it’s running.
  2. 注册runner(可以在项目 => setting => CI/CD查看注册方法)

.gitlab-ci.yml

在项目根目录中创建一个.gitlab-ci.yml文件(使用的是yaml语法,配置前建议先了解下),当开发人员提交代码时,如果检测到根目录中有该文件,就会自动触发CI/CD流程。

一个pipeline包含若干个stage,这些stage是串行执行的,比如build、test、deploy。

每个stage又可以包含若干个job,这些job是并行执行的,比如test这个stage里有三个job:unit_test、lint_test、api_test。

简单模板

下面是一个简单的.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
stages: # 在这里定义执行的stage,以及执行顺序
  - build
  - test
  - deploy

build-job:  # job名称
  stage: build  # stage名称,用来标记这个job是在哪个stage执行的
  script: 
    - echo "Hello, $GITLAB_USER_LOGIN!" # 执行的脚本

test-job1:
  stage: test
  script:
    - echo "This job tests something"

test-job2:
  stage: test
  script:
    - echo "This job tests something, but takes more time than test-job1."
    - echo "After the echo commands complete, it runs the sleep command for 20 seconds"
    - echo "which simulates a test that runs 20 seconds longer than test-job1"
    - sleep 20

deploy-prod:
  stage: deploy
  script:
    - echo "This job deploys something from the $CI_COMMIT_BRANCH branch."

上面这个文件解析成pipeline是这样的:

上面$GITLAB_USER_LOGIN$CI_COMMIT_BRANCH是预定义的变量,具体参考:Predefined CI/CD variables reference | GitLab

关键字

官方文档:CI/CD YAML syntax reference | GitLab

类似于编程语言的关键字(保留字)一样,.gitlab-ci.yaml中也有一些关键字,它们有特定的含义。这里列举一些常用的。

配置pipeline的全局关键字:

关键字

含义

default定义job中的关键字默认值,如果job中没有配置相同关键字的值,则会使用这里的默认值。
include从其他yaml文件中导入配置。比如你有多个前端项目都是用npm构建的,那可以提取出一个公共配置,其他的项目继承自该公共配置就行了。
stages用来定义pipeline的阶段,以及每个阶段的执行顺序(按照从上到下执行)
variables为pipeline中的所有job定义CI/CD用到的变量。
workflow控制运行什么类型的pipeline。

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
default:
  image: ubuntu:16.04 # 默认镜像,如果job没有定义images
  after_script: "echo job finish" # 默认的after_script,如果job中没有定义,就会在ci脚本执行完执行该脚本。
 
include:
  - remote: 'https://gitlab.com/example-project/-/raw/main/.gitlab-ci.yml' # 引用远程文件
  
  - local: '/templates/.gitlab-ci-template.yml' # 引用本地文件
 
  - project: 'my-group/my-project' # 引用其他项目指定分支的文件,可以多个
    ref: main
    file: 
      - '/templates/.gitlab-ci-template.yml'
      - '/templates/.tests.yml'

  - project: 'my-group/my-project'
    ref: v1.0.0                    # 可以是某个tag
    file: '/templates/.gitlab-ci-template.yml'

  - project: 'my-group/my-project'
    ref: 787123b47f14b552955ca2786bc9542ae66fee5b  # 也可以是 Git SHA
    file: '/templates/.gitlab-ci-template.yml'

stages:  # 定义阶段和执行顺序
  - build
  - test
  - deploy

variables: # 定义全局变量,在job中用 $+变量名 来引用
  DEPLOY_SITE: "https://example.com/"


workflow: # 只有当至少符合一个规则时,才会执行pipeline
  rules:
    - if: $CI_COMMIT_TITLE =~ /-draft$/  # 这里指如果提交标题(提交消息的第一行)没有以-draft结尾,才为True
      when: never
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"  # 判断事件,merge事件时为True
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH  # 判断提交的分支是否默认分支

配置job的关键字

关键字

含义

after_script覆盖job完成后执行的一组命令。
allow_failure允许job失败。如果配置为true,则该job失败后,不会导致整个pipeline失败终止。
artifactsjob执行成功后附加到job的文件或目录列表(类似构建产物),这些文件或目录会保存起来。
before_script覆盖job开始前执行的一组命令。
cache需要缓存的文件列表,可以用来缓存一些公共依赖(下面会单独介绍)
coverage设置job的代码覆盖率。
dast_configuration在job级别使用dast配置文件中的配置。
dependencies这里定义的是一些job列表,表示会使用到这些job中工件(artifacts)
environmentjob部署到的环境名称。
except控制什么时候不执行job,与之相反的是only关键字。
extends继承配置,比如一些公共的配置。
image定义Docker镜像,会在该镜像中执行job,比如一些需要特定编译环境的job,可以先自定义构建镜像。
inherit配置true表示继承pipeline关键字default中定义的全部默认值,false表示全部不继承。配置列表,可以选定继承需要的默认值。
interruptible表示如果触发了相同的新的job,该job是否可以被终止。
needs这个关键字可以无视stages中定义的阶段顺序。配置空列表,会立即执行job。假如有build_a、build_b、test_a、test_b,定义的stage顺序是是build => test。但是build_b耗时很长,那么可以在test_a中配置needs: [“build_a”],这样的话build_a执行完就会马上执行test_a,而不用继续等待build_b执行完。
only控制什么时候执行job,与之相反的是except关键字。
pages将静态文件部署到git page,需要将内容放在public/目录中,然后在工件中path中包含public目录。
parallel在单个管道中并行运行多个job,可以配置每个job实例具有不同的变量值。
release这个是用于发布的,需要在runner上安装有release-cli。
resource_group避免job并发执行。配置资源组后,对于同一个组员组内的job,永远不会并发执行,即使是独立的pipeline之间也不会并发。这样可以避免重复测试、重复部署等问题。
retry用于配置job发生故障时可以自动重试的时间和次数。
rules定于规则以决定job是否执行,不能和only、except一起使用。
script由运行程序执行的 Shell 脚本。
secretsCI/CD时需要用到一些敏感信息,如数据库密码等
services配置Docker 服务镜像,在镜像中执行pipeline。
stage定义job属于哪个阶段。
tags用于筛选runner机器。
timeoutjob执行超时时间。
trigger用于触发下游pipeline,如果是触发一个,则配置yaml文件路径,如果是触发多个,则配置这些yaml所在的路径。
variables定义job级别的变量
when定义何时运行job,默认是on_success(pipeline成功时),on_failure(pipeline失败时)、always(总是)、manual(需要人工触发)

在容器中运行CI/CD

配置了runner之后,pipeline是在runner指定目录去pull代码,然后执行.gitlab-ci.yml中定义的CI/CD脚本。

但是不同项目的依赖环境是不一样的(例如不同的后端语言java、python、c++、golang等),我们不可能在runner上安装好所有的构建环境。所以我们需要先自定义一些镜像,然后通过job的image配置使用哪个镜像。

配置之后,runner会基于该镜像启动一个容器,pipeline就会在容器中运行了。

1
2
3
4
5
6
7
defalut:
  image: ubuntu-python3:latest # 定义默认的镜像

test-job1:
  image: ubuntu-python2:1.0 # 优先使用job中定义的镜像,如果不配置,就使用默认的。
  script:
    - sh build.sh

缓存依赖项提高构建速度

在job中配置需要缓存的文件或目录,可以在job之间共享(即使是不同的pipeline也可以)

使用cache:paths关键字选择要缓存的文件或目录。

使用cache:key关键字给每个缓存一个唯一的标识键。所有使用相同缓存键的作业都使用相同的缓存,包括在不同的管道中。

使用cache:key:files监听一些文件,当这些更改时(通过计算这些文件sha值来确定是否更改),会生成新的缓存。比如监听yarn.lock文件,对应的缓存路径是node_modules,如果我的yarn.lock文件没有改动,则复用node_modules。如果yarn更新了,则重新创建缓存node_modules。

cache:untracked: true缓存 Git 存储库中未跟踪的所有文件。因为这些文件是未跟踪的(也就是说不会变动),那么缓存下来可以提高下载速度。

cache:when根据job的状态定义何时保存缓存。

要更改缓存的上传和下载行为,请使用cache:policy关键字。默认情况下,job在开始时下载缓存,并在job结束时将更改上传到缓存。此缓存样式是pull-push策略(默认)。

要将job设置为仅在作业开始时下载缓存,但在job完成时从不上传更改,请使用cache:policy:pull.

要将job设置为仅在作业完成时上传缓存,但在job开始时从不下载缓存,请使用cache:policy:push

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
example_job1:
  script: 
    - echo "This job uses a cache."
  cache:
    key: binaries-cache-$CI_COMMIT_REF_SLUG # 使用字符串作为key
    paths:
      - binaries/

example_job2:
  script:
    - npm i
    - npm run build
  cache:
    key:
      files:
        - package.json # 因为这个文件是用来管理依赖的,所以可以用它的sha值作为key,以确定使用哪个缓存
    paths:
      - node_modules

yaml文件优化

对于一个复杂的项目,.gitlab-ci.yml往往会比较复杂,重复的配置也多,这时可以利用yaml的锚点语法进行优化。

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
.job_template: &job_configuration
  script:
    - test project
  tags:
    - dev

.postgres_services:
  services: &postgres_configuration
    - postgres
    - ruby

.mysql_services:
  services: &mysql_configuration
    - mysql
    - ruby

test:postgres:
  <<: *job_configuration
  services: *postgres_configuration
  tags:
    - postgres

test:mysql:
  <<: *job_configuration
  services: *mysql_configuration

实际渲染之后的文件是这样的:

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
.job_template:
  script:
    - test project
  tags:
    - dev

.postgres_services:
  services:
    - postgres
    - ruby

.mysql_services:
  services:
    - mysql
    - ruby

test:postgres:
  script:
    - test project
  services:
    - postgres
    - ruby
  tags:
    - postgres

test:mysql:
  script:
    - test project
  services:
    - mysql
    - ruby
  tags:
    - dev

script中使用锚点

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
.some-script-before: &some-script-before
  - echo "Execute this script first"

.some-script: &some-script
  - echo "Execute this script second"
  - echo "Execute this script too"

.some-script-after: &some-script-after
  - echo "Execute this script last"

job1:
  before_script:
    - *some-script-before
  script:
    - *some-script
    - echo "Execute something, for this job only"
  after_script:
    - *some-script-after

job2:
  script:
    - *some-script-before
    - *some-script
    - echo "Execute something else, for this job only"
    - *some-script-after

变量的锚点

1
2
3
4
5
6
7
8
9
10
11
12
# global variables
variables: &global-variables
  SAMPLE_VARIABLE: sample_variable_value
  ANOTHER_SAMPLE_VARIABLE: another_sample_variable_value

# a job that must set the GIT_STRATEGY variable, yet depend on global variables
job_no_git_strategy:
  stage: cleanup
  variables:
    <<: *global-variables
    GIT_STRATEGY: none
  script: echo $SAMPLE_VARIABLE

除此之外,还可以结合extendsinclude一起使用。

具体可以参考官方文档,这里不再赘述。Optimize GitLab CI/CD configuration files | GitLab

定时执行pipeline

进入你的项目中,然后点击左侧 CI/CD => Schedules,根据指引配置即可。这里的配置类似于Jenkins里的定时调度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值