【GitLab 公式 を訳してみた】Kubernetes エクゼキュータ

法律: IT 解説記事 GitLab CI コンテナ フノス(訳者) マニュアル

 GitLab Runner>エクゼキュータ>Kubernetesエクゼキュータ

目次
>概要
>全体の作業工程
>Kubernetes APIに接続する

>キーワード
 >エクゼキュータ・サービスアカウントを設定する
 >Kubernetesの名前空間を上書きする
 >デフォルトのKubernetesサービスアカウントを上書きする
 >ベアラトークンの設定(Kubernetes APIを呼び出すときに必要)
 >Podアノテーションを上書きする
>「config toml」ファイルから、キーワードを定義する

>ボリュームを使う
 >hostPathボリューム
 >PVCボリューム
 >Config Mapボリューム
 >Secretボリューム
 >Empty Dirボリューム

>Dockerをビルドに使う上での注意点
 >「/var/run/docker.sock」が外部に公開されてしまうリスク
 >「docker:dind」を使うリスク
 >gitが適用されない問題
 >リソースの分割で生じる問題

 

  GitLab ランナーでは、kubernetesクラスター上でアプリをビルドする際に、Kubernetesを利用することができます。
 ただし、それにはKubernetesエクゼキュータの利用が必須です。

  DockerエクゼキュータがGitLab CIで使用された場合、ランナーはクラスター内のKubernetes APIへ接続します。そこではGitLab CIに課せられたそれぞれのjobに対して、podが作成されます。
 Podとは、とてもかいつまんでいえば、ビルドコンテナにサービス(GitLab CI yaml の serviceで定義可能)などの追加コンテナを付属させたものです。

 これらのコンテナには、それぞれ名前があります。


 これらのコンテナが同じKubernetes podに入っているため、ローカルホストアドレスはどちらも同じ扱いになります。
 アクセスするには、次の要件にご注意ください。


 全体の作業工程

  Kubernetesエクゼキュータでビルドする際には、大まかに次のような手順を踏みます。

  1. 準備:KubernetesクラスターでPodを作成する。ここでビルド用とサービス用のコンテナが作成される。
  2. ビルド前:キャッシュをクローン、リストアして、前のステージからアーティファクトをダウンロードしてくる。これはPodに付属している専用コンテナ上で実行される。
  3. ビルド:ユーザービルド。
  4. ビルド後:キャッシュを作成し、GitLabにアーティファクトをアップロードする。この工程もPodに付属している専用コンテナ上で実行される。



 Kubernetes APIに接続する

  Kubernetes APIに接続するには、次の要件を満たしてください。


 ユーザーアカウントには、権限認証を取り付けなくてはいけません。このあたりの設定は、Pods側の名前空間を指定する機能で補うことができるでしょう。

  もしも、GitLab CI Runnerそのものが、Kubernetes クラスターの中にインストールされていた場合は、上記の設定がなくてもランナーがKubernetes APIを自動で発見してくれるので、安心です。
 Kubernetesを継続的に使用する開発形態なら、ランナーもKubernetesクラスター内に設置しておいた方がそつがないといえます。

 クラスター外からビルドを実施する場合は、ランナーがクラスター内Kubernetes APIに到達できるように、上記のキーワードをランナー側にあらかじめ設定しておくことが大切です。

 

  キーワード

  Kubernetes内で動かしているランナーなら、次のキーワードが役に立つはずです。


  エクゼキュータ・サービスアカウントを設定する

 これは先ほど登場した「KUBERNETES_SERVICE_ACCOUNT」環境変数か、「--service-account」フラグを使うことで設定できます。

 

  Kubernetesの名前空間を上書きする

  ちなみに、Kubernetes の名前空間は、「gitlab-ci.yml」から変更可能です。
 その際に使用する環境変数は、「KUBERNETES_NAMESPACE_OVERWRITE」です。

  名前空間の扱いを可変にしておくことで、CIにの目的に応じて独立した権限を作り上げたり、ポッドのセットを作成してデプロイするのは誰にするかなど、プロジェクトの役割を明確にできます。
 ランナーによって作成されたPodは、名前空間を書き換えます。これによって、CIステージ間で発生するコンテナ間のアクセスが、より無駄なく明確に区別されるようになります。

======================
variables:
 KUBERNETES_NAMESPACE_OVERWRITE: ci-${CI_COMMIT_REF_NAME}
