↓メインコンテンツへスキップ
  1. Blogs/

TerraformでGKE Workload IdentityからCloud Storageへアクセスしてみた

2 分
Terraform GoogleCloud GKE WorkloadIdentity
0222-nnn
著者
0222-nnn
猫が好き
目次
Terraform-GoogleCloud - この記事は連載の一部です
パート 19: この記事

概要
#

GKE PodからGoogle Cloud APIを呼ぶとき、JSON Keyを使う方法は管理の手間が増えます。Secretとしての漏洩経路にもなります。PodにKeyファイルを配りたくないところです。

Workload Identity Federation for GKEを使えば、鍵なしで権限を借用できます。Kubernetes Service Account(KSA)をGoogle Cloud Service Account(GSA)に紐づける仕組みです。ここでは実際にPodからCloud Storageへ書き込みます。

Terraformの基本操作とkubectlの基本操作は前提としています。GKEのWorkload Identityが初めての方向けです。

Private Cluster化、Network Policy、複数Namespaceでの権限分離は扱いません。

検証すること
#

  • Workload Identity Federationを有効にしたGKE Clusterを作成できること
  • Kubernetes Service AccountとGoogle Cloud Service Accountを関連付けられること
  • Service Account KeyなしでPodからCloud Storageへ書き込めること

前提環境
#

  • Google Cloud CLI、Terraform、kubectl
  • Billingが有効な検証用Google Cloud Project
  • GKE、IAM、Cloud Storageを操作できるGoogleアカウント
  • 検証時のバージョン:Terraform 1.14.3、google 7.43.0、kubernetes 2.38.0

今回の構成
#

KubernetesのService AccountとGoogle CloudのService Accountは別物です。Workload Identityは、その2つを結びつけます。

flowchart TB
    subgraph GCP["Google Cloud"]
        subgraph Project["Project"]
            GSA["Google Cloud
Service Account"] Bucket["Cloud Storage Bucket"] subgraph Region["asia-northeast1"] subgraph Cluster["GKE Cluster"] subgraph NS["Namespace"] Pod["Job / Pod"] KSA["Kubernetes
Service Account"] Pod --- KSA end end end end end KSA -.->|"Workload Identity で紐付け"| GSA GSA -.->|"objectCreator"| Bucket Pod -->|"オブジェクトを書き込み"| Bucket

点線が権限の関係、実線が実際の通信です。鍵ファイルをPodへ配らずに済みます。

Podが書き込むまでの流れです。

sequenceDiagram
    participant Pod as Job / Pod
    participant KSA as Kubernetes SA
    participant Meta as GKE Metadata Server
    participant GSA as Google Cloud SA
    participant GCS as Cloud Storage

    Pod->>Meta: 認証情報を要求
    Meta->>KSA: 紐付けを確認
    KSA-->>Meta: Workload Identity の対応あり
    Meta->>GSA: 権限を借用
    GSA-->>Pod: 一時的なアクセストークン
    Pod->>GCS: オブジェクトを書き込み

Service Account Keyを作らないため、Secretとして鍵を管理する必要がありません。

使用するTerraformコード
#

KSAとGSAを関連付ける
#

resource "google_service_account_iam_member" "workload_identity_user" {
  service_account_id = google_service_account.gcs.name
  role               = "roles/iam.workloadIdentityUser"
  member             = "serviceAccount:${var.project_id}.svc.id.goog[${var.k8s_namespace}/${var.k8s_service_account}]"
}

resource "kubernetes_service_account_v1" "gcs" {
  metadata {
    name      = var.k8s_service_account
    namespace = kubernetes_namespace_v1.demo.metadata[0].name
    annotations = {
      "iam.gke.io/gcp-service-account" = google_service_account.gcs.email
    }
  }
}

IAM MemberのNamespaceとKSA名、KSA AnnotationのGSA Emailが対応します。GSAにはBucket単位でObject書込権限を付与し、Project全体へ広げません。

GKEと検証Job
#

ClusterではWorkload Poolを有効化します。

workload_identity_config {
  workload_pool = "${var.project_id}.svc.id.goog"
}

サンプルのKubernetes Jobは対象KSAで起動し、gcloud storage cpでObjectを作成します。TerraformのKubernetes Providerは作成したClusterのEndpointとToken、CA Certificateを使います。

実行と確認
#

cd Advanced-Examples/03-gke-workload-identity-gcs
cp terraform.tfvars.example terraform.tfvars
terraform init
terraform fmt -check
terraform validate
terraform apply

VPC、GKE Cluster、Spot Node Pool、Bucket、Namespace、Jobが作成されます。合わせて15リソースです。GKE作成に十数分、Job完了待ちでさらに1分ほどかかりました。

Apply complete! Resources: 15 added, 0 changed, 0 destroyed.

Outputs:

bucket_name = "tf-adv-gke-wi-YOUR_PROJECT_ID"
cluster_name = "tf-adv-gke-wi"
gcp_service_account_email = "tf-adv-gke-wi-gcs@YOUR_PROJECT_ID.iam.gserviceaccount.com"
k8s_namespace = "wi-demo"
object_name = "workload-identity/hello.txt"

ClusterがRUNNING、Jobが実際にオブジェクトを書き込めたかを確認します。

gcloud container clusters describe "$(terraform output -raw cluster_name)" \
  --zone="$(terraform output -raw cluster_location)" \
  --format='value(status)'

gcloud storage cat "gs://$(terraform output -raw bucket_name)/$(terraform output -raw object_name)"
RUNNING
hello-from-workload-identity

Job Logも確認します。

eval "$(terraform output -raw get_credentials_example)"
kubectl -n "$(terraform output -raw k8s_namespace)" logs job/wi-gcs-write
Copying from <STDIN>...
Operation completed over 1 objects.
hello-from-workload-identity

ObjectとJob Logの両方にhello-from-workload-identityが表示されました。KSAからGSAを経由した書き込みが成功しています。

後片付けと注意点
#

terraform destroy
Destroy complete! Resources: 15 destroyed.

GKE Clusterは課金が発生します。サンプルは費用を抑えるためSpot Nodeを使いますが、中断を許容できる検証用です。Kubernetes ResourceをTerraformで扱う場合は、Cluster削除より先にProviderが到達不能にならないDependencyにも注意します。

まとめ
#

  • PodへService Account Keyを保存せずGoogle Cloud APIを利用できる
  • KSAとGSAの対応をIAMとAnnotationで宣言できる
  • GCS権限をBucket単位へ限定できる
  • Jobによって実際のObject書込みまで検証できる

参考資料
#

次回
#

次回はTerraform StateをCloud Storage Backendへ移行します。

Terraform-GoogleCloud - この記事は連載の一部です
パート 19: この記事

関連記事

TerraformでGitHub Actions用Workload Identity Federationを構築してみた
2 分
Terraform GoogleCloud GitHubActions WorkloadIdentity
Terraform StateをCloud Storage Remote Backendへ移行してみた
2 分
Terraform GoogleCloud CloudStorage
TerraformからGoogle Cloudへ接続してProject情報を取得してみた
3 分
Terraform GoogleCloud
TerraformでArtifact RegistryのDocker Repositoryを作成してみた
2 分
Terraform GoogleCloud Docker
TerraformでArtifact RegistryのコンテナをCloud Runへデプロイしてみた
2 分
Terraform GoogleCloud CloudRun ArtifactRegistry
TerraformでBigQuery DatasetとTableを作成してみた
2 分
Terraform GoogleCloud