The azure-native:network:Subnet resource, part of the Pulumi Azure Native provider, carves address space from a virtual network and defines how resources within that space connect to Azure services. This guide focuses on three capabilities: address prefix allocation, service endpoint configuration, and network identity control for service traffic.
Subnets belong to virtual networks and reference resource groups. Service endpoint examples may reference public IP addresses for traffic routing. The examples are intentionally small. Combine them with your own network security groups, route tables, and NAT gateways.
Create a basic subnet with address space
Most Azure networking starts by carving address space from a virtual network into subnets, with each subnet getting a CIDR block that determines capacity.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const subnet = new azure_native.network.Subnet("subnet", {
addressPrefix: "10.0.0.0/16",
resourceGroupName: "subnet-test",
subnetName: "subnet1",
virtualNetworkName: "vnetname",
});
import pulumi
import pulumi_azure_native as azure_native
subnet = azure_native.network.Subnet("subnet",
address_prefix="10.0.0.0/16",
resource_group_name="subnet-test",
subnet_name="subnet1",
virtual_network_name="vnetname")
package main
import (
network "github.com/pulumi/pulumi-azure-native-sdk/network/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := network.NewSubnet(ctx, "subnet", &network.SubnetArgs{
AddressPrefix: pulumi.String("10.0.0.0/16"),
ResourceGroupName: pulumi.String("subnet-test"),
SubnetName: pulumi.String("subnet1"),
VirtualNetworkName: pulumi.String("vnetname"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var subnet = new AzureNative.Network.Subnet("subnet", new()
{
AddressPrefix = "10.0.0.0/16",
ResourceGroupName = "subnet-test",
SubnetName = "subnet1",
VirtualNetworkName = "vnetname",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.network.Subnet;
import com.pulumi.azurenative.network.SubnetArgs;
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 subnet = new Subnet("subnet", SubnetArgs.builder()
.addressPrefix("10.0.0.0/16")
.resourceGroupName("subnet-test")
.subnetName("subnet1")
.virtualNetworkName("vnetname")
.build());
}
}
resources:
subnet:
type: azure-native:network:Subnet
properties:
addressPrefix: 10.0.0.0/16
resourceGroupName: subnet-test
subnetName: subnet1
virtualNetworkName: vnetname
The addressPrefix property defines the IP range using CIDR notation. The virtualNetworkName and resourceGroupName properties identify where the subnet lives. Without additional configuration, the subnet uses Azure’s default routing and allows all outbound traffic.
Enable service endpoints for Azure services
Applications accessing Azure Storage or SQL Database from VMs often use service endpoints to route traffic over Azure’s backbone network instead of the public internet.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const subnet = new azure_native.network.Subnet("subnet", {
addressPrefix: "10.0.0.0/16",
resourceGroupName: "subnet-test",
serviceEndpoints: [{
service: "Microsoft.Storage",
}],
subnetName: "subnet1",
virtualNetworkName: "vnetname",
});
import pulumi
import pulumi_azure_native as azure_native
subnet = azure_native.network.Subnet("subnet",
address_prefix="10.0.0.0/16",
resource_group_name="subnet-test",
service_endpoints=[{
"service": "Microsoft.Storage",
}],
subnet_name="subnet1",
virtual_network_name="vnetname")
package main
import (
network "github.com/pulumi/pulumi-azure-native-sdk/network/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := network.NewSubnet(ctx, "subnet", &network.SubnetArgs{
AddressPrefix: pulumi.String("10.0.0.0/16"),
ResourceGroupName: pulumi.String("subnet-test"),
ServiceEndpoints: network.ServiceEndpointPropertiesFormatArray{
&network.ServiceEndpointPropertiesFormatArgs{
Service: pulumi.String("Microsoft.Storage"),
},
},
SubnetName: pulumi.String("subnet1"),
VirtualNetworkName: pulumi.String("vnetname"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var subnet = new AzureNative.Network.Subnet("subnet", new()
{
AddressPrefix = "10.0.0.0/16",
ResourceGroupName = "subnet-test",
ServiceEndpoints = new[]
{
new AzureNative.Network.Inputs.ServiceEndpointPropertiesFormatArgs
{
Service = "Microsoft.Storage",
},
},
SubnetName = "subnet1",
VirtualNetworkName = "vnetname",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.network.Subnet;
import com.pulumi.azurenative.network.SubnetArgs;
import com.pulumi.azurenative.network.inputs.ServiceEndpointPropertiesFormatArgs;
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 subnet = new Subnet("subnet", SubnetArgs.builder()
.addressPrefix("10.0.0.0/16")
.resourceGroupName("subnet-test")
.serviceEndpoints(ServiceEndpointPropertiesFormatArgs.builder()
.service("Microsoft.Storage")
.build())
.subnetName("subnet1")
.virtualNetworkName("vnetname")
.build());
}
}
resources:
subnet:
type: azure-native:network:Subnet
properties:
addressPrefix: 10.0.0.0/16
resourceGroupName: subnet-test
serviceEndpoints:
- service: Microsoft.Storage
subnetName: subnet1
virtualNetworkName: vnetname
Service endpoints change how traffic flows to Azure services. The serviceEndpoints array lists which services (like Microsoft.Storage) should receive traffic over private paths. This keeps data transfer within Azure’s network, improving security and often reducing latency.
Route service endpoint traffic through specific public IPs
Some organizations need to control which public IP addresses appear as the source when subnet traffic reaches Azure services, often for firewall allowlisting.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const subnet = new azure_native.network.Subnet("subnet", {
addressPrefix: "10.0.0.0/16",
resourceGroupName: "subnet-test",
serviceEndpoints: [{
networkIdentifier: {
id: "/subscriptions/subid/resourceGroups/subnet-test/providers/Microsoft.Network/publicIPAddresses/test-ip",
},
service: "Microsoft.Storage",
}],
subnetName: "subnet1",
virtualNetworkName: "vnetname",
});
import pulumi
import pulumi_azure_native as azure_native
subnet = azure_native.network.Subnet("subnet",
address_prefix="10.0.0.0/16",
resource_group_name="subnet-test",
service_endpoints=[{
"network_identifier": {
"id": "/subscriptions/subid/resourceGroups/subnet-test/providers/Microsoft.Network/publicIPAddresses/test-ip",
},
"service": "Microsoft.Storage",
}],
subnet_name="subnet1",
virtual_network_name="vnetname")
package main
import (
network "github.com/pulumi/pulumi-azure-native-sdk/network/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := network.NewSubnet(ctx, "subnet", &network.SubnetArgs{
AddressPrefix: pulumi.String("10.0.0.0/16"),
ResourceGroupName: pulumi.String("subnet-test"),
ServiceEndpoints: network.ServiceEndpointPropertiesFormatArray{
&network.ServiceEndpointPropertiesFormatArgs{
NetworkIdentifier: &network.SubResourceArgs{
Id: pulumi.String("/subscriptions/subid/resourceGroups/subnet-test/providers/Microsoft.Network/publicIPAddresses/test-ip"),
},
Service: pulumi.String("Microsoft.Storage"),
},
},
SubnetName: pulumi.String("subnet1"),
VirtualNetworkName: pulumi.String("vnetname"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var subnet = new AzureNative.Network.Subnet("subnet", new()
{
AddressPrefix = "10.0.0.0/16",
ResourceGroupName = "subnet-test",
ServiceEndpoints = new[]
{
new AzureNative.Network.Inputs.ServiceEndpointPropertiesFormatArgs
{
NetworkIdentifier = new AzureNative.Network.Inputs.SubResourceArgs
{
Id = "/subscriptions/subid/resourceGroups/subnet-test/providers/Microsoft.Network/publicIPAddresses/test-ip",
},
Service = "Microsoft.Storage",
},
},
SubnetName = "subnet1",
VirtualNetworkName = "vnetname",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.network.Subnet;
import com.pulumi.azurenative.network.SubnetArgs;
import com.pulumi.azurenative.network.inputs.ServiceEndpointPropertiesFormatArgs;
import com.pulumi.azurenative.network.inputs.SubResourceArgs;
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 subnet = new Subnet("subnet", SubnetArgs.builder()
.addressPrefix("10.0.0.0/16")
.resourceGroupName("subnet-test")
.serviceEndpoints(ServiceEndpointPropertiesFormatArgs.builder()
.networkIdentifier(SubResourceArgs.builder()
.id("/subscriptions/subid/resourceGroups/subnet-test/providers/Microsoft.Network/publicIPAddresses/test-ip")
.build())
.service("Microsoft.Storage")
.build())
.subnetName("subnet1")
.virtualNetworkName("vnetname")
.build());
}
}
resources:
subnet:
type: azure-native:network:Subnet
properties:
addressPrefix: 10.0.0.0/16
resourceGroupName: subnet-test
serviceEndpoints:
- networkIdentifier:
id: /subscriptions/subid/resourceGroups/subnet-test/providers/Microsoft.Network/publicIPAddresses/test-ip
service: Microsoft.Storage
subnetName: subnet1
virtualNetworkName: vnetname
The networkIdentifier property within a service endpoint specifies a public IP address resource. When VMs in this subnet access the service, traffic appears to originate from that IP. This lets you configure service-side firewalls to allow specific addresses rather than entire subnet ranges.
Beyond these examples
These snippets focus on specific subnet-level features: address space allocation, service endpoint configuration, and network identity control for service endpoints. They’re intentionally minimal rather than full network deployments.
The examples reference pre-existing infrastructure such as virtual networks, resource groups, and public IP addresses (for network identifier example). They focus on configuring the subnet rather than provisioning the surrounding network.
To keep things focused, common subnet patterns are omitted, including:
- Network security groups and route tables
- NAT gateway attachment
- Subnet delegation to Azure services
- Private endpoint and private link policies
- Default outbound access and sharing scope settings
These omissions are intentional: the goal is to illustrate how each subnet feature is wired, not provide drop-in network modules. See the Subnet resource reference for all available configuration options.
Let's configure Azure Virtual Network Subnets
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Configuration & Immutability
resourceGroupName, subnetName, and virtualNetworkName. Changing any of these requires recreating the subnet.defaultOutboundAccess can only be set at subnet creation time and cannot be updated for an existing subnet.sharingScope property requires two conditions: defaultOutboundAccess must be set to false, and the subnet must be empty (no deployed resources).Service Endpoints & Connectivity
serviceEndpoints array with an entry where service is set to Microsoft.Storage.networkIdentifier property within serviceEndpoints, setting id to the resource ID of your public IP address.addressPrefix (e.g., 10.0.0.0/16), resourceGroupName, subnetName, and virtualNetworkName.Network Policies & Access Control
privateEndpointNetworkPolicies is set to Disabled, while privateLinkServiceNetworkPolicies is set to Enabled.sharingScope to Tenant, but only if defaultOutboundAccess is false and the subnet is empty.