Workload Identity Federation for GKE について


GKE 用 Workload Identity 連携は、Google Kubernetes Engine(GKE)で実行されているワークロードが安全かつ管理しやすい方法で Google Cloud サービスにアクセスできるようにするために推奨される方法です。

GKE 用 Workload Identity 連携は、Google Cloud 内外の環境で実行されるワークロードに ID を提供する、IAM Workload Identity 連携を介して利用できます。IAM Workload Identity 連携を使用すると、AWS、Azure、セルフマネージド Kubernetes などで実行されているワークロードから、サポートされている Google Cloud API を安全に認証できます。GKE では、Google Cloud が Workload Identity プールとプロバイダを管理するため、外部 ID プロバイダは必要ありません。

用語

このページでは、Kubernetes サービス アカウントIdentity and Access Management(IAM)サービス アカウントを区別しています。

Kubernetes サービス アカウント
GKE Pod で実行されるプロセスの ID を提供する Kubernetes リソース。
IAM サービス アカウント
アプリケーションが Google Cloud API への承認された呼び出しを実行できるようにする Google Cloud リソース。

GKE 用 Workload Identity 連携とは

GKE で実行されるアプリケーションで、Compute Engine API、BigQuery Storage API、ML API などの Google Cloud API へのアクセスが必要になる場合があります。

GKE 用 Workload Identity 連携では、IAM ポリシーを使用して、GKE クラスタ内の Kubernetes ワークロードに特定の Google Cloud API へのアクセス権を付与できます。手動構成や、サービス アカウント キー ファイルのような安全性の低い方法は必要ありません。GKE 用 Workload Identity 連携を使用すると、クラスタ内のアプリケーションごとに詳細に設定した個別の ID と認可を割り当てることができます。

GKE 用 Workload Identity 連携はメタデータ隠蔽機能に代わるものです。メタデータ隠蔽機能によって保護される機密メタデータは、GKE 用 Workload Identity 連携によっても保護されます。

GKE 用 Workload Identity 連携の仕組み

クラスタで GKE 用 Workload Identity 連携を有効にすると、GKE は次の処理を行います。

  • クラスタの Google Cloud プロジェクトに対して固定の Workload Identity プールを次の形式で作成します。

    PROJECT_ID.svc.id.goog
    

    Workload Identity プールは、IAM が Kubernetes 認証情報を理解し、信頼できるようにする命名規則を指定します。プロジェクト内のすべてのクラスタを削除しても、この Workload Identity プールは削除されません。

  • GKE クラスタを Workload Identity プールの ID プロバイダとして登録します。

  • GKE メタデータ サーバーをデプロイします。このサーバーは、すべてのノードでワークロードからの認証情報リクエストをインターセプトします。

Google Cloud リソースに IAM 許可ポリシーを作成する

GKE 用 Workload Identity 連携を使用してアクセス権を付与するには、アプリケーションの ID に対応するプリンシパルに特定の Google Cloud リソースに対するアクセス権を付与する IAM 許可ポリシーを作成します。たとえば、database-reader Kubernetes ServiceAccount を使用するすべての Pod に、Cloud Storage バケットの読み取り権限を付与できます。

許可ポリシーをサポートするリソースの一覧については、許可ポリシーを受け入れるリソースタイプをご覧ください。

IAM ポリシーで条件を使用する

また、許可ポリシーで条件を設定することで、アクセスの範囲を制限することもできます。条件は、許可ポリシーを適用するタイミングを指定する拡張可能な方法です。たとえば、条件を使用して特定の Google Cloud リソースのワークロードに一時的にアクセス権を付与すると、そのアクセスを手動で管理する必要がなくなります。

条件は、Secret Manager シークレットや Cloud Storage バケットなどの特定のリソースではなく、プロジェクト、フォルダ、組織レベルで許可ポリシーを設定する場合に便利です。

許可ポリシーに条件を追加するには、次のリソースを使用します。

次の式の例は、条件を使用する一般的なシナリオを想定しています。式で使用できる属性のリストについては、IAM Conditions の属性リファレンスをご覧ください。

条件式の例
指定した時刻になるまでアクセスを許可する
request.time < timestamp('TIMESTAMP')

TIMESTAMP は、UTC のタイムスタンプ(2024-08-30T00:00:00.000Z など)に置き換えます。

リクエストに含まれているリソースに、指定されたタグが付いている場合にアクセスを許可する
resource.matchTag('TAG_KEY', 'TAG_VALUE')

次のように置き換えます。

  • TAG_KEY: 照合するタグキー(env など)
  • TAG_VALUE: タグの値(dev など)

IAM ポリシーで Kubernetes リソースを参照する

IAM ポリシーでは、IAM のプリンシパル ID を使用してリソースを選択することで、Kubernetes リソースを参照します。この ID の構文は次のとおりです。

PREFIX://iam.googleapis.com/projects/1234567890/locations/global/workloadIdentityPools/example-project.svc.id.goog/SELECTOR

この例では、次のフィールドについて考えてみましょう。

  • PREFIX: 選択したリソースに応じて principal または principalSet にする必要があります。principal は、単一の ServiceAccount などの特定のリソースを対象とします。principalSet は、特定のクラスタ内のすべての Pod など、指定されたリソースに属する複数のリソースを対象とします。
  • SELECTOR: プリンシパル タイプを選択する文字列。たとえば、kubernetes.serviceaccount.uid/SERVICEACCOUNT_UID は UID で ServiceAccount を選択します。

次の表に、GKE でサポートされているプリンシパル タイプを示します。

プリンシパル ID のタイプ 構文
特定の Kubernetes ServiceAccount を使用するすべての Pod 名前で ServiceAccount を選択します。
principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/SERVICEACCOUNT

次のように置き換えます。

  • PROJECT_NUMBER: 数値のプロジェクト番号。プロジェクト番号を取得するには、プロジェクトを特定するをご覧ください。
  • PROJECT_ID: Google Cloud プロジェクト ID。
  • NAMESPACE: Kubernetes の Namespace。
  • SERVICEACCOUNT: Kubernetes ServiceAccount 名。

UID で ServiceAccount を選択します。
principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/kubernetes.serviceaccount.uid/SERVICEACCOUNT_UID

次のように置き換えます。

  • PROJECT_NUMBER: 数値のプロジェクト番号。プロジェクト番号を取得するには、プロジェクトを特定するをご覧ください。
  • PROJECT_ID: Google Cloud プロジェクト ID。
  • SERVICEACCOUNT_UID: API サーバー内の ServiceAccount オブジェクトの UID。
サービス アカウントやクラスタに関係なく、Namespace 内のすべての Pod
principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/namespace/NAMESPACE

次のように置き換えます。

  • PROJECT_NUMBER: 数値のプロジェクト番号。プロジェクト番号を取得するには、プロジェクトを特定するをご覧ください。
  • PROJECT_ID: Google Cloud プロジェクト ID。
  • NAMESPACE: Kubernetes の Namespace。
特定のクラスタ内のすべての Pod
principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/kubernetes.cluster/https://container.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/clusters/CLUSTER_NAME

次のように置き換えます。

  • PROJECT_NUMBER: 数値のプロジェクト番号。プロジェクト番号を取得するには、プロジェクトを特定するをご覧ください。
  • PROJECT_ID: Google Cloud プロジェクト ID。
  • CLUSTER_NAME: GKE クラスタの名前。
  • LOCATION: クラスタのロケーション。

認証情報フロー

Google Cloud クライアント ライブラリを使用する場合など、ワークロードが Google Cloud API にアクセスするためのリクエストを送信すると、次の認証処理が行われます。

