Skip to content

EKS Pod Identity

EKS logo

Applications running in pods can use an AWS SDK or the AWS CLI to make API requests to AWS services using IAM permissions. Until recently, IRSA (IAM Roles for Service Accounts) using OpenID Connect was the standard authentication mechanism for pods.

EKS Pod Identity was introduced to simplify this process. It enables mapping a Kubernetes ServiceAccount directly to an AWS IAM role, simplifying configuration and enabling IAM role reuse across clusters.

Configuring Pod Identity

  1. Install the EKS Pod Identity agent add-on
  2. Create an IAM role with a Pod Identity trust policy and assign necessary permissions
  3. Create a Pod Identity association on the EKS cluster
  4. Configure the application to use the configured ServiceAccount

Scenario

Your pod must be able to list and retrieve objects from an S3 bucket. The Pod Identity agent is already installed on the EKS cluster. The application runs in the example namespace using ServiceAccount exampleserviceaccount.

Create an IAM role

Create an IAM role with the Pod Identity trust policy below. Attach the necessary S3 permissions and name the role pod-id-example-role.

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

Associate the ServiceAccount with the role

Navigate to AWS Console → EKS cluster → Access tab → Create Pod Identity association. Specify the role, namespace, and ServiceAccount name.

pod identity association

Deploy the application

Create the ServiceAccount in the example namespace and configure the app to use it. The pod below has the AWS CLI pre-installed for testing.

cat >example.yaml <<EOF
apiVersion: v1
kind: Namespace
metadata:
  name: example
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: exampleserviceaccount
  namespace: example
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: dvawscli
  name: dvawscli
  namespace: example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dvawscli
  template:
    metadata:
      labels:
        app: dvawscli
    spec:
      serviceAccountName: exampleserviceaccount
      containers:
      - image: dennysv/dvawscli
        name: dvawscli
        resources: {}
EOF

Apply and test:

kubectl apply -f example.yaml
# Exec into the pod and verify S3 access
kubectl exec -it deployment/dvawscli -n example -- bash
aws s3 ls s3://eks-automation/

Pod Identity vs IRSA comparison

Pod Identity and IRSA are both methods for granting pods access to AWS resources on EKS. Pod Identity is more flexible — it works across clusters, requires no ServiceAccount annotations, and enables IAM role reuse. It behaves similarly to an EC2 instance profile.

Pod Identity IRSA
No external authentication provider needed Requires an OIDC provider to be configured
ServiceAccount name maps to the role Requires a ServiceAccount annotation with the IAM role ARN
Works across clusters Bound to a single OIDC provider
IAM role can be reused across clusters IAM role trust policy is tied to a specific OIDC configuration

Terraform example

Creates an IAM role with Pod Identity trust policy, attaches S3 read-only access, and associates it with a namespace and ServiceAccount.

data "aws_iam_policy_document" "assume_role" {
  statement {
    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["pods.eks.amazonaws.com"]
    }

    actions = [
      "sts:AssumeRole",
      "sts:TagSession"
    ]
  }
}

resource "aws_iam_role" "example" {
  name               = "eks-pod-identity-example"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

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

resource "aws_eks_pod_identity_association" "example" {
  cluster_name    = aws_eks_cluster.example.name
  namespace       = "example"
  service_account = "exampleserviceaccount"
  role_arn        = aws_iam_role.example.arn
}