Terraform如何遍历映射内列表实现多集群多VM部署?
需求可行性与实现方案
这个需求完全可行,核心问题是当前配置的for_each仅遍历集群维度,而非每个集群下的虚拟机实例。以下是具体实现思路和代码:
实现思路
将集群与虚拟机的层级结构扁平化,生成包含每个虚拟机实例的键值对集合,让for_each遍历每个虚拟机条目,从而为每个VM单独创建EC2实例,并通过标签设置指定的实例名称。
具体配置示例
1. 扁平化集群-VM结构(提升可读性)
在locals中生成包含所有VM实例的映射,方便后续资源引用:
locals { clusters = { "cluster1" = { instance_type = "t2.large" vms = ["vm1", "vm2", "vm3"] cidr_block = "10.0.0.0/24" } "cluster2" = { instance_type = "t2.large" vms = ["vm1", "vm2", "vm3"] cidr_block = "10.0.0.0/24" } } # 生成每个集群下VM的扁平化映射 cluster_vms_map = { for cluster_name, cluster_data in local.clusters : for vm_name in cluster_data.vms : "${cluster_name}_${vm_name}" => { cluster_name = cluster_name instance_type = cluster_data.instance_type } } }
2. 修改EC2资源配置
使用扁平化后的映射作为for_each的数据源,并设置实例名称标签:
resource "aws_instance" "cluster_vms" { for_each = local.cluster_vms_map ami = local.amis.ubuntu2204 instance_type = each.value.instance_type subnet_id = aws_subnet.public_subnets[each.value.cluster_name].id vpc_security_group_ids = [aws_security_group.generic_sg.id] key_name = "my_pair" # 设置实例名称为指定格式 tags = { Name = each.key # 自动生成 cluster1_vm1、cluster1_vm2 等名称 } }
简化版(无需额外locals)
如果不想单独定义扁平化映射,也可以直接在资源的for_each中嵌套表达式:
resource "aws_instance" "cluster_vms" { for_each = { for cluster_name, cluster_data in local.clusters : for vm_name in cluster_data.vms : "${cluster_name}_${vm_name}" => { cluster_name = cluster_name instance_type = cluster_data.instance_type } } ami = local.amis.ubuntu2204 instance_type = each.value.instance_type subnet_id = aws_subnet.public_subnets[each.value.cluster_name].id vpc_security_group_ids = [aws_security_group.generic_sg.id] key_name = "my_pair" tags = { Name = each.key } }
效果说明
上述配置会生成6台EC2实例,实例名称分别为cluster1_vm1、cluster1_vm2、cluster1_vm3、cluster2_vm1、cluster2_vm2、cluster2_vm3,完全符合需求。
内容的提问来源于stack exchange,提问作者user3139566
相关产品推荐
相关产品推荐

