Čo majú spoločné LVM a Matrioška?

Dobrý deň.
Rád by som sa s komunitou podelil o svoje praktické skúsenosti s budovaním systému ukladania dát pre KVM pomocou md RAID + LVM.

Program bude obsahovať:

  • Budovanie md RAID 1 z NVMe SSD.
  • Zostavenie md RAID 6 zo SATA SSD a bežných diskov.
  • Funkcie prevádzky orezania/vyradenia na SSD RAID 1/6.
  • Vytvorenie zavádzacieho poľa MD RAID 1/6 na spoločnej sade diskov.
  • Inštalácia systému na NVMe RAID 1, keď v systéme BIOS nie je podpora NVMe.
  • Použitie vyrovnávacej pamäte LVM a tenkého LVM.
  • Používanie snímok BTRFS a odosielajte/prijímať na zálohovanie.
  • Použitie tenkých snímok LVM a thin_delta pre zálohy v štýle BTRFS.

Ak máte záujem, pozrite si kat.

výkaz

Autor nenesie žiadnu zodpovednosť za následky použitia alebo nepoužitia materiálov/príkladov/kódu/tipov/údajov z tohto článku. Čítaním alebo používaním tohto materiálu akýmkoľvek spôsobom preberáte zodpovednosť za všetky dôsledky týchto akcií. Možné dôsledky zahŕňajú:

  • Vyprážané NVMe SSD disky.
  • Úplne vyčerpaný zdroj nahrávania a zlyhanie jednotiek SSD.
  • Úplná strata všetkých údajov na všetkých jednotkách vrátane záložných kópií.
  • Chybný hardvér počítača.
  • Stratený čas, nervy a peniaze.
  • Akékoľvek ďalšie dôsledky, ktoré nie sú uvedené vyššie.

železo

K dispozícii boli:

Základná doska z roku 2013 s čipsetom Z87, doplnený o Intel Core i7 / Haswell.

  • Procesor 4 jadrá, 8 vlákien
  • 32 GB DDR3 RAM
  • 1 x 16 alebo 2 x 8 PCIe 3.0
  • 1 x 4 + 1 x 1 PCIe 2.0
  • 6 x 6 GBps SATA 3 konektory

Adaptér SAS LSI SAS9211-8i blikal do režimu IT / HBA. Firmvér podporovaný RAID bol úmyselne nahradený firmvérom HBA na:

  1. Tento adaptér môžete kedykoľvek vyhodiť a nahradiť ho akýmkoľvek iným, na ktorý ste narazili.
  2. Zastričenie/vyradenie normálne pracovalo na diskoch, pretože ... V RAID Firmware nie sú tieto príkazy vôbec podporované a HBA vo všeobecnosti sa nestará o to, aké príkazy sa prenášajú cez autobus.

Pevné disky - 8 kusov HGST Travelstar 7K1000 s kapacitou 1 TB v prevedení 2.5, ako pre notebooky. Tieto disky boli predtým v poli RAID 6. Využitie budú mať aj v novom systéme. Na ukladanie lokálnych záloh.

Dodatočne pridané:

6 kusov SATA SSD Model Samsung 860 QVO 2TB. Tieto SSD vyžadovali veľký objem, prítomnosť vyrovnávacej pamäte SLC, spoľahlivosť a nízka cena. Vyžadovala sa podpora pre vyradenie/nula, ktorá je skontrolovaná riadkom v DMESG:

kernel: ata1.00: Enabling discard_zeroes_data

2 kusy NVMe SSD model Samsung SSD 970 EVO 500GB.

Pre tieto SSD je dôležitá rýchlosť náhodného čítania/zápisu a kapacita zdrojov pre vaše potreby. Radiátor pre nich. Nevyhnutne. Absolútne. V opačnom prípade ich počas prvej synchronizácie RAID opečte do chrumkava.

StarTech PEX8M2E2 adaptér pre 2 x NVMe SSD nainštalovaný v PCIe 3.0 8x slote. Toto je opäť len HBA, ale pre NVMe. Od lacných adaptérov sa líši tým, že nevyžaduje podporu rozdvojenia PCIe zo základnej dosky vďaka prítomnosti vstavaného PCIe prepínača. Bude fungovať aj v najstaršom systéme s PCIe, aj keď ide o slot x1 PCIe 1.0. Prirodzene, v primeranej rýchlosti. Nie sú tam žiadne RAID. Na doske nie je zabudovaný BIOS. Váš systém sa teda vďaka tomuto zariadeniu magicky nenaučí zaviesť systém s NVMe, tým menej to urobí NVMe RAID.

Tento komponent bol spôsobený výlučne prítomnosťou iba jedného voľného 8x PCIe 3.0 v systéme a ak sú k dispozícii 2 voľné sloty, možno ho ľahko nahradiť dvoma centmi PEX4M2E1 alebo analógmi, ktoré je možné kúpiť kdekoľvek za cenu 600. rubľov.

Odmietnutie všetkých druhov hardvéru alebo vstavaných čipsetov/BIOS RAIDov bolo urobené zámerne, aby bolo možné kompletne nahradiť celý systém s výnimkou samotného SSD/HDD pri zachovaní všetkých dát. Ideálne tak, aby ste pri prechode na úplne nový/iný hardvér ušetrili aj nainštalovaný operačný systém. Hlavná vec je, že existujú porty SATA a PCIe. Je to ako živé CD alebo bootovací flash disk, len veľmi rýchly a trochu objemný.

ЮморV opačnom prípade viete, čo sa stane - niekedy musíte naliehavo vziať so sebou celé pole. Ale nechcem prísť o dáta. K tomu sú všetky spomínané médiá vhodne umiestnené na sklíčkach v 5.25 pozíciách štandardného puzdra.

No a, samozrejme, na experimentovanie s rôznymi metódami ukladania SSD do vyrovnávacej pamäte v Linuxe.

Hardvérové ​​nájazdy sú nudné. Zapnúť. Buď to funguje, alebo nie. A s mdadm sú vždy možnosti.

