InfoGrab DocsInfoGrab Docs

러너 구성

요약

이 문서는 GitLab UI에서 러너를 구성하는 방법을 설명합니다. GitLab Runner를 설치한 머신에서 러너를 구성해야 한다면 GitLab Runner 문서를 참고합니다. 더 긴 job 제한 시간을 가진 프로젝트가 러너를 사용하지 못하도록, 각 러너에 대해 최대 job 제한 시간을 지정할 수 있습니다.

이 문서는 GitLab UI에서 러너를 구성하는 방법을 설명합니다.

GitLab Runner를 설치한 머신에서 러너를 구성해야 한다면 GitLab Runner 문서를 참고합니다.

최대 job 제한 시간 설정#

더 긴 job 제한 시간을 가진 프로젝트가 러너를 사용하지 못하도록, 각 러너에 대해 최대 job 제한 시간을 지정할 수 있습니다. 프로젝트에 정의된 job 제한 시간보다 짧은 경우 최대 job 제한 시간이 사용됩니다.

러너의 최대 제한 시간을 설정하려면, REST API 엔드포인트 PUT /runners/:id에서 maximum_timeout 파라미터를 설정합니다.

인스턴스 러너의 경우#

사전 요구 사항:

  • 관리자여야 합니다.

GitLab Self-Managed에서는 인스턴스 러너의 job 제한 시간을 재정의할 수 있습니다.

GitLab.com에서는 GitLab 호스팅 인스턴스 러너의 job 제한 시간을 재정의할 수 없으며, 대신 프로젝트에 정의된 제한 시간을 사용해야 합니다.

최대 job 제한 시간을 설정하려면:

  1. 오른쪽 상단에서 Admin을 선택합니다.
  2. 왼쪽 사이드바에서 CI/CD > Runners를 선택합니다.
  3. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. Maximum job timeout 필드에 초 단위로 값을 입력합니다. 최소값은 600초(10분)입니다.
  5. Save changes를 선택합니다.

그룹 러너의 경우#

사전 요구 사항:

  • 그룹에 대한 Owner 권한이 있어야 합니다.

최대 job 제한 시간을 설정하려면:

  1. 상단 바에서 Search or go to를 선택하고 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Build > Runners를 선택합니다.
  3. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. Maximum job timeout 필드에 초 단위로 값을 입력합니다. 최소값은 600초(10분)입니다.
  5. Save changes를 선택합니다.

프로젝트 러너의 경우#

사전 요구 사항:

  • 프로젝트에 대한 Owner 권한이 있어야 합니다.

최대 job 제한 시간을 설정하려면:

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
  3. Runners를 확장합니다.
  4. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  5. Maximum job timeout 필드에 초 단위로 값을 입력합니다. 최소값은 600초(10분)입니다. 정의되지 않은 경우 프로젝트의 job 제한 시간이 대신 사용됩니다.
  6. Save changes를 선택합니다.

최대 job 제한 시간의 동작 방식#

예제 1 - 러너 제한 시간이 프로젝트 제한 시간보다 긴 경우

  1. 러너의 maximum_timeout 파라미터를 24시간으로 설정합니다.
  2. 프로젝트의 Maximum job timeout을 2시간으로 설정합니다.
  3. job을 시작합니다.
  4. job 이 더 오래 실행되면 2시간 후에 제한 시간이 초과됩니다.

예제 2 - 러너 제한 시간이 구성되지 않은 경우

  1. 러너에서 maximum_timeout 파라미터 구성을 제거합니다.
  2. 프로젝트의 Maximum job timeout을 2시간으로 설정합니다.
  3. job을 시작합니다.
  4. job 이 더 오래 실행되면 2시간 후에 제한 시간이 초과됩니다.

예제 3 - 러너 제한 시간이 프로젝트 제한 시간보다 짧은 경우

  1. 러너의 maximum_timeout 파라미터를 30분으로 설정합니다.
  2. 프로젝트의 Maximum job timeout을 2시간으로 설정합니다.
  3. job을 시작합니다.
  4. job 이 더 오래 실행되면 30분 후에 제한 시간이 초과됩니다.

script 및 after_script 제한 시간 설정#

script 및 after_script가 종료되기까지 실행되는 시간을 제어하려면, .gitlab-ci.yml 파일에 제한 시간 값을 지정합니다.

예를 들어, 장시간 실행되는 script를 조기에 종료하도록 제한 시간을 지정할 수 있습니다. 이렇게 하면 job 제한 시간이 초과되기 전에 아티팩트와 캐시를 계속 업로드할 수 있습니다. script와 after_script의 제한 시간 값은 job 제한 시간보다 짧아야 합니다.

  • script의 제한 시간을 설정하려면 job 변수 RUNNER_SCRIPT_TIMEOUT을 사용합니다.
  • after_script의 제한 시간을 설정하고 기본값인 5분을 재정의하려면 job 변수 RUNNER_AFTER_SCRIPT_TIMEOUT을 사용합니다.

이 두 변수는 모두 Go의 duration 형식을 허용합니다(예: 40s, 1h20m, 2h 4h30m30s).

예를 들면:

job-with-script-timeouts:
  variables:
    RUNNER_SCRIPT_TIMEOUT: 15m
    RUNNER_AFTER_SCRIPT_TIMEOUT: 10m
  script:
    - "I am allowed to run for min(15m, remaining job timeout)."
  after_script:
    - "I am allowed to run for min(10m, remaining job timeout)."

job-artifact-upload-on-timeout:
  timeout: 1h                           # set job timeout to 1 hour
  variables:
     RUNNER_SCRIPT_TIMEOUT: 50m         # only allow script to run for 50 minutes
  script:
    - long-running-process > output.txt # will be terminated after 50m

  artifacts: # artifacts will have roughly ~10m to upload
    paths:
      - output.txt
    when: on_failure # on_failure because script termination after a timeout is treated as a failure

after_script 실행 보장#

after_script가 성공적으로 실행되려면 RUNNER_SCRIPT_TIMEOUT과 RUNNER_AFTER_SCRIPT_TIMEOUT의 합이 job에 구성된 제한 시간을 초과하지 않아야 합니다.

다음 예제는 메인 스크립트가 제한 시간을 초과하더라도 after_script가 실행되도록 제한 시간을 구성하는 방법을 보여줍니다.

job-with-script-timeouts:
  timeout: 5m
  variables:
    RUNNER_SCRIPT_TIMEOUT: 1m
    RUNNER_AFTER_SCRIPT_TIMEOUT: 1m
  script:
    - echo "Starting build..."
    - sleep 120 # Wait 2 minutes to trigger timeout. Script aborts after 1 minute due to RUNNER_SCRIPT_TIMEOUT.
    - echo "Build finished."
  after_script:
    - echo "Starting Clean-up..."
    - sleep 15 # Wait just a few seconds. Runs successfully because it's within RUNNER_AFTER_SCRIPT_TIMEOUT.
    - echo "Clean-up finished."

script는 RUNNER_SCRIPT_TIMEOUT에 의해 취소되지만, after_script는 15초가 걸려 RUNNER_AFTER_SCRIPT_TIMEOUT과 job의 timeout 값 둘 다보다 짧으므로 성공적으로 실행됩니다.

민감한 정보 보호#

인스턴스 러너는 GitLab 인스턴스의 모든 그룹과 프로젝트에서 기본적으로 사용할 수 있으므로, 인스턴스 러너를 사용할 때 보안 위험이 더 큽니다. 러너 실행기(executor)와 파일 시스템 구성은 보안에 영향을 미칩니다. 러너 호스트 환경에 접근할 수 있는 사용자는 러너가 실행한 코드와 러너 인증을 볼 수 있습니다. 예를 들어, 러너 인증 토큰에 접근할 수 있는 사용자는 러너를 복제하여 공격 벡터로 가짜 job을 제출할 수 있습니다. 자세한 내용은 보안 고려 사항을 참고합니다.

롱 폴링 구성#

GitLab 서버의 job 대기 시간과 부하를 줄이려면 롱 폴링을 구성합니다.

포크된 프로젝트에서 인스턴스 러너 사용#

프로젝트가 포크되면 job과 관련된 job 설정이 복사됩니다. 프로젝트에 인스턴스 러너가 구성되어 있고 사용자가 해당 프로젝트를 포크하면, 인스턴스 러너가 이 프로젝트의 job을 처리합니다.

알려진 이슈로 인해, 포크된 프로젝트의 러너 설정이 새 프로젝트 네임스페이스와 일치하지 않으면 다음 메시지가 표시됩니다: An error occurred while forking the project. Please try again..

이 문제를 해결하려면, 포크된 프로젝트와 새 네임스페이스에서 인스턴스 러너 설정이 일치하도록 합니다.

  • 포크된 프로젝트에서 인스턴스 러너가 활성화되어 있다면, 새 네임스페이스에서도 활성화해야 합니다.
  • 포크된 프로젝트에서 인스턴스 러너가 비활성화되어 있다면, 새 네임스페이스에서도 비활성화해야 합니다.

프로젝트의 러너 등록 토큰 재설정 (지원 중단됨)#

Warning

러너 등록 토큰을 전달하는 옵션과 특정 구성 인수에 대한 지원은 레거시로 간주되며 권장되지 않습니다. 러너를 등록할 인증 토큰을 생성하려면 러너 생성 워크플로를 사용합니다. 이 프로세스는 러너 소유권에 대한 완전한 추적성을 제공하고 러너 플릿의 보안을 강화합니다. 자세한 내용은 새 러너 등록 워크플로로 마이그레이션을 참고합니다.

프로젝트의 등록 토큰이 노출되었다고 생각되면 재설정해야 합니다. 등록 토큰은 프로젝트에 다른 러너를 등록하는 데 사용될 수 있습니다. 그 새 러너는 이후 시크릿 변수의 값을 얻거나 프로젝트 코드를 복제하는 데 사용될 수 있습니다.

등록 토큰을 재설정하려면:

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
  3. Runners를 확장합니다.
  4. New project runner 오른쪽에서 세로 점 3개(⋮)를 선택합니다.
  5. Reset registration token을 선택합니다.
  6. Reset token을 선택합니다.

등록 토큰을 재설정하면 더 이상 유효하지 않으며 프로젝트에 새 러너를 등록하지 않습니다. 새 값을 프로비저닝하고 등록하는 데 사용하는 도구에서도 등록 토큰을 업데이트해야 합니다.

인증 토큰 보안#

각 러너는 GitLab 인스턴스에 연결하고 인증하기 위해 러너 인증 토큰을 사용합니다.

토큰이 침해되는 것을 방지하려면, 지정된 간격으로 토큰이 자동으로 로테이션되도록 할 수 있습니다. 토큰이 로테이션되면 러너의 상태(online 또는 offline)와 관계없이 각 러너에 대해 업데이트됩니다.

수동 개입이 필요하지 않으며 실행 중인 job에도 영향을 미치지 않습니다. 토큰 로테이션에 대한 자세한 내용은 로테이션 시 러너 인증 토큰이 업데이트되지 않음을 참고합니다.

러너 인증 토큰을 수동으로 업데이트해야 한다면 토큰 재설정 명령을 실행할 수 있습니다.

러너 구성 인증 토큰 재설정#

러너의 인증 토큰이 노출되면, 공격자가 이를 사용해 러너를 복제할 수 있습니다.

러너 구성 인증 토큰을 재설정하려면:

  1. 러너를 삭제합니다:
  2. 새 러너 인증 토큰이 할당되도록 새 러너를 생성합니다:
  3. 선택 사항. 이전 러너 인증 토큰이 폐기되었는지 확인하려면 Runners API를 사용합니다.

러너 구성 인증 토큰을 재설정하는 데는 Runners API도 사용할 수 있습니다.

러너 인증 토큰 자동 로테이션#

러너 인증 토큰을 로테이션할 간격을 지정할 수 있습니다. 러너 인증 토큰을 정기적으로 로테이션하면 침해된 토큰을 통한 GitLab 인스턴스 무단 접근 위험을 최소화하는 데 도움이 됩니다.

사전 요구 사항:

  • 관리자여야 합니다.

러너 인증 토큰을 자동으로 로테이션하려면:

  1. 오른쪽 상단에서 Admin을 선택합니다.
  2. 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
  3. Continuous Integration and Deployment를 확장합니다.
  4. 러너에 대한 Runners expiration 시간을 설정합니다. 만료되지 않게 하려면 비워 둡니다.
  5. Save changes를 선택합니다.

간격이 만료되기 전에 러너는 자동으로 새 러너 인증 토큰을 요청합니다. 토큰 로테이션에 대한 자세한 내용은 로테이션 시 러너 인증 토큰이 업데이트되지 않음을 참고합니다.

러너가 민감한 정보를 노출하지 않도록 방지#

러너가 민감한 정보를 노출하지 않도록 하려면, 보호된 브랜치에서 job만 실행하거나 보호된 태그가 있는 job만 실행하도록 구성할 수 있습니다.

보호된 브랜치에서 job을 실행하도록 구성된 러너는 머지 리퀘스트 파이프라인에서 job을 실행하도록 선택적으로 설정할 수 있습니다.

인스턴스 러너의 경우#

사전 요구 사항:

  • 관리자여야 합니다.
  1. 오른쪽 상단에서 Admin을 선택합니다.
  2. 왼쪽 사이드바에서 CI/CD > Runners를 선택합니다.
  3. 보호할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. Protected 체크박스를 선택합니다.
  5. Save changes를 선택합니다.

그룹 러너의 경우#

사전 요구 사항:

  • 그룹에 대한 Owner 권한이 있어야 합니다.
  1. 상단 바에서 Search or go to를 선택하고 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Build > Runners를 선택합니다.
  3. 보호할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. Protected 체크박스를 선택합니다.
  5. Save changes를 선택합니다.

