사용자 정의 실행자

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed
  • 소개된 것으로, GitLab Runner 12.1에서 소개되었습니다.

GitLab Runner은 기본적으로 지원하지 않는 환경을 위해 사용할 수 있는 사용자 정의 실행자(Custom executor)를 제공합니다. 예를 들어, LXD 또는 Libvirt와 같은 환경을 지원합니다.

이를 통해 GitLab Runner를 구성하여 환경을 프로비저닝하고 실행하며 정리할 수 있는 실행자를 직접 만들 수 있습니다.

사용자 지정 실행자를 구성하는 스크립트를 드라이버(Drivers)라고 합니다. 예를 들어, LXD 드라이버Libvirt 드라이버를 생성할 수 있습니다.

제한 사항

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

구성(Configuration)

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

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

[[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은 필수 필드입니다.

작업(Job)을 실행하는 데 필요한 소프트웨어 요구 사항

사용자는 다음과 같은 것들이 PATH에 존재해야 하는 환경을 설정해야 합니다:

단계

사용자 정의 실행자는 작업의 일부 세부 정보를 구성하고 환경을 준비하고 정리하며 해당 환경에서 작업 스크립트를 실행하는 데 사용할 수 있는 단계를 제공합니다. 각 단계는 특정 작업을 처리하고 염두에 두어야 할 다른 사항을 가지고 있습니다.

사용자 정의 실행자에 의해 실행되는 각 단계는 내장 GitLab Runner 실행자가 그 단계를 실행할 때 실행됩니다.

각 실행될 단계마다 특정 환경 변수가 실행 가능 파일에 노출되어 해당 작업에 대한 정보를 얻기 위해 사용할 수 있습니다. 모든 단계에서 다음과 같은 환경 변수가 사용할 수 있습니다:

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

서비스

  • 소개된 것으로, GitLab Runner 13.6에서 소개되었습니다.

서비스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는 표준 출력에서 읽고 특정 키가 있는 유효한 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 string 작업의 작업 디렉토리가 생성될 기본 디렉토리입니다.
cache_dir string 로컬 캐시가 저장될 기본 디렉토리입니다.
builds_dir_is_shared bool n/a 환경이 동시 작업 간에 공유되는 지 여부를 정의합니다.
hostname string 실행자가 저장하는 작업의 “메타데이터”에 연결할 호스트 이름입니다. 정의되지 않으면 호스트 이름은 설정되지 않습니다.
driver.name string 드라이버에 대한 사용자 정의 이름입니다. Using custom executor... 라인에 표시됩니다. 정의되지 않으면 드라이버에 대한 정보가 표시되지 않습니다.
driver.version string 드라이버에 대한 사용자 정의 버전입니다. Using custom executor... 라인에 표시됩니다. 정의되지 않으면 이름 정보만 표시됩니다.
job_env object 실행 환경 변수 시스템에 모든 후속 단계에서 사용할 수 있는 이름-값 쌍입니다. 작업이 아닌 드라이버에서 사용할 수 있습니다. 자세한 내용은 job_env 사용을 참조하십시오.

실행 가능의 STDERR는 작업 로그에 출력됩니다.

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

만약 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_exec(실행) 및 cleanup_exec(정리)에 대해 받는 커스텀 실행 호출의 변수 목록에 추가될 것입니다. 이를 통해 드라이버는 매번 자격 증명 제공자에 연결하는 대신 변수를 읽고 존재하는 자격 증명을 사용할 수 있습니다.

이해해야 할 중요한 점은 변수가 작업 자체에 자동으로 사용 가능한 것이 아니라는 것입니다. 이는 완전히 커스텀 실행 드라이버가 구현된 방식에 따라 완전히 달려있으며 많은 경우 여기에는 포함되지 않을 것입니다.

특정 Runner에 의해 실행되는 모든 작업에 일련의 변수를 전달할 수 있도록 job_env를 고려 중이라면 [[runners]] 내부의 environment 설정을 확인하세요.

변수가 동적이고 값이 다른 작업 간에 변경될 것으로 예상되는 경우, job_env에 의해 전달된 변수가 작업 실행 호출에 추가될 것이라는 점을 확인해야 합니다.

준비

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

이 시점에서 GitLab 러너는 작업에 대해 모든 것을 알고 있습니다(어디에서 실행될지 및 어떻게 실행될지). 남은 것은 작업이 실행될 수 있도록 환경을 설정하는 것뿐입니다. GitLab 러너는 prepare_exec에 지정된 실행 가능 파일을 실행합니다.

이 코드는 환경을 준비하는 데 책임이 있습니다(예: 가상 머신 또는 컨테이너 생성, 서비스 또는 기타). 이 작업이 완료되면 환경이 작업을 실행할 준비가 되었다고 기대합니다.

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

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

이 실행 가능 파일에서 반환된 STDOUTSTDERR은 작업 로그에 인쇄됩니다.

만약 prepare_exec_args 중 하나라도 정의된 경우, 이러한 내용은 prepare_exec에 정의된 실행 파일에 순서대로 추가됩니다. 예를 들어 다음과 같이 config.toml 내용이 있다고 가정하면:

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

GitLab 러너는 /path/to/bin Arg1 Arg2로 실행될 것입니다.

실행

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

이 실행 가능 파일에서 반환된 STDOUTSTDERR은 작업 로그에 인쇄됩니다.

다른 단계와는 달리 run_exec 단계는 여러 번 실행됩니다. 그 이유는 순차적으로 나열된 서브 단계로 분할되기 때문입니다. (아래에 나열됨) 1. prepare_script 1. get_sources 1. restore_cache 1. download_artifacts 1. step_* 1. build_script 1. step_* 1. after_script 1. archive_cache 또는 archive_cache_on_failure 1. upload_artifacts_on_success 또는 upload_artifacts_on_failure 1. cleanup_file_variables

:::주의::: GitLab 러너 14.0 이상 버전에서 build_scriptstep_script로 대체될 것입니다. 자세한 내용은 이 이슈를 참조하세요.

위에서 언급된 각 단계에 대해 run_exec 실행 파일은 보통의 환경 변수와 두 가지 인수와 함께 실행될 것입니다: 1. 커스텀 실행 프로그램이 실행할 스크립트의 경로 2. 단계 이름

예: shell /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 러너가 그 이에 추가합니다. 예를 들어 다음과 같이 config.toml이 있다고 가정하면:

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

GitLab 러너는 다음과 같이 실행될 것입니다:

/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이 제공하는 Git 전략의 모든 이점을 사용할 수 있도록 하는 저장소를 복제 및 가져오는 것을 포함하고 있을 것입니다. 이 스크립트들은 아래에 설명된 모든 단계를 포함하여 일반적으로 커스텀 실행기가 복제, 아티팩트 다운로드, 사용자 스크립트 실행 및 다른 모든 단계를 수행하는 프로그램입니다. 스크립트는 다음과 같은 셸을 사용할 수 있습니다: - Bash - PowerShell 데스크톱 - PowerShell Core - 배치 (사용 중지)

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

아래 표에서는 각 스크립트가 수행하는 내용과 해당 스크립트의 주요 목표에 대해 자세한 설명을 제공합니다.

스크립트 이름 스크립트 내용
prepare_script 작업이 실행되는 머신에 대한 간단한 디버그 정보
get_sources Git 구성을 준비하고 저장소를 복제/가져옵니다. 여기에는 GitLab이 제공하는 모든 이점이 포함되므로 유지하는 것을 권장합니다.
restore_cache 정의된 캐시를 추출합니다. 이는 gitlab-runner 이진 파일이 $PATH에서 사용 가능하다고 예상합니다.
download_artifacts 정의된 아티팩트를 다운로드합니다. 이는 gitlab-runner 이진 파일이 $PATH에서 사용 가능하다고 예상합니다.
step_* GitLab에서 생성됨. 실행하지 않을 수 있습니다. 여러 단계를 가질 수 있으며 .gitlab-ci.yml 파일의 기능일 수 있습니다.
build_script before_scriptscript의 조합입니다. GitLab 러너 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은 GitLab Runner 로그에 디버그 수준으로 출력됩니다. STDERR는 로그에 경고 수준으로 출력됩니다.

만약 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는 사용자 작업에 실패가 있음을 알리는 종료 코드로 실행 파일이 사용해야 할 BUILD_FAILURE_EXIT_CODE 환경 변수를 제공합니다. 실행 파일이 BUILD_FAILURE_EXIT_CODE에서 코드로 나가면 GitLab CI에서 빌드가 적절히 실패로 표시됩니다.

.gitlab-ci.yml 파일 내에서 사용자가 정의한 스크립트가 0이 아닌 코드로 종료되면 run_execBUILD_FAILURE_EXIT_CODE 값을 가지고 종료되어야 합니다.

참고: 우리는 여러분이 이진 파일/스크립트를 미래에도 사용할 수 있도록 하기 위해 하드 코딩된 값 대신에 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 초

참고: 우리는 여러분이 이진 파일/스크립트를 미래에도 사용할 수 있도록 하기 위해 하드 코딩된 값 대신에 SYSTEM_FAILURE_EXIT_CODE를 종료로 사용하는 것을 강력히 권장합니다.

작업 응답

작업 레벨의 CUSTOM_ENV_ 변수를 변경할 수 있으며, 이는 문서화된 CI/CD 변수 우선 순위를 따릅니다. 이 기능이 유용할 수 있지만, 신뢰할 수 있는 작업 맥락이 필요한 경우, 러너는 자동으로 전체 JSON 작업 응답을 제공합니다. 임시 파일이 생성되며, 이 파일은 모든 단계에 존재하며 정리 중에 자동으로 제거됩니다.

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