(共556篇)
全部分类

CI/CD中的cache--job与pipeline之间的文件缓存与传递
[ CICD ] 

cache

cache 用来在 pipeline、job 之间传递文件, 且 cache 在不同的项目之间是相互隔离的(互相访问不到的)

如果 cache 写在最顶层的 default 任务中, 表示当前所有参与 pipeline 的 job 都会根据它的规则缓存文件

如果 cache 写在 job 中, 会覆盖全局定义的 cache 规则

(cache 中定义的文件, 会被压缩为 cache.zip 被保存在 runner 所在的服务器上, 所以不管是在 pipeline 中还是 job 之间使用 cache, 必须保证他们在同一个 runner 上执行)

job 之间的 cache 共享

直接看下面的案例:

 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
default:
  cache:
    paths:
      - cat.txt

job1:
  stage: build
  tags:
    - nuxt2
  script:
    - ls -alh
    - if [[ -f cat.txt ]]; then echo "cat.txt exists ,file content:" && cat cat.txt; else echo "cat.txt not found ,will create cat.txt content 'job1' " &&  echo 'job1' > cat.txt && cat cat.txt; fi

job2:
  stage: build
  needs: [job1]
  tags:
    - nuxt2
  script:
    - ls -alh
    - if [[ -f cat.txt ]]; then echo "cat.txt exists ,file content:" && cat cat.txt && echo 'job2' > cat.txt ; else echo 'cat.txt not found' > cat.txt; fi

job3:
  stage: build
  needs: [job2]
  tags:
    - nuxt2
  script:
    - ls -alh
    - if [[ -f cat.txt ]]; then echo "cat.txt exists ,file content:" && cat cat.txt && echo 'job3' > cat.txt ; else echo 'cat.txt not found' > cat.txt; fi

看一下各 job 的执行结果(内容太多了, 以下只保留关键输出):

  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
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# job1
Running with gitlab-runner 15.1.0 (76984217)
  on localhost.localdomain U7XjgRjY
Preparing the "shell" executor
Using Shell executor...
Preparing environment
Running on localhost.localdomain...
Getting source from Git repository
Fetching changes with git depth set to 20...
已重新初始化已存在的 Git 仓库于 /home/gitlab-runner/builds/U7XjgRjY/0/liyun/cicd/.git/
Checking out 88b24f11 as main...
正删除 cat.txt
Skipping Git submodules setup
Restoring cache
Checking cache for default-9-protected...
Runtime platform                                    arch=amd64 os=linux pid=20655 revision=76984217 version=15.1.0
No URL provided, cache will not be downloaded from shared cache server. Instead a local version of cache will be extracted.
Successfully extracted cache
Executing "step_script" stage of the job script

$ ls -alh
总用量 4.0K
drwxrwxr-x. 3 gitlab-runner gitlab-runner  40 7月  25 13:37 .
drwxrwxr-x. 4 gitlab-runner gitlab-runner  34 7月  24 00:49 ..
drwxrwxr-x. 5 gitlab-runner gitlab-runner 117 7月  25 13:37 .git
-rw-rw-r--. 1 gitlab-runner gitlab-runner 765 7月  25 13:37 .gitlab-ci.yml
$ if [[ -f cat.txt ]]; then echo "cat.txt exists ,file content:" && cat cat.txt; else echo "cat.txt not found ,will create cat.txt content 'job1' " &&  echo 'job1' > cat.txt && cat cat.txt; fi
cat.txt not found ,will create cat.txt content 'job1'
job1

Saving cache for successful job
Creating cache default-9-protected...
Runtime platform                                    arch=amd64 os=linux pid=20738 revision=76984217 version=15.1.0
cat.txt: found 1 matching files and directories
No URL provided, cache will not be uploaded to shared cache server. Cache will be stored only locally.
Created cache
Job succeeded

# job2
Running with gitlab-runner 15.1.0 (76984217)
  on localhost.localdomain U7XjgRjY
Preparing the "shell" executor
Using Shell executor...
Preparing environment
Running on localhost.localdomain...
Getting source from Git repository
Fetching changes with git depth set to 20...
已重新初始化已存在的 Git 仓库于 /home/gitlab-runner/builds/U7XjgRjY/0/liyun/cicd/.git/
Checking out 88b24f11 as main...
正删除 cat.txt
Skipping Git submodules setup
Restoring cache
Checking cache for default-9-protected...
Runtime platform                                    arch=amd64 os=linux pid=20872 revision=76984217 version=15.1.0
No URL provided, cache will not be downloaded from shared cache server. Instead a local version of cache will be extracted.
Successfully extracted cache
Executing "step_script" stage of the job script

