Terraform - GCP VM - provision Multiple VMs with Multiple extra disks

Viewed 1192

I am trying to create Multiple VMs with few Extra Disks. I gave 2 extra disks and want to create 2 VMs. it seems the extra disk created only for one vm and not for another one vm and it throws that extra disk name already exists.

Error: Error creating instance: googleapi: Error 400: The disk resource 'projects/xxxxxxx/zones/us-central1-a/disks/extra-disk-1-ab23e8823b41ac18' is already being used by 'projects/xxxxxxx/zones/us-central1-a/instances/xxxxxx', resourceInUseByAnotherResource
│ 
│   with module.compute_vm.google_compute_instance.vm_instance[1],
│   on ../../main.tf line 66, in resource "google_compute_instance" "vm_instance":
│   66: resource "google_compute_instance" "vm_instance" {

Main.tf in examples folder (calling module)

module "compute_vm" {
  source              = "../../"
  num_instances       = 2
  boot_disk_size_gb   = "10"
  disk2_type          = "pd-ssd"
  os_distro           = "ubuntu"
  extra_disks = [{ name = "extra-disk-1", disk2_size_gb = "16" }, { name = "extra-disk-2", disk2_size_gb = "15" }]
}

in module Main.tf

resource "google_compute_disk" "disk2" {
  project = var.project_id
  count   = length(var.extra_disks)
  name    = "${var.extra_disks[count.index].name}-${random_id.instance_id.hex}"
  type    = var.disk2_type
  size    = var.extra_disks[count.index].disk2_size_gb
  zone    = var.zone
  labels = {
    environment = var.environment
  }
}

resource "random_id" "instance_id" {
  byte_length = 8
}

resource "google_compute_instance" "vm_instance" {
  project      = var.gcp_project_id
  count        = var.num_instances
  name         = "vm-${random_id.instance_id.hex}-${count.index + 1}"
  machine_type = var.machine_type
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = lookup(var.image, var.os_distro)
      size  = var.boot_disk_size_gb
    }
  }

  dynamic "attached_disk" {
    for_each = google_compute_disk.disk2
    content {
      source      = attached_disk.value.self_link
      device_name = attached_disk.value.name
    }
  }
  # attached_disk {
  #   source      = element(google_compute_disk.disk2.*.self_link, count.index)
  #   device_name = element(google_compute_disk.disk2.*.name, count.index)
  # }

  network_interface {
    subnetwork = data.google_compute_subnetwork.subnet.self_link
    network_ip = element(google_compute_address.static.*.address, count.index)
  }

  lifecycle {
    ignore_changes = [attached_disk]
  }

}

1 Answers

@Gopalakrishnan answering this for rest of the community.

Why is this happening?

Count in vm_instance is based on var.num_instances while count on disks is based on var.extra_disks. 1st VM will be attached with extra_disks as part of the config, 2nd VM will also try to attach the same disks but will fail because those disks are already attached to VM1.

What we need to do? :

We need to make sure that for every instance created new disks are created and attached to the instance rather than reusing the same disks.

How do we do it? (One of the ways)
  1. Remove the count variable from google_compute_instance block.
  2. Call this terraform code as a module from another folder. [Creating a terraform module]
  3. Use count in modules to create multiple VMs with multiple disks in them.
Other ways :
  • Making the count in google_compute_disk = Number of disks needed * Number of VMs and including a logic to call specific elements of google_compute_disk.disk2 in google_compute_instance based on count.index of VM being created.
Related