Last Update: Sep 04, 2024 | Published: Jan 28, 2015
One of the techniques I talked about in Saving Money with Microsoft Azure Virtual Machines was to schedule the startup and shutdown of virtual machines. In this article, I will show you how to accomplish this using a very powerful PowerShell feature called Azure Automation.
As I’ve said in my previous article, many businesses operate during a set number of hours. For example, a company might be open between 8 am and 6 pm. That’s 10 hours of the entire day that virtual machines are required. If we allow for an hour before and after the day, then we only need virtual machines 12 hours per day, or 50 percent of the time.
The pricing of Azure virtual machines is based on how many hours they are running for. Yes, there are also egress data and storage costs, but the virtual machine cost is normally the largest component. If a virtual machine is required for just 50 percent of the day, then why are we running it or, more importantly, paying for it 100 percent of the time?
We can use Azure Automation to cleanly shutdown virtual machines that aren’t required after the end of the day, and then start them up before employees start the day.
In this post, I will show you how to implement basic solutions. Some previous posts by my colleagues at Petri.com go into more detail. The scripts that I will use in my runbooks are basic — everyone’s requirements are different. But the solution will be enough for you to get started, and you can customize it to meet your own needs.
This should also be a nice solution for those of you who are trying to squeeze as much as possible out of your monthly partner internal usage rights, free MSDN benefits, or an Azure trial.
Some of my colleagues have previously written introductions to Azure Automation. Blair Greenwood wrote Getting Started with Microsoft Azure Automation and Russell Smith wrote How to Use Microsoft Azure Automation. Here’s a little refresher.
Azure Automation uses a feature of PowerShell called workflows to create runbooks. A runbook is an atomic unit, allowing you to automate some piece of work, such as powering up or shutting down a bunch of virtual machines in Azure. Automation uses something called assets, where an asset is defined as a reusable resource. Examples of assets are credentials (enabling a runbook to sign into Azure to manipulate resources) and schedules (allowing you to automatically execute a runbook at days/times of your choosing).
By now you should start to understand the solution:
To do this work, you will be using the old Azure management portal. Refer back to Russell Smith’s post and you’ll learn how to:
Browse into the Azure Automation account, navigate into Assets, and click Add Setting. A pop-up window will appear; select Add Credential. The Add Credential wizard is where you will enter the details of the new Azure AD user account.
Set the Credential Type to be PowerShell Credential. Give the credential a reference name (Name) and in the following screen, enter the Azure AD username and password that this credential will store.
Azure Automation, just like its on-premises cousin Service Management Automation, is driven by PowerShell workflows. And like with Windows Server, you need some level of PowerShell skills to start using the really powerful features.
We are going to have two runbooks:
The scripts that I am posting are very simple and serve only to prove the concept. Every organization will have different processes for shutting down virtual machines and starting them up. Think for a moment. Do you start up your VMs in a specific order to model application dependencies? Do you wait a certain amount of time for those dependencies to start up? If so, your workflow code will be more complex to accommodate those processes. It’s not that hard; you’ll use some Start-Sleep, Stop-AzureVM, and Start-AzureVM cmdlets. You can find some examples of more complex startup and shutdown workflows written by Peter Selch Dahl on the TechNet Gallery.
Here is the code for my startup workflow:
workflow StartVMs { $Cred = Get-AutomationPSCredential -Name 'PetriAutomation' Add-AzureAccount -Credential $Cred InlineScript { Select-AzureSubscription -SubscriptionName "Azure in Open" $VMS = Get-AzureVM ForEach ($VM in $VMS) { $VMName = $VM.Name Write-Output "Attempting to start VM: $VMName" Start-AzureVM -ServiceName $VM.ServiceName -Name $VM.Name } } }
Note the Select-AzureSubscription line refers to the name of my Azure subscription. Substitute a different name for your subscription or use some code to query it, as shown in this post.
My shutdown workflow looks like the following:
workflow ShutDownVMs { $Cred = Get-AutomationPSCredential -Name 'PetriAutomation' Add-AzureAccount -Credential $Cred InlineScript { Select-AzureSubscription -SubscriptionName "Azure in Open" $VMS = Get-AzureVM ForEach ($VM in $VMS) { $VMName = $VM.Name Write-Output "Attempting to shut down VM: $VMName" Stop-AzureVM -ServiceName $VM.ServiceName -Name $VM.Name } } }
You can create each runbook by:
When complete, you can either:
Repeat these actions to create two runbooks, one to start VMs and one to stop VMs. Make sure you test the runbooks before proceeding — yes, they will start or shutdown VMs so make sure that’s okay first! When you’re happy, you can publish the runbooks.
I want my StartVMs runbook to automatically execute at 7 am, and the ShutDownVMs runbook to automatically execute at 7 pm. To do this, we will create schedule assets in Azure Automation, one for the morning and one for the evening. Then we will link each schedule to the appropriate runbook. Then we can let Azure Automation do its magic.
Browse back to Assets and click Add Setting. Choose Add Schedule and then configure a schedule of your choosing. This can be a one-time event, an hourly event, or in this case a daily event. Note that I don’t have options for Monday to Friday, only every day. That means I will have VMs running at the weekend, but I’m still saving money by having my virtual machines only run 50 percent of the time. I chose Daily, configured the start date, and set the time as 07:00 in one schedule called Daily 7AM or 19:00 in another schedule called Daily 7PM. I like to keep these settings formal and well docuemented because these schedules are reusable for lots of different runbooks.
The next step is to link each runbook to the appropriate schedule. Browse into each runbook, then into the Schedule tab, click Link, and select Link To An Existing Schedule. Select the appropriate schedule and save the change.
Now you have a solution for automatically starting and stopping your virtual machines. I have a few more suggestions for you to look into: