Workload Identity の使用

このページでは、Google API によって提供されるサービスを Google Kubernetes Engine(GKE)アプリケーションで使用する際に推奨される方法を説明します。

概要

Workload Identity を使用して GKE 内で実行しているアプリケーションから Google Cloud サービスにアクセスすることをおすすめするのは、セキュリティのプロパティと管理性が優れているからです。GKE から Google Cloud APIs にアクセスする別の方法については、下の別の方法セクションをご覧ください。

フリートの Workload Identity は、Anthos クラスタを含むフリートに登録されているクラスタに対する Workload Identity 連携をサポートしています。

用語

このドキュメントでは、Kubernetes サービス アカウントGoogle サービス アカウントを区別しています。Kubernetes サービス アカウントは Kubernetes のリソースですが、Google サービス アカウントは Google Cloud 固有のものです。Google Cloud の他のドキュメントでは、Google サービス アカウントを「サービス アカウント」と表記しています。

コンセプト

GKE で実行されるアプリケーションで、Compute API、Storage API、Database API、Machine Learning API などの Google Cloud APIs を使用するには認証が必要です。

Workload Identity では、Kubernetes サービス アカウントを構成して Google サービス アカウントとして使用します。Kubernetes サービス アカウントとして実行される Pod は、Google Cloud APIs にアクセスする際に、Google サービス アカウントとして自動的に認証されます。これにより、クラスタ内のアプリケーションごとに詳細に設定した個別の ID と認証を割り当てることができます。

Kubernetes サービス アカウントと Google サービス アカウント間の安全なマッピングを実現するために、Workload Identity は、クラスタのワークロード ID プールのコンセプトを導入します。これにより、Identity and Access Management(IAM)は Kubernetes サービス アカウントの認証情報を信頼して確認できます。

GKE クラスタで Workload Identity を有効にすると、クラスタの Workload Identity プールが PROJECT_ID.svc.id.goog に設定されます。これにより、IAM は次のメンバー名で Kubernetes サービス アカウントを認証できます。

serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/KSA_NAME]

このメンバー名で:

  • PROJECT_ID.svc.id.goog は、クラスタで設定された Workload Identity プールです。
  • KSA_NAME は、リクエストを行っている Kubernetes サービス アカウントの名前です。
  • K8S_NAMESPACE は、Kubernetes サービス アカウントが定義されている Kubernetes 名前空間です。

GKE は、Google Cloud プロジェクトごとに固定の Workload Identity プール PROJECT_ID.svc.id.goog を自動的に作成します。この Workload Identity プールは、プロジェクト内のすべての GKE クラスタに使用されます。

クラスタ間での ID の同一性

名前、名前空間名、workload identity プールを共有するすべての Kubernetes サービス アカウントが同じメンバー名に解決されて、Google Cloud リソースへのアクセスが共有されます。この共通 ID によって、Workload Identity プール内のアプリケーションに、クラスタ単位ではなく外部リソースへのアクセス権をまとめて付与できます。

この点についてより具体的に理解するため、次の例を考えてみましょう。クラスタ A、B、C が同じ Workload Identity プールに登録されています。backend 名前空間のアプリケーションが Google Cloud リソースにアクセスすると、アプリケーションがホストされているクラスタに関係なく、ID が back という共通の Google サービス アカウントにマッピングされます。Google サービス アカウント back は、Cloud Storage から Cloud SQL まで、任意の数の Google Cloud APIs で認証できます。

ID の同一性により、Workload Identity プール内のすべてのクラスタが高い信頼性を付与され、適切に管理されていることが重要です。前の例をもう一度見てみましょう。クラスタ C が別の信頼できないチームによって所有されている場合、backend 名前空間を作成し、クラスタ A またはクラスタ B に存在する backend であるかのように Google Cloud APIs にアクセスできます。

Workload Identity プール内の ID の同一性を示す図
Workload Identity を使用して Google Cloud APIs にアクセスする際の ID の同一性

