Wat hawwe LVM en matryoshka mienskiplik?

Kening tiid fan 'e dei.
Ik wol myn praktyske ûnderfining mei de mienskip diele mei it bouwen fan in gegevensopslachsysteem foar KVM mei md RAID + LVM.

It programma sil omfetsje:

  • Bouwe md RAID 1 fan NVMe SSD.
  • Sammelje md RAID 6 fan SATA SSD en reguliere skiven.
  • Skaaimerken fan TRIM / DISCARD operaasje op SSD RAID 1/6.
  • It meitsjen fan in bootbere md RAID 1/6-array op in mienskiplike set fan skiven.
  • It systeem ynstallearje op NVMe RAID 1 as d'r gjin NVMe-stipe is yn 'e BIOS.
  • Gebrûk fan LVM-cache en LVM thin.
  • BTRFS-snapshots brûke en ferstjoere / ûntfange foar reservekopy.
  • Gebrûk fan LVM tinne snapshots en thin_delta foar backups fan BTRFS-styl.

As jo ​​​​ynteressearre binne, sjoch dan kat.

Bewurkingsfoarm

De skriuwer draacht gjin ferantwurdlikens foar de gefolgen fan it brûken fan materialen / foarbylden / koade / tips / gegevens út dit artikel of net. Troch dit materiaal op ien of oare manier te lêzen of te brûken, nimme jo ferantwurdlikens foar alle gefolgen fan dizze aksjes. Mooglike gefolgen omfetsje:

  • Crisp-fried NVMe SSD's.
  • Folslein brûkte opnameboarne en mislearjen fan SSD-skiven.
  • Folslein ferlies fan alle gegevens op alle skiven, ynklusyf reservekopyen.
  • Defekte kompjûter hardware.
  • Fergrieme tiid, senuwen en jild.
  • Alle oare gefolgen dy't net hjirboppe neamd binne.

Iron

Beskikber wiene:

Motherboard út om 2013 mei Z87 chipset, kompleet mei Intel Core i7 / Haswell.

  • Prosessor 4 kearnen, 8 triedden
  • 32 GB DDR3 RAM
  • 1 x 16 of 2 x 8 PCIe 3.0
  • 1 x 4 + 1 x 1 PCIe 2.0
  • 6 x 6 GBps SATA 3 Anschlüsse

SAS adapter LSI SAS9211-8I flashed nei IT / HBA modus. RAID-ynskeakele firmware is mei opsetsin ferfongen troch HBA-firmware om:

  1. Jo kinne dizze adapter op elk momint útsmite en ferfange troch elke oare dy't jo tsjinkaam.
  2. TRIM / Discard wurke normaal op skiven, om't ... yn RAID firmware dizze kommando's wurde net stipe hielendal, en de HBA, yn it algemien, net skele hokker kommando's wurde oerdroegen oer de bus.

Hurde skiven - 8 stikken HGST Travelstar 7K1000 mei in kapasiteit fan 1 TB yn in 2.5-foarmfaktor, lykas foar laptops. Dizze skiven wiene earder yn in RAID 6-array. Se sille ek in gebrûk hawwe yn it nije systeem. Om lokale backups op te slaan.

Dêrneist tafoege:

6 stikken SATA SSD model Samsung 860 QVO 2TB. Dizze SSD's easke in grut folume, de oanwêzigens fan in SLC-cache, betrouberens en in lege priis wiene winske. Stipe foar wegerje / nul wie fereaske, wat wurdt kontrolearre troch de line yn dmesg:

kernel: ata1.00: Enabling discard_zeroes_data

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

Foar dizze SSD's binne willekeurige lês- / skriuwsnelheid en boarnekapasiteit foar jo behoeften wichtich. Radiator foar harren. Needsaaklik. Absolút. Oars, fry se oant krokante tidens de earste RAID-syngronisaasje.

StarTech PEX8M2E2 adapter foar 2 x NVMe SSD ynstallearre yn PCIe 3.0 8x slot. Dit is wer gewoan in HBA, mar foar NVMe. It ferskilt fan goedkeape adapters yn dat it gjin PCIe-bifurkaasje-stipe fan it moederbord fereasket troch de oanwêzigens fan in ynboude PCIe-switch. It sil wurkje sels yn de âldste systeem mei PCIe, sels as it is in x1 PCIe 1.0 slot. Fansels, op 'e passende snelheid. Der binne gjin RAIDs dêr. Der is gjin ynboude BIOS oan board. Dat, jo systeem sil net magysk leare om te booten mei NVMe, folle minder dwaan NVMe RAID tanksij dit apparaat.

Dizze komponint wie allinich te tankjen oan de oanwêzigens fan mar ien frije 8x PCIe 3.0 yn it systeem, en, as d'r 2 frije slots binne, kin it maklik wurde ferfongen troch twa penny PEX4M2E1 of analogen, dy't oeral kinne wurde kocht foar in priis fan 600 roebels.

De ôfwizing fan allerhanne hardware of ynboude chipset/BIOS RAID's waard bewust makke, om it hiele systeem folslein te ferfangen, mei útsûndering fan 'e SSD / HDD sels, wylst alle gegevens behâlde wurde. Ideaal, sadat jo sels it ynstalleare bestjoeringssysteem kinne bewarje as jo ferhúzje nei folslein nije / oare hardware. It wichtichste is dat d'r SATA- en PCIe-poarten binne. It is as in live CD as bootbere flash-drive, allinich heul rap en in bytsje bulk.

HumorOars witte jo wat der bart - soms moatte jo driuwend de hiele array meinimme om fuort te nimmen. Mar ik wol gjin gegevens ferlieze. Om dit te dwaan, binne alle neamde media maklik te finen op 'e dia's yn' e 5.25 baaien fan 'e standert saak.

No, en, fansels, foar eksperimintearjen mei ferskate metoaden fan SSD-caching yn Linux.

Hardware ynfallen binne saai. Set it oan. It wurket of it wurket net. En mei mdadm binne d'r altyd opsjes.

Software

Earder waard Debian 8 Jessie ynstalleare op 'e hardware, dy't tichtby EOL is. RAID 6 waard gearstald út de hjirboppe neamde HDD's keppele mei LVM. It rûn firtuele masines yn kvm/libvirt.

Omdat De skriuwer hat gaadlike ûnderfining yn it meitsjen fan draachbere bootbere SATA / NVMe-flash-driven, en ek, om it gewoane apt-sjabloan net te brekken, waard Ubuntu 18.04 keazen as it doelsysteem, dat al genôch stabilisearre is, mar noch 3 jier hat fan stipe yn 'e takomst.

It neamde systeem befettet alle hardware-bestjoerders dy't wy út 'e doaze nedich binne. Wy hawwe gjin software of stjoerprogramma's fan tredden nedich.

Tariede op ynstallaasje

Om it systeem te ynstallearjen hawwe wy Ubuntu Desktop Image nedich. It serversysteem hat in soarte fan krêftige ynstallearder, dy't oermjittige ûnôfhinklikens toant dy't net kin wurde útskeakele troch de UEFI-systeemdieling op ien fan 'e skiven te skowen, en alle skientme fergriemt. Dêrom wurdt it allinich ynstalleare yn UEFI-modus. Biedt gjin opsjes.

Hjir binne wy ​​net bliid mei.

Wêrom?Spitigernôch is UEFI-boot ekstreem min kompatibel mei bootsoftware RAID, om't ... Nimmen biedt ús reservearrings foar de UEFI ESP-partysje. D'r binne resepten online dy't suggerearje it pleatsen fan de ESP-partysje op in flash-drive yn in USB-poarte, mar dit is in punt fan mislearring. D'r binne resepten dy't software brûke mdadm RAID 1 mei metadata ferzje 0.9 dy't net foarkomme dat de UEFI BIOS dizze partysje sjocht, mar dit libbet oant it lokkige momint as de BIOS of in oare hardware OS wat skriuwt nei de ESP en ferjit it te syngronisearjen mei oare spegels.

Derneist is UEFI-boot ôfhinklik fan NVRAM, dy't net mei de skiven nei it nije systeem ferpleatse, om't is diel fan it moederbord.

Dat, wy sille gjin nij tsjil útfine. Wy hawwe al in klearmakke, yn 'e tiid hifke pake-fyts, no neamd Legacy / BIOS-boot, mei de grutske namme fan CSM op UEFI-kompatible systemen. Wy nimme it gewoan fan 'e planke, smearje it, pompe de bannen op en feie it mei in fochtige doek.

De buroblêdferzje fan Ubuntu kin ek net goed ynstalleare wurde mei de Legacy bootloader, mar hjir, lykas se sizze, binne d'r teminsten opsjes.

En sa sammelje wy de hardware en laden it systeem fan 'e Ubuntu Live bootbere flash drive. Wy sille pakketten moatte downloade, dus wy sille it netwurk ynstelle dat foar jo wurket. As it net wurket, kinne jo de nedige pakketten fan tefoaren op in flash drive laden.

Wy geane yn 'e buroblêd-omjouwing, starte de terminalemulator, en geane wy:

#sudo bash

Hoe…?De line hjirboppe is de kanonike trigger foar holiwars oer sudo. C bоgruttere kânsen komme enоgruttere ferantwurdlikens. De fraach is oft jo it sels nimme kinne. In protte minsken tinke dat it brûken fan sudo op dizze manier teminsten net foarsichtich is. Lykwols:

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

Wêrom net ZFS...?As wy software op ús kompjûter ynstallearje, liene wy ​​yn essinsje ús hardware oan de ûntwikkelders fan dizze software om te riden.
As wy dizze software fertrouwe mei de feiligens fan ús gegevens, nimme wy in liening út lykweardich oan de kosten fan it werombringen fan dizze gegevens, dy't wy ienris moatte betelje.

Ut dit eachpunt, ZFS is in Ferrari, en mdadm + lvm is mear as in fyts.

Subjektyf lient de skriuwer leaver in fyts op kredyt oan ûnbekende persoanen yn stee fan in Ferrari. Dêr is de priis fan de útjefte net heech. Gjin ferlet fan rjochten. Ienfâldiger dan ferkearsregels. Parkearje is fergees. Cross-country fermogen is better. Jo kinne altyd heakje skonken oan in fyts, en jo kinne reparearje in fyts mei jo eigen hannen.

Wêrom dan BTRFS...?Om it bestjoeringssysteem te booten, hawwe wy in bestânsysteem nedich dat wurdt stipe yn Legacy / BIOS GRUB út 'e doaze, en tagelyk live snapshots stipet. Wy sille it brûke foar de /boot-partysje. Derneist hat de auteur it leafst dizze FS te brûken foar / (root), net te ferjitten om te notearjen dat jo foar elke oare software aparte partysjes kinne oanmeitsje op LVM en se yn 'e nedige mappen montearje.

Wy sille gjin ôfbyldings fan firtuele masines of databases opslaan op dizze FS.
Dizze FS sil allinich brûkt wurde om snapshots fan it systeem te meitsjen sûnder it út te skeakeljen en dizze snapshots dan oer te setten nei in reservekopyskiif mei ferstjoere/ûntfange.

Derneist hat de auteur oer it algemien it leafst in minimum fan software direkt op 'e hardware te hâlden en alle oare software yn firtuele masines út te fieren mei dingen lykas it trochstjoeren fan GPU's en PCI-USB Host-controllers nei KVM fia IOMMU.

De ienige dingen oerbleaun op 'e hardware binne gegevens opslach, virtualisaasje en backup.

As jo ​​​​ZFS mear fertrouwe, dan binne se yn prinsipe útwikselber foar de oantsjutte applikaasje.

De skriuwer negeart lykwols bewust de ynboude spegeljen / RAID- en redundânsjefunksjes dy't ZFS, BRTFS en LVM hawwe.

As ekstra argumint hat BTRFS de mooglikheid om willekeurige skriuwwizen te feroarjen yn opfolgjende, dy't in ekstreem posityf effekt hat op 'e snelheid fan syngronisaasje fan snapshots / backups op' e HDD.

Litte wy alle apparaten opnij scannen:

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

Litte wy ris omhinne sjen:

#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

Skiif yndieling

NVMe SSD's

Mar wy sille net markearje se op hokker wize. Dochs sjocht ús BIOS dizze skiven net. Dat, se sille folslein nei software RAID gean. Wy sille dêr sels gjin seksjes oanmeitsje. As jo ​​​​de "kanon" of "prinsipieel" wolle folgje, meitsje dan ien grutte partysje, lykas in HDD.

SATA HDDs

It is net nedich om hjir wat spesjaal út te finen. Wy meitsje ien seksje foar alles. Wy sille in partysje meitsje om't de BIOS dizze skiven sjocht en kin sels besykje fan har te booten. Wy sille sels GRUB letter op dizze skiven ynstallearje, sadat it systeem dit ynienen kin dwaan.

#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

Dit is wêr't dingen foar ús ynteressant wurde.

As earste binne ús skiven 2 TB yn grutte. Dit is binnen it akseptabele berik foar MBR, dat is wat wy sille brûke. As it nedich is, kin wurde ferfongen troch GPT. GPT-skiven hawwe in kompatibiliteitslaach wêrtroch MBR-kompatibele systemen de earste 4-partysjes kinne sjen as se binnen de earste 2 terabytes lizze. It wichtichste is dat de bootpartysje en bios_grub-partysje op dizze skiven oan it begjin moatte wêze. Hjirmei kinne jo sels bootje fan GPT Legacy / BIOS-skiven.

Mar dit is net ús gefal.

Hjir sille wy twa seksjes oanmeitsje. De earste sil 1 GB yn grutte wêze en brûkt foar RAID 1 /boot.

De twadde sil brûkt wurde foar RAID 6 en sil alle oerbleaune frije romte opnimme, útsein foar in lyts net-allokearre gebiet oan 'e ein fan it stasjon.

Wat is dit net markearre gebiet?Neffens boarnen op it netwurk hawwe ús SATA SSD's oan board in dynamysk útwreidbere SLC-cache, fariearjend yn grutte fan 6 oant 78 gigabytes. Wy krije 6 gigabytes "fergees" troch it ferskil tusken "gigabytes" en "gibibytes" yn it gegevensblêd fan it stasjon. De oerbleaune 72 gigabytes wurde tawiisd út net brûkte romte.

Hjir moat opmurken wurde dat wy hawwe in SLC cache, en de romte is beset yn 4 bit MLC modus. Wat foar ús effektyf betsjut dat wy foar elke 4 gigabyte frije romte allinich 1 gigabyte fan SLC-cache krije.

Fermannichfâldigje 72 gigabyte mei 4 en krije 288 gigabyte. Dit is de frije romte dy't wy net sille markearje om de skiven folslein gebrûk te meitsjen fan 'e SLC-cache.

Sa sille wy effektyf oant 312 gigabytes fan SLC-cache krije fan in totaal fan seis skiven. Fan alle skiven sille 2 wurde brûkt yn RAID foar redundânsje.

Dit bedrach fan cache sil tastean ús te komselden yn it echte libben tsjinkomme in situaasje dêr't in skriuwen net giet nei de cache. Dit kompensearret ekstreem goed foar it tryste neidiel fan QLC-ûnthâld - de ekstreem lege skriuwsnelheid as gegevens skreaun wurde om de cache te omgean. As jo ​​loads net oerienkomme mei dit, dan advisearje ik dat jo hurd tinke oer hoe lang jo SSD sil duorje ûnder sa'n lading, rekken hâldend mei de TBW fan it gegevensblêd.

#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

Arrays oanmeitsje

Earst moatte wy de masine omneame. Dit is nedich om't de hostnamme diel is fan 'e arraynamme earne binnen mdadm en earne wat beynfloedet. Fansels kinne arrays letter omneamd wurde, mar dit is in ûnnedige stap.

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

NVMe SSD's

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

Wêrom -oannimme-skjin...?Om foar te kommen inisjalisearjen fan arrays. Foar beide RAID-nivo's 1 en 6 is dit jildich. Alles kin wurkje sûnder inisjalisaasje as it in nije array is. Boppedat is it inisjalisearjen fan de SSD-array by skepping in fergriemerij fan TBW-boarne. Wy brûke TRIM / DISCARD wêr mooglik op gearstalde SSD-arrays om se "inisjalisearje".

Foar SSD-arrays wurdt RAID 1 DISCARD út it fak stipe.

Foar SSD RAID 6 DISCARD-arrays moatte jo it ynskeakelje yn 'e parameters fan' e kernelmodule.

Dit moat allinnich dien wurde as alle SSD's brûkt yn nivo 4/5/6 arrays yn dit systeem hawwe wurkjende stipe foar discard_zeroes_data. Soms komme jo frjemde skiven tsjin dy't de kernel fertelle dat dizze funksje wurdt stipe, mar yn feite is it der net, of de funksje wurket net altyd. Op it stuit is stipe hast oeral beskikber, lykwols binne d'r âlde skiven en firmware mei flaters. Om dizze reden is DISCARD-stipe standert útskeakele foar RAID 6.

Oandacht, it folgjende kommando sil alle gegevens op NVMe-skiven ferneatigje troch de array te "initialisearjen" mei "nullen".

#blkdiscard /dev/md0

As der wat mis giet, besykje dan in stap op te jaan.

#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

Wêrom sa grut...?It fergrutsjen fan de brok-grutte hat in posityf effekt op de snelheid fan willekeurich lêzen yn blokken oant brok-grutte ynklusyf. Dit bart om't ien operaasje fan 'e passende grutte of lytser folslein kin wurde foltôge op ien apparaat. Dêrom wurdt de IOPS fan alle apparaten gearfette. Neffens statistiken is 99% fan IO net mear as 512K.

