Kubernetesインテグレーション開発ガイドライン

このドキュメントでは、GitLabKubernetesインテグレーションを開発する際の様々なガイドラインを提供します。

開発者向け

アーキテクチャ

制限されたプロジェクト名前空間の作成など、一部のKubernetesオペレーションはGitLab Railsアプリケーション上で実行されます。これらのオペレーションはクライアントライブラリを使用して実行され、リスクの要素を伴います。オペレーションはGitLab Railsアプリケーションを実行しているユーザーと同じユーザーとして実行されます。詳細については、以下のセキュリティセクションをお読みください。

クラスター・アプリケーションのインストールなど一部のKubernetesオペレーションは、Kubernetesクラスター自体の単発ポッドで実行されます。これらのインストールポッドはinstall-<application_name> という名前で、gitlab-managed-apps 名前空間内に作成されます。

コードの構成としては、一般的に、lib/gitlab/kubernetes にKubernetesリソースを表すオブジェクトを追加します。

クライアントライブラリ

KubernetesのAPIコールを行うために、kubeclient gemを使用しています。kubeclient gemは1つのクライアントから異なるAPIグループ(apis/rbac.authorization.k8s.ioなど)をサポートしないため、これを実現するラッパークラスGitlab::Kubernetes::KubeClient を作成しました。

一部のKubernetes APIグループがサポートされています。新しいAPIグループやメソッドを使用する必要がある場合は、Gitlab::Kubernetes::KubeClient 。新しいAPIグループまたはAPIグループのバージョンは、SUPPORTED_API_GROUPS - 内部的には、これはそのグループの内部クライアントを作成します。新しいメソッドは、関連する内部クライアントへのデリゲーションとして追加できます。

パフォーマンスに関する考慮事項

Kubernetes APIへの呼び出しはすべてバックグラウンドプロセスで行う必要があります。Webリクエスト内でKubernetes APIコールを実行しないでください。これはウェブサーバをブロックし、Kubernetesクラスタのレスポンスタイムは私たちのコントロール外であるため、GitLabのサービス拒否(DoS)攻撃につながる可能性があります。

呼び出しがバックグラウンドプロセスで行われるようにする最も簡単な方法は、そのような作業がSidekiqワーカーで行われるように委譲することです。

Kubernetesにコールを行い、レスポンスを返したいかもしれませんが、バックグラウンドワーカーは適していません。リアクティブキャッシュの使用を検討してください。たとえば

  def calculate_reactive_cache!
    { pods: cluster.platform_kubernetes.kubeclient.get_pods }
  end

  def pods
    with_reactive_cache do |data|
      data[:pods]
    end
  end

テスト

KubernetesHelpers 、Kubernetes APIをモックするためのWebMockスタブを用意しています。

Amazon EKSインテグレーション

このセクションでは、GitLabインスタンスがEKSクラスターを作成できるようにするためのプロセスの概要を説明します。

以下の前提条件が必要です:

Customer AWSアカウント。EKSクラスターはこのアカウントで作成されます。以下のリソースが存在する必要があります:

  • クラスターと関連リソースを作成する権限を持つプロビジョニングロール。GitLab AWSアカウントを信頼できるエンティティとしてリストする必要があります。
  • クラスターが使用するVPC、管理ロール、セキュリティグループ、およびサブネット。

GitLab AWSアカウント。これはプロビジョニングアクションを実行するアカウントです。以下のリソースが存在する必要があります:

  • 上記のCustomer アカウントのプロビジョニングロールを引き受ける権限を持つサービスアカウント。
  • gitlab.ymlkubernetes セクションを経由して GitLab で設定されたこのサービスアカウントの認証情報。

クラスターを作成する手順は次のとおりです:

  1. :provision_role_external_id を使って、GitLab は:provision_role_arn が提供するロールを引き受け、プロバイダレコードに一時的な認証情報のセットを保存します。デフォルトでは、これらの認証情報は1時間有効です。
  2. AWS CloudFormation EKS template に基づいて CloudFormation スタックが作成され、EKS クラスターに必要なすべてのリソースが作成されます。
  3. GitLabはすべてのリソースの準備が整うまでスタックのステータスをポーリングしますが、ほとんどの場合10分から15分かかります。
  4. スタックの準備ができると、GitLab はクラスターの詳細を保存し、kubeclient 経由でクラスターに接続するための一時的な認証情報を生成します。この認証情報は一分間有効です。
  5. GitLab はワーカーノードがクラスターに認証できるように設定し、今後のオペレーションに備えて自分用のサービスアカウントを作成します。
  6. 不要になった認証情報は削除されます。これにより、以下の属性が削除されます:

    • access_key_id
    • secret_access_key
    • session_token

セキュリティ

Server Side Request Forgery(SSRF) 攻撃

KubernetesクラスタのURLはユーザーが制御するため、Server Side Request Forgery(SSRF) 攻撃の影響を受けやすいです。クラスターにAPIコールを追加する場合は、緩和策を理解する必要があります。

緩和戦略には以下が含まれます:

  1. 攻撃者コントローラのリソースへのリダイレクトを許可しない:Kubeclient::KubeClient は、オプションとしてhttp_max_redirects: 0 を渡すことで、リダイレクトを許可しないように設定できます。
  2. エラーメッセージを公開しない: こうすることで、攻撃者がエラーをトリガーして、 攻撃者が制御したリクエストの結果を公開することを防ぎます。例えば、生のエラーメッセージは公開しません (あるいは保存しません):

    rescue Kubernetes::HttpError => e
      # bad
      # app.make_errored!("Kubernetes error: #{e.message}")
       
      # good
      app.make_errored!("Kubernetes error: #{e.error_code}")
    

Kubernetesインテグレーションのデバッグ

Kubernetesインテグレーションに関連するログは、kubernetes.log にあります。ローカルにGDKをインストールした場合、これらのログはlog/kubernetes.log にあります。

インストールに関するイシューをデバッグするために、インストールログをたどることもできます。インストール/アップグレードが完了したら、ポッドが作成されるのを待ちます。その後、以下を実行すると、ポッドのログが書き込まれます:

kubectl logs <pod_name> --follow -n gitlab-managed-apps