The gcp:compute/routerPeer:RouterPeer resource, part of the Pulumi GCP provider, configures BGP peering sessions on Cloud Routers: peer ASN, interface binding, route priorities, and session parameters. This guide focuses on four capabilities: basic BGP session establishment, BFD failure detection, third-party appliance peering, and route filtering with policies.
BGP peers require existing Cloud Routers with configured interfaces, and may reference VPN tunnels, Interconnect attachments, or Network Connectivity infrastructure. The examples are intentionally small. Combine them with your own routing infrastructure and connectivity setup.
Establish a basic BGP peering session
Most BGP deployments begin by establishing a peering session between a Cloud Router and an external peer, exchanging routing information to enable connectivity between networks.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const peer = new gcp.compute.RouterPeer("peer", {
name: "my-router-peer",
router: "my-router",
region: "us-central1",
peerAsn: 65513,
advertisedRoutePriority: 100,
"interface": "interface-1",
});
import pulumi
import pulumi_gcp as gcp
peer = gcp.compute.RouterPeer("peer",
name="my-router-peer",
router="my-router",
region="us-central1",
peer_asn=65513,
advertised_route_priority=100,
interface="interface-1")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewRouterPeer(ctx, "peer", &compute.RouterPeerArgs{
Name: pulumi.String("my-router-peer"),
Router: pulumi.String("my-router"),
Region: pulumi.String("us-central1"),
PeerAsn: pulumi.Int(65513),
AdvertisedRoutePriority: pulumi.Int(100),
Interface: pulumi.String("interface-1"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var peer = new Gcp.Compute.RouterPeer("peer", new()
{
Name = "my-router-peer",
Router = "my-router",
Region = "us-central1",
PeerAsn = 65513,
AdvertisedRoutePriority = 100,
Interface = "interface-1",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.RouterPeer;
import com.pulumi.gcp.compute.RouterPeerArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var peer = new RouterPeer("peer", RouterPeerArgs.builder()
.name("my-router-peer")
.router("my-router")
.region("us-central1")
.peerAsn(65513)
.advertisedRoutePriority(100)
.interface_("interface-1")
.build());
}
}
resources:
peer:
type: gcp:compute:RouterPeer
properties:
name: my-router-peer
router: my-router
region: us-central1
peerAsn: 65513
advertisedRoutePriority: 100
interface: interface-1
The peerAsn property specifies the Autonomous System Number of the external peer. The interface property binds the peer to a specific router interface. The advertisedRoutePriority controls route preference when multiple paths exist to the same destination; lower values win.
Enable fast failure detection with BFD
Networks that require rapid detection of link failures use Bidirectional Forwarding Detection (BFD) to monitor BGP session health and trigger faster failover than BGP keepalives alone.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const peer = new gcp.compute.RouterPeer("peer", {
name: "my-router-peer",
router: "my-router",
region: "us-central1",
peerIpAddress: "169.254.1.2",
peerAsn: 65513,
advertisedRoutePriority: 100,
"interface": "interface-1",
bfd: {
minReceiveInterval: 1000,
minTransmitInterval: 1000,
multiplier: 5,
sessionInitializationMode: "ACTIVE",
},
});
import pulumi
import pulumi_gcp as gcp
peer = gcp.compute.RouterPeer("peer",
name="my-router-peer",
router="my-router",
region="us-central1",
peer_ip_address="169.254.1.2",
peer_asn=65513,
advertised_route_priority=100,
interface="interface-1",
bfd={
"min_receive_interval": 1000,
"min_transmit_interval": 1000,
"multiplier": 5,
"session_initialization_mode": "ACTIVE",
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewRouterPeer(ctx, "peer", &compute.RouterPeerArgs{
Name: pulumi.String("my-router-peer"),
Router: pulumi.String("my-router"),
Region: pulumi.String("us-central1"),
PeerIpAddress: pulumi.String("169.254.1.2"),
PeerAsn: pulumi.Int(65513),
AdvertisedRoutePriority: pulumi.Int(100),
Interface: pulumi.String("interface-1"),
Bfd: &compute.RouterPeerBfdArgs{
MinReceiveInterval: pulumi.Int(1000),
MinTransmitInterval: pulumi.Int(1000),
Multiplier: pulumi.Int(5),
SessionInitializationMode: pulumi.String("ACTIVE"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var peer = new Gcp.Compute.RouterPeer("peer", new()
{
Name = "my-router-peer",
Router = "my-router",
Region = "us-central1",
PeerIpAddress = "169.254.1.2",
PeerAsn = 65513,
AdvertisedRoutePriority = 100,
Interface = "interface-1",
Bfd = new Gcp.Compute.Inputs.RouterPeerBfdArgs
{
MinReceiveInterval = 1000,
MinTransmitInterval = 1000,
Multiplier = 5,
SessionInitializationMode = "ACTIVE",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.RouterPeer;
import com.pulumi.gcp.compute.RouterPeerArgs;
import com.pulumi.gcp.compute.inputs.RouterPeerBfdArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var peer = new RouterPeer("peer", RouterPeerArgs.builder()
.name("my-router-peer")
.router("my-router")
.region("us-central1")
.peerIpAddress("169.254.1.2")
.peerAsn(65513)
.advertisedRoutePriority(100)
.interface_("interface-1")
.bfd(RouterPeerBfdArgs.builder()
.minReceiveInterval(1000)
.minTransmitInterval(1000)
.multiplier(5)
.sessionInitializationMode("ACTIVE")
.build())
.build());
}
}
resources:
peer:
type: gcp:compute:RouterPeer
properties:
name: my-router-peer
router: my-router
region: us-central1
peerIpAddress: 169.254.1.2
peerAsn: 65513
advertisedRoutePriority: 100
interface: interface-1
bfd:
minReceiveInterval: 1000
minTransmitInterval: 1000
multiplier: 5
sessionInitializationMode: ACTIVE
The bfd block configures failure detection timing. The minReceiveInterval and minTransmitInterval set how frequently BFD packets are exchanged (in milliseconds). The multiplier determines how many missed packets trigger failure detection. The sessionInitializationMode controls whether this peer actively initiates BFD or waits passively. This configuration detects failures in approximately 5 seconds (1000ms × 5 missed packets).
Peer with third-party network appliances
Hybrid cloud architectures often route traffic through third-party appliances like firewalls or SD-WAN devices. Cloud Router can peer with these appliances via BGP to exchange routes.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const network = new gcp.compute.Network("network", {
name: "my-router-net",
autoCreateSubnetworks: false,
});
const subnetwork = new gcp.compute.Subnetwork("subnetwork", {
name: "my-router-sub",
network: network.selfLink,
ipCidrRange: "10.0.0.0/16",
region: "us-central1",
});
const addrIntf = new gcp.compute.Address("addr_intf", {
name: "my-router-addr-intf",
region: subnetwork.region,
subnetwork: subnetwork.id,
addressType: "INTERNAL",
});
const addrIntfRedundant = new gcp.compute.Address("addr_intf_redundant", {
name: "my-router-addr-intf-red",
region: subnetwork.region,
subnetwork: subnetwork.id,
addressType: "INTERNAL",
});
const addrPeer = new gcp.compute.Address("addr_peer", {
name: "my-router-addr-peer",
region: subnetwork.region,
subnetwork: subnetwork.id,
addressType: "INTERNAL",
});
const instance = new gcp.compute.Instance("instance", {
name: "router-appliance",
zone: "us-central1-a",
machineType: "e2-medium",
canIpForward: true,
bootDisk: {
initializeParams: {
image: "debian-cloud/debian-11",
},
},
networkInterfaces: [{
networkIp: addrPeer.address,
subnetwork: subnetwork.selfLink,
}],
});
const hub = new gcp.networkconnectivity.Hub("hub", {name: "my-router-hub"});
const spoke = new gcp.networkconnectivity.Spoke("spoke", {
name: "my-router-spoke",
location: subnetwork.region,
hub: hub.id,
linkedRouterApplianceInstances: {
instances: [{
virtualMachine: instance.selfLink,
ipAddress: addrPeer.address,
}],
siteToSiteDataTransfer: false,
},
});
const router = new gcp.compute.Router("router", {
name: "my-router-router",
region: subnetwork.region,
network: network.selfLink,
bgp: {
asn: 64514,
},
});
const interfaceRedundant = new gcp.compute.RouterInterface("interface_redundant", {
name: "my-router-intf-red",
region: router.region,
router: router.name,
subnetwork: subnetwork.selfLink,
privateIpAddress: addrIntfRedundant.address,
});
const _interface = new gcp.compute.RouterInterface("interface", {
name: "my-router-intf",
region: router.region,
router: router.name,
subnetwork: subnetwork.selfLink,
privateIpAddress: addrIntf.address,
redundantInterface: interfaceRedundant.name,
});
const peer = new gcp.compute.RouterPeer("peer", {
name: "my-router-peer",
router: router.name,
region: router.region,
"interface": _interface.name,
routerApplianceInstance: instance.selfLink,
peerAsn: 65513,
peerIpAddress: addrPeer.address,
});
import pulumi
import pulumi_gcp as gcp
network = gcp.compute.Network("network",
name="my-router-net",
auto_create_subnetworks=False)
subnetwork = gcp.compute.Subnetwork("subnetwork",
name="my-router-sub",
network=network.self_link,
ip_cidr_range="10.0.0.0/16",
region="us-central1")
addr_intf = gcp.compute.Address("addr_intf",
name="my-router-addr-intf",
region=subnetwork.region,
subnetwork=subnetwork.id,
address_type="INTERNAL")
addr_intf_redundant = gcp.compute.Address("addr_intf_redundant",
name="my-router-addr-intf-red",
region=subnetwork.region,
subnetwork=subnetwork.id,
address_type="INTERNAL")
addr_peer = gcp.compute.Address("addr_peer",
name="my-router-addr-peer",
region=subnetwork.region,
subnetwork=subnetwork.id,
address_type="INTERNAL")
instance = gcp.compute.Instance("instance",
name="router-appliance",
zone="us-central1-a",
machine_type="e2-medium",
can_ip_forward=True,
boot_disk={
"initialize_params": {
"image": "debian-cloud/debian-11",
},
},
network_interfaces=[{
"network_ip": addr_peer.address,
"subnetwork": subnetwork.self_link,
}])
hub = gcp.networkconnectivity.Hub("hub", name="my-router-hub")
spoke = gcp.networkconnectivity.Spoke("spoke",
name="my-router-spoke",
location=subnetwork.region,
hub=hub.id,
linked_router_appliance_instances={
"instances": [{
"virtual_machine": instance.self_link,
"ip_address": addr_peer.address,
}],
"site_to_site_data_transfer": False,
})
router = gcp.compute.Router("router",
name="my-router-router",
region=subnetwork.region,
network=network.self_link,
bgp={
"asn": 64514,
})
interface_redundant = gcp.compute.RouterInterface("interface_redundant",
name="my-router-intf-red",
region=router.region,
router=router.name,
subnetwork=subnetwork.self_link,
private_ip_address=addr_intf_redundant.address)
interface = gcp.compute.RouterInterface("interface",
name="my-router-intf",
region=router.region,
router=router.name,
subnetwork=subnetwork.self_link,
private_ip_address=addr_intf.address,
redundant_interface=interface_redundant.name)
peer = gcp.compute.RouterPeer("peer",
name="my-router-peer",
router=router.name,
region=router.region,
interface=interface.name,
router_appliance_instance=instance.self_link,
peer_asn=65513,
peer_ip_address=addr_peer.address)
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networkconnectivity"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
network, err := compute.NewNetwork(ctx, "network", &compute.NetworkArgs{
Name: pulumi.String("my-router-net"),
AutoCreateSubnetworks: pulumi.Bool(false),
})
if err != nil {
return err
}
subnetwork, err := compute.NewSubnetwork(ctx, "subnetwork", &compute.SubnetworkArgs{
Name: pulumi.String("my-router-sub"),
Network: network.SelfLink,
IpCidrRange: pulumi.String("10.0.0.0/16"),
Region: pulumi.String("us-central1"),
})
if err != nil {
return err
}
addrIntf, err := compute.NewAddress(ctx, "addr_intf", &compute.AddressArgs{
Name: pulumi.String("my-router-addr-intf"),
Region: subnetwork.Region,
Subnetwork: subnetwork.ID(),
AddressType: pulumi.String("INTERNAL"),
})
if err != nil {
return err
}
addrIntfRedundant, err := compute.NewAddress(ctx, "addr_intf_redundant", &compute.AddressArgs{
Name: pulumi.String("my-router-addr-intf-red"),
Region: subnetwork.Region,
Subnetwork: subnetwork.ID(),
AddressType: pulumi.String("INTERNAL"),
})
if err != nil {
return err
}
addrPeer, err := compute.NewAddress(ctx, "addr_peer", &compute.AddressArgs{
Name: pulumi.String("my-router-addr-peer"),
Region: subnetwork.Region,
Subnetwork: subnetwork.ID(),
AddressType: pulumi.String("INTERNAL"),
})
if err != nil {
return err
}
instance, err := compute.NewInstance(ctx, "instance", &compute.InstanceArgs{
Name: pulumi.String("router-appliance"),
Zone: pulumi.String("us-central1-a"),
MachineType: pulumi.String("e2-medium"),
CanIpForward: pulumi.Bool(true),
BootDisk: &compute.InstanceBootDiskArgs{
InitializeParams: &compute.InstanceBootDiskInitializeParamsArgs{
Image: pulumi.String("debian-cloud/debian-11"),
},
},
NetworkInterfaces: compute.InstanceNetworkInterfaceArray{
&compute.InstanceNetworkInterfaceArgs{
NetworkIp: addrPeer.Address,
Subnetwork: subnetwork.SelfLink,
},
},
})
if err != nil {
return err
}
hub, err := networkconnectivity.NewHub(ctx, "hub", &networkconnectivity.HubArgs{
Name: pulumi.String("my-router-hub"),
})
if err != nil {
return err
}
_, err = networkconnectivity.NewSpoke(ctx, "spoke", &networkconnectivity.SpokeArgs{
Name: pulumi.String("my-router-spoke"),
Location: subnetwork.Region,
Hub: hub.ID(),
LinkedRouterApplianceInstances: &networkconnectivity.SpokeLinkedRouterApplianceInstancesArgs{
Instances: networkconnectivity.SpokeLinkedRouterApplianceInstancesInstanceArray{
&networkconnectivity.SpokeLinkedRouterApplianceInstancesInstanceArgs{
VirtualMachine: instance.SelfLink,
IpAddress: addrPeer.Address,
},
},
SiteToSiteDataTransfer: pulumi.Bool(false),
},
})
if err != nil {
return err
}
router, err := compute.NewRouter(ctx, "router", &compute.RouterArgs{
Name: pulumi.String("my-router-router"),
Region: subnetwork.Region,
Network: network.SelfLink,
Bgp: &compute.RouterBgpArgs{
Asn: pulumi.Int(64514),
},
})
if err != nil {
return err
}
interfaceRedundant, err := compute.NewRouterInterface(ctx, "interface_redundant", &compute.RouterInterfaceArgs{
Name: pulumi.String("my-router-intf-red"),
Region: router.Region,
Router: router.Name,
Subnetwork: subnetwork.SelfLink,
PrivateIpAddress: addrIntfRedundant.Address,
})
if err != nil {
return err
}
interface, err := compute.NewRouterInterface(ctx, "interface", &compute.RouterInterfaceArgs{
Name: pulumi.String("my-router-intf"),
Region: router.Region,
Router: router.Name,
Subnetwork: subnetwork.SelfLink,
PrivateIpAddress: addrIntf.Address,
RedundantInterface: interfaceRedundant.Name,
})
if err != nil {
return err
}
_, err = compute.NewRouterPeer(ctx, "peer", &compute.RouterPeerArgs{
Name: pulumi.String("my-router-peer"),
Router: router.Name,
Region: router.Region,
Interface: interface.Name,
RouterApplianceInstance: instance.SelfLink,
PeerAsn: pulumi.Int(65513),
PeerIpAddress: addrPeer.Address,
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var network = new Gcp.Compute.Network("network", new()
{
Name = "my-router-net",
AutoCreateSubnetworks = false,
});
var subnetwork = new Gcp.Compute.Subnetwork("subnetwork", new()
{
Name = "my-router-sub",
Network = network.SelfLink,
IpCidrRange = "10.0.0.0/16",
Region = "us-central1",
});
var addrIntf = new Gcp.Compute.Address("addr_intf", new()
{
Name = "my-router-addr-intf",
Region = subnetwork.Region,
Subnetwork = subnetwork.Id,
AddressType = "INTERNAL",
});
var addrIntfRedundant = new Gcp.Compute.Address("addr_intf_redundant", new()
{
Name = "my-router-addr-intf-red",
Region = subnetwork.Region,
Subnetwork = subnetwork.Id,
AddressType = "INTERNAL",
});
var addrPeer = new Gcp.Compute.Address("addr_peer", new()
{
Name = "my-router-addr-peer",
Region = subnetwork.Region,
Subnetwork = subnetwork.Id,
AddressType = "INTERNAL",
});
var instance = new Gcp.Compute.Instance("instance", new()
{
Name = "router-appliance",
Zone = "us-central1-a",
MachineType = "e2-medium",
CanIpForward = true,
BootDisk = new Gcp.Compute.Inputs.InstanceBootDiskArgs
{
InitializeParams = new Gcp.Compute.Inputs.InstanceBootDiskInitializeParamsArgs
{
Image = "debian-cloud/debian-11",
},
},
NetworkInterfaces = new[]
{
new Gcp.Compute.Inputs.InstanceNetworkInterfaceArgs
{
NetworkIp = addrPeer.IPAddress,
Subnetwork = subnetwork.SelfLink,
},
},
});
var hub = new Gcp.NetworkConnectivity.Hub("hub", new()
{
Name = "my-router-hub",
});
var spoke = new Gcp.NetworkConnectivity.Spoke("spoke", new()
{
Name = "my-router-spoke",
Location = subnetwork.Region,
Hub = hub.Id,
LinkedRouterApplianceInstances = new Gcp.NetworkConnectivity.Inputs.SpokeLinkedRouterApplianceInstancesArgs
{
Instances = new[]
{
new Gcp.NetworkConnectivity.Inputs.SpokeLinkedRouterApplianceInstancesInstanceArgs
{
VirtualMachine = instance.SelfLink,
IpAddress = addrPeer.IPAddress,
},
},
SiteToSiteDataTransfer = false,
},
});
var router = new Gcp.Compute.Router("router", new()
{
Name = "my-router-router",
Region = subnetwork.Region,
Network = network.SelfLink,
Bgp = new Gcp.Compute.Inputs.RouterBgpArgs
{
Asn = 64514,
},
});
var interfaceRedundant = new Gcp.Compute.RouterInterface("interface_redundant", new()
{
Name = "my-router-intf-red",
Region = router.Region,
Router = router.Name,
Subnetwork = subnetwork.SelfLink,
PrivateIpAddress = addrIntfRedundant.IPAddress,
});
var @interface = new Gcp.Compute.RouterInterface("interface", new()
{
Name = "my-router-intf",
Region = router.Region,
Router = router.Name,
Subnetwork = subnetwork.SelfLink,
PrivateIpAddress = addrIntf.IPAddress,
RedundantInterface = interfaceRedundant.Name,
});
var peer = new Gcp.Compute.RouterPeer("peer", new()
{
Name = "my-router-peer",
Router = router.Name,
Region = router.Region,
Interface = @interface.Name,
RouterApplianceInstance = instance.SelfLink,
PeerAsn = 65513,
PeerIpAddress = addrPeer.IPAddress,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.compute.Subnetwork;
import com.pulumi.gcp.compute.SubnetworkArgs;
import com.pulumi.gcp.compute.Address;
import com.pulumi.gcp.compute.AddressArgs;
import com.pulumi.gcp.compute.Instance;
import com.pulumi.gcp.compute.InstanceArgs;
import com.pulumi.gcp.compute.inputs.InstanceBootDiskArgs;
import com.pulumi.gcp.compute.inputs.InstanceBootDiskInitializeParamsArgs;
import com.pulumi.gcp.compute.inputs.InstanceNetworkInterfaceArgs;
import com.pulumi.gcp.networkconnectivity.Hub;
import com.pulumi.gcp.networkconnectivity.HubArgs;
import com.pulumi.gcp.networkconnectivity.Spoke;
import com.pulumi.gcp.networkconnectivity.SpokeArgs;
import com.pulumi.gcp.networkconnectivity.inputs.SpokeLinkedRouterApplianceInstancesArgs;
import com.pulumi.gcp.compute.Router;
import com.pulumi.gcp.compute.RouterArgs;
import com.pulumi.gcp.compute.inputs.RouterBgpArgs;
import com.pulumi.gcp.compute.RouterInterface;
import com.pulumi.gcp.compute.RouterInterfaceArgs;
import com.pulumi.gcp.compute.RouterPeer;
import com.pulumi.gcp.compute.RouterPeerArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var network = new Network("network", NetworkArgs.builder()
.name("my-router-net")
.autoCreateSubnetworks(false)
.build());
var subnetwork = new Subnetwork("subnetwork", SubnetworkArgs.builder()
.name("my-router-sub")
.network(network.selfLink())
.ipCidrRange("10.0.0.0/16")
.region("us-central1")
.build());
var addrIntf = new Address("addrIntf", AddressArgs.builder()
.name("my-router-addr-intf")
.region(subnetwork.region())
.subnetwork(subnetwork.id())
.addressType("INTERNAL")
.build());
var addrIntfRedundant = new Address("addrIntfRedundant", AddressArgs.builder()
.name("my-router-addr-intf-red")
.region(subnetwork.region())
.subnetwork(subnetwork.id())
.addressType("INTERNAL")
.build());
var addrPeer = new Address("addrPeer", AddressArgs.builder()
.name("my-router-addr-peer")
.region(subnetwork.region())
.subnetwork(subnetwork.id())
.addressType("INTERNAL")
.build());
var instance = new Instance("instance", InstanceArgs.builder()
.name("router-appliance")
.zone("us-central1-a")
.machineType("e2-medium")
.canIpForward(true)
.bootDisk(InstanceBootDiskArgs.builder()
.initializeParams(InstanceBootDiskInitializeParamsArgs.builder()
.image("debian-cloud/debian-11")
.build())
.build())
.networkInterfaces(InstanceNetworkInterfaceArgs.builder()
.networkIp(addrPeer.address())
.subnetwork(subnetwork.selfLink())
.build())
.build());
var hub = new Hub("hub", HubArgs.builder()
.name("my-router-hub")
.build());
var spoke = new Spoke("spoke", SpokeArgs.builder()
.name("my-router-spoke")
.location(subnetwork.region())
.hub(hub.id())
.linkedRouterApplianceInstances(SpokeLinkedRouterApplianceInstancesArgs.builder()
.instances(SpokeLinkedRouterApplianceInstancesInstanceArgs.builder()
.virtualMachine(instance.selfLink())
.ipAddress(addrPeer.address())
.build())
.siteToSiteDataTransfer(false)
.build())
.build());
var router = new Router("router", RouterArgs.builder()
.name("my-router-router")
.region(subnetwork.region())
.network(network.selfLink())
.bgp(RouterBgpArgs.builder()
.asn(64514)
.build())
.build());
var interfaceRedundant = new RouterInterface("interfaceRedundant", RouterInterfaceArgs.builder()
.name("my-router-intf-red")
.region(router.region())
.router(router.name())
.subnetwork(subnetwork.selfLink())
.privateIpAddress(addrIntfRedundant.address())
.build());
var interface_ = new RouterInterface("interface", RouterInterfaceArgs.builder()
.name("my-router-intf")
.region(router.region())
.router(router.name())
.subnetwork(subnetwork.selfLink())
.privateIpAddress(addrIntf.address())
.redundantInterface(interfaceRedundant.name())
.build());
var peer = new RouterPeer("peer", RouterPeerArgs.builder()
.name("my-router-peer")
.router(router.name())
.region(router.region())
.interface_(interface_.name())
.routerApplianceInstance(instance.selfLink())
.peerAsn(65513)
.peerIpAddress(addrPeer.address())
.build());
}
}
resources:
network:
type: gcp:compute:Network
properties:
name: my-router-net
autoCreateSubnetworks: false
subnetwork:
type: gcp:compute:Subnetwork
properties:
name: my-router-sub
network: ${network.selfLink}
ipCidrRange: 10.0.0.0/16
region: us-central1
addrIntf:
type: gcp:compute:Address
name: addr_intf
properties:
name: my-router-addr-intf
region: ${subnetwork.region}
subnetwork: ${subnetwork.id}
addressType: INTERNAL
addrIntfRedundant:
type: gcp:compute:Address
name: addr_intf_redundant
properties:
name: my-router-addr-intf-red
region: ${subnetwork.region}
subnetwork: ${subnetwork.id}
addressType: INTERNAL
addrPeer:
type: gcp:compute:Address
name: addr_peer
properties:
name: my-router-addr-peer
region: ${subnetwork.region}
subnetwork: ${subnetwork.id}
addressType: INTERNAL
instance:
type: gcp:compute:Instance
properties:
name: router-appliance
zone: us-central1-a
machineType: e2-medium
canIpForward: true
bootDisk:
initializeParams:
image: debian-cloud/debian-11
networkInterfaces:
- networkIp: ${addrPeer.address}
subnetwork: ${subnetwork.selfLink}
hub:
type: gcp:networkconnectivity:Hub
properties:
name: my-router-hub
spoke:
type: gcp:networkconnectivity:Spoke
properties:
name: my-router-spoke
location: ${subnetwork.region}
hub: ${hub.id}
linkedRouterApplianceInstances:
instances:
- virtualMachine: ${instance.selfLink}
ipAddress: ${addrPeer.address}
siteToSiteDataTransfer: false
router:
type: gcp:compute:Router
properties:
name: my-router-router
region: ${subnetwork.region}
network: ${network.selfLink}
bgp:
asn: 64514
interfaceRedundant:
type: gcp:compute:RouterInterface
name: interface_redundant
properties:
name: my-router-intf-red
region: ${router.region}
router: ${router.name}
subnetwork: ${subnetwork.selfLink}
privateIpAddress: ${addrIntfRedundant.address}
interface:
type: gcp:compute:RouterInterface
properties:
name: my-router-intf
region: ${router.region}
router: ${router.name}
subnetwork: ${subnetwork.selfLink}
privateIpAddress: ${addrIntf.address}
redundantInterface: ${interfaceRedundant.name}
peer:
type: gcp:compute:RouterPeer
properties:
name: my-router-peer
router: ${router.name}
region: ${router.region}
interface: ${interface.name}
routerApplianceInstance: ${instance.selfLink}
peerAsn: 65513
peerIpAddress: ${addrPeer.address}
The routerApplianceInstance property references the VM instance running the network appliance. The peerIpAddress specifies the appliance’s BGP endpoint. This configuration requires a Network Connectivity Hub and Spoke to register the appliance instance. The spoke’s linkedRouterApplianceInstances block associates the VM with the hub, enabling Cloud Router to establish BGP sessions with it.
Control route advertisement with import and export policies
Production BGP deployments need fine-grained control over which routes are learned from peers and which routes are advertised outbound. Route policies use expressions to filter and manipulate routing information.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const network = new gcp.compute.Network("network", {
name: "my-router-net",
autoCreateSubnetworks: false,
});
const subnetwork = new gcp.compute.Subnetwork("subnetwork", {
name: "my-router-subnet",
network: network.selfLink,
ipCidrRange: "10.0.0.0/16",
region: "us-central1",
});
const address = new gcp.compute.Address("address", {
name: "my-router",
region: subnetwork.region,
});
const vpnGateway = new gcp.compute.HaVpnGateway("vpn_gateway", {
name: "my-router-gateway",
network: network.selfLink,
region: subnetwork.region,
});
const externalGateway = new gcp.compute.ExternalVpnGateway("external_gateway", {
name: "my-router-external-gateway",
redundancyType: "SINGLE_IP_INTERNALLY_REDUNDANT",
description: "An externally managed VPN gateway",
interfaces: [{
id: 0,
ipAddress: "8.8.8.8",
}],
});
const router = new gcp.compute.Router("router", {
name: "my-router",
region: subnetwork.region,
network: network.selfLink,
bgp: {
asn: 64514,
},
});
const vpnTunnel = new gcp.compute.VPNTunnel("vpn_tunnel", {
name: "my-router",
region: subnetwork.region,
vpnGateway: vpnGateway.id,
peerExternalGateway: externalGateway.id,
peerExternalGatewayInterface: 0,
sharedSecret: "unguessable",
router: router.name,
vpnGatewayInterface: 0,
});
const routerInterface = new gcp.compute.RouterInterface("router_interface", {
name: "my-router",
router: router.name,
region: router.region,
vpnTunnel: vpnTunnel.name,
});
const rp_export = new gcp.compute.RouterRoutePolicy("rp-export", {
name: "my-router-rp-export",
router: router.name,
region: router.region,
type: "ROUTE_POLICY_TYPE_EXPORT",
terms: [{
priority: 2,
match: {
expression: "destination == '10.0.0.0/12'",
title: "export_expression",
description: "acceptance expression for export",
},
actions: [{
expression: "accept()",
}],
}],
}, {
dependsOn: [routerInterface],
});
const rp_import = new gcp.compute.RouterRoutePolicy("rp-import", {
name: "my-router-rp-import",
router: router.name,
region: router.region,
type: "ROUTE_POLICY_TYPE_IMPORT",
terms: [{
priority: 1,
match: {
expression: "destination == '10.0.0.0/12'",
title: "import_expression",
description: "acceptance expression for import",
},
actions: [{
expression: "accept()",
}],
}],
}, {
dependsOn: [
routerInterface,
rp_export,
],
});
const routerPeer = new gcp.compute.RouterPeer("router_peer", {
name: "my-router-peer",
router: router.name,
region: router.region,
peerAsn: 65515,
advertisedRoutePriority: 100,
"interface": routerInterface.name,
md5AuthenticationKey: {
name: "my-router-peer-key",
key: "my-router-peer-key-value",
},
importPolicies: [rp_import.name],
exportPolicies: [rp_export.name],
}, {
dependsOn: [
rp_export,
rp_import,
routerInterface,
],
});
import pulumi
import pulumi_gcp as gcp
network = gcp.compute.Network("network",
name="my-router-net",
auto_create_subnetworks=False)
subnetwork = gcp.compute.Subnetwork("subnetwork",
name="my-router-subnet",
network=network.self_link,
ip_cidr_range="10.0.0.0/16",
region="us-central1")
address = gcp.compute.Address("address",
name="my-router",
region=subnetwork.region)
vpn_gateway = gcp.compute.HaVpnGateway("vpn_gateway",
name="my-router-gateway",
network=network.self_link,
region=subnetwork.region)
external_gateway = gcp.compute.ExternalVpnGateway("external_gateway",
name="my-router-external-gateway",
redundancy_type="SINGLE_IP_INTERNALLY_REDUNDANT",
description="An externally managed VPN gateway",
interfaces=[{
"id": 0,
"ip_address": "8.8.8.8",
}])
router = gcp.compute.Router("router",
name="my-router",
region=subnetwork.region,
network=network.self_link,
bgp={
"asn": 64514,
})
vpn_tunnel = gcp.compute.VPNTunnel("vpn_tunnel",
name="my-router",
region=subnetwork.region,
vpn_gateway=vpn_gateway.id,
peer_external_gateway=external_gateway.id,
peer_external_gateway_interface=0,
shared_secret="unguessable",
router=router.name,
vpn_gateway_interface=0)
router_interface = gcp.compute.RouterInterface("router_interface",
name="my-router",
router=router.name,
region=router.region,
vpn_tunnel=vpn_tunnel.name)
rp_export = gcp.compute.RouterRoutePolicy("rp-export",
name="my-router-rp-export",
router=router.name,
region=router.region,
type="ROUTE_POLICY_TYPE_EXPORT",
terms=[{
"priority": 2,
"match": {
"expression": "destination == '10.0.0.0/12'",
"title": "export_expression",
"description": "acceptance expression for export",
},
"actions": [{
"expression": "accept()",
}],
}],
opts = pulumi.ResourceOptions(depends_on=[router_interface]))
rp_import = gcp.compute.RouterRoutePolicy("rp-import",
name="my-router-rp-import",
router=router.name,
region=router.region,
type="ROUTE_POLICY_TYPE_IMPORT",
terms=[{
"priority": 1,
"match": {
"expression": "destination == '10.0.0.0/12'",
"title": "import_expression",
"description": "acceptance expression for import",
},
"actions": [{
"expression": "accept()",
}],
}],
opts = pulumi.ResourceOptions(depends_on=[
router_interface,
rp_export,
]))
router_peer = gcp.compute.RouterPeer("router_peer",
name="my-router-peer",
router=router.name,
region=router.region,
peer_asn=65515,
advertised_route_priority=100,
interface=router_interface.name,
md5_authentication_key={
"name": "my-router-peer-key",
"key": "my-router-peer-key-value",
},
import_policies=[rp_import.name],
export_policies=[rp_export.name],
opts = pulumi.ResourceOptions(depends_on=[
rp_export,
rp_import,
router_interface,
]))
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
network, err := compute.NewNetwork(ctx, "network", &compute.NetworkArgs{
Name: pulumi.String("my-router-net"),
AutoCreateSubnetworks: pulumi.Bool(false),
})
if err != nil {
return err
}
subnetwork, err := compute.NewSubnetwork(ctx, "subnetwork", &compute.SubnetworkArgs{
Name: pulumi.String("my-router-subnet"),
Network: network.SelfLink,
IpCidrRange: pulumi.String("10.0.0.0/16"),
Region: pulumi.String("us-central1"),
})
if err != nil {
return err
}
_, err = compute.NewAddress(ctx, "address", &compute.AddressArgs{
Name: pulumi.String("my-router"),
Region: subnetwork.Region,
})
if err != nil {
return err
}
vpnGateway, err := compute.NewHaVpnGateway(ctx, "vpn_gateway", &compute.HaVpnGatewayArgs{
Name: pulumi.String("my-router-gateway"),
Network: network.SelfLink,
Region: subnetwork.Region,
})
if err != nil {
return err
}
externalGateway, err := compute.NewExternalVpnGateway(ctx, "external_gateway", &compute.ExternalVpnGatewayArgs{
Name: pulumi.String("my-router-external-gateway"),
RedundancyType: pulumi.String("SINGLE_IP_INTERNALLY_REDUNDANT"),
Description: pulumi.String("An externally managed VPN gateway"),
Interfaces: compute.ExternalVpnGatewayInterfaceArray{
&compute.ExternalVpnGatewayInterfaceArgs{
Id: pulumi.Int(0),
IpAddress: pulumi.String("8.8.8.8"),
},
},
})
if err != nil {
return err
}
router, err := compute.NewRouter(ctx, "router", &compute.RouterArgs{
Name: pulumi.String("my-router"),
Region: subnetwork.Region,
Network: network.SelfLink,
Bgp: &compute.RouterBgpArgs{
Asn: pulumi.Int(64514),
},
})
if err != nil {
return err
}
vpnTunnel, err := compute.NewVPNTunnel(ctx, "vpn_tunnel", &compute.VPNTunnelArgs{
Name: pulumi.String("my-router"),
Region: subnetwork.Region,
VpnGateway: vpnGateway.ID(),
PeerExternalGateway: externalGateway.ID(),
PeerExternalGatewayInterface: pulumi.Int(0),
SharedSecret: pulumi.String("unguessable"),
Router: router.Name,
VpnGatewayInterface: pulumi.Int(0),
})
if err != nil {
return err
}
routerInterface, err := compute.NewRouterInterface(ctx, "router_interface", &compute.RouterInterfaceArgs{
Name: pulumi.String("my-router"),
Router: router.Name,
Region: router.Region,
VpnTunnel: vpnTunnel.Name,
})
if err != nil {
return err
}
rp_export, err := compute.NewRouterRoutePolicy(ctx, "rp-export", &compute.RouterRoutePolicyArgs{
Name: pulumi.String("my-router-rp-export"),
Router: router.Name,
Region: router.Region,
Type: pulumi.String("ROUTE_POLICY_TYPE_EXPORT"),
Terms: compute.RouterRoutePolicyTermArray{
&compute.RouterRoutePolicyTermArgs{
Priority: pulumi.Int(2),
Match: &compute.RouterRoutePolicyTermMatchArgs{
Expression: pulumi.String("destination == '10.0.0.0/12'"),
Title: pulumi.String("export_expression"),
Description: pulumi.String("acceptance expression for export"),
},
Actions: compute.RouterRoutePolicyTermActionArray{
&compute.RouterRoutePolicyTermActionArgs{
Expression: pulumi.String("accept()"),
},
},
},
},
}, pulumi.DependsOn([]pulumi.Resource{
routerInterface,
}))
if err != nil {
return err
}
rp_import, err := compute.NewRouterRoutePolicy(ctx, "rp-import", &compute.RouterRoutePolicyArgs{
Name: pulumi.String("my-router-rp-import"),
Router: router.Name,
Region: router.Region,
Type: pulumi.String("ROUTE_POLICY_TYPE_IMPORT"),
Terms: compute.RouterRoutePolicyTermArray{
&compute.RouterRoutePolicyTermArgs{
Priority: pulumi.Int(1),
Match: &compute.RouterRoutePolicyTermMatchArgs{
Expression: pulumi.String("destination == '10.0.0.0/12'"),
Title: pulumi.String("import_expression"),
Description: pulumi.String("acceptance expression for import"),
},
Actions: compute.RouterRoutePolicyTermActionArray{
&compute.RouterRoutePolicyTermActionArgs{
Expression: pulumi.String("accept()"),
},
},
},
},
}, pulumi.DependsOn([]pulumi.Resource{
routerInterface,
rp_export,
}))
if err != nil {
return err
}
_, err = compute.NewRouterPeer(ctx, "router_peer", &compute.RouterPeerArgs{
Name: pulumi.String("my-router-peer"),
Router: router.Name,
Region: router.Region,
PeerAsn: pulumi.Int(65515),
AdvertisedRoutePriority: pulumi.Int(100),
Interface: routerInterface.Name,
Md5AuthenticationKey: &compute.RouterPeerMd5AuthenticationKeyArgs{
Name: pulumi.String("my-router-peer-key"),
Key: pulumi.String("my-router-peer-key-value"),
},
ImportPolicies: pulumi.StringArray{
rp_import.Name,
},
ExportPolicies: pulumi.StringArray{
rp_export.Name,
},
}, pulumi.DependsOn([]pulumi.Resource{
rp_export,
rp_import,
routerInterface,
}))
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var network = new Gcp.Compute.Network("network", new()
{
Name = "my-router-net",
AutoCreateSubnetworks = false,
});
var subnetwork = new Gcp.Compute.Subnetwork("subnetwork", new()
{
Name = "my-router-subnet",
Network = network.SelfLink,
IpCidrRange = "10.0.0.0/16",
Region = "us-central1",
});
var address = new Gcp.Compute.Address("address", new()
{
Name = "my-router",
Region = subnetwork.Region,
});
var vpnGateway = new Gcp.Compute.HaVpnGateway("vpn_gateway", new()
{
Name = "my-router-gateway",
Network = network.SelfLink,
Region = subnetwork.Region,
});
var externalGateway = new Gcp.Compute.ExternalVpnGateway("external_gateway", new()
{
Name = "my-router-external-gateway",
RedundancyType = "SINGLE_IP_INTERNALLY_REDUNDANT",
Description = "An externally managed VPN gateway",
Interfaces = new[]
{
new Gcp.Compute.Inputs.ExternalVpnGatewayInterfaceArgs
{
Id = 0,
IpAddress = "8.8.8.8",
},
},
});
var router = new Gcp.Compute.Router("router", new()
{
Name = "my-router",
Region = subnetwork.Region,
Network = network.SelfLink,
Bgp = new Gcp.Compute.Inputs.RouterBgpArgs
{
Asn = 64514,
},
});
var vpnTunnel = new Gcp.Compute.VPNTunnel("vpn_tunnel", new()
{
Name = "my-router",
Region = subnetwork.Region,
VpnGateway = vpnGateway.Id,
PeerExternalGateway = externalGateway.Id,
PeerExternalGatewayInterface = 0,
SharedSecret = "unguessable",
Router = router.Name,
VpnGatewayInterface = 0,
});
var routerInterface = new Gcp.Compute.RouterInterface("router_interface", new()
{
Name = "my-router",
Router = router.Name,
Region = router.Region,
VpnTunnel = vpnTunnel.Name,
});
var rp_export = new Gcp.Compute.RouterRoutePolicy("rp-export", new()
{
Name = "my-router-rp-export",
Router = router.Name,
Region = router.Region,
Type = "ROUTE_POLICY_TYPE_EXPORT",
Terms = new[]
{
new Gcp.Compute.Inputs.RouterRoutePolicyTermArgs
{
Priority = 2,
Match = new Gcp.Compute.Inputs.RouterRoutePolicyTermMatchArgs
{
Expression = "destination == '10.0.0.0/12'",
Title = "export_expression",
Description = "acceptance expression for export",
},
Actions = new[]
{
new Gcp.Compute.Inputs.RouterRoutePolicyTermActionArgs
{
Expression = "accept()",
},
},
},
},
}, new CustomResourceOptions
{
DependsOn =
{
routerInterface,
},
});
var rp_import = new Gcp.Compute.RouterRoutePolicy("rp-import", new()
{
Name = "my-router-rp-import",
Router = router.Name,
Region = router.Region,
Type = "ROUTE_POLICY_TYPE_IMPORT",
Terms = new[]
{
new Gcp.Compute.Inputs.RouterRoutePolicyTermArgs
{
Priority = 1,
Match = new Gcp.Compute.Inputs.RouterRoutePolicyTermMatchArgs
{
Expression = "destination == '10.0.0.0/12'",
Title = "import_expression",
Description = "acceptance expression for import",
},
Actions = new[]
{
new Gcp.Compute.Inputs.RouterRoutePolicyTermActionArgs
{
Expression = "accept()",
},
},
},
},
}, new CustomResourceOptions
{
DependsOn =
{
routerInterface,
rp_export,
},
});
var routerPeer = new Gcp.Compute.RouterPeer("router_peer", new()
{
Name = "my-router-peer",
Router = router.Name,
Region = router.Region,
PeerAsn = 65515,
AdvertisedRoutePriority = 100,
Interface = routerInterface.Name,
Md5AuthenticationKey = new Gcp.Compute.Inputs.RouterPeerMd5AuthenticationKeyArgs
{
Name = "my-router-peer-key",
Key = "my-router-peer-key-value",
},
ImportPolicies = new[]
{
rp_import.Name,
},
ExportPolicies = new[]
{
rp_export.Name,
},
}, new CustomResourceOptions
{
DependsOn =
{
rp_export,
rp_import,
routerInterface,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.compute.Subnetwork;
import com.pulumi.gcp.compute.SubnetworkArgs;
import com.pulumi.gcp.compute.Address;
import com.pulumi.gcp.compute.AddressArgs;
import com.pulumi.gcp.compute.HaVpnGateway;
import com.pulumi.gcp.compute.HaVpnGatewayArgs;
import com.pulumi.gcp.compute.ExternalVpnGateway;
import com.pulumi.gcp.compute.ExternalVpnGatewayArgs;
import com.pulumi.gcp.compute.inputs.ExternalVpnGatewayInterfaceArgs;
import com.pulumi.gcp.compute.Router;
import com.pulumi.gcp.compute.RouterArgs;
import com.pulumi.gcp.compute.inputs.RouterBgpArgs;
import com.pulumi.gcp.compute.VPNTunnel;
import com.pulumi.gcp.compute.VPNTunnelArgs;
import com.pulumi.gcp.compute.RouterInterface;
import com.pulumi.gcp.compute.RouterInterfaceArgs;
import com.pulumi.gcp.compute.RouterRoutePolicy;
import com.pulumi.gcp.compute.RouterRoutePolicyArgs;
import com.pulumi.gcp.compute.inputs.RouterRoutePolicyTermArgs;
import com.pulumi.gcp.compute.inputs.RouterRoutePolicyTermMatchArgs;
import com.pulumi.gcp.compute.RouterPeer;
import com.pulumi.gcp.compute.RouterPeerArgs;
import com.pulumi.gcp.compute.inputs.RouterPeerMd5AuthenticationKeyArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var network = new Network("network", NetworkArgs.builder()
.name("my-router-net")
.autoCreateSubnetworks(false)
.build());
var subnetwork = new Subnetwork("subnetwork", SubnetworkArgs.builder()
.name("my-router-subnet")
.network(network.selfLink())
.ipCidrRange("10.0.0.0/16")
.region("us-central1")
.build());
var address = new Address("address", AddressArgs.builder()
.name("my-router")
.region(subnetwork.region())
.build());
var vpnGateway = new HaVpnGateway("vpnGateway", HaVpnGatewayArgs.builder()
.name("my-router-gateway")
.network(network.selfLink())
.region(subnetwork.region())
.build());
var externalGateway = new ExternalVpnGateway("externalGateway", ExternalVpnGatewayArgs.builder()
.name("my-router-external-gateway")
.redundancyType("SINGLE_IP_INTERNALLY_REDUNDANT")
.description("An externally managed VPN gateway")
.interfaces(ExternalVpnGatewayInterfaceArgs.builder()
.id(0)
.ipAddress("8.8.8.8")
.build())
.build());
var router = new Router("router", RouterArgs.builder()
.name("my-router")
.region(subnetwork.region())
.network(network.selfLink())
.bgp(RouterBgpArgs.builder()
.asn(64514)
.build())
.build());
var vpnTunnel = new VPNTunnel("vpnTunnel", VPNTunnelArgs.builder()
.name("my-router")
.region(subnetwork.region())
.vpnGateway(vpnGateway.id())
.peerExternalGateway(externalGateway.id())
.peerExternalGatewayInterface(0)
.sharedSecret("unguessable")
.router(router.name())
.vpnGatewayInterface(0)
.build());
var routerInterface = new RouterInterface("routerInterface", RouterInterfaceArgs.builder()
.name("my-router")
.router(router.name())
.region(router.region())
.vpnTunnel(vpnTunnel.name())
.build());
var rp_export = new RouterRoutePolicy("rp-export", RouterRoutePolicyArgs.builder()
.name("my-router-rp-export")
.router(router.name())
.region(router.region())
.type("ROUTE_POLICY_TYPE_EXPORT")
.terms(RouterRoutePolicyTermArgs.builder()
.priority(2)
.match(RouterRoutePolicyTermMatchArgs.builder()
.expression("destination == '10.0.0.0/12'")
.title("export_expression")
.description("acceptance expression for export")
.build())
.actions(RouterRoutePolicyTermActionArgs.builder()
.expression("accept()")
.build())
.build())
.build(), CustomResourceOptions.builder()
.dependsOn(routerInterface)
.build());
var rp_import = new RouterRoutePolicy("rp-import", RouterRoutePolicyArgs.builder()
.name("my-router-rp-import")
.router(router.name())
.region(router.region())
.type("ROUTE_POLICY_TYPE_IMPORT")
.terms(RouterRoutePolicyTermArgs.builder()
.priority(1)
.match(RouterRoutePolicyTermMatchArgs.builder()
.expression("destination == '10.0.0.0/12'")
.title("import_expression")
.description("acceptance expression for import")
.build())
.actions(RouterRoutePolicyTermActionArgs.builder()
.expression("accept()")
.build())
.build())
.build(), CustomResourceOptions.builder()
.dependsOn(
routerInterface,
rp_export)
.build());
var routerPeer = new RouterPeer("routerPeer", RouterPeerArgs.builder()
.name("my-router-peer")
.router(router.name())
.region(router.region())
.peerAsn(65515)
.advertisedRoutePriority(100)
.interface_(routerInterface.name())
.md5AuthenticationKey(RouterPeerMd5AuthenticationKeyArgs.builder()
.name("my-router-peer-key")
.key("my-router-peer-key-value")
.build())
.importPolicies(rp_import.name())
.exportPolicies(rp_export.name())
.build(), CustomResourceOptions.builder()
.dependsOn(
rp_export,
rp_import,
routerInterface)
.build());
}
}
resources:
network:
type: gcp:compute:Network
properties:
name: my-router-net
autoCreateSubnetworks: false
subnetwork:
type: gcp:compute:Subnetwork
properties:
name: my-router-subnet
network: ${network.selfLink}
ipCidrRange: 10.0.0.0/16
region: us-central1
address:
type: gcp:compute:Address
properties:
name: my-router
region: ${subnetwork.region}
vpnGateway:
type: gcp:compute:HaVpnGateway
name: vpn_gateway
properties:
name: my-router-gateway
network: ${network.selfLink}
region: ${subnetwork.region}
externalGateway:
type: gcp:compute:ExternalVpnGateway
name: external_gateway
properties:
name: my-router-external-gateway
redundancyType: SINGLE_IP_INTERNALLY_REDUNDANT
description: An externally managed VPN gateway
interfaces:
- id: 0
ipAddress: 8.8.8.8
router:
type: gcp:compute:Router
properties:
name: my-router
region: ${subnetwork.region}
network: ${network.selfLink}
bgp:
asn: 64514
vpnTunnel:
type: gcp:compute:VPNTunnel
name: vpn_tunnel
properties:
name: my-router
region: ${subnetwork.region}
vpnGateway: ${vpnGateway.id}
peerExternalGateway: ${externalGateway.id}
peerExternalGatewayInterface: 0
sharedSecret: unguessable
router: ${router.name}
vpnGatewayInterface: 0
routerInterface:
type: gcp:compute:RouterInterface
name: router_interface
properties:
name: my-router
router: ${router.name}
region: ${router.region}
vpnTunnel: ${vpnTunnel.name}
rp-export:
type: gcp:compute:RouterRoutePolicy
properties:
name: my-router-rp-export
router: ${router.name}
region: ${router.region}
type: ROUTE_POLICY_TYPE_EXPORT
terms:
- priority: 2
match:
expression: destination == '10.0.0.0/12'
title: export_expression
description: acceptance expression for export
actions:
- expression: accept()
options:
dependsOn:
- ${routerInterface}
rp-import:
type: gcp:compute:RouterRoutePolicy
properties:
name: my-router-rp-import
router: ${router.name}
region: ${router.region}
type: ROUTE_POLICY_TYPE_IMPORT
terms:
- priority: 1
match:
expression: destination == '10.0.0.0/12'
title: import_expression
description: acceptance expression for import
actions:
- expression: accept()
options:
dependsOn:
- ${routerInterface}
- ${["rp-export"]}
routerPeer:
type: gcp:compute:RouterPeer
name: router_peer
properties:
name: my-router-peer
router: ${router.name}
region: ${router.region}
peerAsn: 65515
advertisedRoutePriority: 100
interface: ${routerInterface.name}
md5AuthenticationKey:
name: my-router-peer-key
key: my-router-peer-key-value
importPolicies:
- ${["rp-import"].name}
exportPolicies:
- ${["rp-export"].name}
options:
dependsOn:
- ${["rp-export"]}
- ${["rp-import"]}
- ${routerInterface}
The importPolicies and exportPolicies properties reference RouterRoutePolicy resources that define filtering rules. Each policy contains terms with match expressions (using destination prefix patterns) and actions (accept or reject). The expression syntax allows complex filtering logic. Policies are evaluated in priority order; this example accepts routes matching 10.0.0.0/12. The dependsOn relationships ensure policies exist before the peer references them.
Beyond these examples
These snippets focus on specific BGP peer features: basic peering and session configuration, failure detection with BFD, third-party appliance integration, and route filtering with import/export policies. They’re intentionally minimal rather than full network architectures.
The examples may reference pre-existing infrastructure such as Cloud Routers with configured interfaces, VPN tunnels or Interconnect attachments for connectivity, and Network Connectivity Hubs and Spokes for appliance scenarios. They focus on configuring the BGP peer rather than provisioning the underlying routing infrastructure.
To keep things focused, common BGP peer patterns are omitted, including:
- Session disabling and maintenance (enable property)
- MD5 authentication for session security
- Custom route priorities (advertisedRoutePriority, customLearnedRoutePriority)
- IPv6 peering configuration (enableIpv6, ipv6NexthopAddress)
- Custom IP range advertisement (advertisedIpRanges, advertisedGroups)
These omissions are intentional: the goal is to illustrate how each BGP peer feature is wired, not provide drop-in routing modules. See the Router Peer resource reference for all available configuration options.
Let's configure GCP Cloud Router BGP Peers
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Configuration & Immutability
interface, name, router, region, and project. You must recreate the peer to change these.[a-z][-a-z0-9]*[a-z0-9]. Start with a lowercase letter, use only lowercase letters, digits, or dashes, and end with a letter or digit (not a dash).Route Priorities & Advertisement
advertisedRoutePriority to 0, you must also set zeroAdvertisedRoutePriority to true. Similarly, to set customLearnedRoutePriority to 0, set zeroCustomLearnedRoutePriority to true.advertiseMode to CUSTOM, then configure advertisedGroups (e.g., ALL_SUBNETS) or advertisedIpRanges. These fields only work in CUSTOM mode.customLearnedRoutePriority. You can choose a value from 0 to 65335.IP Addressing & IPv6
ipv6NexthopAddress and peerIpv6NexthopAddress) must be in the range 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64. If you don’t specify them, Google Cloud automatically assigns unused addresses from these ranges.enableIpv6 to true to enable it. IPv4 is enabled by default if peerIpAddress is version 4.Session Management
enable to false. This terminates any active session with the peer and removes all associated routing information. The default is true.managementType is a computed output field you can’t set. It’s MANAGED_BY_USER by default (managed by you or other users), or MANAGED_BY_ATTACHMENT for BGP peers automatically created by partner InterconnectAttachments.Advanced Features
bfd block with minReceiveInterval, minTransmitInterval, multiplier, and sessionInitializationMode properties.md5AuthenticationKey with a name and key value to enable MD5 authentication on the BGP session.importPolicies and exportPolicies arrays. Policies must have type ROUTE_POLICY_TYPE_IMPORT or ROUTE_POLICY_TYPE_EXPORT respectively. Use dependsOn to ensure policies exist before creating the peer.Using a different cloud?
Explore networking guides for other cloud providers: