Configure GCP Interconnect Attachments

The gcp:compute/interconnectAttachment:InterconnectAttachment resource, part of the Pulumi GCP provider, defines a VLAN attachment that connects a Cloud Router to an Interconnect circuit, establishing BGP peering and traffic flow. This guide focuses on three capabilities: PARTNER attachment creation, IPsec encryption configuration, and dual-stack BGP peering.

Interconnect attachments depend on a VPC network and Cloud Router with BGP configuration. IPsec-encrypted attachments require reserved internal IP addresses for HA VPN gateways. The examples are intentionally small. Combine them with your own network infrastructure and routing policies.

Create a PARTNER attachment with basic configuration

Most deployments begin with a PARTNER attachment that connects your on-premises network through a service provider. The attachment defines the VLAN, MTU, and availability domain.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const foobarNetwork = new gcp.compute.Network("foobar", {
    name: "network-1",
    autoCreateSubnetworks: false,
});
const foobar = new gcp.compute.Router("foobar", {
    name: "router-1",
    network: foobarNetwork.name,
    bgp: {
        asn: 16550,
    },
});
const onPrem = new gcp.compute.InterconnectAttachment("on_prem", {
    name: "on-prem-attachment",
    edgeAvailabilityDomain: "AVAILABILITY_DOMAIN_1",
    type: "PARTNER",
    router: foobar.id,
    mtu: "1500",
    labels: {
        mykey: "myvalue",
    },
});
import pulumi
import pulumi_gcp as gcp

foobar_network = gcp.compute.Network("foobar",
    name="network-1",
    auto_create_subnetworks=False)
foobar = gcp.compute.Router("foobar",
    name="router-1",
    network=foobar_network.name,
    bgp={
        "asn": 16550,
    })
on_prem = gcp.compute.InterconnectAttachment("on_prem",
    name="on-prem-attachment",
    edge_availability_domain="AVAILABILITY_DOMAIN_1",
    type="PARTNER",
    router=foobar.id,
    mtu="1500",
    labels={
        "mykey": "myvalue",
    })
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 {
		foobarNetwork, err := compute.NewNetwork(ctx, "foobar", &compute.NetworkArgs{
			Name:                  pulumi.String("network-1"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		foobar, err := compute.NewRouter(ctx, "foobar", &compute.RouterArgs{
			Name:    pulumi.String("router-1"),
			Network: foobarNetwork.Name,
			Bgp: &compute.RouterBgpArgs{
				Asn: pulumi.Int(16550),
			},
		})
		if err != nil {
			return err
		}
		_, err = compute.NewInterconnectAttachment(ctx, "on_prem", &compute.InterconnectAttachmentArgs{
			Name:                   pulumi.String("on-prem-attachment"),
			EdgeAvailabilityDomain: pulumi.String("AVAILABILITY_DOMAIN_1"),
			Type:                   pulumi.String("PARTNER"),
			Router:                 foobar.ID(),
			Mtu:                    pulumi.String("1500"),
			Labels: pulumi.StringMap{
				"mykey": pulumi.String("myvalue"),
			},
		})
		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 foobarNetwork = new Gcp.Compute.Network("foobar", new()
    {
        Name = "network-1",
        AutoCreateSubnetworks = false,
    });

    var foobar = new Gcp.Compute.Router("foobar", new()
    {
        Name = "router-1",
        Network = foobarNetwork.Name,
        Bgp = new Gcp.Compute.Inputs.RouterBgpArgs
        {
            Asn = 16550,
        },
    });

    var onPrem = new Gcp.Compute.InterconnectAttachment("on_prem", new()
    {
        Name = "on-prem-attachment",
        EdgeAvailabilityDomain = "AVAILABILITY_DOMAIN_1",
        Type = "PARTNER",
        Router = foobar.Id,
        Mtu = "1500",
        Labels = 
        {
            { "mykey", "myvalue" },
        },
    });

});
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.Router;
import com.pulumi.gcp.compute.RouterArgs;
import com.pulumi.gcp.compute.inputs.RouterBgpArgs;
import com.pulumi.gcp.compute.InterconnectAttachment;
import com.pulumi.gcp.compute.InterconnectAttachmentArgs;
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 foobarNetwork = new Network("foobarNetwork", NetworkArgs.builder()
            .name("network-1")
            .autoCreateSubnetworks(false)
            .build());

        var foobar = new Router("foobar", RouterArgs.builder()
            .name("router-1")
            .network(foobarNetwork.name())
            .bgp(RouterBgpArgs.builder()
                .asn(16550)
                .build())
            .build());

        var onPrem = new InterconnectAttachment("onPrem", InterconnectAttachmentArgs.builder()
            .name("on-prem-attachment")
            .edgeAvailabilityDomain("AVAILABILITY_DOMAIN_1")
            .type("PARTNER")
            .router(foobar.id())
            .mtu("1500")
            .labels(Map.of("mykey", "myvalue"))
            .build());

    }
}
resources:
  onPrem:
    type: gcp:compute:InterconnectAttachment
    name: on_prem
    properties:
      name: on-prem-attachment
      edgeAvailabilityDomain: AVAILABILITY_DOMAIN_1
      type: PARTNER
      router: ${foobar.id}
      mtu: 1500
      labels:
        mykey: myvalue
  foobar:
    type: gcp:compute:Router
    properties:
      name: router-1
      network: ${foobarNetwork.name}
      bgp:
        asn: 16550
  foobarNetwork:
    type: gcp:compute:Network
    name: foobar
    properties:
      name: network-1
      autoCreateSubnetworks: false

The type property set to “PARTNER” indicates the attachment will be provisioned by a Google Cloud partner. The edgeAvailabilityDomain property controls which Google edge location handles the connection; for redundancy, create a second attachment in a different domain. The router property links the attachment to your Cloud Router, which handles BGP routing. The mtu property sets the maximum packet size; 1500 is standard for most networks.

Encrypt traffic with IPsec over Interconnect

Organizations with strict security requirements can encrypt Interconnect traffic using IPsec, which requires reserving internal IP addresses for HA VPN gateways.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const network = new gcp.compute.Network("network", {
    name: "test-network",
    autoCreateSubnetworks: false,
});
const address = new gcp.compute.Address("address", {
    name: "test-address",
    addressType: "INTERNAL",
    purpose: "IPSEC_INTERCONNECT",
    address: "192.168.1.0",
    prefixLength: 29,
    network: network.selfLink,
});
const router = new gcp.compute.Router("router", {
    name: "test-router",
    network: network.name,
    encryptedInterconnectRouter: true,
    bgp: {
        asn: 16550,
    },
});
const ipsec_encrypted_interconnect_attachment = new gcp.compute.InterconnectAttachment("ipsec-encrypted-interconnect-attachment", {
    name: "test-interconnect-attachment",
    edgeAvailabilityDomain: "AVAILABILITY_DOMAIN_1",
    type: "PARTNER",
    router: router.id,
    encryption: "IPSEC",
    ipsecInternalAddresses: [address.selfLink],
});
import pulumi
import pulumi_gcp as gcp

network = gcp.compute.Network("network",
    name="test-network",
    auto_create_subnetworks=False)
address = gcp.compute.Address("address",
    name="test-address",
    address_type="INTERNAL",
    purpose="IPSEC_INTERCONNECT",
    address="192.168.1.0",
    prefix_length=29,
    network=network.self_link)
router = gcp.compute.Router("router",
    name="test-router",
    network=network.name,
    encrypted_interconnect_router=True,
    bgp={
        "asn": 16550,
    })
ipsec_encrypted_interconnect_attachment = gcp.compute.InterconnectAttachment("ipsec-encrypted-interconnect-attachment",
    name="test-interconnect-attachment",
    edge_availability_domain="AVAILABILITY_DOMAIN_1",
    type="PARTNER",
    router=router.id,
    encryption="IPSEC",
    ipsec_internal_addresses=[address.self_link])
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("test-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		address, err := compute.NewAddress(ctx, "address", &compute.AddressArgs{
			Name:         pulumi.String("test-address"),
			AddressType:  pulumi.String("INTERNAL"),
			Purpose:      pulumi.String("IPSEC_INTERCONNECT"),
			Address:      pulumi.String("192.168.1.0"),
			PrefixLength: pulumi.Int(29),
			Network:      network.SelfLink,
		})
		if err != nil {
			return err
		}
		router, err := compute.NewRouter(ctx, "router", &compute.RouterArgs{
			Name:                        pulumi.String("test-router"),
			Network:                     network.Name,
			EncryptedInterconnectRouter: pulumi.Bool(true),
			Bgp: &compute.RouterBgpArgs{
				Asn: pulumi.Int(16550),
			},
		})
		if err != nil {
			return err
		}
		_, err = compute.NewInterconnectAttachment(ctx, "ipsec-encrypted-interconnect-attachment", &compute.InterconnectAttachmentArgs{
			Name:                   pulumi.String("test-interconnect-attachment"),
			EdgeAvailabilityDomain: pulumi.String("AVAILABILITY_DOMAIN_1"),
			Type:                   pulumi.String("PARTNER"),
			Router:                 router.ID(),
			Encryption:             pulumi.String("IPSEC"),
			IpsecInternalAddresses: pulumi.StringArray{
				address.SelfLink,
			},
		})
		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 = "test-network",
        AutoCreateSubnetworks = false,
    });

    var address = new Gcp.Compute.Address("address", new()
    {
        Name = "test-address",
        AddressType = "INTERNAL",
        Purpose = "IPSEC_INTERCONNECT",
        IPAddress = "192.168.1.0",
        PrefixLength = 29,
        Network = network.SelfLink,
    });

    var router = new Gcp.Compute.Router("router", new()
    {
        Name = "test-router",
        Network = network.Name,
        EncryptedInterconnectRouter = true,
        Bgp = new Gcp.Compute.Inputs.RouterBgpArgs
        {
            Asn = 16550,
        },
    });

    var ipsec_encrypted_interconnect_attachment = new Gcp.Compute.InterconnectAttachment("ipsec-encrypted-interconnect-attachment", new()
    {
        Name = "test-interconnect-attachment",
        EdgeAvailabilityDomain = "AVAILABILITY_DOMAIN_1",
        Type = "PARTNER",
        Router = router.Id,
        Encryption = "IPSEC",
        IpsecInternalAddresses = new[]
        {
            address.SelfLink,
        },
    });

});
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.Address;
import com.pulumi.gcp.compute.AddressArgs;
import com.pulumi.gcp.compute.Router;
import com.pulumi.gcp.compute.RouterArgs;
import com.pulumi.gcp.compute.inputs.RouterBgpArgs;
import com.pulumi.gcp.compute.InterconnectAttachment;
import com.pulumi.gcp.compute.InterconnectAttachmentArgs;
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("test-network")
            .autoCreateSubnetworks(false)
            .build());

        var address = new Address("address", AddressArgs.builder()
            .name("test-address")
            .addressType("INTERNAL")
            .purpose("IPSEC_INTERCONNECT")
            .address("192.168.1.0")
            .prefixLength(29)
            .network(network.selfLink())
            .build());

        var router = new Router("router", RouterArgs.builder()
            .name("test-router")
            .network(network.name())
            .encryptedInterconnectRouter(true)
            .bgp(RouterBgpArgs.builder()
                .asn(16550)
                .build())
            .build());

        var ipsec_encrypted_interconnect_attachment = new InterconnectAttachment("ipsec-encrypted-interconnect-attachment", InterconnectAttachmentArgs.builder()
            .name("test-interconnect-attachment")
            .edgeAvailabilityDomain("AVAILABILITY_DOMAIN_1")
            .type("PARTNER")
            .router(router.id())
            .encryption("IPSEC")
            .ipsecInternalAddresses(address.selfLink())
            .build());

    }
}
resources:
  ipsec-encrypted-interconnect-attachment:
    type: gcp:compute:InterconnectAttachment
    properties:
      name: test-interconnect-attachment
      edgeAvailabilityDomain: AVAILABILITY_DOMAIN_1
      type: PARTNER
      router: ${router.id}
      encryption: IPSEC
      ipsecInternalAddresses:
        - ${address.selfLink}
  address:
    type: gcp:compute:Address
    properties:
      name: test-address
      addressType: INTERNAL
      purpose: IPSEC_INTERCONNECT
      address: 192.168.1.0
      prefixLength: 29
      network: ${network.selfLink}
  router:
    type: gcp:compute:Router
    properties:
      name: test-router
      network: ${network.name}
      encryptedInterconnectRouter: true
      bgp:
        asn: 16550
  network:
    type: gcp:compute:Network
    properties:
      name: test-network
      autoCreateSubnetworks: false

The encryption property set to “IPSEC” enables IPsec encryption for all traffic through this attachment. The ipsecInternalAddresses property references a reserved internal IP address range that HA VPN gateways will use. The Address resource with purpose “IPSEC_INTERCONNECT” reserves RFC 1918 addresses specifically for this use case. The Cloud Router must have encryptedInterconnectRouter set to true to support encrypted attachments.

Configure dual-stack BGP with custom IP ranges

Dual-stack deployments that need both IPv4 and IPv6 connectivity can specify custom IP addresses for BGP peering sessions.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const foobarNetwork = new gcp.compute.Network("foobar", {
    name: "test-network",
    autoCreateSubnetworks: false,
});
const foobar = new gcp.compute.Router("foobar", {
    name: "test-router",
    network: foobarNetwork.name,
    bgp: {
        asn: 16550,
    },
});
const custom_ranges_interconnect_attachment = new gcp.compute.InterconnectAttachment("custom-ranges-interconnect-attachment", {
    name: "test-custom-ranges-interconnect-attachment",
    edgeAvailabilityDomain: "AVAILABILITY_DOMAIN_1",
    type: "PARTNER",
    router: foobar.id,
    mtu: "1500",
    stackType: "IPV4_IPV6",
    labels: {
        mykey: "myvalue",
    },
    candidateCloudRouterIpAddress: "192.169.0.1/29",
    candidateCustomerRouterIpAddress: "192.169.0.2/29",
    candidateCloudRouterIpv6Address: "748d:2f23:6651:9455:828b:ca81:6fe0:fed1/125",
    candidateCustomerRouterIpv6Address: "748d:2f23:6651:9455:828b:ca81:6fe0:fed2/125",
});
import pulumi
import pulumi_gcp as gcp

foobar_network = gcp.compute.Network("foobar",
    name="test-network",
    auto_create_subnetworks=False)
foobar = gcp.compute.Router("foobar",
    name="test-router",
    network=foobar_network.name,
    bgp={
        "asn": 16550,
    })
custom_ranges_interconnect_attachment = gcp.compute.InterconnectAttachment("custom-ranges-interconnect-attachment",
    name="test-custom-ranges-interconnect-attachment",
    edge_availability_domain="AVAILABILITY_DOMAIN_1",
    type="PARTNER",
    router=foobar.id,
    mtu="1500",
    stack_type="IPV4_IPV6",
    labels={
        "mykey": "myvalue",
    },
    candidate_cloud_router_ip_address="192.169.0.1/29",
    candidate_customer_router_ip_address="192.169.0.2/29",
    candidate_cloud_router_ipv6_address="748d:2f23:6651:9455:828b:ca81:6fe0:fed1/125",
    candidate_customer_router_ipv6_address="748d:2f23:6651:9455:828b:ca81:6fe0:fed2/125")
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 {
		foobarNetwork, err := compute.NewNetwork(ctx, "foobar", &compute.NetworkArgs{
			Name:                  pulumi.String("test-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		foobar, err := compute.NewRouter(ctx, "foobar", &compute.RouterArgs{
			Name:    pulumi.String("test-router"),
			Network: foobarNetwork.Name,
			Bgp: &compute.RouterBgpArgs{
				Asn: pulumi.Int(16550),
			},
		})
		if err != nil {
			return err
		}
		_, err = compute.NewInterconnectAttachment(ctx, "custom-ranges-interconnect-attachment", &compute.InterconnectAttachmentArgs{
			Name:                   pulumi.String("test-custom-ranges-interconnect-attachment"),
			EdgeAvailabilityDomain: pulumi.String("AVAILABILITY_DOMAIN_1"),
			Type:                   pulumi.String("PARTNER"),
			Router:                 foobar.ID(),
			Mtu:                    pulumi.String("1500"),
			StackType:              pulumi.String("IPV4_IPV6"),
			Labels: pulumi.StringMap{
				"mykey": pulumi.String("myvalue"),
			},
			CandidateCloudRouterIpAddress:      pulumi.String("192.169.0.1/29"),
			CandidateCustomerRouterIpAddress:   pulumi.String("192.169.0.2/29"),
			CandidateCloudRouterIpv6Address:    pulumi.String("748d:2f23:6651:9455:828b:ca81:6fe0:fed1/125"),
			CandidateCustomerRouterIpv6Address: pulumi.String("748d:2f23:6651:9455:828b:ca81:6fe0:fed2/125"),
		})
		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 foobarNetwork = new Gcp.Compute.Network("foobar", new()
    {
        Name = "test-network",
        AutoCreateSubnetworks = false,
    });

    var foobar = new Gcp.Compute.Router("foobar", new()
    {
        Name = "test-router",
        Network = foobarNetwork.Name,
        Bgp = new Gcp.Compute.Inputs.RouterBgpArgs
        {
            Asn = 16550,
        },
    });

    var custom_ranges_interconnect_attachment = new Gcp.Compute.InterconnectAttachment("custom-ranges-interconnect-attachment", new()
    {
        Name = "test-custom-ranges-interconnect-attachment",
        EdgeAvailabilityDomain = "AVAILABILITY_DOMAIN_1",
        Type = "PARTNER",
        Router = foobar.Id,
        Mtu = "1500",
        StackType = "IPV4_IPV6",
        Labels = 
        {
            { "mykey", "myvalue" },
        },
        CandidateCloudRouterIpAddress = "192.169.0.1/29",
        CandidateCustomerRouterIpAddress = "192.169.0.2/29",
        CandidateCloudRouterIpv6Address = "748d:2f23:6651:9455:828b:ca81:6fe0:fed1/125",
        CandidateCustomerRouterIpv6Address = "748d:2f23:6651:9455:828b:ca81:6fe0:fed2/125",
    });

});
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.Router;
import com.pulumi.gcp.compute.RouterArgs;
import com.pulumi.gcp.compute.inputs.RouterBgpArgs;
import com.pulumi.gcp.compute.InterconnectAttachment;
import com.pulumi.gcp.compute.InterconnectAttachmentArgs;
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 foobarNetwork = new Network("foobarNetwork", NetworkArgs.builder()
            .name("test-network")
            .autoCreateSubnetworks(false)
            .build());

        var foobar = new Router("foobar", RouterArgs.builder()
            .name("test-router")
            .network(foobarNetwork.name())
            .bgp(RouterBgpArgs.builder()
                .asn(16550)
                .build())
            .build());

        var custom_ranges_interconnect_attachment = new InterconnectAttachment("custom-ranges-interconnect-attachment", InterconnectAttachmentArgs.builder()
            .name("test-custom-ranges-interconnect-attachment")
            .edgeAvailabilityDomain("AVAILABILITY_DOMAIN_1")
            .type("PARTNER")
            .router(foobar.id())
            .mtu("1500")
            .stackType("IPV4_IPV6")
            .labels(Map.of("mykey", "myvalue"))
            .candidateCloudRouterIpAddress("192.169.0.1/29")
            .candidateCustomerRouterIpAddress("192.169.0.2/29")
            .candidateCloudRouterIpv6Address("748d:2f23:6651:9455:828b:ca81:6fe0:fed1/125")
            .candidateCustomerRouterIpv6Address("748d:2f23:6651:9455:828b:ca81:6fe0:fed2/125")
            .build());

    }
}
resources:
  custom-ranges-interconnect-attachment:
    type: gcp:compute:InterconnectAttachment
    properties:
      name: test-custom-ranges-interconnect-attachment
      edgeAvailabilityDomain: AVAILABILITY_DOMAIN_1
      type: PARTNER
      router: ${foobar.id}
      mtu: 1500
      stackType: IPV4_IPV6
      labels:
        mykey: myvalue
      candidateCloudRouterIpAddress: 192.169.0.1/29
      candidateCustomerRouterIpAddress: 192.169.0.2/29
      candidateCloudRouterIpv6Address: 748d:2f23:6651:9455:828b:ca81:6fe0:fed1/125
      candidateCustomerRouterIpv6Address: 748d:2f23:6651:9455:828b:ca81:6fe0:fed2/125
  foobar:
    type: gcp:compute:Router
    properties:
      name: test-router
      network: ${foobarNetwork.name}
      bgp:
        asn: 16550
  foobarNetwork:
    type: gcp:compute:Network
    name: foobar
    properties:
      name: test-network
      autoCreateSubnetworks: false

The stackType property set to “IPV4_IPV6” enables dual-stack operation. The candidateCloudRouterIpAddress and candidateCustomerRouterIpAddress properties specify the IPv4 addresses for the BGP session, while candidateCloudRouterIpv6Address and candidateCustomerRouterIpv6Address specify the IPv6 addresses. These addresses must be in CIDR notation with appropriate prefix lengths (/29 for IPv4, /125 for IPv6). Google Cloud will configure the Cloud Router interface with the specified addresses.

Beyond these examples

These snippets focus on specific attachment-level features: PARTNER attachment provisioning, IPsec encryption with reserved addresses, and dual-stack BGP configuration. They’re intentionally minimal rather than full network connectivity solutions.

The examples may reference pre-existing infrastructure such as VPC networks and Cloud Router BGP configuration. They focus on configuring the attachment rather than provisioning the surrounding network infrastructure.

To keep things focused, common attachment patterns are omitted, including:

  • DEDICATED attachment type (requires physical interconnect)
  • VLAN tag management (vlanTag8021q)
  • Bandwidth selection and tuning
  • Candidate subnet restrictions (candidateSubnets)

These omissions are intentional: the goal is to illustrate how each attachment feature is wired, not provide drop-in connectivity modules. See the InterconnectAttachment resource reference for all available configuration options.

Let's configure GCP Interconnect Attachments

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Attachment Types & Configuration
What's the difference between DEDICATED, PARTNER, and PARTNER_PROVIDER attachment types?
DEDICATED attachments are user-managed and require the interconnect property. PARTNER attachments are managed by a Google Partner, have read-only bandwidth, and must not set interconnect. PARTNER_PROVIDER is for partners managing attachments on behalf of customers.
Why can't I set the bandwidth for my PARTNER attachment?
For PARTNER type attachments, bandwidth is output-only and must be set by the Google Partner operating the interconnect. Only PARTNER_PROVIDER and DEDICATED types allow user-configured bandwidth.
Encryption & Security
Why can't my VMs send traffic directly through my IPSEC-encrypted attachment?
When encryption is set to IPSEC, the VLAN attachment only carries encrypted traffic from an IPsec device like an HA VPN gateway or third-party IPsec VPN. VMs cannot directly send or receive traffic through such attachments.
How do I configure IPsec encryption for my interconnect attachment?
Set encryption to IPSEC, provide ipsecInternalAddresses with RFC 1918 IP address ranges, and configure your Cloud Router with encryptedInterconnectRouter set to true.
What IP address ranges can I use for ipsecInternalAddresses?
You must use RFC 1918 IP address ranges. These addresses are used to allocate HA VPN gateway IP addresses when creating an HA VPN gateway over the interconnect attachment.
Networking & IP Configuration
What IP address ranges are allowed for candidateSubnets?
All candidate prefixes must be within link-local address space (169.254.0.0/16) and must be /29 or shorter (/28, /27, etc). Google will attempt to select an unused /29 from the supplied prefixes.
How do I enable IPv6 support for my interconnect attachment?
Set stackType to IPV4_IPV6 and provide candidateCloudRouterIpv6Address and candidateCustomerRouterIpv6Address with IPv6 addresses and prefix lengths.
What MTU values are supported for interconnect attachments?
Valid MTU values are 1440 (default), 1460, 1500, and 8896 bytes.
What's the default subnet length and when does it change?
The default subnetLength is 29, which is preferred for better Google Cloud Support debugging visibility. However, for Cross-Cloud Interconnect connections using Azure remote locations, the default is 30, and requesting 29 returns an error.
High Availability & Reliability
Should I configure multiple attachments for high availability?
Yes, for improved reliability with PARTNER type attachments, configure a pair of attachments with one per availability domain using the edgeAvailabilityDomain property.
Immutability & Limitations
What properties can't be changed after creating an interconnect attachment?
The following properties are immutable: type, edgeAvailabilityDomain, router, name, project, vlanTag8021q, encryption, interconnect, candidateCloudRouterIpAddress, candidateCloudRouterIpv6Address, candidateCustomerRouterIpAddress, candidateCustomerRouterIpv6Address, candidateSubnets, ipsecInternalAddresses, and subnetLength.
Does my Cloud Router need to be in the same region as the attachment?
Yes, the router must be in the same region as the InterconnectAttachment. The attachment automatically connects the Interconnect to the network and region where the Cloud Router is configured.

Using a different cloud?

Explore networking guides for other cloud providers: