Cloud Migration Platform: Azure Migrate, Site Recovery, App Service Migration, and Hybrid Cloud

Cloud Migration Platform: Azure Migrate, Site Recovery, App Service Migration, and Hybrid Cloud

Introduction

Enterprise cloud migration requires comprehensive planning, assessment, migration execution, and ongoing optimization. This deep dive builds a complete cloud migration platform leveraging Azure Migrate for discovery and assessment, Azure Site Recovery for VM migration and disaster recovery, App Service Migration Assistant for web apps, Azure Arc for hybrid cloud management, and post-migration cost optimization with Azure Advisor.

Solution Architecture

flowchart TB ONPREM[On-Premises Environment] --> DISCOVERY[Azure Migrate Discovery] subgraph "Assessment Phase" DISCOVERY --> ASSESSMENT[Azure Migrate Assessment] ASSESSMENT --> SIZING[VM Sizing] ASSESSMENT --> COSTS[Cost Estimation] ASSESSMENT --> READINESS[Readiness Analysis] end subgraph "Migration Execution" READINESS --> ASR[Azure Site Recovery] READINESS --> DMS[Database Migration Service] READINESS --> APPMIG[App Service Migration] ASR --> VMS[Azure VMs] DMS --> SQLDB[Azure SQL Database] APPMIG --> APPSERVICE[App Service] end subgraph "Hybrid Management" ONPREM --> ARC[Azure Arc] ARC --> ARCVMS[Arc-enabled Servers] ARC --> ARCDATA[Arc-enabled Data Services] ARC --> ARCK8S[Arc-enabled Kubernetes] end VMS --> MONITOR[Azure Monitor] SQLDB --> MONITOR APPSERVICE --> MONITOR MONITOR --> ADVISOR[Azure Advisor] ADVISOR --> OPTIMIZE[Cost Optimization] ARC --> POLICY[Azure Policy] POLICY --> COMPLIANCE[Compliance Reporting] VMS --> BACKUP[Azure Backup] ASR --> DR[Disaster Recovery]

Components Overview

Component Role Key Features
Azure Migrate Assessment hub Discovery, dependency mapping, sizing recommendations
Azure Site Recovery Migration & DR Replication, failover, failback orchestration
Database Migration Service Database migration Online/offline migration, schema conversion
App Service Migration Assistant Web app migration Compatibility assessment, automated migration
Azure Arc Hybrid management Unified control plane, policy enforcement
Azure Advisor Optimization Cost, performance, security recommendations
Azure Monitor Observability Logs, metrics, alerts, workbooks

Implementation Guide

Phase 1: Azure Migrate Discovery & Assessment

Deploy Azure Migrate Appliance:

# Download Azure Migrate appliance OVA/VHD
Invoke-WebRequest -Uri "https://aka.ms/migrate/appliance/vmware" -OutFile "AzureMigrateAppliance.ova"

# Import to VMware/Hyper-V (manual via vSphere/Hyper-V Manager)

# After appliance deployment, register with Azure Migrate project
$projectKey = "your-project-key"
$applianceUrl = "https://migrate-appliance.local:44368"

Invoke-RestMethod -Method Post -Uri "$applianceUrl/api/register" -Body @{
    projectKey = $projectKey
    cloudType = "AzureCloud"
} -ContentType "application/json"

Azure CLI Project Setup:

# Create Azure Migrate project
az migrate project create \
  --name migrate-contoso-platform \
  --resource-group rg-migration \
  --location eastus

# Enable assessment and migration tools
az migrate project enable-tools \
  --project migrate-contoso-platform \
  --resource-group rg-migration \
  --tools AzureMigrate:ServerAssessment AzureMigrate:ServerMigration

Run Assessment:

# Create assessment
az migrate assessment create \
  --name assessment-production-vms \
  --project migrate-contoso-platform \
  --resource-group rg-migration \
  --azure-location eastus \
  --sizing-criterion PerformanceBased \
  --percentile 95 \
  --currency USD \
  --discount-percentage 30 \
  --reserved-instance true

# Get assessment results
az migrate assessment show \
  --name assessment-production-vms \
  --project migrate-contoso-platform \
  --resource-group rg-migration \
  --query '{readiness:properties.azureReadinessSummary, costs:properties.monthlyCostEstimate}'

