3. IaC工具选型与工程环境搭建

在 AWS 上做网络基础设施即代码,第一步不是写 VPC,而是决定“用哪把锤子”。Terraform、AWS CDK 和 CloudFormation 都能把 VPC、子网、路由表、安全组、Transit Gateway 等网络资源声明成代码,但它们的抽象层次、状态管理方式、语言生态和团队协作模型差异很大。选错工具,后期往往要付出迁移成本;选对工具,网络拓扑的迭代、审查和回滚都会顺畅得多。

三种工具的本质差异

CloudFormation 是 AWS 原生的声明式模板服务,模板用 JSON 或 YAML 编写,由 AWS 托管栈状态。它的优势是与 AWS 服务同步最快、无需自建状态后端、天然支持 StackSets 做多账号多区域部署;代价是模板冗长、缺乏真正的编程抽象,复杂网络里大量重复的 CIDR、AZ 和标签容易写错。

Terraform 是 HashiCorp 的声明式工具,使用 HCL 语言,通过 Provider 管理多云资源。它的核心特征是显式状态文件(state),状态记录资源与真实世界的映射,因此必须规划远程后端(如 S3 + DynamoDB 锁)。Terraform 的模块化、for_each、动态块和 plan 预览,让大规模网络代码更易复用和审查。

AWS CDK 则是“用编程语言生成 CloudFormation”的框架,支持 TypeScript、Python、Java 等。它把 VPC、子网等封装成构造块(Construct),用循环、条件、类型检查来生成模板,最终仍由 CloudFormation 部署。CDK 适合已有强编程能力的团队,但引入了一层抽象,调试时需理解合成后的模板。

三种 IaC 工具的抽象层次与状态归属 AWS CDK TypeScript / Python 代码 Construct 抽象(Vpc、Subnet) 合成 CloudFormation 模板 状态由 CloudFormation 托管 CloudFormation JSON / YAML 模板 Resources / Parameters / Outputs Stack 为单位部署 状态由 AWS 托管,无需自建 Terraform HCL 声明式配置 Provider + Resource + Module plan / apply 两阶段 状态自管:S3 + DynamoDB 锁 选型关键维度对比 维度 AWS CDK CloudFormation Terraform 语言 TS/Python/Java JSON/YAML HCL 状态管理 CFN 托管 CFN 托管 自建远程后端 多云能力 仅 AWS 仅 AWS 多云 适合团队 强编程能力 AWS 原生运维 平台/网络工程

选型判断:从网络工程的实际约束出发

如果团队只使用 AWS,且希望把网络资源与账号基线、组织策略一起管理,CloudFormation 的 StackSets 和原生漂移检测很有吸引力。但网络代码往往需要大量参数化——比如按环境生成不同数量的子网、按 AZ 动态分配 CIDR——这时 Terraform 的 for_each 和模块化更自然。CDK 则适合已经用 TypeScript 写应用、希望网络与应用栈共享类型和构造块的团队。

一个实用的判断顺序是:先看是否需要多云或混合云,是则选 Terraform;再看团队是否愿意维护状态后端和 HCL 技能,否则 CloudFormation 更省心;最后看是否已有强编程栈和 CDK 经验,是则可选 CDK。对于本课程后续的网络实验,我们以 Terraform 为主线,因为它对 VPC、子网、路由、Transit Gateway 的表达最直观,且 plan 预览能清晰展示网络变更。

安装与配置:以 Terraform 为例

在 macOS 上可用 Homebrew 安装,在 Linux 上建议用官方 apt 源或直接下载二进制。安装后先验证版本,再配置 AWS 凭证。推荐使用 AWS CLI 的命名 profile,而不是把密钥写进代码。

# 安装(Ubuntu 示例)
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | \
  sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
  https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
  sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install -y terraform

# 验证
terraform version

# 配置 AWS 凭证(使用命名 profile)
aws configure --profile network-iac
# 输入 Access Key、Secret Key、默认区域 ap-southeast-1、输出格式 json

# 让 Terraform 使用该 profile
export AWS_PROFILE=network-iac
aws sts get-caller-identity

如果使用 CDK,则需要 Node.js 和 AWS CDK CLI:npm install -g aws-cdk,然后 cdk bootstrap 在目标账号区域创建引导栈。CloudFormation 无需本地安装,直接用 AWS CLI 的 aws cloudformation deploy 即可。

版本控制与项目结构

网络 IaC 的仓库必须做到“代码、状态配置、环境参数”三者分离。推荐目录结构如下,以 Terraform 为例:

network-iac/
├── modules/
│   ├── vpc/                 # 可复用 VPC 模块
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── tgw-attachment/      # Transit Gateway 挂载模块
├── environments/
│   ├── dev/
│   │   ├── main.tf          # 调用模块,传入 dev 参数
│   │   ├── backend.tf       # S3 后端 + DynamoDB 锁
│   │   └── terraform.tfvars
│   └── prod/
│       ├── main.tf
│       ├── backend.tf
│       └── terraform.tfvars
├── .gitignore               # 忽略 .terraform/、*.tfstate、*.tfvars(敏感)
└── README.md

远程后端配置示例:

# environments/dev/backend.tf
terraform {
  backend "s3" {
    bucket         = "my-network-iac-state"
    key            = "dev/network.tfstate"
    region         = "ap-southeast-1"
    dynamodb_table = "network-iac-lock"
    encrypt        = true
  }
}

注意:terraform.tfvars 若含敏感值不应提交;状态文件必须加密并开启版本控制。分支策略上,建议 main 对应生产,功能分支通过 Pull Request 触发 terraform plan,合并后再由 CI 执行 apply,避免本地直接操作生产。

选型没有绝对最优:小团队单账号可先用 CloudFormation 快速起步;网络规模扩大、需要模块复用时再迁移到 Terraform。关键是先把状态管理和目录结构定好,再写第一行 VPC 代码。