Kion komune LVM kaj Matryoshka havas?

Bonan tempon de tago.
Mi ŝatus dividi kun la komunumo mian praktikan sperton pri konstruado de datuma stokadosistemo por KVM uzante md RAID + LVM.

La programo inkluzivos:

  • Konstruante md RAID 1 de NVMe SSD.
  • Kunvenado de md RAID 6 de SATA SSD kaj regulaj diskoj.
  • Trajtoj de TRIM/DISCARD operacio sur SSD RAID 1/6.
  • Kreante starteblan md RAID 1/6 tabelon sur ofta aro de diskoj.
  • Instali la sistemon sur NVMe RAID 1 kiam ne ekzistas NVMe-subteno en la BIOS.
  • Uzante LVM-kaŝmemoron kaj LVM maldikan.
  • Uzante BTRFS-fotojn kaj sendu/ricevu por sekurkopio.
  • Uzante LVM maldikajn momentfotojn kaj thin_delta por BTRFS-stilaj sekurkopioj.

Se vi interesiĝas, bonvolu vidi katon.

Formularo de apliko

La aŭtoro ne havas respondecon pri la konsekvencoj de uzado aŭ ne uzado de materialoj/ekzemploj/kodo/konsiloj/datumoj de ĉi tiu artikolo. Legante aŭ uzante ĉi tiun materialon iel ajn, vi supozas respondecon pri ĉiuj konsekvencoj de ĉi tiuj agoj. Eblaj sekvoj inkluzivas:

  • Kreska frititaj NVMe SSDoj.
  • Tute eluzita registra rimedo kaj fiasko de SSD-diskoj.
  • Kompleta perdo de ĉiuj datumoj sur ĉiuj diskoj, inkluzive de rezervaj kopioj.
  • Misa komputila aparataro.
  • Perdita tempo, nervoj kaj mono.
  • Ajnaj aliaj konsekvencoj, kiuj ne estas listigitaj supre.

Fero

Disponeblaj estis:

Motherboard de ĉirkaŭ 2013 kun Z87-pecetaro, kompleta kun Intel Core i7 / Haswell.

  • Procesoro 4 kernoj, 8 fadenoj
  • 32 GB DDR3 RAM
  • 1 x 16 aŭ 2 x 8 PCIe 3.0
  • 1 x 4 + 1 x 1 PCIe 2.0
  • 6 x 6 GBps SATA 3 konektiloj

SAS-adaptilo LSI SAS9211-8I ekbrilis al IT/HBA-reĝimo. RAID-ebligita firmvaro estis intencite anstataŭigita kun HBA-firmvaro por:

  1. Vi povus forĵeti ĉi tiun adaptilon iam ajn kaj anstataŭigi ĝin per iu ajn alia, kiun vi renkontis.
  2. TRIM/Forĵeti funkciis normale sur diskoj, ĉar... en RAID-firmvaro ĉi tiuj komandoj tute ne estas subtenataj, kaj la HBA, ĝenerale, ne zorgas pri tio, kiaj komandoj estas transdonitaj tra la buso.

Malmolaj diskoj - 8 pecoj de HGST Travelstar 7K1000 kun kapacito de 1 TB en formo de 2.5, kiel por tekkomputiloj. Ĉi tiuj diskoj antaŭe estis en RAID 6 tabelo. Ili ankaŭ havos uzon en la nova sistemo. Stoki lokajn sekurkopiojn.

Aldone aldonis:

6 pecoj SATA SSD modelo Samsung 860 QVO 2TB. Ĉi tiuj SSD-oj postulis grandan volumon, la ĉeesto de SLC-kaŝmemoro, fidindeco kaj malalta prezo estis dezirita. Subteno por forĵeti/nul estis postulata, kiu estas kontrolita per la linio en dmesg:

kernel: ata1.00: Enabling discard_zeroes_data

2 pecoj de NVMe SSD modelo Samsung SSD 970 EVO 500GB.

Por ĉi tiuj SSD-oj gravas hazarda legado/skriba rapideco kaj rimedkapablo por viaj bezonoj. Radiatoro por ili. Necese. Absolute. Alie, fritu ilin ĝis kroĉaj dum la unua RAID-sinkronigo.

StarTech PEX8M2E2-adaptilo por 2 x NVMe SSD instalita en PCIe 3.0 8x fendo. Ĉi tio, denove, estas nur HBA, sed por NVMe. Ĝi diferencas de malmultekostaj adaptiloj pro tio, ke ĝi ne postulas PCIe-forkaĵsubtenon de la baztabulo pro la ĉeesto de enkonstruita PCIe-ŝaltilo. Ĝi funkcios eĉ en la plej antikva sistemo kun PCIe, eĉ se ĝi estas x1 PCIe 1.0-fendo. Nature, je la taŭga rapido. Ne estas RAID-oj tie. Ne estas enkonstruita BIOS surŝipe. Do, via sistemo ne magie lernos ekbruligi per NVMe, des malpli fari NVMe RAID danke al ĉi tiu aparato.

Ĉi tiu komponanto estis nur pro la ĉeesto de nur unu senpaga 8x PCIe 3.0 en la sistemo, kaj, se estas 2 senpagaj fendoj, ĝi povas esti facile anstataŭigita per du penco PEX4M2E1 aŭ analogoj, kiuj povas esti aĉetitaj ie ajn je prezo de 600. rubloj.

La malakcepto de ĉiaj aparataro aŭ enkonstruitaj chipset/BIOS RAID-oj estis farita intence, por povi tute anstataŭigi la tutan sistemon, escepte de la SSD/HDD mem, konservante ĉiujn datumojn. Ideale, por ke vi povu konservi eĉ la instalitan operaciumon kiam vi translokiĝas al tute nova/malsama aparataro. La ĉefa afero estas, ke ekzistas SATA kaj PCIe-havenoj. Ĝi estas kiel viva KD aŭ startebla fulmo, nur tre rapida kaj iom dika.

HumuroAlie, vi scias, kio okazas - foje vi urĝe bezonas kunporti la tutan tabelon por forporti. Sed mi ne volas perdi datumojn. Por fari tion, ĉiuj menciitaj amaskomunikiloj estas oportune lokitaj sur la diapozitivoj en la 5.25 golfoj de la norma kazo.

Nu, kaj, kompreneble, por eksperimenti kun malsamaj metodoj de SSD-kaŝmemoro en Linukso.

Aparataj atakoj estas enuigaj. Ŝaltu ĝin. Ĝi aŭ funkcias aŭ ne. Kaj kun mdadm ĉiam estas ebloj.

Milda

Antaŭe, Debian 8 Jessie estis instalita sur la aparataro, kiu estas proksima al EOL. RAID 6 estis kunvenita de la supre menciitaj HDDs parigitaj kun LVM. Ĝi prizorgis virtualajn maŝinojn en kvm/libvirt.

Ĉar La aŭtoro havas taŭgan sperton pri kreado de porteblaj starteblaj SATA/NVMe-memordiskoj, kaj ankaŭ, por ne rompi la kutiman taŭgan ŝablonon, kiel celsistemon oni elektis Ubuntu 18.04, kiu jam sufiĉe stabiliĝis, sed ankoraŭ havas 3 jarojn. subteno en la estonteco.

La menciita sistemo enhavas ĉiujn aparatajn ŝoforojn, kiujn ni bezonas el la skatolo. Ni ne bezonas iun ajn programaron aŭ ŝoforojn de triaj.

Preparante por instali

Por instali la sistemon ni bezonas Ubuntu Desktop Image. La servila sistemo havas ian viglan instalilon, kiu montras troan sendependecon, kiu ne povas esti malŝaltita per ŝovo de la UEFI-sistemdisko sur unu el la diskoj, difektante la tutan belecon. Sekve, ĝi estas instalita nur en UEFI-reĝimo. Ne ofertas eblojn.

Ni ne estas feliĉaj kun ĉi tio.

Kial?Bedaŭrinde, UEFI-ŝargo estas ekstreme malbone kongrua kun lanĉa programaro RAID, ĉar... Neniu proponas al ni rezervojn por la UEFI ESP-diskodo. Estas receptoj interrete, kiuj sugestas meti la ESP-sekcion sur flash drive en USB-havenon, sed ĉi tio estas punkto de fiasko. Estas receptoj uzantaj programaron mdadm RAID 1 kun metadatuma versio 0.9, kiuj ne malhelpas la UEFI-BIOS vidi ĉi tiun subdiskon, sed ĉi tio vivas ĝis la feliĉa momento, kiam la BIOS aŭ alia aparataro OS skribas ion al la ESP kaj forgesas sinkronigi ĝin al aliaj. speguloj.

Krome, UEFI-ŝargo dependas de NVRAM, kiu ne moviĝos kune kun la diskoj al la nova sistemo, ĉar estas parto de la baztabulo.

Do, ni ne reinventos novan radon. Ni jam havas pretan, tempelprovitan biciklon de avo, nun nomitan Legacy/BIOS-boto, portanta la fieran nomon de CSM sur UEFI-kongruaj sistemoj. Ni nur deprenos ĝin de la breto, lubrigos ĝin, pumpos la pneŭojn kaj viŝos ĝin per malseka tuko.

La labortabla versio de Ubuntu ankaŭ ne povas esti instalita ĝuste per la Legacy ekŝargilo, sed ĉi tie, kiel oni diras, almenaŭ estas ebloj.

Kaj do, ni kolektas la aparataron kaj ŝarĝas la sistemon de la Ubuntu Live ekŝargebla ekbrilo. Ni devos elŝuti pakaĵojn, do ni starigos la reton, kiu funkcias por vi. Se ĝi ne funkcias, vi povas antaŭe ŝarĝi la necesajn pakaĵojn sur poŝmemorilon.

Ni eniras la Labortablan medion, lanĉas la terminalan emulilon, kaj ni iras:

#sudo bash

Kiel…?La supra linio estas la kanona ellasilo por Holiwars pri sudo. C bоpli grandaj ŝancoj venas kajоpli granda respondeco. La demando estas ĉu vi povas preni ĝin sur vi mem. Multaj homoj opinias, ke uzi sudo tiamaniere estas almenaŭ ne zorgema. Tamen:

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

Kial ne ZFS...?Kiam ni instalas programaron sur nia komputilo, ni esence pruntedonas nian aparataron al la programistoj de ĉi tiu programaro por stiri.
Kiam ni fidas ĉi tiun programaron kun la sekureco de niaj datumoj, ni prenas prunton egalan al la kosto de restarigo de ĉi tiuj datumoj, kiun ni devos pagi iam.

El ĉi tiu vidpunkto, ZFS estas Ferrari, kaj mdadm+lvm pli similas al biciklo.

Subjektive, la aŭtoro preferas pruntedoni biciklon kredite al nekonataj individuoj anstataŭ Ferrari. Tie, la prezo de la afero ne estas alta. Ne necesas rajtoj. Pli simpla ol trafikreguloj. Parkado estas senpaga. Transterena kapablo estas pli bona. Vi ĉiam povas ligi krurojn al biciklo, kaj vi povas ripari biciklon per viaj propraj manoj.

Kial do BTRFS...?Por lanĉi la operaciumon, ni bezonas dosiersistemon kiu estas subtenata en Legacy/BIOS GRUB el la skatolo, kaj samtempe subtenas vivajn momentfotojn. Ni uzos ĝin por la diskdisko /boot. Krome, la aŭtoro preferas uzi ĉi tiun FS por / (radiko), ne forgesante rimarki, ke por iu ajn alia programaro vi povas krei apartajn subdiskojn sur LVM kaj munti ilin en la necesaj dosierujoj.

Ni ne stokos iujn ajn bildojn de virtualaj maŝinoj aŭ datumbazoj sur ĉi tiu FS.
Ĉi tiu FS nur estos uzata por krei momentfotojn de la sistemo sen malŝalti ĝin kaj poste transdoni ĉi tiujn momentfotojn al rezerva disko per send/riceve.

Krome, la aŭtoro ĝenerale preferas konservi minimumon da programaro rekte sur la aparataro kaj ruli ĉiujn aliajn programojn en virtualaj maŝinoj uzante aferojn kiel plusendante GPU-ojn kaj PCI-USB-Gastigregilojn al KVM per IOMMU.

La nuraj aferoj restantaj sur la aparataro estas datumstokado, virtualigo kaj sekurkopio.

Se vi pli fidas ZFS, tiam, principe, por la specifita aplikaĵo ili estas interŝanĝeblaj.

Tamen, la aŭtoro intence ignoras la enkonstruitajn spegulajn/RAID- kaj redundajn funkciojn, kiujn ZFS, BRTFS kaj LVM havas.

Kiel kroma argumento, BTRFS havas la kapablon turni hazardajn skribaĵojn en sinsekvajn, kio havas ekstreme pozitivan efikon al la rapideco de sinkronigado de momentfotoj / sekurkopioj sur la HDD.

Ni resanu ĉiujn aparatojn:

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

Ni rigardu ĉirkaŭen:

#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

Diska aranĝo

NVMe SSD

Sed ni neniel markos ilin. Tamen, nia BIOS ne vidas ĉi tiujn diskojn. Do, ili iros tute al programaro RAID. Ni eĉ ne kreos sekciojn tie. Se vi volas sekvi la "kanonon" aŭ "ĉefe", kreu unu grandan sekcion, kiel HDD.

SATA HDD

Ne necesas inventi ion specialan ĉi tie. Ni kreos unu sekcion por ĉio. Ni kreos sekcion ĉar la BIOS vidas ĉi tiujn diskojn kaj eble eĉ provos lanĉi de ili. Ni eĉ instalos GRUB sur ĉi tiuj diskoj poste por ke la sistemo subite povu fari tion.

#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

Ĉi tie aferoj fariĝas interesaj por ni.

Unue, niaj diskoj estas 2 TB en grandeco. Ĉi tio estas ene de la akceptebla intervalo por MBR, kio estas kion ni uzos. Se necese, povas esti anstataŭigita per GPT. GPT-diskoj havas kongruecan tavolon kiu permesas al MBR-kongruaj sistemoj vidi la unuajn 4 sekciojn se ili situas ene de la unuaj 2 terabajtoj. La ĉefa afero estas, ke la ekfunkciigo kaj bios_grub diskparto sur ĉi tiuj diskoj estu ĉe la komenco. Ĉi tio eĉ ebligas al vi lanĉi de GPT Legacy/BIOS-diskoj.

Sed ĉi tio ne estas nia kazo.

Ĉi tie ni kreos du sekciojn. La unua estos 1 GB en grandeco kaj uzata por RAID 1 /boot.

La dua estos uzata por RAID 6 kaj okupos la tutan restantan liberan spacon krom malgranda neasignita areo ĉe la fino de la disko.

Kio estas ĉi tiu nemarkita areo?Laŭ fontoj en la reto, niaj SATA SSD-oj havas surŝipe dinamike ekspansiebla SLC-kaŝmemoro, kiu varias en grandeco de 6 ĝis 78 gigabajtoj. Ni ricevas 6 gigabajtojn "senpage" pro la diferenco inter "gigabajtoj" kaj "gibibajtoj" en la datumfolio de la disko. La ceteraj 72 gigabajtoj estas asignitaj de neuzata spaco.

Ĉi tie oni devas rimarki, ke ni havas SLC-kaŝmemoron, kaj la spaco estas okupata en 4-bita MLC-reĝimo. Kio por ni efike signifas, ke por ĉiu 4 gigabajtoj da libera spaco ni ricevos nur 1 gigabajton da SLC-kaŝmemoro.

Multipliku 72 gigabajtojn per 4 kaj ricevu 288 gigabajtojn. Ĉi tiu estas la libera spaco, kiun ni ne markos por permesi al la diskoj plene uzi la SLC-kaŝmemoron.

Tiel, ni efike ricevos ĝis 312 gigabajtojn da SLC-kaŝmemoro el entute ses diskoj. El ĉiuj diskoj, 2 estos uzataj en RAID por redundo.

Ĉi tiu kvanto de kaŝmemoro permesos al ni ege malofte en la reala vivo renkonti situacion kie skribo ne iras al la kaŝmemoro. Ĉi tio ege bone kompensas la plej malĝojan malavantaĝon de QLC-memoro - la ekstreme malaltan skribrapidecon kiam datumoj estas skribitaj preterpasante la kaŝmemoron. Se viaj ŝarĝoj ne respondas al ĉi tio, tiam mi rekomendas, ke vi pripensu kiom longe via SSD daŭros sub tia ŝarĝo, konsiderante la TBW de la datuma folio.

#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

Kreante tabelojn

Unue, ni devas renomi la maŝinon. Ĉi tio estas necesa ĉar la gastiga nomo estas parto de la tabelnomo ie ene de mdadm kaj influas ion ie. Kompreneble, tabeloj povas esti renomitaj poste, sed ĉi tio estas nenecesa paŝo.

#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

Kial -supozi-purigi...?Por eviti pravalorigon de tabeloj. Por ambaŭ RAID-niveloj 1 kaj 6 tio validas. Ĉio povas funkcii sen komencado se ĝi estas nova tabelo. Plie, pravalorigi la SSD-aron post kreado estas malŝparo de TBW-rimedo. Ni uzas TRIM/DISCARD kie eblas sur kunvenitaj SSD-aroj por "komencigi" ilin.

Por SSD-aroj, RAID 1 DISCARD estas subtenata el la skatolo.

Por SSD RAID 6 DISCARD tabeloj, vi devas ebligi ĝin en la parametroj de la kernaj moduloj.

Ĉi tio devus esti farita nur se ĉiuj SSDoj uzataj en nivelo 4/5/6 tabeloj en ĉi tiu sistemo havas funkciantan subtenon por diskard_zeroes_data. Kelkfoje vi trovas strangajn diskojn, kiuj diras al la kerno, ke ĉi tiu funkcio estas subtenata, sed fakte ĝi ne estas tie, aŭ la funkcio ne ĉiam funkcias. Nuntempe, subteno disponeblas preskaŭ ĉie, tamen ekzistas malnovaj diskoj kaj firmvaro kun eraroj. Tial, DISCARD-subteno estas malebligita defaŭlte por RAID 6.

Atentu, la sekva komando detruos ĉiujn datumojn sur NVMe-diskoj "komencigante" la tabelon per "nuloj".

#blkdiscard /dev/md0

Se io misfunkcias, provu specifi paŝon.

#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

Kial tiom granda...?Pliigi la pecon-grandecon havas pozitivan efikon sur la rapideco de hazarda legado en blokoj ĝis peco-grandeco inkluzive. Ĉi tio okazas ĉar unu operacio de la taŭga grandeco aŭ pli malgranda povas esti kompletigita tute sur ununura aparato. Tial, la IOPS de ĉiuj aparatoj estas resumitaj. Laŭ statistiko, 99% de IO ne superas 512K.

