Microsoft has released a new Azure Mv3 series App Service Plan, which has double the amount of ram. In this blog I explain how to deploy and migrate your existing web apps.

The M series are hosted on different servers, you won’t be able to upgrade or scale to this plan. The subnet also can’t be the same as the original plan.

Start by creating the new M series App Service Plan, when I deployed it, it was only available by Bash and not in the portal.

az appservice plan create --resource-group MyRG --name MyAPS --sku p3mv3

That was easy! Migrating the web apps is a bit trickier; you can clone the web app within the same resource group, but the hostname can’t be the same. This could run up to a lot of work depending on your environment.

The workaround is to create temporary resource group with a P1V3 app service plan, and use that as a temporary location from which you can restore your website with the original name to the original resource group.

  1. Clone original app to temp app service plan in a new resource group
  2. Delete original app
  3. Clone temp app back to new app service plan in original resource group
  4. Delete temp app
  5. Restore network integration
You can easily clone sites through the portal to the temp location – Track cloning in the Activity portal, and wait 10 minutes between each action.

Migrate multiple sites with PowerShell

If you need to migrate multiple sites, PowerShell is the way! Below the script I wrote, I included subnet integration after restoring the App Service back to the original name and resource group.

As usual, you can find the latest version on Github.

#MigrateWebApps
#2023.08.27 JPot
#prof-it.services

$region = ""

$rgnorg = 'AppS'
$rgntemp = 'AppSM'


$appserviceplanorg = "AppServicePlan"
$appserviceplannew = "AppServicePlanM"
$appserviceplantemp = "AppServicePlanT"

#VNet Specs for all sites
$VNetRGN= "VNetRGN"
$vNetName = 'vnet'
$integrationSubnetName = 'new_subnet'
$subscriptionId = ''
$subnetResourceId = "/subscriptions/$subscriptionId/resourceGroups/$VNetRGN/providers/Microsoft.Network/virtualNetworks/$vNetName/subnets/$integrationSubnetName"

$sites = Get-AzWebApp -ResourceGroupName $rgnorg
$count = 0

#CLONING, in batches of 10 sites
foreach($site in $sites)
{
  if ($count -ge 10) {
    break
  }

  if (!($site.ServerFarmId.EndsWith($appserviceplanorg))) {
    continue
  }

  $tempname = "TEMP-$($site.Name)"

  try {  
    write-output "$($site.Name) - Cloning original to temp site"
    New-AzWebApp -ResourceGroupName $rgntemp -Name $tempname -Location $region -AppServicePlan $appserviceplantemp -SourceWebApp $site
  }
  catch {
    throw "$($site.Name) - error cloning"
  }
  $count = $count + 1
}

write-output "Done. Pausing for 10 minutes."
Start-Sleep -Seconds 600

#GET TEMP SITES
$tempsites = Get-AzWebApp -ResourceGroupName $rgntemp

#REMOVE ORIGINAL, based on cloned TEMP sites
foreach($site in $tempsites)
{
  if (!($site.ServerFarmId.EndsWith($appserviceplantemp))) {
    continue
  }

  if (!($site.Name.Contains("TEMP-"))) {
    continue
  }
  $siteorgname = $site.Name.Split("TEMP-")[1]

  try {
    write-output "$($site.Name) - Removing original site"
    $orgsite = Get-AzWebApp -ResourceGroupName $rgnorg -Name $siteorgname
    $orgsite | Remove-AzWebApp  -Force
  }
  catch {
    throw "$($site.Name) - error removing original"

  }
}

write-output "Done. Pausing for 10 minutes."
Start-Sleep -Seconds 600

#RESTORE SITES
foreach($site in $tempsites)
{
    if (!($site.ServerFarmId.EndsWith($appserviceplantemp))) {
      continue
    }
    
    if (!($site.Name.Contains("TEMP-"))) {
      continue
    }

    $siteorgname = $site.Name.Split("TEMP-")[1]

    try {
      if (Get-AzResource -ResourceType Microsoft.Web/sites -ResourceGroupName $rgnorg -ResourceName $siteorgname -ErrorAction SilentlyContinue) {
        Write-Output "$($site.Name) - Site already restored"
      } else {
        write-output "$($site.Name) - Restoring clone to original site"
        New-AzWebApp -ResourceGroupName $rgnorg -Name $siteorgname -Location $region -AppServicePlan $appserviceplannew -SourceWebApp $site
      }
      
      Write-Output "$($site.Name) - Restoring network integration"
      $sitenew = Get-AzResource -ResourceType Microsoft.Web/sites -ResourceGroupName $rgnorg -ResourceName $siteorgname
      $sitenew.Properties.virtualNetworkSubnetId = $subnetResourceId
      $sitenew | Set-AzResource -Force
    }
    catch {
      throw "$($site.Name) - error restoring site"
    }
}

write-output "Done. Pausing for 10 minutes."
Start-Sleep -Seconds 600

#DELETE TEMP Sites
foreach($site in $tempsites)
{
  if (!($site.ServerFarmId.EndsWith($appserviceplantemp))) {
    continue
  }

  if (!($site.Name.Contains("TEMP-"))) {
    continue
  }

  $siteorgname = $site.Name.Split("TEMP-")[1]

  try {
    if (!(Get-AzResource -ResourceType Microsoft.Web/sites -ResourceGroupName $rgnorg -ResourceName $siteorgname)) {
        Write-Output "$($site.Name) - new site not found"
        pause
    } else {
        write-output "$($site.Name) - Removing temp site"
        $site | Remove-AzWebApp -Force
    }
  }
  catch {
    throw "$($site.Name) - error removing temp site"
  }
}

Happy Migrating!

Categories:

No responses yet

Leave a Reply

Your email address will not be published. Required fields are marked *