GitLab CI/CD에서의 캐싱

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-Managed, GitLab Dedicated

캐시는 작업이 다운로드하고 저장하는 하나 이상의 파일입니다. 동일한 캐시를 사용하는 후속 작업은 파일을 다시 다운로드할 필요가 없어 더 빠르게 실행됩니다.

.gitlab-ci.yml 파일에서 캐시를 정의하는 방법은 캐시 참조를 참조하세요.

캐시와 아티팩트의 차이점

캐시는 인터넷에서 다운로드하는 패키지와 같은 의존성에 대해 사용합니다. 캐시는 GitLab Runner가 설치된 위치에 저장되며 분산 캐시가 활성화된 경우 S3에 업로드됩니다.

아티팩트는 단계 간에 중간 빌드 결과를 전달하는 데 사용됩니다. 아티팩트는 작업에 의해 생성되며 GitLab에 저장되어 다운로드할 수 있습니다.

아티팩트와 캐시는 프로젝트 디렉터리를 기준으로 경로를 정의하며 해당 디렉터리 외부의 파일에 연결할 수 없습니다.

캐시

  • cache 키워드를 사용하여 작업당 캐시를 정의합니다. 그렇지 않으면 비활성화됩니다.
  • 후속 파이프라인은 캐시를 사용할 수 있습니다.
  • 동일한 파이프라인의 후속 작업은 의존성이 동일하다면 캐시를 사용할 수 있습니다.
  • 서로 다른 프로젝트는 캐시를 공유할 수 없습니다.
  • 기본적으로 보호 및 보호되지 않은 브랜치는 캐시를 공유하지 않습니다. 그러나 이 동작을 변경할 수 있습니다.

아티팩트

  • 작업당 아티팩트를 정의합니다.
  • 동일 파이프라인의 후속 작업은 아티팩트를 사용할 수 있습니다.
  • 서로 다른 프로젝트는 아티팩트를 공유할 수 없습니다.
  • 기본적으로 아티팩트는 30일 후에 만료됩니다. 사용자 정의 만료 시간을 정의할 수 있습니다.
  • 최신 아티팩트는 최신 성공적인 작업에서 아티팩트를 유지하는 경우 만료되지 않습니다.
  • 어떤 작업이 아티팩트를 가져올지를 제어하려면 의존성을 사용하세요.

캐싱의 좋은 관행

캐시를 최대한 활용하기 위해 다음 중 하나 이상을 수행하세요:

  • 러너(runner)에 태그를 지정하고 캐시를 공유하는 작업에 해당 태그를 사용합니다.
  • 특정 프로젝트에만 사용 가능한 러너(runner)를 사용합니다.
  • 워크플로에 맞는 key를 사용합니다. 예를 들어, 각 브랜치마다 다른 캐시를 구성할 수 있습니다.

캐시가 효율적으로 사용되려면 다음 중 하나를 수행해야 합니다:

  • 모든 작업에 하나의 러너(runner)를 사용합니다.
  • 캐시가 S3 버킷에 저장되는 분산 캐싱을 하는 여러 러너(runner)를 사용합니다. GitLab.com의 인스턴스 러너(runner)는 이 방식으로 동작합니다. 이러한 러너(runner)는 autoscale 모드에 있어야 하지만 필수는 아닙니다. 캐시 객체를 관리하려면 일정 기간 지난 후에 캐시 객체를 삭제하기 위해 오브젝트 스토리지 서버에서 라이프사이클 규칙을 적용하세요.
  • 동일한 아키텍처를 가진 여러 러너(runner)를 사용하고 이러한 러너(runner)가 캐시를 저장하는 공통 네트워크 마운트 디렉터리를 공유합니다. 이 디렉터리는 NFS 또는 유사한 것을 사용해야 합니다. 이러한 러너(runner)는 autoscale 모드에 있어야 합니다.

여러 캐시 사용

최대 네 개의 캐시를 가질 수 있습니다:

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...

여러 캐시가 대체 캐시 키와 결합된 경우 전역 대체 캐시가 발견되지 않을 때마다 전역 대체 캐시가 가져옵니다.

대체 캐시 키 사용

캐시별 대체 키

각 캐시 항목은 fallback_keys 키워드로 최대 다섯 개의 대체 키를 지원합니다. 작업이 캐시 키를 찾지 못하면 작업은 대신 대체 캐시를 가져오려고 시도합니다. 대체 키는 순서대로 검색되며 캐시가 발견될 때까지 찾습니다. 캐시가 발견되지 않으면 해당 캐시를 사용하지 않고 작업이 실행됩니다. 예:

test-job:
  stage: build
  cache:
    - key: cache-$CI_COMMIT_REF_SLUG
      fallback_keys:
        - cache-$CI_DEFAULT_BRANCH
        - cache-default
      paths:
        - vendor/ruby
  script:
    - bundle config set --local path 'vendor/ruby'
    - bundle install
    - echo Run tests...

이 예에서:

  1. 작업은 cache-$CI_COMMIT_REF_SLUG 캐시를 찾습니다.
  2. cache-$CI_COMMIT_REF_SLUG를 찾지 못하면 작업은 대체 옵션으로 cache-$CI_DEFAULT_BRANCH를 찾습니다.
  3. cache-$CI_DEFAULT_BRANCH도 발견되지 않을 경우 작업은 두 번째 대체 옵션인 cache-default를 찾습니다.
  4. 발견되지 않을 경우 작업은 모든 Ruby 의존성을 사용하여 새로운 캐시를 만들지만, 작업이 완료될 때 cache-$CI_COMMIT_REF_SLUG용 캐시를 생성합니다.

대체 키는 cache:key와 동일한 처리 로직을 따릅니다:

전역 대체 키

$CI_COMMIT_REF_SLUG 사전 정의된 변수를 사용하여 cache:key를 지정할 수 있습니다. 예를 들어, $CI_COMMIT_REF_SLUGtest인 경우 test로 태그가 지정된 캐시를 가져오도록 작업을 설정할 수 있습니다.

이 태그와 일치하는 캐시를 찾을 수 없을 때 CACHE_FALLBACK_KEY를 사용하여 사용할 캐시를 지정할 수 있습니다.

다음 예에서, $CI_COMMIT_REF_SLUG를 찾을 수 없는 경우 작업은 CACHE_FALLBACK_KEY 변수가 정의한 키를 사용합니다:

variables:
  CACHE_FALLBACK_KEY: fallback-key

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

캐시 추출의 순서는 다음과 같습니다:

  1. cache:key를 검색합니다.
  2. fallback_keys의 각 항목에 대해 순서대로 검색합니다.
  3. CACHE_FALLBACK_KEY의 전역 대체 키를 검색합니다.

캐시 추출 프로세스는 첫 번째 성공한 캐시를 검색한 후에 중지됩니다.

특정 작업에 대한 캐시 비활성화

전역으로 캐시를 정의하면 각 작업이 동일한 정의를 사용합니다. 각 작업에 대해 이 동작을 재정의할 수 있습니다.

작업을 완전히 비활성화하려면 빈 디렉터리을 사용합니다:

job:
  cache: []

전역 구성 상속 및 특정 설정 재정의

앵커를 사용하여 전체 캐시를 덮어쓰지 않고 작업별로 캐시 설정을 재정의할 수 있습니다. 예를 들어, 하나의 작업에서 policy를 재정의하려면:

default:
  cache: &global_cache
    key: $CI_COMMIT_REF_SLUG
    paths:
      - node_modules/
      - public/
      - vendor/
    policy: pull-push

job:
  cache:
    # 모든 전역 캐시 설정을 상속합니다
    <<: *global_cache
    # 정책을 재정의합니다
    policy: pull

캐시의 일반적인 사용 사례

일반적으로 작업을 실행할 때마다 의존성이나 라이브러리를 매번 다운로드하지 않도록 하기 위해 캐시를 사용합니다. Node.js 패키지, PHP 패키지, Ruby gem, Python 라이브러리 등이 캐시될 수 있습니다.

예를 들어, GitLab CI/CD 템플릿을 참조하세요.

동일 브랜치 내에서 작업 간에 캐시 공유

각 브랜치의 작업이 동일한 캐시를 사용하도록 하려면 key: $CI_COMMIT_REF_SLUG로 캐시를 정의하세요:

cache:
  key: $CI_COMMIT_REF_SLUG

이 구성은 캐시를 실수로 덮어쓰지 않도록 방지합니다. 그러나 Merge Request에 대한 첫 번째 파이프라인은 느립니다. 브랜치에 커밋이 다음으로 푸시되면 캐시가 재사용되어 작업이 더 빨리 실행됩니다.

