KubernetesクラスタでGitLab CI/CDを使用する場合

  • GitLab 14.1 で導入されました
  • GitLab 14.2 で導入された設定済み変数$KUBECONFIG.
  • GitLab 14.3 でci_access 属性を導入
  • GitLab 14.3でグループの作成者を認証する機能が導入れました。
  • 14.5でGitLab Freeに移行
  • GitLab 14.5でLinuxパッケージのインストールをサポートしました
  • GitLab 14.9 で、証明書ベースのクラスターとエージェントを切り替える機能が導入されました。証明書ベースのクラスター・コンテキストは常にgitlab-deploy と呼ばれます。
  • GitLab 14.9で_CI/CDトンネルから_ CI/CDワークフローに名前が変更されました。

GitLab CI/CDワークフローを使って、Kubernetesクラスターへのデプロイやアップデートを安全に行うことができます。

そのためには、まずエージェントをクラスターにインストールする必要があります。インストールが完了すると、Kubernetesコンテキストができ、GitLab CI/CDパイプラインでKubernetes APIコマンドを実行できるようになります。

クラスターへのアクセスを安全にするために

  • 各エージェントは個別のコンテキスト(kubecontext)を持っています。
  • エージェントが設定されているプロジェクトと、作成者が追加したプロジェクトだけが、クラスター内のエージェントにアクセスできます。

CI/CD ワークフローではランナーを GitLab に登録する必要がありますが、これらのランナーはエージェントがあるクラスターにいる必要はありません。

GitLab CI/CDワークフローのステップ

GitLab CI/CDを使ってKubernetesクラスターをアップデートするには、以下の手順を実行します。

  1. Kubernetesクラスターが動作し、マニフェストがGitLabプロジェクトにあることを確認します。
  2. 同じGitLabプロジェクトで、GitLabエージェントを登録し、インストールします。
  3. .gitlab-ci.yml ファイル を更新して、エージェントのKubernetesコンテキストを選択し、Kubernetes APIコマンドを実行します。
  4. パイプラインを実行してクラスターにデプロイまたは更新します。

Kubernetesマニフェストを含む複数のGitLabプロジェクトがある場合:

  1. GitLabエージェントを独自のプロジェクト、またはKubernetesマニフェストを保管しているGitLabプロジェクトの1つにインストールしてください。
  2. エージェントがGitLabプロジェクトにアクセスできるように作成者を認証します。
  3. オプションです。セキュリティを強化するには、なりすましを使用します。
  4. .gitlab-ci.yml ファイル を更新して、エージェントの Kubernetes コンテキストを選択し、Kubernetes API コマンドを実行します。
  5. パイプラインを実行してクラスターにデプロイまたは更新します。

エージェントの作成者

複数のGitLabプロジェクトがある場合、Kubernetesマニフェストを保存しているプロジェクトにアクセスできるようにエージェントを作成者に認可する必要があります。エージェントが個々のプロジェクトにアクセスできるように権限を与えることもできますし、グループやサブグループに権限を与えて、その中のすべてのプロジェクトがアクセスできるようにすることもできます。セキュリティを強化するために、なりすましを使用することもできます。

権限設定には、伝播に1~2分かかることがあります。

エージェントがプロジェクトにアクセスすることを許可します。

  • GitLab 14.4で導入されました
  • GitLab 15.6で階層の制限を取り除くように変更
  • GitLab 15.7でユーザーネームスペース内のプロジェクトの作成者を許可するように変更

Kubernetesマニフェストを保管しているGitLabプロジェクトにエージェントがアクセスできるように作成者を認証するには:

  1. 左サイドバーで、Search を選択するか、または go to を選択して、エージェント設定ファイル(config.yaml) を含むプロジェクトを見つけます。
  2. config.yaml ファイルを編集します。ci_access キーワードの下に、projects 属性を追加します。
  3. id には、プロジェクトへのパスを追加します。パスを引用符で囲まないでください。

    ci_access:
      projects:
        - id: path/to/project
    
    • 作成者は、エージェントの設定プロジェクトと同じルートグループまたはユーザーネーム空間を持っている必要があります。
    • 同じクラスターにさらにエージェントをインストールして、階層を増やすことができます。
    • 最大100のプロジェクトを作成できます。

