Autoresize EBS root volume on Linux-based Amazon AMIs
I can’t increase the size of my EBS root volume when I launch a new Debian instance!
Setting a larger than default (8GiB) root EBS device, when launching Debian AMIs, does not result in a similarly sized root filesystem.
In this article we are investigating why this doesn’t work out of the box, and how to create new AMIs that will be resized correctly after launch.
Example:
You want to launch a new Debian instance with the root device on Amazon EBS.
So you select an appropriate root EBS AMI, for example: Debian-jessie
In the “Add Storage” step, change the default size from 8 GiB to something larger; 33 GiB in this example:
After the instance has come up, ssh using your keypair1 and your root filesystem is still showing 8GiB:
admin@ip-172-31-2-65:~$ df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 7.8G 641M 6.8G 9% /
Where did my space go?
Digging a bit deeper with lsblk, we can see:
admin@ip-172-31-2-65:~$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 33G 0 disk └─xvda1 202:1 0 8G 0 part /
The Amazon EBS disk (/dev/xvda) presented to the OS has the right size: 33G
However the partition where the OS resides (/dev/xvda1) is stuck at 8G.
Linux AMIs come preinstalled with a customized version of the cloud-init package. This includes Python modules that can resize partitions and filesystems, if CLI tools like growpart and gpart are present. On standard Debian AMIs, they aren’t there.
CentOS AMIs/EPEL in comparison have the cloud-utils-growpart rpm package available providing the growpart tool.
cloud-init tools will also detect if the root file system (/) size differs from the partition size and utilize the appropriate filesystem expansion tool (e.g. resize2fs
for ext4) to match the partition size.
Resizing an online partition on a linux AMI
Naturally we would like our AMIs to resize the root partition by themselves, to use all available space.
Since growpart is not available in Debian AMIs, we can accomplish this with parted and an init script that runs on the first boot (when the instance gets launched).
Making parted work non-interactively
One challenge here is that most tools will complain about resizing the partition containing a mounted [root] file system.
The version of parted shipped with Debian jessie allows us to grow a partition interactively and -- albeit not so well documented -- non interactively as well.
Normally, a command like this would suffice, but because the partition is in use, parted prompts for confirmation which would interrupt the flow in a script:
root@ip-172-31-2-65:~# /sbin/parted /dev/xvda resizepart 1 100% Warning: Partition /dev/xvda1 is being used. Are you sure you want to continue? /sbin/parted: invalid token: 100% Yes/No?
Luckily parted has an undocumented cli parameter that allows us force grow the partition without prompts:
root@ip-172-31-2-65:~# /sbin/parted ---pretend-input-tty /dev/xvda resizepart 1 yes 100% Warning: Partition /dev/xvda1 is being used. Are you sure you want to continue? Information: You may need to update /etc/fstab.
The output may not be very encouraging, but it worked:
root@ip-172-31-2-65:~# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 33G 0 disk └─xvda1 202:1 0 33G 0 part /
The only thing remaining is to resize the filesystem. This will be done automatically by the cloud-init tools after a reboot or by running resize2fs /dev/xvda1
Putting it all together
If you are building your own custom AMI, it makes sense to add an init script that does the above steps immediately after a new instance gets launched and ensures it won’t rerun itself again.
An important requirement is to have parted installed; you can either do that inside the script or ensure parted gets preinstalled as part of the scripts building your custom AMI.
For Debian AMIs running the following script will create an init script linked to /etc/rc5.d/S05ami-resizerootpart.sh, that will take care of all the resizing. As the last step it will deactivate itself and report activities under /var/log/resizerrootfs.log
Are other AMIs affected by this problem?
Yes! CentOS6 AMIs are affected. Instead of parted though -- which is an old version that can’t resize online partitions -- make sure growpart is installed from the package cloud-utils-growpart. This package is part of the EPEL6 repo. The resize command is:
/usr/bin/growpart /dev/xdva 1
Finally SLES11.x AMIs seem to suffer from the same issue.
Conclusion
Some Linux AMIs will fail to utilize the whole EBS volume size you've chosen when you launch them!
If you have been bitten by this issue, I'd love to hear about it and whether the ideas presented here were of help.
A few tips to keep in mind:
- Use packer.io to build your custom AMIs.
- Prefer growpart if it is available in your target distribution as it was built precisely for that purpose.
- The cloud changes all the time and AMIs are no exception! The above issues may go away with newer releases.
Script for Debian AMIs
#!/bin/bash # Run this to create init script for Debian 8 AMIs that autoresizes the root EBS partition ROOTDEV="xvda" ROOTPART="xvda1" rootdevsize=$(blockdev --getsize /dev/${ROOTDEV}) rootpartsize=$(blockdev --getsize /dev/${ROOTPART}) if ! grep -q ${ROOTPART} /proc/partitions then # EBS volume is unpartitioned ... no work for us exit 0 fi source /etc/os-release if [ $VERSION_ID -gt 8 ] then # Exclude future Debian AMIs that hopefully will have this fixed exit 0 fi cat >/etc/init.d/ami-resizerootpart.sh <<'EOF' #! /bin/sh ### BEGIN INIT INFO # Provides: ami-resizerootpart # Required-Start: $local_fs $syslog # Required-Stop: # Should-Start: # Default-Start: 2 3 4 5 # Default-Stop: # Short-Description: Resize root partition on AWS if it smaller than the size of the device # Description: When using the Debian 8 AWS AMIs with root EBS fs, EBS is partitioned. # As a result, when launching a new instance with a larger than default # root EBS size, /dev/xvda has desired size but not /dev/xvda1 root # partition. # /etc/init.d/ami-resizerootpart detects this discrepancy and resizes # the partition, triggering a reboot and fsck. cloud-init will resize the # fs by itself after the reboot. ### END INIT INFO . /lib/init/vars.sh . /lib/init/mount-functions.sh . /lib/lsb/init-functions PATH=/sbin:/bin:/usr/sbin:/usr/bin do_start() { ROOTDEV="xvda" ROOTPART="xvda1" LOGFILE="/var/log/resizerootfs.log" rootdevsize=$(blockdev --getsize /dev/${ROOTDEV}) rootpartsize=$(blockdev --getsize /dev/${ROOTPART}) if ! grep -q ${ROOTPART} /proc/partitions then # EBS volume is unpartitioned ... no work for us echo "Unpartitioned EBS volume no need to run" >>$LOGFILE return 0 fi # Check if raw EBS device and partition differ by more than 10MB if [ ! $(($rootdevsize-$rootpartsize)) -ge 10485760 ] then # No need to resize echo "EBS partition is <=10MB of the device size; no need to act" >>$LOGFILE return 0 fi # Resize root partition /sbin/parted ---pretend-input-tty /dev/${ROOTDEV} resizepart 1 yes 100% if [ ! $? -eq 0 ] then echo "Resize failed" >>$LOGFILE return 0 fi echo "Successfully resized rootfs!" >>$LOGFILE # Force fsck on next reboot /usr/bin/touch /forcefsck # Disable myself job done rm /etc/rc5.d/S05ami-resizerootpart.sh sync reboot } case "$1" in start|"") do_start ;; stop|status) # No-op ;; *) echo "Usage: ami-resizerootpart.sh [start|stop]" >&2 exit 3 ;; esac EOF chmod 755 /etc/init.d/ami-resizerootpart.sh chown root:root /etc/init.d/ami-resizerootpart.sh ln -s /etc/init.d/ami-resizerootpart.sh /etc/rc5.d/S05ami-resizerootpart.sh
1. ssh as admin
on Debian AMIs. Back to text