각 작업 및 브랜치에 대한 캐싱 활성화:

cache:
  key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"

각 스테이지 및 브랜치에 대한 캐싱 활성화:

cache:
  key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG"

서로 다른 브랜치의 작업 간에 캐시 공유

모든 브랜치 및 모든 작업 간에 캐시를 공유하려면 모든 것에 동일한 키를 사용하세요:

cache:
  key: one-key-to-rule-them-all

브랜치 간에 캐시를 공유하되 각 작업에는 고유한 캐시가 있도록 하려면:

cache:
  key: $CI_JOB_NAME

작업의 캐시 정책을 제어하기 위해 변수 사용

작업이 다른 점이 이미지 끌어오기 정책일 경우에만 중복 작업을 줄이려면 CI/CD 변수를 사용할 수 있습니다.

예:

conditional-policy:
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      variables:
        POLICY: pull-push
    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
      variables:
        POLICY: pull
  stage: build
  cache:
    key: gems
    policy: $POLICY
    paths:
      - vendor/bundle
  script:
    - echo "This job pulls and pushes the cache depending on the branch"
    - echo "Downloading dependencies..."

이 예에서 작업의 캐시 정책은:

  • 기본 브랜치에 대한 변경의 경우 pull-push.
  • 다른 브랜치에 대한 변경의 경우 pull.

Node.js 의존성 캐시

프로젝트가 npm을 통해 Node.js 의존성을 설치하는 경우, 다음 예제는 모든 작업이 기본 cache를 상속하도록 합니다. 기본적으로 npm은 캐시 데이터를 홈 폴더(~/.npm)에 저장합니다. 그러나 프로젝트 디렉터리 외부에는 캐시할 수 없습니다. 대신 npm에게 ./.npm을 사용하도록 지시하고 브랜치별로 캐시될 수 있도록 합니다:

default:
  image: node:latest
  cache:  # 작업 간에 모듈을 캐시
    key: $CI_COMMIT_REF_SLUG
    paths:
      - .npm/
  before_script:
    - npm ci --cache .npm --prefer-offline

test_async:
  script:
    - node ./specs/start.js ./specs/async.spec.js

Lock 파일에서 캐시 키 계산

cache:key:files를 사용하여 package-lock.json이나 yarn.lock과 같은 lock 파일에서 캐시 키를 계산하고 여러 작업에서 재사용할 수 있습니다.

default:
  cache:  # Lock 파일을 사용하여 모듈 캐싱
    key:
      files:
        - package-lock.json
    paths:
      - .npm/

Yarn을 사용하는 경우, yarn-offline-mirror를 사용하여 압축된 node_modules 타볼을 캐시할 수 있습니다. 더 적은 파일을 압축해야 하기 때문에 캐시가 더 빨리 생성됩니다:

job:
  script:
    - echo 'yarn-offline-mirror ".yarn-cache/"' >> .yarnrc
    - echo 'yarn-offline-mirror-pruning true' >> .yarnrc
    - yarn install --frozen-lockfile --no-progress
  cache:
    key:
      files:
        - yarn.lock
    paths:
      - .yarn-cache/

PHP 의존성 캐시

프로젝트가 Composer를 사용하여 PHP 의존성을 설치하는 경우, 다음 예제는 모든 작업이 상속할 수 있도록 기본 cache를 정의합니다. PHP 라이브러리 모듈은 vendor/에 설치되며 브랜치별로 캐시됩니다:

default:
  image: php:7.2
  cache:  # 작업간에 라이브러리를 캐시
    key: $CI_COMMIT_REF_SLUG
    paths:
      - vendor/
  before_script:
    # 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

Python 의존성 캐시

프로젝트가 pip를 사용하여 Python 의존성을 설치하는 경우, 다음 예제는 모든 작업이 상속할 수 있도록 기본 cache를 정의합니다. pip의 캐시는 .cache/pip/에 정의되며 브랜치별로 캐시됩니다:

default:
  image: python:latest
  cache:                       # Pip의 캐시는 파이썬 패키지를 저장하지 않습니다
    paths:                     # https://pip.pypa.io/en/stable/topics/caching/
      - .cache/pip
  before_script:
    - python -V                # 디버그를 위해 파이썬 버전 출력
    - pip install virtualenv
    - virtualenv venv
    - source venv/bin/activate

