Mi a közös az LVM-ben és a Matrjoskában?

Jó napot kívánok.
Szeretném megosztani a közösséggel gyakorlati tapasztalataimat a KVM adattároló rendszerének md RAID + LVM segítségével történő felépítéséről.

A program a következőket tartalmazza majd:

  • Md RAID 1 építése NVMe SSD-ről.
  • Md RAID 6 összeszerelése SATA SSD-ről és normál meghajtókról.
  • A TRIM/DISCARD működés jellemzői SSD RAID 1/6-on.
  • Bootolható md RAID 1/6 tömb létrehozása közös lemezkészleten.
  • A rendszer telepítése NVMe RAID 1-re, ha a BIOS nem támogatja az NVMe-t.
  • LVM gyorsítótár és LVM vékony használata.
  • BTRFS pillanatképek használata és küldés/fogadás biztonsági mentéshez.
  • LVM vékony pillanatképek és vékony_delta használata BTRFS stílusú biztonsági mentésekhez.

Ha érdekel, nézd meg a kat.

nyilatkozat

A szerző nem vállal felelősséget a cikkből származó anyagok/példák/kód/tippek/adatok használatának vagy elmulasztásának következményeiért. Ha elolvassa vagy bármilyen módon használja ezt az anyagot, felelősséget vállal ezen cselekedetek minden következményéért. A lehetséges következmények a következők:

  • Ropogósra sült NVMe SSD-k.
  • Teljesen elhasználódott a rögzítési erőforrás és az SSD meghajtók meghibásodása.
  • Az összes adat teljes elvesztése az összes meghajtón, beleértve a biztonsági másolatokat is.
  • Hibás számítógépes hardver.
  • Elpazarolt idő, idegek és pénz.
  • Bármilyen egyéb következmény, amely nem szerepel fent.

vas

Elérhetőek voltak:

2013 körüli alaplap Z87 lapkakészlettel, Intel Core i7 / Haswell kompletten.

  • Processzor 4 mag, 8 szál
  • 32 GB DDR3 RAM
  • 1 x 16 vagy 2 x 8 PCIe 3.0
  • 1 x 4 + 1 x 1 PCIe 2.0
  • 6 x 6 GBps SATA 3 csatlakozók

SAS adapter LSI SAS9211-8I villogott IT / HBA módba. A RAID-kompatibilis firmware-t szándékosan lecserélték HBA firmware-re, hogy:

  1. Bármikor kidobhatja ezt az adaptert, és lecserélheti bármelyik másikra.
  2. A TRIM/Discard rendesen működött a lemezeken, mert... a RAID firmware-ben ezek a parancsok egyáltalán nem támogatottak, és a HBA-t általában nem érdekli, hogy milyen parancsokat továbbítanak a buszon.

Merevlemezek - 8 db HGST Travelstar 7K1000 1 TB kapacitással 2.5-ös formátumban, mint a laptopoknál. Ezek a meghajtók korábban RAID 6 tömbben voltak. Az új rendszerben is lesz hasznuk. Helyi biztonsági mentések tárolására.

Továbbá hozzáadva:

6 db SATA SSD modell Samsung 860 QVO 2TB. Ezekhez az SSD-khez nagy mennyiség kellett, SLC gyorsítótár megléte, megbízhatóság és alacsony ár volt a kívánatos. Szükség volt a discard/zero támogatására, amit a dmesg sora ellenőrzött:

kernel: ata1.00: Enabling discard_zeroes_data

2 db NVMe SSD modell Samsung SSD 970 EVO 500GB.

Ezeknél az SSD-knél fontos a véletlenszerű olvasási/írási sebesség és az Ön igényeinek megfelelő erőforráskapacitás. Radiátor nekik. Szükségszerűen. Teljesen. Ellenkező esetben az első RAID-szinkronizálás során süsse őket ropogósra.

StarTech PEX8M2E2 adapter 2 x NVMe SSD-hez PCIe 3.0 8x foglalatba telepítve. Ez ismét csak egy HBA, de az NVMe számára. Az olcsó adapterektől abban különbözik, hogy a beépített PCIe switch megléte miatt nem igényel PCIe bifurkáció támogatást az alaplaptól. Még a legrégebbi PCIe rendszerben is működik, még akkor is, ha x1 PCIe 1.0 slotról van szó. Természetesen a megfelelő sebességgel. Ott nincsenek RAID-ek. A fedélzeten nincs beépített BIOS. Tehát a rendszere nem fog varázsütésre megtanulni az NVMe-vel való rendszerindítást, még kevésbé az NVMe RAID-et ennek az eszköznek köszönhetően.

Ez az összetevő kizárólag annak köszönhető, hogy csak egy ingyenes 8x PCIe 3.0 van a rendszerben, és ha van 2 szabad slot, akkor könnyen lecserélhető két filléres PEX4M2E1-re vagy analógokra, amelyek bárhol megvásárolhatók 600-os áron. rubel.

Mindenféle hardver vagy beépített chipset/BIOS RAID elutasítása tudatosan történt, hogy az SSD/HDD kivételével az egész rendszert teljesen le lehessen cserélni, az összes adat megőrzése mellett. Ideális esetben, hogy a teljesen új/más hardverre költözéskor akár a telepített operációs rendszert is el tudja menteni. A lényeg, hogy vannak SATA és PCIe portok. Olyan, mint egy élő CD vagy indítható flash meghajtó, csak nagyon gyors és kissé terjedelmes.

HumorEllenkező esetben tudja, mi történik – néha sürgősen magával kell vinnie az egész tömböt, hogy elvigye. De nem akarom elveszíteni az adatokat. Ehhez az összes említett adathordozó kényelmesen elhelyezhető a szabványos ház 5.25-ös rekeszeiben lévő diákon.

Nos, és természetesen az SSD gyorsítótárazás különböző módszereivel való kísérletezéshez Linux alatt.

A hardveres raidek unalmasak. Kapcsolja be. Vagy működik, vagy nem. Az mdadm-mel pedig mindig vannak lehetőségek.

lágy

Korábban a Debian 8 Jessie volt telepítve a hardverre, ami közel áll az EOL-hez. A RAID 6 a fent említett LVM-mel párosított HDD-kből lett összeállítva. Virtuális gépeket futtatott kvm/libvirt-ben.

Mert A szerző megfelelő tapasztalattal rendelkezik hordozható bootolható SATA/NVMe pendrive-ok létrehozásában, valamint, hogy a megszokott találó sablon ne törjön meg, az Ubuntu 18.04-et választották célrendszernek, amely már kellően stabilizálódott, de még mindig 3 évre képes. támogatást a jövőben.

Az említett rendszer tartalmazza az összes szükséges hardver-illesztőprogramot. Nincs szükségünk harmadik féltől származó szoftverekre vagy illesztőprogramokra.

Felkészülés a telepítésre

A rendszer telepítéséhez Ubuntu Desktop Image szükséges. A szerverrendszerben van valami erőteljes telepítő, ami túlzott függetlenséget mutat, amit nem lehet letiltani úgy, hogy az UEFI rendszerpartíciót az egyik lemezre tolja, elrontva a szépséget. Ennek megfelelően csak UEFI módban van telepítve. Nem kínál semmilyen lehetőséget.

Nem örülünk ennek.

Miért?Sajnos az UEFI boot rendkívül rosszul kompatibilis a RAID indítószoftverrel, mert... Senki nem ajánl nekünk foglalást az UEFI ESP partícióhoz. Vannak olyan receptek az interneten, amelyek azt javasolják, hogy az ESP-partíciót helyezze egy USB-porton lévő flash meghajtóra, de ez egy hibapont. Vannak olyan receptek az mdadm RAID 1 szoftvert használó 0.9-es metaadatokkal, amelyek nem akadályozzák meg, hogy az UEFI BIOS lássa ezt a partíciót, de ez a boldog pillanatig él, amikor a BIOS vagy egy másik hardver operációs rendszer ír valamit az ESP-re, és elfelejti szinkronizálni a másikkal. tükrök.

Ezenkívül az UEFI rendszerindítás az NVRAM-tól függ, amely nem költözik a lemezekkel együtt az új rendszerbe, mert az alaplap része.

Tehát nem fogunk feltalálni egy új kereket. Már van egy kész, jól bevált nagypapa bringánk, most Legacy/BIOS boot néven, amely a CSM büszke nevet viseli UEFI-kompatibilis rendszereken. Csak levesszük a polcról, megkenjük, felpumpáljuk a gumikat és nedves ronggyal letöröljük.

Az Ubuntu asztali verziója szintén nem telepíthető megfelelően a Legacy bootloaderrel, de itt, mint mondják, legalább vannak lehetőségek.

Így összegyűjtjük a hardvert, és betöltjük a rendszert az Ubuntu Live indítható flash meghajtóról. Csomagokat kell letöltenünk, így beállítjuk az Ön számára megfelelő hálózatot. Ha nem működik, akkor előre betöltheti a szükséges csomagokat egy flash meghajtóra.

Bemegyünk az asztali környezetbe, elindítjuk a terminál emulátort, és már megy is:

#sudo bash

Hogyan…?A fenti sor a sudo-val kapcsolatos holiwars kanonikus triggerje. C bоnagyobb lehetőségek jönnek ésоnagyobb felelősség. A kérdés az, hogy fel tudod-e vállalni magad. Sokan úgy gondolják, hogy a sudo ilyen módon történő használata legalább nem óvatos. Azonban:

#apt-get install mdadm lvm2 thin-provisioning-tools btrfs-tools util-linux lsscsi nvme-cli mc

Miért nem a ZFS...?Amikor szoftvert telepítünk a számítógépünkre, lényegében kölcsönadjuk hardverünket a szoftver fejlesztőinek, hogy vezessék.
Amikor erre a szoftverre bízzuk adataink biztonságát, akkor az adatok helyreállításának költségével megegyező kölcsönt veszünk fel, amit egyszer majd ki kell fizetnünk.

Ebből a szempontból a ZFS egy Ferrari, az mdadm+lvm pedig inkább egy bicikli.

Szubjektív módon a szerző szívesebben ad hitelből biciklit kölcsön Ferrari helyett ismeretleneknek. Ott nem magas a kibocsátás ára. Nincs szükség jogokra. Egyszerűbb, mint a közlekedési szabályok. A parkolás ingyenes. A terepfutás jobb. A kerékpárhoz mindig rögzíthet lábakat, és saját kezével megjavíthatja a kerékpárt.

Miért akkor a BTRFS...?Az operációs rendszer indításához olyan fájlrendszerre van szükségünk, amely már a dobozból támogatott Legacy/BIOS GRUB-ban, és egyben támogatja az élő pillanatképeket is. A /boot partícióhoz fogjuk használni. Ezenkívül a szerző szívesebben használja ezt az FS-t a / (root) számára, ne felejtse el megjegyezni, hogy bármely más szoftverhez külön partíciókat hozhat létre az LVM-en, és csatlakoztathatja azokat a szükséges könyvtárakba.

Ezen az FS-en nem tárolunk virtuális gépekről vagy adatbázisokról készült képeket.
Ez az FS csak pillanatképek készítésére szolgál a rendszerről anélkül, hogy kikapcsolná, majd ezeket a pillanatképeket a küldés/fogadás funkcióval biztonsági mentési lemezre továbbítja.

