How to shrink VMDK with a couple of PowerShell scripts?

While extending a VMDK file is a fairly easy task that can be performed right in Disk Manager, shrinking a virtual disk is a bit tricky. And, you need to be really careful because unless done properly, reducing virtual disk size may cause data loss! Sure, you can just use VMware Converter to make a VMDK smaller, but, for my money, it is always better to have a script at hand. In this article, I’ll discuss how to shrink virtual disks with 2 simple PowerShell scripts.

How to shrink virtual disks with 2 simple PowerShell scripts

 

Let’s take a closer look at the whole process of shrinking VMDKs

To understand better the whole magic behind reducing VMDK size, let’s discuss what a virtual disk is. *.vmdk file is just an abstraction existing between hardware and a VM. Neither VM nor physical datastore cares that much about what’s going on inside that entity, meaning that they exist in different layers. I think that the image below perfectly reflects the whole concept of virtual disks. To learn more about virtual disk types, check out my previous article that discusses each of them in detail.

Concept of virtual disks

 

Let me explain now why one needs resizing virtual disks. Until you run out of the free space on the datastore or have to migrate a VM with a huge VMDK quickly, everything is just fine and you do not care how big a virtual disk is. At some point, to utilize the storage efficiently, one may naturally consider using a thin provisioned virtual device… but that thing bloats up at the end of the day, and the worst thing is that it doesn’t become any smaller even after you delete some data from it. And, that’s actually why you need to reduce VMDK size somehow.

What’s the catch with resizing a VMDK? By playing around with the disk size, you may corrupt the data as VM is not aware of those manipulations. Maybe, that’s why there’s no way to shrink the device in VM Disk Management.

To reduce VMDK size, it may be smart to resize the partition, separating the occupied disk volume from the free volume. Next, you need to “cut off” the free space to shrink VMDK such that no data will be lost. This being said, the process can be formally split into 2 subtasks:

  1. Resizing partition on the guest OS level.
  2. Shrinking the VMDK itself.

For each step, you need a PowerShell script. I discuss them later.

Now, as I’m getting closer to the main part, I’d like to mention requirements for shrinking the disk. You need your PowerShell version to be 5.11 or higher and PowerCLI version needs to be 11.0.0 or higher. You also need a VMware vCenter Server instance; otherwise, you won’t be able to run the commands. Additionally, you need an extra datastore on the ESXi host where your VM is running. Note that it should have enough space to be used as temporary storage for copying the resized VMDK. .

DISCLAIMER: If you mess things up that’s not my fault. The scripts I mentioned here worked for me, but none of them grants your data safety and VM stability if you do something wrong. So, always keep a copy of your disk before reducing its size as you can screw things up fairly easily.

Script one: How to resize the partition

Well, any script like that can be transformed into one that works on Linux. Today, though, I have a Windows VMs that’s why I present PowerShell scripts here. Now, I’d like to discuss some things about starting the script for resizing partitions.

1.The script is executed remotely so it can be run on several VMs simultaneously.

2. To run the script, use the following flags:

  1. VMIP – IP of the VM that has its VMDK disk shrunk.
  2. VMUser –VM administrator account.

3. Start the script as administrator on the local PowerShell instance.

Here’s the command to start the script:

VMUser "Administrator"

Unless the VM is running, you’ll get the warning and script will be stopped. To restart the script, switch on the VM and start the script again.

Next, enter the credentials and connect to the remote PowerShell session.

Enter the credentials and connect to the remote PowerShell session

After authorizing, select the disk (F, in my case). You can exit the script by typing Exit.

Exit the script by typing Exit

Here’s the screenshot from the VM Disk Management. I strongly recommend closing Disk Management to avoid any errors during shrinking (that’s one of those annoying Windows bugs).

 VM Disk Management

Next, see whether you have selected the right disk. Pay attention to the minimum and maximum partition size. Here, the partition size matches the maximum disk volume. Now, let’s shrink it! Enter the new partition size (4096 MB, let’s say).

Enter the new partition size

If the process has run smoothly, there will be an output saying that everything is fine. In the output, you can find the new partition size and recommendations for running the next script.

Find the new partition size and recommendations for running the next script

Jot down these numbers from the output. You will need them to shrink VMDK. Also, I strongly recommend adding some more space to the disk (512-1024 MB) to avoid any data loss due to errors that may occur while shrinking the disk.

