Create and Manage GCP DNS Managed Zones

The gcp:dns/managedZone:ManagedZone resource, part of the Pulumi GCP provider, defines a Cloud DNS managed zone: its domain name, visibility scope, and integration with VPC networks or service registries. This guide focuses on four capabilities: public and private zone visibility, DNS forwarding to on-premises name servers, VPC network and GKE cluster integration, and Service Directory-backed zones.

Managed zones reference VPC networks, GKE clusters, or Service Directory namespaces that must exist separately. The examples are intentionally small. Combine them with your own network infrastructure and DNS record sets.

Create a public DNS zone with labels

Most DNS deployments start with a public zone that hosts records for a domain, exposing DNS records to the Internet for external resolution.

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

const example_zone = new gcp.dns.ManagedZone("example-zone", {
    name: "example-zone",
    dnsName: "my-domain.com.",
    description: "Example DNS zone",
    labels: {
        foo: "bar",
    },
});
import pulumi
import pulumi_gcp as gcp

example_zone = gcp.dns.ManagedZone("example-zone",
    name="example-zone",
    dns_name="my-domain.com.",
    description="Example DNS zone",
    labels={
        "foo": "bar",
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := dns.NewManagedZone(ctx, "example-zone", &dns.ManagedZoneArgs{
			Name:        pulumi.String("example-zone"),
			DnsName:     pulumi.String("my-domain.com."),
			Description: pulumi.String("Example DNS zone"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
		})
		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 example_zone = new Gcp.Dns.ManagedZone("example-zone", new()
    {
        Name = "example-zone",
        DnsName = "my-domain.com.",
        Description = "Example DNS zone",
        Labels = 
        {
            { "foo", "bar" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.dns.ManagedZone;
import com.pulumi.gcp.dns.ManagedZoneArgs;
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 example_zone = new ManagedZone("example-zone", ManagedZoneArgs.builder()
            .name("example-zone")
            .dnsName("my-domain.com.")
            .description("Example DNS zone")
            .labels(Map.of("foo", "bar"))
            .build());

    }
}
resources:
  example-zone:
    type: gcp:dns:ManagedZone
    properties:
      name: example-zone
      dnsName: my-domain.com.
      description: Example DNS zone
      labels:
        foo: bar

The dnsName property sets the domain (must end with a dot). The visibility defaults to “public”, making records accessible from the Internet. The labels property adds metadata for organization and cost tracking.

Restrict zone visibility to specific VPC networks

Internal services often need DNS resolution isolated from the public Internet. Private zones make records visible only to specified VPC networks.

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

const network_1 = new gcp.compute.Network("network-1", {
    name: "network-1",
    autoCreateSubnetworks: false,
});
const network_2 = new gcp.compute.Network("network-2", {
    name: "network-2",
    autoCreateSubnetworks: false,
});
const private_zone = new gcp.dns.ManagedZone("private-zone", {
    name: "private-zone",
    dnsName: "private.example.com.",
    description: "Example private DNS zone",
    labels: {
        foo: "bar",
    },
    visibility: "private",
    privateVisibilityConfig: {
        networks: [
            {
                networkUrl: network_1.id,
            },
            {
                networkUrl: network_2.id,
            },
        ],
    },
});
import pulumi
import pulumi_gcp as gcp

network_1 = gcp.compute.Network("network-1",
    name="network-1",
    auto_create_subnetworks=False)
network_2 = gcp.compute.Network("network-2",
    name="network-2",
    auto_create_subnetworks=False)
private_zone = gcp.dns.ManagedZone("private-zone",
    name="private-zone",
    dns_name="private.example.com.",
    description="Example private DNS zone",
    labels={
        "foo": "bar",
    },
    visibility="private",
    private_visibility_config={
        "networks": [
            {
                "network_url": network_1.id,
            },
            {
                "network_url": network_2.id,
            },
        ],
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		network_1, err := compute.NewNetwork(ctx, "network-1", &compute.NetworkArgs{
			Name:                  pulumi.String("network-1"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		network_2, err := compute.NewNetwork(ctx, "network-2", &compute.NetworkArgs{
			Name:                  pulumi.String("network-2"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = dns.NewManagedZone(ctx, "private-zone", &dns.ManagedZoneArgs{
			Name:        pulumi.String("private-zone"),
			DnsName:     pulumi.String("private.example.com."),
			Description: pulumi.String("Example private DNS zone"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Visibility: pulumi.String("private"),
			PrivateVisibilityConfig: &dns.ManagedZonePrivateVisibilityConfigArgs{
				Networks: dns.ManagedZonePrivateVisibilityConfigNetworkArray{
					&dns.ManagedZonePrivateVisibilityConfigNetworkArgs{
						NetworkUrl: network_1.ID(),
					},
					&dns.ManagedZonePrivateVisibilityConfigNetworkArgs{
						NetworkUrl: network_2.ID(),
					},
				},
			},
		})
		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_1 = new Gcp.Compute.Network("network-1", new()
    {
        Name = "network-1",
        AutoCreateSubnetworks = false,
    });

    var network_2 = new Gcp.Compute.Network("network-2", new()
    {
        Name = "network-2",
        AutoCreateSubnetworks = false,
    });

    var private_zone = new Gcp.Dns.ManagedZone("private-zone", new()
    {
        Name = "private-zone",
        DnsName = "private.example.com.",
        Description = "Example private DNS zone",
        Labels = 
        {
            { "foo", "bar" },
        },
        Visibility = "private",
        PrivateVisibilityConfig = new Gcp.Dns.Inputs.ManagedZonePrivateVisibilityConfigArgs
        {
            Networks = new[]
            {
                new Gcp.Dns.Inputs.ManagedZonePrivateVisibilityConfigNetworkArgs
                {
                    NetworkUrl = network_1.Id,
                },
                new Gcp.Dns.Inputs.ManagedZonePrivateVisibilityConfigNetworkArgs
                {
                    NetworkUrl = network_2.Id,
                },
            },
        },
    });

});
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.dns.ManagedZone;
import com.pulumi.gcp.dns.ManagedZoneArgs;
import com.pulumi.gcp.dns.inputs.ManagedZonePrivateVisibilityConfigArgs;
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_1 = new Network("network-1", NetworkArgs.builder()
            .name("network-1")
            .autoCreateSubnetworks(false)
            .build());

        var network_2 = new Network("network-2", NetworkArgs.builder()
            .name("network-2")
            .autoCreateSubnetworks(false)
            .build());

        var private_zone = new ManagedZone("private-zone", ManagedZoneArgs.builder()
            .name("private-zone")
            .dnsName("private.example.com.")
            .description("Example private DNS zone")
            .labels(Map.of("foo", "bar"))
            .visibility("private")
            .privateVisibilityConfig(ManagedZonePrivateVisibilityConfigArgs.builder()
                .networks(                
                    ManagedZonePrivateVisibilityConfigNetworkArgs.builder()
                        .networkUrl(network_1.id())
                        .build(),
                    ManagedZonePrivateVisibilityConfigNetworkArgs.builder()
                        .networkUrl(network_2.id())
                        .build())
                .build())
            .build());

    }
}
resources:
  private-zone:
    type: gcp:dns:ManagedZone
    properties:
      name: private-zone
      dnsName: private.example.com.
      description: Example private DNS zone
      labels:
        foo: bar
      visibility: private
      privateVisibilityConfig:
        networks:
          - networkUrl: ${["network-1"].id}
          - networkUrl: ${["network-2"].id}
  network-1:
    type: gcp:compute:Network
    properties:
      name: network-1
      autoCreateSubnetworks: false
  network-2:
    type: gcp:compute:Network
    properties:
      name: network-2
      autoCreateSubnetworks: false

Setting visibility to “private” restricts access to resources in the specified networks. The privateVisibilityConfig property lists VPC networks by their resource URLs. Resources in these networks can resolve the zone’s records; external clients cannot.

Forward DNS queries to on-premises name servers

Hybrid cloud architectures often need to resolve on-premises DNS names from GCP. Forwarding sends queries for the zone’s domain to specified name servers in your data center.

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

const network_1 = new gcp.compute.Network("network-1", {
    name: "network-1",
    autoCreateSubnetworks: false,
});
const network_2 = new gcp.compute.Network("network-2", {
    name: "network-2",
    autoCreateSubnetworks: false,
});
const private_zone = new gcp.dns.ManagedZone("private-zone", {
    name: "private-zone",
    dnsName: "private.example.com.",
    description: "Example private DNS zone",
    labels: {
        foo: "bar",
    },
    visibility: "private",
    privateVisibilityConfig: {
        networks: [
            {
                networkUrl: network_1.id,
            },
            {
                networkUrl: network_2.id,
            },
        ],
    },
    forwardingConfig: {
        targetNameServers: [
            {
                ipv4Address: "172.16.1.10",
            },
            {
                ipv4Address: "172.16.1.20",
            },
        ],
    },
});
import pulumi
import pulumi_gcp as gcp

network_1 = gcp.compute.Network("network-1",
    name="network-1",
    auto_create_subnetworks=False)
network_2 = gcp.compute.Network("network-2",
    name="network-2",
    auto_create_subnetworks=False)
private_zone = gcp.dns.ManagedZone("private-zone",
    name="private-zone",
    dns_name="private.example.com.",
    description="Example private DNS zone",
    labels={
        "foo": "bar",
    },
    visibility="private",
    private_visibility_config={
        "networks": [
            {
                "network_url": network_1.id,
            },
            {
                "network_url": network_2.id,
            },
        ],
    },
    forwarding_config={
        "target_name_servers": [
            {
                "ipv4_address": "172.16.1.10",
            },
            {
                "ipv4_address": "172.16.1.20",
            },
        ],
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		network_1, err := compute.NewNetwork(ctx, "network-1", &compute.NetworkArgs{
			Name:                  pulumi.String("network-1"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		network_2, err := compute.NewNetwork(ctx, "network-2", &compute.NetworkArgs{
			Name:                  pulumi.String("network-2"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = dns.NewManagedZone(ctx, "private-zone", &dns.ManagedZoneArgs{
			Name:        pulumi.String("private-zone"),
			DnsName:     pulumi.String("private.example.com."),
			Description: pulumi.String("Example private DNS zone"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Visibility: pulumi.String("private"),
			PrivateVisibilityConfig: &dns.ManagedZonePrivateVisibilityConfigArgs{
				Networks: dns.ManagedZonePrivateVisibilityConfigNetworkArray{
					&dns.ManagedZonePrivateVisibilityConfigNetworkArgs{
						NetworkUrl: network_1.ID(),
					},
					&dns.ManagedZonePrivateVisibilityConfigNetworkArgs{
						NetworkUrl: network_2.ID(),
					},
				},
			},
			ForwardingConfig: &dns.ManagedZoneForwardingConfigArgs{
				TargetNameServers: dns.ManagedZoneForwardingConfigTargetNameServerArray{
					&dns.ManagedZoneForwardingConfigTargetNameServerArgs{
						Ipv4Address: pulumi.String("172.16.1.10"),
					},
					&dns.ManagedZoneForwardingConfigTargetNameServerArgs{
						Ipv4Address: pulumi.String("172.16.1.20"),
					},
				},
			},
		})
		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_1 = new Gcp.Compute.Network("network-1", new()
    {
        Name = "network-1",
        AutoCreateSubnetworks = false,
    });

    var network_2 = new Gcp.Compute.Network("network-2", new()
    {
        Name = "network-2",
        AutoCreateSubnetworks = false,
    });

    var private_zone = new Gcp.Dns.ManagedZone("private-zone", new()
    {
        Name = "private-zone",
        DnsName = "private.example.com.",
        Description = "Example private DNS zone",
        Labels = 
        {
            { "foo", "bar" },
        },
        Visibility = "private",
        PrivateVisibilityConfig = new Gcp.Dns.Inputs.ManagedZonePrivateVisibilityConfigArgs
        {
            Networks = new[]
            {
                new Gcp.Dns.Inputs.ManagedZonePrivateVisibilityConfigNetworkArgs
                {
                    NetworkUrl = network_1.Id,
                },
                new Gcp.Dns.Inputs.ManagedZonePrivateVisibilityConfigNetworkArgs
                {
                    NetworkUrl = network_2.Id,
                },
            },
        },
        ForwardingConfig = new Gcp.Dns.Inputs.ManagedZoneForwardingConfigArgs
        {
            TargetNameServers = new[]
            {
                new Gcp.Dns.Inputs.ManagedZoneForwardingConfigTargetNameServerArgs
                {
                    Ipv4Address = "172.16.1.10",
                },
                new Gcp.Dns.Inputs.ManagedZoneForwardingConfigTargetNameServerArgs
                {
                    Ipv4Address = "172.16.1.20",
                },
            },
        },
    });

});
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.dns.ManagedZone;
import com.pulumi.gcp.dns.ManagedZoneArgs;
import com.pulumi.gcp.dns.inputs.ManagedZonePrivateVisibilityConfigArgs;
import com.pulumi.gcp.dns.inputs.ManagedZoneForwardingConfigArgs;
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_1 = new Network("network-1", NetworkArgs.builder()
            .name("network-1")
            .autoCreateSubnetworks(false)
            .build());

        var network_2 = new Network("network-2", NetworkArgs.builder()
            .name("network-2")
            .autoCreateSubnetworks(false)
            .build());

        var private_zone = new ManagedZone("private-zone", ManagedZoneArgs.builder()
            .name("private-zone")
            .dnsName("private.example.com.")
            .description("Example private DNS zone")
            .labels(Map.of("foo", "bar"))
            .visibility("private")
            .privateVisibilityConfig(ManagedZonePrivateVisibilityConfigArgs.builder()
                .networks(                
                    ManagedZonePrivateVisibilityConfigNetworkArgs.builder()
                        .networkUrl(network_1.id())
                        .build(),
                    ManagedZonePrivateVisibilityConfigNetworkArgs.builder()
                        .networkUrl(network_2.id())
                        .build())
                .build())
            .forwardingConfig(ManagedZoneForwardingConfigArgs.builder()
                .targetNameServers(                
                    ManagedZoneForwardingConfigTargetNameServerArgs.builder()
                        .ipv4Address("172.16.1.10")
                        .build(),
                    ManagedZoneForwardingConfigTargetNameServerArgs.builder()
                        .ipv4Address("172.16.1.20")
                        .build())
                .build())
            .build());

    }
}
resources:
  private-zone:
    type: gcp:dns:ManagedZone
    properties:
      name: private-zone
      dnsName: private.example.com.
      description: Example private DNS zone
      labels:
        foo: bar
      visibility: private
      privateVisibilityConfig:
        networks:
          - networkUrl: ${["network-1"].id}
          - networkUrl: ${["network-2"].id}
      forwardingConfig:
        targetNameServers:
          - ipv4Address: 172.16.1.10
          - ipv4Address: 172.16.1.20
  network-1:
    type: gcp:compute:Network
    properties:
      name: network-1
      autoCreateSubnetworks: false
  network-2:
    type: gcp:compute:Network
    properties:
      name: network-2
      autoCreateSubnetworks: false

The forwardingConfig property defines target name servers by IP address. When a VPC resource queries a name in this zone’s domain, Cloud DNS forwards the query to your on-premises servers rather than hosting records directly. This extends private zone configuration with forwarding behavior.

Make zone visible to GKE cluster workloads

GKE clusters can access private DNS zones through cluster-specific visibility, allowing pods to resolve internal service names without exposing the zone to the entire VPC.

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

const network_1 = new gcp.compute.Network("network-1", {
    name: "network-1",
    autoCreateSubnetworks: false,
});
const subnetwork_1 = new gcp.compute.Subnetwork("subnetwork-1", {
    name: network_1.name,
    network: network_1.name,
    ipCidrRange: "10.0.36.0/24",
    region: "us-central1",
    privateIpGoogleAccess: true,
    secondaryIpRanges: [
        {
            rangeName: "pod",
            ipCidrRange: "10.0.0.0/19",
        },
        {
            rangeName: "svc",
            ipCidrRange: "10.0.32.0/22",
        },
    ],
});
const cluster_1 = new gcp.container.Cluster("cluster-1", {
    name: "cluster-1",
    location: "us-central1-c",
    initialNodeCount: 1,
    networkingMode: "VPC_NATIVE",
    defaultSnatStatus: {
        disabled: true,
    },
    network: network_1.name,
    subnetwork: subnetwork_1.name,
    privateClusterConfig: {
        enablePrivateEndpoint: true,
        enablePrivateNodes: true,
        masterIpv4CidrBlock: "10.42.0.0/28",
        masterGlobalAccessConfig: {
            enabled: true,
        },
    },
    masterAuthorizedNetworksConfig: {},
    ipAllocationPolicy: {
        clusterSecondaryRangeName: subnetwork_1.secondaryIpRanges.apply(secondaryIpRanges => secondaryIpRanges[0].rangeName),
        servicesSecondaryRangeName: subnetwork_1.secondaryIpRanges.apply(secondaryIpRanges => secondaryIpRanges[1].rangeName),
    },
    deletionProtection: true,
});
const private_zone_gke = new gcp.dns.ManagedZone("private-zone-gke", {
    name: "private-zone",
    dnsName: "private.example.com.",
    description: "Example private DNS zone",
    labels: {
        foo: "bar",
    },
    visibility: "private",
    privateVisibilityConfig: {
        gkeClusters: [{
            gkeClusterName: cluster_1.id,
        }],
    },
});
import pulumi
import pulumi_gcp as gcp

network_1 = gcp.compute.Network("network-1",
    name="network-1",
    auto_create_subnetworks=False)
subnetwork_1 = gcp.compute.Subnetwork("subnetwork-1",
    name=network_1.name,
    network=network_1.name,
    ip_cidr_range="10.0.36.0/24",
    region="us-central1",
    private_ip_google_access=True,
    secondary_ip_ranges=[
        {
            "range_name": "pod",
            "ip_cidr_range": "10.0.0.0/19",
        },
        {
            "range_name": "svc",
            "ip_cidr_range": "10.0.32.0/22",
        },
    ])
cluster_1 = gcp.container.Cluster("cluster-1",
    name="cluster-1",
    location="us-central1-c",
    initial_node_count=1,
    networking_mode="VPC_NATIVE",
    default_snat_status={
        "disabled": True,
    },
    network=network_1.name,
    subnetwork=subnetwork_1.name,
    private_cluster_config={
        "enable_private_endpoint": True,
        "enable_private_nodes": True,
        "master_ipv4_cidr_block": "10.42.0.0/28",
        "master_global_access_config": {
            "enabled": True,
        },
    },
    master_authorized_networks_config={},
    ip_allocation_policy={
        "cluster_secondary_range_name": subnetwork_1.secondary_ip_ranges[0].range_name,
        "services_secondary_range_name": subnetwork_1.secondary_ip_ranges[1].range_name,
    },
    deletion_protection=True)
private_zone_gke = gcp.dns.ManagedZone("private-zone-gke",
    name="private-zone",
    dns_name="private.example.com.",
    description="Example private DNS zone",
    labels={
        "foo": "bar",
    },
    visibility="private",
    private_visibility_config={
        "gke_clusters": [{
            "gke_cluster_name": cluster_1.id,
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/container"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/dns"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		network_1, err := compute.NewNetwork(ctx, "network-1", &compute.NetworkArgs{
			Name:                  pulumi.String("network-1"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		subnetwork_1, err := compute.NewSubnetwork(ctx, "subnetwork-1", &compute.SubnetworkArgs{
			Name:                  network_1.Name,
			Network:               network_1.Name,
			IpCidrRange:           pulumi.String("10.0.36.0/24"),
			Region:                pulumi.String("us-central1"),
			PrivateIpGoogleAccess: pulumi.Bool(true),
			SecondaryIpRanges: compute.SubnetworkSecondaryIpRangeArray{
				&compute.SubnetworkSecondaryIpRangeArgs{
					RangeName:   pulumi.String("pod"),
					IpCidrRange: pulumi.String("10.0.0.0/19"),
				},
				&compute.SubnetworkSecondaryIpRangeArgs{
					RangeName:   pulumi.String("svc"),
					IpCidrRange: pulumi.String("10.0.32.0/22"),
				},
			},
		})
		if err != nil {
			return err
		}
		cluster_1, err := container.NewCluster(ctx, "cluster-1", &container.ClusterArgs{
			Name:             pulumi.String("cluster-1"),
			Location:         pulumi.String("us-central1-c"),
			InitialNodeCount: pulumi.Int(1),
			NetworkingMode:   pulumi.String("VPC_NATIVE"),
			DefaultSnatStatus: &container.ClusterDefaultSnatStatusArgs{
				Disabled: pulumi.Bool(true),
			},
			Network:    network_1.Name,
			Subnetwork: subnetwork_1.Name,
			PrivateClusterConfig: &container.ClusterPrivateClusterConfigArgs{
				EnablePrivateEndpoint: pulumi.Bool(true),
				EnablePrivateNodes:    pulumi.Bool(true),
				MasterIpv4CidrBlock:   pulumi.String("10.42.0.0/28"),
				MasterGlobalAccessConfig: &container.ClusterPrivateClusterConfigMasterGlobalAccessConfigArgs{
					Enabled: pulumi.Bool(true),
				},
			},
			MasterAuthorizedNetworksConfig: &container.ClusterMasterAuthorizedNetworksConfigArgs{},
			IpAllocationPolicy: &container.ClusterIpAllocationPolicyArgs{
				ClusterSecondaryRangeName: subnetwork_1.SecondaryIpRanges.ApplyT(func(secondaryIpRanges []compute.SubnetworkSecondaryIpRange) (*string, error) {
					return &secondaryIpRanges[0].RangeName, nil
				}).(pulumi.StringPtrOutput),
				ServicesSecondaryRangeName: subnetwork_1.SecondaryIpRanges.ApplyT(func(secondaryIpRanges []compute.SubnetworkSecondaryIpRange) (*string, error) {
					return &secondaryIpRanges[1].RangeName, nil
				}).(pulumi.StringPtrOutput),
			},
			DeletionProtection: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		_, err = dns.NewManagedZone(ctx, "private-zone-gke", &dns.ManagedZoneArgs{
			Name:        pulumi.String("private-zone"),
			DnsName:     pulumi.String("private.example.com."),
			Description: pulumi.String("Example private DNS zone"),
			Labels: pulumi.StringMap{
				"foo": pulumi.String("bar"),
			},
			Visibility: pulumi.String("private"),
			PrivateVisibilityConfig: &dns.ManagedZonePrivateVisibilityConfigArgs{
				GkeClusters: dns.ManagedZonePrivateVisibilityConfigGkeClusterArray{
					&dns.ManagedZonePrivateVisibilityConfigGkeClusterArgs{
						GkeClusterName: cluster_1.ID(),
					},
				},
			},
		})
		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_1 = new Gcp.Compute.Network("network-1", new()
    {
        Name = "network-1",
        AutoCreateSubnetworks = false,
    });

    var subnetwork_1 = new Gcp.Compute.Subnetwork("subnetwork-1", new()
    {
        Name = network_1.Name,
        Network = network_1.Name,
        IpCidrRange = "10.0.36.0/24",
        Region = "us-central1",
        PrivateIpGoogleAccess = true,
        SecondaryIpRanges = new[]
        {
            new Gcp.Compute.Inputs.SubnetworkSecondaryIpRangeArgs
            {
                RangeName = "pod",
                IpCidrRange = "10.0.0.0/19",
            },
            new Gcp.Compute.Inputs.SubnetworkSecondaryIpRangeArgs
            {
                RangeName = "svc",
                IpCidrRange = "10.0.32.0/22",
            },
        },
    });

    var cluster_1 = new Gcp.Container.Cluster("cluster-1", new()
    {
        Name = "cluster-1",
        Location = "us-central1-c",
        InitialNodeCount = 1,
        NetworkingMode = "VPC_NATIVE",
        DefaultSnatStatus = new Gcp.Container.Inputs.ClusterDefaultSnatStatusArgs
        {
            Disabled = true,
        },
        Network = network_1.Name,
        Subnetwork = subnetwork_1.Name,
        PrivateClusterConfig = new Gcp.Container.Inputs.ClusterPrivateClusterConfigArgs
        {
            EnablePrivateEndpoint = true,
            EnablePrivateNodes = true,
            MasterIpv4CidrBlock = "10.42.0.0/28",
            MasterGlobalAccessConfig = new Gcp.Container.Inputs.ClusterPrivateClusterConfigMasterGlobalAccessConfigArgs
            {
                Enabled = true,
            },
        },
        MasterAuthorizedNetworksConfig = null,
        IpAllocationPolicy = new Gcp.Container.Inputs.ClusterIpAllocationPolicyArgs
        {
            ClusterSecondaryRangeName = subnetwork_1.SecondaryIpRanges.Apply(secondaryIpRanges => secondaryIpRanges[0].RangeName),
            ServicesSecondaryRangeName = subnetwork_1.SecondaryIpRanges.Apply(secondaryIpRanges => secondaryIpRanges[1].RangeName),
        },
        DeletionProtection = true,
    });

    var private_zone_gke = new Gcp.Dns.ManagedZone("private-zone-gke", new()
    {
        Name = "private-zone",
        DnsName = "private.example.com.",
        Description = "Example private DNS zone",
        Labels = 
        {
            { "foo", "bar" },
        },
        Visibility = "private",
        PrivateVisibilityConfig = new Gcp.Dns.Inputs.ManagedZonePrivateVisibilityConfigArgs
        {
            GkeClusters = new[]
            {
                new Gcp.Dns.Inputs.ManagedZonePrivateVisibilityConfigGkeClusterArgs
                {
                    GkeClusterName = cluster_1.Id,
                },
            },
        },
    });

});
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.inputs.SubnetworkSecondaryIpRangeArgs;
import com.pulumi.gcp.container.Cluster;
import com.pulumi.gcp.container.ClusterArgs;
import com.pulumi.gcp.container.inputs.ClusterDefaultSnatStatusArgs;
import com.pulumi.gcp.container.inputs.ClusterPrivateClusterConfigArgs;
import com.pulumi.gcp.container.inputs.ClusterPrivateClusterConfigMasterGlobalAccessConfigArgs;
import com.pulumi.gcp.container.inputs.ClusterMasterAuthorizedNetworksConfigArgs;
import com.pulumi.gcp.container.inputs.ClusterIpAllocationPolicyArgs;
import com.pulumi.gcp.dns.ManagedZone;
import com.pulumi.gcp.dns.ManagedZoneArgs;
import com.pulumi.gcp.dns.inputs.ManagedZonePrivateVisibilityConfigArgs;
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_1 = new Network("network-1", NetworkArgs.builder()
            .name("network-1")
            .autoCreateSubnetworks(false)
            .build());

        var subnetwork_1 = new Subnetwork("subnetwork-1", SubnetworkArgs.builder()
            .name(network_1.name())
            .network(network_1.name())
            .ipCidrRange("10.0.36.0/24")
            .region("us-central1")
            .privateIpGoogleAccess(true)
            .secondaryIpRanges(            
                SubnetworkSecondaryIpRangeArgs.builder()
                    .rangeName("pod")
                    .ipCidrRange("10.0.0.0/19")
                    .build(),
                SubnetworkSecondaryIpRangeArgs.builder()
                    .rangeName("svc")
                    .ipCidrRange("10.0.32.0/22")
                    .build())
            .build());

        var cluster_1 = new Cluster("cluster-1", ClusterArgs.builder()
            .name("cluster-1")
            .location("us-central1-c")
            .initialNodeCount(1)
            .networkingMode("VPC_NATIVE")
            .defaultSnatStatus(ClusterDefaultSnatStatusArgs.builder()
                .disabled(true)
                .build())
            .network(network_1.name())
            .subnetwork(subnetwork_1.name())
            .privateClusterConfig(ClusterPrivateClusterConfigArgs.builder()
                .enablePrivateEndpoint(true)
                .enablePrivateNodes(true)
                .masterIpv4CidrBlock("10.42.0.0/28")
                .masterGlobalAccessConfig(ClusterPrivateClusterConfigMasterGlobalAccessConfigArgs.builder()
                    .enabled(true)
                    .build())
                .build())
            .masterAuthorizedNetworksConfig(ClusterMasterAuthorizedNetworksConfigArgs.builder()
                .build())
            .ipAllocationPolicy(ClusterIpAllocationPolicyArgs.builder()
                .clusterSecondaryRangeName(subnetwork_1.secondaryIpRanges().applyValue(_secondaryIpRanges -> _secondaryIpRanges[0].rangeName()))
                .servicesSecondaryRangeName(subnetwork_1.secondaryIpRanges().applyValue(_secondaryIpRanges -> _secondaryIpRanges[1].rangeName()))
                .build())
            .deletionProtection(true)
            .build());

        var private_zone_gke = new ManagedZone("private-zone-gke", ManagedZoneArgs.builder()
            .name("private-zone")
            .dnsName("private.example.com.")
            .description("Example private DNS zone")
            .labels(Map.of("foo", "bar"))
            .visibility("private")
            .privateVisibilityConfig(ManagedZonePrivateVisibilityConfigArgs.builder()
                .gkeClusters(ManagedZonePrivateVisibilityConfigGkeClusterArgs.builder()
                    .gkeClusterName(cluster_1.id())
                    .build())
                .build())
            .build());

    }
}
resources:
  private-zone-gke:
    type: gcp:dns:ManagedZone
    properties:
      name: private-zone
      dnsName: private.example.com.
      description: Example private DNS zone
      labels:
        foo: bar
      visibility: private
      privateVisibilityConfig:
        gkeClusters:
          - gkeClusterName: ${["cluster-1"].id}
  network-1:
    type: gcp:compute:Network
    properties:
      name: network-1
      autoCreateSubnetworks: false
  subnetwork-1:
    type: gcp:compute:Subnetwork
    properties:
      name: ${["network-1"].name}
      network: ${["network-1"].name}
      ipCidrRange: 10.0.36.0/24
      region: us-central1
      privateIpGoogleAccess: true
      secondaryIpRanges:
        - rangeName: pod
          ipCidrRange: 10.0.0.0/19
        - rangeName: svc
          ipCidrRange: 10.0.32.0/22
  cluster-1:
    type: gcp:container:Cluster
    properties:
      name: cluster-1
      location: us-central1-c
      initialNodeCount: 1
      networkingMode: VPC_NATIVE
      defaultSnatStatus:
        disabled: true
      network: ${["network-1"].name}
      subnetwork: ${["subnetwork-1"].name}
      privateClusterConfig:
        enablePrivateEndpoint: true
        enablePrivateNodes: true
        masterIpv4CidrBlock: 10.42.0.0/28
        masterGlobalAccessConfig:
          enabled: true
      masterAuthorizedNetworksConfig: {}
      ipAllocationPolicy:
        clusterSecondaryRangeName: ${["subnetwork-1"].secondaryIpRanges[0].rangeName}
        servicesSecondaryRangeName: ${["subnetwork-1"].secondaryIpRanges[1].rangeName}
      deletionProtection: true

The gkeClusters property in privateVisibilityConfig scopes visibility to specific clusters. Pods in the referenced cluster can resolve the zone’s records. This provides finer-grained access control than network-level visibility.

Peer DNS zones across VPC networks

Organizations with multiple VPC networks sometimes need to share DNS resolution between them. DNS peering allows one network to resolve records from a zone visible in another network.

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

const network_source = new gcp.compute.Network("network-source", {
    name: "network-source",
    autoCreateSubnetworks: false,
});
const network_target = new gcp.compute.Network("network-target", {
    name: "network-target",
    autoCreateSubnetworks: false,
});
const peering_zone = new gcp.dns.ManagedZone("peering-zone", {
    name: "peering-zone",
    dnsName: "peering.example.com.",
    description: "Example private DNS peering zone",
    visibility: "private",
    privateVisibilityConfig: {
        networks: [{
            networkUrl: network_source.id,
        }],
    },
    peeringConfig: {
        targetNetwork: {
            networkUrl: network_target.id,
        },
    },
});
import pulumi
import pulumi_gcp as gcp

network_source = gcp.compute.Network("network-source",
    name="network-source",
    auto_create_subnetworks=False)
network_target = gcp.compute.Network("network-target",
    name="network-target",
    auto_create_subnetworks=False)
peering_zone = gcp.dns.ManagedZone("peering-zone",
    name="peering-zone",
    dns_name="peering.example.com.",
    description="Example private DNS peering zone",
    visibility="private",
    private_visibility_config={
        "networks": [{
            "network_url": network_source.id,
        }],
    },
    peering_config={
        "target_network": {
            "network_url": network_target.id,
        },
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		network_source, err := compute.NewNetwork(ctx, "network-source", &compute.NetworkArgs{
			Name:                  pulumi.String("network-source"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		network_target, err := compute.NewNetwork(ctx, "network-target", &compute.NetworkArgs{
			Name:                  pulumi.String("network-target"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = dns.NewManagedZone(ctx, "peering-zone", &dns.ManagedZoneArgs{
			Name:        pulumi.String("peering-zone"),
			DnsName:     pulumi.String("peering.example.com."),
			Description: pulumi.String("Example private DNS peering zone"),
			Visibility:  pulumi.String("private"),
			PrivateVisibilityConfig: &dns.ManagedZonePrivateVisibilityConfigArgs{
				Networks: dns.ManagedZonePrivateVisibilityConfigNetworkArray{
					&dns.ManagedZonePrivateVisibilityConfigNetworkArgs{
						NetworkUrl: network_source.ID(),
					},
				},
			},
			PeeringConfig: &dns.ManagedZonePeeringConfigArgs{
				TargetNetwork: &dns.ManagedZonePeeringConfigTargetNetworkArgs{
					NetworkUrl: network_target.ID(),
				},
			},
		})
		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_source = new Gcp.Compute.Network("network-source", new()
    {
        Name = "network-source",
        AutoCreateSubnetworks = false,
    });

    var network_target = new Gcp.Compute.Network("network-target", new()
    {
        Name = "network-target",
        AutoCreateSubnetworks = false,
    });

    var peering_zone = new Gcp.Dns.ManagedZone("peering-zone", new()
    {
        Name = "peering-zone",
        DnsName = "peering.example.com.",
        Description = "Example private DNS peering zone",
        Visibility = "private",
        PrivateVisibilityConfig = new Gcp.Dns.Inputs.ManagedZonePrivateVisibilityConfigArgs
        {
            Networks = new[]
            {
                new Gcp.Dns.Inputs.ManagedZonePrivateVisibilityConfigNetworkArgs
                {
                    NetworkUrl = network_source.Id,
                },
            },
        },
        PeeringConfig = new Gcp.Dns.Inputs.ManagedZonePeeringConfigArgs
        {
            TargetNetwork = new Gcp.Dns.Inputs.ManagedZonePeeringConfigTargetNetworkArgs
            {
                NetworkUrl = network_target.Id,
            },
        },
    });

});
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.dns.ManagedZone;
import com.pulumi.gcp.dns.ManagedZoneArgs;
import com.pulumi.gcp.dns.inputs.ManagedZonePrivateVisibilityConfigArgs;
import com.pulumi.gcp.dns.inputs.ManagedZonePeeringConfigArgs;
import com.pulumi.gcp.dns.inputs.ManagedZonePeeringConfigTargetNetworkArgs;
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_source = new Network("network-source", NetworkArgs.builder()
            .name("network-source")
            .autoCreateSubnetworks(false)
            .build());

        var network_target = new Network("network-target", NetworkArgs.builder()
            .name("network-target")
            .autoCreateSubnetworks(false)
            .build());

        var peering_zone = new ManagedZone("peering-zone", ManagedZoneArgs.builder()
            .name("peering-zone")
            .dnsName("peering.example.com.")
            .description("Example private DNS peering zone")
            .visibility("private")
            .privateVisibilityConfig(ManagedZonePrivateVisibilityConfigArgs.builder()
                .networks(ManagedZonePrivateVisibilityConfigNetworkArgs.builder()
                    .networkUrl(network_source.id())
                    .build())
                .build())
            .peeringConfig(ManagedZonePeeringConfigArgs.builder()
                .targetNetwork(ManagedZonePeeringConfigTargetNetworkArgs.builder()
                    .networkUrl(network_target.id())
                    .build())
                .build())
            .build());

    }
}
resources:
  peering-zone:
    type: gcp:dns:ManagedZone
    properties:
      name: peering-zone
      dnsName: peering.example.com.
      description: Example private DNS peering zone
      visibility: private
      privateVisibilityConfig:
        networks:
          - networkUrl: ${["network-source"].id}
      peeringConfig:
        targetNetwork:
          networkUrl: ${["network-target"].id}
  network-source:
    type: gcp:compute:Network
    properties:
      name: network-source
      autoCreateSubnetworks: false
  network-target:
    type: gcp:compute:Network
    properties:
      name: network-target
      autoCreateSubnetworks: false

The peeringConfig property specifies a target network. Resources in the source network (listed in privateVisibilityConfig) can resolve records from zones visible in the target network. DNS peering works independently of VPC network peering.

Integrate with Service Directory for service discovery

Service Directory provides a managed service registry for microservices. Backing a DNS zone with Service Directory automatically creates DNS records for registered services.

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

const example = new gcp.servicedirectory.Namespace("example", {
    namespaceId: "example",
    location: "us-central1",
});
const sd_zone = new gcp.dns.ManagedZone("sd-zone", {
    name: "peering-zone",
    dnsName: "services.example.com.",
    description: "Example private DNS Service Directory zone",
    visibility: "private",
    serviceDirectoryConfig: {
        namespace: {
            namespaceUrl: example.id,
        },
    },
});
const network = new gcp.compute.Network("network", {
    name: "network",
    autoCreateSubnetworks: false,
});
import pulumi
import pulumi_gcp as gcp

example = gcp.servicedirectory.Namespace("example",
    namespace_id="example",
    location="us-central1")
sd_zone = gcp.dns.ManagedZone("sd-zone",
    name="peering-zone",
    dns_name="services.example.com.",
    description="Example private DNS Service Directory zone",
    visibility="private",
    service_directory_config={
        "namespace": {
            "namespace_url": example.id,
        },
    })
network = gcp.compute.Network("network",
    name="network",
    auto_create_subnetworks=False)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/dns"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/servicedirectory"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := servicedirectory.NewNamespace(ctx, "example", &servicedirectory.NamespaceArgs{
			NamespaceId: pulumi.String("example"),
			Location:    pulumi.String("us-central1"),
		})
		if err != nil {
			return err
		}
		_, err = dns.NewManagedZone(ctx, "sd-zone", &dns.ManagedZoneArgs{
			Name:        pulumi.String("peering-zone"),
			DnsName:     pulumi.String("services.example.com."),
			Description: pulumi.String("Example private DNS Service Directory zone"),
			Visibility:  pulumi.String("private"),
			ServiceDirectoryConfig: &dns.ManagedZoneServiceDirectoryConfigArgs{
				Namespace: &dns.ManagedZoneServiceDirectoryConfigNamespaceArgs{
					NamespaceUrl: example.ID(),
				},
			},
		})
		if err != nil {
			return err
		}
		_, err = compute.NewNetwork(ctx, "network", &compute.NetworkArgs{
			Name:                  pulumi.String("network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		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 example = new Gcp.ServiceDirectory.Namespace("example", new()
    {
        NamespaceId = "example",
        Location = "us-central1",
    });

    var sd_zone = new Gcp.Dns.ManagedZone("sd-zone", new()
    {
        Name = "peering-zone",
        DnsName = "services.example.com.",
        Description = "Example private DNS Service Directory zone",
        Visibility = "private",
        ServiceDirectoryConfig = new Gcp.Dns.Inputs.ManagedZoneServiceDirectoryConfigArgs
        {
            Namespace = new Gcp.Dns.Inputs.ManagedZoneServiceDirectoryConfigNamespaceArgs
            {
                NamespaceUrl = example.Id,
            },
        },
    });

    var network = new Gcp.Compute.Network("network", new()
    {
        Name = "network",
        AutoCreateSubnetworks = false,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.servicedirectory.Namespace;
import com.pulumi.gcp.servicedirectory.NamespaceArgs;
import com.pulumi.gcp.dns.ManagedZone;
import com.pulumi.gcp.dns.ManagedZoneArgs;
import com.pulumi.gcp.dns.inputs.ManagedZoneServiceDirectoryConfigArgs;
import com.pulumi.gcp.dns.inputs.ManagedZoneServiceDirectoryConfigNamespaceArgs;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
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 example = new Namespace("example", NamespaceArgs.builder()
            .namespaceId("example")
            .location("us-central1")
            .build());

        var sd_zone = new ManagedZone("sd-zone", ManagedZoneArgs.builder()
            .name("peering-zone")
            .dnsName("services.example.com.")
            .description("Example private DNS Service Directory zone")
            .visibility("private")
            .serviceDirectoryConfig(ManagedZoneServiceDirectoryConfigArgs.builder()
                .namespace(ManagedZoneServiceDirectoryConfigNamespaceArgs.builder()
                    .namespaceUrl(example.id())
                    .build())
                .build())
            .build());

        var network = new Network("network", NetworkArgs.builder()
            .name("network")
            .autoCreateSubnetworks(false)
            .build());

    }
}
resources:
  sd-zone:
    type: gcp:dns:ManagedZone
    properties:
      name: peering-zone
      dnsName: services.example.com.
      description: Example private DNS Service Directory zone
      visibility: private
      serviceDirectoryConfig:
        namespace:
          namespaceUrl: ${example.id}
  example:
    type: gcp:servicedirectory:Namespace
    properties:
      namespaceId: example
      location: us-central1
  network:
    type: gcp:compute:Network
    properties:
      name: network
      autoCreateSubnetworks: false

The serviceDirectoryConfig property links the zone to a Service Directory namespace. Cloud DNS automatically generates DNS records for services registered in that namespace, eliminating manual record management for dynamic service inventories.

Beyond these examples

These snippets focus on specific managed zone features: public and private zone visibility, DNS forwarding and peering, and GKE cluster and Service Directory integration. They’re intentionally minimal rather than full DNS deployments.

The examples may reference pre-existing infrastructure such as VPC networks and subnets, GKE clusters with VPC-native networking, Service Directory namespaces, and on-premises name servers for forwarding. They focus on configuring the zone rather than provisioning the surrounding infrastructure.

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

  • DNSSEC configuration (dnssecConfig)
  • Cloud logging setup (cloudLoggingConfig)
  • Reverse lookup zones (reverseLookup)
  • Force destroy for non-empty zones (forceDestroy)

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

Let's create and Manage GCP DNS Managed Zones

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Zone Configuration & Setup
Why does my DNS name need a trailing dot?
The dnsName property must end with a dot (e.g., my-domain.com.). This follows DNS convention where the trailing dot represents the root of the DNS hierarchy.
What properties can't I change after creating a managed zone?
The following properties are immutable: dnsName, name, project, visibility, reverseLookup, and serviceDirectoryConfig. Changing any of these requires recreating the zone.
What's the default visibility for a managed zone?
Zones default to public visibility, making them accessible from the Internet. Set visibility to private to restrict access to VPC resources.
Private Zones & Networking
How do I create a private DNS zone?
Set visibility to private and configure privateVisibilityConfig with at least one of networks (VPC network URLs) or gkeClusters (GKE cluster names).
How do I make my zone visible to GKE clusters?
In privateVisibilityConfig, use gkeClusters with gkeClusterName set to the cluster’s resource ID.
DNS Forwarding & Peering
What's the difference between DNS forwarding and DNS peering?
Forwarding (forwardingConfig) sends DNS queries to external name servers you specify. Peering (peeringConfig) shares DNS resolution with another VPC network in GCP.
Can I forward DNS queries to both IPv4 and IPv6 name servers?
Yes. In forwardingConfig.targetNameServers, use ipv4Address for IPv4 or ipv6Address for IPv6 addresses.
Zone Management
How do I delete a managed zone that contains DNS records?
Set forceDestroy to true to automatically delete all DNS records when deleting the zone. Without this, deletion will fail if records exist.
What does non-authoritative mean for the labels field?
The labels field only manages labels defined in your Pulumi configuration. Labels set by other clients or services aren’t removed. Use effectiveLabels to view all labels on the resource.

Using a different cloud?

Explore networking guides for other cloud providers: