Introduction
As organizations continue to migrate their workloads to the cloud, Microsoft Azure stands out as a leading platform for deploying scalable, reliable, and cost-effective virtual machines (VMs). Managing these VMs efficiently is crucial for cloud engineers, DevOps engineers, and Enterprise IT Administrators. While Azure Portal offers a straightforward graphical interface, PowerShell provides a powerful, flexible, and automatable way to create and manage Azure VMs. This article explores, in detail, how to create and manage Azure Virtual Machines using PowerShell, empowering you to automate your cloud infrastructure confidently.
Why use PowerShell for Azure VM Management?
Prerequisites :
- An Azure subscription is require to perform this task.
- Windows PowerShell 5.1 or PowerShell 7+ Should be installed (PowerShell comes preinstalled with windows OS. however, For macOS/Linux install PowerShell Core)
- The Az PowerShell module should be installed.
- Sufficient permissions in Azure account to create and manage resources.
Setting Up PowerShell and connect to Azure account.
- Install the Az Module – If you haven’t installed the Az module, open PowerShell as administrator and run following command.
Install-Module -Name Az -AllowClobber -Scope CurrentUser
- Sign in to Azure account – Connect PowerShell session to Azure account .
Connect-AzAccount
- If you have multiple Azure Subscription, Set the Subscription under which you want to deploy vm .
You will be prompted to authenticate interactively, in my case i have already logged in to my Azure account and subscription (above screenshot).
Set-AzContext -SubscriptionId 'your-subscription-id'
Deploying an Azure Virtual Machine with PowerShell
$resourceGroup = "myResourceGroup"
$location = "EastUS"
$vmName = "myVM"
$vnetName = "myVnet"
$subnetName = "mySubnet"
$ipName = "myPublicIP"
$nicName = "myNIC"
$size = "Standard_B2s"
$image = "Windows2019Datacenter"
New-AzResourceGroup -Name $resourceGroup -Location $location
Step 3: Create a Virtual Network and Subnet – virtual network (VNet) allows VM to communicate securely.
# Create VNet
$vnet = New-AzVirtualNetwork -ResourceGroupName $resourceGroup `
-Location $location -Name $vnetName -AddressPrefix "10.0.0.0/16"
# Create Subnet
$subnet = Add-AzVirtualNetworkSubnetConfig -Name $subnetName `
-AddressPrefix "10.0.0.0/24" -VirtualNetwork $vnet
# Update the VNet with the new subnet
$vnet | Set-AzVirtualNetwork
Step 4: Create Public IP and Network Interface – Create a public IP for RDP/SSH access, and a network interface(NIC).
# Public IP
$publicIP = New-AzPublicIpAddress -ResourceGroupName $resourceGroup `
-Name $ipName -Location $location -AllocationMethod Dynamic
# NIC
$nic = New-AzNetworkInterface -ResourceGroupName $resourceGroup `
-Name $nicName -Location $location `
-SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $publicIP.Id
Step 5: Configure VM Credentials – Set up an admin username and password for that VM.
# Securely prompt for password
$adminUsername = "azureuser"
$adminPassword = Read-Host -Prompt "Enter VM admin password" -AsSecureString
Step 6: Now create the Virtual Machine by Defining the VM configuration and create it.
# VM Config
$vmConfig = New-AzVMConfig -VMName $vmName -VMSize $size
# Set OS Disk
$vmConfig = Set-AzVMOperatingSystem -VM $vmConfig -Windows ` -ComputerName $vmName -Credential (New-Object System.Management.Automation.PSCredential($adminUsername, $adminPassword)) ` -ProvisionVMAgent -EnableAutoUpdate
# Set Image
$vmConfig = Set-AzVMSourceImage -VM $vmConfig ` -PublisherName ‘MicrosoftWindowsServer’ ` -Offer ‘WindowsServer’ ` -Skus ‘2019-Datacenter’ ` -Version ‘latest’
# Set NIC
$vmConfig = Add-AzVMNetworkInterface -VM $vmConfig -Id $nic.Id
# Create the VM
New-AzVM -ResourceGroupName $resourceGroup -Location $location -VM $vmConfig
Stop-AzVM -ResourceGroupName $resourceGroup -Name $vmName -Force
Restart-AzVM -ResourceGroupName $resourceGroup -Name $vmName
Deallocate VM:
Stop-AzVM -ResourceGroupName $resourceGroup -Name $vmName -Force
Resizing a VM – To scale up or down VM size.
$vm = Get-AzVM -ResourceGroupName $resourceGroup -Name $vmName
$vm.HardwareProfile.VmSize = 'Standard_DS2_v2'
Update-AzVM -VM $vm -ResourceGroupName $resourceGroup
Note: The VM should be deallocated before resizing.
$diskConfig = New-AzDiskConfig -Location $location -CreateOption Empty -DiskSizeGB 128
$dataDisk = New-AzDisk -ResourceGroupName $resourceGroup -DiskName "myDataDisk" -Disk $diskConfig
$vm = Get-AzVM -ResourceGroupName $resourceGroup -Name $vmName
$vm = Add-AzVMDataDisk -VM $vm -Name "myDataDisk" -ManagedDiskId $dataDisk.Id -Lun 1 -CreateOption Attach
Update-AzVM -ResourceGroupName $resourceGroup -VM $vm
Deleting a VM When no longer needed.
Remove-AzVM -ResourceGroupName $resourceGroup -Name $vmName -Force
We may also want to delete associated resources (NIC, disks, IPs) to avoid charges.
Note : The PS script provided above are examples. Please make sure to replace placeholders like resource group names, VM names, locations, and other values according to your specific environment and requirements.
Best Practices for Azure VM Automation
- Use Parameters and Variables to make scripts reusable by using parameters for VM names, sizes, regions, etc.
- Leverage Azure Resource Manager (ARM) Tags to Tag the VMs for cost tracking, automation, and management.
- Secure Credentials- Never hard-code passwords. Use Azure Key Vault or encrypted credential objects.
- Error Handling- Use try/catch blocks for robust scripts.
- Logging- Log all actions performed by the scripts for audit and troubleshooting.
- Template Automation- For repeated deployments, consider using ARM templates or Azure Bicep in combination with PowerShell.
Troubleshooting Common Issues
- For Authentication Errors- Ensure your Az PowerShell module is up-to-date and you are signed in with sufficient permissions.
- Resource Limits- Check your subscription’s quotas for VMs, IPs, and storage.
- Region Availability- Not all VM sizes or images are available in every Azure region so cross check this one before the action
- Networking Issues- Open required ports (like 3389 for RDP or 22 for SSH) in the Network Security Group (NSG).
- Billing- Remember to delete unused resources to avoid unexpected costs.