As an Azure administrator, one of your key responsibilities is managing resources efficiently. A common task is starting and stopping virtual machines on a schedule to reduce costs. While you could do this manually, automation is the way to go for consistent and error-free execution. In this post, we’ll walk through creating an Azure Automation runbook to manage VM power states.
Creating the PowerShell Script
Let’s start by creating a PowerShell script that we’ll later convert into a runbook. This script will take an action (Start or Stop), a resource group name, and a list of VM names as parameters:
param (
[Parameter(Mandatory)]
[ValidateSet('Start', 'Stop')]
[string]$Action,
[Parameter(Mandatory)]
[string]$ResourceGroupName,
[Parameter(Mandatory)]
[string[]]$VMName
)
$ErrorActionPreference = 'Stop'
foreach ($name in $VMName) {
try {
if ($Action -eq 'Start') {
Start-AzVM -ResourceGroupName $ResourceGroupName -Name $name
Write-Output "$name started successfully."
} else {
Stop-AzVM -ResourceGroupName $ResourceGroupName -Name $name -Force
Write-Output "$name stopped successfully."
}
}
catch {
Write-Error "Failed to $Action $name. Error: $_"
}
}
Save this script to a file, for example, `C:\runbook_azure_vm_schedule.ps1`.
Testing the Script Locally
Before we turn this into a runbook, let’s test it locally. First, check the current state of our VMs:
'SRV2','LINUX' | % { Get-AzVm -Name $_ -Status } | select name,powerstate
Now, let’s stop these VMs using our script:
C:\runbook_azure_vm_schedule.ps1 -Action Stop -ResourceGroupName 'psforsysadmins' -VMName 'SRV2','LINUX'
After the script completes, verify the VM states again:
'SRV2','LINUX' | % { Get-AzVm -Name $_ -Status } | select name,powerstate
You should see that the VMs are now deallocated. Great! Our script works locally.
Creating the Azure Automation Runbook
Now, let’s create a runbook in Azure Automation. We’ll use the Azure Automation VS Code extension for this.
1. Open VS Code and navigate to the Azure extension.
2. Find your Automation Account under your subscription.
3. Right-click on “Runbooks” and select “Create runbook”.
4. Name the runbook “ManageVMState” and choose PowerShell 7.2 as the type.
Once the runbook is created, copy your script into the new file that VS Code opens.
Testing the Runbook Locally
Before publishing, let’s test the runbook locally:
1. Right-click on the runbook and select “Run Local”.
2. Enter the parameters when prompted:
-Action 'Stop' -ResourceGroupName 'psforsysadmins' -VMName @('SRV2','LINUX')
If successful, you’ll see output indicating the VMs were stopped.
Publishing and Running the Runbook in Azure
Now, let’s publish the runbook to Azure:
1. Right-click on the runbook and choose “Publish Runbook”.
2. Confirm when prompted.
To run the runbook in Azure:
1. Right-click on the runbook and choose “Start Automation Job”.
2. Select “Azure” as the runtime environment.
3. Enter the parameters when prompted:
ResourceGroupName: psforsysadmins
Action: stop
VMNames: ['SRV2','LINUX']
Note: For arrays in Azure Automation runbooks, use JSON array syntax (e.g., [‘VM1′,’VM2’]) instead of PowerShell array syntax.
Troubleshooting: Authentication Issues
If you encounter an error like “No subscription found in this context”, it means the runbook isn’t authenticated to access and control the VMs when running in Azure. This is a common issue when moving from local testing to Azure execution.
To resolve this, you’ll need to add authentication to your script using a service principal or managed identity. We’ll cover that in a future post, so stay tuned!
Conclusion
Creating an Azure Automation runbook to manage VM power states is a powerful way to optimize your Azure resource usage. By scheduling these runbooks, you can ensure VMs are only running when needed, potentially saving significant costs.
Remember, while we’ve created a functional runbook, there’s still more to consider, like proper error handling, logging, and most importantly, secure authentication. In our next post, we’ll dive into these advanced topics to create a production-ready VM management solution.
Happy automating!