GitLab Runner とコンテナの entrypoint
これは GitLab Adventcalendar 2023 の 3日目 の記事です。
はじめに
GitLab Runner の docker executor や kubernetes executor で、こんな現象に見舞われたことはないでしょうか。
-
Preparing environment
の段階でunable to upgrade connection: container not found
というエラーでジョブが fail する - entrypoint が実行されるが、
.gitlab-ci.yml
のスクリプトが実行されない - entrypoint が実行されないで、スクリプトだけが実行される
その原因と対策を解説します。
Runner がコンテナを起動してスクリプトを実行するシーケンス
解説の前提として、Runner がどうやってコンテナを起動してスクリプトを実行しているのかを説明します。
ドキュメントのここに記載されている通り、こんなシーケンスです。
- コンテナを command を付けて起動 (command の内容は下記のコードブロックの通り)
- コンテナに attach
- attach したコンテナの shell の stdin にスクリプトを入力
- スクリプトの出力を stdout から取得
1.でコンテナを起動する際の command の内容
sh -c if [ -x /usr/local/bin/bash ]; then
exec /usr/local/bin/bash
elif [ -x /usr/bin/bash ]; then
exec /usr/bin/bash
elif [ -x /bin/bash ]; then
exec /bin/bash
elif [ -x /usr/local/bin/sh ]; then
exec /usr/local/bin/sh
elif [ -x /usr/bin/sh ]; then
exec /usr/bin/sh
elif [ -x /bin/sh ]; then
exec /bin/sh
elif [ -x /busybox/sh ]; then
exec /busybox/sh
else
echo shell not found
exit 1
fi
各現象の原因と対策
entrypoint が実行されるが、スクリプトが実行されない
原因
Runner は、前述のシーケンスの 2. ~ 3. の段階で、コンテナ内で shell が動作していることを期待しています。
コンテナは動作しているけれどもプロセスが shell ではない場合は、当然ですが 3. で入力されたスクリプトは実行されず、entrypoint だけが実行されてコンテナが終了します。
対策
command つまり entrypoint 内の "${@}"
には前述のコマンドが渡されているので、entrypoint の最後でそれを exec
しておきます。
exec "${@}"
Preparing environment
の段階で unable to upgrade connection: container not found
というエラーでジョブが fail する
原因
前述のシーケンスの 2. の段階で、attach 先のコンテナが存在しない、というエラーです。
Runner が attach する前に entrypoint つまり pid = 1 のプロセスが終了すると、コンテナも終了するのでこうなります。
対策
従って対策は前項と同じ、entrypoint の最後で shell を exec
しておくことです。
exec "${@}"
.gitlab-ci.yml
のスクリプトだけが実行される
entrypoint が実行されないで 原因1
Kubernetes executor の場合、FF_KUBERNETES_HONOR_ENTRYPOINT
というフィーチャーフラグを true
にしないとentrypoint は実行されません。
これは、CI/CD変数がその設定方法次第で entrypoint 内で参照できないことがあるなどの制限事項があるためです。
対策1
フィーチャーフラグ FF_KUBERNETES_HONOR_ENTRYPOINT
を true
(でも 1
でもいいんですが) に設定します。
Runner のフィーチャーフラグは、CI/CD変数か config.toml
で設定できます。
原因2
entrypoint は、.gitlab-ci/yml
の images.entrypoint:
でオーバーライドできます。
.gitlab-ci.yml
の image:
セクションに下記のように entrypoint:
があると、オーバーライドされています。
image:
name: my-image
entrypoint: [""]
対策2
コンテナで定義された entrypoint を実行したい場合は、image:
セクションの entrypoint:
を削除します。
Discussion