GitLab Runner の Kubernetes Executor


はじめに

GitLab で CICD をする際に、実際にジョブを実行してくれる GitLab Runner 君ですが、Kubernetes 上に Pod として実行可能な、 Kubernetes Executor という仕組みが提供されています。

Kubernetes Executor の Job 実行の流れ

公式ドキュメントにも記載がありますが、ざっくり下図のような流れでCICDを実行するpodが作成されます。

  1. まず、Kubernetes 上に Deploy された GitLab Runner Pod が、GitLab のインスタンスに対して、実行可能な Job があるか問い合わせます。
  2. 次に、仕事をもらった Runner Pod は、Kubernetes API に対して Pod の作成を Request し、
  3. 生成された Job 実行 Pod が実際に仕事をこなします。
  4. 仕事を終えた Job Pod はひっそりと姿を消します

さて、この Job Pod には、最大3種類のコンテナが含まれているのですが、なんと2年前のアドベントカレンダーで詳しく説明してくださっているので、割愛させていただきます

Kubernetes Executor のデプロイ

Kubernetes 上への、 GitLab Runner のデプロイは、GitLab Kubernetes Agent と呼ばれる、Agent を Kubernetes Cluster に導入して Agent 経由でデプロイする方法と、Helm chart を用いて、Runner のみを Kubernetes Cluster にデプロイする方法の2つがあります。

Helm Chart リポジトリはこちらです。
Chart.yaml をみてみましょう。

Chart.yaml
apiVersion: v1
name: gitlab-runner
version: 0.35.0
appVersion: 14.5.0
description: GitLab Runner
keywords:
- git
- ci
- deploy
sources:
- https://hub.docker.com/r/gitlab/gitlab-runner/
- https://docs.gitlab.com/runner/
icon: https://gitlab.com/uploads/-/system/project/avatar/250833/runner_logo.png
maintainers:
- name: GitLab Inc.
  email: [email protected]

12/11現在の、安定板 Chart バージョンは 0.35.0 で、だいたい毎月20日前後にマイナーバージョンが更新されています。
なお、Chart.yaml に併記されている appVersion は values.yaml で image 名を上書かないかぎり、デプロイされるgitlab/gitlab-runner image の tag バージョンに使用されます。

gitlab/gitlab-runner:alpine-v14.5.0

Kubernetes Executor の設定項目

Helm Chart の values.yaml を中心に、Kubernetes Executor の設定項目を見ていこうと思います。
GitLab Runner の Helm Chart values.yaml には、GitLab Runner Pod の設定と、Job 毎に生成される Job Pod の設定の両方が記載されています。

GitLab Runner Pod 自体の設定項目

  • gitlabUrl
    • GitLab Runner が問い合わせる GitLab インスタンスの URL を指定します
values.yaml
## The GitLab Server URL (with protocol) that want to register the runner against
## ref: https://docs.gitlab.com/runner/commands/README.html#gitlab-runner-register
##
# gitlabUrl: http://gitlab.your-domain.com/
  • runnerRegistrationToken
    • GitLab Runner を GitLab インスタンスに登録するためのトークンです
    • サブグループやリポジトリ単位で異なり、CI/CD Settings 画面の Runners セクションから取得できます
    • サブグループやリポジトリのトークンを使用することで、Runner の使用をそのサブグループ下、リポジトリなど任意のスコープに限定することができます
values.yaml
## The Registration Token for adding new Runners to the GitLab Server. This must
## be retrieved from your GitLab Instance.
## ref: https://docs.gitlab.com/ce/ci/runners/README.html
##
# runnerRegistrationToken: ""
  • concurrent
    • この GitLab Runner が生成し、同時に実行できるジョブの数を制限します
    • 値10は、同時に実行できるジョブが10個以下であることを意味しています
values.yaml
## Configure the maximum number of concurrent jobs
## ref: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section
##
concurrent: 10
  • rbac.rules
    • この GitLab Runner で実行されるジョブにどれだけの権限を与えるか細かく設定可能です
values.yaml
  ## Define list of rules to be added to the rbac role permissions.
  ## Each rule supports the keys:
  ## - apiGroups: default "" (indicates the core API group) if missing or empty.
  ## - resources: default "*" if missing or empty.
  ## - verbs: default "*" if missing or empty.
  rules: []
  • rbac.clusterWideAccess
    • この GitLab Runner で実行されるジョブのアクセス範囲を、Cluster 全体とするか、GitLab Runner がデプロイされている namespace に閉じるか、選択します
values.yaml
  ## Run the gitlab-bastion container with the ability to deploy/manage containers of jobs
  ## cluster-wide or only within namespace
  clusterWideAccess: false
  • runners.config
    • この GitLab Runner が生成する Job Pod の設定をここで実施します
    • 詳しくは次のセクションで説明します
