Я новичок в терраформировании и пытаюсь создать VPC с несколькими подсетями и добавляю таблицы маршрутов ко всем этим подсетям в цикле for.
ВПК: 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), чтобы получить подсети и добавить таблицу маршрутов для каждой:
# 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
и не помогло.
Как бы я написал это, чтобы заставить его работать?
Любая помощь приветствуется.
Я пытался использовать 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
без получения ошибки зависимости?
Кстати, они находятся в одном каталоге/корневом модуле/модуле? Я имею в виду подсети, а также таблицу маршрутизации?
Вы можете избежать использования источника данных? И перейти напрямую aws_subnet.test_subnets
к for_each
метааргументу
@DaniloCacace Проблема в том, что подсети были созданы с помощью count
, не так ли?
@MarkoE Я думал, что проблема заключается в for_each в источнике данных, потому что в документации говорится, что «значение for_each должно быть известно до того, как Terraform выполнит какие-либо действия с удаленными ресурсами».
Да, это одна часть проблемы, я думаю, что вторая часть заключается в том, что подсети используют таблицу счетчиков и маршрутов для каждой, поэтому оба должны быть исправлены, IMO.
Я попытался создать модуль для aws_route_table_association
, но он все равно выдает ту же ошибку. Есть ли другой способ получить цикл for?
Да, но это зависит от того, что вы хотите сделать. Это разные модули, один и тот же модуль?
Они были в одном файле, main.tf. Я также пытался отделить aws_route_table_association
в модуле, но все равно выдает ту же ошибку. Я думаю, было бы лучше, если бы это было в том же файле.
Я добавил раздел Update1 в первый пост с новым main.tf (один файл), который все еще дает ошибку зависимости. Есть ли другой способ передать подсети в aws_route_table_association без получения ошибки зависимости?
Поскольку вы используете count
, очень сложно заставить count
работать с for_each
. Было бы лучше продолжать использовать count
для ассоциации с таблицей маршрутов. Если вы решите пойти по этому пути, единственное изменение, которое вам нужно, это:
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.
После создания целевых ресурсов вы можете повторно запустить terraform apply
, и он должен создать ассоциации таблицы маршрутов.
[1] https://www.terraform.io/cli/commands/plan#целевой-адрес
Чем много. Это очень полезно. :)
Пожалуйста, примите ответ, если он решит вашу проблему.
Вот как работает
for_each
, значения должны быть известны заранее: terraform.io/language/meta-arguments/…