[分享] 如何配置使用分布式缓存

首先说下为什么要配置分布式缓存?分布式缓存的作用是什么?
当我们使用 gitlab runner 运行作业的时候,可以通过 CI/CD 关键字 cache 创建一个或者一组文件的缓存,提供给同项目的其他作业或者流水线使用。

Cache创建后是存储在 runner 机器本地的,当我们只使用一个 runner 的时候这当然是没有问题的,执行器始终都会在同一个位置去寻找缓存,但是如果当我们使用多个 runner 的时候,在没有绑定 tag 声明使用哪个 runner 的情况下,执行器就不一定可以找到缓存了,因为缓存只在上一次执行过这个作业的那个 runner 上面。

为了解决缓存在多个 runner 间的使用问题,可以通过配置分布式缓存在 runner 之间共享缓存。目前主要支持的方式是使用兼容 S3 的存储桶。

示例配置/etc/gitlab-runner/config.toml

[[runners]]
  name = "55126c983ed2"
  url = "https://gitlab.example.com"
  id = 2
  token = "aE--1ZFjDB1ydLxF1SYz"
  token_obtained_at = 2023-01-17T03:07:03Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "docker"
  [runners.custom_build_dir]
  [runners.cache]
    Type = "s3"
    Path = "path_prefix"
    Shared = true
    MaxUploadedArchiveSize = 0
    [runners.cache.s3]
      ServerAddress = "172.35.9.8:9000"
      AccessKey = "PN9kz8aC9Eh2I1jq"
      SecretKey = "r19XMjx3jz740YI6x3AEnmOpTFES5olw"
      BucketName = "gitlab-runner-cache"
      BucketLocation = "cn-east-1"
      Insecure = true
    [runners.cache.gcs]
    [runners.cache.azure]

参数设置后作用于所有后续流水线。

Type: 使用兼容 s3 的对象存储直接填写 s3 即可。
Path: s3 URL 的前缀,可任意自定义。
Share: true or false,此值不仅会影响 s3 URL的格式,还决定着每个 runner 的 cache 是否可以共享给其他 runner,如何设置取决于项目的私密性,此外默认情况下保护分支和非保护分支缓存不共享

  • false - http(s)://<ServerAddress>/<BucketName>/<Path>/runner/<runner-id>/project/<id>/<cache-key>
  • true - http(s)://<ServerAddress>/<BucketName>/<Path>/project//<cache-key>

AccessKey: 访问对象存储的 access key。
SecretKey: 访问对象存储的 secret key。
BucketName: 存放缓存的存储桶,需要提前创建好,仅需要创建存储桶即可。
BucketLocation: 根据实际填写即可,即使是使用自建的类似 minio 存储,也可以自行设置区域。
Insecure: 以上示例使用 http 进行访问,否则应设置为 false。

下面介绍几种分布式缓存的使用方式

  1. 使用多个缓存(每个作业最多可以创建 4 个缓存)
test-job:
  stage: build
  cache:
    - key:
        files:
          - Gemfile.lock
      paths:
        - vendor/ruby
    - key:
        files:
          - yarn.lock
      paths:
        - .yarn-cache/
  script:
    - bundle config set --local path 'vendor/ruby'
    - bundle install
    - yarn install --cache-folder .yarn-cache
    - echo Run tests...
  1. 使用回退缓存
variables:
  CACHE_FALLBACK_KEY: fallback-key

job1:
  script:
    - echo
  cache:
    key: "$CI_COMMIT_REF_SLUG"
    paths:
      - binaries/

如果 key="$CI_COMMIT_REF_SLUG"的缓存不存在,则使用 key=“fallback-key” 的缓存。
3. 为某个作业禁用缓存

job:
  cache: []
  1. 继承并覆写全局缓存
cache: &global_cache
  key: $CI_COMMIT_REF_SLUG
  paths:
    - node_modules/
    - public/
    - vendor/
  policy: pull-push

job:
  cache:
    # inherit all global cache settings
    <<: *global_cache
    # override the policy
    policy: pull

继承全局缓存的同时,修改了缓存的操作方式,修改为仅拉取。

以下是一些常见使用示例:
在相同分支的不同作业间共享缓存:

  • key: “$CI_COMMIT_REF_SLUG”
    同项目内在同分支的所有作业之间共享。

  • key: “$CI_JOB_NAME-$CI_COMMIT_REF_SLUG”
    同项目内在同名分支的同名作业之间使用缓存,主要应用于跨流水线。

  • key: “$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG”
    同项目内在同名分支的相同阶段间共享缓存。

  • key: global-key
    同项目内在所有作业所有分支间共享。

  • key: $CI_JOB_NAME
    同项目内同作业名的所有分支间共享。

注意:缓存不能跨项目共享。