カスタムエグゼキューター
GitLab Runner 12.1 で導入されました。
GitLab Runnerはネイティブでサポートしていない環境のためにCustom Executorを提供します。例えば、LXD や Libvirt などです。
これは、GitLab Runnerがあなたの環境のプロビジョニング、実行、クリーンアップを行うための実行ファイルを使用するように設定することで、独自のエクゼキュータを作成するためのコントロールを提供します。
カスタム Executor 用に設定したスクリプトはDrivers
と呼ばれます。例えば、LXDドライバや Libvirtドライバを作成することができます。
制限事項
Custom Executorを使用する際の現在の制限事項を以下に示します:
- インタラクティブウェブターミナルをサポートしていません。
設定
いくつかの設定キーがあります。いくつかはオプションです。
以下はCustom Executorの設定例です:
[[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_dir
とcache_dir
の両方が必須フィールドです。
ジョブを実行するために必要なソフトウェア
ユーザーはPATH
に存在しなければならない以下を含む環境をセットアップしなければなりません:
- Gitと Git LFS:共通の前提条件を参照。
- GitLab Runner:アーティファクトとキャッシュのダウンロード/更新に使用します。
ステージ
Custom Executorはジョブの詳細を設定し、環境を準備し、クリーンアップし、その中でジョブスクリプトを実行するためのステージを提供します。各ステージは特定のことを担当し、注意すべきことが異なります。
Custom executorによって実行される各ステージは、組み込みのGitLab Runner executorが実行する時間に実行されます。
実行される各ステージに対して、実行ファイルに特定の環境変数が公開され、実行中の特定のジョブに関する情報を得るために使うことができます。すべてのステージは以下の環境変数を利用できます:
- 定義済みの変数を含む、標準的な CI/CD環境変数。
- Custom Executor Runnerホストシステムが提供するすべての環境変数。
- 全てのサービスと利用可能な設定。
CUSTOM_ENV_CI_JOB_SERVICES
としてJSON形式で公開。
CI/CD環境変数と定義済み変数の両方は、システム環境変数との競合を防ぐために、CUSTOM_ENV_
が先頭に付きます。例えば、CI_BUILDS_DIR
はCUSTOM_ENV_CI_BUILDS_DIR
として利用できます。
ステージは以下の順序で実行されます:
config_exec
prepare_exec
run_exec
cleanup_exec
サービス
GitLab Runner 13.6 で導入されました。
サービスは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_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文字列でない場合、ステージは失敗し、さらに2回再試行されます。
パラメータ | 種類 | 必須 | 空 | 説明 |
---|---|---|---|---|
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 usage を参照してください。 |
実行ファイルのSTDERR
は、ジョブログに出力されます。
ユーザは、GitLab Runnerが処理を終了する前にJSON文字列を返すまでの期限を設定したい場合、config_exec_timeout
。
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
設定の主な目的は、ジョブ実行の後続ステージのカスタムExecutorドライバ呼び出しのコンテキストに変数を渡すことです。
ジョブ実行環境との接続にいくつかの認証情報を準備する必要があり、このオペレーションが非常に高価であるドライバの例を考えてみましょう。ジョブ実行環境と接続するために、カスタムエグゼキュータが次に使用できる一時的なSSHユーザ名とパスワードを取得するために、ローカルの認証情報プロバイダに接続する必要があるとします。
Custom Executor の実行フローでは、各ジョブ実行ステージ(prepare
、複数のrun
コール、cleanup
)がドライバの別個の実行であり、コンテキストはそれぞれ別個です。資格情報を解決する例では、資格情報プロバイダへの接続は毎回行う必要があります。
このオペレーションが高価な場合、ジョブ実行全体に対して一度だけ行い、その後すべてのジョブ実行ステージでクレデンシャルを再利用したいと思うかもしれません。ここでjob_env
が役立ちます。これによって、config_exec
呼び出し中にプロバイダと一度だけ接続し、job_env
で受信した資格情報を渡すことができます。次に、prepare_exec
、run_exec
、cleanup_exec
のカスタムエグゼキュータ呼び出しが受信する変数のリストに追加されます。これにより、ドライバは、毎回資格情報プロバイダに接続する代わりに、変数を読み込んで、存在する資格情報を使用することができます。
理解すべき重要な点は、変数はジョブ自体で自動的に利用できるわけではないということです。これは、Custom Executor Driver がどのように実装されているかに完全に依存し、多くの場合、そこには存在しません。
job_env
、特定のRunnerによって実行されるすべてのジョブに変数のセットを渡せるようにしたいと考えているのであれば、[[runners]]
](../configuration/advanced-configuration.md#the-runners-section) の[environment
設定を見てください。
変数が動的で、異なるジョブ間で値が変更されることが予想される場合は、job_env
によって渡された変数がジョブ実行呼び出しに追加されるようにドライバが実装されていることを確認する必要があります。
準備
Prepareステージはprepare_exec
によって実行されます。
この時点で、GitLab Runnerはジョブに関するすべてのことを知っています(どこで、どのように実行されるのか)。あとは、ジョブが実行できるように環境をセットアップするだけです。GitLab Runnerはprepare_exec
で指定された実行ファイルを実行します。
これは、環境のセットアップ(たとえば、仮想マシンやコンテナ、サービスなどの作成)を行います。これが終わると、ジョブを実行する環境が整います。
このステージはジョブ実行の中で一度だけ実行されます。
ユーザは、GitLab Runnerがプロセスを終了する前に環境を準備するために待つ時間の期限を設定したい場合、prepare_exec_timeout
。
この実行ファイルから返されるSTDOUT
とSTDERR
はジョブログに出力されます。
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 ステージはrun_exec
によって実行されます。
この実行ファイルから返されるSTDOUT
とSTDERR
はジョブログに出力されます。
他のステージとは異なり、run_exec
ステージは複数回実行されます。これは、以下のサブステージに順次分割されるためです:
prepare_script
get_sources
restore_cache
download_artifacts
step_*
build_script
step_*
after_script
-
archive_cache
ORarchive_cache_on_failure
-
upload_artifacts_on_success
ORupload_artifacts_on_failure
cleanup_file_variables
上記の各ステージで、run_exec
の実行ファイルが実行されます:
- 通常の環境変数。
- 2つの引数:
- GitLab RunnerがCustom Executorを実行するために作成するスクリプトへのパス。
- ステージの名前。
使用例:
/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 Executor が通常実行するクローン、アーティファクトのダウンロード、ユーザースクリプトの実行、その他後述するすべてのステップを実行するためのすべてのスクリプトが含まれています。スクリプトには以下のシェルを使うことができます:
- Bash
- PowerShellデスクトップ
- PowerShellコア
- バッチ(非推奨)
[[runners]]
の内部でshell
によって設定されたシェルを使用してスクリプトを生成します。 何も指定されていない場合は、OS プラットフォームのデフォルトが使用されます。
以下の表は、各スクリプトが何を行い、そのスクリプトの主な目的が何であるかを詳細に説明したものです。
スクリプト名 | スクリプトの内容 |
---|---|
prepare_script | ジョブが実行されているマシンの簡単なデバッグ情報。 |
get_sources | Git の設定を準備し、リポジトリをクローン/フェッチします。GitLab が提供する Git 戦略のすべての利点を得ることができるので、このままにしておくことをお勧めします。 |
restore_cache | キャッシュが定義されていれば、それを取り出します。これは、gitlab-runner のバイナリが$PATH にあることを期待します。 |
download_artifacts | アーティファクトが定義されている場合は、ダウンロードします。これは、gitlab-runner のバイナリが$PATH で利用可能であることを想定しています。 |
step_* | GitLabによって生成されます。実行するスクリプトのセット。カスタムエグゼキューターに送られることはありません。step_release やstep_accessibility のように複数のステップを持つこともあります。これは.gitlab-ci.yml ファイルの機能です。 |
build_script |
before_script とscript の組み合わせ。 GitLab Runner 14.0 以降では、build_script はstep_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_exec
とrun_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
の間にこれらのタイムアウトに達した場合、ビルドは失敗とみなされます。
GitLab 13.1では、ドライバによって生成された子プロセスも、UNIXベースのシステムで上で説明したグレースフル・ターミネーション処理を受けます。これは、すべての子プロセスが属するプロセスグループとしてメインプロセスを設定することで実現されます。
エラーハンドリング
GitLab Runnerが処理できるエラーには2種類あります。これらのエラーは、config_exec
,prepare_exec
,run_exec
,cleanup_exec
の内部の実行ファイルがこれらのコードで終了した場合にのみ処理されます。ユーザーがゼロ以外の終了コードで終了した場合は、以下のエラーコードの一つとして伝搬されるはずです。
ユーザースクリプトがこれらのコードで終了した場合、実行可能ファイルの終了コードに反映される必要があります。
ビルドの失敗
GitLab RunnerはBUILD_FAILURE_EXIT_CODE
環境変数を BUILD_FAILURE_EXIT_CODE
提供しBUILD_FAILURE_EXIT_CODE
、実行変数がユーザージョブの失敗をGitLab Runnerに通知するための終了コードとして使用 BUILD_FAILURE_EXIT_CODE
します。BUILD_FAILURE_EXIT_CODE
もし実行ファイルがこのコードで終了した BUILD_FAILURE_EXIT_CODE
場合、GitLab CIではビルドは失敗とみなされます。
ユーザーが.gitlab-ci.yml
ファイル内部で定義したスクリプトがゼロ以外のコードで終了した場合、run_exec
はBUILD_FAILURE_EXIT_CODE
の値で終了する必要があります。
BUILD_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
を使用して終了することを強くお勧めします。なぜなら、この値はどのリリースでも変更される可能性があり、バイナリやスクリプトを将来的にも使えるようにするためです。ジョブ応答
文書化されたCI/CD 変数の優先順位に従って、ジョブレベルのCUSTOM_ENV_
変数を変更することができます。この機能は望ましいものですが、信頼されたジョブコンテキストが必要な場合、完全なJSONジョブレスポンスが自動的に提供されます。ランナーはJOB_RESPONSE_FILE
環境変数で参照される一時ファイルを生成します。このファイルはすべてのステージに存在し、クリーンアップの間に自動的に削除されます。
$ cat ${JOB_RESPONSE_FILE}
{"id": 123456, "token": "jobT0ken",...}