Skip to main content

Migration Patterns

How to migrate existing Azure environments to landing zone architecture.

Migration Scenarios

Migration Assessment

Current State Analysis

Assessment Queries

// Get all subscriptions
ResourceContainers
| where type == "microsoft.resources/subscriptions"
| project subscriptionId, name, tags

// Get resource count by type
Resources
| summarize count() by type
| order by count_ desc
| take 20

// Get VNets and address spaces
Resources
| where type == "microsoft.network/virtualnetworks"
| extend addressSpace = properties.addressSpace.addressPrefixes
| project name, resourceGroup, subscriptionId, addressSpace

// Check for public IP addresses
Resources
| where type == "microsoft.network/publicipaddresses"
| project name, resourceGroup, subscriptionId, properties.ipAddress

// Check encryption status
Resources
| where type == "microsoft.storage/storageaccounts"
| extend encryption = properties.encryption.services.blob.enabled
| project name, resourceGroup, encryption

Migration Phases

Phase 1: Foundation

Phase 2: Governance

Phase 3: Workload Migration

Subscription Migration

Moving Subscriptions to Management Groups

// Move subscription to target management group
resource subscriptionPlacement 'Microsoft.Management/managementGroups/subscriptions@2021-04-01' = {
name: '${managementGroupId}/${subscriptionId}'
}

PowerShell Migration Script

# Migration script
param(
[string]$SubscriptionId,
[string]$TargetManagementGroupId
)

# Get current placement
$subscription = Get-AzSubscription -SubscriptionId $SubscriptionId
$currentMG = Get-AzManagementGroup | Where-Object {
$_.Children.Id -contains "/subscriptions/$SubscriptionId"
}

Write-Host "Current MG: $($currentMG.DisplayName)"
Write-Host "Target MG: $TargetManagementGroupId"

# Move subscription
New-AzManagementGroupSubscription `
-GroupId $TargetManagementGroupId `
-SubscriptionId $SubscriptionId

Write-Host "Subscription moved successfully"

Network Migration

VNet Integration Pattern

Peering Existing VNets

// Create peering from hub to existing VNet
resource peeringToExisting 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2023-05-01' = {
parent: hubVnet
name: 'peer-to-existing-vnet'
properties: {
remoteVirtualNetwork: {
id: existingVnetId
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: true
useRemoteGateways: false
}
}

// Create reverse peering
resource peeringFromExisting 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2023-05-01' = {
parent: existingVnet
name: 'peer-to-hub'
properties: {
remoteVirtualNetwork: {
id: hubVnet.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: true
}
}

Policy Migration

Gradual Policy Enforcement

Audit-First Approach

// Step 1: Deploy in audit mode
resource policyAssignmentAudit 'Microsoft.Authorization/policyAssignments@2022-06-01' = {
name: 'require-encryption-audit'
location: location
properties: {
policyDefinitionId: policyDefinition.id
displayName: 'Require encryption (Audit)'
enforcementMode: 'DoNotEnforce' // Audit only
}
}

// Step 2: After remediation, enable enforcement
resource policyAssignmentEnforce 'Microsoft.Authorization/policyAssignments@2022-06-01' = {
name: 'require-encryption-enforce'
location: location
properties: {
policyDefinitionId: policyDefinition.id
displayName: 'Require encryption (Enforce)'
enforcementMode: 'Default' // Full enforcement
}
}

Remediation Tasks

// Create remediation task for non-compliant resources
resource remediationTask 'Microsoft.PolicyInsights/remediations@2021-10-01' = {
name: 'remediate-diagnostics'
properties: {
policyAssignmentId: policyAssignment.id
policyDefinitionReferenceId: 'deployDiagnostics'
resourceDiscoveryMode: 'ExistingNonCompliant'
}
}

Tagging Migration

Tag Discovery Query

// Find resources without required tags
Resources
| where isnull(tags.CostCenter) or isnull(tags.Environment)
| project name, type, resourceGroup, subscriptionId, tags

Bulk Tag Update Script

# Update tags on existing resources
param(
[string]$SubscriptionId,
[hashtable]$RequiredTags
)

Set-AzContext -SubscriptionId $SubscriptionId

$resources = Get-AzResource | Where-Object {
$null -eq $_.Tags.CostCenter
}

foreach ($resource in $resources) {
$tags = $resource.Tags
if ($null -eq $tags) {
$tags = @{}
}

# Add missing tags
foreach ($key in $RequiredTags.Keys) {
if (-not $tags.ContainsKey($key)) {
$tags[$key] = $RequiredTags[$key]
}
}

Set-AzResource -ResourceId $resource.ResourceId -Tag $tags -Force
Write-Host "Updated: $($resource.Name)"
}

Migration Runbook

Pre-Migration Checklist

## Pre-Migration Checklist

### Discovery
- [ ] Complete resource inventory
- [ ] Document network topology
- [ ] Identify IP address conflicts
- [ ] Catalog existing policies
- [ ] List RBAC assignments
- [ ] Identify compliance requirements

### Planning
- [ ] Define target architecture
- [ ] Create management group hierarchy plan
- [ ] Plan IP address scheme
- [ ] Define subscription organization
- [ ] Create migration wave plan
- [ ] Identify dependencies

### Preparation
- [ ] Deploy landing zone foundation
- [ ] Configure hub networking
- [ ] Set up centralized logging
- [ ] Prepare policy definitions
- [ ] Test in sandbox subscription

### Communication
- [ ] Notify stakeholders
- [ ] Schedule migration windows
- [ ] Document rollback procedures
- [ ] Establish support channels

Migration Wave Template

## Migration Wave: [Wave Name]

### Subscriptions in Scope
| Subscription | Current MG | Target MG | Owner |
|--------------|-----------|-----------|-------|
| sub-app1-prod | None | Corp-Prod | Team A |
| sub-app1-dev | None | Corp-Dev | Team A |

### Pre-Migration Tasks
- [ ] Backup configurations
- [ ] Document current RBAC
- [ ] Snapshot network config

### Migration Steps
1. [ ] Move subscription to target MG
2. [ ] Verify policy inheritance
3. [ ] Peer VNet to hub
4. [ ] Update DNS settings
5. [ ] Validate connectivity
6. [ ] Assign RBAC

### Post-Migration Validation
- [ ] Test application connectivity
- [ ] Verify policy compliance
- [ ] Check monitoring data
- [ ] Validate access controls

### Rollback Plan
If issues occur:
1. Move subscription back to original MG
2. Remove VNet peering
3. Restore original DNS
4. Contact support

Common Challenges

IP Address Conflicts

Dependency Discovery

// Find cross-subscription dependencies
Resources
| where type == "microsoft.network/privateendpoints"
| extend targetResource = tostring(properties.privateLinkServiceConnections[0].properties.privateLinkServiceId)
| project name, subscriptionId, targetResource
| where targetResource !contains subscriptionId

Quick Reference Card

PhaseDurationActivities
Assessment2-4 weeksDiscovery, gap analysis
Foundation2-4 weeksMG, policies, hub network
Governance2-4 weeksPolicy rollout (audit → deny)
Migration4-12 weeksWorkload waves
OptimizationOngoingContinuous improvement

Conclusion

Congratulations! You've completed the Azure Landing Zones guide. You now have the knowledge to:

  • ✅ Design enterprise-scale Azure environments
  • ✅ Implement governance with Azure Policy
  • ✅ Configure hub-spoke or Virtual WAN networking
  • ✅ Deploy with Bicep or Terraform
  • ✅ Automate subscription vending
  • ✅ Handle multi-region and hybrid scenarios
  • ✅ Migrate existing environments

Additional Resources