使用 Terraform 基于一组变量创建多个资源
Using terraform to create multiple resources based on a set of variables
我在terraform.tfvars
中有一组变量:
resource_groups = {
cow = {
name = "Cow"
location = "eastus"
},
horse = {
name = "Horse"
location = "eastus"
},
chicken = {
name = "Chicken"
location = "westus2"
},
}
我的 main.tf
看起来像这样:
...
module "myapp" {
source = "./modules/myapp"
resource_groups = var.resource_groups
}
variable "resource_groups" {}
...
./modules/myapp.main.tf
看起来像这样:
module "resource_group" {
source = "../myapp.resource_group"
resource_groups = var.resource_groups
for_each = {
for key, value in try(var.resource_groups, {}) : key => value
if try(value.reuse, false) == false
}
}
variable "resource_groups" {}
和 ../myapp.resource_group
看起来像这样:
resource "azurerm_resource_group" "resource_group" {
name = var.resource_groups.cow.name
location = var.resource_groups.cow.location
}
variable "resource_groups" {}
我希望在 terraform plan
之后我会看到三个新的 RG 将被设置为添加。事实上我确实得到了三个新的,但它们都使用牛 RG 的名称和位置,因为我指定了 var.resource_groups.cow.name
问题是我已经尝试了各种不同的迭代器来代替 .cow。而且我无法让 terraform 使用 terraform.tfvars
文件中的其他变量。我试过方括号、星号和其他通配符。我卡住了。
我希望在一个地方定义一个资源,然后使用它为每个变量映射创建该资源的多个实例。
非常感谢指导。
谢谢。
比尔
对于这种情况,您需要决定您的模块是代表一个资源组还是代表多个资源组。对于一个无论如何只包含一个资源的模块来说,这个决定并不是特别重要,但我假设你把它分解到一个单独的模块中,因为除了单个资源组资源之外还有更多的东西,所以你可以在两者之间做出决定这两个基于此模块代表的其他内容:您要重复此模块中的所有内容,还是仅重复资源组资源?
如果您需要模块代表单个资源组,那么您应该更改其输入变量以仅获取有关单个资源组的数据,然后在您的调用中传递当前资源组的数据module
块。
模块内部:
variable "resource_group" {
type = object({
name = string
location = string
})
}
resource "azurerm_resource_group" "resource_group" {
name = var.resource_group.name
location = var.resource_group.location
}
调用模块时:
variable "resource_groups" {
type = map(
object({
name = string
location = string
})
)
}
module "resource_group" {
source = "../myapp.resource_group"
for_each = var.resource_groups
# each.value is the value of the current
# element of var.resource_groups, and
# so it's just a single resource group.
resource_group = each.value
}
使用此策略,您将使用以下地址声明资源实例,表明重复发生在整个模块级别而不是其中的单个资源:
module.resource_group["cow"].azurerm_resource_group.resource_group
module.resource_group["horse"].azurerm_resource_group.resource_group
module.resource_group["chicken"].azurerm_resource_group.resource_group
如果您需要模块来表示完整的资源组集,那么模块会将资源组的完整映射作为输入变量而不是 使用for_each
在 module
块上。 for_each
参数将属于嵌套资源。
模块内部:
variable "resource_groups" {
type = map(
object({
name = string
location = string
})
)
}
resource "azurerm_resource_group" "resource_group" {
for_each = var.resource_groups
name = each.value.name
location = each.value.location
}
调用模块时:
variable "resource_groups" {
type = map(
object({
name = string
location = string
})
)
}
module "resource_group" {
source = "../myapp.resource_group"
# NOTE: No for_each here, because we need only
# one instance of this module which will itself
# then contain multiple instances of the resource.
resource_group = var.resource_groups
}
使用此策略,您将使用以下地址声明资源实例,表明模块只有一个实例,但其中有多个资源实例:
module.resource_group.azurerm_resource_group.resource_group["cow"]
module.resource_group.azurerm_resource_group.resource_group["horse"]
module.resource_group.azurerm_resource_group.resource_group["chicken"]
从您分享的信息中不清楚哪种策略更适合您的情况,因为您将此模块描述为好像它只是 azurerm_resource_group
资源类型的薄包装器,并且因此并不清楚这个模块 代表什么 ,以及为什么它比在根模块中只写一个内联 resource "azurerm_resource_group"
块更有帮助。
在考虑上述哪种设计最适合您的 use-case 时,我建议考虑 Terraform 文档中 When to Write a Module 中的建议。编写一个仅包含单个 resource
块的模块可能没问题,但这通常用于更复杂的资源类型,其中模块 hard-codes 一些本地约定,因此它们不需要 re-specified 整个组织的 Terraform 配置。
如果您只是将值直接传递给资源参数,而没有额外的转换和额外的 hard-coded 设置,那么这表明该模块没有用,而且编写起来会更简单resource
内联块。
我在terraform.tfvars
中有一组变量:
resource_groups = {
cow = {
name = "Cow"
location = "eastus"
},
horse = {
name = "Horse"
location = "eastus"
},
chicken = {
name = "Chicken"
location = "westus2"
},
}
我的 main.tf
看起来像这样:
...
module "myapp" {
source = "./modules/myapp"
resource_groups = var.resource_groups
}
variable "resource_groups" {}
...
./modules/myapp.main.tf
看起来像这样:
module "resource_group" {
source = "../myapp.resource_group"
resource_groups = var.resource_groups
for_each = {
for key, value in try(var.resource_groups, {}) : key => value
if try(value.reuse, false) == false
}
}
variable "resource_groups" {}
和 ../myapp.resource_group
看起来像这样:
resource "azurerm_resource_group" "resource_group" {
name = var.resource_groups.cow.name
location = var.resource_groups.cow.location
}
variable "resource_groups" {}
我希望在 terraform plan
之后我会看到三个新的 RG 将被设置为添加。事实上我确实得到了三个新的,但它们都使用牛 RG 的名称和位置,因为我指定了 var.resource_groups.cow.name
问题是我已经尝试了各种不同的迭代器来代替 .cow。而且我无法让 terraform 使用 terraform.tfvars
文件中的其他变量。我试过方括号、星号和其他通配符。我卡住了。
我希望在一个地方定义一个资源,然后使用它为每个变量映射创建该资源的多个实例。
非常感谢指导。
谢谢。
比尔
对于这种情况,您需要决定您的模块是代表一个资源组还是代表多个资源组。对于一个无论如何只包含一个资源的模块来说,这个决定并不是特别重要,但我假设你把它分解到一个单独的模块中,因为除了单个资源组资源之外还有更多的东西,所以你可以在两者之间做出决定这两个基于此模块代表的其他内容:您要重复此模块中的所有内容,还是仅重复资源组资源?
如果您需要模块代表单个资源组,那么您应该更改其输入变量以仅获取有关单个资源组的数据,然后在您的调用中传递当前资源组的数据module
块。
模块内部:
variable "resource_group" {
type = object({
name = string
location = string
})
}
resource "azurerm_resource_group" "resource_group" {
name = var.resource_group.name
location = var.resource_group.location
}
调用模块时:
variable "resource_groups" {
type = map(
object({
name = string
location = string
})
)
}
module "resource_group" {
source = "../myapp.resource_group"
for_each = var.resource_groups
# each.value is the value of the current
# element of var.resource_groups, and
# so it's just a single resource group.
resource_group = each.value
}
使用此策略,您将使用以下地址声明资源实例,表明重复发生在整个模块级别而不是其中的单个资源:
module.resource_group["cow"].azurerm_resource_group.resource_group
module.resource_group["horse"].azurerm_resource_group.resource_group
module.resource_group["chicken"].azurerm_resource_group.resource_group
如果您需要模块来表示完整的资源组集,那么模块会将资源组的完整映射作为输入变量而不是 使用for_each
在 module
块上。 for_each
参数将属于嵌套资源。
模块内部:
variable "resource_groups" {
type = map(
object({
name = string
location = string
})
)
}
resource "azurerm_resource_group" "resource_group" {
for_each = var.resource_groups
name = each.value.name
location = each.value.location
}
调用模块时:
variable "resource_groups" {
type = map(
object({
name = string
location = string
})
)
}
module "resource_group" {
source = "../myapp.resource_group"
# NOTE: No for_each here, because we need only
# one instance of this module which will itself
# then contain multiple instances of the resource.
resource_group = var.resource_groups
}
使用此策略,您将使用以下地址声明资源实例,表明模块只有一个实例,但其中有多个资源实例:
module.resource_group.azurerm_resource_group.resource_group["cow"]
module.resource_group.azurerm_resource_group.resource_group["horse"]
module.resource_group.azurerm_resource_group.resource_group["chicken"]
从您分享的信息中不清楚哪种策略更适合您的情况,因为您将此模块描述为好像它只是 azurerm_resource_group
资源类型的薄包装器,并且因此并不清楚这个模块 代表什么 ,以及为什么它比在根模块中只写一个内联 resource "azurerm_resource_group"
块更有帮助。
在考虑上述哪种设计最适合您的 use-case 时,我建议考虑 Terraform 文档中 When to Write a Module 中的建议。编写一个仅包含单个 resource
块的模块可能没问题,但这通常用于更复杂的资源类型,其中模块 hard-codes 一些本地约定,因此它们不需要 re-specified 整个组织的 Terraform 配置。
如果您只是将值直接传递给资源参数,而没有额外的转换和额外的 hard-coded 设置,那么这表明该模块没有用,而且编写起来会更简单resource
内联块。