variables:  # 로컬 항목만 캐시할 수 있기 때문에 pip의 캐시 디렉터리를 프로젝트 디렉터리 내로 변경
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"

test:
  script:
    - python setup.py test
    - pip install ruff
    - ruff --format=gitlab .

Ruby 의존성 캐시

프로젝트가 Bundler를 사용하여 gem 의존성을 설치하는 경우, 다음 예제는 모든 작업이 상속할 수 있도록 기본 cache를 정의합니다. Gems는 vendor/ruby/에 설치되며 브랜치별로 캐시됩니다:

default:
  image: ruby:2.6
  cache:                                             # 작업 간에 gems를 캐시
    key: $CI_COMMIT_REF_SLUG
    paths:
      - vendor/ruby
  before_script:
    - ruby -v                                        # 디버그를 위해 루비 버전 출력
    - bundle config set --local path 'vendor/ruby'   # 지정된 gem의 설치 위치
    - bundle install -j $(nproc)                     # ./vendor/ruby에 의존성 설치

rspec:
  script:
    - rspec spec

다른 gem이 필요한 작업이 있는 경우 글로벌 cache 정의에서 prefix 키워드를 사용하세요. 이 구성은 각 작업에 대해 다른 캐시를 생성합니다.

예를 들어, 테스트 작업은 프로덕션으로 배포하는 작업과 같은 gem이 필요하지 않을 수 있습니다:

default:
  cache:
    key:
      files:
        - Gemfile.lock
      prefix: $CI_JOB_NAME
    paths:
      - vendor/ruby

test_job:
  stage: test
  before_script:
    - bundle config set --local path 'vendor/ruby'
    - bundle install --without production
  script:
    - bundle exec rspec

deploy_job:
  stage: production
  before_script:
    - bundle config set --local path 'vendor/ruby'   # 지정된 gem의 설치 위치
    - bundle install --without test
  script:
    - bundle exec deploy

Go 의존성 캐시

프로젝트가 Go Modules를 사용하여 Go 의존성을 설치하는 경우, 다음 예제는 모든 작업에서 확장할 수 있는 go-cache 템플릿에 cache를 정의합니다. Go 모듈은 ${GOPATH}/pkg/mod/에 설치되며 모든 go 프로젝트에서 캐시됩니다.

.go-cache:
  variables:
    GOPATH: $CI_PROJECT_DIR/.go
  before_script:
    - mkdir -p .go
  cache:
    paths:
      - .go/pkg/mod/
      
test:
  image: golang:1.13
  extends: .go-cache
  script:
    - go test ./... -v -short

캐시의 가용성

캐싱은 최적화입니다. 하지만 항상 작동한다고 보장할 수는 없습니다. 필요한 각 작업에서 캐시된 파일을 다시 생성해야 할 수 있습니다.

.gitlab-ci.yml에 캐시를 정의한 후 캐시의 가용성은 다음에 따라 달라집니다.

  • 러너의 실행자 유형.
  • 캐시를 작업 간에 전달하기 위해 다른 러너가 사용되는지 여부.

캐시가 저장된 위치

작업에 정의된 모든 캐시는 단일 cache.zip 파일에 보관됩니다. 러너 구성에서 파일이 저장되는 위치를 정의합니다. 기본적으로 캐시는 GitLab 러너가 설치된 기계에 저장됩니다. 위치는 실행자 유형에 따라 달라집니다.

러너 실행자 캐시의 기본 경로
Shell 로컬에서 gitlab-runner 사용자의 홈 디렉터리 하위에 저장됨: /home/gitlab-runner/cache/<user>/<project>/<cache-key>/cache.zip.
Docker 로컬에서 도커 볼륨에 저장됨: /var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip.
Docker Machine (자동확장 러너) 도커 실행자와 동일함.

작업에서 동일한 경로에 캐시와 아티팩트를 저장하는 경우 캐시가 덮어쓰일 수 있습니다. 왜냐하면 캐시는 아티팩트보다 먼저 복원되기 때문입니다.

캐시 키명

캐시 키에 접미사가 추가됩니다. 글로벌 대체 캐시 키를 제외하고 추가됩니다.

