How to Configure Workload Identity for GKE Pods
Workload Identity enables a Kubernetes Service Account (KSA) to impersonate a Google Service Account (GSA) so that GKE pods can securely authenticate to Google Cloud APIs without managing long-lived service account keys.
Configuring Workload Identity for GKE pods eliminates the security risks of storing JSON keys in Secrets or container images. According to the google/skills repository, this configuration requires binding IAM permissions at the Google Cloud layer and annotating the KSA to establish the impersonation mapping. Once configured, the GKE metadata server automatically injects short-lived OAuth 2.0 tokens into pods.
Prerequisites: Enable Workload Identity on the Cluster
Before configuring individual pods, the GKE cluster must have Workload Identity enabled at the platform level. As documented in skills/cloud/gke-platform-security/SKILL.md, this requires setting the workloadPool parameter to <project>.svc.id.goog during cluster creation or modification.
If creating a new cluster, include the --workload-pool flag:
gcloud container clusters create my-cluster \
--workload-pool=my-project.svc.id.goog \
--region=us-central1
For existing clusters, verify that the workloadMetadataConfig.mode is set to GKE_METADATA in the node pool configuration, as detailed in skills/cloud/gke-basics/SKILL.md.
Step-by-Step Configuration
The complete configuration process involves three main components: creating the Kubernetes Service Account, granting IAM permissions on the Google Service Account, and linking them via annotation.
Create a Kubernetes Service Account
First, create a namespace and KSA that will represent the pod's identity within the cluster. The skills/cloud/gke-workload-security/SKILL.md file provides the standard pattern for this step.
apiVersion: v1
kind: Namespace
metadata:
name: workload-identity-test-ns
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-ksa
namespace: workload-identity-test-ns
Apply this configuration using kubectl apply -f ksa.yaml.
Grant IAM Permissions on the Google Service Account
Next, authorize the KSA to impersonate the GSA by granting the roles/iam.workloadIdentityUser role. The IAM binding must reference the KSA using the specific format serviceAccount:<project>.svc.id.goog[<namespace>/<ksa-name>].
Execute the binding command as shown in skills/cloud/gke-workload-security/SKILL.md:
gcloud iam service-accounts add-iam-policy-binding \
my-gsa@my-project.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:my-project.svc.id.goog[workload-identity-test-ns/my-ksa]"
This command grants the specific KSA permission to generate short-lived credentials for the GSA.
Annotate the Kubernetes Service Account
The final linkage step requires annotating the KSA with the target GSA's email address. GKE reads this annotation to determine which Google identity tokens to serve when pods query the metadata server.
Update the KSA manifest to include the iam.gke.io/gcp-service-account annotation:
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-ksa
namespace: workload-identity-test-ns
annotations:
iam.gke.io/gcp-service-account: my-gsa@my-project.iam.gserviceaccount.com
Apply the updated configuration. GKE now recognizes that pods running as my-ksa should receive tokens for my-gsa.
Deploy a Pod Using the Service Account
Reference the KSA in the pod specification. No volume mounts or environment variables containing credentials are required.
apiVersion: v1
kind: Pod
metadata:
name: hello-workload-identity
namespace: workload-identity-test-ns
spec:
serviceAccountName: my-ksa
containers:
- name: app
image: python:3.11
command: ["python", "-c"]
args:
- |
from google.cloud import storage
client = storage.Client()
buckets = list(client.list_buckets())
print("Buckets:", buckets)
When this pod starts, the Google Cloud client library automatically queries http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token to obtain a valid access token.
How It Works
The Workload Identity mechanism operates through the GKE metadata server running on each node. When a pod with an annotated KSA requests a token, the metadata server validates the pod's identity against the IAM binding and mints a short-lived OAuth 2.0 access token for the associated GSA.
Key architectural characteristics include:
- Token lifecycle: Access tokens expire after one hour and are automatically refreshed by client libraries
- No key material: JSON service account keys are never stored in etcd, Secrets, or container images
- Standard client behavior: Applications use default credential chains without modification
The skills/cloud/gke-workload-security/SKILL.md file emphasizes that this approach eliminates the need to rotate long-lived credentials while maintaining strict identity boundaries between namespaces.
Summary
- Enable Workload Identity at the cluster level using
--workload-pool=<project>.svc.id.googas documented inskills/cloud/gke-platform-security/SKILL.md - Create a KSA in your target namespace to serve as the pod's identity
- Bind IAM permissions using
gcloud iam service-accounts add-iam-policy-bindingwith theroles/iam.workloadIdentityUserrole and the member formatserviceAccount:<project>.svc.id.goog[<ns>/<ksa>] - Annotate the KSA with
iam.gke.io/gcp-service-account: <gsa>@<project>.iam.gserviceaccount.comto establish the impersonation link - Deploy pods referencing the KSA in
spec.serviceAccountNamewithout mounting any credential files
Frequently Asked Questions
What is the difference between Workload Identity and traditional service account keys?
Traditional service account keys are long-lived JSON files that must be manually rotated and securely stored in Kubernetes Secrets, creating persistent breach risks. Workload Identity uses short-lived tokens (maximum one-hour lifetime) minted dynamically by the GKE metadata server, eliminating key storage entirely and leveraging IAM for access control. As implemented in the google/skills repository examples, Workload Identity represents the recommended security posture for GKE workloads.
How do I verify that Workload Identity is working in my pod?
Execute a shell inside the running pod and query the metadata server directly using curl:
curl -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
If Workload Identity is configured correctly, the response contains a valid OAuth 2.0 access token. You can also inspect the token's claims using jwt.io to verify that the email claim matches your target GSA.
Can I use Workload Identity with multiple Google Cloud projects?
Yes, but the IAM binding must exist in the project that owns the Google Service Account. If your GKE cluster runs in Project A but needs to impersonate a GSA in Project B, you must run the gcloud iam service-accounts add-iam-policy-binding command in Project B while referencing the KSA from Project A using the full serviceAccount:<project-a>.svc.id.goog[<ns>/<ksa>] identifier.
What permissions does the KSA need in the Kubernetes cluster?
The Kubernetes Service Account itself requires no special RBAC permissions within the cluster to use Workload Identity. The authorization occurs entirely at the Google Cloud IAM layer through the roles/iam.workloadIdentityUser binding. However, the pod must be able to reach the metadata server at 169.254.169.254, which requires standard network connectivity without restrictive network policies blocking that address.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →