10 MIN READ

Azure App Service Pmv3 deployment & migration

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.

<strong>#MigrateWebApps
#2023.08.27 JPot
#prof-it.services</strong>

$region = ""

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


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

<strong>#VNet Specs for all sites</strong>
$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

<strong>#CLONING, in batches of 10 sites</strong>
foreach($site in $sites)
{
  if ($count -ge <strong>10</strong>) {
    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

<strong>#REMOVE ORIGINAL, based on cloned TEMP sites</strong>
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

<strong>#RESTORE SITES</strong>
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

<strong>#DELETE TEMP Sites</strong>
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"
  }
}Code language: PHP (php)

Happy Migrating!

Latest Articles

SOAR: Block Log Analytics IP Entities on Azure Frontdoor / WAF #3
How it works Previously, I’ve blogged about two variants that we used at Prof-IT Services to block malicious IP addresses on Azure Frontdoor that were ...
The G-Door: Microsoft 365 & the risk of unmanaged Google Doc accounts
It’s time to secure Google Workspace—even if you’re not using it. Read about our recent discovered vulnerability, called 'G-Door', which allows users to bypass Microsoft ...
Automating Azure SQL Maintenance with Azure Automation
Keeping Your Azure SQL Databases Healthy: The Power of Automation In the realm of database management, maintaining optimal performance and storage efficiency for your Azure ...
Malware Analysis – Shortcuts in zip file
Recently, we encountered two distinct variants of a payload delivered through Google Drive, both containing a malicious shortcut. While these threats were successfully mitigated, it’s ...