Managing Amazon EKS at Fleet Scale · Part 5 of 18

Golden Paths for an EKS Fleet: The Self-Service Platform Layer

Parts 1–4 built the fleet: a reference architecture, a cluster-count decision, IaC provisioning, and the GitOps layer that keeps every cluster identical. This is where that machinery becomes a product a developer can consume — a paved road where the compliant way to get a cluster, a namespace, or an app is also the fastest way, with no ticket in the middle.

TL;DR

  • A fleet platform only pays off when a team can get a compliant cluster or tenant without filing a ticket. Build the golden path as a paved road, not a cage: the easy path is the compliant one.
  • Ship a single golden-path template — Karpenter compute, EKS Pod Identity, access entries, baseline policy, observability agents, and standard add-ons, pre-wired — and deliver it through the GitOps layer from Part 4 with Argo CD ApplicationSets.
  • The real add-on decision: EKS managed add-ons by default (AWS owns lifecycle, version, and compatibility, and they surface in Cluster Insights), self-managed via Helm only when you need a version or config AWS doesn’t expose.
  • Make self-service a pull request, not a portal you have to build: a developer opens a PR, the template renders, GitOps syncs, and a compliant tenant appears — with a policy gate that rejects non-compliant config before it lands.
  • Guardrails should make the wrong thing impossible, not merely discouraged — and the golden path needs a documented, reviewed exit for the rare team that genuinely has to go off-road.
  • Add-on versions and Cluster Insights behavior are current as of 2026-06-30; re-verify at publish.

Design it this way

  • One golden-path template carrying compute, identity, policy, observability, and add-ons.
  • Fan it out with an ApplicationSet generator, so a new tenant inherits it on registration.
  • Managed add-ons by default; self-managed only for a version or build AWS doesn’t expose.
  • A policy gate in the pipeline that rejects non-compliant config before it syncs.

Don’t do this

  • Don’t make the compliant cluster the one that needs a ticket and a two-week wait.
  • Don’t hand-assemble each tenant — drift starts on day one.
  • Don’t self-manage add-ons you have no reason to own; you inherit every upgrade.
  • Don’t let “off the golden path” be an undocumented, unreviewed free-for-all.

Why the platform only pays off when the compliant path needs no ticket

Here is the verdict up front: everything Parts 1–4 built — the reference architecture, the many-vs-few decision, IaC provisioning, and the GitOps layer — is plumbing until a developer can consume it without asking you. The platform earns its keep the day a team gets a compliant cluster, namespace, or app on their own.

The trap is subtle. Most platforms make the compliant path the slow one: fill in a request, wait for a review, wait for a human to wire up identity and policy and observability by hand. So teams route around it. They spin up their own cluster, skip the baseline, and now you have a fleet where every cluster is a little different — which is the exact problem the fleet was supposed to solve.

A golden path fixes the incentive. It is the well-lit, fully-paved default route to production: the fastest way to get a cluster is also the way that comes pre-wired with everything security and platform require. Compliance stops being a gate you pass and becomes a property you inherit.

The word that matters is paved road, not cage. A cage says “you may only do this.” A paved road says “this is so easy and complete that you’ll want to.” The road is optional in principle; it wins because taking it is less work than not. When the golden path is genuinely the least-effort option, standardization happens by choice, and that is the only kind that lasts.

This is the first article of the series’ second wave. It turns the spine into a product; Part 6 hardens it with policy-as-code, and Part 7 uses it as the default for a greenfield build.

What a new tenant gets for free — the golden-path template

The golden path is not a document. It is a template — a concrete bundle that a new cluster or tenant comes pre-wired with, delivered automatically. Think of it as the house default from Part 1, packaged so a team never assembles it by hand.

Five things ride in every template, and they map to the decisions the rest of this series makes in depth:

The delivery mechanism is the GitOps layer from Part 4. AWS’s current guidance is a stable core Terraform module for the cluster itself, with EKS Blueprints patterns bootstrapping the add-ons on top — and explicitly not using Blueprints to provision the core cluster in production.1 The template is the shape of that add-on layer, and Argo CD ApplicationSets are what stamp it onto each cluster (Figure 1).

Figure 1 · The golden-path template One template, fanned out to every new tenant golden-path template ApplicationSet generator new tenant cluster GOLDEN-PATH TEMPLATE Compute · Karpenter NodePool / EC2NodeClass Identity · Pod Identity plus access entries Policy · baseline audit then enforce Observability · agents metrics + logs, day one Add-ons · standard set core networking + DNS ApplicationSet cluster generator renders per tenant NEW TENANTS (N) team-a tenant full stack, pre-wired team-b tenant identical baseline team-c tenant same policy + add-ons + N more, byte-for-byte the same reads generate + sync
The template is the product: one bundle of compute, identity, policy, observability, and add-ons, fanned out by an ApplicationSet generator so every tenant is pre-wired identically — the compliant baseline arrives with the cluster, not after a ticket.

How the template reaches every cluster — ApplicationSet generators

