For AWS EC2 Linux instances created from offical AWS AMI, the root EBS volume is at minimal size of 8G. Unfortunately, there is no direct way to create a smaller root EBS volume or shrink it.
Shrinking a root volume could have several benefits:
- It may save you a few penny each month,
- By mounting important directories to other volumes/partitions, you can enhance the flexibility, maintainability and security of the system setup.
When searching for available solutions, I found both Alexander Todorov and Matt Berther have provided useful tips, but following their step-by-step instructions only resulting to a unbootable EC2 instance. Luckily, Mike Oliver’s comment under Matt’s article and web_ninjia’s Q&A on StackOverflow pointed out the right direction.
Since the BIOS boot partition is required for a root EBS volume, the whole process is about to copy the entire volume data, including the MBR, partition table and BIOS boot partition, from the bigger volume to a smaller one. Detailed procedure is described below:
Take notes about the availability zone (AZ) and block device name of current root EBS volume. You can find them in the AWS Console.
Take notes about the disk usage of current root EBS volume. You can find it by SSH into your EC2 instance, then
df -h
.$ df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 7.8G 780M 6.6G 11% / ....
Backup by shutting down your EC2 instance and taking a snapshot from the current root EBS volume.
Create an EBS volume from the snapshot created in step 3, give it a name such as “source”.
Create another empty EBS volume with a smaller size, give it a name such as “target”.
Launch your instance to fully running.
Attach the source volume to
/dev/sdf
and the target volume to/dev/sdg
. In SSH terminal, their block device name will become/dev/xvdf
and/dev/xvdg
respectively.SSH into your instance, check the filesystem of source volume by
e2fsck -f /dev/xvdf1
.# e2fsck -f /dev/xvdf1 e2fsck 1.42.9 (4-Feb-2014) Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information cloudimg-rootfs: 58324/524288 files (0.2% non-contiguous), 265281/2094474 blocks
Resize the filesystem of source volume to a small size by
resize2fs -p /dev/xvdf1 SMALL-SIZE
. TheSMALL-SIZE
must be larger than the actual disk usage found in step 2.# resize2fs -p /dev/xvdf1 1024M resize2fs 1.42.9 (4-Feb-2014) Resizing the filesystem on /dev/xvdf1 to 262144 (4k) blocks. Begin pass 2 (max = 101573) Relocating blocks XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Begin pass 3 (max = 64) Scanning inode table XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Begin pass 4 (max = 7856) Updating inode references XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX The filesystem on /dev/xvdf1 is now 262144 blocks long.
Take notes about the number of 16MB blocks, by following Matt’s instruction: “The last line from the
resize2fs
command should tell you how many 4k blocks the filesystem now is. To calculate the number of 16MB blocks you need, use the following formula:blockcount * 4 / (16 * 1024)
. Round this number up to give yourself a little buffer.” (So the number of 16MB blocks is262144 * 4 / (16 * 1024) = 64
. We round it up to 70, ensuring that the MBR, partition table and BIOS boot partition in source volume could get copied in the following steps.)Resize the root partition of source volume to equal or a little bit larger than the resized filesystem, by
parted /dev/xvdf
, thenresizepart
.# parted /dev/xvdf GNU Parted 2.3 Using /dev/xvdf Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) print Model: Xen Virtual Block Device (xvd) Disk /dev/xvdf: 8590MB Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 8225kB 8587MB 8579MB primary ext4 boot (parted) resizepart Partition number? 1 Warning: Partition /dev/xvdf1 is being used. Are you sure you want to continue? Yes/No? Yes End? [8587MB]? 1056MB Warning: Shrinking a partition can cause data loss, are you sure you want to continue? Yes/No? Yes (parted) print Model: Xen Virtual Block Device (xvd) Disk /dev/xvdf: 8590MB Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 8225kB 1056MB 1048MB primary ext4 boot (parted) quit Information: You may need to update /etc/fstab.
Issue a source volume to target volume copy, by
dd bs=16M if=/dev/xvdf of=/dev/xvdg count=NUMBER-OF-16MB-BLKS
. TheNUMBER-OF-16MB-BLKS
is what we get in step 10.# dd bs=16M if=/dev/xvdf of=/dev/xvdg count=70 70+0 records in 70+0 records out 1174405120 bytes (1.2 GB) copied, 17.6647 s, 66.5 MB/s
Check the partition table and filesystem of target volume with
fdisk -l
.# fdisk -l Disk /dev/xvda: 8589 MB, 8589934592 bytes ... Device Boot Start End Blocks Id System /dev/xvda1 * 16065 16771859 8377897+ 83 Linux Disk /dev/xvdf: 8589 MB, 8589934592 bytes ... Device Boot Start End Blocks Id System /dev/xvdf1 * 16065 2062500 1023218 83 Linux Disk /dev/xvdg: 3221 MB, 3221225472 bytes ... Device Boot Start End Blocks Id System /dev/xvdg1 * 16065 2062500 1023218 83 Linux
Resize the root partition in target volume, by
parted /dev/xvdg
thenresizepart
.# parted /dev/xvdg GNU Parted 2.3 Using /dev/xvdg Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) print Model: Xen Virtual Block Device (xvd) Disk /dev/xvdg: 3221MB Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 8225kB 1056MB 1048MB primary ext4 boot (parted) resizepart Partition number? 1 End? [1056MB]? 3150MB (parted) print Model: Xen Virtual Block Device (xvd) Disk /dev/xvdg: 3221MB Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 8225kB 3150MB 3142MB primary ext4 boot (parted) quit Information: You may need to update /etc/fstab.
Resize the filesystem of target volume, by
resize2fs -p /dev/xvdg1
.# resize2fs -p /dev/xvdg1 resize2fs 1.42.9 (4-Feb-2014) Resizing the filesystem on /dev/xvdg1 to 767034 (4k) blocks. The filesystem on /dev/xvdg1 is now 767034 blocks long.
Stop your EC2 instance, detach all EBS volumes.
Attach the target volume to your EC2 instance at position
/dev/sda1
, so it becomes the root volume of your instance.Launch your instance and check if everything is working properly.
If everything goes right, remember to clean up by deleting the leftover EBS volumes, and the backup snapshot created in step 3. Also, you could create a snapshot or even your own AMI from the new smaller root volume, in case of similar situation.
As you can see, shrinking a root EBS volume for AWS EC2 Linux instances is a daunting job and consists lots of steps. My final thoughts is: When infrastructure dynamically scales up and down, could the extra layer of complexity derives from it be another problem?
What’s your idea?