# Terraform GitOps Bridge Modules for EKS: A Cleaner Way to Bootstrap Clusters and Hand Off to Argo CD Source: https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html Published: 2026-03-14T15:46:00.000-07:00 Updated: 2026-10-13T00:08:21.574-07:00 Author: Unknown Topics: gitops, kubernetes, terraform **Listen to this article** AI-narrated article - 11 min 58 sec. Narration may not include the latest examples. Use the written guide for implementation details. Your browser does not support audio playback. [Open the MP3](https://manomatt.github.io/devopsdreams-audio/audio/post-2535562775798922906-v1.mp3). [Read the narration transcript](https://manomatt.github.io/devopsdreams-audio/transcripts/post-2535562775798922906-v1.html) - [Open audio](https://manomatt.github.io/devopsdreams-audio/audio/post-2535562775798922906-v1.mp3) # 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](https://www.google.com/search?ved=1t:260882&q=define+cloud+metadata+in+Kubernetes&bbid=3735948330054827072&bpid=2535562775798922906), 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](https://www.google.com/search?ved=1t:260882&q=GitOps+bridge+pattern&bbid=3735948330054827072&bpid=2535562775798922906) solves that handoff. ## TL;DR [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-1) - 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. [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-2) 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](https://www.google.com/search?ved=1t:260882&q=Kubernetes+Helm+charts&bbid=3735948330054827072&bpid=2535562775798922906) 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.** ![GitOps bridge architecture diagram showing Terraform, Argo CD, and Git repositories](https://raw.githubusercontent.com/aws-ia/terraform-aws-eks-blueprints/main/patterns/gitops/getting-started-argocd/static/gitops-bridge.drawio.png) Screenshot: the GitOps bridge architecture used in the AWS IA EKS Blueprints Argo CD bootstrap pattern. Source: AWS IA. ## What the GitOps Bridge Pattern Actually Does [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-3) 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](https://www.google.com/search?ved=1t:260882&q=metadata+contract+GitOps&bbid=3735948330054827072&bpid=2535562775798922906) 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. Use targeting only for an exceptional staged bootstrap. Review each saved plan, protect plan files as sensitive artifacts, and finish with a full plan and apply to cover the complete dependency graph. [Resource targeting](https://developer.hashicorp.com/terraform/cli/commands/plan#resource-targeting). ```bash terraform init # Exceptional staged bootstrap: inspect and approve each targeted plan. terraform plan -target="module.vpc" -out=vpc-bootstrap.tfplan terraform apply vpc-bootstrap.tfplan terraform plan -target="module.eks" -out=eks-bootstrap.tfplan terraform apply eks-bootstrap.tfplan # Complete the graph with a full plan; targeted applies are not final validation. terraform plan -out=platform.tfplan terraform apply platform.tfplan terraform plan 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 [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-4) 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](https://www.google.com/search?ved=1t:260882&q=AWS+Load+Balancer+Controller+EKS&bbid=3735948330054827072&bpid=2535562775798922906) 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 [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-5) A clean bootstrap flow usually looks like this: 1. Terraform provisions foundational infrastructure such as the VPC and EKS cluster. 2. Terraform provisions external dependencies required by add-ons, such as IAM roles for service accounts. 3. A bootstrap module creates or updates the [Argo CD cluster secret](https://www.google.com/search?ved=1t:260882&q=Argo+CD+cluster+secret+details&bbid=3735948330054827072&bpid=2535562775798922906) and seeds an app-of-apps style starting point. 4. Argo CD reads Git, consumes the metadata, and installs add-ons and workloads through its reconciliation loop. A simplified metadata shape looks like this: ```hcl 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 [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-6) 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](https://www.google.com/search?ved=1t:260882&q=EKS+Blueprints+blue-green+upgrade+pattern&bbid=3735948330054827072&bpid=2535562775798922906) 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 This Reference Design Uses These Trade-offs [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-7) The real value of the bridge pattern is not fewer lines of Terraform. It is cleaner [failure domains](https://www.google.com/search?ved=1t:260882&q=define+failure+domains+DevOps&bbid=3735948330054827072&bpid=2535562775798922906). 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 [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-8) 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: Inspect names and types without exposing Secret data. Finding a matching cluster Secret does not prove that Argo CD can reach or authenticate to the target cluster; verify that connection separately. ```bash kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster -o custom-columns=NAME:.metadata.name,TYPE:.type --no-headers ``` 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?” ## App-of-apps bootstrap is a privileged administration boundary [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-9-2) If a parent Application manages child Applications, repository write access can become cluster administration authority. Restrict writers, require review of child `spec.project` and destination fields, and constrain the child AppProjects. A parent project name alone does not establish those controls. Argo CD documents app-of-apps as an admin-level capability and currently recommends evaluating ApplicationSets with cluster labels for typical fleet bootstrap. [Cluster bootstrapping guidance](https://argo-cd.readthedocs.io/en/stable/operator-manual/cluster-bootstrapping/). This reference parent deliberately omits automated pruning and a cascading-deletion finalizer during initial inspection. Replace the repository, commit and path, install Argo CD, create a suitably constrained `platform-admin` AppProject and review every generated child Application before syncing. The example is not a complete bootstrap installation. Adding prune, self-heal or a finalizer later changes mutation/deletion behavior and requires a deliberate policy. ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: cluster-bootstrap namespace: argocd spec: project: platform-admin source: repoURL: https://github.com/example/platform-config.git targetRevision: REPLACE_WITH_REVIEWED_COMMIT_SHA path: clusters/prod destination: server: https://kubernetes.default.svc namespace: argocd ``` The destination here is the cluster hosting Argo CD; child Applications define their own reviewed destinations. A child can reference another project or namespace, so inspect the generated resources rather than assuming the parent constrains every child. Sync waves order eligible resources but are not a substitute for dependency readiness and health checks. Pin module/provider dependencies and retain the dependency lock file alongside reviewed Terraform plans. ## Validate the handoff and rehearse recovery by ownership layer [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-10-2) Before declaring bootstrap complete, establish that infrastructure exists, Argo CD can authenticate to the intended cluster and repository, child Applications point to authorized destinations, and resource health matches the intended state. A matching cluster Secret or a successful apply is only one checkpoint. ```bash kubectl -n argocd get application cluster-bootstrap kubectl -n argocd get application cluster-bootstrap -o jsonpath='{.status.sync.status}{" "}{.status.health.status}{"\n"}' # Review the referenced project and child Applications before authorizing sync. kubectl -n argocd get appproject platform-admin kubectl -n argocd get applications ``` For Terraform-managed failures, diagnose the current state and review a corrective plan; reverting configuration does not imply that infrastructure or data can be rolled back safely. For Argo-managed failures, a reviewed Git revert changes desired state, while an emergency live edit can be reconciled away by self-heal. Argo CD application rollback is unavailable with automated sync enabled. Test recovery, application data compatibility and any deletion policy independently. [Automated sync semantics](https://argo-cd.readthedocs.io/en/stable/user-guide/auto_sync/), [Application deletion](https://argo-cd.readthedocs.io/en/stable/user-guide/app_deletion/). ## Repository layout must reflect authority, not just convenience [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-11) The following optional layout separates bootstrap, cluster overlays and team applications. Directory structure alone is not an access-control boundary. Use repository permissions, review rules and constrained Argo CD projects to define who may change each delivery surface. A monorepo can simplify shared discovery and review; separate repositories can provide independent access and release boundaries. Choose by those requirements rather than a universal preference. ```text platform/ bootstrap/ argocd/ addons/ clusters/ dev/ stage/ prod/ apps/ shared/ team-a/ team-b/ ``` Cloud identifiers and IAM permissions remain distinct: passing a region, VPC ID or role ARN to a chart does not establish workload authorization. Verify trust policies and the workload identity mechanism separately. A Terraform local/output object only describes metadata; an appropriate module or registration step must actually write the handoff consumed by Argo CD. Pin and inspect that implementation's version and keys. ## Sync, health and retry each need their own check [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-12) Auto-sync defines when desired state is applied. Health assessment describes observed resource condition. Sync waves order eligible resources within a sync operation; use a Namespace at an earlier wave than resources that need it, and test custom-resource health and child-Application behavior. A wave annotation on a parent Application alone is not evidence that all child workloads are ready. Keep sequencing short and inspect the installed Argo CD version's health behavior. [Sync phases and waves](https://argo-cd.readthedocs.io/en/stable/user-guide/sync-waves/); [resource health](https://argo-cd.readthedocs.io/en/stable/operator-manual/health/). A retry/backoff policy can accommodate bounded transient failures, but it does not fix a denied IAM action, invalid chart or unreachable repository. Record the actual failure, correct its cause and inspect the next operation. An NGINX demonstration Deployment is not a platform reconciliation controller; the consolidated reference does not retain that misleading example. ## Managed EKS Argo CD changes the control-plane operating model [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-13) AWS documents EKS Capability for Argo CD alongside self-managed Argo CD. Compare the actual supported authentication, cluster registration, repository access, networking, Region availability and pricing for the selected service. A self-managed Kubernetes cluster-Secret bridge must not be assumed to work unchanged with the managed capability. The ownership contract still needs explicit cloud prerequisites, delivery intent and authorization. No measured toil reduction or DevOpsDreams deployment is claimed. [AWS managed/self-managed comparison](https://docs.aws.amazon.com/eks/latest/userguide/argocd-comparison.html). For the developer-facing catalog and self-service task, use the [Backstage IDP guide](https://devopsdreams.blogspot.com/2026/03/building-internal-developer-platform-on_01252328738.html). This article covers the infrastructure-to-GitOps handoff. ## Frequently Asked Questions [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-9) **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. ## Resources [Section link](https://devopsdreams.blogspot.com/2026/03/using-terraform-gitops-bridge-modules_0735566041.html#dd-section-10) - [Amazon EKS Blueprints for Terraform: ArgoCD Getting Started](https://aws-ia.github.io/terraform-aws-eks-blueprints/patterns/gitops/gitops-getting-started-argocd/) - [Amazon EKS Blueprints for Terraform: Blue/Green Upgrade Pattern](https://aws-ia.github.io/terraform-aws-eks-blueprints/patterns/blue-green-upgrade/) - [AWS IA EKS Blueprints Addons Module](https://github.com/aws-ia/terraform-aws-eks-blueprints-addons) - [AWS IA EKS Blueprints Addon Module](https://github.com/aws-ia/terraform-aws-eks-blueprints-addon) - [GitOps Bridge Project](https://github.com/gitops-bridge-dev/gitops-bridge) - [GitOps Bridge Argo CD Bootstrap Terraform Module](https://github.com/gitops-bridge-dev/gitops-bridge-argocd-bootstrap-terraform)