Terraform for_each创建GCE实例传VM名至启动脚本报循环依赖如何解决
问题根因
你遇到循环依赖报错的核心原因有两个:
- 你在
google_compute_instance资源块内部引用了这个资源自身的属性。Terraform执行时必须先计算完资源的所有配置参数,才能发起资源创建请求;你在参数里引用资源自身创建后才会生成的属性,相当于要求"先创建完资源拿到属性,再用属性当参数创建资源",必然形成循环依赖。 - 你写的
google_compute_instance.compute_instance.0.name本身是语法错误:for_each生成的资源是键值映射结构,不是按数字索引排序的列表,不存在0这个索引键。
修复方案
你需要的所有实例名称完全不需要等实例创建完成后再从资源属性里获取——实例命名规则是你自己定义的固定格式dev-${each.key},完全可以基于传入for_each的集合提前计算出所有实例名,从根源上避免自引用。
修改后的可运行配置如下:
locals { # 把for_each使用的实例键集合抽为局部值,统一维护避免重复定义 instance_keys = toset(["1", "2"]) # 按照命名规则提前生成所有实例名列表 all_instance_names = [for key in local.instance_keys : "dev-${key}"] } resource "google_compute_instance" "compute_instance" { project = var.project_id for_each = local.instance_keys name = "dev-${each.key}" machine_type = "e2-micro" zone = "${var.region}-b" boot_disk { initialize_params { image = "ubuntu-os-cloud/ubuntu-1804-lts" } } network_interface { network = "default" access_config {} } lifecycle { ignore_changes = [attached_disk] } metadata_startup_script = templatefile("copy.tftpl", { vm_name = local.all_instance_names nfs_ip = google_filestore_instance.instance.networks[0].ip_addresses[0] file_share_name = google_filestore_instance.instance.file_shares[0].name zone = "${var.region}-b" }) }
额外场景说明
- 如果你的启动脚本只需要获取当前正在创建的这台实例自己的名称,不需要拿全量实例名,可以直接用
self引用当前实例,不会触发循环依赖,写法为vm_name = self.name。 - Terraform HCL语法中,非字符串拼接场景下不需要额外包裹
"${}"插值符号,直接传入属性/局部值引用即可,配置会更简洁。
内容的提问来源于stack exchange,提问作者doctore
相关产品推荐
相关产品推荐

