---
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
