4
votes

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"
    }
}
2

2 Answers

1
votes

Connecting to a Cloud sql instance through a private IP requires configuring private service access that uses an allocated IP address range that must not overlap with any existing VPC subnet.

The private connection links your VPC network with the service's VPC network. This connection allows VM instances in your VPC network to use internal IP addresses to reach the service resources, for example a Cloud sql instance that has internal IP addresses.

Once created, the allocated IP address range and the connection can then be reused with other services.

0
votes

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"
  }
}