Softvér

Predtým bol Debian 8 Jessie nainštalovaný na hardvéri, ktorý je blízko EOL. RAID 6 bol zostavený z vyššie uvedených HDD spárovaných s LVM. Spúšťal virtuálne stroje v kvm/libvirt.

Pretože Autor má vhodné skúsenosti s tvorbou prenosných bootovateľných SATA/NVMe flash diskov a taktiež, aby sa neporušila zaužívaná apt šablóna, ako cieľový systém bol vybraný Ubuntu 18.04, ktorý je už dostatočne stabilizovaný, no má ešte 3 roky podporu v budúcnosti.

Uvedený systém obsahuje všetky hardvérové ​​ovládače, ktoré potrebujeme z krabice. Nepotrebujeme žiadny softvér alebo ovládače tretích strán.

Príprava na inštaláciu

Na inštaláciu systému potrebujeme Ubuntu Desktop Image. Serverový systém má nejaký rázny inštalačný program, ktorý vykazuje prílišnú nezávislosť, ktorú nemožno deaktivovať vložením systémovej partície UEFI na jeden z diskov, čo pokazí všetku krásu. Preto je nainštalovaný iba v režime UEFI. Neponúka žiadne možnosti.

Nie sme s tým spokojní.

Prečo?Bohužiaľ, UEFI boot je extrémne zle kompatibilný s bootovacím softvérom RAID, pretože... Nikto nám neponúka rezervácie na partíciu UEFI ESP. Na internete existujú recepty, ktoré odporúčajú umiestniť oblasť ESP na flash disk do portu USB, ale toto je bod zlyhania. Existujú recepty využívajúce softvér mdadm RAID 1 s metadátami verzie 0.9, ktoré nebránia systému UEFI BIOS vidieť tento oddiel, ale ten žije až do šťastného okamihu, keď BIOS alebo iný hardvérový OS niečo zapíše do ESP a zabudne to synchronizovať s iným zrkadlá.

Okrem toho spustenie UEFI závisí od NVRAM, ktorá sa nepresunie spolu s diskami do nového systému, pretože je súčasťou základnej dosky.

Takže nebudeme znovu vynájsť nové koleso. Máme už hotový, rokmi overený bicykel starého otca, teraz nazývaný Legacy/BIOS boot, nesúci hrdé meno CSM na systémoch kompatibilných s UEFI. Len ho vyberieme z police, namažeme, napumpujeme pneumatiky a utrieme vlhkou handričkou.

Desktopová verzia Ubuntu sa tiež nedá správne nainštalovať pomocou zavádzača Legacy, ale tu, ako sa hovorí, aspoň existujú možnosti.

A tak zhromažďujeme hardvér a načítame systém z jednotky Ubuntu Live Boot -Flash Drive. Budeme si musieť stiahnuť balíčky, takže nastavíme sieť, ktorá bude fungovať pre vás. Ak to nefunguje, môžete vopred načítať potrebné balíčky na jednotku Flash.

Ideme do prostredia pracovnej plochy, spustíme emulátor terminálu a vypnuté:

#sudo bash

Ako…?Riadok vyššie je kanonický spúšťač pre holiwars o sudo. C bоprichádzajú väčšie príležitosti aоväčšiu zodpovednosť. Otázkou je, či to dokážete vziať na seba. Mnoho ľudí si myslí, že používanie suda týmto spôsobom nie je prinajmenšom opatrné. Avšak:

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

Prečo nie ZFS...?Keď inštalujeme softvér do nášho počítača, v podstate požičiavame náš hardvér vývojárom tohto softvéru na riadenie.
Keď dôverujeme tomuto softvéru s bezpečnosťou našich údajov, vyberieme pôžičku rovnajúcu sa nákladom na obnovenie týchto údajov, ktoré budeme niekedy musieť vyplatiť.

Z tohto hľadiska je ZFS Ferrari a MDADM+LVM je skôr ako bicykel.

Subjektívne autor namiesto Ferrari radšej požičiava bicykel na úver neznámym osobám. Tam cena emisie nie je vysoká. Nie sú potrebné práva. Jednoduchšie ako pravidlá cestnej premávky. Parkovanie je bezplatné. Bežecké schopnosti sú lepšie. Na bicykel môžete vždy pripevniť nohy a bicykel môžete opraviť vlastnými rukami.

Prečo potom BTRFS...?Na spustenie operačného systému potrebujeme súborový systém, ktorý je podporovaný v Legacy/BIOS GRUB a zároveň podporuje živé snímky. Použijeme ho pre oddiel /boot. Okrem toho autor uprednostňuje použitie tohto FS pre / (root), pričom nezabudol poznamenať, že pre akýkoľvek iný softvér môžete vytvoriť samostatné oddiely na LVM a pripojiť ich do potrebných adresárov.

Na tomto FS nebudeme ukladať žiadne obrázky virtuálnych strojov ani databáz.
Tento FS sa bude používať iba na vytváranie snímok systému bez jeho vypnutia a potom na prenos týchto snímok na záložný disk pomocou odosielania/prijímania.

Okrem toho autor vo všeobecnosti uprednostňuje ponechať minimum softvéru priamo na hardvéri a všetok ďalší softvér spustiť vo virtuálnych strojoch pomocou vecí, ako je preposielanie GPU a PCI-USB Host radičov do KVM cez IOMMU.

Jediné veci, ktoré zostali na hardvéri, sú ukladanie údajov, virtualizácia a záloha.

Ak viac dôverujete ZFS, potom sú v zásade pre špecifikovanú aplikáciu zameniteľné.

Autor však zámerne ignoruje vstavané funkcie zrkadlenia/RAID a redundancie, ktoré majú ZFS, BRTFS a LVM.

Ako dodatočný argument má BTRFS možnosť premeniť náhodné zápisy na sekvenčné, čo má mimoriadne pozitívny vplyv na rýchlosť synchronizácie snímok/záloh na HDD.

Znova prehľadáme všetky zariadenia:

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

Poďme sa pozrieť okolo seba:

#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

Rozloženie diskov

NVMe SSD

Nijako ich však neoznačíme. Náš BIOS však tieto jednotky nevidí. Pôjdu teda výlučne na softvérový RAID. Nebudeme tam ani vytvárať sekcie. Ak chcete postupovať podľa „kánonu“ alebo „v zásade“, vytvorte jeden veľký oddiel, napríklad HDD.

SATA HDD

Tu netreba nič špeciálne vymýšľať. Vytvoríme jednu sekciu pre všetko. Vytvoríme oddiel, pretože BIOS tieto disky vidí a môže sa z nich dokonca pokúsiť zaviesť systém. Dokonca na tieto disky neskôr nainštalujeme GRUB, aby to systém mohol zrazu urobiť.

#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

Tu sú veci pre nás zaujímavé.

Po prvé, naše disky majú veľkosť 2 TB. To je v prijateľnom rozsahu pre MBR, čo budeme používať. V prípade potreby je možné nahradiť GPT. Disky GPT majú vrstvu kompatibility, ktorá umožňuje systémom kompatibilným s MBR vidieť prvé 4 oddiely, ak sa nachádzajú v rámci prvých 2 terabajtov. Hlavná vec je, že zavádzacia oblasť a oblasť bios_grub na týchto diskoch by mali byť na začiatku. To vám dokonca umožňuje zaviesť systém z jednotiek GPT Legacy/BIOS.

Ale to nie je náš prípad.

Tu vytvoríme dve sekcie. Prvý bude mať veľkosť 1 GB a bude sa používať pre RAID 1 /boot.

Druhý sa použije pre RAID 6 a zaberie všetko zostávajúce voľné miesto okrem malej nepridelenej oblasti na konci disku.

Čo je to za neoznačenú oblasť?Podľa zdrojov v sieti majú naše SATA SSD na palube dynamicky rozšíriteľnú vyrovnávaciu pamäť SLC s veľkosťou od 6 do 78 gigabajtov. Získame 6 gigabajtov „zadarmo“ kvôli rozdielu medzi „gigabajtmi“ a „gibibajtmi“ v údajovom liste jednotky. Zvyšných 72 gigabajtov je pridelených z nevyužitého priestoru.

Tu je potrebné poznamenať, že máme vyrovnávaciu pamäť SLC a priestor je obsadený v 4 bitovom režime MLC. Čo pre nás efektívne znamená, že za každé 4 gigabajty voľného miesta dostaneme iba 1 gigabajt SLC cache.

Vynásobte 72 gigabajtov 4 a získajte 288 gigabajtov. Toto je voľné miesto, ktoré nebudeme vymedzovať, aby disky mohli plne využívať vyrovnávaciu pamäť SLC.

Efektívne tak získame až 312 gigabajtov SLC cache z celkovo šiestich diskov. Zo všetkých diskov budú 2 použité v RAID kvôli redundancii.

Toto množstvo vyrovnávacej pamäte nám umožní veľmi zriedkavo pri skutočnom živote stretnúť situáciu, keď zápis do vyrovnávacej pamäte nechodí. To mimoriadne dobre kompenzuje najsmutnejšiu nevýhodu pamäte QLC - extrémne nízka rýchlosť zápisu, keď sa údaje zapisujú obchádzanie vyrovnávacej pamäte. Ak tomu vaše zaťaženia nezodpovedajú, potom odporúčam, aby ste tvrdo premýšľali o tom, ako dlho bude váš SSD vydržať pri takomto zaťažení, pričom zohľadňuje TBW z dátového hárku.

#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

Vytváranie polí

Najprv musíme stroj premenovať. Je to potrebné, pretože názov hostiteľa je súčasťou názvu poľa niekde vo vnútri Mdadm a niekde niečo ovplyvňuje. Polia sa samozrejme môžu premenovať neskôr, ale toto je zbytočný krok.

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

NVMe SSD

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

Prečo -zmelá čistá ...?Aby ste sa vyhli inicializácii polí. Toto platí pre obe úrovne RAID 1 a 6. Všetko môže fungovať bez inicializácie, ak ide o nové pole. Okrem toho inicializácia poľa SSD po vytvorení je plytvaním zdrojom TBW. Ak je to možné, používame TRIM/DISCARD na zostavených poliach SSD na ich „inicializáciu“.

V prípade polí SSD je vyradenie RAID 1 podporované z krabice.

Pre polia SSD RAID 6 DISCARD ho musíte povoliť v parametroch modulu jadra.

Toto by sa malo vykonať iba vtedy, ak všetky SSD používané v poliach úrovne 4/5/6 v tomto systéme majú funkčnú podporu pre discard_zeroes_data. Niekedy sa stretnete so zvláštnymi jednotkami, ktoré jadru hovoria, že táto funkcia je podporovaná, ale v skutočnosti tam nie je, alebo funkcia nie vždy funguje. V súčasnosti je podpora dostupná takmer všade, existujú však staré jednotky a firmvér s chybami. Z tohto dôvodu je podpora DISCARD pre RAID 6 predvolene vypnutá.

Pozor, nasledujúci príkaz zničí všetky údaje na jednotkách NVMe „inicializáciou“ poľa s „nulami“.

#blkdiscard /dev/md0

Ak sa niečo pokazí, skúste zadať krok.

#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

Prečo taký veľký...?Zväčšenie veľkosti chunk-size má pozitívny vplyv na rýchlosť náhodného čítania v blokoch až do chunk size vrátane. Stáva sa to preto, že jednu operáciu vhodnej veľkosti alebo menšej je možné vykonať úplne na jednom zariadení. Preto sa IOPS zo všetkých zariadení sčítajú. Podľa štatistík 99% IO nepresahuje 512K.

RAID 6 IOPS na zápis vždy menší alebo rovný IOPS jedného disku. Keď pri náhodnom čítaní môže byť IOPS niekoľkonásobne vyšší ako u jedného disku, a tu je kľúčová veľkosť bloku.
Autor nevidí zmysel v snahe optimalizovať parameter, ktorý je zlý v RAID 6 by-design a namiesto toho optimalizuje to, v čom je RAID 6 dobrý.
Slabý náhodný zápis RAID 6 vykompenzujeme vyrovnávacou pamäťou NVMe a trikmi na tenké poskytovanie.

Zatiaľ sme nepovolili DISCARD pre RAID 6. Toto pole teda zatiaľ nebudeme „inicializovať“. Urobíme to neskôr, po inštalácii OS.

SATA HDD

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

LVM na NVME RAID

Kvôli rýchlosti chceme koreňový súborový systém umiestniť na NVMe RAID 1, čo je /dev/md0.
Toto rýchle pole však budeme stále potrebovať pre iné potreby, ako sú swap, metadáta a LVM-cache a LVM-thin metadáta, takže na tomto poli vytvoríme LVM VG.

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

Vytvorme oddiel pre koreňový súborový systém.

#lvcreate -L 128G --name root root

Vytvorme partíciu na swapovanie podľa veľkosti RAM.

#lvcreate -L 32G --name swap root

Inštalácia OS

Celkovo máme všetko potrebné na inštaláciu systému.

Spustite Sprievodcu inštaláciou systému z prostredia Ubuntu Live. Normálna inštalácia. Iba vo fáze výberu diskov na inštaláciu musíte zadať nasledujúce:

  • /dev/md1, - bod pripojenia /boot, FS - BTRFS
  • /dev/root/root (aka /dev/mapper/root-root), - bod pripojenia / (root), FS - BTRFS
  • /dev/root/swap (aka /dev/mapper/root-swap), - použiť ako odkladací oddiel
  • Nainštalujte bootloader na /dev/sda

Keď vyberiete BTRFS ako systém koreňových súborov, inštalátor automaticky vytvorí dva zväzky BTRFS s názvom „@“ pre / (root) a „@Home“ pre / domov.

Začnime s inštaláciou...

Inštalácia sa skončí modálnym dialógovým oknom, ktoré označuje chybu pri inštalácii bootloaderu. Bohužiaľ nebudete môcť opustiť toto dialógové okno pomocou štandardných prostriedkov a pokračovať v inštalácii. Odhýbame sa zo systému a znova sa prihlásime, skončíme v čistej pracovnej ploche Ubuntu Live. Otvorte terminál a znova:

#sudo bash

Ak chcete pokračovať v inštalácii, vytvorte prostredie chroot:

#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

Konfigurujeme sieť a názov hostiteľa v Chroot:

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

Poďme do prostredia chroot:

#chroot /mnt/chroot

V prvom rade doručíme balíčky:

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

Poďme skontrolovať a opraviť všetky balíky, ktoré boli nainštalované nesprávne z dôvodu neúplnej inštalácie systému:

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

Ak niečo nefunguje, možno budete musieť najprv upraviť /etc/apt/sources.list

Upravme parametre pre modul RAID 6, aby sme povolili TRIM/DISCARD:

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

Poďme trochu vyladiť naše polia:

#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

Čo to bolo..?Vytvorili sme súbor pravidiel udev, ktoré budú robiť nasledovné:

  • Veľkosť blokovej vyrovnávacej pamäte pre RAID 2020 nastavte tak, aby bola adekvátna pre rok 6. Predvolená hodnota sa, zdá sa, od stvorenia Linuxu nezmenila a už dlho nie je adekvátna.
  • Vyhraďte si minimálne IO počas trvania kontrol/synchronizácie poľa. Toto má zabrániť tomu, aby sa vaše polia zasekli v stave večnej synchronizácie pri zaťažení.
  • Obmedzte maximálnu IO počas kontrol/synchronizácie polí. Je to potrebné, aby synchronizácia/kontrola SSD RAID nevyprážala vaše disky do chrumkava. To platí najmä pre NVMe. (Pamätáš si na radiátor? Nerobil som si srandu.)
  • Zakážte diskom zastaviť rotáciu vretena (HDD) prostredníctvom APM a nastavte časový limit spánku pre radiče disku na 7 hodín. APM môžete úplne zakázať, ak to vaše disky dokážu (-B 255). Pri predvolenej hodnote sa pohony zastavia po piatich sekundách. Potom chce OS resetovať vyrovnávaciu pamäť disku, disky sa znova roztočia a všetko začne odznova. Kotúče majú obmedzený maximálny počet otáčok vretena. Takýto jednoduchý predvolený cyklus môže ľahko zabiť vaše disky za pár rokov. Nie všetky disky tým trpia, ale naše sú „notebookové“ s príslušnými predvolenými nastaveniami, vďaka ktorým RAID vyzerá ako mini-MAID.
  • Nainštalujte predbežné čítanie na disky (rotujúce) 1 megabajt - dva po sebe idúce bloky/kus RAID 6
  • Zakázať predčítanie na samotných poliach.

Upravme /etc/fstab:

#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

Prečo je to..?Vyhľadáme oddiel /boot podľa UUID. Pomenovanie polí by sa teoreticky mohlo zmeniť.

Zvyšné sekcie budeme hľadať podľa názvov LVM v zápise /dev/mapper/vg-lv, pretože identifikujú oddiely celkom jednoznačne.

UUID pre LVM nepoužívame, pretože UUID zväzkov LVM a ich snímky môžu byť rovnaké.Pripojiť /dev/mapper/root-root.. dvakrát?Áno. Presne. Funkcia BTRFS. Tento súborový systém je možné pripojiť niekoľkokrát s rôznymi podskupinami.

Kvôli rovnakej funkcii neodporúčam nikdy vytvárať snímky LVM aktívnych zväzkov BTRFS. Po reštarte môžete byť prekvapení.

Obnovme konfiguráciu mdadm:

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

Upravme nastavenia LVM:

#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

Čo to bolo..?Po dosiahnutí 90% okupovaného priestoru sme umožnili automatickú expanziu tenkých bazénov LVM o 5% objemu.

Zvýšili sme maximálny počet blokov vyrovnávacej pamäte pre vyrovnávaciu pamäť LVM.

Zabránili sme LVM vo vyhľadávaní zväzkov LVM (PV) na:

  • zariadenia obsahujúce vyrovnávaciu pamäť LVM (cdata)
  • zariadenia uložené do vyrovnávacej pamäte pomocou vyrovnávacej pamäte LVM, pričom sa vynecháva vyrovnávacia pamäť ( _corig). V tomto prípade bude samotné zariadenie uložené vo vyrovnávacej pamäti stále kontrolované prostredníctvom vyrovnávacej pamäte (len ).
  • zariadenia obsahujúce metadáta vyrovnávacej pamäte LVM (cmeta)
  • všetky zariadenia vo VG s obrázkami názvov. Tu budeme mať obrazy diskov virtuálnych počítačov a nechceme, aby LVM na hostiteľovi aktivoval zväzky patriace hosťujúcemu OS.
  • Všetky zariadenia vo VG s zálohou mena. Tu budeme mať záložné kópie obrázkov virtuálnych strojov.
  • všetky zariadenia, ktorých názov končí na „gpv“ (hosťovský fyzický zväzok)

Pri uvoľnení voľného priestoru na LVM VG sme povolili podporu vyradenia. Buď opatrný. Vďaka tomu bude odstránenie LV na SSD dosť náročné. Platí to najmä pre RAID SSD 6. Podľa plánu však použijeme tenké zabezpečenie, takže nám to vôbec nebráni.

Aktualizujme obrázok initramfs:

#update-initramfs -u -k all

Nainštalujte a nakonfigurujte grub:

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

Ktoré disky si vybrať?Všetci, ktorí sú sd*. Systém musí byť schopný zaviesť systém z akéhokoľvek funkčného disku SATA alebo SSD.

Prečo pridali os-prober..?Pre nadmernú nezávislosť a hravé ruky.

Nepracuje správne, ak je jeden z RAID v zhoršenom stave. Pokúša sa vyhľadať OS na oddieloch, ktoré sa používajú vo virtuálnych strojoch spustených na tomto hardvéri.

Ak to potrebujete, môžete to nechať, ale nezabudnite na všetky vyššie uvedené. Odporúčam hľadať recepty na odstránenie nezbedných rúk online.

Týmto sme dokončili úvodnú inštaláciu. Je čas reštartovať do novo nainštalovaného OS. Nezabudnite vybrať bootovacie Live CD/USB.

#exit
#reboot

Ako spúšťacie zariadenie vyberte ktorýkoľvek z SATA SSD.

LVM na SATA SSD

V tomto okamihu sme už zaviedli do nového OS, nakonfigurovali sme sieť, otvorili emulátor terminálu a spustili:

#sudo bash

Pokračujme.

„Inicializujte“ pole zo SATA SSD:

#blkdiscard /dev/md2

Ak to nefunguje, skúste:

#blkdiscard --step 65536 /dev/md2
Vytvorte LVM VG na SATA SSD:

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

Prečo ďalší vg ..?V skutočnosti už máme VG s názvom root. Prečo nepridať všetko do jedného VG?

Ak je vo VG niekoľko PV, potom pre správnu aktiváciu VG musia byť prítomné všetky PV (online). Výnimkou je LVM RAID, ktorý zámerne nepoužívame.

Naozaj chceme, aby ak dôjde k poruche (strate dát) na niektorom z polí RAID 6, operačný systém sa normálne zavedie a poskytne nám možnosť problém vyriešiť.

Aby sme to dosiahli, na prvej úrovni abstrakcie izolujeme každý typ fyzického „média“ do samostatného VG.

Z vedeckého hľadiska patria rôzne polia RAID do rôznych „domén spoľahlivosti“. Nemali by ste pre nich vytvárať ďalší spoločný bod zlyhania tým, že ich napcháte do jedného VG.

Prítomnosť LVM na „hardvérovej“ úrovni nám umožní ľubovoľne rezať kúsky rôznych polí RAID ich kombinovaním rôznymi spôsobmi. Napríklad - beh v rovnakom čase bcache + LVM tenký, bcache + BTRFS, LVM cache + LVM tenký, zložitá konfigurácia ZFS s vyrovnávacími pamäťami alebo akákoľvek iná pekelná zmes na vyskúšanie a porovnanie.

Na „hardvérovej“ úrovni nebudeme používať nič iné ako staré dobré „hrubé“ zväzky LVM. Výnimkou z tohto pravidla môže byť záložný oddiel.

Myslím, že v tejto chvíli už mnohí čitatelia začali tušiť niečo o hniezdiacej bábike.

LVM na SATA HDD

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

Opäť nové VG..?Veľmi nám záleží na tom, aby v prípade výpadku diskového poľa, ktoré použijeme na zálohovanie dát, náš operačný systém naďalej normálne fungoval, pričom si zachoval prístup k nezálohovaným dátam ako obvykle. Preto, aby sme sa vyhli problémom s aktiváciou VG, vytvárame samostatný VG.

Nastavenie vyrovnávacej pamäte LVM

Poďme vytvoriť LV na NVMe RAID 1, aby sme ho mohli použiť ako zariadenie na ukladanie do vyrovnávacej pamäte.

#lvcreate -L 70871154688B --name cache root

Prečo je toho tak málo...?Faktom je, že naše NVMe SSD disky majú aj SLC cache. 4 gigabajty „zadarmo“ a 18 gigabajtov dynamických vďaka voľnému priestoru obsadenému v 3-bitovom MLC. Po vyčerpaní tejto vyrovnávacej pamäte nebudú disky NVMe SSD oveľa rýchlejšie ako naše SATA SSD s vyrovnávacou pamäťou. V skutočnosti z tohto dôvodu nemá zmysel, aby bol oddiel vyrovnávacej pamäte LVM oveľa väčší ako dvojnásobok veľkosti vyrovnávacej pamäte SLC disku NVMe. Pre použité NVMe disky autor považuje za rozumné urobiť 32-64 gigabajtov cache.

