如何在Terraform中按集群和AZ生成二级嵌套实例名称输出?
解决方案
要实现按集群和可用区(AZ)分组的实例名称输出,有两种简洁的实现方式:
方法1:使用groupby函数(推荐)
利用Terraform的groupby函数先按集群名称分组,再为每个集群构建可用区到实例名称的映射:
output "instances_names_by_cluster" { value = { for cluster_name, cluster_groups in groupby(local.cluster_module_output, "cluster_name") : cluster_name => { for cluster in cluster_groups : cluster.cluster_az_name => cluster.instance_names } } }
逻辑说明:
groupby(local.cluster_module_output, "cluster_name")会将原始模块输出按cluster_name分组,得到类似{"api": [api集群1a, api集群1b], "web": [web集群1a]}的结构。- 外层
for循环遍历每个集群名称和对应的集群组,内层for循环遍历组内的每个集群,以可用区为key、实例名称列表为value,最终构造出嵌套的映射结构。
方法2:基于你的尝试改进
在你尝试2的基础上,通过merge函数将同集群下的可用区对象数组合并为单一映射:
output "instances_names_by_cluster" { value = { for cluster_name, az_obj_list in tomap({ for item in flatten([ for cluster in local.cluster_module_output : { cluster_name = cluster.cluster_name cluster_az = cluster.cluster_az_name instance_names = cluster.instance_names } ]) : item.cluster_name => { (item.cluster_az) = item.instance_names }... }) : cluster_name => merge(az_obj_list...) } }
逻辑说明:
- 你尝试2的输出中,每个集群对应一个可用区对象数组(比如
api对应[{eu-west-1a: [...]}, {eu-west-1b: [...]}])。 - 使用
merge(az_obj_list...)将数组中的多个小对象展开合并为一个大对象,从而得到{"eu-west-1a": [...], "eu-west-1b": [...]}的结构。
关于中间本地值
不需要强制使用中间本地值,但如果后续需要重复使用这个分组结构,将逻辑提取到本地值中可以提升代码可读性:
locals { instances_by_cluster_az = { for cluster_name, cluster_groups in groupby(local.cluster_module_output, "cluster_name") : cluster_name => { for cluster in cluster_groups : cluster.cluster_az_name => cluster.instance_names } } } output "instances_names_by_cluster" { value = local.instances_by_cluster_az }
内容的提问来源于stack exchange,提问作者CDuv
相关产品推荐
相关产品推荐

