将多个输出传递到 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 经验的未来维护人员而言是直观的。
我试图将每个部分都作为模块来涵盖,而不是将其保存在单个 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 经验的未来维护人员而言是直观的。