Daná veľkosť oddielu je potrebná na usporiadanie 64 gigabajtov vyrovnávacej pamäte, metadát vyrovnávacej pamäte a zálohy metadát.

Okrem toho poznamenávam, že po špinavom vypnutí systému LVM označí celú vyrovnávaciu pamäť ako špinavú a znova sa synchronizuje. Navyše sa to bude opakovať vždy, keď sa na tomto zariadení použije lvchange, kým sa systém znova nereštartuje. Preto odporúčam okamžite znova vytvoriť vyrovnávaciu pamäť pomocou príslušného skriptu.

Poďme vytvoriť LV na SATA RAID 6, aby sme ho mohli použiť ako zariadenie s vyrovnávacou pamäťou.

#lvcreate -L 3298543271936B --name cache data

Prečo len tri terabajty?Aby ste v prípade potreby mohli použiť SATA SSD RAID 6 na iné potreby. Veľkosť priestoru vo vyrovnávacej pamäti sa môže dynamicky zväčšovať za behu bez zastavenia systému. Ak to chcete urobiť, musíte dočasne zastaviť a znova povoliť vyrovnávaciu pamäť, ale výraznou výhodou vyrovnávacej pamäte LVM oproti napríklad bcache je, že to možno vykonať za behu.

Vytvorme nový VG na ukladanie do vyrovnávacej pamäte.

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

Vytvorme LV na zariadení vo vyrovnávacej pamäti.

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

Tu sme okamžite zaberali všetok voľný priestor na/dev/data/vyrovnávacia pamäť, aby boli všetky ostatné potrebné oddiely vytvorené okamžite na/dev/root/cache. Ak ste niečo vytvorili na nesprávnom mieste, môžete ho presunúť pomocou PVMove.

Poďme vytvoriť a povoliť vyrovnávaciu pamäť:

#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

Prečo taká veľkosť..?Prostredníctvom praktických experimentov autor bol schopný zistiť, že najlepší výsledok sa dosiahne, ak sa veľkosť bloku vyrovnávacej pamäte LVM zhoduje s veľkosťou tenkého bloku LVM. Navyše, čím menšia je veľkosť, tým lepšia konfigurácia vykonáva pri náhodnom zázname.

64k je minimálna veľkosť bloku povolená pre LVM tenký.

Pozor na odpis..!Áno. Tento typ vyrovnávacej pamäte odkladá synchronizáciu zápisu do zariadenia vo vyrovnávacej pamäti. To znamená, že ak dôjde k strate vyrovnávacej pamäte, môžete stratiť údaje na zariadení vo vyrovnávacej pamäti. Neskôr vám autor povie, aké opatrenia je možné okrem NVMe RAID 1 prijať na kompenzáciu tohto rizika.

Tento typ vyrovnávacej pamäte bol zvolený zámerne, aby kompenzoval slabý výkon náhodného zápisu RAID 6.

Pozrime sa, čo máme:

#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)

Iba [cachedata_corig] by sa malo nachádzať na /dev/data/cache. Ak niečo nie je v poriadku, použite pvmove.

V prípade potreby môžete zakázať vyrovnávaciu pamäť jedným príkazom:

#lvconvert -y --uncache cache/cachedata

Toto sa vykonáva online. LVM jednoducho zosynchronizuje vyrovnávaciu pamäť na disk, odstráni ju a premenuje cachedata_corig späť na cachedata.

Nastavenie LVM tenký

Poďme zhruba odhadnúť, koľko miesta potrebujeme pre tenké metadáta LVM:

#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"

Zaokrúhliť na 4 gigabajty: 4294967296B

Vynásobte dvomi a pridajte 4194304B pre metadáta LVM PV: 8594128896B
Vytvorme samostatný oddiel na NVMe RAID 1, aby sme naň umiestnili tenké metadáta LVM a ich záložnú kópiu:

#lvcreate -L 8594128896B --name images root

Prečo..?Tu môže nastať otázka: Prečo umiestniť tenké metadáta LVM osobitne, ak bude stále uložená ukladaná do vyrovnávacej pamäte na NVME a bude fungovať rýchlo.

Aj keď je tu rýchlosť dôležitá, zďaleka nie je hlavným dôvodom. Ide o to, že vyrovnávacia pamäť je bodom zlyhania. Mohlo by sa mu niečo stať a ak sa tenké metadáta LVM uložia do vyrovnávacej pamäte, spôsobí to úplnú stratu všetkého. Bez úplných metadát bude takmer nemožné zostaviť tenké zväzky.

Presunutím metadát do samostatného neuloženého, ​​ale rýchleho zväzku zaručujeme bezpečnosť metadát v prípade straty alebo poškodenia vyrovnávacej pamäte. V tomto prípade budú všetky škody spôsobené stratou vyrovnávacej pamäte lokalizované vo vnútri tenkých zväzkov, čo rádovo zjednoduší procedúru obnovy. S vysokou pravdepodobnosťou budú tieto škody obnovené pomocou protokolov FS.

Okrem toho, ak sa predtým urobila snímka tenkého objemu a potom bola vyrovnávacia pamäť úplne synchronizovaná aspoň raz, potom v dôsledku vnútorného dizajnu LVM Thin bude integrita snímky zaručená v prípade straty vyrovnávacej pamäte .

Vytvorime nový VG, ktorý bude zodpovedný za tenké poskytovanie:

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

Vytvorme si bazén:

#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T images/thin-pool
Prečo -Z yOkrem toho, pre čo je tento režim v skutočnosti určený - aby sa zabránilo uniknutiu údajov z jedného virtuálneho počítača do iného virtuálneho počítača, keď redistribúcia priestoru - nulaing sa dodatočne používa na zvýšenie rýchlosti náhodného písania v blokoch menších ako 64 64. Akýkoľvek zápis menej ako 64 XNUMX do predtým nepridelenej oblasti tenkého objemu sa v vyrovnávacej pamäti stane XNUMX k okraju. Umožní to, aby sa operácia vykonala úplne prostredníctvom vyrovnávacej pamäte, ktorá obchádza zariadenie na uložené cache.

