docs(iac): enforce single source of truth for infrastructure
Add IaC practice section to coding-standards.md: - All infrastructure state via Terraform or Helm (never ad-hoc scripts) - Clear division: Terraform owns helm releases/namespaces/storage/state - Anti-pattern: split bucket definitions across multiple files - Bootstrap-only exception: document one-time setup with rationale Rationale: prevents state drift, credential duplication, and unclear ownership.
This commit is contained in:
@@ -70,6 +70,59 @@ set:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Infrastructure as Code (IaC) — Single Source of Truth
|
||||||
|
|
||||||
|
**Core principle:** All infrastructure state must be declaratively managed via Terraform or Helm (via helmfile + Terraform). No ad-hoc scripts, manual kubectl, or side-by-side resource definitions.
|
||||||
|
|
||||||
|
### Terraform + Helm Division of Labor
|
||||||
|
|
||||||
|
- **Terraform manages:**
|
||||||
|
- Helm releases (chart + version + values)
|
||||||
|
- Namespaces
|
||||||
|
- StorageClasses
|
||||||
|
- Static Kubernetes resources (RBAC, NetworkPolicies, IngressClasses)
|
||||||
|
- Cloud infrastructure (Vault, S3 backends, secrets)
|
||||||
|
- State persistence (S3 backend in MinIO)
|
||||||
|
|
||||||
|
- **Helmfile manages:**
|
||||||
|
- Chart release ordering via `needs:`
|
||||||
|
- Environment-specific value interpolation (Go templating, not shell)
|
||||||
|
- Hook workflows (pre/post-sync orchestration)
|
||||||
|
- **Never use helmfile for one-off bucket creation, job runs, or manual setup** — those belong in Terraform or a documented bootstrap process
|
||||||
|
|
||||||
|
- **Kubernetes manifests (`k8s/`) manage:**
|
||||||
|
- ArgoCD applications (single source of truth for GitOps)
|
||||||
|
- Service definitions that ArgoCD syncs
|
||||||
|
- **Never manage app objects (Deployments, StatefulSets) directly** — let helm + ArgoCD own them
|
||||||
|
|
||||||
|
### Anti-Pattern: Ad-Hoc Resource Creation
|
||||||
|
|
||||||
|
❌ **Bad:** Separate `minio-buckets.tf` using `aws_s3_bucket` resources + post-deploy scripts
|
||||||
|
- Split responsibility: some buckets in Terraform, others in helmfile, others manual
|
||||||
|
- State drift: unclear what's managed where
|
||||||
|
- Credential duplication: secrets in multiple places
|
||||||
|
|
||||||
|
✅ **Good:** Single source in `minio.tf` helm release:
|
||||||
|
```hcl
|
||||||
|
buckets = [
|
||||||
|
{ name = "terraform-state", policy = "none", purge = false },
|
||||||
|
{ name = "vault", policy = "none", purge = false },
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
|
- One place to define, one place to audit
|
||||||
|
- Credentials in variables + Vault, not scattered
|
||||||
|
- TF state tracks all changes
|
||||||
|
|
||||||
|
### When to Break the Rule
|
||||||
|
|
||||||
|
Only when **explicitly documented**:
|
||||||
|
- Bootstrap scripts (one-time cluster init) — commit to `scripts/` with clear "run once" warning
|
||||||
|
- Temporary debugging (never leave in git) — stash or delete before committing
|
||||||
|
- Manual steps for constraint (e.g., "create namespace before ArgoCD bootstraps") — document in `TROUBLESHOOTING.md` with rationale
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## YAML & ConfigMap/Secret Patterns
|
## YAML & ConfigMap/Secret Patterns
|
||||||
|
|
||||||
### Secret Field Naming
|
### Secret Field Naming
|
||||||
|
|||||||
Reference in New Issue
Block a user