Ubuntu – How to reduce AWS EBS root volume size

amazon ec2amazon-ebsUbuntu

Enlarging an EC2 instance is easy like a breath (for instance, create an AMI, launch an instance from it and then change the storage size).

But reducing it becomes more difficult. I’d like to reduce an Amazon Web Services (AWS) EC2 instance Elastic Block Store (EBS) root volume size. There are a couples of old high level procedures on the net. The more detailed version I found is a one year old answer on a StackOverflow question: how to can i reduce my ebs volume capacity, steps have a pretty high level:

Create a new EBS volume that is the desired size (e.g. /dev/xvdg)

Launch an instance, and attach both EBS volumes to it

Check the file system (of the original root volume): (e.g.) e2fsck -f /dev/xvda1

Maximally shrink the original root volume: (e.g. ext2/3/4) resize2fs -M -p /dev/xvda1

Copy the data over with dd:

  • Choose a chunk size (I like 16MB)

  • Calculate the number of chunks (using the number of blocks from the resize2fs output): blocks*4/(chunk_size_in_mb*1024) – round up a bit for safety

  • Copy the data: (e.g.) dd if=/dev/xvda1 ibs=16M of=/dev/xvdg obs=16M count=80

Resize the filesystem on the new (smaller) EBS volume: (e.g.) resize2fs -p /dev/xvdg

Check the file system (of the original root volume): (e.g.) e2fsck -f /dev/xvdg

Detach your new EBS root volume, and attach it to your original instance

I’m unable to find a detailed step by step “how to” solution.

My EBS root volume is attached to a HVM Ubuntu instance.

Any help would be really appreciated.

Best Answer

None of the other solutions will work if the volume is used as a root (bootable) device.

The newly created disk is missing the boot partition, so it would need to have GRUB installed and some flags set up correctly before an instance can use it as a root volume.

My (as of today, working) solution for shrinking a root volume is:

Background: We have an instance A, whose root volume we want to shrink. Let's call this volume VA. We want to shrink VA from 30GB to let's say 10GB

  1. Create a new ec2 instance, B, with the same OS as the instance A. Also kernels must match so upgrade or downgrade as needed. As storage, pick a volume that's the same type as VA, but with a size of 10GB. (or whatever your target size is). So now we have an instance B which uses this new volume (let's call it VB) as a root volume.
  2. Once the new instance (B) is running. Stop it and detach it's root volume (VB).

NOTE: The following steps are mostly taken from @bill 's solution:

  1. Stop the instance you want to resize (A).

  2. Create a snapshot of the volume VA and then create a "General Purpose SSD" volume from that snapshot. This volume we'll call it VASNAP.

  3. Spin a new instance with amazon Linux, we'll call this instance C. We will just use this instance to copy the contents of VASNAP to VB. We could probably also use instance A to do these steps, but I prefer to do it in an independent machine.

  4. Attach the following volumes to instance C. /dev/xvdf for VB. /dev/xvdg for VASNAP.

  5. Reboot instance C.

  6. Log onto instance C via SSH.

  7. Create these new directories:

mkdir /source /target

  1. Format VB's main partition with an ext4 filesystem:

mkfs.ext4 /dev/xvdf1

If you get no errors, proceed to Step 11. Otherwise, if you do not have /dev/xvdf1, you need to create the partition by doing the following i-vii:

i) If /dev/xvdf1 does not exist for whatever reason, you need to create it. First enter:

sudo fdisk /dev/xvdf.

ii) Wipe disk by entering: wipefs

iii) Create a new partition by entering: n

iv) Enter p to create primary partition

v) Keep pressing enter to continue with default settings.

vi) When it asks for a command again, enter w to write changes and quit.

vii) Verify you have the /dev/xvdf1 partition by doing: lsblk

You should see something like:

NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  250G  0 disk
└─xvda1 202:1    0  250G  0 part
xvdf    202:80   0   80G  0 disk
└─xvdf1 202:81   0   80G  0 part 
xvdg    202:96   0  250G  0 disk
└─xvdg1 202:97   0  250G  0 part

Now proceed to Step 11.

  1. Mount it to this directory:

mount -t ext4 /dev/xvdf1 /target

  1. This is very important, the file system needs an e2label for Linux to recognize it and boot it, use "e2label /dev/xvda1" on an active instance to see what it should be, in this case the label is: "/"

e2label /dev/xvdf1 /

  1. Mount VASNAP on /source:

mount -t ext4 /dev/xvdg1 /source

  1. Copy the contents:

rsync -vaxSHAX /source/ /target

Note: there is no "/" following "/target". Also, there may be a few errors about symlinks and attrs, but the resize was still successful

  1. Umount VB:

umount /target

  1. Back in AWS Console: Dettach VB from instance C, and also dettach VA from A.

  2. Attach the new sized volume (VB) to the instance as: "/dev/xvda"

  3. Boot instance A, now it's root device is 10GB :)

  4. Delete both instances B and C, and also all volumes but VB, which is now instance A's root volume.

Related Topic