クラスタが権限を共有しないようにするには、クラスタを個別のプロジェクトにするか、別の Kubernetes 名前空間名を使用する必要があります。具体的な例として、寛容な「dev」クラスタとロックダウンされた「prod」クラスタを使用するユーザーは、これらのクラスタを別々のプロジェクトに分離して別々の Workload Identity プールを使用させることを考慮すべきです。

制限事項

  • 現在のところ、Google Cloud プロジェクトごとに自動的に Workload Identity プール PROJECT_ID.svc.id.goog が 1 つだけ作成され、固定されます。

  • Workload Identity は、メタデータ隠蔽機能に代わるもので、この 2 つに互換性はありません。メタデータ隠蔽機能で保護された機密メタデータは Workload Identity でも保護されます。

  • ノードプールで GKE メタデータ サーバーが有効にされると、Pod は Compute Engine のメタデータ サーバーにアクセスできなくなります。代わりに、これらの Pod からメタデータ API に送信されたリクエストは、GKE メタデータ サーバーにルーティングされます。ただし、ホスト ネットワークで実行されている Pod は例外です(次をご覧ください)。

  • ホスト ネットワークで実行されている Pod で Workload Identity を使用することはできません。これらの Pod からメタデータ API に送信されたリクエストは、Compute Engine のメタデータ サーバーにルーティングされます。

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

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

  • Workload Identity を有効にしても Cloud Run for Anthos によるリクエスト指標のリリースを継続するには手動設定が必要です。

  • Workload Identity は、クラスタが --disable-default-snat フラグなしで作成された場合に ip-masq-agent をインストールします。

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

始める前に

作業を始める前に、次のことを確認してください。

次のいずれかの方法で gcloud のデフォルトの設定を指定します。

  • gcloud init。デフォルトの設定全般を確認する場合に使用します。
  • gcloud config。プロジェクト ID、ゾーン、リージョンを個別に設定する場合に使用します。

gcloud init の使用

エラー One of [--zone, --region] must be supplied: Please specify location を受信した場合は、このセクションの内容を実施します。

  1. gcloud init を実行して、次の操作を行います。

    gcloud init

    リモート サーバーで SSH を使用している場合は、--console-only フラグを指定して、コマンドがブラウザを起動しないようにします。

    gcloud init --console-only
  2. 手順に従って gcloud を承認し、Google Cloud アカウントを使用します。
  3. 新しい構成を作成するか、既存の構成を選択します。
  4. Google Cloud プロジェクトを選択します。
  5. ゾーンクラスタの場合はデフォルトの Compute Engine ゾーン、リージョン クラスタまたは Autopilot クラスタの場合はデフォルトの Compute Engine リージョンを選択します。

gcloud config の使用

  • デフォルトのプロジェクト ID を設定します。
    gcloud config set project PROJECT_ID
  • ゾーンクラスタを使用する場合は、デフォルトのコンピューティング ゾーンを設定します。
    gcloud config set compute/zone COMPUTE_ZONE
  • Autopilot クラスタまたはリージョン クラスタを使用する場合は、デフォルトのコンピューティング リージョンを設定します。
    gcloud config set compute/region COMPUTE_REGION
  • gcloud を最新バージョンに更新します。
    gcloud components update

クラスタで Workload Identity を有効にする

新規または既存の GKE Standard クラスタで Workload Identity を有効にするには、gcloud ツールを使用します。GKE Autopilot クラスタでは、Workload Identity がデフォルトで有効になっています。

  1. IAM Service Account Credentials API が有効になっているかを確認します。

    IAM Credentials API を有効にする

  2. Workload Identity を有効にして新しいクラスタを作成するには、次のコマンドを使用します。

    gcloud container clusters create CLUSTER_NAME \
        --workload-pool=PROJECT_ID.svc.id.goog
    

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

    • CLUSTER_NAME: クラスタの名前。
    • PROJECT_ID: Google Cloud プロジェクトの ID。

    この操作を行うには、プロジェクトに対する container.clusters.create 権限が必要です。

  3. 既存のクラスタで Workload Identity を有効にするには、次のコマンドを使用してクラスタを変更します。

    gcloud container clusters update CLUSTER_NAME \
        --workload-pool=PROJECT_ID.svc.id.goog
    

    既存のノードプールは影響を受けません。新しいノードプールはデフォルトで --workload-metadata=GKE_METADATA になります。

    この操作を行うには、クラスタに対する container.clusters.update 権限が必要です。

アプリケーションを Workload Identity に移行する

ご使用の環境に適した移行方法を選択します。ノードプールを移行するか、新しいノードプールを作成して Workload Identity を有効にすることもできます。この機能に対応するようにアプリケーションを変更する必要がある場合は、新しいノードプールの作成をおすすめします。

新しいノードプールをクラスタに追加して Workload Identity を有効にし、そのプールにワークロードを手動で移行します。この操作が成功するのは、Workload Identity がクラスタで有効になっている場合のみです。

gcloud container node-pools create NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --workload-metadata=GKE_METADATA

クラスタで Workload Identity が有効になっている場合、--workload-metadata=GCE_METADATA を明示的に指定することで特定のノードプールで選択的に無効にできます。詳しくは、クラスタ メタデータの保護をご覧ください。

オプション 2: ノードプールの変更

既存のノードプールを変更して、GKE_METADATA を有効にします。Workload Identity がクラスタで有効になっている場合のみ、この更新が成功します。更新が成功すると、ノードプールにデプロイされたワークロードの Workload Identity がすぐに有効になります。この変更により、ワークロードは Compute Engine サービス アカウントを使用できなくなるので、慎重にロールアウトする必要があります。

gcloud container node-pools update NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --workload-metadata=GKE_METADATA

この操作を行うには、プロジェクトに対する container.nodes.update 権限が必要です。

Google Cloud の認証

