Note: I’ve moved everything to a new server running CentOS 7 and everything works without any problems with the same instructions. The RAID-5 array works on the new server without any modifications.
The hard disk in my home server had a minor hick up recently reminding me of my sloppy backup policy. The error was big enough to force me to make some changes to the server so I decided to start from scratch. The server had previously had several jobs to do, it was a router/gateway, a dhcp server, a dns server and on top of that a virtual machine host running KVM. I had already moved all services other than the VM host to another devices so getting a clean start looked like a good idea.
I decided to set up a RAID-5 array to minimise the risk of data loss because of disk problems and after a little testing I decided to use the built in RAID support in Linux, assuming that it’s more than good enough for my needs.
So for the setup, there are four disks in the machine, one SSD disk for the host OS and three 2TB SATA HDD that will form the RAID array. The SSD disk is /dev/sda
, and the disks that will build the array are /dev/sdb
, /dev/sdc
and /dev/sdd
and the RAID array will be named /dev/md0
. I will use these device names below, make sure you always substitute them with the correct devices for your setup.
After installing the host OS I started on the RAID. I found several sites and pages with information about how to build a RAID-5 array but no two of them seemed to have the same information so this became a trial and error solution for me, I’m not going to write up all the test I did, only what finally worked. Almost all of it came from this forum thread so most of the credit must go to the user “Nathan” – I’m not registered on this forum so I have no further information about him.
The first step is to create a partition table and one partition on each drive:
1 2 3 4 5 |
parted /dev/sdb (parted) mklabel New disk label type? gpt Warning: The existing disk label on /dev/sdb will be destroyed and all data on this disk will be lost. Do you want to continue? Yes/No? yes |
Now to create a partition, first take a look at the disk to get some information about it:
1 2 3 4 5 6 7 |
(parted) p Model: ATA ST2000DM001-1CH1 (scsi) Disk /dev/sdb: 2000GB Sector size (logical/physical): 512B/4096B Partition Table: gpt Number Start End Size File system Name Flags |
With the size information I then create the partition, I name the partitions according to which disk they are on, part1 on sdb, part2 on sdc and part3 on sdd:
1 2 3 4 5 |
(parted) mkpart Partition name? []? part1 File system type? [ext2]? ext4 Start? 0GB End? 2000GB |
Finally set the raid array flag on the partition, note that the “1” in the command is the partition number, it should always be 1 but you can check by printing the information about the device:
1 2 3 4 5 6 7 8 9 |
(parted) set 1 raid on (parted) p MModel: ATA ST2000DM001-1CH1 (scsi) Disk /dev/sdd: 2000GB Sector size (logical/physical): 512B/4096B Partition Table: gpt Number Start End Size File system Name Flags 1 1049kB 2000GB 2000GB part1 raid |
Now repeat this for the remaining disks, to jump to the next disk simply use select to jump to the next device and repeat the above steps for each disk:
1 |
(parted) select /dev/sdc |
After this was done I created a new RAID-5 array with mdadm
, notice the list of partitions at the end, make sure you use the partitions and not the devices and that they match yours:
1 2 3 4 5 6 7 8 9 |
# mdadm --create --verbose /dev/md0 --level=5 --raid-devices=3 /dev/sdb1 /dev/sdc1 /dev/sdd1 mdadm: layout defaults to left-symmetric mdadm: layout defaults to left-symmetric mdadm: chunk size defaults to 512K mdadm: size set to 1953382912K Continue creating array? y mdadm: Defaulting to version 1.2 metadata mdadm: array /dev/md0 started. # |
Now it may seem that the RAID array is ready but in fact it has only just started. To see how much remains try entering
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# mdadm --detail /dev/md0 /dev/md0: Version : 1.2 Creation Time : Sat May 3 20:58:14 2014 Raid Level : raid5 Array Size : 3906765824 (3725.78 GiB 4000.53 GB) Used Dev Size : 1953382912 (1862.89 GiB 2000.26 GB) Raid Devices : 3 Total Devices : 3 Persistence : Superblock is persistent Update Time : Sat May 3 21:23:14 2014 State : clean, degraded, recovering Active Devices : 2 Working Devices : 3 Failed Devices : 0 Spare Devices : 1 Layout : left-symmetric Chunk Size : 512K Rebuild Status : 8% complete Name : atlas.home:0 (local to host atlas.home) UUID : 18ef3e2a:e5fec71f:0a442b90:4faeb812 Events : 10 Number Major Minor RaidDevice State 0 8 16 0 active sync /dev/sdb 1 8 32 1 active sync /dev/sdc 3 8 48 2 spare rebuilding /dev/sdd |
The “Rebuild Status” line tells you how much of the array building is done. You’ll have to wait until this is at 100% before you can create a partition and format it. You have to run that command over and over until the rebuild is done or you can use a different method that helps you watch the rebuild:
1 |
# watch cat /proc/mdstat |
This polls the rebuild process every two seconds and gives you an estimated remaining time as well
1 2 3 4 5 6 7 8 |
Every 2.0s: cat /proc/mdstat Personalities : [raid6] [raid5] [raid4] md0 : active raid5 sdd[3] sdc[1] sdb[0] 3906765824 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/2] [UU_] [===>.................] recovery = 15.7% (308459520/1953382912) finish=278.8min speed=98308K/sec unused devices: <none> |
Once the RAID array is ready the next step is to create a partition and format it. Start parted up again and create a partition table:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# parted /dev/md0 GNU Parted 2.1 Using /dev/md0 Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) p Error: /dev/md0: unrecognised disk label (parted) mklabel New disk label type? gpt (parted) p Model: Unknown (unknown) Disk /dev/md0: 4001GB Sector size (logical/physical): 512B/4096B Partition Table: gpt Number Start End Size File system Name Flags |
The next step is to initialise the disk for the logical volume manager (LVM). First create the physical volume with pvcreate
, then create the volume group with vgcreate
and then take a look at the volume group with vgdisplay
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# pvcreate /dev/md0 Physical volume "/dev/md0" successfully created # vgcreate lvm-raid /dev/md0 Volume group "lvm-raid" successfully created # vgdisplay lvm-raid --- Volume group --- VG Name lvm-raid System ID Format lvm2 Metadata Areas 1 Metadata Sequence No 1 VG Access read/write VG Status resizable MAX LV 0 Cur LV 0 Open LV 0 Max PV 0 Cur PV 1 Act PV 1 VG Size 3.64 TiB PE Size 4.00 MiB Total PE 953799 Alloc PE / Size 0 / 0 Free PE / Size 953799 / 3.64 TiB VG UUID mAgkTz-sbWA-02ie-1jWD-SvfJ-t6ar-NJCgaW |
The important information here is the “Free PE / Size”, that’s what we’ll use when creating the logical volume. After that we view the volume information.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# lvcreate -l 953799 lvm-raid -n lvm0 Logical volume "lvm0" created # lvdisplay /dev/lvm-raid/lvm0 --- Logical volume --- LV Path /dev/lvm-raid/lvm0 LV Name lvm0 VG Name lvm-raid LV UUID OwAnBI-yYTL-9knN-aaog-hpj9-8foT-mGyifc LV Write Access read/write LV Creation host, time host.example.com, 2014-05-04 20:59:59 +0200 LV Status available # open 0 LV Size 3.64 TiB Current LE 953799 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 4096 Block device 253:0 |
Now to format the newly created logical volume, this will take a while:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# mkfs.ext4 /dev/lvm-raid/lvm0 mke2fs 1.41.12 (17-May-2010) Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) Stride=128 blocks, Stripe width=256 blocks 244178944 inodes, 976690176 blocks 48834508 blocks (5.00%) reserved for the super user First data block=0 Maximum filesystem blocks=4294967296 29807 block groups 32768 blocks per group, 32768 fragments per group 8192 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968, 102400000, 214990848, 512000000, 550731776, 644972544 Writing inode tables: done Creating journal (32768 blocks): done Writing superblocks and filesystem accounting information: done This filesystem will be automatically checked every 20 mounts or 180 days, whichever comes first. Use tune2fs -c or -i to override. |
This next step is to write the raid information to the config file. It’s not strictly necessary but may help if the server is having some problems with the raid arrays or if you are running the md monitoring service you can store your e-mail address here for notification mails (see here).
1 |
# mdadm --detail --scan > /etc/mdadm.conf |
Now try to mount the new volume somewhere. I want to mount it to a directory called data
in the root. So the first thing to do is to create the directory and then mount the device manually to that directory:
1 2 |
# mkdir /data # mount -t ext4 /dev/lvm-raid/lvm0 /data |
This gave me no errors so I umount it again so I can try mounting it with fstab:
1 |
# umount /dev/lvm-raid/lvm0 |
To do so I add this line to /etc/fstab
:
1 |
/dev/lvm-raid/lvm0 /data ext4 defaults 0 0 |
and then mount it with mount -a
and voila, the new RAID-5 array up and running and accessible. I have some more work to do before I can start running virtual machines from the RAID but the most difficult job is done.