프로젝트 러너의 경우#

사전 요구 사항:

  • 프로젝트에 대한 Owner 권한이 있어야 합니다.
  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
  3. Runners를 확장합니다.
  4. 보호할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  5. Protected 체크박스를 선택합니다.
  6. Save changes를 선택합니다.

러너가 실행할 수 있는 job 제어#

태그를 사용해 러너가 실행할 수 있는 job을 제어할 수 있습니다. 예를 들어, Rails 테스트 스위트를 실행하는 데 필요한 의존성을 가진 러너에 rails 태그를 지정할 수 있습니다.

GitLab CI/CD 태그는 Git 태그와 다릅니다. GitLab CI/CD 태그는 러너와 연결됩니다. Git 태그는 커밋과 연결됩니다.

인스턴스 러너의 경우#

사전 요구 사항:

  • 관리자여야 합니다.

인스턴스 러너가 실행할 수 있는 job을 제어하려면:

  1. 오른쪽 상단에서 Admin을 선택합니다.
  2. 왼쪽 사이드바에서 CI/CD > Runners를 선택합니다.
  3. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. 러너가 태그가 있는 job 또는 태그가 없는 job을 실행하도록 설정합니다:
    • 태그가 있는 job을 실행하려면, Tags 필드에 job 태그를 쉼표로 구분하여 입력합니다. 예: macos, rails.
    • 태그가 없는 job을 실행하려면, Run untagged jobs 체크박스를 선택합니다.
  5. Save changes를 선택합니다.

그룹 러너의 경우#

사전 요구 사항:

  • 그룹에 대한 Owner 권한이 있어야 합니다.

그룹 러너가 실행할 수 있는 job을 제어하려면:

  1. 상단 바에서 Search or go to를 선택하고 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Build > Runners를 선택합니다.
  3. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. 러너가 태그가 있는 job 또는 태그가 없는 job을 실행하도록 설정합니다:
    • 태그가 있는 job을 실행하려면, Tags 필드에 job 태그를 쉼표로 구분하여 입력합니다. 예: macos, ruby.
    • 태그가 없는 job을 실행하려면, Run untagged jobs 체크박스를 선택합니다.
  5. Save changes를 선택합니다.

프로젝트 러너의 경우#

사전 요구 사항:

  • 프로젝트에 대한 Owner 권한이 있어야 합니다.

프로젝트 러너가 실행할 수 있는 job을 제어하려면:

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
  3. Runners를 확장합니다.
  4. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  5. 러너가 태그가 있는 job 또는 태그가 없는 job을 실행하도록 설정합니다:
    • 태그가 있는 job을 실행하려면, Tags 필드에 job 태그를 쉼표로 구분하여 입력합니다. 예: macos, ruby.
    • 태그가 없는 job을 실행하려면, Run untagged jobs 체크박스를 선택합니다.
  6. Save changes를 선택합니다.

러너가 태그를 사용하는 방식#

러너가 태그가 있는 job만 실행하는 경우#

다음 예제는 러너가 태그가 있는 job만 실행하도록 설정된 경우 발생할 수 있는 영향을 보여줍니다.

예제 1:

  1. 러너가 태그가 있는 job만 실행하도록 구성되어 있고 docker 태그를 가지고 있습니다.
  2. hello 태그를 가진 job 이 실행되어 멈춥니다.

예제 2:

  1. 러너가 태그가 있는 job만 실행하도록 구성되어 있고 docker 태그를 가지고 있습니다.
  2. docker 태그를 가진 job 이 실행되어 처리됩니다.

예제 3:

  1. 러너가 태그가 있는 job만 실행하도록 구성되어 있고 docker 태그를 가지고 있습니다.
  2. 태그가 정의되지 않은 job 이 실행되어 멈춥니다.

러너가 태그가 없는 job 실행을 허용하는 경우#

다음 예제는 러너가 태그가 있는 job과 태그가 없는 job을 모두 실행하도록 설정된 경우 발생할 수 있는 영향을 보여줍니다.

예제 1:

  1. 러너가 태그가 없는 job을 실행하도록 구성되어 있고 docker 태그를 가지고 있습니다.
  2. 태그가 정의되지 않은 job 이 실행되어 처리됩니다.
  3. docker 태그가 정의된 두 번째 job 이 실행되어 처리됩니다.

예제 2:

  1. 러너가 태그가 없는 job을 실행하도록 구성되어 있고 태그가 정의되어 있지 않습니다.
  2. 태그가 정의되지 않은 job 이 실행되어 처리됩니다.
  3. docker 태그가 정의된 두 번째 job은 멈춥니다.

러너와 job에 여러 태그가 있는 경우#

job과 러너를 매칭하는 선택 로직은 job에 정의된 tags 목록을 기준으로 합니다.

다음 예제는 러너와 job에 여러 태그가 있을 때의 영향을 보여줍니다. 러너가 job을 실행하도록 선택되려면, job 스크립트 블록에 정의된 태그를 모두 가지고 있어야 합니다.

예제 1:

  1. 러너가 [docker, shell, gpu] 태그로 구성되어 있습니다.
  2. job 이 [docker, shell, gpu] 태그를 가지고 있어 실행되어 처리됩니다.

예제 2:

  1. 러너가 [docker, shell, gpu] 태그로 구성되어 있습니다.
  2. job 이 [docker, shell,] 태그를 가지고 있어 실행되어 처리됩니다.

예제 3:

  1. 러너가 [docker, shell] 태그로 구성되어 있습니다.
  2. job 이 [docker, shell, gpu] 태그를 가지고 있어 실행되지 않습니다.

태그를 사용해 서로 다른 플랫폼에서 job 실행#

태그를 사용하면 서로 다른 플랫폼에서 서로 다른 job을 실행할 수 있습니다. 예를 들어, osx 태그를 가진 OS X 러너와 windows 태그를 가진 Windows 러너가 있다면, 각 플랫폼에서 job을 실행할 수 있습니다.

.gitlab-ci.yml의 tags 필드를 업데이트합니다:

windows job:
  stage: build
  tags:
    - windows
  script:
    - echo Hello, %USERNAME%!

osx job:
  stage: build
  tags:
    - osx
  script:
    - echo "Hello, $USER!"

태그에 CI/CD 변수 사용#

.gitlab-ci.yml 파일에서, 동적 러너 선택을 위해 tags와 함께 CI/CD 변수를 사용합니다:

variables:
  KUBERNETES_RUNNER: kubernetes

  job:
    tags:
      - docker
      - $KUBERNETES_RUNNER
    script:
      - echo "Hello runner selector feature"

변수로 러너 동작 구성#

CI/CD 변수를 사용하면 러너의 Git 동작을 전역으로 또는 개별 작업 단위로 구성할 수 있습니다.

변수를 사용하면 러너가 작업 실행의 특정 단계를 몇 번 시도할지도 구성할 수 있습니다.

Kubernetes executor를 사용할 때는 변수를 사용해 Kubernetes CPU·메모리 요청 및 제한 할당량을 재정의할 수 있습니다.

러너 기능 플래그도 작업 및 파이프라인 변수로 사용할 수 있습니다.

Git 전략#

GIT_STRATEGY 변수는 빌드 디렉터리를 준비하고 리포지터리 콘텐츠를 가져오는 방식을 구성합니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

variables:
  GIT_STRATEGY: clone

가능한 값은 clone, fetch, none, empty 입니다. 값을 지정하지 않으면 작업은 프로젝트의 파이프라인 설정을 사용합니다.

clone은 가장 느린 옵션입니다. 모든 작업마다 리포지터리를 처음부터 클론하므로 로컬 작업 사본이 항상 깨끗한 상태로 유지됩니다. 기존 워크트리가 있으면 클론 전에 제거합니다.

fetch는 로컬 작업 사본을 재사용하므로 더 빠릅니다(사본이 없으면 clone으로 대체됩니다). git clean은 이전 작업에서 발생한 변경 사항을 되돌리는 데 사용되고, git fetch는 이전 작업 실행 이후에 생긴 커밋을 가져오는 데 사용됩니다.

다만 fetch는 이전 워크트리에 대한 접근이 필요합니다. shell 또는 docker executor를 사용할 때는 기본적으로 워크트리를 보존하고 재사용하려 하므로 잘 동작합니다.

Docker Machine executor를 사용할 때는 이 방식에 제약이 있습니다.

Git 전략이 none 이면 로컬 작업 사본을 재사용하지만, GitLab 이 평소 수행하는 Git 작업은 모두 건너뜁니다. GitLab Runner의 pre-clone 스크립트가 있다면 이 또한 건너뜁니다. 이 전략을 사용하면 .gitlab-ci.yml 스크립트에 fetch와 checkout 명령을 추가해야 할 수 있습니다.

이 전략은 배포 작업처럼 아티팩트만으로 동작하는 작업에 사용할 수 있습니다. Git 리포지터리 데이터가 남아 있을 수 있지만 오래된 상태일 가능성이 높습니다. 캐시나 아티팩트에서 로컬 작업 사본으로 가져온 파일에만 의존해야 합니다. 이전 파이프라인의 캐시·아티팩트 파일이 여전히 남아 있을 수 있다는 점에 유의합니다.

none과 달리 empty Git 전략은 캐시나 아티팩트 파일을 다운로드하기 전에 전용 빌드 디렉터리를 삭제한 뒤 다시 생성합니다. 이 전략을 사용해도 추가적인 동작 커스터마이징을 위해 GitLab Runner 후크 스크립트는(있는 경우) 계속 실행됩니다. 다음과 같은 경우 empty Git 전략을 사용합니다.

  • 리포지터리 데이터가 존재할 필요가 없는 경우
  • 작업이 실행될 때마다 깨끗하고 통제되거나 커스터마이징된 시작 상태를 원하는 경우

Git 서브모듈 전략#

GIT_SUBMODULE_STRATEGY 변수는 빌드 전 코드를 가져올 때 Git 서브모듈을 포함할지, 어떻게 포함할지를 제어하는 데 사용됩니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

가능한 값은 none, normal, recursive 세 가지입니다.

  • none은 프로젝트 코드를 가져올 때 서브모듈을 포함하지 않는다는 의미입니다. 이 설정은 1.10 이전 버전의 기본 동작과 동일합니다.

  • normal은 최상위 서브모듈만 포함한다는 의미입니다. 다음과 동일합니다.

    git submodule sync
    git submodule update --init
    
  • recursive는 (서브모듈의 서브모듈을 포함해) 모든 서브모듈을 포함한다는 의미입니다. 이 기능에는 Git v1.8.1 이상이 필요합니다. Docker 기반이 아닌 executor를 사용하는 GitLab Runner에서는 Git 버전이 이 요구 사항을 충족하는지 확인합니다. 다음과 동일합니다.

    git submodule sync --recursive
    git submodule update --init --recursive
    

이 기능이 올바르게 동작하려면 서브모듈이 (.gitmodules에서) 다음 중 하나로 구성되어 있어야 합니다.

  • 공개적으로 접근 가능한 리포지터리의 HTTP(S) URL, 또는
  • 동일한 GitLab 서버에 있는 다른 리포지터리에 대한 상대 경로. 자세한 내용은 Git 서브모듈 문서를 참고합니다.

고급 동작을 제어하는 추가 플래그는 GIT_SUBMODULE_UPDATE_FLAGS를 사용해 지정할 수 있습니다.

Git 체크아웃#

GIT_CHECKOUT 변수는 GIT_STRATEGY가 clone 또는 fetch로 설정되었을 때 git checkout 실행 여부를 지정하는 데 사용할 수 있습니다. 지정하지 않으면 기본값은 true 입니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

false로 설정하면 러너는 다음과 같이 동작합니다.

  • fetch를 수행할 때 - 리포지터리를 업데이트하고 작업 사본을 현재 리비전에 그대로 둡니다.
  • clone을 수행할 때 - 리포지터리를 클론하고 작업 사본을 기본 브랜치에 그대로 둡니다.

GIT_CHECKOUT 이 true로 설정되면 clone과 fetch는 동일하게 동작합니다. 러너는 CI 파이프라인과 관련된 리비전의 작업 사본을 체크아웃합니다.

variables:
  GIT_STRATEGY: clone
  GIT_CHECKOUT: "false"
script:
  - git checkout -B master origin/master
  - git merge $CI_COMMIT_SHA

Git clean 플래그#

GIT_CLEAN_FLAGS 변수는 소스를 체크아웃한 뒤 git clean의 기본 동작을 제어하는 데 사용됩니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

GIT_CLEAN_FLAGS는 git clean 명령의 모든 옵션을 허용합니다.

GIT_CHECKOUT: "false"가 지정되면 git clean은 비활성화됩니다.

GIT_CLEAN_FLAGS가 다음과 같으면:

  • 지정되지 않은 경우, git clean 플래그는 기본값 -ffdx를 사용합니다.
  • 값이 none 인 경우, git clean을 실행하지 않습니다.

예를 들면 다음과 같습니다.

variables:
  GIT_CLEAN_FLAGS: -ffdx -e cache/
script:
  - ls -al cache/

Git fetch 추가 플래그#

GIT_FETCH_EXTRA_FLAGS 변수를 사용해 git fetch의 동작을 제어합니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

GIT_FETCH_EXTRA_FLAGS는 git fetch 명령의 모든 옵션을 허용합니다. 다만 GIT_FETCH_EXTRA_FLAGS 플래그는 수정할 수 없는 기본 플래그 뒤에 추가됩니다.

기본 플래그는 다음과 같습니다.

GIT_FETCH_EXTRA_FLAGS가 다음과 같으면:

  • 지정되지 않은 경우, git fetch 플래그는 기본 플래그와 함께 --prune --quiet를 기본값으로 사용합니다.
  • 값이 none 인 경우, git fetch는 기본 플래그로만 실행됩니다.