このセクションでは、Workload Identity を使用してアプリケーションが Google Cloud で認証を行う方法について説明します。これを行うため、アプリケーションに Kubernetes サービス アカウントを割り当て、Google サービス アカウントとして機能するように構成します。

  1. クラスタと通信を行うように kubectl を構成します。

    gcloud container clusters get-credentials CLUSTER_NAME
    

    CLUSTER_NAME は、前のステップで作成したクラスタの名前に置き換えます。

    この操作を行うには、プロジェクトに対する container.clusters.get 権限が必要です。

  2. 他のほとんどのリソースと同様に、Kubernetes サービス アカウントは名前空間に存在します。Kubernetes サービス アカウントに使用する名前空間を作成します。

    kubectl create namespace K8S_NAMESPACE
    

    この操作を行うには、クラスタ内に名前空間の RBAC を作成する権限が必要です。

  3. アプリケーションで使用する Kubernetes サービス アカウントを作成します。

    kubectl create serviceaccount --namespace K8S_NAMESPACE KSA_NAME
    

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

    • K8S_NAMESPACE: 前のステップで作成した Kubernetes の名前空間の名前。
    • KSA_NAME: Kubernetes サービス アカウントに使用する名前。

    この操作を行うには、名前空間内でサービス アカウントの RBAC を作成する権限が必要です。

    また、デフォルトの名前空間または他の既存の名前空間でデフォルトの Kubernetes サービス アカウントを使用することもできます。

  4. Kubernetes サービス アカウントを使用するようにアプリケーションを構成します。

    spec:
      serviceAccountName: KSA_NAME
    
  5. アプリケーションに Google サービス アカウントを作成するか、既存の Google サービス アカウントを使用します。組織内の任意のプロジェクトで、任意の Google サービス アカウントを使用できます。Config Connector の場合は、選択したサービス アカウントに IAMServiceAccount オブジェクトを適用します。

    gcloud

    gcloud ツールを使用して新しい Google サービス アカウントを作成するには、次のコマンドを実行します。

    gcloud iam service-accounts create GSA_NAME
    

    GSA_NAME は、新しい Google Cloud サービス アカウントの名前に置き換えます。

    Config Connector

    Config Connector で新規または既存の Google サービス アカウントを使用するには、次の構成ファイルを適用します。

    注: この手順には Config Connector が必要です。Config Connector をクラスタにインストールするには、インストール手順を実施してください。

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMServiceAccount
    metadata:
      name: [GSA_NAME]
    spec:
      displayName: [GSA_NAME]
    このマニフェストをデプロイするには、service-account.yaml という名前でマシンにダウンロードします。

    kubectl を使用してマニフェストを適用します。

    kubectl apply -f service-account.yaml
    

    この操作を行うには、プロジェクトに対する iam.serviceAccounts.create 権限が必要です。

    Google サービス アカウントから Google Cloud APIs へのアクセスを承認する方法については、サービス アカウントについてをご覧ください。

  6. Google サービス アカウントに必要な IAM ロールがあることを確認します。次のコマンドを使用して、追加のロールを付与できます。

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member "serviceAccount:GSA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
        --role "ROLE_NAME"
    

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

    • PROJECT_ID: Google Cloud プロジェクト ID。
    • GSA_NAME: Google サービス アカウントの名前。
    • ROLE_NAME: roles/spanner.viewer など、サービス アカウントに割り当てる IAM ロール。
  7. Kubernetes サービス アカウントが Google サービス アカウントの権限を借用できるように、この 2 つの間の IAM ポリシー バインディングを作成します。このバインドでは、Kubernetes サービス アカウントが Google サービス アカウントとして機能します。

    gcloud

    gcloud iam service-accounts add-iam-policy-binding \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/KSA_NAME]" \
        GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    

    Config Connector

    注: この手順には Config Connector が必要です。Config Connector をクラスタにインストールするには、インストール手順を実施してください。

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMPolicy
    metadata:
      name: iampolicy-workload-identity-sample
    spec:
      resourceRef:
        apiVersion: iam.cnrm.cloud.google.com/v1beta1
        kind: IAMServiceAccount
        name: [GSA_NAME]
      bindings:
        - role: roles/iam.workloadIdentityUser
          members:
            - serviceAccount:[PROJECT_ID].svc.id.goog[[K8S_NAMESPACE]/[KSA_NAME]]
    このマニフェストをデプロイするには、policy-binding.yaml という名前でマシンにダウンロードします。GSA_NAMEPROJECT_IDK8S_NAMESPACEKSA_NAME を、実際の環境での値に置き換えます。次のコマンドを実行します。

    kubectl apply -f policy-binding.yaml
    

    この操作を行うには、プロジェクトに対する iam.serviceAccounts.setIamPolicy 権限が必要です。

  8. Google サービス アカウントのメールアドレスを使用して、iam.gke.io/gcp-service-account=GSA_NAME@PROJECT_ID アノテーションを Kubernetes サービス アカウントに追加します。

    kubectl

    kubectl annotate serviceaccount \
        --namespace K8S_NAMESPACE KSA_NAME \
        iam.gke.io/gcp-service-account=GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    

    yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      annotations:
        iam.gke.io/gcp-service-account: GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
      name: KSA_NAME
      namespace: K8S_NAMESPACE
    

    この操作を行うには、Kubernetes サービス アカウントに RBAC を編集する権限が必要です。

  9. サービス アカウントが正しく構成されていることを確認します。Kubernetes サービス アカウントを使用して、OS 固有のコンテナ イメージを実行する Pod を作成し、インタラクティブなセッションで Pod に接続します。

    Linux ノードの場合

    1. Kubernetes サービス アカウントを使用して、cloud-sdk コンテナ イメージを実行する Pod を作成します。

      次の構成を wi-test.yaml として保存します。

      apiVersion: v1
      kind: Pod
      metadata:
        name: workload-identity-test
        namespace: K8S_NAMESPACE
      spec:
        containers:
        - image: google/cloud-sdk:slim
          name: workload-identity-test
          command: ["sleep","infinity"]
        serviceAccountName: KSA_NAME
      

      Pod を作成します。

      kubectl apply -f wi-test.yaml
      

      Pod でインタラクティブ セッションを開きます。

      kubectl exec -it workload-identity-test \
          --namespace K8S_NAMESPACE -- /bin/bash
      

      google/cloud-sdk イメージには gcloud コマンドライン ツールが含まれています。このツールを使用すると、Google Cloud APIs を簡単に利用できます。イメージのダウンロードに時間がかかる場合があります。

      この操作を行うには、名前空間内で Pod 作成の RBAC 権限が必要です。

    2. これで、作成した Pod 内でインタラクティブ シェルに接続できました。Pod 内で次のコマンドを実行します。

      gcloud auth list
      

      サービス アカウントが正しく構成されている場合、Google サービス アカウントのメールアドレスがアクティブな唯一の ID になります。デフォルトでは、Google Cloud APIs を呼び出すときに Google サービス アカウントの権限が使用されます。

    Windows Server ノードの場合

    1. Kubernetes サービス アカウントを使用して、servercore コンテナ イメージを実行する Pod を作成します。

      apiVersion: v1
      kind: Pod
      metadata:
        name: workload-identity-test
        namespace: K8S_NAMESPACE
      spec:
        containers:
        - image: IMAGE_NAME
          name: workload-identity-test
          command: ["powershell.exe", "sleep", "3600"]
        serviceAccountName: KSA_NAME
        nodeSelector:
          kubernetes.io/os: windows
          cloud.google.com/gke-os-distribution: windows_ltsc
      

      IMAGE_NAME を、次のいずれかのコンテナ サーバーコア イメージの値に置き換えます。

      Windows Server ノードイメージ コンテナ servercore イメージ
      WINDOWS_LTSC
      WINDOWS_LTSC_CONTAINERD
      mcr.microsoft.com/windows/servercore:ltsc2019
      WINDOWS_SAC
      WINDOWS_SAC_CONTAINERD
      GKE ノード バージョンと Windows SAC バージョンの間のバージョン マッピングを確認します。Windows Server バージョン 1909 の場合は mcr.microsoft.com/windows/servercore:1909 を指定し、それ以外の場合は mcr.microsoft.com/windows/servercore:20H2 を指定します。

      この操作を行うには、名前空間内で Pod 作成の RBAC 権限が必要です。

      Pod でインタラクティブ セッションを開きます。

      kubectl exec -it workload-identity-test \
          --namespace K8S_NAMESPACE -- powershell
      
    2. これで、作成した Pod 内でインタラクティブ シェルに接続できました。Pod 内で次の powershell コマンドを実行します。

      Invoke-WebRequest  -Headers @{"Metadata-Flavor"="Google"} -Uri  http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email  -UseBasicParsing
      

      サービス アカウントが正しく構成されている場合、Google サービス アカウントのメールアドレスがアクティブな唯一の ID になります。デフォルトでは、Google Cloud APIs を呼び出すときに Google サービス アカウントの権限が使用されます。