すべての CI/CD ジョブは、kubeconfig すべての共有エージェント接続のコンテキストを含むファイルを kubeconfig含むようになりました。kubeconfig パスは kubeconfig環境変数$KUBECONFIG で利用可能です。CI/CD スクリプトからkubectl コマンドを実行するコンテキストを選択します。

エージェントがグループのプロジェクトにアクセスできるように作成者を許可します。

エージェントがグループまたはサブグループ内のすべてのGitLabプロジェクトにアクセスすることを作成者に許可するには:

  1. 左サイドバーで、Search を選択するか、または go to を選択して、エージェント設定ファイル(config.yaml) を含むプロジェクトを見つけます。
  2. config.yaml ファイルを編集します。ci_access キーワードの下に、groups 属性を追加します。
  3. id に、パスを追加します:

    ci_access:
      groups:
        - id: path/to/group/subgroup
    
    • 作成者は、エージェントの設定プロジェクトと同じルートグループを持っている必要があります。
    • 同じクラスターにさらにエージェントをインストールして、階層を増やすことができます。
    • 作成者グループのすべてのサブグループも同じエージェントにアクセスできます(個別に指定する必要はありません)。
    • 最大100グループまで作成することができます。

グループとそのサブグループに属するすべてのプロジェクトは、エージェントへのアクセス権限が付与されます。すべての CI/CD ジョブは、kubeconfig すべての共有エージェント接続のコンテキストを含むファイルを kubeconfig含むようになりました。kubeconfig パスは kubeconfig環境変数$KUBECONFIG で利用可能です。CI/CD スクリプトからkubectl コマンドを実行するコンテキストを選択します。

kubectl コマンドを実行するために.gitlab-ci.yml ファイルを更新してください。

Kubernetesコマンドを実行したいプロジェクトで、プロジェクトの.gitlab-ci.yml ファイルを編集します。

script キーワードの下の最初のコマンドで、エージェントのコンテキストを設定します。path/to/agent/repository:agent-name.例えば

deploy:
  image:
    name: bitnami/kubectl:latest
    entrypoint: ['']
  script:
    - kubectl config get-contexts
    - kubectl config use-context path/to/agent/repository:agent-name
    - kubectl get pods

エージェントのコンテキストがわからない場合は、ターミナルを開き、クラスターに接続します。kubectl config get-contexts を実行します。

Auto DevOpsを使用する環境

Auto DevOpsが有効な場合、CI/CD変数KUBE_CONTEXT.の値を KUBE_CONTEXTAuto DevOps に使用させたいエージェントのコンテキストにKUBE_CONTEXT設定 KUBE_CONTEXTします:

deploy:
  variables:
    KUBE_CONTEXT: <path_to_agent_config_repository>:<agent_name>

異なるエージェントを別々のAuto DevOpsジョブに割り当てることができます。インスタンスンスでは、Auto DevOpsはstaging ジョブに1つのエージェントを使用し、production ジョブに別のエージェントを使用することができます。複数のエージェントを使用するには、各エージェントに対して環境スコープのCI/CD変数を定義します。例えば

  1. KUBE_CONTEXT という名前の変数を2つ定義します。
  2. 最初の変数には
    1. environmentstagingに設定します。
    2. 値をステージングエージェントのコンテキストに設定します。
  3. つ目の変数には
    1. environmentproductionに設定します。
    2. 値を本番エージェントのコンテキストに設定します。

証明書ベースとエージェントベースの両方の接続を持つ環境

証明書ベースのクラスター(非推奨)とエージェント接続の両方を持つ環境にデプロイする場合:

  • 証明書ベースのクラスタのコンテキストはgitlab-deploy と呼ばれます。このコンテキストはデフォルトで常に選択されています。
  • GitLab 14.9以降では、エージェントコンテキストは$KUBECONFIG に含まれています。kubectl config use-context path/to/agent/repository:agent-name を使って選択することができます。
  • GitLab 14.8以前では、エージェント接続を使うことはできますが、すでに証明書ベースのクラスターを持っている環境では、エージェント接続は$KUBECONFIG に含まれていません。

証明書ベースの接続があるときにエージェント接続を使うには、手動で新しいkubectl 設定コンテキストを設定します。例えば

