matwasilewski
matwasilewski

Reputation: 426

Can't create a GCE instance with static IP with Terraform

I'm trying to create a GCE instance with a static, external IP address that will persist after the machine's lifecycle.

I have two separate terraform directories.

(1) creates the IP address:

# project_ips/ip.tf

locals {
  project_id             = "my_project"
  region                 = "my-region"
  static_ip_address_name  = "my-address"

}

module "address-fe" {
  source       = "terraform-google-modules/address/google"
  version      = "~> 3.1"
  project_id   = local.project_id
  region       = local.region
  address_type = "EXTERNAL"
  names = [
    local.static_ip_address_name,
  ]
  global = true
}

(2) Creates the VM and its networks:

# project_vm/networks.tf

# ...
# code where network and subnetwork are created 
# ...

data "google_compute_address" "vm_address" {
  project = var.project_id
  region  = var.region
  name    = "my-address"
}

VM:

# project_vm/neo4j.tf

resource "google_compute_instance" "vm" {
  project      = var.project_id
  name         = "my-instance"
  machine_type = var.machine_type
  zone         = var.zone

  network_interface {
    subnetwork_project = var.project_id
    subnetwork         = google_compute_subnetwork.public_subnet.name
    access_config {
      nat_ip = data.google_compute_address.vm_address.address
    }
  }
}

However, when the machine is created it is assigned a new, ephemeral IP address instead of the one created in the other project and presumably, passed via the data block. What is missing here?

Upvotes: 2

Views: 736

Answers (3)

Breith
Breith

Reputation: 2298

It is not possible to use this configuration with a "global" (global = true) type IP. This works only with the creation of a regional type IP. The al-dann response is correct.


Global IP addresses are intended to be used with HTTP(S) load balancers, SSL Proxy, and TCP Proxy to distribute traffic across multiple instances.

For example, you can add a global IP address with the resource: google_compute_global_forwarding_rule.

Upvotes: 0

matwasilewski
matwasilewski

Reputation: 426

After doing some more digging I realized that al-dann's answer solved the problem only partially. What it does is create the static address within the same project as the VM is, which means that the IP address will not persist after running terraform destroy. What I wanted to do was to create the static IP in another project and use it in this one.

My config from the original question would not detect the existing IP because the data block refers to a regional IP, but the actual reserved IP address is global - even though they have the same names, they are different resources because of that difference. Therefore, for it to work I had to remove the global = true attribute from the address-fe resource block.

# project_ips/ip.tf

locals {
  project_id             = "my_project"
  region                 = "my-region"
  static_ip_address_name  = "my-address"

}

module "address-fe" {
  source       = "terraform-google-modules/address/google"
  version      = "~> 3.1"
  project_id   = local.project_id
  region       = local.region
  address_type = "EXTERNAL"
  names = [
    local.static_ip_address_name,
  ]

}

It would be possible to do the opposite as well and remove regions, retaining the global flag.

Upvotes: 1

al-dann
al-dann

Reputation: 2725

You might neeed to create an address using a resource clause, rather than fetch information about it using the data clause (see your code).

So, instead of

data "google_compute_address" "vm_address" {
  project = var.project_id
  region  = var.region
  name    = "my-address"
}

you might need something like

resource "google_compute_address" "vm_address" {
  project      = var.project_id
  address_type = "EXTERNAL"
  network_tier = "PREMIUM"
  region       = var.region
  name         = "some name"
  description  = "An external IP address for my virtual machine"
}

and use it in the network_interface section as:

nat_ip = google_compute_address.vm_address.address

And no need for the data prefix in the above clause. See Terraform documentation and examples here: google_compute_address

Upvotes: 2

Related Questions