values.yaml
## Configuration for the Pods that the runner launches for each new job
##
runners:
  # runner configuration, where the multi line strings is evaluated as
  # template so you can specify helm values inside of it.
  #
  # tpl: https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function
  # runner configuration: https://docs.gitlab.com/runner/configuration/advanced-configuration.html
  config: |
    [[runners]]
      [runners.kubernetes]
        namespace = "{{.Release.Namespace}}"
        image = "ubuntu:16.04"

values.yaml の中には DEPRECATED: See https://docs.gitlab.com/runner/install/kubernetes.html#additional-configuration と書かれている箇所が多々あります。
以前は、yaml の中に直接設定を記述することで、それぞれの機能を実現していましたが、最近はここ runners.config に config.toml に従って、設定を記述する方向にシフトしているようです。機能が増えるごとに template のメンテナンスが必要となることや、より柔軟な設定ができるようにすることが目的だと思います。

生成される Job Pod の設定項目

生成される Job Pod の設定は、values.yaml の runners.config に toml ファイルのフォーマットで記述していきます。
ここにも、Kubernetes Executor ならではの設定がありますので、いくつか見ていきます。

まず1つ目が各種リソースクォータです。
下記のように、Job Pod に対して、 cpu / memory に request / limit を設定することができます。

[[runners]]
  executor = "kubernetes"
  [runners.kubernetes]
    cpu_limit = "1000m"
    cpu_limit_overwrite_max_allowed = "2000m"
    cpu_request = "100m"
    cpu_request_overwrite_max_allowed = "1000m"
    service_cpu_request = "100m"
    service_cpu_request_overwrite_max_allowed = "1000m"
    memory_limit = "2Gi"
    memory_request = "128Mi"
    memory_request_overwrite_max_allowed = "2Gi"
    service_memory_request = "256Mi"
    service_memory_request_overwrite_max_allowed = "2Gi"

ここで面白いのが、*_overwrite_max_allowed という名前の設定群です。
特定のリポジトリで実行されるパイプラインのみ、必要とするリソース量が多い場合などに対応するため、overwrite する仕組みが設けられています。
例えば何も設定しない場合のリソースリクエストは *_request ですが、 *_request_overwrite_max_allowed の設定は、リポジトリごとで overwrite できるリクエストの最大値を規定しています。

リポジトリ側では、.gitlab-ci.yml に下記のように overwrite したい値を変数で設定することで、そのコンテナのリソースクォータを上書きすることができます。

.gitlab-ci.yml
 variables:
   KUBERNETES_CPU_REQUEST: 1               # build container
   KUBERNETES_CPU_LIMIT: 2                 # build container
   KUBERNETES_MEMORY_REQUEST: 1Gi          # build container
   KUBERNETES_SERVICE_CPU_REQUEST: 1       # service container
   KUBERNETES_SERVICE_MEMORY_REQUEST: 2Gi  # service container

更に、.gitlab-ci.yml で overwrite 可能な設定はリソースクォータだけではなく、下記のように使用する service account や Job Pod がデプロイされる namespace、pod annotation まで overwrite させることができます。

[[runners]]
  executor = "kubernetes"
  [runners.kubernetes]
    service_account_overwrite_allowed = ".*"
    namespace_overwrite_allowed = "ci-.*"
    pod_annotations_overwrite_allowed = ".*"

それぞれリポジトリ側で .gitlab-ci.yml を下記のように記述し、overwrite できます。

.gitlab-ci.yml
variables:
  KUBERNETES_SERVICE_ACCOUNT_OVERWRITE: ci-service-account
  KUBERNETES_NAMESPACE_OVERWRITE: ci-${CI_COMMIT_REF_SLUG}
  KUBERNETES_POD_ANNOTATIONS_1: "Key1=Val1"

また、toleration や、node selector も記述することとができるため、Job Pod の生成される Node Pool を制限することも可能です。

[[runners]]
  executor = "kubernetes"
  [runners.kubernetes]
    [runners.kubernetes.node_selector]
      dedicated = "ops"
    [runners.kubernetes.node_tolerations]
      "app=ops" = "NoSchedule"

その他にも、例えば host パス、pvc、config map、secret、empty dir のボリュームマウントをして CICD の中で利用することや、Job Pod に Security Context を設定すること、Pod affinity を設定すること、life cycle hook を設定することなどなどが可能なようですが、今回はここまでにしたいと思います

まとめ

GitLab Runner の Kubernetes Executor について、その構成と設定内容の一例をご紹介しました。
今回紹介したもの以外にも、まだ試したことのない面白い設定がたくさんあるので、もっといろいろ試してみたいと思います。
ここまで読んでいただきありがとうございましたー