A template is only a product if it deploys itself. The delivery workhorse is the Argo CD ApplicationSet, the same construct Part 4 leaned on for fleet rollout, now carrying the golden path instead of a single app.

Instead of hand-writing one Argo Application per component per cluster — the N×M problem that sinks naive setups — you write one ApplicationSet whose cluster generator enumerates the clusters Argo knows about, filters them by label, and stamps out the right set of Applications for each match.2 “Every tenant tagged tier=standard gets the golden-path stack” becomes a few lines of YAML.

The join that makes this automatic is the GitOps bridge from Part 3. IaC writes each new cluster’s metadata — its labels, endpoint, and the IAM role ARNs its add-ons should assume — into the Argo CD cluster secret.1 Registering the cluster is what enrolls it: on the next reconcile, the generator sees a new match and deploys the entire template. Cluster number 141 gets the same baseline as cluster number 1, with no human wiring per cluster.

That is what turns “golden path” from a wiki page into an operational fact. The path is not a checklist someone follows; it is what the generator does by default. Drift is designed out because the same manifests render onto every matching cluster, and self-heal reverts anyone who edits a live resource by hand back to what Git says.

Who should own each add-on — let AWS run it, or run it yourself

Every add-on in the template arrives one of two ways, and choosing between them is the most consequential decision in this article. An EKS managed add-on is one AWS installs and operates: AWS owns its lifecycle, its version compatibility with the control plane, and its upgrade path. A self-managed add-on is one you install yourself — typically a Helm chart delivered through GitOps — and own end to end.

The default is managed, and the reasoning is ownership cost. A managed add-on is one less thing your team upgrades, tests for version skew, and debugs at 2 a.m. AWS validates its compatibility with each Kubernetes version, and its health and available versions surface in EKS Cluster Insights, the same built-in scanner that flags upgrade blockers across the fleet.7 At a hundred clusters, “AWS tracks this for me and warns me before it breaks” is worth a great deal.

Self-managed earns its place only when managed can’t do the job. Reach for it when you need a version AWS hasn’t published yet, a configuration flag the managed add-on doesn’t expose, or a non-standard build — a custom CNI configuration, a patched image, a bleeding-edge feature. The price is that you now own the upgrade cadence, the compatibility testing, and the failure modes for that component, on every cluster it runs on (Figure 2).

Figure 2 · Managed vs self-managed add-ons Who owns the add-on lifecycle EKS MANAGED ADD-ONS — THE DEFAULT AWS owns lifecycle, version, compatibility Surfaces in Cluster Insights (upgrade-aware) Less for your team to own and test Console / API / IaC install, per cluster CHOOSE WHEN the standard version and config do the job SELF-MANAGED (HELM VIA GITOPS) You own the version, config, and build You own every upgrade and skew test Full control; nothing hidden from you Delivered by the same GitOps pipeline CHOOSE WHEN you need a version or build AWS won’t expose THE THREE CORE ADD-ONS — UPGRADE IN THIS ORDER kube-proxy → VPC CNI → CoreDNS (a Part 14 concern)
Default to the green side: managed add-ons hand AWS the lifecycle and light up in Cluster Insights; self-manage only when you need a version or build AWS won’t expose — and remember the three core add-ons carry a fixed upgrade order.

Why the three core add-ons decide your upgrade order

Three add-ons are special: kube-proxy, the VPC CNI, and CoreDNS. Every EKS cluster runs them — they are the networking and DNS substrate the rest of the cluster stands on — and they are the canonical case for letting AWS own the lifecycle, because their compatibility is tied directly to the Kubernetes version.

That coupling shows up as an upgrade order you don’t get to reorder. When you move a cluster to a new version, the sequence is control plane first, then the add-ons in the order kube-proxy → VPC CNI → CoreDNS, then the node groups.8 Managed add-ons make this tractable: AWS knows which add-on version pairs with which control-plane version, and Cluster Insights warns you before a mismatch bites.

This is a teaser, not the full treatment — Part 14 owns day-2 upgrades, where this order and the version-skew rules (a node can trail the control plane, but only within a bounded window) get the depth they deserve. The reason it belongs here is that the golden-path template is where you decide these three are managed, and that decision is what makes the eventual fleet-wide upgrade a routine operation instead of a research project.

Why this matters at fleet scale. The core add-ons are the same on every cluster, so an upgrade-order mistake isn’t a one-cluster incident — it is the same incident repeated across the fleet. Letting AWS own their lifecycle, and reading Cluster Insights before you upgrade, is how you keep that from happening a hundred times.

How a developer gets a compliant tenant without filing a ticket

Now the self-service mechanics — the part that makes this a platform rather than a well-organized ops team. The goal is a request flow where a developer expresses what they want, and a compliant tenant appears, with no human standing in the middle wiring things up.

The cheapest version that actually works is a pull request. The developer doesn’t need a bespoke portal; they open a PR against the fleet repo — a small manifest that says “team-c, standard tier, these environments.” That PR is the request. On merge, the ApplicationSet generator picks up the new tenant and renders the whole golden-path template onto it (Figure 3).

