A virtual network (VNet) is a regional, logically isolated layer 3 network that provides controllable private IPv4 and IPv6 addressing for the virtual machines, container instances, and App Service deployments produced in Chapter 3. Without a VNet, those compute resources would have no customer-defined private addressing, no path to peer with other workloads, and no place to attach traffic filters. The alternative (a shared platform-managed network) would prevent overlapping address spaces across tenants and would prevent operators from defining their own routes to on-premises systems.
A VNet differs from a traditional on-premises LAN in three ways that affect application compatibility. First, there is no broadcast or multicast domain: UDP traffic to 255.255.255.255 or to a 224.0.0.0/4 multicast group is dropped by the host. Second, VMs cannot ping the subnet default gateway because Azure does not implement ICMP echo response on the platform router. Third, there is no spanning tree, no MAC learning, and no concept of attaching to a physical switch port: the network is implemented in software on the host fabric.
Address space and CIDR planning
Every VNet declares at least one address space in CIDR notation. RFC 1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) are conventional, but any range can be assigned including the IETF link-local range or public-routable ranges that the customer does not own. Assigning a public range to a VNet (for example, 25.0.0.0/8) is permitted by the platform but prevents the workload from reaching the actual owners of those public IPs on the internet, because the VNet route table treats the range as local.
A VNet supports multiple non-contiguous address spaces. Adding a second address space such as 10.40.0.0/16 to a VNet that already contains 10.20.0.0/16 is supported without redeployment. Address spaces can be removed only when no subnet within the affected range is in use. The smallest permitted VNet address space is /29 and the largest is /2; in practice, production VNets are sized between /16 and /22 to balance address availability against subnet planning overhead.
💡 Exam Trap: Address spaces of two peered VNets must not overlap. The platform blocks the creation of a peering between vnet-prod-weu-001 (10.20.0.0/16) and vnet-shared-weu-001 (10.20.128.0/17) because the second range is contained within the first. The same rule applies when adding a new address space to an already-peered VNet: the addition is blocked if it overlaps the peer.
Subnets, reservations, and reserved names
A subnet is a CIDR range carved from one of the VNet's address spaces. Subnets cannot overlap each other inside the same VNet, and a subnet cannot straddle two address spaces. The minimum subnet size is /29 and the maximum is /2.
Azure reserves five IP addresses in every subnet. For the subnet 10.20.1.0/24, the reserved addresses are 10.20.1.0 (network address), 10.20.1.1 (used by the platform default gateway), 10.20.1.2 and 10.20.1.3 (used by Azure-provided DNS resolver routing), and 10.20.1.255 (broadcast). A /29 subnet contains 8 total addresses and therefore yields only 3 usable host addresses, which limits its practical use to gateway placements where the platform consumes the addresses anyway.
📊 Limit: A subnet always loses 5 IP addresses to platform reservations regardless of size. A /24 subnet yields 251 usable addresses, a /26 yields 59, and a /29 yields 3.
Specific subnet names are reserved by the platform for specific services and must be created with exact capitalization. GatewaySubnet hosts virtual network gateways for VPN or ExpressRoute and should be /27 or larger to accommodate forced tunneling and active-active gateways. AzureFirewallSubnet hosts an Azure Firewall instance and must be at least /26. AzureBastionSubnet hosts an Azure Bastion deployment and must be at least /26 for Standard and Premium SKUs. RouteServerSubnet hosts an Azure Route Server instance and must be at least /27.
💡 Exam Trap: The subnet name
GatewaySubnetis case-sensitive. Creating a subnet namedgatewaysubnetorGatewaysubnetwill not be recognized as a valid gateway subnet, and gateway deployment will fail with a misleading "subnet not found" error.
Subnet delegation
Subnet delegation grants a specific Azure PaaS resource provider permission to inject managed resources into the subnet. Delegating snet-sqlmi-001 to Microsoft.Sql/managedInstances allows an Azure SQL Managed Instance to deploy its virtual cluster into the subnet, with the platform managing the route table and NSG rules required by that service. A single subnet can be delegated to only one service at a time.
Common delegations and their minimum subnet sizes include Microsoft.Sql/managedInstances at /27, Microsoft.Web/serverFarms (App Service VNet integration) at /28 for limited plans and /26 for full flexibility, Microsoft.ContainerInstance/containerGroups at /29 for limited deployments, and Microsoft.NetApp/volumes for Azure NetApp Files at /28. Delegation also imposes constraints on the subnet: for example, a subnet delegated to SQL Managed Instance cannot host any other resources and cannot be used for service endpoints in the same configuration as a non-delegated subnet.
Creating and modifying VNets
The following Azure CLI command creates a VNet with an initial subnet:
az network vnet create \
--name vnet-prod-weu-001 \
--resource-group rg-network-prod \
--location westeurope \
--address-prefixes 10.20.0.0/16 \
--subnet-name snet-web-001 \
--subnet-prefixes 10.20.1.0/24
Additional subnets are added in separate commands, which allows per-subnet delegations and NSG associations:
az network vnet subnet create \
--name snet-app-001 \
--resource-group rg-network-prod \
--vnet-name vnet-prod-weu-001 \
--address-prefixes 10.20.2.0/24 \
--delegations Microsoft.Web/serverFarms
The equivalent Bicep declaration is idempotent and parameterized, which makes it the preferred approach for repeatable environments:
resource vnet 'Microsoft.Network/virtualNetworks@2023-11-01' = {
name: 'vnet-prod-weu-001'
location: 'westeurope'
properties: {
addressSpace: {
addressPrefixes: [
'10.20.0.0/16'
]
}
subnets: [
{
name: 'snet-web-001'
properties: {
addressPrefix: '10.20.1.0/24'
}
}
{
name: 'snet-app-001'
properties: {
addressPrefix: '10.20.2.0/24'
delegations: [
{
name: 'appservice'
properties: {
serviceName: 'Microsoft.Web/serverFarms'
}
}
]
}
}
]
}
}
IP addressing on network interfaces
A network interface (NIC) is the resource that attaches a VM to a subnet. Every NIC carries one primary IP configuration and may carry additional secondary IP configurations. Each IP configuration holds one private IPv4 address, optionally one private IPv6 address, optionally one public IPv4 address, and optionally one public IPv6 address. Secondary IP configurations are how a single VM hosts multiple TLS certificates on distinct addresses or runs multiple services without port conflicts.
Private IP allocation is either Dynamic or Static. Dynamic means the platform selects an address from the unreserved pool when the NIC is attached to a running VM; the address may change after the VM is deallocated and started again. Static means a specific address is reserved permanently to the NIC and persists through stop, start, and reassignment.
Public IP addresses come in two SKUs. The Basic SKU is being retired and supports only zonal allocation, Dynamic or Static allocation, and Basic SKU load balancers. The Standard SKU supports Static allocation only, supports zone-redundant or zonal placement, and is required for Standard SKU load balancers, Azure Firewall, Bastion, and the Standard SKU NAT Gateway. New deployments should use Standard SKU exclusively.
A public IP prefix reserves a contiguous range of public IPs that can be assigned to individual NICs, load balancers, or NAT gateways. Prefix sizes range from /28 (16 addresses) down to /31 (2 addresses) for IPv4. Using a prefix guarantees that outbound addresses are contiguous, which matters when an external partner must allow-list a range rather than enumerate individual addresses.
💡 Exam Trap: A Standard SKU public IP cannot coexist on the same Load Balancer or NIC as a Basic SKU public IP, and a Basic SKU public IP cannot be upgraded to Standard in place except through the documented upgrade workflow that temporarily detaches the IP. Mixed-SKU configurations produce validation failures at deployment time, not at runtime.
VNet peering
VNet peering connects two VNets so resources in either VNet communicate using private IPs over the Azure backbone, bypassing the internet. Peering is configured as two unidirectional resources, one on each side; both must exist with peeringState of Connected before traffic flows. Peering is non-transitive: if vnet-hub peers with vnet-spoke-a and with vnet-spoke-b, traffic between vnet-spoke-a and vnet-spoke-b does not flow unless a UDR or a transit gateway routes it through the hub.
Regional VNet peering connects VNets within the same Azure region. Global VNet peering connects VNets across regions, including across geographies. Both variants traverse the Azure backbone and support the same functional features; the historical limitation that prevented reaching a Basic SKU internal load balancer over global peering applies only to that legacy SKU. Standard SKU load balancers and Standard SKU public IPs work across both regional and global peerings.
Peerings can cross subscription boundaries and Microsoft Entra tenant boundaries. Cross-tenant peering requires the operator on each side to hold at least the Network Contributor role at the VNet scope and to use the peer's full resource ID when creating the peering.
The following CLI command creates one direction of a regional peering:
az network vnet peering create \
--name peer-hub-to-spoke-a \
--resource-group rg-network-prod \
--vnet-name vnet-hub-weu-001 \
--remote-vnet vnet-spoke-a-weu-001 \
--allow-vnet-access \
--allow-forwarded-traffic
💡 Exam Trap: Setting
--allow-gateway-transiton the hub side and--use-remote-gatewayson the spoke side enables the spoke to use the hub's VPN or ExpressRoute gateway. Setting both--use-remote-gatewaysflags simultaneously on both peerings is invalid and the second peering will fail validation, because a VNet cannot both expose its gateway to peers and use a peer's gateway at the same time.
Routing fundamentals
Every subnet inherits a system route table populated by the platform. The default system routes include in-VNet traffic with next hop VirtualNetwork, peered VNet ranges with next hop VirtualNetwork, 0.0.0.0/0 with next hop Internet, and reserved ranges (such as 10.0.0.0/8 when not used by the VNet) with next hop None. These default routes cannot be edited, only overridden.
A user-defined route (UDR) is stored in a route table resource and the route table is associated with one or more subnets. UDRs override system routes following longest-prefix-match: the most specific prefix wins regardless of next-hop type. When two routes tie on prefix length, UDR wins over BGP-learned route, which wins over system default. The available next-hop types are VirtualNetworkGateway, VirtualNetwork, Internet, VirtualAppliance (with an explicit next-hop IP), and None (which silently drops traffic).
Forced tunneling is implemented by a UDR for 0.0.0.0/0 with next hop VirtualNetworkGateway, which sends all egress traffic across the VPN or ExpressRoute connection to on-premises for inspection. This pattern is mandated by some compliance regimes and breaks direct internet egress from the subnet.
az network route-table create \
--name rt-egress-inspection-001 \
--resource-group rg-network-prod \
--location westeurope
az network route-table route create \
--name route-default-to-firewall \
--resource-group rg-network-prod \
--route-table-name rt-egress-inspection-001 \
--address-prefix 0.0.0.0/0 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.20.10.4
⚠️ Anti-Pattern: Attaching a UDR that points 10.0.0.0/8 to a virtual appliance on a subnet that itself sits in 10.20.1.0/24 creates an asymmetric routing loop, because in-VNet traffic that would normally be delivered by the default
VirtualNetworkroute is now redirected through the appliance. Always exclude the local VNet ranges from broad summary routes by adding more specific routes (such as 10.20.0.0/16 with next hopVirtualNetwork) that win on longest-prefix-match.
Service endpoints (network identity)
A virtual network service endpoint extends the VNet identity to specific Azure PaaS resource providers (Microsoft.Storage, Microsoft.Sql, Microsoft.KeyVault, Microsoft.ServiceBus, and others). When enabled on a subnet, traffic from that subnet to the PaaS resource transits the Azure backbone rather than the internet, and the source IP seen by the PaaS firewall is the private subnet address rather than a public SNAT address.
Service endpoints do not change DNS resolution. The PaaS resource is still reached by its public DNS name and public IP, but the network path is internal. The PaaS resource firewall can be configured to accept connections only from subnets with the matching service endpoint enabled, which provides identity-based filtering at the storage account or SQL server level.
az network vnet subnet update \
--name snet-app-001 \
--vnet-name vnet-prod-weu-001 \
--resource-group rg-network-prod \
--service-endpoints Microsoft.Storage Microsoft.KeyVault
Reference: VNet topology
Decision rules
Choose a single large VNet when all workloads share a lifecycle, a single subscription, and a single ownership boundary, because peering management overhead is zero and routing is implicit. Choose a hub-and-spoke topology with peering when workloads have distinct lifecycles, multiple subscription owners, or a shared egress inspection requirement, because the hub centralizes gateways and firewalls while spokes remain independently deployable. Choose regional peering when both VNets sit in the same region and need lowest latency on the backbone, and choose global peering when business continuity or geographic placement requires VNets in different regions.
🎯 Scenario: A retail company runs three workloads (a public storefront, an internal analytics pipeline, and a payments service) that must share an egress firewall for compliance but must not be able to reach each other directly. A hub-and-spoke design places
fw-prod-weu-001in vnet-hub-weu-001 and places each workload in its own spoke. Peering connects each spoke to the hub but no spoke peers with another. A UDR on each spoke subnet sends 0.0.0.0/0 and the address ranges of the other spokes to the firewall's internal IP, which enforces spoke-to-spoke and egress inspection. The non-transitive property of peering guarantees that even if a misconfigured route is removed, traffic between spokes does not flow directly.
💡 Exam Trap: Peering does not create a route to the on-premises network of a peered hub by default. The spoke must have a peering with
--use-remote-gatewaysset, and the hub peering toward that spoke must have--allow-gateway-transitset. Setting only one side leaves the spoke without a route to the on-premises range, even though the gateway is present in the hub.
