Software RAID 1 (mirroring) na linuksie (mdadm)!

  • Posted on: 14 February 2006
  • By: robson

Dla kogo jest ten HOW-TO? Dla osób, które pierwszy raz chcą postawić Software RAID 1 (mirroring) na linuksie, oraz dla osób, które już to robiły, ale po zainstalowaniu nowych pakietów Raidtools2 ku swojemu przerażeniu nie znalazły polecenia mkraid.

Czym jest Raid 1 (mirroring)? W wielkim skrócie - jest to technika zapisywania danych na dwa dyski jednocześnie. Partycje wraz z danymi na obu dyskach są dla siebie jakby lustrzanymi odbiciami. W razie awarii jednego z dysków system może pracować dalej bez utraty danych. W takim wypadku wystarczy wymienić uszkodzony dysk i odbudować dane na nowym.

Jaka jest różnica między hardware RAID a software RAID? Przede wszystkim w cenie. Do software RAID-a nie musimy kupować dodatkowego sprzętu oprócz dysków, natomiast hardware RAID wymaga specjalnego kontrolera (więcej informacji, ceny itp. można uzyskać w linkach Google po lewej stronie). Poza tym hardware RAID w znacznie mniejszym stopniu obciąża procesor serwera.

Obecne dystrybucje linuksa (np. Debian 3.1) umożliwiają konfigurację software raid-u podczas instalacji systemu, ale tu zajmiemy się instalacją raid-u na gotowym, już istniejącym systemie.

Sponsor:

Co będzie potrzebne? Dwa dyski twarde, najlepiej identyczne, odpowiednio przygotowane jądro systemu, oraz pakiet mdadm zamiast dotychczasowego raidtools. W jądro powinna być wkompilowana obsługa Raid1 (mirroring). Jak sprawdzić, czy jest? Jeśli istnieje plik /proc/mdstat wszystko powinno być ok, jeśli nie - trzeba będzie samemu skompilować jajko. Źródełka pakietu mdadm można pobrać ze strony http://www.kernel.org/pub/linux/utils/raid/mdadm/ lub w przypadku Debiana zainstalować binarki:

# apt-get install mdadm

Nasz przykład oprzemy na takim przykładowym ustawieniu partycji na dysku:

Urządzenie Pojemność  Punkt montowania
/dev/sda1     30MB     /boot
/dev/sda2   9600MB     /
/dev/sda3    512MB      swap
/dev/sda4  67000MB     /home

A więc mamy podłączony drugi dysk - pusty, bez partycji, więc je tworzymy tak by wyglądały identycznie na obu dyskach. Nasz pierwszy dysk wygląda tak:

# fdisk -l /dev/sda

Disk /dev/sda: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1           4       32098+  83  Linux
/dev/sda2               5        1220     9767520   82  Linux
/dev/sda3            1221        1342      979965   83  Linux Swap
/dev/sda4            1343        9729    67368577+  83  Linux

Tworzymy partycje identycznie, z tym, że typ partycji ustawiamy na fd - Linux raid autodetect. Nasz drugi dysk powinien wyglądać tak:

# fdisk -l /dev/sdb

Disk /dev/sdb: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1           4       32098+  fd  Linux raid autodetect
/dev/sdb2               5        1220     9767520   fd  Linux raid autodetect
/dev/sdb3            1221        1342      979965   fd  Linux raid autodetect
/dev/sdb4            1343        9729    67368577+  fd  Linux raid autodetect

Teraz możemy przystąpić do tworzenia macierzy raid:

mdadm --create /dev/md0 --level 1 --raid-devices=2 missing /dev/sdb1

a to oznacza, że tworzymy (--create) partycję macierzy /dev/md0 typu --level 1 (mirroring) składającą się z --raid-devices=2 (dwóch dysków) i niestety pierwszy dysk missing (brakuje, ponieważ na razie istnieje na nim nasz system - nie chcemy go uszkodzić), a drugi to /dev/sdb1. Warto tu zauważyć, że partycje macierzy raid numerujemy od zera, a więc partycja /dev/md0 będzie odpowiadała połączonym partycjom /dev/sda1 i /dev/sdb1 (tak będzie w naszym przykładzie).
A więc jedziemy dalej:

mdadm --create /dev/md1 --level 1 --raid-devices=2 missing /dev/sdb2
mdadm --create /dev/md2 --level 1 --raid-devices=2 missing /dev/sdb3
mdadm --create /dev/md3 --level 1 --raid-devices=2 missing /dev/sdb4

Hurra! Powołaliśmy nasz raid do istnienia! Ale na razie niestety nie pomoże nam w razie awarii dysku. Więc dalej do pracy. Jak możemy obejrzeć w jakim stanie jest nasz mirroring? Zawsze w ten sam sposób:

# cat /proc/mdstat

Personalities : [raid1]
md0 : active raid1 sdb1[1]
      32000 blocks [2/1] [_U]

md1 : active raid1 sdb2[1]
      9767424 blocks [2/1] [_U]

md2 : active raid1 sdb3[1]
      979840 blocks [2/1] [_U]

md3 : active raid1 sdb4[1]
      67534912 blocks [2/1] [_U]

Powyższy wynik należy czytać tak: Personalities : [raid1] - utworzyliśmy raid1! Pierwsza partycja to md0 : active raid1 sdb1[1] - aktywny raid na partycji sdb1 na razie jednej, jest to dysk drugi [1] (pierwszy to [0] - który jest na razie missing). Partycja ma 32000 blocks pojemności, [2/1] jeden z dwóch dysków jest czynny i jest to dysk [_U] drugi ("_" oznacza brak dysku, "U" oznacza "Up and running" - czyli podniesiony i chodzi).

No to partycje mamy, teraz trzeba utworzyć na nich system plików i podmontować je. A więc do dzieła:

# mkfs.ext3 /dev/md0
# mkfs.ext3 /dev/md1
# mkswap /dev/md2
# mkfs.ext3 /dev/md3
# mkdir /mntroot
# mkdir /mntboot
# mkdir /mnthome
# mount /dev/md0 /mntboot
# mount /dev/md1 /mntroot
# mount /dev/md3 /mnthome

Teraz poprawiamy initrd (UWAGA!!! jeśli używasz initramfs - w nowszych dystrybucjach - zobacz uwagi p. Artura Skrzypczyńskiego tutaj) - jeśli używamy go przy starcie systemu (w grubie - /boot/grub/menu.lst będziemy mieli wpis w naszej sekcji uruchomieniowej podobny do tego: initrd /initrd.img-2.6.8). Jest to szczególnie ważne gdy używamy dysków SATA, a chcemy, by komputer wstał po restarcie ;). A więc w pliku /etc/mkinitrd/mkinitrd.conf dokonujemy następujących zmian: MODULES=most zamieniamy na MODULES=dep i ROOT=probe na ROOT="/dev/md1 ext3". Po tych zmianach wydajemy polecenie:

#mkinitrd -o /boot/initrd.img-2.6.8-md 2.6.8

Czyli tworzymy plik initrd.img. Teraz musimy trochę pozmieniać w konfiguracji GRUB-a. Edytujemy /boot/grub/menu.lst, usuwamy opcje savedefault (patrz uwagi p. Vladimira Mitioucheva tutaj) a opcję default saved zamieniamy na default num, gdzie num to numer naszej domyślnej sekwencji uruchomieniowej (licząc kolejno od góry listingu zaczynając liczyć od zera). Następnie kopiujemy naszą domyślną sekwencję uruchomieniową i wklejamy poniżej:


title Debian GNU/Linux, kernel 2.6.8
root (hd0,0)
kernel /vmlinuz-2.6.8 root=/dev/sda2 ro 
initrd /initrd.img-2.6.8
boot

i zmieniamy, jak poniżej - zgodnie z wcześniejszą konfiguracją:


title Debian GNU/Linux, kernel 2.6.8-md Disk1
root (hd0,0)
kernel /vmlinuz-2.6.8 root=/dev/md1 ro 
initrd /initrd.img-2.6.8-md
boot

