Çfarë kanë të përbashkët LVM dhe matryoshka?

Mirëmëngjes.
Deshiroj të ndaj me komunitetin përvojën time praktike në ndërtimin e një sistemi ruajtjeje të të dhënave për KVM duke përdorur md RAID + LVM.

Programi do të përfshijë:

  • Ndërtimi i md RAID 1 nga NVMe SSD.
  • Ndërtimi i md RAID 6 nga SATA SSD dhe disqe të zakonshme.
  • Veçoritë e funksionimit TRIM/DISCARD në SSD RAID 1/6.
  • Krijimi i një skeme startuese md RAID 1/6 në një grup të zakonshëm disqesh.
  • Instalimi i sistemit në NVMe RAID 1 në mungesë të mbështetjes NVMe në BIOS.
  • Përdorimi i LVM cache dhe LVM thin.
  • Përdorimi i BTRFS snapshots dhe send/receive për backup.
  • Përdorimi i LVM thin snapshots dhe thin_delta për backup në stilin BTRFS.

Nëse jeni të interesuar, ju lutem klikoni më poshtë.

Deklaratë

Autori nuk merr asnjë përgjegjësi për pasojat e përdorimit ose mospërdorimit të materialeve/shembujve/kodit/këshillave/të dhënave nga ky artikull. Duke lexuar ose ndonjë mënyrë duke përdorur këtë material, ju merrni përsipër përgjegjësinë për të gjitha pasojat e këtyre veprimeve. Pasojat e mundshme përfshijnë:

  • NVMe SSD të skuqura deri në krocim.
  • Plotësisht të shpenzuar burimet e shkrimit dhe dështimi i SSD-së.
  • Humorja e plotë e të dhënave në të gjitha ruajtësit, duke përfshirë kopjet e rezervës.
  • Pajisje kompjuterike të defektojnë.
  • Koha, nervat dhe paratë e shpenzuara.
  • Çdo pasojë tjetër që nuk është përmendur më lart.

Hardueri

Në dispozitë kishte:

Një plaka amë nga vitit 2013 me chipset Z87 së bashku me Intel Core i7 / Haswell.

  • Procesori 4 bërthama, 8 pika.
  • 32 Giga të memories DDR3.
  • 1 x 16 ose 2 x 8 PCIe 3.0.
  • 1 x 4 + 1 x 1 PCIe 2.0.
  • 6 x 6 GBps SATA 3 port.

Adaptori SAS LSI SAS9211-8I i ri në modalitetin IT / HBA. Firmware me mbështetje për RAID është qëllimisht zëvendësuar me firmware HBA për të:

  1. Mund të hidhet këto adaptator në çdo moment dhe të zëvendësohet me ndonjë tjetër që do.
  2. TRIM/Discard punonte normalisht në disqe, pasi në firmware RAID këto komanda nuk përkrahen fare, ndërsa HBA nuk ka rëndësi çfarë komandash dërgohen përmes busit.

Të dhënat e ngurta, — 8 copë HGST Travelstar 7K1000 me kapacitet 1 TB në formatin 2.5, si për laptopët. Këto disqe kanë qenë më parë në një RAID 6. Në sistemin e ri do të gjejnë përdorim për ruajtjen e kopjeve lokale të rezervës.

Shtesë e bërë:

6 copë SATA SSD modeli Samsung 860 QVO 2TB. Nga këto SSD kërkohej një kapacitet i madh, prania e cache SLC, preferohej besueshmëria dhe një çmim jo të lartë. Mbështetje për discard/zero ishte e nevojshme, e cila kontrollohej nga një linjë në dmesg:

kernel: ata1.00: Aktivizimi i discard_zeroes_data

2 njësi NVMe SSD modeli Samsung SSD 970 EVO 500GB.

Për këto SSD, rëndësishme është shpejtësia e leximit/shkruarjes rastësore dhe burimi për nevojat tuaja. Radiatori është i domosdoshëm. Absolutisht i domosdoshëm. Në të kundërt, do ti skuqni ato deri në një kërpudhë të thatë gjatë sinkronizimit të parë të RAID-it.

Adaptori StarTech PEX8M2E2 për 2 x NVMe SSD me instalim në slot PCIe 3.0 8x. Kjo, përsëri, është thjesht HBA, por për NVMe. Dallohet nga adaptoret e lirë për mungesë të kërkesës për mbështetje të bifurcacionit PCIe nga motherboard-i për shkak të një switch-i të integruar PCIe. Do të punojë madje edhe në sistemet më të vjetra që kanë PCIe, madje nëse është një slot x1 PCIe 1.0. Natyrisht, me shpejtësinë përkatëse. Nuk ka RAID aty. Nuk ka BIOS të integruar mbi bord. Pra, sistemi juaj nuk do të mësojë magjisht të ngarkohet nga NVMe, e as të krijojë RAID NVMe falë këtij pajisjeje.

Ky komponent u përcaktua ekskluzivisht nga disponueshmëria e vetëm një slot-i të lirë 8x PCIe 3.0 në sistem, dhe, me 2 slot-a të lirë, lehtësisht mund të zëvendësohet me dy PEX4M2E1 të lirë ose analoge, të cilat mund të blihen kudo me çmim nga 600 rubla.

Dorëheqja nga të gjitha RAID-et e mundshme harduerike ose të integruara në chipset/BIOS u bë me vetëdije, me qëllim që të kemi mundësinë të zëvendësojmë tërë sistemin, përveç SSD/HDD-ve vetë, duke ruajtur të gjithë të dhënat. Në mënyrën ideale, që të ruajnë madje edhe sistemin operativ të instaluar gjatë kalimit në një harduer krejtësisht të ri/dalë. E rëndësishme është që të ketë porte SATA dhe PCIe. Ky është si një CD live ose një USB ngarkues, vetëm shumë i shpejtë dhe pak më i madh.

HumoriE, e dini si ndodhin gjërat, – ndonjëherë duhet ta marrim të gjithë grumbullin me vete. Dhe nuk duam të humbasim të dhënat. Për këtë, të gjithë mediat e përmendura vendosen lehtësisht në rrakulla në hapësirat e kutisë standarde 5.25.

Po ashtu, për eksperimente me mënyra të ndryshme të cache SSD në Linux.

RAID-ët harduerikë janë të mërzitshëm. I ndizni. Ose punon, ose jo. Me mdadm gjithmonë ka mundësi.

Software

Më parë në harduer ishte instaluar Debian 8 Jessie e cila është afër EOL. U ndërtua një RAID 6 nga HDD-të e përmendura më sipër në çift me LVM. Atje ishin duke punuar makina virtuale në kvm/libvirt.

Duke autori ka përvojë të duhur në krijimin e pajisjeve portative të ngarkueshme SATA/NVMe, dhe për të mos prishur modelin e njohur apt, sistemi i synuar është zgjedhur Ubuntu 18.04 i cili tashmë është stabilizuar mjaft, por ende ka 3 vite mbështetje në perspektivë.

Në sistemin e përmendur janë të pranishëm të gjitha shoferët e nevojshëm për pajisjet tona nga kutia. Nuk do të na nevojiten softuerë dhe shoferë të jashtëm.

Përgatitja për instalim

Për të instaluar sistemin, na nevojitet Ubuntu Desktop Image. Instaluesi për sistemin e serverit është një installues shumë i theksuar, i cili shfaq një autonomi të tepërt duke futur patjetër një ndarje sistemike UEFI në njërin nga diskët duke prishur të gjithë bukurinë. Kështu, instalohet vetëm në modin UEFI. Nuk ofron opsione të tjera.

Kjo nuk na kënaq.

Pse?Fatkeqësisht, ngarkimi UEFI nuk është shumë i përshtatshëm me RAID-in programor të ngarkueshëm, sepse askush nuk ofron rezervim për ndarjen UEFI ESP. Në internet ka receta që sugjerojnë vendosjen e ndarjes ESP në një pajisje USB, por kjo është një pikë dështimi. Ka receta që përdorin software mdadm RAID 1 me të dhëna versioni 0.9 që nuk shpërqendrojnë BIOS-in UEFI për të parë këtë ndarje, por kjo do të ekzistojë deri në momentin e lumtur kur BIOS-i ose një OS tjetër në harduer shënon diçka në ESP duke harruar të sinkronizojë me pasqyrat e tjera.

Përveç kësaj, ngarkimi UEFI varet nga NVRAM, e cila nuk do të kalojë me diskët në sistemin e ri, pasi është pjesë e pllakës ndërlidhëse.

Prandaj, ne nuk do të shpikim një biçikletë të re. Ne tashmë kemi një biçikletë të gatshme, të provuar me vite tani e quajtur ngarkim Legacy/BIOS, që ka emrin krenar CSM në sistemet e përputhshme me UEFI. Ne thjesht do ta nxjerrim atë nga rafti, do ta lyejmë, do t’i fryjmë gomat dhe do ta fshijmë me një leckë të lagur.

Versioni Desktop i Ubuntu gjithashtu nuk di të instalohet siç duhet me ngarkuesin Legacy, por këtu, siç thuhet, të paktën ka disa mundësi.

Pra, mbledhim pajisjet dhe ngarkojmë sistemin nga pajisja USB ngarkuese Ubuntu Live. Na nevojitet të shkarkojmë paketat, kështu që përshtatim rrjetin, çfarë do të punojë. Nëse nuk funksionon, — paketat e nevojshme mund t’i ngarkojmë në pajisjen USB paraprakisht.

Hyjmë në mjedisin Desktop, hapim emulatorin e terminalit, dhe, le të fillojmë:

#sudo bash

Si…?Rreshti më sipër është një tërheqës kanonik për polemika rreth sudo. Me boMë shumë mundësi vjen edhe më shumë përgjegjësi. Pyetja është, a do të jeni në gjendje ta merrni atë mbi supet tuaja. Shumë mendojnë se përdorimi i sudo në këtë mënyrë është së paku një mënyrë e papërgjegjshme. Sidoqoftë:oPse jo ZFS…?

Luaj videon

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

Kur instalojmë softuerin në kompjuterin tonë, në thelb, ne i huazojmë zhvilluesve të tij energjinë e pajisjeve tona.Kur i besojmë këtij softueri ruajtjen e të dhënave tona, ne marrim një kredi të barabartë me vlerën e rikuperimit të këtyre të dhënave, për të cilën herët a vonë do të duhet të paguajmë.
Nga ky këndvështrim, ZFS është si një Ferrari, ndërsa mdadm+lvm më shumë ngjan me një biçikletë.

Subjektivisht, autori preferon të huazojë një biçikletë të marrë me kredi nga persona të panjohur në vend të Ferrari-t. Ashtu edhe çmimi i çështjes nuk është i lartë. Nuk ka nevojë për leje. Rregullat janë më të thjeshta. Parking është falas. Kalueshmëria është më e mirë. Një biçikletë gjithmonë mund t’i vihet një gjymtyrë, disa riparime mund të bëhen me duar.

Pse BTRFS…?

Për të ngarkuar sistemin operativ, do të na duhet një sistem skedari i mbështetur nga Legacy/BIOS GRUB nga kutia, dhe, përveç kësaj, të mbështesë pamjet në kohë reale. Ne do ta përdorim atë për pjesën /boot. Përveç kësaj, autori preferon ta përdorë këtë FS për / (rrënja) duke mos harruar të theksojë se për çdo softuer tjetër mund të krijohen pjesë të veçanta në LVM dhe të montohen në katalogët e nevojshëm.As imazhet

, as bazat e të dhënave nuk do të ruhen në këtë FS. makinat virtualeKy FS do të përdoret vetëm për të krijuar pamje të menjëhershme të sistemit pa e çaktivizuar atë që më pas do të dërgohen në diskun rezervë përmes send/recieve.
Përveç kësaj, autori preferon të mbajë në minimum softuerin direkt në pajisje dhe të ngarkojë gjithë softin tjetër në makina virtuale duke përdorur gjëra si kalimi i GPU-së dhe kontrollorëve PCI-USB në KVM përmes IOMMU.

Në pajisjet mbeten vetëm - ruajtja e të dhënave, virtualizimi dhe kopjimi rezervë.

Nëse preferoni më shumë ZFS, atëherë, në parim, për përdorimin e specifikuar ato janë të ndërsjella.

Megjithatë, autori me vetëdije injoron funksionet e ndërtuara të pasqyrimit / RAID dhe redundancës që kanë ZFS, BRTFS dhe LVM.

Megjithatë, autori e injoron qëllimisht funksionalitetet e ndërtuara të pasqyrimit / RAID dhe tepërtisë që ekzistojnë në ZFS, BRTFS dhe LVM.

Si në një argument shtesë, BTRFS ka pronën për të kthyer shkrimin e rastësishëm në një të renditur, gjë që ndikon shumë pozitivisht në shpejtësinë e sinkronizimit të skenave / kopjeve rezervë në HDD.

Do të skanojmë përsëri të gjitha pajisjet:

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

Të shohim:

#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

Shkallëzimi i "disqeve"

NVMe SSD

Ashtu se si nuk do t'i shkallëzojmë ato. Sidoqoftë, BIOS ynë nuk i sheh këto njësi. Kështu që, ato do të shkojnë tërësisht në RAID-in programor. As nuk do të krijojmë ndarje atje. Nëse dëshironi sipas "kanonit" ose "parimor" - krijoni një ndarje të madhe, siç është në HDD.

SATA HDD

Këtu nuk ka nevojë të shpikim asgjë. Ne do të krijojmë një ndarje për të gjithë. Dardin do të krijojmë sepse këto disqe i sheh BIOS dhe madje mund të përpiqet të boot nga ata. Ne madje do të instalojmë më vonë GRUB në këto disqe që sistemi ta realizojë këtë papritur.

#cat >hdd.part << EOF
etiketa: dos
etiketa-id: 0x00000000
dispositivi: /dev/sdg
njësia: sektori

/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

Këtu kemi më shumë interesante.

Së pari, njësi tona kanë madhësinë 2 TB. Kjo është brenda kufijve të pranueshëm për MBR, të cilin do ta shfrytëzojmë. Nëse është e nevojshme, mund të zëvendësohet me GPT. Disqet GPT kanë një shtresë shkallëzimi që lejon sistemet e pajtueshme me MBR të shohin katër ndarje të para nëse ato janë të vendosura brenda dy terabajtve të parë. E rëndësishme është që ndarja e boot-it dhe ndarja bios_grub në këto disqe të jenë në fillim. Kjo lejon madje të bëhet boot Legacy/BIOS nga disqet GPT.

Por, ky nuk është rasti ynë.

Këtu do të krijojmë dy ndarje. E para do të ketë madhësinë 1 GB dhe do të përdoret për RAID 1 /boot.

E dyta do të përdoret për RAID 6 dhe do të marrë të gjithë hapësirën e mbetur të lirë përveç një zone të vogël të papërcaktuar në fund të njësi.

Çfarë është kjo zonë e papërcaktuar?Sipas burimeve në internet, SATA SSD-tonë kanë në bord një SLC cache që shtrihen dinamikisht me një madhësi nga 6 deri në 78 gigabajt. 6 gigabajt i marrim "falas" për shkak të diferencës midis "gigabajtëve" dhe "gibibajtëve" në dokumentin teknik të pajisjes. 72 gigabajtët e tjerë shfaqen për shkak të hapësirës së pa përdorur.

Këtu është e nevojshme të theksohet se cache është SLC, ndërsa hapësira merret në modin 4 bit MLC. Çka për ne do të thotë se për çdo 4 gigabajt hapësirë të lirë do të marrim vetëm 1 gigabajt SLC cache.

Shumëzojmë 72 gigabajt me 4 dhe marrim 288 gigabajt. Kjo është hapësira e lirë që nuk do ta përcaktojmë, për të lejuar disqet të shfrytëzojnë plotësisht SLC cache.

Kështu, do të merrnim deri në 312 gigabajt SLC cache në total nga gjashtë shkallë. Nga të gjitha shkallëve, 2 do të përdoren në RAID për redundancë.

Kjo sasi cache do të na lejojë të hasim shumë rrallë në praktikën reale situatën kur shkrimi ndodh jashtë cache. Kjo e kompenson jashtëzakonisht mirë humbjen më të madhe të memories QLC, – shpejtësinë e ulët të shkrimit kur të dhënat shkruhen anash cache. Nëse ngarkesat tuaja nuk përputhen me këtë, atëherë ju rekomandoj të mendoni fort për sa do të jetojnë SSD-të tuaj nën një ngarkesë të tillë duke marrë parasysh TBW nga fleta teknike.

#cat >ssd.part << EOF
etiketa: dos
etiketa-id: 0x00000000
dispozitiv: \/dev\/sda
njësia: sektori

/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

Krijimi i grupeve

Së pari, na nevojitet të riemërojmë makinën. Kjo është e nevojshme sepse emri i hostit është pjesë e emrit të grupit diku brenda mdadm dhe ndikon diku në diçka. Grupet sigurisht që mund të riemërohen më vonë, por kjo është një veprim i panevojshëm.

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

NVMe SSD

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

Pse —assume-clean…?Për të mos inicializuar grupet. Për të dy nivelet RAID 1 dhe 6, kjo është e pranueshme. Të gjitha mund të funksionojnë edhe pa inicializim, nëse është një grup i ri. Për më tepër, inicializimi i grupit SSD gjatë krijimit – është një humbje e tepërt e burimeve TBW. Ne përdorim TRIM/DISCARD ku është e mundur në grupet e mbledhura SSD për t'i "iniçializuar".

Në grupet SSD RAID 1, DISCARD mbështetet jashtë kutisë.

Në grupet SSD RAID 6, DISCARD duhet të aktivizohet në parametrat e modulit të bërthamës.

Kjo duhet të bëhet vetëm kur të gjithë SSD-të e përdorur në grupet e niveleve 4/5/6 në këtë sistem kanë mbështetje funksionuese për discard_zeroes_data. Ndonjëherë hasen disqe të çuditshme, të cilat raportojnë bërthamës për mbështetje të kësaj funksioni, por në fakt, kjo nuk ekziston, ose funksioni nuk punon gjithmonë. Aktualisht, mbështetje ka pothuajse kudo, megjithatë, disqet e vjetra dhe firmware me defekte ndodhin. Për këtë arsye, mbështetje DISCARD është çaktivizuar për të parën për RAID 6.

Kujdes, komandat e mëposhtme do të shkatërrojnë të dhënat në disqet NVMe "duke inicializuar" grupin "me zeros".

#blkdiscard /dev/md0

Nëse diçka shkoi keq, provoni të specifikoni një hap.

#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

Pse kaq e madhe…?Rritja e chunk-size ka një ndikim pozitiv në shpejtësinë e leximit të rastit me blloqe deri në chunk-size përfshirë. Kjo ndodh sepse një operacion i përputhshëm ose më i vogël mund të përmbyllet plotësisht në një pajisje. Prandaj, IOPS nga të gjitha pajisjet kumulon. Statistikat tregojnë se 99% e IO nuk e kalon 512K.

Në RAID 6, IOPS për shkrim të ashpër në është më i vogël ose i barabartë me IOPS e një disku të vetëm. Ndërsa për leximin rastësor, IOPS mund të jetë disa herë më i lartë se ai i një disku të vetëm, dhe këtu madhësia e bllokut ka rëndësi kryesore.
Autori nuk sheh kuptim në përpjekjet për të optimizuar një parametr që është i dobët në RAID 6 me dizajn dhe përkundrazi optimizon atë në të cilën RAID 6 tregon performancë të mirë.
Shkrimi rastësor i dobët në RAID 6 do të kompensohet me një cache në NVMe dhe truka me thin-provisioning.

Ende nuk e kemi aktivizuar DISCARD për RAID 6. Pra, nuk do ta "inicializojmë" këtë grup deri më vonë, pas instalimit të OS-së.

SATA HDD

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

LVM në NVMe RAID

Për shpejtësi, ne duam të vendosim sistemin e dosjeve fillestare në NVMe RAID 1 që është /dev/md0.
Megjithatë, ky grup i shpejtë na duhet edhe për nevoja të tjera si swap, metadatat dhe cache-in e LVM-cache dhe metadatat e LVM-thin, kështu që ne do të krijojmë LVM VG në këtë grup.

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

Do të krijojmë një ndarje për sistemin e dosjeve fillestare.

#lvcreate -L 128G --name root root

Do të krijojmë një ndarje për swap me madhësi të memorjes RAM.

#lvcreate -L 32G --name swap root

Instalimi i OS

Pra, tani kemi gjithçka të nevojshme për të instaluar sistemin.

Nisim masterin e instalimit të sistemit nga ambienti Ubuntu Live. Instalimi normal. Vetëm në fazën e zgjedhjes së disqeve për instalim, duhet të tregojmë sa vijon:

  • /dev/md1, — точка монтирования /boot, ФС — BTRFS
  • /dev/root/root (a.k.a /dev/mapper/root-root), — точка монтирования / (корень), ФС — BTRFS
  • /dev/root/swap (a.k.a /dev/mapper/root-swap), — использовать как раздел подкачки
  • Instaloni ngarkuesin në /dev/sda

Kur zgjidhni BTRFS si sistemin e dosjeve fillestare, instaluesi do të krijojë automatikisht dy volum BTRFS me emrat "@" për / (rrënjën), dhe "@home" për /home.

Nisim instalimin...

Instalimi do të përfundojë me një dritare modal që komunikon për një gabim në instalimin e ngarkuesit. Fatkeqësisht, nuk do të mund të dalim nga ky dialog në mënyrë të zakonshme dhe të vazhdojmë instalimin. Bëjmë logaut nga sistemi dhe hynë përsëri, duke kaluar në një desktop të pastër Ubuntu Live. Hapim terminalin, dhe përsëri:

#sudo bash

Krijojmë një ambient chroot për të vazhduar instalimin:

#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

Do të konfigurojmë rrjetin dhe hostname në chroot:

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

Hynë në ambientin chroot:

#chroot /mnt/chroot

Së pari, do të sjellim paketat:

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

Do të kontrollojmë dhe rregullojmë të gjitha paketat që janë instaluar gabim nga instalimi i papër tamam i sistemit:

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

Nëse diçka nuk shkon siç duhet, ndoshta do t'ju duhet të redaktoni më parë /etc/apt/sources.list

Do të rregullojmë parametrat për modulin RAID 6 për të aktivizuar TRIM/DISCARD:

#cat >/etc/modprobe.d/raid456.conf << EOF
mundësi raid456 pajisje_përpunimi_shkarkimi_sigurt=1
EOF

Pak do të rregullojmë grupet tona:

#cat >/etc/udev/rules.d/60-md.rules << EOF
NENDRICK=="blok", KERNEL=="md*", AKSIONE=="ndryshim", TEST=="md/stripe_cache_size", ATTR{md/stripe_cache_size}="32768"
NENDRICK=="blok", KERNEL=="md*", AKSIONE=="ndryshim", TEST=="md/sync_speed_min", ATTR{md/sync_speed_min}="48000"
NENDRICK=="blok", KERNEL=="md*", AKSIONE=="ndryshim", TEST=="md/sync_speed_max", ATTR{md/sync_speed_max}="300000"
EOF
#cat >/etc/udev/rules.d/62-hdparm.rules << EOF
NENDRICK=="blok", AKSIONE=="shto|ndryshim", 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
NENDRICK=="blok", AKSIONE=="shto|ndryshim", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", RUN+="/sbin/blockdev --setra 1024 /dev/%k"
NENDRICK=="blok", AKSIONE=="shto|ndryshim", KERNEL=="md*", RUN+="/sbin/blockdev --setra 0 /dev/%k"
EOF

Çfarë ishte kjo..?Kemi krijuar një set rregullash udev që do të bëjnë sa vijon:

  • Të vendosni një madhësi të arsyeshme për cache-in e blloqeve për RAID 6 për vitin 2020. Vlera e parazgjedhur, duket se nuk është ndryshuar që nga krijimi i Linux-it dhe është e pamjaftueshme prej kohësh.
  • Të rezervoni minimumin IO gjatë kontrolleve/sinkronizimeve të grupeve. Kjo është e nevojshme që grupet tuaja të mos ngecin në një gjendje të përhershme sinkronizimi nën ngarkesë.
  • Të kufizoni maksimumin IO gjatë kontrolleve/sinkronizimeve të grupeve. Kjo është e nevojshme që sinkronizimi/kontrolli i RAID-ve SSD të mos i nxehë pajisjet deri në një gjendje të krisur. Kjo është veçanërisht e rëndësishme për NVMe. (A e mbani mend radiatorin? Nuk po shaka.)
  • Të ndaloni diskët që të ndalin rrotullimin e spirales (HDD) përmes APM dhe të vendosni një kohëzgjatje për gjumin e kontrolluesve të diskëve në 7 orë. Mund të çaktivizoni krejtësisht APM-në nëse diskët tuaj e mbështesin atë (-B 255). Me vlerën e parazgjedhur, diskët do të ndalojnë pas pesë sekondash. Pastaj OS do të dëshirojë të zbresë cache-në e diskut, diskët do të rrotullohen përsëri, dhe gjithçka do të përsëritet. Diskët kanë një numër maksimal të rrotullimeve të spirales. Ky cikël i thjeshtë me vlerë të parazgjedhur mund t'i vrasë diskët tuaj për disa vjet. Kjo nuk ndikon në të gjithë diskët, por ata
  • Të vendosni readahead në diskët (me rrotullim) në 1 megabayt — dy blloqe të njëpasnjëshme/chunks RAID 6
  • Të ndaloni readahead në vetë grupe.

Të redaktojmë /etc/fstab:

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

Pse kështu..?Ne do të kërkojmë pjesën /boot sipas UUID, sepse emërtimi i grupeve teorikisht mund të ndryshojë.

Pjesët e tjera do t’i kërkojmë sipas emrave LVM në notacionin /dev/mapper/vg-lv, sepse ato identifikojnë mjaft unikisht pjesët.

Nuk përdorim UUID për LVM sepse UUID e volumeve LVM dhe snapshot-eve të tyre mund të përputhen.A po e montojmë dy herë /dev/mapper/root-root..?Po. Pikërisht kështu. Karakteristika e BTRFS. Kjo FS mund të montohet disa herë me subvol të ndryshme.

Në përfundim të kësaj veçorie, rekomandoj të mos krijoni kurrë snapshot-e LVM për volumet aktive BTRFS. Mund të merrni një surprizë gjatë rinisjes.

Të rigjenerojmë konfigurimin mdadm:

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

Të saktësojmë parametrat e LVM:

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

