Modify and remove Azure VMs using PowerShell

Using PowerShell, engineers and IT administrators successfully automate various tasks when working not only with on-premises, but also with cloud infrastructures, in particular, with Azure. Working through PowerShell in some cases is much more convenient and faster than through the Azure portal. Thanks to its cross-platform capabilities, PowerShell can be used for any OS.

It doesn’t matter if you work with Ubuntu, Red Hat or Windows – PowerShell will help control cloud resources. Using module Azure PowerShell, for example, you can set any properties of virtual machines.

In this article, we will look at how you can use PowerShell to resize VMs in the Azure cloud, and also to remove VMs and its associated objects.



Important! Do not forget wipe your hands with a sanitizer prepare for work:

  • You will need a module Azure PowerShell Module – it can be downloaded from PowerShell Gallery with the command Install-Module Az.
  • You need to authenticate in the Azure cloud, where the virtual machine is spinning by running the command Connect-AzAccount.

First, create a script that resizes Azure VM. Open VS Code and save a new PowerShell script called Resize-AzVirtualMachine.ps1 – we will add pieces of code to it as we go through the example.

We request the available VM sizes

Before changing the size of the VM, you need to find out what sizes are generally acceptable for virtual machines in the Azure cloud. To do this, run the command Get-AzVMSize.

So for the virtual machine devvm01 from the resource group dev we request all sorts of permissible sizes:

Get-AzVMSize -ResourceGroupName dev -VMName devvm01

(In real tasks, of course, instead of ResourceGroupName = dev and VMName = devvm01 you will indicate your values ​​for these parameters.)

The command will return approximately the following list:

These are all possible size options that can be set for this virtual machine.

Resize car

For example, we will resize to a new size Standard_B1ls – He comes first on the list above. (In actual tasks, of course, you choose any size you need.)

  1. Using command first Get-AzVM we get information about our object (virtual machine), storing them in a variable $virtualMachine:
    $virtualMachine = Get-AzVM -ResourceGroupName dev -VMName devvm01
  2. Then we take the property from this object .HardwareProfile.VmSize and set the desired new value:
    $virtualMachine.HardwareProfile.VmSize = "Standard_B1ls"
  3. And now just execute the update command of the VM – Update-AzVm:
    Update-AzVM -VM devvm01 -ResourceGroupName dev
  4. We make sure that everything went well – for this, again, we request information about our object and look at the property $virtualMachine.HardwareProfile:
    $virtualMachine = Get-AzVM -ResourceGroupName dev -VMName devvm01
    $virtualMachine.HardwareProfile

If we see there Standard_B1ls – it means everything is in order, the size of the machine has been changed. You can go further and develop success by resizing several VMs at once using an array.

What about removing VMs in Azure?

With removal, not everything is as simple and straightforward as it might seem. After all, you need to delete a number of resources associated with this machine, including:

  • Store diagnostics storage containers
  • Network interfaces
  • Public IP Addresses
  • System disk and blob where its status is stored
  • Data Disks

Therefore, we will create a function and call it Remove-AzrVirtualMachine – and it will delete not only Azure VM, but all of the above.

We follow the standard path and first we get our object (VM) using the command Get-AzVm. For example, let it be a car WINSRV19 from the resource group MyTestVMs.

Save this object with all its properties in a variable $vm:

$vm = Get-AzVm -Name WINSRV19 -ResourceGroupName MyTestVMs

Delete the container with boot diagnostic files

When creating a VM in Azure, the user is also prompted to create a container for storing boot diagnostics (boot diagnostics container), so that if there are problems with the boot, there is something to turn to for troubleshooting. However, when the VM is removed, this container remains to continue its now purposeless existence. Correct this situation.

  1. First, find out to which storage account this container belongs – for this we need to find the property storageUri in the bowels of the object DiagnosticsProfile our VM. For this, I use this regular expression:
    $diagSa = [regex]::match($vm.DiagnosticsProfile.bootDiagnostics.storageUri, '^http[s]?://(.+?)\.').groups[1].value
  2. Now you need to find out the name of the container, and for this you need to get the VM ID using the command Get-AzResource:
    
    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)
    
  3. Next, we get the name of the resource group to which the container belongs:
    $diagSaRg = (Get-AzStorageAccount | where { $_.StorageAccountName -eq $diagSa }).ResourceGroupName
  4. And now we have everything we need to remove the container with the command Remove-AzStorageContainer:
    $saParams = @{
        'ResourceGroupName' = $diagSaRg
        'Name' = $diagSa
    }
     
    Get-AzStorageAccount @saParams | Get-AzStorageContainer | where { $_.Name-eq $diagContainerName } | Remove-AzStorageContainer -Force

