将多个输出传递到 Terraform 中的不同模块

pass multiple outputs to a different module in Terraform

我试图将每个部分都作为模块来涵盖,而不是将其保存在单个 main.tf 文件中。
我的意图是创建 1 个 vnet (TESTVNET)、多个子网、每个子网的 NIC。

我可以在我的 Vnet 中创建多个子网。我正在寻找的是如何将子网 ID 传递给 NETWORKINTERFACE 模块。请在下面找到我的代码;

Main.tf

resource "azurerm_resource_group" "resource_group" {
  name     = var.RGname
  location = var.RGlocation
}

module "VNET" {
  source              = "./Modules/NetworkConfig"
  name                = var.VNETname
  address_space       = var.address_space
  location            = var.RGlocation
  resource_group_name = azurerm_resource_group.resource_group.name
}

module "SUBNETS" {
  source               = "./Modules/SubnetConfig"
  Subnetlist           = var.Subnetlist
  virtual_network_name = module.VNET.vnet_name
  resource_group_name  = azurerm_resource_group.resource_group.name
  depends_on           = [azurerm_resource_group.resource_group, module.VNET.vnet]

}

module "NETWORKINTERFACE" {
  source              = "./Modules/NIConfig"
  niclist             = var.niclist
  resource_group_name = azurerm_resource_group.resource_group.name
  location            = azurerm_resource_group.resource_group.location

SUBNET.tf

resource "azurerm_subnet" "SUBNETS" {
for_each=var.Subnetlist
name=each.value.name
address_prefixes=[each.value.address]
  resource_group_name  = var.resource_group_name
  virtual_network_name = var.virtual_network_name
}

output "subnet_ids" {
   value = values(azurerm_subnet.SUBNETS)[*].id
}

NETWORKINTERFACE.tf

resource "azurerm_network_interface" "NETWORKINTERFACE" {
  for_each=var.niclist
  name                = each.value.name
  location            = var.location
  resource_group_name = var.resource_group_name

  ip_configuration {
    name                          = "ipconfig1"
    subnet_id                     =   # part where I'm confused
    private_ip_address_allocation = "Dynamic"
  }
}

我如何将子网模块(总共 3 个子网 = 3 个 ID)的输出值传递给 NETWORKINTERFACE 模块,它应该在 for_each=var.niclist 循环中获取这些 ID 中的每一个。 如果您发现此方法不正确,请告诉我

PS。我是 terraform 的新手

-- 更新2

请找到我的 tfvars

RGlocation = "westus"
RGname     = "TEST-RG1-TERRAFORM"
VNETname      = "TEST-VNET-TERRAFORM"
address_space = "10.0.0.0/16"
Subnetlist = {
  "s1" = { name = "TESTSUBNET1-TERRAFORM", address = "10.0.1.0/24" },
  "s2" = { name = "TESTSUBNET2-TERRAFORM", address = "10.0.2.0/24" },
  "s3" = { name = "TESTSUBNET3-TERRAFORM", address = "10.0.3.0/24" }
}

niclist = {
  "s1" = { name = "TESTNIC1-TERRAFORM" },
  "s2" = { name = "TESTNIC2-TERRAFORM" },
  "s3" = { name = "TESTNIC3-TERRAFORM" }
}

这就是变量的填充方式。我使用了@martin 的建议并修改了一些命令。它现在正在按照我想要的方式创建子网和 NIC。

Main.tf

module "VNET" {
  source              = "./Modules/NetworkConfig"
  name                = var.VNETname
  address_space       = var.address_space
  location            = var.RGlocation
  resource_group_name = azurerm_resource_group.resource_group.name
}

module "SUBNETS" {
  source               = "./Modules/SubnetConfig"
  Subnetlist           = var.Subnetlist
  virtual_network_name = module.VNET.vnet_name
  resource_group_name  = azurerm_resource_group.resource_group.name
  depends_on           = [azurerm_resource_group.resource_group, module.VNET.vnet]

}

module "NETWORKINTERFACE" {
  source = "./Modules/NIConfig"
  
  resource_group_name = azurerm_resource_group.resource_group.name
  location            = azurerm_resource_group.resource_group.location
  nics = tomap({
    for k, subnet_id in module.SUBNETS.subnet_ids : k => {
      name      = var.niclist[k].name
      subnet_id = subnet_id
    }
  })
}

SUBNETS.tf

resource "azurerm_subnet" "SUBNETS" {
for_each=var.Subnetlist
name=each.value.name
address_prefixes=[each.value.address]
  resource_group_name  = var.resource_group_name
  virtual_network_name = var.virtual_network_name
}

output "subnet_ids" {
  value = tomap({ for k, s in azurerm_subnet.SUBNETS : k => s.id })
}

NETWORKINTERFACE.tf

resource "azurerm_network_interface" "NETWORKINTERFACE" {
  for_each=var.nics
  name                = each.value.name
  location            = var.location
  resource_group_name = var.resource_group_name

  ip_configuration {
    name                          = "ipconfig1"
    subnet_id                     =  each.value.subnet_id
    private_ip_address_allocation = "Dynamic"
  }
}

像这样跨多个资源和模块使用 for_each 时,保留对象的跟踪键很重要,这样 Terraform 才能看到一个资源的哪些实例与另一个资源的实例以及中间数据结构相关你用来传递数据的。

在您的情况下,这意味着将 subnet_ids 输出值的形状更改为从子网密钥到子网 ID 的映射,而不仅仅是子网 ID,以便清楚属于哪个 ID到哪个子网密钥:

resource "azurerm_subnet" "all" {
  for_each = var.Subnetlist

  name                 = each.value.name
  address_prefixes     = [each.value.address]
  resource_group_name  = var.resource_group_name
  virtual_network_name = var.virtual_network_name
}

output "subnet_ids" {
 value = tomap({ for k, s in azurerm_subnet.all : k => s.id })
}

您的网络接口模块似乎有一个输入变量 niclist 您没有显示其声明,但我假设它看起来像这样,我将把它重命名为nics 因为我要将其改为地图:

variable "nics" {
  type = map(
    object({
      name      = string
      subnet_id = string
    })
  )
}

然后您可以使用该变量作为 for_each 网络接口的基础:

resource "azurerm_network_interface" "all" {
  for_each = var.nics

  name                = each.value.name
  location            = var.location
  resource_group_name = var.resource_group_name

  ip_configuration {
    name                          = "ipconfig1"
    subnet_id                     = each.value.subnet_id
    private_ip_address_allocation = "Dynamic"
  }
}

剩下的问题是如何从根模块内部构建 nics 输入变量的值。您没有显示根模块的 niclist 变量是如何填充的,所以我不知道 NIC 和子网是如何相关的。由于您显示的配置建议每个子网一个 NIC,因此直接从子网映射中导出 nics 变量值并完全删除 var.niclist 可能就足够了:

module "network_interface" {
  source              = "./Modules/NIConfig"

  resource_group_name = azurerm_resource_group.resource_group.name
  location            = azurerm_resource_group.resource_group.location
  nics = tomap({
    for k, subnet_id in module.subnets.subnet_ids : k => {
      name      = k
      subnet_id = subnet_id
    }
  })
}

注意:您当前使用的命名方案与通常的 Terraform 惯用语不匹配,因此我在此处更改了我的答案中的一些名称,以使用 all-lowercase 名称的标准样式,其中单词由下划线。我建议遵循标准命名方案,以便您的配置对于可能已经从其他地方获得 Terraform 经验的未来维护人员而言是直观的。