コードから Workload Identity を使用する

コードで Google Cloud サービスに対する認証を行うプロセスは、Compute Engine のメタデータ サーバーを使用した認証と同じです。Workload Identity を使用すると、インスタンス メタデータ サーバーに対するリクエストが GKE メタデータ サーバーにルーティングされます。インスタンス メタデータ サーバーを使用して認証する既存のコードは(Google Cloud クライアント ライブラリを使用したコード同様)、変更せずにそのまま使用できます。

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

GKE メタデータ サーバーは、Kubernetes で使用するために設計された新しいメタデータ サーバーです。サーバーは各クラスタ Linux ノードに 1 つの Pod を使用して DaemonSet として、または各 Windows ノードでネイティブ Windows サービスとして実行されます。メタデータ サーバーは、Pod がその役割を果たすように構成された Google サービス アカウントのトークンを取得するための GET /computeMetadata/v1/instance/service-accounts/default/token などのリクエストも含め、http://metadata.google.internal(169.254.169.254:80)への HTTP リクエストをインターセプトします。メタデータ サーバーへのトラフィックは必ず、Pod をホストする VM インスタンスに向かいます。

GKE メタデータ サーバーは、Kubernetes ワークロードとの関連性があり、安全な Compute Engine メタデータ サーバー エンドポイントのサブセットのみを実装します。

  • /computeMetadata/v1/instance/attributes/cluster-location
  • /computeMetadata/v1/instance/attributes/cluster-name
  • /computeMetadata/v1/instance/attributes/cluster-uid
  • /computeMetadata/v1/instance/hostname
  • /computeMetadata/v1/instance/id
  • /computeMetadata/v1/project/numeric-project-id
  • /computeMetadata/v1/project/project-id
  • /computeMetadata/v1/instance/service-accounts
  • /computeMetadata/v1/instance/service-accounts/default
  • /computeMetadata/v1/instance/service-accounts/default/aliases
  • /computeMetadata/v1/instance/service-accounts/default/email
  • /computeMetadata/v1/instance/service-accounts/default/identity
  • /computeMetadata/v1/instance/service-accounts/default/identity?audience=audience
  • /computeMetadata/v1/instance/service-accounts/default/scopes
  • /computeMetadata/v1/instance/service-accounts/default/token
  • /computeMetadata/v1/instance/service-accounts/default/token?scopes=comma-separated-list-of-scopes

