416 lines
9.1 KiB
Markdown
416 lines
9.1 KiB
Markdown
---
|
|
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
|