Ezenkívül a szerző általában előnyben részesíti, hogy minimális szoftvert tartson közvetlenül a hardveren, és az összes többi szoftvert virtuális gépeken futtassa, például GPU-k és PCI-USB-gazdavezérlők továbbítása a KVM-hez az IOMMU-n keresztül.

A hardveren csak az adattárolás, a virtualizáció és a biztonsági mentés marad.

Ha jobban megbízik a ZFS-ben, akkor elvileg a megadott alkalmazáshoz felcserélhetők.

A szerző azonban szándékosan figyelmen kívül hagyja a ZFS, BRTFS és LVM beépített tükrözési/RAID- és redundancia funkcióit.

További érvként a BTRFS képes a véletlenszerű írásokat szekvenciálissá alakítani, ami rendkívül pozitív hatással van a pillanatképek / biztonsági mentések szinkronizálásának sebességére a HDD-n.

Szkenneljük újra az összes eszközt:

#udevadm control --reload-rules && udevadm trigger

Nézzünk körül:

#lsscsi && nvme list
[0:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sda
[1:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sdb
[2:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sdc
[3:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sdd
[4:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sde
[5:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sdf
[6:0:0:0] disk ATA HGST HTS721010A9 A3J0 /dev/sdg
[6:0:1:0] disk ATA HGST HTS721010A9 A3J0 /dev/sdh
[6:0:2:0] disk ATA HGST HTS721010A9 A3J0 /dev/sdi
[6:0:3:0] disk ATA HGST HTS721010A9 A3B0 /dev/sdj
[6:0:4:0] disk ATA HGST HTS721010A9 A3B0 /dev/sdk
[6:0:5:0] disk ATA HGST HTS721010A9 A3B0 /dev/sdl
[6:0:6:0] disk ATA HGST HTS721010A9 A3J0 /dev/sdm
[6:0:7:0] disk ATA HGST HTS721010A9 A3J0 /dev/sdn
Node SN Model Namespace Usage Format FW Rev
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1 S466NXXXXXXX15L Samsung SSD 970 EVO 500GB 1 0,00 GB / 500,11 GB 512 B + 0 B 2B2QEXE7
/dev/nvme1n1 S5H7NXXXXXXX48N Samsung SSD 970 EVO 500GB 1 0,00 GB / 500,11 GB 512 B + 0 B 2B2QEXE7

Lemezelrendezés

NVMe SSD-k

De semmilyen módon nem jelöljük meg őket. Mindazonáltal a BIOS-unk nem látja ezeket a meghajtókat. Tehát teljes egészében a szoftveres RAID-re fognak menni. Nem is fogunk ott szakaszokat létrehozni. Ha követni szeretné a „canont” vagy „elsősorban”, hozzon létre egy nagy partíciót, például egy HDD-t.

SATA merevlemez

Itt nem kell semmi különöset kitalálni. Mindenhez létrehozunk egy szakaszt. Létrehozunk egy partíciót, mert a BIOS látja ezeket a lemezeket, és akár meg is próbálhat róluk indítani. A későbbiekben még a GRUB-ot is telepítjük ezekre a lemezekre, hogy a rendszer ezt hirtelen meg tudja tenni.

#cat >hdd.part << EOF
label: dos
label-id: 0x00000000
device: /dev/sdg
unit: sectors

/dev/sdg1 : start= 2048, size= 1953523120, type=fd, bootable
EOF
#sfdisk /dev/sdg < hdd.part
#sfdisk /dev/sdh < hdd.part
#sfdisk /dev/sdi < hdd.part
#sfdisk /dev/sdj < hdd.part
#sfdisk /dev/sdk < hdd.part
#sfdisk /dev/sdl < hdd.part
#sfdisk /dev/sdm < hdd.part
#sfdisk /dev/sdn < hdd.part

SATA SSD

Itt válnak érdekessé számunkra a dolgok.

Először is, meghajtóink 2 TB méretűek. Ez az MBR számára elfogadható tartományon belül van, ezt fogjuk használni. Szükség esetén GPT-vel helyettesíthető. A GPT lemezek kompatibilitási réteggel rendelkeznek, amely lehetővé teszi az MBR-kompatibilis rendszerek számára, hogy lássák az első 4 partíciót, ha azok az első 2 terabájton belül helyezkednek el. A lényeg az, hogy ezeken a lemezeken a rendszerindító partíció és a bios_grub partíció az elején legyen. Ez még a GPT Legacy/BIOS meghajtókról való rendszerindítást is lehetővé teszi.

De ez nem a mi esetünk.

Itt két szakaszt hozunk létre. Az első 1 GB méretű lesz, és RAID 1 /boothoz használható.

A második a RAID 6-hoz lesz használva, és elfoglalja az összes fennmaradó szabad helyet, kivéve a meghajtó végén található kis, ki nem osztott területet.

Mi ez a jelöletlen terület?Hálózati források szerint a SATA SSD-kben dinamikusan bővíthető SLC-gyorsítótár található, 6 és 78 gigabájt között. 6 gigabájtot „ingyen” kapunk a meghajtó adatlapján szereplő „gigabájt” és „gibibájt” különbsége miatt. A fennmaradó 72 gigabájtot a fel nem használt területről foglalják le.

Itt kell megjegyezni, hogy SLC gyorsítótárral rendelkezünk, és a hely 4 bites MLC módban van elfoglalva. Ami számunkra gyakorlatilag azt jelenti, hogy minden 4 gigabájt szabad hely után csak 1 gigabájt SLC gyorsítótárat kapunk.

Szorozza meg a 72 gigabájtot 4-gyel, és 288 gigabájtot kap. Ez az a szabad terület, amelyet nem jelölünk ki, hogy a meghajtók teljes mértékben kihasználhassák az SLC gyorsítótárat.

Így összesen hat meghajtóból gyakorlatilag akár 312 gigabájtnyi SLC gyorsítótárat is kapunk majd. Az összes meghajtó közül kettőt a RAID-ben használnak redundanciára.

Ez a mennyiségű gyorsítótár lehetővé teszi számunkra, hogy a való életben rendkívül ritkán találkozzunk olyan helyzettel, amikor az írás nem megy a gyorsítótárba. Ez rendkívül jól kompenzálja a QLC memória legszomorúbb hátrányát – a rendkívül alacsony írási sebességet, amikor az adatok a gyorsítótár megkerülésével íródnak. Ha a terheléseid ennek nem felelnek meg, akkor azt javaslom, hogy alaposan gondold át, meddig bírja az SSD-d ilyen terhelés mellett, figyelembe véve az adatlapon szereplő TBW-t.

#cat >ssd.part << EOF
label: dos
label-id: 0x00000000
device: /dev/sda
unit: sectors

/dev/sda1 : start= 2048, size= 2097152, type=fd, bootable
/dev/sda2 : start= 2099200, size= 3300950016, type=fd
EOF
#sfdisk /dev/sda < ssd.part
#sfdisk /dev/sdb < ssd.part
#sfdisk /dev/sdc < ssd.part
#sfdisk /dev/sdd < ssd.part
#sfdisk /dev/sde < ssd.part
#sfdisk /dev/sdf < ssd.part

Tömbök létrehozása

Először is át kell neveznünk a gépet. Erre azért van szükség, mert a gazdagépnév valahol az mdadm-en belül a tömbnév része, és valahol hatással van valamire. Természetesen a tömbök később át is nevezhetők, de ez egy felesleges lépés.

#mcedit /etc/hostname
#mcedit /etc/hosts
#hostname
vdesk0

NVMe SSD-k

#mdadm --create --verbose --assume-clean /dev/md0 --level=1 --raid-devices=2 /dev/nvme[0-1]n1

Miért -feltételezzük-tisztát...?A tömbök inicializálásának elkerülése érdekében. Ez mind az 1., mind a 6. RAID-szintre érvényes. Minden működhet inicializálás nélkül, ha új tömbről van szó. Ezenkívül az SSD-tömb létrehozása utáni inicializálása a TBW-erőforrás pazarlása. Lehetőség szerint TRIM/DISCARD-ot használunk az összeállított SSD-tömbökön, hogy „inicializáljuk”.

SSD-tömbök esetén a RAID 1 DISCARD már a dobozból is támogatott.

SSD RAID 6 DISCARD tömbök esetén engedélyeznie kell a kernelmodul paramétereiben.

Ezt csak akkor szabad megtenni, ha a rendszerben a 4/5/6 szintű tömbökben használt összes SSD támogatja a discard_zeroes_data funkciót. Néha furcsa meghajtókkal találkozhatunk, amelyek azt mondják a kernelnek, hogy ez a funkció támogatott, de valójában nincs, vagy a függvény nem mindig működik. Jelenleg a támogatás szinte mindenhol elérhető, azonban vannak régi meghajtók és hibás firmware. Emiatt a DISCARD támogatás alapértelmezés szerint le van tiltva a RAID 6 esetében.

Figyelem, a következő parancs megsemmisíti az NVMe meghajtókon lévő összes adatot a tömb „nullákkal történő inicializálásával”.

#blkdiscard /dev/md0

Ha valami elromlik, próbáljon meg megadni egy lépést.

#blkdiscard --step 65536 /dev/md0

SATA SSD

#mdadm --create --verbose --assume-clean /dev/md1 --level=1 --raid-devices=6 /dev/sd[a-f]1
#blkdiscard /dev/md1
#mdadm --create --verbose --assume-clean /dev/md2 --chunk-size=512 --level=6 --raid-devices=6 /dev/sd[a-f]2

Miért olyan nagy...?A darab méretének növelése pozitív hatással van a véletlenszerű olvasás sebességére blokkokban egészen a darabméretig. Ez azért van így, mert egy megfelelő méretű vagy kisebb művelet teljes egészében elvégezhető egyetlen eszközön. Ezért az összes eszköz IOPS-értékét összegzik. A statisztikák szerint az IO 99%-a nem haladja meg az 512K-t.

RAID 6 IOPS írásonként mindig kisebb vagy egyenlő, mint egy meghajtó IOPS-e. Amikor véletlenszerű olvasásként az IOPS többszöröse lehet egy meghajtóénak, és itt a blokk mérete kulcsfontosságú.
A szerző nem látja értelmét annak, hogy egy rossz paramétert próbáljanak optimalizálni a RAID 6 melléktervében, hanem azt optimalizálják, amiben a RAID 6 jó.
A RAID 6 rossz véletlenszerű írását NVMe gyorsítótárral és vékony kiépítési trükkökkel kompenzáljuk.

Még nem engedélyeztük a DISCARD funkciót a RAID 6-hoz. Tehát egyelőre nem „inicializáljuk” ezt a tömböt. Ezt később, az operációs rendszer telepítése után tesszük meg.

SATA merevlemez

#mdadm --create --verbose --assume-clean /dev/md3 --chunk-size=512 --level=6 --raid-devices=8 /dev/sd[g-n]1

LVM NVMe RAID-en

A gyorsaság érdekében a gyökérfájlrendszert az NVMe RAID 1-en szeretnénk elhelyezni, ami a /dev/md0.
Erre a gyors tömbre azonban továbbra is szükségünk lesz más igényekhez, mint például a csere, a metaadatok és az LVM-gyorsítótár és az LVM-vékony metaadatok, ezért ezen a tömbön fogunk létrehozni egy LVM VG-t.

#pvcreate /dev/md0
#vgcreate root /dev/md0

Hozzunk létre egy partíciót a gyökér fájlrendszer számára.

#lvcreate -L 128G --name root root

Hozzunk létre egy partíciót a cseréhez a RAM méretének megfelelően.

#lvcreate -L 32G --name swap root

OS telepítése

Összességében mindennel rendelkezünk, ami a rendszer telepítéséhez szükséges.

Indítsa el a rendszertelepítő varázslót az Ubuntu Live környezetből. Normál telepítés. Csak a telepítéshez szükséges lemezek kiválasztásának szakaszában kell megadnia a következőket:

  • /dev/md1, - csatolási pont /boot, FS - BTRFS
  • /dev/root/root (más néven /dev/mapper/root-root), - csatolási pont / (gyökér), FS - BTRFS
  • /dev/root/swap (más néven /dev/mapper/root-swap), - swap partícióként használható
  • Telepítse a rendszerbetöltőt a /dev/sda könyvtárba

Ha a BTRFS-t választja ki gyökérfájlrendszerként, a telepítő automatikusan létrehoz két BTRFS-kötetet, amelyek neve „@” a / (root), és „@home” a /home számára.

Kezdjük a telepítést...

A telepítés egy modális párbeszédpanelen zárul, amely a rendszerbetöltő telepítésének hibáját jelzi. Sajnos nem tud normál eszközökkel kilépni ebből a párbeszédpanelből, és folytatni a telepítést. Kijelentkezünk a rendszerből, majd újra bejelentkezünk, így egy tiszta Ubuntu Live asztalra kerülünk. Nyissa meg a terminált, és ismét:

#sudo bash

Hozzon létre egy chroot környezetet a telepítés folytatásához:

#mkdir /mnt/chroot
#mount -o defaults,space_cache,noatime,nodiratime,discard,subvol=@ /dev/mapper/root-root /mnt/chroot
#mount -o defaults,space_cache,noatime,nodiratime,discard,subvol=@home /dev/mapper/root-root /mnt/chroot/home
#mount -o defaults,space_cache,noatime,nodiratime,discard /dev/md1 /mnt/chroot/boot
#mount --bind /proc /mnt/chroot/proc
#mount --bind /sys /mnt/chroot/sys
#mount --bind /dev /mnt/chroot/dev

Állítsuk be a hálózatot és a gazdagépnevet a chrootban:

#cat /etc/hostname >/mnt/chroot/etc/hostname
#cat /etc/hosts >/mnt/chroot/etc/hosts
#cat /etc/resolv.conf >/mnt/chroot/etc/resolv.conf

Menjünk a chroot környezetbe:

#chroot /mnt/chroot

Első körben a csomagokat szállítjuk ki:

apt-get install --reinstall mdadm lvm2 thin-provisioning-tools btrfs-tools util-linux lsscsi nvme-cli mc debsums hdparm

Ellenőrizzük és javítsuk ki az összes olyan csomagot, amely a rendszer telepítésének hiánya miatt rosszul lett telepítve:

#CORRUPTED_PACKAGES=$(debsums -s 2>&1 | awk '{print $6}' | uniq)
#apt-get install --reinstall $CORRUPTED_PACKAGES

Ha valami nem sikerül, lehet, hogy először módosítani kell az /etc/apt/sources.list fájlt

Állítsuk be a RAID 6 modul paramétereit a TRIM/DISCARD engedélyezéséhez:

#cat >/etc/modprobe.d/raid456.conf << EOF
options raid456 devices_handle_discard_safely=1
EOF

Csináljunk egy kicsit a tömbjeinket:

#cat >/etc/udev/rules.d/60-md.rules << EOF
SUBSYSTEM=="block", KERNEL=="md*", ACTION=="change", TEST=="md/stripe_cache_size", ATTR{md/stripe_cache_size}="32768"
SUBSYSTEM=="block", KERNEL=="md*", ACTION=="change", TEST=="md/sync_speed_min", ATTR{md/sync_speed_min}="48000"
SUBSYSTEM=="block", KERNEL=="md*", ACTION=="change", TEST=="md/sync_speed_max", ATTR{md/sync_speed_max}="300000"
EOF
#cat >/etc/udev/rules.d/62-hdparm.rules << EOF
SUBSYSTEM=="block", ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", RUN+="/sbin/hdparm -B 254 /dev/%k"
EOF
#cat >/etc/udev/rules.d/63-blockdev.rules << EOF
SUBSYSTEM=="block", ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", RUN+="/sbin/blockdev --setra 1024 /dev/%k"
SUBSYSTEM=="block", ACTION=="add|change", KERNEL=="md*", RUN+="/sbin/blockdev --setra 0 /dev/%k"
EOF

Mi volt az..?Létrehoztunk egy udev-szabálykészletet, amely a következőket teszi:

  • Állítsa be a RAID 2020 blokk-gyorsítótár méretét úgy, hogy 6-ra megfelelő legyen. Az alapértelmezett érték, úgy tűnik, nem változott a Linux létrejötte óta, és hosszú ideje nem volt megfelelő.
  • Foglaljon le egy minimális IO-t a tömbellenőrzések/szinkronizálások idejére. Ezzel elkerülhető, hogy a tömbök terhelés alatt az örök szinkronizálás állapotában ragadjanak.
  • Korlátozza a maximális IO-t a tömbök ellenőrzése/szinkronizálása során. Erre azért van szükség, hogy az SSD RAID-ek szinkronizálása/ellenőrzése ne süsse ropogósra a meghajtókat. Ez különösen igaz az NVMe-re. (Emlékszel a radiátorra? Nem vicceltem.)
  • Tiltsa le a lemezeket, hogy az APM-en keresztül leállítsák az orsó forgását (HDD), és állítsa be a lemezvezérlők alvási időkorlátját 7 órára. Teljesen letilthatja az APM-et, ha a meghajtói meg tudják csinálni (-B 255). Az alapértelmezett értéknél a meghajtók öt másodperc után leállnak. Ezután az operációs rendszer vissza akarja állítani a lemez gyorsítótárát, a lemezek újra felpörögnek, és minden kezdődik elölről. A tárcsák korlátozott maximális orsófordulatszámmal rendelkeznek. Egy ilyen egyszerű alapértelmezett ciklus könnyen megölheti a lemezeket néhány év alatt. Nem minden lemez szenved ettől, de a miénk „laptopos”, a megfelelő alapértelmezett beállításokkal, amitől a RAID mini-MAID-nek tűnik.
  • Readahead telepítése lemezekre (forgó) 1 megabájt – két egymást követő blokk/darab RAID 6
  • Az előreolvasás letiltása magukon a tömbökön.

Szerkesszük az /etc/fstab fájlt:

#cat >/etc/fstab << EOF
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
# file-system mount-point type options dump pass
/dev/mapper/root-root / btrfs defaults,space_cache,noatime,nodiratime,discard,subvol=@ 0 1
UUID=$(blkid -o value -s UUID /dev/md1) /boot btrfs defaults,space_cache,noatime,nodiratime,discard 0 2
/dev/mapper/root-root /home btrfs defaults,space_cache,noatime,nodiratime,discard,subvol=@home 0 2
/dev/mapper/root-swap none swap sw 0 0
EOF

Miert van az..?A /boot partíciót UUID alapján fogjuk megkeresni. A tömb elnevezése elméletileg változhat.

A fennmaradó szakaszokat LVM nevek alapján fogjuk keresni a /dev/mapper/vg-lv jelölésben, mert meglehetősen egyedi módon azonosítják a partíciókat.

Nem használunk UUID-t LVM-hez, mert Az LVM-kötetek és pillanatképeik UUID-je megegyezhet.Csatlakoztassa /dev/mapper/root-root.. kétszer?Igen. Pontosan. A BTRFS jellemzője. Ez a fájlrendszer többször is felcsatolható különböző alvoltokkal.

Ugyanezen funkció miatt azt javaslom, hogy soha ne készítsenek LVM-pillanatképeket az aktív BTRFS-kötetekről. Újraindításkor meglepetés érheti.

Állítsuk újra az mdadm konfigurációt:

#/usr/share/mdadm/mkconf | sed 's/#DEVICE/DEVICE/g' >/etc/mdadm/mdadm.conf

Állítsuk be az LVM beállításait:

#cat >>/etc/lvm/lvmlocal.conf << EOF

activation {
thin_pool_autoextend_threshold=90
thin_pool_autoextend_percent=5
}
allocation {
cache_pool_max_chunks=2097152
}
devices {
global_filter=["r|^/dev/.*_corig$|","r|^/dev/.*_cdata$|","r|^/dev/.*_cmeta$|","r|^/dev/.*gpv$|","r|^/dev/images/.*$|","r|^/dev/mapper/images.*$|","r|^/dev/backup/.*$|","r|^/dev/mapper/backup.*$|"] issue_discards=1
}
EOF

Mi volt az..?Lehetővé tettük az LVM vékony medencék automatikus bővítését, ha az elfoglalt terület 90%-át a térfogat 5%-ával elérik.

Megnöveltük a gyorsítótár blokkok maximális számát az LVM gyorsítótárhoz.

Megakadályoztuk az LVM-et abban, hogy LVM köteteket (PV) keressen a következő helyen:

  • LVM gyorsítótárat (cdata) tartalmazó eszközök
  • az LVM gyorsítótár használatával gyorsítótárazott eszközök, a gyorsítótár megkerülésével ( _corig). Ebben az esetben magát a gyorsítótárban lévő eszközt továbbra is a rendszer a gyorsítótáron keresztül vizsgálja (csak ).
  • LVM gyorsítótár metaadatokat (cmeta) tartalmazó eszközök
  • az összes VG-beli eszköz a névképekkel. Itt a virtuális gépek lemezképei lesznek, és nem akarjuk, hogy a gazdagépen lévő LVM aktiválja a vendég operációs rendszerhez tartozó köteteket.
  • minden eszköz a VG-ben a biztonsági mentés névvel. Itt lesz a virtuális gép képeinek biztonsági másolata.
  • minden olyan eszköz, amelynek neve „gpv”-re végződik (vendég fizikai kötet)

Engedélyeztük a DISCARD támogatást, amikor szabad helyet szabadítunk fel az LVM VG-n. Légy óvatos. Ez meglehetősen időigényessé teszi az LV-k törlését az SSD-ről. Ez különösen igaz az SSD RAID 6-ra. A terv szerint azonban vékony kiépítést fogunk alkalmazni, így ez egyáltalán nem fog akadályozni.

Frissítsük az initramfs képet:

#update-initramfs -u -k all

A grub telepítése és konfigurálása:

#apt-get install grub-pc
#apt-get purge os-prober
#dpkg-reconfigure grub-pc

Milyen lemezeket érdemes választani?Mindenki, aki sd*. A rendszernek képesnek kell lennie bármely működő SATA-meghajtóról vagy SSD-ről indítani.

Miért adtak hozzá os-prober..-t?A túlzott önállóságért és játékos kezekért.

Nem működik megfelelően, ha az egyik RAID leromlott állapotban van. Megpróbálja megkeresni az operációs rendszert azokon a partíciókon, amelyeket az ezen a hardveren futó virtuális gépeken használnak.

Ha szüksége van rá, elhagyhatja, de tartsa szem előtt a fentieket. Azt javaslom, hogy keress online recepteket a szemtelen kezek megszabadulására.

Ezzel a kezdeti telepítést befejeztük. Ideje újraindítani az újonnan telepített operációs rendszert. Ne felejtse el eltávolítani a rendszerindító Live CD/USB-t.

#exit
#reboot

Válasszon ki egy SATA SSD-t rendszerindító eszközként.

LVM SATA SSD-n

Ezen a ponton már elindítottuk az új operációs rendszert, konfiguráltuk a hálózatot, megnyitottuk a terminál emulátort, és elindítottuk:

#sudo bash

Folytassuk.

„Inicializálja” a tömböt SATA SSD-ről:

#blkdiscard /dev/md2

Ha nem működik, próbálkozzon:

#blkdiscard --step 65536 /dev/md2
LVM VG létrehozása SATA SSD-n:

#pvcreate /dev/md2
#vgcreate data /dev/md2

Miért még egy VG..?Valójában már van egy root nevű VG-nk. Miért nem ad hozzá mindent egy VG-be?

Ha egy VG-ben több PV van, akkor a VG megfelelő aktiválásához minden PV-nek jelen kell lennie (online). A kivétel az LVM RAID, amelyet szándékosan nem használunk.

Nagyon szeretnénk, ha meghibásodás (olvasási adatvesztés) történik valamelyik RAID 6 tömbön, akkor az operációs rendszer rendesen elinduljon, és lehetőséget adjon a probléma megoldására.

Ehhez az absztrakció első szintjén minden fizikai „médiát” külön VG-be fogunk elkülöníteni.

Tudományosan szólva, a különböző RAID-tömbök különböző „megbízhatósági tartományokhoz” tartoznak. Nem szabad további közös hibapontot létrehozni számukra azzal, hogy egy VG-be zsúfolják őket.

Az LVM jelenléte „hardver” szinten lehetővé teszi, hogy különböző RAID-tömbök darabjait tetszőlegesen kivágjuk, különböző módon kombinálva őket. Például - fuss egyszerre bcache + LVM vékony, bcache + BTRFS, LVM gyorsítótár + LVM vékony, összetett ZFS-konfiguráció gyorsítótárral, vagy bármilyen más pokoli keverék, hogy megpróbálja összehasonlítani az egészet.

„Hardver” szinten nem fogunk mást használni, mint a jó öreg „vastag” LVM köteteket. Ez alól a szabály alól kivétel lehet a biztonsági mentési partíció.

Azt hiszem, ebben a pillanatban sok olvasó már kezdett gyanakodni valamit a fészkelő babával kapcsolatban.

LVM SATA HDD-n

#pvcreate /dev/md3
#vgcreate backup /dev/md3

Megint új VG..?Nagyon szeretnénk, ha az adatmentésre használt lemeztömb meghibásodik, operációs rendszerünk továbbra is a megszokott módon működjön, miközben a szokásos módon hozzáférhet a nem biztonsági mentéshez szükséges adatokhoz. Ezért a VG aktiválási problémák elkerülése érdekében külön VG-t hozunk létre.

LVM gyorsítótár beállítása

Hozzon létre egy LV-t az NVMe RAID 1-en, hogy gyorsítótárként használhassa.

#lvcreate -L 70871154688B --name cache root

Miért olyan kevés...?A helyzet az, hogy NVMe SSD-ink SLC gyorsítótárral is rendelkeznek. 4 gigabájt „szabad” és 18 gigabájt dinamikus a 3 bites MLC-ben elfoglalt szabad hely miatt. Ha ez a gyorsítótár kimerült, az NVMe SSD-k nem lesznek sokkal gyorsabbak, mint a gyorsítótárral rendelkező SATA SSD-ink. Valójában ezért nincs értelme, hogy az LVM gyorsítótár-partíciót sokkal nagyobbra tegyük, mint az NVMe meghajtó SLC gyorsítótárának kétszeresét. A felhasznált NVMe meghajtóknál a szerző 32-64 gigabájt gyorsítótár készítését tartja indokoltnak.

A megadott partícióméret 64 gigabájt gyorsítótár, gyorsítótár metaadatok és metaadatok biztonsági mentésének rendezéséhez szükséges.

Ezenkívül megjegyzem, hogy egy piszkos rendszerleállás után az LVM a teljes gyorsítótárat piszkosként jelöli meg, és újra szinkronizál. Sőt, ez megismétlődik minden alkalommal, amikor az lvchange parancsot használják ezen az eszközön, amíg a rendszer újra nem indul. Ezért azt javaslom, hogy azonnal hozza létre újra a gyorsítótárat a megfelelő szkript segítségével.

Hozzon létre egy LV-t a SATA RAID 6-on, hogy gyorsítótárazott eszközként használhassa.

#lvcreate -L 3298543271936B --name cache data

Miért csak három terabájt..?Így szükség esetén használhatja a SATA SSD RAID 6-ot más igényekre. A gyorsítótárazott terület mérete dinamikusan, menet közben, a rendszer leállítása nélkül növelhető. Ehhez ideiglenesen le kell állítani és újra engedélyezni kell a gyorsítótárat, de az LVM-cache megkülönböztető előnye például a bcache-hez képest, hogy ezt menet közben is meg lehet tenni.

Hozzunk létre egy új VG-t a gyorsítótárazáshoz.

#pvcreate /dev/root/cache
#pvcreate /dev/data/cache
#vgcreate cache /dev/root/cache /dev/data/cache

Hozzon létre egy LV-t a gyorsítótárazott eszközön.

#lvcreate -L 3298539077632B --name cachedata cache /dev/data/cache

Itt azonnal elfoglaltuk a /dev/data/cache összes szabad területét, így az összes többi szükséges partíció azonnal létrejött a /dev/root/cache oldalon. Ha rossz helyen hozott létre valamit, a pvmove segítségével áthelyezheti.

Hozzuk létre és engedélyezzük a gyorsítótárat:

#lvcreate -y -L 64G -n cache cache /dev/root/cache
#lvcreate -y -L 1G -n cachemeta cache /dev/root/cache
#lvconvert -y --type cache-pool --cachemode writeback --chunksize 64k --poolmetadata cache/cachemeta cache/cache
#lvconvert -y --type cache --cachepool cache/cache cache/cachedata

Miért ilyen darabok..?Gyakorlati kísérletekkel a szerző rájött, hogy a legjobb eredményt akkor érjük el, ha az LVM cache blokk mérete egybeesik az LVM vékony blokk méretével. Sőt, minél kisebb a méret, annál jobban teljesít a konfiguráció véletlenszerű felvételen.

64k a legkisebb megengedett blokkméret az LVM vékonyhoz.

Legyen óvatos az írással..!Igen. Az ilyen típusú gyorsítótár késlelteti az írási szinkronizálást a gyorsítótárazott eszközzel. Ez azt jelenti, hogy a gyorsítótár elvesztése esetén a gyorsítótárazott eszközön lévő adatok elveszhetnek. Később a szerző elmondja, hogy az NVMe RAID 1 mellett milyen intézkedésekkel lehet kompenzálni ezt a kockázatot.

Ezt a gyorsítótártípust szándékosan választották ki, hogy kompenzálják a RAID 6 rossz véletlenszerű írási teljesítményét.

Nézzük, mit kaptunk:

#lvs -a -o lv_name,lv_size,devices --units B cache
LV LSize Devices
[cache] 68719476736B cache_cdata(0)
[cache_cdata] 68719476736B /dev/root/cache(0)
[cache_cmeta] 1073741824B /dev/root/cache(16384)
cachedata 3298539077632B cachedata_corig(0)
[cachedata_corig] 3298539077632B /dev/data/cache(0)
[lvol0_pmspare] 1073741824B /dev/root/cache(16640)

Csak a [cachedata_corig] lehet a /dev/data/cache könyvtárban. Ha valami nem stimmel, használd a pvmove-ot.

Ha szükséges, egy paranccsal letilthatja a gyorsítótárat:

#lvconvert -y --uncache cache/cachedata

Ez on-line történik. Az LVM egyszerűen szinkronizálja a gyorsítótárat a lemezzel, eltávolítja, és a cachedata_corig-ot visszanevezi cachedata-ra.

Az LVM vékony beállítása

Nagyjából becsüljük meg, mennyi helyre van szükségünk az LVM vékony metaadatokhoz:

#thin_metadata_size --block-size=64k --pool-size=6terabytes --max-thins=100000 -u bytes
thin_metadata_size - 3385794560 bytes estimated metadata area size for "--block-size=64kibibytes --pool-size=6terabytes --max-thins=100000"

Kerekítés 4 gigabájtig: 4294967296B

Szorozza meg kettővel, és adjon hozzá 4194304B-t az LVM PV metaadatokhoz: 8594128896B
Hozzon létre egy külön partíciót az NVMe RAID 1-en az LVM vékony metaadatok és azok biztonsági másolatának elhelyezéséhez:

#lvcreate -L 8594128896B --name images root

Miért..?Itt felmerülhet a kérdés: miért helyezzük el külön az LVM vékony metaadatokat, ha azok továbbra is gyorsítótárban lesznek az NVMe-n, és gyorsan működnek.

Bár itt a sebesség fontos, messze nem ez a fő ok. A helyzet az, hogy a gyorsítótár egy hibapont. Valami történhet vele, és ha az LVM vékony metaadatokat gyorsítótárazzák, akkor minden teljesen elveszik. Teljes metaadatok nélkül szinte lehetetlen lesz vékony köteteket összeállítani.

Ha a metaadatokat egy külön, nem gyorsítótárazott, de gyors kötetre helyezi át, garantáljuk a metaadatok biztonságát a gyorsítótár elvesztése vagy sérülése esetén. Ebben az esetben a gyorsítótár elvesztése által okozott károk vékony köteteken belül lesznek lokalizálva, ami nagyságrendekkel leegyszerűsíti a helyreállítási eljárást. Nagy valószínűséggel ezek a károk helyreállnak az FS naplók segítségével.

Sőt, ha előzőleg egy vékony kötetről készült pillanatfelvétel, és ezt követően a gyorsítótárat legalább egyszer teljesen szinkronizálták, akkor az LVM vékony belső kialakítása miatt a pillanatfelvétel integritása garantált a gyorsítótár elvesztése esetén. .

Hozzunk létre egy új VG-t, amely a vékony-kiépítésért lesz felelős:

#pvcreate /dev/root/images
#pvcreate /dev/cache/cachedata
#vgcreate images /dev/root/images /dev/cache/cachedata

Hozzunk létre egy medencét:

#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T images/thin-pool
Miért -Z yAmellett, hogy ez a mód valójában mire szolgál – annak megakadályozására, hogy az egyik virtuális gépről származó adatok egy másik virtuális gépre szivárogjanak a hely újraelosztása során – a nullázást ezenkívül a véletlenszerű írás sebességének növelésére is használják 64 KB-nál kisebb blokkokban. A 64 KB-nál kisebb írás a vékony kötet korábban le nem osztott területére 64 KB-ra lesz igazítva a gyorsítótárban. Ez lehetővé teszi a művelet teljes egészében a gyorsítótáron keresztül történő végrehajtását, a gyorsítótárazott eszköz megkerülésével.

Helyezzük át az LV-ket a megfelelő PV-kre:

#pvmove -n images/thin-pool_tdata /dev/root/images /dev/cache/cachedata
#pvmove -n images/lvol0_pmspare /dev/cache/cachedata /dev/root/images
#pvmove -n images/thin-pool_tmeta /dev/cache/cachedata /dev/root/images

Nézzük meg:

#lvs -a -o lv_name,lv_size,devices --units B images
LV LSize Devices
[lvol0_pmspare] 4294967296B /dev/root/images(0)
thin-pool 274877906944B thin-pool_tdata(0)
[thin-pool_tdata] 274877906944B /dev/cache/cachedata(0)
[thin-pool_tmeta] 4294967296B /dev/root/images(1024)

Hozzunk létre egy vékony kötetet a tesztekhez:

#lvcreate -V 64G --thin-pool thin-pool --name test images

Csomagokat telepítünk tesztekhez és monitorozáshoz:

#apt-get install sysstat fio

Így figyelheti meg valós időben a tárolási konfigurációnk viselkedését:

#watch 'lvs --rows --reportformat basic --quiet -ocache_dirty_blocks,cache_settings cache/cachedata && (lvdisplay cache/cachedata | grep Cache) && (sar -p -d 2 1 | grep -E "sd|nvme|DEV|md1|md2|md3|md0" | grep -v Average | sort)'

Így tesztelhetjük konfigurációnkat:

#fio --loops=1 --size=64G --runtime=4 --filename=/dev/images/test --stonewall --ioengine=libaio --direct=1
--name=4kQD32read --bs=4k --iodepth=32 --rw=randread
--name=8kQD32read --bs=8k --iodepth=32 --rw=randread
--name=16kQD32read --bs=16k --iodepth=32 --rw=randread
--name=32KQD32read --bs=32k --iodepth=32 --rw=randread
--name=64KQD32read --bs=64k --iodepth=32 --rw=randread
--name=128KQD32read --bs=128k --iodepth=32 --rw=randread
--name=256KQD32read --bs=256k --iodepth=32 --rw=randread
--name=512KQD32read --bs=512k --iodepth=32 --rw=randread
--name=4Kread --bs=4k --rw=read
--name=8Kread --bs=8k --rw=read
--name=16Kread --bs=16k --rw=read
--name=32Kread --bs=32k --rw=read
--name=64Kread --bs=64k --rw=read
--name=128Kread --bs=128k --rw=read
--name=256Kread --bs=256k --rw=read
--name=512Kread --bs=512k --rw=read
--name=Seqread --bs=1m --rw=read
--name=Longread --bs=8m --rw=read
--name=Longwrite --bs=8m --rw=write
--name=Seqwrite --bs=1m --rw=write
--name=512Kwrite --bs=512k --rw=write
--name=256write --bs=256k --rw=write
--name=128write --bs=128k --rw=write
--name=64write --bs=64k --rw=write
--name=32write --bs=32k --rw=write
--name=16write --bs=16k --rw=write
--name=8write --bs=8k --rw=write
--name=4write --bs=4k --rw=write
--name=512KQD32write --bs=512k --iodepth=32 --rw=randwrite
--name=256KQD32write --bs=256k --iodepth=32 --rw=randwrite
--name=128KQD32write --bs=128k --iodepth=32 --rw=randwrite
--name=64KQD32write --bs=64k --iodepth=32 --rw=randwrite
--name=32KQD32write --bs=32k --iodepth=32 --rw=randwrite
--name=16KQD32write --bs=16k --iodepth=32 --rw=randwrite
--name=8KQD32write --bs=8k --iodepth=32 --rw=randwrite
--name=4kQD32write --bs=4k --iodepth=32 --rw=randwrite
| grep -E 'read|write|test' | grep -v ioengine

Gondosan! Forrás!Ez a kód 36 különböző tesztet fog futtatni, mindegyik 4 másodpercig fut. A tesztek fele rögzítésre szolgál. 4 másodperc alatt rengeteget rögzíthetsz az NVMe-n. Akár 3 gigabájt másodpercenként. Tehát minden írási teszt futtatása akár 216 gigabájt SSD-erőforrást is elfogyaszthat Öntől.

Írás és olvasás vegyesen?Igen. Érdemes külön futtatni az olvasási és írási teszteket. Ezen túlmenően célszerű gondoskodni arról, hogy az összes gyorsítótár szinkronizálva legyen, hogy a korábban végrehajtott írás ne befolyásolja az olvasást.

Az eredmények nagyban változnak az első indításkor és a későbbiekben, ahogy a gyorsítótár és a vékony kötet megtelik, illetve attól függően, hogy a rendszernek sikerült-e szinkronizálnia az utolsó indításkor feltöltött gyorsítótárakat.

Többek között azt javaslom, hogy mérje meg a sebességet egy már teljesen vékony köteten, amelyről éppen pillanatfelvétel készült. A szerzőnek lehetősége volt megfigyelni, hogy a véletlenszerű írások miként gyorsulnak fel hirtelen az első pillanatkép elkészítése után, különösen akkor, ha a gyorsítótár még nem teljesen megtelt. Ennek oka a másolás írásra írási szemantikája, a gyorsítótár és a vékony kötetblokkok egymáshoz igazítása, valamint az a tény, hogy a RAID 6-ba történő véletlenszerű írás a RAID 6-ból véletlenszerű olvasássá válik, amelyet a gyorsítótárba történő írás követ. A mi konfigurációnkban a RAID 6 véletlenszerű olvasása akár hatszor gyorsabb (a tömbben lévő SATA SSD-k száma) gyorsabb, mint az írás. Mert A CoW blokkjai szekvenciálisan kerülnek kiosztásra egy vékony készletből, majd a felvétel többnyire szintén szekvenciálissá válik.

Mindkét funkció az Ön javára használható.

Gyorsítótárazza a „koherens” pillanatképeket

A gyorsítótár sérülése/vesztése esetén az adatvesztés kockázatának csökkentése érdekében a szerző javasolja a pillanatképek forgatása gyakorlatának bevezetését az integritásuk garantálása érdekében.

Először is, mivel a vékony térfogatú metaadatok nem gyorsítótárazott eszközön találhatók, a metaadatok konzisztensek lesznek, és az esetleges veszteségeket adatblokkokon belül elkülönítik.

A következő pillanatkép-forgatási ciklus garantálja a pillanatképeken belüli adatok integritását gyorsítótár elvesztése esetén:

  1. Minden vékony, <név> nevű kötethez hozzon létre egy pillanatképet <név>.cached néven
  2. Állítsuk be az átállási küszöböt egy ésszerűen magas értékre: #lvchange --quiet --cachesettings "migration_threshold=16384" cache/cachedata
  3. A hurokban ellenőrizzük a gyorsítótárban lévő piszkos blokkok számát: #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' amíg nullát nem kapunk. Ha a nulla túl sokáig hiányzik, akkor a gyorsítótár ideiglenes átírási módba kapcsolásával hozható létre. Figyelembe véve azonban SATA és NVMe SSD tömbjeink sebességi jellemzőit, valamint TBW erőforrásaikat, akkor vagy gyorsan elkaphatja a pillanatot a gyorsítótár mód megváltoztatása nélkül, vagy a hardver teljesen felemészti a teljes erőforrását. néhány nap. Az erőforrások korlátai miatt a rendszer elvileg nem tud folyamatosan 100%-os írási terhelés alatt lenni. NVMe SSD-ink 100%-os írási terhelés alatt teljesen kimerítik az erőforrást 3-4 nap. A SATA SSD-k csak kétszer annyi ideig bírják. Ezért feltételezzük, hogy a terhelés nagy része az olvasásra megy, és viszonylag rövid ideig tartó, rendkívül nagy aktivitású sorozatokat tapasztalunk, amihez az írás átlagosan alacsony terhelése társul.
  4. Amint elkaptunk (vagy létrehoztunk) egy nullát, a <name>.cached nevet átnevezzük a <név>.committed névre. A régi <név>.committed törlődik.
  5. Opcionálisan, ha a gyorsítótár 100%-ban megtelt, egy szkript segítségével újra létrehozható, így törli. Félig üres gyorsítótár mellett a rendszer sokkal gyorsabban működik írás közben.
  6. Állítsa a migrációs küszöböt nullára: #lvchange --quiet --cachesettings "migration_threshold=0" cache/cachedata Ez átmenetileg megakadályozza a gyorsítótár szinkronizálását a fő adathordozóval.
  7. Megvárjuk, amíg elég sok változás halmozódik fel a gyorsítótárban #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' vagy az időzítő kikapcsol.
  8. Ismételjük meg újra.

Miért nehézségekbe ütközik a migrációs küszöb...?A helyzet az, hogy a gyakorlatban a „véletlenszerű” felvétel valójában nem teljesen véletlenszerű. Ha egy 4 kilobájt méretű szektorba írunk valamit, akkor nagy a valószínűsége annak, hogy a következő pár percben ugyanabba, vagy valamelyik szomszédos (+- 32K) szektorba rekord készül.

Az átállási küszöb nullára állításával elhalasztjuk az írási szinkronizálást a SATA SSD-n, és több módosítást összesítünk a gyorsítótár egy 64K-s blokkjában. Ez jelentősen megtakarítja a SATA SSD erőforrásait.

Hol a kód..?Sajnos a szerző nem tartja magát kellően kompetensnek a bash szkriptek fejlesztésében, mert 100%-ban autodidakta, és „google”-vezérelt fejlesztést folytat, ezért úgy gondolja, hogy a kezei közül kikerülő szörnyű kódot senki sem használhatja. más.

Úgy gondolom, hogy ezen a területen a szakemberek szükség esetén képesek lesznek önállóan lerajzolni a fent leírt logikát, és talán még gyönyörűen is megtervezik rendszerszolgáltatásként, ahogyan a szerző igyekezett.

Egy ilyen egyszerű pillanatfelvétel-forgatási séma nemcsak azt teszi lehetővé számunkra, hogy egy pillanatfelvételt folyamatosan teljesen szinkronizálva legyen a SATA SSD-n, hanem azt is lehetővé teszi számunkra, hogy a thin_delta segédprogram segítségével megtudjuk, mely blokkokat változtatták meg létrehozása után, és így lokalizálhatjuk a sérüléseket a fő kötetek, nagyban leegyszerűsítve a helyreállítást .

TRIM/DISCARD a libvirt/KVM-ben

Mert az adattárolást a libvirt futtató KVM fogja használni, akkor érdemes lenne megtanítani a virtuális gépeinket, hogy ne csak a szabad helyet foglalják el, hanem azt is, hogy felszabadítsák azt, ami már nem kell.

Ez a TRIM/DISCARD támogatás emulálásával valósítható meg a virtuális lemezeken. Ehhez módosítani kell a vezérlő típusát virtio-scsi-re, és módosítani kell az xml-t.

#virsh edit vmname
<disk type='block' device='disk'>
<driver name='qemu' type='raw' cache='writethrough' io='threads' discard='unmap'/>
<source dev='/dev/images/vmname'/>
<backingStore/>
<target dev='sda' bus='scsi'/>
<alias name='scsi0-0-0-0'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>

<controller type='scsi' index='0' model='virtio-scsi'>
<alias name='scsi0'/>
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</controller>

Az LVM megfelelően feldolgozza az ilyen DISCARD-okat a vendég operációs rendszerekből, és a blokkokat megfelelően felszabadítja mind a gyorsítótárban, mind a vékony készletben. Esetünkben ez főleg késleltetett módon, a következő pillanatkép törlésekor történik.

BTRFS biztonsági mentés

Használjon kész szkripteket szélső óvatosság és saját felelősségére. A szerző ezt a kódot saját maga és kizárólag saját maga írta. Biztos vagyok benne, hogy sok tapasztalt Linux-felhasználó rendelkezik hasonló eszközökkel, és nincs szükség másnak másolására.

Hozzunk létre egy kötetet a biztonsági mentési eszközön:

#lvcreate -L 256G --name backup backup

Formázzuk BTRFS-ben:

#mkfs.btrfs /dev/backup/backup

Hozzuk létre a csatolási pontokat, és csatoljuk a fájlrendszer gyökér alszakaszait:

#mkdir /backup
#mkdir /backup/btrfs
#mkdir /backup/btrfs/root
#mkdir /backup/btrfs/back
#ln -s /boot /backup/btrfs
# cat >>/etc/fstab << EOF

/dev/mapper/root-root /backup/btrfs/root btrfs defaults,space_cache,noatime,nodiratime 0 2
/dev/mapper/backup-backup /backup/btrfs/back btrfs defaults,space_cache,noatime,nodiratime 0 2
EOF
#mount -a
#update-initramfs -u
#update-grub

Hozzunk létre könyvtárakat a biztonsági mentésekhez:

#mkdir /backup/btrfs/back/remote
#mkdir /backup/btrfs/back/remote/root
#mkdir /backup/btrfs/back/remote/boot

Hozzunk létre egy könyvtárat a biztonsági mentési szkriptek számára:

#mkdir /root/btrfs-backup

Másoljuk a szkriptet:

Sok ijesztő bash kód. Használat csak saját felelősségre. Ne írj dühös levelet a szerzőnek...#cat >/root/btrfs-backup/btrfs-backup.sh << EOF
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

SCRIPT_FILE="$(realpath $0)"
SCRIPT_DIR="$(dirname $SCRIPT_FILE)"
SCRIPT_NAME="$(basename -s .sh $SCRIPT_FILE)"

LOCK_FILE="/dev/shm/$SCRIPT_NAME.lock"
DATE_PREFIX='%Y-%m-%d'
DATE_FORMAT=$DATE_PREFIX'-%H-%M-%S'
DATE_REGEX='[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
BASE_SUFFIX=".@base"
PEND_SUFFIX=".@pend"
SNAP_SUFFIX=".@snap"
MOUNTS="/backup/btrfs/"
BACKUPS="/backup/btrfs/back/remote/"

function terminate ()
{
echo "$1" >&2
exit 1
}

function wait_lock()
{
flock 98
}

function wait_lock_or_terminate()
{
echo "Wating for lock..."
wait_lock || terminate "Failed to get lock. Exiting..."
echo "Got lock..."
}

function suffix()
{
FORMATTED_DATE=$(date +"$DATE_FORMAT")
echo "$SNAP_SUFFIX.$FORMATTED_DATE"
}

function filter()
{
FORMATTED_DATE=$(date --date="$1" +"$DATE_PREFIX")
echo "$SNAP_SUFFIX.$FORMATTED_DATE"
}

function backup()
{
SOURCE_PATH="$MOUNTS$1"
TARGET_PATH="$BACKUPS$1"
SOURCE_BASE_PATH="$MOUNTS$1$BASE_SUFFIX"
TARGET_BASE_PATH="$BACKUPS$1$BASE_SUFFIX"
TARGET_BASE_DIR="$(dirname $TARGET_BASE_PATH)"
SOURCE_PEND_PATH="$MOUNTS$1$PEND_SUFFIX"
TARGET_PEND_PATH="$BACKUPS$1$PEND_SUFFIX"
if [ -d "$SOURCE_BASE_PATH" ] then
echo "$SOURCE_BASE_PATH found"
else
echo "$SOURCE_BASE_PATH File not found creating snapshot of $SOURCE_PATH to $SOURCE_BASE_PATH"
btrfs subvolume snapshot -r $SOURCE_PATH $SOURCE_BASE_PATH
sync
if [ -d "$TARGET_BASE_PATH" ] then
echo "$TARGET_BASE_PATH found out of sync with source... removing..."
btrfs subvolume delete -c $TARGET_BASE_PATH
sync
fi
fi
if [ -d "$TARGET_BASE_PATH" ] then
echo "$TARGET_BASE_PATH found"
else
echo "$TARGET_BASE_PATH not found. Synching to $TARGET_BASE_DIR"
btrfs send $SOURCE_BASE_PATH | btrfs receive $TARGET_BASE_DIR
sync
fi
if [ -d "$SOURCE_PEND_PATH" ] then
echo "$SOURCE_PEND_PATH found removing..."
btrfs subvolume delete -c $SOURCE_PEND_PATH
sync
fi
btrfs subvolume snapshot -r $SOURCE_PATH $SOURCE_PEND_PATH
sync
if [ -d "$TARGET_PEND_PATH" ] then
echo "$TARGET_PEND_PATH found removing..."
btrfs subvolume delete -c $TARGET_PEND_PATH
sync
fi
echo "Sending $SOURCE_PEND_PATH to $TARGET_PEND_PATH"
btrfs send -p $SOURCE_BASE_PATH $SOURCE_PEND_PATH | btrfs receive $TARGET_BASE_DIR
sync
TARGET_DATE_SUFFIX=$(suffix)
btrfs subvolume snapshot -r $TARGET_PEND_PATH "$TARGET_PATH$TARGET_DATE_SUFFIX"
sync
btrfs subvolume delete -c $SOURCE_BASE_PATH
sync
btrfs subvolume delete -c $TARGET_BASE_PATH
sync
mv $SOURCE_PEND_PATH $SOURCE_BASE_PATH
mv $TARGET_PEND_PATH $TARGET_BASE_PATH
sync
}

function list()
{
LIST_TARGET_BASE_PATH="$BACKUPS$1$BASE_SUFFIX"
LIST_TARGET_BASE_DIR="$(dirname $LIST_TARGET_BASE_PATH)"
LIST_TARGET_BASE_NAME="$(basename -s .$BASE_SUFFIX $LIST_TARGET_BASE_PATH)"
find "$LIST_TARGET_BASE_DIR" -maxdepth 1 -mindepth 1 -type d -printf "%fn" | grep "${LIST_TARGET_BASE_NAME/$BASE_SUFFIX/$SNAP_SUFFIX}.$DATE_REGEX"
}

function remove()
{
REMOVE_TARGET_BASE_PATH="$BACKUPS$1$BASE_SUFFIX"
REMOVE_TARGET_BASE_DIR="$(dirname $REMOVE_TARGET_BASE_PATH)"
btrfs subvolume delete -c $REMOVE_TARGET_BASE_DIR/$2
sync
}

function removeall()
{
DATE_OFFSET="$2"
FILTER="$(filter "$DATE_OFFSET")"
while read -r SNAPSHOT ; do
remove "$1" "$SNAPSHOT"
done < <(list "$1" | grep "$FILTER")

}

(
COMMAND="$1"
shift

case "$COMMAND" in
"--help")
echo "Help"
;;
"suffix")
suffix
;;
"filter")
filter "$1"
;;
"backup")
wait_lock_or_terminate
backup "$1"
;;
"list")
list "$1"
;;
"remove")
wait_lock_or_terminate
remove "$1" "$2"
;;
"removeall")
wait_lock_or_terminate
removeall "$1" "$2"
;;
*)
echo "None.."
;;
esac
) 98>$LOCK_FILE

