简单介绍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。
大概的过程类似于:
- 
选择一个执行器
也就是执行命令等操作的环境,需要gitlab-runner中配置。例如shell也就是在gitlab-runner主机上运行。docker就是拉取某个镜像,在镜像中执行命令。
下文的runner的执行器均为docker
 
- 
拉取源码
 
- 
重建缓存
如果当前job或者流水线有配置缓存,会拉取缓存。(下文详细说)
 
- 
下载artifacts
如果当前job的上游有配置artifacts,会下载artifacts(下文详细说)
 
- 
执行命令
执行您的scripts
 
顾名思义,流水线 ,也就是定义整个流程需要完成哪些阶段,每个阶段需要做什么。
以下为官方示例为例:
 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."
  | 
 
对于更多内容,可参考官方文档
作业才是流水线每个阶段实际执行的内容,每个作业都应该定义在顶级,并且拥有至少一个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时想使用上一个阶段编译出来的文件该如何操作呢?
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 的速度
⚠️需要注意的点:
配置阿里云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
  | 
 
示例讲解
- 
GitLab CI/CD variables | GitLab   变量
可以在文档Predefined variables reference | GitLab  中查看预定义的变量
首先定义变量 ONLIE_IMAGE_NAME 以供使用
 
- 
定义stages 流水线阶段
定义了4个阶段,preInstall,install,build,deploy,下面的job将按照关联的stag顺序执行
 
- 
定义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 可将这个属性定义为空数组