RAID 6 IOPS per skriuwen altyd minder as of gelyk oan de IOPS fan ien stasjon. Wannear't, as in willekeurige lêzing, IOPS kin ferskate kearen grutter wêze as dy fan ien stasjon, en hjir is de blokgrutte fan kaai belang.
De skriuwer sjocht it punt net yn it besykjen om in parameter te optimalisearjen dy't min is yn RAID 6 by-ûntwerp en optimisearret ynstee wêryn RAID 6 goed is.
Wy sille kompensearje foar it minne willekeurich skriuwen fan RAID 6 mei in NVMe-cache en tinne-foarsjenningstricks.

Wy hawwe DISCARD noch net ynskeakele foar RAID 6. Sa sille wy dizze array foar no net "inisjalisearje". Wy sille dit letter dwaan, nei it ynstallearjen fan it OS.

SATA HDDs

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

LVM op NVMe RAID

Foar snelheid wolle wy it rootbestânsysteem pleatse op NVMe RAID 1 dat is /dev/md0.
Wy sille dizze snelle array lykwols noch nedich hawwe foar oare behoeften, lykas swap, metadata en LVM-cache en LVM-tinne metadata, sadat wy in LVM VG op dizze array meitsje.

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

Litte wy in partysje meitsje foar it rootbestânsysteem.

#lvcreate -L 128G --name root root

Litte wy in partysje meitsje foar ruiljen neffens de grutte fan 'e RAM.

#lvcreate -L 32G --name swap root

OS ynstallaasje

Yn totaal hawwe wy alles nedich om it systeem te ynstallearjen.

Starte de systeemynstallaasjewizard fanút de Ubuntu Live-omjouwing. Normale ynstallaasje. Allinich op it poadium fan it selektearjen fan skiven foar ynstallaasje, moatte jo de folgjende opjaan:

  • /dev/md1, - mount punt /boot, FS - BTRFS
  • /dev/root/root (aka /dev/mapper/root-root), - mount point / (root), FS - BTRFS
  • /dev/root/swap (aka /dev/mapper/root-swap), - brûke as swap-partysje
  • Ynstallearje de bootloader op /dev/sda

As jo ​​​​BTRFS selektearje as it rootbestânsysteem, sil de ynstallator automatysk twa BTRFS-voluminten oanmeitsje mei de namme "@" foar / (root), en "@home" foar /home.

Litte wy de ynstallaasje begjinne ...

De ynstallaasje sil einigje mei in modaal dialoochfinster dat in flater oanjout by it ynstallearjen fan de bootloader. Spitigernôch sille jo dit dialooch net kinne ferlitte mei standert middels en trochgean mei de ynstallaasje. Wy logje út fan it systeem en loggen opnij oan, einigje op in skjinne Ubuntu Live-buroblêd. Iepenje de terminal, en wer:

#sudo bash

Meitsje in chroot-omjouwing om de ynstallaasje troch te gean:

#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

Litte wy it netwurk en de hostnamme yn chroot konfigurearje:

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

Litte wy yn 'e chroot-omjouwing gean:

#chroot /mnt/chroot

As earste sille wy de pakketten leverje:

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

Litte wy alle pakketten kontrolearje en reparearje dy't krom binne ynstalleare fanwegen ûnfolsleine systeemynstallaasje:

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

As der wat net wurket, moatte jo miskien earst /etc/apt/sources.list bewurkje

Litte wy de parameters foar de RAID 6-module oanpasse om TRIM / DISCARD yn te skeakeljen:

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

Litte wy ús arrays in bytsje oanpasse:

#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

Wat wie it..?Wy hawwe in set udev-regels makke dy't it folgjende sille dwaan:

  • Stel de blokcache-grutte foar RAID 2020 yn om adekwaat te wêzen foar 6. De standertwearde, liket it, is net feroare sûnt de skepping fan Linux, en hat in lange tiid net genôch west.
  • Reservearje in minimum fan IO foar de doer fan arraykontrôles / syngronisaasjes. Dit is om te foarkommen dat jo arrays yn in steat fan ivige syngronisaasje ûnder load sitte.
  • Beheine de maksimale IO by kontrôles / syngronisaasje fan arrays. Dit is nedich sadat syngronisearje / kontrolearje SSD RAIDs net fry jo driuwfearren ta in crisp. Dit is benammen wier foar NVMe. (Onthâld oer de radiator? Ik makke gjin grapke.)
  • Ferbiede skiven fan it stopjen fan spindelrotaasje (HDD) fia APM en set de slieptiid foar skiifcontrollers op 7 oeren. Jo kinne APM folslein útskeakelje as jo skiven it kinne dwaan (-B 255). Mei de standertwearde stopje de skiven nei fiif sekonden. Dan wol it OS de skiifcache weromsette, de skiven sille opnij draaie, en alles sil opnij begjinne. Discs hawwe in beheind maksimum oantal spindle rotations. Sa'n ienfâldige standertsyklus kin jo skiven maklik yn in pear jier deadzje. Net alle skiven lije hjirfan, mar ús binne "laptop", mei de passende standertynstellingen, dy't de RAID meitsje as in mini-MAID.
  • Ynstallearje readahead op skiven (draaiend) 1 megabyte - twa opienfolgjende blokken / brok RAID 6
  • Utskeakelje readahead op de arrays sels.

Litte wy /etc/fstab bewurkje:

#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

Wêrom is dat..?Wy sille sykje nei de / boot partition troch UUID. Array-namme koe teoretysk feroarje.

Wy sille sykje nei de oerbleaune seksjes troch LVM-nammen yn 'e /dev/mapper/vg-lv-notaasje, om't se identifisearje partysjes frij unyk.

Wy brûke gjin UUID foar LVM omdat De UUID fan LVM-voluminten en har snapshots kinne itselde wêze.Mount /dev/mapper/root-root .. twa kear?Ja. Krekt. Funksje fan BTRFS. Dit bestânsysteem kin ferskate kearen wurde monteare mei ferskate subvols.

Fanwegen deselde funksje advisearje ik nea LVM-snapshots te meitsjen fan aktive BTRFS-voluminten. Jo kinne in ferrassing krije as jo opnij starte.

Litte wy de mdadm-konfiguraasje regenerearje:

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

Litte wy de LVM-ynstellingen oanpasse:

#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

Wat wie it..?Wy hawwe automatyske útwreiding fan LVM tinne swimbaden ynskeakele by it berikken fan 90% fan 'e besette romte mei 5% fan it folume.

Wy hawwe it maksimale oantal cacheblokken foar LVM-cache ferhege.

Wy hawwe foarkommen dat LVM nei LVM-voluminten (PV) sykje op:

  • apparaten mei LVM-cache (cdata)
  • apparaten yn 'e cache mei LVM-cache, om de cache ( _corig). Yn dit gefal sil it cache-apparaat sels noch troch de cache skend wurde (gewoan ).
  • apparaten mei LVM-cache-metadata (cmeta)
  • alle apparaten yn VG mei de namme ôfbyldings. Hjir sille wy skiifôfbyldings hawwe fan firtuele masines, en wy wolle net dat LVM op 'e host folumes aktivearje dy't ta it gast OS hearre.
  • alle apparaten yn VG mei de namme reservekopy. Hjir sille wy reservekopyen hawwe fan ôfbyldings fan firtuele masines.
  • alle apparaten wêrfan de namme einiget mei "gpv" (fysike gastvolume)

Wy hawwe DISCARD-stipe ynskeakele by it frijmeitsjen fan frije romte op LVM VG. Wês foarsichtich. Dit sil it wiskjen fan LV's op 'e SSD frij tiidslinend meitsje. Dat jildt benammen foar SSD RAID 6. Lykwols, neffens it plan, wy sille brûke tinne foarsjenning, dus dit sil net hinderje ús hielendal.

Litte wy it initramfs-ôfbylding bywurkje:

#update-initramfs -u -k all

Ynstallearje en konfigurearje grub:

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

Hokker skiven te kiezen?Allegear dy't sd* binne. It systeem moat opstarte kinne fan elke wurkjende SATA-drive of SSD.

Wêrom hawwe se os-prober tafoege..?Foar oermjittige ûnôfhinklikens en boartlike hannen.

It wurket net goed as ien fan 'e RAID's yn in degradearre steat is. It besiket te sykjen nei it OS op partysjes dy't wurde brûkt yn firtuele masines dy't op dizze hardware rinne.

As jo ​​​​it nedich hawwe, kinne jo it ferlitte, mar hâld al it boppesteande yn gedachten. Ik riede oan op syk nei resepten foar it kwytreitsje fan stoute hannen online.

Hjirmei hawwe wy de earste ynstallaasje foltôge. It is tiid om te herstarten yn it nij ynstalleare OS. Ferjit net de bootbere Live CD / USB te ferwiderjen.

#exit
#reboot

Selektearje ien fan 'e SATA SSD's as it bootapparaat.

LVM op SATA SSD

Op dit punt hawwe wy al booten yn it nije OS, it netwurk konfigureare, apt, de terminalemulator iepene en lansearre:

#sudo bash

Litte wy trochgean.

"Inisjalisearje" de array fan SATA SSD:

#blkdiscard /dev/md2

As it net wurket, besykje dan:

#blkdiscard --step 65536 /dev/md2
Meitsje LVM VG op SATA SSD:

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

Wêrom noch in VG..?Yn feite hawwe wy al in VG mei de namme root. Wêrom net alles tafoegje yn ien VG?

As d'r ferskate PV's binne yn in VG, dan moatte alle PV's oanwêzich wêze (online) om de VG goed te aktivearjen. De útsûndering is LVM RAID, dy't wy mei opsetsin net brûke.

Wy wolle wirklik dat as d'r in mislearring is (lês gegevensferlies) op ien fan 'e RAID 6-arrays, it bestjoeringssysteem normaal sil bootje en ús de kâns jaan om it probleem op te lossen.

Om dit te dwaan, sille wy op it earste nivo fan abstraksje elk type fysike "media" isolearje yn in aparte VG.

Wittenskiplik sjoen hearre ferskate RAID-arrays ta ferskate "betrouwensdomeinen". Jo moatte gjin ekstra mienskiplik punt fan mislearring foar har meitsje troch se yn ien VG te proppen.

De oanwêzigens fan LVM op it "hardware" nivo sil ús tastean om willekeurich stikken fan ferskate RAID-arrays te snijen troch se op ferskate manieren te kombinearjen. Bygelyks - rinne tagelyk bcache + LVM tinne, bcache + BTRFS, LVM cache + LVM tinne, in komplekse ZFS-konfiguraasje mei caches, of in oar helske mingsel om te besykjen en fergelykje it allegear.

Op it nivo "hardware" sille wy neat oars brûke as goede âlde "dikke" LVM-voluminten. De útsûndering op dizze regel kin de reservekopydieling wêze.

Ik tink dat op dit stuit in protte lêzers al wat begûnen te fertinken oer de nêstpop.

LVM op SATA HDD

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

Wer Nije VG..?Wy wolle wirklik dat as de skiif-array dy't wy sille brûke foar gegevensreservekopy mislearret, ús bestjoeringssysteem normaal sil wurkje, wylst tagong ta net-reservekopygegevens as gewoanlik behâldt. Dêrom, om VG-aktivearringsproblemen te foarkommen, meitsje wy in aparte VG.

LVM-cache ynstelle

Litte wy in LV oanmeitsje op NVMe RAID 1 om it as caching-apparaat te brûken.

#lvcreate -L 70871154688B --name cache root

Wêrom is der sa min...?It feit is dat ús NVMe SSD's ek in SLC-cache hawwe. 4 gigabytes "fergees" en 18 gigabytes dynamysk fanwegen de frije romte beset yn 'e 3-bit MLC. Ienris dizze cache is útput, sille NVMe SSD's net folle rapper wêze dan ús SATA SSD mei cache. Eigentlik makket it om dizze reden gjin sin foar ús om de LVM-cache-partition folle grutter te meitsjen as twa kear de grutte fan 'e SLC-cache fan it NVMe-stasjon. Foar de brûkte NVMe-skiven achtet de auteur it ridlik om 32-64 gigabytes fan cache te meitsjen.

De opjûne partitiongrutte is nedich om 64 gigabytes fan cache, cache-metadata en metadata-backup te organisearjen.

Derneist, Ik merk op dat nei in smoarch systeem shutdown, LVM sil markearje de hiele cache as smoarch en sil syngronisearje wer. Boppedat sil dit elke kear werhelle wurde as lvchange wurdt brûkt op dit apparaat oant it systeem wer opnij is. Dêrom advisearje ik de cache fuortendaliks opnij oan te meitsjen mei it passende skript.

Litte wy in LV meitsje op SATA RAID 6 om it te brûken as in cached apparaat.

#lvcreate -L 3298543271936B --name cache data

Wêrom mar trije terabytes ..?Sadat jo, as it nedich is, SATA SSD RAID 6 kinne brûke foar guon oare behoeften. De grutte fan 'e cached romte kin dynamysk ferhege wurde, op 'e flecht, sûnder it systeem te stopjen. Om dit te dwaan, moatte jo de cache tydlik stopje en opnij ynskeakelje, mar it ûnderskiedende foardiel fan LVM-cache boppe bygelyks bcache is dat dit op 'e flecht dien wurde kin.

Litte wy in nije VG oanmeitsje foar caching.

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

Lit ús meitsje in LV op de cache apparaat.

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

Hjir namen wy fuortendaliks alle frije romte op /dev/data/cache yn, sadat alle oare nedige partysjes fuortendaliks oanmakke waarden op /dev/root/cache. As jo ​​​​wat op it ferkearde plak makke hawwe, kinne jo it ferpleatse mei pvmove.

Litte wy de cache oanmeitsje en ynskeakelje:

#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

Wêrom sa'n chunksize..?Troch praktyske eksperiminten koe de skriuwer útfine dat it bêste resultaat berikt wurdt as de grutte fan it LVM-cacheblok oerienkomt mei de grutte fan it tinne blok LVM. Boppedat, hoe lytser de grutte, hoe better de konfiguraasje docht yn in willekeurige opname.

64k is de minimale blokgrutte tastien foar LVM thin.

Wês foarsichtich mei skriuwen ..!Ja. Dit soarte fan cache stelt skriuwsyngronisaasje út nei it cache-apparaat. Dit betsjut dat as de cache ferlern is, jo gegevens kinne ferlieze op it cache-apparaat. Letter sil de skriuwer jo fertelle hokker maatregels, neist NVMe RAID 1, kinne wurde nommen om dit risiko te kompensearjen.

Dit cache-type is mei opsetsin keazen om te kompensearjen foar de minne willekeurige skriuwprestaasjes fan RAID 6.

Litte wy kontrolearje wat wy krigen:

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

Allinnich [cachedata_corig] moat lizze op /dev/data/cache. As der wat mis is, brûk dan pvmove.

Jo kinne de cache as nedich útskeakelje mei ien kommando:

#lvconvert -y --uncache cache/cachedata

Dit wurdt online dien. LVM sil de cache gewoan syngronisearje nei skiif, fuortsmite, en omneame cachedata_corig werom nei cachedata.

It ynstellen fan LVM tinne

Litte wy rûchwei skatte hoefolle romte wy nedich binne foar LVM tinne metadata:

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

Rûn oant 4 gigabyte: 4294967296B

Fermannichfâldigje mei twa en foegje 4194304B ta foar LVM PV-metadata: 8594128896B
Litte wy in aparte partysje oanmeitsje op NVMe RAID 1 om tinne LVM-metadata en har reservekopy derop te pleatsen:

#lvcreate -L 8594128896B --name images root

Foar wat..?Hjir kin de fraach opkomme: wêrom LVM tinne metadata apart pleatse as it noch yn NVMe yn 'e cache sil wurde en fluch wurket.

Hoewol't snelheid hjir wichtich is, is it fier fan 'e wichtichste reden. It ding is dat de cache in punt fan mislearring is. Der kin wat mei barre, en as de tinne LVM-metadata yn 'e cache is, sil it feroarsaakje dat alles folslein ferlern giet. Sûnder folsleine metadata sil it hast ûnmooglik wêze om tinne dielen te sammeljen.

Troch de metadata te ferpleatsen nei in apart net-cached, mar fluch, folume, garandearje wy de feiligens fan 'e metadata yn gefal fan cacheferlies of korrupsje. Yn dit gefal sil alle skea feroarsake troch cacheferlies wurde pleatst yn tinne folumes, wat de herstelproseduere sil ferienfâldigje troch oarders fan grutte. Mei in hege kâns sille dizze skea weromset wurde mei FS-logs.

Boppedat, as earder in momintopname fan in tinne folume waard makke, en dêrnei waard de cache op syn minst ien kear folslein syngronisearre, dan, troch it ynterne ûntwerp fan LVM thin, sil de yntegriteit fan 'e momintopname garandearre wurde yn gefal fan cacheferlies .

Litte wy in nije VG oanmeitsje dy't ferantwurdlik is foar tinne-foarsjenning:

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

Litte wy in swimbad meitsje:

#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T images/thin-pool
Wêrom -Z yNeist wêr't dizze modus eins foar bedoeld is - om te foarkommen dat gegevens fan ien firtuele masine nei in oare firtuele masine lekke by it werferdielen fan romte - wurdt nulearring ek brûkt om de snelheid fan willekeurich skriuwen te ferheegjen yn blokken lytser dan 64k. Elk skriuwen minder dan 64k nei in earder net-allokearre gebiet fan it tinne folume sil 64K râne-ôfstimd wurde yn 'e cache. Dit sil tastean de operaasje te wurde útfierd folslein fia de cache, it omgean fan it cache apparaat.

Litte wy de LV's ferpleatse nei de oerienkommende PV's:

#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

Litte wy kontrolearje:

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

Litte wy in tinne folume meitsje foar testen:

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

Wy sille pakketten ynstallearje foar testen en tafersjoch:

#apt-get install sysstat fio

Dit is hoe't jo it gedrach fan ús opslachkonfiguraasje yn realtime kinne observearje:

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

Dit is hoe't wy ús konfiguraasje kinne testen:

#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

Foarsichtich! Helpmiddel!Dizze koade sil 36 ferskillende tests útfiere, elk foar 4 sekonden. De helte fan de tests is foar opname. Jo kinne in protte opnimme op NVMe yn 4 sekonden. Oant 3 gigabyte per sekonde. Dat, elke run fan skriuwtests kin oant 216 gigabyte oan SSD-boarne fan jo ite.

Lêzen en skriuwen mingd?Ja. It makket sin om de lês- en skriuwtests apart út te fieren. Boppedat hat it sin om te soargjen dat alle caches syngronisearre binne, sadat in earder makke skriuw gjin ynfloed hat op it lêzen.

De resultaten sille sterk ferskille tidens de earste lansearring en de folgjende as de cache en it tinne folume folje, en ek ôfhinklik fan oft it systeem slagge om de caches te syngronisearjen dy't fol binne tidens de lêste lansearring.

Under oare dingen advisearje ik de snelheid te mjitten op in al folslein tinne folume wêrfan in momintopname krekt makke is. De skriuwer hie de kâns om te observearjen hoe't willekeurige skriuwwizen fuortendaliks nei it meitsjen fan de earste momintopname skerp fersnelle, benammen as de cache noch net folslein fol is. Dit bart troch copy-on-write skriuwsemantyk, ôfstimming fan cache en tinne folume blokken, en it feit dat willekeurich skriuwt nei RAID 6 feroaret yn willekeurige lêzen fan RAID 6 folge troch skriuwt nei de cache. Yn ús konfiguraasje is willekeurich lêzen fan RAID 6 oant 6 kear (it oantal SATA SSD's yn 'e array) flugger as skriuwen. Omdat blokken foar CoW wurde sequentially tawiisd út in tinne pool, dan de opname, foar it grutste part, ek feroaret yn sekwinsjele.

Beide fan dizze funksjes kinne brûkt wurde foar jo foardiel.

Cache "koherinte" snapshots

Om it risiko fan gegevensferlies te ferminderjen yn gefal fan cache-skea / ferlies, stelt de auteur foar om de praktyk fan rotearjende snapshots yn te fieren om har yntegriteit yn dit gefal te garandearjen.

Earst, om't tinne folume metadata wennet op in uncached apparaat, de metadata sil wêze konsekwint en mooglike ferliezen sille wurde isolearre binnen gegevens blokken.

De folgjende snapshot-rotaasjesyklus garandearret de yntegriteit fan 'e gegevens binnen de snapshots yn gefal fan cacheferlies:

  1. Foar elk tinne folume mei de namme <namme>, meitsje in momintopname mei de namme <namme>.cached
  2. Litte wy de migraasjedrompel op in ridlike hege wearde ynstelle: #lvchange --quiet --cachesettings "migration_threshold=16384" cache/cachedata
  3. Yn 'e loop kontrolearje wy it oantal smoarge blokken yn' e cache: #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' oant wy nul krije. As de nul te lang ûntbrekt, kin it makke wurde troch de cache tydlik te wikseljen nei skriuwmodus. As jo ​​​​lykwols rekken hâlde mei de snelheidskarakteristiken fan ús SATA- en NVMe SSD-arrays, lykas har TBW-boarne, kinne jo it momint óf fluch fange sûnder de cache-modus te feroarjen, of jo hardware sil har heule boarne folslein opetje yn in pear dagen. Fanwegen boarnebeperkingen is it systeem yn prinsipe net yn steat om hieltyd ûnder 100% skriuwlast te wêzen. Us NVMe SSD's ûnder 100% skriuwlast sille de boarne folslein útputte 3-4 dagen. SATA SSD's sille mar twa kear sa lang duorje. Dêrom sille wy oannimme dat it grutste part fan 'e lading giet nei lêzen, en wy hawwe relatyf koarte-termyn bursts fan ekstreem hege aktiviteit kombinearre mei in lege lading gemiddeld foar skriuwen.
  4. Sa gau as wy fongen (of makke) in nul, wy omneame <namme>.cached nei <namme>.committed. De âlde <name>.committed is wiske.
  5. Opsjoneel, as de cache 100% fol is, kin it opnij makke wurde troch in skript, sadat it wiske wurdt. Mei in heal lege cache wurket it systeem folle flugger by it skriuwen.
  6. Stel de migraasjedrompel op nul: #lvchange --quiet --cachesettings "migration_threshold=0" cache/cachedata Dit sil tydlik foarkomme dat de cache syngronisearje mei de haadmedia.
  7. Wy wachtsje oant in protte feroaringen sammelje yn 'e cache #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' of de timer sil útgean.
  8. Wy werhelje wer.

Wêrom swierrichheden mei migraasje drompel ...?It ding is dat yn 'e echte praktyk in "willekeurige" opname eins net folslein willekeurich is. As wy wat skreaun hawwe oan in sektor fan 4 kilobytes yn grutte, is d'r in hege kâns dat yn 'e folgjende pear minuten in rekord wurdt makke foar deselde of ien fan' e oanbuorjende (+- 32K) sektoaren.

Troch de migraasjedrompel op nul te setten, stelle wy skriuwsyngronisaasje op 'e SATA SSD út en sammelje ferskate wizigingen yn ien 64K-blok yn' e cache. Dit besparret de boarne fan SATA SSD signifikant.

Wêr is de koade..?Spitigernôch achtet de skriuwer himsels net genôch kompetint yn 'e ûntwikkeling fan bash-skripts, om't hy 100% autodidakt is en "google"-oandreaune ûntwikkeling praktisearret, dêrom is hy fan betinken dat de skriklike koade dy't út syn hannen komt, net troch ien moat wurde brûkt oars.

Ik tink dat professionals op dit mêd selsstannich alle hjirboppe beskreaune logika kinne ôfbyldzje, as it nedich is, en miskien sels prachtich ûntwerpe as in systemd tsjinst, lykas de skriuwer besocht te dwaan.

Sa'n ienfâldige momintopname-rotaasjeskema sil ús net allinich tastean om konstant ien momintopname folslein te syngronisearjen op 'e SATA SSD, mar sil ús ek tastean, mei help fan it thin_delta-hulpprogramma, út te finen hokker blokken binne feroare nei har skepping, en sadwaande skea lokalisearje op de wichtichste folumes, sterk ferienfâldigje herstel.

TRIM/DISCARD yn libvirt/KVM

Omdat de gegevensopslach sil brûkt wurde foar KVM dy't libvirt draait, dan soe it in goed idee wêze om ús VM's te learen net allinich frije romte yn te nimmen, mar ek frij te meitsjen wat net mear nedich is.

Dit wurdt dien troch it emulearjen fan TRIM / DISCARD-stipe op firtuele skiven. Om dit te dwaan, moatte jo it controllertype feroarje nei virtio-scsi en de xml bewurkje.

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

Sokke DISCARDs fan gast OSes wurde korrekt ferwurke troch LVM, en blokken wurde befrijd korrekt sawol yn it cache en yn it tinne swimbad. Yn ús gefal bart dit benammen op in fertrage manier by it wiskjen fan de folgjende momintopname.

BTRFS Reservekopy

Brûk klearmakke skripts mei ekstreem foarsichtich en op eigen risiko. De skriuwer skreau dizze koade sels en allinnich foar himsels. Ik bin der wis fan dat in protte betûfte Linux-brûkers ferlykbere ark hawwe, en d'r is gjin ferlet fan in oar te kopiearjen.

Litte wy in folume oanmeitsje op it reservekopyapparaat:

#lvcreate -L 256G --name backup backup

Litte wy it formatearje yn BTRFS:

#mkfs.btrfs /dev/backup/backup

Litte wy berchpunten oanmeitsje en de root-subseksjes fan it bestânsysteem montearje:

#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

Litte wy mappen meitsje foar backups:

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

Litte wy in map meitsje foar reservekopyskripts:

#mkdir /root/btrfs-backup

Litte wy it skript kopiearje:

In protte enge bash-koade. Brûk op jo eigen risiko. Skriuw gjin lilke brieven oan de skriuwer...#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

Wat docht it sels..?Befettet in set ienfâldige kommando's foar it meitsjen fan BTRFS-snapshots en kopiearje se nei in oare FS mei BTRFS ferstjoere / ûntfange.

De earste lansearring kin relatyf lang duorje, omdat... Oan it begjin wurde alle gegevens kopiearre. Fierdere lansearringen sille heul rap wêze, om't ... Allinnich wizigingen wurde kopiearre.

In oar skript dat wy yn cron sille pleatse:

Wat mear bash koade#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

Wat docht it..?Makket en syngronisearje inkrementele snapshots fan 'e neamde BTRFS-voluminten op' e reservekopy FS. Hjirnei wisket it alle foto's makke 60 dagen lyn. Nei lansearring sille datearre snapshots fan de neamde folumes ferskine yn 'e /backup/btrfs/back/remote/ submappen.

Litte wy de koade útfieringsrjochten jaan:

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

Litte wy it kontrolearje en it yn 'e cron pleatse:

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

Litte wy in tinne pool meitsje op it reservekopyapparaat:

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

Litte wy ddrescue ynstallearje, om't ... skripts sille dit ark brûke:

#apt-get install gddrescue

Litte wy in map meitsje foar skripts:

#mkdir /root/lvm-thin-backup

Litte wy de skripts kopiearje:

In protte drokte binnen ...#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

Wat docht it...?Befettet in set fan kommando's foar it manipulearjen fan tinne snapshots en syngronisearje it ferskil tusken twa tinne snapshots ûntfongen fia thin_delta nei in oar blok apparaat mei help fan ddrescue en blkdiscard.

In oar skript dat wy sille pleatse yn cron:

In bytsje mear 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

Wat docht it...?Brûkt it foarige skript om backups te meitsjen en te syngronisearjen fan de neamde tinne folumes. It skript sil ynaktive snapshots litte fan 'e neamde folumes, dy't nedich binne om feroarings te folgjen sûnt de lêste syngronisaasje.

Dit skript moat bewurke wurde, en spesifisearje de list mei tinne dielen wêrfoar reservekopyen makke wurde moatte. De opjûne nammen binne allinich foar yllustrative doelen. As jo ​​​​wolle, kinne jo in skript skriuwe dat alle folumes sil syngronisearje.

Litte wy de rjochten jaan:

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

Litte wy it kontrolearje en it yn 'e cron pleatse:

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

De earste lansearring sil lang duorje, want... tinne folumes sille wurde folslein syngronisearre troch kopiearjen alle brûkte romte. Mei tank oan LVM tinne metadata, wy witte hokker blokken binne eins yn gebrûk, dus allinnich echt brûkt tinne folume blokken wurde kopiearre.

Opfolgjende runs sille de gegevens stadichoan kopiearje tanksij wizigings folgjen fia LVM tinne metadata.

Litte wy sjen wat der bard is:

#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

Wat hat dit te krijen mei nêstpoppen?

Meast wierskynlik, jûn dat LVM LV logyske folumes kinne LVM PV fysike folumes wêze foar oare VG's. LVM kin rekursyf wêze, lykas nêstpoppen. Dit jout LVM ekstreme fleksibiliteit.

PS

Yn it folgjende artikel sille wy besykje ferskate ferlykbere mobile opslachsystemen / KVM te brûken as basis foar it meitsjen fan in geo-ferdielde opslach / vm-kluster mei redundânsje op ferskate kontininten mei help fan thúsburoblêden, it thúsynternet en P2P-netwurken.

Boarne: www.habr.com

Add a comment