Terraform 使用 for_each 引用另一个模块的输出 [英] Terraform referencing output from another module with for_each
问题描述
我在引用另一个模块中的一个模块的输出时遇到问题.第一个模块中的资源是使用 for_each 部署的.第二个模块中的资源正在尝试引用第一个模块中的资源
I am having trouble referencing an output from a module in another module. The resources in the first module was deployed using for_each. The resources in the second module is trying to reference the resources from first module
创建了 2 个模块
- 安全组
- 虚拟机
目的是将安全组分配给虚拟机
The intention is to assign the Security Group to the VM
以下是安全组的模块
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 的 id
The security group module source has an output file which outputs the id of the 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
Generally, if there isn't a for_each, I could access the nsg_id like this
module.configserver_nsg.id
到目前为止这很好,现在问题是我无法从另一个模块访问 nsg_id
So far this is good, now the issue is that I am not able to access the nsg_id from another module
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
}
根据我的研究,一些帖子(这里,这里,这里说我应该能够使用 each.key 然而
Based on my research these, a number of posts (here, here, here say I should be able to loop through the map using each.key however
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)
还有其他方法可以引用该值吗?
Is there any other way to reference the value?
推荐答案
我看到的第一个问题是您使用错误的方式从模块 configserver_nsg
引用 NSG id 的内容,应该是这样的:
As I see the first problem is that you use the wrong way to quote the things from the module configserver_nsg
for the NSG id, it should be like this:
nsg_id = module.configserver_nsg[each.value.name].nsg_id
@Matt 已经提到了第二个问题.这是两个模块之间的循环依赖.造成循环依赖的东西是 NSG 规则,似乎 NSG 规则需要 VM 私有 IP 地址.据我所知,如果不进行更改,就无法解决循环依赖问题.因此,我建议您进行更改,将 NSG 规则与模块 configserver_nsg
分开,并使用资源 azurerm_network_security_rule
而不是这两个模块之后.
And the second problem has been said by @Matt. It's a cyclical dependency between the two modules. The thing that makes the cyclical dependency is the NSG rule, it seems the NSG rule needs the VM private IP address. According to my knowledge, you cannot solve the cyclical dependency if you do not make a change. So I recommend you make a change that separates the NSG rule from the module configserver_nsg
and use the resource azurerm_network_security_rule
instead after the two modules.
最后,它看起来像这样:
And finally, it seems like this:
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"
}
这篇关于Terraform 使用 for_each 引用另一个模块的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!