0

我遇到的问题与负载均衡器前端 IP 有关,因此它可以使用唯一的公共 IP 访问不同可用区中的不同服务器。我在创建公共 IP 时使用计数,但我没有在负载均衡器上使用计数,因为我不想为每个服务器创建一个新的 LB。如果我能以某种方式将公共 IP 保存到一个变量中,那么我可以在动态块内使用 for_each 引用它们,但我找不到这样做的方法。这是我到目前为止的代码,但它不能按原样工作。这个问题可能没有解决方案,真的很臭。顺便说一句,我正在使用下面的 split 函数,因此它返回属性需要的列表。这有点骇人听闻,但确实有效。

resource "azurerm_public_ip" "pip" {
  count               = "${var.nblinuxvms}"
  name                = "${var.proj_name}-lbpip${count.index}-${var.region}-${var.app_env}"
  location            =  var.region
  resource_group_name = "${azurerm_resource_group.rg.name}"
  allocation_method   = "Static"   #Public IP Standard SKUs require allocation_method to be set to Static
  sku                 = "Standard" #Standard SKU Required for Zones
  domain_name_label   = "${var.proj_name}${count.index}${split("", "${element(["1", "2", "3"], "${count.index}")}")}"
  zones = "${var.avzones}" ? split("", "${element(["1", "2", "3"], "${count.index}")}") : null
}
resource "azurerm_lb" "lb" {
  name                = "externallb"
  location            = "${azurerm_resource_group.rg.location}"
  resource_group_name = "${azurerm_resource_group.rg.name}"
  sku                 = "standard" #standard SKU needed to support zones
 dynamic "frontend_ip_configuration" {
   for_each             = "${azurerm_public_ip.test.*.ip_address}" #this is the problem line. I need a way to store all the IPs in a variable and then iterate through them for each new frontend ip configuration
   content{
     name  = "primary${count.index}" #This name is also important as this is how I'll connect the nat rule down below
     public_ip_address_id = "${azurerm_public_ip.pip.id}"
  }
resource "azurerm_lb_nat_rule" "lbnr" {
  count                          = "${var.nblinuxvms}"
  resource_group_name            = "${azurerm_resource_group.rg.name}"
  loadbalancer_id                = "${azurerm_lb.lb.id}"
  name                           = "SSHHost${count.index}"
  protocol                       = "Tcp"
  frontend_port                  = "${2200 + count.index}"
  backend_port                   = 22
  frontend_ip_configuration_name = "primary${count.index}" #This name needs to match the LB Front End IP Configuartion
}

frontend_ip_configuration_name 需要与负载均衡器名称匹配。带有 for_each 的动态块似乎是特定问题的最佳解决方案,因为它不是资源……但我看不到将公共 ip 保存到我可以引用的任何变量的方法。如果没有解决方案,人们如何解决这个问题?通过为每个 Azure 可用区创建单独的 LB?因为它必须是一个标准,而不是看起来成本高昂的基本 LB。希望我只是错过了一些东西。任何帮助将不胜感激。请注意,我只分享了我的 terraform 项目中的相关代码。如果需要更多代码,请告诉我。(我无法在问题标签中添加动态块,因为我的代表很低。)谢谢,-Sam Kachar

4

2 回答 2

1

我觉得您正在尝试做的事情非常有意义并且应该是可能的。需要注意的一些事项:

  • for_each块内,您可以使用each.value来访问值(在本例中为公共 ip 对象)。有关详细信息,请参阅for_each 文档
  • ip_address指的是实际分配的ip,而不是对象
  • count块中不可用for_each,因此块的名称frontend_ip_configuration应直接从公共 ip 对象中推导出来。

鉴于上述情况,您可以尝试这样的事情(未经测试!):

resource "azurerm_lb_nat_rule" "lbnr" {
  count                          = "${var.nblinuxvms}"
  ...
  frontend_ip_configuration_name = "config_${azurerm_public_ip[count].name}"
}
dynamic "frontend_ip_configuration" {
   for_each = "${azurerm_public_ip.pip}"
   content{
     name                 = "config_${each.value.name}" 
     public_ip_address_id = "${each.value.id}"
  }

我假设您使用的是 terraform 0.12,因为for_each在 0.11 中不可用。您正在使用的详细插值语法在最新版本中已被弃用,最好使用新的:

resource "azurerm_lb_nat_rule" "lbnr" {
  count                          = var.nblinuxvms
  ...
  frontend_ip_configuration_name = "config_${azurerm_public_ip[count].name}"
}
dynamic "frontend_ip_configuration" {
   for_each = azurerm_public_ip.pip
   content{
     name                 = "config_${each.value.name}" 
     public_ip_address_id = each.value.id
}
于 2019-11-18T10:18:34.167 回答
0

韦斯利,我非常感谢你的回复。它给了我确认我需要看透这一切的确认,而且我实际上正朝着正确的方向前进。我昨晚才能够开始测试解决方案。不过,它需要更多的研究才能最终让它发挥作用。

尝试使用 each.value 引用一直失败。它抛出了一个错误,比如 each.value 需要与 for_each 一起使用......我发现这很令人沮丧,因为 for_each 仅比我尝试使用/引用它的地方高 2 行。此外,在错误中它创建了 3 条错误消息,因此它正在使用 for_each 进行迭代。无论出于何种原因,尽管它无法使用 each.value 提取值。

最终为我的 LB / Azure 可用区工作的代码如下(提示,必须使用迭代器选项):

resource "azurerm_lb" "lb" {
  name                = "externallb"
  location            = "${azurerm_resource_group.rg.location}"
  resource_group_name = "${azurerm_resource_group.rg.name}"
  sku                 = "standard" #standard SKU needed to support zones
  dynamic "frontend_ip_configuration" {
    iterator = pub
    for_each = azurerm_public_ip.pip 
    content {
      name                 = "config_${pub.value.ip_address}"
      public_ip_address_id = pub.value.id
    }

  }
}

....

resource "azurerm_lb_nat_rule" "lbnr" {
  count                          = "${var.nblinuxvms}"
  resource_group_name            = "${azurerm_resource_group.rg.name}"
  loadbalancer_id                = "${azurerm_lb.lb.id}"
  name                           = "SSHHost${count.index}"
  protocol                       = "Tcp"
  frontend_port                  = "${2200 + count.index}"
  backend_port                   = 22
  frontend_ip_configuration_name = "config_${azurerm_public_ip.pip[count.index].ip_address}"
}

根据我对迭代器选项的理解,您不必使用它,并且可以直接引用动态块标签中的内容作为前缀,但这将是超长且笨拙的。我上面发布的代码示例是功能代码:-)。当那件事发生时,我很高兴。花了几天时间试图解决这一切。

至于你关于这不是第 11 版的最后陈述,我不需要所有插值语法,我正在努力清理它。这是我需要完成的待办事项列表中的一项任务,因为我完成了这个项目以获得一个功能齐全的 VM 模块。如果 terraform 注册表在其计算模块中包含 Azure 区域,我会节省大量时间,但是在构建所有这些代码时,我必须比我仅仅调用注册表更好地学习语言。

就像我上面说的,再次感谢您发布答案,它确认我走在正确的道路上。希望我投入的所有时间都可以帮助其他人遇到类似的问题。请注意,对于阅读本文的任何人,我都有一个 azurerm_public_ip 块,它可以根据需要为 VM 和 LB 创建尽可能多的 PIP。如果有人要我添加该代码,我可以。只需给我发消息或评论我的帖子。

干杯,-Sam Kachar

于 2019-11-23T05:51:41.417 回答