Summary: Anders Wahlqvist talks about using Windows PowerShell to scale Azure websites.
Microsoft Scripting Guy, Ed Wilson, is here. Today we have a guest post from Anders Wahlqvist. Anders is really active on Twitter—as a matter of fact, that is where we met. I saw references to his blog, read it, and found that he was a good writer and had a lot of excellent stuff to say. So I contacted him and asked if he would like to write for the Hey, Scripting Guy! Blog.
Here is more about Anders:
I work as a consultant at Lumagate focusing on automation and PowerShell. I have a very strong passion about automation and enjoy it to the point where I have also created PowerShell functions and modules for all kinds of things outside of work. They range between controlling lights and amplifiers to buying groceries and waking me up depending on traffic conditions. Partly because it is convenient, but mostly because it’s a lot fun!
When I wanted to start blogging, I got a recommendation to host the blog in Azure. It was so easy to start. I picked a blog platform in the gallery and deployed it all in minutes. And you know what? Completely free!
The problem I’ve faced is that even though the free tier is enough sometimes, the site can quickly hit the quotas when traffic gets heavier. There is this great functionality in Azure called Autoscale, which basically adds new instances to a website as needed, but it’s only available with the Standard tier.
Wouldn’t it be great if we could detect when the traffic starts to hit the site, change it to the Standard tier with Autoscale turned on, and then scale it back again when the traffic calms down again? We run the site in Azure, so it would make a lot of sense to also run the code for this in Azure Automation. Is it possible?
Luckily, it is!
We’ll dive right into how this is done, but first I would like to give you an overview of the steps involved:
- Set up the automation account in Azure Automation with the required assets (modules) we need, including any custom functions we create.
- Create the runbook needed for scaling the site
- Set up alerts for the site in question, including a webhook that can call the runbook we created in step 2.
Simple as that!
Keep in mind that this just an example to show how you can use the new Azure module (more on that later) together with Azure Automation to manage your resources in the cloud in a way that will not only save you money, but make sure the applications get the resources they need. To make the code a bit easier to follow, it has been simplified quite a bit. The goal is to give you an idea of the process more than creating a function for production use.
But enough of that. Let’s start!
Set up the automation account
I decided to use the new preview module and Azure Resource Manager to achieve the scaling part of this. At the time I’m writing this, the preview module requires a few extra steps to import it successfully into Azure Automation. I won’t go into detail on how to do that, but you'll need to restructure the folders a bit and rename the zip files and folders you create to match those of the DLLs that contain the cmdlets. You should end up with something like this when you’re done (this screenshot is from Azure Automation > Assets > Modules in the Azure preview portal):
I’d also like to point out that because the module is in preview, things will change before it reaches production.
After those are imported, we also need to import the module that contains the function that will do the “heavy lifting” for scaling the website (AzureRMUtilitiesAndHelperFunctions in the previous screenshot).
Right now, this module only contains one function, the Set-WebAppServicePlan function. But you normally end up with many more “helper functions” when working with things like this, so I usually try to put them into a module right away.
If you want to take a look at the code for this function, it is available at the Script Center Repository: Set-WebAppServicePlan - Change app service plan of a web app in Azure. We’ll go through the steps this function does in the next part of this post. If you’re new to this, I recommend that you try to follow the steps described here in the code as we go along.
Create the function for scaling a website
There are quite a lot of things that needs to be configured for this to work, and in an attempt to not get lost in the details here, I’ll just give you the “broad strokes” here in a list:
- We need to create a new resource of the type “Microsoft.Web/serverFarms.” This is basically the name for the app service plan resource provider. For example, it contains the settings for worker size, app service plan, and the number of workers configured. This resource is created by using the New-AzureRmResource cmdlet.
- We then need to assign our web app to use this resource. We do that by using the Set-AzureRmResource cmdlet by specifying the resource ID of our web app and the name of the App Service Plan we created earlier.
- If we want to configure Autoscale, we also need to configure the rules for when the site should be scaled up, and when it should be scaled down.
You do this by using the New-AutoscaleRule cmdlet. AutoScale rules can be bundled in Autoscale profiles. The profiles also specify the scaling range, that is, how many workers can be assigned as a maximum and minimum. To create an Autoscale profile, we call the New-AutoscaleProfile cmdlet and specify our scaling range, a name, and our rules.
Because you can also bundle multiple profiles into an Autoscale setting, we create that setting by calling the Add-AutoscaleSetting cmdlet, which will also assign the settings to our web app.
To summarize a bit:
1. Create the rules (New-AutoscaleRule)
2. Add them to an Autoscale profile (New-AutoscaleProfile)
3. Assign them all together to the web app (Add-AutoscaleSetting)
An argument could be made to split this up into multiple functions, to check if a profile with the specified name already exists, and so on. But for the sake of this post, I thought we should keep things simple.
Oh, and while we talk about Autoscale...
The details here are very important, and they require some knowledge of how the application works. Is it CPU intensive? Or does it use a lot of memory? Both? Something else?
Depending on your answer here, you’ll need to configure your rules differently. In this case, we’ll go with the default values for scaling (those used if you do this through the UI in the Azure portal)—that is, CPU usage on the workers hosting the web application.
When the CPU goes beyond 80% for the specified amount of time, we’ll scale up, when it goes below 60%, we’ll scale down.
But what if you want to use another metric for scaling? How can you find the names for them?
Well, there’s a cmdlet for that!
Play around a bit with the Get-MetricDefinitions and Get-Metrics cmdlets (I have a strong feeling the name of these cmdlets will change though). Specify the resource ID you want to check and you’ll soon realize that you’re not limited to CPU and memory—you can do a lot more.
Remember that the ServerFarm object and the site itself have different metrics, so make sure you check both!
You can use the Azure portal to explore the different metrics, of course, but PowerShell is much more fun, isn’t it?
Create the runbook
So, we have the modules required to interact with Azure and the function we need to scale our website. It’s time to create the runbook that will put all of that together!
This runbook will be in charge of the following tasks:
- Fetch some credentials and connect/authenticate to Azure (Add-AzureRmAccount)
- Parse the data passed to the webhook from the alerts (which we’ll create soon!) and determine if the alert is active or if it has been resolved (ConvertFrom-Json)
- Call Set-WebAppServicePlan to configure our web app accordingly
If you want to take a look at it, the code for this runbook is available in the description section of Set-WebAppServicePlan - Change app service plan of a web app in Azure.
Set up alerts and webhooks
The process of setting up alerts and webhooks together have been posted in detail in Using Azure Automation to take action on Azure Alerts, so head over there if you want some guidance regarding that.
To simplify testing this a bit, I’ll create an alert rule that will trigger after only 10 requests within a 5 minute window on the site:
This allows me to quickly test that everything works as expected (this site hasn't receive any traffic yet), and then simply edit the alert to match what I really want later.
Also, since the data sent from the alert specifies the affected Resource ID, the same runbook can be used for multiple web apps. It will still know which site needs scaling!
Testing and results
This is how it looked when traffic started to flow (the following screenshots are from the Azure preview portal):
You can see that the “TrafficVolumeAlert” has been triggered. That triggered the webhook as you can see in this screenshot from Azure Automation:
The runbooks starts…
And the site is changed to use the Standard tier with Autoscale turned on:
Here's the Autoscale rule:
The site is now ready for a lot of traffic! And when the traffic slows down, the opposite happens. The alert will call the webhook with a status of Resolved, and the runbook will scale the site back to the Free tier again.
I hope that this post has given you an idea of what’s possible to do with the tools used here, and that it will help you get started with automating your resources in Azure, automatically!
Thanks, Anders, for your time and knowledge.
Now you know how to use Windows PowerShell to scale Azure websites. Join me tomorrow when I will talk about more cool stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy