【问题标题】:Terraform referencing output from another module with for_eachTerraform 使用 for_each 引用另一个模块的输出
【发布时间】:2021-03-21 21:20:33
【问题描述】:

我在引用另一个模块中的一个模块的输出时遇到问题。第一个模块中的资源是使用 for_each 部署的。第二个模块中的资源正在尝试引用第一个模块中的资源

创建了 2 个模块

  1. 安全组
  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 的 id

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
}

根据我的研究,一些帖子(hereherehere 说我应该能够使用 each.key 遍历地图

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)

还有其他方法可以引用该值吗?

【问题讨论】:

  • 嗨。也许将 for_each 逻辑打包在模块中是有意义的?我的意思是提供var.configservermodule.configserver_nsg 作为模块的输入变量,而不是使用for_each 作为"../../../terraform/modules/azure-linux-vm" 模块内部的资源。还是这种方法有问题?
  • 这个错误意味着你有一个循环依赖,你需要先解开。
  • @FedorPetrov 这是否意味着我们现在必须为 VM 和安全组创建一个模块?让我知道我是否理解正确。我们希望为 VM 和安全组提供单独的模块,以便它们可重用。
  • @MattSchuchard 是的,是的,在查看 terraform 状态文件后,我看到了一些依赖项,看起来依赖项调用正在作为 terraform 抱怨的循环进行。我不太确定如何解决这个问题。如果我不在 for_each 循环中调用模块,它会起作用。还在研究中
  • 关于这个问题还有更多更新吗?它解决了你的问题吗?如果解决了您的问题,请采纳。

标签: terraform terraform-provider-azure


【解决方案1】:

我看到第一个问题是您使用错误的方式引用模块 configserver_nsg 中的内容作为 NSG id,应该是这样的:

nsg_id             = module.configserver_nsg[each.value.name].nsg_id

@Matt 已经提到了第二个问题。这是两个模块之间的循环依赖。造成循环依赖的东西是 NSG 规则,似乎 NSG 规则需要 VM 私有 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"
}

【讨论】:

    猜你喜欢
    • 2021-03-07
    • 2021-03-31
    • 1970-01-01
    • 2022-07-11
    • 2021-08-26
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    相关资源
    最近更新 更多