EOF

Mégis mit csinál..?Egy sor egyszerű parancsot tartalmaz a BTRFS-pillanatképek létrehozásához és egy másik FS-be másolásához a BTRFS küldés/fogadás segítségével.

Az első indítás viszonylag hosszú lehet, mert... Kezdetben minden adat másolásra kerül. A további indulások nagyon gyorsak lesznek, mert... Csak a módosítások másolása megtörténik.

Egy másik szkript, amelyet a cronba helyezünk:

Még néhány bash kód#cat >/root/btrfs-backup/cron-daily.sh << EOF
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

SCRIPT_FILE="$(realpath $0)"
SCRIPT_DIR="$(dirname $SCRIPT_FILE)"
SCRIPT_NAME="$(basename -s .sh $SCRIPT_FILE)"

BACKUP_SCRIPT="$SCRIPT_DIR/btrfs-backup.sh"
RETENTION="-60 day"
$BACKUP_SCRIPT backup root/@
$BACKUP_SCRIPT removeall root/@ "$RETENTION"
$BACKUP_SCRIPT backup root/@home
$BACKUP_SCRIPT removeall root/@home "$RETENTION"
$BACKUP_SCRIPT backup boot/
$BACKUP_SCRIPT removeall boot/ "$RETENTION"
EOF

Mit csinal..?Létrehozza és szinkronizálja a felsorolt ​​BTRFS-kötetek növekményes pillanatképeit a biztonsági mentési FS-en. Ezt követően törli az összes 60 napja készített képet. Az indítás után a felsorolt ​​kötetek dátumozott pillanatképei megjelennek a /backup/btrfs/back/remote/ alkönyvtárban.

Adjuk meg a kódvégrehajtási jogokat:

#chmod +x /root/btrfs-backup/cron-daily.sh
#chmod +x /root/btrfs-backup/btrfs-backup.sh

Nézzük meg és tegyük a cronba:

#/usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/btrfs-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t btrfs-backup
#cat /var/log/syslog | grep btrfs-backup
#crontab -e
0 2 * * * /usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/btrfs-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t btrfs-backup

LVM vékony biztonsági mentés

Hozzon létre egy vékony készletet a biztonsági mentési eszközön:

#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T backup/thin-pool

Telepítsük a ddrescue-t, mert... A szkriptek ezt az eszközt fogják használni:

#apt-get install gddrescue

Hozzunk létre egy könyvtárat a szkriptek számára:

#mkdir /root/lvm-thin-backup

Másoljuk a szkripteket:

Rengeteg balhé belül...#cat >/root/lvm-thin-backup/lvm-thin-backup.sh << EOF
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

SCRIPT_FILE="$(realpath $0)"
SCRIPT_DIR="$(dirname $SCRIPT_FILE)"
SCRIPT_NAME="$(basename -s .sh $SCRIPT_FILE)"

LOCK_FILE="/dev/shm/$SCRIPT_NAME.lock"
DATE_PREFIX='%Y-%m-%d'
DATE_FORMAT=$DATE_PREFIX'-%H-%M-%S'
DATE_REGEX='[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
BASE_SUFFIX=".base"
PEND_SUFFIX=".pend"
SNAP_SUFFIX=".snap"
BACKUPS="backup"
BACKUPS_POOL="thin-pool"

export LVM_SUPPRESS_FD_WARNINGS=1

function terminate ()
{
echo "$1" >&2
exit 1
}

function wait_lock()
{
flock 98
}

function wait_lock_or_terminate()
{
echo "Wating for lock..."
wait_lock || terminate "Failed to get lock. Exiting..."
echo "Got lock..."
}

function suffix()
{
FORMATTED_DATE=$(date +"$DATE_FORMAT")
echo "$SNAP_SUFFIX.$FORMATTED_DATE"
}

function filter()
{
FORMATTED_DATE=$(date --date="$1" +"$DATE_PREFIX")
echo "$SNAP_SUFFIX.$FORMATTED_DATE"
}

function read_thin_id {
lvs --rows --reportformat basic --quiet -othin_id "$1/$2" | awk '{print $2}'
}

function read_pool_lv {
lvs --rows --reportformat basic --quiet -opool_lv "$1/$2" | awk '{print $2}'
}

function read_lv_dm_path {
lvs --rows --reportformat basic --quiet -olv_dm_path "$1/$2" | awk '{print $2}'
}

function read_lv_active {
lvs --rows --reportformat basic --quiet -olv_active "$1/$2" | awk '{print $2}'
}

function read_lv_chunk_size {
lvs --rows --reportformat basic --quiet --units b --nosuffix -ochunk_size "$1/$2" | awk '{print $2}'
}

function read_lv_size {
lvs --rows --reportformat basic --quiet --units b --nosuffix -olv_size "$1/$2" | awk '{print $2}'
}

function activate_volume {
lvchange -ay -Ky "$1/$2"
}

function deactivate_volume {
lvchange -an "$1/$2"
}

function read_thin_metadata_snap {
dmsetup status "$1" | awk '{print $7}'
}

function thindiff()
{
DIFF_VG="$1"
DIFF_SOURCE="$2"
DIFF_TARGET="$3"
DIFF_SOURCE_POOL=$(read_pool_lv $DIFF_VG $DIFF_SOURCE)
DIFF_TARGET_POOL=$(read_pool_lv $DIFF_VG $DIFF_TARGET)

if [ "$DIFF_SOURCE_POOL" == "" ] then
(>&2 echo "Source LV is not thin.")
exit 1
fi

if [ "$DIFF_TARGET_POOL" == "" ] then
(>&2 echo "Target LV is not thin.")
exit 1
fi

if [ "$DIFF_SOURCE_POOL" != "$DIFF_TARGET_POOL" ] then
(>&2 echo "Source and target LVs belong to different thin pools.")
exit 1
fi

DIFF_POOL_PATH=$(read_lv_dm_path $DIFF_VG $DIFF_SOURCE_POOL)
DIFF_SOURCE_ID=$(read_thin_id $DIFF_VG $DIFF_SOURCE)
DIFF_TARGET_ID=$(read_thin_id $DIFF_VG $DIFF_TARGET)
DIFF_POOL_PATH_TPOOL="$DIFF_POOL_PATH-tpool"
DIFF_POOL_PATH_TMETA="$DIFF_POOL_PATH"_tmeta
DIFF_POOL_METADATA_SNAP=$(read_thin_metadata_snap $DIFF_POOL_PATH_TPOOL)

if [ "$DIFF_POOL_METADATA_SNAP" != "-" ] then
(>&2 echo "Thin pool metadata snapshot already exist. Assuming stale one. Will release metadata snapshot in 5 seconds.")
sleep 5
dmsetup message $DIFF_POOL_PATH_TPOOL 0 release_metadata_snap
fi

dmsetup message $DIFF_POOL_PATH_TPOOL 0 reserve_metadata_snap
DIFF_POOL_METADATA_SNAP=$(read_thin_metadata_snap $DIFF_POOL_PATH_TPOOL)

if [ "$DIFF_POOL_METADATA_SNAP" == "-" ] then
(>&2 echo "Failed to create thin pool metadata snapshot.")
exit 1
fi

#We keep output in variable because metadata snapshot need to be released early.
DIFF_DATA=$(thin_delta -m$DIFF_POOL_METADATA_SNAP --snap1 $DIFF_SOURCE_ID --snap2 $DIFF_TARGET_ID $DIFF_POOL_PATH_TMETA)

dmsetup message $DIFF_POOL_PATH_TPOOL 0 release_metadata_snap

echo $"$DIFF_DATA" | grep -E 'different|left_only|right_only' | sed 's/</"/g' | sed 's/ /"/g' | awk -F'"' '{print $6 "t" $8 "t" $11}' | sed 's/different/copy/g' | sed 's/left_only/copy/g' | sed 's/right_only/discard/g'

}

function thinsync()
{
SYNC_VG="$1"
SYNC_PEND="$2"
SYNC_BASE="$3"
SYNC_TARGET="$4"
SYNC_PEND_POOL=$(read_pool_lv $SYNC_VG $SYNC_PEND)
SYNC_BLOCK_SIZE=$(read_lv_chunk_size $SYNC_VG $SYNC_PEND_POOL)
SYNC_PEND_PATH=$(read_lv_dm_path $SYNC_VG $SYNC_PEND)

activate_volume $SYNC_VG $SYNC_PEND

while read -r SYNC_ACTION SYNC_OFFSET SYNC_LENGTH ; do
SYNC_OFFSET_BYTES=$((SYNC_OFFSET * SYNC_BLOCK_SIZE))
SYNC_LENGTH_BYTES=$((SYNC_LENGTH * SYNC_BLOCK_SIZE))
if [ "$SYNC_ACTION" == "copy" ] then
ddrescue --quiet --force --input-position=$SYNC_OFFSET_BYTES --output-position=$SYNC_OFFSET_BYTES --size=$SYNC_LENGTH_BYTES "$SYNC_PEND_PATH" "$SYNC_TARGET"
fi

if [ "$SYNC_ACTION" == "discard" ] then
blkdiscard -o $SYNC_OFFSET_BYTES -l $SYNC_LENGTH_BYTES "$SYNC_TARGET"
fi
done < <(thindiff "$SYNC_VG" "$SYNC_PEND" "$SYNC_BASE")
}

function discard_volume()
{
DISCARD_VG="$1"
DISCARD_LV="$2"
DISCARD_LV_PATH=$(read_lv_dm_path "$DISCARD_VG" "$DISCARD_LV")
if [ "$DISCARD_LV_PATH" != "" ] then
echo "$DISCARD_LV_PATH found"
else
echo "$DISCARD_LV not found in $DISCARD_VG"
exit 1
fi
DISCARD_LV_POOL=$(read_pool_lv $DISCARD_VG $DISCARD_LV)
DISCARD_LV_SIZE=$(read_lv_size "$DISCARD_VG" "$DISCARD_LV")
lvremove -y --quiet "$DISCARD_LV_PATH" || exit 1
lvcreate --thin-pool "$DISCARD_LV_POOL" -V "$DISCARD_LV_SIZE"B --name "$DISCARD_LV" "$DISCARD_VG" || exit 1
}

function backup()
{
SOURCE_VG="$1"
SOURCE_LV="$2"
TARGET_VG="$BACKUPS"
TARGET_LV="$SOURCE_VG-$SOURCE_LV"
SOURCE_BASE_LV="$SOURCE_LV$BASE_SUFFIX"
TARGET_BASE_LV="$TARGET_LV$BASE_SUFFIX"
SOURCE_PEND_LV="$SOURCE_LV$PEND_SUFFIX"
TARGET_PEND_LV="$TARGET_LV$PEND_SUFFIX"
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")
SOURCE_PEND_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_PEND_LV")
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
TARGET_PEND_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_PEND_LV")

if [ "$SOURCE_BASE_LV_PATH" != "" ] then
echo "$SOURCE_BASE_LV_PATH found"
else
echo "Source base not found creating snapshot of $SOURCE_VG/$SOURCE_LV to $SOURCE_VG/$SOURCE_BASE_LV"
lvcreate --quiet --snapshot --name "$SOURCE_BASE_LV" "$SOURCE_VG/$SOURCE_LV" || exit 1
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
echo "Discarding $SOURCE_BASE_LV_PATH as we need to bootstrap."
SOURCE_BASE_POOL=$(read_pool_lv $SOURCE_VG $SOURCE_BASE_LV)
SOURCE_BASE_CHUNK_SIZE=$(read_lv_chunk_size $SOURCE_VG $SOURCE_BASE_POOL)
discard_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
sync
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found out of sync with source... removing..."
lvremove -y --quiet $TARGET_BASE_LV_PATH || exit 1
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
sync
fi
fi
SOURCE_BASE_SIZE=$(read_lv_size "$SOURCE_VG" "$SOURCE_BASE_LV")
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found"
else
echo "$TARGET_VG/$TARGET_LV not found. Creating empty volume."
lvcreate --thin-pool "$BACKUPS_POOL" -V "$SOURCE_BASE_SIZE"B --name "$TARGET_BASE_LV" "$TARGET_VG" || exit 1
echo "Have to rebootstrap. Discarding source at $SOURCE_BASE_LV_PATH"
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
SOURCE_BASE_POOL=$(read_pool_lv $SOURCE_VG $SOURCE_BASE_LV)
SOURCE_BASE_CHUNK_SIZE=$(read_lv_chunk_size $SOURCE_VG $SOURCE_BASE_POOL)
discard_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
TARGET_BASE_POOL=$(read_pool_lv $TARGET_VG $TARGET_BASE_LV)
TARGET_BASE_CHUNK_SIZE=$(read_lv_chunk_size $TARGET_VG $TARGET_BASE_POOL)
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
echo "Discarding target at $TARGET_BASE_LV_PATH"
discard_volume "$TARGET_VG" "$TARGET_BASE_LV"
sync
fi
if [ "$SOURCE_PEND_LV_PATH" != "" ] then
echo "$SOURCE_PEND_LV_PATH found removing..."
lvremove -y --quiet "$SOURCE_PEND_LV_PATH" || exit 1
sync
fi
lvcreate --quiet --snapshot --name "$SOURCE_PEND_LV" "$SOURCE_VG/$SOURCE_LV" || exit 1
SOURCE_PEND_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_PEND_LV")
sync
if [ "$TARGET_PEND_LV_PATH" != "" ] then
echo "$TARGET_PEND_LV_PATH found removing..."
lvremove -y --quiet $TARGET_PEND_LV_PATH
sync
fi
lvcreate --quiet --snapshot --name "$TARGET_PEND_LV" "$TARGET_VG/$TARGET_BASE_LV" || exit 1
TARGET_PEND_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_PEND_LV")
SOURCE_PEND_LV_SIZE=$(read_lv_size "$SOURCE_VG" "$SOURCE_PEND_LV")
lvresize -L "$SOURCE_PEND_LV_SIZE"B "$TARGET_PEND_LV_PATH"
activate_volume "$TARGET_VG" "$TARGET_PEND_LV"
echo "Synching $SOURCE_PEND_LV_PATH to $TARGET_PEND_LV_PATH"
thinsync "$SOURCE_VG" "$SOURCE_PEND_LV" "$SOURCE_BASE_LV" "$TARGET_PEND_LV_PATH" || exit 1
sync

TARGET_DATE_SUFFIX=$(suffix)
lvcreate --quiet --snapshot --name "$TARGET_LV$TARGET_DATE_SUFFIX" "$TARGET_VG/$TARGET_PEND_LV" || exit 1
sync
lvremove --quiet -y "$SOURCE_BASE_LV_PATH" || exit 1
sync
lvremove --quiet -y "$TARGET_BASE_LV_PATH" || exit 1
sync
lvrename -y "$SOURCE_VG/$SOURCE_PEND_LV" "$SOURCE_BASE_LV" || exit 1
lvrename -y "$TARGET_VG/$TARGET_PEND_LV" "$TARGET_BASE_LV" || exit 1
sync
deactivate_volume "$TARGET_VG" "$TARGET_BASE_LV"
deactivate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
}

