CTS-KB

KSA・IAM service accountの使い分け:GKEのキーレス認証

⏱ 約 3 分で読めます
#Kubernetes#GKE#KSA#IAM#Workload Identity

GKE上のアプリケーションがSecret ManagerやCloud Storageへアクセスするとき、サービスアカウントJSONキーをPodへ置く必要はありません。Workload Identity Federation for GKE を使い、短命な認証情報を取得します。

ここで混乱しやすいのがKSAと、Google CloudのIAM service accountです。

2種類のservice account

呼び方正式な対象管理場所役割
KSAKubernetes ServiceAccountKubernetes NamespacePodがKubernetes内で名乗るID
IAM service accountGoogle Cloud IAM service accountGoogle Cloud IAMGoogle Cloud APIで使うワークロードID

Kubernetes関連資料では後者を GSA と呼ぶことがありますが、Google Cloudの正式名称ではなく、KSAと区別するための便宜的な略称です。本記事では「IAM service account」と表記します。

まずKSAをワークロードごとに分ける

apiVersion: v1
kind: ServiceAccount
metadata:
  name: example-api
  namespace: YOUR_NAMESPACE
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-api
  namespace: YOUR_NAMESPACE
spec:
  replicas: 2
  selector:
    matchLabels:
      app: example-api
  template:
    metadata:
      labels:
        app: example-api
    spec:
      serviceAccountName: example-api
      containers:
        - name: api
          image: registry.gitlab.com/GROUP/PROJECT/IMAGE:TAG

Namespaceの default KSAを全アプリで共有すると、権限境界が曖昧になります。API、バッチ、オペレーターなど役割ごとに専用KSAを作ります。

推奨:KSA主体をIAMへ直接認可する

現在のGKEでは、Workload Identity Pool内のKSA主体へIAMロールを直接付与できます。対応サービスではこの方式が経路が短く、IAM service accountを追加せずに済みます。

まずプロジェクト番号を確認します。

gcloud projects describe YOUR_PROJECT_ID \
  --format='value(projectNumber)'

次に、対象リソースまたはプロジェクトへKSA主体を許可します。次はSecret Manager参照ロールをプロジェクト単位で付ける構文例です。実運用では可能なら個別Secret単位へ狭めます。

gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
  --role=roles/secretmanager.secretAccessor \
  --member="principal://iam.googleapis.com/projects/YOUR_PROJECT_NUMBER/locations/global/workloadIdentityPools/YOUR_PROJECT_ID.svc.id.goog/subject/ns/YOUR_NAMESPACE/sa/YOUR_KSA_NAME" \
  --condition=None

Podの serviceAccountNameYOUR_KSA_NAME を指定します。Google CloudクライアントライブラリがApplication Default Credentialsを使うと、GKEのメタデータサービスを通じて短命トークンを取得できます。

GKE側の前提

  • AutopilotクラスタではWorkload Identity Federation for GKEが常に有効
  • StandardクラスタではクラスタとNode Poolの設定を確認する
  • NodeのIAM service accountと、PodのKSA主体を混同しない

特にコンテナイメージのpullは、通常はNode側の資格情報または imagePullSecrets が関係し、アプリPodのWorkload Identityとは別経路です。

必要な場合:KSAからIAM service accountを借用する

一部のAPIや既存アプリがWorkload Identity Poolの主体を直接扱えない場合は、KSAがIAM service accountを借用する方式を使います。

gcloud iam service-accounts create YOUR_IAM_SA_NAME \
  --project=YOUR_PROJECT_ID

gcloud iam service-accounts add-iam-policy-binding \
  YOUR_IAM_SA_NAME@YOUR_PROJECT_ID.iam.gserviceaccount.com \
  --role=roles/iam.workloadIdentityUser \
  --member="serviceAccount:YOUR_PROJECT_ID.svc.id.goog[YOUR_NAMESPACE/YOUR_KSA_NAME]" \
  --project=YOUR_PROJECT_ID

kubectl annotate serviceaccount YOUR_KSA_NAME \
  -n YOUR_NAMESPACE \
  iam.gke.io/gcp-service-account=YOUR_IAM_SA_NAME@YOUR_PROJECT_ID.iam.gserviceaccount.com

さらに、そのIAM service account自体へ必要最小限の業務ロールを付与します。roles/owner や広いEditor権限で済ませません。

どちらを選ぶか

KSA主体を対象Google Cloud APIが直接認可できるか
  ├─ はい → KSA主体へ対象リソースのIAMロールを直接付与
  └─ いいえ/互換性要件あり
       → KSAが専用IAM service accountを借用

「KSAには必ずIAM service accountを1対1で紐付ける」という古い定型だけで設計せず、直接認可を先に検討します。

権限設計の要点

  • KSAはワークロード単位、Namespace単位で分離する
  • IAMロールはプロジェクト全体より個別リソースへ狭める
  • JSONキーをKubernetes Secretやイメージへ置かない
  • アプリの権限と、Nodeやデプロイ担当者の権限を分ける
  • kubectl auth can-i はKubernetes RBACの確認で、Google Cloud IAMとは別物

動作確認

Pod内へ gcloud を常設する必要はありません。アプリが利用する公式クライアントライブラリで対象APIへの最小操作を行い、Cloud Audit LogsとPodログを確認します。デバッグ用Podを使う場合も、本番KSAを無関係なイメージへ割り当てないよう注意します。

次回

このキーレス認証を使い、GKEでSecret Managerを安全に利用する方法を比較します。

参考資料