Создание подсетей и присвоение им таблиц маршрутизации

Я новичок в терраформировании и пытаюсь создать 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 и не помогло.

Как бы я написал это, чтобы заставить его работать?

Любая помощь приветствуется.

ОБНОВЛЕНИЕ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 без получения ошибки зависимости?

Вот как работает for_each, значения должны быть известны заранее: terraform.io/language/meta-arguments/…

Marko E 22.03.2022 11:09

Кстати, они находятся в одном каталоге/корневом модуле/модуле? Я имею в виду подсети, а также таблицу маршрутизации?

Marko E 22.03.2022 11:11

Вы можете избежать использования источника данных? И перейти напрямую aws_subnet.test_subnets к for_each метааргументу

Danilo Cacace 22.03.2022 11:48

@DaniloCacace Проблема в том, что подсети были созданы с помощью count, не так ли?

Marko E 22.03.2022 12:20

@MarkoE Я думал, что проблема заключается в for_each в источнике данных, потому что в документации говорится, что «значение for_each должно быть известно до того, как Terraform выполнит какие-либо действия с удаленными ресурсами».

Danilo Cacace 22.03.2022 13:58

Да, это одна часть проблемы, я думаю, что вторая часть заключается в том, что подсети используют таблицу счетчиков и маршрутов для каждой, поэтому оба должны быть исправлены, IMO.

Marko E 22.03.2022 14:44

Я попытался создать модуль для aws_route_table_association, но он все равно выдает ту же ошибку. Есть ли другой способ получить цикл for?

Amin Persia 22.03.2022 19:21

Да, но это зависит от того, что вы хотите сделать. Это разные модули, один и тот же модуль?

Marko E 22.03.2022 19:30

Они были в одном файле, main.tf. Я также пытался отделить aws_route_table_association в модуле, но все равно выдает ту же ошибку. Я думаю, было бы лучше, если бы это было в том же файле.

Amin Persia 22.03.2022 19:33

Я добавил раздел Update1 в первый пост с новым main.tf (один файл), который все еще дает ошибку зависимости. Есть ли другой способ передать подсети в aws_route_table_association без получения ошибки зависимости?

Amin Persia 22.03.2022 20:44
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
10
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку вы используете 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#целевой-адрес

Чем много. Это очень полезно. :)

Amin Persia 23.03.2022 02:30

Пожалуйста, примите ответ, если он решит вашу проблему.

Marko E 23.03.2022 07:22

Другие вопросы по теме