正在加载,请稍候…

使用 Terraform 实现基础设施即代码:模块、状态与最佳实践

使用 Terraform 管理云基础设施。学习模块、状态管理、工作区、远程状态、Terraform Cloud 以及团队协作的最佳实践。

使用 Terraform 实现基础设施即代码:模块、状态与最佳实践

使用 Terraform 实现基础设施即代码

项目结构

terraform/
├── environments/
│   ├── dev/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── terraform.tfvars
│   └── prod/
│       ├── main.tf
│       └── terraform.tfvars
├── modules/
│   ├── vpc/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   ├── ecs-service/
│   └── rds/
└── shared/
    └── backend.tf

使用 Terraform 实现基础设施即代码:模块、状态与最佳实践 插图

模块设计

# modules/ecs-service/main.tf
variable "name" { type = string }
variable "image" { type = string }
variable "cpu" { type = number; default = 256 }
variable "memory" { type = number; default = 512 }
variable "environment_variables" {
  type = map(string)
  default = {}
}

resource "aws_ecs_task_definition" "this" {
  family                   = var.name
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = var.cpu
  memory                   = var.memory

  container_definitions = jsonencode([{
    name  = var.name
    image = var.image
    portMappings = [{ containerPort = 3000 }]
    environment = [
      for k, v in var.environment_variables : { name = k, value = v }
    ]
    logConfiguration = {
      logDriver = "awslogs"
      options = {
        "awslogs-group"  = "/ecs/\${var.name}"
        "awslogs-region" = data.aws_region.current.name
        "awslogs-stream-prefix" = "ecs"
      }
    }
  }])
}

output "task_definition_arn" {
  value = aws_ecs_task_definition.this.arn
}

使用模块

# environments/prod/main.tf
module "api_service" {
  source = "../../modules/ecs-service"

  name   = "api-prod"
  image  = "123456789.dkr.ecr.us-east-1.amazonaws.com/api:${var.image_tag}"
  cpu    = 512
  memory = 1024

  environment_variables = {
    NODE_ENV    = "production"
    DB_HOST     = module.rds.endpoint
    REDIS_URL   = "redis://${module.redis.endpoint}:6379"
  }
}

使用 Terraform 实现基础设施即代码:模块、状态与最佳实践 插图

使用 S3 的远程状态

# backend.tf
terraform {
  backend "s3" {
    bucket         = "my-company-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-state-lock"  # 防止并发执行
  }
}

# 创建锁表
resource "aws_dynamodb_table" "terraform_lock" {
  name           = "terraform-state-lock"
  billing_mode   = "PAY_PER_REQUEST"
  hash_key       = "LockID"
  attribute { name = "LockID"; type = "S" }
}

用于环境的工作区

# 创建工作区
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod

# 切换工作区
terraform workspace select prod

# 在配置中使用
locals {
  env_config = {
    dev     = { instance_type = "t3.small"; min_count = 1; max_count = 3 }
    staging = { instance_type = "t3.medium"; min_count = 2; max_count = 5 }
    prod    = { instance_type = "t3.large"; min_count = 3; max_count = 20 }
  }
  config = local.env_config[terraform.workspace]
}

使用 Terraform 实现基础设施即代码:模块、状态与最佳实践 插图

CI/CD 集成

# .github/workflows/terraform.yml
- name: Terraform Init
  run: terraform init -backend-config="key=${{ github.ref_name }}/terraform.tfstate"

- name: Terraform Plan
  run: terraform plan -out=tfplan -var="image_tag=${{ github.sha }}"

- name: Terraform Apply (main branch only)
  if: github.ref == 'refs/heads/main'
  run: terraform apply tfplan

漂移检测

# 检测配置漂移(控制台中的手动更改)
terraform plan -detailed-exitcode
# 退出码 0:无更改
# 退出码 1:错误
# 退出码 2:发现差异(漂移!)

Terraform 模块使得跨环境和团队可复用的 DRY 基础设施代码成为可能。