This is a reference AWS EKS platform I built in public. It runs entirely on GitOps and holds no static cloud credentials. Identity comes from IRSA, secrets come from AWS Secrets Manager, and every deploy is a Git commit.
Status and ownership. This is a personal reference build, not client work. It has no users and no traffic, so nothing here is a production claim. I designed and wrote all of it: the Terraform, the ArgoCD manifests and the ESO wiring. The code is open at talhaimtiaz09/eks-paved-road. My production Kubernetes work runs on both GCP/GKE and AWS/EKS. On AWS, that's the healthcare estate, which I inherited hand-built and imported into Terraform. This build is the greenfield version. It covers the whole provisioning path from an empty account, which is the part client work never lets me show.
Three constraints drove everything. No human runs kubectl apply. No AWS access key lands in a pod or a repo. And the environment can be destroyed and rebuilt from source.
From hand-run deploys and stored keys to Git-driven deploys with no keys
The platform, layer by layer
First the whole system on one diagram. Then the two pieces that make the no-static-credentials design work: the keyless identity path and the separate control loops.
The platform, end to end
There are three layers, each with one job. Terraform owns the cloud: the VPC, the EKS cluster and the IAM roles. That includes the OIDC provider and the role IRSA hands to workloads. ArgoCD owns the cluster's desired state. It watches Git and applies an app-of-apps hierarchy, with Kustomize overlays per environment. External Secrets Operator (ESO) closes the last gap. It reads from AWS Secrets Manager and writes the values back as native Kubernetes Secrets. Applications read a plain Secret and never learn where it came from.
The important boundary is between Terraform and ArgoCD. Terraform stops at the edge of the cluster, and ArgoCD takes over inside it. Nothing manual bridges the two.
Keyless secrets with IRSA
The default approach is to give the pod an AWS access key. That key then has to be stored somewhere and rotated by hand.
I enabled the EKS OIDC provider instead. It lets AWS trust tokens that the cluster issues to service accounts. I bound ESO's service account to a dedicated IAM role through IRSA (IAM Roles for Service Accounts). ESO now assumes that role using a projected service-account token, a short-lived token Kubernetes mounts into the pod. It then writes Secrets Manager values back as ordinary Kubernetes Secrets. The application reads them without touching AWS at all.
The result I care about is where the boundary ended up. The application knows nothing about AWS. Swapping the secret backend later is an operator change, not an application change.
The two decisions that shaped it
IRSA + External Secrets Operator (keyless)
Injecting static AWS access keys into pods via Kubernetes Secrets
Why: A static key is a standing liability. It has to be stored somewhere, it spreads across environments, and it leaks through logs and repos. Rotating it is a manual event. IRSA replaces it with a short-lived token that AWS trusts through OIDC. The credential only lives for the length of a request and never sits in Git or the cluster. ESO then delivers the secret values as native K8s Secrets, so the app never has to know about AWS.
Keep Terraform and ArgoCD as two separate control loops
One combined provision-and-deploy pipeline
Why: Infrastructure and workloads really do run on different control loops. Terraform orders its work by resource dependencies. ArgoCD orders by sync waves and keeps reconciling against Git. Provisioning converges once. Workload state is reconciled forever and has to heal itself when it drifts. One pipeline would tie together two problems that fail differently and recover differently. It would add operational complexity and buy nothing.
I reached the second decision by watching the system run. Infrastructure state and application state drift independently. A green ArgoCD sync doesn't mean the workload is healthy. Secret delivery also has to finish before a workload starts, not alongside it. Each layer has its own idea of "correct" and its own recovery path. Forcing them through one pipeline would have made the setup fragile.
Validating reproducibility
There's no traffic to load-test, so validation here comes down to two questions. Can the platform be destroyed and come back the same way every time? And does it heal itself when the live state drifts from Git? I tested three scenarios that a real on-call engineer would eventually hit.
- Fresh cluster provisioning. I tore the whole environment down and rebuilt it from Terraform plus Git. I checked that repeated rebuilds landed in the same state instead of drifting from run to run.
- Secret rotation. I rotated a value in AWS Secrets Manager and confirmed that ESO pushed the new value into the Kubernetes Secret with no manual step.
- Drift and accidental deletion. I deleted live resources out from under ArgoCD to see whether reconciliation noticed and restored them.
What held up:
- ArgoCD detected the deleted resources and restored them to the state declared in Git.
- Secret rotation worked end to end with no manual step. The app picked up the new value through the normal Secret.
- Cluster rebuilds came out the same across repeated runs.
These aren't performance numbers, and they aren't meant to be. They show the control loops doing what the design says they should when something goes wrong.
What I'd harden before real traffic
The architecture is sound, but a reference build skips the operational hardening that real traffic forces. If this were about to carry load, this is the order I'd work in:
- Tighter IRSA scoping. The ESO role is scoped enough to show the pattern. A production role needs least privilege per namespace and per secret, so a compromised operator can't read everything.
- Secret-rotation blast radius. Rotation propagates cleanly. Before trusting it under load, I'd map exactly which workloads restart or reconnect when a secret rotates.
- ArgoCD drift alerting. Self-healing happens silently today. I'd want an alert whenever ArgoCD corrects drift, because a resource that keeps getting deleted is a signal worth seeing.
- Cluster autoscaling. There's no autoscaling yet. With real workloads, I'd add node and workload autoscaling before capacity becomes the incident.
- Backup and DR cadence. Reliable rebuilds cover most of DR. I'd still formalize state backups (Terraform state and any stateful data) and a real restore schedule, instead of relying on rebuild-from-source alone.
Key results
- A working, open-source reference GitOps platform on AWS EKS: github.com/talhaimtiaz09/eks-paved-road
- Zero static AWS credentials in the cluster or in Git. Identity is keyless through IRSA and EKS OIDC.
- Fully reproducible infrastructure from Terraform, tested by repeated teardown and rebuild
- Keyless secret sync from AWS Secrets Manager through External Secrets Operator
- Terraform and ArgoCD kept as separate control loops, with ArgoCD healing drift back to Git