예를 들어 기본 플래그는 --prune --quiet 이므로, 이를 --prune 만으로 재정의하면 git fetch 출력을 더 자세하게 만들 수 있습니다.

variables:
  GIT_FETCH_EXTRA_FLAGS: --prune
script:
  - ls -al cache/

위 설정을 적용하면 git fetch는 다음과 같이 호출됩니다.

git fetch origin $REFSPECS --depth 20  --prune

여기서 $REFSPECS는 GitLab 이 내부적으로 러너에 제공하는 값입니다.

Git clone 추가 플래그#

GIT_CLONE_EXTRA_FLAGS 변수를 사용해 네이티브 git clone 작업에 추가 인자를 전달합니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

GIT_CLONE_EXTRA_FLAGS를 사용하려면 다음과 같이 합니다.

  • FF_USE_GIT_NATIVE_CLONE을 true로 설정해 네이티브 git clone 기능을 활성화합니다.
  • fetch 대신 clone 전략을 사용하도록 GIT_STRATEGY를 clone으로 설정합니다.
  • Git 클라이언트는 2.49 버전 이상이어야 합니다. 이 조건은 헬퍼 이미지가 18.1 버전 이상의 Linux 계열 이미지이면 자동으로 충족됩니다.

GIT_CLONE_EXTRA_FLAGS는 git clone 명령의 모든 옵션을 허용합니다. 이 플래그는 대체 리포지터리 참조나 클론 성능 최적화 등 고급 사용 사례에서 유연성을 제공하도록 네이티브 git clone 명령 뒤에 추가됩니다.

예를 들어 참조 리포지터리를 사용해 클론 성능을 최적화할 수 있습니다.

variables:
  FF_USE_GIT_NATIVE_CLONE: true
  GIT_STRATEGY: clone
  GIT_CLONE_EXTRA_FLAGS: "--reference-if-available /tmp/test"

GIT_CLONE_EXTRA_FLAGS가 지정되지 않으면 git clone은 기본 플래그만 사용합니다.

CI 작업에서 특정 서브모듈 동기화 또는 제외#

GIT_SUBMODULE_PATHS 변수를 사용해 어떤 서브모듈을 동기화하거나 업데이트할지 제어합니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

경로 구문은 git submodule과 동일합니다.

  • 특정 경로를 동기화하고 업데이트하려면:

    variables:
       GIT_SUBMODULE_PATHS: submoduleA submoduleB
    
  • 특정 경로를 제외하려면:

    variables:
       GIT_SUBMODULE_PATHS: ":(exclude)submoduleA :(exclude)submoduleB"
    
Warning

Git은 중첩된 경로를 무시합니다. 중첩된 서브모듈을 무시하려면 상위 서브모듈을 제외한 뒤 작업 스크립트에서 수동으로 클론합니다. 예를 들면 git clone <repo> --recurse-submodules=':(exclude)nested-submodule'와 같습니다. YAML 이 올바르게 파싱되도록 문자열을 작은따옴표로 감싸야 합니다.

Git 서브모듈 업데이트 플래그#

GIT_SUBMODULE_STRATEGY가 normal 또는 recursive로 설정된 경우 GIT_SUBMODULE_UPDATE_FLAGS 변수를 사용해 git submodule update의 동작을 제어합니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

GIT_SUBMODULE_UPDATE_FLAGS는 git submodule update 하위 명령의 모든 옵션을 허용합니다. 다만 GIT_SUBMODULE_UPDATE_FLAGS 플래그는 몇 가지 기본 플래그 뒤에 추가됩니다.

Git은 인자 목록에서 마지막으로 나온 플래그를 우선 적용하므로, GIT_SUBMODULE_UPDATE_FLAGS에 직접 지정하면 이 기본 플래그를 재정의합니다.

예를 들어 이 변수를 사용해 다음과 같이 할 수 있습니다.

  • --remote 플래그를 사용해 리포지터리에서 추적 중인 커밋(기본값) 대신 최신 원격 HEAD를 가져와 모든 서브모듈을 자동으로 업데이트합니다.
  • --jobs 4 플래그로 여러 작업을 병렬로 실행해 서브모듈을 가져오는 속도를 높입니다.
variables:
  GIT_SUBMODULE_STRATEGY: recursive
  GIT_SUBMODULE_UPDATE_FLAGS: --remote --jobs 4
script:
  - ls -al .git/modules/

위 설정을 적용하면 git submodule update는 다음과 같이 호출됩니다.

git submodule update --init --depth 20 --recursive --remote --jobs 4
Warning

--remote 플래그를 사용할 때는 빌드의 보안, 안정성, 재현성에 미치는 영향을 알고 있어야 합니다. 대부분의 경우 설계된 대로 서브모듈 커밋을 명시적으로 추적하고, 자동 교정/의존성 봇을 사용해 업데이트하는 편이 더 낫습니다.

서브모듈을 커밋된 리비전으로 체크아웃하는 데 --remote 플래그가 필요한 것은 아닙니다. 이 플래그는 서브모듈을 최신 원격 버전으로 자동 업데이트하려는 경우에만 사용합니다.

--remote의 동작은 Git 버전에 따라 다릅니다. 상위 프로젝트의 .gitmodules 파일에 지정된 브랜치가 서브모듈 리포지터리의 기본 브랜치와 다르면, 일부 Git 버전에서는 다음 오류로 실패합니다.

fatal: Unable to find refs/remotes/origin/<branch> revision in submodule path '<submodule-path>'

러너는 서브모듈 업데이트가 실패하면 원격 참조를 가져오려고 시도하는 "최선의 노력(best effort)" 폴백을 구현합니다.

이 폴백이 사용 중인 Git 버전에서 동작하지 않으면 다음 우회 방법 중 하나를 시도합니다.

  • 서브모듈 리포지터리의 기본 브랜치를 상위 프로젝트의 .gitmodules에 설정된 브랜치와 일치하도록 업데이트합니다.
  • GIT_SUBMODULE_DEPTH를 0으로 설정합니다.
  • 서브모듈을 별도로 업데이트하고 GIT_SUBMODULE_UPDATE_FLAGS에서 --remote 플래그를 제거합니다.

서브모듈 URL을 HTTPS로 재작성#

GIT_SUBMODULE_FORCE_HTTPS 변수를 사용해 모든 Git·SSH 서브모듈 URL을 강제로 HTTPS로 재작성합니다. Git 또는 SSH 프로토콜로 구성되어 있더라도, 동일한 GitLab 인스턴스에서 절대 URL을 사용하는 서브모듈을 클론할 수 있습니다.

variables:
  GIT_SUBMODULE_STRATEGY: recursive
  GIT_SUBMODULE_FORCE_HTTPS: "true"

이 설정을 활성화하면 GitLab Runner는 CI/CD 작업 토큰을 사용해 서브모듈을 클론합니다. 이 토큰은 작업을 실행하는 사용자의 권한을 사용하며 SSH 자격 증명이 필요하지 않습니다.

얕은 클로닝#

GIT_DEPTH를 사용해 가져오기와 클론의 깊이를 지정할 수 있습니다. GIT_DEPTH는 리포지터리를 얕은 클론으로 처리해 클론 속도를 크게 높일 수 있습니다. 커밋 수가 많거나 오래된 대용량 바이너리가 있는 리포지터리에서 유용할 수 있습니다. 이 값은 git fetch와 git clone에 전달됩니다.

새로 생성된 프로젝트는 자동으로 기본 git depth 값 20을 갖습니다.

깊이를 1로 사용하면서 작업 대기열이 있거나 작업을 재시도하면 작업이 실패할 수 있습니다.

Git 가져오기와 클론은 브랜치 이름 같은 참조(ref)를 기준으로 하므로, 러너는 특정 커밋 SHA를 클론할 수 없습니다. 여러 작업이 대기열에 있거나 오래된 작업을 재시도하는 경우, 테스트할 커밋이 클론된 Git 히스토리에 있어야 합니다. GIT_DEPTH 값을 너무 작게 설정하면 이런 오래된 커밋을 실행할 수 없게 되어 작업 로그에 unresolved reference가 표시됩니다. 이 경우 GIT_DEPTH를 더 큰 값으로 변경하는 것을 다시 고려해야 합니다.

GIT_DEPTH가 설정되면 Git 히스토리의 일부만 존재하므로 git describe에 의존하는 작업은 올바르게 동작하지 않을 수 있습니다.

마지막 커밋 3개만 가져오거나 클론하려면 다음과 같이 합니다.

variables:
  GIT_DEPTH: "3"

이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

Git 서브모듈 깊이#

GIT_SUBMODULE_STRATEGY가 normal 또는 recursive로 설정된 경우 GIT_SUBMODULE_DEPTH 변수를 사용해 서브모듈을 가져오고 클론하는 깊이를 지정합니다. 이 변수는 variables 섹션에서 전역으로 또는 특정 작업 단위로 설정할 수 있습니다.

GIT_SUBMODULE_DEPTH 변수를 설정하면 서브모듈에 한해서만 GIT_DEPTH 설정을 덮어씁니다.

마지막 커밋 3개만 가져오거나 클론하려면 다음과 같이 합니다.

variables:
  GIT_SUBMODULE_DEPTH: 3

사용자 지정 빌드 디렉터리#

기본적으로 GitLab Runner는 $CI_BUILDS_DIR 디렉터리의 고유한 하위 경로에 리포지터리를 클론합니다. 다만 프로젝트에 따라 코드가 특정 디렉터리에 있어야 할 수도 있습니다(예: Go 프로젝트). 이 경우 GIT_CLONE_PATH 변수를 지정해 러너에게 리포지터리를 클론할 디렉터리를 알려줄 수 있습니다.

variables:
  GIT_CLONE_PATH: $CI_BUILDS_DIR/project-name

test:
  script:
    - pwd

GIT_CLONE_PATH는 항상 $CI_BUILDS_DIR 내부에 있어야 합니다. $CI_BUILDS_DIR에 설정되는 디렉터리는 executor와 runners.builds_dir 설정 구성에 따라 달라집니다.

이 기능은 러너 구성에서 custom_build_dir 이 활성화된 경우에만 사용할 수 있습니다.

동시성 처리#

동시성을 1보다 크게 사용하는 executor는 실패로 이어질 수 있습니다. 작업 간에 builds_dir가 공유되면 여러 작업이 동일한 디렉터리에서 작업할 수 있습니다.

러너는 이런 상황을 방지하려 하지 않습니다. 러너 구성의 요구 사항을 준수하는 것은 관리자와 개발자의 몫입니다.

이런 상황을 피하려면 $CI_BUILDS_DIR에 고유한 경로를 사용할 수 있습니다. 러너는 동시성의 고유 ID를 제공하는 추가 변수 두 개를 노출하기 때문입니다.

  • $CI_CONCURRENT_ID: 지정된 executor에서 실행되는 모든 작업의 고유 ID
  • $CI_CONCURRENT_PROJECT_ID: 지정된 executor와 프로젝트에서 실행되는 모든 작업의 고유 ID

어떤 시나리오와 executor에서도 잘 동작하는 가장 안정적인 구성은 GIT_CLONE_PATH에 $CI_CONCURRENT_ID를 사용하는 것입니다. 예를 들면 다음과 같습니다.

variables:
  GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/project-name

test:
  script:
    - pwd -P

$CI_CONCURRENT_PROJECT_ID는 $CI_PROJECT_PATH와 함께 사용해야 합니다. $CI_PROJECT_PATH는 group/subgroup/project 형식으로 리포지터리 경로를 제공합니다. 예를 들면 다음과 같습니다.

variables:
  GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH

test:
  script:
    - pwd -P

중첩 경로#

GIT_CLONE_PATH 값은 한 번만 확장됩니다. 이 값 안에 변수를 중첩할 수 없습니다.

예를 들어 .gitlab-ci.yml 파일에 다음 변수를 정의했다고 가정합니다.

variables:
  GOPATH: $CI_BUILDS_DIR/go
  GIT_CLONE_PATH: $GOPATH/src/namespace/project

GIT_CLONE_PATH 값은 한 번만 확장되어 $CI_BUILDS_DIR/go/src/namespace/project가 되며, $CI_BUILDS_DIR가 확장되지 않으므로 실패합니다.

after_script에서 오류 무시#

작업에서 after_script를 사용해 작업의 before_script와 script 섹션 이후에 실행할 명령 배열을 정의할 수 있습니다. after_script 명령은 스크립트 종료 상태(실패 또는 성공)와 관계없이 실행됩니다.

기본적으로 GitLab Runner는 after_script 실행 중 발생하는 오류를 무시합니다. after_script 실행 중 오류가 발생하면 작업이 즉시 실패하도록 설정하려면 AFTER_SCRIPT_IGNORE_ERRORS CI/CD 변수를 false로 설정합니다. 예를 들면 다음과 같습니다.

variables:
  AFTER_SCRIPT_IGNORE_ERRORS: false

작업 단계 재시도 횟수#

실행 중인 job이 다음 단계를 실행하는 시도 횟수를 설정할 수 있습니다:

변수 설명
ARTIFACT_DOWNLOAD_ATTEMPTS job 실행 중 아티팩트를 다운로드하는 시도 횟수입니다.
EXECUTOR_JOB_SECTION_ATTEMPTS job에서 No Such Container 오류가 발생한 후 섹션을 실행하는 시도 횟수입니다(Docker executor 전용).
GET_SOURCES_ATTEMPTS job 실행 중 소스를 가져오는 시도 횟수입니다.
RESTORE_CACHE_ATTEMPTS job 실행 중 캐시를 복원하는 시도 횟수입니다.

기본값은 단일 시도입니다.

예시:

variables:
  GET_SOURCES_ATTEMPTS: 3

