Mis on ühist LVM-il ja Matrjoškal?

Tere päevast.
Tahaksin jagada kogukonnaga oma praktilist kogemust KVM-i andmesalvestussüsteemi loomisel md RAID + LVM-i abil.

Programm sisaldab:

  • Md RAID 1 ehitamine NVMe SSD-lt.
  • Md RAID 6 kokkupanek SATA SSD-lt ja tavalistest draividest.
  • SSD RAID 1/6 TRIM/DISCARD toimingu omadused.
  • Alglaaditava md RAID 1/6 massiivi loomine ühisele ketaste komplektile.
  • Süsteemi installimine NVMe RAID 1-le, kui BIOS-is puudub NVMe tugi.
  • Kasutades LVM vahemälu ja LVM thin.
  • BTRFS-i hetktõmmiste kasutamine ja varundamiseks saatmine/vastuvõtmine.
  • LVM-i õhukeste hetktõmmiste ja thin_delta kasutamine BTRFS-stiilis varukoopiate jaoks.

Huvi korral vaadake kassi.

Avaldus

Autor ei vastuta selle artikli materjalide/näidete/koodi/näpunäidete/andmete kasutamise või mittekasutamise tagajärgede eest. Seda materjali lugedes või mis tahes viisil kasutades võtate endale vastutuse nende toimingute kõigi tagajärgede eest. Võimalike tagajärgede hulka kuuluvad:

  • Krõbedaks praetud NVMe SSD-d.
  • Salvestusressurss on täielikult ära kasutatud ja SSD-draivide rike.
  • Kõigi draivide kõigi andmete, sealhulgas varukoopiate täielik kadu.
  • Vigane arvuti riistvara.
  • Raisatud aeg, närvid ja raha.
  • Kõik muud tagajärjed, mida ei ole ülalpool loetletud.

Raud

Saadaval olid:

Umbes 2013. aastast pärit emaplaat Z87 kiibistikuga koos Intel Core i7 / Haswelliga.

  • Protsessor 4 tuuma, 8 keerme
  • 32 GB DDR3 RAM
  • 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 pistikud

SAS-adapter LSI SAS9211-8I vilkus IT / HBA režiimi. RAID-toega püsivara on tahtlikult asendatud HBA püsivaraga, et:

  1. Võite selle adapteri igal ajal välja visata ja asendada mõne muu vastutuleva adapteriga.
  2. TRIM/Discard töötas ketaste puhul normaalselt, kuna... RAID-i püsivaras ei toetata neid käske üldse ja HBA-d üldiselt ei huvita, milliseid käske siini kaudu edastatakse.

Kõvakettad - 8 tükki HGST Travelstar 7K1000 mahutavusega 1 TB vormiteguriga 2.5, nagu sülearvutite puhul. Need draivid olid varem RAID 6 massiivi sees. Neid saab kasutada ka uues süsteemis. Kohalike varukoopiate salvestamiseks.

Lisaks lisatud:

6 tk SATA SSD mudel Samsung 860 QVO 2TB. Need SSD-d nõudsid suurt mahtu, SLC-vahemälu olemasolu, töökindlust ja madalat hinda. Vaja oli discard/zero tuge, mida kontrollib dmesg rida:

kernel: ata1.00: Enabling discard_zeroes_data

2 tk NVMe SSD mudeli Samsung SSD 970 EVO 500GB.

Nende SSD-de puhul on teie vajadustele vastav juhuslik lugemis-/kirjutuskiirus ja ressursi maht olulised. Radiaator neile. Tingimata. Absoluutselt. Vastasel juhul praadige neid esimese RAID-i sünkroonimise ajal krõbedaks.

StarTech PEX8M2E2 adapter 2 x NVMe SSD jaoks, mis on installitud PCIe 3.0 8x pessa. See on jällegi lihtsalt HBA, kuid NVMe jaoks. See erineb odavatest adapteritest selle poolest, et see ei vaja sisseehitatud PCIe-lüliti olemasolu tõttu emaplaadilt PCIe bifurkatsiooni tuge. See töötab isegi kõige iidsemas PCIe-ga süsteemis, isegi kui see on x1 PCIe 1.0 pesa. Loomulikult sobiva kiirusega. RAIDe seal pole. Pardal pole sisseehitatud BIOS-i. Nii et teie süsteem ei õpi tänu sellele seadmele võluväel NVMe-ga alglaadimist, veel vähem NVMe RAID-i.

Selle komponendi põhjuseks oli ainult üks tasuta 8x PCIe 3.0 olemasolu süsteemis ja kui on 2 vaba pesa, saab selle hõlpsasti asendada kahe pennise PEX4M2E1 või analoogiga, mida saab osta kõikjal hinnaga 600 rublad.

Igasuguse riistvara või sisseehitatud kiibistiku/BIOS RAID-ide tagasilükkamine tehti teadlikult, et oleks võimalik kogu süsteem täielikult välja vahetada, välja arvatud SSD/HDD ise, säilitades samal ajal kõik andmed. Ideaalis selleks, et täiesti uuele/teistsugusele riistvarale üle minnes saaks salvestada isegi installitud operatsioonisüsteemi. Peaasi, et seal on SATA ja PCIe pordid. See on nagu reaalajas CD või buutitav mälupulk, ainult väga kiire ja veidi mahukas.

ЮморVastasel juhul teate, mis juhtub – mõnikord peate kiiresti kogu massiivi kaasa võtma, et ära viia. Kuid ma ei taha andmeid kaotada. Selleks asuvad kõik mainitud kandjad mugavalt standardkorpuse 5.25 lahtrites liugustel.

Noh, ja muidugi erinevate SSD vahemällu salvestamise meetodite katsetamiseks Linuxis.

Riistvara haarangud on igavad. Lülita sisse. See kas töötab või ei tööta. Ja mdadmiga on alati valikud.

Tarkvara

Varem oli riistvarale installitud Debian 8 Jessie, mis on EOL-i lähedal. RAID 6 pandi kokku ülalmainitud kõvaketastest, mis olid seotud LVM-iga. See käivitas virtuaalmasinaid kvm/libvirtis.

Sest Autoril on sobiv kogemus kaasaskantavate buutivate SATA/NVMe mälupulkade loomisel ning samuti, et tavapärast tabavat malli mitte murda, valiti sihtsüsteemiks Ubuntu 18.04, mis on küll juba piisavalt stabiliseeritud, kuid millel on veel 3 aastat kasutusaega. toetada tulevikus.

Mainitud süsteem sisaldab kõiki riistvaradraivereid, mida me karbist väljas vajame. Me ei vaja kolmanda osapoole tarkvara ega draivereid.

Ettevalmistus paigaldamiseks

Süsteemi installimiseks vajame Ubuntu Desktop Image. Serverisüsteemil on mingi jõuline installer, mis näitab liigset sõltumatust, mida ei saa keelata UEFI süsteemipartitsiooni ühele kettale toppimisega, rikkudes kogu ilu. Seetõttu installitakse see ainult UEFI-režiimis. Ei paku mingeid valikuid.

Me ei ole sellega rahul.

Miks?Kahjuks ühildub UEFI alglaadimine alglaadimistarkvaraga RAID äärmiselt halvasti, kuna... Keegi ei paku meile UEFI ESP partitsiooni broneeringuid. Internetis on retsepte, mis soovitavad paigutada ESP-partitsiooni USB-porti asuvale mälupulgale, kuid see on tõrkepunkt. On olemas retsepte, mis kasutavad tarkvara mdadm RAID 1 metaandmete versiooniga 0.9, mis ei takista UEFI BIOS-il seda partitsiooni nägemast, kuid see kestab õnneliku hetkeni, mil BIOS või mõni muu riistvaraline OS kirjutab midagi ESP-sse ja unustab selle muuga sünkroonida. peeglid.

Lisaks sõltub UEFI alglaadimine NVRAM-ist, mis ei liigu koos ketastega uude süsteemi, kuna on osa emaplaadist.

Niisiis, me ei leiuta uut ratast. Meil on juba valmis, ajaproovitud vanaisa jalgratas, nüüd nimega Legacy/BIOS boot, mis kannab UEFI-ga ühilduvates süsteemides uhket nime CSM. Võtame selle lihtsalt riiulilt maha, määrime, pumpame rehvid üles ja pühime niiske lapiga.

Ka Ubuntu töölauaversiooni ei saa Legacy bootloaderiga korralikult installida, kuid siin, nagu öeldakse, on vähemalt valikud.

Ja nii kogume riistvara ja laadime süsteemi Ubuntu Live'i käivitatavast välkmäluseadmest. Peame alla laadima paketid, nii et seadistame teie jaoks sobiva võrgu. Kui see ei tööta, saate vajalikud paketid eelnevalt mälupulgale laadida.

Me läheme töölauakeskkonda, käivitame terminali emulaatori ja asume:

#sudo bash

Kuidas…?Ülaltoodud rida on sudo holiwarsi kanooniline päästik. C bоtulevad suuremad võimalused jaоsuurem vastutus. Küsimus on selles, kas sa suudad seda enda peale võtta. Paljud inimesed arvavad, et sellisel viisil sudo kasutamine pole vähemalt ettevaatlik. Kuid:

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

Miks mitte ZFS...?Kui installime oma arvutisse tarkvara, laename oma riistvara sisuliselt selle tarkvara arendajatele, et seda juhtida.
Kui usaldame sellele tarkvarale oma andmete turvalisuse, võtame laenu, mis on võrdne nende andmete taastamise kuludega, mille peame kunagi ära tasuma.

Sellest vaatenurgast on ZFS Ferrari ja mdadm+lvm pigem jalgratas.

Subjektiivselt eelistab autor Ferrari asemel laenu laenuks tundmatutele isikutele jalgratast. Seal ei ole emissiooni hind kõrge. Õigusi pole vaja. Lihtsam kui liikluseeskirjad. Parkimine on tasuta. Murdmaavõimekus on parem. Jalgratta külge saab alati kinnitada ja jalgratast saab parandada oma kätega.

Miks siis BTRFS...?Operatsioonisüsteemi käivitamiseks vajame failisüsteemi, mida toetab Legacy/BIOS GRUB ja mis toetab samal ajal reaalajas hetktõmmiseid. Kasutame seda /boot partitsiooni jaoks. Lisaks eelistab autor seda FS-i kasutada / (juur) jaoks, unustamata märkida, et mis tahes muu tarkvara jaoks saate LVM-is luua eraldi partitsioonid ja ühendada need vajalikesse kataloogidesse.

Me ei salvesta selles FS-is ühtegi virtuaalmasina või andmebaasi kujutist.
Seda FS-i kasutatakse ainult süsteemi hetktõmmiste loomiseks ilma seda välja lülitamata ja nende hetktõmmiste edastamiseks varukettale, kasutades käsku Saada/vastuvõtt.

Lisaks eelistab autor üldiselt hoida minimaalselt tarkvara otse riistvaras ja käitada kogu muud tarkvara virtuaalmasinates, kasutades näiteks GPU-de ja PCI-USB-hostikontrollerite edastamist KVM-ile IOMMU kaudu.

Riistvarale jäävad ainult andmete salvestamine, virtualiseerimine ja varundamine.

Kui usaldate ZFS-i rohkem, on need määratud rakenduse jaoks põhimõtteliselt asendatavad.

Autor ignoreerib aga teadlikult ZFS-i, BRTFS-i ja LVM-i sisseehitatud peegeldamise/RAID-i ja koondamise funktsioone.

Täiendava argumendina on BTRFS-il võimalus muuta juhuslikud kirjutamised järjestikusteks, millel on äärmiselt positiivne mõju hetktõmmiste/varukoopiate sünkroonimise kiirusele HDD-l.

Skaneerime kõik seadmed uuesti:

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

Vaatame ringi:

#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

Ketta paigutus

NVMe SSD

Kuid me ei märgi neid mingil viisil. Samas meie BIOS neid draive ei näe. Seega lähevad nad täielikult tarkvara RAID-ile. Me ei loo seal isegi jaotisi. Kui soovite järgida "kaanonit" või "põhimõtteliselt", looge üks suur partitsioon, näiteks HDD.

SATA HDD

Siin pole vaja midagi erilist välja mõelda. Loome kõige jaoks ühe jaotise. Loome partitsiooni, kuna BIOS näeb neid kettaid ja võib isegi proovida neilt käivitada. Hiljem installime neile ketastele isegi GRUB-i, et süsteem saaks seda ootamatult teha.

#cat >hdd.part << EOF
label: dos
label-id: 0x00000000
device: /dev/sdg
unit: sectors

/dev/sdg1 : start= 2048, size= 1953523120, type=fd, bootable
EOF
#sfdisk /dev/sdg < hdd.part
#sfdisk /dev/sdh < hdd.part
#sfdisk /dev/sdi < hdd.part
#sfdisk /dev/sdj < hdd.part
#sfdisk /dev/sdk < hdd.part
#sfdisk /dev/sdl < hdd.part
#sfdisk /dev/sdm < hdd.part
#sfdisk /dev/sdn < hdd.part

SATA SSD

Siin lähevad asjad meie jaoks huvitavaks.

Esiteks on meie draivid 2 TB suurused. See jääb MBR-i jaoks vastuvõetavasse vahemikku, mida me kasutame. Vajadusel saab asendada GPT-ga. GPT-ketastel on ühilduvuskiht, mis võimaldab MBR-iga ühilduvatel süsteemidel näha 4 esimest partitsiooni, kui need asuvad kahe esimese terabaidi piires. Peaasi, et nende ketaste alglaadimise partitsioon ja bios_grub partitsioon oleksid alguses. See võimaldab teil isegi käivitada GPT Legacy/BIOS-draividelt.

Kuid see pole meie juhtum.

Siin loome kaks jaotist. Esimene neist on 1 GB suurune ja seda kasutatakse RAID 1 / alglaadimise jaoks.

Teist kasutatakse RAID 6 jaoks ja see võtab kogu ülejäänud vaba ruumi, välja arvatud väike jaotamata ala draivi lõpus.

Mis on see tähistamata ala?Võrguallikate kohaselt on meie SATA SSD-del dünaamiliselt laiendatav SLC-vahemälu, mille suurus on vahemikus 6–78 gigabaiti. Saame 6 gigabaiti “tasuta” tänu “gigabaitide” ja “gibibaitide” erinevusele draivi andmelehel. Ülejäänud 72 gigabaiti eraldatakse kasutamata ruumist.

Siinkohal tuleb märkida, et meil on SLC-vahemälu ja ruum on hõivatud 4-bitises MLC-režiimis. Mis meie jaoks tähendab sisuliselt seda, et iga 4 gigabaidi vaba ruumi kohta saame vaid 1 gigabaidi SLC vahemälu.

Korrutage 72 gigabaiti 4-ga ja saate 288 gigabaiti. See on vaba ruum, mida me välja ei märgi, et draivid saaksid SLC-vahemälu täielikult ära kasutada.

Seega saame kokku kuuelt kettalt tõhusalt kuni 312 gigabaiti SLC vahemälu. Kõigist draividest 2 kasutatakse RAIDis koondamiseks.

Selline vahemälu maht võimaldab meil päriselus väga harva kokku puutuda olukorraga, kus kirjutus ei lähe vahemällu. See kompenseerib ülihästi QLC-mälu kurvema puuduse – ülimadalat kirjutamiskiirust, kui andmeid kirjutatakse vahemälust mööda minnes. Kui teie koormused sellele ei vasta, siis soovitan põhjalikult läbi mõelda, kui kaua teie SSD sellise koormuse all vastu peab, võttes arvesse andmelehe TBW-d.

#cat >ssd.part << EOF
label: dos
label-id: 0x00000000
device: /dev/sda
unit: sectors

/dev/sda1 : start= 2048, size= 2097152, type=fd, bootable
/dev/sda2 : start= 2099200, size= 3300950016, type=fd
EOF
#sfdisk /dev/sda < ssd.part
#sfdisk /dev/sdb < ssd.part
#sfdisk /dev/sdc < ssd.part
#sfdisk /dev/sdd < ssd.part
#sfdisk /dev/sde < ssd.part
#sfdisk /dev/sdf < ssd.part

Massiivide loomine

Esiteks peame masina ümber nimetama. See on vajalik, kuna hostinimi on osa massiivinimest kuskil mdadm-is ja mõjutab kuskil midagi. Muidugi saab massiive hiljem ümber nimetada, kuid see on tarbetu samm.

#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 -oletame-puhas...?Massiivide initsialiseerimise vältimiseks. See kehtib nii RAIDi 1. kui ka 6. taseme puhul. Kõik võib töötada ilma initsialiseerimiseta, kui tegemist on uue massiiviga. Pealegi on SSD massiivi lähtestamine loomisel TBW ressursi raiskamine. Võimaluse korral kasutame kokkupandud SSD massiividel nende "initsialiseerimiseks" TRIM/DISCARD.

SSD-massiivide puhul toetatakse RAID 1 DISCARD juba karbist välja.

SSD RAID 6 DISCARD massiivide puhul peate selle tuumamooduli parameetrites lubama.

Seda tuleks teha ainult siis, kui kõik selle süsteemi 4/5/6 massiivides kasutatavad SSD-d toetavad funktsiooni discard_zeroes_data. Mõnikord puutute kokku kummaliste draividega, mis ütlevad kernelile, et see funktsioon on toetatud, kuid tegelikult seda seal pole või funktsioon ei tööta alati. Praegu on tugi saadaval peaaegu kõikjal, kuid seal on vanu draive ja vigadega püsivara. Sel põhjusel on RAID 6 puhul DISCARDi tugi vaikimisi keelatud.

Tähelepanu, järgmine käsk hävitab kõik NVMe-draividel olevad andmed, "initsialiseerides" massiivi "nullidega".

#blkdiscard /dev/md0

Kui midagi läheb valesti, proovige määrata samm.

#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...?Tüki suuruse suurendamine avaldab positiivset mõju juhusliku lugemise kiirusele plokkides kuni tükkide suuruseni (kaasa arvatud). See juhtub seetõttu, et ühe sobiva suurusega või väiksema toimingu saab teha täielikult ühes seadmes. Seetõttu võetakse kõigi seadmete IOPS-id kokku. Statistika järgi ei ületa 99% IO-st 512K.

RAID-il on 6 IOPS-i kirjutamise kohta alati väiksem või võrdne ühe draivi IOPS-iga. Kui juhusliku lugemisena võib IOPS olla mitu korda suurem kui ühe draivi oma, ja siin on ploki suurus võtmetähtsusega.
Autor ei näe mõtet püüda optimeerida RAID 6 kõrvaldisaini puhul halba parameetrit ja selle asemel optimeerib seda, milles RAID 6 hea on.
Kompenseerime RAID 6 kehva juhusliku kirjutamise NVMe vahemälu ja õhukeste vahenditega.

Me pole veel RAID 6 jaoks funktsiooni DISCARD lubanud. Seega me praegu seda massiivi ei "initsialiseeri". Teeme seda hiljem, pärast OS-i 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-is

Kiiruse huvides tahame juurfailisüsteemi paigutada NVMe RAID 1-le, mis on /dev/md0.
Seda kiiret massiivi vajame siiski muudeks vajadusteks, nagu vahetus, metaandmed ja LVM-vahemälu ja LVM-õhukesed metaandmed, seega loome sellele massiivile LVM VG.

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

Loome juurfailisüsteemi partitsiooni.

#lvcreate -L 128G --name root root

Loome vahetamiseks partitsiooni vastavalt RAM-i suurusele.

#lvcreate -L 32G --name swap root

OS-i installimine

Kokku on meil olemas kõik vajalik süsteemi paigaldamiseks.

Käivitage süsteemi installiviisard Ubuntu Live'i keskkonnast. Tavaline paigaldus. Ainult installimiseks ketaste valimise etapis peate määrama järgmise:

  • /dev/md1, - ühenduspunkt /boot, FS - BTRFS
  • /dev/root/root (teise nimega /dev/mapper/root-root), - ühenduspunkt / (juur), FS - BTRFS
  • /dev/root/swap (teise nimega /dev/mapper/root-swap), - kasutage vahetuspartitsioonina
  • Installige alglaadur kausta /dev/sda

Kui valite juurfailisüsteemiks BTRFS-i, loob installer automaatselt kaks BTRFS-i köidet nimega "@" jaoks / (juur) ja "@home" /home jaoks.

Alustame installimist...

Installimine lõpeb modaalse dialoogiboksiga, mis näitab alglaaduri installimisel tekkinud viga. Kahjuks ei saa te sellest dialoogist tavaliste vahenditega väljuda ja installimist jätkata. Logime süsteemist välja ja uuesti sisse, lõpetades puhta Ubuntu Live'i töölauaga. Avage terminal ja uuesti:

#sudo bash

Installimise jätkamiseks looge chroot-keskkond:

#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

Seadistame võrgu ja hostinime chrootis:

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

Läheme chroot-keskkonda:

#chroot /mnt/chroot

Esiteks viime pakid kohale:

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

Kontrollime ja parandame kõiki pakette, mis olid süsteemi mittetäieliku installimise tõttu valesti installitud:

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

Kui midagi ei õnnestu, peate võib-olla esmalt muutma faili /etc/apt/sources.list

Kohandagem RAID 6 mooduli parameetreid, et lubada TRIM/DISCARD:

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

Kohandagem oma massiive veidi:

#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 udev-reeglite komplekti, mis teeb järgmist:

  • Määrake RAID 2020 ploki vahemälu suurus 6. aastaks piisavaks. Tundub, et vaikeväärtus pole Linuxi loomisest saadik muutunud ja pole pikka aega olnud piisav.
  • Broneerige massiivi kontrollimise/sünkroonimise ajaks minimaalne IO. Seda tehakse selleks, et teie massiivid ei jääks koormuse all igavese sünkroonimise olekusse kinni.
  • Piirake maksimaalset IO-d massiivide kontrollimise/sünkroonimise ajal. See on vajalik selleks, et SSD RAID-ide sünkroonimine/kontrollimine teie kettaid krõbedaks ei praeks. See kehtib eriti NVMe kohta. (Kas mäletate radiaatorit? Ma ei teinud nalja.)
  • Keelake ketastel spindli pöörlemise (HDD) peatamine APM-i kaudu ja määrake kettakontrollerite une ajalõpuks 7 tundi. Saate APM-i täielikult keelata, kui teie draivid seda suudavad (-B 255). Vaikeväärtuse korral peatuvad ajamid viie sekundi pärast. Seejärel soovib OS lähtestada ketta vahemälu, kettad lähevad uuesti üles ja kõik algab otsast peale. Ketastel on piiratud maksimaalne spindli pöörete arv. Selline lihtne vaiketsükkel võib teie kettad paari aastaga kergesti tappa. Kõik kettad selle all ei kannata, kuid meie omad on “sülearvutid”, vastavate vaikeseadetega, mis muudavad RAID-i mini-MAID-i sarnaseks.
  • Installige ettelugemine ketastele (pöörlevad) 1 megabait – kaks järjestikust plokki/tükk RAID 6
  • Keela ettelugemine massiividel endil.

Redigeerime faili /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

Miks nii..?Otsime /boot partitsiooni UUID abil. Massiivide nimetamine võib teoreetiliselt muutuda.

Ülejäänud jaotisi otsime LVM-i nimede järgi /dev/mapper/vg-lv tähistuses, sest nad tuvastavad partitsioonid üsna ainulaadselt.

Me ei kasuta LVM-i jaoks UUID-d, kuna LVM-i köidete UUID ja nende hetktõmmised võivad olla samad.Kas ühendada /dev/mapper/root-root.. kaks korda?Jah. Täpselt nii. BTRFS-i funktsioon. Seda failisüsteemi saab erinevate alamvoldidega mitu korda ühendada.

Selle sama funktsiooni tõttu ei soovita ma mitte kunagi luua LVM-i hetktõmmiseid aktiivsetest BTRFS-i mahtudest. Taaskäivitamisel võite saada üllatuse.

Regenereerime mdadm konfiguratsiooni:

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

Reguleerime LVM-i sätteid:

#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 võimaldanud LVM õhukeste basseinide automaatset laiendamist, kui saavutatakse 90% hõivatud pinnast 5% mahust.

Oleme suurendanud LVM-i vahemälu maksimaalset vahemäluplokkide arvu.

Oleme takistanud LVM-il LVM-i mahtude (PV) otsimist:

  • LVM-i vahemälu sisaldavad seadmed (cdata)
  • seadmed vahemällu kasutades LVM-i vahemälu, vahemälust mööda minnes ( _corig). Sel juhul skannitakse vahemälu vahemälu kaudu (lihtsalt ).
  • seadmed, mis sisaldavad LVM-i vahemälu metaandmeid (cmeta)
  • kõik seadmed VG-s koos nimekujutistega. Siin on virtuaalmasinate kettakujutised ja me ei soovi, et hostis olev LVM aktiveeriks külalis-OS-ile kuuluvaid köiteid.
  • kõik VG-s olevad seadmed nimega backup. Siin on virtuaalmasina piltide varukoopiad.
  • kõik seadmed, mille nimi lõpeb tähega „gpv” (külalise füüsiline helitugevus)

Oleme LVM VG-s vaba ruumi vabastamisel lubanud DISCARDi toe. Ole ettevaatlik. See muudab LV-de kustutamise SSD-lt üsna aeganõudvaks. Eriti puudutab see SSD RAID 6. Plaani kohaselt kasutame aga õhukest provisjoni, nii et see meid üldse ei takista.

Värskendame initramfsi pilti:

#update-initramfs -u -k all

Installige ja konfigureerige grub:

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

Milliseid kettaid valida?Kõik, kes on sd*. Süsteem peab suutma käivitada mis tahes töötavalt SATA-draivilt või SSD-lt.

Miks nad lisasid os-proberi..?Liigse iseseisvuse ja mänguliste käte eest.

See ei tööta korralikult, kui üks RAID-idest on halvenenud olekus. See proovib otsida OS-i partitsioonidelt, mida kasutatakse selles riistvaras töötavates virtuaalsetes masinates.

Kui teil on seda vaja, võite selle jätta, kuid pidage meeles kõike ülaltoodut. Soovitan otsida internetist retsepte, kuidas ulakatest kätest lahti saada.

Sellega oleme esialgse paigalduse lõpetanud. On aeg taaskäivitada äsja installitud OS-i. Ärge unustage eemaldada buutivat Live CD/USB-d.

#exit
#reboot

Valige alglaadimisseadmeks mõni SATA SSD.

LVM SATA SSD-l

Sel hetkel oleme juba uude OS-i käivitanud, võrgu konfigureerinud, apt, avanud terminali emulaatori ja käivitanud:

#sudo bash

Jätkame.

"Initsialiseerige" massiiv SATA SSD-lt:

#blkdiscard /dev/md2

Kui see ei tööta, proovige:

#blkdiscard --step 65536 /dev/md2
Looge SATA SSD-l LVM VG:

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

Miks veel VG..?Tegelikult on meil juba VG nimega root. Miks mitte lisada kõike ühte VG-sse?

Kui VG-s on mitu PV-d, peavad VG korrektseks aktiveerimiseks kõik PV-d olemas olema (online). Erandiks on LVM RAID, mida me teadlikult ei kasuta.

Me tõesti tahame, et kui mõnes RAID 6 massiivis ilmneb tõrge (lugemisandmete kadu), käivitub operatsioonisüsteem normaalselt ja annaks meile võimaluse probleem lahendada.

Selleks eraldame abstraktsiooni esimesel tasemel iga tüüpi füüsilised "meediumid" eraldi VG-ks.

Teaduslikult öeldes kuuluvad erinevad RAID-massiivid erinevatesse "usaldusväärsuse domeenidesse". Te ei tohiks luua neile täiendavat ühist tõrkepunkti, koondades need ühte VG-sse.

LVM-i olemasolu "riistvara" tasemel võimaldab meil meelevaldselt lõigata erinevate RAID-massiivide tükke, kombineerides neid erineval viisil. Näiteks - jookse samaaegselt bcache + LVM thin, bcache + BTRFS, LVM cache + LVM thin, keeruline ZFS-i konfiguratsioon vahemäludega või mõni muu põrgulik segu, et seda kõike võrrelda.

“Riistvara” tasemel ei kasuta me midagi muud peale vanade heade “paksude” LVM-köidete. Selle reegli erand võib olla varupartitsioon.

Arvan, et selleks hetkeks olid paljud lugejad juba hakanud pesitseva nuku kohta midagi kahtlustama.

LVM SATA HDD-l

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

Jälle uus VG..?Tahame väga, et kui andmete varundamiseks kasutatav kettamassiivi ebaõnnestub, jätkaks meie operatsioonisüsteem normaalset tööd, säilitades samal ajal tavapärase juurdepääsu mittevarundusandmetele. Seetõttu loome VG aktiveerimisprobleemide vältimiseks eraldi VG.

LVM-i vahemälu seadistamine

Loome NVMe RAID 1-s LV, et seda vahemäluseadmena kasutada.

#lvcreate -L 70871154688B --name cache root

Miks on nii vähe...?Fakt on see, et meie NVMe SSD-del on ka SLC-vahemälu. 4 gigabaiti "tasuta" ja 18 gigabaiti dünaamilist tänu 3-bitises MLC-s hõivatud vabale ruumile. Kui vahemälu on ammendatud, ei ole NVMe SSD-d palju kiiremad kui meie vahemäluga SATA SSD. Tegelikult pole sel põhjusel meil mõtet muuta LVM-i vahemälu partitsioon palju suuremaks kui kaks korda suurem kui NVMe-draivi SLC-vahemälu. Kasutatavate NVMe-draivide puhul peab autor mõistlikuks teha 32-64 gigabaiti vahemälu.

Antud partitsiooni suurus on vajalik 64 gigabaidise vahemälu, vahemälu metaandmete ja metaandmete varundamise korraldamiseks.

Lisaks märgin, et pärast süsteemi määrdunud väljalülitamist märgib LVM kogu vahemälu määrdunud ja sünkroonib uuesti. Lisaks korratakse seda iga kord, kui selles seadmes kasutatakse lvchange'i, kuni süsteem uuesti taaskäivitatakse. Seetõttu soovitan kohe vahemälu vastava skripti abil uuesti luua.

Loome SATA RAID 6-le LV, et kasutada seda vahemällu salvestatud seadmena.

#lvcreate -L 3298543271936B --name cache data

Miks ainult kolm terabaiti..?Et vajadusel saaks SATA SSD RAID 6 kasutada mõneks muuks vajaduseks. Vahemällu salvestatud ruumi suurust saab suurendada dünaamiliselt, käigult, ilma süsteemi peatamata. Selleks tuleb vahemälu ajutiselt peatada ja uuesti lubada, kuid LVM-vahemälu eristav eelis näiteks bcache ees on see, et seda saab teha käigu pealt.

Loome vahemällu salvestamiseks uue VG.

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

Loome vahemällu salvestatud seadmes LV.

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

Siin võtsime kohe kogu vaba ruumi /dev/data/cache, nii et kõik muud vajalikud partitsioonid loodi kohe /dev/root/cache. Kui lõite midagi vales kohas, saate selle pvmove abil teisaldada.

Loome ja lubame 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 sellised tükid..?Autoril õnnestus praktiliste katsete abil välja selgitada, et parim tulemus saavutatakse siis, kui LVM vahemälu ploki suurus langeb kokku LVM õhukese ploki suurusega. Veelgi enam, mida väiksem on suurus, seda paremini toimib konfiguratsioon juhuslikul salvestamisel.

64 k on minimaalne lubatud ploki suurus LVM thin jaoks.

Ettevaatust kirjutamisega..!Jah. Seda tüüpi vahemälu lükkab vahemällu salvestatud seadmesse kirjutamise sünkroonimise edasi. See tähendab, et kui vahemälu kaob, võite kaotada vahemällu salvestatud seadmes olevad andmed. Hiljem räägib autor teile, milliseid meetmeid saab lisaks NVMe RAID 1-le võtta selle riski kompenseerimiseks.

See vahemälu tüüp valiti tahtlikult, et kompenseerida RAID 6 halba juhuslikku kirjutamist.

Vaatame, mis meil on:

#lvs -a -o lv_name,lv_size,devices --units B cache
LV LSize Devices
[cache] 68719476736B cache_cdata(0)
[cache_cdata] 68719476736B /dev/root/cache(0)
[cache_cmeta] 1073741824B /dev/root/cache(16384)
cachedata 3298539077632B cachedata_corig(0)
[cachedata_corig] 3298539077632B /dev/data/cache(0)
[lvol0_pmspare] 1073741824B /dev/root/cache(16640)

Ainult [cachedata_corig] peaks asuma kaustas /dev/data/cache. Kui midagi on valesti, kasutage pvmove'i.

Vajadusel saate vahemälu keelata ühe käsuga:

#lvconvert -y --uncache cache/cachedata

Seda tehakse võrgus. LVM sünkroonib lihtsalt vahemälu kettaga, eemaldab selle ja nimetab cachedata_corig uuesti cachedata-ks.

LVM õhukese seadistamine

Hinnake ligikaudselt, kui palju ruumi vajame LVM-i õhukeste metaandmete jaoks:

#thin_metadata_size --block-size=64k --pool-size=6terabytes --max-thins=100000 -u bytes
thin_metadata_size - 3385794560 bytes estimated metadata area size for "--block-size=64kibibytes --pool-size=6terabytes --max-thins=100000"

Ümarda kuni 4 gigabaiti: 4294967296B

Korrutage kahega ja lisage LVM PV metaandmete jaoks 4194304B: 8594128896B
Loome NVMe RAID 1-le eraldi partitsiooni, et asetada sellele õhukesed LVM-i metaandmed ja nende varukoopia:

#lvcreate -L 8594128896B --name images root

Milleks..?Siin võib tekkida küsimus: miks asetada LVM-i õhukesed metaandmed eraldi, kui need jäävad endiselt NVMe-sse vahemällu ja töötavad kiiresti.

Kuigi kiirus on siin oluline, pole see kaugeltki peamine põhjus. Asi on selles, et vahemälu on tõrkepunkt. Sellega võib midagi juhtuda ja kui LVM-i õhukesed metaandmed vahemällu salvestatakse, kaob kõik täielikult. Ilma täielike metaandmeteta on õhukesi köiteid peaaegu võimatu kokku panna.

Teisaldades metaandmed eraldi vahemäluta, kuid kiiresse köitesse, garanteerime metaandmete ohutuse vahemälu kaotsimineku või riknemise korral. Sel juhul lokaliseeritakse kõik vahemälu kadumisest põhjustatud kahjustused õhukestes köites, mis lihtsustab taastamisprotseduuri suurusjärgu võrra. Suure tõenäosusega taastatakse need kahjustused FS-i logide abil.

Veelgi enam, kui eelnevalt tehti õhukesest mahust hetktõmmis ja pärast seda sünkrooniti vahemälu vähemalt üks kord täielikult, siis on LVM thin sisekujunduse tõttu vahemälu kadumise korral hetketõmmise terviklikkus tagatud. .

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 tegelikult mõeldud on – vältimaks ruumi ümberjagamisel ühest virtuaalmasinast andmete lekkimist teise virtuaalmasinasse – kasutatakse lisaks nullimist, et suurendada juhusliku kirjutamise kiirust väiksemates kui 64k plokkides. Kõik, mis kirjutatakse alla 64 64 õhukese helitugevuse varem eraldamata alale, joondatakse vahemälus XNUMX XNUMX servaga. See võimaldab toimingut teha täielikult vahemälu kaudu, jättes vahele vahemällu salvestatud seadme.

Liigutame LV-d vastavatesse PV-desse:

#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 Devices
[lvol0_pmspare] 4294967296B /dev/root/images(0)
thin-pool 274877906944B thin-pool_tdata(0)
[thin-pool_tdata] 274877906944B /dev/cache/cachedata(0)
[thin-pool_tmeta] 4294967296B /dev/root/images(1024)

Loome testide jaoks õhukese mahu:

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

Paigaldame testimiseks ja jälgimiseks paketid:

#apt-get install sysstat fio

Nii saate jälgida meie salvestuskonfiguratsiooni 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 saame oma konfiguratsiooni testida:

#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

Hoolikalt! Ressurss!See kood käivitab 36 erinevat testi, millest igaüks töötab 4 sekundit. Pooled testid on salvestamiseks. NVMe-s saate 4 sekundiga palju salvestada. Kuni 3 gigabaiti sekundis. Seega võib iga kirjutustestide jooks sinult ära süüa kuni 216 gigabaiti SSD ressurssi.

Kas lugemine ja kirjutamine on segamini?Jah. Lugemis- ja kirjutamistestid on mõttekas läbi viia eraldi. Lisaks on mõistlik tagada, et kõik vahemälud oleksid sünkroonitud, nii et varem tehtud kirjutamine ei mõjuta lugemist.

Tulemused varieeruvad esmakordsel käivitamisel ja järgnevatel vahemälu ja õhuke helitugevuse täitumisel suuresti, samuti olenevalt sellest, kas süsteemil õnnestus viimase käivitamise ajal täidetud vahemälud sünkroonida.

Muuhulgas soovitan mõõta kiirust juba täitsa õhukesel helitugevusel, millest just hetktõmmis tehti. Autoril oli võimalus jälgida, kuidas juhuslikud kirjutamised järsult kiirenevad kohe pärast esimese hetktõmmise tegemist, eriti kui vahemälu pole veel täielikult täis. See juhtub kirjutamise kopeerimisel kirjutamise semantika, vahemälu joondamise ja õhukeste mahuplokkide tõttu ning asjaolu, et juhuslik RAID 6 kirjutamine muutub juhuslikuks lugemiseks RAID 6-st, millele järgneb vahemällu kirjutamine. Meie konfiguratsioonis on RAID 6 juhuslik lugemine kuni 6 korda kiirem (SATA SSD-de arv massiivis) kui kirjutamine. Sest CoW-i plokid eraldatakse õhukesest kogumist järjestikku, seejärel muutub salvestamine enamasti ka järjestikuseks.

Mõlemat funktsiooni saab kasutada oma eeliseks.

Vahemällu "sidusad" hetktõmmised

Andmete kadumise ohu vähendamiseks vahemälu kahjustamise/kao korral teeb autor ettepaneku võtta kasutusele hetktõmmiste pööramise praktika, et tagada antud juhul nende terviklikkus.

Esiteks, kuna õhukesed metaandmed asuvad vahemällu salvestamata seadmes, on metaandmed järjepidevad ja võimalikud kaod eraldatakse andmeplokkides.

Järgmine hetktõmmiste pööramise tsükkel tagab vahemälu kadumise korral hetktõmmistes olevate andmete terviklikkuse:

  1. Iga õhukese köite jaoks, mille nimi on <nimi>, looge hetktõmmis nimega <nimi>.cached
  2. Seadke migratsioonilävi mõistlikult kõrgele väärtusele: #lvchange --quiet --cachesettings "migration_threshold=16384" cache/cachedata
  3. Silmuses kontrollime vahemälus olevate määrdunud plokkide arvu: #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' kuni saame nulli. Kui null on liiga kaua puudu, saab selle luua, lülitades vahemälu ajutiselt kirjutusrežiimile. Kuid võttes arvesse meie SATA ja NVMe SSD massiivide kiirusomadusi ning nende TBW ressurssi, saate kas kiiresti hetke tabada ilma vahemälurežiimi muutmata või sööb teie riistvara täielikult ära kogu oma ressursi. mõned päevad. Ressursipiirangute tõttu ei suuda süsteem põhimõtteliselt olla kogu aeg alla 100% kirjutuskoormuse. Meie 100% kirjutuskoormusega NVMe SSD-d ammendavad ressursi täielikult 3-4 päeva. SATA SSD-d peavad vastu vaid kaks korda kauem. Seetõttu eeldame, et suurem osa koormusest läheb lugemisele ja meil on suhteliselt lühiajalised ülikõrge aktiivsuse puhangud koos keskmise kirjutamiskoormusega.
  4. Niipea, kui saime nulli (või tegime), nimetame <name>.cached ümber nimeks <nimi>.committed. Vana <nimi>.committed kustutatakse.
  5. Valikuliselt, kui vahemälu on 100% täis, saab selle skripti abil uuesti luua, tühjendades selle. Pooltühja vahemälu puhul töötab süsteem kirjutamisel palju kiiremini.
  6. Määrake migratsioonilävi nulliks: #lvchange --quiet --cachesettings "migration_threshold=0" cache/cachedata See takistab ajutiselt vahemälu sünkroonimist põhimeediumiga.
  7. Ootame, kuni vahemällu koguneb päris palju muudatusi #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' või taimer kustub.
  8. Kordame uuesti.

Miks raskused migratsioonilävega...?Asi on selles, et tegelikus praktikas pole "juhuslik" salvestus tegelikult täiesti juhuslik. Kui kirjutaksime midagi 4 kilobaidisesse sektorisse, siis on suur tõenäosus, et järgmise paari minuti jooksul tehakse rekord samasse või mõnda naabersektorisse (+- 32K).

Seades migratsiooniläveks nulli, lükkame SATA SSD-l kirjutamise sünkroonimise edasi ja koondame mitu muudatust ühele 64K plokile vahemälus. See säästab oluliselt SATA SSD ressurssi.

Kus on kood..?Kahjuks peab autor end bash-skriptide arendamisel ebapiisavalt pädevaks, kuna on 100% iseõppija ja praktiseerib “google” juhitavat arendust, mistõttu leiab ta, et tema käest välja tulnud kohutavat koodi ei tohiks keegi kasutada. muidu.

Arvan, et selle valdkonna spetsialistid suudavad vajadusel iseseisvalt kujutada kogu ülalkirjeldatud loogikat ja võib-olla isegi kaunilt kujundada selle süsteemse teenusena, nagu autor püüdis teha.

Selline lihtne hetktõmmise pööramise skeem võimaldab meil mitte ainult pidevalt üht hetktõmmist SATA SSD-l täielikult sünkroonida, vaid võimaldab ka utiliidi thin_delta abil teada saada, milliseid plokke pärast selle loomist muudeti, ja seega lokaliseerida kahjustused peamised mahud, lihtsustades oluliselt taastamist.

TRIM/DISCARD libvirt/KVM-is

Sest andmesalvestust kasutatakse libvirti jooksutava KVM jaoks, siis oleks hea mõte õpetada meie VM-e mitte ainult vaba ruumi hõivama, vaid ka vabastama seda, mida enam ei vajata.

Seda tehakse virtuaalsetel ketastel emuleerides TRIM/DISCARD tuge. Selleks peate muutma kontrolleri tüübiks virtio-scsi ja muutma xml-i.

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

<controller type='scsi' index='0' model='virtio-scsi'>
<alias name='scsi0'/>
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</controller>

Selliseid külalis-OS-ide DISCARDe töötleb LVM õigesti ja plokid vabastatakse õigesti nii vahemälus kui ka õhukeses kogumis. Meie puhul juhtub see peamiselt viivitusega, järgmise hetktõmmise kustutamisel.

BTRFS-i varukoopia

Kasutage valmis skripte koos äärmuslik ettevaatust ja omal vastutusel. Autor kirjutas selle koodi ise ja ainult enda jaoks. Olen kindel, et paljudel kogenud Linuxi kasutajatel on sarnased tööriistad ja kellegi teise tööriistu pole vaja kopeerida.

Loome varundusseadmes helitugevuse:

#lvcreate -L 256G --name backup backup

Vormindame selle BTRFS-is:

#mkfs.btrfs /dev/backup/backup

Loome ühenduspunktid ja ühendame failisüsteemi juuralajaotised:

#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 varukoopiate jaoks kataloogid:

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

Loome varuskriptide jaoks kataloogi:

#mkdir /root/btrfs-backup

Kopeerime skripti:

Palju hirmutavat bash-koodi. Kasutage omal vastutusel. Ärge kirjutage autorile vihaseid 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 "Wating for lock..."
wait_lock || terminate "Failed to get lock. Exiting..."
echo "Got lock..."
}

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

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

function backup()
{
SOURCE_PATH="$MOUNTS$1"
TARGET_PATH="$BACKUPS$1"
SOURCE_BASE_PATH="$MOUNTS$1$BASE_SUFFIX"
TARGET_BASE_PATH="$BACKUPS$1$BASE_SUFFIX"
TARGET_BASE_DIR="$(dirname $TARGET_BASE_PATH)"
SOURCE_PEND_PATH="$MOUNTS$1$PEND_SUFFIX"
TARGET_PEND_PATH="$BACKUPS$1$PEND_SUFFIX"
if [ -d "$SOURCE_BASE_PATH" ] then
echo "$SOURCE_BASE_PATH found"
else
echo "$SOURCE_BASE_PATH File not found creating snapshot of $SOURCE_PATH to $SOURCE_BASE_PATH"
btrfs subvolume snapshot -r $SOURCE_PATH $SOURCE_BASE_PATH
sync
if [ -d "$TARGET_BASE_PATH" ] then
echo "$TARGET_BASE_PATH found out of sync with source... removing..."
btrfs subvolume delete -c $TARGET_BASE_PATH
sync
fi
fi
if [ -d "$TARGET_BASE_PATH" ] then
echo "$TARGET_BASE_PATH found"
else
echo "$TARGET_BASE_PATH not found. Synching to $TARGET_BASE_DIR"
btrfs send $SOURCE_BASE_PATH | btrfs receive $TARGET_BASE_DIR
sync
fi
if [ -d "$SOURCE_PEND_PATH" ] then
echo "$SOURCE_PEND_PATH found removing..."
btrfs subvolume delete -c $SOURCE_PEND_PATH
sync
fi
btrfs subvolume snapshot -r $SOURCE_PATH $SOURCE_PEND_PATH
sync
if [ -d "$TARGET_PEND_PATH" ] then
echo "$TARGET_PEND_PATH found removing..."
btrfs subvolume delete -c $TARGET_PEND_PATH
sync
fi
echo "Sending $SOURCE_PEND_PATH to $TARGET_PEND_PATH"
btrfs send -p $SOURCE_BASE_PATH $SOURCE_PEND_PATH | btrfs receive $TARGET_BASE_DIR
sync
TARGET_DATE_SUFFIX=$(suffix)
btrfs subvolume snapshot -r $TARGET_PEND_PATH "$TARGET_PATH$TARGET_DATE_SUFFIX"
sync
btrfs subvolume delete -c $SOURCE_BASE_PATH
sync
btrfs subvolume delete -c $TARGET_BASE_PATH
sync
mv $SOURCE_PEND_PATH $SOURCE_BASE_PATH
mv $TARGET_PEND_PATH $TARGET_BASE_PATH
sync
}

function list()
{
LIST_TARGET_BASE_PATH="$BACKUPS$1$BASE_SUFFIX"
LIST_TARGET_BASE_DIR="$(dirname $LIST_TARGET_BASE_PATH)"
LIST_TARGET_BASE_NAME="$(basename -s .$BASE_SUFFIX $LIST_TARGET_BASE_PATH)"
find "$LIST_TARGET_BASE_DIR" -maxdepth 1 -mindepth 1 -type d -printf "%fn" | grep "${LIST_TARGET_BASE_NAME/$BASE_SUFFIX/$SNAP_SUFFIX}.$DATE_REGEX"
}

function remove()
{
REMOVE_TARGET_BASE_PATH="$BACKUPS$1$BASE_SUFFIX"
REMOVE_TARGET_BASE_DIR="$(dirname $REMOVE_TARGET_BASE_PATH)"
btrfs subvolume delete -c $REMOVE_TARGET_BASE_DIR/$2
sync
}

function removeall()
{
DATE_OFFSET="$2"
FILTER="$(filter "$DATE_OFFSET")"
while read -r SNAPSHOT ; do
remove "$1" "$SNAPSHOT"
done < <(list "$1" | grep "$FILTER")

}

(
COMMAND="$1"
shift

case "$COMMAND" in
"--help")
echo "Help"
;;
"suffix")
suffix
;;
"filter")
filter "$1"
;;
"backup")
wait_lock_or_terminate
backup "$1"
;;
"list")
list "$1"
;;
"remove")
wait_lock_or_terminate
remove "$1" "$2"
;;
"removeall")
wait_lock_or_terminate
removeall "$1" "$2"
;;
*)
echo "None.."
;;
esac
) 98>$LOCK_FILE

EOF

Mida see üldse teeb..?Sisaldab lihtsate käskude komplekti BTRFS-i hetktõmmiste loomiseks ja nende kopeerimiseks teise FS-i kasutades BTRFS-i saatmist/vastuvõtmist.

Esimene käivitamine võib olla suhteliselt pikk, sest... Alguses kopeeritakse kõik andmed. Edasised käivitamised on väga kiired, sest... Kopeeritakse ainult muudatused.

Teine skript, mille paneme cronisse:

Veel 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 day"
$BACKUP_SCRIPT backup root/@
$BACKUP_SCRIPT removeall root/@ "$RETENTION"
$BACKUP_SCRIPT backup root/@home
$BACKUP_SCRIPT removeall root/@home "$RETENTION"
$BACKUP_SCRIPT backup boot/
$BACKUP_SCRIPT removeall boot/ "$RETENTION"
EOF

Mida see teeb..?Loob ja sünkroonib varukoopia FS-is loetletud BTRFS-i köidete järkjärgulisi hetktõmmiseid. Pärast seda kustutab see kõik 60 päeva tagasi loodud pildid. Pärast käivitamist ilmuvad alamkataloogides /backup/btrfs/back/remote/ loetletud köidete dateeritud hetktõmmised.

Anname koodi täitmise õigused:

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

Kontrollime seda ja paneme selle kroni:

#/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 õhuke varukoopia

Loome varuseadmesse õhukese kogumi:

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

Installime ddrescue, sest... skriptid kasutavad seda tööriista:

#apt-get install gddrescue

Loome skriptide jaoks kataloogi:

#mkdir /root/lvm-thin-backup

Kopeerime skriptid:

Palju jama 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 "Wating for lock..."
wait_lock || terminate "Failed to get lock. Exiting..."
echo "Got lock..."
}

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

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

function read_thin_id {
lvs --rows --reportformat basic --quiet -othin_id "$1/$2" | awk '{print $2}'
}

function read_pool_lv {
lvs --rows --reportformat basic --quiet -opool_lv "$1/$2" | awk '{print $2}'
}

function read_lv_dm_path {
lvs --rows --reportformat basic --quiet -olv_dm_path "$1/$2" | awk '{print $2}'
}

function read_lv_active {
lvs --rows --reportformat basic --quiet -olv_active "$1/$2" | awk '{print $2}'
}

function read_lv_chunk_size {
lvs --rows --reportformat basic --quiet --units b --nosuffix -ochunk_size "$1/$2" | awk '{print $2}'
}

function read_lv_size {
lvs --rows --reportformat basic --quiet --units b --nosuffix -olv_size "$1/$2" | awk '{print $2}'
}

function activate_volume {
lvchange -ay -Ky "$1/$2"
}

function deactivate_volume {
lvchange -an "$1/$2"
}

function read_thin_metadata_snap {
dmsetup status "$1" | awk '{print $7}'
}

function thindiff()
{
DIFF_VG="$1"
DIFF_SOURCE="$2"
DIFF_TARGET="$3"
DIFF_SOURCE_POOL=$(read_pool_lv $DIFF_VG $DIFF_SOURCE)
DIFF_TARGET_POOL=$(read_pool_lv $DIFF_VG $DIFF_TARGET)

if [ "$DIFF_SOURCE_POOL" == "" ] then
(>&2 echo "Source LV is not thin.")
exit 1
fi

if [ "$DIFF_TARGET_POOL" == "" ] then
(>&2 echo "Target LV is not thin.")
exit 1
fi

if [ "$DIFF_SOURCE_POOL" != "$DIFF_TARGET_POOL" ] then
(>&2 echo "Source and target LVs belong to different thin pools.")
exit 1
fi

DIFF_POOL_PATH=$(read_lv_dm_path $DIFF_VG $DIFF_SOURCE_POOL)
DIFF_SOURCE_ID=$(read_thin_id $DIFF_VG $DIFF_SOURCE)
DIFF_TARGET_ID=$(read_thin_id $DIFF_VG $DIFF_TARGET)
DIFF_POOL_PATH_TPOOL="$DIFF_POOL_PATH-tpool"
DIFF_POOL_PATH_TMETA="$DIFF_POOL_PATH"_tmeta
DIFF_POOL_METADATA_SNAP=$(read_thin_metadata_snap $DIFF_POOL_PATH_TPOOL)

if [ "$DIFF_POOL_METADATA_SNAP" != "-" ] then
(>&2 echo "Thin pool metadata snapshot already exist. Assuming stale one. Will release metadata snapshot in 5 seconds.")
sleep 5
dmsetup message $DIFF_POOL_PATH_TPOOL 0 release_metadata_snap
fi

dmsetup message $DIFF_POOL_PATH_TPOOL 0 reserve_metadata_snap
DIFF_POOL_METADATA_SNAP=$(read_thin_metadata_snap $DIFF_POOL_PATH_TPOOL)

if [ "$DIFF_POOL_METADATA_SNAP" == "-" ] then
(>&2 echo "Failed to create thin pool metadata snapshot.")
exit 1
fi

#We keep output in variable because metadata snapshot need to be released early.
DIFF_DATA=$(thin_delta -m$DIFF_POOL_METADATA_SNAP --snap1 $DIFF_SOURCE_ID --snap2 $DIFF_TARGET_ID $DIFF_POOL_PATH_TMETA)

dmsetup message $DIFF_POOL_PATH_TPOOL 0 release_metadata_snap

echo $"$DIFF_DATA" | grep -E 'different|left_only|right_only' | sed 's/</"/g' | sed 's/ /"/g' | awk -F'"' '{print $6 "t" $8 "t" $11}' | sed 's/different/copy/g' | sed 's/left_only/copy/g' | sed 's/right_only/discard/g'

}

function thinsync()
{
SYNC_VG="$1"
SYNC_PEND="$2"
SYNC_BASE="$3"
SYNC_TARGET="$4"
SYNC_PEND_POOL=$(read_pool_lv $SYNC_VG $SYNC_PEND)
SYNC_BLOCK_SIZE=$(read_lv_chunk_size $SYNC_VG $SYNC_PEND_POOL)
SYNC_PEND_PATH=$(read_lv_dm_path $SYNC_VG $SYNC_PEND)

activate_volume $SYNC_VG $SYNC_PEND

while read -r SYNC_ACTION SYNC_OFFSET SYNC_LENGTH ; do
SYNC_OFFSET_BYTES=$((SYNC_OFFSET * SYNC_BLOCK_SIZE))
SYNC_LENGTH_BYTES=$((SYNC_LENGTH * SYNC_BLOCK_SIZE))
if [ "$SYNC_ACTION" == "copy" ] then
ddrescue --quiet --force --input-position=$SYNC_OFFSET_BYTES --output-position=$SYNC_OFFSET_BYTES --size=$SYNC_LENGTH_BYTES "$SYNC_PEND_PATH" "$SYNC_TARGET"
fi

if [ "$SYNC_ACTION" == "discard" ] then
blkdiscard -o $SYNC_OFFSET_BYTES -l $SYNC_LENGTH_BYTES "$SYNC_TARGET"
fi
done < <(thindiff "$SYNC_VG" "$SYNC_PEND" "$SYNC_BASE")
}

function discard_volume()
{
DISCARD_VG="$1"
DISCARD_LV="$2"
DISCARD_LV_PATH=$(read_lv_dm_path "$DISCARD_VG" "$DISCARD_LV")
if [ "$DISCARD_LV_PATH" != "" ] then
echo "$DISCARD_LV_PATH found"
else
echo "$DISCARD_LV not found in $DISCARD_VG"
exit 1
fi
DISCARD_LV_POOL=$(read_pool_lv $DISCARD_VG $DISCARD_LV)
DISCARD_LV_SIZE=$(read_lv_size "$DISCARD_VG" "$DISCARD_LV")
lvremove -y --quiet "$DISCARD_LV_PATH" || exit 1
lvcreate --thin-pool "$DISCARD_LV_POOL" -V "$DISCARD_LV_SIZE"B --name "$DISCARD_LV" "$DISCARD_VG" || exit 1
}

function backup()
{
SOURCE_VG="$1"
SOURCE_LV="$2"
TARGET_VG="$BACKUPS"
TARGET_LV="$SOURCE_VG-$SOURCE_LV"
SOURCE_BASE_LV="$SOURCE_LV$BASE_SUFFIX"
TARGET_BASE_LV="$TARGET_LV$BASE_SUFFIX"
SOURCE_PEND_LV="$SOURCE_LV$PEND_SUFFIX"
TARGET_PEND_LV="$TARGET_LV$PEND_SUFFIX"
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")
SOURCE_PEND_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_PEND_LV")
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
TARGET_PEND_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_PEND_LV")

if [ "$SOURCE_BASE_LV_PATH" != "" ] then
echo "$SOURCE_BASE_LV_PATH found"
else
echo "Source base not found creating snapshot of $SOURCE_VG/$SOURCE_LV to $SOURCE_VG/$SOURCE_BASE_LV"
lvcreate --quiet --snapshot --name "$SOURCE_BASE_LV" "$SOURCE_VG/$SOURCE_LV" || exit 1
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
echo "Discarding $SOURCE_BASE_LV_PATH as we need to bootstrap."
SOURCE_BASE_POOL=$(read_pool_lv $SOURCE_VG $SOURCE_BASE_LV)
SOURCE_BASE_CHUNK_SIZE=$(read_lv_chunk_size $SOURCE_VG $SOURCE_BASE_POOL)
discard_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
sync
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found out of sync with source... removing..."
lvremove -y --quiet $TARGET_BASE_LV_PATH || exit 1
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
sync
fi
fi
SOURCE_BASE_SIZE=$(read_lv_size "$SOURCE_VG" "$SOURCE_BASE_LV")
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found"
else
echo "$TARGET_VG/$TARGET_LV not found. Creating empty volume."
lvcreate --thin-pool "$BACKUPS_POOL" -V "$SOURCE_BASE_SIZE"B --name "$TARGET_BASE_LV" "$TARGET_VG" || exit 1
echo "Have to rebootstrap. Discarding source at $SOURCE_BASE_LV_PATH"
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
SOURCE_BASE_POOL=$(read_pool_lv $SOURCE_VG $SOURCE_BASE_LV)
SOURCE_BASE_CHUNK_SIZE=$(read_lv_chunk_size $SOURCE_VG $SOURCE_BASE_POOL)
discard_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
TARGET_BASE_POOL=$(read_pool_lv $TARGET_VG $TARGET_BASE_LV)
TARGET_BASE_CHUNK_SIZE=$(read_lv_chunk_size $TARGET_VG $TARGET_BASE_POOL)
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
echo "Discarding target at $TARGET_BASE_LV_PATH"
discard_volume "$TARGET_VG" "$TARGET_BASE_LV"
sync
fi
if [ "$SOURCE_PEND_LV_PATH" != "" ] then
echo "$SOURCE_PEND_LV_PATH found removing..."
lvremove -y --quiet "$SOURCE_PEND_LV_PATH" || exit 1
sync
fi
lvcreate --quiet --snapshot --name "$SOURCE_PEND_LV" "$SOURCE_VG/$SOURCE_LV" || exit 1
SOURCE_PEND_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_PEND_LV")
sync
if [ "$TARGET_PEND_LV_PATH" != "" ] then
echo "$TARGET_PEND_LV_PATH found removing..."
lvremove -y --quiet $TARGET_PEND_LV_PATH
sync
fi
lvcreate --quiet --snapshot --name "$TARGET_PEND_LV" "$TARGET_VG/$TARGET_BASE_LV" || exit 1
TARGET_PEND_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_PEND_LV")
SOURCE_PEND_LV_SIZE=$(read_lv_size "$SOURCE_VG" "$SOURCE_PEND_LV")
lvresize -L "$SOURCE_PEND_LV_SIZE"B "$TARGET_PEND_LV_PATH"
activate_volume "$TARGET_VG" "$TARGET_PEND_LV"
echo "Synching $SOURCE_PEND_LV_PATH to $TARGET_PEND_LV_PATH"
thinsync "$SOURCE_VG" "$SOURCE_PEND_LV" "$SOURCE_BASE_LV" "$TARGET_PEND_LV_PATH" || exit 1
sync

TARGET_DATE_SUFFIX=$(suffix)
lvcreate --quiet --snapshot --name "$TARGET_LV$TARGET_DATE_SUFFIX" "$TARGET_VG/$TARGET_PEND_LV" || exit 1
sync
lvremove --quiet -y "$SOURCE_BASE_LV_PATH" || exit 1
sync
lvremove --quiet -y "$TARGET_BASE_LV_PATH" || exit 1
sync
lvrename -y "$SOURCE_VG/$SOURCE_PEND_LV" "$SOURCE_BASE_LV" || exit 1
lvrename -y "$TARGET_VG/$TARGET_PEND_LV" "$TARGET_BASE_LV" || exit 1
sync
deactivate_volume "$TARGET_VG" "$TARGET_BASE_LV"
deactivate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
}

function verify()
{
SOURCE_VG="$1"
SOURCE_LV="$2"
TARGET_VG="$BACKUPS"
TARGET_LV="$SOURCE_VG-$SOURCE_LV"
SOURCE_BASE_LV="$SOURCE_LV$BASE_SUFFIX"
TARGET_BASE_LV="$TARGET_LV$BASE_SUFFIX"
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")

if [ "$SOURCE_BASE_LV_PATH" != "" ] then
echo "$SOURCE_BASE_LV_PATH found"
else
echo "$SOURCE_BASE_LV_PATH not found"
exit 1
fi
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found"
else
echo "$TARGET_BASE_LV_PATH not found"
exit 1
fi
activate_volume "$TARGET_VG" "$TARGET_BASE_LV"
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
echo Comparing "$SOURCE_BASE_LV_PATH" with "$TARGET_BASE_LV_PATH"
cmp "$SOURCE_BASE_LV_PATH" "$TARGET_BASE_LV_PATH"
echo Done...
deactivate_volume "$TARGET_VG" "$TARGET_BASE_LV"
deactivate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
}

function resync()
{
SOURCE_VG="$1"
SOURCE_LV="$2"
TARGET_VG="$BACKUPS"
TARGET_LV="$SOURCE_VG-$SOURCE_LV"
SOURCE_BASE_LV="$SOURCE_LV$BASE_SUFFIX"
TARGET_BASE_LV="$TARGET_LV$BASE_SUFFIX"
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")

if [ "$SOURCE_BASE_LV_PATH" != "" ] then
echo "$SOURCE_BASE_LV_PATH found"
else
echo "$SOURCE_BASE_LV_PATH not found"
exit 1
fi
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found"
else
echo "$TARGET_BASE_LV_PATH not found"
exit 1
fi
activate_volume "$TARGET_VG" "$TARGET_BASE_LV"
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
SOURCE_BASE_POOL=$(read_pool_lv $SOURCE_VG $SOURCE_BASE_LV)
SYNC_BLOCK_SIZE=$(read_lv_chunk_size $SOURCE_VG $SOURCE_BASE_POOL)

echo Syncronizing "$SOURCE_BASE_LV_PATH" to "$TARGET_BASE_LV_PATH"

CMP_OFFSET=0
while [[ "$CMP_OFFSET" != "" ]] ; do
CMP_MISMATCH=$(cmp -i "$CMP_OFFSET" "$SOURCE_BASE_LV_PATH" "$TARGET_BASE_LV_PATH" | grep differ | awk '{print $5}' | sed 's/,//g' )
if [[ "$CMP_MISMATCH" != "" ]] ; then
CMP_OFFSET=$(( CMP_MISMATCH + CMP_OFFSET ))
SYNC_OFFSET_BYTES=$(( ( CMP_OFFSET / SYNC_BLOCK_SIZE ) * SYNC_BLOCK_SIZE ))
SYNC_LENGTH_BYTES=$(( SYNC_BLOCK_SIZE ))
echo "Synching $SYNC_LENGTH_BYTES bytes at $SYNC_OFFSET_BYTES from $SOURCE_BASE_LV_PATH to $TARGET_BASE_LV_PATH"
ddrescue --quiet --force --input-position=$SYNC_OFFSET_BYTES --output-position=$SYNC_OFFSET_BYTES --size=$SYNC_LENGTH_BYTES "$SOURCE_BASE_LV_PATH" "$TARGET_BASE_LV_PATH"
else
CMP_OFFSET=""
fi
done
echo Done...
deactivate_volume "$TARGET_VG" "$TARGET_BASE_LV"
deactivate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
}

function list()
{
LIST_SOURCE_VG="$1"
LIST_SOURCE_LV="$2"
LIST_TARGET_VG="$BACKUPS"
LIST_TARGET_LV="$LIST_SOURCE_VG-$LIST_SOURCE_LV"
LIST_TARGET_BASE_LV="$LIST_TARGET_LV$SNAP_SUFFIX"
lvs -olv_name | grep "$LIST_TARGET_BASE_LV.$DATE_REGEX"
}

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

function removeall()
{
DATE_OFFSET="$3"
FILTER="$(filter "$DATE_OFFSET")"
while read -r SNAPSHOT ; do
remove "$SNAPSHOT"
done < <(list "$1" "$2" | grep "$FILTER")

}

(
COMMAND="$1"
shift

case "$COMMAND" in
"--help")
echo "Help"
;;
"suffix")
suffix
;;
"filter")
filter "$1"
;;
"backup")
wait_lock_or_terminate
backup "$1" "$2"
;;
"list")
list "$1" "$2"
;;
"thindiff")
thindiff "$1" "$2" "$3"
;;
"thinsync")
thinsync "$1" "$2" "$3" "$4"
;;
"verify")
wait_lock_or_terminate
verify "$1" "$2"
;;
"resync")
wait_lock_or_terminate
resync "$1" "$2"
;;
"remove")
wait_lock_or_terminate
remove "$1"
;;
"removeall")
wait_lock_or_terminate
removeall "$1" "$2" "$3"
;;
*)
echo "None.."
;;
esac
) 98>$LOCK_FILE

EOF

Mida see teeb...?Sisaldab käskude komplekti õhukeste hetktõmmistega manipuleerimiseks ja kahe õhukese hetktõmmise vahe sünkroonimiseks, mis on saadud läbi thin_delta teise plokkseadmega, kasutades ddrescue ja blkdiscard.

Teine skript, mille paneme cronisse:

Natuke rohkem jahmatust#cat >/root/lvm-thin-backup/cron-daily.sh << EOF
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

SCRIPT_FILE="$(realpath $0)"
SCRIPT_DIR="$(dirname $SCRIPT_FILE)"
SCRIPT_NAME="$(basename -s .sh $SCRIPT_FILE)"

BACKUP_SCRIPT="$SCRIPT_DIR/lvm-thin-backup.sh"
RETENTION="-60 days"

$BACKUP_SCRIPT backup images linux-dev
$BACKUP_SCRIPT backup images win8
$BACKUP_SCRIPT backup images win8-data
#etc

$BACKUP_SCRIPT removeall images linux-dev "$RETENTION"
$BACKUP_SCRIPT removeall images win8 "$RETENTION"
$BACKUP_SCRIPT removeall images win8-data "$RETENTION"
#etc

EOF

Mida see teeb...?Kasutab eelmist skripti loetletud õhukeste köidete varukoopiate loomiseks ja sünkroonimiseks. Skript jätab loetletud köidetest passiivsed hetktõmmised, mida on vaja pärast viimast sünkroonimist toimunud muudatuste jälgimiseks.

Seda skripti tuleb redigeerida, täpsustades õhukeste köidete loendi, millest tuleks teha varukoopiaid. Toodud nimed on illustratiivse tähendusega. Soovi korral võite kirjutada skripti, mis sünkroonib kõik köited.

Anname õigused:

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

Kontrollime seda ja paneme selle kroni:

#/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 venib pikaks, sest... õhukesed köited sünkroonitakse täielikult, kopeerides kogu kasutatud ruumi. Tänu LVM õhukeste metaandmetele teame, millised plokid on tegelikult kasutusel, seega kopeeritakse ainult tegelikult kasutatud õhukesed mahuplokid.

Tänu LVM-i õhukeste metaandmete kaudu toimuvale muudatuste jälgimisele kopeerivad järgmised käitused andmeid järk-järgult.

Vaatame, mis juhtus:

#time /root/btrfs-backup/cron-daily.sh
real 0m2,967s
user 0m0,225s
sys 0m0,353s

#time /root/lvm-thin-backup/cron-daily.sh
real 1m2,710s
user 0m12,721s
sys 0m6,671s

#ls -al /backup/btrfs/back/remote/*
/backup/btrfs/back/remote/boot:
total 0
drwxr-xr-x 1 root root 1260 мар 26 09:11 .
drwxr-xr-x 1 root root 16 мар 6 09:30 ..
drwxr-xr-x 1 root root 322 мар 26 02:00 .@base
drwxr-xr-x 1 root root 516 мар 6 09:39 [email protected]
drwxr-xr-x 1 root root 516 мар 6 09:39 [email protected]
...
/backup/btrfs/back/remote/root:
total 0
drwxr-xr-x 1 root root 2820 мар 26 09:11 .
drwxr-xr-x 1 root root 16 мар 6 09:30 ..
drwxr-xr-x 1 root root 240 мар 26 09:11 @.@base
drwxr-xr-x 1 root root 22 мар 26 09:11 @home.@base
drwxr-xr-x 1 root root 22 мар 6 09:39 @[email protected]
drwxr-xr-x 1 root root 22 мар 6 09:39 @[email protected]
...
drwxr-xr-x 1 root root 240 мар 6 09:39 @[email protected]
drwxr-xr-x 1 root root 240 мар 6 09:39 @[email protected]
...

#lvs -olv_name,lv_size images && lvs -olv_name,lv_size backup
LV LSize
linux-dev 128,00g
linux-dev.base 128,00g
thin-pool 1,38t
win8 128,00g
win8-data 2,00t
win8-data.base 2,00t
win8.base 128,00g
LV LSize
backup 256,00g
images-linux-dev.base 128,00g
images-linux-dev.snap.2020-03-08-10-09-11 128,00g
images-linux-dev.snap.2020-03-08-10-09-25 128,00g
...
images-win8-data.base 2,00t
images-win8-data.snap.2020-03-16-14-11-55 2,00t
images-win8-data.snap.2020-03-16-14-19-50 2,00t
...
images-win8.base 128,00g
images-win8.snap.2020-03-17-04-51-46 128,00g
images-win8.snap.2020-03-18-03-02-49 128,00g
...
thin-pool <2,09t

Mis on sellel pistmist pesitsevate nukkudega?

Tõenäoliselt, arvestades, et LVM LV loogilised mahud võivad olla LVM PV füüsilised mahud teiste VGde jaoks. LVM võib olla rekursiivne, nagu pesitsevad nukud. See annab LVM-ile äärmise paindlikkuse.

PS

Järgmises artiklis proovime kasutada mitut sarnast mobiilset salvestussüsteemi/KVM-i, et luua mitmel kontinendil koduseid töölaudu, koduinterneti ja P2P-võrke kasutades koondatud geo-jaotatud salvestus-/vm-klastrit.

Allikas: www.habr.com

Lisa kommentaar