Terraform GitOps Bridge Modules for EKS: A Cleaner Way to Bootstrap Clusters and Hand Off to Argo CD
Terraform GitOps Bridge Modules for EKS: A Cleaner Way to Bootstrap Clusters and Hand Off to Argo CD
Bootstrapping an EKS cluster is not the hard part. The hard part is handing cloud metadata, add-on dependencies, and day-2 ownership from Terraform to GitOps without making both systems fight over the same cluster. This guide explains how the GitOps bridge pattern solves that handoff.
TL;DR
- The GitOps bridge pattern separates cloud provisioning from in-cluster reconciliation.
- Terraform creates the EKS cluster and external dependencies, then passes cluster-specific metadata to Argo CD.
- Argo CD uses that metadata to install and reconcile add-ons and workloads from Git.
- The key operational rule is simple: do not let Terraform and Argo CD both think they own the same add-on.
- The result is a cleaner day-0 to day-2 handoff and a more maintainable EKS platform.
The Hard Part Is Not Creating the Cluster. It Is Handing It Off Cleanly.
Most teams can get an EKS cluster online with Terraform. The harder problem starts immediately after that: add-ons need IAM roles, VPC data, DNS details, load-balancer settings, and environment-specific values that exist outside Kubernetes, but you still want Argo CD to own in-cluster reconciliation.
If Terraform installs every Helm chart forever, your GitOps story is weak. If Argo CD gets no cloud metadata, your bootstrap is incomplete. The GitOps bridge pattern exists to solve that handoff.
The AWS IA EKS Blueprints documentation describes the core idea clearly: Infrastructure as Code creates the cloud resources and the metadata those add-ons need, but it does not remain the tool that installs and continuously manages those Helm charts. Instead, Terraform writes the metadata into GitOps-facing resources, and Argo CD uses that data during add-on and workload installation.
- Terraform owns cluster creation and cloud-side dependencies.
- Argo CD owns day-2 add-on and workload reconciliation.
- Bridge metadata tells Argo CD how to configure cluster-specific installs.
- The handoff is explicit instead of tribal knowledge.
What the GitOps Bridge Pattern Actually Does
The easiest way to misunderstand this pattern is to think it is simply "Terraform plus Argo CD." It is more specific than that. The bridge is the metadata contract between the two systems.
In the EKS Blueprints GitOps pattern, Terraform can populate Argo CD cluster-secret annotations with values such as repository URL, repository path, revision, AWS account ID, cluster name, region, VPC ID, and IAM role details needed by add-ons.
That is the missing link in many homemade bootstraps. Without it, Argo CD knows what Git repo to read but not how to adapt those manifests or Helm values to the actual cluster Terraform just created.
terraform init
terraform apply -target="module.vpc" -auto-approve
terraform apply -target="module.eks" -auto-approve
terraform apply -auto-approve
terraform output -raw configure_kubectl
After bootstrap, the Blueprints documentation shows annotations that include values such as addons_repo_url, addons_repo_path, aws_region, aws_vpc_id, and aws_cluster_name. That tells you exactly what the bridge is carrying across the boundary.
A Better Ownership Model: Terraform for Day 0, Argo CD for Day 2
The most important design decision is ownership.
Terraform is good at provisioning cloud resources and expressing dependencies that live outside Kubernetes: VPC context, EKS cluster infrastructure, IAM roles, and add-on prerequisites such as SQS queues or AWS Load Balancer Controller roles.
Argo CD is better at continuous reconciliation of in-cluster desired state: add-ons installed from Git-managed ApplicationSets, workloads, ongoing version drift inside the cluster, and promotions or rollbacks driven by Git changes.
If you let both systems manage the same add-on, you create a control problem instead of a platform. One tool will keep planning changes while the other keeps reconciling them away. The bridge pattern prevents that by drawing a harder line: Terraform may create the dependency, but Argo CD installs and reconciles the chart or workload.
A Practical Bootstrap Flow for EKS
A clean bootstrap flow usually looks like this:
- Terraform provisions foundational infrastructure such as the VPC and EKS cluster.
- Terraform provisions external dependencies required by add-ons, such as IAM roles for service accounts.
- A bootstrap module creates or updates the Argo CD cluster secret and seeds an app-of-apps style starting point.
- Argo CD reads Git, consumes the metadata, and installs add-ons and workloads through its reconciliation loop.
A simplified metadata shape looks like this:
locals {
addons_metadata = {
addons_repo_url = "https://github.com/aws-samples/eks-blueprints-add-ons"
addons_repo_basepath = "argocd/"
addons_repo_path = "bootstrap/control-plane/addons"
addons_repo_revision = "main"
aws_region = var.aws_region
aws_cluster_name = module.eks.cluster_name
aws_vpc_id = module.vpc.vpc_id
environment = var.environment
}
}
The point of this object is not syntax trivia. The point is to make cloud context machine-readable for Argo CD.
On the add-on side, the AWS IA modules are designed to help with prerequisite creation. The single-add-on module documents a pattern where a Terraform module can create a Helm release and the IAM role for service accounts. In a bridge-based operating model, that same style of module output is often more valuable as a source of metadata than as proof that Terraform must own the long-term chart lifecycle.
Where This Pattern Pays Off in Real Platform Work
The bridge pattern becomes most valuable when your add-ons are not self-contained.
- AWS Load Balancer Controller needs AWS-facing configuration and IAM.
- ExternalDNS needs Route 53 context and permissions.
- External Secrets needs cloud secret backends and identity wiring.
- Argo CD itself needs cluster registration and repository metadata for app-of-apps bootstraps.
These are exactly the cases where purely in-cluster GitOps is not enough, because the controller needs values Terraform already knows.
The Blueprints blue-green upgrade pattern makes this concrete. It describes a flow where the GitOps bridge module extracts metadata from the add-ons module, stores it in the cluster, and lets Argo CD adapt installation to the target cluster context. That is a strong operating model because application teams can deploy through GitOps without needing to understand every cloud-side prerequisite, while platform teams still control the cluster contract.
Why We Built It This Way
The real value of the bridge pattern is not fewer lines of Terraform. It is cleaner failure domains.
When Terraform owns both cloud infrastructure and every in-cluster Helm release, cluster changes become coupled to Terraform state, provider credentials, and plan/apply windows. When Argo CD owns everything but has no reliable metadata bridge, platform engineers end up hand-carving secrets and values files after bootstrap. Both approaches create brittle ownership.
The bridge pattern is a compromise that is actually worth keeping: Terraform stays authoritative for external infrastructure and cluster metadata, GitOps stays authoritative for in-cluster convergence, and the cluster secret or Git bootstrap data becomes the contract between them.
That makes upgrades, add-on rollouts, and environment replication easier to reason about. It also makes audits cleaner, because you can point to one layer for infrastructure intent and one layer for runtime reconciliation instead of explaining a tangled hybrid.
What the Argo CD Cluster Secret Actually Carries
The most concrete technical proof that the bridge pattern is real is the Argo CD cluster secret itself. In the AWS IA pattern, Terraform writes metadata into that secret so Argo CD can reconcile add-ons and workloads with cluster-specific values already attached.
A quick verification loop looks like this:
kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster -o yaml
In the AWS IA getting-started pattern, you should expect metadata values that include repository pathing and cluster context such as addons_repo_url, addons_repo_path, addons_repo_revision, aws_region, aws_cluster_name, and aws_vpc_id.
That is what makes the bridge more than a bootstrap slogan. It is a metadata contract that allows Argo CD to render the right values for the cluster Terraform actually created.
One current nuance is worth stating clearly: self-managed Argo CD on EKS is not the only supported path anymore. Amazon EKS now documents a managed Argo CD capability as well. That does not invalidate the bridge pattern, but it changes how you should word the decision. The question is no longer “Can EKS run Argo CD?” It is “Which Argo CD operating model fits your platform boundaries?”
Frequently Asked Questions
Q: Should Terraform install Argo CD itself?
A: It can during bootstrap, especially for the first control-plane setup, but the long-term goal is usually for Argo CD to reconcile its own app-of-apps model after the initial handoff. What matters most is keeping ownership explicit after that first bootstrapping step.
Q: What goes wrong if Terraform and Argo CD both manage the same add-on?
A: You get reconciliation fights. Terraform plans never settle cleanly, Argo CD keeps restoring Git-defined state, and upgrades become harder because you no longer know which control loop is supposed to win.
Q: Is the bridge only for add-ons?
A: No. The same pattern also helps with workload bootstraps that depend on environment metadata, identity wiring, repository paths, or cloud-side service endpoints. Add-ons are just the most obvious early use case.
Q: What should I verify after bootstrap?
A: Verify that the Argo CD cluster secret contains the expected metadata, that the repository URL, path, and revision values are correct, and that the first add-on and workload ApplicationSets reconcile successfully in the target cluster.
Comments
Post a Comment