Figure 3 · The self-service request flow A pull request in, a compliant tenant out Developer PR tenant + tier Template renders ApplicationSet GitOps syncs Argo CD reconcile Compliant tenant baseline inherited POLICY GATE non-compliant config is rejected before it can ever sync
Self-service is a merge, not a portal: the PR is the request, the template renders and GitOps syncs it, and the policy gate in the middle rejects anything non-compliant before it reaches a cluster — so the fast path can only produce a compliant tenant.

For larger organizations, that PR flow often sits behind a thin platform API or a portal — a form that generates the same manifest, so a developer never edits YAML. That is a nicety, not the substance. The substance is underneath: whether the form calls an API or a human opens the PR, the request resolves to a manifest that the template renders and GitOps syncs. Start with the PR flow; add the portal when the audience outgrows it.

The scaffolding side matters too. A golden path includes starter templates for the things a team actually builds — a service repo pre-wired with a Dockerfile, a Helm chart, a CI pipeline, and the manifests that register it with the platform — so “new service” is a scaffold command, not a week of copy-paste from a sibling team’s repo. The tenant template and the app scaffold are the same idea at two levels: a compliant default you get by asking, not by assembling.

How you make the compliant way the only easy way — guardrails and the exit

The last piece is what separates a paved road from a suggestion. The golden path works because the guardrails make non-compliant configuration impossible to ship on the fast path, not merely frowned upon in a review.

That is the policy gate in Figure 3. The pod-security baseline from the template — no privileged containers, no host namespaces, no privilege escalation — is enforced in the pipeline, so a manifest that violates it is rejected before it can sync, whether it came from a self-service PR or a platform engineer.6 Roll it out in audit mode first to see what would break, then flip to enforce.

The difference between “we recommend” and “the pipeline won’t let you” is the difference between a guideline and a guardrail. Part 6 is the full treatment of policy-as-code — Kyverno versus OPA/Gatekeeper, baseline versus restricted — but the design decision starts here: the baseline lives in the template and the gate enforces it.

Guardrails that only say no, though, breed the workarounds they were meant to prevent. The honest complement is a documented exit. Some team, someday, will have a legitimate need the golden path doesn’t cover — a workload that needs a privileged container, a build the standard add-ons can’t run. The answer is not “never,” and it is not “quietly go around us.” It is a reviewed, deliberate off-ramp: request the exception, justify it, get a scoped approval, and carry the extra ownership that comes with leaving the paved road.

A good exit protects the golden path in both directions. It keeps the 95% on the road because the road is genuinely the easiest route, and it gives the 5% a sanctioned way off that you can see, review, and revisit — instead of a shadow fleet you find out about during an incident. The exit being rare and visible is what keeps the default meaningful.

So the decision thresholds, plainly:

Get those right and “compliant” and “fast” stop being a trade-off. That is the whole point of a platform: the right way is the easy way. Part 6 hardens the policy layer this platform enforces, and Part 7 builds a greenfield cluster with this golden path as its default.

Sources

Version, pricing, and Cluster Insights behavior below are current as of 2026-06-30 and should be re-verified at publish. Practitioner-reported figures are labelled as such in the text; they are not AWS commitments.

  1. AWS — EKS Blueprints and the GitOps bridge: a stable core Terraform module for the cluster plus Blueprints patterns for add-ons; IaC-generated metadata (IAM role ARNs, labels) is stored in the Argo CD cluster secret for ApplicationSets and Helm to consume. aws-ia.github.io/terraform-aws-eks-blueprints
  2. Argo CD — ApplicationSet controller and the cluster generator: template Applications across clusters by label selector to solve the N×M problem at fleet scale. argo-cd.readthedocs.io/.../applicationset
  3. AWS — EKS Pod Identity: the recommended default over IRSA for EKS-in-cloud — no per-cluster OIDC provider, reusable IAM roles across clusters. docs.aws.amazon.com/.../pod-identities.html
  4. AWS — EKS access entries: replace the deprecated aws-auth ConfigMap as the way to grant cluster access to IAM principals. docs.aws.amazon.com/.../access-entries.html
  5. Karpenter — groupless, workload-aware node provisioning via NodePool / EC2NodeClass; the fleet compute default (AWS states there is no SLA for Karpenter). karpenter.sh
  6. Kyverno — policy-as-code for Kubernetes: enforce a pod-security baseline (no privileged, no host namespaces, no privilege escalation) in audit mode first, then enforce, managed via GitOps. OPA/Gatekeeper is the Rego alternative. kyverno.io
  7. AWS — EKS Cluster Insights: built-in scanner for upgrade blockers and add-on compatibility, surfacing managed add-on health and versions across the fleet. docs.aws.amazon.com/.../cluster-insights.html
  8. AWS — updating an EKS cluster: upgrade order is control plane, then add-ons (kube-proxy, VPC CNI, CoreDNS), then node groups, one minor version at a time. docs.aws.amazon.com/.../update-cluster.html