Resize Azure Virtual Machines in Parallel
Published Jun 16 2020 11:30 PM 5,022 Views
Microsoft

Imagine you had to resize a whole bunch of VMs in Azure, rather than doing a resize one after the other in serial, you can do this in parallel with the new ForEach-Object Parallel feature in PowerShell v7. More details on this feature here - https://devblogs.microsoft.com/powershell/powershell-foreach-object-parallel-feature/

 

Doing this in parallel will greatly speed up the process by resizing any number of VMs all at once. To start with, you will need a CSV file with two columns, vmname,targetsize. Enter all the VM names of the VMs that you want to resize, also the correct VM size. 

 

Sample CSV file:

 

 

 

vmname,targetsize
VM01,Standard_DS14_v2
VM02,Standard_DS14_v2

 

 

 

To get a list of Azure VM sizes and the correct format for the name, run the following:

 

 

 

(Get-AzVMSize -Location 'Australia East').Name

 

 

 

This script will loop through all the VMs in the CSV file, shutting down the VM first before the resize happens. A full shutdown of the VM ensures that all target VM sizes are on offer across all Azure clusters, not just VM sizes of the current cluster in which your VM is a member of. First the script will get the status of the Private IP Allocation Method for the VM (Static or Dynamic) and if the private IP address is Dynamic, it will change it to a Static private address temporarily to make sure that the VM's private address stays the same while it's in a shut down state. Then after the resize happens, the VM is powered back up and if the Private IP Allocation Method was changed to Static part of this process, then it changed back to Dynamic, to keep the VM the same as it was originally. 

 

The full script can be found below and here, be sure to read the lines at the top to make sure you gave the correct version of PowerShell v7 and the correct version of the Az (Azure) PowerShell module. 

 

 

 

 

<#
Written with PowerShell v7.0.1 - install available here https://github.com/PowerShell/powershell/releases
Written with version 4.2.0 of the Az PowerShell Module 
available from here https://github.com/Azure/azure-powershell/releases/tag/v4.2.0-June2020 or run: Install-Module -Name Az -RequiredVersion 4.2.0 -AllowClobber
Migration instructions Azure.RM to Az - https://azure.microsoft.com/en-au/blog/how-to-migrate-from-azurerm-to-az-in-azure-powershell/
#>

##########################################################################################
############################    Logon to Microsoft Azure     #############################
##########################################################################################

$AzContextPath = "$($env:TEMP)\$(Get-Date -Format yyyyMMdd)AzEnv.json"

#region Logon to Azure | @marckean
Connect-AzAccount -Tenant '72f988bf-86f1-41af-91ab-2d7cd011db47'

##################### Subscription Select #####################
$subscriptions = Get-AzSubscription
$cnt = 1
Write-Host "ID    Subscription Name"
Write-Host "-----------------------"

foreach ($sub in $subscriptions){
    Write-Host "$cnt   $($sub.name)"
    $cnt++
}
$selection = Read-Host -Prompt "Select a subscription to deploy to"
$subSelect = $subscriptions[$selection - 1] # Revert 1-index to 0-index

Select-AzSubscription $subSelect.SubscriptionId
Save-AzContext -Path $AzContextPath -Force

#endregion

##########################################################################################
################################    List of VM sizes     #################################
##########################################################################################

# Get a list of VM sizes, so you know exactly the format of the name:
(Get-AzVMSize -Location 'Australia East').Name | Select-String 'DS14'

##########################################################################################
#############################    List of VMs to re-size     ##############################
##########################################################################################
#region List of VMs to re-size | @marckean

###########       Only do one of two options here       ###########

# Option 1: Pull VMs from a .CSV file - two columns, headers (vmname,targetsize) | @marckean
$VMs_to_resize = Import-Csv -Path 'W:\VMs_to_resize.csv'

# Option 2: Pull VMs from a comma separated here string - this is practically a mini CSV file anyway | @marckean
$VMs = @'
vmname,targetsize
Hadoop01,Standard_DS14_v2
Hadoop02,Standard_DS14_v2
'@
$VMs_to_resize = $VMs | ConvertFrom-Csv

#endregion

##########################################################################################
################################     Resize the VMs     ###################$##############
##########################################################################################

$VMs_to_resize | ForEach-Object -Parallel {

    Import-AzContext -Path $using:AzContextPath

    # Set private IP address to static to not loose it
    $NicID = ((Get-AzVM -Name $_.vmname).NetworkProfile.NetworkInterfaces[0].Id)
    $Nic = Get-AzNetworkInterface -ResourceId $NicID
    $PrivateIpAllocationMethod = $Nic.IpConfigurations[0].PrivateIpAllocationMethod # Remember original Private IP Allocation Method
    If($PrivateIpAllocationMethod -eq 'Dynamic'){ # only change the IP addess to static it's Dynamic
    $Nic.IpConfigurations[0].PrivateIpAllocationMethod = 'Static'
    Set-AzNetworkInterface -NetworkInterface $Nic}
    Write-Output "$($_.vmname) is currently set as $PrivateIpAllocationMethod"

    # Stop deallocate, resize the VM
    $vm = Get-AzVM -Name $_.vmname
    $VMsize = $_.targetsize
    Write-Output "Change $($_.vmname) to $VMsize"
    $vm | Stop-AzVM -Force
    $vm.HardwareProfile.VmSize = $VMsize
    Update-AzVM -VM $vm -ResourceGroupName $vm.ResourceGroupName
    $vm | Start-AzVM

    # Changing the Private IP address allocation method of a running VM to Dynamic using PowerShell doesn't cause a restart
    If($PrivateIpAllocationMethod -eq 'Dynamic'){ # only change the IP addess back to Dynamic it was Dynamic in the first instance
    $Nic = Get-AzNetworkInterface -ResourceId ((Get-AzVM -Name $_.vmname).NetworkProfile.NetworkInterfaces[0].Id)
    $Nic.IpConfigurations[0].PrivateIpAllocationMethod = 'Dynamic'
    Set-AzNetworkInterface -NetworkInterface $Nic}

  }

 

 

 

 

https://gist.github.com/marckean/41c35f4160bdc1c40fb0865fbcdbe638

1 Comment
Co-Authors
Version history
Last update:
‎Apr 04 2022 01:52 PM
Updated by: