最后审核时间:2026年5月
使用原生 Terraform 构建 ANS-C01 考试中的 AWS 服务——每次构建一个代码块,并紧扣考试领域。相同的代码可在 OpenTofu 上运行。
到本实验结束时,您将使用纯 Terraform 预置经典的 AWS 多 VPC 骨干网络——在同一区域中的两个双栈(IPv4 + IPv6)VPC,通过 Transit Gateway 连接,并带有显式路由表关联,以及在主 VPC 上启用由 CloudWatch 支持的 VPC 流日志,以便您能实际看到网络中传输的内容。这是所有 ANS-C01 多 VPC 问题所假定的架构。
所有资源都是纯 Terraform。将代码片段放入一个 main.tf 文件中,运行 terraform init,然后逐步运行 terraform apply。
>= 1.5 或 OpenTofu >= 1.6。us-east-1 区域配置好身份验证的 AWS CLI。本实验大部分内容是廉价或免费的,但 Transit Gateway 不是:
TGW 每小时费用是本实验的主要开销。两个附件 × $0.05/小时 × 24 小时 × 30 天 ≈ 运行时每月 $72。探索完成后请立即销毁——TGW 是任何 ANS-C01 实验中最大的成本陷阱。
标准开头。Transit Gateway 是区域性的——所有附件都必须位于 TGW 所在的区域。对于跨区域连接,您需要添加 TGW 对等连接(v1 范围之外)。我们默认使用 us-east-1。
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.60"
}
}
}
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
Project = "certlabpro-ans-c01"
ManagedBy = "terraform"
}
}
}
data "aws_availability_zones" "available" {
state = "available"
}ANS-C01 专门测试双栈 VPC——如果您设置 assign_generated_ipv6_cidr_block = true,AWS 现在默认会为每个新 VPC 分配一个 IPv6 /56 CIDR 块。考试的“网络设计”领域既测试 IPv4 CIDR 规划数学(如果需要对等连接或连接到 TGW,则使用不重叠的 /16 CIDR 块),也测试 IPv6 子网派生(每个子网从 VPC 的 /56 中划分出一个 /64)。
我们分配 IPv4 10.0.0.0/16 和一个 AWS 自动生成的 IPv6 /56。这里的单个子网使用一个 /24 IPv4 块和一个从 VPC 的 /56 中划分出的 /64 IPv6 块——cidrsubnet 是 Terraform 内置的用于此计算的函数。在现代 AWS 区域中,互联网网关默认是双栈的。
resource "aws_vpc" "primary" {
cidr_block = "10.0.0.0/16"
assign_generated_ipv6_cidr_block = true
enable_dns_hostnames = true
tags = { Name = "certlabpro-ans-c01-primary" }
}
resource "aws_subnet" "primary_a" {
vpc_id = aws_vpc.primary.id
cidr_block = "10.0.1.0/24"
ipv6_cidr_block = cidrsubnet(aws_vpc.primary.ipv6_cidr_block, 8, 1)
availability_zone = data.aws_availability_zones.available.names[0]
assign_ipv6_address_on_creation = true
tags = { Name = "certlabpro-ans-c01-primary-a" }
}
resource "aws_internet_gateway" "primary" {
vpc_id = aws_vpc.primary.id
}我们在 10.1.0.0/16 处构建第二个 VPC——故意不与 VPC #1 的 10.0.0.0/16 重叠。ANS-C01 强调这一设计规则,因为一旦您想连接两个 VPC(对等连接、TGW 或任何其他方式),AWS API 层就会禁止重叠的 CIDR。您无法将流量路由到本地也声明的 CIDR。
VPC #2 也会获得自己的 AWS 自动生成的 IPv6 /56(每个 VPC 都获得一个全局唯一的块,因此默认情况下没有 IPv6 重叠的风险)。子网划分的计算方式与步骤 2 相同。
resource "aws_vpc" "secondary" {
cidr_block = "10.1.0.0/16"
assign_generated_ipv6_cidr_block = true
enable_dns_hostnames = true
tags = { Name = "certlabpro-ans-c01-secondary" }
}
resource "aws_subnet" "secondary_a" {
vpc_id = aws_vpc.secondary.id
cidr_block = "10.1.1.0/24"
ipv6_cidr_block = cidrsubnet(aws_vpc.secondary.ipv6_cidr_block, 8, 1)
availability_zone = data.aws_availability_zones.available.names[0]
assign_ipv6_address_on_creation = true
tags = { Name = "certlabpro-ans-c01-secondary-a" }
}Transit Gateway 是中心。它可以扩展到数千个 VPC 附件,通过 AWS Resource Access Manager (RAM) 支持跨账户共享,并为您提供一个单一的路由表进行推理,而不是 N² 个对等连接。ANS-C01 考试会在问题提及“超过三个 VPC”或“随着我们网络的发展”时,反复测试这种中心辐射型架构而非 VPC 对等连接的选择。
我们创建 TGW 时,默认路由表关联和传播是禁用的——这是 ANS-C01 更常测试的模式,因为它强制您明确哪些附件填充哪些路由表。自动关联是便捷设置;手动设置则是审计友好的设置。
附件资源是每个 VPC 的桥梁。连接两个 VPC 后,TGW 了解两者的 CIDR;我们仍然需要从每个 VPC 的主路由表添加指向 TGW 的路由(步骤 5)。
resource "aws_ec2_transit_gateway" "hub" {
description = "certlabpro-ans-c01 hub"
default_route_table_association = "disable"
default_route_table_propagation = "disable"
multicast_support = "disable"
tags = { Name = "certlabpro-ans-c01-tgw" }
}
resource "aws_ec2_transit_gateway_route_table" "main" {
transit_gateway_id = aws_ec2_transit_gateway.hub.id
tags = { Name = "certlabpro-ans-c01-tgw-rt" }
}
resource "aws_ec2_transit_gateway_vpc_attachment" "primary" {
transit_gateway_id = aws_ec2_transit_gateway.hub.id
vpc_id = aws_vpc.primary.id
subnet_ids = [aws_subnet.primary_a.id]
transit_gateway_default_route_table_association = false
transit_gateway_default_route_table_propagation = false
}
resource "aws_ec2_transit_gateway_vpc_attachment" "secondary" {
transit_gateway_id = aws_ec2_transit_gateway.hub.id
vpc_id = aws_vpc.secondary.id
subnet_ids = [aws_subnet.secondary_a.id]
transit_gateway_default_route_table_association = false
transit_gateway_default_route_table_propagation = false
}
resource "aws_ec2_transit_gateway_route_table_association" "primary" {
transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.primary.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.main.id
}
resource "aws_ec2_transit_gateway_route_table_association" "secondary" {
transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.secondary.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.main.id
}
resource "aws_ec2_transit_gateway_route_table_propagation" "primary" {
transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.primary.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.main.id
}
resource "aws_ec2_transit_gateway_route_table_propagation" "secondary" {
transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.secondary.id
transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.main.id
}步骤 4 中的 TGW 知道两个 VPC,但每个 VPC 自己的路由表仍然不知道如何访问另一个 VPC。我们在两个方向上都添加了显式路由:VPC #1 的路由表将 10.1.0.0/16 流量发送到 TGW,反之亦然。考试反复测试这种双向要求——“我将两者都连接到 TGW,为什么它们不能 ping 通?”几乎总是缺少返回路径路由。
最后,VPC 流日志。ANS-C01 的“网络监控”领域将其作为查看实际通过网络的数据包的唯一方式进行测试——包括已接受、已拒绝和仅元数据(5 元组 + 字节 + 数据包 + 结果)。我们为主 VPC 开启了流日志,日志流向一个专用的 CloudWatch 日志组。我们附加的 IAM 角色是流日志写入日志组时所扮演的角色。
路由到位且流日志运行后,骨干网络就完成了。两个双栈 VPC,通过 TGW 连接,具有显式(审计友好)路由,并在主侧提供数据包级别的可见性。ANS-C01 的所有其他模式(Direct Connect Gateway、TGW 对等连接、NAT、PrivateLink、VPC 端点)都以此基础进行连接。
resource "aws_route" "primary_to_secondary" {
route_table_id = aws_vpc.primary.main_route_table_id
destination_cidr_block = "10.1.0.0/16"
transit_gateway_id = aws_ec2_transit_gateway.hub.id
depends_on = [aws_ec2_transit_gateway_vpc_attachment.primary]
}
resource "aws_route" "secondary_to_primary" {
route_table_id = aws_vpc.secondary.main_route_table_id
destination_cidr_block = "10.0.0.0/16"
transit_gateway_id = aws_ec2_transit_gateway.hub.id
depends_on = [aws_ec2_transit_gateway_vpc_attachment.secondary]
}
# ── VPC Flow Logs ─────────────────────────────────────────────
resource "aws_cloudwatch_log_group" "vpc_flow" {
name = "/aws/vpc-flow/certlabpro-ans-c01-primary"
retention_in_days = 30
}
resource "aws_iam_role" "vpc_flow" {
name = "certlabpro-ans-c01-vpc-flow"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "vpc-flow-logs.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy" "vpc_flow" {
name = "write-flow-logs"
role = aws_iam_role.vpc_flow.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
]
Resource = aws_cloudwatch_log_group.vpc_flow.arn
}]
})
}
resource "aws_flow_log" "primary" {
vpc_id = aws_vpc.primary.id
traffic_type = "ALL"
log_destination_type = "cloud-watch-logs"
log_destination = aws_cloudwatch_log_group.vpc_flow.arn
iam_role_arn = aws_iam_role.vpc_flow.arn
max_aggregation_interval = 60
}terraform destroy 会销毁本实验中的所有内容,但请注意顺序——Transit Gateway 附件需要 5–10 分钟才能分离,并且 TGW 本身在所有附件完全删除之前无法删除。terraform destroy 会正确处理依赖图,但操作并不快。不要在销毁过程中 Ctrl-C,否则您最终会得到一半分离的附件,必须通过控制台手动清理。
尽快销毁的最大原因是TGW 每小时费用——两个附件每个 $0.05/小时 = 总计每月 $72。如果您忘记它正在运行,实验费用会迅速累积。
ANS-C01 涵盖了本实验无法容纳的网络方面——Direct Connect(没有物理端口无法进行测试)、AWS Site-to-Site VPN(需要客户侧端点)、用于混合 DNS 的 Route 53 Resolver 入站/出站端点、PrivateLink + VPC 端点服务、AWS Network Firewall、AWS Global Accelerator、Route 53 健康检查 + 故障转移、Network Access Analyzer、Reachability Analyzer、Transit Gateway 对等连接(跨区域)、Cloud WAN、AWS App Mesh 以及 BGP 特定场景(路由过滤、预置、AS-PATH 操作)。
我们坚持多 VPC 骨干网络架构,因为它是考试中测试最多的单一架构——Direct Connect 附件、VPN 隧道、混合 DNS 和 PrivateLink 都以此类 TGW 中心为基础。掌握好中心辐射型架构;辐条类型是其扩展。
对于未预置的方面,此认证页面的 浏览、手册 和 Editorial 部分提供了概念性覆盖。一个后续实验,如果增加 Route 53 Resolver + VPN 附件 + PrivateLink,将完善混合网络的叙述。