$ ls -alh
总用量 8.0K
drwxrwxr-x. 3 gitlab-runner gitlab-runner  55 7月  25 13:38 .
drwxrwxr-x. 4 gitlab-runner gitlab-runner  34 7月  24 00:49 ..
-rw-rw-r--. 1 gitlab-runner gitlab-runner   5 7月  25 13:37 cat.txt
drwxrwxr-x. 5 gitlab-runner gitlab-runner 117 7月  25 13:38 .git
-rw-rw-r--. 1 gitlab-runner gitlab-runner 765 7月  25 13:37 .gitlab-ci.yml
$ if [[ -f cat.txt ]]; then echo "cat.txt exists ,file content:" && cat cat.txt && echo 'job2' > cat.txt; else echo 'cat.txt not found' > cat.txt; fi
cat.txt exists ,file content:
job1

Saving cache for successful job
Creating cache default-9-protected...
Runtime platform                                    arch=amd64 os=linux pid=20948 revision=76984217 version=15.1.0
cat.txt: found 1 matching files and directories
No URL provided, cache will not be uploaded to shared cache server. Cache will be stored only locally.
Created cache
Job succeeded

# job3
Running with gitlab-runner 15.1.0 (76984217)
  on localhost.localdomain U7XjgRjY
Preparing the "shell" executor
Using Shell executor...
Preparing environment
Running on localhost.localdomain...
Getting source from Git repository
Fetching changes with git depth set to 20...
已重新初始化已存在的 Git 仓库于 /home/gitlab-runner/builds/U7XjgRjY/0/liyun/cicd/.git/
Checking out 88b24f11 as main...
正删除 cat.txt
Skipping Git submodules setup
Restoring cache
Checking cache for default-9-protected...
Runtime platform                                    arch=amd64 os=linux pid=21085 revision=76984217 version=15.1.0
No URL provided, cache will not be downloaded from shared cache server. Instead a local version of cache will be extracted.
Successfully extracted cache
Executing "step_script" stage of the job script

$ ls -alh
总用量 8.0K
drwxrwxr-x. 3 gitlab-runner gitlab-runner  55 7月  25 13:38 .
drwxrwxr-x. 4 gitlab-runner gitlab-runner  34 7月  24 00:49 ..
-rw-rw-r--. 1 gitlab-runner gitlab-runner   5 7月  25 13:38 cat.txt
drwxrwxr-x. 5 gitlab-runner gitlab-runner 117 7月  25 13:38 .git
-rw-rw-r--. 1 gitlab-runner gitlab-runner 765 7月  25 13:37 .gitlab-ci.yml
$ if [[ -f cat.txt ]]; then echo "cat.txt exists ,file content:" && cat cat.txt && echo 'job2' > cat.txt; else echo 'cat.txt not found' > cat.txt; fi
cat.txt exists ,file content:
job2

Saving cache for successful job
Creating cache default-9-protected...
Runtime platform                                    arch=amd64 os=linux pid=21163 revision=76984217 version=15.1.0
cat.txt: found 1 matching files and directories
No URL provided, cache will not be uploaded to shared cache server. Cache will be stored only locally.
Created cache
Job succeeded

从这个案例中可以看出:

  1. job1 中缓存的文件, 被传递给 job2, job2 中缓存的文件,被传递给 job3
  2. job 在执行 script 前, 会先拉取上一次的缓存文件
  3. job 在执行结束前, 会重新按照 cache 规则缓存文件

同一个项目 pipeline 之间共享 cache

gitlab 允许在同一个项目上不同分支上触发 pipeline 产生的 cache 会传递给下一次 pipeline, 比如上面的 job1 重新执行, 就可以发现, job1 中继承了上次 pipeline 中 job3 产生的 cache:

 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
# job1
Running with gitlab-runner 15.1.0 (76984217)
  on localhost.localdomain U7XjgRjY
Preparing the "shell" executor
Using Shell executor...
Preparing environment
Running on localhost.localdomain...
Getting source from Git repository
Fetching changes with git depth set to 20...
已重新初始化已存在的 Git 仓库于 /home/gitlab-runner/builds/U7XjgRjY/0/liyun/cicd/.git/
Checking out d04bea89 as main...
正删除 cat.txt
Skipping Git submodules setup
Restoring cache
Checking cache for default-11-protected...
Runtime platform                                    arch=amd64 os=linux pid=23936 revision=76984217 version=15.1.0
No URL provided, cache will not be downloaded from shared cache server. Instead a local version of cache will be extracted.
Successfully extracted cache
Executing "step_script" stage of the job script

$ ls -alh
总用量 8.0K
drwxrwxr-x. 3 gitlab-runner gitlab-runner  55 7月  25 13:45 .
drwxrwxr-x. 4 gitlab-runner gitlab-runner  34 7月  24 00:49 ..
-rw-rw-r--. 1 gitlab-runner gitlab-runner   5 7月  25 13:45 cat.txt
drwxrwxr-x. 5 gitlab-runner gitlab-runner 117 7月  25 13:45 .git
-rw-rw-r--. 1 gitlab-runner gitlab-runner 767 7月  25 13:45 .gitlab-ci.yml
$ if [[ -f cat.txt ]]; then echo "cat.txt exists ,file content:" && cat cat.txt; else echo "cat.txt not found ,will create cat.txt content 'job1' " &&  echo 'job1' > cat.txt && cat cat.txt; fi
cat.txt exists ,file content:
job3