예를 들어, cache.key$CI_COMMIT_REF_SLUG로 설정되고 mainfeature 두 개의 브랜치가 있다고 가정하면, 다음 표는 결과적인 캐시 키를 나타냅니다.

브랜치 이름 캐시 키
main main-protected
feature feature-non_protected
모든 브랜치에 동일한 캐시 사용

캐시 키명을 사용하고 싶지 않으면 모든 브랜치(보호된 브랜치 및 비보호된 브랜치)에 동일한 캐시를 사용할 수 있습니다.

캐시 키명으로 캐시 분리는 보안 기능이며, 개발자 역할을 하는 모든 사용자가 높은 신뢰를 가진 환경에서만 비활성화해야 합니다.

모든 브랜치에 동일한 캐시를 사용하려면:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
  2. 설정 > CI/CD를 선택합니다.
  3. 일반 파이프라인을 확장합니다.
  4. 보호된 브랜치에 대해 별도의 캐시 사용 확인란을 선택해제합니다.
  5. 변경 사항 저장을 선택합니다.

아카이빙 및 추출 작업 방식

다음 예제는 두 연속 단계에서 두 작업을 보여줍니다.

stages:
  - build
  - test

default:
  cache:
    key: build-cache
    paths:
      - vendor/
  before_script:
    - echo "Hello"

job A:
  stage: build
  script:
    - mkdir vendor/
    - echo "build" > vendor/hello.txt
  after_script:
    - echo "World"

job B:
  stage: test
  script:
    - cat vendor/hello.txt

한 기계에 한 러너가 설치된 경우 프로젝트의 모든 작업이 동일한 호스트에서 실행됩니다.

  1. 파이프라인 시작.
  2. job A 실행.
  3. 캐시가 추출됨(존재하는 경우).
  4. before_script 실행.
  5. script 실행.
  6. after_script 실행.
  7. cache 실행 및 vendor/ 디렉터리가 cache.zip로 압축됩니다. 이 파일은 러너 설정cache: key에 기반하여 디렉터리에 저장됩니다.
  8. job B 실행.
  9. 캐시가 추출됨(존재하는 경우).
  10. before_script 실행.
  11. script 실행.
  12. 파이프라인 완료.

한 기계에서 단일 러너를 사용하면 job Bjob A와 다른 러너에서 실행될 수 있는 문제가 없습니다. 이 설정은 단계 간에 캐시를 재사용할 수 있음을 보장합니다. build 단계에서 test 단계로 실행이 동일한 러너/기계에서 이루어진다는 전제하에만 작동합니다. 그렇지 않으면 캐시가 사용 불가할 수 있습니다.

캐싱 프로세스 중에 고려해야 할 몇 가지 사항이 있습니다.

  • 다른 경로를 가진 또 다른 작업이 다른 캐시 구성을 사용하여 캐시를 저장한 경우 덮어쓰입니다. S3 기반 공유 캐시를 사용한 경우 파일은 캐시 키에 따라 S3에 추가로 업로드됩니다. 따라서 경로가 다르지만 캐시 키가 동일한 두 작업은 자신의 캐시를 덮어씁니다.
  • cache.zip에서 캐시를 추출할 때 zip 파일의 모든 것을 작업의 작업 디렉터리(일반적으로 다운로드된 리포지터리)에 추출하며, job A의 아카이브가 job B의 아카이브를 덮어쓰더라도 러너가 이를 처리합니다.

한 러너에서 생성된 캐시는 보통 다른 러너에서 사용할 수 없습니다. 다른 러너는 다른 아키텍처에서 실행할 수 있습니다(예: 캐시에 바이너리 파일이 포함된 경우). 또한 다른 단계가 다른 기계에서 실행될 수 있기 때문에 안전한 기본값입니다.

캐시 지우기

러너는 캐시 사용하여 작업 실행을 가속화합니다. 때로는 일관성 없는 동작을 유발할 수 있습니다.

캐시의 새로운 복사본으로 시작하는 두 가지 방법이 있습니다.

cache:key를 변경하여 캐시 지우기

.gitlab-ci.yml 파일의 cache: key 값을 변경합니다. 다음번 파이프라인 실행 시 캐시는 다른 위치에 저장됩니다.

매뉴얼으로 캐시 지우기