PowerShell: Export Assessment Report:

# Connect to Azure
Connect-AzAccount

# Get assessment details
$assessment = Get-AzMigrateAssessment -ProjectName "migrate-contoso-platform" -ResourceGroupName "rg-migration"

# Export to CSV
$assessment.AssessedMachines | Select-Object MachineName, AzureReadiness, RecommendedVmSize, MonthlyComputeCost, MonthlyStorageCost | Export-Csv -Path "assessment-report.csv" -NoTypeInformation

# Group by readiness
$assessment.AssessedMachines | Group-Object AzureReadiness | Select-Object Name, Count | Format-Table

Phase 2: Azure Site Recovery Migration

Site Recovery Vault Setup:

# Create Recovery Services vault
az backup vault create \
  --name vault-migration-asr \
  --resource-group rg-migration \
  --location eastus

# Configure replication settings
az backup vault backup-properties set \
  --name vault-migration-asr \
  --resource-group rg-migration \
  --backup-storage-redundancy GeoRedundant

Bicep Configuration for ASR:

resource recoveryServicesVault 'Microsoft.RecoveryServices/vaults@2023-01-01' = {
  name: 'vault-migration-asr'
  location: location
  sku: {
    name: 'RS0'
    tier: 'Standard'
  }
  properties: {
    publicNetworkAccess: 'Enabled'
  }
}

resource replicationPolicy 'Microsoft.RecoveryServices/vaults/replicationPolicies@2023-01-01' = {
  parent: recoveryServicesVault
  name: 'replication-policy-24hr'
  properties: {
    providerSpecificInput: {
      instanceType: 'A2A'
      recoveryPointHistory: 1440 // 24 hours
      appConsistentFrequencyInMinutes: 60
      crashConsistentFrequencyInMinutes: 5
      multiVmSyncStatus: 'Enable'
    }
  }
}

resource replicationFabric 'Microsoft.RecoveryServices/vaults/replicationFabrics@2023-01-01' = {
  parent: recoveryServicesVault
  name: 'fabric-onprem-vmware'
  properties: {
    customDetails: {
      instanceType: 'VMware'
      processServers: [
        {
          friendlyName: 'process-server-1'
          ipAddress: '10.0.1.10'
        }
      ]
    }
  }
}

Enable Replication (PowerShell):

# Get vault
$vault = Get-AzRecoveryServicesVault -Name "vault-migration-asr" -ResourceGroupName "rg-migration"
Set-AzRecoveryServicesAsrVaultContext -Vault $vault

# Get protection container
$protectionContainer = Get-AzRecoveryServicesAsrProtectionContainer -Fabric (Get-AzRecoveryServicesAsrFabric)

# Get replication policy
$replicationPolicy = Get-AzRecoveryServicesAsrPolicy -Name "replication-policy-24hr"

# Enable replication for VM
$vm = Get-AzVM -ResourceGroupName "rg-onprem" -Name "web-server-01"
$replicationProtectedItem = New-AzRecoveryServicesAsrReplicationProtectedItem `
    -VMwareToAzure `
    -ProtectionContainer $protectionContainer `
    -Name "web-server-01" `
    -Policy $replicationPolicy `
    -RecoveryAzureStorageAccountId "/subscriptions/.../storageAccounts/stmigration" `
    -ProcessServer "process-server-1" `
    -Account "vmware-credentials" `
    -RecoveryResourceGroupId "/subscriptions/.../resourceGroups/rg-migrated-vms" `
    -RecoveryAzureNetworkId "/subscriptions/.../virtualNetworks/vnet-prod" `
    -RecoveryAzureSubnetName "subnet-web"

Test Failover:

# Start test failover
$testFailoverJob = Start-AzRecoveryServicesAsrTestFailoverJob `
    -ReplicationProtectedItem $replicationProtectedItem `
    -Direction PrimaryToRecovery `
    -AzureVMNetworkId "/subscriptions/.../virtualNetworks/vnet-test"

# Monitor job
while ($testFailoverJob.State -ne "Succeeded") {
    $testFailoverJob = Get-AzRecoveryServicesAsrJob -Job $testFailoverJob
    Start-Sleep -Seconds 30
}

# Cleanup test failover
Start-AzRecoveryServicesAsrTestFailoverCleanupJob -ReplicationProtectedItem $replicationProtectedItem

Production Failover:

# Planned failover (graceful shutdown)
$failoverJob = Start-AzRecoveryServicesAsrPlannedFailoverJob `
    -ReplicationProtectedItem $replicationProtectedItem `
    -Direction PrimaryToRecovery

# Commit failover
Update-AzRecoveryServicesAsrProtectionDirection `
    -ReplicationProtectedItem $replicationProtectedItem `
    -Direction RecoveryToPrimary

Phase 3: Database Migration Service

DMS Instance Setup:

# Create DMS instance
az dms create \
  --name dms-sql-migration \
  --resource-group rg-migration \
  --location eastus \
  --sku-name Premium_4vCores \
  --subnet /subscriptions/.../subnets/subnet-dms

# Create migration project
az dms project create \
  --name project-sql-migration \
  --service-name dms-sql-migration \
  --resource-group rg-migration \
  --location eastus \
  --source-platform SQL \
  --target-platform SQLDB

Online Migration Task:

# Create online migration task
az dms project task create \
  --name task-migrate-salesdb \
  --project-name project-sql-migration \
  --service-name dms-sql-migration \
  --resource-group rg-migration \
  --task-type Migrate.SqlServer.AzureSqlDb.Sync \
  --source-connection-json '{
    "userName": "sa",
    "password": "<password>",
    "dataSource": "sql-onprem.contoso.com",
    "encryptConnection": true,
    "trustServerCertificate": false
  }' \
  --target-connection-json '{
    "userName": "sqladmin",
    "password": "<password>",
    "dataSource": "sqlserver-prod.database.windows.net",
    "encryptConnection": true,
    "trustServerCertificate": false
  }' \
  --database-options-json '[
    {
      "name": "SalesDB",
      "targetDatabaseName": "SalesDB",
      "makeSourceDbReadOnly": false,
      "tableMap": {
        "dbo.Customers": "dbo.Customers",
        "dbo.Orders": "dbo.Orders"
      }
    }
  ]'

Cutover Script:

# Monitor migration progress
$task = az dms project task show `
    --name task-migrate-salesdb `
    --project-name project-sql-migration `
    --service-name dms-sql-migration `
    --resource-group rg-migration | ConvertFrom-Json

# When ready, perform cutover
az dms project task cutover `
    --name task-migrate-salesdb `
    --project-name project-sql-migration `
    --service-name dms-sql-migration `
    --resource-group rg-migration `
    --object-name SalesDB

Phase 4: App Service Migration

Migration Assistant Assessment:

# Download App Service Migration Assistant
Invoke-WebRequest -Uri "https://appmigration.microsoft.com/api/download/windows/AppServiceMigrationAssistant.msi" -OutFile "AppServiceMigrationAssistant.msi"

# Install
Start-Process msiexec.exe -ArgumentList "/i AppServiceMigrationAssistant.msi /quiet" -Wait

# Run assessment (CLI mode)
& "C:\Program Files\AppServiceMigrationAssistant\Migrate.exe" assess `
    --site-name "contoso-webapp" `
    --output assessment-report.json

Migration via Azure CLI:

# Create App Service Plan
az appservice plan create \
  --name plan-migrated-apps \
  --resource-group rg-migration \
  --location eastus \
  --sku P1V3 \
  --is-linux

# Create web app
az webapp create \
  --name webapp-contoso-prod \
  --resource-group rg-migration \
  --plan plan-migrated-apps \
  --runtime "DOTNET|8.0"

# Deploy from on-prem (via zip)
az webapp deployment source config-zip \
  --resource-group rg-migration \
  --name webapp-contoso-prod \
  --src app-package.zip

Connection String Migration:

# Migrate connection strings
az webapp config connection-string set \
  --resource-group rg-migration \
  --name webapp-contoso-prod \
  --connection-string-type SQLAzure \
  --settings DefaultConnection="Server=tcp:sqlserver-prod.database.windows.net,1433;Database=SalesDB;User ID=sqladmin;Password=<password>;Encrypt=True;"

