Stworzenie mirrora z dysku systemowego w LVM

Sprawa niby wydaje się prosta, bo jest kilka poradników jak dołożyć drugi dysk do Volume Group i przekształcić to w mirror. I jak to w świecie IT bywa, dopóki wszystko działa zgodnie z dokumentacją, to każdy potrafiłby to zrobić. Schody zaczynają się, kiedy jeden z wymienionych tam kroków kończy się niepowodzeniem. Ale nie uprzedzajmy faktów, jak zwykł mawiać klasyk.
Środowisko wygląda tak, że jest zainstalowana wirtualna maszyna na VMWare ESXi, która ma dysk systemowy w jednym datastore. W celu zapewnienia redundancji na poziomie samego systemu postanowiłem dołożyć dysk z drugiego datastore o tej samej pojemności i spiąć te dyski w RAID-1 czyli mirror.

Opis bieżącej sytuacji w LVM wygląda tak:

[root@prod ~]# lvs
  LV   VG     Attr       LSize  Pool Origin Data%  Move Log Cpy%Sync Convert
  root centos -wi-ao---- 11.60g
  swap centos -wi-ao----  3.91g
  srv  data   rwi-aor--- 99.99g                               100.00

[root@prod ~]# pvs
  PV         VG     Fmt  Attr PSize   PFree
  /dev/sda2  centos lvm2 a--   15.51g    0
  /dev/sdb   data   lvm2 a--  100.00g    0
  /dev/sdc   data   lvm2 a--  100.00g    0

[root@prod ~]# pvscan
  PV /dev/sda2   VG centos   lvm2 [15.51 GiB / 0    free]
  PV /dev/sdb    VG data     lvm2 [100.00 GiB / 0    free]
  PV /dev/sdc    VG data     lvm2 [100.00 GiB / 0    free]
  Total: 3 [215.50 GiB] / in use: 3 [215.50 GiB] / in no VG: 0 [0   ]

[root@prod ~]# vgscan
  Reading all physical volumes.  This may take a while...
  Found volume group "centos" using metadata type lvm2
  Found volume group "data" using metadata type lvm2

Jak widać jest tu VG „centos” na wolumenie fizycznym /dev/sda2, na której są dwa wolumeny logiczne: root oraz swap. Jest też druga VG o nazwie „data”, ale ta jest już zmirrorowana i nie będziemy się nią zajmować. Zobaczmy więc jak wygląda wolumen utworzony na /dev/sda2:

[root@prod ~]# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               centos
  PV Size               15.51 GiB / not usable 3.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              3970
  Free PE               0
  Allocated PE          3970
  PV UUID               RJaYrc-pV0r-qfNf-S92B-NSJc-mLpF-A5GOkf

Jak już wspominałem, rzecz dzieje się w środowisku VMWare ESXi, gdzie utworzyłem na drugim datastore nowy wolumen o tej samej pojemności co dysk systemowy i podłączyłem go do wirtualnej maszyny. System operacyjny VM nie wie jeszcze o jego istnieniu i należy go o tym powiadomić. Można by było to zrobić restartując VM, ale do tego potrzebny jest downtime, na który nie zawsze można sobie pozwolić. Zróbmy to więc bez restartu, wydając systemowi polecenie przeskanowania magistrali. Najpierw jednak zobaczmy co mamy:

[root@prod ~]# fdisk -l

Disk /dev/sdb: 107.4 GB, 107374182400 bytes, 209715200 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/sdc: 107.4 GB, 107374182400 bytes, 209715200 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/sda: 17.2 GB, 17179869184 bytes, 33554432 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x00015ff8

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1026047      512000   83  Linux
/dev/sda2         1026048    33554431    16264192   8e  Linux LVM

Disk /dev/mapper/centos-swap: 4194 MB, 4194304000 bytes, 8192000 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/mapper/centos-root: 12.5 GB, 12457082880 bytes, 24330240 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/mapper/data-srv_rmeta_0: 4 MB, 4194304 bytes, 8192 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/mapper/data-srv_rimage_0: 107.4 GB, 107365793792 bytes, 209698816 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/mapper/data-srv_rmeta_1: 4 MB, 4194304 bytes, 8192 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/mapper/data-srv_rimage_1: 107.4 GB, 107365793792 bytes, 209698816 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/mapper/data-srv: 107.4 GB, 107365793792 bytes, 209698816 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Proszę zwrócić uwagę na dodatkowe metadane w przypadku zmirrorowanego już wolumenu data-srv w stosunku do centos-root oraz centos-swap.
Skanujemy magistrale:

[root@prod ~]# echo "- - -" > /sys/class/scsi_host/host0/scan
[root@prod ~]# echo "- - -" > /sys/class/scsi_host/host1/scan