function verify()
{
SOURCE_VG="$1"
SOURCE_LV="$2"
TARGET_VG="$BACKUPS"
TARGET_LV="$SOURCE_VG-$SOURCE_LV"
SOURCE_BASE_LV="$SOURCE_LV$BASE_SUFFIX"
TARGET_BASE_LV="$TARGET_LV$BASE_SUFFIX"
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")

if [ "$SOURCE_BASE_LV_PATH" != "" ] then
echo "$SOURCE_BASE_LV_PATH found"
else
echo "$SOURCE_BASE_LV_PATH not found"
exit 1
fi
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found"
else
echo "$TARGET_BASE_LV_PATH not found"
exit 1
fi
activate_volume "$TARGET_VG" "$TARGET_BASE_LV"
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
echo Comparing "$SOURCE_BASE_LV_PATH" with "$TARGET_BASE_LV_PATH"
cmp "$SOURCE_BASE_LV_PATH" "$TARGET_BASE_LV_PATH"
echo Done...
deactivate_volume "$TARGET_VG" "$TARGET_BASE_LV"
deactivate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
}

function resync()
{
SOURCE_VG="$1"
SOURCE_LV="$2"
TARGET_VG="$BACKUPS"
TARGET_LV="$SOURCE_VG-$SOURCE_LV"
SOURCE_BASE_LV="$SOURCE_LV$BASE_SUFFIX"
TARGET_BASE_LV="$TARGET_LV$BASE_SUFFIX"
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")

if [ "$SOURCE_BASE_LV_PATH" != "" ] then
echo "$SOURCE_BASE_LV_PATH found"
else
echo "$SOURCE_BASE_LV_PATH not found"
exit 1
fi
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found"
else
echo "$TARGET_BASE_LV_PATH not found"
exit 1
fi
activate_volume "$TARGET_VG" "$TARGET_BASE_LV"
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
SOURCE_BASE_POOL=$(read_pool_lv $SOURCE_VG $SOURCE_BASE_LV)
SYNC_BLOCK_SIZE=$(read_lv_chunk_size $SOURCE_VG $SOURCE_BASE_POOL)

echo Syncronizing "$SOURCE_BASE_LV_PATH" to "$TARGET_BASE_LV_PATH"

CMP_OFFSET=0
while [[ "$CMP_OFFSET" != "" ]] ; do
CMP_MISMATCH=$(cmp -i "$CMP_OFFSET" "$SOURCE_BASE_LV_PATH" "$TARGET_BASE_LV_PATH" | grep differ | awk '{print $5}' | sed 's/,//g' )
if [[ "$CMP_MISMATCH" != "" ]] ; then
CMP_OFFSET=$(( CMP_MISMATCH + CMP_OFFSET ))
SYNC_OFFSET_BYTES=$(( ( CMP_OFFSET / SYNC_BLOCK_SIZE ) * SYNC_BLOCK_SIZE ))
SYNC_LENGTH_BYTES=$(( SYNC_BLOCK_SIZE ))
echo "Synching $SYNC_LENGTH_BYTES bytes at $SYNC_OFFSET_BYTES from $SOURCE_BASE_LV_PATH to $TARGET_BASE_LV_PATH"
ddrescue --quiet --force --input-position=$SYNC_OFFSET_BYTES --output-position=$SYNC_OFFSET_BYTES --size=$SYNC_LENGTH_BYTES "$SOURCE_BASE_LV_PATH" "$TARGET_BASE_LV_PATH"
else
CMP_OFFSET=""
fi
done
echo Done...
deactivate_volume "$TARGET_VG" "$TARGET_BASE_LV"
deactivate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
}

function list()
{
LIST_SOURCE_VG="$1"
LIST_SOURCE_LV="$2"
LIST_TARGET_VG="$BACKUPS"
LIST_TARGET_LV="$LIST_SOURCE_VG-$LIST_SOURCE_LV"
LIST_TARGET_BASE_LV="$LIST_TARGET_LV$SNAP_SUFFIX"
lvs -olv_name | grep "$LIST_TARGET_BASE_LV.$DATE_REGEX"
}

function remove()
{
REMOVE_TARGET_VG="$BACKUPS"
REMOVE_TARGET_LV="$1"
lvremove -y "$REMOVE_TARGET_VG/$REMOVE_TARGET_LV"
sync
}

function removeall()
{
DATE_OFFSET="$3"
FILTER="$(filter "$DATE_OFFSET")"
while read -r SNAPSHOT ; do
remove "$SNAPSHOT"
done < <(list "$1" "$2" | grep "$FILTER")

}

(
COMMAND="$1"
shift

case "$COMMAND" in
"--help")
echo "Help"
;;
"suffix")
suffix
;;
"filter")
filter "$1"
;;
"backup")
wait_lock_or_terminate
backup "$1" "$2"
;;
"list")
list "$1" "$2"
;;
"thindiff")
thindiff "$1" "$2" "$3"
;;
"thinsync")
thinsync "$1" "$2" "$3" "$4"
;;
"verify")
wait_lock_or_terminate
verify "$1" "$2"
;;
"resync")
wait_lock_or_terminate
resync "$1" "$2"
;;
"remove")
wait_lock_or_terminate
remove "$1"
;;
"removeall")
wait_lock_or_terminate
removeall "$1" "$2" "$3"
;;
*)
echo "None.."
;;
esac
) 98>$LOCK_FILE

EOF

Mit csinal...?Parancskészletet tartalmaz a vékony pillanatképek manipulálására és a thin_delta-n keresztül kapott vékony pillanatképek közötti különbség szinkronizálására egy másik blokkeszközzel a ddrescue és a blkdiscard használatával.

Egy másik szkript, amelyet a cron-ba helyezünk:

Még egy kicsit bőgés#cat >/root/lvm-thin-backup/cron-daily.sh << EOF
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

SCRIPT_FILE="$(realpath $0)"
SCRIPT_DIR="$(dirname $SCRIPT_FILE)"
SCRIPT_NAME="$(basename -s .sh $SCRIPT_FILE)"

BACKUP_SCRIPT="$SCRIPT_DIR/lvm-thin-backup.sh"
RETENTION="-60 days"

$BACKUP_SCRIPT backup images linux-dev
$BACKUP_SCRIPT backup images win8
$BACKUP_SCRIPT backup images win8-data
#etc

$BACKUP_SCRIPT removeall images linux-dev "$RETENTION"
$BACKUP_SCRIPT removeall images win8 "$RETENTION"
$BACKUP_SCRIPT removeall images win8-data "$RETENTION"
#etc

EOF

Mit csinal...?Az előző szkriptet használja a felsorolt ​​vékony kötetek biztonsági másolatainak létrehozásához és szinkronizálásához. A szkript inaktív pillanatképeket hagy a felsorolt ​​kötetekről, amelyek az utolsó szinkronizálás óta történt változások nyomon követéséhez szükségesek.

Ezt a szkriptet szerkeszteni kell, megadva azon vékony kötetek listáját, amelyekről biztonsági másolatot kell készíteni. A megadott nevek csak illusztrációk. Ha szeretné, írhat egy szkriptet, amely az összes kötetet szinkronizálja.

Adjuk meg a jogokat:

#chmod +x /root/lvm-thin-backup/cron-daily.sh
#chmod +x /root/lvm-thin-backup/lvm-thin-backup.sh

Nézzük meg és tegyük a cronba:

#/usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/lvm-thin-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t lvm-thin-backup
#cat /var/log/syslog | grep lvm-thin-backup
#crontab -e
0 3 * * * /usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/lvm-thin-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t lvm-thin-backup

Az első indítás hosszú lesz, mert... a vékony kötetek teljesen szinkronizálva lesznek az összes felhasznált terület másolásával. Az LVM vékony metaadatainak köszönhetően tudjuk, hogy mely blokkok vannak ténylegesen használatban, így csak a ténylegesen használt vékony kötetblokkokat másoljuk.

A további futtatások az LVM vékony metaadatokon keresztül történő változáskövetésnek köszönhetően fokozatosan másolják az adatokat.

Nézzük meg mi történt:

#time /root/btrfs-backup/cron-daily.sh
real 0m2,967s
user 0m0,225s
sys 0m0,353s

#time /root/lvm-thin-backup/cron-daily.sh
real 1m2,710s
user 0m12,721s
sys 0m6,671s

#ls -al /backup/btrfs/back/remote/*
/backup/btrfs/back/remote/boot:
total 0
drwxr-xr-x 1 root root 1260 мар 26 09:11 .
drwxr-xr-x 1 root root 16 мар 6 09:30 ..
drwxr-xr-x 1 root root 322 мар 26 02:00 .@base
drwxr-xr-x 1 root root 516 мар 6 09:39 [email protected]
drwxr-xr-x 1 root root 516 мар 6 09:39 [email protected]
...
/backup/btrfs/back/remote/root:
total 0
drwxr-xr-x 1 root root 2820 мар 26 09:11 .
drwxr-xr-x 1 root root 16 мар 6 09:30 ..
drwxr-xr-x 1 root root 240 мар 26 09:11 @.@base
drwxr-xr-x 1 root root 22 мар 26 09:11 @home.@base
drwxr-xr-x 1 root root 22 мар 6 09:39 @[email protected]
drwxr-xr-x 1 root root 22 мар 6 09:39 @[email protected]
...
drwxr-xr-x 1 root root 240 мар 6 09:39 @[email protected]
drwxr-xr-x 1 root root 240 мар 6 09:39 @[email protected]
...

#lvs -olv_name,lv_size images && lvs -olv_name,lv_size backup
LV LSize
linux-dev 128,00g
linux-dev.base 128,00g
thin-pool 1,38t
win8 128,00g
win8-data 2,00t
win8-data.base 2,00t
win8.base 128,00g
LV LSize
backup 256,00g
images-linux-dev.base 128,00g
images-linux-dev.snap.2020-03-08-10-09-11 128,00g
images-linux-dev.snap.2020-03-08-10-09-25 128,00g
...
images-win8-data.base 2,00t
images-win8-data.snap.2020-03-16-14-11-55 2,00t
images-win8-data.snap.2020-03-16-14-19-50 2,00t
...
images-win8.base 128,00g
images-win8.snap.2020-03-17-04-51-46 128,00g
images-win8.snap.2020-03-18-03-02-49 128,00g
...
thin-pool <2,09t

Mi köze ennek a fészkelő babákhoz?

Valószínűleg, mivel az LVM LV logikai kötetei lehetnek LVM PV fizikai kötetei más VG-k számára. Az LVM lehet rekurzív, mint a fészkelő babák. Ez rendkívüli rugalmasságot biztosít az LVM számára.

PS

A következő cikkben megpróbálunk több hasonló mobil tárolórendszert/KVM-et felhasználni egy geo-elosztott tárolási/vm-klaszter létrehozásának alapjául több kontinensen, otthoni asztali számítógépek, otthoni internet és P2P hálózatok használatával.

Forrás: will.com

Hozzászólás