Terraform引用另一个模块的输出,每个模块都有for_

Terraform引用另一个模块的输出,每个模块都有for_,terraform,terraform-provider-azure,Terraform,Terraform Provider Azure,我在引用另一个模块中某个模块的输出时遇到问题。第一个模块中的资源是使用for_部署的。第二个模块中的资源正在尝试引用第一个模块中的资源 创建了两个模块 安全组 虚拟机 目的是将安全组分配给VM 以下是安全组的模块 variable "configserver" { type = map(object({ name = string location = string subnet

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

创建了两个模块

  • 安全组
  • 虚拟机
  • 目的是将安全组分配给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

    output "nsg_id" {
      description = "The ID of the newly created Network Security Group"
      value       = azurerm_network_security_group.nsg.id
    }
    
    一般来说,如果没有for_,我可以像这样访问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
    }
    
    根据我的研究,很多帖子(,比如我应该能够使用每个.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)
    

    是否有其他方法引用该值?

    正如我看到的第一个问题是,您使用错误的方法引用模块
    configserver\u nsg
    中的内容作为nsg id,应该是这样的:

    nsg_id             = module.configserver_nsg[each.value.name].nsg_id
    
    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"
    }
    
    第二个问题是@Matt所说的。这是两个模块之间的周期性依赖。造成周期性依赖的是NSG规则,似乎NSG规则需要VM私有IP地址。据我所知,如果不进行更改,您无法解决周期性依赖。因此我建议您进行更改这将NSG规则与模块
    configserver\u NSG
    分开,并在两个模块之后使用资源

    最后,看起来是这样的:

    nsg_id             = module.configserver_nsg[each.value.name].nsg_id
    
    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"
    }
    

    您好。也许将for_打包为模块内部的每个逻辑是有意义的?我的意思是提供
    var.configserver
    module.configserver\u nsg
    作为模块的输入变量,并将for_分别用于
    内部的资源。/../../terraform/modules/azure linux vm”
    module。或者这种方法有问题吗?这个错误意味着你有一个循环依赖关系,你需要先解开它。@FedorPetrov不是说我们现在必须为VM和安全组创建一个单独的模块吗?请告诉我我是否理解正确。我们更希望为VM和安全组创建单独的模块,以便“这些都是可重用的。@MattSchuchard是的,正确,在查看terraform状态文件后,我看到一些依赖项,看起来依赖项调用是作为一个循环进行的,terraform正在抱怨。我不太确定如何解决这个问题。如果我不为每个循环调用其中的模块,它会起作用。我仍在研究该模块的更多更新。”estion?它解决了你的问题吗?如果它解决了你的问题,请接受它。