Introduction
If you're running apps on Amazon EKS, you've faced this challenge: your pods need to talk to AWS services (S3, DynamoDB, SQS), and you must provide credentials securely without baking long-lived access keys into a Kubernetes Secret.
For years, the standard was IRSA (IAM Roles for Service Accounts). It's secure, but setting it up can feel like assembling complex furniture with a vague manual. AWS introduced EKS Pod Identity as a simpler, native alternative.
Having managed both architectures and handled migrations between them, here is the breakdown of how they work under the hood, the gotchas, and how to choose.
The Anti-Pattern: Static Credentials
# ❌ Avoid this pattern
apiVersion: v1
kind: Secret
metadata:
name: aws-credentials
stringData:
AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Why this fails at scale:
- Long-lived credentials that never expire.
- High risk of source control leaks or log exposure.
- No granular audit trail or automatic rotation.
Both IRSA and Pod Identity solve this by yielding short-lived, auto-rotated, pod-scoped credentials.
1. IRSA: The OIDC Federation Approach
Introduced in 2019, IRSA bridges Kubernetes and AWS IAM using OpenID Connect (OIDC) federation. EKS exposes a public OIDC endpoint, AWS IAM trusts that endpoint, and your pods leverage JWTs to assume IAM roles.
The IRSA Authentication Flow
-
Pod Request: A pod deploys utilizing a
ServiceAccountannotated witheks.amazonaws.com/role-arn. -
Mutation: The EKS
pod-identity-webhookintercepts creation, mounts a projected JWT token file, and injectsAWS_ROLE_ARNandAWS_WEB_IDENTITY_TOKEN_FILEenvironment variables. -
STS Call: The application AWS SDK reads this token and executes
sts:AssumeRoleWithWebIdentity. -
Validation: AWS STS validates the signature using the cluster's public OIDC keys, confirms the audience (
sts.amazonaws.com), and validates the IAM trust policy before returning 1-hour temporary credentials.
IRSA Configuration Example
# Associate the OIDC provider with IAM (one-time task)
eksctl utils associate-iam-oidc-provider --cluster my-cluster --approve
IAM Trust Policy:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:my-namespace:my-sa",
"oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
}
}
}]
}
ServiceAccount Definition:
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa
namespace: my-namespace
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-app-role
Pros & Cons of IRSA
- Pros: Standardized on open specifications (OIDC); production-hardened; works across standard EC2, AWS Fargate, Windows nodes, and hybrid environments like EKS Anywhere.
- Cons: The trust policy explicitly tightly couples IAM to a single cluster OIDC URL. Cross-account architecture demands manual OIDC registrations in every target AWS account, hitting limits quickly. Cryptic error logs make debugging failure states a challenge.
2. EKS Pod Identity: The Agent-Based Approach
EKS Pod Identity bypasses OIDC federation completely. Instead, it relies on a local node agent combined with a centralized AWS-managed service to abstract identity management.
Mechanics Under the Hood
-
The Webhook: The EKS control plane injects environment metadata directly into authorized pods, including
AWS_CONTAINER_CREDENTIALS_FULL_URIpointing to a local link-local address (http://169.254.170.23/v1/credentials). -
The Node Agent: A Linux DaemonSet (
eks-pod-identity-agent) intercepts credential inquiries, validates the calling pod's signature locally, and calls the EKS Auth API (eks-auth:AssumeRoleForPodIdentity). - Caching: The backend infrastructure returns temporary credentials, cached at the node level to reduce total outbound calls to AWS STS.
Pod Identity Configuration Example
# Install the EKS Agent Addon
aws eks create-addon --cluster-name my-cluster --addon-name eks-pod-identity-agent
IAM Trust Policy:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "pods.eks.amazonaws.com" },
"Action": ["sts:AssumeRole", "sts:TagSession"]
}]
}
Note: This trust policy is completely universal. It requires zero edits across clusters, namespaces, or accounts.
Pod Identity Association Mapping:
aws eks create-pod-identity-association \
--cluster-name my-cluster \
--namespace my-namespace \
--service-account my-sa \
--role-arn arn:aws:iam::123456789012:role/my-app-role
The Superpower: Native Session Tags (ABAC)
Pod Identity automatically appends rich session tags to every token checkout request, including eks-cluster-name, kubernetes-namespace, and kubernetes-service-account.
This enables powerful Attribute-Based Access Control (ABAC). You can authorize a single IAM role across infinite environments by enforcing context dynamically:
"Condition": {
"StringEquals": {
"aws:ResourceTag/environment": "${aws:PrincipalTag/kubernetes-namespace}"
}
}
Current Limitations
- No Fargate Support: Fargate does not run standard node DaemonSets, forcing workloads back to traditional IRSA patterns.
- No Windows or Hybrid Nodes: The local agent requires Linux primitives and does not support Windows Server or bare-metal EKS Anywhere topologies.
- Requirements: Requires EKS clusters on version 1.24+ alongside updated runtime AWS SDK dependencies.
Cross-Account Access: A Clear Winner
Cross-account token distribution highlights the major configuration advantages of Pod Identity over IRSA.
IRSA Flow
Pod Identity Flow
Pod Identity coordinates this via clean IAM role chaining. The configuration targets a primary local role which assumes the remote target role using a built-in sts:ExternalId structurally derived from cluster values (region/account-id/cluster-name/namespace/service-account), safely solving the Confused Deputy problem with zero manual OIDC overhead.
Head-to-Head Comparison
| Capability | IRSA | EKS Pod Identity |
|---|---|---|
| Setup Overhead | High (OIDC per cluster + complex trust JSON) | Low (Single global service trust + EKS mapping) |
| Configuration Engine | Kubernetes Annotations + IAM | EKS API Associations + IAM |
| Token Delivery | File-mounted projected JWT volume | Local link-local network agent proxy |
| Cross-Account Mechanics | Manual target account OIDC mirrors | Native IAM Role Chaining |
| Session Tracking / ABAC | Unavailable | Native metadata context tags injected |
| Fargate & Windows | Fully Supported | Unsupported |
| Min EKS Version | 1.13+ | 1.24+ |
Practical Troubleshooting Commands
Debugging IRSA Issues
# Verify the annotation matches exactly
kubectl get sa my-sa -n my-namespace -o jsonpath='{.metadata.annotations}'
# Inspect the injected web identity filesystem token mount
kubectl exec my-pod -n my-namespace -- ls -l /var/run/secrets/eks.amazonaws.com/serviceaccount/
# Decode token metadata to audit system claims
kubectl exec my-pod -n my-namespace -- cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token | cut -d. -f2 | base64 -d 2>/dev/null | jq .
Debugging Pod Identity Issues
# Confirm the DaemonSet pods are running healthy
kubectl get pods -n kube-system -l app.kubernetes.io/name=eks-pod-identity-agent
# Audit your current cluster associations via the CLI
aws eks list-pod-identity-associations --cluster-name my-cluster
# Check the system agent application logs for validation failures
kubectl logs -n kube-system -l app.kubernetes.io/name=eks-pod-identity-agent --tail=30
Migration Blueprint
Pod Identity takes explicit execution precedence over IRSA. If both configurations exist simultaneously on a single ServiceAccount, the EKS webhook uses Pod Identity variables, allowing zero-downtime, rolling structural migrations.
-
Install Addon: Add
eks-pod-identity-agentto the target cluster. -
Update IAM Trust: Append the
pods.eks.amazonaws.comservice principal statement directly to your existing IAM role's trust document alongside the old OIDC block. - Create Association: Create the EKS Pod Identity Association pointing to your target ServiceAccount.
-
Cycle Workloads: Run a
kubectl rollout restarton your deployments. Verify runtime credentials map cleanly usingaws sts get-caller-identity. -
Clean Up: Strip old
eks.amazonaws.com/role-arnannotations from Kubernetes objects and clean up legacy OIDC providers.
The Verdict
- Choose EKS Pod Identity if: You are spinning up new standard Linux EC2 clusters, managing complex multi-cluster topologies, or operating heavy cross-account service paths.
- Stick with IRSA if: Your engineering footprint depends strongly on AWS Fargate serverless profiles, Windows nodes, or hybrid cluster topologies like EKS Anywhere.


Top comments (0)