我是 terraform 的新手,我正在尝试为多个 vnet 和多个子网下创建模块
我可以使用该模块创建多个虚拟网络,但在创建的一个或多个虚拟网络上创建多个子网时遇到问题。
下面是我的模块代码以及 main.tf
网络资源模块/main.tf
data "azurerm_resource_group" "network" {
name = var.resource_group_name
}
resource "azurerm_virtual_network" "vnets" {
count = length(var.vnet_names)
name = var.vnet_names[count.index]
resource_group_name = data.azurerm_resource_group.network.name
location = var.vnet_location != null ? var.vnet_location : data.azurerm_resource_group.network.location
address_space = [var.vnet_adress_spaces[count.index]]
}
网络资源模块/variables.tf
variable "vnet_names" {
description = "Name of the vnets to be created"
type = list(string)
default = ["vnet1","vnet2","vnet3"]
}
variable "vnet_adress_spaces" {
description = "Name of the vnets to be created"
type = list(string)
default = ["192.168.0.0/16" ,"10.0.0.0/16","10.80.0.0/16"]
}
variable "resource_group_name" {
description = "Name of the resource group to be imported."
type = string
}
variable "vnet_location" {
description = "The location of the vnet to create. Defaults to the location of the resource group."
type = string
default = null
}
variable "subnet_names" {
description = "The list of subnets which needs to be created"
type = list(list(string))
default = [[],["subnet1_vnet1","subnet2_vnet1"],["subnet1_vnet3","subnet2_vnet3","subnet3_vnet3"]]
}
variable "subnet_addresses" {
description = "The list of subnets which needs to be created"
type = list(list(string))
default = [[],["10.0.2.0/24","10.0.0.0/24"],["10.80.2.0/24","10.80.1.0/24","10.80.0.0/24"]]
}
main.tf
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=2.98.0"
}
}
}
# Configure the Microsoft Azure Provider
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "rg1" {
name = "rg1"
location = "West Europe"
}
module network {
source = "./network_resources"
resource_group_name = azurerm_resource_group.rg1.name
}
3 个虚拟网络已成功创建,但我在编写子网创建时遇到问题,如 Variables.tf 中所述 请您帮我解决这个问题,或者提出更好的实现方法
模块的输出.tf
output "vnet_names" {
description = "The name of the virtual networks"
value = {for k, v in azurerm_virtual_network.vnets: k => v.name}
}
output "vnet_addresses" {
description = "The name of the virtual networks"
value = {for k, v in azurerm_virtual_network.vnets: k => v.address_space}
}
output "subnet_names" {
description = "The name of the subnets"
value = {for k, v in azurerm_subnet.subnets: k => v.name}
}
output "subnet_addresses" {
description = "The name of the subnet addresses"
value = {for k, v in azurerm_subnet.subnets: k => v.address_prefixes}
}
output "subnet_ids" {
description = "The name of the subnet addresses"
value = {for k, v in azurerm_subnet.subnets: k => v.id}
}
当我根据更新的变量为两个虚拟网络采用相同的子网值时。tf
vnets = {
"mel-dev-identity-vnet01" = {
address_space = "10.0.0.0/16",
subnets = [
{
subnet_name = "subnet-mel-AD-dev"
subnet_address = "10.0.2.0/24"
service_endpoints = []
},
{
subnet_name = "subnet-mel-okt-dev"
subnet_address = "10.0.0.0/24"
service_endpoints = []
},
{
subnet_name = "GatewaySubnet"
subnet_address = "10.0.0.0/26"
service_endpoints = []
},
]
},
"mel-dev-identity-vnet02" = {
address_space = "10.80.0.0/16"
subnets = [
{
subnet_name = "subnet-syd-AD-dev"
subnet_address = "10.80.2.0/24"
service_endpoints = []
},
{
subnet_name = "subnet-syd-okt-dev"
subnet_address = "10.80.1.0/24"
service_endpoints = []
},
{
subnet_name = "GatewaySubnet"
subnet_address = "10.80.0.0/26"
service_endpoints = []
},
]
}
}
我收到以下错误:
│ 错误:对象键重复
│
│ 在network_resources\locals.tf第11行,在本地:
│ 11:子网 = { 对于 local.subnets_flatlist 中的子网:subnet.subnet_name => 子网 }
│ ├────────────────
│ │subnet.subnet_name 是“GatewaySubnet”
│
│ 两个不同的项目在此“for”表达式中生成了密钥“GatewaySubnet”。如果需要重复,请使用
│ 值表达式后面的省略号 (...) 以启用按键分组。
我在您的代码中看到两个问题:
您将相同资源的属性(例如subnet_name、subnet_addressed)存储在列表或嵌套列表类型的不同变量中。 这样,您必须手动确保不同变量之间的一致性,这可能会变得乏味且容易出错。假设您想要将第三个子网添加到 vnet bupavnet2。您必须确保在两个嵌套列表中的相应位置插入新名称和子网。
顺便说一句:vnet bupavnet2中的子网是否打算命名为subnet#-bupavnet1?明白我的意思吗??? :)
为了在多个 vnet 中动态创建多个子网,您需要一个嵌套循环,该循环遍历外循环中的 vnet 以及内循环中的子网。但是,Terraform 不支持资源级别的嵌套 for_each 循环。
克服第一个问题的一种方法是使用对象或映射等复杂类型,以使资源属性之间的关系明确。这样就可以很容易地发现bupavnet2中子网的命名问题。如果您想添加额外的子网,只需在子网列表中添加一个额外的对象即可。
variable "vnets" {
type = map(object({
address_space = string
subnets = list(object({
subnet_name = string
subnet_address = string
}))
}))
default = {
"bupavnet1" = {
address_space = "192.168.0.0/16",
subnets = []
},
"bupavnet2" = {
address_space = "10.0.0.0/16",
subnets = [
{
subnet_name = "subnet1_bupavnet1"
subnet_address = "10.0.2.0/24"
},
{
subnet_name = "subnet2_bupavnet1"
subnet_address = "10.0.0.0/24"
}
]
},
"bupavnet3" = {
address_space = "10.80.0.0/16"
subnets = [
{
subnet_name = "subnet1_bupavnet3"
subnet_address = "10.80.2.0/24"
},
{
subnet_name = "subnet2_bupavnet3"
subnet_address = "10.80.1.0/24"
},
{
subnet_name = "subnet3_bupavnet3"
subnet_address = "10.80.0.0/24"
},
]
}
}
}
随后,vnet 的创建将更改为
resource "azurerm_virtual_network" "vnets" {
for_each = var.vnets
name = each.key
resource_group_name = data.azurerm_resource_group.network.name
location = var.vnet_location != null ? var.vnet_location : data.azurerm_resource_group.network.location
address_space = [each.value.address_space]
}
现在让我们看看如何解决嵌套 for 循环问题。在 Terraform 中,您可以通过展平我们上面定义的嵌套结构来解决这个问题。在第一步中,我们创建一个表示要创建的子网的对象的平面列表。所以我们的变量
subnets_flatlist
具有类型对象元组。
不幸的是,Terraform 中的 for_each
参数需要类型 map 或 字符串集。因此,我们需要第二步从平面列表中创建地图。
locals {
subnets_flatlist = flatten([for key, val in var.vnets : [
for subnet in val.subnets : {
vnet_name = key
subnet_name = subnet.subnet_name
subnet_address = subnet.subnet_address
}
]
])
subnets = { for subnet in local.subnets_flatlist : subnet.subnet_name => subnet }
}
创建辅助结构后,我们可以迭代子网映射并创建子网资源:
resource "azurerm_subnet" "subnets" {
for_each = local.subnets
name = each.value.subnet_name
resource_group_name = data.azurerm_resource_group.network.name
virtual_network_name = azurerm_virtual_network.vnets[each.value.vnet_name].name
address_prefixes = [each.value.subnet_address]
}
这最终成功了。
vnet_id
module.network.vnet_id[keys(var.vnets)[0]]
vnet_名称
module.network.vnet_name[keys(var.vnets)[0]]