variables 섹션에서 전역으로 설정하거나 job 단위로 설정할 수 있습니다.

GitLab.com 인스턴스 러너에서 사용할 수 없는 시스템 호출#

GitLab.com 인스턴스 러너는 CoreOS에서 실행됩니다. 따라서 C 표준 라이브러리의 getlogin과 같은 일부 시스템 호출을 사용할 수 없습니다.

아티팩트 및 캐시 설정#

아티팩트 및 캐시 설정은 아티팩트와 캐시의 압축률을 제어합니다. 이 설정을 사용해 job이 생성하는 아카이브의 크기를 지정합니다.

  • 네트워크 속도가 느리면 아카이브 크기가 작을수록 업로드가 더 빠를 수 있습니다.
  • 대역폭과 저장 공간이 문제되지 않는 빠른 네트워크에서는 생성되는 아카이브가 더 크더라도 가장 빠른 압축률을 사용하는 편이 업로드가 더 빠를 수 있습니다.

GitLab Pages가 HTTP Range 요청을 처리하려면, 아티팩트는 ARTIFACT_COMPRESSION_LEVEL: fastest 설정을 사용해야 합니다. 압축하지 않은 zip 아카이브만 이 기능을 지원하기 때문입니다.

업로드와 다운로드의 전송 속도를 표시하는 미터를 활성화할 수 있습니다.

CACHE_REQUEST_TIMEOUT 설정으로 캐시 업로드와 다운로드의 최대 시간을 설정할 수 있습니다. 캐시 업로드가 느려 job 소요 시간이 크게 늘어나는 경우 이 설정을 사용합니다.

variables:
  # output upload and download progress every 2 seconds
  TRANSFER_METER_FREQUENCY: "2s"

  # Use fast compression for artifacts, resulting in larger archives
  ARTIFACT_COMPRESSION_LEVEL: "fast"

  # Use no compression for caches
  CACHE_COMPRESSION_LEVEL: "fastest"

  # Set maximum duration of cache upload and download
  CACHE_REQUEST_TIMEOUT: 5
변수 설명
TRANSFER_METER_FREQUENCY 미터의 전송 속도를 출력하는 주기를 지정합니다. 기간 값(예: 1s 또는 1m30s)으로 설정할 수 있습니다. 0으로 설정하면 미터가 비활성화됩니다(기본값). 값을 설정하면 파이프라인이 아티팩트 및 캐시 업로드·다운로드에 대한 진행률 미터를 표시합니다.
ARTIFACT_COMPRESSION_LEVEL 압축률을 조정하려면 fastest, fast, default, slow, slowest 중 하나로 설정합니다. 이 설정은 Fastzip 아카이버에서만 동작하므로 GitLab Runner 기능 플래그 FF_USE_FASTZIP도 함께 활성화해야 합니다.
CACHE_COMPRESSION_LEVEL 압축률을 조정하려면 fastest, fast, default, slow, slowest 중 하나로 설정합니다. 이 설정은 Fastzip 아카이버에서만 동작하므로 GitLab Runner 기능 플래그 FF_USE_FASTZIP도 함께 활성화해야 합니다.
CACHE_REQUEST_TIMEOUT 단일 job에 대한 캐시 업로드·다운로드 작업의 최대 시간을(분 단위로) 설정합니다. 기본값은 10분입니다.

지연 시간이 긴 연결을 위한 TCP 설정 튜닝#

러너와 GitLab 인스턴스 사이에 네트워크 지연이 크게 발생하는 경우, 기본 TCP 윈도 크기가 처리량을 제한할 수 있습니다. 러너 호스트에서 TCP 윈도 크기를 늘려 더 많은 데이터를 전송 중 상태로 둘 수 있게 합니다.

예를 들어 Linux에서는 다음과 같이 최대 TCP 버퍼 크기를 늘립니다:

sudo sysctl -w net.core.rmem_max=16777216
sudo sysctl -w net.core.wmem_max=16777216
sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"

재부팅 후에도 이 변경 사항을 유지하려면 /etc/sysctl.conf에 추가합니다.

Note

TCP 튜닝은 러너 머신의 모든 네트워크 연결에 영향을 주는 호스트 수준 변경 사항입니다. 프로덕션이 아닌 환경에서 먼저 변경 사항을 테스트합니다.

아티팩트 출처 메타데이터#

러너는 SLSA Provenance를 생성하고 모든 빌드 아티팩트에 출처(provenance)를 결합하는 SLSA Statement를 만들 수 있습니다. 이 statement를 아티팩트 출처 메타데이터라고 합니다.

아티팩트 출처 메타데이터를 활성화하려면 RUNNER_GENERATE_ARTIFACTS_METADATA 환경 변수를 true로 설정합니다. 이 변수는 전역으로 설정하거나 개별 job에 대해 설정할 수 있습니다:

variables:
  RUNNER_GENERATE_ARTIFACTS_METADATA: "true"

job1:
  variables:
    RUNNER_GENERATE_ARTIFACTS_METADATA: "true"

메타데이터는 아티팩트와 함께 저장되는 일반 텍스트 .json 파일로 표현됩니다. 파일 이름은 {ARTIFACT_NAME}-metadata.json 입니다. ARTIFACT_NAME은 .gitlab-ci.yml 파일에 정의된 아티팩트 이름 입니다. 이름이 정의되지 않은 경우 기본 파일 이름은 artifacts-metadata.json 입니다.

출처 메타데이터 형식#

아티팩트 출처 메타데이터는 in-toto v0.1 Statement 형식으로 생성됩니다. 여기에는 SLSA 1.0 Provenance 형식으로 생성된 provenance predicate가 포함됩니다.

다음 필드는 기본으로 채워집니다:

필드 값
_type https://in-toto.io/Statement/v0.1
subject 메타데이터가 적용되는 소프트웨어 아티팩트 집합입니다.
subject[].name 아티팩트의 파일 이름입니다.
subject[].sha256 아티팩트의 sha256 체크섬입니다.
predicateType https://slsa.dev/provenance/v1
predicate.buildDefinition.buildType https://gitlab.com/gitlab-org/gitlab-runner/-/blob/{GITLAB_RUNNER_VERSION}/PROVENANCE.md. 예를 들어 v19.0.0
predicate.runDetails.builder.id 러너 세부 정보 페이지를 가리키는 URI입니다. 예: https://gitlab.com/gitlab-com/www-gitlab-com/-/runners/3785264.
predicate.buildDefinition.externalParameters 빌드 명령 실행 중 사용 가능한 CI/CD 또는 환경 변수의 이름입니다. 시크릿을 보호하기 위해 값은 항상 빈 문자열로 표시됩니다.
predicate.buildDefinition.externalParameters.source 프로젝트의 URL입니다.
predicate.buildDefinition.externalParameters.entryPoint 빌드를 트리거한 CI/CD job의 이름입니다.
predicate.buildDefinition.internalParameters.name 러너의 이름입니다.
predicate.buildDefinition.internalParameters.executor 러너 실행기(executor)입니다.
predicate.buildDefinition.internalParameters.architecture CI/CD job이 실행되는 아키텍처입니다.
predicate.buildDefinition.internalParameters.job 빌드를 트리거한 CI/CD job의 ID입니다.
predicate.buildDefinition.resolvedDependencies[0].uri 프로젝트의 URL입니다.
predicate.buildDefinition.resolvedDependencies[0].digest.sha256 프로젝트의 커밋 리비전입니다.
predicate.runDetails.metadata.invocationId 빌드를 트리거한 CI/CD job의 ID입니다.
predicate.runDetails.metadata.startedOn 빌드가 시작된 시간입니다. 이 필드는 RFC3339 형식입니다.
predicate.runDetails.metadata.finishedOn 빌드가 종료된 시간입니다. 메타데이터 생성이 빌드 중에 이루어지므로 이 시간은 GitLab에 보고되는 시간보다 약간 이릅니다. 이 필드는 RFC3339 형식입니다.

provenance statement는 다음 예시와 유사한 형태입니다:

{
 "_type": "https://in-toto.io/Statement/v0.1",
 "predicateType": "https://slsa.dev/provenance/v1",
 "subject": [
  {
   "name": "x.txt",
   "digest": {
    "sha256": "ac097997b6ec7de591d4f11315e4aa112e515bb5d3c52160d0c571298196ea8b"
   }
  },
  {
   "name": "y.txt",
   "digest": {
    "sha256": "9eb634f80da849d828fcf42740d823568c49e8d7b532886134f9086246b1fdf3"
   }
  }
 ],
 "predicate": {
  "buildDefinition": {
   "buildType": "https://gitlab.com/gitlab-org/gitlab-runner/-/blob/2147fb44/PROVENANCE.md",
   "externalParameters": {
    "CI": "",
    "CI_API_GRAPHQL_URL": "",
    "CI_API_V4_URL": "",
    "CI_COMMIT_AUTHOR": "",
    "CI_COMMIT_BEFORE_SHA": "",
    "CI_COMMIT_BRANCH": "",
    "CI_COMMIT_DESCRIPTION": "",
    "CI_COMMIT_MESSAGE": "",
    [... additional environmental variables ...]
    "entryPoint": "build-job",
    "source": "https://gitlab.com/my-group/my-project/test-runner-generated-slsa-statement"
   },
   "internalParameters": {
    "architecture": "amd64",
    "executor": "docker+machine",
    "job": "10340684631",
    "name": "green-4.saas-linux-small-amd64.runners-manager.gitlab.com/default"
   },
   "resolvedDependencies": [
    {
     "uri": "https://gitlab.com/my-group/my-project/test-runner-generated-slsa-statement",
     "digest": {
      "sha256": "bdd2ecda9ef57b129c88617a0215afc9fb223521"
     }
    }
   ]
  },
  "runDetails": {
   "builder": {
    "id": "https://gitlab.com/my-group/my-project/test-runner-generated-slsa-statement/-/runners/12270857",
    "version": {
     "gitlab-runner": "2147fb44"
    }
   },
   "metadata": {
    "invocationId": "10340684631",
    "startedOn": "2025-06-13T07:25:13Z",
    "finishedOn": "2025-06-13T07:25:40Z"
   }
  }
 }
}

스테이징 디렉터리#

시스템의 기본 임시 디렉터리에 캐시와 아티팩트를 아카이브하고 싶지 않다면 다른 디렉터리를 지정할 수 있습니다.

시스템의 기본 임시 경로에 제약이 있는 경우 디렉터리를 변경해야 할 수 있습니다. 해당 디렉터리 위치에 빠른 디스크를 사용하면 성능도 향상될 수 있습니다.

디렉터리를 변경하려면 CI job에서 변수로 ARCHIVER_STAGING_DIR을 설정하거나, 러너를 등록할 때 러너 변수를 사용합니다(gitlab register --env ARCHIVER_STAGING_DIR=<dir>).

지정한 디렉터리는 압축 해제 전에 아티팩트를 다운로드하는 위치로 사용됩니다. fastzip 아카이버를 사용하는 경우 이 위치는 아카이브 생성 시 스크래치 공간으로도 사용됩니다.

성능 향상을 위한 fastzip 구성#

fastzip을 튜닝하려면 FF_USE_FASTZIP 플래그가 활성화되어 있는지 확인합니다. 그런 다음 다음 환경 변수 중 원하는 것을 사용합니다.

변수 설명
FASTZIP_ARCHIVER_CONCURRENCY 동시에 압축할 파일 수입니다. 기본값은 사용 가능한 CPU 개수입니다.
FASTZIP_ARCHIVER_BUFFER_SIZE 파일마다 동시성 단위로 할당되는 버퍼 크기입니다. 이 크기를 초과하는 데이터는 스크래치 공간으로 이동합니다. 기본값은 2 MiB입니다.
FASTZIP_EXTRACTOR_CONCURRENCY 동시에 압축 해제할 파일 수입니다. 기본값은 사용 가능한 CPU 개수입니다.

zip 아카이브 안의 파일은 순차적으로 추가됩니다. 이 때문에 동시 압축이 어렵습니다. fastzip은 먼저 파일을 디스크에 동시에 압축한 다음, 그 결과를 zip 아카이브로 순차적으로 복사하는 방식으로 이 제약을 해결합니다.

작은 파일에 대해 디스크에 쓰고 다시 읽는 과정을 피하기 위해 동시성 단위로 작은 버퍼를 사용합니다. 이 설정은 FASTZIP_ARCHIVER_BUFFER_SIZE로 제어할 수 있습니다. 이 버퍼의 기본 크기는 2 MiB이므로 동시성 16이면 32 MiB가 할당됩니다. 버퍼 크기를 초과하는 데이터는 디스크에 쓰고 다시 읽어옵니다. 따라서 버퍼를 사용하지 않는 FASTZIP_ARCHIVER_BUFFER_SIZE: 0 설정으로 스크래치 공간만 사용하는 것도 유효한 선택지입니다.

FASTZIP_ARCHIVER_CONCURRENCY는 동시에 압축할 파일 수를 제어합니다. 앞서 설명한 대로 이 설정은 사용되는 메모리 양을 늘릴 수 있습니다. 또한 스크래치 공간에 기록되는 임시 데이터도 늘어날 수 있습니다. 기본값은 사용 가능한 CPU 개수이지만, 메모리에 미치는 영향을 고려하면 항상 최선의 설정은 아닐 수 있습니다.

FASTZIP_EXTRACTOR_CONCURRENCY는 한 번에 압축 해제할 파일 수를 제어합니다. zip 아카이브의 파일은 기본적으로 동시에 읽을 수 있으므로 추출기에 필요한 것 외에 추가 메모리가 할당되지 않습니다. 이 값의 기본값은 사용 가능한 CPU 개수입니다.

러너 구성

GitLab v19.4
Tier: Free, Premium, Ultimate
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
원문 보기

요약

