Amazon EKS Pod Identity: Credential Delivery, Trust, and Migration
Operate EKS Pod Identity with scoped IAM roles, SDK credential-chain checks, node agents, cross-account delegation, and a reversible migration plan.
Amazon EKS Pod Identity connects a Kubernetes service account to an AWS IAM role without placing long-lived AWS keys in a Pod or creating one IAM OIDC provider per cluster. The mechanism is deliberately split across systems: an association is stored in the EKS control plane, a node-local Pod Identity Agent brokers credentials, the EKS Auth API supplies temporary role credentials, and an AWS SDK in the container retrieves them through its container credential provider. Each boundary has its own prerequisites and failure modes.
It is not enough to create an association and assume the application will use it. The Pod must run on a supported node with the agent installed, its Kubernetes service account must match the association, the IAM role must trust the EKS Pod Identity service principal, the role policy must permit the intended API operations, and the SDK credential chain must actually reach the injected provider. This guide treats those conditions as an operational contract rather than a single setup command.
The credential path
An association maps one cluster, namespace, Kubernetes service account, and IAM role. EKS stores that mapping outside Kubernetes objects: there is no special service-account annotation that represents the association. When a Pod using the selected service account is created, EKS injects the container credential endpoint variables and a projected token intended for the EKS Pod Identity service. The Pod Identity Agent runs as a DaemonSet on each eligible node and uses the token to call the EKS Auth API. It returns short-lived credentials to an AWS SDK or CLI inside the container.
This architecture differs from IAM Roles for Service Accounts (IRSA). IRSA relies on the cluster’s OIDC issuer and AWS STS AssumeRoleWithWebIdentity; Pod Identity uses the EKS Auth API and a node agent. The difference changes trust-policy shape, network dependencies, operational ownership, supported environments, and how credentials are obtained. Neither option grants permissions merely because a service account exists. The IAM role’s permissions policy remains the authorization boundary for AWS actions.
An association is cluster-scoped in EKS but its role is in the same AWS account as that cluster. Cross-account access uses role chaining: first associate a role in the cluster account, then allow that role to assume a target role in the resource-owning account. This preserves the iam:PassRole relationship that EKS requires, while the target role defines the remote account’s actual permissions.
Define a least-privilege role
The role trust relationship identifies EKS Pod Identity as the service principal and permits session establishment and session tags. Session tags can support attribute-based access policies, but they should be treated as identity inputs and tested against the exact policies that consume them. Avoid broad Resource: "*" permissions simply because the role is attached to a Pod; the service account is a principal-selection mechanism, not a reason to weaken IAM scoping.
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowEKSWorkloadIdentity",
"Effect": "Allow",
"Principal": {"Service": "pods.eks.amazonaws.com"},
"Action": ["sts:AssumeRole", "sts:TagSession"]
}]
}
The trust policy above only permits the EKS Pod Identity service to assume the role. It does not grant access to S3, DynamoDB, Secrets Manager, or any other service. Attach a separate permissions policy with the narrowest resource ARNs and actions the workload needs. Where authorization depends on session tags, verify that the EKS-provided tags are present and that the policy’s condition keys match the documented tag names and values.
Create an association using a controlled deployment identity with iam:PassRole limited to approved workload roles. Review the cluster, namespace, service-account name, and role ARN together in the change record. Kubernetes administrators who can create Pods in the namespace can often select the associated service account, so namespace RBAC and admission policy form part of the effective identity boundary. A dedicated service account per workload reduces accidental privilege reuse.
Configure the workload explicitly
The association binds to a Kubernetes service account name. A deployment should name that account rather than silently inheriting the namespace’s default service account. This makes the credential boundary visible in review and avoids changing which identity an unrelated Pod receives when a default service account is repurposed.
apiVersion: v1
kind: ServiceAccount
metadata:
name: invoice-reader
namespace: billing
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: invoice-worker
namespace: billing
spec:
replicas: 2
selector:
matchLabels:
app: invoice-worker
template:
metadata:
labels:
app: invoice-worker
spec:
serviceAccountName: invoice-reader
containers:
- name: worker
image: example.invalid/billing/worker@sha256:REPLACE_WITH_APPROVED_DIGEST
command: ["/app/worker"]
The image reference is intentionally a placeholder, not a deployable registry address. Replace it with an approved immutable digest, and create the EKS association out of band through infrastructure as code or an explicitly reviewed AWS API operation. Do not add a fictitious eks.amazonaws.com/role-arn annotation for Pod Identity; that annotation is associated with other identity patterns, not the EKS Pod Identity association mechanism.
Verify the SDK actually selects the role
AWS SDKs use a credential provider chain. A static environment credential, shared credentials file, web-identity token, or another earlier provider can take precedence over the container credential endpoint. As a result, an association can be healthy while the application silently uses a different identity. Before removing legacy configuration, inspect the workload’s environment and mounted files for unintended credentials. Do not print secret values in logs or CI output.
Use an identity-only diagnostic from the same container image and service account, such as aws sts get-caller-identity, and compare the returned account and role session with the expected role. This proves which principal signed the request; it does not prove that the principal is authorized for every application operation. Follow it with a harmless read against the exact service and resource the application uses, and inspect CloudTrail when the result differs from expectations.
The AWS CLI and SDK must support the container credential provider behavior used by Pod Identity. Pin and update SDK dependencies intentionally, especially for controllers and third-party add-ons. If the identity test fails, check in order: the Pod’s service account, EKS association status and role ARN, agent DaemonSet health on the scheduled node, node connectivity to the EKS Auth API, the injected endpoint variables, SDK version, earlier credential providers, role trust, and role permission policy. A network policy or host firewall that blocks the agent path can produce symptoms that look like IAM denial.
Plan cross-account access without widening the first role
When a workload needs resources in another account, use a target role with a trust policy that accepts the cluster-account role, then grant only the desired actions to that target role. The application or SDK assumes the target role after it obtains the initial Pod Identity credentials. Treat the two roles as separate authorization steps: the first proves the workload’s cluster-account identity, and the second grants access to a resource account. Validate external ID or organization conditions if your account model requires them, and ensure CloudTrail records both assumptions.
Do not attach a target-account role directly to an EKS association if the association API requires the role to be in the cluster account. Do not solve a cross-account access problem by giving every workload a broad role in the cluster account. Role chaining makes the account boundary explicit and lets the resource owner review and revoke its own trust independently.
Migrate from IRSA or static credentials safely
Inventory the current identity source before changing it: service-account annotations, trust policies, secret volumes, environment variables, SDK configuration files, and any node role permissions. Create the Pod Identity role and association while the old source is still available. Because earlier providers in a chain may continue to win, first remove or disable only the legacy credential source for a canary deployment, then verify the caller identity and service-level operation.
Roll out by workload, not by cluster-wide replacement. Monitor authentication errors, AWS API AccessDenied responses, throttles, and application-level success metrics. Keep a tested rollback that restores the former identity configuration, but avoid leaving long-lived keys active after the migration is accepted. For IRSA migrations, preserve the old OIDC provider until no workload depends on it and the audit window is complete; removing it too early can break unrelated service accounts.
Operational checks and limits
Pod Identity depends on a node agent and EKS control-plane support, so verify compatibility for the node type and operating system before standardizing it. A successful IAM association does not prove the agent is scheduled, a Pod can reach the local credential endpoint, or an SDK supports the provider. Also account for service quotas and association lifecycle in infrastructure-as-code plans. Review changes that delete or recreate an association as credential changes, not cosmetic metadata edits.
Use CloudTrail for API-level evidence and Kubernetes events and Pod logs for scheduling and application symptoms. Record the expected role ARN, service account, AWS account, and test operation in a runbook. Alert on unexpected identity results and denied calls without logging tokens or full credential documents. Re-evaluate the role when a workload changes its AWS API usage; identity associations do not automatically adapt permissions to new application behavior.
EKS Pod Identity is strongest when identity selection is explicit, the IAM role is narrow, the agent and SDK path are observable, and migration is incremental. Treat each layer as independently testable, and keep cross-account delegation visible in both policy review and CloudTrail.
Related:
- Amazon EKS Access Entries: Authorization Design and aws-auth Migration
- Kubernetes ServiceAccount Token Projection: Audience, Rotation, and Trust Boundaries
Sources: