Last Update: Sep 04, 2024 | Published: Dec 17, 2017
In this “how to” post, I will show you how to use Azure Automation to scale up (increase) or scale down (decrease) the size of an Azure virtual machine.
In the cloud world, we are supposed to, as I teach, deploy “an army of ants, not a squad of giants”. By deploying lots of small workloads, each instance has little value (especially if it fails). We then have the granular ability to scale in or out, depending on workload (see virtual machine scale sets). The latter is financially beneficial because machines are only running and therefore paid for, while there is a load for them to exist and service.
There are times when an application cannot scale out or in, and the only choice is to add more performance by changing the processor, RAM, etc. I can think of two examples of this:
The DR scenario is fairly simple; when things are normal, the virtual machine is low spec because there is little-to-no load. When a recovery plan is triggered, the virtual machine spec is increased to a normal operational level.
The monolithic application scenario can be more interesting. It may be that there are stages of spec/size increase or decrease with a minimum and maximum level. This is the scenario that I will demonstrate.
You should note two things:
The key to automating the solution is to use Azure Automation. You will deploy an automation account in the Azure Portal. The automation account will execute two runbooks (PowerShell scripts). One is to increase the virtual machine size and the other is to decrease the virtual machine size.
In my example, I will allow the virtual machine to move between three sizes in the B-Series of Azure virtual machines. There is a minimum size and a maximum size, allowing me to set a minimum level of performance and a maximum spend.
Tip: Make sure you run the Update Azure Modules command under Shared Resources > Modules in the automation account or you will get strange PowerShell errors when you run the below runbooks.
Here is the scale-up runbook. Some things to note:
$connectionName = "AzureRunAsConnection" try { # Get the connection "AzureRunAsConnection " $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName "Logging in to Azure..." Add-AzureRmAccount ` -ServicePrincipal ` -TenantId $servicePrincipalConnection.TenantId ` -ApplicationId $servicePrincipalConnection.ApplicationId ` -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint } catch { if (!$servicePrincipalConnection) { $ErrorMessage = "Connection $connectionName not found." throw $ErrorMessage } else{ Write-Error -Message $_.Exception throw $_.Exception } } #Script Runs Here function ResizeVM ($FuncRGName, $FuncVMName, $FuncNewSize) { Write-Output "Upgrading $FuncVMName to $FuncNewSize ... this will require a reboot" $FuncVM = Get-AzureRmVM -ResourceGroupName $FuncRGName -Name $FuncVMName $FuncVM.HardwareProfile.VmSize = $FuncNewSize Update-AzureRmVM -VM $FuncVM -ResourceGroupName $FuncRGName } $ResourceGroupName = "petri2" $VMName = "vm-petri2-01" Write-Output "Starting the scale up process" $VM = Get-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $VMName $CurrentSize = $VM.HardwareProfile.VmSize switch ($CurrentSize) { 'Standard_B1ms' { ResizeVM $ResourceGroupName $VMName "Standard_B2ms" } 'Standard_B2ms' { ResizeVM $ResourceGroupName $VMName "Standard_B4ms" } 'Standard_B4ms' { Write-Output "The VM is at the max allowed size for this application" } } Write-Output "The resizing runbook is finished"
This runbook is almost identical to the previous one:
$connectionName = "AzureRunAsConnection" try { # Get the connection "AzureRunAsConnection " $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName "Logging in to Azure..." Add-AzureRmAccount ` -ServicePrincipal ` -TenantId $servicePrincipalConnection.TenantId ` -ApplicationId $servicePrincipalConnection.ApplicationId ` -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint } catch { if (!$servicePrincipalConnection) { $ErrorMessage = "Connection $connectionName not found." throw $ErrorMessage } else{ Write-Error -Message $_.Exception throw $_.Exception } } #Script Runs Here function ResizeVM ($FuncRGName, $FuncVMName, $FuncNewSize) { Write-Output "Downgrading $FuncVMName to $FuncNewSize ... this will require a reboot" $FuncVM = Get-AzureRmVM -ResourceGroupName $FuncRGName -Name $FuncVMName $FuncVM.HardwareProfile.VmSize = $FuncNewSize Update-AzureRmVM -VM $FuncVM -ResourceGroupName $FuncRGName } $ResourceGroupName = "petri2" $VMName = "vm-petri2-01" Write-Output "Starting the scale down process" $VM = Get-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $VMName $CurrentSize = $VM.HardwareProfile.VmSize switch ($CurrentSize) { 'Standard_B1ms' { Write-Output "The VM is at the min allowed size for this application" } 'Standard_B2ms' { ResizeVM $ResourceGroupName $VMName "Standard_B1ms" } 'Standard_B4ms' { ResizeVM $ResourceGroupName $VMName "Standard_B2ms" } } Write-Output "The resizing runbook is finished"
One could always start the runbooks manually, trigger them from a recovery plan, or even schedule them. In this case, I will automatically trigger my runbooks based on a virtual machine performance alert.
You will require at least two alerts:
You could also add alerts for memory usage and more.
In my first example, I will alert for when CPU usage has been over 80 percent for more than 5 minutes; this prevents brief spikes causing a needless size increase. An email will be sent to subscription owners, etc, to let them know that the process is being triggered.
I will add an action to start a user-defined runbook from my automation account. In this case, I will start the scale-up runbook.
Note the option to add parameters. Instead of using variables for the virtual machine name and resource group, I could pass those values into a generic script!
I’ll then create a similar alert for under 80 percent utilization that will trigger the scale-down runbook. And that’s it! Azure will now automatically increase and decrease the size of my virtual machine based on CPU utilization or any other metric that I specify.