사용자 지정 실행기

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-Managed형

GitLab Runner은 기본적으로 지원하지 않는 환경을 위해 사용자 지정 실행기를 제공합니다. 예를 들어, LXD 또는 Libvirt를 사용하는 경우입니다.

이를 통해 환경을 프로비저닝, 실행 및 정리하는 데 사용할 실행 파일을 구성하여 자체 실행기를 만들 수 있습니다.

사용자 정의 실행기에 구성하는 스크립트는 드라이버라고 불립니다. 예를 들어 LXD 드라이버Libvirt 드라이버를 만들 수 있습니다.

제한 사항

사용자 지정 실행기를 사용할 때 다음은 현재의 일부 제한 사항입니다:

구성

선택할 수 있는 몇 가지 구성 키가 있습니다. 일부는 선택 사항입니다.

다음은 모든 가능한 구성 키를 사용하여 사용자 지정 실행기를 위한 구성 예시입니다:

[[runners]]
  name = "custom"
  url = "https://gitlab.com"
  token = "TOKEN"
  executor = "custom"
  builds_dir = "/builds"
  cache_dir = "/cache"
  [runners.custom]
    config_exec = "/path/to/config.sh"
    config_args = [ "SomeArg" ]
    config_exec_timeout = 200
    
    prepare_exec = "/path/to/script.sh"
    prepare_args = [ "SomeArg" ]
    prepare_exec_timeout = 200
    
    run_exec = "/path/to/binary"
    run_args = [ "SomeArg" ]
    
    cleanup_exec = "/path/to/executable"
    cleanup_args = [ "SomeArg" ]
    cleanup_exec_timeout = 200
    
    graceful_kill_timeout = 200
    force_kill_timeout = 200

필드 정의 및 필수 필드에 대해서는 [runners.custom] 섹션을 참조하세요.

또한, [[runners]] 내부의 builds_dircache_dir은 필수 필드입니다.

작업 실행에 필요한 전제 소프트웨어

사용자는 다음과 같은 환경을 설정해야 합니다. 이러한 환경은 PATH에 있어야 합니다:

단계

사용자 지정 실행기는 작업의 세부 정보를 구성하고, 환경을 준비하고 정리하며 작업 스크립트를 실행하기 위한 단계를 제공합니다. 각 단계는 특정 작업을 담당하며 고려해야 할 사항이 다릅니다.

사용자 지정 실행기에 의해 실행되는 각 단계는 내장된 GitLab Runner 실행기가 그들을 실행하는 시간에 실행됩니다.

실행될 각 단계에 대해 해당 실행 파일에서 사용할 수 있는 특정 환경 변수가 노출됩니다. 이러한 모든 단계에 대해 다음과 같은 환경 변수가 제공됩니다.

CI/CD 환경 변수와 사전 정의 변수는 시스템 환경 변수와의 충돌을 방지하기 위해 CUSTOM_ENV_로 접두어가 붙습니다. 예를 들어 CI_BUILDS_DIRCUSTOM_ENV_CI_BUILDS_DIR로 사용할 수 있습니다.

단계는 다음 순서로 실행됩니다:

  1. config_exec
  2. prepare_exec
  3. run_exec
  4. cleanup_exec

서비스

서비스CUSTOM_ENV_CI_JOB_SERVICES로 JSON 배열 형식으로 노출됩니다.

예시:

custom:
  script:
    - echo $CUSTOM_ENV_CI_JOB_SERVICES
  services:
    - redis:latest
    - name: my-postgres:9.4
      alias: pg
      entrypoint: ["path", "to", "entrypoint"]
      command: ["path", "to", "cmd"]

위의 예시는 CUSTOM_ENV_CI_JOB_SERVICES 환경 변수에 다음과 같은 값을 설정합니다:

[{"name":"redis:latest","alias":"","entrypoint":null,"command":null},{"name":"my-postgres:9.4","alias":"pg","entrypoint":["path","to","entrypoint"],"command":["path","to","cmd"]}]

구성

구성 단계는 config_exec에 의해 실행됩니다.

가끔 실행 중에 일부 설정을 지정해야 할 수 있습니다. 예를 들어 프로젝트 ID에 따라 빌드 디렉터리를 설정하는 경우입니다. config_exec는 STDOUT에서 읽고 특정 키를 포함한 유효한 JSON 문자열을 예상합니다.

예를 들어:

#!/usr/bin/env bash

cat << EOS
{
  "builds_dir": "/builds/${CUSTOM_ENV_CI_CONCURRENT_PROJECT_ID}/${CUSTOM_ENV_CI_PROJECT_PATH_SLUG}",
  "cache_dir": "/cache/${CUSTOM_ENV_CI_CONCURRENT_PROJECT_ID}/${CUSTOM_ENV_CI_PROJECT_PATH_SLUG}",
  "builds_dir_is_shared": true,
  "hostname": "custom-hostname",
  "driver": {
    "name": "test driver",
    "version": "v0.0.1"
  },
  "job_env" : {
    "CUSTOM_ENVIRONMENT": "example"
  }
}
EOS

JSON 문자열 내 추가 키는 무시됩니다. 유효한 JSON 문자열이 아닌 경우, 해당 단계가 실패하고 두 번 더 재시도됩니다.

매개변수 유형 필수 허용 여부 설명
builds_dir 문자열 작업의 작업 디렉터리가 만들어질 기본 디렉터리입니다.
cache_dir 문자열 로컬 캐시가 저장될 기본 디렉터리입니다.
builds_dir_is_shared 불린 n/a 환경이 동시 작업 사이에서 공유되는지 여부를 정의합니다.
hostname 문자열 실행기가 저장하는 작업의 “메타 데이터”에 연결할 호스트 이름입니다. 정의되지 않은 경우, 호스트 이름이 설정되지 않습니다.
driver.name 문자열 드라이버에 대한 사용자 정의 이름입니다. Using custom executor... 행에 인쇄됩니다. 정의되지 않은 경우 드라이버에 대한 정보가 인쇄되지 않습니다.
driver.version 문자열 드라이버에 대한 사용자 정의 버전입니다. Using custom executor... 행에 인쇄됩니다. 정의되지 않은 경우 이름 정보만 인쇄됩니다.
job_env 객체 작업 실행의 모든 후속 단계에서 환경 변수를 통해 사용할 수 있는 이름-값 쌍입니다. 이는 작업이 아닌 드라이버에 대해 사용 가능합니다. 자세한 내용은 job_env 사용을 참조하세요.

실행 파일의 STDERR는 작업 로그로 출력됩니다.

사용자는 config_exec_timeout 를 설정하여 GitLab Runner가 프로세스를 종료하기 전에 JSON 문자열을 반환하기까지 대기해야 하는 기한을 설정할 수 있습니다.

만약 config_exec_args 중 하나라도 정의되어 있다면, 실행 파일에서 정의된 실행 파일에 순서대로 추가됩니다. 예를 들어 config.toml의 내용은 다음과 같습니다:

...
[runners.custom]
  ...
  config_exec = "/path/to/config"
  config_args = [ "Arg1", "Arg2" ]
  ...

GitLab Runner는 이를 /path/to/config Arg1 Arg2로 실행합니다.

job_env 사용법

job_env 구성의 주된 목적은 작업 실행의 후속 단계를 위해 변수를 사용자 정의 실행기 드라이버 호출의 맥락으로 전달하는 것입니다.

작업 실행 환경과의 연결이 일시적인 SSH 사용자 이름과 비밀번호를 가져오는 자격 증명을 준비해야 하며 이 작업은 매우 비용이 많이 드는 운영이 필요한 예를 들어 사용자 정의 실행기가 다음에 작업 실행 환경과 연결하기 위해 사용할 수 있습니다.

각 작업 실행 단계인 준비, 복수의 실행 호출, 정리와 같은 사용자 정의 실행기 실행 흐름을 사용하는 경우에는 맥락은 각각 다릅니다. 자격 증명 해결 예제에서 자격 증명 제공자에 연결해야 할 때마다 이것이 수행되어야 합니다.

이 작업이 비용이 많이 든다면 전체 작업 실행을 위해 한 번 수행하고 나서 자격 증명을 모든 작업 실행 단계에 재사용하고 싶을 수 있습니다. 여기서 job_env가 도움을 줄 수 있습니다. 이를 통해 config_exec 호출 중에 제공자를 한 번 연결하고 나서 job_env로 수신된 자격 증명을 전달할 수 있습니다. 이것들은 다음으로 사용자 정의 실행기 호출에 의해 prepare_exec, run_execcleanup_exec에 전달됩니다. 이를 통해 드라이버는 매번 자격 증명 제공자에 연결하는 대신 변수를 읽고 있는 자격 증명을 사용할 수 있습니다.

중요한 점은 변수가 작업 자체에 자동으로 사용 가능하지는 않다는 것입니다. 이것은 사용자 정의 실행기 드라이버가 어떻게 구현되었는지에 완전히 의존하며 많은 경우에는 여기에 존재하지 않을 것입니다.

특정 실행기에서 특정 실행기에 의해 실행되는 각 작업에 일련의 변수를 전달할 수 있도록 job_env 설정을 고려하고 있다면 [[runners]]environment 설정을 확인하세요.

변수가 동적이고 그 값이 다른 작업 간에 변경될 것으로 예상된다면 job_env에 의해 전달된 변수가 작업 실행 호출에 추가될 것이 확실하도록 사용자 정의 실행기가 구현되었는지 확인해야 합니다.

준비

준비 단계는 prepare_exec에 의해 실행됩니다.

이 시점에서 GitLab Runner는 작업에 대해 모든 것을 알고 있습니다(어디에서 실행될 것인가, 어떻게 실행될 것인가). 환경이 설정되어 작업이 실행될 수 있도록 하는 것만 남았습니다. GitLab Runner는 prepare_exec에 지정된 실행 파일을 실행할 것입니다.

이것은 환경을 설정하는 데 책임이 있습니다(예: 가상 머신이나 컨테이너, 서비스 등을 만드는 것). 이 작업이 완료된 후, 우리는 환경이 작업을 실행할 수 있는 준비가 되어 있다고 기대합니다.

이 단계는 작업 실행 중에 한 번만 실행됩니다.

사용자는 구성에서 prepare_exec_timeout을 설정하여 GitLab Runner가 프로세스를 종료하기 전에 환경을 준비하는 데 대기할 시간 제한을 설정할 수 있습니다.

이 실행 파일에서 반환된 STDOUTSTDERR은 작업 로그에 출력됩니다.

만약 정의된 prepare_exec_args 중 어느 것이라도 정의된 경우, 그것들은 prepare_exec에서 정의된 실행 파일에 순서대로 추가됩니다. 예를 들어, 아래와 같이 config.toml 콘텐츠가 있는 경우:

...
[runners.custom]
  ...
  prepare_exec = "/path/to/bin"
  prepare_args = [ "Arg1", "Arg2" ]
  ...

GitLab Runner는 /path/to/bin Arg1 Arg2와 같이 실행할 것입니다.

실행

실행 단계는 run_exec에 의해 실행됩니다.

이 실행 파일에서 반환된 STDOUTSTDERR은 작업 로그에 출력됩니다.

다른 단계와는 달리 run_exec 단계는 여러 번 실행되며, 순서대로 나열된 하위 단계로 분할됩니다.

  1. prepare_script
  2. get_sources
  3. restore_cache
  4. download_artifacts
  5. step_*
  6. build_script
  7. step_*
  8. after_script
  9. archive_cache 또는 archive_cache_on_failure
  10. upload_artifacts_on_success 또는 upload_artifacts_on_failure
  11. cleanup_file_variables
note
GitLab Runner 14.0 이상에서 build_scriptstep_script로 대체됩니다. 자세한 내용은 이 이슈를 참조하십시오.

위에서 언급된 각 단계에 대해 run_exec 실행 파일은 다음과 함께 실행될 것입니다:

  • 평소의 환경 변수.
  • 두 가지 인자:
    • 사용자 정의 실행기에서 실행해야 하는 스크립트의 경로.
    • 단계의 이름.

예를 들어:

/path/to/run_exec.sh /path/to/tmp/script1 prepare_executor
/path/to/run_exec.sh /path/to/tmp/script1 prepare_script
/path/to/run_exec.sh /path/to/tmp/script1 get_sources

정의된 run_args가 있다면, 그것들은 run_exec 실행 파일에 전달되는 첫 번째 인수의 집합으로, 그리고 GitLab Runner는 기타 인수를 추가합니다. 예를 들어, 아래와 같이 config.toml이 있다면:

...
[runners.custom]
  ...
  run_exec = "/path/to/run_exec.sh"
  run_args = [ "Arg1", "Arg2" ]
  ...

GitLab Runner는 실행 파일을 다음과 같은 인수로 실행할 것입니다:

/path/to/run_exec.sh Arg1 Arg2 /path/to/tmp/script1 prepare_executor
/path/to/run_exec.sh Arg1 Arg2 /path/to/tmp/script1 prepare_script
/path/to/run_exec.sh Arg1 Arg2 /path/to/tmp/script1 get_sources

이 실행 파일은 첫 번째 인수에 지정된 스크립트를 실행하는 책임이 있습니다. 그것들은 일반적인 GitLab Runner 실행기가 일반적으로 실행하는 모든 스크립트를 포함합니다. 이 스크립트들은 다음과 같은 쉘일 수 있습니다:

  • Bash
  • PowerShell Desktop
  • PowerShell Core
  • Batch (deprecated)

우리는 [[runners]] 내부의 shell로 구성된 쉘을 사용하여 스크립트를 생성합니다. 제공되지 않는 경우 OS 플랫폼에 대한 기본값이 사용됩니다.

아래 표는 각 스크립트가 무엇을 하는지와 해당 스크립트의 주된 목표가 무엇인지에 대해 자세히 설명한 것입니다.

스크립트 이름 스크립트 내용
prepare_script 작업이 실행 중인 기계에 대한 간단한 디버그 정보입니다.
get_sources Git 구성을 준비하고 리포지터리를 클론/페치합니다. GitLab의 모든 이점을 얻을 수 있도록 이것을 그대로 유지하는 것을 권장합니다.
restore_cache 정의된 경우 캐시를 추출합니다. 이것은 gitlab-runner 바이너리가 $PATH에서 사용 가능하다고 예상합니다.
download_artifacts 정의된 경우 아티팩트를 다운로드합니다. 이것은 gitlab-runner 바이너리가 $PATH에서 사용 가능하다고 예상합니다.
step_* GitLab에서 생성됩니다. 실행기에 전달될 수는 없을 수도 있습니다. step_releasestep_accessibility와 같이 여러 단계가 있을 수 있습니다. 이것은 .gitlab-ci.yml 파일의 기능일 수 있습니다.
build_script before_scriptscript의 조합입니다. GitLab Runner 14.0 이상에서 build_scriptstep_script로 대체됩니다. 자세한 내용은 이 이슈를 참조하십시오.
after_script 작업에서 정의된 after_script입니다. 지금까지 어떤 단계라도 실패한 경우에도 항상 호출됩니다.
archive_cache 모든 캐시의 아카이브를 작성합니다. build_script이 성공했을 때만 실행됩니다.
archive_cache_on_failure 모든 캐시의 아카이브를 작성합니다. build_script이 실패했을 때만 실행됩니다.
upload_artifacts_on_success 정의된 아티팩트를 업로드합니다. build_script이 성공했을 때만 실행됩니다.
upload_artifacts_on_failure 정의된 아티팩트를 업로드합니다. build_script이 실패했을 때만 실행됩니다.
cleanup_file_variables 디스크에서 모든 파일 기반 변수를 삭제합니다.

정리

정리 단계는 cleanup_exec에 의해 실행됩니다.

이 최종 단계는 이전 단계 중 하나라도 실패한 경우에도 실행됩니다. 이 단계의 주요 목표는 설정되었을 수 있는 모든 환경을 정리하는 것입니다. 예를 들어, VM을 끄거나 컨테이너를 삭제하는 것 등이 있을 수 있습니다.

cleanup_exec의 결과는 작업 상태에 영향을 주지 않습니다. 예를 들어, 작업은 다음과 같은 경우에도 성공적으로 표시됩니다:

  • prepare_execrun_exec 둘 다 성공하는 경우
  • cleanup_exec이 실패하는 경우

사용자는 cleanup_exec_timeout을 설정하여 GitLab Runner가 환경을 정리하기 전에 대기해야 하는 시간 제한을 설정할 수 있습니다.

이 실행 파일의 STDOUT은 DEBUG 수준의 GitLab Runner 로그에 출력됩니다. STDERR는 WARN 수준의 로그에 출력됩니다.

만약 cleanup_exec_args 중 하나라도 정의되어 있다면, 이들은 cleanup_exec에서 정의된 실행 파일에 순서대로 추가됩니다. 예를 들어, 아래는 config.toml의 내용입니다:

...
[runners.custom]
  ...
  cleanup_exec = "/path/to/bin"
  cleanup_args = [ "Arg1", "Arg2" ]
  ...

GitLab Runner는 이를 /path/to/bin Arg1 Arg2로 실행할 것입니다.

실행 파일 종료 및 중단

GitLab Runner는 다음 조건 중 하나에 해당하는 경우 실행 파일을 정상적으로 종료하려고 시도할 것입니다:

  • config_exec_timeout, prepare_exec_timeout 또는 cleanup_exec_timeout이 만족될 때
  • 작업이 시간 초과되었을 때
  • 작업이 취소되었을 때

시간 초과가 발생하면 SIGTERM 시그널이 실행 파일로 전송되며, exec_terminate_timeout의 카운트다운이 시작됩니다. 실행 파일은 이 시그널을 수신하여 모든 리소스를 정리해야 합니다. exec_terminate_timeout가 지나도 실행 파일이 여전히 실행 중이면, SIGKILL이 전송되어 프로세스가 종료되며, exec_force_kill_timeout가 시작됩니다. 만약 exec_force_kill_timeout 이후에도 프로세스가 계속 실행 중이라면, GitLab Runner는 프로세스를 포기하고 더 이상 중단/종료를 시도하지 않을 것입니다. 이러한 시간 초과가 config_exec, prepare_exec 또는 run_exec 중에 도달하면 빌드는 실패로 표시됩니다.

드라이버에 의해 생성된 모든 하위 프로세스는 UNIX 기반 시스템에서도 위에서 설명한 정상적인 종료 프로세스를 받게 됩니다. 이는 모든 하위 프로세스가 속한 프로세스 그룹으로 주 프로세스가 설정되어 있어서 가능합니다.

오류 처리

GitLab Runner는 다르게 처리할 수 있는 두 가지 유형의 오류가 있습니다. 이러한 오류는 config_exec, prepare_exec, run_exec, cleanup_exec 내부의 실행 파일이 다음 코드 중 하나로 종료될 때에만 처리됩니다. 사용자가 0이 아닌 종료 코드로 종료하면, 아래의 오류 코드 중 하나로 전파되어야 합니다.

빌드 실패

GitLab Runner는 사용자 작업에서 실패가 발생했음을 GitLab Runner에 알리기 위해 실행 파일에서 사용되어야 하는 BUILD_FAILURE_EXIT_CODE 환경 변수를 제공합니다. 실행 파일이 BUILD_FAILURE_EXIT_CODE에서 코드로 종료하면, GitLab CI에서 작업이 적절히 실패로 표시됩니다.

만약 사용자가 .gitlab-ci.yml 파일 내에서 정의한 스크립트가 0이 아닌 코드로 종료하면, run_execBUILD_FAILURE_EXIT_CODE 값으로 종료해야 합니다.

note
변경 사항이 있을 수 있으므로 하드 코딩된 값 대신 BUILD_FAILURE_EXIT_CODE를 사용하는 것을 강력히 권장합니다.

시스템 실패

SYSTEM_FAILURE_EXIT_CODE에 지정된 오류 코드로 프로세스를 종료하여 시스템 오류를 GitLab Runner로 보낼 수 있습니다. 이 오류 코드가 반환되면, 특정 단계에서 GitLab Runner가 단계를 재시도하며, 재시도가 모두 실패한 경우 작업은 실패로 표시됩니다.

아래는 어떤 단계가 몇 번 재시도되며 각 재시도 사이의 기다림 시간입니다.

단계 이름 시도 횟수 각 재시도 사이의 기다림 시간
prepare_exec 3 3 초
get_sources GET_SOURCES_ATTEMPTS 변수의 값 (기본값 1) 0 초
restore_cache RESTORE_CACHE_ATTEMPTS 변수의 값 (기본값 1) 0 초
download_artifacts ARTIFACT_DOWNLOAD_ATTEMPTS 변수의 값 (기본값 1) 0 초
note
변경 사항이 있을 수 있으므로 하드 코딩된 값 대신 SYSTEM_FAILURE_EXIT_CODE를 사용하는 것을 강력히 권장합니다.

작업 응답

작업 수준의 CUSTOM_ENV_ 변수를 변경할 수 있으며, 이들은 CI/CD 변수 우선순위를 준수합니다. 이 기능이 바람직할 수 있지만, 신뢰할 수 있는 작업 컨텍스트가 필요한 경우, 전체 JSON 작업 응답이 자동으로 제공됩니다. Runner는 JOB_RESPONSE_FILE 환경 변수에서 참조되는 임시 파일을 생성하고, 이 파일은 모든 단계에 존재하며 정리 중에 자동으로 제거됩니다.

$ cat ${JOB_RESPONSE_FILE}
{"id": 123456, "token": "jobT0ken",...}