Production-ready Infrastructure as Code patterns for AWS, GCP, and Azure using Crossplane and Terraform.
Most multi-cloud examples are either:
- Too simple (a single VM with no real-world applicability)
- Too complex (enterprise frameworks that take weeks to understand)
- Missing the WHY (just code, no architectural decisions documented)
This repository provides battle-tested patterns with:
- Clear documentation of trade-offs
- Side-by-side comparison of Crossplane vs Terraform
- Architectural Decision Records (ADRs) for every major choice
- Real-world examples you can actually use
multi-cloud-iac-patterns/
├── aws/
│ ├── crossplane/ # Crossplane compositions & claims
│ └── terraform/ # Equivalent Terraform modules
├── gcp/
│ ├── crossplane/
│ └── terraform/
├── azure/
│ ├── crossplane/
│ └── terraform/
├── docs/
│ ├── adrs/ # Architectural Decision Records
│ ├── diagrams/ # Architecture diagrams
│ └── comparisons/ # Crossplane vs Terraform analysis
└── examples/ # Ready-to-use examples
| Pattern | AWS | GCP | Azure | Status |
|---|---|---|---|---|
| Network Foundation (VPC/VNet) | [ ] | [ ] | [ ] | Planned |
| Compute (VM/Instance) | [ ] | [ ] | [ ] | Planned |
| Managed Kubernetes | [ ] | [ ] | [ ] | Planned |
| Object Storage | [ ] | [ ] | [ ] | Planned |
| Managed Database (RDS/CloudSQL/Azure SQL) | [ ] | [ ] | [ ] | Planned |
| Serverless Functions | [ ] | [ ] | [ ] | Planned |
TL;DR: Neither is universally better. Each has trade-offs.
- Native Kubernetes API (if you already live in K8s)
- Continuous reconciliation (infrastructure drift is auto-corrected)
- No state file management headaches
- GitOps-friendly by design
- Reconciliation can be dangerous if not understood
- Steeper learning curve for non-K8s teams
- Debugging is harder than Terraform
- Smaller community and fewer examples
- Mature ecosystem with massive community
- Predictable plan/apply workflow
- Easier debugging and state inspection
- Works without Kubernetes
- State file management is a pain at scale
- Drift detection requires extra tooling
- Not truly declarative (imperative workflow)
Full analysis: docs/comparisons/crossplane-vs-terraform.md
- Kubernetes cluster (local: kind/minikube, or managed: EKS/GKE/AKS)
- kubectl configured
- Crossplane installed (installation guide)
- Cloud provider credentials configured as Kubernetes secrets
- Terraform >= 1.5
- Cloud provider CLI configured (aws, gcloud, az)
- Backend configured for state (S3, GCS, or Azure Storage)
# 1. Install Crossplane (if not already)
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm install crossplane crossplane-stable/crossplane -n crossplane-system --create-namespace
# 2. Install AWS Provider
kubectl apply -f aws/crossplane/provider.yaml
# 3. Configure credentials
kubectl apply -f aws/crossplane/provider-config.yaml
# 4. Deploy a pattern (e.g., VPC)
kubectl apply -f aws/crossplane/network/vpc-claim.yaml
# 5. Check status
kubectl get vpccd aws/terraform/network
# 1. Initialize
terraform init
# 2. Review plan
terraform plan
# 3. Apply
terraform applyEvery significant decision is documented:
- ADR-001: Why Crossplane as primary IaC
- ADR-002: Network architecture pattern
- ADR-003: Kubernetes cluster configuration
Contributions are welcome! Please read CONTRIBUTING.md first.
MIT License - See LICENSE for details.
Manuel Pirez
- GitHub: @manpirez
- LinkedIn: Manuel Pirez
- Blog: manpirez.com
"The best infrastructure code is the one that's understood, not just the one that works."