Dobrze byłoby wiedzieć do której podpięty jest nowy dysk, ale nic się nie powinno stać jeśli przeskanujecie wszystkie. Warto zajrzeć do logów systemowych, czy coś nowego się pojawiło.

[root@prod ~]# less /var/log/messages
[root@prod ~]# echo "- - -" > /sys/class/scsi_host/host2/scan
[root@prod ~]# less /var/log/messages

Teraz zajrzyjmy jeszcze raz co mamy:

[root@prod ~]# fdisk -l

Disk /dev/sdb: 107.4 GB, 107374182400 bytes, 209715200 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/sdc: 107.4 GB, 107374182400 bytes, 209715200 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/sda: 17.2 GB, 17179869184 bytes, 33554432 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x00015ff8

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1026047      512000   83  Linux
/dev/sda2         1026048    33554431    16264192   8e  Linux LVM

Disk /dev/mapper/centos-swap: 4194 MB, 4194304000 bytes, 8192000 sectors
[...]

Disk /dev/sdd: 17.2 GB, 17179869184 bytes, 33554432 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Trochę obciąłem wynik, bo jest taki sam jak poprzednio, z tą zmianą, że po liście wolumenów logicznych doszedł nam nowy dysk fizyczny /dev/sdd.
Teraz, skoro dysk ma być mirrorem dysku systemowego, musi mieć taką samą strukturę, odtworzymy więc rozkład partycji z pierwszego dysku:

[root@prod ~]# sfdisk -d /dev/sda
# partition table of /dev/sda
unit: sectors

/dev/sda1 : start=     2048, size=  1024000, Id=83, bootable
/dev/sda2 : start=  1026048, size= 32528384, Id=8e
/dev/sda3 : start=        0, size=        0, Id= 0
/dev/sda4 : start=        0, size=        0, Id= 0

I tenże rozkład partycji zapiszemy na nowy dysk:

[root@prod ~]# sfdisk -d /dev/sda  |sfdisk /dev/sdd
Checking that no-one is using this disk right now ...
OK

Disk /dev/sdd: 2088 cylinders, 255 heads, 63 sectors/track
sfdisk:  /dev/sdd: unrecognized partition table type

Old situation:
sfdisk: No partitions found

New situation:
Units: sectors of 512 bytes, counting from 0

   Device Boot    Start       End   #sectors  Id  System
/dev/sdd1   *      2048   1026047    1024000  83  Linux
/dev/sdd2       1026048  33554431   32528384  8e  Linux LVM
/dev/sdd3             0         -          0   0  Empty
/dev/sdd4             0         -          0   0  Empty
Warning: partition 1 does not end at a cylinder boundary
Warning: partition 2 does not start at a cylinder boundary
Warning: partition 2 does not end at a cylinder boundary
Successfully wrote the new partition table

Re-reading the partition table ...

If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)
to zero the first 512 bytes:  dd if=/dev/zero of=/dev/foo7 bs=512 count=1
(See fdisk(8).)

Zobaczmy jak teraz wyglądają partycje na urządzeniu /dev/sdd:

[root@prod ~]# sfdisk -d /dev/sdd
# partition table of /dev/sdd
unit: sectors

/dev/sdd1 : start=     2048, size=  1024000, Id=83, bootable
/dev/sdd2 : start=  1026048, size= 32528384, Id=8e
/dev/sdd3 : start=        0, size=        0, Id= 0
/dev/sdd4 : start=        0, size=        0, Id= 0

Całkiem dobrze, zróbmy więc z niego wolumen fizyczny:

[root@prod ~]# pvcreate /dev/sdd2
  Physical volume "/dev/sdd2" successfully created

[root@prod ~]# pvs
  PV         VG     Fmt  Attr PSize   PFree
  /dev/sda2  centos lvm2 a--   15.51g     0
  /dev/sdb   data   lvm2 a--  100.00g     0
  /dev/sdc   data   lvm2 a--  100.00g     0
  /dev/sdd2         lvm2 a--   15.51g 15.51g

Poszerzmy o niego grupę „centos”:

[root@prod ~]# vgextend centos /dev/sdd2
  Volume group "centos" successfully extended

[root@prod ~]# pvs
  PV         VG     Fmt  Attr PSize   PFree
  /dev/sda2  centos lvm2 a--   15.51g     0
  /dev/sdb   data   lvm2 a--  100.00g     0
  /dev/sdc   data   lvm2 a--  100.00g     0
  /dev/sdd2  centos lvm2 a--   15.51g 15.51g

Załatwione, teraz zostaje przekształcić to w mirror:

[root@prod ~]# lvconvert -m 1 --corelog centos/root
  Insufficient free space: 1 extents needed, but only 0 available
[root@prod ~]# lvconvert -m 1 --alloc anywhere centos/root
  Insufficient free space: 1 extents needed, but only 0 available

I w tym miejscu wszystkie wspomniane na początku instrukcje tworzenia mirrora straciły właśnie swoją ważność. Wszelkie które znalazłem albo nie przewidywały takiego obrotu sprawy, albo nie podawały sensownego rozwiązania problemu. Były jeszcze różne próby z alokacją miejsca na metadane w różnych miejscach, czy też zmniejszaniem partycji, ale kończyły się niepowodzeniem lub totalną katastrofą ze spójnością danych. Szukając rozwiązań problemu, nie spotkałem się jednak z tym co zrobiłem, dlatego też Wam to opisuję. Postanowiłem wyłączyć przestrzeń wymiany (swap) i zmniejszyć jej rozmiar, tak aby wygospodarować miejsce na metadane. Zaczynamy więc od sprawdzenia:

[root@prod ~]# swapon
NAME      TYPE      SIZE USED PRIO
/dev/dm-0 partition 3.9G   0B   -1

Wyłączamy przestrzeń wymiany (jest tylko jedna, więc można użyć -a):

[root@prod ~]# swapoff -av
swapoff /dev/dm-0

Sprawdzamy:

[root@prod ~]# swapon

Teraz pora zmniejszyć wielkość wolumenu logicznego (tutaj się pomyliłem i zamiast dać „-512M”, czyli zmniejszyć o 512M, to zmniejszyłem do 512M, pamiętajcie więc o minusie):

[root@prod ~]# lvreduce centos/swap -L 512M
  WARNING: Reducing active logical volume to 512.00 MiB
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce swap? [y/n]: y
  Reducing logical volume swap to 512.00 MiB
  Logical volume swap successfully resized

Sprawdzamy:

[root@prod ~]# lvs
  LV   VG     Attr       LSize   Pool Origin Data%  Move Log Cpy%Sync Convert
  root centos -wi-ao----  11.60g
  swap centos -wi-a----- 512.00m
  srv  data   rwi-aor---  99.99g                               100.00

Zwolniło się miejsce, próbujemy więc przekształcić root filesystem w mirror:

[root@prod ~]# lvconvert -m 1 centos/root
[root@prod ~]# lvs
  LV   VG     Attr       LSize   Pool Origin Data%  Move Log Cpy%Sync Convert
  root centos rwi-aor---  11.60g                                 0.00
  swap centos -wi-a----- 512.00m
  srv  data   rwi-aor---  99.99g                               100.00

Voila! Operacja udana, zróbmy więc to samo ze swapem:

[root@prod ~]# lvconvert -m 1 centos/swap

I sprawdzimy jak to wygląda:

[root@prod ~]# lvs
  LV   VG     Attr       LSize   Pool Origin Data%  Move Log Cpy%Sync Convert
  root centos rwi-aor---  11.60g                                55.66
  swap centos rwi-a-r--- 512.00m                               100.00
  srv  data   rwi-aor---  99.99g                               100.00

Mirrory zrobione, root filesystem się jeszcze synchronizuje, ale można już rozszerzyć z powrotem swap do maksymalnej możliwej wielkości:

[root@prod ~]# lvextend -l 100%FREE centos/swap
  Extending 2 mirror images.
  Extending logical volume swap to 6.80 GiB
  device-mapper: resume ioctl on  failed: Invalid argument
  Unable to resume centos-swap (253:0)
  Problem reactivating swap
  libdevmapper exiting with 1 device(s) still suspended.

Niestety system nie potrafił sobie podpiąć swapa samodzielnie, gdyż sygnatura zapewne została zniszczona, trzeba ją odtworzyć:

[root@prod ~]# mkswap /dev/centos/swap

Oraz włączyć swap z powrotem do systemu:

[root@prod ~]# swapon -av
swapon /dev/mapper/centos-swap
swapon: /dev/mapper/centos-swap: found swap signature: version 1, page-size 4, same byte order
swapon: /dev/mapper/centos-swap: pagesize=4096, swapsize=4185915392, devsize=4185915392

Sprawdzamy:

[root@prod ~]# swapon
NAME      TYPE      SIZE USED PRIO
/dev/dm-4 partition 3.9G   0B   -1

Tym sposobem przeszedłem właśnie przyspieszony kurs logiki działania oraz obsługi LVM, którego wcześniej jakoś nie miałem okazji używać, a opis mam nadzieję przyda się tym, którzy z podobnym problemem się zetkną.

Możesz również polubić…

Leave a Reply

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.