deploy:
  variables:
    KUBE_CONTEXT: my-context # The name to use for the new context
    AGENT_ID: 1234 # replace with your agent's numeric ID
    K8S_PROXY_URL: https://<KAS_DOMAIN>/k8s-proxy/ # For agent server (KAS) deployed in Kubernetes cluster (for gitlab.com use kas.gitlab.com); replace with your URL
    # K8S_PROXY_URL: https://<GITLAB_DOMAIN>/-/kubernetes-agent/k8s-proxy/ # For agent server (KAS) in Omnibus
    # ... any other variables you have configured
  before_script:
    - kubectl config set-credentials agent:$AGENT_ID --token="ci:${AGENT_ID}:${CI_JOB_TOKEN}"
    - kubectl config set-cluster gitlab --server="${K8S_PROXY_URL}"
    - kubectl config set-context "$KUBE_CONTEXT" --cluster=gitlab --user="agent:${AGENT_ID}"
    - kubectl config use-context "$KUBE_CONTEXT"
  # ... rest of your job configuration

自己署名証明書を使用するKASのある環境

KASと自己署名証明書を使用する環境を使用する場合は、証明書に署名した認証局(CA) を信頼するようにKubernetesクライアントを設定する必要があります。

クライアントを設定するには、以下のいずれかを実行します:

  • CI/CD 変数SSL_CERT_FILE に PEM 形式の KAS 証明書を設定します。
  • --certificate-authority=$KAS_CERTIFICATE でKubernetesクライアントを設定します。KAS_CERTIFICATE はKASのCA証明書を持つCI/CD変数です。
  • コンテナイメージを更新するか、Runner経由でマウントすることで、証明書をジョブコンテナの適切な場所に配置します。
  • 推奨しません。Kubernetes クライアントを--insecure-skip-tls-verify=true で設定します。

なりすましを使用してプロジェクトとグループのアクセスを制限します。

  • GitLab 14.5 で導入されました
  • GitLab 15.5で変更され、環境ティアのインパーソネーションのサポートが追加されました。

デフォルトでは、CI/CDジョブはエージェントをクラスターにインストールする際に使用したサービスアカウントからすべての権限を継承します。クラスターへのアクセスを制限するために、インパーソネーションを使うことができます。

なりすましを指定するには、エージェント設定ファイルでaccess_as 属性を使用し、Kubernetes RBACルールを使用してなりすましアカウントの権限を管理します。

なりすましが可能です:

  • エージェント自身 (デフォルト)。
  • クラスターにアクセスする CI/CD ジョブ。
  • クラスター内で定義された特定のユーザーまたはシステムアカウント。

権限設定には、伝播に1~2分かかることがあります。

エージェントになりすます

エージェントはデフォルトで偽装されています。偽装するために何もする必要はありません。

クラスターにアクセスする CI/CD ジョブを偽装します。

クラスターにアクセスするCI/CDジョブをインパーソネートするには、access_as キーの下に、ci_job: {} key-valueを追加します。

エージェントが実際のKubernetes APIにリクエストを行うと、次のようになりすまし認証情報を設定します:

  • UserNamegitlab:ci_job:<job id> に設定されます。 例:gitlab:ci_job:1074499489.
  • Groups に設定されます:

    • gitlab:ci_job に設定すると、CIジョブからのすべてのリクエストを識別します。
    • プロジェクトが所属するグループのIDのリストです。
    • プロジェクトID。
    • このジョブが属する環境のスラッグと階層。

      例:group1/group1-1/project1 の CI ジョブの場合:

      • グループgroup1 の ID は 23 です。
      • グループgroup1/group1-1 の ID は 25 です。
      • プロジェクトgroup1/group1-1/project1 の ID は 150 です。
      • ジョブはproduction 環境階層を持つprod 環境で実行されています。

    グループリストは[gitlab:ci_job, gitlab:group:23, gitlab:group_env_tier:23:production, gitlab:group:25, gitlab:group_env_tier:25:production, gitlab:project:150, gitlab:project_env:150:prod, gitlab:project_env_tier:150:production] になります。

  • Extra はリクエストに関する追加情報を提供します。以下のプロパティがなりすましIDに設定されます:
