Home > Blockchain >  How to create two GCP VM instances with deferent static external IP from same template via Terraform
How to create two GCP VM instances with deferent static external IP from same template via Terraform

Time:09-28

Trying to find way how I can to create two GCP instances with static external IP from same template. I have a code that create two instances with ephemeral external IP in two unmanaged instance group . I need to improve code for creating instances with static external IP. The existing code :

resource "google_compute_instance_template" "default" {
  # name         = format("%s-template", var.hostname)
  name_prefix  = var.hostname
  project      = var.project
  machine_type = var.machine_type

  region = var.region

  tags = var.target_tags

  labels = var.instance_labels

  can_ip_forward = var.can_ip_forward

  service_account {
    email  = var.service_account_email
    scopes = var.service_account_scopes
  }

  disk {
    auto_delete  = lookup(var.main_disk, "auto_delete", true)
    boot         = true
    source_image = lookup(var.main_disk, "source_image", "projects/debian-cloud/global/images/family/debian-9")
    device_name  = lookup(var.main_disk, "device_name", null)
    mode         = lookup(var.main_disk, "device_name", "READ_WRITE")
    type         = lookup(var.main_disk, "type", "PERSISTENT")
    disk_name    = lookup(var.main_disk, "disk_name", null)
    disk_type    = lookup(var.main_disk, "disk_type", "pd-ssd")
    disk_size_gb = lookup(var.main_disk, "disk_size_gb", null)
  }

  dynamic "disk" {
    for_each = [for d in var.additional_disks : {
      # auto_delete - (Optional) Whether or not the disk should be auto-deleted. This defaults to true.
      auto_delete = lookup(d, "auto_delete", true)
      # device_name - (Optional) A unique device name that is reflected into the /dev/ tree of a Linux operating system running within the instance. If not specified, the server chooses a default device name to apply to this disk.
      device_name = lookup(d, "device_name", null)
      # disk_name - (Optional) Name of the disk. When not provided, this defaults to the name of the instance.
      disk_name = lookup(d, "disk_name", null)
      # mode - (Optional) The mode in which to attach this disk, either READ_WRITE or READ_ONLY. If you are attaching or creating a boot disk, this must read-write mode.
      mode = lookup(d, "mode", "READ_WRITE")
      # source - (Required if source_image not set) The name (not self_link) of the disk (such as those managed by google_compute_disk) to attach.
      source = d.source
      # disk_type - (Optional) The GCE disk type. Can be either "pd-ssd", "local-ssd", or "pd-standard".
      disk_type = lookup(d, "disk_type", "pd-ssd")
      # disk_size_gb - (Optional) The size of the image in gigabytes. If not specified, it will inherit the size of its base image.
      disk_size_gb = lookup(d, "disk_size_gb", null)
      #type - (Optional) The type of GCE disk, can be either "SCRATCH" or "PERSISTENT".
      type = lookup(d, "type", "PERSISTENT")
    }]

    content {
      auto_delete  = disk.value.auto_delete
      boot         = disk.value.boot
      device_name  = disk.value.device_name
      disk_name    = disk.value.disk_name
      mode         = disk.value.mode
      source       = disk.value.source
      disk_type    = disk.value.disk_type
      disk_size_gb = disk.value.disk_size_gb
      type         = disk.value.type
    }
  }

  dynamic "network_interface" {
    for_each = [for n in var.interfaces : {
      network      = lookup(n, "network", null)
      subnetwork   = lookup(n, "subnetwork", null)
      network_ip   = lookup(n, "network_ip", null)
      nat_ip       = lookup(n, "nat_ip", null)
      network_tier = lookup(n, "network_tier", "PREMIUM")
      public_ip    = lookup(n, "public_ip", false)
    }]

    content {
      network    = network_interface.value.network
      subnetwork = network_interface.value.subnetwork
      network_ip = network_interface.value.network_ip

      dynamic "access_config" {
        for_each = network_interface.value.public_ip == "true" ? list(0) : []

        content {
          nat_ip       = network_interface.value.public_ip
          network_tier = network_interface.value.network_tier
        }
      }
    }
  }

  metadata = var.metadata

  metadata_startup_script = var.startup_script

  scheduling {
    preemptible         = var.scheduling["preemptible"]
    automatic_restart   = var.scheduling["automatic_restart"]
    on_host_maintenance = var.scheduling["on_host_maintenance"]
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "google_compute_instance_from_template" "compute_instance" {
  count                    = var.num_instances
  project                  = var.project
  name                     = format("%s%d", var.hostname, count.index   1)
  zone                     = var.zone[count.index]
  source_instance_template = google_compute_instance_template.default.self_link
}

resource "google_compute_instance_group" "instance_group" {
  count   = var.num_instances
  project = var.project
  name    = format("%s-ig-%d", var.hostname, count.index)
  zone    = var.zone[count.index]

  instances = [google_compute_instance_from_template.compute_instance[count.index].self_link]

  dynamic "named_port" {
    for_each = var.named_ports
    content {
      name = named_port.value.name
      port = named_port.value.port
    }
  }
}

I'm find out module for creating static external IP

module "address" {
  source  = "terraform-google-modules/address/google"
  version = "2.1.0"
  project_id = var.project
  region = var.region
  address_type = "EXTERNAL"
  enable_cloud_dns = false
  names = [
    "ip",
    "ip2",
  ]
 }

The module give output module.address.addresses in format

[ 
  xxx.xxx.xxx.xxx,
  yyy.yyy.yyy.yyy
]

But I'm still cant find a tricky way how to get instances with this IP from module via template.

May be anybody give me suggestion how I can realize it ?

CodePudding user response:

I'm fairly new with TF and GCP as well but...from the top of the mind comes two ideas (Remember I'm new and might be a better solution for this)

  • Define a variable for each of those IPs with that value and then call that IP in the resource you want.
  • Declare and output for the IPs and then call the output of those IPs in the resource you want such IP

CodePudding user response:

I solved issue by override template setting

resource "google_compute_address" "static" {
  count = var.num_instances
  project      = var.project
  name  = var.ext_ip_name[count.index] # ["ip", "ip2"]
  address_type = "EXTERNAL"
}

<...>

resource "google_compute_instance_from_template" "compute_instance" {
  count                    = var.num_instances
  project                  = var.project
  name                     = format("%s%d", var.hostname, count.index   1)
  zone                     = var.zone[count.index]
  source_instance_template = google_compute_instance_template.default.self_link
  dynamic "network_interface" {
    for_each = [for n in var.interfaces : {
      network      = lookup(n, "network", null)
      subnetwork   = lookup(n, "subnetwork", null)
      network_ip   = lookup(n, "network_ip", null)
      nat_ip       = lookup(n, "nat_ip", null)
      network_tier = lookup(n, "network_tier", "PREMIUM")
      public_ip    = lookup(n, "public_ip", false)
    }]

    content {
      network    = network_interface.value.network
      subnetwork = network_interface.value.subnetwork
      network_ip = network_interface.value.network_ip

      dynamic "access_config" {
        for_each = network_interface.value.public_ip == "true" ? list(0) : []

        content {
          nat_ip       = google_compute_address.static[count.index].address
          network_tier = network_interface.value.network_tier
        }
      }
    }
  }
}

<...>
  • Related