How to Convert EXT4 to XFS on AWS EC2 EBS Volume for Consistent Snapshots


4 views

Converting a root filesystem from EXT4 to XFS while the system is running presents unique technical constraints. The primary obstacle is that the root partition contains:

  • Running OS processes
  • Active mount points
  • Essential system daemons

Here's the step-by-step approach I've successfully used in production environments:


# 1. Create new EBS volume in the same AZ
aws ec2 create-volume --availability-zone us-east-1a --size 20 --volume-type gp3

# 2. Attach to your instance
aws ec2 attach-volume --volume-id vol-123456 --instance-id i-abcdef --device /dev/sdf

After attaching the new volume:


# Verify the disk is detected
lsblk

# Create partition table
sudo parted /dev/xvdf mklabel gpt

# Create primary partition
sudo parted -a opt /dev/xvdf mkpart primary 0% 100%

# Format as XFS
sudo mkfs.xfs /dev/xvdf1

# Create mount point and mount
sudo mkdir -p /mnt/xfs_volume
sudo mount /dev/xvdf1 /mnt/xfs_volume

For critical directories like /var/www and /var/lib/mysql:


# Use rsync for initial copy (run during low traffic)
sudo rsync -avz /var/www/ /mnt/xfs_volume/www/

# For MySQL, stop service first
sudo systemctl stop mysql
sudo rsync -avz /var/lib/mysql/ /mnt/xfs_volume/mysql/

Modify /etc/fstab to persist the mount:


# Add this line to /etc/fstab
UUID=(xfs_volume_uuid) /var/www xfs defaults,nofail 0 2

For database directories, consider symlink approach:


sudo mv /var/lib/mysql /var/lib/mysql.old
sudo ln -s /mnt/xfs_volume/mysql /var/lib/mysql

Key advantages for your backup workflow:


# Freeze filesystem before snapshot
sudo xfs_freeze -f /mnt/xfs_volume

# Create snapshot (via AWS CLI)
aws ec2 create-snapshot --volume-id vol-123456

# Unfreeze
sudo xfs_freeze -u /mnt/xfs_volume

Always test the new configuration before deleting old data:


# Create validation script
#!/bin/bash
if [ -f /var/www/index.php ]; then
    echo "Web content verified"
else
    echo "ERROR: Content missing" >&2
    exit 1
fi

When your production server runs everything on a single ext4-formatted EBS volume, converting to XFS for better snapshot consistency becomes tricky. The main obstacle is that you can't modify the root filesystem while the system is running. Here's what we're dealing with:

# Current disk layout example
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  50G  0 disk 
└─xvda1 202:1    0  50G  0 part /

Instead of attempting a risky in-place conversion, we'll implement a safer migration path:

  1. Create new EBS volumes with XFS
  2. Migrate data partitions incrementally
  3. Maintain service availability throughout

1. Preparing New XFS Volumes

First, create and attach additional EBS volumes through AWS Console or CLI:

aws ec2 create-volume --availability-zone us-east-1a \
--volume-type gp2 --size 100 --tag-specifications \
'ResourceType=volume,Tags=[{Key=Name,Value=xfs-data}]'

After attaching to your instance, initialize them:

# List available disks
lsblk

# Format as XFS (example for /dev/xvdf)
mkfs.xfs /dev/xvdf

2. Migrating /var/www

For web content that needs snapshot consistency:

# Create temporary mount point
mkdir /mnt/xfs-www

# Mount new XFS volume
mount /dev/xvdf /mnt/xfs-www

# Sync data (using rsync for integrity)
rsync -avz /var/www/ /mnt/xfs-www/

# Update fstab
echo "/dev/xvdf /var/www xfs defaults,noatime 0 2" >> /etc/fstab

# Remount to final location
umount /mnt/xfs-www
mount /var/www

3. Handling Database Migration

For MySQL data in /var/lib/mysql:

# Stop MySQL service first
service mysql stop

# Create XFS volume for database
mkfs.xfs /dev/xvdg

# Mount and transfer data
mount /dev/xvdg /mnt/xfs-mysql
rsync -avz /var/lib/mysql/ /mnt/xfs-mysql/

# Update ownership
chown -R mysql:mysql /mnt/xfs-mysql

# Update fstab and remount
echo "/dev/xvdg /var/lib/mysql xfs defaults,noatime 0 2" >> /etc/fstab
umount /mnt/xfs-mysql
mount /var/lib/mysql

# Restart MySQL
service mysql start

After completing all migrations, verify filesystem types:

df -Th | grep -E 'Filesystem|/var/www|/var/lib'

Expected output should show XFS for migrated partitions while keeping ext4 for the root filesystem.

Now with XFS volumes, you can use AWS's native snapshot capability or implement pre/post snapshot scripts:

# Example pre-snapshot script for MySQL
FLUSH TABLES WITH READ LOCK;
FLUSH LOGS;
SHOW MASTER STATUS;
\! xfs_freeze -f /var/lib/mysql

# Post-snapshot
\! xfs_freeze -u /var/lib/mysql
UNLOCK TABLES;

For larger deployments, consider automating with AWS Systems Manager:

aws ssm send-command \
--instance-ids i-1234567890abcdef0 \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["mkfs.xfs /dev/xvdf"]'

Remember to test the entire procedure in a staging environment before applying to production.