Building Resilient Networks with Azure Networking Services Part 2: Understanding Azure Virtual Networks Peering

Resilient Networking in Azure - VNet Peering

Introduction

In today’s cloud-first landscape, resilient network architectures not only enhance security but also facilitate seamless connectivity between distributed resources. In this installment, we explore two essential capabilities:

  • VNet Peering: Enabling seamless, low-latency connectivity between Virtual Networks within the same region and across different regions.
  • Subnet Peering: Taking VNet peering to a lower level deeper, allowing specific subnets within Virtual Networks to be peered to over Virtual Network subnets, increasing security by not having broad networks connected but specific subnets instead.

We will demonstrate how to implement this solution using both the Azure Portal and Bicep templates. Whether you prefer the intuitive UI or automated, repeatable deployments via Infrastructure-as-Code, you’ll find practical steps and code samples to guide your setup.

VNet Peering: Connecting Virtual Networks

Concept Overview

VNet peering allows you to connect two virtual networks in Azure so that resources in different VNets can communicate with each other via the Microsoft backbone network. Peering can be done:

  • Within the same region: For low latency, high-bandwidth connectivity.
  • Across regions: Enabling global networking scenarios, though take note that data transfer costs may apply.

This connectivity model is ideal for building resilient architectures that span multiple deployments, environments, or even geographic locations.

ℹ️

Importance of Planning with IPAM

Extending your on-premises infrastructure to the cloud requires plenty of advanced planning, no more so than in networking. When you being the planning stages of your cloud adoption you need to allocate a IP address range that does not overlap with your internal ranges to avoid the costly re-work required to fix the problem in future.

Subnet Peering: Connecting Subnets across Virtual Networks

Concept Overview

Subnet peering enables more granular connectivity by allowing you to peer selected subnets between virtual networks instead of merging the entire address space, as is the case with standard VNet peering. This extra level of control is particularly beneficial in scenarios such as micro-segmentation, where you may want only specific tiers or service components to communicate across virtual networks while keeping other parts isolated for security or network management purposes.

With subnet peering, you can:

  • Selectively Share IP Space: Rather than exposing all subnets within a virtual network, you can specify which subnets should be privy to traffic from a remote network. This reduces the attack surface and maintains clearer security boundaries.
  • Optimise IP Space Allocation: For organisations facing IP address exhaustion, subnet peering allows the sharing of only parts of the IP space that are needed for inter-VNet communication, rather than requiring a large, contiguous block of addresses.
  • Enhance Security and Compliance: By limiting connectivity to only designated subnets, you can implement internal segmentation strategies that better align with your organisational security policies and regulatory requirements.
ℹ️
Subnet peering is currently in public preview. This means it’s available through the Azure CLI, PowerShell, API, and ARM templates—but not yet via the Azure Portal.

To enable subnet peering, you must set parameters such as --peer-complete-vnets to false and specify the local and remote subnet names you wish to peer.

Before using subnet level peering you need to ensure that Microsoft.Network/AllowMultiplePeeringLinksBetweenVnets preview feature is enabled in your subscription

1
2
Set-AzContext -Subscription "Subscription Name"
Register-AzProviderFeature -FeatureName AllowMultiplePeeringLinksBetweenVnets -ProviderNamespace Microsoft.Network

A Architecture Diagram

I have always find it best to understand these concepts using diagrams

Here is an example of Geo Peering where the peering happens across regions

architecture-beta group azure(cloud)[Azure] group clouda(cloud)[Australia Southeast] in azure service vnet01(fluent:virtual-network-20-filled)[MyVnet01] in clouda service vm01(fluent:server-20-filled)[Virtual Machine] in clouda group cloudb(cloud)[Australia East] in azure service vnet02(fluent:virtual-network-20-filled)[MyVnet02] in cloudb service vm02(fluent:server-20-filled)[Virtual Machine] in cloudb vm01:T -- B:vnet01 vnet02:B -- T:vm02 vnet01:R <--> L:vnet02

Here is an example of local vnet peering

architecture-beta group clouda(cloud)[Azure Australia East] service vnet01(fluent:virtual-network-20-regular)[MyVnet01] in clouda service vm01(fluent:server-20-filled)[Virtual Machine] in clouda service vnet02(fluent:virtual-network-20-regular)[MyVnet02] in clouda service vm02(fluent:server-20-filled)[Virtual Machine] in clouda vm01:T -- B:vnet01 vnet02:B -- T:vm02 vnet01:R <--> L:vnet02

Here is an example where using Gateway Traversal allows connectivity back to on-prem