物件概要説明
agent.gitlab.com/idエージェントIDをコンテナします。
agent.gitlab.com/config_project_idエージェントの設定プロジェクト ID を含みます。
agent.gitlab.com/project_idCI プロジェクト ID を含みます。
agent.gitlab.com/ci_pipeline_idCI パイプライン ID をコンテナで指定します。
agent.gitlab.com/ci_job_idCI ジョブ ID。
agent.gitlab.com/usernameCI ジョブが実行されているユーザーのユーザー名をコンテナで指定します。
agent.gitlab.com/environment_slug環境のスラッグを含みます。環境で実行されている場合のみ設定されます。
agent.gitlab.com/environment_tier環境の階層をコンテナで指定します。環境で動作している場合のみ設定されます。

config.yaml CI/CD ジョブの ID でアクセスを制限する場合:

ci_access:
  projects:
    - id: path/to/project
      access_as:
        ci_job: {}

CI/CDジョブを制限するRBACの例

次のRoleBinding リソースは、すべての CI/CD ジョブを閲覧権限のみに制限します。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ci-job-view
roleRef:
  name: view
  kind: ClusterRole
  apiGroup: rbac.authorization.k8s.io
subjects:
  - name: gitlab:ci_job
    kind: Group

静的アイデンティティのなりすまし

指定した接続に対して、静的な ID を使用してなりすますことができます。

access_as キーの下にimpersonate キーを追加して、提供された ID を使ってリクエストを行います。

IDは以下のキーで指定できます:

  • username (必須)
  • uid
  • groups
  • extra

詳細はKubernetesの公式ドキュメントを参照してください。

特定の環境へのプロジェクトやグループのアクセス制限

GitLab 15.7 で導入されました

デフォルトでは、エージェントがプロジェクトで利用可能な場合、プロジェクトのすべてのCI/CDジョブがそのエージェントを利用できます。

特定の環境を持つジョブだけにエージェントへのアクセスを制限するには、ci_access.projects またはci_access.groupsenvironments を追加します。例えば

ci_access:
  projects:
    - id: path/to/project-1
    - id: path/to/project-2
      environments:
        - staging
        - review/*
  groups:
    - id: path/to/group-1
      environments:
        - production

この例では:

  • project-1 以下のすべての CI/CD ジョブはエージェントにアクセスできます。
  • staging またはreview/* 環境のproject-2 以下の CI/CD ジョブはエージェントにアクセスできます。
    • * はワイルドカードなので、review/*review 以下のすべての環境にマッチします。
  • production 環境を持つgroup-1 以下のプロジェクトの CI/CD ジョブはエージェントにアクセスできます。

トラブルシューティング

書き込み権限を~/.kube/cache

kubectl 、Helm、kpt 、およびkustomize のようなツールは、~/.kube/cacheにクラスターに関する情報をキャッシュします。このディレクトリが書き込み可能でない場合、ツールは呼び出すたびに情報を取得するため、インタラクションが遅くなり、クラスターに不要な負荷がかかります。最高のエクスペリエンスを得るには、.gitlab-ci.yml ファイルで使用するイメージで、このディレクトリが書き込み可能であることを確認してください。

TLSを有効にします。

セルフマネジメントのGitLabインスタンスを使用している場合は、インスタンスがトランスポート・レイヤー・セキュリティ(TLS) で設定されていることを確認してください。

TLS なしでkubectl を使おうとすると、次のようなエラーが出るかもしれません:

$ kubectl get pods
error: You must be logged in to the server (the server has asked for the client to provide credentials)

サーバーに接続できません: 証明書の作成者が不明です。

KASと自己署名証明書がある環境を使用している場合、kubectl の呼び出しがこのエラーを返すことがあります:

kubectl get pods
Unable to connect to the server: x509: certificate signed by unknown authority

このエラーは、ジョブがKAS証明書に署名した認証局(CA) を信頼していないために発生します。

このイシューを解決するには、 kubectl 、CA を信頼するように設定します。

検証エラー

kubectl v1.27.0またはv.1.27.1を使用している場合、以下のエラーが発生する可能性があります:

error: error validating "file.yml": error validating data: the server responded with the status code 426 but did not return more information; if you choose to ignore these errors, turn validation off with --validate=false

このイシューは、kubectl および共有 Kubernetes ライブラリを使用するその他のツールのバグが原因です。

イシューを解決するには、別のバージョンのkubectl を使用してください。