Delete VM

Now we will delete the virtual machine itself, fortunately we have already created a variable $vm for the corresponding object. Well, run the command Remove-AzVm:

$null = $vm | Remove-AzVM -Force

Delete the network interface and public IP address

Our VM has one (or even several) network interfaces (NICs) – to remove them as unnecessary, we’ll go through the property NetworkInterfaces our VM object and delete the NIC command Remove-AzNetworkInterface. In case there are more than one network interface, we use a loop. At the same time, for each NIC, we check the property IpConfiguration whether the interface has a public IP address. If one is found, delete it with the command Remove-AzPublicIpAddress.

Here is an example of just such a code, where we loop through all the NICs, delete them, check if there is a public IP. If there is, then parse the property PublicIpAddress, get the name of the corresponding resource by ID and delete it:


foreach($nicUri in $vm.NetworkProfile.NetworkInterfaces.Id) {
    $nic = Get-AzNetworkInterface -ResourceGroupName $vm.ResourceGroupName -Name $nicUri.Split("https://habr.com/")[-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("https://habr.com/")[-1] -Force
        }
    }
}

Delete the system drive

The OS disk is a blob, for the removal of which there is a command Remove-AzStorageBlob – but before you execute it, you will need to set the required values ​​for its parameters. For this, in particular, you need to get the name of the storage container containing the system disk, and then transfer it to this command along with the corresponding storage account.

$osDiskUri = $vm.StorageProfile.OSDisk.Vhd.Uri
$osDiskContainerName = $osDiskUri.Split("https://habr.com/")[-2]
$osDiskStorageAcct = Get-AzStorageAccount | where { $_.StorageAccountName -eq $osDiskUri.Split("https://habr.com/")[2].Split('.')[0] }
$osDiskStorageAcct | Remove-AzStorageBlob -Container $osDiskContainerName -Blob $osDiskUri.Split("https://habr.com/")[-1]

Delete Blob System Disk Status

To do this, as you probably already guessed, we take the storage container in which this disk is stored, and implying that the blob at the end contains status, transfer the appropriate parameters to the delete command Remove-AzStorageBlob:

$osDiskStorageAcct | Get-AzStorageBlob -Container $osDiskContainerName -Blob "$($vm.Name)*.status" | Remove-AzStorageBlob

And finally, delete data discs

Our VM could have disks with data attached to it. If they are not necessary, we will remove them too. First parsim StorageProfile our VM and find the property Uri. If there are several disks, we organize a cycle by URI. For each URI, we will find the corresponding hundred account using Get-AzStorageAccount. Then, let’s parse the storage URI to pull out the blob name you need and pass it to the delete command Remove-AzStorageBlob along with a storages account. Here’s how it would look in code:

if ($vm.DataDiskNames.Count -gt 0) {
    foreach ($uri in $vm.StorageProfile.DataDisks.Vhd.Uri) {
        $dataDiskStorageAcct = Get-AzStorageAccount -Name $uri.Split("https://habr.com/")[2].Split('.')[0]
        $dataDiskStorageAcct | Remove-AzStorageBlob -Container $uri.Split("https://habr.com/")[-2] -Blob $uri.Split("https://habr.com/")[-1]
    }
}

And so “we got to a happy ending!” Now from all these fragments it is necessary to collect a single whole. The kind author Adam Bertram went to meet the users and did it himself. Here is a link to the resulting script called Remove-AzrVirtualMachine.ps1:

Github

I hope that these practical tips come in handy to save you time, effort and money when working with Azure VMs.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *