😃
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