Presuňme LV na zodpovedajúce PV:

#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

Skontrolujme to:

#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)

Vytvorme tenký objem pre testy:

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

Nainštalujeme balíčky na testy a monitorovanie:

#apt-get install sysstat fio

Takto môžete pozorovať správanie našej konfigurácie ukladania v reálnom čase:

#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)'

Takto môžeme otestovať našu konfiguráciu:

#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

Opatrne! Zdroj!Tento kód spustí 36 rôznych testov, z ktorých každý beží 4 sekundy. Polovica testov je na nahrávanie. Za 4 sekundy môžete na NVMe nahrať veľa. Až 3 gigabajty za sekundu. Takže každé spustenie testov zápisu od vás môže zjesť až 216 gigabajtov prostriedkov SSD.

Zmiešané čítanie a písanie?Áno. Má zmysel spúšťať testy čítania a zápisu oddelene. Okrem toho má zmysel zabezpečiť, aby boli všetky vyrovnávacie pamäte synchronizované, aby predtým vykonaný zápis neovplyvnil čítanie.

Výsledky sa budú značne líšiť počas prvého spustenia a nasledujúcich s tým, ako sa zaplní vyrovnávacia pamäť a tenký zväzok a tiež v závislosti od toho, či sa systému podarilo synchronizovať vyrovnávacie pamäte zaplnené pri poslednom spustení.

Okrem iného odporúčam zmerať rýchlosť na už plnom tenkom zväzku, z ktorého bola práve urobená momentka. Autor mal možnosť pozorovať, ako sa náhodné zápisy prudko zrýchľujú hneď po vytvorení prvej snímky, najmä keď cache ešte nie je úplne plná. Stáva sa to v dôsledku sémantiky zápisu kopírovania pri zápise, zarovnania vyrovnávacej pamäte a blokov tenkého zväzku a skutočnosti, že náhodný zápis do RAID 6 sa zmení na náhodné čítanie z RAID 6, po ktorom nasleduje zápis do vyrovnávacej pamäte. V našej konfigurácii je náhodné čítanie z RAID 6 až 6-krát (počet SATA SSD v poli) rýchlejšie ako zápis. Pretože bloky pre CoW sú prideľované postupne z tenkého fondu, potom sa nahrávanie z väčšej časti tiež zmení na sekvenčné.

Obe tieto funkcie môžete využiť vo svoj prospech.

Ukladať do vyrovnávacej pamäte „koherentné“ snímky

Aby sa znížilo riziko straty údajov v prípade poškodenia/straty vyrovnávacej pamäte, autor navrhuje zaviesť prax otáčania snímok, aby sa v tomto prípade zaručila ich integrita.

Po prvé, pretože metadáta tenkého objemu sa nachádzajú na zariadení bez vyrovnávacej pamäte, metadáta budú konzistentné a možné straty budú izolované v rámci dátových blokov.

Nasledujúci cyklus rotácie snímok zaručuje integritu údajov vo vnútri snímok v prípade straty vyrovnávacej pamäte:

  1. Pre každý tenký zväzok s názvom <názov> vytvorte snímku s názvom <názov>.cached
  2. Nastavme prah migrácie na primerane vysokú hodnotu: #lvchange --quiet --cachesettings "migration_threshold=16384" cache/cachedata
  3. V slučke kontrolujeme počet špinavých blokov vo vyrovnávacej pamäti: #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' Kým nedostaneme nulu. Ak nula chýba príliš dlho, dá sa vytvoriť dočasným prepnutím vyrovnávacej pamäte do režimu zapisovania. Ak však vezmeme do úvahy rýchlostné charakteristiky našich polí SATA a NVME SSD, ako aj ich zdroj TBW, budete môcť rýchlo zachytiť okamih bez zmeny režimu vyrovnávacej pamäte, alebo váš hardvér úplne zje celý svoj zdroj niekoľko dní. Vzhľadom na obmedzenia zdrojov systém v zásade nemôže byť stále pod 100% načítať záťaž. Naše NVME SSDS pod 100% zaťaženie zápisu úplne vyčerpajú zdroj v 3 4-dni. SATA SSD vydržia len dvakrát tak dlho. Preto budeme predpokladať, že väčšina záťaže ide na čítanie a máme relatívne krátkodobé výbuchy extrémne vysokej aktivity v kombinácii s nízkou priemernou záťažou pri písaní.
  4. Hneď ako sme zachytili (alebo urobili) nulu, premenujeme <name>.cached na <name>.committed. Starý súbor <name>.committed je odstránený.
  5. Voliteľne, ak je vyrovnávacia pamäť 100% plná, môže byť znovu vytvorená skriptom, čím sa vymaže. S poloprázdnou vyrovnávacou pamäťou funguje systém pri zápise oveľa rýchlejšie.
  6. Nastavte prah migrácie na nulu: #lvchange --quiet --cachesettings "migration_threshold=0" cache/cachedata Toto dočasne zabráni synchronizácii vyrovnávacej pamäte s hlavným médiom.
  7. Čakáme, kým sa vo vyrovnávacej pamäti nahromadí veľa zmien #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' alebo sa časovač vypne.
  8. Opakujeme znova.

Prečo problémy s migračným prahom...?Ide o to, že v reálnej praxi „náhodný“ záznam v skutočnosti nie je úplne náhodný. Ak sme niečo zapísali do sektora s veľkosťou 4 kilobajty, je vysoká pravdepodobnosť, že v najbližších minútach sa vytvorí záznam do rovnakého alebo jedného zo susedných (+- 32K) sektorov.

Nastavením prahu migrácie na nulu odložíme synchronizáciu zápisu na SATA SSD a agregujeme niekoľko zmien do jedného 64K bloku vo vyrovnávacej pamäti. To výrazne šetrí zdroje SATA SSD.

Kde je kód..?Žiaľ, autor sa považuje za nedostatočne kompetentného vo vývoji bash skriptov, pretože je 100% samouk a praktizuje vývoj riadený „googlením“, preto sa domnieva, že strašný kód, ktorý vychádza z jeho rúk, by nemal používať nikto inak.

Myslím si, že profesionáli v tejto oblasti budú v prípade potreby schopní nezávisle zobraziť všetku vyššie opísanú logiku a možno ju dokonca krásne navrhnúť ako systémovú službu, ako sa o to pokúsil autor.

Takáto jednoduchá schéma rotácie snímky nám umožní nielen neustále mať jednu snímku plne synchronizovanú na SATA SSD, ale umožní nám pomocou utility thin_delta zistiť, ktoré bloky boli po jej vytvorení zmenené, a tak lokalizovať poškodenie na hlavné objemy, čo výrazne zjednodušuje obnovu .

TRIM/DISCARD v libvirt/KVM

Pretože Ukladanie údajov sa použije na KVM spustenie libvirt, potom by bolo dobré naučiť naše virtuálne počítače nielen zaberať voľný priestor, ale tiež uvoľniť to, čo už nie je potrebné.

To sa dosiahne emuláciou podpory TRIM/DISCARD na virtuálnych diskoch. Ak to chcete urobiť, musíte zmeniť typ ovládača na virtio-scsi a upraviť xml.

#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>

Takéto DISCARDs z hosťujúcich OS sú správne spracované LVM a bloky sú správne uvoľnené vo vyrovnávacej pamäti aj v tenkom fonde. V našom prípade sa to deje najmä oneskorene, pri odstraňovaní nasledujúcej snímky.

Záloha BTRFS

Použite hotové skripty s extrémna opatrnosť a na vlastné riziko. Autor napísal tento kód sám a výlučne pre seba. Som si istý, že mnoho skúsených používateľov Linuxu má podobné nástroje a nie je potrebné kopírovať nástroje niekoho iného.

Vytvorime hlasitosť na záložnom zariadení:

#lvcreate -L 256G --name backup backup

Naformátujme ho v BTRFS:

#mkfs.btrfs /dev/backup/backup

Poďme vytvoriť body pripojenia a pripojiť koreňové podsekcie systému súborov:

#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

Vytvorme adresáre pre zálohy:

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

Vytvorme adresár pre záložné skripty:

#mkdir /root/btrfs-backup

Skopírujeme skript:

Veľa strašidelného bash kódu. Použitie na vlastné riziko. Nepíšte autorovi nahnevané listy...#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

Čo to dokonca robí ..?Obsahuje sadu jednoduchých príkazov na vytváranie BTRFS snímok a ich kopírovanie do iného FS pomocou BTRFS odosielať/prijímať.

Prvé spustenie môže byť relatívne dlhé, pretože ... Na začiatku sa skopírujú všetky údaje. Ďalšie spustenie bude veľmi rýchle, pretože ... Skopírujú sa iba zmeny.

Ďalší skript, ktorý vložíme do cronu:

Ešte nejaký 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

Čo to robí..?Vytvára a synchronizuje prírastkové snímky uvedených zväzkov BTRFS na záložnom FS. Potom vymaže všetky obrázky vytvorené pred 60 dňami. Po spustení sa v podadresároch /backup/btrfs/back/remote/ zobrazia datované snímky uvedených zväzkov.

Dajme práva na spustenie kódu:

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

Skontrolujeme to a vložíme do cronu:

#/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

Tenká záloha LVM

Vytvorme tenký fond na záložnom zariadení:

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

Poďme nainštalovať ddrescue, pretože... skripty budú používať tento nástroj:

#apt-get install gddrescue

Vytvorme adresár pre skripty:

#mkdir /root/lvm-thin-backup

Skopírujeme skripty:

Veľa bashu vo vnútri...#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

Čo to robí...?Obsahuje sadu príkazov na manipuláciu s tenkými snímkami a synchronizáciu rozdielu medzi dvoma tenkými snímkami prijatými cez thin_delta do iného blokového zariadenia pomocou ddrescue a blkdiscard.

Ďalší skript, ktorý vložíme do cronu:

Trochu viac bash#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

Čo to robí...?Používa predchádzajúci skript na vytváranie a synchronizáciu záloh uvedených tenkých zväzkov. Skript ponechá neaktívne snímky uvedených zväzkov, ktoré sú potrebné na sledovanie zmien od poslednej synchronizácie.

Tento skript je potrebné upraviť a určiť zoznam tenkých zväzkov, pre ktoré sa majú vytvárať záložné kópie. Uvedené názvy sú len ilustračné. Ak chcete, môžete napísať skript, ktorý zosynchronizuje všetky zväzky.

Dajme práva:

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

Skontrolujeme to a vložíme do cronu:

#/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

Prvé spustenie bude dlhé, pretože ... Tenké objemy budú úplne synchronizované kopírovaním všetkého použitého priestoru. Vďaka LVM tenkým metadátom vieme, ktoré bloky sa skutočne používajú, takže sa skopírujú iba použité iba tenké objemové bloky.

Nasledujúce spustenia budú kopírovať údaje postupne vďaka sledovaniu zmien prostredníctvom tenkých metadát LVM.

Pozrime sa, čo sa stalo:

#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

Čo to má spoločné s hniezdiacimi bábikami?

S najväčšou pravdepodobnosťou, vzhľadom na to, že logické zväzky LVM LV môžu byť fyzickými zväzkami LVM PV pre iné VG. LVM môže byť rekurzívne, ako hniezdiace bábiky. To dáva LVM extrémnu flexibilitu.

PS

V ďalšom článku sa pokúsime použiť niekoľko podobných mobilných úložných systémov/KVM ako základ pre vytvorenie geo-distribuovaného úložného/vm klastra s redundanciou na viacerých kontinentoch pomocou domácich desktopov, domáceho internetu a P2P sietí.

Zdroj: hab.com

Pridať komentár