Skip to content

EKS Pod Identity Guide

EKS logo

EKS Pod Identity is AWS's recommended mechanism for granting Kubernetes pods secure, temporary access to AWS services (e.g. Amazon S3, DynamoDB, Secrets Manager).

Prior to Pod Identity, IRSA (IAM Roles for Service Accounts) required configuring an OIDC identity provider per cluster, managing complex trust policies bound to specific OIDC URLs, and annotating ServiceAccounts with IAM role ARNs. EKS Pod Identity simplifies this by mapping a Kubernetes ServiceAccount directly to an IAM role.


How EKS Pod Identity Works

sequenceDiagram
    participant App as Application Pod
    participant Agent as EKS Pod Identity Agent (DaemonSet)
    participant EKSAuth as EKS Auth Backend
    participant STS as AWS STS

    App->>Agent: Request AWS Credentials (via SDK)
    Agent->>EKSAuth: Authenticate Pod (ServiceAccount token)
    EKSAuth->>STS: AssumeRole (Service: pods.eks.amazonaws.com)
    STS-->>App: Return temporary credentials (AWS_CONTAINER_CREDENTIALS_FULL_URI)

The EKS Pod Identity Agent DaemonSet runs on each worker node, intercepting metadata requests from AWS SDKs and exchanging the pod's ServiceAccount token for short-lived AWS IAM credentials.


Pod Identity vs. IRSA Comparison

Feature EKS Pod Identity IAM Roles for Service Accounts (IRSA)
Setup Complexity Zero OIDC provider setup required Requires an OIDC identity provider per cluster
Trust Policy Principal Standard pods.eks.amazonaws.com Complex Federated OIDC ARN + Condition block
Multi-Cluster Role Reuse Yes — same role can be mapped across 100+ clusters No — trust policy is tied to a single cluster's OIDC URL
ServiceAccount Configuration Clean (no annotations needed) Requires eks.amazonaws.com/role-arn annotation
Session Tagging Support Native (supports ABAC via cluster/namespace tags) Limited
AWS SDK Compatibility Supported in all modern AWS SDKs (Java, Go, Python, JS, .NET) Supported in legacy & modern SDKs

Step-by-Step Configuration

Step 1. Install the EKS Pod Identity Agent Add-on

aws eks create-addon \
  --cluster-name $CLUSTERNAME \
  --addon-name eks-pod-identity-agent \
  --profile $PROFILE

Step 2. Create the IAM Role with Pod Identity Trust Policy

The trust policy must specify pods.eks.amazonaws.com as the principal and allow sts:AssumeRole and sts:TagSession:

iam-trust-policy.json

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

Attach your application permissions (for example, AmazonS3ReadOnlyAccess) to this role.


Step 3. Create the Pod Identity Association

Associate the IAM role with the target namespace and ServiceAccount:

aws eks create-pod-identity-association \
  --cluster-name $CLUSTERNAME \
  --role-arn arn:aws:iam::<ACCOUNT-ID>:role/pod-id-s3-demo-role \
  --namespace demo \
  --service-account demo-sa \
  --profile $PROFILE

Alternatively, configure the association in the AWS Console:

Pod Identity Association


Step 4. Deploy and Verify the Workload

deploy-demo.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: demo
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: demo-sa
  namespace: demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: s3-test-app
  namespace: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: s3-test-app
  template:
    metadata:
      labels:
        app: s3-test-app
    spec:
      serviceAccountName: demo-sa
      containers:
        - name: aws-cli
          image: amazon/aws-cli:latest
          command: ["sleep", "3600"]

# 1. Apply deployment
kubectl apply -f deploy-demo.yaml

# 2. Exec into the container and test S3 access
kubectl exec -it deployment/s3-test-app -n demo -- aws s3 ls

Complete Terraform Example

pod-identity.tf

# 1. Pod Identity Agent Add-on
resource "aws_eks_addon" "pod_identity" {
  cluster_name                = module.eks.cluster_name
  addon_name                  = "eks-pod-identity-agent"
  addon_version               = "v1.3.4-eksbuild.1"
  resolve_conflicts_on_create = "OVERWRITE"
  resolve_conflicts_on_update = "OVERWRITE"
}

# 2. IAM Role with Pod Identity Trust Policy
data "aws_iam_policy_document" "pod_identity_trust" {
  statement {
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["pods.eks.amazonaws.com"]
    }
    actions = [
      "sts:AssumeRole",
      "sts:TagSession"
    ]
  }
}

resource "aws_iam_role" "app_role" {
  name               = "eks-app-s3-access-${module.eks.cluster_name}"
  assume_role_policy = data.aws_iam_policy_document.pod_identity_trust.json
}

resource "aws_iam_role_policy_attachment" "app_s3_readonly" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
  role       = aws_iam_role.app_role.name
}

# 3. Pod Identity Association
resource "aws_eks_pod_identity_association" "app_association" {
  cluster_name    = module.eks.cluster_name
  namespace       = "demo"
  service_account = "demo-sa"
  role_arn        = aws_iam_role.app_role.arn
}