Scheduling Azure VM Startup and Shutdown using Azure Automation

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.

The Scenario

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.

What is Azure Automation?

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:

  • Runbooks: We will have two scripts to start up and shut down the virtual machines.
  • Credentials: We need one asset to authenticate the runbooks.
  • Schedules: There will be two schedules — one in the morning and one in the evening.

Preparing Azure Automation

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:

  1. Create an Automation account: This will enable Automation in your subscription
  2. Create an Azure AD user account and change the password: There is no need to make the user an administrator. Let’s assume the user is called PetriAutomation.
An Azure Automation user account in Azure Active Directory. (Image Credit: Aidan Finn)
An Azure Automation user account in Azure Active Directory. (Image Credit: Aidan Finn)

Create Credentials Asset

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.

Creating a new PowerShell Credential for Azure Automation. (Image Credit: Aidan Finn)
Creating a new PowerShell Credential for Azure Automation. (Image Credit: Aidan Finn)

Edit the Runbooks

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:

  • StartVMs: This will be used to start up VMs in the morning.
  • ShutDownVMs: The second runbook will be used to cleanly shutdown the VMs in the evening.

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:

  1. Click New > App Services > Automation > Runbook > Quick Create
  2. Name the runbook and ensure that your Automation account and subscription are correct
  3. Wait a few seconds for the runbook to be created and click Edit Runbook in the completion notification. This allows you to edit a draft runbook.
  4. Paste in (and modify, if required) the workflow code.

When complete, you can either:

  • Save the code for later testing
  • Save the code to test it now.

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.

Creating the Schedules Assets

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.

Configuring a new Azure Automation schedule asset. (Image Credit: Aidan Finn)
Configuring a new Azure Automation schedule asset. (Image Credit: Aidan Finn)

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:

  • Look at ordering your virtual machine actions and verifying that they have completed.
  • You can create a maintenance window by powering up the virtual machines for a couple of hours one night and then shutting them down. Do this by linking additional schedules to the existing runbooks.
  • Bear in mind that Azure virtual machines can be slow to start up. The scripts I posted start and stop the virtual machines in a sequential order, which is far from efficient. Test the scripts and verify that they will complete early enough in the morning before the services are required.
  • You don’t have to shut everything down at night. But consider doing it for machines that are not required.
  • Also look at Auto-Scale for scaled-out virtual machines. This will power up/down machines automatically based on demand.