GitLab UI에서 캐시를 지울 수 있습니다.

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하여 프로젝트를 찾습니다.
  2. 빌드 > 파이프라인을 선택합니다.
  3. 오른쪽 상단에서 러너 캐시 지우기를 선택합니다.

다음 커밋부터 CI/CD 작업은 새로운 캐시를 사용합니다.

note
매뉴얼으로 캐시를 지울 때마다 내부 캐시 이름이 업데이트됩니다. 이름은 cache-<index> 형식을 사용하며, 인덱스는 1씩 증가합니다. 이전 캐시는 삭제되지 않습니다. 이러한 파일은 러너 리포지터리에서 매뉴얼으로 삭제할 수 있습니다.

문제 해결

캐시 불일치

캐시 불일치가 발생한 경우, 다음 단계를 따라 문제를 해결하세요.

캐시 불일치의 이유 해결 방법
하나의 프로젝트에 여러 개의 독립 실행형 러너(자동 스케일 모드가 아닌)가 공유 캐시 없이 연결됨. 프로젝트에 한 개의 러너만 사용하거나 분산 캐시가 활성화된 여러 러너를 사용하세요.
자동 스케일 모드의 러너를 사용하고 분산 캐시가 비활성화되어 있는 경우. 자동 스케일 러너를 구성하여 분산 캐시를 사용하도록 설정하세요.
러너가 설치된 머신의 디스크 공간이 부족하거나 분산 캐시가 설정된 경우, 캐시가 저장된 S3 버킷에 충분한 공간이 없음. 새 캐시를 저장할 공간을 확보하기 위해 어느 정도의 공간을 비워주세요. 이 과정에는 자동화된 방법이 없습니다.
동일한 key를 사용하여 다른 경로에 캐시되는 작업. 각 작업에 대해 다른 캐시 키를 사용하여 캐시 아카이브를 다른 위치에 저장하고 잘못된 캐시를 덮어쓰지 않도록 해주세요.
러너에서 분산 러너 캐싱을 활성화하지 않은 경우. Shared = false로 설정하고 러너를 재구성하세요.

캐시 불일치 예제 1

프로젝트에 할당된 러너가 한 개뿐이라면, 기본적으로 캐시는 러너의 머신에 저장됩니다.

두 개의 작업이 동일한 캐시 키를 가지고 다른 경로를 참조하는 경우, 캐시가 덮어씌워질 수 있습니다. 예시:

stages:
  - build
  - test

작업 A:
  stage: build
  script: make build
  cache:
    key: same-key
    paths:
      - public/

작업 B:
  stage: test
  script: make test
  cache:
    key: same-key
    paths:
      - vendor/
  1. 작업 A를 실행합니다.
  2. public/cache.zip로 캐시됩니다.
  3. 작업 B를 실행합니다.
  4. 이전의 캐시가 있다면 압축을 푼다.
  5. vendor/cache.zip으로 캐시되어 이전 것을 덮어씁니다.
  6. 다음으로 작업 A가 실행될 때, 다른 작업 B의 캐시가 사용되어 잘못된 효과를 낳습니다.

이 문제를 해결하려면 각 작업에 대해 다른 key를 사용하세요.

캐시 불일치 예제 2

이 예제에서는 프로젝트에 여러 러너가 할당되어 있고 분산 캐시가 비활성화되어 있는 경우입니다.

파이프라인이 두 번째 실행되는 경우, 작업 A작업 B가 각자 다른 캐시를 재사용하길 원합니다(이 경우에는 다릅니다):

stages:
  - build
  - test

작업 A:
  stage: build
  script: build
  cache:
    key: keyA
    paths:
      - vendor/

작업 B:
  stage: test
  script: test
  cache:
    key: keyB
    paths:
      - vendor/

key가 다르더라도, 다음 파이프라인에서 각 작업이 다른 러너에서 실행된다면 각 스테이지마다 캐시된 파일이 “정리”될 수 있습니다.

동시에 실행되는 작업들을 위해 캐시를 공유하기 위해서는 다음 중 하나를 선택할 수 있습니다:

  • 러너의 config.toml[runners.docker] 섹션을 사용하여 각 컨테이너의 /cache에 매핑된 호스트의 단일 마운트 지점을 구성합니다. 이는 러너가 고유한 볼륨 이름을 생성하는 것을 방지합니다.
  • 분산 캐시를 사용합니다.