Automating Azure Autoscale Rules via PowerShell and REST API

In recent articles, we've walked through automated provisioning for an Azure VM environment using Azure Automation and PowerShell DSC.  We've also explored leveraging the Azure Cross-Platform CLI for automated provisioning of Linux workloads on Azure.  After provisioning our workloads, we've even automated the configuration of ongoing health monitoring and alerting.

What's next? Let's automate the configuration of Azure Autoscale for our cloud workloads!

What is Azure Autoscale?

Azure Autoscale helps us align utilization of active cloud services to the volume of users and requests currently hitting an application.  As such, Autoscale helps us avoid overprovisioned scenarios where we'd otherwise be paying for excess resources that may not be needed all the time.

When using Autoscale, the Azure cloud platform can dynamically scale-out/scale-in application instances based on defined schedules or in response to CPU utilization or volume of requests waiting on an Azure Queue, which is useful when designing an application that leverages a Queue-centric Work Pattern.  As part of the Autoscale configuration, you can customize minimum instances, maximum instances, scheduled times and thresholds to optimize scaling behavior for your unique application load patterns.

Learn more! Watch Module 4, Virtual Machines in this MVA Hybrid Cloud Jump Start course

Click to zoom in ...
Configuring Azure Autoscale using the Azure Management Portal

We can manually configure Azure Autoscale using the Azure Management Portal, but in this article we'll walk through automating our Autoscale configuration as part of an overall scripted process for provisioning new workloads on the Azure cloud platform.

Automating Azure Autoscale Configuration

The Azure PowerShell module doesn't yet support direct configuration of Azure Autoscale properties, so we'll want to leverage a combination of Azure PowerShell and the Azure Service Management REST API operations for Autoscaling.  The REST API provides operations for adding, deleting, updating and retrieving Autoscale configurations.

Authenticate to Azure Active Directory

When using Azure PowerShell and the Azure Service Management REST API, we'll first need to authenticate with credentials that provide administrator access to our Azure subscription.  We can authenticate to Azure using either certificate-based authentication or Azure Active Directory authentication

In prior articles, I've provided examples using both approaches. Be sure to check them out for more specific steps in each authentication process.

Azure AD authentication is the preferred authentication approach going forward, so in this article, we'll use Azure AD to authenticate to the REST API with a valid administrator account from within our PowerShell script.

# Load ADAL Assemblies

$adal = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\
ServiceManagement\Azure\Services\
Microsoft.IdentityModel.Clients.ActiveDirectory.dll"

$adalforms = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\
ServiceManagement\Azure\Services\
Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll"

[System.Reflection.Assembly]::LoadFrom($adal)

[System.Reflection.Assembly]::LoadFrom($adalforms)

# Set Azure AD Tenant name

$adTenant = "contoso.onmicrosoft.com"

# Set well-known client ID for AzurePowerShell

$clientId = "1950a258-227b-4e31-a9cf-717495945fc2"

# Set redirect URI for Azure PowerShell

$redirectUri = "urn:ietf:wg:oauth:2.0:oob"

# Set Resource URI to Azure Service Management API

$resourceAppIdURI = "
https://management.core.windows.net/"

# Set Authority to Azure AD Tenant

$authority = "
https://login.windows.net/ $adTenant"

# Create Authentication Context tied to Azure AD Tenant

$authContext = New-Object "Microsoft.IdentityModel.Clients.
ActiveDirectory.AuthenticationContext" -ArgumentList $authority

# Acquire token

$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId,
$redirectUri, "Auto")

PowerShell Snippet - Authenticating to Azure Active Directory

Specify Azure Subscription, Cloud Service and Autoscale Values

Now that we've authenticated to Azure AD as an Azure subscription administrator or co-administrator, we can specify the Subscription ID and Cloud Service.  In addition, we'll also specify # of instances and CPU thresholds for autoscaling.

# Set Azure subscription ID

$subscriptionId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX"

# Set Azure deployment values

$cloudServiceName = "demoapp"

$availabilitySetName = "demoapp-as"

# Set Azure autoscale values

$minInstances = "2"

$maxInstances = "10"

$defaultInstances = "2"

$cpuScaleOut = "80"

$cpuScaleIn = "60"

PowerShell Snippet - Specify Azure Subscription, Cloud Service and Autoscale Values

Build Autoscale REST API Web Request

Next, we'll build the JSON web request that we'll submit to the Azure Service Management REST API to configure our desired Autoscale settings.

# Build JSON web request
$jsonBody = @"
{
"Profiles": [
{
"Name": "Week Day",
"Capacity": {
"Minimum": "$minInstances",
"Maximum": "$maxInstances",
"Default": "$defaultInstances"
},
"Rules": [
{
"MetricTrigger": {
"MetricName": "Percentage CPU",
"MetricNamespace": "",
"MetricSource": "/VirtualMachinesAvailabilitySet/
$cloudServiceName/$availabilitySetName",
"TimeGrain": "PT5M",
"Statistic": "Average",
"TimeWindow": "PT45M",
"TimeAggregation": "Average",
"Operator": "GreaterThanOrEqual",
"Threshold": "$cpuScaleOut"
},
"ScaleAction": {
"Direction": "Increase",
"Type": "ChangeCount",
"Value": "1",
"Cooldown": "PT20M"
}
},
{
"MetricTrigger": {
"MetricName": "Percentage CPU",
"MetricNamespace": "",
"MetricSource": "/VirtualMachinesAvailabilitySet/
$cloudServiceName/$availabilitySetName",
"TimeGrain": "PT5M",
"Statistic": "Average",
"TimeWindow": "PT45M",
"TimeAggregation": "Average",
"Operator": "LessThanOrEqual",
"Threshold": "$cpuScaleIn"
},
"ScaleAction": {
"Direction": "Decrease",
"Type": "ChangeCount",
"Value": "1",
"Cooldown": "PT20M"
}
}
],
"Recurrence": {
"Frequency": "Week",
"Schedule": {
"TimeZone": "Eastern Standard Time",
"Days": [ "Monday", "Tuesday", "Wednesday",
"Thursday" ,"Friday" ],
"Hours": [ 8 ],
"Minutes": [ 0 ]
}
}
},
{
"Name": "Week Night",
"Capacity": {
"Minimum": "$defaultInstances",
"Maximum": "$defaultInstances",
"Default": "$defaultInstances"
},
"Rules": [ ],
"Recurrence": {
"Frequency": "Week",
"Schedule": {
"TimeZone": "Eastern Standard Time",
"Days": [ "Monday", "Tuesday", "Wednesday",
"Thursday" ],
"Hours": [ 20 ],
"Minutes": [ 0 ]
}
}
},
{
"Name": "Week End",
"Capacity": {
"Minimum": "$defaultInstances",
"Maximum": "$defaultInstances",
"Default": "$defaultInstances"
},
"Rules": [ ],
"Recurrence": {
"Frequency": "Week",
"Schedule": {
"TimeZone": "Eastern Standard Time",
"Days": [ "Friday" ],
"Hours": [ 20 ],
"Minutes": [ 0 ]
}
}
}
],
"Enabled": true
}
"@

PowerShell Snippet - Build Autoscale Web Request

Calling the REST API

We're ready to call the Azure Service Management REST API and pass it our Autoscale configuration request.  To do so, we'll first need to create an authorization header with our access token and then encode the web request body that we've built above.  After we've done that, we can submit the request to the REST API using the Invoke-RestMethod PowerShell cmdlet.

# Create Authorization Header

$authHeader = $authResult.CreateAuthorizationHeader()

# Set HTTP request headers to include Authorization header
$requestHeader = @{"x-ms-version" = "2013-10-01";
"Authorization" = $authHeader}

# Encode the JSON web request body

[byte[]]$requestBody =
[System.Text.Encoding]::UTF8.GetBytes($jsonBody)

$contentType = "application/json;charset=utf-8"

# Call Azure Service Management REST API to add Autoscale settings
$azureMgmtUri = "https://management.core.windows.net/
$subscriptionId/services/monitoring/autoscalesettings
?resourceId=/virtualmachines/$cloudServiceName/
availabilitySets/$availabilitySetName"

$response = Invoke-RestMethod `
-Uri $azureMgmtUri `
-Method Put `
-Headers $requestHeader `
-Body $requestBody `
-ContentType $contentType

PowerShell Snippet - Add Autoscale Rules via Azure Service Management REST API

Confirming the Results

We've submitted our request to configure new Autoscale settings for our Azure cloud application, but how do we know that they really are in place? Easy! We can call the same REST API again with a Get method.

# Call Azure Service Management REST API to get current Autoscale settings

$response = Invoke-RestMethod
-Uri $azureMgmtUri `
-Method Get `
-Headers $requestHeader

$response | ConvertTo-Json

$response.Profiles |
ConvertTo-Json -Depth 10 |
Out-File json.txt

PowerShell Snippet - Confirm Autoscale Rules via Azure Service Management REST API

What do you want to Automate?

In this article, we've stepped through the process for automating the configuration of Autoscale rules as part of a scripted approach to workload provisioning on the Azure cloud platform. 

What are you looking to automate next as you provision and manage cloud workloads?

Feel free to leave your suggestions in the comments below, and we'll be sure to consider them for a future article!

See you in the Clouds!

- Keith