Terraform always tries to replace gcp compute instance without changes

Viewed 1093

Good morning

I am having a problem with my terraform code. I have defined two gcp compute instances in the following way inside a specific module:


resource "google_compute_instance" "dev_machine" {
  name = "dev-machine-${var.tag}"
  deletion_protection = true
  machine_type = "e2-standard-2"

  boot_disk {
      initialize_params {
        image = "ubuntu-os-pro-cloud/ubuntu-pro-2004-lts"
        size = 200
      }
  }

  network_interface {
    network = var.vpc.name
    subnetwork = var.subnet.name
    access_config {
      
    }
  }

  tags = ["dev-vm-${var.tag}"]
}


resource "google_compute_instance" "dev_machine-minor" {
  name = "dev-machine-minor-${var.tag}"
  deletion_protection = true
  
  machine_type = "n1-standard-1"

  boot_disk {
      initialize_params {
        image = "ubuntu-os-pro-cloud/ubuntu-pro-2004-lts"
        size = 30
      }
  }

  network_interface {
    network = var.vpc.name
    subnetwork = var.subnet.name
    access_config {
      
    }
  }

  tags = ["dev-vm-${var.tag}"]
}

resource "google_compute_firewall" "ssh_access" {
  name = "allow-ssh-access-${var.tag}"
  network = var.vpc.name

  allow {
    protocol = "tcp"
    ports = ["22"]
  }

  source_ranges = [ "0.0.0.0/0" ]
  target_tags = ["dev-vm-${var.tag}"]
}

The variables are defined in the following way:

variable "vpc" {
  description = "vpc to deploy instance"
}

variable "subnet" {
  description = "subnet to deploy the subnet"
}


variable "tag" {
  description = "general project tag"
}

Everything works as expected when I run the command 'terraform apply', but if I run it again it always states that the instances must be replaced, even if I did not make any changes to the code. When I connect to the instance via ssh, I notice that everything was wiped out.

This is the output from 'terraform plan' with no changes to the code:

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # module.dev_environment.google_compute_instance.dev_machine must be replaced
-/+ resource "google_compute_instance" "dev_machine" {
      ~ cpu_platform         = "Intel Broadwell" -> (known after apply)
      ~ current_status       = "RUNNING" -> (known after apply)
      ~ deletion_protection  = false -> true
      - enable_display       = false -> null
      ~ guest_accelerator    = [] -> (known after apply)
      ~ id                   = "<id with project>" -> (known after apply)
      ~ instance_id          = "<instance id>" -> (known after apply)
      ~ label_fingerprint    = "<label fingerprint>" -> (known after apply)
      - labels               = {} -> null
      - metadata             = {} -> null
      ~ metadata_fingerprint = "<metadata fingerprint>=" -> (known after apply)
      + min_cpu_platform     = (known after apply)
        name                 = "dev-machine-pweather"
      ~ project              = "<project id>" -> (known after apply)
      - resource_policies    = [] -> null
      ~ self_link            = "<project id url>/instances/dev-machine-pweather" -> (known after apply)
        tags                 = [
            "dev-vm-pweather",
        ]
      ~ tags_fingerprint     = "<tag fingerprint>" -> (known after apply)
      ~ zone                 = "us-east4-a" -> (known after apply)
        # (2 unchanged attributes hidden)

      ~ boot_disk {
          ~ device_name                = "persistent-disk-0" -> (known after apply)
          + disk_encryption_key_sha256 = (known after apply)
          + kms_key_self_link          = (known after apply)
          ~ source                     = "<project id url>/us-east4-a/disks/dev-machine-pweather" -> (known after apply)
            # (2 unchanged attributes hidden)

          ~ initialize_params {
              ~ image  = "https://www.googleapis.com/compute/v1/projects/ubuntu-os-pro-cloud/global/images/ubuntu-pro-2004-focal-v20210720" -> "ubuntu-os-pro-cloud/ubuntu-pro-2004-lts" # forces replacement
              ~ labels = {} -> (known after apply)
              ~ type   = "pd-standard" -> (known after apply)
                # (1 unchanged attribute hidden)
            }
        }

      + confidential_instance_config {
          + enable_confidential_compute = (known after apply)
        }

      ~ network_interface {
          ~ name               = "nic0" -> (known after apply)
          ~ network            = "<project id url>/global/networks/pweather-vpc" -> "pweather-vpc"
          ~ network_ip         = "10.0.0.17" -> (known after apply)
          ~ subnetwork         = "<project id url>/subnetworks/pweather-subnet" -> "pweather-subnet"
          ~ subnetwork_project = "<project>" -> (known after apply)

          ~ access_config {
              ~ nat_ip       = "<NAT IP> -> (known after apply)
              ~ network_tier = "PREMIUM" -> (known after apply)
            }
        }

      + reservation_affinity {
          + type = (known after apply)

          + specific_reservation {
              + key    = (known after apply)
              + values = (known after apply)
            }
        }

      ~ scheduling {
          ~ automatic_restart   = true -> (known after apply)
          ~ min_node_cpus       = 0 -> (known after apply)
          ~ on_host_maintenance = "MIGRATE" -> (known after apply)
          ~ preemptible         = false -> (known after apply)

          + node_affinities {
              + key      = (known after apply)
              + operator = (known after apply)
              + values   = (known after apply)
            }
        }

      - shielded_instance_config {
          - enable_integrity_monitoring = true -> null
          - enable_secure_boot          = false -> null
          - enable_vtpm                 = true -> null
        }
    }

  # module.dev_environment.google_compute_instance.dev_machine-minor must be replaced