Jeśli nie korzystamy z dysków SATA i nie mamy linii rozpoczynającej się od initrd, to je pomijamy. Teraz kopiujemy jeszcze raz powyższy fragment, wklejamy poniżej i ustawiamy tak by w razie awarii mieć możliwość wyboru dysku z którego chcemy odpalić system:


title Debian GNU/Linux, kernel 2.6.8-md Disk2
root (hd1,0)
kernel /vmlinuz-2.6.8 root=/dev/md1 ro 
initrd /initrd.img-2.6.8-md
boot

Teraz jeszcze musimy stworzyć plik konfiguracyjny macierzy - edytujemy /etc/mdadm/mdadm.conf i wpisujemy do pustego pliku:

DEVICE /dev/sda* /dev/sdb*

Resztę pliku konfiguracynego dopisze za nas polecenie mdadm. Musimy tylko wydać poniższe polecenie:

# mdadm --detail --scan >> /etc/mdadm/mdadm.conf

No to wszystko mamy przygotowane. Teraz trzeba przekopiować nasz system z aktualnego dysku na macierz (która narazie składa się z jednego dysku - /dev/sdb). Świetnym narzędziem do kopiowania w tym wypadku będzie rsync - polecam. Jeżeli go nie mamy, a mamy Debiana, to wiemy co zrobić ( apt-get install rsync). Kopiujemy po kolei wszystko na podmontowane partycje:

# rsync -auHx --exclude=/proc/* --exclude=/sys/* --exclude=/boot/* 
        --exclude=/home/* --exclude=/mntboot --exclude=/mntroot/ /* /mntroot/
# mkdir /mntroot/proc /mntroot/boot /mntroot/sys 
# chmod 555 /mntroot/proc
# rsync -auHx   /boot/ /mntboot/
# rsync -auHx   /home/ /mnthome/

Jeszcze nie restartujmy systemu. Ważna sprawa - zmiany w fstab na macierzy (jak słusznie zauważył Artur S.) czyli /mntroot/etc/fstab. Po restarcie system będzie musiał wiedzieć jak ma zamontować partycje. A więc zamieniamy odpowiednio /dev/sda1 na /dev/md0, /dev/sda2 na /dev/md1, /dev/sda3 na /dev/md2 i /dev/sda4 na /dev/md3.

 

No i wreszcie możemy zrestartować system. Po restarcie system powinien uruchomić się na uszkodzonym RAID1 (bez pierwszego dysku) - w tym celu trzeba będzie wybrać z gruba Disk2 naszego RAID-a. Jeśli się udało - GRATULACJE!

Teraz, zanim przystąpimy do dodania pierwszego dysku do naszej macierzy warto by sprawdzić, czy system faktycznie uruchomił się na RAID-zie. Najprościej chyba tak:

# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/md1               7692840   6432572    869492  89% /
tmpfs                   257360         0    257360   0% /dev/shm
/dev/md0                 15429      8100      6533  56% /boot
/dev/md3              31190444   3263284  26342756  12% /home

Widzimy powyżej, że poszczególne partycje zostały zamontowane na urządzeniach RAID (/dev/md*), a więc jest OK. No więc trzeba przygotować teraz dysk pierwszy. Za pomocą fdisk zmieniamy typy partycji na fd (linux raid autodetect) - spowoduje to utratę danych na tym dysku. Powinno to wyglądać tak:

# fdisk -l /dev/sda

Disk /dev/sda: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1           4       32098+  fd  Linux raid autodetect
/dev/sda2               5        1220     9767520   fd  Linux raid autodetect
/dev/sda3            1221        1342      979965   fd  Linux raid autodetect
/dev/sda4            1343        9729    67368577+  fd  Linux raid autodetect

Mamy dysk przygotowany, więc trzeba go teraz dodać (wszystkie poszczególne partycje) do naszego matrix-a:

# mdadm /dev/md0 -a /dev/sda1
# mdadm /dev/md1 -a /dev/sda2
# mdadm /dev/md2 -a /dev/sda3
# mdadm /dev/md3 -a /dev/sda4

Teraz możemy sprawdzić jak odbudowuje się system na dodanym dysku:

# cat /proc/mdstat


Personalities : [raid1]
md0 : active raid1 sda1[0] sdb1[1]
      32000 blocks [2/2] [UU]

md1 : active raid1 sda2[0] sdb2[1]
      9767424 blocks [2/1] [_U]
      [======>..............]  recovery = 28.9% (2767468/9767424) 
                                               finish=12.4min speed=x

md2 : active raid1 sda3[0] sdb3[1]
      979840 blocks [2/2] [UU]

md3 : active raid1 sda4[0] sdb4[1]
      67534912 blocks [2/2] [UU]
unused devices: 

Teraz musimy utworzyć na nowo plik konfiguracyjny /etc/mdadm/mdadm.conf. Kasujemy więc w nim wszystko oprócz DEVICE /dev/sda* /dev/sdb* i wykonujemy:

# mdadm --detail --scan >> /etc/mdadm/mdadm.conf

Teraz pozostało nam jeszcze zainstalować GRUB-a na obu dyskach w MBR by w razie awarii każdy z nich mógł wystartować:

#grub --device-map=/boot/grub/device.map

        >> root (hd0,0)
        >> setup (hd0)
        >> root (hd1,0)
        >> setup (hd1)
        >> quit 

Gdyby GRUB krzyczał, że nie zna takiego dysku jak hd1, zajrzyjmy do pliku /boot/grub/device.map. Jeśli brakuje aliasu (hd1) dodajmy go:

(hd1)    /dev/sdb

i powtórzmy jeszcze raz instalację GRUBa do MBR. Wyedytujmy jeszcze /boot/grub/menu.lst i wskażmy (zmieńmy na) właściwą partycję głównego katalogu:

# kopt=root=/dev/md1 ro

Ten # na początku też musi zostać (nie wiedzieć czemu). No i THAT'S ALL!

 

Zawsze stan macierzy (naszego RAID1) możemy sprawdzić poleceniem cat /proc/mdstat. Pakiet mdadm można również skonfigurować tak, by wysyłał nam maila w razie jakiejkolwiek awarii. W przypadku Debiana wystarczy:

# dpkg-reconfigure mdadm

jeśli nie zrobiliśmy tego już przy instalacji.



Uwagi Pana Artura Skrzypczyńskiego dotyczące initramfs za które bardzo dziękuję:

[cytat](...) przy kolejnym serwerze, który robiłem nawet zostawienie wpisu =most nie zadziałało więc odkryłem pewien drobiazg. Z jakiegoś powodu mkinitramfs (czy też update-initramfs) nie zawsze poprawnie wkompilowuje moduły (zła kolejność lub coś innego) co powoduje standardowy błąd podczas startu - czyli nie widać macierzy mdx. Otóż najlepszą metodą jest PRZED wykonaniem mkinitramfs zrobić coś takiego:

# depmod
# lsmod >> /etc/initramfs-tools/initramfs.conf

(to spowoduje wpisanie listy modułów do pliku konfiguracyjnego, z którego korzysta mkinitramfs)

# vim /etc/initramfs-tools/initramfs.conf 

(edytujemy plik żeby zostawić tylko pierwszą kolumnę wpisów - z nazwami modułów - resztę kasujemy. Ponadto moduły scsi lub sata należy umieścić na szczycie listy). Teraz uzupełniamy plik mdadm.conf w/g Pana instrukcji i UWAGA - usuwamy wpisy METADATA=xxxxxx. Dopiero teraz uruchamiamy mkinitramfs. To działa w 100% - przynajmniej na nowych Debianach, w których mkinitrd zostało zastąpione przez mkinitramfs.
[koniec cytatu]

Uwagi Pana Vladimira Mitioucheva dotyczące grub i opcji savedefault za które bardzo dziękuję:

[cytat] w opisie menu.lst vel grub.conf widnieje opcja savedefault, a nie można jej używać bo grub nie wie że raid to raid skutkiem czego zapisuje ostatni wybrany kernel na partycję fizyczną zamiast na naszego raida czego skutkiem jest rozsynchronizowanie się raida dla /boot.
[koniec cytatu]