gitlab-ci/cd

简单介绍gitlab-ci/cd的使用


官方文档: GitLab CI/CD

没有比官方文档更好不过的教程了!

gitlab-ci如何运行?

gitlab-ci并不是平白无故运行起来的,依托于一个叫做GitLab Runner 的东西,我们配置的gitlab-ci 才会顺利的运行。

如果你对Install GitLab Runner 感兴趣,可以参看文档,gitlab-runner是如何安装的。

ci/cd的运行 至少需要一个gitlab-runner。当然也可以配置多个,比如您可以在macos系统上安装gitlab-runner并注册到gitlab中,这样您就可以将类似ios打包的过程放到这个runner上了。以此类推,如果您有特殊要求的ci/cd,可以指定特殊的runner。

ci/cd运行过程:

gitlab按照您项目中的的gitlab-ci.yaml配置,创建一个或多个job,然后等待gitlab-runner运行这些job。

大概的过程类似于:

  1. 选择一个执行器

    也就是执行命令等操作的环境,需要gitlab-runner中配置。例如shell也就是在gitlab-runner主机上运行。docker就是拉取某个镜像,在镜像中执行命令。

    下文的runner的执行器均为docker

  2. 拉取源码

  3. 重建缓存

    如果当前job或者流水线有配置缓存,会拉取缓存。(下文详细说)

  4. 下载artifacts

    如果当前job的上游有配置artifacts,会下载artifacts(下文详细说)

  5. 执行命令

    执行您的scripts

CI/CD pipelines 流水线

顾名思义,流水线 ,也就是定义整个流程需要完成哪些阶段,每个阶段需要做什么。

  • Stages 阶段: 定义了整个pipelines需要做哪些事,这些事需要顺序执行。 例如:先下载依赖,然后编译代码,再推送编译后的代码,最后发一个ci/cd成功的通知

  • Jobs 作业: 每个阶段需要完成的操作,例如:使用某个php镜像,执行composer install 命令下载依赖。

以下为官方示例为例:

 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
39
40
41
stages: # 阶段
  - build
  - test
  - deploy

image: alpine

# 作业
build_a:
  stage: build
  script:
    - echo "This job builds something."

build_b:
  stage: build
  script:
    - echo "This job builds something else."

test_a:
  stage: test
  script:
    - echo "This job tests something. It will only run when all jobs in the"
    - echo "build stage are complete."

test_b:
  stage: test
  script:
    - echo "This job tests something else. It will only run when all jobs in the"
    - echo "build stage are complete too. It will start at about the same time as test_a."

deploy_a:
  stage: deploy
  script:
    - echo "This job deploys something. It will only run when all jobs in the"
    - echo "test stage complete."

deploy_b:
  stage: deploy
  script:
    - echo "This job deploys something else. It will only run when all jobs in the"
    - echo "test stage complete. It will start at about the same time as deploy_a."

对于更多内容,可参考官方文档

Jobs 作业

作业才是流水线每个阶段实际执行的内容,每个作业都应该定义在顶级,并且拥有至少一个script

您可以理解为流水线的工人

以官方文档为例:

1
2
3
4
5
job1: # 作业的名称
  script: "execute-script-for-job1" # 作业执行的脚本

job2: # 作业的名称
  script: "execute-script-for-job2" # 作业执行的脚本

作业定义的数量不受限制,每个作业都是独立的单独运行。

⚠️ 每个作业都是单独,独立运行。所以,即使在同一个流水线中 也就是在一次ci/cd中。每个作业运行的runner都可能是不同的。

例如:你在runner1 上拉取了依赖,你在runner2上编译了代码,你在runner3上发送了一个通知。

那么,如果在deploy时想使用上一个阶段编译出来的文件该如何操作呢?

Caching / Artifacts 缓存和制品

Artifacts 制品,可以理解为作业产出的内容(上个流水线工人产出的内容)

简单以下面这个为例:

 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
stages:
  - install
  - build
  - deploy

install-online:
  stage: install
  image: tool/yarn:v1
  script:
    - yarn install
    - yarn build:prod 
   # 将yarn build 打包出来的dist 作为制品,传到下一个job
  artifacts:
    paths:
      - dist/

# 默认情况下,后面阶段的作业会自动下载由前面阶段的作业创建的所有制品。
build-online-image:
  stage: build
  image: tool/docker:latest
  only:
    - master
  script:
    - docker build -t $ONLIE_IMAGE_NAME .
    - docker push $ONLIE_IMAGE_NAME
    - docker tag $ONLIE_IMAGE_NAME $IMAGE
    - docker push $IMAGE
    
deploy-online:
  stage: deploy
  image: kubematrix/cli:v1
  # 如果您不需要依赖任何的制品,你可以使用dependencies: []
  dependencies: []
  only:
    - master
  script:
    - matrix workloads deploy

install时安装依赖并打包出一个dist文件夹,使用artifacts将这个文件夹打包出来。

install执行完成后,build阶段时会自动下载之前的artifacts 也就是dist文件夹,完成了将上个阶段编译出来的文件带到下个阶段的操作。

dependencies 依赖 可参考官方文档,


Cache 缓存

以php为例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#
# https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
#
image: php:7.2

# Cache libraries in between jobs
cache:
  key: $CI_COMMIT_REF_SLUG
  paths:
    - vendor/

before_script:
  # Install and run Composer
  - curl --show-error --silent "https://getcomposer.org/installer" | php
  - php composer.phar install

test:
  script:
    - vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never

$CI_COMMIT_REF_SLUG(预定义变量,这里是指分支的名称)为key, 将vendor/目录缓存下来。

