Attaching a larger EBS volume to a running EC2 instance without downtime is surprisingly straightforward once you understand the two distinct phases involved.
Here’s how it looks on a live system. Imagine we have an instance i-0123456789abcdef0 with an attached EBS volume vol-0123456789abcdef0 currently formatted with XFS and mounted at /data. We want to grow this volume from 100 GiB to 200 GiB.
First, we detach the original volume and attach a new, larger one. This is the only point where the data becomes inaccessible, and it’s typically a matter of seconds.
# Detach the old volume (replace vol-0123456789abcdef0 and the attachment name)
aws ec2 detach-volume --volume-id vol-0123456789abcdef0 --instance-id i-0123456789abcdef0 --device /dev/sdf
# Wait for detachment to complete (check console or 'aws ec2 describe-volumes')
# Create a new, larger volume (200 GiB, same AZ, same type as original)
aws ec2 create-volume --availability-zone us-east-1a --size 200 --volume-type gp3 --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=my-data-volume-resized}]'
# Note the new volume ID, let's say it's vol-abcdef01234567890
# Attach the new volume to the instance
aws ec2 attach-volume --volume-id vol-abcdef01234567890 --instance-id i-0123456789abcdef0 --device /dev/sdf
Once attached, the instance sees the new, larger block device. The magic happens next, where we tell the operating system to recognize and utilize this extra space without rebooting.
On the instance, you’ll first need to identify the new device. It will likely appear as a new block device, e.g., /dev/xvdf or /dev/nvme1n1 if using NVMe.
# List block devices to confirm the new one is visible
lsblk
You’ll see the original volume’s size and then a new, larger device. Now, we need to expand the filesystem to encompass this new space. This is a two-step process: first, extend the partition table entry, and then extend the filesystem itself.
For XFS, the process is simpler as it directly resizes the filesystem.
# For XFS, directly resize the filesystem
xfs_growfs /dev/xvdf # Or whatever your new device is
If you were using ext4, it would look like this:
# For ext4, first grow the partition (using growpart)
sudo growpart /dev/xvdf 1 # Assumes partition 1 is the one you want to grow
# Then resize the filesystem
sudo resize2fs /dev/xvdf1
The key here is that xfs_growfs and resize2fs are designed to operate on live, mounted filesystems. They don’t need the underlying block device to be "unmounted" or the filesystem to be checked offline. They work by updating the filesystem’s metadata structures to acknowledge the larger contiguous space available. The OS’s block layer handles the mapping of I/O requests to the now-larger EBS volume transparently.
The problem this solves is avoiding application downtime for storage expansion. Traditionally, growing storage meant taking an application offline, detaching the volume, resizing it (often by creating a new, larger one and copying data), reattaching, and bringing the application back up. This process can be disruptive and time-consuming for critical services.
The internal mechanism relies on the Linux kernel’s ability to dynamically update filesystem metadata and the EBS volume’s detachment/attachment API allowing for near-instantaneous replacement of the underlying block device. The OS doesn’t "know" the underlying storage device changed; it just sees a block device of a certain size. When that device’s size expands, and the filesystem metadata is updated to match, the OS can then address the larger space.
The one thing most people don’t realize is that the device name you use when attaching the volume (/dev/sdf in the example) is what the OS sees, but it’s not necessarily the persistent identifier for that volume within the OS. If the instance reboots, or if you detach and reattach the same EBS volume, the OS might assign it a different device name (e.g., /dev/sdg or /dev/nvme2n1). This is why using filesystem UUIDs or labels for mounting is crucial in /etc/fstab rather than relying on device names. When you perform the xfs_growfs or resize2fs command, you must use the current device name that the OS has assigned to the newly attached volume.
The next challenge you’ll face is ensuring your applications correctly use the expanded storage, especially if they have hardcoded paths or fixed buffer sizes.