别再用老掉牙的方式建 VPC 了
老实说,我 2026 年还在看到有人手写一堆 aws_vpc、aws_subnet 资源,每个环境复制粘贴改 CIDR。这操作在 2020 年还算勤快,放到现在就是给自己挖坑。
上个月我们团队接手了一个遗留项目,光 VPC 相关的 Terraform 代码就 800 多行,全是裸资源。想加个新的 NAT 网关?你得手动改三个文件,还得祈祷没有手滑把路由表搞炸。结果真炸了——生产环境一个子网的路由指向了错误的网关,半夜三点被 on-call 电话叫醒。
所以我们今天聊的,不是“怎么用 Terraform 创建一个 VPC”,而是“2026 年怎么正确、省心、可维护地搞一个生产级 VPC”。
2026 年的标准答案:用社区模块
如果你还在手搓 aws_vpc 资源,建议你立刻停下来。Terraform AWS VPC 模块 (terraform-aws-modules/vpc/aws) 到现在已经迭代了 5 年多,该踩的坑社区都帮你踩过了。
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "production-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b", "us-east-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
single_nat_gateway = false # 生产环境别省这个钱,除非你想单点故障
}
这段代码干了什么?一个 VPC、6 个子网、3 个 NAT 网关、3 个路由表、Internet Gateway,外加一堆关联。手写的话至少 150 行,用模块 30 行搞定。
NAT 网关的选择:别省那点钱
模块支持三种 NAT 网关模式,我直接拿我踩过的坑说:
| 模式 | 配置 | 成本 (月) | 可靠性 | 适用场景 |
|---|---|---|---|---|
| 单 NAT | single_nat_gateway = true | ~$35 | ⚠️ 单点故障 | 开发/测试 |
| 每 AZ 一个 | one_nat_gateway_per_az = true | ~$105 | ✅ 高可用 | 生产环境 |
| 零 NAT | enable_nat_gateway = false | $0 | ❌ 私有子网无出站 | 仅内部服务 |
我们去年在 staging 环境用了单 NAT,结果那个 AZ 挂了,整个 staging 的私有子网全断网。虽然 staging 不是生产,但 CI/CD pipeline 跑了两个小时全挂在那。每 AZ 一个 NAT 网关多花的 $70,换来的是你周末不被叫起来修东西。
2026 年的新趋势:Zero Trust 接入 VPC
最近 Reddit 上有个帖子挺火,讲的是用 Cloudflare WARP + Tunnel 实现 AWS VPC 的 Zero Trust 访问。我仔细看了下,这确实是 2026 年的方向——VPN 正在被淘汰。
传统 OpenVPN 或者 WireGuard 方案的问题是:你得管理客户端证书、IP 分配、路由推送,而且一旦 VPC CIDR 变化,所有客户端配置都得更新。更别说安全问题了——一个泄露的私钥就能让攻击者直通你的内网。
Cloudflare 的方案是:WARP 客户端装在所有设备上,cloudflared tunnel 部署在 VPC 内部(ECS Fargate 或 EC2 都行),配置 split tunnel 只路由 VPC CIDR 段。每个团队通过 IdP 组控制能访问哪些 IP。
# cloudflared config.yaml
tunnel: your-tunnel-id
credentials-file: /etc/cloudflared/credentials.json
ingress:
- hostname: "*.internal.example.com"
service: https://10.0.1.100:443
- hostname: "db.internal.example.com"
service: tcp://10.0.2.50:5432
- service: http_status:404
这玩意的好处是:没有入站端口。cloudflared 只主动出站连接到 Cloudflare 的边缘网络,你的 VPC 安全组根本不需要开任何入站 SSH 或 VPN 端口。攻击者连扫描你的 VPC 入口都做不到。
模块化之后,别忘了状态管理
这是另一个我见过无数人翻车的地方。VPC 创建好了,Terraform state 放在哪?本地文件?
别。
2026 年了,Terraform state 必须用远程后端。S3 + DynamoDB 锁是标准配置,没有例外。
terraform {
backend "s3" {
bucket = "my-org-terraform-state"
key = "network/vpc/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-state-lock"
encrypt = true
}
}
这个 DynamoDB 锁表是干嘛的?防止你和同事同时跑 terraform apply 把 state 搞坏。我见过有人没配锁,两个人同时 apply,结果 state 文件损坏,整个基础设施“失忆”了——Terraform 不知道哪些资源是它创建的。
最佳实践速查表
| 实践 | 推荐做法 | 别这么做 |
|---|---|---|
| VPC 创建 | 使用社区模块 v5.x | 手写裸资源 |
| 子网规划 | 每个 AZ 至少一个公有+私有子网 | 只建一个 AZ |
| NAT 网关 | 生产环境每 AZ 一个 | 单 NAT 网关省钱 |
| 网络入口 | Cloudflare Tunnel / Zero Trust | 开放 SSH 端口 |
| State 存储 | S3 + DynamoDB 锁 | 本地文件 |
| 模块版本 | 锁定 ~> 5.0 大版本 | 用 latest |
| 标签管理 | 模块内置 tags 参数 | 手动给每个资源加标签 |
FAQ
为什么用 Terraform 模块而不是手写资源?
模块封装了最佳实践和边界情况。比如 VPC 模块自动处理了路由表关联、子网 CIDR 计算、NAT 网关依赖等问题。手写资源很容易遗漏某个路由条目或者搞错依赖顺序。
单 NAT 网关和生产环境不兼容吗?
兼容,但风险很高。单 NAT 网关部署在某个 AZ,如果那个 AZ 故障,所有私有子网的出站流量都会中断。生产环境建议每 AZ 一个 NAT 网关,或者使用 NAT 实例 + 自动恢复方案。
Cloudflare Tunnel 比传统 VPN 好在哪?
零入站端口、细粒度访问控制、与 IdP 集成、无需管理客户端证书。缺点是依赖 Cloudflare 的网络,且对非 HTTP 协议的支持有限(TCP 隧道可以,但 UDP 不行)。
Terraform state 锁的必要性是什么?
防止并发操作导致 state 文件损坏。没有锁的话,两个 terraform apply 同时执行,最后一个写入的会覆盖前一个的变更,导致资源状态不一致。
2026 年 VPC 设计有哪些新变化?
IPv6 双栈支持更成熟,VPC Lattice 开始被用于服务网格,而 Zero Trust 网络接入(如 Cloudflare Tunnel、AWS PrivateLink + Client VPN)正在取代传统的 VPN 方案。
社区灵感与参考 (References & Community Insights)
本文探讨的架构演进与技术实现方案,深度提炼自 Hacker News、Reddit 等极客社区的真实工程师讨论、线上事故复盘(Post-mortems)以及一线技术博客的实战经验分享。