Workload Identity

このページでは、GKE アプリケーションが Google API 提供のサービスを使用するための推奨方法について説明します。これを行うには、Kubernetes サービス アカウントGoogle サービス アカウントとして構成します。 Kubernetes サービス アカウントとして実行されるすべてのポッドは、Google サービス アカウントを使用してクラウド サービスへの認証を行います。

概要

セキュリティのプロパティと管理性に優れているため、GKE から Google Cloud サービスにアクセスする場合は Workload Identity の使用をおすすめします。詳細については、以下の別の方法をご覧ください。

GKE で実行されるワークロードでは、Compute API、Storage API、Database API、Machine Learning API などの Google Cloud APIを使用する必要があります。Kubernetes サービス アカウントと Google サービス アカウント間の関係を構成すると、Kubernetes サービス アカウントとして実行されるワークロードは、Google Cloud API にアクセスするときに自動的に Google サービス アカウントとして認証されます。

Cloud API にアクセスする Google サービス アカウントの認証については、サービス アカウントについてをご覧ください。

用語

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

クラスタ間 ID

GSA と KSA の関係は、プロジェクトに関連付けられた ID の名前空間によって定義されます。名前、名前空間名、ID の名前空間を共有するすべての Kubernetes サービス アカウントは、GSA へのアクセスを共有します。これは、複数のクラスタに同じ ID が含まれている場合に便利ですが、Kubernetes サービス アカウント名と名前空間が慎重に管理されていないと危険です。

たとえば、次のコマンドは、デフォルトのサービス アカウントと名前空間を使用するクラスタ内のすべての Kubernetes ワークロードに同じアクセス権を付与し、クラスタで Workload Identity を有効にします。クラスタが権限を共有しないようにするには、クラスタを個別のプロジェクトにするか、別の Kubernetes 名前空間名を使用する必要があります。たとえば、制約のない「dev」クラスタとロックダウンされた「prod」クラスタがある場合、これらのクラスタを別のプロジェクトに分離し、別々の ID の名前空間を取得することを検討します。

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

制限事項

  • Workload Identity は、GKE バージョン 1.12 以降を実行するクラスタで使用可能です。

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

  • Workload Identity が有効な場合、Compute Engine のデフォルトのサービス アカウントは使用できません。詳細については、下記の別の方法をご覧ください。

  • Workload Identity は、ホスト ネットワークで実行中のポッドでは使用できません。

  • Stackdriver や Heapster などの GKE インフラストラクチャ ポッドは、引き続きノードのサービス アカウントを使用します。

始める前に

このタスクの準備として、次の手順を行います。

  • Google Kubernetes Engine API が有効になっていることを確認します。
  • Enable Google Kubernetes Engine API を有効にする
  • Cloud SDK がインストール済みであることを確認します。
  • デフォルトのプロジェクト ID を設定します。
    gcloud config set project [PROJECT_ID]
  • ゾーンクラスタを使用する場合は、デフォルトのコンピューティング ゾーンを設定します。
    gcloud config set compute/zone [COMPUTE_ZONE]
  • リージョン クラスタを使用する場合は、デフォルトのコンピューティング リージョンを設定します。
    gcloud config set compute/region [COMPUTE_REGION]
  • gcloud を最新バージョンに更新します。
    gcloud components update

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

このセクションでは、Workload Identity が有効になっているクラスタの作成方法と、Google サービス アカウント(GSA)の ID を使用してポッドを開始する方法について説明します。

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

    Cloud IAM Credentials API を有効にする

  2. Workload Identity を有効にしてクラスタを作成します。[CLUSTER_NAME] をクラスタの名前に置き換え、[PROJECT_ID] は Google Cloud プロジェクトの名前に置き換えます。

    gcloud beta container clusters create [CLUSTER_NAME] \
      --cluster-version=1.12 \
      --identity-namespace=[PROJECT_ID].svc.id.goog
    

    クラスタの作成には数分かかります。

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

    最小権限の原則に従って、権限の低い役割で残りの手順を行います。 各手順で必要な権限を示します。

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

    gcloud container clusters get-credentials [CLUSTER_NAME]
    

    [CLUSTER_NAME] は、前の手順で作成したクラスタの名前です。

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

  4. Google サービス アカウントを作成します。この操作を行うには、プロジェクトに対する iam.serviceAccounts.create 権限が必要です。新しいサービス アカウントを作成せずに、既存のサービス アカウントを使用することもできます。

    gcloud

    [GSA_NAME] は、サービス アカウントに選択した名前に置き換えます。

    gcloud iam service-accounts create [GSA_NAME]
    

    コネクタの構成

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

    apiVersion: iam.cnrm.cloud.google.com/v1alpha1
    kind: IAMServiceAccount
    metadata:
      name: [GSA_NAME]
    spec:
      displayName: [GSA_NAME]
    このマニフェストをデプロイするには、マニフェストを service-account.yaml というファイル名でマシンにダウンロードします。GSA_NAME は、サービス アカウントに選択した名前に置き換えます。次のコマンドを実行します。

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

    kubectl create namespace [K8S_NAMESPACE]
    

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

  6. Kubernetes サービス アカウントを作成します。前の手順で作成した名前空間を --namespace オプションに使用します。[KSA_NAME] は、サービス アカウントに使用する名前で置き換ます。

    kubectl create serviceaccount \
     --namespace [K8S_NAMESPACE] \
     [KSA_NAME]
    

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

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

  7. Kubernetes サービス アカウントが Google サービス アカウントを使用できるように、この 2 つのアカウント間に Cloud IAM ポリシー バインドを作成します。このバインドにより、Kubernetes サービス アカウントが Google サービス アカウントとして機能します。この操作を行うには、Google サービス アカウントに対する iam.serviceAccounts.setIamPolicy 権限が必要です。

    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 をクラスタにインストールするには、インストールの手順を実行してください。

    apiVersion: iam.cnrm.cloud.google.com/v1alpha1
    kind: IAMPolicy
    metadata:
      name: iampolicy-workload-identity-sample
    spec:
      resourceRef:
        apiVersion: iam.cnrm.cloud.google.com/v1alpha1
        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
  8. Google サービス アカウントのメールアドレスを使用して、iam.gke.io/gcp-service-account=[GSA_NAME]@[PROJECT_ID] アノテーションを Kubernetes サービス アカウントに追加します。

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

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

  9. サービス アカウントが正しく構成されていることを確認します。そうするには、Kubernetes サービス アカウントを使って cloud-sdk コンテナ イメージを実行するポッドを作成し、インタラクティブなセッションでそれに接続します。

    kubectl run --rm -it \
      --generator=run-pod/v1 \
      --image google/cloud-sdk:slim \
      --serviceaccount [KSA_NAME] \
      --namespace [K8S_NAMESPACE] \
      workload-identity-test
    

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

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

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

    gcloud auth list
    

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

クリーンアップ

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

    gcloud

    [GSA_NAME] は、サービス アカウントに選択した名前に置き換えます。

    gcloud iam service-accounts delete [GSA_NAME]
    

    コネクタの構成

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

    kubectl delete -f service-account.yaml

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

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

    gcloud auth list
    

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

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

    gcloud beta container clusters update [CLUSTER_NAME] \
      --disable-workload-identity
    

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

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

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

    Cloud IAM Credentials API を有効にする

  2. クラスタを変更して Workload Identity を有効にします。既存のノードプールへの影響はありません。新しいノードプールはデフォルトで --workload-metadata-from-node=GKE_METADATA_SERVER になります。

    gcloud beta container clusters update [CLUSTER_NAME] \
      --identity-namespace=[PROJECT_ID].svc.id.goog
    

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

ワークロードを Workload Identity に移行する

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

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

既存のノードプールを変更して、GKE_METADATA_SERVER を有効にします。Workload Identity がクラスタで有効になっている場合のみ、この更新が成功します。ノードプールにデプロイされたワークロードの Workload Identity がすぐに有効になります。

gcloud beta container node-pools update [NODEPOOL_NAME] \
  --cluster=[CLUSTER_NAME] \
  --workload-metadata-from-node=GKE_METADATA_SERVER

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

オプション 2: Workload Identity を使用したノードプールの作成

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

gcloud beta container node-pools create [NODEPOOL_NAME] \
  --cluster=[CLUSTER_NAME] \
  --workload-metadata-from-node=GKE_METADATA_SERVER

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

gcloud beta container node-pools create [NODEPOOL_NAME] \
  --cluster=[CLUSTER_NAME] \
  --workload-metadata-from-node=SECURE

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

クリーンアップ

  1. 既存のノードプールを変更して Workload Identity を無効にします。

    gcloud beta container node-pools update [NODEPOOL_NAME] \
      --cluster=[CLUSTER_NAME] \
      --workload-metadata-from-node=EXPOSED
    

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

  2. Workload Identity を無効にするようにクラスタを変更します。既存のノードプールが影響を受けることはありません。ただし、ノードプールが GKE_METADATA_SERVER を使用している場合は変更がブロックされます。Workload Identity を無効にした後に作成されたノードプールでは、そのノードプール内で実行されるポッドからノードの基盤となる Compute Engine メタデータ サーバーにアクセスできます。

    gcloud beta container clusters update [CLUSTER_NAME] \
      --disable-workload-identity
    

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

別の方法

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

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

  2. ノードで Compute Engine のデフォルトのサービス アカウントを使用します。Compute Engine のデフォルトのサービス アカウントは、そのノードにデプロイされているすべてのワークロードで共有されます。これにより、権限が過剰にプロビジョニングされることがあります。

次のステップ