添加VPC对等连接路由后Terraform重复更新aws_route_table问题
嘿,我碰到过一模一样的糟心事!同一账户下多VPC peering配置路由,明明初始配置正常,可每次跑terraform plan或apply都提示要更新路由表,完全摸不着头脑对吧?咱们一步步来排查解决:
先搞清楚到底是什么在触发变更
先仔细看terraform plan的输出,定位到那个被标记为要更新的路由规则。你大概率会看到类似这样的内容:
~ resource "aws_route_table" "your_rt" { id = "rtb-xxxxxx" # 其他不变的字段... ~ route { ~ gateway_id = "pcx-xxxxxx" -> "pcx-xxxxxx" # 看起来值完全一样,但Terraform硬说要改 destination_cidr_block = "10.0.0.0/16" } }
这种情况要么是参数用错了,要么是模块输出的变量有问题,咱们一个个来排查。
最容易踩的坑:用错了路由目标字段
VPC peering的路由规则,Terraform里必须用vpc_peering_connection_id字段,而不是gateway_id!很多人会搞混这俩:
gateway_id是给Internet Gateway、NAT Gateway这类网关用的- 指向VPC peering的路由,得专门用
vpc_peering_connection_id来指定peering连接的ID
如果之前你错误地写了gateway_id = module.xxx.peering_id,AWS API返回的实际路由信息里gateway_id其实是空的,Terraform每次都会试图把它设成peering ID,直接导致无限循环更新。赶紧改成下面这样:
resource "aws_route_table" "your_rt" { vpc_id = aws_vpc.your_vpc.id route { destination_cidr_block = var.remote_vpc_cidr # 这里用正确的字段! vpc_peering_connection_id = module.peering_module.vpc_peering_connection_id } }
检查模块输出的变量是否稳定
如果字段用对了还是有问题,那得看看那个来自其他模块的peering ID是不是“不稳定”:
- 先看模块的输出定义,是不是输出的是peering连接的ID而不是ARN?模块里应该这么写才对:
output "vpc_peering_connection_id" { value = aws_vpc_peering_connection.this.id }
要是输出的是ARN(比如arn:aws:ec2:.../pcx-xxxxxx),那你引用的时候得提取ID部分:
vpc_peering_connection_id = element(split("/", module.peering_module.vpc_peering_connection_arn), 1)
- 要是模块输出的是敏感值,Terraform会显示
(sensitive value),但内部比较是正常的。如果实在担心,可以用nonsensitive()函数(Terraform 0.14+支持)来包装引用:
vpc_peering_connection_id = nonsensitive(module.peering_module.vpc_peering_connection_id)
动态生成路由?确保迭代顺序稳定
如果是用dynamic "route"块批量生成路由,那要注意迭代的集合是稳定的。别用普通列表(顺序可能莫名变化),而是用以目标CIDR为键的映射,这样Terraform只会关注每个路由的内容,而不是顺序:
resource "aws_route_table" "your_rt" { vpc_id = aws_vpc.your_vpc.id dynamic "route" { # 用目标CIDR作为唯一键,避免顺序变化触发更新 for_each = { for r in var.routes : r.destination_cidr_block => r } content { destination_cidr_block = route.key vpc_peering_connection_id = route.value.peering_id } } }
最后,同步状态排除漂移
如果以上都没问题,那可能是状态文件和实际AWS资源不一致。跑一下terraform refresh同步状态,然后再执行terraform plan,应该就不会有假变更了。
内容的提问来源于stack exchange,提问作者Kerry Knopp

