使用 terraform 模块的多个 Vnet 和子网

问题描述 投票:0回答:2

我是 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”。如果需要重复,请使用
│ 值表达式后面的省略号 (...) 以启用按键分组。

terraform
2个回答
2
投票

我在您的代码中看到两个问题:

  1. 您将相同资源的属性(例如subnet_name、subnet_addressed)存储在列表或嵌套列表类型的不同变量中。 这样,您必须手动确保不同变量之间的一致性,这可能会变得乏味且容易出错。假设您想要将第三个子网添加到 vnet bupavnet2。您必须确保在两个嵌套列表中的相应位置插入新名称和子网。

    顺便说一句:vnet bupavnet2中的子网是否打算命名为subnet#-bupavnet1?明白我的意思吗??? :)

  2. 为了在多个 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]
}

0
投票

这最终成功了。
vnet_id

module.network.vnet_id[keys(var.vnets)[0]]

vnet_名称

module.network.vnet_name[keys(var.vnets)[0]]
© www.soinside.com 2019 - 2024. All rights reserved.