aktivizimi {
threshold_autoextend_tank=90
percent_autoextend_tank=5
}
alokimi {
cache_pool_max_chunks=2097152
}
devices {
filter_global=["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

Çfarë ishte kjo..?Kemi aktivizuar zgjerimin automatik të grupeve LVM thin kur arrin 90% të hapësirës së zënë me 5% të vëllimit.

Kemi rritur numrin maksimal të blloqeve të cache për LVM cache.

Kemi ndaluar LVM-së të kërkojë LVM volumet (PV) në:

  • disqe që përmbajnë LVM cache (cdata)
  • disqe që janë mbështjellur me LVM cache duke përjashtuar cache (<lv_name>_corig). Megjithatë, disku i mbështjellur do të skanohet përmes cache (thjesht <lv_name>).
  • disqe që përmbajnë metadatat e LVM cache (cmeta)
  • të gjitha disqet në VG me emrin images. Këtu do kemi imazhe të disqeve të makinave virtuale, dhe nuk duam që LVM në host të aktivizojë volumet e pronarit të sistemit.
  • të gjitha disqet në VG me emrin backup. Këtu do kemi kopje rezervë të imazheve të makinave virtuale.
  • të gjitha disqet të cilat përfundojnë me "gpv" (guest physical volume)

Kemi aktivizuar mbështetje për DISCARD kur lirohet hapësira e lirë në LVM VG. Kujdes! Kjo do ta bëjë fshirjen e LV në SSD mjaft të gjatë. Sidomos kjo i referohet SSD RAID 6. Sidoqoftë, sipas planit, do të përdorim thin provisioning, kështu që, kjo nuk do të na shqetësojë fare.

Do të përditësojmë imazhin initramfs:

#update-initramfs -u -k all

Do të instalojmë dhe konfigurojmë grub:

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

Cilat disqe të zgjedhim?Të gjitha ato që janë sd*. Sistemi duhet të jetë në gjendje të ngarkohet nga çdo disk SATA ose SSD që funksionon.

Pse e ndalëm os-prober..?Për vetëpavarësinë e tepruar dhe duar të lodhura.

Ai nuk punon siç duhet nëse një nga RAID-t është në një gjendje të degraduar. Ai përpiqet të kërkojë OS-në në pjesët që përdoren në makinat virtuale që punojnë në këtë hardware.

Nëse ju duhet, mund ta lini, por, kini parasysh të gjitha të mësipërmet. Rekomandoj të kërkoni receta për të hequr duar të lodhura në internet.

Me këtë ne përfunduam instalimin fillestar. Është koha të ri-boot në OS-në e sapo instaluar. Mos harroni të nxirrni CD-në/USB-në Live që e keni përdorur për ngarkim.

#exit
#reboot

Si pajisje për ngarkim zgjidhni çdo SATA SSD.

LVM në SATA SSD

Në këtë moment ne tashmë kemi ngarkuar në OS-në e re, kemi konfiguruar rrjetin, apt, hapur emulatorin e terminalit, dhe kemi nisur:

#sudo bash

Të vazhdojmë.

“Inicizojmë” masivin nga SATA SSD:

#blkdiscard /dev/md2

Nëse nuk funksionon, provoni:

#blkdiscard --step 65536 /dev/md2
Krijojmë LVM VG në SATA SSD:

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

Pse ende një VG..?Vërtet, ne tashmë kemi një VG me emrin root. Pse të mos i shtojmë të gjitha në një VG?

Nëse në VG ka disa PV, për aktivizimin e saktë të VG-së, të gjitha PV-të duhet të jenë të pranishme (online). Përjashtimi është LVM RAID, të cilin ne qëllimisht nuk e përdorim.

Ne dëshirojmë shumë që kur ndodh ndonjë rënie (lexo humbje të të dhënave) në ndonjë nga RAID 6 gratë e diskave, sistemi ynë operativ të ngarkohet normalisht dhe të na japë mundësinë për të zgjidhur problemin.

Për këtë, në nivelin e parë të abstraktimit do të izolojmë çdo lloj «mbajtësi» fizik në një VG të veçantë.

Nëse flasim shkencërisht, grumbujt e ndryshëm RAID i përkasin «domenëve të ndryshëm të besueshmërisë». Nuk ka sens të krijojmë një pikë të përbashkët dështimi për ta, duke i futur në një VG.

Prania e LVM në nivelin «harduer» do të na lejojë të prishim në mënyrë arbitrare copat e grumbujve të ndryshëm RAID, duke i kombinuar ata në mënyra të ndryshme. Për shembull, – të запуска në të njëjtën kohë bcache + LVM thin, bcache + BTRFS, LVM cache + LVM thin, një konfigurim të komplikuar ZFS me кеши ose çdo tjetër përzierje infernale, për të 'prekur' dhe krahasuar të gjitha këto.

Në nivelin «harduer», ne nuk do të përdorim asgjë përveç LVM volumesh të njohura dhe të mira. Përjashtimi nga ky rregull, ndoshta, do të jetë ndarja për kopje rezervë.

Mendoj se deri në këtë pikë, shumë lexues tashmë kanë filluar të dyshojnë për lidhjen me matryoshkën.

LVM në SATA HDD

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

Përsëri një VG e re..?Ne dëshirojmë shumë që kur ndodh dështimi i grumbullit të disqeve, të cilin do ta përdorim për ruajtjen e të dhënave rezervë, sistemi ynë operativ të vazhdojë të funksionojë si zakonisht, duke ruajtur gjithashtu qasjen në të dhënat që nuk janë rezervë. Prandaj, për të shmangur problemet me aktivizimin e VG-së, krijojmë një VG të veçantë.

Konfigurimi i LVM cache

Do të krijojmë LV në NVMe RAID 1 për ta përdorur si një pajisje cache.

#lvcreate -L 70871154688B --name cache root

Pse ka kaq pak…?Kjo është për shkak se NVMe SSD-të tona gjithashtu kanë SLC cache. 4 gigabajt «falas» dhe 18 gigabajt dinamike për shkak të hapësirës së lirë që zë në 3-bit MLC. Pas shterimit të këtij cache, NVMe SSD-të nuk do të jenë shumë më të shpejtë se SATA SSD-të tona me cache. Në thelb, për këtë arsye nuk ka kuptim të bëjmë një ndarje LVM cache shumë më të madhe se dyfishi i kapacitetit të SLC cache të mbajtësit NVMe. Për mbajtësit NVMe që përdoren, autori e konsideron të arsyeshme të krijohet një cache prej 32-64 gigabajt.

Kjo madhësi ndarjeje është e nevojshme për organizimin e 64 gigabajt cache, vendosjen e metadatenave të cache dhe kopjen rezervë të metadatenave.

Dua të theksoj se, pas një fikjeje të papritur të sistemit, LVM do ta markojë të gjithë cache-in si të papastër dhe do të sinkronizojë përsëri. Më shumë se kaq, kjo do të përsëritet sa herë që përdoret lvchange në këtë pajisje deri në një rindezje të re të sistemit. Prandaj, rekomandoj të rikonstruoni menjëherë cache-in me skenarin përkatës.

Do të krijojmë një LV në SATA RAID 6 për ta përdorur si një pajisje të cache-uar.

#lvcreate -L 3298543271936B --name cache data

Pse vetëm tri terabajtë..?Që, në rast nevoje, mund të përdoret SATA SSD RAID 6 për nevoja të tjera. Madhësia e hapësirës së cache-uar mund të rritet dinamikisht, gjatë funksionimit, pa ndaluar punën e sistemit. Për këtë, është e nevojshme të ndaloni dhe ta ndizni përsëri cache-in, por avantazhi dallues i LVM-cache në krahasim me, për shembull, bcache, është se kjo mund të bëhet gjatë funksionimit.

Do të krijojmë një VG të re për cache.

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

Do të krijojmë një LV në pajisjen e cache-uar.

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

Këtu menjëherë e zëmë të gjithë hapësirën e lirë në /dev/data/cache që të gjitha pjesët e nevojshme të krijohen menjëherë në /dev/root/cache. Nëse diçka është krijuar ndryshe, mund ta zhvendosni me pvmove.

Do të krijojmë dhe aktivizojmë cache:

#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

Pse një chunksize të tillë..?Me anë të eksperimenteve praktike, autori arriti të zbulojë se rezultati më i mirë arrihet kur madhësia e bllokut të LVM cache përputhet me madhësinë e bllokut të LVM thin. Në të njëjtën kohë, sa më e vogël të jetë madhësia, aq më mirë përshtatet konfigurimi për shkrimin e rastësishëm.

64k është madhësia minimale e bllokut e pranueshme për LVM thin.

Kujdes writeback..!Po. Ky lloj cache-i ka demtime të sinkronizimit të shkrimit në pajisjen e cache-uar. Kjo çon në atë që, në rast humbjeje të cache-it, mund të humbni të dhëna në pajisjen e cache-uar. Më vonë, autori do të shpjegojë çfarë masash, përveç NVMe RAID 1, mund të merren për të kompensuar këtë rrezik.

Ky lloj cache-i është zgjedhur me qëllim për të kompensuar performancën e ulët të RAID 6 për shkrimin e rastësishëm.

Do të kontrollojmë se çfarë kemi arritur:

#lvs -a -o lv_name,lv_size,devices --units B cache
LV LSize Pajisje
[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)

Në /dev/data/cache duhet të gjendet vetëm [cachedata_corig]. Nëse diçka nuk është në rregull, përdorni pvmove.

Për ta çaktivizuar cache-in në rast nevoje mund të përdorni një komandë:

#lvconvert -y --uncache cache/cachedata

Kjo bëhet on-line. LVM thjesht sincronizon cache-in në disk, e fshin atë dhe e rinomina cachedata_corig përsëri në cachedata.

Konfigurimi i LVM thin

Të bëjmë një vlerësim të përafërt se sa hapësirë na nevojitet për metadatën LVM thin:

#thin_metadata_size --block-size=64k --pool-size=6terabytes --max-thins=100000 -u bytes
thin_metadata_size - 3385794560 bytes sipas vlerësimit për sipërfaqen e metadatas për "--block-size=64kibibytes --pool-size=6terabytes --max-thins=100000"

Të rrumbullakosim në 4 gigabajt: 4294967296B

Mundësojmë me dy dhe shtojmë 4194304B për metadata LVM PV: 8594128896B
Të krijojmë një seksion të veçantë në NVMe RAID 1 për të vendosur aty metadatën LVM thin dhe kopjen e saj rezervë:

#lvcreate -L 8594128896B --name images root

Pse..?Këtu mund të lindë pyetja, pse të vendosim metadatën LVM thin veçmas, kur ato do të ruajnë ende ne NVMe dhe do të punojnë shpejt.

Shpejtësia këtu është e rëndësishme, por nuk është arsyeja kryesore. E gjitha është se cache është një pikë dështimi. Mund të ndodhi diçka me të, dhe, nëse metadatët LVM thin janë të ruajtura në cache, kjo do të çojë në një humbje të plotë të të gjithave. Pa metadatë të plota, mbledhja e volumeve thin do të jetë praktikisht e pamundur.

Duke zhvendosur metadatën në një volum të veçantë që nuk është i ruajtur në cache, por është i shpejtë, ne garantojmë ruajtjen e metadatave në rast humbjeje apo dëmtimi të caches. Në këtë rast, të gjitha dëmtimet e shkaktuara nga humbja e caches do të jenë lokalizuar brenda volumeve thin, duke e bërë procedurën e rikuperimit shumë më të thjeshtë. Shumë me gjasë, këto dëmtime do të mund të rikuperohen me ndihmën e regjistrave të FS.

Më shumë se kaq, nëse më parë është bërë një foto e menjëhershme e volumit thin, dhe pas kësaj, caches është sinkronizuar të paktën një herë plotësisht, atëherë, për shkak të karakteristikave të brendshme të LVM thin, integriteti i fotos do të garantohet në rast humbjeje të caches.

Të krijojmë një VG të re që do të kujdeset për thin-provisioning:

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

Të krijojmë një pool:

#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T images/thin-pool
Pse -Z yPërveç asaj për çfarë ky mod është e destinuar, — që të mos lejojë që të dhënat nga një makinë virtuale të rrjedhin në një tjetër makinë virtuale gjatë ri-shpërndarjes së hapësirës, — zeroing gjithashtu përdoret për të rritur shpejtësinë e shkrimit të rastësishëm me blloqe më pak se 64k. Çdo shkrim më pak se 64k në një zonë që nuk është ndarë më parë në volumthin do të kthehet në 64K të përputhura me kufirin e caches. Kjo do të lejojë që operacioni të kryhet plotësisht përmes caches pa kaluar nëpër pajisjen e ruajtur në cache.

Të zhvendosim LV në PV-të përkatëse:

#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

Të kontrollojmë:

#lvs -a -o lv_name,lv_size,devices --units B images
LV LSize Pajisje
[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)

Të krijojmë një volum thin për teste:

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

Të instalojmë paketa për teste dhe vëzhgim:

#apt-get install sysstat fio

Ja se si mund të monitoroni sjelljen e konfigurimit tonë të ruajtjes në kohë reale:

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

Ja se si mund të testoni konfigurimin tonë:

#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

Kujdes! Burimi!Ky këtij kodi do të startojnë 36 teste të ndryshme, secili do të kryhet për 4 sekonda. Gjatë kësaj, gjysma e testeve janë për shkarkim. Në 4 sekonda mbi NVMe mund të shkruhet shumë. Deri në 3 gigabajt në sekondë. Pra, çdo herë testi për shkarkim mund t’ju konsumojë deri në 216 gigabajt burim SSD.

Leximi dhe shkarkimi përzier?Po. Ka kuptim që testet për lexim dhe shkarkim të kryhen veçmas. Për më tepër, është e rëndësishme të siguroheni që të gjitha caches janë sync, në mënyrë që shkarkimi i mëparshëm të mos ndikojë në lexim.

Rezultatet do të ndryshojnë ndjeshëm gjatë startit të parë dhe pasuesve, për sa kohë që cache është mbushur dhe volume i hollë, si dhe në varësi të faktit nëse sistemi ka arritur të sinkronizojë caches të mbushur gjatë startit të kaluar.

Përveç kësaj, unë rekomandoj matjen e shpejtësisë në një volum të hollë të mbushur tashmë, nga i cili sapo është bërë një snapshot. Autori ka pasur mundësinë të vëzhgojë si shkarkimi i rastësishëm përshpejtohet menjëherë pas krijimit të snapshot-it të parë, veçanërisht kur cache ende nuk është plotësisht e mbushur. Kjo ndodh falë semantikës së copy-on-write, rregullimit të blloqeve të caches dhe volumit të hollë dhe se shkarkimi i rastësishëm në RAID 6 shndërrohet në lexim të rastësishëm me RAID 6 dhe pastaj shkarkim në cache. Në konfigurimin tonë, leximi i rastësishëm me RAID 6 është deri në 6 herë (numri i SATA SSD-ve në grup) më i shpejtë se shkarkimi. Duke qenë se blloqet për CoW alokohen rresht pas rreshti nga pool-i i hollë, atëherë shkarkimi, në të shumtën e rastit, shndërrohet në sekondar.

Të dy këto veçori mund të shfrytëzohen me përfitim.

Snapshotet e kesh-«koherente»

Për të reduktuar rrezikun e humbjes së të dhënave në rast dështimi/ humbjeje të keshit, autori propozon praktikën e rotacionit të snapshot-eve që garanton integritetin e tyre në këtë rast.

Së pari, falë faktit se metadat e volumit të hollë janë të vendosura në një pajisje të pa-cache, metadata do të jetë e plotë dhe humbjet e mundshme do të jenë të izoluara brenda blloqeve të të dhënave.

Cikli i ardhshëm i rotacionit të snapshot-eve garanton integritetin e të dhënave brenda snapshot-eve në rast të humbjes së caches:

  1. Për çdo volum të hollë me emrin <emri>, krijojmë një snapshot me emrin <emri>.cached
  2. Të vendosim threshold-in e migrimit në një vlerë shumë të lartë të arsyeshme: #lvchange --quiet --cachesettings "migration_threshold=16384" cache/cachedata
  3. Në cikël kontrollojmë numrin e blloqeve të ndotura në kesh: #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' deri në zero. Nëse zeroja mungon për një kohë të gjatë, mund ta krijoni përkohësisht duke kaluar cache në modin writethrough. Sidoqoftë, duke marrë parasysh karakteristikat e shpejtësisë së sistemeve tona SATA dhe NVMe SSD, si dhe burimin e tyre TBW, ose do të jeni në gjendje ta kapni momentin mjaft shpejt pa ndryshuar modin e cache-it, ose hardueri juaj do ta konsumonte të gjithë burimin e tij në disa ditë. Për shkak të kufizimeve të burimit, sistemi në parim nuk është në gjendje të mbetet nën një ngarkesë 100% për shkrim përherë. SSD-të tona NVMe nën ngarkesë 100% për shkrim do të shpenzojnë plotësisht burimin brenda 3-4 ditë. SSD-të SATA do të jetojnë rreth dy herë më shumë. Prandaj, ne do ta konsiderojmë se pjesa më e madhe e ngarkesës shkon në lexim, dhe për shkrim kemi – përjetime relativisht të shkurtra me aktivitet shumë të lartë në kombim me ngarkesë të ulët në mes.
  4. Sapo e kapëm (apo e krijuam) zero-n – e riemërojmë <emri>.cached në <emri>.committed. Të vjetrin <emri>.committed e heqim.
  5. Opcionalisht, nëse cache-i është plotësisht i mbushur, mund ta rikrijoni me një skript, duke pastruar kështu. Me një cache gjysmë të zbrazët sistemi punon shumë më shpejt në shkrim.
  6. Do ta vendosim pragun e migrimit në zero: #lvchange --quiet --cachesettings "migration_threshold=0" cache/cachedata Kjo përkohësisht do ndalojë sinkronizimin e cache-it me mediumin kryesor.
  7. Presim derisa në cache të grumbullohen mjaft ndryshime #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' ose të aktivizohet timeri.
  8. Përsërisim përsëri.

Pse kaq shumë vështirësi me pragun e migrimit…?E gjithë puna është që në praktikën reale shkrimi ‘rasësor’ nuk është në të vërtetë krejtësisht rastësor. Nëse kemi shkruar diçka në një sektor prej 4 kilobajt, ka shumë mundësi që për disa minuta të ardhshme të bëhet një shkrim në këtë ose një nga sektorët fqinj (+- 32K).

Duke e vendosur pragun e migrimit në zero ne shtyjmë sinkronizimin e shkrimit në SSD-të SATA dhe grumbullojmë disa ndryshime të një blloku 64K në cache. Kështu, ndjeshëm kursejmë burimin e SSD-ve SATA.

Dhe ku është kodi..?Fatkeqësisht, autori e konsideron veten të paaftë në fushën e zhvillimit të skripteve bash pasi është 100% vetë-mësuar dhe praktikon zhvillim të drejtuar nga ‘google’, kështu që mendon se ai kod i frikshëm që del nga duar deri më tani, nuk duhet të përdoret nga askush tjetër.

Mendoj se profesionistët e kësaj fushe do të jenë në gjendje të ilustrojnë logjikën e përshkruar më lart në rast nevoje, dhe ndoshta madje ta zbukurojnë atë si një shërbim systemd, ashtu siç përpiqet ta bëjë autori.

Një skemë e tillë e thjeshtë për rotacionin e snapshot-eve do të na lejojë jo vetëm të kemi një snapshot të plotë të sinkronizuar në SATA SSD, por gjithashtu do të na mundësojë, përmes utilit të thin_delta, të zbulojmë cilat blloqe janë modifikuar pas krijimit të tij dhe, në këtë mënyrë, të lokalizojmë dëmtimet në volumin e bazës, duke e thjeshtuar shumë procesin e rikuperimit.

TRIM/DISCARD në libvirt/KVM

Duke qenë se ruajtja e të dhënave do të përdoret për KVM nën menaxhimin e libvirt, do të ishte mirë t'i mësonim VM tonë jo vetëm të zënë hapësirë të lirë, por gjithashtu të çlirojnë atë që nuk është më e nevojshme.

Kjo bëhet përmes imitim të mbështetjes TRIM/DISCARD në disqet virtuale. Për këtë, është e nevojshme të ndryshohet lloji i kontrolluesit në virtio-scsi dhe të redaktohet xml.

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


</disk>

<controller type='scsi' index='0' model='virtio-scsi'>
<alias name='scsi0'/>


</controller>

DISCARD-të e tilla nga OS-të mysafire përpunohen saktësisht nga LVM, dhe blloqet lëshohen saktësisht si në cache ashtu edhe në rezervuarin e hollë. Në rastin tonë, kjo ndodh, kryesisht, në mënyrë të vonuar, gjatë fshirjes së një snapshot-i tjetër.

Backup me BTRFS

Përdorni skriptet e gatshme me kujdes të ekstrem dhe me rrezikun tuaj. Autori e ka shkruar këtë kod vetëm për vete. Jam i sigurt se shumë përdorues të avancuar të Linux kanë të tilla ndihma të rikrijuara, dhe nuk ka nevojë të kopjoni të tjerët.

Të krijojmë një volum në pajisjen rezervë:

#lvcreate -L 256G --name backup backup

Formato në BTRFS:

#mkfs.btrfs /dev/backup/backup

Të krijojmë pika montimi dhe të montojmë nënndezat e FS-së:

#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

Të krijojmë katalogë për kopjet rezervë:

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

Të krijojmë një katalog për skriptet e kopjimit rezervë:

#mkdir /root/btrfs-backup

Të kopjojmë skriptin:

Një shumë e frikshme e kodit bash. Përdorni në përgjegjësinë tuaj. Mos dërgoni letra të zemëruara autorit...#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\/"

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

funksioni wait_lock()
{
flock 98
}

funksioni wait_lock_or_terminate()
{
echo "Wating for lock..."
wait_lock || terminate "Dështoi për të marrë bllokimin. Duke dalë..."
echo "Mora bllokimin..."
}

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

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

funksioni 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"
nëse [ -d "$SOURCE_BASE_PATH" ]
then
echo "$SOURCE_BASE_PATH u gjetur"
else
echo "$SOURCE_BASE_PATH Skedari nuk u gjet, duke krijuar një snapshot të $SOURCE_PATH në $SOURCE_BASE_PATH"
btrfs subvolume snapshot -r $SOURCE_PATH $SOURCE_BASE_PATH
sync
nëse [ -d "$TARGET_BASE_PATH" ]
then
echo "$TARGET_BASE_PATH u gjet jashtë sinkronizimit me burimin... duke e hequr..."
btrfs subvolume delete -c $TARGET_BASE_PATH
sync
fi
fi
nëse [ -d "$TARGET_BASE_PATH" ]
then
echo "$TARGET_BASE_PATH u gjet"
else
echo "$TARGET_BASE_PATH nuk u gjet. Duke sinkronizuar në $TARGET_BASE_DIR"
btrfs send $SOURCE_BASE_PATH | btrfs receive $TARGET_BASE_DIR
sync
fi
nëse [ -d "$SOURCE_PEND_PATH" ]
then
echo "$SOURCE_PEND_PATH u gjet duke e hequr..."
btrfs subvolume delete -c $SOURCE_PEND_PATH
sync
fi
btrfs subvolume snapshot -r $SOURCE_PATH $SOURCE_PEND_PATH
sync
nëse [ -d "$TARGET_PEND_PATH" ]
then
echo "$TARGET_PEND_PATH u gjet duke e hequr..."
btrfs subvolume delete -c $TARGET_PEND_PATH
sync
fi
echo "Duke dërguar $SOURCE_PEND_PATH në $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
}

funksioni 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"
}

funksioni 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
}

funksioni removeall()
{
DATE_OFFSET="$2"
FILTER="$(filter "$DATE_OFFSET")"
ndërsa lexon -r SNAPSHOT ; bëj
remove "$1" "$SNAPSHOT"
mbarova <(list "$1" | grep "$FILTER")

}

(
COMMAND="$1"
shift

rast "$COMMAND" në
"--help")
echo "Ndihmë"
;;
"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 "Asnjë..."
;;
esac
) 98>$LOCK_FILE

EOF

Çfarë bën kjo..?Përmban një grup komandash të thjeshta për të krijuar snapshot-e BTRFS dhe për t'i kopjuar ato në një sistem tjetër përmes BTRFS send/receive.

E para herë që përdoret mund të jetë relativisht e gjatë, pasi në fillim do të kopjohen të gjithë të dhënat. Përdorimet e ardhshme do të jenë shumë të shpejta, pasi vetëm ndryshimet do të kopjohen.

Një skenar tjetër që do ta vendosim në cron:

Pak më shumë kod bash#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 ditë"
$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

Çfarë bën kjo..?Krijon dhe sinkronizon në sistemin rezervë snapshot-e inkrementale të volumeve të listuara BTRFS. Pas kësaj, fshin të gjitha snapshot-et e krijuara 60 ditë më parë. Pas ekzekutimit do të shfaqen snapshot-e të datuara të volumeve të listuara në nënkatalogët /backup/btrfs/back/remote/

Do t'i japim kodit të drejtat për ekzekutimin:

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

Do ta kontrollojmë dhe do ta vendosim në cron:

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

Kopjimi rezervë LVM thin

Do të krijojmë një puli të hollë në pajisjen rezervë:

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

Do të instalojmë ddrescue, pasi skriptet do të përdorin këtë mjet:

#apt-get install gddrescue

Do të krijojmë një katalog për skriptet:

#mkdir /root/lvm-thin-backup

Të kopjojmë skriptet:

Ka shumë bash brenda…#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

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

funksioni wait_lock()
{
flock 98
}

funksioni wait_lock_or_terminate()
{
echo "Wating for lock..."
wait_lock || terminate "Dështoi për të marrë bllokimin. Duke dalë..."
echo "Mora bllokimin..."
}

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

funksioni 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 është jo i hollë.")
exit 1
fi

if [ "$DIFF_TARGET_POOL" == "" ]
then
(>&2 echo "Target LV është jo i hollë.")
exit 1
fi

if [ "$DIFF_SOURCE_POOL" != "$DIFF_TARGET_POOL" ]
then
(>&2 echo "Source dhe target LV-të i takojnë pool-eve të ndryshme të holla.")
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 "Snapshot-i i metadata-s së pool-it të hollë ekziston tashmë. Duke supozuar se është i vjetëruar. Do të lirojë snapshot-in e metadata-s pas 5 sekondash.")
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 "Dështoi në krijimin e snapshot-it të metadata-s për pool-in e hollë.")
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 u gjet"
else
echo "$DISCARD_LV nuk është gjetur në $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
}

funksioni 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"
}

funksioni 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"
}

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

funksioni removeall()
{
DATE_OFFSET="$3"
FILTER="$(filter "$DATE_OFFSET")"
ndërsa lexon -r SNAPSHOT ; bëj
remove "$SNAPSHOT"
done < <(list "$1" "$2" | grep "$FILTER")

}

(
COMMAND="$1"
shift

rast "$COMMAND" në
"--help")
echo "Ndihmë"
;;
"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 "Asnjë..."
;;
esac
) 98>$LOCK_FILE

EOF

Çfarë bën...?Përmban një set urdhrash për manipulimin eSnapshot-ve të hollë dhe sinhronizimin e diferencës midis dySnapshot-ve të hollë, të arritura nëpërmjet thin_delta, në një pajisje tjetër bllokimi duke përdorur ddrescue dhe blkdiscard.

Një tjetër skenar që do ta vendosim në cron:

Pak më shumë 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 ditë"

$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

Çfarë bën...?Përdor skenarin e mëparshëm për të krijuar dhe sinkronizuar kopje rezervë tëVolume-ve të hollë të renditur. Skripti do të lërëSnapshot-et joaktive tëVolum-ve të renditur që nevojiten për të ndjekur ndryshimet që nga sinkronizimi i fundit.

Ky skenar duhet edituar duke treguar listën eVolume-ve të hollë për të cilat kërkohen kopje rezervë. Emrat e dhënë janë vetëm për shembuj. Nëse dëshironi, mund të shkruani një skenar që do të sinkronizonte të gjithaVolume-t.

Të kemi të drejtat:

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

Do ta kontrollojmë dhe do ta vendosim në cron:

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

Starti i parë do të zgjasë gjatë, pasiVolume-t e hollë do të sinkronizohen plotësisht duke kopjuar gjithë hapësirën e përdorur. Falë të dhënave të metadata-s LVM thin, ne e dimë se cilat blloqe janë në të vërtetë të përdorura, kështu që vetëm blloqet e vërteta të përdorura tëVolume-ve të hollë do të kopjohen.

Kopjet pasuese do të kopjojnë të dhënat në mënyrë incrementale falë ndjekjes së ndryshimeve përmes metadata-s LVM thin.

Le të shohim se çfarë ndodhi:

#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 mar 26 09:11 .
drwxr-xr-x 1 root root 16 mar 6 09:30 ..
drwxr-xr-x 1 root root 322 mar 26 02:00 .@base
drwxr-xr-x 1 root root 516 mar 6 09:39 .@snap.2020-03-06-09-39-37
drwxr-xr-x 1 root root 516 mar 6 09:39 .@snap.2020-03-06-09-39-57
...
/backup/btrfs/back/remote/root:
total 0
drwxr-xr-x 1 root root 2820 mar 26 09:11 .
drwxr-xr-x 1 root root 16 mar 6 09:30 ..
drwxr-xr-x 1 root root 240 mar 26 09:11 @.@base
drwxr-xr-x 1 root root 22 mar 26 09:11 @home.@base
drwxr-xr-x 1 root root 22 mar 6 09:39 @home.@snap.2020-03-06-09-39-35
drwxr-xr-x 1 root root 22 mar 6 09:39 @home.@snap.2020-03-06-09-39-57
...
drwxr-xr-x 1 root root 240 mar 6 09:39 @.@snap.2020-03-06-09-39-26
drwxr-xr-x 1 root root 240 mars 6 09:39 @.@snap.2020-03-06-09-39-56
...

#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

Çfarë kanë të bëjnë matreshkat?

Me shumë gjasë, është se volumet logjike LVM LV mund të jenë volume fizike LVM PV për VG të tjera. LVM mund të jetë rekurziv, si matreshkat. Kjo i jep LVM fleksibilitet të jashtëzakonshëm.

P.S.

Në artikullin e ardhshëm do të përpiqemi të përdorim disa sisteme të ngjashme të ruajtjes mobile/KVM si bazë për krijimin e një storage/vm-cluster të shpërndarë gjeografikisht me kopje rezervë në disa kontinente përmes desktopëve të shtëpisë, internetit të shtëpisë dhe rrjeteve P2P.

Burimi: habr.com

Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS 🔥 Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS | ProHoster