アクセス権の取り消し

  1. IAM を使用して Google サービス アカウントへのアクセス権を取り消します。

    gcloud

    gcloud iam service-accounts remove-iam-policy-binding \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/KSA_NAME]" \
        GSA_NAME@GSA_PROJECT_ID.iam.gserviceaccount.com
    

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

    • PROJECT_ID: GKE クラスタのプロジェクト ID コンテナ。
    • K8S_NAMESPACE: Kubernetes サービス アカウントが配置されている Kubernetes 名前空間の名前。
    • KSA_NAME: アクセス権が取り消される Kubernetes サービス アカウントの名前。
    • GSA_NAME: Google サービス アカウントの名前。
    • GSA_PROJECT_ID: Google サービス アカウントを含むプロジェクト ID。

    Config Connector

    Config Connector を使用してサービス アカウントを作成した場合は、kubectl を使用してサービス アカウントを削除します。

    kubectl delete -f service-account.yaml
    

    この操作を実行するには、サービス アカウントに対する iam.serviceAccounts.setIamPolicy 権限が必要です。

    キャッシュ内のトークンの有効期限は 30 分です。キャッシュ内のトークンが期限切れになっているかどうかは、次のコマンドで確認できます。

    gcloud auth list
    

    このコマンドの出力に GSA_NAME@PROJECT_ID.iam.gserviceaccount.com が含まれない場合は、キャッシュ内のトークンはすでに期限切れです。

  2. Kubernetes サービス アカウントからアノテーションを削除します。IAM によってアクセス権が取り消されたため、このステップは省略可能です。

    kubectl annotate serviceaccount KSA_NAME \
        --namespace K8S_NAMESPACE iam.gke.io/gcp-service-account-
    

トラブルシューティング

Pod が Google Cloud に対して認証できない

アプリケーションが Google Cloud で認証できない場合は、次の設定が正しく構成されていることを確認してください。

  1. GKE クラスタを含むプロジェクトで IAM Service Account Credentials API が有効になっているかを確認します。

    IAM Credentials API を有効にする

  2. Workload Identity がクラスタで有効になっていることを確かにするには、ワークロード ID プールが設定されていることを確認します。

    gcloud container clusters describe CLUSTER_NAME \
        --format="value(workloadIdentityConfig.workloadPool)"
    
  3. GKE メタデータ サーバー(GKE_METADATA)が、アプリケーションが実行されているノードプールで構成されていることを確認します。

    gcloud container node-pools describe NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --format="value(config.workloadMetadataConfig.mode)"
    
  4. Kubernetes サービス アカウントに正しくアノテーションが付けられていることを確認します。

    kubectl describe serviceaccount \
        --namespace K8S_NAMESPACE KSA_NAME
    

    アノテーションの形式は次のとおりです。

    iam.gke.io/gcp-service-account: GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    
  5. Google サービス アカウントが正しく構成されていることを確認します。

    gcloud iam service-accounts get-iam-policy \
        GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    

    次の形式のバインディングがあることを確認します。

    - members:
      - serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/KSA_NAME]
      role: roles/iam.workloadIdentityUser
    
  6. クラスタ ネットワーク ポリシーを導入している場合は、ポート 988 で 127.0.0.1/32 への下り(外向き)が許可されていることを確認します。

    kubectl describe networkpolicy NETWORK_POLICY_NAME
    