이 문서는 GitLab UI에서 러너를 구성하는 방법을 설명합니다. GitLab Runner를 설치한 머신에서 러너를 구성해야 한다면 GitLab Runner 문서를 참고합니다. 더 긴 job 제한 시간을 가진 프로젝트가 러너를 사용하지 못하도록, 각 러너에 대해 최대 job 제한 시간을 지정할 수 있습니다.

이 문서는 GitLab UI에서 러너를 구성하는 방법을 설명합니다.

GitLab Runner를 설치한 머신에서 러너를 구성해야 한다면 GitLab Runner 문서를 참고합니다.

최대 job 제한 시간 설정#

더 긴 job 제한 시간을 가진 프로젝트가 러너를 사용하지 못하도록, 각 러너에 대해 최대 job 제한 시간을 지정할 수 있습니다. 프로젝트에 정의된 job 제한 시간보다 짧은 경우 최대 job 제한 시간이 사용됩니다.

러너의 최대 제한 시간을 설정하려면, REST API 엔드포인트 PUT /runners/:id에서 maximum_timeout 파라미터를 설정합니다.

인스턴스 러너의 경우#

사전 요구 사항:

  • 관리자여야 합니다.

GitLab Self-Managed에서는 인스턴스 러너의 job 제한 시간을 재정의할 수 있습니다.

GitLab.com에서는 GitLab 호스팅 인스턴스 러너의 job 제한 시간을 재정의할 수 없으며, 대신 프로젝트에 정의된 제한 시간을 사용해야 합니다.

최대 job 제한 시간을 설정하려면:

  1. 오른쪽 상단에서 Admin을 선택합니다.
  2. 왼쪽 사이드바에서 CI/CD > Runners를 선택합니다.
  3. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. Maximum job timeout 필드에 초 단위로 값을 입력합니다. 최소값은 600초(10분)입니다.
  5. Save changes를 선택합니다.

그룹 러너의 경우#

사전 요구 사항:

  • 그룹에 대한 Owner 권한이 있어야 합니다.

최대 job 제한 시간을 설정하려면:

  1. 상단 바에서 Search or go to를 선택하고 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Build > Runners를 선택합니다.
  3. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. Maximum job timeout 필드에 초 단위로 값을 입력합니다. 최소값은 600초(10분)입니다.
  5. Save changes를 선택합니다.

프로젝트 러너의 경우#

사전 요구 사항:

  • 프로젝트에 대한 Owner 권한이 있어야 합니다.

최대 job 제한 시간을 설정하려면:

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
  3. Runners를 확장합니다.
  4. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  5. Maximum job timeout 필드에 초 단위로 값을 입력합니다. 최소값은 600초(10분)입니다. 정의되지 않은 경우 프로젝트의 job 제한 시간이 대신 사용됩니다.
  6. Save changes를 선택합니다.

최대 job 제한 시간의 동작 방식#

예제 1 - 러너 제한 시간이 프로젝트 제한 시간보다 긴 경우

  1. 러너의 maximum_timeout 파라미터를 24시간으로 설정합니다.
  2. 프로젝트의 Maximum job timeout을 2시간으로 설정합니다.
  3. job을 시작합니다.
  4. job 이 더 오래 실행되면 2시간 후에 제한 시간이 초과됩니다.

예제 2 - 러너 제한 시간이 구성되지 않은 경우

  1. 러너에서 maximum_timeout 파라미터 구성을 제거합니다.
  2. 프로젝트의 Maximum job timeout을 2시간으로 설정합니다.
  3. job을 시작합니다.
  4. job 이 더 오래 실행되면 2시간 후에 제한 시간이 초과됩니다.

예제 3 - 러너 제한 시간이 프로젝트 제한 시간보다 짧은 경우

  1. 러너의 maximum_timeout 파라미터를 30분으로 설정합니다.
  2. 프로젝트의 Maximum job timeout을 2시간으로 설정합니다.
  3. job을 시작합니다.
  4. job 이 더 오래 실행되면 30분 후에 제한 시간이 초과됩니다.

script 및 after_script 제한 시간 설정#

script 및 after_script가 종료되기까지 실행되는 시간을 제어하려면, .gitlab-ci.yml 파일에 제한 시간 값을 지정합니다.

예를 들어, 장시간 실행되는 script를 조기에 종료하도록 제한 시간을 지정할 수 있습니다. 이렇게 하면 job 제한 시간이 초과되기 전에 아티팩트와 캐시를 계속 업로드할 수 있습니다. script와 after_script의 제한 시간 값은 job 제한 시간보다 짧아야 합니다.

  • script의 제한 시간을 설정하려면 job 변수 RUNNER_SCRIPT_TIMEOUT을 사용합니다.
  • after_script의 제한 시간을 설정하고 기본값인 5분을 재정의하려면 job 변수 RUNNER_AFTER_SCRIPT_TIMEOUT을 사용합니다.

이 두 변수는 모두 Go의 duration 형식을 허용합니다(예: 40s, 1h20m, 2h 4h30m30s).

예를 들면:

job-with-script-timeouts:
  variables:
    RUNNER_SCRIPT_TIMEOUT: 15m
    RUNNER_AFTER_SCRIPT_TIMEOUT: 10m
  script:
    - "I am allowed to run for min(15m, remaining job timeout)."
  after_script:
    - "I am allowed to run for min(10m, remaining job timeout)."

job-artifact-upload-on-timeout:
  timeout: 1h                           # set job timeout to 1 hour
  variables:
     RUNNER_SCRIPT_TIMEOUT: 50m         # only allow script to run for 50 minutes
  script:
    - long-running-process > output.txt # will be terminated after 50m

  artifacts: # artifacts will have roughly ~10m to upload
    paths:
      - output.txt
    when: on_failure # on_failure because script termination after a timeout is treated as a failure

after_script 실행 보장#

after_script가 성공적으로 실행되려면 RUNNER_SCRIPT_TIMEOUT과 RUNNER_AFTER_SCRIPT_TIMEOUT의 합이 job에 구성된 제한 시간을 초과하지 않아야 합니다.

다음 예제는 메인 스크립트가 제한 시간을 초과하더라도 after_script가 실행되도록 제한 시간을 구성하는 방법을 보여줍니다.

job-with-script-timeouts:
  timeout: 5m
  variables:
    RUNNER_SCRIPT_TIMEOUT: 1m
    RUNNER_AFTER_SCRIPT_TIMEOUT: 1m
  script:
    - echo "Starting build..."
    - sleep 120 # Wait 2 minutes to trigger timeout. Script aborts after 1 minute due to RUNNER_SCRIPT_TIMEOUT.
    - echo "Build finished."
  after_script:
    - echo "Starting Clean-up..."
    - sleep 15 # Wait just a few seconds. Runs successfully because it's within RUNNER_AFTER_SCRIPT_TIMEOUT.
    - echo "Clean-up finished."

script는 RUNNER_SCRIPT_TIMEOUT에 의해 취소되지만, after_script는 15초가 걸려 RUNNER_AFTER_SCRIPT_TIMEOUT과 job의 timeout 값 둘 다보다 짧으므로 성공적으로 실행됩니다.

민감한 정보 보호#

인스턴스 러너는 GitLab 인스턴스의 모든 그룹과 프로젝트에서 기본적으로 사용할 수 있으므로, 인스턴스 러너를 사용할 때 보안 위험이 더 큽니다. 러너 실행기(executor)와 파일 시스템 구성은 보안에 영향을 미칩니다. 러너 호스트 환경에 접근할 수 있는 사용자는 러너가 실행한 코드와 러너 인증을 볼 수 있습니다. 예를 들어, 러너 인증 토큰에 접근할 수 있는 사용자는 러너를 복제하여 공격 벡터로 가짜 job을 제출할 수 있습니다. 자세한 내용은 보안 고려 사항을 참고합니다.

롱 폴링 구성#

GitLab 서버의 job 대기 시간과 부하를 줄이려면 롱 폴링을 구성합니다.

포크된 프로젝트에서 인스턴스 러너 사용#

프로젝트가 포크되면 job과 관련된 job 설정이 복사됩니다. 프로젝트에 인스턴스 러너가 구성되어 있고 사용자가 해당 프로젝트를 포크하면, 인스턴스 러너가 이 프로젝트의 job을 처리합니다.

알려진 이슈로 인해, 포크된 프로젝트의 러너 설정이 새 프로젝트 네임스페이스와 일치하지 않으면 다음 메시지가 표시됩니다: An error occurred while forking the project. Please try again..

이 문제를 해결하려면, 포크된 프로젝트와 새 네임스페이스에서 인스턴스 러너 설정이 일치하도록 합니다.

  • 포크된 프로젝트에서 인스턴스 러너가 활성화되어 있다면, 새 네임스페이스에서도 활성화해야 합니다.
  • 포크된 프로젝트에서 인스턴스 러너가 비활성화되어 있다면, 새 네임스페이스에서도 비활성화해야 합니다.

프로젝트의 러너 등록 토큰 재설정 (지원 중단됨)#

Warning

러너 등록 토큰을 전달하는 옵션과 특정 구성 인수에 대한 지원은 레거시로 간주되며 권장되지 않습니다. 러너를 등록할 인증 토큰을 생성하려면 러너 생성 워크플로를 사용합니다. 이 프로세스는 러너 소유권에 대한 완전한 추적성을 제공하고 러너 플릿의 보안을 강화합니다. 자세한 내용은 새 러너 등록 워크플로로 마이그레이션을 참고합니다.

프로젝트의 등록 토큰이 노출되었다고 생각되면 재설정해야 합니다. 등록 토큰은 프로젝트에 다른 러너를 등록하는 데 사용될 수 있습니다. 그 새 러너는 이후 시크릿 변수의 값을 얻거나 프로젝트 코드를 복제하는 데 사용될 수 있습니다.

등록 토큰을 재설정하려면:

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
  3. Runners를 확장합니다.
  4. New project runner 오른쪽에서 세로 점 3개(⋮)를 선택합니다.
  5. Reset registration token을 선택합니다.
  6. Reset token을 선택합니다.

등록 토큰을 재설정하면 더 이상 유효하지 않으며 프로젝트에 새 러너를 등록하지 않습니다. 새 값을 프로비저닝하고 등록하는 데 사용하는 도구에서도 등록 토큰을 업데이트해야 합니다.

인증 토큰 보안#

각 러너는 GitLab 인스턴스에 연결하고 인증하기 위해 러너 인증 토큰을 사용합니다.

토큰이 침해되는 것을 방지하려면, 지정된 간격으로 토큰이 자동으로 로테이션되도록 할 수 있습니다. 토큰이 로테이션되면 러너의 상태(online 또는 offline)와 관계없이 각 러너에 대해 업데이트됩니다.

수동 개입이 필요하지 않으며 실행 중인 job에도 영향을 미치지 않습니다. 토큰 로테이션에 대한 자세한 내용은 로테이션 시 러너 인증 토큰이 업데이트되지 않음을 참고합니다.

러너 인증 토큰을 수동으로 업데이트해야 한다면 토큰 재설정 명령을 실행할 수 있습니다.

러너 구성 인증 토큰 재설정#

러너의 인증 토큰이 노출되면, 공격자가 이를 사용해 러너를 복제할 수 있습니다.

러너 구성 인증 토큰을 재설정하려면:

  1. 러너를 삭제합니다:
  2. 새 러너 인증 토큰이 할당되도록 새 러너를 생성합니다:
  3. 선택 사항. 이전 러너 인증 토큰이 폐기되었는지 확인하려면 Runners API를 사용합니다.

러너 구성 인증 토큰을 재설정하는 데는 Runners API도 사용할 수 있습니다.

러너 인증 토큰 자동 로테이션#

러너 인증 토큰을 로테이션할 간격을 지정할 수 있습니다. 러너 인증 토큰을 정기적으로 로테이션하면 침해된 토큰을 통한 GitLab 인스턴스 무단 접근 위험을 최소화하는 데 도움이 됩니다.

사전 요구 사항:

  • 관리자여야 합니다.

러너 인증 토큰을 자동으로 로테이션하려면:

  1. 오른쪽 상단에서 Admin을 선택합니다.
  2. 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
  3. Continuous Integration and Deployment를 확장합니다.
  4. 러너에 대한 Runners expiration 시간을 설정합니다. 만료되지 않게 하려면 비워 둡니다.
  5. Save changes를 선택합니다.

간격이 만료되기 전에 러너는 자동으로 새 러너 인증 토큰을 요청합니다. 토큰 로테이션에 대한 자세한 내용은 로테이션 시 러너 인증 토큰이 업데이트되지 않음을 참고합니다.

러너가 민감한 정보를 노출하지 않도록 방지#

러너가 민감한 정보를 노출하지 않도록 하려면, 보호된 브랜치에서 job만 실행하거나 보호된 태그가 있는 job만 실행하도록 구성할 수 있습니다.

보호된 브랜치에서 job을 실행하도록 구성된 러너는 머지 리퀘스트 파이프라인에서 job을 실행하도록 선택적으로 설정할 수 있습니다.

인스턴스 러너의 경우#

사전 요구 사항:

  • 관리자여야 합니다.
  1. 오른쪽 상단에서 Admin을 선택합니다.
  2. 왼쪽 사이드바에서 CI/CD > Runners를 선택합니다.
  3. 보호할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. Protected 체크박스를 선택합니다.
  5. Save changes를 선택합니다.

그룹 러너의 경우#

사전 요구 사항:

  • 그룹에 대한 Owner 권한이 있어야 합니다.
  1. 상단 바에서 Search or go to를 선택하고 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Build > Runners를 선택합니다.
  3. 보호할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. Protected 체크박스를 선택합니다.
  5. Save changes를 선택합니다.

프로젝트 러너의 경우#

사전 요구 사항:

  • 프로젝트에 대한 Owner 권한이 있어야 합니다.
  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
  3. Runners를 확장합니다.
  4. 보호할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  5. Protected 체크박스를 선택합니다.
  6. Save changes를 선택합니다.

러너가 실행할 수 있는 job 제어#

태그를 사용해 러너가 실행할 수 있는 job을 제어할 수 있습니다. 예를 들어, Rails 테스트 스위트를 실행하는 데 필요한 의존성을 가진 러너에 rails 태그를 지정할 수 있습니다.

GitLab CI/CD 태그는 Git 태그와 다릅니다. GitLab CI/CD 태그는 러너와 연결됩니다. Git 태그는 커밋과 연결됩니다.

인스턴스 러너의 경우#

사전 요구 사항:

  • 관리자여야 합니다.

인스턴스 러너가 실행할 수 있는 job을 제어하려면:

  1. 오른쪽 상단에서 Admin을 선택합니다.
  2. 왼쪽 사이드바에서 CI/CD > Runners를 선택합니다.
  3. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. 러너가 태그가 있는 job 또는 태그가 없는 job을 실행하도록 설정합니다:
    • 태그가 있는 job을 실행하려면, Tags 필드에 job 태그를 쉼표로 구분하여 입력합니다. 예: macos, rails.
    • 태그가 없는 job을 실행하려면, Run untagged jobs 체크박스를 선택합니다.
  5. Save changes를 선택합니다.

그룹 러너의 경우#

사전 요구 사항:

  • 그룹에 대한 Owner 권한이 있어야 합니다.

그룹 러너가 실행할 수 있는 job을 제어하려면:

  1. 상단 바에서 Search or go to를 선택하고 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Build > Runners를 선택합니다.
  3. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  4. 러너가 태그가 있는 job 또는 태그가 없는 job을 실행하도록 설정합니다:
    • 태그가 있는 job을 실행하려면, Tags 필드에 job 태그를 쉼표로 구분하여 입력합니다. 예: macos, ruby.
    • 태그가 없는 job을 실행하려면, Run untagged jobs 체크박스를 선택합니다.
  5. Save changes를 선택합니다.

프로젝트 러너의 경우#

사전 요구 사항:

  • 프로젝트에 대한 Owner 권한이 있어야 합니다.

프로젝트 러너가 실행할 수 있는 job을 제어하려면:

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
  3. Runners를 확장합니다.
  4. 편집할 러너 오른쪽에서 Edit(✏️)을 선택합니다.
  5. 러너가 태그가 있는 job 또는 태그가 없는 job을 실행하도록 설정합니다:
    • 태그가 있는 job을 실행하려면, Tags 필드에 job 태그를 쉼표로 구분하여 입력합니다. 예: macos, ruby.
    • 태그가 없는 job을 실행하려면, Run untagged jobs 체크박스를 선택합니다.
  6. Save changes를 선택합니다.

러너가 태그를 사용하는 방식#

러너가 태그가 있는 job만 실행하는 경우#

다음 예제는 러너가 태그가 있는 job만 실행하도록 설정된 경우 발생할 수 있는 영향을 보여줍니다.

예제 1:

  1. 러너가 태그가 있는 job만 실행하도록 구성되어 있고 docker 태그를 가지고 있습니다.
  2. hello 태그를 가진 job 이 실행되어 멈춥니다.

예제 2:

  1. 러너가 태그가 있는 job만 실행하도록 구성되어 있고 docker 태그를 가지고 있습니다.
  2. docker 태그를 가진 job 이 실행되어 처리됩니다.

예제 3:

  1. 러너가 태그가 있는 job만 실행하도록 구성되어 있고 docker 태그를 가지고 있습니다.
  2. 태그가 정의되지 않은 job 이 실행되어 멈춥니다.

러너가 태그가 없는 job 실행을 허용하는 경우#

다음 예제는 러너가 태그가 있는 job과 태그가 없는 job을 모두 실행하도록 설정된 경우 발생할 수 있는 영향을 보여줍니다.

예제 1:

  1. 러너가 태그가 없는 job을 실행하도록 구성되어 있고 docker 태그를 가지고 있습니다.
  2. 태그가 정의되지 않은 job 이 실행되어 처리됩니다.
  3. docker 태그가 정의된 두 번째 job 이 실행되어 처리됩니다.

예제 2:

  1. 러너가 태그가 없는 job을 실행하도록 구성되어 있고 태그가 정의되어 있지 않습니다.
  2. 태그가 정의되지 않은 job 이 실행되어 처리됩니다.
  3. docker 태그가 정의된 두 번째 job은 멈춥니다.

러너와 job에 여러 태그가 있는 경우#

job과 러너를 매칭하는 선택 로직은 job에 정의된 tags 목록을 기준으로 합니다.

다음 예제는 러너와 job에 여러 태그가 있을 때의 영향을 보여줍니다. 러너가 job을 실행하도록 선택되려면, job 스크립트 블록에 정의된 태그를 모두 가지고 있어야 합니다.

예제 1:

  1. 러너가 [docker, shell, gpu] 태그로 구성되어 있습니다.
  2. job 이 [docker, shell, gpu] 태그를 가지고 있어 실행되어 처리됩니다.

예제 2:

  1. 러너가 [docker, shell, gpu] 태그로 구성되어 있습니다.
  2. job 이 [docker, shell,] 태그를 가지고 있어 실행되어 처리됩니다.

예제 3:

  1. 러너가 [docker, shell] 태그로 구성되어 있습니다.
  2. job 이 [docker, shell, gpu] 태그를 가지고 있어 실행되지 않습니다.

태그를 사용해 서로 다른 플랫폼에서 job 실행#

태그를 사용하면 서로 다른 플랫폼에서 서로 다른 job을 실행할 수 있습니다. 예를 들어, osx 태그를 가진 OS X 러너와 windows 태그를 가진 Windows 러너가 있다면, 각 플랫폼에서 job을 실행할 수 있습니다.

.gitlab-ci.yml의 tags 필드를 업데이트합니다:

windows job:
  stage: build
  tags:
    - windows
  script:
    - echo Hello, %USERNAME%!

osx job:
  stage: build
  tags:
    - osx
  script:
    - echo "Hello, $USER!"

태그에 CI/CD 변수 사용#

.gitlab-ci.yml 파일에서, 동적 러너 선택을 위해 tags와 함께 CI/CD 변수를 사용합니다:

variables:
  KUBERNETES_RUNNER: kubernetes

  job:
    tags:
      - docker
      - $KUBERNETES_RUNNER
    script:
      - echo "Hello runner selector feature"

변수로 러너 동작 구성#

CI/CD 변수를 사용하면 러너의 Git 동작을 전역으로 또는 개별 작업 단위로 구성할 수 있습니다.

변수를 사용하면 러너가 작업 실행의 특정 단계를 몇 번 시도할지도 구성할 수 있습니다.

Kubernetes executor를 사용할 때는 변수를 사용해 Kubernetes CPU·메모리 요청 및 제한 할당량을 재정의할 수 있습니다.

러너 기능 플래그도 작업 및 파이프라인 변수로 사용할 수 있습니다.

Git 전략#

GIT_STRATEGY 변수는 빌드 디렉터리를 준비하고 리포지터리 콘텐츠를 가져오는 방식을 구성합니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

variables:
  GIT_STRATEGY: clone

가능한 값은 clone, fetch, none, empty 입니다. 값을 지정하지 않으면 작업은 프로젝트의 파이프라인 설정을 사용합니다.

clone은 가장 느린 옵션입니다. 모든 작업마다 리포지터리를 처음부터 클론하므로 로컬 작업 사본이 항상 깨끗한 상태로 유지됩니다. 기존 워크트리가 있으면 클론 전에 제거합니다.

fetch는 로컬 작업 사본을 재사용하므로 더 빠릅니다(사본이 없으면 clone으로 대체됩니다). git clean은 이전 작업에서 발생한 변경 사항을 되돌리는 데 사용되고, git fetch는 이전 작업 실행 이후에 생긴 커밋을 가져오는 데 사용됩니다.

다만 fetch는 이전 워크트리에 대한 접근이 필요합니다. shell 또는 docker executor를 사용할 때는 기본적으로 워크트리를 보존하고 재사용하려 하므로 잘 동작합니다.

Docker Machine executor를 사용할 때는 이 방식에 제약이 있습니다.

Git 전략이 none 이면 로컬 작업 사본을 재사용하지만, GitLab 이 평소 수행하는 Git 작업은 모두 건너뜁니다. GitLab Runner의 pre-clone 스크립트가 있다면 이 또한 건너뜁니다. 이 전략을 사용하면 .gitlab-ci.yml 스크립트에 fetch와 checkout 명령을 추가해야 할 수 있습니다.

이 전략은 배포 작업처럼 아티팩트만으로 동작하는 작업에 사용할 수 있습니다. Git 리포지터리 데이터가 남아 있을 수 있지만 오래된 상태일 가능성이 높습니다. 캐시나 아티팩트에서 로컬 작업 사본으로 가져온 파일에만 의존해야 합니다. 이전 파이프라인의 캐시·아티팩트 파일이 여전히 남아 있을 수 있다는 점에 유의합니다.

none과 달리 empty Git 전략은 캐시나 아티팩트 파일을 다운로드하기 전에 전용 빌드 디렉터리를 삭제한 뒤 다시 생성합니다. 이 전략을 사용해도 추가적인 동작 커스터마이징을 위해 GitLab Runner 후크 스크립트는(있는 경우) 계속 실행됩니다. 다음과 같은 경우 empty Git 전략을 사용합니다.

  • 리포지터리 데이터가 존재할 필요가 없는 경우
  • 작업이 실행될 때마다 깨끗하고 통제되거나 커스터마이징된 시작 상태를 원하는 경우

Git 서브모듈 전략#

GIT_SUBMODULE_STRATEGY 변수는 빌드 전 코드를 가져올 때 Git 서브모듈을 포함할지, 어떻게 포함할지를 제어하는 데 사용됩니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

가능한 값은 none, normal, recursive 세 가지입니다.

  • none은 프로젝트 코드를 가져올 때 서브모듈을 포함하지 않는다는 의미입니다. 이 설정은 1.10 이전 버전의 기본 동작과 동일합니다.

  • normal은 최상위 서브모듈만 포함한다는 의미입니다. 다음과 동일합니다.

    git submodule sync
    git submodule update --init
    
  • recursive는 (서브모듈의 서브모듈을 포함해) 모든 서브모듈을 포함한다는 의미입니다. 이 기능에는 Git v1.8.1 이상이 필요합니다. Docker 기반이 아닌 executor를 사용하는 GitLab Runner에서는 Git 버전이 이 요구 사항을 충족하는지 확인합니다. 다음과 동일합니다.

    git submodule sync --recursive
    git submodule update --init --recursive
    

이 기능이 올바르게 동작하려면 서브모듈이 (.gitmodules에서) 다음 중 하나로 구성되어 있어야 합니다.

  • 공개적으로 접근 가능한 리포지터리의 HTTP(S) URL, 또는
  • 동일한 GitLab 서버에 있는 다른 리포지터리에 대한 상대 경로. 자세한 내용은 Git 서브모듈 문서를 참고합니다.

고급 동작을 제어하는 추가 플래그는 GIT_SUBMODULE_UPDATE_FLAGS를 사용해 지정할 수 있습니다.

Git 체크아웃#

GIT_CHECKOUT 변수는 GIT_STRATEGY가 clone 또는 fetch로 설정되었을 때 git checkout 실행 여부를 지정하는 데 사용할 수 있습니다. 지정하지 않으면 기본값은 true 입니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

false로 설정하면 러너는 다음과 같이 동작합니다.

  • fetch를 수행할 때 - 리포지터리를 업데이트하고 작업 사본을 현재 리비전에 그대로 둡니다.
  • clone을 수행할 때 - 리포지터리를 클론하고 작업 사본을 기본 브랜치에 그대로 둡니다.

GIT_CHECKOUT 이 true로 설정되면 clone과 fetch는 동일하게 동작합니다. 러너는 CI 파이프라인과 관련된 리비전의 작업 사본을 체크아웃합니다.

variables:
  GIT_STRATEGY: clone
  GIT_CHECKOUT: "false"
script:
  - git checkout -B master origin/master
  - git merge $CI_COMMIT_SHA

Git clean 플래그#

GIT_CLEAN_FLAGS 변수는 소스를 체크아웃한 뒤 git clean의 기본 동작을 제어하는 데 사용됩니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

GIT_CLEAN_FLAGS는 git clean 명령의 모든 옵션을 허용합니다.

GIT_CHECKOUT: "false"가 지정되면 git clean은 비활성화됩니다.

GIT_CLEAN_FLAGS가 다음과 같으면:

  • 지정되지 않은 경우, git clean 플래그는 기본값 -ffdx를 사용합니다.
  • 값이 none 인 경우, git clean을 실행하지 않습니다.

예를 들면 다음과 같습니다.

variables:
  GIT_CLEAN_FLAGS: -ffdx -e cache/
script:
  - ls -al cache/

Git fetch 추가 플래그#

GIT_FETCH_EXTRA_FLAGS 변수를 사용해 git fetch의 동작을 제어합니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

GIT_FETCH_EXTRA_FLAGS는 git fetch 명령의 모든 옵션을 허용합니다. 다만 GIT_FETCH_EXTRA_FLAGS 플래그는 수정할 수 없는 기본 플래그 뒤에 추가됩니다.

기본 플래그는 다음과 같습니다.

GIT_FETCH_EXTRA_FLAGS가 다음과 같으면:

  • 지정되지 않은 경우, git fetch 플래그는 기본 플래그와 함께 --prune --quiet를 기본값으로 사용합니다.
  • 값이 none 인 경우, git fetch는 기본 플래그로만 실행됩니다.