RAID 6 IOPS per skribo ĉiam malpli ol aŭ egala al la IOPS de unu stirado. Kiam, kiel hazarda legado, IOPS povas esti plurfoje pli granda ol tiu de unu stirado, kaj ĉi tie la blokgrandeco gravegas.
La verkinto ne vidas la signifon provi optimumigi parametron kiu estas malbona en RAID 6 laŭdezajno kaj anstataŭe optimumigas pri kio RAID 6 kapablas.
Ni kompensos la malbonan hazardan verkadon de RAID 6 per NVMe-kaŝmemoro kaj maldikaj provizantaj lertaĵoj.

Ni ankoraŭ ne ebligis DISCARD por RAID 6. Do ni ne "komencigos" ĉi tiun tabelon nuntempe. Ni faros tion poste, post instalo de la OS.

SATA HDD

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

LVM sur NVMe RAID

Por rapideco, ni volas meti la radikan dosiersistemon sur NVMe RAID 1 kiu estas /dev/md0.
Tamen, ni ankoraŭ bezonos ĉi tiun rapidan tabelon por aliaj bezonoj, kiel interŝanĝo, metadatumoj kaj LVM-kaŝmemoro kaj LVM-maldika metadatumo, do ni kreos LVM VG sur ĉi tiu tabelo.

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

Ni kreu subdiskon por la radika dosiersistemo.

#lvcreate -L 128G --name root root

Ni kreu subdiskon por interŝanĝi laŭ la grandeco de la RAM.

#lvcreate -L 32G --name swap root

OS-instalado

Entute ni havas ĉion necesan por instali la sistemon.

Lanĉu la sisteminstalan sorĉiston de la Ubuntu Live-medio. Normala instalado. Nur en la stadio de elekto de diskoj por instalado, vi devas specifi la jenajn:

  • /dev/md1, - munta punkto /boot, FS - BTRFS
  • /dev/root/root (alinome /dev/mapper/root-root), - munta punkto / (radiko), FS - BTRFS
  • /dev/root/swap (alinome /dev/mapper/root-swap), - uzu kiel interŝanĝan sekcion
  • Instalu la ekŝargilon sur /dev/sda

Kiam vi elektas BTRFS kiel la radikan dosiersistemon, la instalilo aŭtomate kreos du BTRFS-volumojn nomitajn "@" por / (radiko), kaj "@home" por /home.

Ni komencu la instaladon...

La instalado finiĝos per modala dialogujo indikanta eraron instalante la ekŝargilon. Bedaŭrinde, vi ne povos eliri ĉi tiun dialogon per normaj rimedoj kaj daŭrigi la instaladon. Ni elsalutas el la sistemo kaj ensalutas denove, finiĝante en pura Ubuntu Live labortablo. Malfermu la terminalon, kaj denove:

#sudo bash

Kreu chroot-medion por daŭrigi la instaladon:

#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

Ni agordu la reton kaj gastigan nomon en chroot:

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

Ni iru en la chroot-medion:

#chroot /mnt/chroot

Antaŭ ĉio, ni liveros la pakaĵojn:

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

Ni kontrolu kaj riparu ĉiujn pakaĵojn, kiuj estis malrekte instalitaj pro nekompleta sisteminstalado:

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

Se io ne funkcias, vi eble bezonos redakti /etc/apt/sources.list unue

Ni ĝustigu la parametrojn por la RAID 6-modulo por ebligi TRIM/DISCARD:

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

Ni iom ĝustigu niajn tabelojn:

#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

Kio estis tio..?Ni kreis aron de udev-reguloj, kiuj faros la jenon:

  • Agordu la blokan kaŝmemoron por RAID 2020 por esti taŭga por 6. La defaŭlta valoro, ŝajnas, ne ŝanĝiĝis ekde la kreado de Linukso, kaj ne taŭgas dum longa tempo.
  • Rezervu minimumon de IO por la daŭro de tabelkontroloj/sinkronigoj. Ĉi tio estas por malhelpi viajn tabelojn blokiĝi en stato de eterna sinkronigo sub ŝarĝo.
  • Limigu la maksimuman IO dum kontroloj/sinkronigado de tabeloj. Ĉi tio estas necesa por ke sinkronigi/kontroli SSD-RAID-ojn ne fritu viajn diskojn al krispa. Ĉi tio validas precipe por NVMe. (Memoras pri la radiatoro? Mi ne ŝercis.)
  • Malpermesu diskojn ĉesigi spindelrotacion (HDD) per APM kaj agordu la dormtempon por diskregiloj al 7 horoj. Vi povas tute malŝalti APM se viaj diskoj povas fari ĝin (-B 255). Kun la defaŭlta valoro, la diskoj ĉesos post kvin sekundoj. Tiam la OS volas restarigi la diskon-kaŝmemoron, la diskoj denove ŝpruciĝos, kaj ĉio rekomencos. Diskoj havas limigitan maksimuman nombron da spindelrotacioj. Tia simpla defaŭlta ciklo povas facile mortigi viajn diskojn en kelkaj jaroj. Ne ĉiuj diskoj suferas de tio, sed la niaj estas "tekkomputiloj", kun la taŭgaj defaŭltaj agordoj, kiuj igas RAID-aspekti kiel mini-MAID.
  • Instalu readhead sur diskoj (rotaciantaj) 1 megabajto - du sinsekvaj blokoj/peco RAID 6
  • Malebligu legadon sur la tabeloj mem.

Ni redaktu /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

Kial estas tio..?Ni serĉos la /boot-diskon per UUID. Tabelnomado povus teorie ŝanĝiĝi.

Ni serĉos la ceterajn sekciojn per LVM-nomoj en la notacio /dev/mapper/vg-lv, ĉar ili identigas sekciojn tute unike.

Ni ne uzas UUID por LVM ĉar La UUID de LVM-volumoj kaj iliaj momentfotoj povas esti la samaj.Montu /dev/mapper/root-root.. dufoje?Jes. Ĝuste. Karakterizaĵo de BTRFS. Ĉi tiu dosiersistemo povas esti muntita plurajn fojojn kun malsamaj subvoloj.

Pro ĉi tiu sama funkcio, mi rekomendas neniam krei LVM-fotojn de aktivaj BTRFS-volumoj. Vi eble ricevos surprizon kiam vi rekomencas.

Ni regeneru la mdadm-agordon:

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

Ni ĝustigu la LVM-agordojn:

#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

Kio estis tio..?Ni ebligis aŭtomatan ekspansion de LVM maldikaj naĝejoj atinginte 90% de la okupata spaco je 5% de la volumo.

Ni pliigis la maksimuman nombron da kaŝmemorblokoj por LVM-kaŝmemoro.

Ni malhelpis LVM serĉi LVM-volumojn (PV) sur:

  • aparatoj enhavantaj LVM-kaŝmemoron (cdata)
  • aparatoj konservitaj uzante LVM-kaŝmemoron, preterirante la kaŝmemoron ( _corig). En ĉi tiu kazo, la kaŝmemorita aparato mem ankoraŭ estos skanita tra la kaŝmemoro (nur ).
  • aparatoj enhavantaj LVM-kaŝmemormetadatenojn (cmeta)
  • ĉiuj aparatoj en VG kun la nombildoj. Ĉi tie ni havos diskobildojn de virtualaj maŝinoj, kaj ni ne volas, ke LVM sur la gastiganto aktivigu volumojn apartenantaj al la gasto OS.
  • ĉiuj aparatoj en VG kun la nomo sekurkopio. Ĉi tie ni havos rezervajn kopiojn de virtualaj maŝinaj bildoj.
  • ĉiuj aparatoj kies nomo finiĝas per "gpv" (gasta fizika volumeno)

Ni ebligis DISCARD-subtenon dum liberigado de libera spaco sur LVM VG. Atentu. Ĉi tio faros forigon de LV-oj sur la SSD sufiĉe tempopostula. Ĉi tio precipe validas por SSD RAID 6. Tamen, laŭ la plano, ni uzos maldikan provizon, do ĉi tio tute ne malhelpos nin.

Ni ĝisdatigu la initramfs-bildon:

#update-initramfs -u -k all

Instalu kaj agordu grub:

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

Kiajn diskojn elekti?Ĉiuj kiuj estas sd*. La sistemo devas povi ekbruligi de iu ajn funkcianta SATA-disko aŭ SSD.

Kial ili aldonis os-prober..?Por troa sendependeco kaj ludaj manoj.

Ĝi ne funkcias ĝuste se unu el la RAID-oj estas en degradita stato. Ĝi provas serĉi la OS sur sekcioj kiuj estas uzataj en virtualaj maŝinoj kurantaj sur ĉi tiu aparataro.

Se vi bezonas ĝin, vi povas lasi ĝin, sed memoru ĉion supre. Mi rekomendas serĉi receptojn por forigi malbonajn manojn interrete.

Per tio ni finis la komencan instaladon. Estas tempo rekomenci en la lastatempe instalitan OS. Ne forgesu forigi la starteblan Live KD/USB.

#exit
#reboot

Elektu iun ajn el la SATA-SSD-oj kiel la lanĉa aparato.

LVM sur SATA SSD

Je ĉi tiu punkto, ni jam ekŝaltis la novan OS, agordis la reton, taŭgas, malfermis la terminalan emulilon kaj lanĉis:

#sudo bash

Ni daŭrigu.

"Inicialigu" la tabelon de SATA SSD:

#blkdiscard /dev/md2

Se ĝi ne funkcias, provu:

#blkdiscard --step 65536 /dev/md2
Kreu LVM VG sur SATA SSD:

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

Kial alia VG..?Fakte, ni jam havas VG nomitan radiko. Kial ne aldoni ĉion en unu VG?

Se estas pluraj PV-oj en VG, tiam por ke la VG estu aktivigita ĝuste, ĉiuj PV-oj devas ĉeesti (rete). La escepto estas LVM RAID, kiun ni intence ne uzas.

Ni vere volas, ke se estas malsukceso (legu datumperdon) sur iu el la RAID 6-tabeloj, la operaciumo ekfunkciigos normale kaj donos al ni la ŝancon solvi la problemon.

Por fari tion, ĉe la unua nivelo de abstraktado ni izolos ĉiun specon de fizikaj "amaskomunikiloj" en apartan VG.

Science parolante, malsamaj RAID-aroj apartenas al malsamaj "fidindecaj domajnoj". Vi ne devus krei plian komunan malsukcesan punkton por ili enŝlosante ilin en unu VG.

La ĉeesto de LVM ĉe la "aparataro" nivelo permesos al ni arbitre tranĉi pecojn de malsamaj RAID-tabeloj kombinante ilin en malsamaj manieroj. Ekzemple - kuri samtempe bcache + LVM maldika, bcache + BTRFS, LVM kaŝmemoro + LVM maldika, kompleksa ZFS-agordo kun kaŝmemoroj, aŭ ajna alia infera miksaĵo por provi kompari ĉion.

Je la "aparataro" nivelo, ni ne uzos ion alian ol bonajn malnovajn "dikajn" LVM-volumojn. La escepto al ĉi tiu regulo povas esti la rezerva sekcio.

Mi pensas, ke ĝis ĉi tiu momento, multaj legantoj jam komencis suspekti ion pri la nesta pupo.

LVM sur SATA HDD

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

Nova VG denove..?Ni vere volas, ke se la diska tabelo, kiun ni uzos por sekurkopio de datumoj, malsukcesos, nia operaciumo daŭre funkcios normale, konservante aliron al ne-rezervaj datumoj kiel kutime. Tial, por eviti problemojn pri aktivigo de VG, ni kreas apartan VG.

Agordi LVM-kaŝmemoron

Ni kreu LV sur NVMe RAID 1 por uzi ĝin kiel kaŝmemoran aparaton.

#lvcreate -L 70871154688B --name cache root

Kial estas tiom malmulte...?Fakte, niaj NVMe SSD-oj ankaŭ havas SLC-kaŝmemoron. 4 gigabajtoj de "libera" kaj 18 gigabajtoj de dinamiko pro la libera spaco okupita en la 3-bita MLC. Post kiam ĉi tiu kaŝmemoro estas elĉerpita, NVMe SSD-oj ne estos multe pli rapidaj ol nia SATA SSD kun kaŝmemoro. Efektive, tial, ne havas sencon por ni fari la LVM-kaŝsekcion multe pli granda ol duoble la grandeco de la SLC-kaŝmemoro de la NVMe-disko. Por la NVMe-diskoj uzataj, la aŭtoro konsideras racia fari 32-64 gigabajtojn da kaŝmemoro.

La donita subdisko estas bezonata por organizi 64 gigabajtojn da kaŝmemoro, kaŝmemormetadatumoj, kaj metadatuman sekurkopion.

Aldone, mi rimarkas, ke post malpura sistemhalto, LVM markos la tutan kaŝmemoron kiel malpuran kaj sinkronigos denove. Krome, ĉi tio ripetiĝos ĉiufoje kiam lvchange estas uzata sur ĉi tiu aparato ĝis la sistemo denove rekomencos. Tial mi rekomendas tuj rekrei la kaŝmemoron per la taŭga skripto.

Ni kreu LV sur SATA RAID 6 por uzi ĝin kiel kaŝmemorigitan aparaton.

#lvcreate -L 3298543271936B --name cache data

Kial nur tri terabajtoj..?Por ke, se necese, vi povas uzi SATA SSD RAID 6 por iuj aliaj bezonoj. La grandeco de la kaŝmemorigita spaco povas esti pliigita dinamike, sur la flugo, sen haltigi la sistemon. Por fari tion, vi devas provizore halti kaj reŝalti la kaŝmemoron, sed la karakteriza avantaĝo de LVM-kaŝmemoro super, ekzemple, bcache estas ke tio povas esti farita sur la flugo.

Ni kreu novan VG por kaŝmemoro.

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

Ni kreu LV sur la kaŝmemorita aparato.

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

Ĉi tie ni tuj okupis la tutan liberan spacon sur /dev/data/cache tiel ke ĉiuj aliaj necesaj sekcioj estis kreitaj tuj sur /dev/root/cache. Se vi kreis ion en malĝusta loko, vi povas movi ĝin per pvmove.

Ni kreu kaj ebligu la kaŝmemoron:

#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

Kial tia peco..?Per praktikaj eksperimentoj, la aŭtoro povis malkovri, ke la plej bona rezulto estas atingita se la grandeco de la LVM-kaŝmemorbloko koincidas kun la grandeco de la LVM maldika bloko. Krome, ju pli malgranda estas la grandeco, des pli bone la agordo rezultas en hazarda registrado.

64k estas la minimuma blokgrandeco permesita por LVM maldika.

Atentu reskribadon..!Jes. Ĉi tiu speco de kaŝmemoro prokrastas skriban sinkronigon al la kaŝmemorita aparato. Ĉi tio signifas, ke se la kaŝmemoro estas perdita, vi eble perdos datumojn sur la kaŝmemorita aparato. Poste, la aŭtoro diros al vi, kiajn mezurojn, krom NVMe RAID 1, povas esti prenitaj por kompensi ĉi tiun riskon.

Ĉi tiu kaŝmemorspeco estis elektita intencite por kompensi la malbonan hazardan skriban efikecon de RAID 6.

Ni kontrolu, kion ni ricevis:

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

Nur [cachedata_corig] devus troviĝi sur /dev/data/cache. Se io estas malĝusta, tiam uzu pvmove.

Vi povas malŝalti la kaŝmemoron se necese per unu komando:

#lvconvert -y --uncache cache/cachedata

Ĉi tio estas farita interrete. LVM simple sinkronigos la kaŝmemoron al disko, forigos ĝin kaj renomos cachedata_corig reen al kaŝmemoro.

Agordo de LVM maldika

Ni proksimume taksu kiom da spaco ni bezonas por LVM maldikaj metadatenoj:

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

Rondigi ĝis 4 gigabajtoj: 4294967296B

Multipliku per du kaj aldonu 4194304B por metadatumoj de LVM PV: 8594128896B
Ni kreu apartan sekcion sur NVMe RAID 1 por meti LVM maldikajn metadatumojn kaj ilian rezervan kopion sur ĝin:

#lvcreate -L 8594128896B --name images root

Por kio..?Ĉi tie povas ekesti la demando: kial meti LVM maldikajn metadatumojn aparte se ĝi ankoraŭ estos konservita en NVMe kaj funkcios rapide.

Kvankam rapideco estas grava ĉi tie, ĝi estas malproksima de la ĉefa kialo. La afero estas, ke la kaŝmemoro estas punkto de fiasko. Io povus okazi al ĝi, kaj se la maldikaj metadatumoj de LVM estas konservitaj, ĝi kaŭzos ĉion tute perdita. Sen kompletaj metadatenoj, estos preskaŭ neeble kunveni maldikajn volumojn.

Movante la metadatumojn al aparta nekaŝmemorigita, sed rapida, volumeno, ni garantias la sekurecon de la metadatumoj en kazo de kaŝmemorperdo aŭ korupto. En ĉi tiu kazo, ĉiuj damaĝoj kaŭzitaj de kaŝmemorperdo estos lokalizitaj ene de maldikaj volumoj, kio simpligos la reakiran proceduron laŭ grand-ordoj. Kun alta probableco, ĉi tiuj damaĝoj estos restarigitaj uzante FS-protokolojn.

Krome, se antaŭe estis prenita momentfoto de maldika volumo, kaj post tio la kaŝmemoro estis plene sinkronigita almenaŭ unufoje, tiam, pro la interna dezajno de LVM maldika, la integreco de la momentfoto estos garantiita en la okazo de kaŝmemoro perdo. .

Ni kreu novan VG, kiu respondecos pri maldika provizo:

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

Ni kreu naĝejon:

#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T images/thin-pool
Kial -Z yAldone al tio, por kio ĉi tiu reĝimo efektive estas celita - por malhelpi datumojn de unu virtuala maŝino liki al alia virtuala maŝino dum redistribuo de spaco - nuligo estas aldone uzata por pliigi la rapidecon de hazarda skribo en blokoj pli malgrandaj ol 64k. Ĉiu skribo malpli ol 64k al antaŭe neasignita areo de la maldika volumeno fariĝos 64K rand-vicigita en la kaŝmemoro. Ĉi tio permesos la operacion esti farita tute tra la kaŝmemoro, preterirante la kaŝmemorita aparato.

Ni movu la LV-ojn al la ekvivalentaj PV-oj:

#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

Ni kontrolu:

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

Ni kreu maldikan volumon por provoj:

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

Ni instalos pakaĵojn por testoj kaj monitorado:

#apt-get install sysstat fio

Jen kiel vi povas observi la konduton de nia konserva agordo en reala tempo:

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

Jen kiel ni povas testi nian agordon:

#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

Zorge! Rimedo!Ĉi tiu kodo funkcios 36 malsamajn provojn, ĉiu funkciante dum 4 sekundoj. Duono de la testoj estas por registrado. Vi povas registri multon sur NVMe en 4 sekundoj. Ĝis 3 gigabajtoj por sekundo. Do, ĉiu verkado de testoj povas manĝi ĝis 216 gigabajtojn da SSD-rimedo de vi.

Legado kaj skribo miksitaj?Jes. Estas senco ruli la legadon kaj skribajn testojn aparte. Plie, estas senco certigi, ke ĉiuj kaŝmemoroj estas sinkronigitaj tiel ke antaŭe farita skribo ne influas la legadon.

La rezultoj multe varias dum la unua lanĉo kaj postaj kiam la kaŝmemoro kaj maldika volumo pleniĝas, kaj ankaŭ depende de ĉu la sistemo sukcesis sinkronigi la kaŝmemorojn plenigitajn dum la lasta lanĉo.

Interalie mi rekomendas mezuri la rapidecon sur jam plena maldika volumo, de kiu ĵus estis prenita momentfoto. La aŭtoro havis la ŝancon observi kiel hazardaj skribaĵoj akre akcelas tuj post kreado de la unua momentfoto, precipe kiam la kaŝmemoro ankoraŭ ne estas tute plena. Ĉi tio okazas pro kopi-sur-skriba skribsemantiko, vicigo de kaŝmemoro kaj maldikaj volumblokoj, kaj la fakto ke hazarda skribo al RAID 6 iĝas hazarda legado de RAID 6 sekvita de skribo al la kaŝmemoro. En nia agordo, hazarda legado de RAID 6 estas ĝis 6 fojojn (la nombro da SATA SSD-oj en la tabelo) pli rapida ol skribo. Ĉar blokoj por CoW estas asignitaj sinsekve de maldika naĝejo, tiam la registrado, plejparte, ankaŭ iĝas sinsekva.

Ambaŭ ĉi tiuj funkcioj povas esti uzataj al via avantaĝo.

Kaŝmemoru "koherajn" momentfotojn

Por redukti la riskon de perdo de datumoj en kazo de kaŝmemoro damaĝo/perdo, la aŭtoro proponas enkonduki la praktikon de turnado de momentfotoj por garantii ilian integrecon en ĉi tiu kazo.

Unue, ĉar maldikaj volumaj metadatenoj loĝas sur nekaŝigita aparato, la metadatenoj estos konsekvencaj kaj eblaj perdoj estos izolitaj ene de datumblokoj.

La sekva rotacia ciklo de momentfoto garantias la integrecon de la datumoj ene de la momentfotoj en kazo de kaŝmemorperdo:

  1. Por ĉiu maldika volumo kun la nomo <name>, kreu momentfoton kun la nomo <name>.cached
  2. Ni agordu la migradan sojlon al akceptebla alta valoro: #lvchange --quiet --cachesettings "migration_threshold=16384" cache/cachedata
  3. En la buklo ni kontrolas la nombron da malpuraj blokoj en la kaŝmemoro: #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' ĝis ni ricevas nulon. Se la nulo mankas tro longe, ĝi povas esti kreita per provizore ŝanĝante la kaŝmemoron al skribreĝimo. Tamen, konsiderante la rapidecajn karakterizaĵojn de niaj SATA kaj NVMe SSD-aroj, same kiel ilian TBW-rimedon, vi aŭ povos rapide kapti la momenton sen ŝanĝi la kaŝmemorreĝimon, aŭ via aparataro tute manĝos sian tutan rimedon en kelkaj tagoj. Pro rimedlimigoj, la sistemo principe ne kapablas esti sub 100% skribŝarĝo la tutan tempon. Niaj NVMe SSD-oj sub 100% skribŝarĝo tute elĉerpas la rimedon 3-4 tagoj. SATA SSD-oj daŭros nur duoble pli longe. Sekve, ni supozos, ke la plej granda parto de la ŝarĝo iras al legado, kaj ni havas relative mallongperspektivajn eksplodojn de ekstreme alta agado kombinita kun malalta ŝarĝo averaĝe por skribi.
  4. Tuj kiam ni kaptis (aŭ faris) nulon, ni renomas <name>.cached al <name>.committed. La malnova <nomo>.committed estas forigita.
  5. Laŭvole, se la kaŝmemoro estas 100% plena, ĝi povas esti rekreita per skripto, tiel malbarante ĝin. Kun duonmalplena kaŝmemoro, la sistemo funkcias multe pli rapide dum skribado.
  6. Agordu la migradan sojlon al nulo: #lvchange --quiet --cachesettings "migration_threshold=0" cache/cachedata Ĉi tio provizore malhelpos la kaŝmemoron sinkronigi al la ĉefaj amaskomunikiloj.
  7. Ni atendas ĝis sufiĉe multaj ŝanĝoj akumuliĝas en la kaŝmemoro #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' aŭ la tempigilo estingiĝos.
  8. Ni ripetas denove.

Kial malfacilaĵoj kun migra sojlo...?La afero estas, ke en reala praktiko, "hazarda" registrado fakte ne estas tute hazarda. Se ni skribis ion al sektoro de 4 kilobajtoj en grandeco, estas alta probablo ke en la sekvaj du minutoj rekordo estos farita al la sama aŭ unu el la najbaraj (+- 32K) sektoroj.

Agordante la migradan sojlon al nulo, ni prokrastas skriban sinkronigon sur la SATA SSD kaj kunigas plurajn ŝanĝojn al unu 64K-bloko en la kaŝmemoro. Ĉi tio signife ŝparas la rimedon de SATA SSD.

Kie estas la kodo..?Bedaŭrinde, la aŭtoro konsideras sin nesufiĉe kompetenta pri la disvolvado de bash-skriptoj, ĉar li estas 100% memlernita kaj praktikas disvolvadon de "google", tial li opinias, ke la terura kodo, kiu eliras el liaj manoj, ne devas esti uzata de neniu. alie.

Mi pensas, ke profesiuloj en ĉi tiu kampo povos sendepende bildigi la tutan logikon priskribitan supre, se necese, kaj, eble, eĉ bele desegni ĝin kiel sisteman servon, kiel la aŭtoro provis fari.

Tia simpla turnadskemo de momentfoto permesos al ni ne nur konstante havi unu momentfoton plene sinkronigitan sur la SATA SSD, sed ankaŭ permesos al ni, uzante la thin_delta ilon, ekscii kiuj blokoj estis ŝanĝitaj post ĝia kreado, kaj tiel lokalizi damaĝon sur la ĉefaj volumoj, tre simpligante reakiron.

TRIM/Forĵeti en libvirt/KVM

Ĉar la datumstokado estos uzata por KVM funkcianta libvirt, tiam estus bona ideo instrui niajn VM-ojn ne nur preni liberan spacon, sed ankaŭ liberigi tion, kio ne plu bezonas.

Ĉi tio estas farita per kopiado de TRIM/DISCARD-subteno sur virtualaj diskoj. Por fari tion, vi devas ŝanĝi la regilon tipon al virtio-scsi kaj redakti la 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'/>
<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>

Tiaj forĵetoj de gastaj OS-oj estas ĝuste prilaboritaj de LVM, kaj blokoj estas liberigitaj ĝuste kaj en la kaŝmemoro kaj en la maldika naĝejo. En nia kazo, ĉi tio okazas ĉefe en malfrua maniero, kiam vi forigas la sekvan momentfoton.

BTRFS Rezervo

Uzu pretajn skriptojn kun ekstrema singardemo kaj je propra risko. La aŭtoro verkis ĉi tiun kodon mem kaj ekskluzive por si. Mi certas, ke multaj spertaj uzantoj de Linukso havas similajn ilojn, kaj ne necesas kopii tiujn de iu alia.

Ni kreu volumon sur la rezerva aparato:

#lvcreate -L 256G --name backup backup

Ni formatu ĝin en BTRFS:

#mkfs.btrfs /dev/backup/backup

Ni kreu muntajn punktojn kaj muntu la radikajn subsekciojn de la dosiersistemo:

#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

Ni kreu dosierujojn por sekurkopioj:

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

Ni kreu dosierujon por rezervaj skriptoj:

#mkdir /root/btrfs-backup

Ni kopiu la skripton:

Multaj timiga bash-kodo. Uzu je via propra risko. Ne skribu kolerajn leterojn al la aŭtoro...#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

Kion ĝi eĉ faras..?Enhavas aron de simplaj komandoj por krei BTRFS momentfotojn kaj kopii ilin al alia FS uzante BTRFS sendi/ricevi.

La unua lanĉo povas esti relative longa, ĉar... Komence, ĉiuj datumoj estos kopiitaj. Pliaj lanĉoj estos tre rapidaj, ĉar... Nur ŝanĝoj estos kopiitaj.

Alia skripto, kiun ni metos en cron:

Iom pli da bash-kodo#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

Kion ĝi faras..?Kreas kaj sinkronigas pliigajn momentfotojn de la listigitaj BTRFS-volumoj sur la rezerva FS. Post tio, ĝi forigas ĉiujn bildojn kreitajn antaŭ 60 tagoj. Post lanĉo, datitaj momentfotoj de la listigitaj volumoj aperos en la /backup/btrfs/back/remote/ subdosierujoj.

Ni donu la ekzekutrajtojn de la kodo:

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

Ni kontrolu ĝin kaj metu ĝin en la cron:

#/usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/btrfs-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t btrfs-backup
#cat /var/log/syslog | grep btrfs-backup
#crontab -e
0 2 * * * /usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/btrfs-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t btrfs-backup

LVM maldika sekurkopio

Ni kreu maldikan naĝejon sur la rezerva aparato:

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

Ni instalu ddrescue, ĉar... skriptoj uzos ĉi tiun ilon:

#apt-get install gddrescue

Ni kreu dosierujon por skriptoj:

#mkdir /root/lvm-thin-backup

Ni kopiu la skriptojn:

Multaj batoj interne...#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

Kion ĝi faras...?Enhavas aron da komandoj por manipuli maldikajn momentfotojn kaj sinkronigi la diferencon inter du maldikaj momentfotoj ricevitaj per thin_delta al alia bloka aparato uzante ddrescue kaj blkdiscard.

Alia skripto, kiun ni metos en cron:

Iom pli da bato#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

Kion ĝi faras...?Uzas la antaŭan skripton por krei kaj sinkronigi sekurkopiojn de la listigitaj maldikaj volumoj. La skripto lasos neaktivajn momentfotojn de la listigitaj volumoj, kiuj estas bezonataj por spuri ŝanĝojn ekde la lasta sinkronigo.

Ĉi tiu skripto devas esti redaktita, specifante la liston de maldikaj volumoj por kiuj sekurkopioj estu faritaj. La nomoj donitaj estas nur por ilustraj celoj. Se vi deziras, vi povas skribi skripton, kiu sinkronigos ĉiujn volumojn.

Ni donu la rajtojn:

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

Ni kontrolu ĝin kaj metu ĝin en la cron:

#/usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/lvm-thin-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t lvm-thin-backup
#cat /var/log/syslog | grep lvm-thin-backup
#crontab -e
0 3 * * * /usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/lvm-thin-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t lvm-thin-backup

La unua lanĉo estos longa, ĉar... maldikaj volumoj estos plene sinkronigitaj kopiante la tutan uzatan spacon. Danke al LVM maldikaj metadatenoj, ni scias, kiuj blokoj estas efektive uzataj, do nur efektive uzataj maldikaj volumblokoj estos kopiitaj.

Postaj kuroj kopios la datumojn iom post iom danke al ŝanĝa spurado per maldikaj metadatenoj de LVM.

Ni vidu kio okazis:

#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

Kion ĉi tio rilatas al nestaj pupoj?

Plej verŝajne, konsiderante ke LVM LV-logikaj volumoj povas esti LVM PV fizikaj volumoj por aliaj VGoj. LVM povas esti rekursiva, kiel nestaj pupoj. Ĉi tio donas al LVM ekstreman flekseblecon.

PS

En la sekva artikolo, ni provos uzi plurajn similajn moveblajn stokadsistemojn/KVM kiel la bazon por krei geo-distribuitan stokadon/vm-areton kun redundo sur pluraj kontinentoj uzante hejmajn labortablojn, la hejman Interreton kaj P2P-retojn.

fonto: www.habr.com

Aldoni komenton