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.yml
のkubernetes
セクションを経由して GitLab で設定されたこのサービスアカウントの認証情報。
クラスターを作成する手順は次のとおりです:
-
:provision_role_external_id
を使って、GitLab は:provision_role_arn
が提供するロールを引き受け、プロバイダレコードに一時的な認証情報のセットを保存します。デフォルトでは、これらの認証情報は1時間有効です。 -
AWS CloudFormation EKS template
に基づいて CloudFormation スタックが作成され、EKS クラスターに必要なすべてのリソースが作成されます。 - GitLabはすべてのリソースの準備が整うまでスタックのステータスをポーリングしますが、ほとんどの場合10分から15分かかります。
- スタックの準備ができると、GitLab はクラスターの詳細を保存し、
kubeclient
経由でクラスターに接続するための一時的な認証情報を生成します。この認証情報は一分間有効です。 - GitLab はワーカーノードがクラスターに認証できるように設定し、今後のオペレーションに備えて自分用のサービスアカウントを作成します。
-
不要になった認証情報は削除されます。これにより、以下の属性が削除されます:
access_key_id
secret_access_key
session_token
セキュリティ
Server Side Request Forgery(SSRF) 攻撃
KubernetesクラスタのURLはユーザーが制御するため、Server Side Request Forgery(SSRF) 攻撃の影響を受けやすいです。クラスターにAPIコールを追加する場合は、緩和策を理解する必要があります。
緩和戦略には以下が含まれます:
- 攻撃者コントローラのリソースへのリダイレクトを許可しない:
Kubeclient::KubeClient
は、オプションとしてhttp_max_redirects: 0
を渡すことで、リダイレクトを許可しないように設定できます。 -
エラーメッセージを公開しない: こうすることで、攻撃者がエラーをトリガーして、 攻撃者が制御したリクエストの結果を公開することを防ぎます。例えば、生のエラーメッセージは公開しません (あるいは保存しません):
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