예를 들어 기본 플래그는 --prune --quiet 이므로, 이를 --prune 만으로 재정의하면 git fetch 출력을 더 자세하게 만들 수 있습니다.

variables:
  GIT_FETCH_EXTRA_FLAGS: --prune
script:
  - ls -al cache/

위 설정을 적용하면 git fetch는 다음과 같이 호출됩니다.

git fetch origin $REFSPECS --depth 20  --prune

여기서 $REFSPECS는 GitLab 이 내부적으로 러너에 제공하는 값입니다.

Git clone 추가 플래그#

GIT_CLONE_EXTRA_FLAGS 변수를 사용해 네이티브 git clone 작업에 추가 인자를 전달합니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

GIT_CLONE_EXTRA_FLAGS를 사용하려면 다음과 같이 합니다.

  • FF_USE_GIT_NATIVE_CLONE을 true로 설정해 네이티브 git clone 기능을 활성화합니다.
  • fetch 대신 clone 전략을 사용하도록 GIT_STRATEGY를 clone으로 설정합니다.
  • Git 클라이언트는 2.49 버전 이상이어야 합니다. 이 조건은 헬퍼 이미지가 18.1 버전 이상의 Linux 계열 이미지이면 자동으로 충족됩니다.

GIT_CLONE_EXTRA_FLAGS는 git clone 명령의 모든 옵션을 허용합니다. 이 플래그는 대체 리포지터리 참조나 클론 성능 최적화 등 고급 사용 사례에서 유연성을 제공하도록 네이티브 git clone 명령 뒤에 추가됩니다.

예를 들어 참조 리포지터리를 사용해 클론 성능을 최적화할 수 있습니다.

variables:
  FF_USE_GIT_NATIVE_CLONE: true
  GIT_STRATEGY: clone
  GIT_CLONE_EXTRA_FLAGS: "--reference-if-available /tmp/test"

GIT_CLONE_EXTRA_FLAGS가 지정되지 않으면 git clone은 기본 플래그만 사용합니다.

CI 작업에서 특정 서브모듈 동기화 또는 제외#

GIT_SUBMODULE_PATHS 변수를 사용해 어떤 서브모듈을 동기화하거나 업데이트할지 제어합니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

경로 구문은 git submodule과 동일합니다.

  • 특정 경로를 동기화하고 업데이트하려면:

    variables:
       GIT_SUBMODULE_PATHS: submoduleA submoduleB
    
  • 특정 경로를 제외하려면:

    variables:
       GIT_SUBMODULE_PATHS: ":(exclude)submoduleA :(exclude)submoduleB"
    
Warning

Git은 중첩된 경로를 무시합니다. 중첩된 서브모듈을 무시하려면 상위 서브모듈을 제외한 뒤 작업 스크립트에서 수동으로 클론합니다. 예를 들면 git clone <repo> --recurse-submodules=':(exclude)nested-submodule'와 같습니다. YAML 이 올바르게 파싱되도록 문자열을 작은따옴표로 감싸야 합니다.

Git 서브모듈 업데이트 플래그#

GIT_SUBMODULE_STRATEGY가 normal 또는 recursive로 설정된 경우 GIT_SUBMODULE_UPDATE_FLAGS 변수를 사용해 git submodule update의 동작을 제어합니다. 이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

GIT_SUBMODULE_UPDATE_FLAGS는 git submodule update 하위 명령의 모든 옵션을 허용합니다. 다만 GIT_SUBMODULE_UPDATE_FLAGS 플래그는 몇 가지 기본 플래그 뒤에 추가됩니다.

Git은 인자 목록에서 마지막으로 나온 플래그를 우선 적용하므로, GIT_SUBMODULE_UPDATE_FLAGS에 직접 지정하면 이 기본 플래그를 재정의합니다.

예를 들어 이 변수를 사용해 다음과 같이 할 수 있습니다.

  • --remote 플래그를 사용해 리포지터리에서 추적 중인 커밋(기본값) 대신 최신 원격 HEAD를 가져와 모든 서브모듈을 자동으로 업데이트합니다.
  • --jobs 4 플래그로 여러 작업을 병렬로 실행해 서브모듈을 가져오는 속도를 높입니다.
variables:
  GIT_SUBMODULE_STRATEGY: recursive
  GIT_SUBMODULE_UPDATE_FLAGS: --remote --jobs 4
script:
  - ls -al .git/modules/

위 설정을 적용하면 git submodule update는 다음과 같이 호출됩니다.

git submodule update --init --depth 20 --recursive --remote --jobs 4
Warning

--remote 플래그를 사용할 때는 빌드의 보안, 안정성, 재현성에 미치는 영향을 알고 있어야 합니다. 대부분의 경우 설계된 대로 서브모듈 커밋을 명시적으로 추적하고, 자동 교정/의존성 봇을 사용해 업데이트하는 편이 더 낫습니다.

서브모듈을 커밋된 리비전으로 체크아웃하는 데 --remote 플래그가 필요한 것은 아닙니다. 이 플래그는 서브모듈을 최신 원격 버전으로 자동 업데이트하려는 경우에만 사용합니다.

--remote의 동작은 Git 버전에 따라 다릅니다. 상위 프로젝트의 .gitmodules 파일에 지정된 브랜치가 서브모듈 리포지터리의 기본 브랜치와 다르면, 일부 Git 버전에서는 다음 오류로 실패합니다.

fatal: Unable to find refs/remotes/origin/<branch> revision in submodule path '<submodule-path>'

러너는 서브모듈 업데이트가 실패하면 원격 참조를 가져오려고 시도하는 "최선의 노력(best effort)" 폴백을 구현합니다.

이 폴백이 사용 중인 Git 버전에서 동작하지 않으면 다음 우회 방법 중 하나를 시도합니다.

  • 서브모듈 리포지터리의 기본 브랜치를 상위 프로젝트의 .gitmodules에 설정된 브랜치와 일치하도록 업데이트합니다.
  • GIT_SUBMODULE_DEPTH를 0으로 설정합니다.
  • 서브모듈을 별도로 업데이트하고 GIT_SUBMODULE_UPDATE_FLAGS에서 --remote 플래그를 제거합니다.

서브모듈 URL을 HTTPS로 재작성#

GIT_SUBMODULE_FORCE_HTTPS 변수를 사용해 모든 Git·SSH 서브모듈 URL을 강제로 HTTPS로 재작성합니다. Git 또는 SSH 프로토콜로 구성되어 있더라도, 동일한 GitLab 인스턴스에서 절대 URL을 사용하는 서브모듈을 클론할 수 있습니다.

variables:
  GIT_SUBMODULE_STRATEGY: recursive
  GIT_SUBMODULE_FORCE_HTTPS: "true"

이 설정을 활성화하면 GitLab Runner는 CI/CD 작업 토큰을 사용해 서브모듈을 클론합니다. 이 토큰은 작업을 실행하는 사용자의 권한을 사용하며 SSH 자격 증명이 필요하지 않습니다.

얕은 클로닝#

GIT_DEPTH를 사용해 가져오기와 클론의 깊이를 지정할 수 있습니다. GIT_DEPTH는 리포지터리를 얕은 클론으로 처리해 클론 속도를 크게 높일 수 있습니다. 커밋 수가 많거나 오래된 대용량 바이너리가 있는 리포지터리에서 유용할 수 있습니다. 이 값은 git fetch와 git clone에 전달됩니다.

새로 생성된 프로젝트는 자동으로 기본 git depth 값 20을 갖습니다.

깊이를 1로 사용하면서 작업 대기열이 있거나 작업을 재시도하면 작업이 실패할 수 있습니다.

Git 가져오기와 클론은 브랜치 이름 같은 참조(ref)를 기준으로 하므로, 러너는 특정 커밋 SHA를 클론할 수 없습니다. 여러 작업이 대기열에 있거나 오래된 작업을 재시도하는 경우, 테스트할 커밋이 클론된 Git 히스토리에 있어야 합니다. GIT_DEPTH 값을 너무 작게 설정하면 이런 오래된 커밋을 실행할 수 없게 되어 작업 로그에 unresolved reference가 표시됩니다. 이 경우 GIT_DEPTH를 더 큰 값으로 변경하는 것을 다시 고려해야 합니다.

GIT_DEPTH가 설정되면 Git 히스토리의 일부만 존재하므로 git describe에 의존하는 작업은 올바르게 동작하지 않을 수 있습니다.

마지막 커밋 3개만 가져오거나 클론하려면 다음과 같이 합니다.

variables:
  GIT_DEPTH: "3"

이 변수는 variables 섹션에서 전역으로 또는 작업 단위로 설정할 수 있습니다.

Git 서브모듈 깊이#

GIT_SUBMODULE_STRATEGY가 normal 또는 recursive로 설정된 경우 GIT_SUBMODULE_DEPTH 변수를 사용해 서브모듈을 가져오고 클론하는 깊이를 지정합니다. 이 변수는 variables 섹션에서 전역으로 또는 특정 작업 단위로 설정할 수 있습니다.

GIT_SUBMODULE_DEPTH 변수를 설정하면 서브모듈에 한해서만 GIT_DEPTH 설정을 덮어씁니다.

마지막 커밋 3개만 가져오거나 클론하려면 다음과 같이 합니다.

variables:
  GIT_SUBMODULE_DEPTH: 3

사용자 지정 빌드 디렉터리#

기본적으로 GitLab Runner는 $CI_BUILDS_DIR 디렉터리의 고유한 하위 경로에 리포지터리를 클론합니다. 다만 프로젝트에 따라 코드가 특정 디렉터리에 있어야 할 수도 있습니다(예: Go 프로젝트). 이 경우 GIT_CLONE_PATH 변수를 지정해 러너에게 리포지터리를 클론할 디렉터리를 알려줄 수 있습니다.

variables:
  GIT_CLONE_PATH: $CI_BUILDS_DIR/project-name

test:
  script:
    - pwd

GIT_CLONE_PATH는 항상 $CI_BUILDS_DIR 내부에 있어야 합니다. $CI_BUILDS_DIR에 설정되는 디렉터리는 executor와 runners.builds_dir 설정 구성에 따라 달라집니다.

이 기능은 러너 구성에서 custom_build_dir 이 활성화된 경우에만 사용할 수 있습니다.

동시성 처리#

동시성을 1보다 크게 사용하는 executor는 실패로 이어질 수 있습니다. 작업 간에 builds_dir가 공유되면 여러 작업이 동일한 디렉터리에서 작업할 수 있습니다.

러너는 이런 상황을 방지하려 하지 않습니다. 러너 구성의 요구 사항을 준수하는 것은 관리자와 개발자의 몫입니다.

이런 상황을 피하려면 $CI_BUILDS_DIR에 고유한 경로를 사용할 수 있습니다. 러너는 동시성의 고유 ID를 제공하는 추가 변수 두 개를 노출하기 때문입니다.

  • $CI_CONCURRENT_ID: 지정된 executor에서 실행되는 모든 작업의 고유 ID
  • $CI_CONCURRENT_PROJECT_ID: 지정된 executor와 프로젝트에서 실행되는 모든 작업의 고유 ID

어떤 시나리오와 executor에서도 잘 동작하는 가장 안정적인 구성은 GIT_CLONE_PATH에 $CI_CONCURRENT_ID를 사용하는 것입니다. 예를 들면 다음과 같습니다.

variables:
  GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/project-name

test:
  script:
    - pwd -P

$CI_CONCURRENT_PROJECT_ID는 $CI_PROJECT_PATH와 함께 사용해야 합니다. $CI_PROJECT_PATH는 group/subgroup/project 형식으로 리포지터리 경로를 제공합니다. 예를 들면 다음과 같습니다.

variables:
  GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH

test:
  script:
    - pwd -P

중첩 경로#

GIT_CLONE_PATH 값은 한 번만 확장됩니다. 이 값 안에 변수를 중첩할 수 없습니다.

예를 들어 .gitlab-ci.yml 파일에 다음 변수를 정의했다고 가정합니다.

variables:
  GOPATH: $CI_BUILDS_DIR/go
  GIT_CLONE_PATH: $GOPATH/src/namespace/project

GIT_CLONE_PATH 값은 한 번만 확장되어 $CI_BUILDS_DIR/go/src/namespace/project가 되며, $CI_BUILDS_DIR가 확장되지 않으므로 실패합니다.

after_script에서 오류 무시#

작업에서 after_script를 사용해 작업의 before_script와 script 섹션 이후에 실행할 명령 배열을 정의할 수 있습니다. after_script 명령은 스크립트 종료 상태(실패 또는 성공)와 관계없이 실행됩니다.

기본적으로 GitLab Runner는 after_script 실행 중 발생하는 오류를 무시합니다. after_script 실행 중 오류가 발생하면 작업이 즉시 실패하도록 설정하려면 AFTER_SCRIPT_IGNORE_ERRORS CI/CD 변수를 false로 설정합니다. 예를 들면 다음과 같습니다.

variables:
  AFTER_SCRIPT_IGNORE_ERRORS: false

작업 단계 재시도 횟수#

실행 중인 job이 다음 단계를 실행하는 시도 횟수를 설정할 수 있습니다:

변수 설명
ARTIFACT_DOWNLOAD_ATTEMPTS job 실행 중 아티팩트를 다운로드하는 시도 횟수입니다.
EXECUTOR_JOB_SECTION_ATTEMPTS job에서 No Such Container 오류가 발생한 후 섹션을 실행하는 시도 횟수입니다(Docker executor 전용).
GET_SOURCES_ATTEMPTS job 실행 중 소스를 가져오는 시도 횟수입니다.
RESTORE_CACHE_ATTEMPTS job 실행 중 캐시를 복원하는 시도 횟수입니다.

