Shrink/Reduce Your Windows AMI’s in AWS

September 27, 2018

no comments

Introduction


A few days ago I came across the following question from one of my clients:

“As a part of our CI/CD process we use AWS AMI’s to provision servers dynamically to run our tests. However we realize that some of those AMI’s are larger than we need, causing unnecessary expenses and increasing the provisioning time. How can we reduce the existent AMI’s sizes?”

 

The Problem


  • Larger AMI’s volumes sizes
  • Production AMI’S used in several production processes
  • Create new AMI’s from scratch is not an option

 

The Solution


  • Create an EC2 instance from the AMI (the target instance)
  • Create an EC2 Linux instance (the worker instance)
  • Stop the target instance and detach its volume
  • Attach the volume to the worker instance
  • Shrink the volume using the worker instance
  • Create a smaller volume and attach it to the worker instance
  • Copy the shrinked volume into the smaller one
  • Detach the smaller volume from the worker instance and attach it to the target one
  • Create a new AMI from the target instance

 

The Details


 

Create an EC2 instance from the AMI (the target instance)

I will create an instance from my image “DevOps-2016-With-X-Dynamic-CI” (to reduce it from 160 GB to 65 GB):

Image 1

 

Note that the current size of the volume is 160 GB:

Image 2

 

Check that the instance was created successfully and it’s up and running:

Image 3

 

 

Create an EC2 Linux instance (the worker instance) in the same region that the target instance

Then we need to create the “worker instance” to shrink the target volume (I will use the Centos7 public AMI for this purpose):

Image 4

 

Ensure the working instance is created in the same region that the target instance:

Image 5

 

Check that the instance was created successfully and it’s up and running:

Image 6

 

After create the instance we need to install some stuff to be used later, connect to the worker instance and run the following:

sudo yum update -y
sudo yum install -y epel-release
sudo yum install ntfs-3g -y
sudo yum install ntfsprogs -y
sudo yum install vim -y

 

 

Stop the target instance and detach its volume

Stop the target instance from the instance view:

Image 7

 

Then detach its volume from the volumes view:

Image 8

 

Attach the volume to the worker instance

From the volumes view attach the target volume to the worker instance as /dev/xvdf:

Image 9

 

 

Shrink the volume using the worker instance

Now we have the target volume attached to the worker instance, let’s shrink it by running the commands below from the working instance.

 

Dump current source disk partition info to a file:

sudo sfdisk -d /dev/xvdf > sfdisk-d.xvdf

 

Find out the minimum size the filesystem can be reduced to:

sudo ntfsresize --info /dev/xvdf1

 

In my case “49536 MB”:

ntfsresize v2017.3.23 (libntfs-3g)
Device name        : /dev/xvdf1
NTFS volume version: 3.1
Cluster size       : 4096 bytes
Current volume size: 171795542528 bytes (171796 MB)
Current device size: 171795546112 bytes (171796 MB)
Checking filesystem consistency ...
100.00 percent completed
Accounting clusters ...
Space in use       : 49536 MB (28.8%)
Collecting resizing constraints ...
You might resize at 49535586304 bytes or 49536 MB (freeing 122260 MB).
Please make a test run using both the -n and -s options before real resizing!
[centos@ip-172-31-36-71 ~]$ ntfsresize
ntfsresize v2017.3.23 (libntfs-3g)

 

Resize the filesystem to the suggested 49536 MB:

sudo ntfsresize -s 49536M /dev/xvdf1 -f

 

 

Create a smaller volume and attach it to the worker instance

Let’s create a new smaller volume (in the same region) to store our final volume (in my case I want I final size of 65 GB):

Image 10

 

Then attach it to the worker instance as /dev/xvdg:

Image 11

 

 

Copy the shrinked volume into the smaller one

Let’s copy the content of the shrinked volume into the smaller one by run the command below

NOTE: The count parameter must be the suggested size + 1 (in my case 49536 + 1, namely 49537)
NOTE: Depending on the size it can take a while

sudo dd bs=1M if=/dev/xvdf of=/dev/xvdg count=49537

 

Next we need to update the partition, for this let’s first of all calculate the new size in sectors by run:
(In my case 49536 * 2048, that is to say 101449728)

echo $((<SuggestedSize>*2048)) 

 

Now dump the new target disk xvdg partition info to a file by run:

sudo sfdisk -d /dev/xvdg > sfdisk-d.xvdg

 

Then update the /de/xvdg1 size to the new size in sectors (101449728 in my case) by using vim:

vim sfdisk-d.xvdg

 

Before:

# partition table of /dev/xvdg
unit: sectors

/dev/xvdg1 : start=     2048, size=335538176, Id= 7, bootable
/dev/xvdg2 : start=        0, size=        0, Id= 0
/dev/xvdg3 : start=        0, size=        0, Id= 0
/dev/xvdg4 : start=        0, size=        0, Id= 0

After:

# partition table of /dev/xvdg
unit: sectors

/dev/xvdg1 : start=     2048, size=101449728, Id= 7, bootable
/dev/xvdg2 : start=        0, size=        0, Id= 0
/dev/xvdg3 : start=        0, size=        0, Id= 0
/dev/xvdg4 : start=        0, size=        0, Id= 0

 

Finally update the partition by run:

sudo sfdisk /dev/xvdg < sfdisk-d.xvdg

 

 

Detach the smaller volume from the worker instance and attach it to the target one

From the volumes page, dettach the smaller volume from the worker instance:

Image 12

 

Then attach the volume to the target instance as /dev/sda1:

Image 13

 

Finally, let’s check that everything works as expected by start the target instance:

Image 14

 

And then connect to it to inspect the disk size:

Image 15

 

As you may have noticed the size of the disk is the size of its content and not the size of the volume. So let’s extend it to the total size of the volume from the server manager by right click the volume in the volumes section:

NOTE: If it doesn’t allow you to increase the size of the volume to the maximum size (as in my case in the photo), just increase it to the maximum possible and repeat this step again.

Image 16

 

Come back to “This PC” in the file explorer and look how we achieved our goal (refresh if it’s required):

Image 17

 

Create a new AMI from the target instance

That’s it, we just have to create the new AMI from the instance (and delete the old one):

Image 18

 

Image 19

 

Conclusion


As we could see something that sounds as complicated as reducing the size of a template is not so difficult after all. Remember to delete the instances and the volumes that were left unused to avoid unexpected surprises at the end of the month 馃檪

 
 

Add comment
facebook linkedin twitter email

Leave a Reply