← blog

2025-02-20

Workload Identity vs IRSA: what's actually different

The same problem

Pods need to talk to cloud APIs — S3, Secret Manager, Pub/Sub. The wrong solution is a static key mounted as a secret. The right solution is short-lived credentials bound to the pod's identity.

AWS calls it IRSA (IAM Roles for Service Accounts). GCP calls it Workload Identity. Both use the same primitives underneath: a Kubernetes ServiceAccount, an OIDC token, and a cloud IAM binding.

How IRSA works

  1. EKS exposes an OIDC endpoint.
  2. You create an IAM role with a trust policy that allows the OIDC issuer to assume it, scoped to a specific namespace/service account.
  3. Annotate the Kubernetes ServiceAccount with eks.amazonaws.com/role-arn.
  4. EKS injects AWS_WEB_IDENTITY_TOKEN_FILE and AWS_ROLE_ARN env vars into pods using that SA.
  5. The AWS SDK picks these up automatically — no code changes.

How Workload Identity works

  1. GKE registers as a Workload Identity pool.
  2. You bind a GCP Service Account (GSA) to a Kubernetes Service Account (KSA) with roles/iam.workloadIdentityUser.
  3. Annotate the KSA with iam.gke.io/gcp-service-account=<gsa>@<project>.iam.gserviceaccount.com.
  4. Pods using that KSA get credentials via the metadata server — the GKE metadata server intercepts calls and exchanges the KSA token for a GSA token.

Key differences

Credential delivery: IRSA injects env vars; Workload Identity uses the metadata server. The metadata server approach means the GCP SDK needs no annotation or configuration — it just calls the metadata endpoint as normal. IRSA requires the env vars to be present, which a broken injection (e.g., missing admission webhook) can silently break.

Scope: An IRSA role trust policy is a single binding (namespace + SA name). A Workload Identity binding is an IAM policy on the GSA — you can grant multiple KSAs access to one GSA, or one KSA to multiple GSAs.

Debugging: IRSA failures show up as ExpiredTokenException or AccessDenied from the AWS SDK. Workload Identity failures often surface as 403s from the metadata server with a cryptic message. gcloud auth print-access-token from inside the pod is the fastest diagnostic.

Which is simpler

Honestly, about the same once you've done it a few times. Workload Identity has slightly less boilerplate — no explicit OIDC endpoint configuration, no trust policy JSON. IRSA is more explicit about what's happening, which makes it easier to reason about when something goes wrong.