How do I Reduce OS disk Size

Colby Ralston 40 Reputation points
2023-08-10T20:41:22.28+00:00

Hello, I am waiting on a reply specifically from @kobulloc-MSFT I am wanting to know how to reduce the size of an azure OS drive on an already created, or newly created VM

Azure VMware Solution
Azure VMware Solution
An Azure service that runs native VMware workloads on Azure.
359 questions
Azure
Azure
A cloud computing platform and infrastructure for building, deploying and managing applications and services through a worldwide network of Microsoft-managed datacenters.
1,011 questions
{count} votes

1 answer

Sort by: Most helpful
  1. kobulloc-MSFT 26,351 Reputation points Microsoft Employee
    2023-08-15T01:18:28.8833333+00:00

    Hello, @Colby Ralston !

    How do I decrease the size of my VM's OS disk?

    Officially, decreasing the size of an existing OS disk on a VM is not supported (however you can decrease the size of a data disk):

    https://learn.microsoft.com/en-us/azure/virtual-machines/windows/expand-os-disk

    Shrinking an existing disk isn’t supported and may result in data loss.

    Having said that, if you are properly motivated and don't mind "voiding the warranty" on your virtual machine, there are a couple resources that you would want to look at that guide you through this process: A blog on jrudlin.github.io and an old Azure DevBlog on which the newer solution is based.

    Shrink an Azure VMs OS Managed Disk using PowerShell can be found on Rudlintech here:

    https://jrudlin.github.io/2019-08-27-shrink-azure-vm-osdisk/

    The Azure DevBlog is no longer available but still commonly referenced when answering this question. It was originally posted on January 26th, 2018 by Mike Lapierre (who appears to currently match this profile). Here it is as captured by the Internet Archive on May 17th, 2020.


    In this post, App Dev Manager Mike Lapierre walks us through how to shrink an Azure managed disk.


    Managed disks offer several benefits but are priced differently than their non-managed counterpart. With non-managed disks, even though you create a 128GB disk like several Azure gallery images do, you are just charged for the bytes you use (i.e. pages with data). For example, the standard Windows Server 2016 images uses roughly 13GB, so you’ll be charged for that size. Managed disks sizes are priced by tiers, so currently you’ll be charged at the S10/P10 (128GB) tier while the image would fit in a S4/P4 (32GB) or a S6/P6 (64GB) tier. Though you can easily increase the size of a managed disk from the portal, you cannot shrink it easily. Let’s look at how to shrink managed disks and get the most out of your Azure spend.

    The steps to accomplish this are:

    1. Choose the best disk size
    2. Shrink the partition size in the VM
    3. Export the managed disk to a VHD
    4. Shrink the exported VHD
    5. Create a new managed disk from the VHD
    6. Create a new VM from the new managed disk
    7. Optionally cleanup the old resources

    Let’s now go into the steps in details:

    1. Choose the best disk size

    Since disk sizes are charged to the rounded up nearest size, you should pick the best size accordingly. For example, if you choose 35GB, you’ll be charged for 64GB. Refer to this table for more details.

    2. Shrink the partition size in the VM

    One simple PowerShell to run inside the VM while it’s running (adjust the size accordingly):

    Resize-Partition -DiskNumber 0 -PartitionNumber 1 -Size 32GB
    

    3. Export the managed disk to a VHD

    Make sure the VM is deallocated, and then run the following commands (adjust variables accordingly):

    #Provide the subscription Id of the subscription where snapshot is created
    $subscriptionId = "yourSubscriptionId"
    #Provide the name of your resource group where snapshot is created
    $resourceGroupName ="yourResourceGroupName"
    #Provide the managed disk name
    $managedDiskName = "yourManagedDiskName" 
    #Provide Shared Access Signature (SAS) expiry duration in seconds e.g. 3600.
    $sasExpiryDuration = "3600"
    #Provide storage account name where you want to copy the snapshot. 
    $storageAccountName = "yourstorageaccountName"
    #Name of the storage container where the downloaded snapshot will be stored
    $storageContainerName = "yourstoragecontainername"
    #Provide the key of the storage account where you want to copy snapshot. 
    $storageAccountKey = "yourStorageAccountKey"
    #Provide the name of the VHD file to which snapshot will be copied.
    $destinationVHDFileName = "yourvhdfilename"
    #Logs in to the Azure Account
    Login-AzureRmAccount
    #Set the context to the subscription Id where Snapshot is created
    Select-AzureRmSubscription -SubscriptionId $SubscriptionId
    #Generate the SAS for the managed disk
    $sas = Grant-AzureRmDiskAccess -ResourceGroupName $resourceGroupName -DiskName $managedDiskName -Access Read -DurationInSecond $sasExpiryDuration
    #Create the context for the storage account which will be used to copy snapshot to the storage account 
    $destinationContext = New-AzureStorageContext –StorageAccountName $storageAccountName -StorageAccountKey $storageAccountKey
    #Copy the snapshot to the storage account and wait for it to complete
    Start-AzureStorageBlobCopy -AbsoluteUri $sas.AccessSAS -DestContainer $storageContainerName -DestContext $destinationContext -DestBlob $destinationVHDFileName
    while(($state = Get-AzureStorageBlobCopyState -Context $destinationContext -Blob $destinationVHDFileName -Container $storageContainerName).Status -ne "Success") { $state; Start-Sleep -Seconds 5 }
    $state 
    

    4. Shrink the exported VHD

    This is a tough one, it’s basically not supported to shrink a VHD on Azure. I always thrive to do things in the most efficient way possible. Knowing that Azure uses fixed size VHDs and that resizing them is basically moving around a 512-bytes footer, it does not make sense to me to move around several GBs of data. When looking around, I found WindowsAzureDiskResizer, a tool built in 2013 by Maarten Balliauw that does just this. The tool is efficient since it just rewrites the footer at the end of blob. Although it worked fine for me, I must point out Maarten’s disclaimer:

    Big disclaimer: use the provided code on your own risk! I’m not responsible if something breaks! The provided code is as-is without warranty! I have tested this on a couple of data disks without any problems. I’ve tested this on OS disks and this sometimes works, sometimes fails. Be warned.

    Though it might seem frightening, keep in mind the whole process described here is non-destructive since we haven’t touched the original VM other than shrinking the partition size, which can easily be undone. We are building a new VM with a new managed disk, so you can always go back to the original one.

    That being said, the first version of the tool posted above did not support shrinking, so I forked the repo, updated the dependencies to the latest versions and created a new release for convenience. Again, Maarten’s disclaimer still applies here.

    Before using the tool, run the following commands in the same context as the previous step to get the full blob URI including a shared access signature:

    $StartTime = Get-Date
    $EndTime = $startTime.AddSeconds($sasExpiryDuration)
    New-AzureStorageBlobSASToken -Context $destinationContext -Blob $destinationVHDFileName -Container $storageContainerName -Permission rwd -StartTime $StartTime -ExpiryTime $EndTime -FullUri 
    

    The tool accepts two arguments, the size in GB and the full blob URI as returned by the commands above. For example:

    WindowsAzureDiskResizer.exe 32 “https://storageaccount.blob.core.windows.net/vhds/smalldisk.vhd?<SAS>”

    If you’re still not comfortable using the tool, you can always go the long way and download the whole virtual disk to a machine with Hyper-V client tools installed, use the edit disk feature or the Resize-VHD cmdlet to shrink the virtual disk and reupload it to Azure. Note that you might have to convert back and forth from the VHD and VHDX formats (Azure only supports VHD at this time).

    5. Create a new managed disk from the VHD

    No matter the technique used, your smaller VHD should now be uploaded to Azure. To create a new managed disk, run the following commands in the same context as previous steps (adjust variables accordingly):

    #Provide the name of the Managed Disk
    $diskName = "newManagedDiskName"
    #Provide the size of the disks in GB. It should be greater than the VHD file size.
    $diskSize = "sizeInGB"
    #Provide the storage type for the Managed Disk. PremiumLRS or StandardLRS.
    $accountType = "StandardLRS or PremiumLRS"
    $vhdUri = "https://$storageAccountName.blob.core.windows.net/$storageContainerName/$destinationVHDFileName"
    $ressourceGroup = Get-AzureRmResourceGroup $resourceGroupName
    $diskConfig = New-AzureRmDiskConfig -AccountType $accountType -Location $ressourceGroup.Location -DiskSizeGB $diskSize -SourceUri $vhdUri -CreateOption Import
    #Create Managed disk
    $disk = New-AzureRmDisk -DiskName $diskName -Disk $diskConfig -ResourceGroupName $resourceGroupName 
    

    6. Create a new VM from the new managed disk

    There’s several ways to accomplish this one, you could use PowerShell or an ARM template for example. Whatever option you choose, you need to use “Attach” option for the OS Disk rather than the “FromImage” option. This will create a specialized VM, in other words, the VM is not expected to be generalized (or sysprep’d). Note there’s a little caveat: the computer name will remain empty in the Azure portal, since it’s currently only appears for generalized VMs. Here’s a PowerShell sample you could use, it must be run in the same context as previous steps (adjust variables accordingly):

    #Provide the name of an existing virtual network where virtual machine will be created
    $virtualNetworkName = "yourVirtualNetworkName"
    #Provide the name of the virtual machine
    $virtualMachineName = "yourVirtualMachineName"
    #Provide the size of the virtual machine
    #e.g. Standard_DS3
    #Get all the vm sizes in a region using below script:
    #e.g. Get-AzureRmVMSize -Location westus
    $virtualMachineSize = "Standard_DS1"
    #Initialize virtual machine configuration
    $VirtualMachine = New-AzureRmVMConfig -VMName $virtualMachineName -VMSize $virtualMachineSize
    #Use the Managed Disk Resource Id to attach it to the virtual machine. Please change the OS type to linux if OS disk has linux OS
    $VirtualMachine = Set-AzureRmVMOSDisk -VM $VirtualMachine -ManagedDiskId $disk.Id -CreateOption Attach -Windows
    #Create a public IP for the VM
    $publicIp = New-AzureRmPublicIpAddress -Name ($VirtualMachineName.ToLower()+'_ip') -ResourceGroupName $resourceGroupName -Location $ressourceGroup.Location -AllocationMethod Dynamic
    #Get the virtual network where virtual machine will be hosted
    $vnet = Get-AzureRmVirtualNetwork -Name $virtualNetworkName -ResourceGroupName $resourceGroupName
    # Create NIC in the first subnet of the virtual network 
    $nic = New-AzureRmNetworkInterface -Name ($VirtualMachineName.ToLower()+'_nic') -ResourceGroupName $resourceGroupName -Location $ressourceGroup.Location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $publicIp.Id
    $VirtualMachine = Add-AzureRmVMNetworkInterface -VM $VirtualMachine -Id $nic.Id
    #Create the virtual machine with Managed Disk
    New-AzureRmVM -VM $VirtualMachine -ResourceGroupName $resourceGroupName -Location $ressourceGroup.Location 
    

    7. Optionally cleanup the old resources

    You should now have a fully functional VM with a shrunken managed disk. If not, remember you can always go back to the original VM. Once you are satisfied with your new VM, you could choose to cleanup the old resources like the VM, it’s managed disk, network interface, etc. Obviously, once you’ve deleted the original resources, there’s no going back. You can also delete the temporary VHD used to create the new managed disk. Note that if you do, you won’t be able to reattach the same managed disk to another VM since the source VHD is required when the VM is created.

    So those are the steps to shrink a managed disk. Most of these scripts are based on this repo, so check it out for more samples. When creating brand new VMs, we are now seeing images offering smaller sizes by default like the one labelled “[smalldisk] Windows Server 2016 Datacenter”. If such an image does not exist currently, you could build one yourself. Since the VM would be generalized, you would not run into the computer name caveat discussed at step #6.

    Hope it helps!

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.