Introduction
Azure VNet peering connects two virtual networks for private communication. When peering fails or stays disconnected, resources in different VNets cannot communicate, affecting multi-tier applications and cross-region architectures.
Symptoms
Peering creation failed:
```bash $ az network vnet peering create \ --name my-peering \ --resource-group my-rg \ --vnet-name vnet1 \ --remote-vnet /subscriptions/SUB/resourceGroups/other-rg/providers/Microsoft.Network/virtualNetworks/vnet2
"Error: Address space overlap detected between virtual networks" ```
Peering status disconnected:
```bash $ az network vnet peering show \ --name my-peering \ --resource-group my-rg \ --vnet-name vnet1 \ --query '{State:peeringState,Connected:peeringSyncLevel}'
{ "State": "Disconnected", "Connected": "NotSynced" } ```
Connectivity failed:
# Ping from VM in VNet1 to VM in VNet2 fails
# No route to hostCommon Causes
- 1.Address space overlap - VNets have overlapping IP ranges
- 2.Missing reverse peering - Only one direction configured
- 3.Subscription access denied - No permission to remote VNet
- 4.Different deployment models - Classic vs Resource Manager
- 5.NSG blocking traffic - Security rules preventing connectivity
- 6.Gateway transit disabled - VPN/ExpressRoute not allowed
- 7.Peering in failed state - Previous operation failed
Step-by-Step Fix
Step 1: Check Peering Status
```bash # List all peerings az network vnet peering list \ --resource-group my-rg \ --vnet-name vnet1 \ --query '[].{Name:name,State:peeringState,RemoteVNet:remoteVirtualNetwork.id}'
# Check specific peering az network vnet peering show \ --name my-peering \ --resource-group my-rg \ --vnet-name vnet1 \ --query '{State:peeringState,UseRemoteGateway:allowGatewayTransit,UseHubGateway:useRemoteGateways}' ```
Step 2: Check Address Space Overlap
```bash # Get VNet address spaces az network vnet show \ --name vnet1 \ --resource-group my-rg \ --query 'addressSpace.addressPrefixes'
az network vnet show \ --name vnet2 \ --resource-group other-rg \ --query 'addressSpace.addressPrefixes'
# If overlapping, readdress one VNet # VNet1: 10.0.0.0/16 # VNet2: 10.0.0.0/16 <- OVERLAP
# Fix by changing VNet2 address space az network vnet update \ --name vnet2 \ --resource-group other-rg \ --address-prefixes 10.1.0.0/16 ```
Step 3: Create Bidirectional Peering
```bash # Peering must be created in both directions # VNet1 to VNet2 az network vnet peering create \ --name vnet1-to-vnet2 \ --resource-group my-rg \ --vnet-name vnet1 \ --remote-vnet /subscriptions/SUB/resourceGroups/other-rg/providers/Microsoft.Network/virtualNetworks/vnet2 \ --allow-vnet-access
# VNet2 to VNet1 (required) az network vnet peering create \ --name vnet2-to-vnet1 \ --resource-group other-rg \ --vnet-name vnet2 \ --remote-vnet /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Network/virtualNetworks/vnet1 \ --allow-vnet-access
# Verify both directions az network vnet peering show \ --name vnet1-to-vnet2 \ --resource-group my-rg \ --vnet-name vnet1 \ --query 'peeringState'
az network vnet peering show \ --name vnet2-to-vnet1 \ --resource-group other-rg \ --vnet-name vnet2 \ --query 'peeringState' ```
Step 4: Check Cross-Subscription Permissions
```bash # For cross-subscription peering, need Network Contributor on both VNets az role assignment list \ --scope /subscriptions/SUB1/resourceGroups/my-rg/providers/Microsoft.Network/virtualNetworks/vnet1 \ --query '[].{Role:roleDefinitionName,Principal:principalName}'
az role assignment list \ --scope /subscriptions/SUB2/resourceGroups/other-rg/providers/Microsoft.Network/virtualNetworks/vnet2 \ --query '[].{Role:roleDefinitionName,Principal:principalName}'
# Assign Network Contributor if missing az role assignment create \ --assignee user@example.com \ --role "Network Contributor" \ --scope /subscriptions/SUB2/resourceGroups/other-rg/providers/Microsoft.Network/virtualNetworks/vnet2 ```
Step 5: Check NSG Rules
```bash # Check NSG on source subnet az network nsg show \ --name nsg1 \ --resource-group my-rg \ --query 'securityRules[]'
# Ensure outbound traffic to peered VNet allowed az network nsg rule create \ --nsg-name nsg1 \ --resource-group my-rg \ --name AllowPeeredVNet \ --direction Outbound \ --priority 100 \ --source-address-prefixes 10.0.0.0/16 \ --destination-address-prefixes 10.1.0.0/16 \ --destination-port-ranges '*' \ --protocol '*' \ --access Allow
# Check NSG on destination subnet az network nsg show \ --name nsg2 \ --resource-group other-rg \ --query 'securityRules[]'
# Ensure inbound traffic from peered VNet allowed az network nsg rule create \ --nsg-name nsg2 \ --resource-group other-rg \ --name AllowFromPeeredVNet \ --direction Inbound \ --priority 100 \ --source-address-prefixes 10.0.0.0/16 \ --destination-address-prefixes 10.1.0.0/16 \ --destination-port-ranges '*' \ --protocol '*' \ --access Allow ```
Step 6: Configure Gateway Transit
```bash # If using VPN/ExpressRoute gateway in hub VNet # Enable gateway transit on hub az network vnet peering update \ --name hub-to-spoke \ --resource-group hub-rg \ --vnet-name hub-vnet \ --allow-gateway-transit true
# Use remote gateways on spoke az network vnet peering update \ --name spoke-to-hub \ --resource-group spoke-rg \ --vnet-name spoke-vnet \ --use-remote-gateways true
# Note: Both flags cannot be true on same peering ```
Step 7: Test Connectivity
```bash # Test connectivity between VNets # Create test VMs in each VNet
# From VNet1 VM, test connectivity to VNet2 VM az vm run-command invoke \ --command-id RunShellScript \ --vm-name vm1 \ --resource-group my-rg \ --scripts "ping -c 4 10.1.0.4"
# Check effective routes az network nic show-effective-route-table \ --name vm1-nic \ --resource-group my-rg
# Should show route to peered VNet address space ```
Step 8: Recreate Failed Peering
```bash # If peering stuck in failed state, delete and recreate az network vnet peering delete \ --name my-peering \ --resource-group my-rg \ --vnet-name vnet1
# Wait for deletion to complete az network vnet peering wait \ --name my-peering \ --resource-group my-rg \ --vnet-name vnet1 \ --deleted
# Recreate peering az network vnet peering create \ --name my-peering \ --resource-group my-rg \ --vnet-name vnet1 \ --remote-vnet /subscriptions/SUB/resourceGroups/other-rg/providers/Microsoft.Network/virtualNetworks/vnet2 \ --allow-vnet-access ```
Step 9: Check Global Peering Limits
```bash # Check peering limits az network vnet peering list \ --resource-group my-rg \ --vnet-name vnet1 \ --query 'length(@)'
# Default limit: 500 peerings per VNet # If limit exceeded, request increase or consolidate VNets
# Check if global peering (cross-region) az network vnet show \ --name vnet1 \ --resource-group my-rg \ --query 'location'
az network vnet show \ --name vnet2 \ --resource-group other-rg \ --query 'location' ```
Step 10: Monitor Peering Health
```bash # Create alert for peering state changes az monitor activity-log alert create \ --name vnet-peering-alert \ --resource-group my-rg \ --condition category='ResourceManagement' and operationName='Microsoft.Network/virtualNetworks/virtualNetworkPeerings/write'
VNet Peering States
| State | Description | Action |
|---|---|---|
| Initiated | First peering created | Create reverse peering |
| Connected | Both directions active | No action needed |
| Disconnected | One direction missing | Recreate peering |
| Failed | Configuration error | Delete and recreate |
Verification
```bash # After fixing peering az network vnet peering show \ --name vnet1-to-vnet2 \ --resource-group my-rg \ --vnet-name vnet1 \ --query '{State:peeringState,SyncLevel:peeringSyncLevel}'
# Should show: # State: Connected # SyncLevel: FullyInSync
# Test actual connectivity az vm run-command invoke \ --command-id RunShellScript \ --vm-name vm1 \ --resource-group my-rg \ --scripts "curl -I http://10.1.0.4:80"
# Should receive HTTP response from VM in peered VNet ```
Prevention
To prevent Azure VNet peering issues from recurring, implement these proactive measures:
1. Monitor Peering Health
groups:
- name: azure-networking
rules:
- alert: AzureVNetPeeringDisconnected
expr: |
azure_vnet_peering_state != 1
for: 5m
labels:
severity: warning
annotations:
summary: "Azure VNet peering is not connected"2. Use ARM Templates for Consistency
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"resources": [
{
"type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings",
"apiVersion": "2021-02-01",
"name": "[concat(parameters('vnet1Name'), '/peering-to-vnet2')]",
"properties": {
"allowVirtualNetworkAccess": true,
"allowForwardedTraffic": true,
"allowGatewayTransit": false,
"useRemoteGateways": false,
"remoteVirtualNetwork": {
"id": "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnet2Name'))]"
}
}
}
]
}3. Validate Before Creation
```bash # Pre-flight check script cat << 'EOF' > validate_peering.sh #!/bin/bash VNET1=$1 VNET2=$2 RG=$3
# Check VNets exist az network vnet show --name $VNET1 --resource-group $RG --query id az network vnet show --name $VNET2 --resource-group $RG --query id
# Check no overlapping CIDR CIDR1=$(az network vnet show --name $VNET1 --resource-group $RG --query addressSpace.addressPrefixes[0]) CIDR2=$(az network vnet show --name $VNET2 --resource-group $RG --query addressSpace.addressPrefixes[0]) echo "VNet1: $CIDR1, VNet2: $CIDR2" EOF chmod +x validate_peering.sh ```
Best Practices Checklist
- [ ] Monitor peering health status
- [ ] Use ARM templates for consistency
- [ ] Validate VNets before peering
- [ ] Document peering relationships
- [ ] Test connectivity after creation
- [ ] Set up activity log alerts
Related Issues
- [Fix Azure Network Security Group Blocking Traffic](/articles/fix-azure-nsg-flow-logs-not-capturing)
- [Fix Azure Load Balancer Probe Failing](/articles/fix-azure-load-balancer-probe-failing)
- [Fix Azure Bastion Connection Timeout](/articles/fix-azure-bastion-connection-timeout)
Related Articles
- [Technical troubleshooting: Fix Azure Aks Pod Crashloopbackoff Issue in Azure](azure-aks-pod-crashloopbackoff)
- [Technical troubleshooting: Fix Azure Api Management Policy Expression Runtime](azure-api-management-policy-expression-runtime-error)
- [Technical troubleshooting: Fix Azure App Configuration Feature Flag Not Refre](azure-app-configuration-feature-flag-not-refreshing)
- [Technical troubleshooting: Fix Azure App Service 503 Always On Disabled Issue](azure-app-service-503-always-on-disabled)
- [Technical troubleshooting: Fix Azure Application Gateway Err SSL Unrecognized](azure-application-gateway-err-ssl-unrecognized-name-alert)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix Azure VNet Peering Not Connecting", "description": "Troubleshoot Azure VNet peering issues. Check address space overlap, subscription permissions, and peering status.", "url": "https://www.fixwikihub.com/fix-azure-virtual-network-peering-not-connecting", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-04-03T22:03:38.780Z", "dateModified": "2026-04-03T22:03:38.780Z" } </script>