Configure GCP Network Services Mesh

The gcp:networkservices/mesh:Mesh resource, part of the Pulumi GCP provider, defines a logical configuration grouping for workload-to-workload communication within a service mesh. This guide focuses on one capability: creating meshes with and without sidecar proxy interception.

Meshes serve as logical boundaries that routes reference to control request routing. The examples are intentionally small. Combine them with route resources and workload configuration to build a complete service mesh.

Create a mesh with traffic interception

Service mesh deployments with sidecar proxies configure an interception port to redirect traffic through the proxy layer.

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

const _default = new gcp.networkservices.Mesh("default", {
    name: "my-mesh",
    labels: {
        foo: "bar",
    },
    description: "my description",
    interceptionPort: 443,
});
import pulumi
import pulumi_gcp as gcp

default = gcp.networkservices.Mesh("default",
    name="my-mesh",
    labels={
        "foo": "bar",
    },
    description="my description",
    interception_port=443)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networkservices"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networkservices.NewMesh(ctx, "default", &networkservices.MeshArgs{
			Name: pulumi.String("my-mesh"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Description:      pulumi.String("my description"),
			InterceptionPort: pulumi.Int(443),
		})
		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 @default = new Gcp.NetworkServices.Mesh("default", new()
    {
        Name = "my-mesh",
        Labels = 
        {
            { "foo", "bar" },
        },
        Description = "my description",
        InterceptionPort = 443,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networkservices.Mesh;
import com.pulumi.gcp.networkservices.MeshArgs;
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 default_ = new Mesh("default", MeshArgs.builder()
            .name("my-mesh")
            .labels(Map.of("foo", "bar"))
            .description("my description")
            .interceptionPort(443)
            .build());

    }
}
resources:
  default:
    type: gcp:networkservices:Mesh
    properties:
      name: my-mesh
      labels:
        foo: bar
      description: my description
      interceptionPort: 443

The interceptionPort property tells sidecar proxies to listen on the specified localhost port (here, 443). All traffic gets redirected to this port regardless of its actual destination, allowing the proxy to enforce routing policies. The name and labels properties provide identity and organization.

Create a mesh without traffic interception

When traffic routing happens through other mechanisms, you can omit the interception port.

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

const _default = new gcp.networkservices.Mesh("default", {
    name: "my-mesh-noport",
    labels: {
        foo: "bar",
    },
    description: "my description",
});
import pulumi
import pulumi_gcp as gcp

default = gcp.networkservices.Mesh("default",
    name="my-mesh-noport",
    labels={
        "foo": "bar",
    },
    description="my description")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networkservices"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networkservices.NewMesh(ctx, "default", &networkservices.MeshArgs{
			Name: pulumi.String("my-mesh-noport"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Description: pulumi.String("my description"),
		})
		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 @default = new Gcp.NetworkServices.Mesh("default", new()
    {
        Name = "my-mesh-noport",
        Labels = 
        {
            { "foo", "bar" },
        },
        Description = "my description",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networkservices.Mesh;
import com.pulumi.gcp.networkservices.MeshArgs;
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 default_ = new Mesh("default", MeshArgs.builder()
            .name("my-mesh-noport")
            .labels(Map.of("foo", "bar"))
            .description("my description")
            .build());

    }
}
resources:
  default:
    type: gcp:networkservices:Mesh
    properties:
      name: my-mesh-noport
      labels:
        foo: bar
      description: my description

Without an interceptionPort, the mesh defines a logical boundary but doesn’t configure sidecar proxy behavior. If you later add sidecar proxies, they’ll use the default port 15001. The description and labels properties provide metadata for organization and documentation.

Beyond these examples

These snippets focus on specific mesh-level features: mesh naming and metadata, and sidecar proxy interception. They’re intentionally minimal rather than full service mesh deployments.

The examples assume pre-existing infrastructure such as a GCP project with Network Services API enabled. They focus on configuring the mesh rather than provisioning routes or workloads.

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

  • Route configuration that references the mesh
  • Workload registration and service discovery
  • Multi-region mesh deployment (only ‘global’ location supported)

These omissions are intentional: the goal is to illustrate how the mesh resource is wired, not provide drop-in service mesh modules. See the Network Services Mesh resource reference for all available configuration options.

Let's configure GCP Network Services Mesh

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Labels & Metadata
Why am I seeing label drift on my mesh resource?
The labels field is non-authoritative and only manages labels present in your configuration. Use effectiveLabels to see all labels on the resource, including those set by other clients or services.
Configuration & Defaults
What are the interceptionPort options for a mesh?
You can set interceptionPort to any valid TCP port (1-65535) for sidecar proxy deployments. If unset, it defaults to port 15001.
Can I create a mesh without specifying an interceptionPort?
Yes, interceptionPort is optional. If omitted, the mesh uses the default port 15001 for sidecar proxy deployments.
What location values are supported for a mesh?
Only ‘global’ is currently allowed for the location property. If omitted, it defaults to ‘global’.
Immutability & Lifecycle
What properties are immutable after creating a mesh?
Both project and location are immutable and cannot be changed after the mesh is created.
Import & Migration
How do I import an existing mesh into Pulumi?
Use one of three formats: projects/{{project}}/locations/{{location}}/meshes/{{name}}, {{project}}/{{location}}/{{name}}, or {{location}}/{{name}}.
What's the maximum length for a mesh description?
The description field supports up to 1024 characters.

Using a different cloud?

Explore networking guides for other cloud providers: