CI 설정 성능
GitLab v19.1기본적으로 모든 job은 인터럽트 가능합니다. 머지 리퀘스트에 새 커밋을 푸시하더라도 실행 중인 파이프라인이 완료되길 원한다면, 푸시하기 전에 반드시 dont-interrupt-me job을 시작하세요. GitLab.com은 pack-objects 캐시를 사용하므로, 동일한 파이프라인 ref에 대한 동시 Git fetch 요청은 Gitaly 서버에서 중복 제거되며(항상), 캐시에서 제공됩니다(가능한 경우).
인터럽트 가능 파이프라인#
기본적으로 모든 job은 인터럽트 가능합니다. 단, dont-interrupt-me job은 예외로, main에서는 자동으로 실행되고 그 외의 경우에는 manual로 실행됩니다.
머지 리퀘스트에 새 커밋을 푸시하더라도 실행 중인 파이프라인이 완료되길 원한다면, 푸시하기 전에 반드시 dont-interrupt-me job을 시작하세요.
Git fetch 캐싱#
GitLab.com은 pack-objects 캐시를 사용하므로, 동일한 파이프라인 ref에 대한 동시 Git fetch 요청은 Gitaly 서버에서 중복 제거되며(항상), 캐시에서 제공됩니다(가능한 경우).
이 방식이 효과적인 이유는 다음과 같습니다:
-
GitLab.com의 모든 Gitaly 서버에 pack-objects 캐시가 활성화되어 있습니다.
-
gitlab-org/gitlab의 CI/CD Git 전략 설정이 Git clone으로 설정되어 있어, 모든 job이 동일한 데이터를 fetch하므로 캐시 적중률이 최대화됩니다. -
shallow clone을 사용하여 모든 job에서 전체 Git 히스토리를 다운로드하지 않아도 됩니다.
Gitaly에서 클론/fetch 대신 아티팩트를 통해 리포지터리 fetch하기#
최근 Gitaly에서 다음과 같은 오류가 발생하는 사례가 있었습니다: (이슈 참고)
fatal: remote error: GitLab is currently unable to handle this request due to load.
GitLab.com이 pack-objects 캐시를 사용하더라도, 부하가 너무 높아 Gitaly가 처리하지 못하는 경우가 있습니다. 또한 동시에 많은 job이 리포지터리를 클론할 때 thundering herd 문제가 우려될 수 있습니다.
Gitaly의 부하를 완화하고 줄이기 위해, 일부 job이 동시에 Gitaly에서 클론하는 방식 대신 job 내에서 아티팩트로부터 리포지터리를 fetch하도록 변경했습니다.
현재 이 방식은 대부분의 파이프라인에서 동시 job이 가장 많은 RSpec job에 적용됩니다. 아티팩트에서 fetch하는 것이 클론보다 약간 더 빠르기 때문에 속도도 소폭 향상되었지만, 각 파이프라인에 더 많은 아티팩트를 저장해야 합니다.
2023-12-20 기준 RSpec job용 아티팩트에서 리포지터리 fetch의 수치에 따르면, 추가 스토리지 비용은 파이프라인당 약 280M이며, 각 RSpec job에서 15초를 절약할 수 있습니다.
다른 job 의존성이 없는 job에는 이 방식을 적용하지 않습니다. job 시작을 지연시키고 싶지 않기 때문입니다.
이 동작은 변수 CI_FETCH_REPO_GIT_STRATEGY로 제어할 수 있습니다:
-
none으로 설정하면.repo-from-artifacts를 사용하는 job이 Gitaly에서 클론하는 대신clone-gitlab-repojob의 아티팩트에서 리포지터리를 fetch합니다. -
clone으로 설정하면.repo-from-artifacts를 사용하는 job이 평소대로 리포지터리를 클론합니다. 이 경우clone-gitlab-repojob은 실행되지 않습니다.
비활성화하려면 CI_FETCH_REPO_GIT_STRATEGY를 clone으로 설정하세요. 활성화하려면 CI_FETCH_REPO_GIT_STRATEGY를 none으로 설정하세요.
캐싱 전략#
GitLab CI/CD 파이프라인의 캐시는 다음 기준을 따라야 합니다:
-
pull-push vs pull-only 설정: 캐시 채우기를 담당하는
syncstage(파이프라인 시작 시 실행)의 job은 pull-push 설정을 사용하고, 캐시를 소비하는 job은 브랜치와 독립적으로 동작하며 특정 브랜치 파이프라인 실행에 대한 캐시를 채우기 위해 pull-only 설정을 사용합니다. -
파일별 체크섬: 모든 캐시 키는 의존성이 변경될 때 캐시가 올바르게 무효화되도록 파일별 체크섬과 연결되어야 합니다.
-
언어 버전 연결: 언어 버전 업그레이드 시 캐시가 적절히 무효화되도록 캐시 키에는 해당 언어별 버전을 포함해야 합니다.
-
sync stage 배치: 캐시 업데이트 job은 파이프라인의 맨 처음에 실행되도록
syncstage에 정의해야 합니다. -
재사용 가능한 정의: 프로젝트 전체의 일관성을 위해 재사용 가능한 캐시 키 정의는
.gitlab/ci/global.gitlab-ci.yml파일에 배치합니다.
복잡한 체크섬 계산#
캐시 키에 여러 파일의 복잡한 체크섬 계산이 필요한 경우, sync stage에 특정 job을 추가하여 캐시 체크섬을 계산하고 dotenv 유형 리포트 아티팩트로 저장함으로써 환경 변수를 통해 사용할 수 있도록 해야 합니다. 이렇게 하면 이후의 모든 job이 파이프라인 전반에 걸쳐 일관된 캐시 키 생성을 위해 사전 계산된 체크섬을 사용할 수 있습니다.
아티팩트 전략#
업로드/다운로드 시간과 비용, 그리고 아티팩트 스토리지를 줄이기 위해 job이 저장하고 검색하는 아티팩트를 최소한으로 제한합니다.
스트립된 바이너리#
기본적으로 setup-test-env는 이후 CI job의 스토리지 절약 및 아티팩트 다운로드 속도 향상을 위해 스트립된 바이너리가 포함된 아티팩트를 생성합니다.
스트립된 바이너리로 인한 크래시 디버깅을 더 쉽게 하려면, scripts/gitlab_component_helpers.sh 셸 스크립트의 setup_test_env 함수에서 strip_executable_binaries가 포함된 줄을 주석 처리하고 새 파이프라인을 시작하세요.
머지 리퀘스트 제목에서 파이프라인 건너뛰기#
병합 결과 파이프라인을 사용할 때, 머지 리퀘스트 제목에 [ci skip] 또는 [skip ci]를 추가하여 파이프라인을 건너뛸 수 있습니다.
병합 결과 파이프라인은 MR 제목을 커밋 메시지에 포함하는 가상 커밋을 생성하므로 건너뛰기 플래그가 감지됩니다.
이는 문서화되지 않은 부수 효과이며, 병합 결과 파이프라인이 활성화된 경우에만 작동합니다. 기본 머지 리퀘스트 파이프라인이나 병합 충돌이 있는 경우에는 작동하지 않습니다. 이 방법은 주로 파이프라인 부하를 줄이기 위해 GitLab.com 내부적으로 사용됩니다.
파이프라인을 건너뛰려면:
-
머지 리퀘스트 제목에
[ci skip]또는[skip ci]를 추가하세요. 제목에서 플래그를 제거할 때까지 파이프라인이 건너뜁니다. -
커밋 메시지에
[ci skip]또는[skip ci]를 추가하세요. 해당 특정 커밋에 대한 파이프라인만 건너뜁니다.