Hybrid Connectivity: High Availability (HA) VPN with BGP
Scenario
Your GCP VPC needs to establish an encrypted, highly resilient Site-to-Site tunnel to an On-Premises data center (or another cloud like AWS). You must provision an HA VPN Gateway. Unlike "Classic VPN" which requires manual static route management, HA VPN guarantees 99.99% SLA using dual active tunnels and uses BGP (Border Gateway Protocol) via Cloud Router to dynamically advertise subnet IP blocks.
- Provision a custom VPC and a google_compute_router with BGP ASN enabled.
- Provision a google_compute_ha_vpn_gateway inside the GCP VPC.
- Mock the remote environment by provisioning a google_compute_external_vpn_gateway (representing your On-Prem router).
- Provision two google_compute_vpn_tunnel resources pointing to the external gateway's two interfaces.
- Provision two google_compute_router_interface and two google_compute_router_peer resources to establish BGP peering over the tunnels.
Additional Context
SLA Requirements: To get the 99.99% SLA from Google, you must configure two VPN tunnels. HA VPN Gateways have 2 external interfaces natively. You must map `interface 0` to your on-prem router's first IP, and `interface 1` to the second IP.
BGP API: Cloud Router uses BGP to automatically discover which subnets live On-Prem. For this to work, both sides must agree on a shared secret and unique BGP IPs inside the tunnel (usually `/30` links like `169.254.0.1` and `169.254.0.2`).
variables.tf
variable "project_id" { type = string }main.tf
provider "google" {
project = var.project_id
region = "us-central1"
}
# 1. VPC & BGP Router
resource "google_compute_network" "vpc" {
name = "hybrid-vpc"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "subnet" {
name = "hybrid-subnet"
network = google_compute_network.vpc.id
region = "us-central1"
cidr_range = "10.0.1.0/24"
}
resource "google_compute_router" "bgp_router" {
name = "hybrid-bgp-router"
network = google_compute_network.vpc.id
region = "us-central1"
bgp {
# Private Google ASN
asn = 64514
}
}
# 2. GCP HA VPN Gateway (2 physical interfaces created automatically by Google)
resource "google_compute_ha_vpn_gateway" "gcp_gateway" {
name = "ha-vpn-gateway"
network = google_compute_network.vpc.id
region = "us-central1"
}
# 3. External VPN Gateway (Representation of your On-Prem/AWS Router)
resource "google_compute_external_vpn_gateway" "on_prem_gateway" {
name = "on-prem-gateway"
redundancy_type = "TWO_IPS_REDUNDANCY"
description = "The customer datacenter Cisco CSR"
interface {
id = 0
ip_address = "8.8.8.8" # Mock public IP 1
}
interface {
id = 1
ip_address = "8.8.4.4" # Mock public IP 2
}
}
resource "random_password" "shared_secret" { length = 16; special = false }
# 4. VPN Tunnels (Data Plane)
resource "google_compute_vpn_tunnel" "tunnel_0" {
name = "tunnel-0"
region = "us-central1"
vpn_gateway = google_compute_ha_vpn_gateway.gcp_gateway.id
peer_external_gateway = google_compute_external_vpn_gateway.on_prem_gateway.id
peer_external_gateway_interface = 0
shared_secret = random_password.shared_secret.result
router = google_compute_router.bgp_router.name
vpn_gateway_interface = 0
}
resource "google_compute_vpn_tunnel" "tunnel_1" {
name = "tunnel-1"
region = "us-central1"
vpn_gateway = google_compute_ha_vpn_gateway.gcp_gateway.id
peer_external_gateway = google_compute_external_vpn_gateway.on_prem_gateway.id
peer_external_gateway_interface = 1
shared_secret = random_password.shared_secret.result
router = google_compute_router.bgp_router.name
vpn_gateway_interface = 1
}
# 5. BGP Sessions (Control Plane)
# Interface binds to Tunnel 0
resource "google_compute_router_interface" "router_if0" {
name = "router-if-0"
router = google_compute_router.bgp_router.name
region = "us-central1"
ip_range = "169.254.0.1/30"
vpn_tunnel = google_compute_vpn_tunnel.tunnel_0.name
}
# Peering to On-Prem via Tunnel 0
resource "google_compute_router_peer" "router_peer_0" {
name = "router-peer-0"
router = google_compute_router.bgp_router.name
region = "us-central1"
peer_ip_address = "169.254.0.2"
peer_asn = 65001 # The On-Prem ASN
advertised_route_priority = 100
interface = google_compute_router_interface.router_if0.name
}
# Interface binds to Tunnel 1 ... (Repeated for secondary HA path, using 169.254.1.x subnet)
resource "google_compute_router_interface" "router_if1" {
name = "router-if-1"
router = google_compute_router.bgp_router.name
region = "us-central1"
ip_range = "169.254.1.1/30"
vpn_tunnel = google_compute_vpn_tunnel.tunnel_1.name
}
resource "google_compute_router_peer" "router_peer_1" {
name = "router-peer-1"
router = google_compute_router.bgp_router.name
region = "us-central1"
peer_ip_address = "169.254.1.2"
peer_asn = 65001
advertised_route_priority = 100
interface = google_compute_router_interface.router_if1.name
}Workflow Commands
terraform init
terraform apply -var="project_id=my-gcp-project-123"
# Verify the VPN gateways and tunnel configuration
gcloud compute vpn-tunnels list
gcloud compute routers get-status hybrid-bgp-router --region us-central1
# Status will show BGP sessions as DOWN since the mock 8.8.8.8 endpoint isn't
# actually a responding VPN router configuring the other side of the handshake.
terraform destroy -var="project_id=my-gcp-project-123"