Saving cache for successful job
Creating cache default-11-protected...
Runtime platform                                    arch=amd64 os=linux pid=24015 revision=76984217 version=15.1.0
cat.txt: found 1 matching files and directories
Archive is up to date!
Created cache
Job succeeded

但是, 需要注意的是: gitlab 规定了 protected 分支与 non-protected 分支所产生的 cache 是不允许共享的, 也就是说 protected 分支触发的 pipeline 所产生的 cache, 不会传递给由 non-protected 分支触发的 pipeline, 反之亦然. 这个行为是通过"Project-Setting-CI/CD-General Pipeline"中的"Use separate caches for protected branches"选项来控制的.

cache:key

cache 可以在同一个项目的 pipeline 中传递, 原因是 cache 都有一个默认的 key:default, 也就是说, 默认情况下, 各 pipeline 创建的 cache 文件会根据 key 覆盖之前的文件

在实际项目中, 一般会让分支之间的 cache 相互独立, 互不干扰

cache:key 可以使用变量, 所以可以通过 cache:key 来实现不同分支使用不同 cache 的目的, 比如下面的例子中, 就使用了"分支名"作为 cache 的 key:

1
2
3
4
cache:
  key: "$CI_COMMIT_BRANCH"
  paths:
    - anyfile

cache:key:files

默认情况下, 每个 job 执行时, 如果配置了 cache, 都会先拉取上次的 cache, 再保存本次的 cache, 但有的时候, 如果某个文件没有发生变化, 是不需要触发再次缓存的

比如前端项目中的"node_modules"目录, 如果"package.json"文件没有发生变化, 就不用重复缓存 node_module 目录, cache:key:files 就提供了这个功能, 当 files 包含的文件发生变化时, 才会重新生成 cache

1
2
3
4
5
6
cache:
  key:
    files:
      - package.json
  paths:
    - node_modules

使用 cache:key:files 时, gitlab 生成的 key 是根据最后一次提交计算出来的一个 SHA 值, 如果最后一次提交中没有文件被修改, key 的值会被指定为"default"

所以通常情况下, 一般要与 key:prefix 配合使用, 避免获取到或者更新的 cache 不符合需求

1
2
3
4
5
6
7
cache:
  key:
    files:
      - package.json
    prefix: $CI_JOB_NAME
  paths:
    - node_modules

前端的 cache 案例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
stages:
  - s1
  - s2

job1:
  stage: s1
  tags:
    - nuxt2
  script:
    - echo 'install'
    - yarn install
  cache:
    paths:
      - node_modules

job2:
  stage: s2
  tags:
    - nuxt2
  script:
    - ls -alh

在这个案例中:

  1. job1 中的 cache 表示这个作业执行时, 既要获取上一次的 cache, 又要在执行结束前按照自己的规则缓存 node_modules 文件
  2. job2 中没有定义 cache,所以它不会获取上一次的 cache, 因为"ls -alh"的结果中已经看不到"node_modules"目录了

cache:policy 更精确的控制 cache 的获取与更新行为

前面说了, job 在执行 script 语句前会先获取 cache, 执行结束前再保存 cache, cache:policy 属性可以控制当前 job 只获取 cache,不更新 cache, 或者不获取 cache,只更新 cache

policy 的值有三种:

  1. pull-push, 这是默认值, 表示既要获取老的 cache,又要更新 cache
  2. pull, 表示只需要获取老的 cache, 不需要再更新 cache 了
  3. push, 表示 script 执行前不需要获取老的 cache, 但是 要更新 cache

when 设置 cache 更新的条件

job 在结束前可以根据 when 字段决定是否要更新 cache, 它有三个值:

  1. on_success, 这是默认值, job 执行成功的时候才能更新 cache
  2. on_failure, job 执行失败的时候才能更新 cache
  3. always, 不管 job 执行成功还是失败, 都要更新 cache

when 可以与 cache:key:files 结合使用,来更精确的控制 cache 功能

untracked 缓存所有的未跟踪状态文件

项目在运行的时候, 可能会产生一些新文件, 这些新文件在 job 执行过程中是不被 git 跟踪的, 也就是被标记为 untracked 状态的文件, 通过 untracked:true 可以把这些未跟踪状态文件添加到 cache 文件列表中

untracked 可以与 cache:paths 相结合使用

禁用 cache

如果 pipeline 设置了全局的 cache, 所有的 job 都会按这个规则执行, 如果想在某个 job 中禁用 cache, 可以像这样:

1
2
3
4
5
6
cache:
  paths:
    - anyfile

job1:
  cache: []

清理 cache

cache 会在 pipeline 中传递, 如果修改了 cache:key 的值, pipeline 在下次执行时会被存放到不同的位置, 达到清理 cache 的目的

也可以通过"Project-CI/CD-pipeline-Clear runner caches"手动清理 cache