Introduction
I am using a dedicated root server from hetzner.com which has two 512 GB NVMe SSDs. On each drive are three partitions for swap, /boot and / (everything else). These drives are using software RAID 1 with mdadm for all three partitions. Thereby I have three partitions usable:
- swap or /dev/md0
- /boot or /dev/md1
- / or /dev/md2
Since the swap partition is 32 GiB in size and I am running out of storage space, I want to disable swap, remove its partition and add the space to the /dev/md2 partition. The tricky part is that my system is already in use and contains data that I do not want to lose. So the repartitioning has to be done kind of in place. This tutorial shows how to do exactly that.
Note: This tutorial has been tested on Alma Linux (pretty close to CentOS) but it should work for many other distributions since it mostly uses Linux standard tools.
Overview
Before:
RAID 1 md0 for SWAP |
RAID 1 md1 for /boot |
RAID 1 md2 for / |
|
---|---|---|---|
Disk 1nvme0n1 |
disk 1 partition 1nvme0n1p1 |
disk 1 partition 2nvme0n1p2 |
disk 1 partition 3nvme0n1p3 |
Disk 2nvme1n1 |
disk 2 partition 1nvme1n1p1 |
disk 2 partition 2nvme1n1p2 |
disk 2 partition 3nvme1n1p3 |
In steps 1 and 2 SWAP is disabled and the associated partition is removed:
RAID 1 md1 for /boot |
RAID 1 md2 for / |
||
---|---|---|---|
Disk 1nvme0n1 |
unused storage space | disk 1 partition 2nvme0n1p2 |
disk 1 partition 3nvme0n1p3 |
Disk 2nvme1n1 |
unused storage space | disk 2 partition 2nvme1n1p2 |
disk 2 partition 3nvme1n1p3 |
Step 3 explains how to move the remaining partitions to the left such that the free space is to the right of all partitions:
RAID 1 md1 for /boot |
RAID 1 md2 for / |
||
---|---|---|---|
Disk 1nvme0n1 |
disk 1 partition 2nvme0n1p2 |
disk 1 partition 3nvme0n1p3 |
unused storage space |
Disk 2nvme1n1 |
disk 2 partition 2nvme1n1p2 |
disk 2 partition 3nvme1n1p3 |
unused storage space |
In step 4, the partition md2
is then enlarged such that the free space gained is utilized:
RAID 1 md1 for /boot |
RAID 1 md2 (enlarged)for / |
|
---|---|---|
Disk 1nvme0n1 |
disk 1 partition 2nvme0n1p2 |
disk 1 partition 3 (enlarged)nvme0n1p3 |
Disk 2nvme1n1 |
disk 2 partition 2nvme1n1p2 |
disk 2 partition 3 (enlarged)nvme1n1p3 |
Terminology
- disk is used as a general term for a single SSD or HDD
- disk partition is used to separate normal partitions on a single disk from RAID partitions
Preparation: gather information about disks and partitions
There are several commands to show information like name, size, UUID, start sector, end sector etc. for each partition and disk. These are:
fdisk -l
shows size in bytes and sectors as well as the location of each (RAID and disk) partition on the physical diskblkid
lists disks and partitions together with their UUIDslsblk
shows a hierarchical view of disk and RAID partitions with size, type and mount pointdf -h
OS perspective on the partitions with total, free and used space for each partition
These might be helpful to show an intermediate state to visually approve the success of an operation and for debugging purposes.
Step 1 - Disable swap
Swap space is storage space that is used to extend your system memory. In my case I have enough system memory but not enough storage space. There are many discussions about the question if swap space is still reasonable with modern SSDs at all. I will not focus on that.
To temporarily disable swap, execute:
swapoff -a
You can use htop (if installed) to show the swap space size at the top, right below the memory usage.
To permanently disable swap, comment the line in /etc/fstab that includes "swap" like so:
proc /proc proc defaults 0 0
# /dev/md/0
#UUID=38c56f99-6dd4-43e2-801c-xxxxxxxxxxxx none swap sw 0 0
# /dev/md/1
UUID=8a084a81-e20b-4239-a8ef-xxxxxxxxxxxx /boot ext3 defaults 0 0
# /dev/md/2
UUID=85f9f200-0ade-42de-9eac-xxxxxxxxxxxx / ext4 defaults 0 0
This will prevent the system to mount the swap partition on the following startups. You could also remove the line but in general it is a good idea to keep things and just disable them. Think of it as a way back if something breaks.
Now reboot to test if it works and to prepare for the next step.
Step 2 - Remove the swap partition
To prepare the next steps you should read out the contents of the file /proc/mdstat which will be changed by the following step.
cat /proc/mdstat
At first, you should disable the RAID array for this partition (if your swap does not use RAID, just skip this):
umount /dev/md0
mdadm --stop /dev/md0
mdadm --remove /dev/md0
Note: The last command might fail but this is ok. It is just for backwards compatibility.
Then you should remove the superblocks on the partitions of each disk (this is still for RAID). To get a list of the disk partitions of the RAID partition, have a look at the previously read contents of /proc/mdstat.
My disk partitions of /dev/md0 are /dev/nvme0n1p1 and /dev/nvme1n1p1.
Then execute the following for all disk partitions (space separated):
mdadm --zero-superblock /dev/nvme0n1p1 /dev/nvme1n1p1
Then remove the disk partition(s) with fdisk and the disk name using
fdisk /dev/nvme0n1
Note: this is not the partition name but the disk name of the before used partitions.
Then enter d
to delete a partition. It will ask for the partition number which is 1 in my case. Enter it and your partition will be deleted.
To approve the changes enter w
.
Repeat this step for every disk if you are using RAID.
Note: I am not sure why but I had to comment the line regarding /dev/md0 in /etc/mdadm.conf to really disable RAID for this partition.
The disk space that was used by the swap partitions is now free. In step 3, you can move the remaining partitions on the disk to the left.
md0 for SWAP |
RAID 1 md1 for /boot |
RAID 1 md2 for / |
|
---|---|---|---|
Disk 1nvme0n1 |
availablenvme0n1p1 |
disk 1 partition 2nvme0n1p2 |
disk 1 partition 3nvme0n1p3 |
Disk 2nvme1n1 |
availablenvme1n1p1 |
disk 2 partition 2nvme1n1p2 |
disk 2 partition 3nvme1n1p3 |
Step 3 - Move the other RAID partitions
Now we will treat the tricky part. You should (or even must) use a separate operating system which does not use the partitions you want to move. I used the rescue system which is booted via network and can be configured using the Hetzner administration page of the server.
To move a partition to the left (meaning to the beginning of the disk) type:
echo '-32G,' | sfdisk --move-data /dev/nvme0n1 -N 2
32G
means move the partition 32 GiB to the left (minus is left, plus would be right). The -N 2
stands for partition number 2.
To enlarge a RAID partition in step 4, all disk partitions (on all disks of the RAID array) must be moved such that the free space is directly to the right of the partition to be enlarged. To do this, this step 3 can be repeated for all these disk partitions.
The remaining disk partitions are then on the left of the disk. Next, you can change the disk end point of the partitions next to the available space as explained in step 4. In my case, those are the disk partitions nvme0n1p3
and nvme1n1p3
. Afterwards, we also have to change the size of their RAID partition md2
.
RAID 1 md1 for /boot |
RAID 1 md2 for / |
||
---|---|---|---|
Disk 1nvme0n1 |
disk 1 partition 2nvme0n1p2 |
disk 1 partition 3nvme0n1p3 |
available |
Disk 2nvme1n1 |
disk 2 partition 2nvme1n1p2 |
disk 2 partition 3nvme1n1p3 |
available |
Step 4 - Resize RAID partition
To resize the RAID partition, you need to do the following three steps. A reboot after each step is recommended or even mandatory.
Step 4.1 - Resize the disk partitions
Use parted for resizing (just enter parted
, it will start the interactive tool). There you need to select the correct disk using e.g. select /dev/nvme0n1
.
Then you can show all the partitions and free spaces on the disk with print free
. resizepart
will ask for the partition number and the desired size of the partition.
Again, repeat this for every disk in your RAID array.
Step 4.2 - Resize the RAID partition
This is not an alternative step for step 4.1, it is additional!
You now need to tell mdadm to use more space of the disk partitions for its RAID partition. I my case I want to resize /dev/md2 to 485210 MiB.
mdadm --grow --size=485210M /dev/md2
Step 4.3 - Expand the filesystem
As you might have seen, df -h
still shows the old size. To fix that we have to do one last step:
Finally use resize2fs -p /dev/md2
to enlarge the filesystem to the new size of /dev/md2.
Conclusion
If you call df -h
(again), you should see that the partition you wanted to enlarge (/dev/md2 in my case) is actually bigger than before. Mission accomplished!