创建子网并为其分配路由表

Creating subnets and assinging rout tables to them

我是 terraform 的新手,我正在尝试创建一个具有多个子网的 VPC,并以 for 循环方式向所有这些子网添加路由 tables。

专有网络:10.207.0.0/16

number_of_subnets 将创建这样的子网:10.207.x.0/24

这段代码工作正常:

variable "region" {
  default = "us-east-1"
}

variable "availability_zone" {
  default = "us-east-1a"
}

variable "cidr_block" {
  default = "207"
}

variable "number_of_subnets" {
  default = 5
}

provider "aws" {
  region = var.region
}

resource "aws_vpc" "test_vpc" {
  cidr_block           = "10.${var.cidr_block}.0.0/16"
  instance_tenancy     = "default"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "test_vpc_${var.cidr_block}"
  }
}

resource "aws_subnet" "test_subnets" {
  count                   = var.number_of_subnets
  vpc_id                  = aws_vpc.test_vpc.id
  cidr_block              = "10.${var.cidr_block}.${count.index+1}.0/24" # start from x.x.1.0/24
  availability_zone       = var.availability_zone
  map_public_ip_on_launch = false

  tags = {
    Name = "test_subnet_${var.cidr_block}_${count.index+1}"
  }
}

现在,如果我尝试将此代码添加到同一文件的底部(所有内容都在一个名为 main.tf 的文件中)以获取子网并向每个子网添加路由 table:

# get all subnet IDs
data "aws_subnets" "q_subnets" {
  filter {
    name   = "vpc-id"
    values = [aws_vpc.test_vpc.id]
  }
}

# add route table to all subnets
resource "aws_route_table_association" "rt_assoc_subnet" {
  depends_on = [aws_subnet.test_subnets]
  for_each       = toset(data.aws_subnets.q_subnets.ids)
  subnet_id      = each.value
  route_table_id = aws_route_table.test_rt.id
}

和 运行 terraform apply 它会给出这个错误:

invalid for_each argument...
The "for_each" value depends on resource attribute that cannot be deteremined until apply,...

这没有意义。先创建vpc,再创建子网,然后获取所有子网...

我也试过depends_on但没用。

我应该如何编写才能让它发挥作用?

感谢任何帮助。

更新 1:

我尝试使用 aws_subnet.test_subnets.*.id 而不是数据,但它仍然给出依赖性错误:

variable "region" {
  default = "us-east-1"
}

variable "availability_zone" {
  default = "us-east-1a"
}

variable "cidr_block" {
  default = "207"
}

variable "number_of_subnets" {
  default = 5
}

provider "aws" {
  region = var.region
}

resource "aws_vpc" "test_vpc" {
  cidr_block           = "10.${var.cidr_block}.0.0/16"
  instance_tenancy     = "default"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "test_vpc_${var.cidr_block}"
  }
}

resource "aws_route_table" "test_rt" {
  vpc_id = aws_vpc.test_vpc.id
  route = []

  tags = {
    Name = "test_rt_${var.cidr_block}"
  }
}

resource "aws_subnet" "test_subnets" {
  count                   = var.number_of_subnets
  vpc_id                  = aws_vpc.test_vpc.id
  cidr_block              = "10.${var.cidr_block}.${count.index+1}.0/24" # start from x.x.1.0/24
  availability_zone       = var.availability_zone
  map_public_ip_on_launch = false

  tags = {
    Name = "test_subnet_${var.cidr_block}_${count.index+1}"
  }
}

output "subnets" {
    value = aws_subnet.test_subnets.*.id
}

# add route table to all subnets
resource "aws_route_table_association" "rt_assoc_subnet" {
  depends_on     = [aws_subnet.test_subnets]
  for_each       = toset(aws_subnet.test_subnets.*.id)
  subnet_id      = each.value
  route_table_id = aws_route_table.test_rt.id
}

是否有另一种方法可以将子网传递给 aws_route_table_association 而不会出现依赖性错误?

由于您正在使用 count,因此很难使 countfor_each 一起工作。最好继续使用 count 路由 table 关联。如果您决定走那条路,您唯一需要的改变是:

resource "aws_route_table_association" "rt_assoc_subnet" {
  count          = var.number_of_subnets
  subnet_id      = aws_subnet.test_subnets.*.id[count.index]
  route_table_id = aws_route_table.test_rt.id
}

这将按预期工作。但是,如果您必须使用 for_each,我建议定义一个可以在您现在使用的所有资源中与它一起使用的变量 count。如果你真的想在当前代码中使用 for_each,那么你可以使用 -target 选项 [1]:

terraform apply -target=aws_vpc.test_vpc -target=aws_route_table.test_rt -target=aws_subnet.test_subnets

当运行此命令时,命令输出中将显示:

│ Warning: Resource targeting is in effect
│
│ You are creating a plan with the -target option, which means that the result of this plan may not represent all of the changes requested by the current
│ configuration.
│
│ The -target option is not for routine use, and is provided only for exceptional situations such as recovering from errors or mistakes, or when Terraform
│ specifically suggests to use it as part of an error message.

创建目标资源后,您可以 re-run terraform apply 它应该创建路由 table 关联。


[1] https://www.terraform.io/cli/commands/plan#target-address