======================

  さらに、名前空間を作成しておくだけで、CIの運用はその名義で実施されるようになります。「namespace_overwrite_allowed」は正規表現で設定しますので、変更も簡単です。この設定を放っておくと、それらの操作ができません。

 

  デフォルトのKubernetesサービスアカウントを上書きする

  Kubernetes のサービスアカウントは、「gitlab-ci.yml」から変更可能です。 
 その際に使用する環境変数は、「KUBERNETES_SERVICE_ACCOUNT_OVERWRITE」です。

  この設定は、名前空間とサービスアカウントを関連付けることによく使われます。
 特に、ロールベースアクセス制御の設定を簡略化するときなどに有効です。

======================
variables:
 KUBERNETES_SERVICE_ACCOUNT_OVERWRITE: ci-service-account
======================

  名前空間を上書きして、クラスター内のRBAC設定をする際に、ぜひお使いください。

  さらに、サービスアカウントを設定しておくだけで、CIの運用はその名義で実施されるようになります。「KUBERNETES_SERVICE_ACCOUNT_OVERWRITE_ALLOWED」は、正規表現で設定します。
 この設定を放っておくと、これらの操作ができません。

 

  ベアラトークンの設定(Kubernetes APIを呼び出すときに必要)

  この設定は、名前空間と、サービスアカウントの設定を済ませた状態で取り組んでください。
 Kubernetesはビルドポッドを作成する際に、APIを呼び出します。そのAPIを呼び出すのに、ベアラトークンが必要です。
 これは、プロジェクトの所有者が、プロジェクトの秘密変数として制定するのが望ましいとされます。
 ※ベアラトークンの設定前に、Host コンフィグキーワードを指定しておいてください。
 

======================
variables:
 KUBERNETES_BEARER_TOKEN: thebearertokenfromanothernamespace(外部名前空間から指定した、ベアラトークン)
======================

 

  Podアノテーションを上書きする

  Kubernetes のPodアノテーションは、「gitlab-ci.yml」から変更可能です。
その際に使用する環境変数は、「KUBERNETES_POD_ANNOTATIONS_*」です。そこに「key=value」という数値を用いて設定します。

  Podのアノテーションは「key=value」を変更することで上書きできます。

  同時に複数のアノテーションを設定することも可能です。

======================
variables:
 KUBERNETES_POD_ANNOTATIONS_1: "Key1=Val1"
 KUBERNETES_POD_ANNOTATIONS_2: "Key2=Val2"
 KUBERNETES_POD_ANNOTATIONS_3: "Key3=Val3"
======================

 

  「config toml」ファイルから、キーワードを定義する

 
全てのキーワードをGitLab ランナーの「config.toml」で指定すると、プロジェクトでの設定が一斉に済ませられます。

「config.toml」設定例:

============================================
concurrent = 4
 [[runners]]
  name = "Kubernetes Runner"
  url = "https://gitlab.com/ci"
  token = "......"
  executor = "kubernetes"
  [runners.kubernetes]
   host = "https://45.67.34.123:4892"
   cert_file = "/etc/ssl/kubernetes/api.crt"
   key_file = "/etc/ssl/kubernetes/api.key"
   ca_file = "/etc/ssl/kubernetes/ca.crt"
   namespace = "gitlab"
   namespace_overwrite_allowed = "ci-.*"
   bearer_token_overwrite_allowed = true
   privileged = true
   cpu_limit = "1"
   memory_limit = "1Gi"
   service_cpu_limit = "1"
   service_memory_limit = "1Gi"
   helper_cpu_limit = "500m"
   helper_memory_limit = "100Mi"
   poll_interval = 5
   poll_timeout = 3600
   [runners.kubernetes.node_selector]
    gitlab = "true"
============================================

 

  ボリュームを使う

  端的にいえば、この設定は、ビルドコンテナを特定のボリュームにマウントさせることが目的です。
 hostPath、PVC、configMap、Kubernetesの Secretボリュームに対応しています。
 これらのボリュームにつきましては、いくつ使っても構いません。(種類さえ合っていれば、量的なことは問われません。)
 

  設定例:

============================================
concurrent = 4

 [[runners]]
  # usual configuration
  executor = "kubernetes"
  [runners.kubernetes]
   [[runners.kubernetes.volumes.host_path]]
   name = "hostpath-1"
   mount_path = "/path/to/mount/point"
   read_only = true
   host_path = "/path/on/host"
   [[runners.kubernetes.volumes.host_path]]
    name = "hostpath-2"
    mount_path = "/path/to/mount/point_2"
    read_only = true
    [[runners.kubernetes.volumes.pvc]]
     name = "pvc-1"
     mount_path = "/path/to/mount/point1"
     [[runners.kubernetes.volumes.config_map]]
      name = "config-map-1"
      mount_path = "/path/to/directory"
       [runners.kubernetes.volumes.config_map.items]
       "key_1" = "relative/path/to/key_1_file"
       "key_2" = "key_2"
       [[runners.kubernetes.volumes.secret]]
        name = "secrets"
        mount_path = "/path/to/directory1"
        read_only = true
        [runners.kubernetes.volumes.secret.items]
         "secret_1" = "relative/path/to/secret_1_file"
         [[runners.kubernetes.volumes.empty_dir]]
          name = "empty_dir"
          mount_path = "/path/to/empty_dir"
          medium = "Memory"
