One of the most common uses of the Microsoft Azure cloud for administrators is virtual machines (VMs). It’s easy to create Azure VMs, but it’s not quite as intuitive to remove one. If you need to learn how to delete an Azure VM, you’ve come to the right place.
Not a reader? Watch this related video tutorial!Sure, you can go to the Azure Portal, and find and delete an Azure VM easily enough. You could also use the Remove-AzVM
PowerShell command in the Azure PowerShell module to quickly remove a VM but there’s a lot more to that VM than just the VM itself.
When that VM is created, you could have potentially created many other resources along with it that should be cleaned up as well. Resources like the below can all be associated with a VM that needs to be removed.
- Boot diagnostics storage containers
- Network interfaces
- Public IP addresses
- OS disk and status storage blobs
- Data disks
In this article, we’ll cover how to build a PowerShell function called Remove-AzrVirtualMachine
that will not only delete an Azure VM but also anything directly associated with it.
Prerequisites
To delete an Azure VM and cleanup other related resources with PowerShell, you’re going to need a couple of things.
- The Azure PowerShell Module – This PowerShell module can be downloaded and installed via the PowerShell Gallery by running
Install-Module Az
. - Authenticated to an Azure subscription – You’ll need to be authenticated to the Azure subscription your VM is located in. To do this, run
Connect-AzAccount
.
To verify, you can then run Get-AzVm -Name <VMName> -ResourceGroupName <VMResourceGroupName>
to check if it returns the VM. If no error is returned, you should be good to go.
Getting the Azure VM Object
To make things easier in this script, to delete an Azure VM, we’ll first get the VM object that contains all of the necessary information we’re looking for. To do that, we use the Get-AzVm
command. For this article, I’ll be working with a VM called WINSRV19 in the MyTestVMs resource group.
$vm = Get-AzVm -Name WINSRV19 -ResourceGroupName MyTestVMs
You should now have the VM object stored in the $vm
variable allowing you to read various objects from the variable as you progress through the script.
Removing the Boot Diagnostics Storage Container
When creating an Azure VM, you always have the option of creating a boot diagnostics container. This is useful for troubleshooting VM boot issues but doesn’t get removed when a VM is deleted. Let’s remedy that.
To remove the boot diagnostics container, you first need to figure out the name of the storage account the container resides. To find this storage account, you’ll have to do some parsing of the storageUri
property that’s buried in the DiagnosticsProfile
object on the VM.
To save you some time, here’s some regex to parse out that name.
$diagSa = [regex]::match($vm.DiagnosticsProfile.bootDiagnostics.storageUri, '^http[s]?://(.+?)\\.').groups[1].value
Next, you’ll need to find the name of the boot diagnostics storage container. To find that, you’ll first need to find the VM ID using the Get-AzResource
command. Here is some PowerShell to get that done for you.
if ($vm.Name.Length -gt 9) {
$i = 9
} else {
$i = $vm.Name.Length - 1
}
$azResourceParams = @{
'ResourceName' = WINSRV
'ResourceType' = 'Microsoft.Compute/virtualMachines'
'ResourceGroupName' = MyTestVMs
}
$vmResource = Get-AzResource @azResourceParams
$vmId = $vmResource.Properties.VmId
$diagContainerName = ('bootdiagnostics-{0}-{1}' -f $vm.Name.ToLower().Substring(0, $i), $vmId)
Next, you’ll need the name of the resource group the boot diagnostics container is a part of.
$diagSaRg = (Get-AzStorageAccount | where { $_.StorageAccountName -eq $diagSa }).ResourceGroupName
Finally, you can now remove the storage container with the Remove-AzStorageContainer
command.
$saParams = @{
'ResourceGroupName' = $diagSaRg
'Name' = $diagSa
}
Get-AzStorageAccount @saParams | Get-AzStorageContainer | where { $_.Name-eq $diagContainerName } | Remove-AzStorageContainer -Force
One resource down! Let’s keep going and continue on how to delete an Azure virtual machine from disk.
Finally Delete an Azure VM
Next, we’ll delete an Azure VM itself. Since you’ve already captured the VM in the $vm
variable, you can pass that object to the Remove-AzVm
command and be done with it.
$null = $vm | Remove-AzVM -Force
Removing Network Interfaces and Public IP Addresses
Next up, are one or more network interfaces (NICs) that were once attached to that VM. Using the NetworkInterfaces
property on the VM object, we can loop through each ID, remove the NIC with the Remove-AzNetworkInterface
command.
While we’re in this loop, we can also check the IpConfiguration
property on each NIC to discover if that NIC has a public IP address associated with it. If so, we can remove that with the Remove-AzPublicIpAddress
command.
Below you can see, I’m looking for all NICs, removing each one, checking for public IPs on each NIC and if found, parsing the PublicIpAddress
property’s ID to get the name of the public IP address resource and remove it.
foreach($nicUri in $vm.NetworkProfile.NetworkInterfaces.Id) {
$nic = Get-AzNetworkInterface -ResourceGroupName $vm.ResourceGroupName -Name $nicUri.Split('/')[-1]
Remove-AzNetworkInterface -Name $nic.Name -ResourceGroupName $vm.ResourceGroupName -Force
foreach($ipConfig in $nic.IpConfigurations) {
if($ipConfig.PublicIpAddress -ne $null) {
Remove-AzPublicIpAddress -ResourceGroupName $vm.ResourceGroupName -Name $ipConfig.PublicIpAddress.Id.Split('/')[-1] -Force
}
}
}
Removing the OS Disk
To delete an Azure VM, the OS disk isn’t removed. The OS disk is a storage blob you can remove with the Remove-AzStorageBlob
command but first, like the other steps, you’ll have to do some searching to find the correct parameter values to pass to it.
In the below example PowerShell code snippet, I’m first finding the name of the OS disk storage container. Once I find that I’m then using that along with the storage account the OS disk storage container resides on to pass to Remove-AzStorageBlob
to get the OS disk removed.
$osDiskUri = $vm.StorageProfile.OSDisk.Vhd.Uri
$osDiskContainerName = $osDiskUri.Split('/')[-2]
$osDiskStorageAcct = Get-AzStorageAccount | where { $_.StorageAccountName -eq $osDiskUri.Split('/')[2].Split('.')[0] }
$osDiskStorageAcct | Remove-AzStorageBlob -Container $osDiskContainerName -Blob $osDiskUri.Split('/')[-1]
Removing the OS Disk Status Blob
To clean up the OS disk status blog, I need to find the storage container the OS disk is in, assume the blog itself ends in status, and then pass that to Remove-AzStorageBlob
to obliterate that blob.
$osDiskStorageAcct | Get-AzStorageBlob -Container $osDiskContainerName -Blob "$($vm.Name)*.status" | Remove-AzStorageBlob
Removing Attached Data Disks
Finally, some VMs may have data disks attached to them that you’d rather not use elsewhere. Not a problem. To delete an Azure VM properly, we can remove those too! This is the final step in deleting an Azure VM and all of its components.
First, you’ll read the Uri
property embedded deep in the StorageProfile
object on the original VM object you retrieved. Since there can be more than one data disk with a URI, you’ll loop over each of these URIs to find the storage account each one is on.
Once you’ve discovered the storage account of each one, you’ll use that and parse the storage URI to form the blob name to pass to the Remove-AzStorageBlob
command, as shown below.
if ($vm.DataDiskNames.Count -gt 0) {
foreach ($uri in $vm.StorageProfile.DataDisks.Vhd.Uri) {
$dataDiskStorageAcct = Get-AzStorageAccount -Name $uri.Split('/')[2].Split('.')[0]
$dataDiskStorageAcct | Remove-AzStorageBlob -Container $uri.Split('/')[-2] -Blob $uri.Split('/')[-1]
}
}
Summary
We’ve covered quite a bit in this article. Following best PowerShell coding practices, you could quickly build a tool from this code. Lucky for you, I’ve already done it for you! If you’d like to see an example of how this code could be implemented to delete an Azure VM, check out the Remove-AzrVirtualMachine function.