How to Configure Workload Identity Binding for GKE: Step-by-Step Implementation Guide

Configure Workload Identity binding for GKE by creating an IAM policy binding that grants the roles/iam.workloadIdentityUser role to your Kubernetes Service Account (KSA) on a Google Service Account (GSA), annotating the KSA with iam.gke.io/gcp-service-account=<gsa-email>, and deploying pods with the iam.gke.io/gke-metadata-server-enabled: "true" node selector.

According to the implementation patterns documented in the google/skills repository, specifically within skills/cloud/gke-workload-security/SKILL.md, configuring Workload Identity binding enables GKE workloads to impersonate Google Cloud identities without storing long-lived service account keys in your cluster. This approach leverages the GKE metadata server to inject short-lived OAuth tokens automatically, allowing Google client libraries to authenticate seamlessly while maintaining strict least-privilege controls.

Understanding the Workload Identity Architecture

Before implementing the configuration, it is essential to understand the trust relationship between Kubernetes and Google Cloud identities as defined in the source code.

KSA to GSA Trust Relationship

The foundation of Workload Identity is an IAM policy binding stored on the GSA itself. As specified in skills/cloud/gke-workload-security/SKILL.md, you must grant the roles/iam.workloadIdentityUser role to a member identifier formatted as:


serviceAccount:<PROJECT_ID>.svc.id.goog[<NAMESPACE>/<KSA_NAME>]

This binding explicitly allows the Kubernetes Service Account to impersonate the Google Service Account. The IAM policy resides in your GCP project and serves as the authoritative trust anchor for the entire Workload Identity flow.

Metadata Server Integration

GKE clusters running Workload Identity expose a metadata server enabled via the iam.gke.io/gke-metadata-server-enabled node selector. When a pod uses an annotated KSA, this metadata server intercepts token requests at http://metadata.google.internal and issues short-lived identity tokens valid for the mapped GSA. This mechanism eliminates the need for JSON key files mounted as Kubernetes secrets and handles automatic token rotation transparently.

Step-by-Step Configuration Guide

Follow these precise steps to configure Workload Identity binding for your GKE cluster, referencing the exact commands and manifests from the google/skills repository.

Step 1: Create the Namespace and Kubernetes Service Account

Create a dedicated namespace and KSA to isolate your workload and maintain clear identity boundaries.

kubectl create namespace workload-identity-test-ns
kubectl create serviceaccount <ksa-name> --namespace workload-identity-test-ns

Replace <ksa-name> with your desired Kubernetes Service Account name.

Step 2: Establish the IAM Policy Binding

Configure the critical trust relationship by binding the KSA to the GSA. Execute the gcloud iam service-accounts add-iam-policy-binding command, ensuring you use the exact member identifier format documented in the source code.

gcloud iam service-accounts add-iam-policy-binding \
    <gsa-name>@<project-id>.iam.gserviceaccount.com \
    --role roles/iam.workloadIdentityUser \
    --member "serviceAccount:<project-id>.svc.id.goog[workload-identity-test-ns/<ksa-name>]"

This command modifies the IAM policy on the GSA to recognize the KSA as a valid workload identity user.

Step 3: Annotate the KSA with GSA Identity

Link the Kubernetes Service Account to the Google Service Account using the required annotation key iam.gke.io/gcp-service-account. This annotation is read by the GKE metadata server to determine which GSA to impersonate for pods using this KSA.

kubectl annotate serviceaccount <ksa-name> \
    --namespace workload-identity-test-ns \
    iam.gke.io/gcp-service-account=<gsa-name>@<project-id>.iam.gserviceaccount.com

Step 4: Deploy a Pod with Workload Identity Enabled

Use the manifest from assets/workload-identity-pod.yaml in the google/skills repository to deploy a test pod. The specification must include the iam.gke.io/gke-metadata-server-enabled: "true" node selector and reference your KSA in the serviceAccountName field.

apiVersion: v1
kind: Pod
metadata:
  name: workload-identity-test
  namespace: workload-identity-test-ns
