TL;DR
-
GKE から Google Service Account (GSA) を利用するのに GSA のアカウントキーを発行して Secret を作成してはいけない
-
Kubernetes Service Account (KSA) と GSA を紐づける Workload Identity を利用して認証を行うべき
Why?
以下は公式ドキュメントからの抜粋。
アカウントキーを発行してGCPのプロダクトを利用するのには、
- キーの漏洩リスク
- キーの更新(デフォルトの有効期限は10年)
という Secret を手動で管理、保護する手間がありました。
注: Workload Identity は、GKE 内から Google Cloud サービスにアクセスする場合におすすめの方法です。Workload Identity を使用すると、Kubernetes サービス アカウントを Google サービス アカウントとして機能するよう構成でき、Secret を手動で管理、保護する必要がなくなります。
Workload Identity とは
一言で言うと、「kubernetes の Service Account GCP の Serivce Account を紐づけ(Binding)られるようにする仕組み」です。アカウントキーでの認証方法とWorkload Identity での認証方法を図で比較します。
アカウントキーでの認証方法
Workload Identity での認証方法
利用手順
大別すると以下のようになります。
詳細は公式ドキュメントを参照してください。
- クラスタで Workload Identity を有効化
- GSA を作成し、KSA との IAM policy Binding を作成。
- KSA を作成し、GSA へのアノテーションを追加。
- Pod で KSA を指定
1. クラスタで Workload Identity を有効化
- 新しいクラスタで Workload Identity を有効にする
$ gcloud container clusters create cluster-name \
--release-channel regular \
--workload-pool=project-id.svc.id.goog
- 既存のクラスタで Workload Identity を有効にする
$ gcloud container clusters update cluster-name \
--workload-pool=project-id.svc.id.goog
2. GSA を作成し、KSA との IAM policy Binding を作成
$ gcloud iam service-accounts create gsa-name
$ 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
Terraform
data "google_project" "project" {
}
locals {
annotations = formatlist(
"serviceAccount:${data.google_project.project.project_id}.svc.id.goog[%s]",
var.k8s_service_accounts,
)
}
data "google_service_account" "serviceaccount" {
account_id = var.gcp_service_account_id
}
resource "google_service_account_iam_binding" "wi_iam_binding" {
service_account_id = data.google_service_account.serviceaccount.name
role = "roles/iam.workloadIdentityUser"
members = local.annotations
}
variable "gcp_service_account_id" {
type = string
default = ""
description = "GCP service account ID (before `@`)"
}
variable "k8s_service_accounts" {
type = list(string)
default = []
description = "Kubernetes service accounts in the format of `$ns/$sa_name`"
}
3. KSA を作成し、GSA へのアノテーションを追加
$ kubectl create serviceaccount --namespace k8s-namespace ksa-name
$ kubectl annotate serviceaccount \
--namespace k8s-namespace \
ksa-name \
iam.gke.io/gcp-service-account=gsa-name@project-id.iam.gserviceaccount.com
Manifest
apiVersion: v1
kind: ServiceAccount
metadata:
name: $KSA_NAME
namespace: $K8S_NAMESPACE
annotations:
iam.gke.io/gcp-service-account: "$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com"
4. Pod で KSA を指定
apiVersion: apps/v1
kind: Deployment
# ...
spec:
template:
spec:
serviceAccountName: $KSA_NAME
# ...
nodeSelector:
iam.gke.io/gke-metadata-server-enabled: "true"