我有以下复杂的地形模块
vpc.tf
resource "aws_vpc" "main_vpc" {
cidr_block = var.vpc_range
enable_dns_support = true
enable_dns_hostnames = true
}
resource "aws_internet_gateway" "main_vpc_gateway" {
vpc_id = aws_vpc.main_vpc.id
}
resource "aws_subnet" "main_subnets" {
vpc_id = aws_vpc.main_vpc.id
for_each = { for cidr_data in local.subnet_cidr_range: cidr_data.subnet_name => cidr_data }
cidr_block = each.value.subnet_cidr
availability_zone_id = each.value.subnet_az_id
map_public_ip_on_launch = each.value.is_public
}
resource "aws_route_table" "subnet_route_tables" {
vpc_id = aws_vpc.main_vpc.id
for_each = { for cidr_data in local.subnet_cidr_range: cidr_data.subnet_name => cidr_data }
}
resource "aws_route_table_association" "subnet_route_table_associations" {
for_each = { for route_table_association_details in local.route_table_association_details: route_table_association_details.subnet_name => route_table_association_details }
subnet_id = each.value.subnet_id
route_table_id = each.value.route_table_id
}
resource "aws_route" "vpc_default_gateway" {
route_table_id = aws_vpc.main_vpc.main_route_table_id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main_vpc_gateway.id
}
resource "aws_route" "subnet_internet_gateway" {
for_each = { for details in local.created_subnet_details: details.subnet_name => details if details.is_public }
route_table_id = each.value.route_table_id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main_vpc_gateway.id
}
resource "aws_nat_gateway" "vpc_gateways" {
for_each = { for nat_details in local.private_nat_gateway_details: nat_details.availability_zone => nat_details }
depends_on = [ aws_internet_gateway.main_vpc_gateway ]
allocation_id = lookup(lookup(data.aws_eip.nat_gateway_ips, each.value.availability_zone, ""), "id", "")
subnet_id = each.value.nat_public_subnet_details.subnet_id
}
resource "aws_route" "subnet_nat_gateway" {
for_each = { for details in local.created_subnet_details: details.subnet_name => details if !details.is_public && details.subnet_type != "pvt_internal_privileged" }
route_table_id = each.value.route_table_id
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = lookup(lookup(aws_nat_gateway.vpc_gateways, each.value.availability_zone, ""), "id", "")
}
data.tf
data "aws_availability_zones" "all_azs" {
state = "available"
}
data "aws_eip" "nat_gateway_ips" {
for_each = var.nat_gateway_ips
public_ip = each.value
}
locals.tf
locals {
subnet_id_map = zipmap(data.aws_availability_zones.all_azs.names, data.aws_availability_zones.all_azs.zone_ids)
subnet_cidr_range = flatten([
for each_subnet in var.all_subnets : [
for each_az in each_subnet.azs : {
subnet_type = each_subnet.name
subnet_az = each_az.name
subnet_cidr = each_az.range
subnet_name = "${replace(each_az.name, "-", "_")}_${each_subnet.name}"
subnet_az_id = local.subnet_id_map[each_az.name]
is_public = length(regexall("^pub.*", each_subnet.name)) > 0
}
]
])
created_subnet_details = ([
for each_subnet in local.subnet_cidr_range : {
subnet_name = each_subnet.subnet_name
is_public = each_subnet.is_public
subnet_type = each_subnet.subnet_type
subnet_cidr = each_subnet.subnet_cidr
subnet_id = lookup(lookup(aws_subnet.main_subnets, each_subnet.subnet_name, {}), "id", "")
route_table_id = lookup(lookup(aws_route_table.subnet_route_tables, each_subnet.subnet_name, {}), "id", "")
availability_zone = each_subnet.subnet_az
}
])
created_subnet_map = { for details in local.created_subnet_details: details.subnet_name => details }
route_table_association_details = ([
for each_subnet in local.subnet_cidr_range : {
subnet_id = lookup(lookup(aws_subnet.main_subnets, each_subnet.subnet_name, {}), "id", "")
route_table_id = lookup(lookup(aws_route_table.subnet_route_tables, each_subnet.subnet_name, {}), "id", "")
subnet_name = each_subnet.subnet_name
}
])
# Retrive distinct AZs we want the nat gateways in
private_nat_gateway_azs = distinct([
for details in local.created_subnet_details: details.availability_zone if !details.is_public && details.subnet_type != "pvt_internal_privileged"
])
private_nat_gateway_details = ([
for details in local.private_nat_gateway_azs: {
availability_zone = details
nat_public_subnet_details = lookup(local.created_subnet_map, "${replace(details, "-", "_")}_pub_apps_cust", "")
}
])
}
variables.tf
variable "region" {
type = string
}
variable "vpc_range" {
type = string
}
variable "all_subnets" {}
variable "cluster" {
type = string
}
variable "nat_gateway_ips" {
type = map
}
variable "sensitive_nat_gateway_ips" {
type = map
}
outputs.tf
output "created_subnet_details" {
value = { for details in local.created_subnet_details: details.subnet_name => details }
}
output "vpc_details" {
value = aws_vpc.main_vpc
}
并调用这个模块
root.tf
module "vpc-sa-east-1" {
source = "../../../modules/vpc"
providers = {
aws = aws.sa-east-1
}
region = "sa-east-1"
cluster = ""
vpc_range = "10.73.0.0/16"
nat_gateway_ips = {}
sensitive_nat_gateway_ips = {}
all_subnets = [ {
name: "pub_apps_cust",
azs: [{
name: "sa-east-1a"
range: "10.73.164.0/25"
}, {
name: "sa-east-1b"
range: "10.73.164.128/25"
}]
}]
}
当我尝试在 all_subnets
变量中添加一个新的数组元素并运行 terraform plan
时,它显示它将强制替换 subnet
和 route table
,这将固有地尝试替换route
和 route table association
module "vpc-sa-east-1" {
source = "../../../modules/vpc"
providers = {
aws = aws.sa-east-1
}
region = "sa-east-1"
cluster = ""
vpc_range = "10.73.0.0/16"
nat_gateway_ips = {}
sensitive_nat_gateway_ips = {}
all_subnets = [ {
name: "pub_apps_cust",
azs: [{
name: "sa-east-1a"
range: "10.73.164.0/25"
}, {
name: "sa-east-1b"
range: "10.73.164.128/25"
}]
},
{
name: "pub_apps_internal",
azs: [{
name: "sa-east-1a"
range: "10.73.165.0/25"
}, {
name: "sa-east-1b"
range: "10.73.165.128/25"
}]
}
]
}
module.vpc-sa-east-1.data.aws_availability_zones.all_azs: Refreshing state...
module.vpc-sa-east-1.aws_vpc.main_vpc: Refreshing state... [id=vpc-03290a49cb9a5f386]
module.vpc-sa-east-1.aws_internet_gateway.main_vpc_gateway: Refreshing state... [id=igw-0c347532f77a6d3f1]
module.vpc-sa-east-1.aws_route_table.subnet_route_tables["sa_east_1a_pub_apps_cust"]: Refreshing state... [id=rtb-09007bf313da448a7]
module.vpc-sa-east-1.aws_route_table.subnet_route_tables["sa_east_1b_pub_apps_cust"]: Refreshing state... [id=rtb-02a9db11897c33a60]
module.vpc-sa-east-1.aws_subnet.main_subnets["sa_east_1a_pub_apps_cust"]: Refreshing state... [id=subnet-03e76a75c4657f8c3]
module.vpc-sa-east-1.aws_subnet.main_subnets["sa_east_1b_pub_apps_cust"]: Refreshing state... [id=subnet-002840ae3c5946fe8]
module.vpc-sa-east-1.aws_route.vpc_default_gateway: Refreshing state... [id=r-rtb-0bd35615cda8a41381080289494]
module.vpc-sa-east-1.aws_route_table_association.subnet_route_table_associations["sa_east_1a_pub_apps_cust"]: Refreshing state... [id=rtbassoc-0ff404ba7fb15473f]
module.vpc-sa-east-1.aws_route_table_association.subnet_route_table_associations["sa_east_1b_pub_apps_cust"]: Refreshing state... [id=rtbassoc-07309d0b46df5a8e3]
module.vpc-sa-east-1.aws_route.subnet_internet_gateway["sa_east_1b_pub_apps_cust"]: Refreshing state... [id=r-rtb-02a9db11897c33a601080289494]
module.vpc-sa-east-1.aws_route.subnet_internet_gateway["sa_east_1a_pub_apps_cust"]: Refreshing state... [id=r-rtb-09007bf313da448a71080289494]
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
-/+ destroy and then create replacement
Terraform will perform the following actions:
# module.vpc-sa-east-1.aws_route.subnet_internet_gateway["sa_east_1a_pub_apps_cust"] must be replaced
-/+ resource "aws_route" "subnet_internet_gateway" {
destination_cidr_block = "0.0.0.0/0"
+ destination_prefix_list_id = (known after apply)
+ egress_only_gateway_id = (known after apply)
gateway_id = "igw-0c347532f77a6d3f1"
~ id = "r-rtb-09007bf313da448a71080289494" -> (known after apply)
+ instance_id = (known after apply)
+ instance_owner_id = (known after apply)
+ nat_gateway_id = (known after apply)
+ network_interface_id = (known after apply)
~ origin = "CreateRoute" -> (known after apply)
~ route_table_id = "rtb-09007bf313da448a7" -> (known after apply) # forces replacement
~ state = "active" -> (known after apply)
}
# module.vpc-sa-east-1.aws_route.subnet_internet_gateway["sa_east_1a_pub_apps_internal"] will be created
+ resource "aws_route" "subnet_internet_gateway" {
+ destination_cidr_block = "0.0.0.0/0"
+ destination_prefix_list_id = (known after apply)
+ egress_only_gateway_id = (known after apply)
+ gateway_id = "igw-0c347532f77a6d3f1"
+ id = (known after apply)
+ instance_id = (known after apply)
+ instance_owner_id = (known after apply)
+ nat_gateway_id = (known after apply)
+ network_interface_id = (known after apply)
+ origin = (known after apply)
+ route_table_id = (known after apply)
+ state = (known after apply)
}
# module.vpc-sa-east-1.aws_route.subnet_internet_gateway["sa_east_1b_pub_apps_cust"] must be replaced
-/+ resource "aws_route" "subnet_internet_gateway" {
destination_cidr_block = "0.0.0.0/0"
+ destination_prefix_list_id = (known after apply)
+ egress_only_gateway_id = (known after apply)
gateway_id = "igw-0c347532f77a6d3f1"
~ id = "r-rtb-02a9db11897c33a601080289494" -> (known after apply)
+ instance_id = (known after apply)
+ instance_owner_id = (known after apply)
+ nat_gateway_id = (known after apply)
+ network_interface_id = (known after apply)
~ origin = "CreateRoute" -> (known after apply)
~ route_table_id = "rtb-02a9db11897c33a60" -> (known after apply) # forces replacement
~ state = "active" -> (known after apply)
}
# module.vpc-sa-east-1.aws_route.subnet_internet_gateway["sa_east_1b_pub_apps_internal"] will be created
+ resource "aws_route" "subnet_internet_gateway" {
+ destination_cidr_block = "0.0.0.0/0"
+ destination_prefix_list_id = (known after apply)
+ egress_only_gateway_id = (known after apply)
+ gateway_id = "igw-0c347532f77a6d3f1"
+ id = (known after apply)
+ instance_id = (known after apply)
+ instance_owner_id = (known after apply)
+ nat_gateway_id = (known after apply)
+ network_interface_id = (known after apply)
+ origin = (known after apply)
+ route_table_id = (known after apply)
+ state = (known after apply)
}
# module.vpc-sa-east-1.aws_route_table.subnet_route_tables["sa_east_1a_pub_apps_internal"] will be created
+ resource "aws_route_table" "subnet_route_tables" {
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ route = (known after apply)
+ vpc_id = "vpc-03290a49cb9a5f386"
}
# module.vpc-sa-east-1.aws_route_table.subnet_route_tables["sa_east_1b_pub_apps_internal"] will be created
+ resource "aws_route_table" "subnet_route_tables" {
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ route = (known after apply)
+ vpc_id = "vpc-03290a49cb9a5f386"
}
# module.vpc-sa-east-1.aws_route_table_association.subnet_route_table_associations["sa_east_1a_pub_apps_cust"] must be replaced
-/+ resource "aws_route_table_association" "subnet_route_table_associations" {
~ id = "rtbassoc-0ff404ba7fb15473f" -> (known after apply)
~ route_table_id = "rtb-09007bf313da448a7" -> (known after apply)
~ subnet_id = "subnet-03e76a75c4657f8c3" -> (known after apply) # forces replacement
}
# module.vpc-sa-east-1.aws_route_table_association.subnet_route_table_associations["sa_east_1a_pub_apps_internal"] will be created
+ resource "aws_route_table_association" "subnet_route_table_associations" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.vpc-sa-east-1.aws_route_table_association.subnet_route_table_associations["sa_east_1b_pub_apps_cust"] must be replaced
-/+ resource "aws_route_table_association" "subnet_route_table_associations" {
~ id = "rtbassoc-07309d0b46df5a8e3" -> (known after apply)
~ route_table_id = "rtb-02a9db11897c33a60" -> (known after apply)
~ subnet_id = "subnet-002840ae3c5946fe8" -> (known after apply) # forces replacement
}
# module.vpc-sa-east-1.aws_route_table_association.subnet_route_table_associations["sa_east_1b_pub_apps_internal"] will be created
+ resource "aws_route_table_association" "subnet_route_table_associations" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.vpc-sa-east-1.aws_subnet.main_subnets["sa_east_1a_pub_apps_internal"] will be created
+ resource "aws_subnet" "main_subnets" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = (known after apply)
+ availability_zone_id = "sae1-az2"
+ cidr_block = "10.73.165.0/25"
+ id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = true
+ owner_id = (known after apply)
+ vpc_id = "vpc-03290a49cb9a5f386"
}
# module.vpc-sa-east-1.aws_subnet.main_subnets["sa_east_1b_pub_apps_internal"] will be created
+ resource "aws_subnet" "main_subnets" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = (known after apply)
+ availability_zone_id = "sae1-az1"
+ cidr_block = "10.73.165.128/25"
+ id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = true
+ owner_id = (known after apply)
+ vpc_id = "vpc-03290a49cb9a5f386"
}
Plan: 12 to add, 0 to change, 4 to destroy.
当没有数组索引问题时,我无法弄清楚为什么要重新创建子网和路由表。
`