Terraform未修改代码却重复应用AWS路由变更问题求助
问题分析与解决方案
核心问题1:默认路由表的IGW路由字段配置错误
你的aws_default_route_table.main资源中,错误地将互联网网关(IGW)的ID配置到了nat_gateway_id字段。IGW属于AWS标准网关类型,正确的字段应该是gateway_id。
错误代码片段:
route { cidr_block = "0.0.0.0/0" nat_gateway_id = aws_internet_gateway.ig.id }
修正后:
route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.ig.id }
这就是Terraform持续重复变更这条路由的原因——实际AWS路由表中用gateway_id存储IGW,而代码指定了错误的字段,导致状态始终不匹配。
核心问题2:私有路由表的VPN ENI路由缺失实例ID
你的10.250.0.0/23路由指向VPN实例的ENI,但AWS会自动将该ENI所属的实例ID关联到路由中。而你的Terraform代码仅指定了network_interface_id,未包含instance_id,导致Terraform每次都会尝试移除这个自动添加的实例ID,但AWS会重新补充,形成循环变更。
解决方法是在路由定义中显式添加instance_id字段,匹配AWS实际状态:
# 先添加数据源获取VPN实例ID(如果实例由AWS托管而非Terraform创建) data "aws_instance" "vpn01" { filter { name = "network-interface.id" values = [aws_network_interface.eni_vpn01.id] } } # 修正私有路由表的路由 route { cidr_block = "10.250.0.0/23" network_interface_id = aws_network_interface.eni_vpn01.id instance_id = data.aws_instance.vpn01.id }
如果VPN实例是Terraform管理的资源,直接引用实例资源的id字段即可。
次要问题:空值与空字符串的字段差异
从输出可见,Terraform状态中部分字段为null,而AWS返回的是""(空字符串),这是Terraform AWS Provider 4.x版本的兼容问题。升级到4.60+版本的Provider可缓解这类字段匹配问题,但核心解决仍需修正上述两个配置错误。
修正后的完整代码
# Routing tables to route traffic for Private Subnet resource "aws_route_table" "private" { count = var.az_count vpc_id = aws_vpc.vpc.id route { cidr_block = "0.0.0.0/0" nat_gateway_id = element(aws_nat_gateway.gw.*.id, count.index) } route { cidr_block = "10.250.0.0/23" network_interface_id = aws_network_interface.eni_vpn01.id instance_id = data.aws_instance.vpn01.id } tags = merge( { "Name" = "${var.environment}-${data.aws_availability_zones.available.names[count.index]}-rt-private" }, var.default_tags, {"eo:ops:type" = "networking"} ) } #Route for Internet Gateway resource "aws_default_route_table" "main" { default_route_table_id = aws_vpc.vpc.default_route_table_id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.ig.id } tags = merge( { "Name" = "${var.environment}-rt-public" }, var.default_tags, {"eo:ops:type" = "networking"} ) } # 数据源:通过ENI关联获取VPN实例ID data "aws_instance" "vpn01" { filter { name = "network-interface.id" values = [aws_network_interface.eni_vpn01.id] } }
执行terraform apply后,重复路由变更的问题即可解决。
内容的提问来源于stack exchange,提问作者opti2k4
相关产品推荐
相关产品推荐