spec:
  serviceAccountName: my-ksa   # <-- replace with your KSA

  automountServiceAccountToken: false
  containers:
  - image: gcr.io/google.com/cloudsdktool/cloud-sdk
    name: workload-identity-test
    command: ["sleep", "infinity"]
  nodeSelector:
    iam.gke.io/gke-metadata-server-enabled: "true"
  securityContext:
    runAsNonRoot: true
    runAsUser: 65532
    seccompProfile:
      type: RuntimeDefault

Deploy the pod using:

kubectl apply -f assets/workload-identity-pod.yaml -n workload-identity-test-ns

Step 5: Verify Token Acquisition

Validate the configuration by executing a shell in the running pod and querying the metadata server for an access token.

kubectl exec -it workload-identity-test -n workload-identity-test-ns -- /bin/bash
curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token

A successful JSON response containing an access_token confirms that the Workload Identity binding is properly configured and the pod can impersonate the GSA. You can further verify functionality by running Google Cloud CLI commands inside the pod, such as gcloud storage ls, to confirm API access.

Security Best Practices

When you configure Workload Identity binding for GKE, adhere to these security principles derived from the google/skills implementation:

  • Least-Privilege IAM Roles: Grant the GSA only the specific IAM roles required by your workload (e.g., roles/storage.objectViewer), limiting the blast radius of potential compromises.
  • Disable Legacy Token Auto-Mount: Set automountServiceAccountToken: false in your pod spec, as shown in the example manifest, to prevent legacy Kubernetes service account tokens from being mounted unnecessarily.
  • Namespace Isolation: Use dedicated namespaces for KSAs to prevent cross-namespace identity confusion and maintain clear audit trails for which workloads can assume specific Google identities.

Summary

  • Configure Workload Identity binding by creating an IAM policy binding between your KSA and GSA using the roles/iam.workloadIdentityUser role and the member format serviceAccount:<PROJECT_ID>.svc.id.goog[<NAMESPACE>/<KSA_NAME>].
  • Annotate the KSA with iam.gke.io/gcp-service-account=<gsa-email> to establish the identity mapping recognized by the GKE metadata server.
  • Enable metadata server injection by setting the node selector iam.gke.io/gke-metadata-server-enabled: "true" on your pods.
  • Verify functionality by querying the metadata server endpoint from within a running pod to confirm short-lived token issuance.
  • Reference implementation examples are available in skills/cloud/gke-workload-security/SKILL.md and assets/workload-identity-pod.yaml within the google/skills repository.

Frequently Asked Questions

What is the exact IAM member format for Workload Identity binding?

The IAM member format is serviceAccount:<PROJECT_ID>.svc.id.goog[<NAMESPACE>/<KSA_NAME>]. This unique identifier allows Google Cloud IAM to recognize Kubernetes Service Accounts as valid principals for policy bindings, as implemented in the google/skills repository's GKE security guides. The format must include the project ID, the literal string .svc.id.goog, and the exact namespace and KSA name in brackets.

Why does my pod need the iam.gke.io/gke-metadata-server-enabled node selector?

This node selector ensures the pod is scheduled on nodes running the GKE metadata server, which is the component responsible for intercepting metadata requests and issuing short-lived OAuth tokens for the mapped Google Service Account. Without this selector, the pod cannot obtain valid credentials through Workload Identity and will fail to authenticate with Google Cloud APIs.

How do I troubleshoot 403 errors from the metadata server?

First, verify that the IAM binding includes the correct namespace and KSA name in the member identifier, as typos here are the most common cause of authentication failures. Then confirm that the KSA annotation key iam.gke.io/gcp-service-account exactly matches the GSA email address. Finally, ensure the GSA has the necessary GCP IAM roles granted directly to it, not just to the KSA binding.

Can I use Workload Identity with existing Google Service Accounts?

Yes, you can bind existing GSAs to new or existing KSAs without recreating the GSA. Simply add the IAM policy binding using gcloud iam service-accounts add-iam-policy-binding with the appropriate KSA member format, then annotate the KSA accordingly. This allows you to migrate existing workloads to Workload Identity without rotating service account keys or changing application code.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →