The gcp:networkconnectivity/internalRange:InternalRange resource, part of the Pulumi GCP provider, defines reserved IP address ranges within VPC networks for IPAM operations, tracking both internal VPC allocations and external address space. This guide focuses on four capabilities: fixed CIDR reservation, automatic range allocation, external range tracking, and overlap handling and migration coordination.
Internal ranges belong to VPC networks and may reference existing subnets for overlap or migration scenarios. The examples are intentionally small. Combine them with your own VPC infrastructure and subnet planning.
Reserve a fixed CIDR range for VPC use
Most deployments start by reserving a specific CIDR block for VPC resources, establishing address space ownership and preventing conflicts.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const defaultNetwork = new gcp.compute.Network("default", {
name: "internal-ranges",
autoCreateSubnetworks: false,
});
const _default = new gcp.networkconnectivity.InternalRange("default", {
name: "basic",
description: "Test internal range",
network: defaultNetwork.selfLink,
usage: "FOR_VPC",
peering: "FOR_SELF",
ipCidrRange: "10.0.0.0/24",
labels: {
"label-a": "b",
},
});
import pulumi
import pulumi_gcp as gcp
default_network = gcp.compute.Network("default",
name="internal-ranges",
auto_create_subnetworks=False)
default = gcp.networkconnectivity.InternalRange("default",
name="basic",
description="Test internal range",
network=default_network.self_link,
usage="FOR_VPC",
peering="FOR_SELF",
ip_cidr_range="10.0.0.0/24",
labels={
"label-a": "b",
})
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 {
defaultNetwork, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
Name: pulumi.String("internal-ranges"),
AutoCreateSubnetworks: pulumi.Bool(false),
})
if err != nil {
return err
}
_, err = networkconnectivity.NewInternalRange(ctx, "default", &networkconnectivity.InternalRangeArgs{
Name: pulumi.String("basic"),
Description: pulumi.String("Test internal range"),
Network: defaultNetwork.SelfLink,
Usage: pulumi.String("FOR_VPC"),
Peering: pulumi.String("FOR_SELF"),
IpCidrRange: pulumi.String("10.0.0.0/24"),
Labels: pulumi.StringMap{
"label-a": pulumi.String("b"),
},
})
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 defaultNetwork = new Gcp.Compute.Network("default", new()
{
Name = "internal-ranges",
AutoCreateSubnetworks = false,
});
var @default = new Gcp.NetworkConnectivity.InternalRange("default", new()
{
Name = "basic",
Description = "Test internal range",
Network = defaultNetwork.SelfLink,
Usage = "FOR_VPC",
Peering = "FOR_SELF",
IpCidrRange = "10.0.0.0/24",
Labels =
{
{ "label-a", "b" },
},
});
});
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.networkconnectivity.InternalRange;
import com.pulumi.gcp.networkconnectivity.InternalRangeArgs;
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 defaultNetwork = new Network("defaultNetwork", NetworkArgs.builder()
.name("internal-ranges")
.autoCreateSubnetworks(false)
.build());
var default_ = new InternalRange("default", InternalRangeArgs.builder()
.name("basic")
.description("Test internal range")
.network(defaultNetwork.selfLink())
.usage("FOR_VPC")
.peering("FOR_SELF")
.ipCidrRange("10.0.0.0/24")
.labels(Map.of("label-a", "b"))
.build());
}
}
resources:
default:
type: gcp:networkconnectivity:InternalRange
properties:
name: basic
description: Test internal range
network: ${defaultNetwork.selfLink}
usage: FOR_VPC
peering: FOR_SELF
ipCidrRange: 10.0.0.0/24
labels:
label-a: b
defaultNetwork:
type: gcp:compute:Network
name: default
properties:
name: internal-ranges
autoCreateSubnetworks: false
The ipCidrRange property specifies the exact address block to reserve. The usage property set to FOR_VPC indicates this range is for VPC resource allocation. The peering property controls whether this range is shared with peered networks; FOR_SELF means it’s only for this VPC. The network property links the range to a specific VPC.
Automatically allocate a range from target space
When you need a range of a specific size but don’t care about the exact CIDR, automatic allocation finds available space within your target address ranges.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const defaultNetwork = new gcp.compute.Network("default", {
name: "internal-ranges",
autoCreateSubnetworks: false,
});
const _default = new gcp.networkconnectivity.InternalRange("default", {
name: "automatic-reservation",
network: defaultNetwork.id,
usage: "FOR_VPC",
peering: "FOR_SELF",
prefixLength: 24,
targetCidrRanges: ["192.16.0.0/16"],
});
import pulumi
import pulumi_gcp as gcp
default_network = gcp.compute.Network("default",
name="internal-ranges",
auto_create_subnetworks=False)
default = gcp.networkconnectivity.InternalRange("default",
name="automatic-reservation",
network=default_network.id,
usage="FOR_VPC",
peering="FOR_SELF",
prefix_length=24,
target_cidr_ranges=["192.16.0.0/16"])
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 {
defaultNetwork, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
Name: pulumi.String("internal-ranges"),
AutoCreateSubnetworks: pulumi.Bool(false),
})
if err != nil {
return err
}
_, err = networkconnectivity.NewInternalRange(ctx, "default", &networkconnectivity.InternalRangeArgs{
Name: pulumi.String("automatic-reservation"),
Network: defaultNetwork.ID(),
Usage: pulumi.String("FOR_VPC"),
Peering: pulumi.String("FOR_SELF"),
PrefixLength: pulumi.Int(24),
TargetCidrRanges: pulumi.StringArray{
pulumi.String("192.16.0.0/16"),
},
})
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 defaultNetwork = new Gcp.Compute.Network("default", new()
{
Name = "internal-ranges",
AutoCreateSubnetworks = false,
});
var @default = new Gcp.NetworkConnectivity.InternalRange("default", new()
{
Name = "automatic-reservation",
Network = defaultNetwork.Id,
Usage = "FOR_VPC",
Peering = "FOR_SELF",
PrefixLength = 24,
TargetCidrRanges = new[]
{
"192.16.0.0/16",
},
});
});
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.networkconnectivity.InternalRange;
import com.pulumi.gcp.networkconnectivity.InternalRangeArgs;
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 defaultNetwork = new Network("defaultNetwork", NetworkArgs.builder()
.name("internal-ranges")
.autoCreateSubnetworks(false)
.build());
var default_ = new InternalRange("default", InternalRangeArgs.builder()
.name("automatic-reservation")
.network(defaultNetwork.id())
.usage("FOR_VPC")
.peering("FOR_SELF")
.prefixLength(24)
.targetCidrRanges("192.16.0.0/16")
.build());
}
}
resources:
default:
type: gcp:networkconnectivity:InternalRange
properties:
name: automatic-reservation
network: ${defaultNetwork.id}
usage: FOR_VPC
peering: FOR_SELF
prefixLength: 24
targetCidrRanges:
- 192.16.0.0/16
defaultNetwork:
type: gcp:compute:Network
name: default
properties:
name: internal-ranges
autoCreateSubnetworks: false
Instead of ipCidrRange, the prefixLength property specifies the desired size (24 means a /24 network). The targetCidrRanges property defines the address space to search within; GCP automatically selects an available block. This approach simplifies address planning when exact CIDRs don’t matter.
Track external address space outside the VPC
Organizations with on-premises networks or external systems need to document address ranges that exist outside GCP but must be tracked for routing and conflict prevention.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const defaultNetwork = new gcp.compute.Network("default", {
name: "internal-ranges",
autoCreateSubnetworks: false,
});
const _default = new gcp.networkconnectivity.InternalRange("default", {
name: "external-ranges",
network: defaultNetwork.id,
usage: "EXTERNAL_TO_VPC",
peering: "FOR_SELF",
ipCidrRange: "172.16.0.0/24",
labels: {
"external-reserved-range": "on-premises",
},
});
import pulumi
import pulumi_gcp as gcp
default_network = gcp.compute.Network("default",
name="internal-ranges",
auto_create_subnetworks=False)
default = gcp.networkconnectivity.InternalRange("default",
name="external-ranges",
network=default_network.id,
usage="EXTERNAL_TO_VPC",
peering="FOR_SELF",
ip_cidr_range="172.16.0.0/24",
labels={
"external-reserved-range": "on-premises",
})
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 {
defaultNetwork, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
Name: pulumi.String("internal-ranges"),
AutoCreateSubnetworks: pulumi.Bool(false),
})
if err != nil {
return err
}
_, err = networkconnectivity.NewInternalRange(ctx, "default", &networkconnectivity.InternalRangeArgs{
Name: pulumi.String("external-ranges"),
Network: defaultNetwork.ID(),
Usage: pulumi.String("EXTERNAL_TO_VPC"),
Peering: pulumi.String("FOR_SELF"),
IpCidrRange: pulumi.String("172.16.0.0/24"),
Labels: pulumi.StringMap{
"external-reserved-range": pulumi.String("on-premises"),
},
})
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 defaultNetwork = new Gcp.Compute.Network("default", new()
{
Name = "internal-ranges",
AutoCreateSubnetworks = false,
});
var @default = new Gcp.NetworkConnectivity.InternalRange("default", new()
{
Name = "external-ranges",
Network = defaultNetwork.Id,
Usage = "EXTERNAL_TO_VPC",
Peering = "FOR_SELF",
IpCidrRange = "172.16.0.0/24",
Labels =
{
{ "external-reserved-range", "on-premises" },
},
});
});
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.networkconnectivity.InternalRange;
import com.pulumi.gcp.networkconnectivity.InternalRangeArgs;
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 defaultNetwork = new Network("defaultNetwork", NetworkArgs.builder()
.name("internal-ranges")
.autoCreateSubnetworks(false)
.build());
var default_ = new InternalRange("default", InternalRangeArgs.builder()
.name("external-ranges")
.network(defaultNetwork.id())
.usage("EXTERNAL_TO_VPC")
.peering("FOR_SELF")
.ipCidrRange("172.16.0.0/24")
.labels(Map.of("external-reserved-range", "on-premises"))
.build());
}
}
resources:
default:
type: gcp:networkconnectivity:InternalRange
properties:
name: external-ranges
network: ${defaultNetwork.id}
usage: EXTERNAL_TO_VPC
peering: FOR_SELF
ipCidrRange: 172.16.0.0/24
labels:
external-reserved-range: on-premises
defaultNetwork:
type: gcp:compute:Network
name: default
properties:
name: internal-ranges
autoCreateSubnetworks: false
The usage property set to EXTERNAL_TO_VPC marks this range as existing outside the VPC. This doesn’t allocate GCP resources; it documents external address space for coordination. The labels help identify the external system (here, “on-premises”).
Reserve a range that overlaps existing subnets
Some network designs require internal ranges that overlap with existing subnet allocations, such as when coordinating with peered networks or planning migrations.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const defaultNetwork = new gcp.compute.Network("default", {
name: "internal-ranges",
autoCreateSubnetworks: false,
});
const defaultSubnetwork = new gcp.compute.Subnetwork("default", {
name: "overlapping-subnet",
ipCidrRange: "10.0.0.0/24",
region: "us-central1",
network: defaultNetwork.id,
});
const _default = new gcp.networkconnectivity.InternalRange("default", {
name: "overlap-range",
description: "Test internal range",
network: defaultNetwork.id,
usage: "FOR_VPC",
peering: "FOR_SELF",
ipCidrRange: "10.0.0.0/30",
overlaps: ["OVERLAP_EXISTING_SUBNET_RANGE"],
}, {
dependsOn: [defaultSubnetwork],
});
import pulumi
import pulumi_gcp as gcp
default_network = gcp.compute.Network("default",
name="internal-ranges",
auto_create_subnetworks=False)
default_subnetwork = gcp.compute.Subnetwork("default",
name="overlapping-subnet",
ip_cidr_range="10.0.0.0/24",
region="us-central1",
network=default_network.id)
default = gcp.networkconnectivity.InternalRange("default",
name="overlap-range",
description="Test internal range",
network=default_network.id,
usage="FOR_VPC",
peering="FOR_SELF",
ip_cidr_range="10.0.0.0/30",
overlaps=["OVERLAP_EXISTING_SUBNET_RANGE"],
opts = pulumi.ResourceOptions(depends_on=[default_subnetwork]))
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 {
defaultNetwork, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
Name: pulumi.String("internal-ranges"),
AutoCreateSubnetworks: pulumi.Bool(false),
})
if err != nil {
return err
}
defaultSubnetwork, err := compute.NewSubnetwork(ctx, "default", &compute.SubnetworkArgs{
Name: pulumi.String("overlapping-subnet"),
IpCidrRange: pulumi.String("10.0.0.0/24"),
Region: pulumi.String("us-central1"),
Network: defaultNetwork.ID(),
})
if err != nil {
return err
}
_, err = networkconnectivity.NewInternalRange(ctx, "default", &networkconnectivity.InternalRangeArgs{
Name: pulumi.String("overlap-range"),
Description: pulumi.String("Test internal range"),
Network: defaultNetwork.ID(),
Usage: pulumi.String("FOR_VPC"),
Peering: pulumi.String("FOR_SELF"),
IpCidrRange: pulumi.String("10.0.0.0/30"),
Overlaps: pulumi.StringArray{
pulumi.String("OVERLAP_EXISTING_SUBNET_RANGE"),
},
}, pulumi.DependsOn([]pulumi.Resource{
defaultSubnetwork,
}))
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 defaultNetwork = new Gcp.Compute.Network("default", new()
{
Name = "internal-ranges",
AutoCreateSubnetworks = false,
});
var defaultSubnetwork = new Gcp.Compute.Subnetwork("default", new()
{
Name = "overlapping-subnet",
IpCidrRange = "10.0.0.0/24",
Region = "us-central1",
Network = defaultNetwork.Id,
});
var @default = new Gcp.NetworkConnectivity.InternalRange("default", new()
{
Name = "overlap-range",
Description = "Test internal range",
Network = defaultNetwork.Id,
Usage = "FOR_VPC",
Peering = "FOR_SELF",
IpCidrRange = "10.0.0.0/30",
Overlaps = new[]
{
"OVERLAP_EXISTING_SUBNET_RANGE",
},
}, new CustomResourceOptions
{
DependsOn =
{
defaultSubnetwork,
},
});
});
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.networkconnectivity.InternalRange;
import com.pulumi.gcp.networkconnectivity.InternalRangeArgs;
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 defaultNetwork = new Network("defaultNetwork", NetworkArgs.builder()
.name("internal-ranges")
.autoCreateSubnetworks(false)
.build());
var defaultSubnetwork = new Subnetwork("defaultSubnetwork", SubnetworkArgs.builder()
.name("overlapping-subnet")
.ipCidrRange("10.0.0.0/24")
.region("us-central1")
.network(defaultNetwork.id())
.build());
var default_ = new InternalRange("default", InternalRangeArgs.builder()
.name("overlap-range")
.description("Test internal range")
.network(defaultNetwork.id())
.usage("FOR_VPC")
.peering("FOR_SELF")
.ipCidrRange("10.0.0.0/30")
.overlaps("OVERLAP_EXISTING_SUBNET_RANGE")
.build(), CustomResourceOptions.builder()
.dependsOn(defaultSubnetwork)
.build());
}
}
resources:
default:
type: gcp:networkconnectivity:InternalRange
properties:
name: overlap-range
description: Test internal range
network: ${defaultNetwork.id}
usage: FOR_VPC
peering: FOR_SELF
ipCidrRange: 10.0.0.0/30
overlaps:
- OVERLAP_EXISTING_SUBNET_RANGE
options:
dependsOn:
- ${defaultSubnetwork}
defaultNetwork:
type: gcp:compute:Network
name: default
properties:
name: internal-ranges
autoCreateSubnetworks: false
defaultSubnetwork:
type: gcp:compute:Subnetwork
name: default
properties:
name: overlapping-subnet
ipCidrRange: 10.0.0.0/24
region: us-central1
network: ${defaultNetwork.id}
The overlaps property allows intentional overlap with existing resources. OVERLAP_EXISTING_SUBNET_RANGE permits this range to overlap with the subnet created earlier. The dependsOn ensures the subnet exists before the internal range is created. Without the overlaps property, GCP would reject the conflicting CIDR.
Define a range for subnet migration
Subnet migrations between projects or regions require an internal range that tracks both the source subnet and the target destination.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const defaultNetwork = new gcp.compute.Network("default", {
name: "internal-ranges",
autoCreateSubnetworks: false,
});
const source = new gcp.compute.Subnetwork("source", {
name: "source-subnet",
ipCidrRange: "10.1.0.0/16",
region: "us-central1",
network: defaultNetwork.name,
});
const targetProject = gcp.organizations.getProject({});
const _default = new gcp.networkconnectivity.InternalRange("default", {
name: "migration",
description: "Test internal range",
network: defaultNetwork.selfLink,
usage: "FOR_MIGRATION",
peering: "FOR_SELF",
ipCidrRange: "10.1.0.0/16",
migration: {
source: source.selfLink,
target: targetProject.then(targetProject => `projects/${targetProject.projectId}/regions/us-central1/subnetworks/target-subnet`),
},
});
import pulumi
import pulumi_gcp as gcp
default_network = gcp.compute.Network("default",
name="internal-ranges",
auto_create_subnetworks=False)
source = gcp.compute.Subnetwork("source",
name="source-subnet",
ip_cidr_range="10.1.0.0/16",
region="us-central1",
network=default_network.name)
target_project = gcp.organizations.get_project()
default = gcp.networkconnectivity.InternalRange("default",
name="migration",
description="Test internal range",
network=default_network.self_link,
usage="FOR_MIGRATION",
peering="FOR_SELF",
ip_cidr_range="10.1.0.0/16",
migration={
"source": source.self_link,
"target": f"projects/{target_project.project_id}/regions/us-central1/subnetworks/target-subnet",
})
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networkconnectivity"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
defaultNetwork, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
Name: pulumi.String("internal-ranges"),
AutoCreateSubnetworks: pulumi.Bool(false),
})
if err != nil {
return err
}
source, err := compute.NewSubnetwork(ctx, "source", &compute.SubnetworkArgs{
Name: pulumi.String("source-subnet"),
IpCidrRange: pulumi.String("10.1.0.0/16"),
Region: pulumi.String("us-central1"),
Network: defaultNetwork.Name,
})
if err != nil {
return err
}
targetProject, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
if err != nil {
return err
}
_, err = networkconnectivity.NewInternalRange(ctx, "default", &networkconnectivity.InternalRangeArgs{
Name: pulumi.String("migration"),
Description: pulumi.String("Test internal range"),
Network: defaultNetwork.SelfLink,
Usage: pulumi.String("FOR_MIGRATION"),
Peering: pulumi.String("FOR_SELF"),
IpCidrRange: pulumi.String("10.1.0.0/16"),
Migration: &networkconnectivity.InternalRangeMigrationArgs{
Source: source.SelfLink,
Target: pulumi.Sprintf("projects/%v/regions/us-central1/subnetworks/target-subnet", targetProject.ProjectId),
},
})
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 defaultNetwork = new Gcp.Compute.Network("default", new()
{
Name = "internal-ranges",
AutoCreateSubnetworks = false,
});
var source = new Gcp.Compute.Subnetwork("source", new()
{
Name = "source-subnet",
IpCidrRange = "10.1.0.0/16",
Region = "us-central1",
Network = defaultNetwork.Name,
});
var targetProject = Gcp.Organizations.GetProject.Invoke();
var @default = new Gcp.NetworkConnectivity.InternalRange("default", new()
{
Name = "migration",
Description = "Test internal range",
Network = defaultNetwork.SelfLink,
Usage = "FOR_MIGRATION",
Peering = "FOR_SELF",
IpCidrRange = "10.1.0.0/16",
Migration = new Gcp.NetworkConnectivity.Inputs.InternalRangeMigrationArgs
{
Source = source.SelfLink,
Target = $"projects/{targetProject.Apply(getProjectResult => getProjectResult.ProjectId)}/regions/us-central1/subnetworks/target-subnet",
},
});
});
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.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.networkconnectivity.InternalRange;
import com.pulumi.gcp.networkconnectivity.InternalRangeArgs;
import com.pulumi.gcp.networkconnectivity.inputs.InternalRangeMigrationArgs;
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 defaultNetwork = new Network("defaultNetwork", NetworkArgs.builder()
.name("internal-ranges")
.autoCreateSubnetworks(false)
.build());
var source = new Subnetwork("source", SubnetworkArgs.builder()
.name("source-subnet")
.ipCidrRange("10.1.0.0/16")
.region("us-central1")
.network(defaultNetwork.name())
.build());
final var targetProject = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
var default_ = new InternalRange("default", InternalRangeArgs.builder()
.name("migration")
.description("Test internal range")
.network(defaultNetwork.selfLink())
.usage("FOR_MIGRATION")
.peering("FOR_SELF")
.ipCidrRange("10.1.0.0/16")
.migration(InternalRangeMigrationArgs.builder()
.source(source.selfLink())
.target(String.format("projects/%s/regions/us-central1/subnetworks/target-subnet", targetProject.projectId()))
.build())
.build());
}
}
resources:
default:
type: gcp:networkconnectivity:InternalRange
properties:
name: migration
description: Test internal range
network: ${defaultNetwork.selfLink}
usage: FOR_MIGRATION
peering: FOR_SELF
ipCidrRange: 10.1.0.0/16
migration:
source: ${source.selfLink}
target: projects/${targetProject.projectId}/regions/us-central1/subnetworks/target-subnet
defaultNetwork:
type: gcp:compute:Network
name: default
properties:
name: internal-ranges
autoCreateSubnetworks: false
source:
type: gcp:compute:Subnetwork
properties:
name: source-subnet
ipCidrRange: 10.1.0.0/16
region: us-central1
network: ${defaultNetwork.name}
variables:
targetProject:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The usage property set to FOR_MIGRATION indicates this range coordinates a subnet move. The migration block specifies the source subnet’s self-link and the target subnet’s path. This range acts as a coordination point during the migration process, ensuring address space continuity.
Control allocation strategy for automatic ranges
When using automatic allocation, you can specify how GCP selects from available address space, optimizing for compactness or other allocation patterns.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const defaultNetwork = new gcp.compute.Network("default", {
name: "internal-ranges",
autoCreateSubnetworks: false,
});
const _default = new gcp.networkconnectivity.InternalRange("default", {
name: "allocation-algorithms",
network: defaultNetwork.id,
usage: "FOR_VPC",
peering: "FOR_SELF",
prefixLength: 24,
targetCidrRanges: ["192.16.0.0/16"],
allocationOptions: {
allocationStrategy: "FIRST_SMALLEST_FITTING",
},
});
import pulumi
import pulumi_gcp as gcp
default_network = gcp.compute.Network("default",
name="internal-ranges",
auto_create_subnetworks=False)
default = gcp.networkconnectivity.InternalRange("default",
name="allocation-algorithms",
network=default_network.id,
usage="FOR_VPC",
peering="FOR_SELF",
prefix_length=24,
target_cidr_ranges=["192.16.0.0/16"],
allocation_options={
"allocation_strategy": "FIRST_SMALLEST_FITTING",
})
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 {
defaultNetwork, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
Name: pulumi.String("internal-ranges"),
AutoCreateSubnetworks: pulumi.Bool(false),
})
if err != nil {
return err
}
_, err = networkconnectivity.NewInternalRange(ctx, "default", &networkconnectivity.InternalRangeArgs{
Name: pulumi.String("allocation-algorithms"),
Network: defaultNetwork.ID(),
Usage: pulumi.String("FOR_VPC"),
Peering: pulumi.String("FOR_SELF"),
PrefixLength: pulumi.Int(24),
TargetCidrRanges: pulumi.StringArray{
pulumi.String("192.16.0.0/16"),
},
AllocationOptions: &networkconnectivity.InternalRangeAllocationOptionsArgs{
AllocationStrategy: pulumi.String("FIRST_SMALLEST_FITTING"),
},
})
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 defaultNetwork = new Gcp.Compute.Network("default", new()
{
Name = "internal-ranges",
AutoCreateSubnetworks = false,
});
var @default = new Gcp.NetworkConnectivity.InternalRange("default", new()
{
Name = "allocation-algorithms",
Network = defaultNetwork.Id,
Usage = "FOR_VPC",
Peering = "FOR_SELF",
PrefixLength = 24,
TargetCidrRanges = new[]
{
"192.16.0.0/16",
},
AllocationOptions = new Gcp.NetworkConnectivity.Inputs.InternalRangeAllocationOptionsArgs
{
AllocationStrategy = "FIRST_SMALLEST_FITTING",
},
});
});
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.networkconnectivity.InternalRange;
import com.pulumi.gcp.networkconnectivity.InternalRangeArgs;
import com.pulumi.gcp.networkconnectivity.inputs.InternalRangeAllocationOptionsArgs;
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 defaultNetwork = new Network("defaultNetwork", NetworkArgs.builder()
.name("internal-ranges")
.autoCreateSubnetworks(false)
.build());
var default_ = new InternalRange("default", InternalRangeArgs.builder()
.name("allocation-algorithms")
.network(defaultNetwork.id())
.usage("FOR_VPC")
.peering("FOR_SELF")
.prefixLength(24)
.targetCidrRanges("192.16.0.0/16")
.allocationOptions(InternalRangeAllocationOptionsArgs.builder()
.allocationStrategy("FIRST_SMALLEST_FITTING")
.build())
.build());
}
}
resources:
default:
type: gcp:networkconnectivity:InternalRange
properties:
name: allocation-algorithms
network: ${defaultNetwork.id}
usage: FOR_VPC
peering: FOR_SELF
prefixLength: 24
targetCidrRanges:
- 192.16.0.0/16
allocationOptions:
allocationStrategy: FIRST_SMALLEST_FITTING
defaultNetwork:
type: gcp:compute:Network
name: default
properties:
name: internal-ranges
autoCreateSubnetworks: false
The allocationOptions block controls how GCP chooses from available space. The allocationStrategy property set to FIRST_SMALLEST_FITTING selects the smallest available range that fits the requested size, promoting efficient address packing. This extends the automatic allocation pattern from earlier examples with explicit strategy control.
Beyond these examples
These snippets focus on specific internal range features: fixed and automatic CIDR allocation, external range tracking, and overlap handling and subnet migration. They’re intentionally minimal rather than full network designs.
The examples reference pre-existing infrastructure such as VPC networks, and existing subnets for overlap and migration scenarios. They focus on configuring the internal range rather than provisioning complete network topologies.
To keep things focused, common internal range patterns are omitted, including:
- Exclusion ranges (excludeCidrRanges)
- Immutability controls (immutable property)
- IPv6 range configuration
- Random allocation with firstAvailableRangesLookupSize
These omissions are intentional: the goal is to illustrate how each internal range feature is wired, not provide drop-in IPAM modules. See the InternalRange resource reference for all available configuration options.
Let's configure GCP Internal Ranges for VPC Networks
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
IP Range Configuration
ipCidrRange to manually specify an exact range (e.g., “10.0.0.0/24”), or use prefixLength to let GCP automatically find a free range of that size. If you set both, their sizes must match or you’ll get an error. For IPv6, you must always set ipCidrRange.usage=EXTERNAL_TO_VPC and peering=FOR_SELF. You must explicitly specify ipCidrRange for IPv6. If you also set prefixLength, it must match the ipCidrRange size (it acts as a redundant parameter).prefixLength during updates to change the range size. This allows resizing without recreating the resource.Automatic Allocation
prefixLength to your desired size (e.g., 24 for a /24 network) and optionally configure targetCidrRanges to narrow the search space. GCP will automatically find a free range.targetCidrRanges, GCP defaults to searching within “10.0.0.0/8”. You can specify other RFC-1918 ranges like “172.16.0.0/12” and “192.168.0.0/16”, or non-RFC-1918 ranges used in your VPC.You have two options in allocationOptions:
- FIRST_SMALLEST_FITTING - Finds the smallest available range that fits
- RANDOM_FIRST_N_AVAILABLE - Randomly selects from the first N available ranges (set N with
firstAvailableRangesLookupSize)
Usage Types & Peering
Three usage types are available:
- FOR_VPC - For internal VPC resources
- EXTERNAL_TO_VPC - For on-premises or external networks
- FOR_MIGRATION - For migrating subnets between projects
usage to EXTERNAL_TO_VPC and specify your on-premises IP range in ipCidrRange. This reserves the range without creating VPC resources.peering field controls range sharing: FOR_SELF (only your VPC), FOR_PEER (shared with peered VPCs), or NOT_SHARED (not shared at all).Overlaps & Conflicts
overlaps field to ["OVERLAP_EXISTING_SUBNET_RANGE"]. Use dependsOn to ensure the overlapping subnet exists before creating the internal range.labels field is non-authoritative and only manages labels in your Pulumi configuration. To see all labels (including those set by other clients), use the effectiveLabels output property.Migration & Immutability
usage to FOR_MIGRATION and configure the migration block with source (your existing subnet’s self-link) and target (the destination subnet path in the target project).name, project, allocationOptions, and migration. If you set immutable to true, all fields except labels and description become immutable.Using a different cloud?
Explore networking guides for other cloud providers: