--- trigger: always_on --- # Infrastructure as Code Patterns ## When to Use This Skill Use this skill when: - Managing infrastructure with code - Implementing Terraform modules - Setting up GitOps workflows - Creating Kubernetes operators - Testing infrastructure changes - Managing multi-environment infrastructure - Versioning infrastructure - Automating infrastructure provisioning ## Core Concepts ### Infrastructure as Code Benefits 1. **Version Control**: Track infrastructure changes 2. **Reproducibility**: Consistent environments 3. **Automation**: Reduce manual errors 4. **Testing**: Test infrastructure changes 5. **Collaboration**: Team can review changes ### IaC Tools - **Terraform**: Infrastructure provisioning - **Kubernetes Manifests**: K8s resource definitions - **Helm**: K8s package manager - **ArgoCD/Flux**: GitOps tools ## Terraform Patterns ### Module Structure ``` infra/terraform/ ├── modules/ │ ├── kubernetes-cluster/ │ │ ├── main.tf │ │ ├── variables.tf │ │ └── outputs.tf │ ├── postgresql/ │ │ ├── main.tf │ │ ├── variables.tf │ │ └── outputs.tf │ └── redis/ │ ├── main.tf │ ├── variables.tf │ └── outputs.tf ├── environments/ │ ├── staging/ │ │ ├── main.tf │ │ └── terraform.tfvars │ └── production/ │ ├── main.tf │ └── terraform.tfvars └── shared/ └── backend.tf ``` ### Terraform Module Example ```hcl # infra/terraform/modules/postgresql/main.tf # EN: PostgreSQL module # VI: Module PostgreSQL variable "database_name" { description = "Database name" type = string } variable "environment" { description = "Environment name" type = string } resource "google_sql_database_instance" "postgres" { name = "${var.database_name}-${var.environment}" database_version = "POSTGRES_15" region = "us-central1" settings { tier = "db-f1-micro" backup_configuration { enabled = true start_time = "03:00" } } } resource "google_sql_database" "database" { name = var.database_name instance = google_sql_database_instance.postgres.name } output "connection_name" { value = google_sql_database_instance.postgres.connection_name } output "database_url" { value = "postgresql://user:pass@${google_sql_database_instance.postgres.ip_address}/${var.database_name}" sensitive = true } ``` ### Using Modules ```hcl # infra/terraform/environments/staging/main.tf # EN: Use PostgreSQL module # VI: Sử dụng module PostgreSQL module "postgresql" { source = "../../modules/postgresql" database_name = "goodgo_staging" environment = "staging" } output "database_url" { value = module.postgresql.database_url sensitive = true } ``` ## GitOps Patterns ### ArgoCD Setup ```yaml # infra/gitops/argocd/applications/user-service.yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: user-service namespace: argocd spec: project: default source: repoURL: https://github.com/goodgo/platform targetRevision: main path: deployments/production/kubernetes/user-service destination: server: https://kubernetes.default.svc namespace: production syncPolicy: automated: prune: true selfHeal: true syncOptions: - CreateNamespace=true ``` ### Flux Setup ```yaml # infra/gitops/flux/kustomizations/user-service.yaml apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 kind: Kustomization metadata: name: user-service namespace: flux-system spec: interval: 5m path: ./deployments/production/kubernetes/user-service prune: true sourceRef: kind: GitRepository name: platform-repo validation: client ``` ## Infrastructure Testing ### Terraform Testing ```bash #!/bin/bash # scripts/infra/test-terraform.sh # EN: Test Terraform changes # VI: Test các thay đổi Terraform cd infra/terraform/environments/staging # EN: Validate Terraform # VI: Validate Terraform terraform init terraform validate # EN: Plan changes # VI: Plan changes terraform plan -out=tfplan # EN: Review plan # VI: Review plan terraform show tfplan ``` ### Infrastructure Validation ```typescript // scripts/infra/validate-k8s.ts // EN: Validate Kubernetes manifests // VI: Validate Kubernetes manifests import { execSync } from 'child_process'; function validateKubernetesManifests(path: string): boolean { try { execSync(`kubectl apply --dry-run=client -f ${path}`, { stdio: 'inherit', }); console.log('Kubernetes manifests are valid'); return true; } catch (error) { console.error('Kubernetes validation failed', error); return false; } } ``` ## Environment Management ### Environment Configuration ```hcl # infra/terraform/environments/staging/terraform.tfvars environment = "staging" cluster_name = "goodgo-staging" node_count = 3 instance_type = "t3.medium" # infra/terraform/environments/production/terraform.tfvars environment = "production" cluster_name = "goodgo-production" node_count = 5 instance_type = "t3.large" ``` ### Multi-Environment Module ```hcl # infra/terraform/modules/service/main.tf variable "environment" { type = string } variable "replicas" { type = map(number) default = { staging = 2 production = 5 } } resource "kubernetes_deployment" "service" { metadata { name = "${var.service_name}-${var.environment}" } spec { replicas = var.replicas[var.environment] # ... } } ``` ## Kubernetes Operators ### Custom Resource Definition ```yaml # infra/operators/database-operator/crd.yaml apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: databases.example.com spec: group: example.com versions: - name: v1 served: true storage: true schema: openAPIV3Schema: type: object properties: spec: type: object properties: databaseName: type: string environment: type: string ``` ## Best Practices 1. **Version Control**: Keep all infrastructure in version control 2. **Modules**: Create reusable Terraform modules 3. **Testing**: Test infrastructure changes before applying 4. **GitOps**: Use GitOps for Kubernetes deployments 5. **Environment Isolation**: Separate environments completely 6. **State Management**: Use remote state backends 7. **Secrets**: Never commit secrets, use secrets managers ## Common Mistakes 1. **Committing Secrets**: Exposed credentials ```hcl # ❌ BAD: Hardcoded secrets password = "my-secret-password" # ✅ GOOD: Use variables + secrets manager password = var.db_password # From env or secrets manager ``` 2. **No Remote State**: State conflicts in team ```hcl # ❌ BAD: Local state # (no backend config) # ✅ GOOD: Remote state terraform { backend "s3" { bucket = "terraform-state" key = "staging/terraform.tfstate" } } ``` 3. **No State Locking**: Concurrent modifications ```hcl # ✅ Enable state locking backend "s3" { dynamodb_table = "terraform-locks" } ``` 4. **Applying Without Plan Review**: Unexpected changes ```bash # ❌ BAD: Direct apply terraform apply # ✅ GOOD: Plan first, review, then apply terraform plan -out=tfplan terraform show tfplan # Review terraform apply tfplan ``` ## Quick Reference | Tool | Purpose | State | |------|---------|-------| | **Terraform** | Cloud resources | Stateful | | **Kubernetes** | Container orchestration | Declarative | | **Helm** | K8s package manager | Template | | **ArgoCD/Flux** | GitOps deployment | Git-synced | **Terraform Commands:** ```bash terraform init # Initialize terraform validate # Validate syntax terraform plan # Preview changes terraform apply # Apply changes terraform destroy # Remove resources terraform state list # List state resources ``` **Module Structure:** ``` modules/service/ ├── main.tf # Resources ├── variables.tf # Input variables ├── outputs.tf # Output values └── README.md # Documentation ``` **Environment Pattern:** ``` environments/ ├── staging/ │ ├── main.tf │ └── terraform.tfvars └── production/ ├── main.tf └── terraform.tfvars ``` **GitOps Workflow:** ``` Git Push → CI Validates → ArgoCD Syncs → K8s Applied │ Auto-heal if drift ``` **Best Practices Checklist:** - [ ] Remote state backend configured - [ ] State locking enabled - [ ] No secrets in code - [ ] Modules for reusable components - [ ] Environment-specific tfvars - [ ] PR review for all changes ## Resources - [Terraform Documentation](https://www.terraform.io/docs) - [ArgoCD Documentation](https://argo-cd.readthedocs.io/) - [Flux Documentation](https://fluxcd.io/docs/) - [Deployment Kubernetes](../deployment-kubernetes/SKILL.md) - K8s patterns - [Project Rules](../project-rules/SKILL.md) - GoodGo standards