- 중단 가능한 파이프라인
- Git 페치 캐싱
- 캐싱 전략
- 아티팩트 전략
- 컴포넌트 캐싱
cache-workhorse
cache-assets
compile-*-assets
- 스트립된 바이너리
CI 구성 성능
중단 가능한 파이프라인
기본적으로 모든 작업은 중단 가능합니다,
단, main
에서 자동으로 실행되는 dont-interrupt-me
작업은 매뉴얼으로 실행되며,
새 커밋을 머지 요청에 푸시해도 실행을 마무리하려면 dont-interrupt-me
작업을 시작해야 합니다.
Git 페치 캐싱
GitLab.com은 팩 오브젝트 캐시를 사용하므로, 동시에 진행되는 동일한 파이프라인 ref의 Git 페치는 Gitaly 서버에서 중복 처리되고 (항상) 캐시에서 제공됩니다(사용 가능한 경우).
다음과 같은 이유로 잘 작동합니다:
- 팩 오브젝트 캐시는 GitLab.com의 모든 Gitaly 서버에서 활성화됩니다.
- CI/CD의 Git 전략 설정은 Git 클론으로 설정되어 모든 작업이 동일한 데이터를 가져오도록 하여 캐시 히트 비율을 극대화합니다.
- 얕은 클론을 사용하여 각 작업에 대해 전체 Git 히스토리를 다운로드하지 않도록 합니다.
Gitaly에서 클론/페치하는 대신 아티팩트를 통해 리포지터리 가져오기
최근 Gitaly에서 다음과 같은 오류를 발견했습니다: (자세한 내용은 이슈를 참조하세요)
fatal: remote error: GitLab가 현재 부하로 인해 이 요청을 처리할 수 없습니다.
GitLab.com이 팩 오브젝트 캐시를 사용하더라도 때로는 여전히 Gitaly가 처리하기에 부하가 너무 심하고, 번개 떼가 그 시간에 리포지터리를 여러 개 클론하는 많은 작업이 문제가 될 수 있습니다.
Gitaly의 부하를 완화하고 줄이기 위해 몇 가지 작업을 변경하여 리포지터리를 한꺼번에 모두 Gitaly에서 클론하는 대신 작업 중 하나에서 아티팩트로부터 리포지터리를 가져오도록 했습니다.
현재 대부분의 파이프라인에서 가장 많은 동시 작업을 하는 RSpec 작업에 적용되었으며, 이로써 속도도 약간 향상되었으며 아티팩트로 가져오는 것이 클론하는 것보다 어느 정도 더 빨랐습니다. 이로써 각 파이프라인에 대해 더 많은 아티팩트를 저장하는 비용이 듭니다.
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_STRATEGY
를 clone
로 설정하고, 활성화하려면 CI_FETCH_REPO_GIT_STRATEGY
를 none
으로 설정하세요.
캐싱 전략
- 모든 작업은 기본적으로 캐시를 가져와야 합니다.
- 모든 작업은 빈 캐시로도 통과해야 합니다. 즉, 캐시는 작업을 가속하기 위해서만 있는 것입니다.
- 우리는 현재
.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}
가 포함되어 있어 실제로 두 가지 다른 캐시입니다).
- 이러한 캐시 정의는 다중 원자적 캐시로 구성되어 있습니다.
- 2시간마다 실행되는
maintenance
예약 파이프라인에서만 실행되는 다음 작업들이 캐시에 푸시(즉, 업데이트)하는 유일한 작업입니다:-
[
.gitlab/ci/rails.gitlab-ci.yml](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rails.gitlab-ci.yml)에 정의된
update-setup-test-env-cache` -
[
.gitlab/ci/rails.gitlab-ci.yml](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rails.gitlab-ci.yml)에 정의된
update-gitaly-binaries-cache` -
[
.gitlab/ci/rails.gitlab-ci.yml](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rails.gitlab-ci.yml)에 정의된
update-rubocop-cache` -
[
.gitlab/ci/qa.gitlab-ci.yml](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/qa.gitlab-ci.yml)에 정의된
update-qa-cache` -
[
.gitlab/ci/frontend.gitlab-ci.yml](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/frontend.gitlab-ci.yml)에 정의된
update-assets-compile-production-cache` -
[
.gitlab/ci/frontend.gitlab-ci.yml](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/frontend.gitlab-ci.yml)에 정의된
update-assets-compile-test-cache` -
[
.gitlab/ci/frontend.gitlab-ci.yml](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/frontend.gitlab-ci.yml)에 정의된
update-storybook-yarn-cache`
-
- 이러한 작업들은 또한
pipeline:update-cache
레이블을 가진 Merge Request에서 실행되도록 강제할 수 있습니다(캐시 키를 업데이트하는 MR에서 캐시를 미리 로드하는 데 유용합니다).
아티팩트 전략
업로드/다운로드 시간 및 비용, 그리고 아티팩트 리포지터리를 줄이기 위해 작업이 저장하고 검색하는 아티팩트를 최소화하도록 제한합니다.
컴포넌트 캐싱
GitLab의 일부 외부 컴포넌트(GitLab Workhorse 및 프론트엔드 자산)는 테스트를 실행하기 전에 소스에서 빌드해야 합니다.
cache-workhorse
이 MR에서, 그리고
이 MR에서,
우리는 다음과 같은 새로운 cache-workhorse
작업을 소개했습니다:
- GitLab.com의
gitlab-org/gitlab
예약 파이프라인에 자동으로 실행됩니다. -
master
에 커밋하는 경우에는workhorse/
폴더에 영향을 미치는 커밋에 대해 자동으로 실행됩니다. -
gitlab-org
의 MRs에서는 캐시 관련 파일을 손대는 경우 매뉴얼으로 실행됩니다.
이 작업은 GitLab 테스트 슈트에서 필요한 GitLab Workhorse 이진 파일을 포함하는 일반 패키지를 다운로드하려고 합니다(예: tmp/tests/gitlab-workhorse
).
- 패키지 URL이 404를 반환하면:
-
scripts/setup-test-env
를 실행하여 GitLab Workhorse 바이너리를 빌드합니다. - 그런 다음 바이너리를 포함하는 아카이브를 생성하고 일반 패키지로 업로드합니다.
-
- 그렇지 않은 경우, 패키지가 이미 있는 경우에는 작업을 성공적으로 종료합니다.
또한 setup-test-env
작업을 다음과 같이 변경했습니다:
- 먼저
cache-workhorse
에 의해 빌드 및 업로드된 GitLab Workhorse 일반 패키지를 다운로드합니다. - 패키지가 성공적으로 검색된 경우 해당 내용을 올바른 폴더에 배치하여(
tmp/tests/gitlab-workhorse
등) 나중에scripts/setup-test-env
가 실행될 때 바이너리를 빌드하도록 합니다. - 패키지 URL이 404를 반환하면 현재와 동일한 동작입니다:
scripts/setup-test-env
의 일부로 GitLab Workhorse 바이너리를 빌드합니다.
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
커밋이 assets 관련 폴더를 건드리는 경우에도 자동으로 실행되며 -
gitlab-org
의 MR에서 캐싱 관련 파일을 건드리는 경우 매뉴얼으로 실행됩니다.
이 작업은 GitLab 테스트 스위트에서 필요로 하는 GitLab 컴파일된 assets가 포함된 일반 패키지를 다운로드하려고 시도합니다 (app/assets/javascripts/locale/**/app.js
및 public/assets
).
- 패키지 URL이 404를 반환하는 경우:
-
bin/rake gitlab:assets:compile
을 실행하여 GitLab assets를 컴파일합니다. - assets를 포함하는 아카이브를 생성하고 일반 패키지로 업로드합니다. 패키지 버전은 assets 폴더의 해시 합으로 설정됩니다.
-
- 그렇지 않은 경우, 패키지가 이미 존재하는 경우 작업을 성공적으로 종료합니다.
compile-*-assets
또한 compile-test-assets
, compile-test-assets as-if-foss
, compile-production-assets
작업을 다음과 같이 변경했습니다:
- 먼저 “native” 캐시 assets를 다운로드합니다.
- 컴파일된 assets
-
cached-assets-hash.txt
파일을 포함하여, assets가 의존하는 모든 소스 파일의SHA256
해시 다이제스트를 포함합니다. 이 파일은 비관적인 디렉터리이며 assets가 이러한 파일에 의존하지 않을 수 있습니다. 최악의 경우, assets를 더 자주 컴파일하지만, 오래된 assets를 사용하는 것보다는 더 나은 방법입니다. 이 파일은 assets가 컴파일된 후에 생성됩니다.
- 그런 다음, 현재 체크아웃된 브랜치에 의존하는 assets의 모든 소스 파일의
SHA256
해시 다이제스트를 계산합니다. 계산된 해시 다이제스트를GITLAB_ASSETS_HASH
변수에 저장합니다. -
$CACHE_ASSETS_AS_PACKAGE == "true"
이면,cache-assets:*
에 의해 빌드되고 업로드된 일반 패키지를 다운로드합니다.- 체크아웃된 브랜치에 대해 cache가 최신 상태인 경우, native 캐시 및 캐시 패키지를 다운로드합니다. 우리는 일반 패키지를 다운로드하는 대신 native cache를 다운로드함으로써 최적화할 수 있습니다. 그러나 native 캐시는 실제로 매우 자주 오래된 상태일 수 있습니다. 왜냐하면 2시간마다만 재구성하기 때문입니다.
-
우리는
assets_compile_script
함수를 실행합니다; 이 함수는 자체적으로assets:compile
Rake task를 실행합니다.이 작업은 assets의 컴파일 여부를 결정하는 데 책임이 있습니다. 이 작업은
$GITLAB_ASSETS_HASH
의HEAD
SHA256
해시 다이제스트를cached-assets-hash.txt
의master
해시 다이제스트와 비교합니다. - 해시가 동일하면, 아무것도 컴파일하지 않습니다. 다르다면, assets를 컴파일합니다.
스트립된 바이너리
기본적으로, setup-test-env
는 저장 공간을 절약하고 이후의 CI 작업의 artifact 다운로드를 가속화하기 위해 스트립된 바이너리를 포함하는 artifact를 생성합니다.
스트립된 바이너리에서의 크래시를 디버깅하기 쉽게 하려면 setup-test-job
작업에서 strip_executable_binaries
와 같은 라인을 주석 처리하고, 새로운 파이프라인을 시작하세요.