You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Terraform中同时使用索引与实例值创建OpenStack负载均衡器

在Terraform中遍历OpenStack实例时同时使用实例值与循环索引

问题场景

你已经通过Terraform定义了两个节点输出nodes_1和nodes_2:

output "nodes_1" {
  value = [
    for vm in openstack_compute_instance_v2.type_1_instance[*] : tomap({
      name       = "${vm.name}",
      private_ip = "${vm.network[0].fixed_ip_v4}"
    })
  ]
}

output "nodes_2" {
  value = [
    for vm in openstack_compute_instance_v2.type_2_instance[*] : tomap({
      name       = "${vm.name}",
      private_ip = "${vm.network[0].fixed_ip_v4}"
    })
  ]
}

并将两者合并为单个列表:

cluster_nodes = concat(module.cluster_compute.nodes_1, module.cluster_compute.nodes_2)

现在需要创建OpenStack负载均衡相关资源,同时要用到实例的name、private_ip以及遍历过程中的循环索引,但当前代码中使用index()函数获取索引的方式存在隐患(比如实例重名时会出错,且索引查找效率低),需要更可靠的实现方式。

解决方案

核心思路是在遍历实例时同时保留索引和实例数据,通过构造包含索引信息的映射来实现,避免依赖index()函数。

1. 构造带索引的实例映射

在locals块中生成一个包含索引和实例详情的映射,用索引-实例名称作为唯一键(避免重名冲突):

locals {
  cluster_nodes = concat(module.cluster_compute.nodes_1, module.cluster_compute.nodes_2)
  
  # 生成包含索引的实例映射,键为"索引-实例名称",值包含索引和实例数据
  indexed_nodes = {
    for idx, node in local.cluster_nodes :
    "${idx}-${node.name}" => {
      index = idx
      data  = node
    }
  }
}

2. 修改负载均衡监听器资源

调整监听器的名称(避免重复命名),并确保count等于实例总数:

resource "openstack_lb_listener_v2" "loadbalancer_listener" {
  count = length(local.cluster_nodes)

  name            = "lb-listener-${count.index}"
  loadbalancer_id = openstack_lb_loadbalancer_v2.cluster_loadbalancer.id
  protocol_port   = local.starting_port + count.index
}

3. 修改负载均衡池资源

使用带索引的映射遍历,直接通过each.value.index获取索引,关联对应的监听器:

resource "openstack_lb_pool_v2" "load_balancer_pool" {
  for_each = local.indexed_nodes

  name        = "pool-${each.value.data.name}"
  listener_id = openstack_lb_listener_v2.loadbalancer_listener[each.value.index].id
}

4. 修改负载均衡成员资源

同样使用带索引的映射,直接关联对应的池资源:

resource "openstack_lb_member_v2" "load_balancer_member" {
  for_each = local.indexed_nodes

  name          = "lb-member-${each.value.data.name}"
  pool_id       = openstack_lb_pool_v2.load_balancer_pool[each.key].id
  address       = each.value.data.private_ip
}

关键说明

  • 用${idx}-${node.name}作为for_each的键,既保证了唯一性(即使实例重名也不会冲突),又保留了索引信息。
  • 直接通过each.value.index获取循环索引,比index()函数更可靠高效,避免了列表元素重复导致的索引错误。
  • 监听器名称添加count.index后缀,避免多个监听器重名引发的资源冲突。

内容的提问来源于stack exchange,提问作者sctx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 00:12:10