Shrink EBS Root

This post was published 1 year, 4 months ago. Due to the rapidly evolving world of technology, some concepts may no longer be applicable.

My EC2 instances are setup to have only the operating system and program files on the root volume, with all other data (logs, mail, etc.) on a second EBS volume. This leads to a very stable root volume, which sees a minimum of changes. Fully configured, my root volume (using Amazon’s Linux) is 1.2GB. The default size of the root volume is 8GB. Given the above, it serves little purpose for me to have so much space allocated to my root volume, and unused. I opted to shrink my root volume to 4GB, and my in future reduce this even more.

Before proceeding, it is worth noting that Amazon’s Linux uses ext4 as its root filesystem. Ext2 and ext3 root file systems can be resized in the same way, however other file systems require a different procedure.

  1. Snapshot root volumeThis step is done either as a backup or to create a temporary EBS volume containing the data we will copy to the new, smaller, volume.
  2. Create a new (empty) EBS volume of the target sizeThis will become our new root volume – so, in my case, I created a 4GB EBS volume (it should be in the same availaility zone as the instance you want to attach it to)
  3. Prepare your original root volumeEither:
    • Stop (not terminate) the instance it is attached to, and detach the volume OR
    • Create a new EBS volume using the snapshot created earlier
  4. Attach the volumes from the previous 2 steps to an instance
    While you can attach them to the original instance, these volumes should not be mounted (only attached)
    In the examples below, /dev/xvda1 refers to the original root volume, and /dev/xvdg refers to the new volume.
  5. Run a file system check on the original volume (or volume derived from snapshot)
    e2fsck -f /dev/xvda1
  6. Copy the data to the new volume
    • Option 1: Use rsync
      Format the new volume: mkfs.ext4 /dev/xvdg
      Mount the two volumes, and use rsync -aHAXxSP /source /target

      • The ‘a’ option (archive) is recursive, copies symlinks, preserves permissions, times, groups, owners, device files, and special files
      • the ‘H’ option copies hardlinks
      • the ‘A’ option copies ACLs
      • the ‘X’ option copies extended attributes
      • the ‘x’ option don’t cross file system boundaries
      • the ‘S’ option handle sparse files efficiently
      • the ‘P’ option displays progress

       

    • Option 2: Use dd
      1. Resize the file system of the original volume to its minimum size
        Since this is an ext4 file system, we use resize2fs

        • the ‘M’ option shrinks to the minimum size
        • the ‘p’ option displays progress
        resize2fs -M -p /dev/xvda1

        The above command will output the new file system size. For instance:

        "Resizing the filesystem on /dev/xvda1 to 319011 (4k) blocks.
      2. Calculate the number of chunks
        The filesystem sits at the start of the partition, and is continuous – the size corresponds to output of resize2fs from above. We want to copy everything from the start to that point.

        Since EBS usage charges for I/O, we want to use a somewhat large chunk size – I used 16MB.

        blocks*4/(chunk_size_in_mb*1024) – round up a bit for safety (I ended up with 78 blocks, which I rounded to 80)

      3. Perform the actual copy of data
        dd bs=16M if=/dev/xvda1 of=/dev/xvdg count=80

        Note: dd uses ‘M’ as 1048576B and ‘MB’ as 1000000B

      4. Resize the file system on the new volume to its maximum size
        resize2fs -p /dev/xvdg
  7. Check the new file system for consistency
    e2fsck -f /dev/xvdg
  8. Now that the data has been copied over and everything checked. We can replace our root volume on the target instance.
    If the target instance is running, stop (not terminate) it
    If you haven’t already, detach the root volume from the target instance.
    Attach the new EBS volume to the target instance as /dev/sda1You can determine the root device by running:

    ec2-describe-instance-attribute `curl http://169.254.169.254/latest/meta-data/instance-id -s` --root-device-name

Start your instance and run df -h to verify the size of your root volume.

8 thoughts on “Shrink EBS Root

  1. Yeah… doesn’t work for more recent ubuntu. Just detaching the old and attaching the new root as per above fails. From the system log, printed though the management console:

    Begin: Running /scripts/init-premount ... done.
    Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done.
    Gave up waiting for root device.  Common problems:
     - Boot args (cat /proc/cmdline)
       - Check rootdelay= (did the system wait long enough?)
       - Check root= (did the system wait for the right device?)
     - Missing modules (cat /proc/modules; ls /dev)
    ALERT!  /dev/disk/by-label/uec-rootfs does not exist.  Dropping to a shell!
    • Thanks for the feedback. I don’t work much with Ubuntu, so its always good to hear how things work on it (and I am a fan of Alestic too, so I’ll certainly check it out).

  2. Thank you. Worked well on RHEL 5.4. Only the -M is not supported in that version of “resize2fs”. Simply had to give it a minimum size at the end. e.g. “resize2fs -p /dev/xvda1 8G”

    • Good to know you found it useful – it isn’t uncommon for the tools on various systems to differ in the parameters they accept, but it can definitely make things annoying at times.

  3. This worked perfectly. I shrank the EBS volume of my Ubuntu 12.04 x64 instance from 8GB to 4GB successfully. I used the “dd” option instead of rsync. Thank you.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>