Pod Configuration¶
Configure pods to use Workload Identity and integrate with GCP services. This guide covers deployment patterns and common access scenarios.
Deploy Your Workload¶
Deploy a Pod with the annotated ServiceAccount:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
serviceAccountName: app-sa
containers:
- name: app
image: gcr.io/PROJECT_ID/app:v1.0.0
GKE Default Behavior
On GKE with Workload Identity enabled, Kubernetes automatically injects the token volume into all Pods using an annotated ServiceAccount. You typically don't need to specify it explicitly.
Common Patterns¶
GCS (Google Cloud Storage) Access¶
# Python example
from google.cloud import storage
# Credentials loaded automatically from token
storage_client = storage.Client(project='PROJECT_ID')
bucket = storage_client.bucket('my-bucket')
blob = bucket.blob('data.txt')
blob.download_to_filename('data.txt')
The SDK reads the token from the projected volume and uses it to authenticate.
Firestore Database Access¶
# Python example
from google.cloud import firestore
# Credentials loaded automatically
db = firestore.Client(project='PROJECT_ID')
docs = db.collection('users').where('status', '==', 'active').stream()
for doc in docs:
print(doc.to_dict())
All Google Cloud client libraries support automatic credential discovery.
Cloud API Calls (Direct HTTP)¶
#!/bin/bash
# Bash example: Call Cloud API directly
# Get token from metadata server
TOKEN=$(curl -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token \
| jq -r .access_token)
# Call Cloud API
curl -H "Authorization: Bearer $TOKEN" \
https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/us-central1-a/instances
Direct HTTP requests include the token in the Authorization header.
Cross-Project Access¶
Your app may need to access resources in a different GCP project.
# Create service account in PROJECT_B
gcloud iam service-accounts create external-reader \
--project PROJECT_B \
--display-name "External reader for PROJECT_A"
# Grant permissions in PROJECT_B
gcloud projects add-iam-policy-binding PROJECT_B \
--member="serviceAccount:external-reader@PROJECT_B.iam.gserviceaccount.com" \
--role="roles/storage.objectViewer"
# In PROJECT_A, create a service account for your app
gcloud iam service-accounts create app-gcp \
--project PROJECT_A \
--display-name "App in PROJECT_A"
# Grant PROJECT_A service account permission to impersonate PROJECT_B service account
gcloud iam service-accounts add-iam-policy-binding \
external-reader@PROJECT_B.iam.gserviceaccount.com \
--role="roles/iam.serviceAccountUser" \
--member="serviceAccount:app-gcp@PROJECT_A.iam.gserviceaccount.com"
Now your app running in PROJECT_A can impersonate the service account in PROJECT_B and access its resources.
Secret Manager Access¶
# Python example
from google.cloud import secretmanager
client = secretmanager.SecretManagerServiceClient()
# Access secret (credentials automatic)
secret_name = f"projects/PROJECT_ID/secrets/api-key/versions/latest"
response = client.access_secret_version(request={"name": secret_name})
api_key = response.payload.data.decode('UTF-8')
Combine Workload Identity with Secret Manager for encrypted credential storage.
BigQuery Data Access¶
# Python example
from google.cloud import bigquery
client = bigquery.Client(project='PROJECT_ID')
# Run query (credentials automatic)
query = """
SELECT COUNT(*) as count FROM `PROJECT_ID.dataset.table`
"""
results = client.query(query).result()
for row in results:
print(f"Count: {row['count']}")
Client libraries automatically use the token.
Cloud Pub/Sub Publishing¶
# Python example
from google.cloud import pubsub_v1
publisher = pubsub_v1.PublisherClient()
topic_path = publisher.topic_path('PROJECT_ID', 'my-topic')
# Publish message (credentials automatic)
data = b'Hello, World!'
message_id = publisher.publish(topic_path, data).result()
print(f"Published message ID: {message_id}")
All async operations use the token automatically.
Validation Commands¶
After deployment, verify everything is working:
# 1. Verify ServiceAccount is annotated
kubectl get serviceaccount app-sa -n production -o yaml | grep gcp-service-account
# 2. Verify IAM binding exists
gcloud iam service-accounts get-iam-policy \
app-gcp@PROJECT_ID.iam.gserviceaccount.com \
--format='table(bindings[].role, bindings[].members[])'
# 3. Test Cloud API access from Pod
kubectl run -it --rm debug \
--image=google/cloud-sdk:slim \
--serviceaccount=app-sa \
--namespace=production \
-- gcloud storage ls gs://my-bucket
# 4. Verify token is being injected
kubectl exec -it deployment/app -n production -- \
ls -la /var/run/secrets/tokens/
# 5. Decode the token and verify audience
kubectl exec -it deployment/app -n production -- \
bash -c 'cat /var/run/secrets/tokens/gcp-ksa | head -c 100'
Related Configuration¶
- Service Account Binding - Create service accounts and IAM bindings
- Migration Guide - Migrate from service account keys
- Troubleshooting - Debug auth failures, token issues, permissions
- GKE Hardening - Comprehensive security configuration