Configuring mirror drives with mdadm

Warning: use at your own risk! This works on my configs (Ubuntu 14.04, 16 and 18) but might be different for yours. If you’re not 100% familiar with mdadm, grub and filesystems/partition tables, I would strongly advise you to do some testing on virtual machines before actually applying any of this to your running system.

Credits to (you might want to visit them):

I never go with unprotected data. Although mirror drives don’t protect from everything at all (thunder, theft, flooding, etc. including simultaneous disk failures which actually can happen since the “good” disk is always used more intensely during the recovery and is more prone to fail at that moment – not even speaking about having 2 exact identical disks which makes it more likely for both drives to fail roughly at the same time – but I’ll cover that in another post), they offer the security of not losing everything at once when a hard drive fails (and I’ve had quite a number of failures in decades of using computers…). They also save you the time of reinstalling everything, even if you have a backup of your data. So I’m configuring a linux with 2 drives, one big raid array with our partitions inside (most people create as many arrays as partitions but I prefer one single array, I will also create a raid 10 array rather than a raid 1).

Before starting anything else, make sure that you have mdadm installed on the system you wish to create the mirror for (so you should have an /etc/mdadm directory with a mdadm.conf file in it). To install it on Ubuntu, just type “apt install mdadm” in a terminal.

Before going further, run “hostname” in a terminal and write down the exact host name of the machine.

Boot on a live version of your os (the same version than your system), open a terminal.

First allow all apps to connect to the UI (otherwise on Ubuntu, as soon as you sudo bash, all graphical tools are not available anymore):

xhost +local:

switch to root:

sudo bash

Before doing anything else, ensure that you run with the host name you have previously noted:

hostname your_hostname

Also edit /etc/hostname and /etc/hosts to switch the machine name to your hostname.

Then make sure mdadm is installed and working:

apt install mdadm

Mdadm uses the hostname to generate its arrays. Edit /etc/mdadm/mdadm.conf and set the following line:

HOMEHOST your_hostname

You can create an array on a raw disk (/dev/sdb for instance) but I recommend to create it on a partition instead, since I’ve run into some instabilities when using the full disk (plus you really need 2 exact same disks for that, and you may not have that).

Open gparted and create a partition (/dev/sdb1 here) on the disk you want to create the array on (it will be /dev/sdb here). I recommend to leave something like 16Mb at the beginning and end of the disk (for grub and the mdadm metadata). If you chose gpt as the partition table, you will have to create a small partition (a few Mb) labelled “bios-grub” at the beginning of the drive (before your main partition, let’s say you created it second, it will be /dev/sdb2). Close gparted for now.

Create the new raid array on the newly created partition of the second disk (I’m creating a raid 10 array here, you could as well create a raid 1 array if you want a simple mirror, but I’m leaving options to add other disks later):

mdadm --create /dev/md/your_hostname:root --metadata=1.0 -l10 -pn2 -c512 -n2 missing /dev/sdb1

Explanation of the command:

  • – -create : create a new array.
  • /dev/md/<host>:<array> : do not use /dev/md0 directly otherwise mdadm will fail to create /dev/md/0 later. It will generate an array, very probably /dev/md127 if you don’t have any other arrays on your system but the number may vary – it should not be relied on!
  • – -metadata=1.0 : very important if you want to be able to boot from your array, it tells mdadm to create an array whose metadata is located at the end of your disks (this is why we left some empty space with gparted), otherwise grub will interfere (and has bugs) with the metadata if it’s located at the beginning of the disk.
  • -l10 : level 10 array.
  • -pn2 : indicates that we have 2 disks of same geometry here.
  • -c512 : the chunk size for the array.
  • -n2 : 2 disks for now.
  • missing : tells that the first disk is currently missing, we’ll add it later.
  • /dev/sdb1 : that’s the new partition on the drive we want to create our array on for now, which has the advantage of leaving our data on /dev/sda untouched until we have a working system.

You may want to edit the /etc/mdadm/mdadm.conf file to add this new array in it, you can generate it with /usr/share/mdadm/mkconf and/or create it manually, the declaration of the array looks like:

ARRAY /dev/md/<hostname>:<arrayname> metadata=1.0 UUID=<uuid> name=<hostname>:<arrayname>

Note the declaration as <hostname>:<arrayname> otherwise you’ll get into trouble later (in this example, I chose “root” as arrayname, but it is up to you to chose your favorite name that will not interfere with another existing array on the machine).

Now check the array with the command:

mdadm --examine --scan

If the array was not started automatically after creation, launch:

mdadm --assemble /dev/md/your_hostname:root