============================================

 

  hostPathボリューム

  hostPathボリュームは、Kubernetesに対し、Pod内のコンテナからどのホストパスをマウントするかを指定する項目です。

 

オプション 種類 必須か 説明
name string yes ボリューム名
mount_path string yes コンテナがマウントすべきボリュームにパスを設ける
host_path string no ボリュームとしてマウントさせたいホストのパス。これが指定されなかった場合は、「mount_path」が代わりに使われる
read_only boolean no ボリュームを読み込み限定モードにするかどうか(デフォルトでは『false』)

 

 

  PVCボリューム

  PVCボリュームは、Kubernetesに対し、どのPersistentVolumeClaimを使用するかを指定する項目です。このボリュームはKubernetes内で具体的に定義され、コンテナの内部にマウントされるものです。

 

オプション 種類 必須か 説明
name string yes ボリューム名兼、「PersistentVolumeClaim」名として使われる
mount_path string yes コンテナがマウントすべきボリュームにパスを設ける
read_only boolean no リュームを読み込み限定モードにするかどうか(デフォルトでは『false』)

 

 

  Config Mapボリューム

  ConfigMapボリュームは、Kubernetesに対し、どのconfigMapを使用するかを指定する項目です。このボリュームはKubernetesクラスター内で具体的に定義され、コンテナの内部にマウントされるものです。

 

オプション 種類 必須か 説明
name string yes ボリューム名兼、「configMap」名として使われる
mount_path string yes コンテナがマウントすべきボリュームにパスを設ける
read_only boolean no リュームを読み込み限定モードにするかどうか(デフォルトでは『false』)
items map[string]string no configMapの鍵にKey-to-path mapping を使うかどうかを設定する

 

  configMapボリュームを使用している際に、configMapから指定された鍵はそれぞれファイルに変換され、特定のマウントパスが組まれているディレクトリに格納されます。

  デフォルトの設定でも鍵の管理法は定められており、configMapキーが変換されるファイル名は、そのまま設定用の数値として扱うことができます。

  デフォルトの設定は、「items」オプションで変更可能です。
 

  「items」オプションは、鍵同士のマッピングを定義します。これらは実際に鍵としても使われますし、configMapの数値を保存している場所へのパス(ボリュームのマウントパス関連)としても扱われます。

  「items」オプションでは指定された鍵のみを対象とし、ボリュームを追加することの他には、全項目がスキップされます。

 注:期限が切れた鍵でjobを実施しようとすると、Podを作成する段階で失敗します。


 

  Secretボリューム

  Secretボリュームは、Kubernetesに対し、どの「secret」を使用するかを指定する項目です。このボリュームはKubernetes内で具体的に定義され、コンテナの内部にマウントされるものです。

 

オプション 種類 必須か 説明
name string yes ボリューム名兼、「secret」名として使われる
mount_path string yes コンテナがマウントすべきボリュームにパスを設ける
read_only boolean no ボリュームを読み込み限定モードにするかどうか(デフォルトでは『false』)
items map[string]string no secretの鍵にKey-to-path mapping を使うかどうかを設定する

 

  secretボリュームを使用している際に、configMapから指定された鍵はそれぞれファイルに変換され、特定のマウントパスが組まれているディレクトリに格納されます。

  デフォルトの設定でも鍵の管理法は定められており、secretキーが変換されたファイル名は、そのまま設定用の数値として扱うことができます。

  デフォルトの設定は、「items」オプションで変更可能です。
 

  「items」オプションは、鍵同士のマッピングを定義します。これらは実際に鍵としても使われますし、secretの数値を保存している場所へのパス(ボリュームのマウントパス関連)としても扱われます。

  「items」オプションでは指定された鍵のみを対象とし、ボリュームを追加することの他には、全項目がスキップされます。

 注:期限が切れた鍵でjobを実施しようとすると、Podを作成する段階で失敗します。


 

  Empty Dirボリューム

  emptyDirボリュームは、Kubernetesに対し、コンテナの中からどの空ディレクトリをマウントするかを指定する項目です。

 

