😃

GKE Workload Identity: KSA Principalってなんやねん

に公開

背景

GKE上で動くPod上から、Google Cloudリソースにアクセスする際、従来のGSAに特定のRoleを紐付け、Kubernetes Service Account(KSA)を紐づけるのではなく、KSAに直接IAMロールを付与する方法があることを知ったので、軽く調べることとした

調べること

  • principal:// 形式のIAM memberとは何か
  • 従来のGSA経由の方式と何が違うのか
  • どっちを使えばいいのか

前提: GKE上のPodからGCPリソースにアクセスしたい

GKE上で動くPodがCloud StorageやVertex AIなどのGCPリソースにアクセスするには、何らかの認証情報が必要になる。
サービスアカウントキー(JSONキー)をPodに渡す方法もあるが、キーの流出リスクがあるため非推奨。代わりに使うのが Workload Identity という仕組み。

GSA経由(Workload Identity)

GCP Service Account(GSA)を作り、Kubernetes Service Account(KSA)と紐づける方法。

Pod → KSA → (Workload Identity binding) → GSA → GCPリソース

Terraformで書くとこうなる:

# 1. GSAを作る
resource "google_service_account" "my_app" {
  account_id = "my-app"
}

# 2. GSAにIAMロールを付与
resource "google_project_iam_member" "my_app_storage" {
  role   = "roles/storage.objectViewer"
  member = "serviceAccount:${google_service_account.my_app.email}"
}

# 3. KSAがこのGSAを使えるようにbindingする
resource "google_service_account_iam_member" "workload_identity" {
  service_account_id = google_service_account.my_app.name
  role               = "roles/iam.workloadIdentityUser"
  member             = "serviceAccount:${var.project_id}.svc.id.goog[my-namespace/my-app]"
}

さらにKubernetes側でもKSAにannotationを付ける必要がある

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app
  annotations:
    iam.gke.io/gcp-service-account: my-app@my-project.iam.gserviceaccount.com

GSAの作成、IAM付与、KSA↔GSAのbinding、KSA側のannotation、と手順が多い。

KSA Principal直接付与(Workload Identity Federation / Direct WIF)

GSAを作らず、KSAに直接IAMロールを付与する方法。

Pod → KSA → GCPリソース

GSAが消えて、構成がシンプルになる。

locals {
  ksa_principal = "principal://iam.googleapis.com/projects/${data.google_project.this.number}/locations/global/workloadIdentityPools/${var.project_id}.svc.id.goog/subject/ns/my-namespace/sa/my-app"
}

# これだけでOK
resource "google_project_iam_member" "my_app_storage" {
  role   = "roles/storage.objectViewer"
  member = local.ksa_principal
}
  • KSA側のannotationも不要
  • Terraform側もKubernetes側もリソースが減る

principal:// の構造

principal://iam.googleapis.com/projects/{PROJECT_NUMBER}/locations/global/workloadIdentityPools/{PROJECT_ID}.svc.id.goog/subject/ns/{NAMESPACE}/sa/{KSA_NAME}
パート 意味
{PROJECT_NUMBER} GCPプロジェクト番号(数字)
{PROJECT_ID}.svc.id.goog GKEクラスタのWorkload Identity Pool
ns/{NAMESPACE} KubernetesのNamespace
sa/{KSA_NAME} Kubernetes Service Account名

比較

GSA経由 KSA Principal直接
GCP Service Account 必要 不要
KSAのannotation 必要 不要
Terraform管理リソース数 多い(GSA + binding + IAM) 少ない(IAMだけ)
IAM memberの形式 serviceAccount:xxx@yyy.iam... principal://iam.googleapis.com/...
GCPコンソールでの見え方 GSAが表示される principalとして表示される

どっちを使うか

基本的に新規で作るなら KSA Principal直接付与でいい。GSAを別途管理する理由がない。

GSA経由が必要になるケースとしては:

  • 複数のKSAで同じ権限セットを共有したい場合(GSAを共有する)
  • GKE外(Cloud RunやCloud Functionsなど)と同じSAを使いたい場合
  • 既存のGSA中心の構成にあわせる場合

既存サービスをわざわざ移行する必要はないが、新規サービスはKSA Principal直接付与の方がシンプルに済む。

参考

Discussion