Case Study
8 mins

Built a Reference GitOps Platform on AWS EKS with Zero Static Credentials

Designed and published a reference AWS EKS platform using Terraform and GitOps. Eliminated static cloud credentials using IRSA and automated secret delivery with External Secrets Operator, enabling fully declarative infrastructure and application delivery.

Core Role

DevOps Engineer

Tech Stack

AWS EKS, Terraform, ArgoCD, External Secrets Operator, AWS Secrets Manager, Kubernetes

Architecture diagram of an AWS EKS platform: Terraform provisions the VPC, EKS cluster and IAM roles; ArgoCD applies an app-of-apps hierarchy from Git; External Secrets Operator pulls secrets from AWS Secrets Manager into Kubernetes using IRSA, so no static cloud credentials are stored in the cluster or in Git.

A reference AWS EKS platform, built in public, that runs entirely on GitOps and carries zero static cloud credentials — identity comes from IRSA, secrets come from AWS Secrets Manager, and every deploy is a Git commit.

This is a paved-road build, not a product. It has no users and no traffic — the point was to work out, end to end, how a mature team actually wires EKS so that identity, secrets, and delivery stop being manual. The whole thing is open on GitHub at talhaimtiaz09/eks-paved-road — Terraform, ArgoCD manifests, and the ESO wiring included.

Zero
Static cloud credentials in the cluster or in Git — identity is keyless via IRSA
100% GitOps
Every deploy is a Git commit; ArgoCD reconciles and self-heals drift
Reproducible
The whole platform rebuilds from Terraform + Git, deterministically

The design goal was narrow and opinionated: no human runs kubectl apply, no AWS access key ever lands in a pod or a repo, and the entire environment can be torn down and rebuilt from source. Everything below follows from those three constraints.

Before
After

How mature teams actually run it

The platform, layer by layer

First the whole system on one diagram, then the two pieces that make the 'zero static credentials' claim real — the keyless identity path and the decoupled control loops.

1Architecture

The platform, end to end

Three layers, three responsibilities. Terraform owns the cloud: VPC, the EKS cluster, and the IAM roles — including 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 closes the last gap — it reaches into AWS Secrets Manager and writes the values back as native Kubernetes Secrets, so applications read a plain Secret and never learn where it came from.

The seam that matters is between Terraform and ArgoCD. Terraform stops at the cluster boundary; ArgoCD takes over inside it. Nothing manual bridges the two.

System overview — Terraform provisions, ArgoCD delivers, ESO supplies secrets keylessly (click to enlarge)
The keyless identity path — OIDC to IRSA to a materialized Secret
2Identity

Keyless secrets with IRSA

The obvious way to give a pod access to Secrets Manager is to hand it an AWS access key. That key then has to live somewhere — a Kubernetes Secret, a CI variable, a file — and now you own a long-lived credential that leaks, sprawls across environments, and has to be rotated by hand.

IRSA removes the key entirely. I enabled the EKS OIDC provider and configured IAM Roles for Service Accounts, so the External Secrets Operator runs under a service account that is bound to a dedicated IAM role. At runtime it presents a short-lived, projected service-account token, AWS trusts that token via OIDC, and ESO assumes the role — no static credential anywhere in the path. ESO then fetches from Secrets Manager and materializes the values as ordinary Kubernetes Secrets, which the application consumes without ever touching AWS.

The two decisions that shaped it

Engineering decision
Chose

IRSA + External Secrets Operator (keyless)

Over

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 sprawls across environments, it leaks through logs and repos, and rotation is a manual event. IRSA replaces it with a short-lived token AWS trusts via OIDC, so the credential exists only for the length of a request and never sits in Git or the cluster. ESO then delivers the actual secret values as native K8s Secrets, keeping the app oblivious to AWS entirely.

Engineering decision
Chose

Keep Terraform and ArgoCD as two separate control loops

Over

One combined provision-and-deploy pipeline

Why: Infrastructure lifecycle and workload lifecycle are genuinely different control loops. Terraform's ordering is driven by resource dependencies; ArgoCD's is driven by sync waves and continuous reconciliation against Git. Provisioning is a converge-once operation, while workload state is reconciled forever and must self-heal on drift. Fusing them into one pipeline couples two problems that fail differently and recover differently, and buys nothing but operational complexity.

The second decision came out of actually watching the system behave. Infrastructure state and application state drift independently — a green ArgoCD sync doesn't mean the workload is healthy, and secret delivery has to happen before a workload starts, not alongside it. Once you accept that each layer has its own notion of "correct" and its own recovery path, forcing them through one pipeline stops looking clever and starts looking fragile.

Validating reproducibility

Because there's no traffic to load-test, "validation" here means one thing: can the platform be destroyed and come back deterministically, and does it heal itself when reality diverges from Git? I exercised three scenarios that a real on-call would eventually hit.

  • Fresh cluster provisioning — tearing the whole environment down and rebuilding it from Terraform plus Git, checking that repeated rebuilds land in the same state rather than drifting run to run.
  • Secret rotation — rotating a value in AWS Secrets Manager and confirming ESO propagated the new value into the Kubernetes Secret without any manual step.
  • Drift and accidental deletion — deleting live resources out from under ArgoCD to see whether reconciliation noticed and restored them.

What held up:

  • ArgoCD detected deleted resources and restored them back to the Git-declared state.
  • Secret rotation propagated end to end with no manual intervention — the app picked up the new value through the normal Secret.
  • Cluster rebuilds stayed deterministic across repeated runs.

These aren't performance numbers and they aren't meant to be. They're evidence that the control loops do what the architecture claims 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 tackle it:

  • Tighter IRSA scoping — the ESO role is scoped enough to demonstrate the pattern; a production role wants per-namespace, per-secret least privilege so a compromised operator can't read everything.
  • Secret-rotation blast radius — rotation propagates cleanly, but I'd map exactly which workloads restart or reconnect on a rotation before trusting it under load.
  • ArgoCD drift alerting — self-healing is silent today. I'd want an alert when ArgoCD corrects drift, because a resource that keeps getting deleted is a signal, not a non-event.
  • Cluster autoscaling — there's no autoscaling story yet; with real workloads I'd wire in node and workload autoscaling before capacity becomes the incident.
  • Backup and DR cadence — deterministic rebuilds are most of DR, but I'd formalize state backups (Terraform state, any stateful data) and an actual restore cadence rather than 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 via IRSA and EKS OIDC
  • Fully reproducible infrastructure from Terraform, validated by repeated teardown-and-rebuild
  • Keyless secret synchronization from AWS Secrets Manager via External Secrets Operator
  • Terraform and ArgoCD kept as separate control loops, with ArgoCD self-healing drift back to Git