缓存下来 以后的每一次作业,都会下载缓存,这样会加速composer install 的速度

⚠️需要注意的点:

  • cache:key 如果不指定key,那么默认同一个项目的所有build共享这个缓存。关于cache:key的各种场景使用,可参考:Caching in GitLab CI/CD | GitLab

  • 默认cache使用本地磁盘保存,但这样会出现一个问题。如果每次job运行都在不同的runner上,那么缓存是不可以共享的。这时候就需要引入一个分布式存储这个缓存文件。

配置阿里云OSS存储cache文件

Advanced configuration | GitLab

为了统一缓存,我们需要使用OSS

首先进入gitlab-runner对应的主机,gitlab-runner list 查看配置文件存放的位置

/etc/gitlab-runner/config.toml

 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
[[runners]]
  name = "cloud5"
  url = "https://gitlab.xxx.cn/"
  token = "token"
  executor = "docker"
  [runners.custom_build_dir]
  [runners.cache]
    Type = "s3"
    Shared = true
    Path = "xxx"
    [runners.cache.s3]
      ServerAddress = "oss-cn-hangzhou.aliyuncs.com"
      AccessKey = "key"
      SecretKey = "sec"
      BucketName = "gitlab-runner-cached"
      BucketLocation = "oss-cn-hangzhou"
  [runners.docker]
    tls_verify = false
    image = "ruby:2.6"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/root/.docker/:/root/.docker/", "/data/gitlab-runner/cache:/cache", "/data/gitlab-runner/npm-cache:/root/.npm", "/data/gitlab-runner/composer-cache:/root/.composer"]
    shm_size = 0
    pull_policy = "if-not-present"

主要内容为以下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  [runners.cache]
    Type = "s3" # 缓存类型
    Shared = true # 缓存在多个runner之间共享
    Path = "xxx" # 缓存路径前缀,如果一个gitlab-runner在多个gitlab中注册,可以使用前缀的方式做区分
    [runners.cache.s3]
      ServerAddress = "oss-cn-hangzhou.aliyuncs.com" # oss地址
      AccessKey = "key" # key
      SecretKey = "sec" # secret
      BucketName = "gitlab-runner-cached" # bucketName
      BucketLocation = "oss-cn-hangzhou" # BucketLocation

以此类推,你需要在所有的gitlab-runner中配置此缓存,这样所有的缓存都会被上传到阿里云的OSS中,无论你的job运行在哪个runner中。

示例:

以一个前端项目为例:

 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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# 定义
variables:
  ONLIE_IMAGE_NAME: registry.cn-hangzhou.aliyuncs.com/$CI_PROJECT_NAME:$CI_COMMIT_SHORT_SHA

stages:
  - preInstall
  - install
  - build
  - deploy


build-image:
  stage: build
  image: docker
  only:
    - test
  script:
    - docker build -t $IMAGE .
    - docker push $IMAGE



#  ---------------------------------- master ----------------------------------
# 只有当package.json变化时才会重新install
preInstall-job:
  stage: preInstall
  image: yarn:v1
  cache:
    key: $CI_COMMIT_REF_SLUG
    paths:
      - node_modules/
      - yarn.lock
    # 只需要推送缓存,不需要拉取缓存
    policy: push
  only:
    refs:
      - master
    changes:
      - package.json
  script:
    - yarn install 


install-online:
  stage: install
  image: yarn:v1
  cache:
    key: $CI_COMMIT_REF_SLUG
    paths:
      - node_modules/
      - yarn.lock
    # 只需要拉取缓存,不需要推送缓存
    policy: pull
  only:
    - master
  script:
  # 当缓存存在时不需要install
    - if [ ! -d "./node_modules/" ];then   yarn install;   else   ls -alh; fi
    - yarn build:prod 
  # 打包制品给后面的job
  artifacts:
    paths:
      - dist/

build-online-image:
  stage: build
  # 使用docker镜像
  image: docker:latest
  # 只在master分支变动时运行这个job
  only:
    - master
  script:
    - docker build -t $ONLIE_IMAGE_NAME . # 构建镜像
    - docker push $ONLIE_IMAGE_NAME # 推送镜像

deploy-online:
  stage: deploy
  # 使用kubematrix-cli镜像
  image: kubematrix/cli:v1
  # 依赖为空,表示不需要任何的依赖
  dependencies: []
  only:
    - master
  script:
    - matrix workloads deploy

示例讲解

  1. GitLab CI/CD variables | GitLab 变量

    可以在文档Predefined variables reference | GitLab 中查看预定义的变量

    首先定义变量 ONLIE_IMAGE_NAME 以供使用

  2. 定义stages 流水线阶段

    定义了4个阶段,preInstall,install,build,deploy,下面的job将按照关联的stag顺序执行

  3. 定义job

    stag 定义了job对应的阶段。

    image:定义了执行脚本所使用的docker镜像。

    only : 定义了job只在某些情况下执行。默认为only.refs 输入分支名,或与分支相匹配的正则表达式。only.changes 检测只在某些文件变动时运行。

    cache : 定义了改job使用缓存,cache.policy 缓存规则,默认为pull-push开始job前拉取缓存,job成功后推送缓存。 可修改为push只推送,不拉取。pull只拉取,不推送

    artifacts: 定义了需要打包的制品,给后面的job使用

    dependencies : 需要的依赖,如果上面的job有artifacts 会默认下载,如果不需要artifacts 可将这个属性定义为空数组

Licensed under CC BY-NC-SA 4.0
Built with Hugo
主题 StackJimmy 设计