Search code examples
google-cloud-platformterraformgoogle-vpc

Terraform - re-use an existing subnetwork to create a cloud sql instance on GCP


I am attempting to create a cloud sql instance on GCP using terraform. I want to use an existing VPC subnetwork created in an earlier step but there does not seem to be a way to refer to it. Instead all examples seem to require a new IP range to be setup. This is my current code that creates the new IP range:

  provider = google-beta
  project  = "project_name"

  name          = "private_range"
  purpose       = "VPC_PEERING"
  address_type  = "INTERNAL"
  prefix_length = 18
  network       = "projects/project_name/global/networks/vpc_name"
  address       = "192.168.128.0"
}

resource "google_service_networking_connection" "private_vpc_connection" {
  provider = google-beta

  network                 = "projects/project_name/global/networks/vpc_name"
  service                 = "servicenetworking.googleapis.com"
  reserved_peering_ranges = [google_compute_global_address.private_ip_address.name]
}

resource "google_sql_database_instance" "instance" {
  provider = google-beta
  project  = "project_name"

  name   = "db-instance10"
  region = "us-east1"
  database_version = "MYSQL_5_7"

  depends_on = [google_service_networking_connection.private_vpc_connection]

  settings {
    tier = "db-f1-micro"
    ip_configuration {
      ipv4_enabled    = false
      private_network = "projects/project_name/global/networks/vpc_name"
    }
  }
}

provider "google-beta" {
  region = "us-east1"
  zone   = "us-east1-c"
}

When I specify the exact same IP range as the existing subnet. I receive the error:

Error: Error waiting to create GlobalAddress: Error waiting for Creating GlobalAddress: Requested range conflicts with other resources: The provided IP range overlaps with existing subnetwork IP range.

There does not seem to be any obvious way to refer to the existing subnetwork resource as the reserved_peering_ranges parameter only seems to accept the name of an IP address range resource.

Here is the resource specification for the existing subnetwork:

    creation_timestamp       = "2020-06-03T07:28:05.762-07:00"
    enable_flow_logs         = true
    fingerprint              = "ied1TiEZjgc="
    gateway_address          = "192.168.128.1"
    id                       = "us-east1/vpc_subnet_name"
    ip_cidr_range            = "192.168.128.0/18"
    name                     = "vpc_subnet_name"
    network                  = "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/vpc_name"
    private_ip_google_access = true
    project                  = "project_name"
    region                   = "us-east1"
    secondary_ip_range       = []
    self_link                = "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-east1/subnetworks/vpc_subnet_name"

    log_config {
        aggregation_interval = "INTERVAL_5_SEC"
        flow_sampling        = 0.5
        metadata             = "INCLUDE_ALL_METADATA"
    }
}

Solution

  • you can use the below module to create the cloud sql with exisiting private vpc but you need to modify it according to your network. in this scenario i have created a separate private network & creating the cloud sql using that network.

    https://github.com/gruntwork-io/terraform-google-sql

    1. get the existing network in your cloud infra from which you want to create your cloudsql, the below command gives the gcloud network list --uri
    2. you need to append the network where self link is mentioned & hash out the steps where the vpc is getting created. please refer the below main.tf file

    the location of this file is --- Cloud_SQL.terraform\modules\sql_example_postgres-private-ip\examples\postgres-private-ip\main.tf

    add the variable accordingly.

    # ------------------------------------------------------------------------------
    # LAUNCH A POSTGRES CLOUD SQL PRIVATE IP INSTANCE
    # ------------------------------------------------------------------------------
    
    # ------------------------------------------------------------------------------
    # CONFIGURE OUR GCP CONNECTION
    # ------------------------------------------------------------------------------
    
    provider "google-beta" {
      project = var.project
      region  = var.region
    }
    
    terraform {
      # This module is now only being tested with Terraform 0.14.x. However, to make upgrading easier, we are setting
      # 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
      # forwards compatible with 0.14.x code.
      required_version = ">= 0.12.26"
    
      required_providers {
        google-beta = {
          source  = "hashicorp/google-beta"
          version = "~> 3.57.0"
        }
      }
    }
    
    # ------------------------------------------------------------------------------
    # CREATE A RANDOM SUFFIX AND PREPARE RESOURCE NAMES
    # ------------------------------------------------------------------------------
    
    resource "random_id" "name" {
      byte_length = 2
    }
    
    ####################################################################
    
    # Reserve global internal address range for the peering
    resource "google_compute_global_address" "private_ip_address" {
      provider      = google-beta
    # name          = local.private_ip_name
      name           = var.vpc_network
      purpose       = "VPC_PEERING"
      address_type  = "INTERNAL"
      prefix_length = 16
    #  network       = google_compute_network.private_network.self_link
    #  network       = google_compute_network.vpc_network.self_link
      network       =  "https://www.googleapis.com/compute/v1/projects/lucky-operand-312611/global/networks/myprivatevpc/"
    }
    
    # Establish VPC network peering connection using the reserved address range
    resource "google_service_networking_connection" "private_vpc_connection" {
      provider                = google-beta
    # network                 = google_compute_network.private_network.self_link
      network                 = "https://www.googleapis.com/compute/v1/projects/lucky-operand-312611/global/networks/myprivatevpc"
      service                 = "servicenetworking.googleapis.com"
      reserved_peering_ranges = [google_compute_global_address.private_ip_address.name]
    }
    
    # ------------------------------------------------------------------------------
    # CREATE DATABASE INSTANCE WITH PRIVATE IP
    # ------------------------------------------------------------------------------
    
    module "postgres" {
      # When using these modules in your own templates, you will need to use a Git URL with a ref attribute that pins you
      # to a specific version of the modules, such as the following example:
      # source = "github.com/gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.2.0"
      source = "../../modules/cloud-sql"
    
      project = var.project
      region  = var.region
      name    = var.instance_name
      db_name = var.db_name
    
      engine       = var.postgres_version
      machine_type = var.machine_type
    
      # To make it easier to test this example, we are disabling deletion protection so we can destroy the databases
      # during the tests. By default, we recommend setting deletion_protection to true, to ensure database instances are
      # not inadvertently destroyed.
      deletion_protection = false
    
      # These together will construct the master_user privileges, i.e.
      # 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'.
      # These should typically be set as the environment variable TF_VAR_master_user_password, etc.
      # so you don't check these into source control."
      master_user_password = var.master_user_password
    
      master_user_name = var.master_user_name
      master_user_host = "%"
    
      # Pass the private network link to the module
     # private_network = google_compute_network.private_network.self_link
       private_network = "https://www.googleapis.com/compute/v1/projects/lucky-operand-312611/global/networks/myprivatevpc" 
      # Wait for the vpc connection to complete
      dependencies = [google_service_networking_connection.private_vpc_connection.network]
    
      custom_labels = {
        test-id = "postgres-private-ip-example"
      }
    }