GitLab CI/CD에서의 캐싱

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

캐시는 작업이 다운로드하고 저장하는 하나 이상의 파일입니다.

같은 캐시를 사용하는 후속 작업은 파일을 다시 다운로드할 필요가 없으므로 더 빠르게 실행됩니다.

.gitlab-ci.yml 파일에서 캐시를 정의하는 방법에 대한 자세한 내용은
cache 참조를 참조하세요.

캐시가 아티팩트와 다른 점

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

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

아티팩트와 캐시는 모두 프로젝트 디렉터리에 상대적인 경로를 정의하며,
그 외부의 파일에 연결할 수 없습니다.

캐시

  • cache 키워드를 사용하여 작업별로 캐시를 정의하세요. 그렇지 않으면 비활성화됩니다.

  • 후속 파이프라인은 캐시를 사용할 수 있습니다.

  • 같은 파이프라인의 후속 작업은 종속성이 동일할 경우 캐시를 사용할 수 있습니다.

  • 서로 다른 프로젝트는 캐시를 공유할 수 없습니다.

  • 기본적으로 보호된 분기와 비보호된 분기는 캐시를 공유하지 않습니다. 그러나 이 동작을 변경할 수 있습니다.

아티팩트

  • 작업별로 아티팩트를 정의하세요.

  • 같은 파이프라인의 후속 단계에서 후속 작업은 아티팩트를 사용할 수 있습니다.

  • 서로 다른 프로젝트는 아티팩트를 공유할 수 없습니다.

  • 기본적으로 아티팩트는 30일 후에 만료됩니다. 사용자 지정 만료 시간을 정의할 수 있습니다.

  • 가장 최근 아티팩트를 유지하는 경우 최신 아티팩트는 만료되지 않습니다.

  • 어떤 작업이 아티팩트를 가져오는지 제어하려면 dependencies를 사용하세요.

좋은 캐싱 관행

캐시의 최대 가용성을 보장하기 위해 다음 중 하나 이상을 수행하세요:

캐시와 함께 효율적으로 작업하려면 하나의 러너를 사용하거나 다음 중 하나를 수행해야 합니다:

  • 모든 작업에 대해 단일 러너 사용.

  • 여러 러너를 사용하고 분산 캐싱
    통해 캐시를 S3 버킷에 저장합니다. GitLab.com의 인스턴스 러너는 이렇게 작동합니다. 이러한 러너는 자동 확장 모드에 있을 수 있지만
    반드시 그럴 필요는 없습니다. 캐시 객체를 관리하려면
    일정 기간 후에 캐시 객체를 삭제하도록 수명 주기 규칙을 적용하세요.
    수명 주기 규칙은 객체 저장 서버에서 사용할 수 있습니다.

  • 동일한 아키텍처를 가진 여러 러너를 사용하고 이러한 러너가
    캐시를 저장하기 위해 공통 네트워크 장착 디렉터리를 공유하도록 하세요. 이 디렉터리는 NFS 또는 유사한 것을 사용해야 합니다.
    이러한 러너는 자동 확장 모드일 필요가 있습니다.

여러 캐시 사용하기

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

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

자세한 내용은 cache: policy를 참조하세요.

캐시에 대한 일반적인 사용 사례

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

예제는 GitLab CI/CD 템플릿을 참조하세요.

동일한 브랜치의 작업 간 캐시 공유

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

cache:
  key: $CI_COMMIT_REF_SLUG

이 구성은 실수로 캐시를 덮어씌우는 것을 방지합니다. 그러나 병합 요청에 대한 첫 번째 파이프라인은 느립니다. 브랜치에 커밋이 다시 푸시되면 캐시가 재사용되며 작업이 더 빨리 실행됩니다.

작업 및 브랜치별 캐싱을 활성화하려면:

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 "이 작업은 브랜치에 따라 캐시를 당기고 푸시합니다"
    - echo "의존성 다운로드 중..."

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

  • 기본 브랜치에 대한 변경 사항에 대해 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

잠금 파일에서 캐시 키 계산

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

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

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

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의 캐시는 python 패키지를 저장하지 않습니다
    paths:                    # https://pip.pypa.io/en/stable/topics/caching/
      - .cache/pip
  before_script:
    - python -V               # 디버깅을 위한 python 버전 출력
    - 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 .

루비 종속성 캐시

프로젝트가 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'  # 지정된 gems를 설치할 위치
    - bundle install -j $(nproc)                    # ./vendor/ruby에 종속성 설치

rspec:
  script:
    - rspec spec

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

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

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'   # 지정된 gems를 설치할 위치
    - 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 Runner가 설치된 머신에 저장됩니다. 위치는 실행기 유형에 따라 다릅니다.

러너 실행기 캐시의 기본 경로
Shell 로컬, gitlab-runner 사용자의 홈 디렉토리 아래: /home/gitlab-runner/cache/<user>/<project>/<cache-key>/cache.zip.
Docker 로컬, Docker 볼륨 아래: /var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip.
Docker Machine (자동 확장 러너) Docker 실행기와 동일합니다.

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

캐시 키 이름

캐시 키에는 접미사가 추가되며, 전역 폴백 캐시 키는 제외됩니다.

예를 들어 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으로 압축됩니다. 이 파일은 러너의 설정에 따라 디렉터리에 저장됩니다.
  8. job B가 실행됩니다.
  9. 캐시가 추출됩니다(있는 경우).
  10. before_script가 실행됩니다.
  11. script가 실행됩니다.
  12. 파이프라인이 완료됩니다.

단일 머신에서 단일 러너를 사용함으로써 job Bjob A와 다른 러너에서 실행될 수 있는 문제를 피할 수 있습니다. 이 설정은 캐시가 단계를 넘나들며 재사용될 수 있도록 보장합니다. 이는 실행이 build 단계에서 test 단계로 동일한 러너/머신에서 진행될 경우에만 작동합니다. 그렇지 않으면 캐시가 사용 가능하지 않을 수 있습니다.

캐싱 과정에서 고려해야 할 몇 가지 사항이 있습니다:

  • 다른 캐시 구성으로 다른 작업이 동일한 zip 파일에 캐시를 저장한 경우, 덮어씌워집니다. S3 기반 공유 캐시를 사용하는 경우, 파일이 캐시 키에 기반한 객체로 S3에 추가로 업로드됩니다. 따라서 서로 다른 경로를 가진 두 작업이 동일한 캐시 키를 사용할 경우 그들의 캐시가 덮어씌워집니다.
  • cache.zip에서 캐시를 추출할 때 zip 파일의 모든 내용이 작업의 작업 디렉터리(일반적으로 내려받은 리포지토리)에 추출되며, 러너는 job A의 아카이브가 job B의 아카이브에서 항목을 덮어쓰는 것에 대해 신경 쓰지 않습니다.

이렇게 작동하는 이유는 하나의 러너에서 생성된 캐시가 종종 다른 러너에서 사용할 때 유효하지 않기 때문입니다. 다른 러너는 다른 아키텍처에서 실행될 수 있습니다(예를 들어, 캐시에 바이너리 파일이 포함된 경우). 또한, 다른 단계가 서로 다른 머신에서 실행되는 러너에 의해 실행될 수 있기 때문에, 이는 안전한 기본값입니다.

캐시 지우기

러너는 캐시를 사용하여 작업 실행 속도를 높이고 기존 데이터를 재사용합니다. 이로 인해 때때로 일관되지 않은 동작이 발생할 수 있습니다.

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

cache:key 변경으로 캐시 지우기

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

수동으로 캐시 지우기

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

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

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

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

문제 해결

캐시 불일치

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

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

캐시 불일치 예제 1

프로젝트에 하나의 러너만 할당된 경우, 캐시는 기본적으로 러너의 머신에 저장됩니다.

두 개의 작업이 같은 캐시 키를 가지고 있지만 경로가 다른 경우, 캐시가 덮어쓰기될 수 있습니다. 예를 들어:

stages:
  - build
  - test

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

job B:
  stage: test
  script: make test
  cache:
    key: same-key
    paths:
      - vendor/
  1. job A가 실행됩니다.
  2. public/cache.zip으로 캐시됩니다.
  3. job B가 실행됩니다.
  4. 이전 캐시가 있으면 압축 해제됩니다.
  5. vendor/cache.zip으로 캐시되며 이전 것을 덮어씁니다.
  6. 다음 번 job A가 실행될 때 job B의 캐시를 사용하게 되며 이는 다르므로 효과가 없습니다.

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

캐시 불일치 예제 2

이 예제에서는 프로젝트에 할당된 러너가 여러 개 있으며, 분산 캐시가 활성화되지 않은 상태입니다.

파이프라인이 두 번째로 실행될 때, job Ajob B가 서로 다른 캐시를 재사용하기를 원합니다.

stages:
  - build
  - test

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

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

key가 다르더라도, 작업이 다음 파이프라인에서 서로 다른 러너에서 실행될 경우 각 단계 전에 캐시된 파일이 “정리”될 수 있습니다.

동시 러너의 로컬 캐시 누락

Docker 실행기를 사용하여 여러 개의 동시 러너를 구성한 경우, 동시에 실행되는 작업에서 로컬 캐시된 파일이 존재하지 않을 수 있습니다. 캐시 볼륨의 이름은 각 러너 인스턴스에 대해 고유하게 구성되므로, 한 러너 인스턴스에서 캐시된 파일은 다른 러너 인스턴스의 캐시에서 찾을 수 없습니다.

동시 러너 간에 캐시를 공유하려면 다음 방법 중 하나를 사용할 수 있습니다:

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