architecture-beta group clouda(cloud)[Azure Australia East] group rghub(cloud)[Hub Resource Group] in clouda group rgvm(cloud)[Workload Resource Group] in clouda service vnet01(fluent:virtual-network-20-regular)[MyVnet01] in rghub service vnet03(fluent:virtual-network-20-regular)[MyVnet02] in rgvm service vm01(fluent:server-20-filled)[Virtual Machine] in rgvm service gateway(mdi:vpn)[VPN Gateway] in rghub group onprem(cloud)[On Prem] service vnet02(fluent:virtual-network-20-regular)[Network] in onprem service vm02(fluent:server-20-filled)[Virtual Machine] in onprem service firewall(mdi:firewall)[OnPrem Firewall] in onprem vm01:L -- R:vnet03 vnet01:B <--> T:vnet03 vnet02:B -- T:vm02 vnet01:R -- L:gateway gateway:R <--> L:firewall firewall:R -- L:vnet02

And finally here is a conceptual diagram of subnet peering where we will create bidrectional routing between MySubnetB in MyVnet01 and MySubnetD and MySubnetF in MyVnet02. This will allow for VM 02 to be able to communicate with VM 04 & 06 without allowing other VM’s to communicate between these Virtual Networks.

architecture-beta group azure(cloud)[Azure] group clouda(cloud)[Australia East] in azure group vnet01(fluent:virtual-network-20-filled)[MyVnet01] in clouda service subneta(fluent:virtual-network-20-filled)[MySubnetA] in vnet01 service subnetb(fluent:virtual-network-20-filled)[MySubnetB] in vnet01 service subnetc(fluent:virtual-network-20-filled)[MySubnetC] in vnet01 service vm01(fluent:server-20-filled)[VM 01] in vnet01 service vm02(fluent:server-20-filled)[VM 02] in vnet01 service vm03(fluent:server-20-filled)[VM 03] in vnet01 vm01:L <--> R:subneta vm02:L <--> R:subnetb vm03:L <--> R:subnetc group vnet02(fluent:virtual-network-20-filled)[MyVnet02] in clouda service subnetd(fluent:virtual-network-20-filled)[MySubnetD] in vnet02 service subnete(fluent:virtual-network-20-filled)[MySubnetE] in vnet02 service subnetf(fluent:virtual-network-20-filled)[MySubnetF] in vnet02 service vm04(fluent:server-20-filled)[VM 04] in vnet02 service vm05(fluent:server-20-filled)[VM 05] in vnet02 service vm06(fluent:server-20-filled)[VM 06] in vnet02 vm04:R <--> L:subnetd vm05:R <--> L:subnete vm06:R <--> L:subnetf subnetb:L <--> R:subnetd subnetb:L <--> R:subnetf

Implementing VNet Peering via the Azure Portal

  1. Sign In and Navigate to Virtual Networks:

    • Open the Azure Portal and go to your Virtual Networks.
    • Select the first VNet (e.g., MyVNet1).
  2. Add a Peering Connection:

    • In the Settings section, click on Peerings and then + Add.
    • Name the peering (e.g., MyVNet1-to-MyVNet2).
    • Under Peering link, select the remote Virtual Network (e.g., MyVNet2) and confirm the configuration options:
      • Allow virtual network access: Enabled.
      • Allow forwarded traffic: As per your requirement.
      • Use remote gateways / Allow gateway transit: Configure if a VPN gateway on the remote side needs to be shared.
    • Click OK to create the peering.
  3. Repeat for Reverse Peering:

    • Ensure that the remote VNet (MyVNet2) also has a peering configuration pointing back to MyVNet1.

Implementing VNet Peering via Bicep

Use the following Bicep snippet to deploy a VNet peering between two existing VNets. Adjust the resource names and IDs as needed:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Parameters for flexible deployment
param vnet1Name string = 'MyVNet-01'
param location string = resourceGroup().location
param address1Prefix string = '10.0.0.0/16'
param subnet1Name string = 'MySubnet-01'
param subnet1Prefix string = '10.0.1.0/24'
param vnet2Name string = 'MyVNet-02'
param address2Prefix string = '10.1.0.0/16'
param subnet2Name string = 'MySubnet-02'
param subnet2Prefix string = '10.1.1.0/24'

resource vnet1 'Microsoft.Network/virtualNetworks@2024-05-01' = {
  name: vnet1Name
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        address1Prefix
      ]
    }
    subnets: [
      {
        name: subnet1Name
        properties: {
          addressPrefix: subnet1Prefix
        }
      }
    ]
  }
}

resource vnet2 'Microsoft.Network/virtualNetworks@2024-05-01' = {
  name: vnet2Name
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        address2Prefix
      ]
    }
    subnets: [
      {
        name: subnet2Name
        properties: {
          addressPrefix: subnet2Prefix
        }
      }
    ]
  }
}

resource vnetPeering1 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2024-05-01' = {
  name: '${vnet1.name}-To-${vnet2.name}'
  parent: vnet1
  properties: {
    remoteVirtualNetwork: {
      id: vnet2.id
    }
    allowVirtualNetworkAccess: true
    allowForwardedTraffic: false
    allowGatewayTransit: false
    useRemoteGateways: false
  }
}

