У меня возникли проблемы со ссылкой на вывод из модуля в другом модуле. Ресурсы в первом модуле были развернуты с помощью for_each. Ресурсы во втором модуле пытаются ссылаться на ресурсы из первого модуля.
Создано 2 модуля
Цель состоит в том, чтобы назначить группу безопасности для виртуальной машины.
Ниже приведен модуль для группы безопасности.
variable "configserver" {
type = map(object({
name = string
location = string
subnet = string
availability_zone = string
vm_size = string
hdd_size = string
}))
}
module "configserver_nsg" {
for_each = var.configserver
source = "../../../terraform/modules/azure-network-security-group"
resource_group_name = var.resource_group_name
tags = var.tags
location = each.value.location
nsg_name = "${each.value.name}-nsg"
security_rules = [
{
name = "Office",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_ranges = [
"22"]
source_address_prefix = "192.168.1.100"
destination_address_prefixes = [
module.configserver_vm[each.key].private_ip
]
},
{
name = "Deny-All-Others"
priority = 4096
direction = "Inbound"
access = "Deny"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
}
]
}
// Value
configserver = {
config1 = {
name = "config1"
location = "eastus"
subnet = "services"
availability_zone = 1
vm_size = "Standard_F2s_v2"
hdd_size = 30
}
}
Источник модуля группы безопасности имеет выходной файл, который выводит идентификатор nsg.
output "nsg_id" {
description = "The ID of the newly created Network Security Group"
value = azurerm_network_security_group.nsg.id
}
Как правило, если for_each отсутствует, я мог бы получить доступ к nsg_id следующим образом.
module.configserver_nsg.id
Пока это хорошо, теперь проблема в том, что я не могу получить доступ к nsg_id из другого модуля.
module "configserver_vm" {
for_each = var.configserver
source = "../../../terraform/modules/azure-linux-vm"
resource_group = module.resource_group.name
ssh_public_key = var.ssh_public_key
tags = var.tags
vm_name = each.value.name
location = each.value.location
subnet_id = each.value.subnet
availability-zones = each.value.availability_zone
vm_size = each.value.vm_size
hdd-size = each.value.hdd_size
nsg_id = module.configserver_nsg[each.key].nsg_id
}
Основываясь на моих исследованиях, в ряде сообщений (здесь , здесь , здесь говорится, что я должен иметь возможность перебирать карту, используя каждый ключ, однако
nsg_id = module.configserver_nsg[each.key].nsg_id
это вызывает ошибку
Error: Cycle: module.configserver_nsg (close), module.configserver_vm.var.nsg_id (expand), module.configserver_vm.azurerm_network_interface_security_group_association.this, module.configserver_vm (close), module.configserver_nsg.var.security_rules (expand), module.configserver_nsg.azurerm_network_security_group.nsg, module.configserver_nsg.output.nsg_id (expand)
Есть ли другой способ сослаться на значение?
Ошибка подразумевает, что у вас есть циклическая зависимость, которую вам нужно сначала распутать.
@FedorPetrov Разве это не означает, что теперь нам нужно создать единый модуль для виртуальной машины и группы безопасности? Дайте мне знать, правильно ли я понимаю это. Мы бы предпочли иметь отдельные модули для виртуальных машин и групп безопасности, чтобы их можно было использовать повторно.
@MattSchuchard да, верно, после просмотра файла состояния terraform я вижу некоторую зависимость, и похоже, что вызов зависимости идет как цикл, на который жалуется terraform. Я не совсем уверен, как справиться с этим. Это работает, если я не вызываю модуль в цикле for_each. Все еще смотрю на это
Есть ли еще обновления по этому вопросу? Это решает вашу проблему? Если это решит вашу проблему, пожалуйста, примите это.
Как я вижу, первая проблема заключается в том, что вы используете неправильный способ цитирования вещей из модуля configserver_nsg
для идентификатора NSG, это должно быть так:
nsg_id = module.configserver_nsg[each.value.name].nsg_id
И вторая проблема была упомянута @Matt. Это циклическая зависимость между двумя модулями. Вещь, которая создает циклическую зависимость, — это правило NSG, кажется, что для правила NSG требуется частный IP-адрес виртуальной машины. Насколько мне известно, вы не можете решить циклическую зависимость, если не вносите изменения. Поэтому я рекомендую вам внести изменение, отделяющее правило NSG от модуля configserver_nsg
, и вместо этого использовать ресурс azurerm_network_security_rule после двух модулей.
И, наконец, это выглядит так:
variable "configserver" {
type = map(object({
name = string
location = string
subnet = string
availability_zone = string
vm_size = string
hdd_size = string
}))
}
module "configserver_nsg" {
for_each = var.configserver
source = "../../../terraform/modules/azure-network-security-group"
resource_group_name = var.resource_group_name
tags = var.tags
location = each.value.location
nsg_name = "${each.value.name}-nsg"
security_rules = [
{
},
{
name = "Deny-All-Others"
priority = 4096
direction = "Inbound"
access = "Deny"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
}
]
}
// Value
configserver = {
config1 = {
name = "config1"
location = "eastus"
subnet = "services"
availability_zone = 1
vm_size = "Standard_F2s_v2"
hdd_size = 30
}
}
module "configserver_vm" {
for_each = var.configserver
source = "../../../terraform/modules/azure-linux-vm"
resource_group = module.resource_group.name
ssh_public_key = var.ssh_public_key
tags = var.tags
vm_name = each.value.name
location = each.value.location
subnet_id = each.value.subnet
availability-zones = each.value.availability_zone
vm_size = each.value.vm_size
hdd-size = each.value.hdd_size
nsg_id = module.configserver_nsg[each.value.name].nsg_id
}
resource "azurerm_network_security_rule" "configserver_nsg" {
for_each = var.configserver
name = "Office",
priority = "100"
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_ranges = ["22"]
source_address_prefix = "192.168.1.100"
destination_address_prefixes = [
module.configserver_vm[each.key].private_ip
]
resource_group_name = var.resource_group_name
network_security_group_name = "${each.value.name}-nsg"
}
Привет, почему не module.configserver_nsg[each.key].nsg_id
, а module.configserver_nsg[each.value.name].nsg_id
? Я не понимаю, почему на модуль ссылаются по имени, а не по ключу.
Привет. Может есть смысл запаковать логику for_each внутрь модуля? Я имею в виду предоставить
var.configserver
иmodule.configserver_nsg
в качестве входных переменных для модуля и вместо этого использовать for_each для ресурсов внутри модуля"../../../terraform/modules/azure-linux-vm"
. Или есть проблема с этим подходом?