Skip to content

Latest commit

 

History

History
 
 

net-vpc

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

VPC module

This module allows creation and management of VPC networks including subnetworks and subnetwork IAM bindings, and most features and options related to VPCs and subnets.

Examples

Simple VPC

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  subnets = [
    {
      ip_cidr_range = "10.0.0.0/24"
      name          = "production"
      region        = "europe-west1"
      secondary_ip_ranges = {
        pods     = "172.16.0.0/20"
        services = "192.168.0.0/24"
      }
    },
    {
      ip_cidr_range = "10.0.16.0/24"
      name          = "production"
      region        = "europe-west2"
    }
  ]
}
# tftest modules=1 resources=5 inventory=simple.yaml e2e

Subnet Options

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  subnets = [
    # simple subnet
    {
      name          = "simple"
      region        = "europe-west1"
      ip_cidr_range = "10.0.0.0/24"
    },
    # custom description and PGA disabled
    {
      name                  = "no-pga"
      region                = "europe-west1"
      ip_cidr_range         = "10.0.1.0/24",
      description           = "Subnet b"
      enable_private_access = false
    },
    # secondary ranges
    {
      name          = "with-secondary-ranges"
      region        = "europe-west1"
      ip_cidr_range = "10.0.2.0/24"
      secondary_ip_ranges = {
        a = "192.168.0.0/24"
        b = "192.168.1.0/24"
      }
    },
    # enable flow logs
    {
      name          = "with-flow-logs"
      region        = "europe-west1"
      ip_cidr_range = "10.0.3.0/24"
      flow_logs_config = {
        flow_sampling        = 0.5
        aggregation_interval = "INTERVAL_10_MIN"
      }
    }
  ]
}
# tftest modules=1 resources=7 inventory=subnet-options.yaml e2e

Subnet IAM

Subnet IAM variables follow our general interface, with extra keys/members for the subnet to which each binding will be applied.

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  subnets = [
    {
      name          = "subnet-1"
      region        = "europe-west1"
      ip_cidr_range = "10.0.1.0/24"
      iam = {
        "roles/compute.networkUser" = [
          "group:${var.group_email}"
        ]
      }
      iam_bindings = {
        subnet-1-iam = {
          members = ["group:${var.group_email}"]
          role    = "roles/compute.networkUser"
          condition = {
            expression = "resource.matchTag('123456789012/env', 'prod')"
            title      = "test_condition"
          }
        }
      }
    },
    {
      name          = "subnet-2"
      region        = "europe-west1"
      ip_cidr_range = "10.0.2.0/24"
      iam_bindings_additive = {
        subnet-2-iam = {
          member = "group:${var.group_email}"
          role   = "roles/compute.networkUser"
          subnet = "europe-west1/subnet-2"
        }
      }
    }
  ]
}
# tftest modules=1 resources=8 inventory=subnet-iam.yaml e2e

Peering

A single peering can be configured for the VPC, so as to allow management of simple scenarios, and more complex configurations like hub and spoke by defining the peering configuration on the spoke VPCs. Care must be taken so as a single peering is created/changed/destroyed at a time, due to the specific behaviour of the peering API calls.

If you only want to create the "local" side of the peering, use peering_create_remote_end to false. This is useful if you don't have permissions on the remote project/VPC to create peerings.

module "vpc-hub" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "vpc-hub"
  subnets = [{
    ip_cidr_range = "10.0.0.0/24"
    name          = "subnet-1"
    region        = "europe-west1"
  }]
}

module "vpc-spoke-1" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "vpc-spoke1"
  subnets = [{
    ip_cidr_range = "10.0.1.0/24"
    name          = "subnet-2"
    region        = "europe-west1"
  }]
  peering_config = {
    peer_vpc_self_link = module.vpc-hub.self_link
    import_routes      = true
  }
}
# tftest modules=2 resources=10 inventory=peering.yaml

Shared VPC

Shared VPC is a project-level functionality which enables a project to share its VPCs with other projects. The shared_vpc_host variable is here to help with rapid prototyping, we recommend leveraging the project module for production usage.

module "service-project" {
  source          = "./fabric/modules/project"
  billing_account = var.billing_account_id
  name            = "prj1"
  prefix          = var.prefix
  parent          = var.folder_id
  services = [
    "cloudresourcemanager.googleapis.com",
    "compute.googleapis.com",
    "iam.googleapis.com",
    "serviceusage.googleapis.com"
  ]
}

module "vpc-host" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-host-network"
  subnets = [
    {
      ip_cidr_range = "10.0.0.0/24"
      name          = "subnet-1"
      region        = "europe-west1"
      secondary_ip_ranges = {
        pods     = "172.16.0.0/20"
        services = "192.168.0.0/24"
      }
      iam = {
        "roles/compute.networkUser" = [
          "serviceAccount:${var.service_account.email}"
        ]
        "roles/compute.securityAdmin" = [
          "serviceAccount:${var.service_account.email}"
        ]
      }
    }
  ]
  shared_vpc_host = true
  shared_vpc_service_projects = [
    module.service-project.project_id
  ]
}
# tftest modules=2 resources=14 inventory=shared-vpc.yaml e2e

Private Service Networking

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  subnets = [
    {
      ip_cidr_range = "10.0.0.0/24"
      name          = "production"
      region        = "europe-west1"
    }
  ]
  psa_configs = [{
    ranges = { myrange = "10.0.1.0/24" }
  }]
}
# tftest inventory=psa.yaml e2e

The module prefixes the PSA service to address range names, to disable this behaviour just set the range_prefix attribute in the PSA configuration:

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  subnets = [
    {
      ip_cidr_range = "10.0.0.0/24"
      name          = "production"
      region        = "europe-west1"
    }
  ]
  psa_configs = [{
    ranges       = { myrange = "10.0.1.0/24" }
    range_prefix = ""
  }]
}
# tftest inventory=psa-prefix.yaml e2e

Each PSA service can set a different prefix. Ranges will be allocated to the service they are defined in, as in the following example:

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  subnets = [
    {
      ip_cidr_range = "10.0.0.0/24"
      name          = "production"
      region        = "europe-west1"
    }
  ]
  psa_configs = [
    {
      ranges          = { myrange = "10.0.1.0/24" }
      range_prefix    = ""
      deletion_policy = "ABANDON"
    },
    {
      ranges           = { netapp = "10.0.2.0/24" }
      service_producer = "netapp.servicenetworking.goog"
      range_prefix     = ""
    }
  ]
}
# tftest inventory=psa-prefix-services.yaml e2e

Private Service Networking with peering routes and peered Cloud DNS domains

Custom routes can be optionally exported/imported through the peering formed with the Google managed PSA VPC.

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  subnets = [
    {
      ip_cidr_range = "10.0.0.0/24"
      name          = "production"
      region        = "europe-west1"
    }
  ]
  psa_configs = [{
    ranges         = { myrange = "10.0.1.0/24" }
    export_routes  = true
    import_routes  = true
    peered_domains = ["gcp.example.com."]
  }]
}
# tftest modules=1 resources=8 inventory=psa-routes.yaml e2e

Private Service Networking with multiple service providers

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  subnets = [
    {
      ip_cidr_range = "10.0.0.0/24"
      name          = "production"
      region        = "europe-west1"
    }
  ]
  psa_configs = [
    {
      ranges = { myrange = "10.0.1.0/24" }
      # service_producer = "servicenetworking.googleapis.com" # default value
      deletion_policy = "ABANDON"
    },
    {
      ranges           = { netapp = "10.0.2.0/24" }
      service_producer = "netapp.servicenetworking.goog"
      deletion_policy  = "ABANDON"
    }
  ]
}
# tftest modules=1 resources=10 inventory=psa-multiple-providers.yaml e2e

Subnets for Private Service Connect, Proxy-only subnets

Along with common private subnets module supports creation more service specific subnets for the following purposes:

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"

  subnets_proxy_only = [
    {
      ip_cidr_range = "10.0.1.0/24"
      name          = "regional-proxy"
      region        = "europe-west1"
      active        = true
    },
    {
      ip_cidr_range = "10.0.4.0/24"
      name          = "global-proxy"
      region        = "australia-southeast2"
      active        = true
      global        = true
    }
  ]
  subnets_psc = [
    {
      ip_cidr_range = "10.0.3.0/24"
      name          = "psc"
      region        = "europe-west1"
    }
  ]
}
# tftest modules=1 resources=6 inventory=proxy-only-subnets.yaml e2e

PSC Network Attachments

Network attachments are only supported for subnets directly managed by the module. To create network attachments in service projects, refer to the net-address module documentation.

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  network_attachments = {
    prod-ew1 = {
      subnet = "europe-west1/production"
      producer_accept_lists = [
        "my-project-1"
      ]
    }
    prod-ew2 = {
      subnet               = "europe-west2/production"
      automatic_connection = true
    }
  }
  subnets = [
    {
      ip_cidr_range = "10.0.0.0/24"
      name          = "production"
      region        = "europe-west1"
    },
    {
      ip_cidr_range = "10.0.16.0/24"
      name          = "production"
      region        = "europe-west2"
    }
  ]
}
# tftest modules=1 resources=7 inventory=network-attachments.yaml

DNS Policies

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  dns_policy = {
    inbound = true
    outbound = {
      private_ns = ["10.0.0.1"]
      public_ns  = ["8.8.8.8"]
    }
  }
  subnets = [
    {
      ip_cidr_range = "10.0.0.0/24"
      name          = "production"
      region        = "europe-west1"
    }
  ]
}
# tftest modules=1 resources=5 inventory=dns-policies.yaml e2e

Subnet Factory

The net-vpc module includes a subnet factory (see Resource Factories) for the massive creation of subnets leveraging one configuration file per subnet. The factory also supports proxy-only and PSC subnets via the purpose attribute. The name attribute is optional and defaults to the file name, allowing to use the same name for subnets in different regions. The context attribute of var.factories_config can optionally contain the map regions, which allows for the templatization of the region attribute (e.g. see config/subnets/subnet-simple.yaml below)

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  factories_config = {
    subnets_folder = "config/subnets"
    context = {
      regions = {
        primary   = "europe-west4"
        secondary = "europe-west8"
      }
    }
  }
}
# tftest modules=1 resources=10 files=subnet-simple,subnet-simple-2,subnet-detailed,subnet-proxy,subnet-proxy-global,subnet-psc inventory=factory.yaml
name: simple
region: primary
ip_cidr_range: 10.0.1.0/24

# tftest-file id=subnet-simple path=config/subnets/subnet-simple.yaml schema=subnet.schema.json
name: simple
region: europe-west8
ip_cidr_range: 10.0.2.0/24

# tftest-file id=subnet-simple-2 path=config/subnets/subnet-simple-2.yaml schema=subnet.schema.json
region: europe-west1
description: Sample description
ip_cidr_range: 10.0.0.0/24
# optional attributes
enable_private_access: false  # defaults to true
iam:
  roles/compute.networkUser:
    - group:[email protected]
    - serviceAccount:[email protected]
    - user:[email protected]
secondary_ip_ranges:          # map of secondary ip ranges
  secondary-range-a: 192.168.0.0/24
flow_logs_config:             # enable, set to empty map to use defaults
  aggregation_interval: "INTERVAL_5_SEC"
  flow_sampling: 0.5
  metadata: "INCLUDE_ALL_METADATA"

# tftest-file id=subnet-detailed path=config/subnets/subnet-detailed.yaml schema=subnet.schema.json
region: europe-west4
ip_cidr_range: 10.1.0.0/24
proxy_only: true

# tftest-file id=subnet-proxy path=config/subnets/subnet-proxy.yaml schema=subnet.schema.json
region: australia-southeast2
ip_cidr_range: 10.4.0.0/24
proxy_only: true
global: true

# tftest-file id=subnet-proxy-global path=config/subnets/subnet-proxy-global.yaml schema=subnet.schema.json
region: europe-west4
ip_cidr_range: 10.2.0.0/24
psc: true

# tftest-file id=subnet-psc path=config/subnets/subnet-psc.yaml schema=subnet.schema.json

Custom Routes

VPC routes can be configured through the routes variable.

locals {
  route_types = {
    gateway    = "global/gateways/default-internet-gateway"
    instance   = "zones/europe-west1-b/test"
    ip         = "192.168.0.128"
    ilb        = "regions/europe-west1/forwardingRules/test"
    vpn_tunnel = "regions/europe-west1/vpnTunnels/foo"
  }
}

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  for_each   = local.route_types
  project_id = var.project_id
  name       = "my-network-with-route-${replace(each.key, "_", "-")}"
  routes = {
    next-hop = {
      description   = "Route to internal range."
      dest_range    = "192.168.128.0/24"
      tags          = null
      next_hop_type = each.key
      next_hop      = each.value
    }
    gateway = {
      dest_range    = "0.0.0.0/0",
      priority      = 100
      tags          = ["tag-a"]
      next_hop_type = "gateway",
      next_hop      = "global/gateways/default-internet-gateway"
    }
  }
  create_googleapis_routes = null
}
# tftest modules=5 resources=15 inventory=routes.yaml

Policy Based Routes

Policy based routes can be configured through the policy_based_routes variable.

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-vpc"
  policy_based_routes = {
    skip-pbr-for-nva = {
      use_default_routing = true
      priority            = 100
      target = {
        tags = ["nva"]
      }
    }
    send-all-to-nva = {
      next_hop_ilb_ip = "10.0.0.253"
      priority        = 101
      filter = {
        src_range  = "10.0.0.0/8"
        dest_range = "0.0.0.0/0"
      }
      target = {
        interconnect_attachment = "europe-west8"
      }
    }
  }
  create_googleapis_routes = null
}
# tftest modules=1 resources=3 inventory=pbr.yaml

Private Google Access routes

By default the VPC module creates IPv4 routes for the Private Google Access ranges. This behavior can be controlled through the create_googleapis_routes variable:

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-vpc"
  create_googleapis_routes = {
    restricted   = false
    restricted-6 = true
    private      = false
    private-6    = true
  }
}
# tftest modules=1 resources=3 inventory=googleapis.yaml e2e

