Tere päevast.
Soovin jagada kogemust KVM-i andmesalvestussüsteemi ehitamisel, kasutades md RAID + LVM-i.
Kavas on:
- MD RAID 1 kogumine NVMe SSD-dest.
- MD RAID 6 kogumine SATA SSD-dest ja tavalisest kettadest.
- TRIM/DISCARD funktsiooni omadused SSD RAID 1/6 korral.
- Käivitava md RAID 1/6 massiivi loomine eri kettade komplektist.
- Süsteemi installimine NVMe RAID 1-le, kui BIOS ei toeta NVMe-d.
- LVM cache ja LVM thin kasutamine.
- BTRFS-i kohe ja send/receive kasutamine varundamiseks.
- LVM thin kohe ja thin_delta kasutamine BTRFS-i stiilis varundamiseks.
Kui see huvi pakub, palun vaata edasi.
Märkus
Autor ei vastuta mingite tagajärgede eest, mis tulenevad käesoleva artikli materjalide/näidete/koodi/nõuannete/andmete kasutamisest või mitte kasutamisest. Käesolevat materjali lugedes või mis tahes viisil kasutades võtate enda kanda kõik selle tegevuse tagajärjed. Võimalike tagajärgede hulka kuuluvad:
- Küpsetatud kuni krõbeda NVMe SSD.
- Kirjutusressurss on täielikult välja kulutatud ja SSD-d lõhkemised.
- Kõigi andmete, sealhulgas varukoopiate täielik kaotus kõikidel kettadel.
- Vigane arvutiraud.
- Kulutatud aeg, närvid ja raha.
- Iga muud tagajärjed, mida ei ole eespool loetletud.
Riistvara
Oli saadaval:
Emaplaat, mis on toodetud umbes 2013. aastal Z87 kiibistiku põhjal koos Intel Core i7 / Haswell protsessoriga.
- 4 tuuma, 8 lõime protsessor.
- 32 GB DDR3 operatiivmälu.
- 1 x 16 või 2 x 8 PCIe 3.0.
- 1 x 4 + 1 x 1 PCIe 2.0.
- 6 x 6 GBps SATA 3 porti.
SAS adapter LSI SAS9211-8I, mis on vilkuma IT / HBA režiimi. RAID'i toe püsivara on tahtlikult asendatud HBA püsivara, et:
- Saaks igal hetkel selle adapteri välja visata ja asendada mistahes teise, mis ette jääb.
- TRIM/Discard töötab kõvaketastega normaalselt, kuna RAID püsivara ei toeta neid käske üldse, aga HBA ei ole sisuliselt tähtis, milliseid käske bussil edastada.
Kõvakettad — 8 tükki HGST Travelstar 7K1000, mille maht on 1 TB 2.5-tollises formaat, nagu sülearvutitele. Need kettad olid varem RAID 6 mahus. Uues süsteemis leiavad nad samuti kasutust kohalike varukoopiate säilitamiseks.
Lisaks oli lisatud:
6 tükki SATA SSD mudeleid Samsung 860 QVO 2TB. Need SSD-d nõudsid suurt mahtu, SLC vahemälu olemasolu, soovitav oli usaldusväärsus ja madal hind. Oluline oli, et oleks tugi discard/zero, mida kontrollitakse dmesg rea järgi:
kernel: ata1.00: Lubatakse discard_zeroes_data
2 tükki NVMe SSD mudeleid Samsung SSD 970 EVO 500GB.
Nende SSD-de puhul on oluline juhuslike lugemise/kirjutamise kiirus ja nende tööea sobivus. Radiaator tuleb kindlasti lisada. Absoluutselt. Ilma selleta — jätate nad esimese RAID sünkroniseerimise ajal rabedaks.
StarTech PEX8M2E2 adapter 2 x NVMe SSD jaoks PCIe 3.0 8x pesasse. See on jällegi lihtsalt HBA, kuid NVMe jaoks. Erineb odavatest adapteritest, kuna ei nõua PCIe bifurcationi toe olemasolu emaplaadilt tänu sisseehitatud PCIe lülitile. Töötab isegi kõige vanemas süsteemis, kus on PCIe, isegi kui see on x1 PCIe 1.0 pesa. Loomulikult, vastava kiirusaga. Seal ei ole RAID-e. Sisseehitatud BIOS-i pole. Seega ei õpi teie süsteem maagiliselt käivituma NVMe-lt ja veel vähem tegema NVMe RAID-i tänu sellele seadmele.
See komponent on tingitud ainult ühest vabas 8x PCIe 3.0 pesast süsteemis ning leides 2 vaba pesaga, on see hõlpsasti asendatav kahe odava PEX4M2E1 või sarnasega, mida saab osta igalt poolt alates 600 rubla.
Tavapäraste raudvarade või kiibisti/BIOSe RAIDide kasutamisest loobumine tehti teadlikult, et võimaldada süsteemi täielikku asendamist, välja arvatud SSD/HDD, säilitades kõik andmed. Ideaalselt, et võiks säilitada isegi installitud operatsioonisüsteemi üleminekul täiesti uuele/teisele riistvarale. Peamine on, et seal oleks SATA ja PCIe pesad. See on nagu live CD või käivitatav USB, ainult et väga kiire ja veidi mahukam.
HuviJa tead, kuidas on — vahel on häda tekkinud, et tuleb kogu maht endaga kaasa võtta. Andmeid ei taha kaotada. Selleks on kõik nimetatud seadmed mugavalt paigutatud 5.25 standardkorpuse radadele.
No ja loomulikult eksperimenteerimiseks erinevate SSD vahemälu meetoditega Linuxis.
Riistvara RAID on igav. Lülitad sisse. See kas töötab või ei tööta. Aga mdadmiga on alati erinevad võimalused.
Tarkvara
Varasemal riistvaral oli paigaldatud Debian 8 Jessie, mis on peaaegu EOL. Oli kokku pandud RAID 6 eelmainitud HDD-dega koos LVM-iga. Sellega töötasid virtuaalmasinatele kvm/libvirt.
Kuna autoril on sobiv kogemus kaasaskantavate SATA/NVMe alglaadimise flashide loomisel ja et mitte katkestada tuttavat apt-malli, valiti sihthärkesüsteemiks Ubuntu 18.04, mis on juba piisavalt stabiliseerunud, kuid millel on veel 3 aastat tuge tulevikus.
Mainitud süsteemis on kõik vajalikud riistvarajuhid juba kastist välja. Me ei vaja mingeid kolmandate osapoolte tarkvara ega juhte.
Paigaldamiseks ettevalmistamine
Süsteemi paigaldamiseks vajame Ubuntu Desktop Image'i. Serveri süsteemil on mingi hull paigaldaja, mis käitub üleliia iseseisvalt, pannes kindlasti UEFI süsteemi osa ühele diskile, rikkudes kogu ilu. Seega installitakse see ainult UEFI režiimis. Kõik variandid, mida ei pakuta.
See ei sobi meile.
Miks?Kahjuks on UEFI laadimine äärmiselt halvasti ühilduv käivitusprogrammi RAID-iga, kuna keegi ei paku meile UEFI ESP jao varundamist. Internetis on retsepte, mis soovitavad asendada ESP jao mälupulgaga USB-porti, kuid see on tõrkepunkt. On ka retsepte, mis kasutavad tarkvaralist mdadm RAID 1 metaandmete versiooniga 0.9, mis ei sega UEFI BIOS-il seda jao nägemist, kuid see kestab kuni õnneliku hetkeni, mil BIOS või muu operatsioonisüsteem riistvaral kirjutab midagi ESP-sse, unustades sünkroniseerida teiste peeglitega.
Lisaks sõltub UEFI laadimine NVRAM-ist, mis ei rända koos diskidega uude süsteemi, kuna see on osa emaplaadist.
Seega ei hakka me uut jalgratast leiutama. Meil on juba olemas korralik, aastate jooksul tõestatud vana jalgratas, mida praegu nimetatakse Legacy/BIOS laadimiseks, uhkelt nimega CSM UEFI-ühilduvates süsteemides. Me lihtsalt võtame selle riiulilt, määrime, pumpame rehvid ja pühime niiske lapiga puhtaks.
Ubuntu töölauaversioon ei oska samuti korralikult Legacy laadijaga installida, kuid nagu öeldakse, vähemalt on valikud olemas.
Nii et kogume riistvara ja laadime süsteemi Ubuntu Live käivitatavalt USB-lt. Me peame alla laadima paketid, seega seadistame võrgu, mis teil tööle hakkas. Kui see ei hakka tööle, siis vajalikud paketid saab USB-le eelnevalt laadida.
Siseneme Desktopi keskkonda, käivitame terminali emulaatori ja lähme edasi:
#sudo bash
Kuidas…?Ülalolev rida on kanoniline vallandaja sudo teemaliste vaidluste jaoks. Suuremate võimalustega tuleb ka suurem vastutus. Küsimus on selles, kas suudate selle endale võtta. Paljud arvavad, et sudo sellel viisil kasutamine on vähemalt ettevaatlik.oMiks mitte ZFS…?oKui me installime tarkvara oma arvutisse, siis põhimõtteliselt laename oma riistvara selle tarkvara arendajatelt.

#apt-get install mdadm lvm2 thin-provisioning-tools btrfs-tools util-linux lsscsi nvme-cli mc
Kui me usaldame selle tarkvara oma andmete turvalisuse, siis võtame laenu, mis on võrdne nende andmete taastamise maksumusega, mida me peame kunagi tagasi maksma.Selle nurga alt on ZFS nagu Ferrari, samas kui mdadm+lvm sobib rohkem jalgrattaks.
Когда мы доверяем этому программному обеспечению сохранность своих данных, — мы берем кредит равный стоимости восстановления этих данных, по которому когда-то придется расплачиваться.
С этой точки зрения ZFS — это Феррари, а mdadm+lvm больше походит на велосипед.
Subjektiivne autor eelistab laenata tundmatutele isikutele laenatud jalgratta, mitte Ferrarit. Seal ei ole hind ka kõrge. Ei ole vaja õigusi. Lihtsam on KTT. Parkimine on tasuta. Läbivus on parem. Jalgrattale saab alati jalad külge panna ja seda saab ka omal käel parandada.
Miks siis BTRFS…?Käivitamiseks vajame operatsioonisüsteemile sobivat failisüsteemi, mis toetab Legacy/BIOS GRUB-i kohe ja toetab samal ajal elusfotode tegemist. Kasutame seda /boot jao jaoks. Peale selle eelistab autor kasutada seda failisüsteemi / (juure) jaoks, unustamata märkida, et muud tarkvara jaoks saab luua eraldi jaotised LVM-is ning neid vajalikesse kataloogidesse monteerida.
Me ei hoia selles failisüsteemis ei pilte virtuaalmasinad, ega andmebaase.
Seda failisüsteemi kasutatakse ainult süsteemi hetkede loomiseks ilma seda välja lülitamata, millele järgneb nende hetkede ülekandmine varukoopiadiskile kasutades send/receive.
Lisaks eeltoodule eelistab autor hoida minimaalset tarkvara otse riistvaral ja käitada kogu ülejäänud tarkvara virtuaalmasinates, kasutades selliseid lahendusi nagu GPU ja PCI-USB hostkontrollerite suunamine KVM-i kaudu IOMMU kaudu.
Riistvarale jäävad ainult — andmete salvestamine, virtualiseerimine ja varundamine.
Kui usaldate rohkem ZFS-i, siis põhimõtteliselt on need määratud rakendusele omavahel asendatavad.
Siiski ignoreerib autor teadlikult ZFS-i, BTRFS-i ja LVM-i sisseehitatud peegelduse / RAID-i ja üleliigsuse funktsioone.
Lisaks on BTRFS-l kalduvus muuta juhuslik kirjutamine järjestikuseks, mis mõjutab väga positiivselt varukoopiate / snapshotide sünkroniseerimise kiirus HDD-l.
Skaneerime kõik seadmed uuesti:
#udevadm control --reload-rules && udevadm trigger
Vaata ümber:
#lsscsi && nvme list
[0:0:0:0] kettaseade ATA Samsung SSD 860 2B6Q /dev/sda
[1:0:0:0] kettaseade ATA Samsung SSD 860 2B6Q /dev/sdb
[2:0:0:0] kettaseade ATA Samsung SSD 860 2B6Q /dev/sdc
[3:0:0:0] kettaseade ATA Samsung SSD 860 2B6Q /dev/sdd
[4:0:0:0] kettaseade ATA Samsung SSD 860 2B6Q /dev/sde
[5:0:0:0] kettaseade ATA Samsung SSD 860 2B6Q /dev/sdf
[6:0:0:0] kettaseade ATA HGST HTS721010A9 A3J0 /dev/sdg
[6:0:1:0] kettaseade ATA HGST HTS721010A9 A3J0 /dev/sdh
[6:0:2:0] kettaseade ATA HGST HTS721010A9 A3J0 /dev/sdi
[6:0:3:0] kettaseade ATA HGST HTS721010A9 A3B0 /dev/sdj
[6:0:4:0] kettaseade ATA HGST HTS721010A9 A3B0 /dev/sdk
[6:0:5:0] kettaseade ATA HGST HTS721010A9 A3B0 /dev/sdl
[6:0:6:0] kettaseade ATA HGST HTS721010A9 A3J0 /dev/sdm
[6:0:7:0] kettaseade ATA HGST HTS721010A9 A3J0 /dev/sdn
Sõlm SN Mudel Nimi Kasutamine Vorming 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
Diskide jaotamine
NVMe SSD
Aga me ei hakka neid kuidagi jaotama. Igatahes ei näe meie BIOS neid mälusid. Nii et need lähevad täielikult tarkvaras RAID-i. Isegi jaotusi ei hakka seal looma. Kui tahate 'kanoniga' või 'põhimõtteliselt' — looge üks suur jaotus, nagu HDD-l.
SATA HDD
Siin ei ole vaja midagi eriti leiutada. Loome ühe sektsiooni kõigile. Sektsioon loomine on vajalik, kuna BIOS näeb neid kettaid ja võib isegi proovida nendelt käivituskorraldust teha. Paigaldame hiljem neile ketastele GRUB-i, et süsteem saaks seda ootamatult teha.
#cat >hdd.part << EOF
silt: dos
silt-id: 0x00000000
seade: /dev/sdg
üksus: sektorid
/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
Siin on meil kõige huvitavam.
Esiteks on meie mäluseadmed suurusega 2 TB. See on MBR-i jaoks lubatud, millega me ka kasutame. Vajadusel saab vahetada GPT vastu. GPT ketaste jaoks on olemas ühilduvustase, mis võimaldab MBR-ühilduvatel süsteemidel näha esimest 4 sektsiooni, kui need asuvad esimeses 2 terabaidis. Peamine on, et käivitussektsioon ja sektsioon bios_grub oleksid nende ketaste alguses. See võimaldab isegi teha Legacy/BIOS käivitust GPT ketastelt.
Kuid see ei ole meie juhtum.
Siin loome kaks sektsiooni. Esimene on suurusega 1 GB ja kasutatakse RAID 1 /boot jaoks.
Teine kasutatakse RAID 6 jaoks ja hõlmab kogu ülejäänud vaba ruumi, välja arvatud väike jaotamata ala ketta lõpus.
Mis see jaotamata ala on?Võrgustiku allikate kohaselt on meie SATA SSD-de koostisosadeks dünaamiliselt laiendatav SLC vahemälu, mille suurus on vahemikus 6 kuni 78 gigabaiti. 6 gigabaiti saame „tasuta“ tänu erinevustele „gigabaitide“ ja „gibibaitide“ vahel seadme tehnilistes omadustes. Ülejäänud 72 gigabaiti eraldatakse kasutamata ruumi põhjal.
Siinkohal tuleb märkida, et vahemälu on meil SLC ja ruumi kasutatakse 4 bitti MLC režiimis. See tähendab, et iga 4 gigabaiti vabast ruumist saame ainult 1 gigabaiti SLC vahemälust.
Korrutame 72 gigabaiti neljaga ja saame 288 gigabaiti. See on see vaba ruum, mida me ei märgista, et lubada andmekandjatel SLC vahemälu täielikult kasutada.
Nii saame kokku efektiivselt kuni 312 gigabaiti SLC vahemälu kokku kuuest andmekandjast. Kahest andmekandjast kasutatakse RAID-i kaudu liigse koormuse tagamiseks.
Selline vahemälu maht võimaldab meil äärmiselt harva kogeda olukorda, kus kirjutamine ei toimu vahemälus. See kompenseerib suurepäraselt kõige kurvema QLC mälu puuduse — äärmiselt madal kirjutamiskiirus, kui andmed kirjutatakse vahemälust mööda. Kui teie koormused sellega ei sobi, siis soovitan tõsiselt mõelda, kui kaua teie SSD-d sellise koormuse all kestavad, arvestades TBW-d tehnilises dokumentatsioonis.
#cat >ssd.part << EOF
silt: dos
silt-id: 0x00000000
seade: /dev/sda
üksus: sektorid
/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
Massiivide loomine
Alustuseks peame masina nime muutma. Seda on vaja, sest hostinimi on osa massiivi nimest kuskil mdadm-is ja mõjutab midagi. Muidugi on massiive hiljem võimalik ka ümber nimetada, kuid see on ebavajalik tegevus.
#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
Miks -assume-clean…?Kuna see ei initsialiseeri massiive. RAID 1 ja 6 tasemete puhul on see lubatud. Kõik võib töötada ka ilma initsialiseerimiseta, kui see on uus massiiv. Veelgi enam, SSD massiivi initsialiseerimine loomisel on TBW ressursi raiskamine. Kasutame TRIM/DISCARD-i nii palju kui võimalik kogutud SSD massiivides nende 'initsialiseerimiseks'.
SSD RAID 1 massiivide puhul toetatakse DISCARD-i välja kastist.
SSD RAID 6 massiivide puhul tuleb DISCARD aktiveerida tuumamooduli seadetes.
Seda tuleks teha ainult siis, kui kõik SSD-d, mis on kasutusel 4/5/6 taseme massiivides, toetavad täielikult discard_zeroes_data funktsiooni. Mõnikord esineb kummalisi seadmeid, mis teavitavad tuumast selle funktsiooni toetamisest, kuid tegelikult seda ei toimu või see ei toimi alati. Hetkel on toetus peaaegu igal pool olemas, kuid vanad seadmed ja vigaste püsivara esinemine on ikka veel probleemiks. Sellest tulenevalt on RAID 6 puhul DISCARD tugi vaikimisi välja lülitatud.
Tähelepanu, järgmine käsk hävitab kõik andmed NVMe seadmetel, 'algatades' massiivi 'nullidega'.
#blkdiscard /dev/md0
Kui midagi läks valesti, proovige täpsustada sammu.
#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
Miks nii suur…?Chunk-size suurendamine mõjutab positiivselt juhusliku lugemise kiirus, kuni chunk-size-ni. See juhtub, kuna üks sellise suurusega või väiksem opsioon saab täielikult teostada ühel seadmel. Seetõttu summeeruvad IOPS kõikidelt seadmetelt. Statistika kohaselt ei ületa 99% IO-d 512K.
RAID 6 IOPS kirjutamisel alati ühe ketta IOPS on väiksem või võrdne. Samas võib juhuslik lugemine IOPS olla mitmeid kordi suurem kui ühe ketta oma, kusjuures ploki suurusel on võtmeroll.
Autor ei näe mõtet proovida optimeerida parameetrit, mis on RAID 6 disainispetsiifiliselt halb, ja selle asemel optimeerib ta seda, milles RAID 6 end hästi näitab.
Halva juhusliku kirjutamise RAID 6 kompenseerime NVMe vahemälu ja thin-provisioning nipidega.
Me ei ole veel RAID 6 jaoks DISCARD’i lisanud. Seega ei hakka me seda massiivi 'algatama'. Teeme seda hiljem – pärast operatsioonisüsteemi installimist.
SATA HDD
#mdadm --create --verbose --assume-clean /dev/md3 --chunk-size=512 --level=6 --raid-devices=8 /dev/sd[g-n]1
LVM NVMe RAID-il
Kiirusest lähtudes tahame paigutada juurkatalooge NVMe RAID 1, mis on /dev/md0.
Kuid me vajame seda kiiret massiivi ka muude vajaduste jaoks, nagu swap, metaandmed ja LVM-cache vahemälu ja LVM-thin metaandmed, seetõttu loome sellel massiivil LVM VG.
#pvcreate /dev/md0
#vgcreate root /dev/md0
Loomine juurkatalooge jaoks.
#lvcreate -L 128G --name root root
Loomine vahetusfailile, mille suurus on võrreldav töötavate mälude suurusega.
#lvcreate -L 32G --name swap root
Operatsioonisüsteemi installimine
Kokkuvõttes on meil kõik vajalik süsteemi installimiseks.
Käivitame süsteemi installimise wizard'i Ubuntu Live keskkonnast. Tavaline installatsioon. Ainult ketaste valimise etapis tuleb märkida järgmist:
- /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), — использовать как раздел подкачки
- Käivitaja installimine /dev/sda-le
Kui valite BTRFS-i juureks failisüsteemiks, loob installer automaatselt kaks BTRFS-ruumi nimega "@" juure (/), ja "@home" /home jaoks.
Käivitame installimise…
Installimine lõpeb dialoogakna ilmumisega, mis teatab käivitaja installimise veast. Kahjuks ei õnnestu selle dialooge tavapäraste meetoditega sulgeda ja installimist jätkata. Logime süsteemist välja ja logime uuesti sisse, sisenedes puhtale Ubuntu Live töölauale. Avame terminali ja kirjutame taas:
#sudo bash
Loome chroot keskkonna, et installimist jätkata:
#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
Seame chrootis võrgu ja hosti nime:
#cat /etc/hostname >/mnt/chroot/etc/hostname
#cat /etc/hosts >/mnt/chroot/etc/hosts
#cat /etc/resolv.conf >/mnt/chroot/etc/resolv.conf
Siseneme chroot keskkonda:
#chroot /mnt/chroot
Esmalt paigaldame vajalikud paketid:
apt-get install --reinstall mdadm lvm2 thin-provisioning-tools btrfs-tools util-linux lsscsi nvme-cli mc debsums hdparm
Kontrollime ja parandame kõik paketid, mis on vale installimise tõttu valesti paigaldatud:
#CORRUPTED_PACKAGES=$(debsums -s 2>&1 | awk '{print $6}' | uniq)
#apt-get install --reinstall $CORRUPTED_PACKAGES
Kui midagi ei tööta, peate võib-olla enne seda redigeerima /etc/apt/sources.list faili.
Parandame RAID 6 mooduli seadistused, et lubada TRIM/DISCARD:
#cat >/etc/modprobe.d/raid456.conf << EOF
valikud raid456 seadmed_haldavad_hävitamist_turvaliselt=1
EOF
Meie massiivid saavad veidi seadistust:
#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
Mis see oli..?Oleme loonud komplekti udev reegleid, mis teevad järgmist:
- Seada sobiva 2020. aasta RAID 6 blokki vahemälu suuruse. Tundub, et vaikeväärtust ei ole muudetud alates Linuxi loomise ajast ja see ei ole ammu enam adekvaatne.
- Broneerige kontrollide/sünkroniseerimiste ajal minimaalne IO koormus. See on vajalik, et teie massiivid ei jääks koormuse all igavese sünkroniseerimise olekusse.
- Piirake kontrollide/sünkroniseerimiste ajal maksimaalne IO koormus. See on vajalik, et sünkroniseerimine/kontroll SSD RAID-ide mitte kuumaks küpsetaks teie seadmeid. Eriti oluline NVMe puhul. (Kas mäletate jahutusplekk? Ma ei naljanud.)
- Запрещать через APM дискам останавливать вращение шпинделя (HDD) и устанавливать таймаут для сна контроллеров дисков на 7 часов. Можно совсем отключить APM если ваши диски это умеют (-B 255). Со значением по-умолчанию диски будут останавливаться через пять секунд. Потом ОС захочет сбросить дисковый кэш, диски раскрутятся снова, и, все по-новой. У дисков ограничено максимальное число раскручиваний шпинделя. Такой нехитрый цикл по-умолчанию может легко убить ваши диски за пару лет. Этим страдают не все диски, но, наши-то «ноутбучные», с соответствующими настройками по-умолчанию, которые делают из RAID-а кривое подобие mini-MAID-а.
- Устанавливать readahead на дисках (вращающихся) в 1 мегабайт — два последовательных блока/chunk RAID 6
- Запрещать readahead на самих массивах.
Подредактируем /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
Почему так..?Kandame /boot partitsiooni UUID järgi, kuna massiivide nimed võivad teoreetiliselt muutuda.
Ülejäänud partitsioone otsime LVM nimede kaudu, järgides süntaksit /dev/mapper/vg-lv, kuna need identifitseerivad partitsioone piisavalt unikaalselt.
Ärge kasutage UUID-d LVM jaoks, kuna LVM mahtude ja nende snapshotide UUID-d võivad kattuda.Kuidas kaks korda mountida /dev/mapper/root-root..?Jah. Just nii. BTRFS-i eripära. Seda failisüsteemi saab mountida mitu korda erinevate subvol'idega.
Selle sama eripära tõttu soovitan alati vältida aktiivsete BTRFS mahtude LVM snapshotide loomist. Võite pärast taaskäivitamist üllatuda.
Regenerime mdadm konfiguratsiooni:
#/usr/share/mdadm/mkconf | sed 's/#DEVICE/DEVICE/g' >/etc/mdadm/mdadm.conf
Korrigeerime LVM seaded:
#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
Mis see oli..?Oleme lubanud automaatse LVM thin basseinide laiendamise, kui kohandatud ruum on 90% ja see laieneb 5% võrra.
Oleme suurendanud LVM cache'i jaoks maksimaalset vahemälu plokkide arvu.
Oleme keelanud LVM-il otsida LVM mahtusid (PV) järgmistes seadmetes:
- seadmetes, mis sisaldavad LVM cache'i (cdata)
- seadmetes, mida on LVM cache'i kaudu vahemällu salvestatud (selge _corig). Samuti skaneeritakse vahemällu salvestatud seade siiski vahemälu kaudu (lihtsalt ).
- seadmetes, mis sisaldavad LVM cache'i metadata (cmeta)
- kõikides seadmetes, mis on VG nimega images. Siin hoitakse meie virtuaalmasinate kettapilte, ning me ei soovi, et LVM hostis aktiveeriks külg-OS-i kuuluvad mahud.
- kõigis VG seadmetes, mille nimeks on backup. Siia salvestame virtuaalmasinate pildid.
- kõigis seadmetes, mille nimi lõpeb 'gpv' (guest physical volume)
Oleme lisanud DISCARD toe tühjendamiseks vaba ruumi LVM VG-s. Olge ettevaatlikud. See muudab LV kustutamise SSD-l piisavalt kaua kestvaks. Eriti kehtib see SSD RAID 6 puhul. Siiski plaanime kasutada thin provisioning-d, seega ei tohiks see meid segada.
Uuendame initramfs pilti:
#update-initramfs -u -k all
Paigaldame ja konfigureerime grub:
#apt-get install grub-pc
#apt-get purge os-prober
#dpkg-reconfigure grub-pc
Milliseid kettaid valida?Kõik, mis on sd*. Süsteem peab suutma käivituda mistahes töötavast SATA ketast või SSD-st.
Miks os-prober maha suruti..?Liialt iseseisvuse ja sahkerdamise pärast.
See ei tööta korralikult, kui üks RAID on degradeerunud. Ta püüab otsida OS-i osadest, mis on kasutusel virtuaalmasinates, mis töötavad selle riistvara peal.
Kui see on vajalik, võite jätta, kuid pidage meeles eespool mainitut. Soovitan otsida internetist retsepte, kuidas sahkerdamisest vabaneda.
Selle lõpetame esialgse installimise. On aeg taaskäivitada just installitud operatsioonisüsteemi. Ära unusta eemaldada käivitatavat Live CD/USB-d.
#exit
#reboot
Käivitusseadmeks valime ükskõik millise SATA SSD.
LVM SATA SSD-l
Selleks ajaks oleme juba sisse loginud uude operatsioonisüsteemi, seadnud üles võrgu, apt, avanud terminali emulaatori ja jooksutanud:
#sudo bash
Jätkame.
«Initsialiseerime» massiivi SATA SSD-lt:
#blkdiscard /dev/md2
Kui see ei toimi, siis proovime:
#blkdiscard --step 65536 /dev/md2
Loome SATA SSD-l LVM VG:
#pvcreate /dev/md2
#vgcreate data /dev/md2
Miks veel üks VG..?Tõepoolest, meil on juba VG nimega root. Miks mitte kõik ühte VG lisada?
Kui VG-l on mitu PV-d, siis nende õigeks aktiveerimiseks peavad kõik PV-d olema kohal (online). Erandiks on LVM RAID, mida me sihipäraselt ei kasuta.
Me soovime väga, et RAID 6 massiivi mis tahes tõrke korral (loe andmete kaotust) käivituks operatsioonisüsteem tavapäraselt ja annaks meile võimaluse probleem lahendada.
Selleks, abstraktsiooni esimesel tasemel, isoleerime iga füüsilise "kandja" tüübi eraldi VG-sse.
Teaduslikult öeldes kuuluvad erinevad RAID massiivid erinevatesse "usaldusdomäänidesse". Ei tasu luua neile lisaks ühiseid tõrke-kohti, surudes kõik ühte VG-sse.
LVM-i olemasolu „raudi“ tasemel võimaldab meil erinevate RAID-massiivide osi meelevaldselt jagada, neid omavahel kombineerides. Näiteks, et käivitada samal ajal bcache + LVM thin, bcache + BTRFS, LVM cache + LVM thin, keeruline ZFS konfiguratsioon käivitusfailidega või mis tahes muu segadus, et seda kõike testida ja võrrelda.
„Raudi“ tasemel ei kasuta me midagi muud kui vanade head „paksude“ LVM-mahtude algandmeid. Erandiks sellest reeglist võib olla tagavarakoopia eraldi osa.
Ma arvan, et paljud lugejad on juba hakanud midagi kahtlustama seoses matrooshkaga.
LVM SATA HDD-l
#pvcreate /dev/md3
#vgcreate backup /dev/md3
Jälle uus VG..?Me tahame tõeliselt, et kui diskimassiiv, mida kasutame andmete varundamiseks, ebaõnnestub, siis meie operatsioonisüsteem jätkaks tööd normaalselt, samal ajal säilitades pääsu mittevarundatud andmetele. Seetõttu, et vältida VG aktiveerimise probleeme, loome eraldi VG.
LVM cache'i seadistamine
Loome LV NVMe RAID 1-l, et kasutada seda vahemäluseadmest.
#lvcreate -L 70871154688B --name cache root
Miks on nii vähe...?As it turns out, our NVMe SSDs also feature SLC cache. There are 4 gigabytes of 'free' cache and 18 gigabytes of dynamic cache due to the free space occupied in 3-bit MLC. Once this cache is exhausted, NVMe SSDs won't be much faster than our SATA SSDs with cache. For this reason, there is no point in making the LVM cache partition significantly larger than twice the size of the SLC cache of the NVMe drive. For the NVMe drives we use, it is reasonable to create a cache of 32-64 gigabytes.
The specified partition size is necessary to organize 64 gigabytes of cache, along with the placement of cache metadata and a backup of that metadata.
Additionally, I would note that after a dirty shutdown, LVM will mark the entire cache as dirty and will need to resynchronize. Moreover, this will recur with every use of lvchange on this device until a new system reboot. Therefore, I recommend recreating the cache immediately with the appropriate script.
We will create an LV on SATA RAID 6 to use it as a caching device.
#lvcreate -L 3298543271936B --name cache data
Why only three terabytes..?Ettevalmistamiseks, et vajadusel saaks kasutada SATA SSD RAID 6 mõnede muude vajaduste jaoks. Vahemälu suurust saab dünaamiliselt suurendada, töö käigus, ilma süsteemi tööseisakut. Selleks tuleb vahemälu ajutiselt peatada ja uuesti sisse lülitada, kuid LVM-cache'i eripära, võrreldes näiteks bcache'iga, on see, et seda saab teha töö käigus.
Loome uue VG vahemäluks.
#pvcreate /dev/root/cache
#pvcreate /dev/data/cache
#vgcreate cache /dev/root/cache /dev/data/cache
Loome LV vahemälus.
#lvcreate -L 3298539077632B --name cachedata cache /dev/data/cache
Siin kasutasime koheselt kogu vaba ruumi /dev/data/cache, et kõik muud vajalikud osade loomised toimuksid otse /dev/root/cache. Kui midagi on loodud valele kohale, saab selle liikuda pvmove abil.
Loome ja aktiveerime vahemälu:
#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
Miks selline chunksize..?Praktiliste katsete käigus avastas autor, et parima tulemuse saavutamiseks peab LVM cache'i ploki suurus olema sama kui LVM thin'i ploki suurus. Samal ajal, mida väiksem on suurus, seda paremini töötab konfiguratsioon juhuslike kirjutuste korral.
64k on minimaalne ploki suurus, mis on lubatud LVM thin'i jaoks.
Ole ettevaatlik writeback..!Jah. See tüüp vahemälu lükkab kirje sünkroniseerimise vahemälus hoidmise seadmele edasi. See võib põhjustada andmete kaotuse vahemälu kaotamise korral. Hiljem räägib autor, milliseid meetmeid, välja arvatud NVMe RAID 1, saab võtta riski kompenseerimiseks.
See tüüp vahemälu on valitud teadlikult, et kompenseerida RAID 6 madalat jõudlust juhuslikul kirjutamisel.
Kontrollime, mis meil tuli välja:
#lvs -a -o lv_name,lv_size,devices --units B cache
LV LSize seadmed
[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)
/dev/data/cache peab sisaldama ainult [cachedata_corig]. Kui midagi on valesti, kasutage pvmove.
Vahemälu saab vajadusel ühe kommandiga välja lülitada:
#lvconvert -y --uncache cache/cachedata
See toimub online. LVM sünkroniseerib lihtsalt vahemälu kettale, eemaldab selle ja nimetab cachedata_corig tagasi cachedata-ks.
LVM thin seadistamine
Hinnatakse, kui palju ruumi vajame LVM thin metaandmete jaoks:
#thin_metadata_size --block-size=64k --pool-size=6terabytes --max-thins=100000 -u bytes
thin_metadata_size - 3385794560 baitsi hinnanguline metaandmeala suurus "--block-size=64kibibytes --pool-size=6terabytes --max-thins=100000"
Ümardame 4 gigabaidini: 4294967296B
Korrutame kahega ja lisame 4194304B LVM PV metaandmete jaoks: 8594128896B
Loome NVMe RAID 1 eraldi partitsiooni, et salvestada LVM thin metaandmed ja nende varukoopia:
#lvcreate -L 8594128896B --name images root
Miks..?Siin võib tekkida küsimus, miks paigutada LVM thin metaandmed eraldi, kui need on ikkagi vahemälus ja töötavad kiiresti.
Kuigi kiirus on siin oluline, ei ole see peamine põhjus. Asi on selles, et vahemälu on rikke punkt. Sellega võib midagi juhtuda ja kui LVM thin metaandmed on vahemälus, siis võib see viia kõigi andmete täieliku kadumiseni. Ilma tervete metaandmeteta on õhukeste mahtude ülesehitamine peaaegu võimatu.
Kandes metaandmed eraldi mitte-vahemälustatud, kuid kiirele mahule, tagame metaandmete säilimise vahemälu kaotuse või kahjustumise korral. Sel juhul lokaliseeritakse kõik kahjustused, mis tulenevad vahemälu kaotusest, vaid õhukestesse mahtudesse, mis lihtsustab taastamisprotseduuri oluliselt. Suure tõenäosusega saab need kahjustused taastada failisüsteemi logide abil.
Veelgi enam, kui on eelnevalt tehtud hetkeseis õhukesest mahust, ja pärast seda on vähemalt üks kord vahemälu täielikult sünkroonitud, siis, arvestades LVM thin sisemisi omadusi, on hetkeseisu terviklikkus tagatud vahemälu kaotuse korral.
Loome uue VG, mis vastutab õhukese pakkumise eest:
#pvcreate /dev/root/images
#pvcreate /dev/cache/cachedata
#vgcreate images /dev/root/images /dev/cache/cachedata
Loome basseini:
#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T images/thin-pool
Miks -Z yLisaks sellele, milleks see režiim on mõeldud – et vältida andmete lekkimist ühelt virtuaalmasinalt teisele ruumi ümberjaotamisel – kasutatakse zeroing täiendavalt väiksema kui 64k blokis juhusliku kirjutamise kiirusest suurema tõhususe saavutamiseks. Iga vähem kui 64k kirjutis varem mittejaotatud õhukesesse mahuti alasse muudetakse 64K pühendatuks vahemälu piirides. See võimaldab protsessil täielikult läbi vahemälu toimumist, vältides vahemälu seadme kasutamist.
Liigume LV vastavatele PV-dele:
#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
Kontrollime:
#lvs -a -o lv_name,lv_size,devices --units B images
LV LSize seadmed
[lvol0_pmspare] 4294967296B /dev/root/images(0)
õhuke bassein 274877906944B thin-pool_tdata(0)
[thin-pool_tdata] 274877906944B /dev/cache/cachedata(0)
[thin-pool_tmeta] 4294967296B /dev/root/images(1024)
Loome katsetamiseks õhukese mahuti:
#lvcreate -V 64G --thin-pool thin-pool --name test images
Paigaldame katse- ja jälgimispaketid:
#apt-get install sysstat fio
Nii saab jälgida oma salvestusseadme konfiguratsiooni käitumist reaalajas:
#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)'
Nii saab testida oma konfiguratsiooni:
#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
Oht! Ressurss!See kood käivitab 36 erinevat testi, millest igaüks kestab 4 sekundit. Pool teste on kirjutamistest. 4 sekundi jooksul suudab NVMe kirjutada väga palju. Kuni 3 gigabaiti sekundis. Seega võivad iga kirjutamiskatse käivitamine neelata teie SSD ressursse kuni 216 gigabaiti.
Lugemine ja kirjutamine segamini?Jah. Testid lugemise ja kirwriting jaoks on mõttekas teostada eraldi. Veelgi enam, on mõistlik veenduda, et kõik vahemälud on sünkroniseeritud, et varem tehtud kirje ei mõjuta lugemist.
Tulemused erinevad oluliselt esimese käivitamise ja järgnevate vahel, kuna vahemälu täitub ja õhuke maht areneb, ning olenevalt sellest, kas süsteem on suutnud sünkroniseerida vahemälud, mis täideti eelmisel käivitamisel.
Lisaks soovitan mõõta kiirus juba täidetud õhukeselt mahult, millest just tehti hetkeseis. Autor on märganud, kuidas juhuslik kirjutamine kiireneb pärast esimesena tehtud hetkeseisu loomist, eriti kui vahemälu ei ole veel täielikult täidetud. See toimub tänu copy-on-write kirjutamise semantikale, vahemälu ja õhukese mahu blokki tasandamisele, ning sellele, et juhuslik kirjutamine RAID 6-l muutub juhuslikuks lugemiseks RAID 6-l koos järgneva kirjutamisega vahemällu. Meie konfiguratsioonis on juhuslik lugemine RAID 6-l kuni 6 korda (SATA SSD-de arv maatriksis) kiirem kui kirjutamine. Kuna CoW jaoks blokeeritakse blokid järjestikku õhukesest basseinist, siis kirjutamine, enamasti, muutub ka järjestikuseks.
Mõlemaid neid omadusi saab kasulikult kasutada.
Vahehoidla «koherentsete» snäpšottide
Andmekao riski vähendamiseks vahehoidla kahjustamise või kaotamise korral soovitab autor rakendada snäpšottide vahetamise praktikat, mis tagab nende terviklikkuse sel juhul.
Esiteks, kuna peene mahtude metaandmed asuvad vahehoidmata seadmes, on metaandmed terved ja võimalikud kaotused isoleeritakse andmeplokkidesse.
Järgmine snäpšottide vahetamise tsükkel garanteerib andmete terviklikkuse snäpšottides ka vahehoidla kadumise korral:
- Käitage iga peene mahu jaoks nimega <имя> snäpšott nimega <имя>.cached
- Seame migreerimislävendi mõistlikult kõrgele väärtusele:
#lvchange --quiet --cachesettings "migration_threshold=16384" cache/cachedata - Tsüklis kontrollime määratud plokkide arvu vahehoidlas:
#lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}'kuni saame nulli. Kui nulli pole liiga kaua, saab selle ajutiselt luua, viies vahemälu writethrough režiimi. Siiski, arvestades meie SATA ja NVMe SSD-de kiirusnäitajaid ning nende TBW ressursse, suudate kas piisavalt kiiresti õigel hetkel tabada ilma vahemälu režiimi muutmata või teie riistvara tarbib kogu oma ressursi ära vaid mõne päevaga. Ressursi piirangute tõttu ei suuda süsteem pidevalt püsida 100% kirjutuskoormusel. Meie NVMe SSD-d kulutavad oma ressursid täieliku 100% kirjutuskoormuse all 3-4 päeva. SATA SSD-d elavad vaid kaks korda kauem. Seetõttu oletame, et suurem osa koormusest on lugemine, ja kirjutamine on meil – suhteliselt lühikesed kõrge aktiivsuse perioodid, millega kaasnevad madalad koormused keskmiselt. - Niipea kui oleme nulli saanud (või loonud) – muudame <nimi>.cached nimeks <nimi>.committed. Eemaldame vana <nimi>.committed.
- Valikuline: kui vahemälu on 100% täis, saab seda skripti abil uuesti luua, andes seeläbi tühjendamise. Osaliselt tühja vahemäluga töötab süsteem kirjutamisel palju kiiremini.
- Seame migreerimise lävendi nulliks:
#lvchange --quiet --cachesettings "migration_threshold=0" cache/cachedataSee on ajutiselt keelatud sünkroonida vahemälu peamisele kandjale. - Ootame, kuni vahemälus koguneb piisavalt muudatusi.
#lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}'või kuni taimer käivitub. - Kordame uuesti.
Miks need keerukused migration thresholdiga…?Asi on selles, et reaalses praktikas ei ole 'juhuslik' kirjutamine tegelikult täiesti juhuslik. Kui me kirjutame midagi 4 kilobaidi suurusesse sektorisse, on suur tõenäosus, et järgmise paari minuti jooksul tehakse kirjutamine sellesse või mõnda naaber (+- 32K) sektorisse.
Seades migration threshold nulli, lükkame SATA SSD-l kirjutamise sünkroonimist edasi ja kogume vahemälus mitu 64K ploki muudatust. Sellega säästame oluliselt SATA SSD ressurssi.
Aga kus on kood..?Kahjuks peab autor end bash skriptide arendamisel piisavalt mittekompetentseks, kuna on 100% iseõppija ja praktik, kes järgib 'google'-põhist arendust, seetõttu arvab ta, et see kohutav kood, mis tema käest tuleb, ei ole kedagi teist väärt kasutada.
Usun, et professionaalid suudavad vajadusel kogu eeltoodud loogika ise üles ehitada ja võib-olla isegi ilusasti systemd teenusena kujundada, nagu autor üritas teha.
Selline lihtne snapshotide rotatsiooni skeem võimaldab meil mitte ainult hoida ühte täielikult sünkroonitud SATA SSD snapshotit, vaid ka kasutada utiliiti thin_delta, et teada saada, millised plokid on pärast selle loomist muutunud, hõlbustades seeläbi põhitomide vigade paikamist ja taastamist.
TRIM/DISCARD libvirt/KVM
Kuna andmesalvestus on mõeldud KVM jaoks, mis töötab libvirt'i alt, oleks hea õpetada meie VM-e mitte ainult kasutama vaba ruumi, vaid ka vabastama juba ebavajaliku.
See saavutatakse TRIM/DISCARD toe emuleerimise teel virtuaalsetes ketastes. Selleks tuleb muuta kontrolleri tüüpi virtio-scsi ja redigeerida 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'/>
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</controller>
Delikud DISCARD'id külgvõrkudest töödeldakse LVM-iga korrektselt ja blokid vabastatakse õigesti nii vahemälus kui ka õhukeses mahus. Meie puhul toimub see peamiselt viivitusega, kui eemaldatakse järgmine snapshot.
BTRFS varukoopia
Kasutame valmis skripte äärmise ettevaatlikkusega ja oma riski ja vastutusega. Autor kirjutas selle koodi ise ja ainult enda tarbeks. Olen kindel, et paljudel kogenud Linuxi kasutajatel on olemas sarnased lahendused ja teiste kopeerimine pole vajalik.
Loome mahu varuseadmel:
#lvcreate -L 256G --name backup backup
Formateerime BTRFS-ks:
#mkfs.btrfs /dev/backup/backup
Loome mount-punktid ja mountime FS-i juurosakonnad:
#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
Loome varukoopiaideks kataloogid:
#mkdir /backup/btrfs/back/remote
#mkdir /backup/btrfs/back/remote/root
#mkdir /backup/btrfs/back/remote/boot
Loome varukoopiate skriptide katalooge:
#mkdir /root/btrfs-backup
Kopeerime skripti:
Palju kohutavat bash-koodi. Kasutada omal riskil. Autorile ei saada raevukaid kirju...#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 "Ootan lukku..."
wait_lock || terminate "Luku saamine ebaõnnestus. Väljumine..."
echo "Lukk saadud..."
}
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 leitud"
muud
echo "$SOURCE_BASE_PATH Faili ei leitud, luues $SOURCE_PATH jaoks $SOURCE_BASE_PATH snapshot'i"
btrfs subvolume snapshot -r $SOURCE_PATH $SOURCE_BASE_PATH
sync
if [ -d "$TARGET_BASE_PATH" ]
then
echo "$TARGET_BASE_PATH leitud, allika jaotusest väljas... eemaldatakse..."
btrfs subvolume delete -c $TARGET_BASE_PATH
sync
fi
fi
if [ -d "$TARGET_BASE_PATH" ]
then
echo "$TARGET_BASE_PATH leitud"
muud
echo "$TARGET_BASE_PATH ei leitud. Sünkroonimine $TARGET_BASE_DIR'iga"
btrfs send $SOURCE_BASE_PATH | btrfs receive $TARGET_BASE_DIR
sync
fi
if [ -d "$SOURCE_PEND_PATH" ]
then
echo "$SOURCE_PEND_PATH leitud, eemaldatakse..."
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 leitud, eemaldatakse..."
btrfs subvolume delete -c $TARGET_PEND_PATH
sync
fi
echo "Saadan $SOURCE_PEND_PATH $TARGET_PEND_PATH'ile"
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"
nihke
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
Mida see üldse teeb..?Sisaldab rida lihtsaid käske BTRFS snapshot'ide loomiseks ja nende edastamiseks teisele failisüsteemile BTRFS send/receive'i kaudu.
Esimene käivitamine võib olla suhteliselt aeglane, kuna alguses kopeeritakse kõik andmed. Edasi käivitamised on väga kiired, kuna kopeeritakse vaid muudatused.
Veel üks skript, mille paneme cron'i:
Veidi rohkem bash-koodi#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 päeva"
$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
Mida see teeb..?Loob ja sünkroneerib varukoopiate failisüsteemis sisemisi BTRFS mahutite inkrementaalseid pilte. Pärast seda eemaldab kõik 60 päeva tagasi loodud pildid. Pärast käivitamist ilmuvad kaustades /backup/btrfs/back/remote/ kuupäevalised pildid loetletud mahutitest.
Anname koodile õigused täitmiseks:
#chmod +x /root/btrfs-backup/cron-daily.sh
#chmod +x /root/btrfs-backup/btrfs-backup.sh
Kontrollime ja lisame croni:
#/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 õhukese varukoopia
Loome õhukese basaari varukoopia seadmes:
#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T backup/thin-pool
Paigaldame ddrescue, kuna skriptid kasutavad seda tööriista:
#apt-get install gddrescue
Loome skriptide kausta:
#mkdir /root/lvm-thin-backup
Kopeerime skriptid:
Palju bash'i sees…#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 "Ootan lukku..."
wait_lock || terminate "Luku saamine ebaõnnestus. Väljumine..."
echo "Lukk saadud..."
}
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 "Allikas LV ei ole õhuke.")
exit 1
fi
if [ "$DIFF_TARGET_POOL" == "" ]
then
(>&2 echo "Siht LV ei ole õhuke.")
exit 1
fi
if [ "$DIFF_SOURCE_POOL" != "$DIFF_TARGET_POOL" ]
then
(>&2 echo "Allika ja sihtrühmad kuuluvad erinevatesse õhukestesse basseinidesse.")
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 "Õhukese basseini metainformatsiooni hetkeseis juba eksisteerib. Eeldame, et see on aegunud. Vabastame metainformatsiooni hetkeseisu 5 sekundi pärast.")
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 "Õhukese basseini metainformatsiooni hetkeseisu loomine ebaõnnestus.")
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"
muud
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"
muud
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 ei ühtinud allikaga... eemaldamine..."
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 leitud"
muud
echo "$TARGET_VG/$TARGET_LV ei leitud. Loome tühja mahuti."
lvcreate --thin-pool "$BACKUPS_POOL" -V "$SOURCE_BASE_SIZE"B --name "$TARGET_BASE_LV" "$TARGET_VG" || exit 1
echo "Peame uuesti käivitama. Loovutame allika $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 "Loovutame sihtkohta $TARGET_BASE_LV_PATH"
discard_volume "$TARGET_VG" "$TARGET_BASE_LV"
sync
fi
if [ "$SOURCE_PEND_LV_PATH" != "" ]
then
echo "$SOURCE_PEND_LV_PATH leitud eemaldamine..."
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 leitud eemaldamine..."
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 "Sünkroniseerimine $SOURCE_PEND_LV_PATH $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"
muud
echo "$SOURCE_BASE_LV_PATH ei leitud"
exit 1
fi
if [ "$TARGET_BASE_LV_PATH" != "" ]
then
echo "$TARGET_BASE_LV_PATH leitud"
muud
kui "$TARGET_BASE_LV_PATH" ei leidu
exit 1
fi
aktiveeri_maht "$TARGET_VG" "$TARGET_BASE_LV"
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
võrdlemine "$SOURCE_BASE_LV_PATH" ja "$TARGET_BASE_LV_PATH"
võrdle "$SOURCE_BASE_LV_PATH" "$TARGET_BASE_LV_PATH"
Valmis...
deactivate_volume "$TARGET_VG" "$TARGET_BASE_LV"
deactivate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
}
funktsioon resünkroonimine()
{
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"
muud
echo "$SOURCE_BASE_LV_PATH ei leitud"
exit 1
fi
if [ "$TARGET_BASE_LV_PATH" != "" ]
then
echo "$TARGET_BASE_LV_PATH leitud"
muud
kui "$TARGET_BASE_LV_PATH" ei leidu
exit 1
fi
aktiveeri_maht "$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)
sünkroniseerimine "$SOURCE_BASE_LV_PATH" «"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 "Sünkroniseerimine $SYNC_LENGTH_BYTES baiti alguses $SYNC_OFFSET_BYTES $SOURCE_BASE_LV_PATH-st $TARGET_BASE_LV_PATH-le"
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"
muud
CMP_OFFSET=""
fi
done
Valmis...
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
eemalda "$SNAPSHOT"
done < <(list "$1" "$2" | grep "$FILTER")
}
(
COMMAND="$1"
nihke
case "$COMMAND" in
"--help")
echo "Help"
;;
"suffix")
suffix
;;
"filter")
filter "$1"
;;
"backup")
wait_lock_or_terminate
varunda "$1" "$2"
;;
"list")
loetle "$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
eemalda "$1"
;;
"removeall")
wait_lock_or_terminate
eemalda kõik "$1" "$2" "$3"
;;
*)
echo "None.."
;;
esac
) 98>$LOCK_FILE
EOF
Mida see teeb…?Sisaldab käskude komplekti peente snapshotide manipuleerimiseks ja kahe thin snapshot'i vahel tekkiva erinevuse sünkroonimiseks teise plokkseadmese, kasutades ddrescue ja blkdiscard.
Veel üks skript, mille paneme croni:
Natuke bash'i#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 päeva"
$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
Mida see teeb…?Kasutab eelmist skripti, et luua ja sünkroniseerida loetletud õhukeste mahtude varukoopiaid. Skript jätab loetletud mahtude mitteaktiivsed snapshot'id, mis on vajalikud muudatuste jälgimiseks viimase sünkroniseerimise järel.
Seda skripti tuleb kohandada, määrates loetelu õhukestest mahtudest, mille jaoks on vajalik varukoopia tegemine. Antud nimed on esitatud näitena. Soovi korral võib kirjutada skripti, mis sünkroniseerib kõik mahud.
Anname õigused:
#chmod +x /root/lvm-thin-backup/cron-daily.sh
#chmod +x /root/lvm-thin-backup/lvm-thin-backup.sh
Kontrollime ja lisame croni:
#/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
Esimene käivitamine võtab aega, kuna õhukesed mahud sünkroonitakse täielikult kogu kasutatava ruumi kopeerimise teel. Tänu LVM thin metaandmetele teame, milliseid blokke tegelikult kasutatakse, seega kopeeritakse ainult need õhukeste mahude tõeliselt kasutatavad plokid.
Järgmised käivitamised kopeerivad andmeid inkrementaalselt, jälgides muudatusi LVM thin metaandmete kaudu.
Vaatame, mis sai:
#time /root/btrfs-backup/cron-daily.sh
reaalne 0m2,967s
kasutaja 0m0,225s
süsteem 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 mär 26 09:11 .
drwxr-xr-x 1 root root 16 mär 6 09:30 ..
drwxr-xr-x 1 root root 322 mär 26 02:00 .@base
drwxr-xr-x 1 root root 516 mär 6 09:39 .@snap.2020-03-06-09-39-37
drwxr-xr-x 1 root root 516 mär 6 09:39 .@snap.2020-03-06-09-39-57
...
/backup/btrfs/back/remote/root:
total 0
drwxr-xr-x 1 root root 2820 mär 26 09:11 .
drwxr-xr-x 1 root root 16 mär 6 09:30 ..
drwxr-xr-x 1 root root 240 mär 26 09:11 @.@base
drwxr-xr-x 1 root root 22 mär 26 09:11 @home.@base
drwxr-xr-x 1 root root 22 mär 6 09:39 @home.@snap.2020-03-06-09-39-35
drwxr-xr-x 1 root root 22 mär 6 09:39 @home.@snap.2020-03-06-09-39-57
...
drwxr-xr-x 1 root root 240 mär 6 09:39 @.@snap.2020-03-06-09-39-26
drwxr-xr-x 1 root root 240 mär 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
...
õhuke bassein <2,09t
Mis tähendavad matroškad?
Tõenäoliselt seetõttu, et LVM LV loogilised mahud võivad olla teiste VG füüsilised mahud LVM PV. LVM võib olla rekursiivne nagu matroškad. See annab LVM-le ülima paindlikkuse.
P.S.
Järgmisest artiklist proovime kasutada mitmeid sarnaseid mobiilseid tehishoidlaid/KVM-i geo-jaotatud storage/vm-klastri väljaarendamiseks, pakkudes varundust mitmel mandril koduste lauaarvutite, koduse interneti ja P2P-võrkude kaudu.
Allikas: habr.com