# Migrate app settings
az webapp config appsettings set \
  --resource-group rg-migration \
  --name webapp-contoso-prod \
  --settings \
    ASPNETCORE_ENVIRONMENT=Production \
    ApplicationInsights__InstrumentationKey="<key>"

Phase 5: Azure Arc Hybrid Management

Arc-enabled Servers:

# Install Arc agent on on-premises server
$subscriptionId = "your-subscription-id"
$resourceGroup = "rg-migration"
$location = "eastus"
$servicePrincipalClientId = "<sp-client-id>"
$servicePrincipalSecret = "<sp-secret>"
$tenantId = "<tenant-id>"

Invoke-WebRequest -Uri "https://aka.ms/azcmagent-windows" -OutFile "AzureConnectedMachineAgent.msi"
Start-Process msiexec.exe -ArgumentList "/i AzureConnectedMachineAgent.msi /quiet" -Wait

& "$env:ProgramFiles\AzureConnectedMachineAgent\azcmagent.exe" connect `
    --service-principal-id $servicePrincipalClientId `
    --service-principal-secret $servicePrincipalSecret `
    --tenant-id $tenantId `
    --subscription-id $subscriptionId `
    --resource-group $resourceGroup `
    --location $location `
    --tags "Environment=Production" "DataCenter=OnPrem"

Apply Azure Policy to Arc Servers:

# Assign policy to enforce monitoring agent
az policy assignment create \
  --name "deploy-monitoring-agent-arc" \
  --policy "/providers/Microsoft.Authorization/policyDefinitions/0868462e-646c-4fe3-9ced-a733534b6a2c" \
  --scope /subscriptions/<sub-id>/resourceGroups/rg-migration \
  --assign-identity --location eastus

# Remediation task
az policy remediation create \
  --name remediate-arc-monitoring \
  --policy-assignment deploy-monitoring-agent-arc \
  --resource-group rg-migration

Arc-enabled Kubernetes:

# Connect on-premises Kubernetes cluster
az connectedk8s connect \
  --name arc-k8s-onprem \
  --resource-group rg-migration \
  --location eastus \
  --kube-config ~/.kube/config

# Enable Azure Monitor for Arc K8s
az k8s-extension create \
  --name azuremonitor-containers \
  --cluster-name arc-k8s-onprem \
  --resource-group rg-migration \
  --cluster-type connectedClusters \
  --extension-type Microsoft.AzureMonitor.Containers

Phase 6: Post-Migration Optimization

Azure Advisor Recommendations:

# Get cost recommendations
az advisor recommendation list \
  --category Cost \
  --query "[].{Resource:resourceMetadata.resourceId, Recommendation:shortDescription.solution, Savings:extendedProperties.savingsAmount}" \
  -o table

# Enable automatic remediation
az advisor configuration create \
  --resource-group rg-migration \
  --low-cpu-threshold 10 \
  --exclude false

Cost Optimization Script:

# Identify idle VMs
$vms = Get-AzVM -ResourceGroupName "rg-migrated-vms"
foreach ($vm in $vms) {
    $metrics = Get-AzMetric -ResourceId $vm.Id -MetricName "Percentage CPU" -TimeGrain 01:00:00 -StartTime (Get-Date).AddDays(-7)
    $avgCpu = ($metrics.Data | Measure-Object Average -Average).Average
    
    if ($avgCpu -lt 5) {
        Write-Host "VM $($vm.Name) has low CPU usage: $avgCpu%. Consider resizing or deallocation."
    }
}

# Resize overprovisioned VMs
$vm = Get-AzVM -ResourceGroupName "rg-migrated-vms" -Name "web-server-01"
$vm.HardwareProfile.VmSize = "Standard_B2s"
Update-AzVM -ResourceGroupName "rg-migrated-vms" -VM $vm

Reserved Instances Purchase:

# Calculate reservation recommendations
az reservations reservation-order calculate \
  --reservation-order-id <order-id> \
  --sku-name Standard_D4s_v3 \
  --location eastus \
  --term P1Y \
  --quantity 10

# Purchase reservation
az reservations reservation-order purchase \
  --reservation-order-id <order-id> \
  --sku Standard_D4s_v3 \
  --location eastus \
  --quantity 10 \
  --term P3Y

Phase 7: Monitoring & Validation

Azure Monitor Workbook (KQL):

// Migration progress dashboard
AzureMigrateAssessment
| where TimeGenerated > ago(30d)
| summarize 
    TotalServers = dcount(MachineName),
    ReadyToMigrate = dcountif(MachineName, AzureReadiness == "Ready"),
    ReadyWithConditions = dcountif(MachineName, AzureReadiness == "ReadyWithConditions"),
    NotReady = dcountif(MachineName, AzureReadiness == "NotReady")
| extend ReadinessRate = (ReadyToMigrate * 100.0) / TotalServers

// Post-migration performance comparison
Perf
| where TimeGenerated > ago(7d)
| where ObjectName == "Processor" and CounterName == "% Processor Time"
| summarize 
    AvgCPU_OnPrem = avgif(CounterValue, Computer startswith "onprem"),
    AvgCPU_Azure = avgif(CounterValue, Computer startswith "az")
| extend PerformanceGain = ((AvgCPU_OnPrem - AvgCPU_Azure) / AvgCPU_OnPrem) * 100

// Cost tracking
AzureActivity
| where OperationNameValue contains "Microsoft.Compute/virtualMachines/write"
| join kind=inner (
    Usage
    | where TimeGenerated > ago(30d)
    | summarize TotalCost = sum(Quantity * UnitPrice) by ResourceId
) on $left.ResourceId == $right.ResourceId
| project TimeGenerated, ResourceName = split(ResourceId, '/')[8], TotalCost
| order by TotalCost desc

Validation Checklist:

Pre-Cutover Validation:
  - [ ] Application functionality tests pass
  - [ ] Performance benchmarks meet baselines
  - [ ] Database replication lag < 5 minutes
  - [ ] SSL certificates configured
  - [ ] DNS records prepared (not yet updated)
  - [ ] Backup/DR tested and verified

Cutover Execution:
  - [ ] Graceful shutdown of on-premises services
  - [ ] Finalize database synchronization
  - [ ] Update DNS records to Azure IPs
  - [ ] Verify application startup in Azure
  - [ ] Test authentication/authorization
  - [ ] Confirm monitoring/alerts active

Post-Cutover Validation:
  - [ ] User acceptance testing completed
  - [ ] No critical errors in Application Insights
  - [ ] Performance SLAs met
  - [ ] Cost tracking dashboards operational
  - [ ] Decommission on-premises infrastructure

Best Practices

  • Pilot Migration: Start with non-critical workloads to validate process
  • Dependency Mapping: Use Azure Migrate dependency analysis to identify interdependencies
  • Network Planning: Design VNet architecture with hub-spoke for hybrid connectivity
  • Security: Apply Azure Security Center recommendations immediately post-migration
  • Automation: Use Infrastructure as Code (Bicep/Terraform) for consistency
  • Cost Management: Enable budgets and alerts before migration begins
  • Skills Enablement: Train operations team on Azure management tools

Troubleshooting

Issue: ASR replication fails with network connectivity error
Solution: Verify ExpressRoute/VPN connectivity; check NSG rules allow ports 443, 9443; validate proxy settings

Issue: Database migration timeout during cutover
Solution: Reduce transaction log size; disable non-clustered indexes temporarily; increase DMS SKU

Issue: Arc agent registration fails
Solution: Check firewall allows outbound HTTPS to *.guestconfiguration.azure.com; verify service principal permissions

Key Takeaways

  • Azure Migrate provides comprehensive assessment for informed migration planning
  • Azure Site Recovery enables seamless VM migration with minimal downtime
  • Database Migration Service supports online migration for near-zero RTO
  • Azure Arc extends Azure management to on-premises and multi-cloud environments
  • Post-migration optimization with Advisor ensures cost efficiency

Next Steps

  • Implement Azure Landing Zones for enterprise-scale governance
  • Deploy Azure Sentinel for unified security operations
  • Explore Azure VMware Solution for VMware workload migration without refactoring
  • Implement Azure Backup for comprehensive data protection

Additional Resources


Ready to accelerate your cloud migration journey?