CI 구성의 성능

중단 가능한 파이프라인

기본적으로 모든 작업은 중단 가능합니다. dont-interrupt-me 작업은 main에서 자동으로 실행되며, 그렇지 않은 경우에는 수동입니다.

병합 요청에 새로운 커밋을 푸시하더라도 실행 중인 파이프라인을 완료하려면 푸시하기 전에 dont-interrupt-me 작업을 시작해야 합니다.

Git 페치 캐싱

GitLab.com은 팩 오브젝트 캐시를 사용하기 때문에 동시에 수행되는 동일한 파이프라인 ref의 Git 페치가 Gitaly 서버에서 중복 처리되고 (항상) 캐시에서 제공됩니다 (사용 가능한 경우).

이는 다음과 같은 이유로 잘 작동합니다:

  • 팩 오브젝트 캐시는 GitLab.com의 모든 Gitaly 서버에서 활성화되어 있습니다.
  • CI/CD의 Git 전략 설정Git 클론 이기 때문에 모든 작업이 동일한 데이터를 가져오도록하여 캐시 히트 비율을 극대화합니다.
  • 우리는 얕은 클론을 사용하여 각 작업마다 전체 Git 히스토리를 다운로드하지 않도록 합니다.

Gitaly에서 클론/페치하는 대신 아티팩트를 통해 저장소 가져오기

요즘 우리는 Gitaly에서 다음과 같은 오류를 보게 되었습니다: (문제를 보려면 여기를 참조하십시오)

fatal: remote error: GitLab is currently unable to handle this request due to load.

GitLab.com은 팩 오브젝트 캐시를 사용하지만 가끔 여전히 Gitaly가 처리하기에 부담이 되는 경우가 있고, 천둥의 무리가 리포지토리를 대량으로 복제하는 많은 작업이 동시에 발생할 수도 있습니다.

Gitaly의 부담을 줄이고, 감소시키기 위해 일부 작업을 한 번에 모두 Gitaly에서 복제하는 대신 작업에서 아티팩트로부터 리포지토리를 가져오도록 변경하였습니다.

현재 대부분의 파이프라인에서 가장 많이 동시에 작업하는 RSpec 작업에 이 적용되며, 아티팩트로부터 가져오는 것이 복제보다 약간 더 빠르기도 합니다. 단, 각 파이프라인마다 더 많은 아티팩트를 저장하도록 하기 때문에 약간의 저장 공간을 더 사용하는 대신 약 15초를 절약할 수 있습니다.

2023-12-20의 숫자를 기반으로 한 RSpec 작업을 위한 아티팩트로부터 리포지토리 가져오기에 따르면 추가 저장 비용은 각 파이프라인마다 약 280M이었고, 각 RSpec 작업마다 15초를 절약할 수 있었습니다.

이를 사용하지 않는 이유는 다른 작업이 시작되는 것을 지연시키고 싶지 않기 때문입니다.

이 동작은 변수 CI_FETCH_REPO_GIT_STRATEGY로 제어할 수 있습니다:

  • none으로 설정하면 .repo-from-artifacts를 사용하는 작업은 clone-gitlab-repo 작업에서 아티팩트로부터 리포지토리를 가져오고 복제하지 않습니다.
  • clone으로 설정하면 .repo-from-artifacts를 사용하는 작업은 일반적으로 리포지토리를 복제합니다. 이 경우, clone-gitlab-repo 작업은 실행되지 않습니다.

비활성화하려면 CI_FETCH_REPO_GIT_STRATEGYclone로 설정하십시오. 활성화하려면 CI_FETCH_REPO_GIT_STRATEGYnone으로 설정하십시오.

캐싱 전략

  1. 기본적으로 모든 작업은 캐시를 당겨야 합니다.
  2. 모든 작업은 캐시 없이도 통과할 수 있어야 합니다. 다시 말해, 캐시는 작업을 가속화하기 위해서만 사용됩니다.
  3. 현재 .gitlab/ci/global.gitlab-ci.yml에 정의된 여러 다른 캐시 정의가 있습니다:
    • .setup-test-env-cache
    • .ruby-cache
    • .static-analysis-cache
    • .rubocop-cache
    • .ruby-gems-coverage-cache
    • .ruby-node-cache
    • .qa-cache
    • .yarn-cache
    • .assets-compile-cache (키에 ${NODE_ENV}가 포함되어 있어서 실제로 두 개의 다른 캐시로 나뉩니다).
  4. 이러한 캐시 정의는 여러 가지 원자적 캐시로 구성되어 있습니다.
  5. 2시간마다 실행되는 maintenance 예약 파이프라인에서 실행되는 다음 작업들만이 캐시에 푸시(즉, 업데이트)하는 작업입니다:
  6. 이러한 작업은 또한 pipeline:update-cache 라벨이 있는 머지 요청에서 강제로 실행되도록 할 수 있습니다 (이는 캐시 키를 업데이트하는 MR에서 캐시를 사전에 로드하는 데 유용할 수 있습니다).

아티팩트 전략

작업에 의해 저장 및 검색되는 아티팩트를 최소로 제한하여 업로드/다운로드 시간과 비용, 그리고 아티팩트 저장 공간을 줄입니다.

구성 요소 캐싱

GitLab의 일부 외부 구성 요소(GitLab Workhorse 및 프론트엔드 자산)는 테스트를 실행하기 전에 소스에서 빌드해야 합니다.

cache-workhorse

이 MR을 통해 그리고 이 MR을 통해, 다음을 하는 새로운 cache-workhorse 작업을 소개했습니다:

  • GitLab.com gitlab-org/gitlab 예약된 파이프라인에 자동으로 실행됨
  • workhorse/ 폴더에 속하는 master 커밋을 자동으로 실행함
  • 캐싱 관련 파일에 건드리는 GitLab.com gitlab-org MR에 대해 수동으로 실행함

이 작업은 GitLab 테스트 스위트에서 필요한 GitLab Workhorse 이진 파일을 포함하는 일반 패키지를 다운로드하려고 시도합니다(tmp/tests/gitlab-workhorse 아래).

  • 패키지 URL이 404를 반환하는 경우:
    1. scripts/setup-test-env를 실행하여 GitLab Workhorse 이진 파일을 빌드함.
    2. 그런 다음 바이너리를 포함하는 아카이브를 생성하고 일반 패키지로 업로드함.
  • 그렇지 않으면, 패키지가 이미 존재하면 작업을 성공적으로 종료함.

또한 setup-test-env 작업을 변경하여:

  1. 먼저 cache-workhorse에 의해 빌드되고 업로드된 GitLab Workhorse 일반 패키지를 다운로드함.
  2. 패키지가 성공적으로 검색되면 해당 내용을 올바른 폴더(예: tmp/tests/gitlab-workhorse)에 배치하여 scripts/setup-test-env가 나중에 실행될 때 바이너리를 빌드하는 것을 방지함.
  3. 패키지 URL이 404를 반환하면 현재와 동일한 동작: scripts/setup-test-env의 일부로 GitLab Workhorse 바이너리가 빌드됨.

참고: 패키지 버전은 workhorse 트리 SHA임(예: git rev-parse HEAD:workhorse).

cache-assets

이 MR를 통해, 다음을 하는 세 개의 새로운 cache-assets:test, cache-assets:test as-if-foss, cache-assets:production 작업을 소개했습니다:

  • $CACHE_ASSETS_AS_PACKAGE == "true"인 경우에만 실행되지 않음
  • GitLab.com gitlab-org/gitlab 예약된 파이프라인에 자동으로 실행됨
  • 자산 관련 폴더에 속하는 master 커밋을 자동으로 실행함
  • 캐싱 관련 파일에 건드리는 GitLab.com gitlab-org MR에 대해 수동으로 실행함

이 작업은 GitLab 테스트 스위트에서 필요한 GitLab 빌드된 자산을 포함하는 일반 패키지를 다운로드하려고 시도합니다(app/assets/javascripts/locale/**/app.jspublic/assets 아래).

  • 패키지 URL이 404를 반환하는 경우:
    1. bin/rake gitlab:assets:compile를 실행하여 GitLab 자산을 컴파일함.
    2. 그런 다음 자산을 포함하는 아카이브를 생성하고 일반 패키지로 업로드함. 패키지 버전은 자산 폴더의 해시 합으로 설정됨.
  • 그렇지 않으면, 패키지가 이미 존재하면 작업을 성공적으로 종료함.

compile-*-assets

또한 compile-test-assets, compile-test-assets as-if-foss, compile-production-assets 작업을 변경하여:

  1. 먼저 “원시” 캐시 자산을 다운로드함. 이 자산에는 다음이 포함됨:
    • 컴파일된 자산.
    • cached-assets-hash.txt 파일은 자산이 의존하는 모든 소스 파일의 SHA256 해시 값인 SHA256 해시 값을 포함함. 이 파일은 비관적인 목록이며 자산이 이러한 파일들 중 일부에 의존할 수 있음. 최악의 경우에는 자산을 더 자주 컴파일하지만, 사용되지 않는 자산을 사용하는 것보다는 나음. 파일은 자산이 컴파일된 후에 생성됨.
  2. 그런 다음 현재 체크아웃된 브랜치에 대한 SHA256 해시 값을 계산함. 이 해시 값을 GITLAB_ASSETS_HASH 변수에 저장함.
  3. $CACHE_ASSETS_AS_PACKAGE == "true"이면, cache-assets:*에의해 빌드되고 업로드된 일반 패키지를 다운로드함.
    • 확인된 브랜치의 캐시가 최신 상태인 경우, 원시 캐시와 캐시 패키지를 다운로드함. 원시 캐시를 다운로드하지 않고도 최적화할 수 있지만, 원시 캐시는 실제로 매우 자주 오래되므로 2시간마다 재구축됨.
  4. assets_compile_script 함수를 실행하여 실행하고 assets:compile Rake 태스크를 실행. 이 작업은 자산을 컴파일할지 여부를 결정함. 이 작업$GITLAB_ASSETS_HASHHEAD SHA256 해시를 master의 해시와 비교함.
  5. 해시가 동일하면 아무것도 컴파일하지 않음. 다르면 자산을 컴파일함.

스트립된 이진 파일

기본 설정으로 setup-test-env는 연속적인 CI 작업의 아티팩트 다운로드를 절약하고 가속화하기 위해 스트립된 이진 파일을 포함하는 아티팩트를 생성합니다.

스트립된 이진 파일에서의 충돌을 디버깅하기 쉽게 만들려면 setup-test-job 작업에서 strip_executable_binaries 라인을 주석 처리하고 새로운 파이프라인을 시작하세요.