기본값은 단일 시도입니다.

예시:

variables:
  GET_SOURCES_ATTEMPTS: 3

variables 섹션에서 전역으로 설정하거나 job 단위로 설정할 수 있습니다.

GitLab.com 인스턴스 러너에서 사용할 수 없는 시스템 호출#

GitLab.com 인스턴스 러너는 CoreOS에서 실행됩니다. 따라서 C 표준 라이브러리의 getlogin과 같은 일부 시스템 호출을 사용할 수 없습니다.

아티팩트 및 캐시 설정#

아티팩트 및 캐시 설정은 아티팩트와 캐시의 압축률을 제어합니다. 이 설정을 사용해 job이 생성하는 아카이브의 크기를 지정합니다.

  • 네트워크 속도가 느리면 아카이브 크기가 작을수록 업로드가 더 빠를 수 있습니다.
  • 대역폭과 저장 공간이 문제되지 않는 빠른 네트워크에서는 생성되는 아카이브가 더 크더라도 가장 빠른 압축률을 사용하는 편이 업로드가 더 빠를 수 있습니다.

GitLab Pages가 HTTP Range 요청을 처리하려면, 아티팩트는 ARTIFACT_COMPRESSION_LEVEL: fastest 설정을 사용해야 합니다. 압축하지 않은 zip 아카이브만 이 기능을 지원하기 때문입니다.

업로드와 다운로드의 전송 속도를 표시하는 미터를 활성화할 수 있습니다.

CACHE_REQUEST_TIMEOUT 설정으로 캐시 업로드와 다운로드의 최대 시간을 설정할 수 있습니다. 캐시 업로드가 느려 job 소요 시간이 크게 늘어나는 경우 이 설정을 사용합니다.

variables:
  # output upload and download progress every 2 seconds
  TRANSFER_METER_FREQUENCY: "2s"

  # Use fast compression for artifacts, resulting in larger archives
  ARTIFACT_COMPRESSION_LEVEL: "fast"

  # Use no compression for caches
  CACHE_COMPRESSION_LEVEL: "fastest"

  # Set maximum duration of cache upload and download
  CACHE_REQUEST_TIMEOUT: 5
변수 설명
TRANSFER_METER_FREQUENCY 미터의 전송 속도를 출력하는 주기를 지정합니다. 기간 값(예: 1s 또는 1m30s)으로 설정할 수 있습니다. 0으로 설정하면 미터가 비활성화됩니다(기본값). 값을 설정하면 파이프라인이 아티팩트 및 캐시 업로드·다운로드에 대한 진행률 미터를 표시합니다.
ARTIFACT_COMPRESSION_LEVEL 압축률을 조정하려면 fastest, fast, default, slow, slowest 중 하나로 설정합니다. 이 설정은 Fastzip 아카이버에서만 동작하므로 GitLab Runner 기능 플래그 FF_USE_FASTZIP도 함께 활성화해야 합니다.
CACHE_COMPRESSION_LEVEL 압축률을 조정하려면 fastest, fast, default, slow, slowest 중 하나로 설정합니다. 이 설정은 Fastzip 아카이버에서만 동작하므로 GitLab Runner 기능 플래그 FF_USE_FASTZIP도 함께 활성화해야 합니다.
CACHE_REQUEST_TIMEOUT 단일 job에 대한 캐시 업로드·다운로드 작업의 최대 시간을(분 단위로) 설정합니다. 기본값은 10분입니다.

지연 시간이 긴 연결을 위한 TCP 설정 튜닝#

러너와 GitLab 인스턴스 사이에 네트워크 지연이 크게 발생하는 경우, 기본 TCP 윈도 크기가 처리량을 제한할 수 있습니다. 러너 호스트에서 TCP 윈도 크기를 늘려 더 많은 데이터를 전송 중 상태로 둘 수 있게 합니다.

예를 들어 Linux에서는 다음과 같이 최대 TCP 버퍼 크기를 늘립니다:

sudo sysctl -w net.core.rmem_max=16777216
sudo sysctl -w net.core.wmem_max=16777216
sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"

재부팅 후에도 이 변경 사항을 유지하려면 /etc/sysctl.conf에 추가합니다.

Note

TCP 튜닝은 러너 머신의 모든 네트워크 연결에 영향을 주는 호스트 수준 변경 사항입니다. 프로덕션이 아닌 환경에서 먼저 변경 사항을 테스트합니다.

아티팩트 출처 메타데이터#

러너는 SLSA Provenance를 생성하고 모든 빌드 아티팩트에 출처(provenance)를 결합하는 SLSA Statement를 만들 수 있습니다. 이 statement를 아티팩트 출처 메타데이터라고 합니다.

아티팩트 출처 메타데이터를 활성화하려면 RUNNER_GENERATE_ARTIFACTS_METADATA 환경 변수를 true로 설정합니다. 이 변수는 전역으로 설정하거나 개별 job에 대해 설정할 수 있습니다:

variables:
  RUNNER_GENERATE_ARTIFACTS_METADATA: "true"

job1:
  variables:
    RUNNER_GENERATE_ARTIFACTS_METADATA: "true"

메타데이터는 아티팩트와 함께 저장되는 일반 텍스트 .json 파일로 표현됩니다. 파일 이름은 {ARTIFACT_NAME}-metadata.json 입니다. ARTIFACT_NAME은 .gitlab-ci.yml 파일에 정의된 아티팩트 이름 입니다. 이름이 정의되지 않은 경우 기본 파일 이름은 artifacts-metadata.json 입니다.

출처 메타데이터 형식#

아티팩트 출처 메타데이터는 in-toto v0.1 Statement 형식으로 생성됩니다. 여기에는 SLSA 1.0 Provenance 형식으로 생성된 provenance predicate가 포함됩니다.

다음 필드는 기본으로 채워집니다:

필드 값
_type https://in-toto.io/Statement/v0.1
subject 메타데이터가 적용되는 소프트웨어 아티팩트 집합입니다.
subject[].name 아티팩트의 파일 이름입니다.
subject[].sha256 아티팩트의 sha256 체크섬입니다.
predicateType https://slsa.dev/provenance/v1
predicate.buildDefinition.buildType https://gitlab.com/gitlab-org/gitlab-runner/-/blob/{GITLAB_RUNNER_VERSION}/PROVENANCE.md. 예를 들어 v19.0.0
predicate.runDetails.builder.id 러너 세부 정보 페이지를 가리키는 URI입니다. 예: https://gitlab.com/gitlab-com/www-gitlab-com/-/runners/3785264.
predicate.buildDefinition.externalParameters 빌드 명령 실행 중 사용 가능한 CI/CD 또는 환경 변수의 이름입니다. 시크릿을 보호하기 위해 값은 항상 빈 문자열로 표시됩니다.
predicate.buildDefinition.externalParameters.source 프로젝트의 URL입니다.
predicate.buildDefinition.externalParameters.entryPoint 빌드를 트리거한 CI/CD job의 이름입니다.
predicate.buildDefinition.internalParameters.name 러너의 이름입니다.
predicate.buildDefinition.internalParameters.executor 러너 실행기(executor)입니다.
predicate.buildDefinition.internalParameters.architecture CI/CD job이 실행되는 아키텍처입니다.
predicate.buildDefinition.internalParameters.job 빌드를 트리거한 CI/CD job의 ID입니다.
predicate.buildDefinition.resolvedDependencies[0].uri 프로젝트의 URL입니다.
predicate.buildDefinition.resolvedDependencies[0].digest.sha256 프로젝트의 커밋 리비전입니다.
predicate.runDetails.metadata.invocationId 빌드를 트리거한 CI/CD job의 ID입니다.
predicate.runDetails.metadata.startedOn 빌드가 시작된 시간입니다. 이 필드는 RFC3339 형식입니다.
predicate.runDetails.metadata.finishedOn 빌드가 종료된 시간입니다. 메타데이터 생성이 빌드 중에 이루어지므로 이 시간은 GitLab에 보고되는 시간보다 약간 이릅니다. 이 필드는 RFC3339 형식입니다.

provenance statement는 다음 예시와 유사한 형태입니다:

{
 "_type": "https://in-toto.io/Statement/v0.1",
 "predicateType": "https://slsa.dev/provenance/v1",
 "subject": [
  {
   "name": "x.txt",
   "digest": {
    "sha256": "ac097997b6ec7de591d4f11315e4aa112e515bb5d3c52160d0c571298196ea8b"
   }
  },
  {
   "name": "y.txt",
   "digest": {
    "sha256": "9eb634f80da849d828fcf42740d823568c49e8d7b532886134f9086246b1fdf3"
   }
  }
 ],
 "predicate": {
  "buildDefinition": {
   "buildType": "https://gitlab.com/gitlab-org/gitlab-runner/-/blob/2147fb44/PROVENANCE.md",
   "externalParameters": {
    "CI": "",
    "CI_API_GRAPHQL_URL": "",
    "CI_API_V4_URL": "",
    "CI_COMMIT_AUTHOR": "",
    "CI_COMMIT_BEFORE_SHA": "",
    "CI_COMMIT_BRANCH": "",
    "CI_COMMIT_DESCRIPTION": "",
    "CI_COMMIT_MESSAGE": "",
    [... additional environmental variables ...]
    "entryPoint": "build-job",
    "source": "https://gitlab.com/my-group/my-project/test-runner-generated-slsa-statement"
   },
   "internalParameters": {
    "architecture": "amd64",
    "executor": "docker+machine",
    "job": "10340684631",
    "name": "green-4.saas-linux-small-amd64.runners-manager.gitlab.com/default"
   },
   "resolvedDependencies": [
    {
     "uri": "https://gitlab.com/my-group/my-project/test-runner-generated-slsa-statement",
     "digest": {
      "sha256": "bdd2ecda9ef57b129c88617a0215afc9fb223521"
     }
    }
   ]
  },
  "runDetails": {
   "builder": {
    "id": "https://gitlab.com/my-group/my-project/test-runner-generated-slsa-statement/-/runners/12270857",
    "version": {
     "gitlab-runner": "2147fb44"
    }
   },
   "metadata": {
    "invocationId": "10340684631",
    "startedOn": "2025-06-13T07:25:13Z",
    "finishedOn": "2025-06-13T07:25:40Z"
   }
  }
 }
}

스테이징 디렉터리#

시스템의 기본 임시 디렉터리에 캐시와 아티팩트를 아카이브하고 싶지 않다면 다른 디렉터리를 지정할 수 있습니다.

시스템의 기본 임시 경로에 제약이 있는 경우 디렉터리를 변경해야 할 수 있습니다. 해당 디렉터리 위치에 빠른 디스크를 사용하면 성능도 향상될 수 있습니다.

디렉터리를 변경하려면 CI job에서 변수로 ARCHIVER_STAGING_DIR을 설정하거나, 러너를 등록할 때 러너 변수를 사용합니다(gitlab register --env ARCHIVER_STAGING_DIR=<dir>).

지정한 디렉터리는 압축 해제 전에 아티팩트를 다운로드하는 위치로 사용됩니다. fastzip 아카이버를 사용하는 경우 이 위치는 아카이브 생성 시 스크래치 공간으로도 사용됩니다.

성능 향상을 위한 fastzip 구성#

fastzip을 튜닝하려면 FF_USE_FASTZIP 플래그가 활성화되어 있는지 확인합니다. 그런 다음 다음 환경 변수 중 원하는 것을 사용합니다.

변수 설명
FASTZIP_ARCHIVER_CONCURRENCY 동시에 압축할 파일 수입니다. 기본값은 사용 가능한 CPU 개수입니다.
FASTZIP_ARCHIVER_BUFFER_SIZE 파일마다 동시성 단위로 할당되는 버퍼 크기입니다. 이 크기를 초과하는 데이터는 스크래치 공간으로 이동합니다. 기본값은 2 MiB입니다.
FASTZIP_EXTRACTOR_CONCURRENCY 동시에 압축 해제할 파일 수입니다. 기본값은 사용 가능한 CPU 개수입니다.

zip 아카이브 안의 파일은 순차적으로 추가됩니다. 이 때문에 동시 압축이 어렵습니다. fastzip은 먼저 파일을 디스크에 동시에 압축한 다음, 그 결과를 zip 아카이브로 순차적으로 복사하는 방식으로 이 제약을 해결합니다.

작은 파일에 대해 디스크에 쓰고 다시 읽는 과정을 피하기 위해 동시성 단위로 작은 버퍼를 사용합니다. 이 설정은 FASTZIP_ARCHIVER_BUFFER_SIZE로 제어할 수 있습니다. 이 버퍼의 기본 크기는 2 MiB이므로 동시성 16이면 32 MiB가 할당됩니다. 버퍼 크기를 초과하는 데이터는 디스크에 쓰고 다시 읽어옵니다. 따라서 버퍼를 사용하지 않는 FASTZIP_ARCHIVER_BUFFER_SIZE: 0 설정으로 스크래치 공간만 사용하는 것도 유효한 선택지입니다.

FASTZIP_ARCHIVER_CONCURRENCY는 동시에 압축할 파일 수를 제어합니다. 앞서 설명한 대로 이 설정은 사용되는 메모리 양을 늘릴 수 있습니다. 또한 스크래치 공간에 기록되는 임시 데이터도 늘어날 수 있습니다. 기본값은 사용 가능한 CPU 개수이지만, 메모리에 미치는 영향을 고려하면 항상 최선의 설정은 아닐 수 있습니다.

FASTZIP_EXTRACTOR_CONCURRENCY는 한 번에 압축 해제할 파일 수를 제어합니다. zip 아카이브의 파일은 기본적으로 동시에 읽을 수 있으므로 추출기에 필요한 것 외에 추가 메모리가 할당되지 않습니다. 이 값의 기본값은 사용 가능한 CPU 개수입니다.