Terraform基础设施即代码多环境配置管理与模块化实践

Terraform多环境管理的核心挑战

当团队使用Terraform管理基础设施时,开发、测试、预发、生产等多套环境的配置管理是绕不开的难题。不同环境使用不同的VPC、子网、实例规格和参数值,但底层资源结构高度一致。如何在保证环境隔离的同时避免配置代码大量重复,是Terraform多环境管理的核心问题。Terraform提供了workspaces、目录隔离、模块化+变量文件三种主流方案,各有适用场景。

方案一Workspaces工作空间隔离环境状态

Terraform Workspaces通过在同一代码目录下维护多套state文件来实现环境隔离。每个workspace对应一个独立的state,切换workspace即可在不同环境中操作。这种方式代码量最少,但隐式依赖关系容易导致误操作。

# 创建和切换workspace
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod

terraform workspace select dev

# 在代码中引用workspace名称
resource "aws_instance" "app" {
  ami           = var.ami_id
  instance_type = terraform.workspace == "prod" ? "m5.xlarge" : "t3.medium"
  
  tags = {
    Environment = terraform.workspace
  }
}

Workspaces方案的问题在于:同一个代码目录的变量文件只能有一份,环境差异需要通过terraform.workspace条件判断或variable默认值处理。当环境差异较大时,代码中充斥着三目运算符和条件分支,可维护性急剧下降。Workspaces适合环境差异小(仅规模不同)的场景,不适合环境间有架构差异的情况。

方案二目录隔离各环境独立代码目录

目录隔离方案为每个环境创建独立的Terraform代码目录,各环境完全独立。这种方式最直观,但会导致大量代码重复。标准做法是通过共享模块(shared modules)消除重复,各环境目录仅存放backend配置和变量文件。

# 项目目录结构
infra/
├── modules/
│   ├── vpc/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   ├── ecs/
│   └── rds/
├── environments/
│   ├── dev/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── terraform.tfvars
│   │   └── backend.tf
│   ├── staging/
│   └── prod/

# environments/dev/main.tf
module "vpc" {
  source     = "../../modules/vpc"
  cidr_block = var.vpc_cidr
  env        = "dev"
}

module "ecs" {
  source       = "../../modules/ecs"
  vpc_id       = module.vpc.vpc_id
  subnet_ids   = module.vpc.private_subnet_ids
  instance_type = var.ecs_instance_type
  desired_count = var.ecs_desired_count
  env          = "dev"
}

方案三模块化与变量文件组合

这是大型团队最推荐的方案。将所有基础设施组件抽象为可复用模块,环境差异全部收敛到变量文件中。核心代码只维护一份,通过不同变量值驱动不同环境的资源创建。每个环境的目录只包含一个main.tf(调用模块)、变量定义和backend配置。

# environments/dev/terraform.tfvars
vpc_cidr          = "10.0.0.0/16"
ecs_instance_type = "t3.medium"
ecs_desired_count = 2
rds_instance_class = "db.t3.medium"
rds_multi_az      = false
enable_nat_gateway = false

# environments/prod/terraform.tfvars
vpc_cidr          = "10.1.0.0/16"
ecs_instance_type = "m5.xlarge"
ecs_desired_count = 10
rds_instance_class = "db.r6g.xlarge"
rds_multi_az      = true
enable_nat_gateway = true

Remote Backend多环境状态隔离配置

生产环境必须使用远程Backend存储state文件,避免本地state丢失和团队协作冲突。S3+DynamoDB是AWS环境的标准方案,多环境的state通过workspace key前缀或独立bucket实现隔离。

# environments/dev/backend.tf
terraform {
  backend "s3" {
    bucket         = "terraform-state-dev"
    key            = "infra/dev/terraform.tfstate"
    region         = "cn-north-1"
    encrypt        = true
    dynamodb_table = "terraform-lock-dev"
  }
}

# environments/prod/backend.tf
terraform {
  backend "s3" {
    bucket         = "terraform-state-prod"
    key            = "infra/prod/terraform.tfstate"
    region         = "cn-north-1"
    encrypt        = true
    dynamodb_table = "terraform-lock-prod"
  }
}

state文件包含敏感信息(数据库密码、安全组规则),S3 bucket必须启用版本控制和加密,并通过bucket policy限制访问源IP和IAM角色。DynamoDB表用于state locking,防止并发操作导致state损坏。

模块版本管理与发布流程

共享模块需要有明确的版本管理策略。模块代码变更后,各环境不能自动拉取最新代码,而是通过版本标签显式引用。Git标签是最常见的模块版本管理方式。

# 通过Git标签引用模块版本
module "vpc" {
  source = "git::https://github.com/org/terraform-modules.git//vpc?ref=v2.3.0"
}

# 或通过Terraform Registry
module "vpc" {
  source  = "registry.terraform.io/org/vpc/aws"
  version = "~> 2.3"
}

模块版本升级流程建议:开发环境先升级到新版本验证,预发环境跟随,生产环境最后。任何模块版本变更都需要走代码评审流程。生产环境的模块版本应该锁定精确版本号,避免语义版本前缀导致意外升级。

CI/CD流水线集成Terraform自动化部署

Terraform操作应该通过CI/CD流水线执行,而非人工在本地执行。流水线的标准阶段包括:init -> plan -> 人工审批(仅prod环境) -> apply。plan的输出作为审批依据,apply执行实际变更。

# GitHub Actions示例
name: Terraform Deploy
on:
  push:
    paths:
      - 'environments/prod/**'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
      - name: Terraform Init
        run: terraform init
        working-directory: environments/prod
      - name: Terraform Plan
        run: terraform plan -out=tfplan
        working-directory: environments/prod
      - name: Terraform Apply
        if: github.ref == 'refs/heads/main'
        run: terraform apply -auto-approve tfplan
        working-directory: environments/prod

生产环境的apply操作必须配置审批门禁,plan输出中会显示资源变更明细(+创建、-删除、~修改),审批人需要仔细审查是否有意外删除操作。drift detection(配置偏移检测)也应纳入流水线,定期执行terraform plan检测运行状态与声明配置是否一致。

敏感变量管理与安全实践

Terraform变量文件中可能包含数据库密码、API密钥等敏感信息,这些值不应该硬编码在tfvars文件中。标准做法是使用Vault或云厂商的密钥管理服务(AWS SSM Parameter Store、AWS Secrets Manager)动态注入敏感值。

# 从AWS SSM Parameter Store读取数据库密码
data "aws_ssm_parameter" "db_password" {
  name            = "/prod/database/password"
  with_decryption = true
}

module "rds" {
  source      = "../../modules/rds"
  db_password = data.aws_ssm_parameter.db_password.value
}

Terraform state文件中默认会明文存储所有变量值,包括敏感值。模块的output中标记sensitive = true可以阻止CLI输出显示敏感值,但state文件中仍然是明文。因此state文件的访问控制至少与密钥管理系统同等严格。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/terraform-ji-chu-she-shi-ji-dai-ma-duo-huan-jing-pei-zhi/

(0)
小编小编
上一篇 15小时前
下一篇 15小时前

相关推荐