Now, go to Disk Management and see whether the changes were applied. One more time, if you don’t close the Disk Management window before running the script, you will end up with an error. No worries, if you did encounter one, just close the Disk Management window and open it once again.

Go to Disk Management and check the changes

In this case, I freed 11GB on the disk by shrinking the partition and separating the volume taken by data from the free volume.

Below, you can find the script itself. To run it, copy the script on your PC and save it as Resize-Partition.ps1.

Resize-Partition.ps1

Well, here’s how you resize partition. Now, let’s see how to shrink a VMDK itself!

Script two: How to shrink VMDK

Before I move any further, I’d like to recommend you to switch off the VM strongly. Be careful while entering script parameters as there’s a good risk of data loss.

Now, when the VM is turned off, it may be interesting to read more about how my shrinking script works.

How VMDK shrinking works in a nutshell

1. Copying the VMDK header file to the local directory (the path is picked automatically). Note that there’s always a backup in the Backup directory. It’s going to be called like Backup-yyyyMMddhhmmss-diskname.vmdk, so it’s fairly easy to find it. VMDK header file remains in the Backup folder, and it will be automatically replaced if you try shrinking the VMDK with the same name. The backup is done automatically before running the script. If the script has run smoothly, don’t forget to remove the file manually.

2. Changing the RW variable. This variable represents the disk size that can be derived using this formula: RW = Disk volume (GB)*1024*1024*1024/512. By altering RW value, you return the header file back to the source VM directory.

3. Moving the disk to the temporary datastore and back to the source VM directory. These operations allow the host to separate the fraction of disk volume occupied with data from the free volume using PowerCLI commands.

4. Re-registering the VM in the vCenter inventory have the changes applied.

How I run the script

Now, I’m going to tell you more about the operations that you need to do before running the script. You should start the script remotely from a PC. Here are the prerequisites for running it:

  • You need a vCenter instance (i.e., ESXi host with a vCenter VM)
  • One more datastore on the same ESXi host. You need it to keep the file temporarily during migration.
  • The VM should have no snapshots
  • The VM should be switched off
  • There should be no changes in VM configuration since running the Resize-Partition.ps.1 script.

If you fail to meet any of those prerequisites, the script stops.

So, what is this script for? It allows shrinking a VMDK device such that data won’t be lost. The new size should lay between the partition size that you have entered before and the maximum volume of the initial VMDK. Although the script doesn’t limit the maximum volume, you need to keep in mind that you cannot set the infinitely large disk size. If the input value exceeds the maximum disk size, data on that disks will be corrupted. Anyway, since this article is about shrinking a VMDK file, pay attention rather to the minimum volume that you can set (i.e., minimum partition size).

Here are the parameters that you need to enter to run the script:

  • vCSAIP – IP of vCenter Server instance that can be used to manage the guest ESXi host
  • vCSAUser – vCenter Server account ([email protected])
  • VMName – How is the VM called in vCenter
  • TmpDS – The name of the temporary datastore for copying the VMDK

Run the script as administrator using a local PowerShell instance. Here’s how starting the script looks like:

Run the script as administrator

Enter vCenter Server user password once you start the script.

vCenter Server user password

Next, the script checks whether all the prerequisites for its start are met. If everything is fine, you will be asked to select a VMDK disk.

The script checks whether all the prerequisites

Confirm the disk selection and agree that you still want to run the script regardless of the risk of data loss. One more time, unless the new disk capacity exceeds the maximum allocated capacity, everything should be fine. This being said, type Y and enter the new VMDK volume. Anyway, if you do not want to continue, you can go back to disk selection by typing Exit.

Confirm the disk selection

If everything has run smoothly, here’s the output you’ll get.

Output

Now, go to the VM Disk Management to see whether the changes have been applied.

VM Disk Management

Well, that’s it! The disk became smaller and its content is absolutely OK. If you followed my recommendation and allocated some extra disk space while shrinking the VMDK file, you can expand the partition size later. Run Resize-Partition.ps1 one more time and set the maximum disk size for the desired partition value. Alternatively, you can just press Extend volume… in VM Disk Management and go through the wizard steps..

And, eventually, here comes the script itself.

Resize-VMDK.ps1

Conclusion

Well, that’s how you shrink VMDKs! The way I discuss here is not a universal solution, so if there are any ideas on how to make those two scripts better, I am happy to discuss them in comments! Feel free to fine-tune the scripts for your daily needs. One more time: Be careful while playing around with disk volume as you may corrupt data fairly easy.