Launch gparted and do the following actions with it. The array /dev/md127 (or another number between 125 and 127, let’s keep 127 for now) should appear in gparted. Create a partition table on it (Device->Create Partition Table). If needed, shrink your partitions on /dev/sda so that you leave a few Mb at the beginning and at the end of your partition (note that if your second disk is smaller than the first, then you really want to shrink your partitions so that they can fit on the second disk). This is to ensure that either the raid array’s metadata and grub’s metadata won’t interfere with your partitions. Now copy-paste /dev/sda1 to /dev/md/<hostname>:<arrayname> (and remember to leave a couple of Mb at the beginning). Do the same for any number of partitions you want to get from sda (but not swap). If you use swap partitions, create a swap partition on /dev/md127. Don’t forget to set the “boot” flag on the new boot partition you created if you’re on a msdos partition table (it is not needed if on gpt).

You can also do it from the command line after resizing the partitions on sda with gparted, and change the UUID of the copied partition:

sfdisk -d /dev/sda >partition_table
sfdisk /dev/md127 <partition_table
dd if=/dev/sda1 of=/dev/md127p1 bs=1M
uuidgen --> this will show a brand new UUID which you can copy in the next command
tune2fs /dev/md127p1 -U <uuid>
mkswap /dev/md127p5

Mount /dev/md127p1 on /mnt as well as any other partitions you have (such as /home, /var…).

Now time to reflect these changes into /etc/fstab by changing the uuids and devices there to /dev/mdxpx devices (they are currently pointed to sdax, we want them to point to md127px). Including your swap partition which should be now /dev/md127p5 for instance.

Time to configure grub now. So we will mount /mnt as our root (as it will be when we reboot) but we also need any other partitions mounted (such as /home, /var or /usr if you chose to make separate partitions for these) including special directories:

mount --bind /dev /mnt/dev
mount --bind /dev/pts /mnt/dev/pts
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys

A one-liner for this is also (you can also do it in a for loop, but it’s not like there’s a 100 of them…):

mount -t proc none /mnt/proc && mount -t sysfs none /mnt/sys && mount -t devtmpfs none /mnt/dev

And now let’s switch to our new root filesystem:

chroot /mnt

Make sure that initramfs has the correct modules (this has made me gone mad for hours): edit /etc/initramfs-tools/modules and add there (or simply uncomment) raid10 or raid1 depending on your config.

Edit /etc/grub.d/10_linux and set quick-boot=”0″ instead of 1 to fix a bug in grub upon booting (an annoying bug “Diskfilter writes are not supported” error that was introduced recently in grub – see https://bugzilla.redhat.com/show_bug.cgi?id=606481 ).

Create the mdadm.conf file:

/usr/share/mdadm/mkconf >/etc/mdadm/mdadm.conf

Make sure that the file is generated correctly and open it. Fill in your hostname again in the homehost line and make sure the array is prefixed with the hostname in its path (NOT ONLY the name option).

Run this to make sure mdadm uses your current mdadm.conf file (and update grub):

dpkg-reconfigure mdadm

Let’s generate a boot image for our new system (the first one shouldn’t be needed since it’s run by the previous command):

update-initramfs -c -k all
grub-mkconfig>/boot/grub/grub.cfg
grub-install --recheck --modules=mdraid1x /dev/<your_new_disk>

These commands may return some errors (like a missing drive) but that’s just because one drive is indeed missing (sda is not in the array yet) and Ubuntu doesn’t like to have its own live boot system in sometimes.

Reboot from the new drive in the bios and cross your fingers, normally you’ll boot from the array.

Once you have rebooted, you can check that by simply doing a “df” and check that the line associated with the mount point “/” is indeed something like /dev/md127 rather than /dev/sda.

Open gparted, delete your sda partition. Create a partition sda1 for the RAID array the exact same size as the one you created on sdb (I again recommend leaving some space on the disk before and after that partition). If you’re using gpt, create a bios_grub partition of a few MB at the beginning of the drive.

Before adding sda to the mirror, be sure you have some time ahead of you when you do that since the syncing process generally called “resilvering” can take a long time and the machine SHOULD NOT REBOOT until it is finished (this is absolutely critical).

Add /dev/sda1:

mdadm /dev/md127 -a /dev/sda1

You can watch the process using:

watch cat /proc/mdstat

It should show lines like:

...
State : clean, degraded, recovering
...
 Rebuild Status : 95% complete
...
 2 8 33 0 spare rebuilding /dev/sda1
...

Once the array has finished rebuilding, you’re good to continue!

Reinstall grub on sda since it needs to take into account the new changes:

 grub-install --recheck --modules=mdraid1x /dev/sda

You should make sure that your machine is now booting on either disk by disabling the disks and booting on only one disk. Otherwise the whole purpose of an array is beaten in the first place!

Once the drive is configured, watch its state with:

sudo mdadm --detail /dev/md127

Leave a comment