Managing Amazon EKS at Fleet Scale · Part 10 of 18
EKS Identity at Fleet Scale: Pod Identity vs IRSA, and Access Entries vs aws-auth
Every cluster in the fleet inherits two identity decisions the day it is created — how a pod reaches AWS, and how a human or controller reaches the cluster. Parts 3, 5, and 7 kept saying “wire identity in at creation” and deferred the detail here. This is the detail: pick EKS Pod Identity over IRSA per workload, and move a fleet off the deprecated aws-auth ConfigMap safely.
TL;DR
- Pod-to-AWS: default to EKS Pod Identity. For new workloads on EKS in the AWS cloud it beats IRSA — no per-cluster OIDC provider, one IAM role reusable across N clusters, session tags, and IAM admin decoupled from cluster admin. That reuse is the fleet-scale win.
- Keep IRSA only where you must: portability (EKS Anywhere, self-managed, ROSA), Fargate, Windows, and any non-EC2 pod. EKS Pod Identity is Linux-on-EC2 only. The two coexist; the Pod Identity webhook wins when both are set on the same pod.
- Principal-to-cluster: use access entries, not the aws-auth ConfigMap. Access entries are the managed replacement; the ConfigMap is deprecated. Auth modes are
CONFIG_MAP,API_AND_CONFIG_MAP(the console default), andAPI— and the transitions between them are one-way. - The fleet payoff is the same shape both times: one API-driven object you can template and reconcile through GitOps, instead of a per-cluster artifact you hand-edit and hope stays consistent.
- Product behaviour here is current as of 2026-06-30; re-verify EKS Pod Identity requirements and the access-entry auth modes against AWS docs at publish time.
Do this on a fleet
- Make EKS Pod Identity the default for new EC2-based workloads; reuse one role across clusters.
- Enable the Pod Identity Agent add-on at cluster creation so the choice is available from day one.
- Create clusters in
APIauth mode and grant access through access entries. - Manage roles, associations, and entries as code, reconciled by GitOps.
Don’t do this
- Don’t stand up a new OIDC provider per cluster when Pod Identity would do.
- Don’t reach for IRSA out of habit — reach for it only for Fargate, Windows, non-EC2, or portability.
- Don’t hand-edit
aws-authacross the fleet; one bad edit locks everyone out. - Don’t treat the auth-mode switch as reversible — the transitions are one-way.
The two questions every cluster answers at creation — and why they’re separate
Identity on EKS is really two questions that people often blur into one. Keep them apart and the rest of this gets simple.
The first is how a pod reaches AWS. Your workload needs to call S3, DynamoDB, SQS — that is an IAM problem, and the answer is either EKS Pod Identity or IRSA (IAM Roles for Service Accounts). The second is how a principal reaches the cluster. A platform engineer, a CI runner, or the GitOps controller needs to authenticate to the Kubernetes API and be mapped to RBAC — that is an EKS-access problem, and the answer is either access entries or the old aws-auth ConfigMap.
They are separate axes with separate defaults, and this article takes them in that order: pod-to-AWS first (Pod Identity vs IRSA), then principal-to-cluster (access entries vs aws-auth).
Both get decided at cluster-creation time, which is exactly why earlier parts kept deferring the detail. Provisioning (Part 3), the golden-path platform (Part 5), and the greenfield reference build (Part 7) all said the same thing: wire EKS Pod Identity and access entries in at creation. The reason to decide early is structural — the OIDC provider, the Pod Identity Agent add-on, and the auth mode are all things you want present before the first workload lands, and one of them (the auth mode) is genuinely hard to change later.
How a pod should reach AWS — EKS Pod Identity as the default
For pods that need AWS permissions, the default on EKS-in-the-cloud is EKS Pod Identity.1 It launched at re:Invent 2023, needs Kubernetes 1.24 or newer plus the EKS Pod Identity Agent add-on, and it replaced IRSA as the recommended path for a reason that only gets louder as the cluster count climbs.
The mechanics are deliberately boring. You associate an IAM role with a Kubernetes service account through an EKS API call — a Pod Identity association — and the agent running on each node hands the pod temporary credentials for that role. No annotations that have to match a provider URL, no trust policy that names a specific cluster’s OIDC issuer.
Four properties make it the fleet default, and each maps to a real operational pain it removes:
- No per-cluster OIDC provider. IRSA needs an IAM OIDC identity provider registered for each cluster’s issuer URL. Pod Identity needs none — the association is an EKS-native call, so there is one less create-time artifact per cluster.
- Reusable roles across clusters. Because the role’s trust policy points at the EKS Pod Identity service rather than a specific cluster’s issuer, the same role can be associated in cluster 3 and cluster 300. This is the fleet-scale win, and the next section is entirely about why.
- Session tags. Associations carry tags into the assumed-role session, so you can write IAM policies that scope by cluster, namespace, or service account without minting a separate role per combination.
- Decoupled admin. An IAM administrator manages the role and its policies; a cluster administrator manages the association. Neither has to hold the other’s permissions, which is the separation a platform team wants at scale.
Why one role beats one OIDC provider per cluster — the fleet math
The single-cluster difference between Pod Identity and IRSA is small enough to shrug at. The fleet difference is the whole argument. It comes down to what each model forces you to create per cluster (Figure 1).
Read the two panels as “what does cluster number 300 cost me to onboard?” Under Pod Identity, it costs one association against a role that already exists. Under IRSA, it costs a new OIDC identity provider plus at least one role whose trust policy names that cluster’s issuer — and every role you want that workload to use has to trust that specific issuer, so roles multiply with clusters, not just with workloads.
That is the difference between a per-cluster artifact you template once and reuse, and a per-cluster artifact you regenerate every time. It is the same lesson the GitOps layer taught in Part 4: at fleet scale, anything that scales linearly with cluster count is the thing that eventually breaks. Pod Identity moves role management off that curve.
When IRSA is still the right answer — and when it’s the only one
Pod Identity being the default doesn’t make IRSA legacy. IRSA is still required in specific places, and the reason is a hard platform limit: the EKS Pod Identity Agent runs only on Linux EC2 nodes. Anywhere that constraint doesn’t hold, IRSA is not a preference — it’s the only option (Figure 2).2
The portability case is the one worth internalizing. IRSA is a Kubernetes-native mechanism — a projected service-account token exchanged against an OIDC provider — so it works the same on EKS, EKS Anywhere, a self-managed cluster, or ROSA. EKS Pod Identity is an EKS control-plane feature, so it does not travel. If a workload has to run identically on and off AWS, IRSA is what keeps its identity story portable.
Fargate is the other hard stop that surprises people: because Fargate pods aren’t on EC2 nodes you manage, the Pod Identity Agent isn’t there, so Fargate stays on IRSA. Part 7 already flagged this as one of Fargate’s real constraints. Same story for Windows pods and anything else off Linux EC2.
And the two coexist cleanly. You can run Pod Identity for the bulk of a fleet and IRSA for the Fargate or Windows corners, even on the same cluster. If a single pod somehow has both configured, the Pod Identity webhook takes precedence — a tie-breaker worth knowing during a migration, which is next.
Moving a workload from IRSA to Pod Identity — without a flag day
Most fleets that have been around a while are on IRSA already, so the practical question isn’t “which is better” but “how do I move without breaking anything.” The good news is that the coexistence property makes this a per-workload cutover, not a big-bang migration.
The shape of the move, per workload:
- Prepare the role’s trust. The IAM role a workload uses under IRSA trusts a specific cluster’s OIDC issuer. For Pod Identity, the role instead needs to trust the EKS Pod Identity service principal. You can add that trust to the existing role so it works both ways during the cutover, rather than minting a new role.
- Create the association. Add a Pod Identity association mapping the role to the workload’s service account. Because the webhook takes precedence, a pod that has both the old IRSA annotation and a new association will start using the association on its next restart.
- Roll the pods. Credentials are injected at pod start, so the switch lands on the next rollout — no live pod changes identity underneath itself.
- Remove the IRSA remnants. Once every pod for that workload has cycled and you’ve confirmed it’s using the association, drop the service-account OIDC annotation and, when nothing else needs it, retire the per-cluster OIDC provider.
Two things to watch. First, don’t delete the OIDC provider until every workload that depended on it has moved — it’s a shared per-cluster artifact, and pulling it early breaks any straggler still on IRSA. Second, session tags mean your IAM policies can get stricter after the move; if a policy was written loosely for IRSA, tighten it to scope by the cluster or namespace tags the association now carries, rather than leaving it broad.
Who gets into the cluster — access entries over the aws-auth ConfigMap
Now the second axis: how a human, a CI runner, or the GitOps controller authenticates to the cluster itself. For years the answer was the aws-auth ConfigMap — a single in-cluster YAML object that mapped IAM principals to Kubernetes groups. It is now deprecated, and the managed replacement is access entries.3
The ConfigMap was the fleet’s quiet liability. It lived inside each cluster, so granting access meant editing YAML in the cluster; it had no schema validation, so a typo in a role ARN silently failed; and a bad edit could lock every administrator out of the cluster at once, with no easy way back in. Multiply that by hundreds of clusters and “edit the ConfigMap” is a fleet-wide footgun.
Access entries move that mapping into the EKS API. Each entry associates an IAM principal with Kubernetes access — either through EKS access policies (managed permission sets like cluster-admin or view) or by mapping to your own RBAC groups. Because it’s an API object, it’s validated, auditable, and templatable like any other AWS resource, and it can be created before the cluster is even reachable. The auth mode you choose controls which mechanism the cluster honours (Figure 3).
API mode and treat API_AND_CONFIG_MAP as a migration waypoint, not a resting place.Three things about that flow decide how you run it on a fleet. The mode you inherit by default from the console is API_AND_CONFIG_MAP, which honours both mechanisms — useful while migrating, but not where you want to stay. When both apply to the same principal, the access entry wins, so you can safely add entries alongside an existing ConfigMap and let them take over. And managed node groups and Fargate profiles get their access entries created automatically, so you are not hand-authorizing the cluster’s own node identities.
The catch that governs planning: the transitions are one-way. You can move CONFIG_MAP → API_AND_CONFIG_MAP → API, but never back. That is why the auth mode belongs in the create-time decision the earlier parts kept pointing here for — stand new fleet clusters up in API mode directly, and use API_AND_CONFIG_MAP only as a transient state for clusters you are migrating.
Why this is what lets RBAC scale to hundreds of clusters
The reason access entries matter for a fleet isn’t the single-cluster ergonomics — it’s that they turn cluster access into a fleet-wide API surface instead of hundreds of hand-edited YAML files.
Think about the old workflow for “the platform team gets read-only on every prod cluster.” With aws-auth, that’s an edit to a ConfigMap inside each cluster — a change you can’t easily template, can’t validate before it lands, and can’t roll back if a typo locks people out. Three hundred clusters is three hundred careful edits, and the blast radius of getting one wrong is a locked cluster.
With access entries, the same intent is an API object you declare once and apply everywhere. The pattern is the one this series keeps landing on: define the desired access model as code, and let the pipeline reconcile it across the fleet. A consistent set of entries — the platform team’s role, the CI principal, the GitOps controller’s identity, each mapped to a known access policy or RBAC group — becomes a template the cluster generator applies to every matching cluster, exactly like the golden-path stack in Part 4. Onboarding cluster 301 grants the standard access set automatically, because it inherits the same declared entries every other cluster did.
That is the throughline across both identity axes. EKS Pod Identity makes pod-to-AWS identity a reusable role plus a templatable association; access entries make principal-to-cluster access a templatable API object.
In both cases the fleet win is the same move — replace a per-cluster artifact you touch by hand with an API object you declare once and reconcile.
Secrets and compliance, the next layer of this story, build straight on top of both.
What to actually do — the thresholds
Turn all of this into standing rules for the fleet:
- New EC2-based workloads on EKS-in-the-cloud: EKS Pod Identity, always. Enable the Pod Identity Agent add-on at cluster creation so the option exists from day one, and reuse one role across clusters rather than minting per-cluster roles.
- IRSA only where the agent can’t run: Fargate, Windows, non-EC2 pods, or any workload that must stay portable to EKS Anywhere, self-managed, or ROSA. Let the two coexist; don’t force a rewrite of the corners that genuinely need IRSA.
- Migrate existing IRSA workloads per workload, not per fleet. Add the Pod Identity trust to the role, create the association, roll the pods, then retire the OIDC provider once nothing depends on it — all through the GitOps pipeline.
- Create new fleet clusters in
APIauth mode and grant access exclusively through access entries. ReserveAPI_AND_CONFIG_MAPfor clusters mid-migration, and remember the switch is one-way. - Never hand-edit
aws-authon a fleet. If you still have clusters on the ConfigMap, treat moving them to access entries as the same reviewed, reconciled change as any other fleet-wide rollout.
Get both axes right and identity stops being something you configure cluster by cluster and becomes something the fleet inherits by construction — which is exactly what Parts 3, 5, and 7 meant by “baked in at creation.” The dates and version requirements here are current as of 2026-06-30; re-verify the EKS Pod Identity prerequisites and the access-entry auth modes against the AWS documentation on the day you ship.
Sources
- AWS — EKS Pod Identity: the recommended default over IRSA for EKS-in-the-cloud (needs Kubernetes 1.24+ and the Pod Identity Agent add-on) — no per-cluster OIDC provider, reusable IAM roles across clusters, session tags, and decoupled IAM/cluster administration. docs.aws.amazon.com/…/pod-identities.html
- AWS — IAM Roles for Service Accounts (IRSA): still required for portability (EKS Anywhere, self-managed, ROSA), Fargate, Windows, and non-EC2 pods; coexists with EKS Pod Identity, which takes precedence when both are configured on a pod. docs.aws.amazon.com/…/iam-roles-for-service-accounts.html
- AWS — EKS access entries: the managed replacement for the deprecated
aws-authConfigMap; auth modesCONFIG_MAP/API_AND_CONFIG_MAP(console default) /API, transitions one-way, access entries take precedence over the ConfigMap for the same principal, and managed node groups / Fargate get entries automatically. docs.aws.amazon.com/…/access-entries.html