Gitlab CI/CD 中的 Cache 机制
Cache 的目的
在GitLab CI/CD 中,在 pipeline 中的一些 job 可能会产生一些结果文件,Cache 机制的引入就是为了加快 job 执行的时间。Cache 在使用时制定一系列的文件或者文件目录,使得其在不同的 job 之间被缓存下来。这样当某一个 job 需要依赖于之前步骤产生的一些文件结果,Cache 就帮助我们在上一个 job 将产生的结果缓存下来并且在当前的 job 进行使用。
Cache 的使用方法
首先 cache 的定义范围可以全局定义,这样所有的 job 都会采用这个全局定义的 cache 设置。当然,每个 job 内也可以定义自己特有的 cache 来覆盖全局的配置。
Cache 在使用上主要的配置有以下几种:
1. Cache:paths
paths主要是来指定需要被缓存的文件路径,需要特别指出的是这里的 paths 是相对路径,是相对于gitlab中项目目录的路径,也就是说被缓存的文件都是在项目目录之内的。
以如下配置为例:
在binaries
目录下以 .apk
结尾的所有文件以及 .config
文件会被缓存下来。
当然,如果如果在 job 内部也定义了 cache 配置,全局的配置就会被覆盖,例如:
在 job rspec
中仅 binaries
目录下的所有文件会被缓存,而不是binaries
目录下以 .apk
结尾的所有文件以及 .config
文件。
2. Cache:key
由于 cache 是被不同的 job 所共享,如果不同的 jobs采用了不同的 path
配置,那么 cache 会在每个 job 被执行的时候被覆盖。cache:key
就是为了解决这个问题,当我们给不同 job 定义了不同的 cache:key
时, 每个 job 都会有一个独立的 cache,不同的 key
下的缓存也不会相互影响。
当 cache:key
结合 GitLab CI/CD 中预定义的参数可以有不同的效果:
比如,不同的分支采用不同的 cache,防止分支之间相互影响:
比如每个分支的每个 job 使用不同的 cache :
再比如每个分支的每个 job 使用不同的 stage:
比如不同的分支之间需要共享 cache,但是 pipeline 中的 job 之间的 cache 是相互独立的:
最后,当 key
没有被特别定义的时候,默认为 default,所有没定义 key
的 cache 使用的是同一份 cache,会随着 job 的执行一直被覆盖。
3. Cache:policy
在默认情况下,如果有 cache 的配置,那么每个 job 会在开始执行前将对应路径的文件下载下来,并在任务结束前重新上传,不管文件是否有变化都会如此操作。这个默认的配置是 cache:policy
中的 pull-push
策略。
但是如果我们已经知道,某个 job 只是使用的其他 job 改变的文件,自身并无改变对应路径的文件,那么就不需要进行文件上传操作,采用pull
策略即可。
反过来,某个 job 不依赖于其他 job 改变的文件,自身改变的文件被其他 job 所依赖,那么就不需要在 job 开始前进行文件下载操作,采用push
策略。这样减少了不必要的操作,在一定程度上节约了时间。
在以下配置中,job rspec
使用了pull
策略,所以不会在 job 结束后进行文件的上传操作 :
4. Cache 的继承
如果在使用中,有 job 大部分配置跟全局配置是一样的,但是部分不同,就可以采用继承的方式,而不必全部重写。例如,仅需要覆盖 cache:policy
的配置:
5. Cache 的禁用
如果整个 pipeline 配置全局的 cache,意味着每个 job 在没有特殊配置的情况下会使用全局的配置。但是如果某某个 job 并不使用到 cache,包括缓存文件的上传和下载,那么可以进行如下配置对整个 job 的 cache 禁用:
分布式 Cache
在 GitLab CI/CD 中,我们所使用的 runner 是以 docker 的形式运行不同的任务。普通的 cache 机制,其 cache 均存储在本地,所有如果两个 job 实际运行的位置 是在不用宿主机上,其相互之间的缓存是无法共享的。
为了实现分布式 Cache,需要在配置 GitLab Runner 的 config.toml
的 [runners.cache\]
进行如下配置:
在以上的配置中,对应的 cache 的存储路径如下:
http(s)://<ServerAddress>/<BucketName>/<Path>/project/<id>/<cache-key>
在配置,对应的存储 cache 服务器需要满足 s3 协议,当然也可以自建 cache 服务器。具体操作方法可以参考[自建cache服务器](https://docs.gitlab.com/runner/install/registryandcache_servers.html#install-your-own-cache-server)。
Cache 小实践
1. .gitlab-ci.yml 配置
在以上配置中, job1 和 job3 使用了全局的 cache 配置,job2 独立定义了 ca che 配置,使用了 pull
策略。
2. 执行结果
job1 结果
job2 结果
job3 结果
可以发现:
job2 获取到缓存文件
cattest.txt
的文件内容是 job1 执行后的结果,说明 job1 和 job2 之间实现了缓存共享job3 获取到缓存文件
cattest.txt
的文件与 job1 执行后内容一致而非 j ob2,这是因为 job2 执行后的结果没有进行上传特别注意的是 job1 在执行任务前获取到的
cattest.txt
的文件与 job3 执行完的结果一致,这是因为这个 pipeline 我运行了多次,job1 获取的缓存是上一次 pipeline 中 job3 的执行后的缓存结果。说明 cache 在不同次 pipeline 之间也实现了共享
版权声明: 本文为 InfoQ 作者【Chong】的原创文章。
原文链接:【http://xie.infoq.cn/article/74ad6aefa72e4103260494126】。文章转载请联系作者。
评论