resource vnetPeering2 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2024-05-01' = {
  name: '${vnet2.name}-To-${vnet2.name}'
  parent: vnet2
  properties: {
    remoteVirtualNetwork: {
      id: vnet1.id
    }
    allowVirtualNetworkAccess: true
    allowForwardedTraffic: false
    allowGatewayTransit: false
    useRemoteGateways: false
  }
}

Deployment Steps:

  1. Save the template as VirtualNetworkPeeringDeployment.bicep.

  2. Open your terminal and run:

    1
    2
    3
    4
    
    az login
    az deployment group create \
      --resource-group MyResourceGroup \
      --template-file VirtualNetworkPeeringDeployment.bicep
    

Implementing Subnet Peering via Bicep

ℹ️
At the time of writting this article there is currently no ability to complete subnet peering within the Azure Portal

Use the following Bicep snippet to deploy a Subnet peering between two existing VNets. Adjust the resource names and IDs as needed:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
// This Bicep template creates two virtual networks with multiple subnets and sets up peering between them.
@description('Location of the Resources to be created')
param location string = resourceGroup().location

@description('Name of the first Virtual Network')
param vnet1Name string = 'MyVnet01'

@description('Address prefix for the first Virtual Network')
param vnet1AddressPrefix string = '10.0.0.0/16'

@description('Subnets for the first Virtual Network')
var vnet1Subnets = [
  { name: 'subneta', addressPrefix: '10.0.1.0/24' }
  { name: 'subnetb', addressPrefix: '10.0.2.0/24' }
  { name: 'subnetc', addressPrefix: '10.0.3.0/24' }
]

@description('Name of the second Virtual Network')
param vnet2Name string = 'MyVnet02'

@description('Address prefix for the second Virtual Network')
param vnet2AddressPrefix string = '10.1.0.0/16'

@description('Subnets for the second Virtual Network')
var vnet2Subnets = [
  { name: 'subnetd', addressPrefix: '10.1.1.0/24' }
  { name: 'subnete', addressPrefix: '10.1.2.0/24' }
  { name: 'subnetf', addressPrefix: '10.1.3.0/24' }
]

// Create the first Virtual Network with subnets
resource vnet1 'Microsoft.Network/virtualNetworks@2024-05-01' = {
  name: vnet1Name
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [vnet1AddressPrefix]
    }
    subnets: [for subnet in vnet1Subnets: {
      name: subnet.name
      properties: {
        addressPrefix: subnet.addressPrefix
      }
    }]
  }
}

// Create the second Virtual Network with subnets
resource vnet2 'Microsoft.Network/virtualNetworks@2024-05-01' = {
  name: vnet2Name
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [vnet2AddressPrefix]
    }
    subnets: [for subnet in vnet2Subnets: {
      name: subnet.name
      properties: {
        addressPrefix: subnet.addressPrefix
      }
    }]
  }
}

// This peering allows access from SubnetA and SubnetC of VNet1 to SubnetD and SubnetF of VNet2
resource peering1 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2024-05-01' = {
  name: '${vnet1Name}-to-${vnet2Name}-SubnetB-to-SubnetD-and-SubnetF'
  parent: vnet1
  properties: {
    remoteVirtualNetwork: {
      id: vnet2.id
    }
    peerCompleteVnets: false
    localSubnetNames: [
      'subnetb'
    ]
    remoteSubnetNames: [
      'subnetd'
      'subnetf'
    ]
    allowVirtualNetworkAccess: true
    allowForwardedTraffic: false
    allowGatewayTransit: false
    useRemoteGateways: false
  }
}

// This peering allows access from SubnetD and SubnetF of VNet2 to SubnetB of VNet1
resource peering2 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2024-05-01' = {
  name: '${vnet2Name}-to-${vnet1Name}-SubnetF-and-SubnetD-to-SubnetB'
  parent: vnet2
  properties: {
    remoteVirtualNetwork: {
      id: vnet1.id
    }
    peerCompleteVnets: false
    localSubnetNames: [
      'subnetf'
      'subnetd'
    ]
    remoteSubnetNames: [
      'subnetb'
    ]
    allowVirtualNetworkAccess: true
    allowForwardedTraffic: false
    allowGatewayTransit: false
    useRemoteGateways: false
  }
}

Deployment Steps:

  1. Save the template as SubnetPeeringDeployment.bicep.

  2. Open your terminal and run:

    1
    2
    3
    4
    
    az login
    az deployment group create \
      --resource-group MyResourceGroup \
      --template-file SubnetPeeringDeployment.bicep
    

Conclusion

Building resilient networks in Azure means ensuring that connectivity isn’t just robust but also flexible enough to span both cloud and on-premises resources. VNet Peering provides the ability to interconnect VNets within and across regions to enable seamless communication.

Implementing robust networking strategies using both the Azure Portal and Bicep provides you with the versatility to manage and automate your deployments according to your organisational needs.

Learn More