커스텀 실행기

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

GitLab Runner는 네이티브로 지원하지 않는 환경을 위한 커스텀 실행기를 제공합니다. 예를 들어, LXD 또는 Libvirt입니다.

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

커스텀 실행기에 대해 구성한 스크립트는 Drivers라고 불립니다. 예를 들어, 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]](../configuration/advanced-configuration.md#the-runners-section) 내의 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

서비스

서비스는 JSON 배열로 노출되며, CUSTOM_ENV_CI_JOB_SERVICES로 표현됩니다.

예시:

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 단계는 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_exec에 정의된 실행 파일에 순서대로 추가됩니다. 예시로 아래의 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 사용자 이름과 비밀번호를 얻어야 한다고 가정해 보겠습니다.

각 작업 실행 단계: prepare, 여러 개의 run 호출과 cleanup를 사용하여 사용자 지정 실행기를 실행하는 흐름에서 컨텍스트는 각각 별개의 실행입니다. 자격 증명 해결 예제에서는 각 경우마다 자격 증명 제공업체에 연결해야 합니다.

이 작업이 비쌀 경우, 전체 작업 실행을 위해 한 번만 수행하고 모든 작업 실행 단계에 대해 자격 증명을 재사용할 수 있습니다. 여기서 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에 지정된 실행 파일을 실행합니다.

이것은 환경을 설정하는 책임이 있습니다(예: 가상 머신 또는 컨테이너 생성, 서비스 또는 기타 아무 것이든). 완료되면 환경이 작업을 실행할 준비가 되었기를 기대합니다.

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

사용자는 GitLab Runner가 프로세스를 종료하기 전에 환경을 준비하는 데 얼마나 오랫동안 기다려야 하는지를 설정하려는 경우 prepare_exec_timeout을 설정할 수 있습니다.

이 실행 파일에서 반환된 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

참고: GitLab Runner 14.0 이상에서는 build_scriptstep_script로 대체됩니다. 자세한 내용은 이 문제를 참조하세요.

위에 언급된 각 단계에 대해, run_exec 실행 파일은 다음과 함께 실행됩니다:

  • 일반 환경 변수.
  • 두 개의 인자:
    • GitLab Runner가 커스텀 실행자가 실행할 스크립트의 경로.
    • 단계의 이름.

예를 들어:

/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 (사용 중단)

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

아래의 표는 각 스크립트가 수행하는 작업과 해당 스크립트의 주요 목표에 대한 자세한 설명입니다.

스크립트 이름 스크립트 내용
prepare_script 작업이 실행되는 머신에 대한 간단한 디버그 정보.
get_sources Git 구성을 준비하고, 저장소를 복제/패치합니다. GitLab이 제공하는 Git 전략의 모든 이점을 얻기 때문에 그대로 유지하는 것이 좋습니다.
restore_cache 정의된 경우 캐시를 추출합니다. $PATH에서 gitlab-runner 이진 파일이 사용 가능해야 합니다.
download_artifacts 정의된 경우 아티팩트를 다운로드합니다. $PATH에서 gitlab-runner 이진 파일이 사용 가능해야 합니다.
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가 실패합니다.

사용자는 GitLab Runner가 프로세스를 종료하기 전에 환경을 정리하는 데 얼마나 기다릴지를 설정하려면 cleanup_exec_timeout 을 설정할 수 있습니다.

이 실행 파일의 STDOUT는 GitLab Runner 로그에 DEBUG 수준으로 인쇄됩니다.

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_execcleanup_exec 내에서 실행 파일이 이러한 코드로 종료될 때만 처리됩니다.

사용자가 비제로 종료 코드를 반환하면, 아래의 오류 코드 중 하나로 전파되어야 합니다.

사용자 스크립트가 이 코드 중 하나로 종료되면, 실행 파일 종료 코드로 전파되어야 합니다.

빌드 실패

GitLab Runner는 실행 파일에서 사용해야 하는 BUILD_FAILURE_EXIT_CODE 환경 변수를 제공합니다.

이는 사용자의 작업에서 실패가 발생했음을 GitLab Runner에 알리기 위한 종료 코드입니다.

실행 파일이 BUILD_FAILURE_EXIT_CODE에서 반환된 코드로 종료되면, 빌드는 GitLab CI에서 적절하게 실패로 표시됩니다.

사용자가 .gitlab-ci.yml 파일 내에서 정의한 스크립트가 비영(zero)이 아닌 코드로 종료되면, run_execBUILD_FAILURE_EXIT_CODE 값으로 종료해야 합니다.

참고:

우리는 하드 코딩된 값 대신 BUILD_FAILURE_EXIT_CODE를 사용하는 것을 강력히 권장합니다.

이는 모든 릴리스에서 변경될 수 있으므로 여러분의 바이너리/스크립트가 미래에도 호환되도록 합니다.

시스템 실패

시스템 실패를 GitLab Runner에 보내려면 SYSTEM_FAILURE_EXIT_CODE에서 지정한 오류 코드로 프로세스를 종료하면 됩니다.

이 오류 코드가 반환되면, 특정 단계에서 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 작업 응답이 자동으로 제공됩니다.

러너는 임시 파일을 생성하며, 이는 JOB_RESPONSE_FILE 환경 변수에서 참조됩니다.

이 파일은 모든 단계에서 존재하며 정리 중에 자동으로 제거됩니다.

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