The gcp:compute/globalForwardingRule:GlobalForwardingRule resource, part of the Pulumi GCP provider, defines the entry point for global load balancers: the IP address, port, and target that receives incoming traffic. This guide focuses on three capabilities: HTTP load balancing with target proxies, internal self-managed routing for service mesh, and Private Service Connect to Google APIs.
Forwarding rules sit at the front of load balancing architectures, directing traffic to target proxies, URL maps, and backend services. The examples are intentionally small. Combine them with your own backend infrastructure, health checks, and routing configuration.
Route HTTP traffic to a target proxy
Most HTTP load balancers start by creating a forwarding rule that accepts traffic on port 80 and directs it to a target proxy.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const defaultHttpHealthCheck = new gcp.compute.HttpHealthCheck("default", {
name: "check-backend",
requestPath: "/",
checkIntervalSec: 1,
timeoutSec: 1,
});
const defaultBackendService = new gcp.compute.BackendService("default", {
name: "backend",
portName: "http",
protocol: "HTTP",
timeoutSec: 10,
healthChecks: defaultHttpHealthCheck.id,
});
const defaultURLMap = new gcp.compute.URLMap("default", {
name: "url-map-target-proxy",
description: "a description",
defaultService: defaultBackendService.id,
hostRules: [{
hosts: ["mysite.com"],
pathMatcher: "allpaths",
}],
pathMatchers: [{
name: "allpaths",
defaultService: defaultBackendService.id,
pathRules: [{
paths: ["/*"],
service: defaultBackendService.id,
}],
}],
});
const defaultTargetHttpProxy = new gcp.compute.TargetHttpProxy("default", {
name: "target-proxy",
description: "a description",
urlMap: defaultURLMap.id,
});
const _default = new gcp.compute.GlobalForwardingRule("default", {
name: "global-rule",
target: defaultTargetHttpProxy.id,
portRange: "80",
});
import pulumi
import pulumi_gcp as gcp
default_http_health_check = gcp.compute.HttpHealthCheck("default",
name="check-backend",
request_path="/",
check_interval_sec=1,
timeout_sec=1)
default_backend_service = gcp.compute.BackendService("default",
name="backend",
port_name="http",
protocol="HTTP",
timeout_sec=10,
health_checks=default_http_health_check.id)
default_url_map = gcp.compute.URLMap("default",
name="url-map-target-proxy",
description="a description",
default_service=default_backend_service.id,
host_rules=[{
"hosts": ["mysite.com"],
"path_matcher": "allpaths",
}],
path_matchers=[{
"name": "allpaths",
"default_service": default_backend_service.id,
"path_rules": [{
"paths": ["/*"],
"service": default_backend_service.id,
}],
}])
default_target_http_proxy = gcp.compute.TargetHttpProxy("default",
name="target-proxy",
description="a description",
url_map=default_url_map.id)
default = gcp.compute.GlobalForwardingRule("default",
name="global-rule",
target=default_target_http_proxy.id,
port_range="80")
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 {
defaultHttpHealthCheck, err := compute.NewHttpHealthCheck(ctx, "default", &compute.HttpHealthCheckArgs{
Name: pulumi.String("check-backend"),
RequestPath: pulumi.String("/"),
CheckIntervalSec: pulumi.Int(1),
TimeoutSec: pulumi.Int(1),
})
if err != nil {
return err
}
defaultBackendService, err := compute.NewBackendService(ctx, "default", &compute.BackendServiceArgs{
Name: pulumi.String("backend"),
PortName: pulumi.String("http"),
Protocol: pulumi.String("HTTP"),
TimeoutSec: pulumi.Int(10),
HealthChecks: defaultHttpHealthCheck.ID(),
})
if err != nil {
return err
}
defaultURLMap, err := compute.NewURLMap(ctx, "default", &compute.URLMapArgs{
Name: pulumi.String("url-map-target-proxy"),
Description: pulumi.String("a description"),
DefaultService: defaultBackendService.ID(),
HostRules: compute.URLMapHostRuleArray{
&compute.URLMapHostRuleArgs{
Hosts: pulumi.StringArray{
pulumi.String("mysite.com"),
},
PathMatcher: pulumi.String("allpaths"),
},
},
PathMatchers: compute.URLMapPathMatcherArray{
&compute.URLMapPathMatcherArgs{
Name: pulumi.String("allpaths"),
DefaultService: defaultBackendService.ID(),
PathRules: compute.URLMapPathMatcherPathRuleArray{
&compute.URLMapPathMatcherPathRuleArgs{
Paths: pulumi.StringArray{
pulumi.String("/*"),
},
Service: defaultBackendService.ID(),
},
},
},
},
})
if err != nil {
return err
}
defaultTargetHttpProxy, err := compute.NewTargetHttpProxy(ctx, "default", &compute.TargetHttpProxyArgs{
Name: pulumi.String("target-proxy"),
Description: pulumi.String("a description"),
UrlMap: defaultURLMap.ID(),
})
if err != nil {
return err
}
_, err = compute.NewGlobalForwardingRule(ctx, "default", &compute.GlobalForwardingRuleArgs{
Name: pulumi.String("global-rule"),
Target: defaultTargetHttpProxy.ID(),
PortRange: pulumi.String("80"),
})
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 defaultHttpHealthCheck = new Gcp.Compute.HttpHealthCheck("default", new()
{
Name = "check-backend",
RequestPath = "/",
CheckIntervalSec = 1,
TimeoutSec = 1,
});
var defaultBackendService = new Gcp.Compute.BackendService("default", new()
{
Name = "backend",
PortName = "http",
Protocol = "HTTP",
TimeoutSec = 10,
HealthChecks = defaultHttpHealthCheck.Id,
});
var defaultURLMap = new Gcp.Compute.URLMap("default", new()
{
Name = "url-map-target-proxy",
Description = "a description",
DefaultService = defaultBackendService.Id,
HostRules = new[]
{
new Gcp.Compute.Inputs.URLMapHostRuleArgs
{
Hosts = new[]
{
"mysite.com",
},
PathMatcher = "allpaths",
},
},
PathMatchers = new[]
{
new Gcp.Compute.Inputs.URLMapPathMatcherArgs
{
Name = "allpaths",
DefaultService = defaultBackendService.Id,
PathRules = new[]
{
new Gcp.Compute.Inputs.URLMapPathMatcherPathRuleArgs
{
Paths = new[]
{
"/*",
},
Service = defaultBackendService.Id,
},
},
},
},
});
var defaultTargetHttpProxy = new Gcp.Compute.TargetHttpProxy("default", new()
{
Name = "target-proxy",
Description = "a description",
UrlMap = defaultURLMap.Id,
});
var @default = new Gcp.Compute.GlobalForwardingRule("default", new()
{
Name = "global-rule",
Target = defaultTargetHttpProxy.Id,
PortRange = "80",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.HttpHealthCheck;
import com.pulumi.gcp.compute.HttpHealthCheckArgs;
import com.pulumi.gcp.compute.BackendService;
import com.pulumi.gcp.compute.BackendServiceArgs;
import com.pulumi.gcp.compute.URLMap;
import com.pulumi.gcp.compute.URLMapArgs;
import com.pulumi.gcp.compute.inputs.URLMapHostRuleArgs;
import com.pulumi.gcp.compute.inputs.URLMapPathMatcherArgs;
import com.pulumi.gcp.compute.TargetHttpProxy;
import com.pulumi.gcp.compute.TargetHttpProxyArgs;
import com.pulumi.gcp.compute.GlobalForwardingRule;
import com.pulumi.gcp.compute.GlobalForwardingRuleArgs;
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 defaultHttpHealthCheck = new HttpHealthCheck("defaultHttpHealthCheck", HttpHealthCheckArgs.builder()
.name("check-backend")
.requestPath("/")
.checkIntervalSec(1)
.timeoutSec(1)
.build());
var defaultBackendService = new BackendService("defaultBackendService", BackendServiceArgs.builder()
.name("backend")
.portName("http")
.protocol("HTTP")
.timeoutSec(10)
.healthChecks(defaultHttpHealthCheck.id())
.build());
var defaultURLMap = new URLMap("defaultURLMap", URLMapArgs.builder()
.name("url-map-target-proxy")
.description("a description")
.defaultService(defaultBackendService.id())
.hostRules(URLMapHostRuleArgs.builder()
.hosts("mysite.com")
.pathMatcher("allpaths")
.build())
.pathMatchers(URLMapPathMatcherArgs.builder()
.name("allpaths")
.defaultService(defaultBackendService.id())
.pathRules(URLMapPathMatcherPathRuleArgs.builder()
.paths("/*")
.service(defaultBackendService.id())
.build())
.build())
.build());
var defaultTargetHttpProxy = new TargetHttpProxy("defaultTargetHttpProxy", TargetHttpProxyArgs.builder()
.name("target-proxy")
.description("a description")
.urlMap(defaultURLMap.id())
.build());
var default_ = new GlobalForwardingRule("default", GlobalForwardingRuleArgs.builder()
.name("global-rule")
.target(defaultTargetHttpProxy.id())
.portRange("80")
.build());
}
}
resources:
default:
type: gcp:compute:GlobalForwardingRule
properties:
name: global-rule
target: ${defaultTargetHttpProxy.id}
portRange: '80'
defaultTargetHttpProxy:
type: gcp:compute:TargetHttpProxy
name: default
properties:
name: target-proxy
description: a description
urlMap: ${defaultURLMap.id}
defaultURLMap:
type: gcp:compute:URLMap
name: default
properties:
name: url-map-target-proxy
description: a description
defaultService: ${defaultBackendService.id}
hostRules:
- hosts:
- mysite.com
pathMatcher: allpaths
pathMatchers:
- name: allpaths
defaultService: ${defaultBackendService.id}
pathRules:
- paths:
- /*
service: ${defaultBackendService.id}
defaultBackendService:
type: gcp:compute:BackendService
name: default
properties:
name: backend
portName: http
protocol: HTTP
timeoutSec: 10
healthChecks: ${defaultHttpHealthCheck.id}
defaultHttpHealthCheck:
type: gcp:compute:HttpHealthCheck
name: default
properties:
name: check-backend
requestPath: /
checkIntervalSec: 1
timeoutSec: 1
When a client sends traffic to the forwarding rule’s IP address, the rule directs it to the target proxy specified in the target property. The portRange property defines which port accepts traffic. The target proxy then consults the URL map to route requests to appropriate backend services based on hostname and path.
Configure internal self-managed load balancing
Service mesh deployments need internal load balancing without public IPs, using metadata filters to control routing configuration distribution.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const debianImage = gcp.compute.getImage({
family: "debian-11",
project: "debian-cloud",
});
const instanceTemplate = new gcp.compute.InstanceTemplate("instance_template", {
name: "template-backend",
machineType: "e2-medium",
networkInterfaces: [{
network: "default",
}],
disks: [{
sourceImage: debianImage.then(debianImage => debianImage.selfLink),
autoDelete: true,
boot: true,
}],
});
const igm = new gcp.compute.InstanceGroupManager("igm", {
name: "igm-internal",
versions: [{
instanceTemplate: instanceTemplate.id,
name: "primary",
}],
baseInstanceName: "internal-glb",
zone: "us-central1-f",
targetSize: 1,
});
const defaultHealthCheck = new gcp.compute.HealthCheck("default", {
name: "check-backend",
checkIntervalSec: 1,
timeoutSec: 1,
tcpHealthCheck: {
port: 80,
},
});
const defaultBackendService = new gcp.compute.BackendService("default", {
name: "backend",
portName: "http",
protocol: "HTTP",
timeoutSec: 10,
loadBalancingScheme: "INTERNAL_SELF_MANAGED",
backends: [{
group: igm.instanceGroup,
balancingMode: "RATE",
capacityScaler: 0.4,
maxRatePerInstance: 50,
}],
healthChecks: defaultHealthCheck.id,
});
const defaultURLMap = new gcp.compute.URLMap("default", {
name: "url-map-target-proxy",
description: "a description",
defaultService: defaultBackendService.id,
hostRules: [{
hosts: ["mysite.com"],
pathMatcher: "allpaths",
}],
pathMatchers: [{
name: "allpaths",
defaultService: defaultBackendService.id,
pathRules: [{
paths: ["/*"],
service: defaultBackendService.id,
}],
}],
});
const defaultTargetHttpProxy = new gcp.compute.TargetHttpProxy("default", {
name: "target-proxy",
description: "a description",
urlMap: defaultURLMap.id,
});
const _default = new gcp.compute.GlobalForwardingRule("default", {
name: "global-rule",
target: defaultTargetHttpProxy.id,
portRange: "80",
loadBalancingScheme: "INTERNAL_SELF_MANAGED",
ipAddress: "0.0.0.0",
metadataFilters: [{
filterMatchCriteria: "MATCH_ANY",
filterLabels: [{
name: "PLANET",
value: "MARS",
}],
}],
});
import pulumi
import pulumi_gcp as gcp
debian_image = gcp.compute.get_image(family="debian-11",
project="debian-cloud")
instance_template = gcp.compute.InstanceTemplate("instance_template",
name="template-backend",
machine_type="e2-medium",
network_interfaces=[{
"network": "default",
}],
disks=[{
"source_image": debian_image.self_link,
"auto_delete": True,
"boot": True,
}])
igm = gcp.compute.InstanceGroupManager("igm",
name="igm-internal",
versions=[{
"instance_template": instance_template.id,
"name": "primary",
}],
base_instance_name="internal-glb",
zone="us-central1-f",
target_size=1)
default_health_check = gcp.compute.HealthCheck("default",
name="check-backend",
check_interval_sec=1,
timeout_sec=1,
tcp_health_check={
"port": 80,
})
default_backend_service = gcp.compute.BackendService("default",
name="backend",
port_name="http",
protocol="HTTP",
timeout_sec=10,
load_balancing_scheme="INTERNAL_SELF_MANAGED",
backends=[{
"group": igm.instance_group,
"balancing_mode": "RATE",
"capacity_scaler": 0.4,
"max_rate_per_instance": 50,
}],
health_checks=default_health_check.id)
default_url_map = gcp.compute.URLMap("default",
name="url-map-target-proxy",
description="a description",
default_service=default_backend_service.id,
host_rules=[{
"hosts": ["mysite.com"],
"path_matcher": "allpaths",
}],
path_matchers=[{
"name": "allpaths",
"default_service": default_backend_service.id,
"path_rules": [{
"paths": ["/*"],
"service": default_backend_service.id,
}],
}])
default_target_http_proxy = gcp.compute.TargetHttpProxy("default",
name="target-proxy",
description="a description",
url_map=default_url_map.id)
default = gcp.compute.GlobalForwardingRule("default",
name="global-rule",
target=default_target_http_proxy.id,
port_range="80",
load_balancing_scheme="INTERNAL_SELF_MANAGED",
ip_address="0.0.0.0",
metadata_filters=[{
"filter_match_criteria": "MATCH_ANY",
"filter_labels": [{
"name": "PLANET",
"value": "MARS",
}],
}])
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 {
debianImage, err := compute.LookupImage(ctx, &compute.LookupImageArgs{
Family: pulumi.StringRef("debian-11"),
Project: pulumi.StringRef("debian-cloud"),
}, nil)
if err != nil {
return err
}
instanceTemplate, err := compute.NewInstanceTemplate(ctx, "instance_template", &compute.InstanceTemplateArgs{
Name: pulumi.String("template-backend"),
MachineType: pulumi.String("e2-medium"),
NetworkInterfaces: compute.InstanceTemplateNetworkInterfaceArray{
&compute.InstanceTemplateNetworkInterfaceArgs{
Network: pulumi.String("default"),
},
},
Disks: compute.InstanceTemplateDiskArray{
&compute.InstanceTemplateDiskArgs{
SourceImage: pulumi.String(debianImage.SelfLink),
AutoDelete: pulumi.Bool(true),
Boot: pulumi.Bool(true),
},
},
})
if err != nil {
return err
}
igm, err := compute.NewInstanceGroupManager(ctx, "igm", &compute.InstanceGroupManagerArgs{
Name: pulumi.String("igm-internal"),
Versions: compute.InstanceGroupManagerVersionArray{
&compute.InstanceGroupManagerVersionArgs{
InstanceTemplate: instanceTemplate.ID(),
Name: pulumi.String("primary"),
},
},
BaseInstanceName: pulumi.String("internal-glb"),
Zone: pulumi.String("us-central1-f"),
TargetSize: pulumi.Int(1),
})
if err != nil {
return err
}
defaultHealthCheck, err := compute.NewHealthCheck(ctx, "default", &compute.HealthCheckArgs{
Name: pulumi.String("check-backend"),
CheckIntervalSec: pulumi.Int(1),
TimeoutSec: pulumi.Int(1),
TcpHealthCheck: &compute.HealthCheckTcpHealthCheckArgs{
Port: pulumi.Int(80),
},
})
if err != nil {
return err
}
defaultBackendService, err := compute.NewBackendService(ctx, "default", &compute.BackendServiceArgs{
Name: pulumi.String("backend"),
PortName: pulumi.String("http"),
Protocol: pulumi.String("HTTP"),
TimeoutSec: pulumi.Int(10),
LoadBalancingScheme: pulumi.String("INTERNAL_SELF_MANAGED"),
Backends: compute.BackendServiceBackendArray{
&compute.BackendServiceBackendArgs{
Group: igm.InstanceGroup,
BalancingMode: pulumi.String("RATE"),
CapacityScaler: pulumi.Float64(0.4),
MaxRatePerInstance: pulumi.Float64(50),
},
},
HealthChecks: defaultHealthCheck.ID(),
})
if err != nil {
return err
}
defaultURLMap, err := compute.NewURLMap(ctx, "default", &compute.URLMapArgs{
Name: pulumi.String("url-map-target-proxy"),
Description: pulumi.String("a description"),
DefaultService: defaultBackendService.ID(),
HostRules: compute.URLMapHostRuleArray{
&compute.URLMapHostRuleArgs{
Hosts: pulumi.StringArray{
pulumi.String("mysite.com"),
},
PathMatcher: pulumi.String("allpaths"),
},
},
PathMatchers: compute.URLMapPathMatcherArray{
&compute.URLMapPathMatcherArgs{
Name: pulumi.String("allpaths"),
DefaultService: defaultBackendService.ID(),
PathRules: compute.URLMapPathMatcherPathRuleArray{
&compute.URLMapPathMatcherPathRuleArgs{
Paths: pulumi.StringArray{
pulumi.String("/*"),
},
Service: defaultBackendService.ID(),
},
},
},
},
})
if err != nil {
return err
}
defaultTargetHttpProxy, err := compute.NewTargetHttpProxy(ctx, "default", &compute.TargetHttpProxyArgs{
Name: pulumi.String("target-proxy"),
Description: pulumi.String("a description"),
UrlMap: defaultURLMap.ID(),
})
if err != nil {
return err
}
_, err = compute.NewGlobalForwardingRule(ctx, "default", &compute.GlobalForwardingRuleArgs{
Name: pulumi.String("global-rule"),
Target: defaultTargetHttpProxy.ID(),
PortRange: pulumi.String("80"),
LoadBalancingScheme: pulumi.String("INTERNAL_SELF_MANAGED"),
IpAddress: pulumi.String("0.0.0.0"),
MetadataFilters: compute.GlobalForwardingRuleMetadataFilterArray{
&compute.GlobalForwardingRuleMetadataFilterArgs{
FilterMatchCriteria: pulumi.String("MATCH_ANY"),
FilterLabels: compute.GlobalForwardingRuleMetadataFilterFilterLabelArray{
&compute.GlobalForwardingRuleMetadataFilterFilterLabelArgs{
Name: pulumi.String("PLANET"),
Value: pulumi.String("MARS"),
},
},
},
},
})
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 debianImage = Gcp.Compute.GetImage.Invoke(new()
{
Family = "debian-11",
Project = "debian-cloud",
});
var instanceTemplate = new Gcp.Compute.InstanceTemplate("instance_template", new()
{
Name = "template-backend",
MachineType = "e2-medium",
NetworkInterfaces = new[]
{
new Gcp.Compute.Inputs.InstanceTemplateNetworkInterfaceArgs
{
Network = "default",
},
},
Disks = new[]
{
new Gcp.Compute.Inputs.InstanceTemplateDiskArgs
{
SourceImage = debianImage.Apply(getImageResult => getImageResult.SelfLink),
AutoDelete = true,
Boot = true,
},
},
});
var igm = new Gcp.Compute.InstanceGroupManager("igm", new()
{
Name = "igm-internal",
Versions = new[]
{
new Gcp.Compute.Inputs.InstanceGroupManagerVersionArgs
{
InstanceTemplate = instanceTemplate.Id,
Name = "primary",
},
},
BaseInstanceName = "internal-glb",
Zone = "us-central1-f",
TargetSize = 1,
});
var defaultHealthCheck = new Gcp.Compute.HealthCheck("default", new()
{
Name = "check-backend",
CheckIntervalSec = 1,
TimeoutSec = 1,
TcpHealthCheck = new Gcp.Compute.Inputs.HealthCheckTcpHealthCheckArgs
{
Port = 80,
},
});
var defaultBackendService = new Gcp.Compute.BackendService("default", new()
{
Name = "backend",
PortName = "http",
Protocol = "HTTP",
TimeoutSec = 10,
LoadBalancingScheme = "INTERNAL_SELF_MANAGED",
Backends = new[]
{
new Gcp.Compute.Inputs.BackendServiceBackendArgs
{
Group = igm.InstanceGroup,
BalancingMode = "RATE",
CapacityScaler = 0.4,
MaxRatePerInstance = 50,
},
},
HealthChecks = defaultHealthCheck.Id,
});
var defaultURLMap = new Gcp.Compute.URLMap("default", new()
{
Name = "url-map-target-proxy",
Description = "a description",
DefaultService = defaultBackendService.Id,
HostRules = new[]
{
new Gcp.Compute.Inputs.URLMapHostRuleArgs
{
Hosts = new[]
{
"mysite.com",
},
PathMatcher = "allpaths",
},
},
PathMatchers = new[]
{
new Gcp.Compute.Inputs.URLMapPathMatcherArgs
{
Name = "allpaths",
DefaultService = defaultBackendService.Id,
PathRules = new[]
{
new Gcp.Compute.Inputs.URLMapPathMatcherPathRuleArgs
{
Paths = new[]
{
"/*",
},
Service = defaultBackendService.Id,
},
},
},
},
});
var defaultTargetHttpProxy = new Gcp.Compute.TargetHttpProxy("default", new()
{
Name = "target-proxy",
Description = "a description",
UrlMap = defaultURLMap.Id,
});
var @default = new Gcp.Compute.GlobalForwardingRule("default", new()
{
Name = "global-rule",
Target = defaultTargetHttpProxy.Id,
PortRange = "80",
LoadBalancingScheme = "INTERNAL_SELF_MANAGED",
IpAddress = "0.0.0.0",
MetadataFilters = new[]
{
new Gcp.Compute.Inputs.GlobalForwardingRuleMetadataFilterArgs
{
FilterMatchCriteria = "MATCH_ANY",
FilterLabels = new[]
{
new Gcp.Compute.Inputs.GlobalForwardingRuleMetadataFilterFilterLabelArgs
{
Name = "PLANET",
Value = "MARS",
},
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.ComputeFunctions;
import com.pulumi.gcp.compute.inputs.GetImageArgs;
import com.pulumi.gcp.compute.InstanceTemplate;
import com.pulumi.gcp.compute.InstanceTemplateArgs;
import com.pulumi.gcp.compute.inputs.InstanceTemplateNetworkInterfaceArgs;
import com.pulumi.gcp.compute.inputs.InstanceTemplateDiskArgs;
import com.pulumi.gcp.compute.InstanceGroupManager;
import com.pulumi.gcp.compute.InstanceGroupManagerArgs;
import com.pulumi.gcp.compute.inputs.InstanceGroupManagerVersionArgs;
import com.pulumi.gcp.compute.HealthCheck;
import com.pulumi.gcp.compute.HealthCheckArgs;
import com.pulumi.gcp.compute.inputs.HealthCheckTcpHealthCheckArgs;
import com.pulumi.gcp.compute.BackendService;
import com.pulumi.gcp.compute.BackendServiceArgs;
import com.pulumi.gcp.compute.inputs.BackendServiceBackendArgs;
import com.pulumi.gcp.compute.URLMap;
import com.pulumi.gcp.compute.URLMapArgs;
import com.pulumi.gcp.compute.inputs.URLMapHostRuleArgs;
import com.pulumi.gcp.compute.inputs.URLMapPathMatcherArgs;
import com.pulumi.gcp.compute.TargetHttpProxy;
import com.pulumi.gcp.compute.TargetHttpProxyArgs;
import com.pulumi.gcp.compute.GlobalForwardingRule;
import com.pulumi.gcp.compute.GlobalForwardingRuleArgs;
import com.pulumi.gcp.compute.inputs.GlobalForwardingRuleMetadataFilterArgs;
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) {
final var debianImage = ComputeFunctions.getImage(GetImageArgs.builder()
.family("debian-11")
.project("debian-cloud")
.build());
var instanceTemplate = new InstanceTemplate("instanceTemplate", InstanceTemplateArgs.builder()
.name("template-backend")
.machineType("e2-medium")
.networkInterfaces(InstanceTemplateNetworkInterfaceArgs.builder()
.network("default")
.build())
.disks(InstanceTemplateDiskArgs.builder()
.sourceImage(debianImage.selfLink())
.autoDelete(true)
.boot(true)
.build())
.build());
var igm = new InstanceGroupManager("igm", InstanceGroupManagerArgs.builder()
.name("igm-internal")
.versions(InstanceGroupManagerVersionArgs.builder()
.instanceTemplate(instanceTemplate.id())
.name("primary")
.build())
.baseInstanceName("internal-glb")
.zone("us-central1-f")
.targetSize(1)
.build());
var defaultHealthCheck = new HealthCheck("defaultHealthCheck", HealthCheckArgs.builder()
.name("check-backend")
.checkIntervalSec(1)
.timeoutSec(1)
.tcpHealthCheck(HealthCheckTcpHealthCheckArgs.builder()
.port(80)
.build())
.build());
var defaultBackendService = new BackendService("defaultBackendService", BackendServiceArgs.builder()
.name("backend")
.portName("http")
.protocol("HTTP")
.timeoutSec(10)
.loadBalancingScheme("INTERNAL_SELF_MANAGED")
.backends(BackendServiceBackendArgs.builder()
.group(igm.instanceGroup())
.balancingMode("RATE")
.capacityScaler(0.4)
.maxRatePerInstance(50.0)
.build())
.healthChecks(defaultHealthCheck.id())
.build());
var defaultURLMap = new URLMap("defaultURLMap", URLMapArgs.builder()
.name("url-map-target-proxy")
.description("a description")
.defaultService(defaultBackendService.id())
.hostRules(URLMapHostRuleArgs.builder()
.hosts("mysite.com")
.pathMatcher("allpaths")
.build())
.pathMatchers(URLMapPathMatcherArgs.builder()
.name("allpaths")
.defaultService(defaultBackendService.id())
.pathRules(URLMapPathMatcherPathRuleArgs.builder()
.paths("/*")
.service(defaultBackendService.id())
.build())
.build())
.build());
var defaultTargetHttpProxy = new TargetHttpProxy("defaultTargetHttpProxy", TargetHttpProxyArgs.builder()
.name("target-proxy")
.description("a description")
.urlMap(defaultURLMap.id())
.build());
var default_ = new GlobalForwardingRule("default", GlobalForwardingRuleArgs.builder()
.name("global-rule")
.target(defaultTargetHttpProxy.id())
.portRange("80")
.loadBalancingScheme("INTERNAL_SELF_MANAGED")
.ipAddress("0.0.0.0")
.metadataFilters(GlobalForwardingRuleMetadataFilterArgs.builder()
.filterMatchCriteria("MATCH_ANY")
.filterLabels(GlobalForwardingRuleMetadataFilterFilterLabelArgs.builder()
.name("PLANET")
.value("MARS")
.build())
.build())
.build());
}
}
resources:
default:
type: gcp:compute:GlobalForwardingRule
properties:
name: global-rule
target: ${defaultTargetHttpProxy.id}
portRange: '80'
loadBalancingScheme: INTERNAL_SELF_MANAGED
ipAddress: 0.0.0.0
metadataFilters:
- filterMatchCriteria: MATCH_ANY
filterLabels:
- name: PLANET
value: MARS
defaultTargetHttpProxy:
type: gcp:compute:TargetHttpProxy
name: default
properties:
name: target-proxy
description: a description
urlMap: ${defaultURLMap.id}
defaultURLMap:
type: gcp:compute:URLMap
name: default
properties:
name: url-map-target-proxy
description: a description
defaultService: ${defaultBackendService.id}
hostRules:
- hosts:
- mysite.com
pathMatcher: allpaths
pathMatchers:
- name: allpaths
defaultService: ${defaultBackendService.id}
pathRules:
- paths:
- /*
service: ${defaultBackendService.id}
defaultBackendService:
type: gcp:compute:BackendService
name: default
properties:
name: backend
portName: http
protocol: HTTP
timeoutSec: 10
loadBalancingScheme: INTERNAL_SELF_MANAGED
backends:
- group: ${igm.instanceGroup}
balancingMode: RATE
capacityScaler: 0.4
maxRatePerInstance: 50
healthChecks: ${defaultHealthCheck.id}
igm:
type: gcp:compute:InstanceGroupManager
properties:
name: igm-internal
versions:
- instanceTemplate: ${instanceTemplate.id}
name: primary
baseInstanceName: internal-glb
zone: us-central1-f
targetSize: 1
instanceTemplate:
type: gcp:compute:InstanceTemplate
name: instance_template
properties:
name: template-backend
machineType: e2-medium
networkInterfaces:
- network: default
disks:
- sourceImage: ${debianImage.selfLink}
autoDelete: true
boot: true
defaultHealthCheck:
type: gcp:compute:HealthCheck
name: default
properties:
name: check-backend
checkIntervalSec: 1
timeoutSec: 1
tcpHealthCheck:
port: '80'
variables:
debianImage:
fn::invoke:
function: gcp:compute:getImage
arguments:
family: debian-11
project: debian-cloud
The loadBalancingScheme property set to INTERNAL_SELF_MANAGED keeps traffic within your VPC. The ipAddress of 0.0.0.0 indicates this rule doesn’t bind to a specific IP. The metadataFilters property restricts which xDS-compliant proxies receive routing configuration; only proxies presenting matching node metadata get access to the backend services.
Use external managed load balancing
Modern Application Load Balancers use EXTERNAL_MANAGED scheme for advanced traffic management.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const defaultBackendService = new gcp.compute.BackendService("default", {
name: "backend",
portName: "http",
protocol: "HTTP",
timeoutSec: 10,
loadBalancingScheme: "EXTERNAL_MANAGED",
});
const defaultURLMap = new gcp.compute.URLMap("default", {
name: "url-map-target-proxy",
description: "a description",
defaultService: defaultBackendService.id,
hostRules: [{
hosts: ["mysite.com"],
pathMatcher: "allpaths",
}],
pathMatchers: [{
name: "allpaths",
defaultService: defaultBackendService.id,
pathRules: [{
paths: ["/*"],
service: defaultBackendService.id,
}],
}],
});
const defaultTargetHttpProxy = new gcp.compute.TargetHttpProxy("default", {
name: "target-proxy",
description: "a description",
urlMap: defaultURLMap.id,
});
const _default = new gcp.compute.GlobalForwardingRule("default", {
name: "global-rule",
target: defaultTargetHttpProxy.id,
portRange: "80",
loadBalancingScheme: "EXTERNAL_MANAGED",
networkTier: "PREMIUM",
});
import pulumi
import pulumi_gcp as gcp
default_backend_service = gcp.compute.BackendService("default",
name="backend",
port_name="http",
protocol="HTTP",
timeout_sec=10,
load_balancing_scheme="EXTERNAL_MANAGED")
default_url_map = gcp.compute.URLMap("default",
name="url-map-target-proxy",
description="a description",
default_service=default_backend_service.id,
host_rules=[{
"hosts": ["mysite.com"],
"path_matcher": "allpaths",
}],
path_matchers=[{
"name": "allpaths",
"default_service": default_backend_service.id,
"path_rules": [{
"paths": ["/*"],
"service": default_backend_service.id,
}],
}])
default_target_http_proxy = gcp.compute.TargetHttpProxy("default",
name="target-proxy",
description="a description",
url_map=default_url_map.id)
default = gcp.compute.GlobalForwardingRule("default",
name="global-rule",
target=default_target_http_proxy.id,
port_range="80",
load_balancing_scheme="EXTERNAL_MANAGED",
network_tier="PREMIUM")
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 {
defaultBackendService, err := compute.NewBackendService(ctx, "default", &compute.BackendServiceArgs{
Name: pulumi.String("backend"),
PortName: pulumi.String("http"),
Protocol: pulumi.String("HTTP"),
TimeoutSec: pulumi.Int(10),
LoadBalancingScheme: pulumi.String("EXTERNAL_MANAGED"),
})
if err != nil {
return err
}
defaultURLMap, err := compute.NewURLMap(ctx, "default", &compute.URLMapArgs{
Name: pulumi.String("url-map-target-proxy"),
Description: pulumi.String("a description"),
DefaultService: defaultBackendService.ID(),
HostRules: compute.URLMapHostRuleArray{
&compute.URLMapHostRuleArgs{
Hosts: pulumi.StringArray{
pulumi.String("mysite.com"),
},
PathMatcher: pulumi.String("allpaths"),
},
},
PathMatchers: compute.URLMapPathMatcherArray{
&compute.URLMapPathMatcherArgs{
Name: pulumi.String("allpaths"),
DefaultService: defaultBackendService.ID(),
PathRules: compute.URLMapPathMatcherPathRuleArray{
&compute.URLMapPathMatcherPathRuleArgs{
Paths: pulumi.StringArray{
pulumi.String("/*"),
},
Service: defaultBackendService.ID(),
},
},
},
},
})
if err != nil {
return err
}
defaultTargetHttpProxy, err := compute.NewTargetHttpProxy(ctx, "default", &compute.TargetHttpProxyArgs{
Name: pulumi.String("target-proxy"),
Description: pulumi.String("a description"),
UrlMap: defaultURLMap.ID(),
})
if err != nil {
return err
}
_, err = compute.NewGlobalForwardingRule(ctx, "default", &compute.GlobalForwardingRuleArgs{
Name: pulumi.String("global-rule"),
Target: defaultTargetHttpProxy.ID(),
PortRange: pulumi.String("80"),
LoadBalancingScheme: pulumi.String("EXTERNAL_MANAGED"),
NetworkTier: pulumi.String("PREMIUM"),
})
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 defaultBackendService = new Gcp.Compute.BackendService("default", new()
{
Name = "backend",
PortName = "http",
Protocol = "HTTP",
TimeoutSec = 10,
LoadBalancingScheme = "EXTERNAL_MANAGED",
});
var defaultURLMap = new Gcp.Compute.URLMap("default", new()
{
Name = "url-map-target-proxy",
Description = "a description",
DefaultService = defaultBackendService.Id,
HostRules = new[]
{
new Gcp.Compute.Inputs.URLMapHostRuleArgs
{
Hosts = new[]
{
"mysite.com",
},
PathMatcher = "allpaths",
},
},
PathMatchers = new[]
{
new Gcp.Compute.Inputs.URLMapPathMatcherArgs
{
Name = "allpaths",
DefaultService = defaultBackendService.Id,
PathRules = new[]
{
new Gcp.Compute.Inputs.URLMapPathMatcherPathRuleArgs
{
Paths = new[]
{
"/*",
},
Service = defaultBackendService.Id,
},
},
},
},
});
var defaultTargetHttpProxy = new Gcp.Compute.TargetHttpProxy("default", new()
{
Name = "target-proxy",
Description = "a description",
UrlMap = defaultURLMap.Id,
});
var @default = new Gcp.Compute.GlobalForwardingRule("default", new()
{
Name = "global-rule",
Target = defaultTargetHttpProxy.Id,
PortRange = "80",
LoadBalancingScheme = "EXTERNAL_MANAGED",
NetworkTier = "PREMIUM",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.BackendService;
import com.pulumi.gcp.compute.BackendServiceArgs;
import com.pulumi.gcp.compute.URLMap;
import com.pulumi.gcp.compute.URLMapArgs;
import com.pulumi.gcp.compute.inputs.URLMapHostRuleArgs;
import com.pulumi.gcp.compute.inputs.URLMapPathMatcherArgs;
import com.pulumi.gcp.compute.TargetHttpProxy;
import com.pulumi.gcp.compute.TargetHttpProxyArgs;
import com.pulumi.gcp.compute.GlobalForwardingRule;
import com.pulumi.gcp.compute.GlobalForwardingRuleArgs;
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 defaultBackendService = new BackendService("defaultBackendService", BackendServiceArgs.builder()
.name("backend")
.portName("http")
.protocol("HTTP")
.timeoutSec(10)
.loadBalancingScheme("EXTERNAL_MANAGED")
.build());
var defaultURLMap = new URLMap("defaultURLMap", URLMapArgs.builder()
.name("url-map-target-proxy")
.description("a description")
.defaultService(defaultBackendService.id())
.hostRules(URLMapHostRuleArgs.builder()
.hosts("mysite.com")
.pathMatcher("allpaths")
.build())
.pathMatchers(URLMapPathMatcherArgs.builder()
.name("allpaths")
.defaultService(defaultBackendService.id())
.pathRules(URLMapPathMatcherPathRuleArgs.builder()
.paths("/*")
.service(defaultBackendService.id())
.build())
.build())
.build());
var defaultTargetHttpProxy = new TargetHttpProxy("defaultTargetHttpProxy", TargetHttpProxyArgs.builder()
.name("target-proxy")
.description("a description")
.urlMap(defaultURLMap.id())
.build());
var default_ = new GlobalForwardingRule("default", GlobalForwardingRuleArgs.builder()
.name("global-rule")
.target(defaultTargetHttpProxy.id())
.portRange("80")
.loadBalancingScheme("EXTERNAL_MANAGED")
.networkTier("PREMIUM")
.build());
}
}
resources:
default:
type: gcp:compute:GlobalForwardingRule
properties:
name: global-rule
target: ${defaultTargetHttpProxy.id}
portRange: '80'
loadBalancingScheme: EXTERNAL_MANAGED
networkTier: PREMIUM
defaultTargetHttpProxy:
type: gcp:compute:TargetHttpProxy
name: default
properties:
name: target-proxy
description: a description
urlMap: ${defaultURLMap.id}
defaultURLMap:
type: gcp:compute:URLMap
name: default
properties:
name: url-map-target-proxy
description: a description
defaultService: ${defaultBackendService.id}
hostRules:
- hosts:
- mysite.com
pathMatcher: allpaths
pathMatchers:
- name: allpaths
defaultService: ${defaultBackendService.id}
pathRules:
- paths:
- /*
service: ${defaultBackendService.id}
defaultBackendService:
type: gcp:compute:BackendService
name: default
properties:
name: backend
portName: http
protocol: HTTP
timeoutSec: 10
loadBalancingScheme: EXTERNAL_MANAGED
The EXTERNAL_MANAGED scheme enables features like traffic splitting and global load distribution. The networkTier property set to PREMIUM provides global anycast IP addresses and optimal routing across Google’s network.
Connect privately to Google APIs
Organizations access Google APIs without internet exposure by routing API traffic through their VPC network.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const network = new gcp.compute.Network("network", {
project: "my-project-name",
name: "my-network",
autoCreateSubnetworks: false,
});
const vpcSubnetwork = new gcp.compute.Subnetwork("vpc_subnetwork", {
project: network.project,
name: "my-subnetwork",
ipCidrRange: "10.2.0.0/16",
region: "us-central1",
network: network.id,
privateIpGoogleAccess: true,
});
const _default = new gcp.compute.GlobalAddress("default", {
project: network.project,
name: "global-psconnect-ip",
addressType: "INTERNAL",
purpose: "PRIVATE_SERVICE_CONNECT",
network: network.id,
address: "100.100.100.106",
});
const defaultGlobalForwardingRule = new gcp.compute.GlobalForwardingRule("default", {
project: network.project,
name: "globalrule",
target: "all-apis",
network: network.id,
ipAddress: _default.id,
loadBalancingScheme: "",
serviceDirectoryRegistrations: {
namespace: "sd-namespace",
serviceDirectoryRegion: "europe-west3",
},
});
import pulumi
import pulumi_gcp as gcp
network = gcp.compute.Network("network",
project="my-project-name",
name="my-network",
auto_create_subnetworks=False)
vpc_subnetwork = gcp.compute.Subnetwork("vpc_subnetwork",
project=network.project,
name="my-subnetwork",
ip_cidr_range="10.2.0.0/16",
region="us-central1",
network=network.id,
private_ip_google_access=True)
default = gcp.compute.GlobalAddress("default",
project=network.project,
name="global-psconnect-ip",
address_type="INTERNAL",
purpose="PRIVATE_SERVICE_CONNECT",
network=network.id,
address="100.100.100.106")
default_global_forwarding_rule = gcp.compute.GlobalForwardingRule("default",
project=network.project,
name="globalrule",
target="all-apis",
network=network.id,
ip_address=default.id,
load_balancing_scheme="",
service_directory_registrations={
"namespace": "sd-namespace",
"service_directory_region": "europe-west3",
})
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{
Project: pulumi.String("my-project-name"),
Name: pulumi.String("my-network"),
AutoCreateSubnetworks: pulumi.Bool(false),
})
if err != nil {
return err
}
_, err = compute.NewSubnetwork(ctx, "vpc_subnetwork", &compute.SubnetworkArgs{
Project: network.Project,
Name: pulumi.String("my-subnetwork"),
IpCidrRange: pulumi.String("10.2.0.0/16"),
Region: pulumi.String("us-central1"),
Network: network.ID(),
PrivateIpGoogleAccess: pulumi.Bool(true),
})
if err != nil {
return err
}
_default, err := compute.NewGlobalAddress(ctx, "default", &compute.GlobalAddressArgs{
Project: network.Project,
Name: pulumi.String("global-psconnect-ip"),
AddressType: pulumi.String("INTERNAL"),
Purpose: pulumi.String("PRIVATE_SERVICE_CONNECT"),
Network: network.ID(),
Address: pulumi.String("100.100.100.106"),
})
if err != nil {
return err
}
_, err = compute.NewGlobalForwardingRule(ctx, "default", &compute.GlobalForwardingRuleArgs{
Project: network.Project,
Name: pulumi.String("globalrule"),
Target: pulumi.String("all-apis"),
Network: network.ID(),
IpAddress: _default.ID(),
LoadBalancingScheme: pulumi.String(""),
ServiceDirectoryRegistrations: &compute.GlobalForwardingRuleServiceDirectoryRegistrationsArgs{
Namespace: pulumi.String("sd-namespace"),
ServiceDirectoryRegion: pulumi.String("europe-west3"),
},
})
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()
{
Project = "my-project-name",
Name = "my-network",
AutoCreateSubnetworks = false,
});
var vpcSubnetwork = new Gcp.Compute.Subnetwork("vpc_subnetwork", new()
{
Project = network.Project,
Name = "my-subnetwork",
IpCidrRange = "10.2.0.0/16",
Region = "us-central1",
Network = network.Id,
PrivateIpGoogleAccess = true,
});
var @default = new Gcp.Compute.GlobalAddress("default", new()
{
Project = network.Project,
Name = "global-psconnect-ip",
AddressType = "INTERNAL",
Purpose = "PRIVATE_SERVICE_CONNECT",
Network = network.Id,
Address = "100.100.100.106",
});
var defaultGlobalForwardingRule = new Gcp.Compute.GlobalForwardingRule("default", new()
{
Project = network.Project,
Name = "globalrule",
Target = "all-apis",
Network = network.Id,
IpAddress = @default.Id,
LoadBalancingScheme = "",
ServiceDirectoryRegistrations = new Gcp.Compute.Inputs.GlobalForwardingRuleServiceDirectoryRegistrationsArgs
{
Namespace = "sd-namespace",
ServiceDirectoryRegion = "europe-west3",
},
});
});
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.GlobalAddress;
import com.pulumi.gcp.compute.GlobalAddressArgs;
import com.pulumi.gcp.compute.GlobalForwardingRule;
import com.pulumi.gcp.compute.GlobalForwardingRuleArgs;
import com.pulumi.gcp.compute.inputs.GlobalForwardingRuleServiceDirectoryRegistrationsArgs;
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()
.project("my-project-name")
.name("my-network")
.autoCreateSubnetworks(false)
.build());
var vpcSubnetwork = new Subnetwork("vpcSubnetwork", SubnetworkArgs.builder()
.project(network.project())
.name("my-subnetwork")
.ipCidrRange("10.2.0.0/16")
.region("us-central1")
.network(network.id())
.privateIpGoogleAccess(true)
.build());
var default_ = new GlobalAddress("default", GlobalAddressArgs.builder()
.project(network.project())
.name("global-psconnect-ip")
.addressType("INTERNAL")
.purpose("PRIVATE_SERVICE_CONNECT")
.network(network.id())
.address("100.100.100.106")
.build());
var defaultGlobalForwardingRule = new GlobalForwardingRule("defaultGlobalForwardingRule", GlobalForwardingRuleArgs.builder()
.project(network.project())
.name("globalrule")
.target("all-apis")
.network(network.id())
.ipAddress(default_.id())
.loadBalancingScheme("")
.serviceDirectoryRegistrations(GlobalForwardingRuleServiceDirectoryRegistrationsArgs.builder()
.namespace("sd-namespace")
.serviceDirectoryRegion("europe-west3")
.build())
.build());
}
}
resources:
network:
type: gcp:compute:Network
properties:
project: my-project-name
name: my-network
autoCreateSubnetworks: false
vpcSubnetwork:
type: gcp:compute:Subnetwork
name: vpc_subnetwork
properties:
project: ${network.project}
name: my-subnetwork
ipCidrRange: 10.2.0.0/16
region: us-central1
network: ${network.id}
privateIpGoogleAccess: true
default:
type: gcp:compute:GlobalAddress
properties:
project: ${network.project}
name: global-psconnect-ip
addressType: INTERNAL
purpose: PRIVATE_SERVICE_CONNECT
network: ${network.id}
address: 100.100.100.106
defaultGlobalForwardingRule:
type: gcp:compute:GlobalForwardingRule
name: default
properties:
project: ${network.project}
name: globalrule
target: all-apis
network: ${network.id}
ipAddress: ${default.id}
loadBalancingScheme: ""
serviceDirectoryRegistrations:
namespace: sd-namespace
serviceDirectoryRegion: europe-west3
The target property accepts special values for Private Service Connect: “all-apis” routes to all supported Google APIs, while “vpc-sc” limits access to APIs that support VPC Service Controls. The loadBalancingScheme is set to an empty string for PSC to Google APIs. The serviceDirectoryRegistrations property registers the endpoint in Service Directory for DNS resolution within your VPC.
Beyond these examples
These snippets focus on specific forwarding rule features: HTTP load balancing with target proxies, internal self-managed and external managed schemes, and Private Service Connect to Google APIs. They’re intentionally minimal rather than full load balancing deployments.
The examples reference pre-existing infrastructure such as VPC networks, subnets, and GlobalAddress resources, as well as backend services, health checks, instance groups, URL maps, and target proxies. They focus on configuring the forwarding rule rather than provisioning the complete load balancing stack.
To keep things focused, common forwarding rule patterns are omitted, including:
- Source IP range filtering (sourceIpRanges)
- IPv6 configuration (ipVersion)
- Backend bucket migration (externalManagedBackendBucketMigrationState)
- DNS zone automation control (noAutomateDnsZone)
These omissions are intentional: the goal is to illustrate how each forwarding rule feature is wired, not provide drop-in load balancing modules. See the GlobalForwardingRule resource reference for all available configuration options.
Let's configure GCP Global HTTP Load Balancing Rules
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Configuration & Setup
ipAddress in two cases: when target is targetGrpcProxy with validateForProxyless set to true (use 0.0.0.0), or when target is a Private Service Connect Google APIs bundle. Otherwise, ipAddress is optional and Google Cloud assigns an ephemeral IP if omitted.[a-z][-a-z0-9]*[a-z0-9]. Private Service Connect forwarding rules to Google APIs have stricter requirements: 1-20 characters, lowercase letters and numbers only, must start with a letter.vpc-sc for VPC Service Controls APIs or all-apis for all supported APIs), or service attachments for PSC to managed services.Load Balancing Schemes
EXTERNAL is the default classic load balancing scheme. EXTERNAL_MANAGED is the newer Application Load Balancer. You can migrate between them using externalManagedBackendBucketMigrationState, but the migration requires specific state transitions.INTERNAL_SELF_MANAGED when you need xDS-based routing with metadata filters. This scheme enables metadataFilters for restricting routing configuration to specific xDS-compliant clients based on node metadata.loadBalancingScheme to an empty string when connecting to Google APIs via Private Service Connect. Also set target to all-apis or vpc-sc and specify an ipAddress.Immutability & Updates
target, labels, and migration-related fields (externalManagedBackendBucketMigrationState, externalManagedBackendBucketMigrationTestingPercentage). All other properties including ipAddress, name, network, portRange, and metadataFilters are immutable and require resource recreation to change.externalManagedBackendBucketMigrationState to PREPARE, then TEST_ALL_TRAFFIC, then change loadBalancingScheme to EXTERNAL_MANAGED. Optionally, use TEST_BY_PERCENTAGE with externalManagedBackendBucketMigrationTestingPercentage to gradually migrate traffic. Rollback requires reversing these states.Private Service Connect
target to all-apis or vpc-sc, specify an ipAddress (using a global address with PRIVATE_SERVICE_CONNECT purpose), provide a network, and set loadBalancingScheme to an empty string. Optionally configure serviceDirectoryRegistrations for service discovery.noAutomateDnsZone controls whether Private Service Connect forwarding rules automatically generate a DNS zone. This field only applies to PSC forwarding rules; non-PSC forwarding rules ignore it.Advanced Features
loadBalancingScheme to INTERNAL_SELF_MANAGED and configure metadataFilters with filterMatchCriteria (either MATCH_ANY or MATCH_ALL) and filterLabels. Metadata filters only work with INTERNAL_SELF_MANAGED and are ignored for other schemes.labels field is non-authoritative and only manages labels present in your configuration. To see all labels on the resource (including those set by other clients or services), use the effectiveLabels output property instead.portRange requires ipProtocol to be TCP, UDP, or SCTP. It only applies to specific products (external/internal Network Load Balancers, Application Load Balancers, protocol forwarding, Classic VPN). Some products have additional port restrictions; see the port specifications documentation for details.Using a different cloud?
Explore networking guides for other cloud providers: