Workload Identity

このページでは、GKE アプリケーションが Google API 提供のサービスを使用するための推奨方法について説明します。

概要

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

GKE で実行されるワークロードで、Compute API、Storage API、Database API、Machine Learning API などの Google Cloud APIs を使用するには認証が必要です。

Workload Identity では、Kubernetes サービス アカウント(KSA) を構成して Google サービス アカウント(GSA)として使用します。 KSA として実行されるワークロードは、Google Cloud APIs にアクセスするとき自動的に GSA として認証されます。

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

用語

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

Kubernetes サービス アカウントの認証

Google Cloud がデフォルトで Kubernetes サービス アカウント(KSA)からのリクエストを認証できないのは、サービス アカウントが外部の ID システムから生じているからです。

GKE クラスタで Workload Identity を有効にするときは、クラスタの Workload Identity プールを some.workload-pool.id.goog に設定します。GKE がメンバー名 serviceAccount:workloadpoolname[k8s_ns/ksa_name] を使用して KSA から Google Cloud へのリクエストを認証します。

このメンバー名で:

  • some.workload-pool.id.goog は、クラスタで設定された Workload Identity プールです。
  • ksa_name は、リクエストをしている KSA の名前です。
  • k8s_namespace は、KSA が定義されている Kubernetes Namespace です。

Google Cloud プロジェクトごとにひとつだけ固定される Workload Identity プール project_name.svc.id.goog が、自動的に作成されます。

KSA と GSA の間の関係の作成

Workload Identity によって Google Cloud が KSA を認証できるので、Cloud IAM を使用して KSA が GSA の役割を果たせるよう承認できます。

GSA は、クラスタと同じプロジェクトに存在する必要はありません。あらゆる GSA を組織内で使用できます。

次のコマンドは、cluster_project で管理されている KSA を、gsa_project で GSA として使用できるよう承認します。

    gcloud config set project gsa_project
    gcloud iam service-accounts add-iam-policy-binding \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:cluster_project.svc.id.goog[k8s_namespace/ksa_name]" \
      gsa_name@gsa_project.iam.gserviceaccount.com
    

KSA にアノテーションを付けて KSA と GSA の間をバインドするには:

    kubectl annotate serviceaccount \
      --namespace k8s_namespace \
       ksa_name \
       iam.gke.io/gcp-service-account=gsa_name@gsa_project.iam.gserviceaccount.com
    

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

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

GKE メタデータ サーバーは、Kubernetes で使用するために設計された新しいメタデータ サーバーです。daemonset として実行され、各クラスタノードで Pod が 1 つです。メタデータ サーバーは、http://metadata.google.internal(169.254.169.254:80)への HTTP リクエストを、Pod が役割を果たすよう構成される GSA のトークンを取得する GET /computeMetadata/v1/instance/service-accounts/default/token のようなリクエストも含めて、インターセプトします。メタデータ サーバーへのトラフィックが、Pod をホストする VM インスタンスから出ることはありません。

クラスタ間での ID の共有

名前、Namespace、workload identity プールを共有するすべての KSA が名前メンバー名に解決されて、GSA へのアクセスが共有されます。これは、複数のクラスタに同じ ID が含まれている場合に便利ですが、KSA 名と Namespace が慎重に管理されていないと危険です。

たとえば、Workload Identity がクラスタで有効になっている場合、次のコマンドによって、プロジェクト内のあらゆるクラスタ内で、デフォルトのサービス アカウントと Namespace を使用するすべての Kubernetes ワークロードに、同じアクセス権が付与されます。

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
    

制限事項

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

  • 現在、Workload Identity は、ワークロードが Anthos GKE オンプレミス クラスタで実行されるときはサポートされません。

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

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

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

  • GKE の Logging および Monitoring エージェントは、Node のサービス アカウントを引き続き使用します。

  • Workload Identity は Windows ノードではサポートされていません。

  • Workload Identity では Cloud Run for Anthos on Google Cloud がリクエスト指標を引き続きリリースするための手動設定を必要とします。

始める前に

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

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

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

gcloud init の使用

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

    gcloud init

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

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

gcloud config の使用

  • デフォルトのプロジェクト 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 を使用して Pod を開始する方法について説明します。

  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 \
          --release-channel regular \
          --workload-pool=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

    Config Connectorを使用して、Workload Identity を有効にした新しい GKE クラスタを作成できます。

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

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

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

    kubectl create namespace k8s-namespace
        

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

  6. Kubernetes サービス アカウントを作成します。

    kubectl create serviceaccount --namespace k8s-namespace ksa-name
        

    ここで

    • k8s-namespaceは、前の手順で作成した Namespace の名前です。
    • ksa-nameは、サービス アカウントに使用する名前です。

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

    また、デフォルトの Namespace を使用することも、Namespace でデフォルトの 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

    注: この手順には 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
  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 コンテナ イメージを実行する Pod を作成して、そこにインタラクティブなセッションで接続してください。

    kubectl run -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 APIs を簡単に利用できます。イメージのダウンロードに時間がかかる場合があります。

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

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

    gcloud auth list
        

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

クリーンアップ

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

    gcloud

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

    gcloud iam service-accounts delete gsa-name
        

    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. クラスタで Workload Identity を無効にします。

    gcloud 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 になります。

    gcloud container clusters update cluster-name \
          --workload-pool=project-id.svc.id.goog
        

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

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

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

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

gcloud container node-pools update nodepool-name \
      --cluster=cluster-name \
      --workload-metadata-from-node=GKE_METADATA
    

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

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

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

gcloud container node-pools create nodepool-name \
      --cluster=cluster-name \
      --workload-metadata-from-node=GKE_METADATA
    

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

クリーンアップ

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

    gcloud container node-pools update nodepool-name \
          --cluster=cluster-name \
          --workload-metadata-from-node=GCE_METADATA
        

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

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

    gcloud container clusters update cluster-name \
          --disable-workload-identity
        

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

別の方法

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

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

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

組織内での Workload Identity の無効化

セキュリティの観点から言えば、Workload Identity によってクラスタ(そしてクラスタを管理する人間)が任意の Google Cloud サービス アカウントを作成可能になります。サービス アカウント作成を無効にした管理者やサービス アカウント キー作成を無効にした管理者が組織の Workload Identity を無効にしたいと考えるのは、Workload Identity がこれらのポリシーへのバックドアの役割をするかもしれないからです。

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

次のステップ