Terraform 在没有任何变化时检测到变化

Terraform detects changes when there isn't any

我使用的是 terraform v1.1.3,每当我 运行 terraform plan 时,它都会声明我已经进行了更改,即使本地或远程没有任何更改。例如,如果我 运行 terraform apply 然后 terraform plan 紧随其后,它表示对象已在 Terraform 之外更改并强制替换我的实例。

  # module.database.oci_core_instance.instance[0] has changed
  ~ resource "oci_core_instance" "minstance" {
      + extended_metadata                   = {}
        id                                  = "ocid1.instance.oc1.me-jeddah-1.anvgkljrnghkmsacizo3ubuejydotfi7qz45if32x2e3b55mhirvrvpiw7nq"

为什么?

resource "oci_core_instance" "instance" {
  availability_domain                = random_shuffle.compute_ad.result[count.index % length(random_shuffle.compute_ad.result)]
  compartment_id                      = var.compartment_id
  shape                               = var.instance_shape
  freeform_tags                       = var.freeform_tags 
  shape_config {
        memory_in_gbs = 16 
        ocpus         = 1  
    }
  source_details {
    source_type = "image"
    source_id   = lookup(data.oci_core_images.compute_images.images[0], "id") 
   
  }
  metadata = { 
      ssh_authorized_keys = file(var.ssh_public_key) 
      user_data           = data.template_cloudinit_config.nodes.rendered
  }
  count = var.num_nodes

  depends_on = [
    oci_core_volume.volume_1
  ]
}

这可能是因为数据资源块直到应用才被评估,在计划期间它不知道里面有什么

 data.template_cloudinit_config.nodes.rendered

为了安全起见,将其标记为更改

如果您 1000% 确定这不会改变,您可以添加

lifecycle {
    ignore_changes = [
        extended_metadata
    ]
  }

但是要非常小心,因为如果元数据将来确实发生了变化,它就不再适用了。

我认为您在这里看到的是 OCI 提供程序中的一个小错误。我认为在底层远程 API 中,未设置此参数或将其设置为空映射之间没有区别,因此当提供者在刷新步骤中读取对象的最新状态时,它不会区分这些情况,因此它用空映射覆盖 null(表示它根本没有设置)。

如果这是真的,那么在不修改提供者的情况下,我认为您只能通过以与提供者在刷新对象时产生的内容相匹配的方式编写配置来避免这种情况,方法是为该参数包含一个显式的空映射:

  extended_metadata = {}

然后刷新步骤将找到在初始创建对象期间保存的相同内容,因此不会生成此错误更改报告。

此处的“真正”修复是让提供商将 null{} 视为此参数的等效值,因此不报告从 null{},但这对于提供程序开发人员来说可能很难实现,具体取决于当前如何实现此论点。