9.1 KiB
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
- Version Control: Track infrastructure changes
- Reproducibility: Consistent environments
- Automation: Reduce manual errors
- Testing: Test infrastructure changes
- 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
- Version Control: Keep all infrastructure in version control
- Modules: Create reusable Terraform modules
- Testing: Test infrastructure changes before applying
- GitOps: Use GitOps for Kubernetes deployments
- Environment Isolation: Separate environments completely
- State Management: Use remote state backends
- Secrets: Never commit secrets, use secrets managers
Common Mistakes
-
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 -
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" } } -
No State Locking: Concurrent modifications
# ✅ Enable state locking backend "s3" { dynamodb_table = "terraform-locks" } -
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
- Terraform Documentation
- ArgoCD Documentation
- Flux Documentation
- Deployment Kubernetes - K8s patterns
- Project Rules - GoodGo standards