Get-AzAvailabilityZoneMapping.ps1
Maps logical availability zones to physical datacenters across Azure subscriptions to ensure proper fault domain alignment.
Overview
Azure randomizes the mapping between logical zones (1, 2, 3) and physical datacenters for each subscription. This means logical zone 1 in subscription A might map to a completely different physical datacenter than zone 1 in subscription B. This script reveals these mappings, which is critical for multi-subscription architectures requiring true zone alignment.
Key capabilities
- Physical zone discovery: Reveals actual physical datacenter identifiers
- Cross-subscription mapping: Shows how zones align across multiple subscriptions
- Compliance validation: Ensures deployments meet data residency requirements
- Architecture planning: Essential data for multi-subscription deployment patterns
When to use this script
- Planning multi-subscription deployments with zone redundancy
- Verifying zone alignment before deployment stamp creation
- Troubleshooting zone-related deployment failures
- Compliance audits requiring physical datacenter documentation
- Capacity reservation planning across subscriptions
Prerequisites
# Install Azure PowerShell module
Install-Module -Name Az -Repository PSGallery -Force
# Authenticate to Azure
Connect-AzAccount
# Verify subscription access
Get-AzSubscription | Select-Object Name, Id, State
# Ensure you have Reader access to target subscriptions
Get-AzRoleAssignment | Where-Object {$_.RoleDefinitionName -like "*Reader*"}
Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
| SubscriptionIds | String[] | Array of subscription IDs to analyze | All accessible subscriptions |
| OutputFile | String | CSV output filename | ZonePeers.csv |
Usage examples
Basic usage - all subscriptions
.\Get-AzAvailabilityZoneMapping.ps1
Specific subscriptions for deployment planning
.\Get-AzAvailabilityZoneMapping.ps1 `
-SubscriptionIds @('prod-sub-guid', 'dr-sub-guid') `
-OutputFile "ProdDRZoneAlignment.csv"
Multi-subscription stamp validation
# Get all production subscription IDs
$prodSubs = Get-AzSubscription | Where-Object Name -like "Prod-*" | Select-Object -ExpandProperty Id
# Analyze zone mappings
.\Get-AzAvailabilityZoneMapping.ps1 `
-SubscriptionIds $prodSubs `
-OutputFile "ProductionZoneMappings_$(Get-Date -Format 'yyyyMMdd').csv"
Sample output
Running the script across multiple subscriptions produces output like this:
TenantId,SubscriptionId,SubscriptionName,Location,LogicalZone,PhysicalZone,PhysicalZoneName
12345678-1234-1234-1234-123456789012,abcd1234-5678-90ab-cdef-123456789012,Production-Primary,eastus,1,2,eastus-az2
12345678-1234-1234-1234-123456789012,abcd1234-5678-90ab-cdef-123456789012,Production-Primary,eastus,2,3,eastus-az3
12345678-1234-1234-1234-123456789012,abcd1234-5678-90ab-cdef-123456789012,Production-Primary,eastus,3,1,eastus-az1
12345678-1234-1234-1234-123456789012,efgh5678-90ab-cdef-1234-567890abcdef,Production-Secondary,eastus,1,3,eastus-az3
12345678-1234-1234-1234-123456789012,efgh5678-90ab-cdef-1234-567890abcdef,Production-Secondary,eastus,2,1,eastus-az1
12345678-1234-1234-1234-123456789012,efgh5678-90ab-cdef-1234-567890abcdef,Production-Secondary,eastus,3,2,eastus-az2
12345678-1234-1234-1234-123456789012,ijkl9012-3456-7890-abcd-ef1234567890,Development,eastus,1,1,eastus-az1
12345678-1234-1234-1234-123456789012,ijkl9012-3456-7890-abcd-ef1234567890,Development,eastus,2,2,eastus-az2
12345678-1234-1234-1234-123456789012,ijkl9012-3456-7890-abcd-ef1234567890,Development,eastus,3,3,eastus-az3
Understanding the output
- TenantId: Azure AD tenant identifier
- SubscriptionId: Unique subscription identifier
- SubscriptionName: Friendly subscription name
- Location: Azure region
- LogicalZone: The zone number applications see (1, 2, 3)
- PhysicalZone: Actual physical datacenter identifier
- PhysicalZoneName: Full physical datacenter name
Critical findings from sample
In this example:
- Production-Primary: Logical zone 1 → Physical zone 2
- Production-Secondary: Logical zone 1 → Physical zone 3
- Development: Logical zone 1 → Physical zone 1
This means deploying to "zone 1" across these subscriptions would actually spread resources across three different physical datacenters, defeating zone alignment goals.
Real-world implications
Incorrect assumption
Deploy to Zone 1 in all subscriptions = Same physical datacenter ❌
Reality revealed by script
Subscription A Zone 1 = Physical Datacenter 2
Subscription B Zone 1 = Physical Datacenter 3
Subscription C Zone 1 = Physical Datacenter 1
Result: No actual zone alignment! ⚠️
Correct approach
Use script output to map deployments:
- Subscription A: Deploy to Zone 3 (Physical DC 1)
- Subscription B: Deploy to Zone 2 (Physical DC 1)
- Subscription C: Deploy to Zone 1 (Physical DC 1)
Result: True zone alignment ✅
Troubleshooting
No zone data returned
# Verify the region supports availability zones
Get-AzLocation | Where-Object Location -eq 'eastus' | Select-Object -ExpandProperty Zones
# Check if subscription has zone access
Get-AzComputeResourceSku -Location 'eastus' |
Where-Object {$_.LocationInfo.Zones.Count -gt 0} |
Select-Object -First 5
Access denied errors
# Verify role assignments
Get-AzRoleAssignment -SignInName (Get-AzContext).Account.Id
# Switch to correct subscription context
Set-AzContext -SubscriptionId 'target-subscription-id'
Performance optimization
For large numbers of subscriptions:
# Process in batches
$allSubs = Get-AzSubscription | Select-Object -ExpandProperty Id
$batchSize = 10
for ($i = 0; $i -lt $allSubs.Count; $i += $batchSize) {
$batch = $allSubs[$i..([Math]::Min($i + $batchSize - 1, $allSubs.Count - 1))]
.\Get-AzAvailabilityZoneMapping.ps1 `
-SubscriptionIds $batch `
-OutputFile "ZoneMapping_Batch_$($i / $batchSize + 1).csv"
}
Integration patterns
Excel analysis
- Import CSV into Excel
- Create pivot table by Physical Zone
- Filter by Location
- Identify subscription groups with matching physical zones
Automated deployment alignment
# Load zone mappings
$zoneMappings = Import-Csv "ZonePeers.csv"
# Find subscriptions where logical zone 1 maps to physical zone 1
$alignedSubs = $zoneMappings |
Where-Object {$_.LogicalZone -eq 1 -and $_.PhysicalZone -eq 1} |
Select-Object -Unique SubscriptionId, SubscriptionName
# Deploy to these subscriptions in zone 1 for alignment
Script source
Related scripts
- Get-AzVMQuotaUsage.ps1 - Comprehensive quota analysis with zone restrictions
- Show-AzVMQuotaReport.ps1 - Single-threaded quota reporting