gpt4 book ai didi

azure - Terraform:无法使用 azurerm_lb_backend_address_pool 在 lb 后面创建虚拟机

转载 作者:行者123 更新时间:2023-12-03 05:42:03 25 4
gpt4 key购买 nike

当我尝试同时在后端池内创建一个带有 vm 的 azure lb 时,我有一个奇怪的行为。

我有一个模块来管理虚拟机和一个模块来管理磅。如果我先创建 lb,则一切正常,但如果我同时创建两者,则不起作用。

这是我的配置(terraform 0.12.9、azure 1.33.1):

resource "azurerm_network_interface_backend_address_pool_association" "vm-if-lb-public-association" {
count = var.azure_lb_public_backend_id != "" ? var.countvm : 0
network_interface_id = element(azurerm_network_interface.vm-if.*.id, count.index)
ip_configuration_name = "${var.workspace_config.prefix}-${var.profile}-${count.index + 1}"
backend_address_pool_id = var.azure_lb_public_backend_id
}

var.azure_lb_public_backend_id 来 self 的 lb 模块

output "lb_id" {
value = var.enable ? azurerm_lb_backend_address_pool.lb-backend[0].id : ""
}

resource "azurerm_lb_backend_address_pool" "lb-backend" {
name = "pool-1"
count = var.enable ? 1 : 0
resource_group_name = azurerm_resource_group.lb-rg[0].name
loadbalancer_id = azurerm_lb.lb[0].id
}

当我运行计划时,我得到以下信息:

Error: Invalid count argument

on modules/vm/network.tf line 46, in resource "azurerm_network_interface_backend_address_pool_association" "vm-if-lb-public-association":
46: count = var.azure_lb_public_backend_id != "" ? var.countvm : 0

The "count" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the count depends on.
It's like the plan command doesn't understand vm creation depends on azurerm_lb_backend_address_pool

我自愿不发布所有代码,以避免帖子太大,但如果需要,我会毫不犹豫地询问更多内容。

你知道我为什么会出现这种行为吗?

最佳答案

如错误消息所述,count 值不得依赖于 Terraform 在应用完成后才知道的任何值。在这种情况下,var.azure_lb_public_backend_id 看起来像是一个对象的 ID,在创建该对象之前不会分配该 ID,因此 Terraform 还不知道该对象的值是什么,所以它不能确定它是否等于 ""

要实现此目的,您需要根据 Terraform 在计划时确实了解的信息做出决定。一种方法是将负载均衡器 id 值包装在一个对象中,以便可以根据该对象是否已设置来做出决定:

variable "load_balancer" {
type = object({
backend_address_pool_id = string
})
default = null
}

resource "azurerm_network_interface_backend_address_pool_association" "vm-if-lb-public-association" {
count = var.load_balancer != null ? var.countvm : 0
network_interface_id = element(azurerm_network_interface.vm-if.*.id, count.index)
ip_configuration_name = "${var.workspace_config.prefix}-${var.profile}-${count.index + 1}"
backend_address_pool_id = var.load_balancer.backend_address_pool_id
}

现在的决定是基于 var.load_balancer 对象是否为 null,而不是基于其中的 backend_address_pool_id 属性的值。然后,您的调用模块可以根据它用来决定如何在另一个模块上设置 var.enable 的相同测试来设置它:

  load_balancer = var.load_balancer_enabled ? {
backend_address_pool_id = module.load_balancer.lb_id
} : null

假设 var.load_balancer_enabled 在计划时已知,现在应该可以工作,因为 Terraform 可以决定 load_balancer 是否为 null,从而确定 的值>在所有情况下计数

<小时/>

在上面,我试图尽可能地遵循你的安排方式,以便更容易地看到我提出的更改,但是有一些不同的方法来安排上述原则,这可能会使模块更方便调用者使用。下面是一些与您分享的示例截然不同的示例,展示了我们如何在模块接口(interface)本身中隐藏此切换的细节,以实现更清晰的module composition .

在你的根模块中:

variable "load_balancer_enabled" {
type = bool
default = false
}

resource "azurerm_resource_group" "example" {
name = "example"
location = "West US"
}

module "load_balancer" {
source = "./modules/load-balancer"

resource_group = azurerm_resource_group.example
enabled = var.load_balancer_enabled
}

module "virtual_machines" {
source = "./modules/virtual_machines"

resource_group = azurerm_resource_group.example
vm_count = 4
load_balancer = module.load_balancer
}

负载均衡器模块中:

variable "resource_group" {
type = object({
name = string
location = string
})
}

variable "enabled" {
type = bool
default = true
}

resource "azurerm_lb" "example" {
count = var.enabled ? 1 : 0

name = "example"

resource_group_name = var.resource_group.name
location = var.resource_group.location

# (and probably a frontend IP allocation)
}

resource "azurerm_lb_backend_address_pool" "example" {
count = length(azurerm_lb.example)

name = "example"
resource_group_name = var.resource_group.name
loadbalancer_id = azurerm_lb.lb[count.index].id
}

output "backend_address_pool" {
# Set only if the load balancer is enabled. Null otherwise.
value = var.enabled ? azurerm_lb_backend_address_pool.example[0] : null
}

虚拟机模块中:

variable "resource_group" {
type = object({
name = string
location = string
})
}

variable "vm_count" {
type = number
}

variable "load_balancer" {
type = object({
# We only need to specify the subset of the module outputs
# that we need here.
backend_address_pool = object({
id = string
})
})
}

resource "azurerm_network_interface" "example" {
count = var.vm_count

# (and whatever other settings you need here)
}

resource "azurerm_network_interface_backend_address_pool_association" "vm-if-lb-public-association" {
count = var.load_balancer.backend_address_pool != null ? var.vm_count : 0

network_interface_id = azurerm_network_interface.example[count.index].id
backend_address_pool_id = var.load_balancer.backend_address_pool.id
}

在此变体中,load-balancer 模块会生成一个表示后端地址池的对象,并在模块禁用时将其设置为 null。然后,我们可以将整个模块结果传递给虚拟机模块,并让它根据该对象的空性做出决定,调用模块是只需将模块简单连接在一起,无需任何特殊逻辑。

同样,重要的细节是,最终仅基于 var.load_balancer_enabled 变量(间接)做出决定,而不是基于 Terraform 在应用过程中学习的任何值。

关于azure - Terraform:无法使用 azurerm_lb_backend_address_pool 在 lb 后面创建虚拟机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58005470/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com