Pod の起動時にタイムアウト エラーが発生する

GKE メタデータ サーバーが新しく作成された Pod でリクエストの受信を開始できるようになるまでに数秒かかります。したがって、Pod の有効期間の最初の数秒以内に Workload Identity を使用して認証を試みると、短いタイムアウトが構成されているアプリケーションと Google Cloud クライアント ライブラリで失敗する可能性があります。

タイムアウト エラーが発生した場合は、アプリケーション コードを変更して数秒待ってから再試行してください。また、Pod のメインコンテナを実行する前に、GKE メタデータ サーバーの準備が完了するまで待機する initContainer をデプロイすることもできます。

サンプルの initContainer を備えた Pod を次に示します。

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-initcontainer
spec:
  serviceAccountName: KSA_NAME
  initContainers:
  - image:  gcr.io/google.com/cloudsdktool/cloud-sdk:326.0.0-alpine
    name: workload-identity-initcontainer
    command:
    - '/bin/bash'
    - '-c'
    - |
      curl -s -H 'Metadata-Flavor: Google' 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token' --retry 30 --retry-connrefused --retry-max-time 30 > /dev/null || exit 1
  containers:
  - image: gcr.io/your-project/your-image
    name: your-main-application-container

Workload Identity が失敗する

なんらかの理由で GKE メタデータ サーバーがブロックされていると、Workload Identity は失敗します。

Istio を使用している場合は、Workload Identity を使用するすべてのワークロードに次のアプリケーション レベルのアノテーションを追加する必要があります。

"traffic.sidecar.istio.io/excludeOutboundIPRanges=169.254.169.254/32"

global.proxy.excludeIPRanges Istio ConfigMap キーを変更して同じ処理を行うこともできます。

クラスタでの Workload Identity の無効化

Workload Identity は GKE Standard クラスタでのみ無効にできます。

  1. 各ノードプールで Workload Identity を無効にします。

    gcloud container node-pools update NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --workload-metadata=GCE_METADATA
    

    クラスタ内の各ノードプールに対してこのコマンドを繰り返します。

  2. クラスタで Workload Identity を無効にします。

    gcloud container clusters update CLUSTER_NAME --disable-workload-identity
    

    この操作を行うには、クラスタに対する container.clusters.update 権限が必要です。

組織内での Workload Identity の無効化

セキュリティの観点から、Workload Identity では GKE が、Kubernetes サービス アカウント ID を Google Cloud リソースに対して認証、認可できるものとして表明できるようになっています。サービス アカウントの作成の無効化や、サービス アカウント キーの作成の無効化などを行い、ワークロードを Google Cloud リソースから分離するための措置を講じた管理者は、組織で Workload Identity を無効化することも検討できます。

組織の Workload Identity を無効にするこれらの手順をご覧ください。

Workload Identity に代わる方法

GKE から Cloud APIs にアクセスするには、2 つの方法があります。Workload Identity のリリースに伴い、調整が必要になるため、これらのアプローチはおすすめしません。

  1. サービス アカウント キーをエクスポートして Kubernetes Secret として保存します。Google サービス アカウント キーには有効期限がないため、手動でローテーションする必要があります。サービス アカウント キーをエクスポートすると、セキュリティ侵害を受けた場合、それが検出されなければ侵害の範囲が拡大する可能性があります。

  2. ノードの Compute Engine サービス アカウントを使用します。プロジェクト内の任意の IAM サービス アカウントとしてノードプールを実行できます。ノードプールの作成時にサービス アカウントを指定しなければ、GKE はプロジェクトのデフォルトの Compute Engine サービス アカウントを使用します。デフォルトの Compute Engine サービス アカウントは、そのノードにデプロイされているすべてのワークロードで共有されます。そのため、権限が過剰にプロビジョニングされることがあります。

次のステップ