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.
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:
- Bármikor kidobhatja ezt az adaptert, és lecserélheti bármelyik másikra.
- 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:
- Minden vékony, <név> nevű kötethez hozzon létre egy pillanatképet <név>.cached néven
- Á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
- 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. - 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.
- 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.
- Á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. - 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. - 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