GitLab Runner は、GitLab によってディスパッチされる CI/CD ジョブを実行する Go で記述されたオープンソース アプリケーションです。CI ワークロードは本質的にバースト性があるため、Container Compute Service (ACS) は最適な選択肢です。ACS はオンデマンドでリソースをプロビジョニングし、高速にスケーリングし、イメージを自動的にキャッシュして後続のジョブの開始を高速化します。このトピックでは、Kubernetes エグゼキュータを使用して ACS クラスターに GitLab Runner をデプロイし、コンテナイメージをビルドし、ACS スケーリングポリシーで CI リソースコストを削減する方法について説明します。
仕組み
GitLab Runner は、Kubernetes エグゼキュータを使用して CI ジョブごとに Pod を作成します。Runner マネージャー Pod は Kubernetes API と通信してジョブ Pod をスケジュールし、結果を待機して GitLab にレポートします。各ジョブが完了すると、ジョブ Pod は削除されます。
主要な構成領域:
Runner マネージャー Pod —
values.yamlを介して初期化され、Helm でインストールされます。Kubernetes エグゼキュータ —
values.yaml内のrunners.configで設定されます。
完全な構成リファレンスについては、「GitLab Runner の構成」をご参照ください。
前提条件
開始する前に、以下を確保してください。
kubectl を使用して ACS クラスターに接続済みである必要があります。詳細については、「kubectl を使用して Kubernetes クラスターに接続する」をご参照ください。
ローカルに Helm がインストールされていること。
クラスターからアクセス可能な GitLab インスタンスがあること。
ご利用の GitLab インスタンスから Runner トークンを取得済みであること。詳細については、「Runner の登録」をご参照ください。
GitLab Runner のインストール
この例では、Helm チャートバージョン 0.68.1 を使用して gitlab-runner 17.3.1 をインストールします。他のバージョンについては、「GitLab Runner Helm チャート」をご参照ください。
ステップ 1: GitLab Runner チャートの取得
helm repo add gitlab https://charts.gitlab.io
helm repo update gitlab
helm pull gitlab/gitlab-runner --version 0.68.1 && tar zvxf gitlab-runner-0.68.1.tgzステップ 2: values.yaml の作成
GitLab Runner を実行するには、3 つのパラメーターが必要です。
| パラメーター | 説明 |
|---|---|
gitlabUrl | ご利用の GitLab サーバーの URL。例: https://gitlab.example.com |
runnerToken | ご利用の GitLab インスタンスから取得した Runner トークン。Runner マネージャーは、このトークンを識別子として使用し、作成する Pod と Secret を関連付けます。 |
rbac.create | 必要な RBAC ルールを持つサービスアカウントを自動的に作成するには、true に設定します。 |
以下の values.yaml は、推奨設定を含む動作する構成を示しています。
## GitLab Runner イメージ
##
## デフォルトでは registry.gitlab.com/gitlab-org/gitlab-runner:alpine-v{VERSION} を使用します
## ここで、{VERSION} は Chart.yaml の appVersion フィールドから取得されます
##
## 参照: https://gitlab.com/gitlab-org/gitlab-runner/container_registry/29383?orderBy=NAME&sort=asc&search[]=alpine-v&search[]=
##
## 注: イメージを Ubuntu リリースに変更する場合は、
## securityContext の変更を忘れないでください。
## これらのイメージは異なるユーザー ID で実行されます。
##
...
## runner を登録する GitLab サーバーの URL (プロトコルを含む)
## 参照: https://docs.gitlab.com/runner/commands/index.html#gitlab-runner-register
##
gitlabUrl: https://jihulab.com/
## 非推奨: 新しい Runner を GitLab サーバーに追加するための登録トークン。
##
## 参照: https://docs.gitlab.com/ee/ci/runners/new_creation_workflow.html
##
# runnerRegistrationToken: ""
## 新しい Runner を GitLab サーバーに追加するための Runner トークン。これは
## GitLab インスタンスから取得する必要があります。すでに登録されている runner のトークンです。
## 参照: (これに関するドキュメントはまだありませんが、既存のトークンを使用します)
##
runnerToken: "glrt-t3_sz6xxxxxxxxxDsWF77"
#
## 終了前にすべての runner の登録を解除する
##
## runner の chart バージョンまたは構成を更新すると、runner コンテナが
## 終了されて再作成されます。これにより、Gitlab インスタンスが
## 存在しない runner を参照する可能性があります。終了前に runner の登録を解除すると、この問題が軽減されます。
## 参照: https://docs.gitlab.com/runner/commands/index.html#gitlab-runner-unregister
##
unregisterRunners: true
## runner を停止するときは、ジョブが終了するのを待つ時間を与えます。
##
## runner の chart バージョンまたは構成を更新すると、runner コンテナは
## 正常な停止リクエストで終了します。terminationGracePeriodSeconds は
## runner の Pod が正常に終了するのに十分な時間待機するように Kubernetes に指示します。
## 参照: https://docs.gitlab.com/runner/commands/#signals
terminationGracePeriodSeconds: 3600
## GitLab Runner が使用するカスタム証明書を渡すために certsSecretName を設定します。
## 同じ名前空間にある Kubernetes Secret オブジェクトのリソース名を指定します。
## これは /home/gitlab-runner/.gitlab-runner/certs/ ディレクトリにデータを格納するために使用されます
## 参照: https://docs.gitlab.com/runner/configuration/tls-self-signed.html#supported-options-for-self-signed-certificates-targeting-the-gitlab-server
##
# certsSecretName:
## 同時ジョブの最大数を構成します
## 参照: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section
##
concurrent: 10
...
## RBAC サポートの場合:
rbac:
## Role と RoleBinding を作成するかどうかを指定します
## この値を `true` に設定した場合、`serviceAccount.create` も `true` または `false` のいずれかに設定する必要があります
##
create: true
## create が true に設定されている場合に生成される serviceAccountName を定義します
## 指定しない場合、デフォルトは "gitlab-runner.fullname" になります
## 非推奨: 代わりに `serviceAccount.name` を使用してください
generatedServiceAccountName: ""
...
## runner が新しいジョブごとに起動する Pod の構成
##
runners:
# runner の構成。複数行の文字列は
# テンプレートとして評価されるため、その中に Helm の値を指定できます。
#
# tpl: https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function
# runner の構成: https://docs.gitlab.com/runner/configuration/advanced-configuration.html
config: |
[[runners]]
[runners.kubernetes]
namespace = "{{.Release.Namespace}}"
image = "alpine"
## 既存の runner 構成ファイルの絶対パス
## "volumes" および "volumeMounts" とともに使用して、外部構成ファイルを使用できます
## runners.config が空または null の場合にアクティブになります
configPath: ""
...以下の表は、主要なパラメーターについて説明しています。
| パラメーター | 説明 |
|---|---|
gitlabUrl | Runner を登録する GitLab サーバーの URL。例: https://gitlab.example.com。 |
runnerToken | GitLab から取得した Runner トークン。Runner マネージャーは、このトークンを使用して、作成する Pod と Secret を関連付けます。 |
rbac | ロールベースアクセス制御 (RBAC) を有効にします。create: true に設定すると、サービスアカウントが自動的に作成されます。 |
concurrent | 同時実行ジョブの最大数。デフォルト: 10。高同時実行ワークロードの場合、Runner マネージャー Pod のリソース制限を増やしてください。 |
unregisterRunners | マネージャー Pod が終了する前に unregister コマンドを実行します。これにより、Pod の再起動後に GitLab インスタンスが古い Runner への参照を保持するのを防ぎます。詳細については、「よくある質問」をご参照ください。 |
runners.config | 複数行文字列として指定される Runner 構成。エグゼキュータ設定を変更するには、この文字列を修正します。 |
ステップ 3: GitLab Runner のインストール
helm install --namespace default gitlab-runner -f values.yaml --version 0.68.1 gitlab/gitlab-runnerインストールの検証
kubectl get pod | grep gitlab期待される出力:
gitlab-runner-7c5b4xxxxx-xxxxx 1/1 Running 0 5m17sコンテナイメージのビルド
GitLab Runner は、Kubernetes クラスターでコンテナイメージをビルドするための 2 つのアプローチをサポートしています。ご利用の環境が特権モードを許可するかどうかに基づいて選択してください。
| アプローチ | 特権モードが必要 | 使用する状況 |
|---|---|---|
| Docker-in-Docker (dind) | はい | 特権モードが有効で、完全な Docker デーモンアクセスが必要な場合 |
| kaniko | いいえ | ご利用の環境が特権モードを制限している場合 (ほとんどのケースで推奨) |
Docker-in-Docker を使用したイメージのビルド
Docker-in-Docker は、ビルドコンテナ内で Docker デーモンを直接実行します。
このモードには privileged = true が必要です。この操作を実行するには、続行する前に ACS Pod の特権モードを有効にするために チケットを送信する必要があります。
サンプルプロジェクトについては、「Java デモ」をご参照ください。
ステップ 1: values.yaml の更新
Runner 構成を更新するには、ConfigMap を直接編集するのではなく、helm upgrade を実行してください。...
runners:
config: |
[[runners]]
[runners.kubernetes]
namespace = "{{.Release.Namespace}}"
image = "registry.cn-hangzhou.aliyuncs.com/acs-demo-ns/docker:27-dind"
privileged = true
cpu_limit = 2
cpu_request = 2
memory_limit = "4Gi"
memory_request = "4Gi"
ephemeral_storage_request = "30Gi"
ephemeral_storage_limit = "30Gi"
[[runners.kubernetes.volumes.empty_dir]]
name = "docker-certs"
mount_path = "/certs/client"
medium = "Memory"
[[runners.feature_flags]]
FF_USE_POD_ACTIVE_DEADLINE_SECONDS = true
...| パラメーター | 説明 |
|---|---|
image | dind ビルドのベースイメージ。この例では、Docker コミュニティの dind イメージを使用します。 |
privileged | Runner Pod の特権モードを有効にします。Docker-in-Docker に必要です。 |
cpu_request / cpu_limit | コンテナの CPU 割り当て。ACS の最小値は 0.25 vCore です。ビルド要件に基づいて調整してください。 |
memory_request / memory_limit | メモリ割り当て。ACS の最小値は 0.5 GiB です。ビルド要件に基づいて調整してください。 |
ephemeral_storage_request / ephemeral_storage_limit | エフェメラルストレージ割り当て。ACS はデフォルトで 30 GiB を無料で提供し、イメージを自動的にキャッシュして後続のジョブを高速化します。 |
FF_USE_POD_ACTIVE_DEADLINE_SECONDS | activeDeadlineSeconds 機能ゲートを有効にします。これにより、Pod の TTL がジョブタイムアウトに設定され、不明な原因で関連付けが解除された Pod が終了されます。 |
その他のパラメーターについては、「Kubernetes エグゼキュータ」をご参照ください。
ステップ 2: .gitlab-ci.yml ファイルの作成
この例では、個別のサービスコンテナなしで、ビルドコンテナ内で dockerd プロセスを直接起動します。
image: registry.cn-hangzhou.aliyuncs.com/acs-demo-ns/docker:27-dind
stages:
- build
variables:
# When using dind service, you must instruct Docker to talk with
# the daemon started inside of the service. The daemon is available
# with a network connection instead of the default
# /var/run/docker.sock socket.
DOCKER_HOST: tcp://localhost:2376
#
# The 'docker' hostname is the alias of the service container as described at
# https://docs.gitlab.com/ee/ci/services/#accessing-the-services.
# If you're using GitLab Runner 12.7 or earlier with the Kubernetes executor and Kubernetes 1.6 or earlier,
# the variable must be set to tcp://localhost:2376 because of how the
# Kubernetes executor connects services to the job container
# DOCKER_HOST: tcp://localhost:2376
#
# Specify to Docker where to create the certificates. Docker
# creates them automatically on boot, and creates
# `/certs/client` to share between the service and job
# container, thanks to volume mount from config.toml
DOCKER_TLS_CERTDIR: "/certs"
# These are usually specified by the entrypoint, however the
# Kubernetes executor doesn't run entrypoints
# https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4125
DOCKER_TLS_VERIFY: 1
DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client"
before_script:
- echo "before task"
- sh /usr/local/bin/dockerd-entrypoint.sh &
- sleep 10s
build_image:
stage: build
tags:
- demo
script:
- docker info
- sleep 1d
- docker build --network host -t demo:v1.0.0 -f Dockerfile .
- docker push demo:v1.0.0| ステップ | 説明 |
|---|---|
before_script | dockerd プロセスを起動し、初期化されるのを待機します。 |
build_image | イメージをビルドします。ホストネットワークモード (--network host) を使用するため、dockerd プロセスはコンテナネットワークを介して外部ネットワークに到達できます。 |
kaniko を使用したイメージのビルド
kaniko は、Docker や特権モードを必要とせずにコンテナイメージをビルドするオープンソース ツールです。kaniko は、システムが Docker へのアクセスを制限している場合や、システムが Kubernetes 環境で実行されているシナリオに適しています。
GitLab CI はコマンド実行に Shell エグゼキュータを使用するため、ベースイメージは sh をサポートしている必要があります。この例では、シェルを含む kaniko エグゼキュータイメージのデバッグバージョンを使用します。
ステップ 1: values.yaml の更新
...
runners:
config: |
[[runners]]
[runners.kubernetes]
namespace = "{{.Release.Namespace}}"
ephemeral_storage_request = "30Gi"
ephemeral_storage_limit = "30Gi"
[[runners.feature_flags]]
FF_USE_POD_ACTIVE_DEADLINE_SECONDS = true
...ステップ 2: .gitlab-ci.yml ファイルの作成
stages:
- build
variables:
KUBERNETES_POD_LABELS_1: "alibabacloud.com/compute-class=general-purpose"
KUBERNETES_POD_LABELS_2: "alibabacloud.com/compute-qos=best-effort"
build_image:
stage: build
image:
name: registry.cn-hangzhou.aliyuncs.com/acs-demo-ns/kaniko-executor:v1.21.0-amd64-debug
entrypoint: [""]
tags:
- demo
script:
- /kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"ACS スケーリングポリシーによる CI コストの削減
CI/CD パイプラインでのジョブ実行のリソースコストを削減するために、ACS が提供する BestEffort Pod を使用する以下のいずれかの方法を選択できます。
方法 1: クラスター内のすべての Pod に BestEffort QoS を構成
クラスター内のすべての Pod に BestEffort QoS クラスを構成することを推奨します。ビジネス要件に基づいて、他の QoS クラスを選択することもできます。
Runner が作成するすべてのジョブ Pod に BestEffort QoS を適用するには、values.yaml に Pod ラベルを追加します。
...
runners:
config: |
[[runners]]
[runners.kubernetes]
...
pod_labels_overwrite_allowed = ".*" # Allow the system to overwrite the labels of project pods based on variables.
[[runners.kubernetes.pod_labels]]
"app" = "acs-gitlab-runner"
"alibabacloud.com/compute-class" = "general-purpose"
"alibabacloud.com/compute-qos" = "best-effort" # Configure the BestEffort QoS class for pods.
...プロジェクトごとに異なる QoS クラスを適用するには、代わりにプロジェクトの .gitlab-ci.yml に対応する KUBERNETES_POD_LABELS_* 変数を追加します。上記の「kaniko の例」をご参照ください。
方法 2: 自動フェイルオーバーのための ResourcePolicy の構成
ResourcePolicy を使用すると、カスタムスケジューリング優先度を定義できます。ジョブ Pod は最初に BestEffort 容量にスケジュールされます。リージョンで BestEffort Pod が枯渇すると、システムは自動的にデフォルト Pod を作成し、CI ジョブの継続性と可用性を確保します。
apiVersion: scheduling.alibabacloud.com/v1alpha1
kind: ResourcePolicy
metadata:
name: rp-demo
namespace: default
spec:
selector: # Specify the label selector used to select pods. In this example, the ResourcePolicy is applied to pods that have the app=stress label.
app: acs-gitlab-runner
units: # Specify the priorities of different types of nodes for pod scheduling.
- resource: acs # Prioritize BestEffort resources.
podLabels:
alibabacloud.com/compute-class: general-purpose
alibabacloud.com/compute-qos: best-effort
- resource: acs # Apply for Default resources when the preceding resources are out of stock.
podLabels:
alibabacloud.com/compute-class: general-purpose
alibabacloud.com/compute-qos: defaultよくある質問
Runner マネージャー Pod の再起動後に残留 Pod が存在する理由
マネージャー Pod が異なる Runner トークンで再作成されると、以前のトークンで作成されたジョブ Pod を管理する能力を失います。それらの Pod は残留しますが、追跡されなくなります。
これを回避するには:
GitLab で Runner を再作成し、構成ファイルで Runner トークンを更新してください。
登録トークンを使用する場合は、初期登録からのトークンを含む Secret をマネージャー Pod にマウントしてください。これにより、再起動全体で同じトークンが再利用されることが保証されます。
FF_USE_POD_ACTIVE_DEADLINE_SECONDSを有効にしてください。これにより、各ジョブ Pod の TTL がジョブタイムアウトに設定され、孤立した Pod が自動的にクリーンアップされます。