Change 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. In some cases, working through PowerShell is much more convenient and faster than using the Azure portal. Thanks to cross-platform, PowerShell can be used for any OS.

Whether you're running Ubuntu, Red Hat, or Windows, PowerShell helps you control your cloud resources. Using the module Azure PowerShell, for example, you can set any properties of virtual machines.

In this article, we'll look at how you can use PowerShell to resize a VM in the Azure cloud, as well as delete a VM and its associated objects.

Change and remove Azure VMs using PowerShell

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

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

First, let's create a script that resizes the Azure VM. Open VS Code and save a new PowerShell script called Resize-AzVirtualMachine.ps1 - we will add pieces of code to it in the course of the example.

We request the available dimensions of the VM

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

So for the virtual machine devvm01 from the resource group giant we ask for all possible sizes:

Get-AzVMSize -ResourceGroupName dev -VMName devvm01

(In real problems, of course, instead of ResourceGroupName=dev ΠΈ VMName=devvm01 you will specify your own values ​​for these parameters.)

The command will return something like this:

Change and remove Azure VMs using PowerShell

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

Resize car

For example, we will resize to a new size Standard_B1ls He's number one on the list above. (In real life, of course, you pick whatever size you want.)

  1. First with the command Get-AzVM we get information about our object (virtual machine), saving it to a variable $virtualMachine:
    $virtualMachine = Get-AzVM -ResourceGroupName dev -VMName devvm01
  2. Then we take a property from this object .HardwareProfile.VmSize and set the desired new value:
    $virtualMachine.HardwareProfile.VmSize = "Standard_B1ls"
  3. And now we just execute the VM update command - Update-AzVm:
    Update-AzVM -VM devvm01 -ResourceGroupName dev
  4. We make sure that everything went well - for this we again 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 - so, everything is in order, the size of the machine has been changed. You can go further and develop success - resize several VMs at once using an array.

What about deleting a VM in Azure?

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

  • Boot 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 the Azure VM, but all of the above.

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

Let's save this object along with all its properties into a variable $vm:

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

Removing 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 in case of boot problems, there is something to turn to for troubleshooting. However, when the VM is deleted, this container remains to continue its now purposeless existence. Let's fix this situation.

  1. First, let's find out which storage account this container belongs to - for this we need to find the property storageUri in the bowels of the object DiagnosticsProfile our VM. To do this, I use the following 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 let's delete the virtual machine itself, since we have already created a variable $vm for the corresponding object. Well, let's run the command Remove-AzVm:

$null = $vm | Remove-AzVM -Force

Removing the network interface and public IP address

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

Here is an example of just such code, where we look through all NICs in a loop, delete them, and 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('/')[-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 system drive

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

$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]

Delete the Blob status of the system drive

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

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

And finally, remove the data disks

Our VM could still have disks with data that were attached to it. If they are not needed, we will remove them too. Parse first StorageProfile our VM and find the property Uri. If there are several disks, we organize a loop through URI. For each URI, find the corresponding storage account using Get-AzStorageAccount. Then we parse the storage URI to extract the desired blob name and pass it to the delete command Remove-AzStorageBlob along with a storage 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('/')[2].Split('.')[0]
        $dataDiskStorageAcct | Remove-AzStorageBlob -Container $uri.Split('/')[-2] -Blob $uri.Split('/')[-1]
    }
}

And now β€œwe got to the happy ending!” Now from all these fragments it is necessary to assemble a single whole. Good author Adam Bertram went to meet users and did it himself. Here is a link to the final script called Remove-AzrVirtualMachine.ps1:

β†’ GitHub

I hope you find these practical tips helpful in helping you save time, effort, and money when working with Azure VMs.

Source: habr.com

Add a comment