Managing hundreds of EKS clusters · Part 3 of 18
Provisioning an EKS Fleet: Terraform, Blueprints, eksctl, or Cluster API?
Third in the fleet-scale EKS series. This is where clusters come into existence at scale — and where the tool you pick to create a cluster becomes the tool you own for its whole 26-month life. Here is what provisions what, why AWS now says don't build the core cluster with Blueprints, and how the IaC layer hands off cleanly to GitOps.
TL;DR
Provision the core cluster with a stable, versioned Terraform EKS module and use EKS Blueprints for add-on patterns only — that split is AWS's own current guidance, and it exists to keep a churny add-on from ever threatening your control plane. Set EKS Pod Identity and access entries at creation, write the cluster's generated metadata into the Argo CD cluster secret (the GitOps bridge), and you have a clean seam between what IaC owns and what GitOps owns. Reach for eksctl only for throwaway clusters, and for Cluster API only if you're willing to run an HA management cluster whose downtime blocks every cluster operation.
Design it this way
- Core cluster in a versioned Terraform EKS module; add-ons via Blueprints patterns.
- Set EKS Pod Identity and access entries at provision time, not later.
- Carry IAM role ARNs and cluster metadata across the GitOps bridge secret.
- eksctl for one-offs; Terraform + Blueprints for fleets; CAPI only with an HA management cluster.
Don't do this
- Don't provision the production core cluster with Blueprints — that's what AWS now steers you away from.
- Don't hand-wire role ARNs into Helm values; let the bridge secret carry them.
- Don't adopt Cluster API without committing to operate its HA management cluster.
- Don't treat provisioning as one-time — you'll re-run it through every upgrade.
Why the provisioning tool outlives the cluster it creates
An EKS cluster is not something you create once. AWS keeps each Kubernetes version in standard support for 14 months and extended support for 12 more — a 26-month lifecycle — and at the end of it the control plane auto-upgrades whether you're ready or not.8 (Version calendar current as of 2026-06-30; re-verify it at publish time.) So every cluster you stand up you will also patch, upgrade, and eventually replace, many times over, across a fleet of hundreds.
That reframes the decision. The question isn't "what spins up a cluster fastest?" — almost anything does. It's "what will still be describing this cluster in eighteen months, when it's on its third minor version and its nodes have been rebuilt twice?" The tool you use to create a cluster is the tool you inherit for its entire life.
Two consequences shape everything below. First, provisioning has to be declarative and versioned — the cluster's definition lives in Git, not in a console click or a one-time script. Second, a few things are far cheaper to set at birth than to retrofit:
- the identity model — EKS Pod Identity and access entries, both configured at provision time67
- the VPC and subnets a cluster is permanently bound to
- how it will receive its workloads
Get those into the provisioning code and day-two is calm; bolt them on later and every upgrade fights you.
Why AWS tells you not to build the core cluster with Blueprints
The most common EKS provisioning pattern of 2024–2025 was reasonable at the time: adopt EKS Blueprints for Terraform to stamp out a "batteries-included" cluster — control plane, VPC, and a dozen add-ons — from one module. It demos beautifully. Then it quietly becomes load-bearing in production.
AWS's current guidance is a deliberate split, and it's worth understanding the why: provision the core cluster with a stable, versioned Terraform EKS module, and use Blueprints only for add-on patterns. Do not use Blueprints to provision the core cluster in production.12
The reason is lifecycle coupling and blast radius. An all-in-one module ties the control plane's lifecycle to the add-ons' lifecycle, so a routine change to an add-on pattern re-plans the cluster itself — and the most durable, highest-stakes thing you own, the control plane and its state, is now exposed to churn from the fastest-moving layer. Split them, and the cluster gets to be boring and rarely-touched while the add-ons iterate freely.
So the shape AWS now recommends is two layers with different rhythms:
- Core cluster — a mature, community-maintained Terraform EKS module pinned to a version: the control plane, node groups (or Karpenter's prerequisites), EKS Pod Identity associations, access entries, and the VPC wiring. This layer changes rarely and on purpose.2
- Add-ons — Blueprints add-on patterns (or the managed EKS add-ons API) for the VPC CNI, CoreDNS, kube-proxy, the AWS Load Balancer Controller, Karpenter, and the rest: the layer that iterates.1
This isn't Blueprints being deprecated. It's Blueprints being put in its correct layer — a catalog of add-on patterns and a bootstrapping mechanism, not the thing that owns your control plane.
How Terraform hands the cluster to GitOps — the bridge secret
Once the core cluster and its add-ons are Terraform's job and everything after is GitOps's job, one problem remains: the handoff. Argo CD (the subject of Part 4) needs facts only the IaC run knows — the IAM role ARNs it just created for Pod Identity, the OIDC provider URL, the cluster endpoint, the VPC IDs, the Region. Copy those into Helm values by hand across a fleet and you've built a drift machine.
The GitOps bridge pattern closes this cleanly. Terraform writes the cluster's generated metadata — role ARNs and the rest — into the Argo CD cluster secret as labels and annotations. Argo CD ApplicationSets and Helm charts then read those values straight from the secret at deploy time, so an add-on's chart gets its role ARN without anyone pasting it anywhere.110
That secret is the seam (Figure 1). To its left is IaC: create the cluster, create the roles, record the metadata. To its right is GitOps: deploy add-ons and apps from Git, parameterized by what the bridge handed over. This is exactly why the two systems can own different halves of the same cluster without a shared spreadsheet of ARNs — and it's the precise handoff the next article on GitOps fleet management picks up and runs with.
When eksctl is exactly right — and when it isn't
eksctl, the official CLI, is the fastest way to a working cluster: one command, sensible defaults, a real cluster in minutes.3 For a throwaway dev cluster, a proof of concept, a workshop, or bootstrapping the very first management cluster you'll later manage another way, it's the right tool and Terraform would be overkill.
The trouble begins when an eksctl cluster quietly becomes production. Its definition lives in a YAML file and a series of imperative commands — not in the state-managed, peer-reviewed, drift-detected pipeline that governs the rest of your infrastructure. At fleet scale that's a real liability: no plan/apply review, no shared remote state, no single module whose version bump you can roll across 300 clusters at once. eksctl is excellent at creating one cluster and a poor fit for governing hundreds.
The rule of thumb: eksctl for a cluster whose lifespan you can measure in days, or to bootstrap something. The moment a cluster needs to outlive a sprint, it belongs in the Terraform core module.
What Cluster API asks of you — a management cluster you keep alive
Cluster API (CAPI), through its AWS provider CAPA, comes at provisioning from the Kubernetes-native direction: a cluster is a custom resource, and a controller continuously reconciles real infrastructure to match it.45 That's declarative lifecycle management for the clusters themselves, driven by the same control-loop model you already trust for workloads. It's genuinely elegant — and it's what EKS Anywhere is built on.4
The catch is the price of that control loop: you must operate a management cluster — the cluster that runs the CAPI controllers and holds the desired state of every other cluster — and it has to be highly available, because while it is down, no cluster lifecycle operation can happen anywhere. No new clusters, no scaling changes, no upgrades.4 You have turned cluster provisioning into a service you now run, with its own availability target, its own upgrades, and its own on-call.
For most teams on EKS-in-cloud, that's a worse trade than Terraform, whose "management cluster" is just a CI runner and an S3 state bucket — not an HA Kubernetes control plane to keep alive. CAPI earns its keep when you specifically want a Kubernetes-native declarative control loop for clusters, which usually means edge, air-gapped, or on-prem settings where EKS Anywhere has already put a management cluster in your hands. If you're not in that world, the management-cluster tax rarely pays for itself.
How to vend accounts and clusters together — AFT plus Blueprints
At fleet scale the unit you provision is often not a cluster but an account-with-a-cluster: a new team arrives and needs its own AWS account, baselined to your guardrails, with a cluster already sitting in it. Doing that by hand does not scale to hundreds.
Account Factory for Terraform (AFT) is the AWS Control Tower capability that automates it.9 AFT vends a new account through a Terraform pipeline, applies your account-level baseline, and then runs customization Terraform inside the freshly-created account — which is exactly where your core EKS module and Blueprints add-on patterns slot in. The result is a repeatable pipeline: request an account, and out comes a governed account with a production-shaped cluster, its Pod Identity roles, and its add-ons already in place (Figure 3).
This is where the earlier decisions compound. Because identity is set at provision time, the vended cluster is governed from its first minute — not from whenever someone remembers to add access entries.
Which tool to reach for — the decision
Strip it down to the decision you actually make.
- Reach for eksctl when the cluster is a one-off — dev, a demo, a bootstrap — and its lifespan is short. Don't let one graduate to production without moving it into Terraform.3
- Reach for a stable Terraform EKS core module plus Blueprints add-on patterns for any production fleet. The core module owns the control plane and identity; Blueprints owns the add-ons; the GitOps bridge secret carries the metadata across to Argo CD. This is the golden path for EKS-in-cloud.12
- Reach for Cluster API only when you want a Kubernetes-native declarative control loop for clusters and you can run an HA management cluster reliably — typically edge, air-gapped, or EKS Anywhere. Otherwise the management-cluster tax outweighs the elegance.4
- Wrap the whole thing in AFT when you vend accounts and clusters together, so every cluster is the same governed artifact from birth.9
One thing ties all four together. Whatever creates the cluster, its definition lives in versioned code, EKS Pod Identity and access entries are set at creation, and the cluster is built to be upgraded — because over a 26-month lifecycle you will upgrade it, and the provisioning tool is what you'll do it with.867
Next in the series: GitOps fleet management — how Argo CD ApplicationSets, fed by the bridge secret you just built, deploy and reconcile add-ons and apps across the whole fleet.
Sources
- AWS — terraform-aws-eks-blueprints: batteries-included patterns and the GitOps bridge; current guidance to use a stable core EKS Terraform module for the cluster and Blueprints for add-on patterns. aws-ia.github.io/terraform-aws-eks-blueprints
- terraform-aws-modules/terraform-aws-eks — the community-maintained core EKS module (control plane, node groups, access entries) that AWS points to for provisioning the cluster itself. github.com/terraform-aws-modules/terraform-aws-eks
- eksctl — the official EKS CLI for creating and managing clusters. eksctl.io
- Cluster API Provider AWS (CAPA) — declarative, Kubernetes-native cluster lifecycle; requires an operational (HA) management cluster; EKS Anywhere is built on Cluster API. cluster-api-aws.sigs.k8s.io
- The Cluster API Book — management cluster vs workload cluster, and the controller/reconciliation model. cluster-api.sigs.k8s.io
- AWS — EKS Pod Identity: recommended default over IRSA for EKS-in-cloud; associations configured at provision time. docs.aws.amazon.com/.../pod-identities.html
- AWS — EKS access entries: the replacement for the aws-auth ConfigMap; set at provision time. docs.aws.amazon.com/.../access-entries.html
- AWS — Amazon EKS Kubernetes versions: 14-month standard + 12-month extended support (26-month lifecycle); control-plane auto-upgrade at end of lifecycle. Version calendar current as of 2026-06-30 — re-verify at publish. docs.aws.amazon.com/.../kubernetes-versions.html
- AWS — Account Factory for Terraform (AFT): Control Tower account vending via a Terraform pipeline, with per-account customizations. docs.aws.amazon.com/.../aft-overview.html
- GitOps bridge — the pattern that stores IaC-generated metadata (IAM role ARNs, cluster facts) in the Argo CD cluster secret for charts/ApplicationSets to consume. github.com/gitops-bridge-dev/gitops-bridge