Workload Identity を使用して Workload が IAM サービス アカウント トークンを取得する方法。
図 1: GKE 用 Workload Identity 連携によりワークロードが連携 ID トークンを取得する方法
  1. アプリケーションのデフォルト認証情報(ADC)が、VM 上で実行される Compute Engine メタデータ サーバーに Google Cloud アクセス トークンをリクエストします。
  2. GKE メタデータ サーバーはトークン リクエストをインターセプトし、Kubernetes API サーバーにリクエスト元のワークロードを識別する Kubernetes ServiceAccount トークンを要求します。この認証情報は、API サーバーによって署名された JSON Web Token(JWT)です。
  3. GKE メタデータ サーバーが、Security Token Service を使用して、Kubernetes ワークロードの ID を参照する有効期間の短い Google Cloud 連携アクセス トークンと JWT を交換します。

Security Token Service から返される連携アクセス トークンには、ID 連携: プロダクトと制限事項で説明されているように、一部の Google Cloud サービスへのアクセス時に制限が適用される場合があります。選択した Google Cloud サービスに制限が適用される場合は、必要に応じてサービス アカウントの権限借用を構成できます。この方法では、Workload がターゲット サービスへのアクセスに使用できる IAM サービス アカウントのアクセス トークンが生成されます。詳細については、代替方法: Kubernetes ServiceAccount を IAM にリンクするをご覧ください。

これにより、ワークロードは、ワークロードの IAM プリンシパル ID でアクセスできるすべての Google Cloud API にアクセスできるようになります。

ID の同一性

プリンシパル ID のメタデータが、同じ Google Cloud プロジェクトに属しているために Workload Identity プールを共有する複数のクラスタのワークロードで同じ場合、IAM はこれらのワークロードを同じものとして識別します。たとえば、2 つのクラスタに同じ Namespace があり、IAM でその Namespace へのアクセス権を付与すると、両方のクラスタのその Namespace のワークロードがそのアクセス権を取得します。条件付き IAM ポリシーを使用すると、このアクセスを特定のクラスタに制限できます。

たとえば、次の図について考えてみましょう。クラスタ A とクラスタ B は同じ Workload Identity プールに属しています。Google Cloud は、クラスタ A とクラスタ B の両方の backend Namespace で back-ksa ServiceAccount を使用するアプリケーションを同じ ID として識別します。IAM では、呼び出しを行うクラスタを区別しません。

Workload Identity プール内の ID の同一性を示す図
図 2: GKE 用 Workload Identity 連携により Google Cloud APIs にアクセスする ID の同一性

また、この ID の同一性は、特定の Workload Identity プール内のすべてのクラスタを信頼できるようにする必要があることを意味します。たとえば、上記の例の新しいクラスタ(クラスタ C)が信頼できないチームによって所有されていた場合、クラスタ A とクラスタ B と同様に、backend Namespace を作成し、back-ksa ServiceAccount を使用して Google Cloud APIs にアクセスできます。

信頼できないアクセスを回避するには、クラスタを別々のプロジェクトに配置し、別々の Workload Identity プールを取得できるようにします。また、共通のプリンシパル ID を回避するため、Namespace 名が互いに異なるようにする必要があります。

GKE メタデータ サーバーについて

GKE 用 Workload Identity 連携が有効になっている GKE のすべてのノードは、メタデータを GKE メタデータ サーバーに保存します。GKE メタデータ サーバーは、Kubernetes ワークロードに必要な Compute Engine メタデータ サーバー エンドポイントのサブセットです。

GKE メタデータ サーバーは DaemonSet として実行されます。それぞれの Linux ノードで 1 つの Pod が使用されるか、クラスタ内の各 Windows ノードにネイティブ Windows サービスが実行されます。メタデータ サーバーは、http://metadata.google.internal169.254.169.254:80)への HTTP リクエストをインターセプトします。たとえば、GET /computeMetadata/v1/instance/service-accounts/default/token リクエストは、権限借用に Pod が構成されている IAM サービス アカウントのトークンを取得します。GKE メタデータ サーバーへのトラフィックは、Pod をホストする VM インスタンスから外に送信されません。

次の表に、GKE メタデータ サーバーで使用できる Compute Engine メタデータ サーバー エンドポイントのサブセットを示します。Compute Engine メタデータ サーバーで使用できるエンドポイントの一覧については、デフォルトの VM メタデータ値をご覧ください。

インスタンス メタデータ

インスタンス メタデータは、次のディレクトリに保存されます。

http://metadata.google.internal/computeMetadata/v1/instance/

エントリ 説明
hostname

ノードのホスト名。

id

ノードの一意の ID。

service-accounts/

ノードに関連付けられているサービス アカウントのディレクトリ。各サービス アカウントごとに、次の情報を利用できます。

  • aliases
  • email: サービス アカウントのメールアドレス。
  • identity: ノードに固有の JSON ウェブトークン(JWT)。リクエストには audience パラメータを含める必要があります。例: ?audience=http://www.example.com
  • scopes: サービス アカウントに割り当てられているアクセス スコープ。
  • token: ワークロードを認証するための OAuth 2.0 アクセス トークン。
zone

GKE ノードの Compute Engine ゾーン。

インスタンス属性

インスタンス属性は、次のディレクトリに保存されます。

http://metadata.google.internal/computeMetadata/v1/instance/attributes/

エントリ 説明
cluster-location

クラスタの Compute Engine ゾーンまたはリージョン。

cluster-name

GKE クラスタの名前。

cluster-uid

GKE クラスタの UID。

プロジェクトのメタデータ

クラスタ プロジェクトのメタデータは、次のディレクトリに保存されます。

http://metadata.google.internal/computeMetadata/v1/project/

エントリ 説明
project-id

Google Cloud プロジェクト ID。

numeric-project-id

Google Cloud プロジェクト番号。

Workload Identity Federation for GKE の制限事項

  • GKE が Google Cloud プロジェクト用に作成する Workload Identity プールの名前は変更できません。

  • GKE がノードプールで GKE メタデータ サーバーを有効にすると、Pod は Compute Engine メタデータ サーバーにアクセスできなくなります。GKE メタデータ サーバーは、ホスト ネットワークで実行されている Pod を除き、これらの Pod からメタデータ エンドポイントへのリクエストをインターセプトします。

  • GKE メタデータ サーバーが新しく作成された Pod でのリクエストの承認を開始するまでに数秒かかります。したがって、Pod の有効期間の最初の数秒以内に GKE 用 Workload Identity 連携を使用して認証を試みると、失敗する可能性があります。この問題は、呼び出しを再試行することで解決します。詳しくは、トラブルシューティングをご覧ください。

  • GKE の組み込みの Logging エージェントと Monitoring エージェントは、引き続きノードのサービス アカウントを使用します。

  • GKE 用 Workload Identity 連携を有効にしても、リクエスト指標のリリースを継続するには Knative serving の手動設定が必要になります。

  • GKE 用 Workload Identity 連携では、メモリの問題を回避するため、ノードごとに GKE メタデータ サーバーへの接続数の上限を 200 に設定しています。ノードがこの上限を超えると、タイムアウトが発生することがあります。

  • Windows Server ノードの GKE 用 Workload Identity 連携は、GKE バージョン 1.18.16-gke.1200、1.19.8-gke.1300、1.20.4-gke.1500 以降で使用できます。

  • GKE メタデータ サーバーは、クラスタ内の Kubernetes サービス アカウントの合計数に比例してメモリリソースを使用します。クラスタに 3,000 を超える Kubernetes サービス アカウントがある場合、kubelet はメタデータ サーバー Pod を終了することがあります。軽減策については、トラブルシューティングをご覧ください。

GKE 用 Workload Identity 連携に代わる方法

GKE から Google Cloud API にアクセスする場合、GKE 用 Workload Identity 連携の代わりに、次のいずれかの方法を使用できます。これらの方法では、セキュリティに関して一定の妥協が必要になるため、GKE 用 Workload Identity 連携を使用することをおすすめします。

次のステップ