EKS Pod Identity Guide

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:

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
}