オプション 種類 必須か 説明
name string yes ボリューム名
mount_path string yes コンテナがマウントすべきボリュームにパスを設ける
medium String no "Memory" をtmpfsに配置させる設定。そのままではノードディスクストレージに格納されている(デフォルトでは"")

 

 

  Dockerをビルドに使う上での注意点

  Kubernetesクラスターが動作している状態で、ビルドにDockerコンテナを使う場合ですが、2つほど注意点がございます。
 ほとんどの手順は、 gitlab-ci説明書の『Dockerでアプリをビルドする』というページに書いてある通りなのですが、
 Kubernetesクラスターでビルドをしていくとなると、少し事情が異なる部分が生じます。

 

  「/var/run/docker.sock」が外部に外部に公開されてしまうリスク

  「/var/run/docker.sock」が外部に公開されてしまう、とありますが、そこからビルドコンテナの内部までもを覗かれてしまうリスクがあるところが、さらに怖いところです。
 「runners.kubernetes.volumes.host_path」オプションを使用することも、同様のリスクが伴います。

 ビルドコンテナに関連しているコンテナが、同じクラスター内にある場合などは特に、このオプションがセキュリティリスクを高めてしまいます。

 

  docker:dind」を使うリスク

  「docker:dind」機能は、docker-in-dockerイメージを使用しているときに使われる機能で、これ自体はKubernetesと連携しているときにも使えます。しかし、コンテナが特権モードでしか動かせなくなってしまうところが難点です。
 あらゆるセキュリティルスクを考慮しなくてはならない状況では、この機能を手放しでお勧めできるわけではありません。
 理由として、ビルドにKubernetesを使用している状態で、「.gitlab-ci.yaml」からDockerデーモン(たいていserviceコンテナ)を使用する場合、Dockerコンテナと Kubernetes Podとは、別のコンテナとして扱われていることが挙げられます。
 Pod内にあるコンテナ同士は、ボリュームとIPアドレスを共有しており、やり取りがローカルホスト内で完結するようにできています。
 「docker:dind」コンテナは「/var/run/docker.sock」を共有していません。そこで、dockerバイナリは「/var/run/docker.sock」をなるべく使うようにデフォルトで設定されています。
 Dockerバイナリに使用させるファイルを変更するには、tcpを使って、Dockerデーモンと交信を試みます。ビルドコンテナの環境変数を「DOCKER_HOST=tcp://localhost:2375」などのように設定してください。

 

  gitが適用されない問題

  Kubernetesをビルドに使用した状態で、Dockerイメージにビルドを試みることは、無益です。KubernetesからはDockerイメージにgitを移植することができません。
 それでもjobを実行するには「GIT_STRATEGY=none」を環境変数に追加して、「fetch」や「clone」を必要としないビルド方法を考えるしかありません。
 ビルドに使われるPodは、長期にわたって使用されることを想定しておらず、jobを経るにつれてその内容が変わっていきます。コードのテストをした後、ビルド、Dockerサービスコンテナの立ち上げの時点で、それぞれ全く別のPodを使用していると考えてください。

 ビルド工程にKubernetesとDockerを併用していると、「could not find git binary」という、エラーが表示されることがよくあります。
 Dockerサービスからも、「symlinks」が発見できなかったなどと表示されることがあります。なぜなら、本来ビルドに必要なgitコードを発見できなかったからです。

 

  リソースの分割で生じる問題

  「docker:dind」、「/var/run/docker.sock」の双方の問題において、Dockerデーモンがホストマシンのカーネル最深部に、安易に接続しやすいことが深く関わっています。
 たとえPodにいかなる制約(limits)を設けたとしても、それがDockerイメージの特性でまったく意味を無さなくなることが十分にありうるのです。
 Dockerデーモンは与えられたノードの資源をいっぱいまで使い果たします。そこでは、Kubernetesから作成されたビルド用Dockerコンテナが、作成時点にどれだけ強固な制約をかけられていようと、無効化されてしまいます。
 

  対策の1つとして、ビルドコンテナにはホストカーネルにあまり触れさせないような工夫が必要です。とくに特権モードが必要な操作(『/var/run/docker.sock』の使用・外部への暴露)などには注意が必要です。
 ここで「node_selector」オプションを使うのは、あらかじめラベル数に制限を設けることで、コンテナに必要以上にノードを乱用していないかなど、不審な動きに一定の監視がつけられるからです。
 たとえば、他のサービスコンテナたちが何らかのノードを使用している間、ビルドコンテナには「role=ci」というラベルがあるノードでしか活動できないように設定できます。

 Edit this page

 

 2018-03-23 21:42:22 / Hnoss
原文サイトを表示
[ 原文 ] https://docs.gitlab.com/runner/executors/kubernetes.html
原文ページプロジェクト並びにドキュメントファイルは、MIT Licenseのもと公開されています。(URL:https://gitlab.com/gitlab-com/gitlab-docs/blob/master/LICENSE) この記事の文章は、訳者の判断によりCreative Commons BY (version 3.0) を適用するものとします。