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), and API — 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 API auth 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-auth across 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:

Terminology. It is “EKS Pod Identity” — a specific AWS feature — not a generic “pod identity.” The requirements (K8s 1.24+, the Pod Identity Agent add-on) are current as of 2026-06-30; confirm them against the AWS docs before you publish or roll this out.

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).

Figure 1 · Pod Identity vs IRSA at fleet scale One reusable role vs one OIDC provider per cluster IAM role OIDC provider (per cluster) EKS cluster EKS POD IDENTITY — 1 ROLE, N CLUSTERS One IAM role reused fleet-wide prod-eu-1 prod-us-1 dev-1 … +N more one association per cluster, zero OIDC providers IRSA — 1 OIDC PROVIDER + ROLE PER CLUSTER prod-eu-1 OIDC provider IAM role prod-us-1 OIDC provider IAM role dev-1 … +N more OIDC provider IAM role the provider-plus-role pair repeats for every cluster
The fleet-scale point: under EKS Pod Identity the per-cluster artifact is a single association against one reused role; under IRSA each new cluster brings its own OIDC provider and role, so the thing you manage grows with the fleet.

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

Figure 2 · The pod-to-AWS identity decision Which identity for which pod DEFAULT TO EKS POD IDENTITY New workloads on EKS in the AWS cloud Linux pods on EC2 (managed nodes / Karpenter) You want one role reused across the fleet No per-cluster OIDC provider to maintain Session tags scope IAM by cluster / namespace requires: K8s 1.24+ and the Pod Identity Agent add-on KEEP IRSA WHEN YOU NEED Portability: EKS Anywhere, self-managed, ROSA Fargate pods (Pod Identity is Linux-EC2 only) Windows pods Any non-EC2 pod the agent runs only on Linux EC2 nodes — outside that, IRSA is the only option THEY COEXIST Both can be set on the same pod — the Pod Identity webhook takes precedence when both apply
The rule: Pod Identity by default for Linux EC2 workloads; IRSA where the agent can’t run — Fargate, Windows, non-EC2, or a cluster you need to run outside AWS. When both are configured on a pod, Pod Identity wins.

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:

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.

Do it through the pipeline, not by hand. Associations and role trust policies are exactly the kind of per-cluster metadata the GitOps bridge from Part 4 is built to carry. Express the association in code, let the bridge write the role ARN into the cluster, and the migration becomes a reviewed pull request per workload instead of a console click per cluster.

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).

Figure 3 · Access-entry auth modes are a one-way trip CONFIG_MAP to API_AND_CONFIG_MAP to API — forward only CONFIG_MAP aws-auth ConfigMap only legacy — deprecated API_AND_CONFIG_MAP both honoured at once console default API access entries only the fleet target no going back — every transition is one-way Precedence: an access entry beats the ConfigMap for the same principal. Managed node groups and Fargate profiles get their access entries created automatically.
Decide the mode at creation: new clusters progress from ConfigMap-only toward access-entries-only, and the switch never reverses — so create fleet clusters in 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_MAPAPI_AND_CONFIG_MAPAPI, 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:

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

  1. 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
  2. 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
  3. AWS — EKS access entries: the managed replacement for the deprecated aws-auth ConfigMap; auth modes CONFIG_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