Schedule Scale up/down VMs with Azure Automation

I recently got a request from one of our customers who have an ERP system where they experience slowness due to high load the first monday and tuesday of every month. They wanted us to implement a scheduled scaling of the machine. As this is a single VM we could only scale up/down by changing the VM Size. The drawback is that this requires a reboot, but as long as you’re aware of the necessary downtime and setup your schedules outside office hours this can be solved easily with Azure Automation

Powershell Runbook

 1<#
 2    .SYNOPSIS
 3        This Azure Automation runbook use tags to scape up/down a virtual machine
 4
 5    .DESCRIPTION
 6        This runbook will resize a virtual machine based on the tags attached to the Virtual Machine object. Both 'ScaleUpSize' and 'ScaleDownSize'-tags must be present for scaling to work.
 7
 8        The runbook is ment to be run on two different schedules:
 9        1. Set 'SCALEUP'=$true to resize a VM to the size set in 'ScaleUpSize'
10        2. Set 'SCALEUP'=$false to resize a VM to the size set in 'ScaleDownSize'
11
12        The runbook assume the Automation account is created with a 'Azure Run as Account'
13
14    .PARAMETER RG
15        The Resource group where the Virtual Machine is located
16
17    .PARAMETER VM
18        The name of the Virtual Machine to be scaled
19
20    .PARAMETER SCALEUP
21        The parameter acts as a switch. If set to 'True', the VM will be scaled up. If 'False' the VM is scaled down.
22        Default value is 'False'.
23#>
24
25param(
26    [parameter(Mandatory=$true)]
27    [String] $rg,
28    [parameter(Mandatory=$true)]
29    [String] $vm,
30    [parameter(Mandatory=$false)]
31    [bool] $scaleUp=$false
32)
33
34try
35{
36    $connection = Get-AutomationConnection -Name 'AzureRunAsConnection'
37    Add-AzureRmAccount `
38        -ServicePrincipal `
39        -TenantId $connection.TenantId `
40        -ApplicationId $connection.ApplicationId `
41        -CertificateThumbPrint $connection.CertificateThumbprint | Out-Null
42}
43catch
44{
45    if (!$connection)
46    {
47        $errorMessage = "Connection not found"
48        throw $errorMessage
49    }
50    else
51    {
52        Write-Error -Message $_.Exception
53        throw $_.Exception    
54    }
55}
56
57if($scaleUp) {
58    $scaleTagSwitch = 'ScaleUpSize'
59}
60else
61{
62    $scaleTagSwitch = 'ScaleDownSize'
63}
64
65$vmdetails = Get-AzureRmVM -ResourceGroupName $rg -Name $vm
66$scaleSize = $vmdetails.Tags[$scaleTagSwitch]
67$vmSize = $vmdetails.HardwareProfile.VmSize
68if(($vmSize -ne $scaleSize) -and ($scaleSize))
69{
70    Write-Output "Resource Group=$rg, Virtual Machine=$vm, Size=$vmSize, ScaleTagSwitch=$scaleSize"
71
72    $vmState = Get-AzureRmVM -ResourceGroupName $rg -Name $vm -Status
73    if($vmState.Statuses[1].DisplayStatus -eq "VM running")
74    {
75        Write-Output "$vm is running. stopping…"
76        Stop-AzureRmVM -ResourceGroupName $rg -Name $vm -Force | Out-Null
77    }
78
79    $vmdetails.HardwareProfile.VmSize = $scaleSize
80    Update-AzureRmVM -ResourceGroupName $rg -VM $vmdetails | Out-Null
81    Start-AzureRmVM -ResourceGroupName $rg -Name $vm | Out-Null
82    Write-Output "Resized $vm to $scaleSize"
83}