Automating Azure VM Management with Azure Automation Account

·

5 min read

Cover Image for Automating Azure VM Management with Azure Automation Account

Introduction

Managing Azure Virtual Machines (VMs) manually can be time-consuming, especially for tasks like shutting down idle resources to save costs. Azure Automation Account allows you to automate these operations using Runbooks.

In this guide, we will:
✅ Create an Azure Automation Account
✅ Set up a User Assigned Managed Identity (UMI)
✅ Assign VM Contributor role to the identity
✅ Write and execute a Runbook to stop VMs
Schedule the Runbook for automatic execution

We will use PowerShell in the Runbook and leverage Azure CLI for setup.

1️⃣ Create an Azure Automation Account

An Automation Account is required to manage and run scripts in Azure.

Steps:

  1. Go to the Azure Portal → Search for Automation Accounts.

  2. Click Create and provide the following details:

    • Subscription: Select your subscription

    • Resource Group: Create or select an existing one

    • Automation Account Name: e.g., MyAutomationAccount

    • Region: Choose the preferred region

    • Managed Identity: Select None (we’ll create a separate UMI later)

  3. Click Review + CreateCreate.

  4. Please find the screenshot of the Azure Automation Account I created.

2️⃣ Create a User-Assigned Managed Identity (UMI)

A User Assigned Managed Identity (UMI) allows our Automation Account to authenticate and execute actions without storing credentials.

Steps:

  1. Go to Azure Portal → Search for Managed Identities.

  2. Click Create and enter:

    • Subscription & Resource Group: Select same as Automation Account

    • Name: e.g., MyAutomationIdentity

    • Region: Choose the same as Automation Account

  3. Click Review + CreateCreate.

3️⃣ Assign "VM Contributor" Role to the Managed Identity

The VM Contributor role allows our Runbook to manage VMs (start, stop, deallocate, etc.).

Steps:

  1. Go to Azure Portal → Open the Managed Identity created earlier.

  2. Navigate to Access control (IAM) → Click Add role assignment.

  3. Select:

    • Role: Virtual Machine Contributor

    • Scope: Subscription (or specific resource group if needed)

    • Assign access to: Managed Identity

    • Identity: Select autoreizeum

  4. Click Save.

  5. You can see in the image below that created User Managed Identity has VM contributor role assigned.


4️⃣ Create and Publish a Runbook to Stop VMs

Now, we’ll create a PowerShell Runbook that will connect to Azure using the Managed Identity and stop all VMs.

Steps:

  1. Open Azure Portal → Go to your Automation Account.

  2. Click RunbooksCreate a runbook.

  3. Provide:

    • Name: Stop-All-VMs

    • Runbook Type: PowerShell

    • Runtime Version: Latest

  4. Click Create.

  5. Edit the Runbook → Paste the following PowerShell script:

Find the script below.

### this is final runbook script which will stop VMs. Only those VMs with autostop = true

 # Input parameters
 param(


     [Parameter(Mandatory = $true)]
     [string]$SubscriptionId = "Enter your sunscriptionID",

     [Parameter(Mandatory = $true)]
     [string]$UserAssignedIdentityClientId = "Enter your user managed Identity"

 )


 try {
     # Ensures you do not inherit an AzContext in your runbook
     Disable-AzContextAutosave -Scope Process

     # Connect using user-assigned managed identity
     Write-Output "Connecting to Azure using User-Assigned Managed Identity..."
     Connect-AzAccount -Identity -AccountId $UserAssignedIdentityClientId

     # Set context to your subscription
     Write-Output "Setting context to subscription: $SubscriptionId"
     Set-AzContext -SubscriptionId $SubscriptionId

     # Get all VMs in the subscription
     Write-Output "Getting all VMs in the subscription..."
     $vms = Get-AzVM

     # Check if any VMs were found
     if ($null -eq $vms -or $vms.Count -eq 0) {
         Write-Output "No VMs found."
         return
     }

     Write-Output "Found $($vms.Count) VMs"

     # Stop VMs with autostop = true tag
     foreach ($vm in $vms) {
         try {
             # Check for autostop tag
             $autostop = $vm.Tags["autostop"]

             if ($autostop -eq "true") {  # Case-insensitive comparison
                 Write-Output "Stopping VM: $($vm.Name) in resource group: $($vm.ResourceGroupName) (autostop tag present)"
                 $stopResult = Stop-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Force

                 if ($stopResult.Status -eq "Succeeded") {
                     Write-Output "Successfully stopped VM: $($vm.Name)"
                 } else {
                     Write-Error "Failed to stop VM: $($vm.Name). Status: $($stopResult.Status)"
                 }
             } else {
                 Write-Output "Skipping VM: $($vm.Name) in resource group: $($vm.ResourceGroupName) (autostop tag NOT present or not 'true')"
             }
         } catch {
             Write-Error "Error processing VM $($vm.Name): $_"
             continue # Continue to the next VM even if one fails
         }
     }

     Write-Output "VM stop operations completed"

 } catch {
     Write-Error "Error in runbook execution: $_"
     throw $_
 } finally {
     # Clean up authentication context
     Write-Output "Cleaning up Azure context..."
     Clear-AzContext -Force
 }

🔥 Alternatively, you can get the full script from your GitHub repo:
➡️ GitHub Repo: final-runbookstop.ps1

  1. Click SavePublish.

5️⃣ Create a Schedule for the Runbook

To automate the Runbook execution, we’ll create a schedule.

Steps:

  1. Open Azure Portal → Go to your Automation Account.

  2. Select Runbooks → Click on Stop-All-VMs.

  3. Click SchedulesAdd a Schedule.

  4. Select Create a new schedule, and provide:

    • Name: Daily-VM-Shutdown

    • Recurrence: Daily

    • Time: Choose a suitable time (e.g., 10 PM UTC)

  5. Click Create.

  6. Under Parameters and run settings, ensure the default values are correct.

  7. Click OK to save.

6️⃣ Testing and Verification

To ensure everything is working:
Schedule triggers the Runbook → at specified schedule.
Check VM Status → Go to Azure Portal → Open Virtual Machines and verify the VMs are stopping.
Check Logs → View Job Output in the Runbook to see if any errors occurred.



Mode             : Process

ContextDirectory : None

ContextFile      : None

CacheDirectory   : None

CacheFile        : None

KeyStoreFile     : None

Settings         : {[InstallationId, 102b9476-d6c9-4337-870a-4149300e7a15]}



Connecting to Azure using User-Assigned Managed Identity...





Environments                                                                                           Context

------------                                                                                           -------

{[AzureChinaCloud, AzureChinaCloud], [AzureUSGovernment, AzureUSGovernment], [AzureCloud, AzureCloud]} Microsoft.Azure.…



Setting context to subscription: 6baeb535-5ac9-402f-83c4-4aed96077df6






Getting all VMs in the subscription...



Found 2 VMs



Skipping VM: backend1-vm in resource group: RUNBOOKRG (autostop tag NOT present or not 'true')



Stopping VM: backend2-vm in resource group: RUNBOOKRG (autostop tag present)



Successfully stopped VM: backend2-vm

VM stop operations completed

Cleaning up Azure context...

Above is the output of the Job in Azure.

Conclusion

🎯 We successfully automated Azure VM shutdown using Azure Automation Account and Runbooks.
🎯 We used a User Assigned Managed Identity to authenticate securely.
🎯 We scheduled the Runbook for automatic execution.

🎯 We only shutdown the VMs with tag autoshutdown = true