GitOps with ArgoCD: Separating IaC from Application Config
Why Separate IaC from Application Config?
One of the most common mistakes I see in GitOps implementations is mixing infrastructure definitions with application configuration in the same ArgoCD application. This creates a tangled dependency graph where a Terraform change can trigger an application redeployment, or vice versa.
At my current role, I designed a pattern that cleanly separates these concerns.
The Two-Application Pattern
Application 1: Infrastructure (IaC)
This ArgoCD application manages:
- Terraform-provisioned resources (referenced via state)
- Cluster-level configurations (namespaces, RBAC, network policies)
- Shared infrastructure (ingress controllers, cert-manager, external-dns)
- Monitoring stack deployment
Application 2: Application Configuration
This ArgoCD application manages:
- Helm releases for application workloads
- Environment-specific ConfigMaps and Secrets
- HPA and PDB configurations
- Service mesh configurations
Repository Structure
gitops-repo/
├── infrastructure/
│ ├── base/
│ │ ├── namespaces.yaml
│ │ ├── rbac.yaml
│ │ └── network-policies.yaml
│ └── overlays/
│ ├── staging/
│ └── production/
├── applications/
│ ├── app-a/
│ │ ├── base/
│ │ └── overlays/
│ └── app-b/
│ ├── base/
│ └── overlays/
└── argocd/
├── infra-app.yaml
└── apps-app.yaml
CI/CD Pipeline Integration
The Jenkins pipeline I built has clear separation between CI and CD:
- CI Stage: Build, test, scan (Snyk/Trivy), push image
- CD Stage: Update Helm values in the GitOps repo, ArgoCD syncs automatically
This means developers push code, the CI pipeline validates and builds, and ArgoCD handles the deployment — no manual kubectl commands, no direct cluster access needed.
Key Takeaways
- Separation of concerns reduces blast radius of changes
- Different sync policies for infra (manual) vs apps (auto-sync)
- Clear ownership — platform team owns infra, dev teams own app configs
- Audit trail — every change is a git commit with a clear author and reason
GitOps isn’t just about storing manifests in git. It’s about designing a workflow that gives teams confidence in their deployments while maintaining operational safety.