-/+ resource "google_compute_instance" "dev_machine-minor" {
      ~ cpu_platform         = "Intel Broadwell" -> (known after apply)
      ~ current_status       = "RUNNING" -> (known after apply)
      ~ deletion_protection  = false -> true
      - enable_display       = false -> null
      ~ guest_accelerator    = [] -> (known after apply)
      ~ id                   = "<project id url>/instances/dev-machine-minor-pweather" -> (known after apply)
      ~ instance_id          = "<instance id>" -> (known after apply)
      ~ label_fingerprint    = "<label fingerprint>" -> (known after apply)
      - labels               = {} -> null
      - metadata             = {} -> null
      ~ metadata_fingerprint = "udK04sf2kcQ=" -> (known after apply)
      + min_cpu_platform     = (known after apply)
        name                 = "dev-machine-minor-pweather"
      ~ project              = "<project name>" -> (known after apply)
      - resource_policies    = [] -> null
      ~ self_link            = "<project id url>/us-east4-a/instances/dev-machine-minor-pweather" -> (known after apply)
        tags                 = [
            "dev-vm-pweather",
        ]
      ~ tags_fingerprint     = "<tag fingerprint>" -> (known after apply)
      ~ zone                 = "us-east4-a" -> (known after apply)
        # (2 unchanged attributes hidden)

      ~ boot_disk {
          ~ device_name                = "persistent-disk-0" -> (known after apply)
          + disk_encryption_key_sha256 = (known after apply)
          + kms_key_self_link          = (known after apply)
          ~ source                     = "<project id url>/us-east4-a/disks/dev-machine-minor-pweather" -> (known after apply)
            # (2 unchanged attributes hidden)

          ~ initialize_params {
              ~ image  = "https://www.googleapis.com/compute/v1/projects/ubuntu-os-pro-cloud/global/images/ubuntu-pro-2004-focal-v20210720" -> "ubuntu-os-pro-cloud/ubuntu-pro-2004-lts" # forces replacement
              ~ labels = {} -> (known after apply)
              ~ type   = "pd-standard" -> (known after apply)
                # (1 unchanged attribute hidden)
            }
        }

      + confidential_instance_config {
          + enable_confidential_compute = (known after apply)
        }

      ~ network_interface {
          ~ name               = "nic0" -> (known after apply)
          ~ network            = "<project id url>>/global/networks/pweather-vpc" -> "pweather-vpc"
          ~ network_ip         = "10.0.0.16" -> (known after apply)
          ~ subnetwork         = "<project id url>/us-east4/subnetworks/pweather-subnet" -> "pweather-subnet"
          ~ subnetwork_project = "<project>" -> (known after apply)

          ~ access_config {
              ~ nat_ip       = "<NAT IP>" -> (known after apply)
              ~ network_tier = "PREMIUM" -> (known after apply)
            }
        }

      + reservation_affinity {
          + type = (known after apply)

          + specific_reservation {
              + key    = (known after apply)
              + values = (known after apply)
            }
        }

      ~ scheduling {
          ~ automatic_restart   = true -> (known after apply)
          ~ min_node_cpus       = 0 -> (known after apply)
          ~ on_host_maintenance = "MIGRATE" -> (known after apply)
          ~ preemptible         = false -> (known after apply)

          + node_affinities {
              + key      = (known after apply)
              + operator = (known after apply)
              + values   = (known after apply)
            }
        }

      - shielded_instance_config {
          - enable_integrity_monitoring = true -> null
          - enable_secure_boot          = false -> null
          - enable_vtpm                 = true -> null
        }
    }

Plan: 2 to add, 0 to change, 2 to destroy.

Changes to Outputs:
  ~ vm_ip = "<VM IP>" -> (known after apply)

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

I tried to review the documentation, but (to my understanding) I did not find anything that could help me. Is there something I am doing wrong or is it a bug in the provider? Thank you!

EDIT 1: Added output of 'terraform plan' command.

2 Answers

According to the plan output, the argument value forcing a replacement is:

~ boot_disk {
      ...
      ~ initialize_params {
          ~ image  = "https://www.googleapis.com/compute/v1/projects/ubuntu-os-pro-cloud/global/images/ubuntu-pro-2004-focal-v20210720" -> "ubuntu-os-pro-cloud/ubuntu-pro-2004-lts" # forces replacement
      }
}

If you are comfortable updating the value from ubuntu-os-pro-cloud/ubuntu-pro-2004-lts to https://www.googleapis.com/compute/v1/projects/ubuntu-os-pro-cloud/global/images/ubuntu-pro-2004-focal-v20210720, then this will prevent the resource from having a Delete/Create operation applied to it.

However, the additional question here is why your argument value for image is changing. If you changed the config or someone manually changed the resource's attributes, then these would cause the change. However, you stated that did not occur. The provider may be attempting to auto-correct and modify the value during validation, but according to the documentation, your value is completely valid. Therefore, this is likely a bug in the provider for that resource's schema.

Related