Files
pos-system/.agent/rules/infrastructure-as-code.md

9.1 KiB

trigger
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

# 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

# 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

# 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

# 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

#!/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

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

# 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

# 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

# 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

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

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

    # ✅ Enable state locking
    backend "s3" {
      dynamodb_table = "terraform-locks"
    }
    
  4. Applying Without Plan Review: Unexpected changes

    # ❌ 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:

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