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ą.