DEV Community

Cover image for EKS Security Deep Dive: IRSA vs. EKS Pod Identity
Hima
Hima

Posted on

EKS Security Deep Dive: IRSA vs. EKS Pod Identity

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

Enter fullscreen mode Exit fullscreen mode

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

  1. Pod Request: A pod deploys utilizing a ServiceAccount annotated with eks.amazonaws.com/role-arn.
  2. Mutation: The EKS pod-identity-webhook intercepts creation, mounts a projected JWT token file, and injects AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE environment variables.
  3. STS Call: The application AWS SDK reads this token and executes sts:AssumeRoleWithWebIdentity.
  4. 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

Enter fullscreen mode Exit fullscreen mode

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"
      }
    }
  }]
}

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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

  1. The Webhook: The EKS control plane injects environment metadata directly into authorized pods, including AWS_CONTAINER_CREDENTIALS_FULL_URI pointing to a local link-local address (http://169.254.170.23/v1/credentials).
  2. 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).
  3. 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

Enter fullscreen mode Exit fullscreen mode

IAM Trust Policy:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "pods.eks.amazonaws.com" },
    "Action": ["sts:AssumeRole", "sts:TagSession"]
  }]
}

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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}"
  }
}

Enter fullscreen mode Exit fullscreen mode

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

IRSA

Pod Identity Flow

Pod Identity

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 .

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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.

  1. Install Addon: Add eks-pod-identity-agent to the target cluster.
  2. Update IAM Trust: Append the pods.eks.amazonaws.com service principal statement directly to your existing IAM role's trust document alongside the old OIDC block.
  3. Create Association: Create the EKS Pod Identity Association pointing to your target ServiceAccount.
  4. Cycle Workloads: Run a kubectl rollout restart on your deployments. Verify runtime credentials map cleanly using aws sts get-caller-identity.
  5. Clean Up: Strip old eks.amazonaws.com/role-arn annotations 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)