Allow Firewall Policy to be evaluated before Firewall Rules

module "vpc" {
  source                            = "./fabric/modules/net-vpc"
  project_id                        = var.project_id
  name                              = "my-network"
  firewall_policy_enforcement_order = "BEFORE_CLASSIC_FIREWALL"
  subnets = [
    {
      ip_cidr_range = "10.0.0.0/24"
      name          = "production"
      region        = "europe-west1"
      secondary_ip_ranges = {
        pods     = "172.16.0.0/20"
        services = "192.168.0.0/24"
      }
    },
    {
      ip_cidr_range = "10.0.16.0/24"
      name          = "production"
      region        = "europe-west2"
    }
  ]
}
# tftest modules=1 resources=5 inventory=firewall_policy_enforcement_order.yaml e2e

IPv6

A non-overlapping private IPv6 address space can be configured for the VPC via the ipv6_config variable. If an internal range is not specified, a unique /48 ULA prefix from the fd20::/20 range is assigned.

module "vpc" {
  source     = "./fabric/modules/net-vpc"
  project_id = var.project_id
  name       = "my-network"
  ipv6_config = {
    # internal_range is optional
    enable_ula_internal = true
    # internal_range      = "fd20:6b2:27e5::/48"
  }
  subnets = [
    {
      ip_cidr_range = "10.0.0.0/24"
      name          = "test"
      region        = "europe-west1"
      ipv6          = {}
    },
    {
      ip_cidr_range = "10.0.1.0/24"
      name          = "test"
      region        = "europe-west3"
      ipv6 = {
        access_type = "EXTERNAL"
      }
    }
  ]
}
# tftest modules=1 resources=5 inventory=ipv6.yaml e2e

Variables

name description type required default
name The name of the network being created. string
project_id The ID of the project where this VPC will be created. string
auto_create_subnetworks Set to true to create an auto mode subnet, defaults to custom mode. bool false
create_googleapis_routes Toggle creation of googleapis private/restricted routes. Disabled when vpc creation is turned off, or when set to null. object({…}) {}
delete_default_routes_on_create Set to true to delete the default routes at creation time. bool false
description An optional description of this resource (triggers recreation on change). string "Terraform-managed."
dns_policy DNS policy setup for the VPC. object({…}) null
factories_config Paths to data files and folders that enable factory functionality. object({…}) {}
firewall_policy_enforcement_order Order that Firewall Rules and Firewall Policies are evaluated. Can be either 'BEFORE_CLASSIC_FIREWALL' or 'AFTER_CLASSIC_FIREWALL'. string "AFTER_CLASSIC_FIREWALL"
ipv6_config Optional IPv6 configuration for this network. object({…}) {}
mtu Maximum Transmission Unit in bytes. The minimum value for this field is 1460 (the default) and the maximum value is 1500 bytes. number null
network_attachments PSC network attachments, names as keys. map(object({…})) {}
peering_config VPC peering configuration. object({…}) null
policy_based_routes Policy based routes, keyed by name. map(object({…})) {}
psa_configs The Private Service Access configuration. list(object({…})) []
routes Network routes, keyed by name. map(object({…})) {}
routing_mode The network routing mode (default 'GLOBAL'). string "GLOBAL"
shared_vpc_host Enable shared VPC for this project. bool false
shared_vpc_service_projects Shared VPC service projects to register with this host. list(string) []
subnets Subnet configuration. list(object({…})) []
subnets_private_nat List of private NAT subnets. list(object({…})) []
subnets_proxy_only List of proxy-only subnets for Regional HTTPS or Internal HTTPS load balancers. Note: Only one proxy-only subnet for each VPC network in each region can be active. list(object({…})) []
subnets_psc List of subnets for Private Service Connect service producers. list(object({…})) []
vpc_create Create VPC. When set to false, uses a data source to reference existing VPC. bool true

Outputs

name description sensitive
id Fully qualified network id.
internal_ipv6_range ULA range.
name Network name.
network Network resource.
network_attachment_ids IDs of network attachments.
project_id Project ID containing the network. Use this when you need to create resources after the VPC is fully set up (e.g. subnets created, shared VPC service projects attached, Private Service Networking configured).
self_link Network self link.
subnet_ids Map of subnet IDs keyed by name.
subnet_ips Map of subnet address ranges keyed by name.
subnet_ipv6_external_prefixes Map of subnet external IPv6 prefixes keyed by name.
subnet_regions Map of subnet regions keyed by name.
subnet_secondary_ranges Map of subnet secondary ranges keyed by name.
subnet_self_links Map of subnet self links keyed by name.
subnets Subnet resources.
subnets_private_nat Private NAT subnet resources.
subnets_proxy_only L7 ILB or L7 Regional LB subnet resources.
subnets_psc Private Service Connect subnet resources.