Ciò chì LVM è Matryoshka anu in cumunu?

Kind of time of day.
Vogliu sparte cù a cumunità a mo sperienza pratica di custruisce un sistema di almacenamiento di dati per KVM utilizendu md RAID + LVM.

U prugramma includerà:

  • Custruisce md RAID 1 da NVMe SSD.
  • Assemblage md RAID 6 da SATA SSD è unità regulare.
  • Funzioni di l'operazione TRIM/DISCARD in SSD RAID 1/6.
  • Creazione di un array md RAID 1/6 bootable nantu à un settore cumuni di discu.
  • Installà u sistema in NVMe RAID 1 quandu ùn ci hè micca supportu NVMe in u BIOS.
  • Utilizà a cache LVM è LVM thin.
  • Utilizendu snapshots BTRFS è mandà / riceve per a copia di salvezza.
  • Utilizà LVM thin snapshots è thin_delta per backups in stile BTRFS.

Sè site interessatu, vede cat.

Forma d'applicazione

L'autore ùn hà micca rispunsabilità per e cunsequenze di l'usu o micca di l'usu di materiali / esempi / codice / cunsiglii / dati da questu articulu. Leghjendu o aduprendu stu materiale in ogni modu, assumete a rispunsabilità per tutte e cunsequenze di queste azioni. I pussibuli cunsequenze includenu:

  • SSD NVMe fritti croccanti.
  • Risorse di registrazione cumpletamente utilizzate è fallimentu di unità SSD.
  • Perdita cumpleta di tutti i dati nantu à tutte e unità, cumprese e copie di salvezza.
  • Hardware di computer difettu.
  • Perdu tempu, nervi è soldi.
  • Qualchese altre cunsequenze chì ùn sò micca listate sopra.

Ferru

Disponibile eranu:

Scheda madre da circa 2013 cù chipset Z87, cumpletu cù Intel Core i7 / Haswell.

  • Processore 4 core, 8 fili
  • 32 GB di RAM DDR3
  • 1 x 16 o 2 x 8 PCIe 3.0
  • 1 x 4 + 1 x 1 PCIe 2.0
  • 6 x 6 GBps connettori SATA 3

L'adattatore SAS LSI SAS9211-8I lampò in modalità IT / HBA. U firmware RAID hè statu rimpiazzatu intenzionalmente cù firmware HBA per:

  1. Pudete scaccià stu adattatore in ogni mumentu è rimpiazzà cù qualsiasi altru chì avete scontru.
  2. TRIM/Discard hà travagliatu nurmale nantu à i dischi, perchè ... in u firmware RAID questi cumandamenti ùn sò micca supportati in tuttu, è l'HBA, in generale, ùn importa micca ciò chì cumandamenti sò trasmessi nantu à u bus.

Dischi duru - 8 pezzi di HGST Travelstar 7K1000 cù una capacità di 1 TB in un fattore di forma 2.5, cum'è per i laptops. Queste unità eranu prima in un array RAID 6. Anu ancu avè un usu in u novu sistema. Per almacenà backups lucali.

In più aghjustatu:

6 pezzi SATA SSD mudellu Samsung 860 QVO 2TB. Questi SSD necessitanu un grande voluminu, a presenza di una cache SLC, affidabilità è un prezzu bassu eranu desiderati. U supportu per scartà / zero era necessariu, chì hè verificatu da a linea in dmesg:

kernel: ata1.00: Enabling discard_zeroes_data

2 pezzi di NVMe SSD mudellu Samsung SSD 970 EVO 500GB.

Per questi SSD, a velocità di lettura / scrittura aleatoria è a capacità di risorse per i vostri bisogni sò impurtanti. Radiatore per elli. Necessariamente. Assolutamente. Altrimenti, fritti finu à croccante durante a prima sincronizazione RAID.

Adattatore StarTech PEX8M2E2 per 2 SSD NVMe installati in slot PCIe 3.0 8x. Questu, di novu, hè solu un HBA, ma per NVMe. Differisce da l'adattatori economici in quantu ùn hè micca bisognu di supportu di bifurcazione PCIe da a scheda madre per via di a presenza di un switch PCIe integratu. Funcionà ancu in u sistema più anticu cù PCIe, ancu s'ellu hè un slot x1 PCIe 1.0. Naturalmente, à a velocità adatta. Ùn ci sò micca RAID. Ùn ci hè micca un BIOS integratu à bordu. Dunque, u vostru sistema ùn hà micca magicu imparà à boot cù NVMe, assai menu fà NVMe RAID grazia à stu dispusitivu.

Stu cumpunente era solu per a presenza di un solu 8x PCIe 3.0 gratuitu in u sistema, è, se ci sò 2 slots gratuiti, pò esse facilmente rimpiazzati cù dui centesimi PEX4M2E1 o analoghi, chì ponu esse compru in ogni locu à u prezzu di 600. rubli.

U rifiutu di ogni tipu di hardware o di chipset / BIOS RAID integrati hè statu fattu deliberatamente, per pudè rimpiazzà cumplettamente u sistema tutale, cù l'eccezzioni di i SSD / HDD stessi, mentre priservendu tutte e dati. Ideale, cusì chì pudete salvà ancu u sistema operatore installatu quandu si move à un hardware completamente novu / sfarente. A cosa principal hè chì ci sò porti SATA è PCIe. Hè cum'è un CD live o un drive flash bootable, solu assai veloce è un pocu voluminoso.

UmorismoAltrimenti, sapete ciò chì succede - qualchì volta avete bisognu urgente di piglià l'intera matrice cun voi per piglià. Ma ùn vogliu micca perde dati. Per fà questu, tutti i media citati sò convenientemente situati nantu à i slides in i 5.25 baies di u casu standard.

Ebbè, è, sicuru, per sperimentà diversi metudi di cache SSD in Linux.

I raids di hardware sò noiosi. Accende. O funziona o ùn hè micca. È cù mdadm ci sò sempre opzioni.

Soffiu

Nanzu, Debian 8 Jessie hè stata installata nantu à u hardware, chì hè vicinu à EOL. RAID 6 hè stata assemblata da i HDD sopra citati accoppiati cù LVM. Eseguiva macchine virtuali in kvm/libvirt.

Perchè L'autore hà una sperienza adatta in a creazione di unità flash SATA / NVMe bootable portable, è ancu, per ùn rompe u mudellu abituale, Ubuntu 18.04 hè statu sceltu cum'è u sistema di destinazione, chì hè digià abbastanza stabilizatu, ma hà ancu 3 anni di sustegnu in u futuru.

U sistema citatu cuntene tutti i driver hardware chì avemu bisognu fora di a scatula. Ùn avemu micca bisognu di software o driver di terzu.

Preparendu l'installazione

Per installà u sistema avemu bisognu di Ubuntu Desktop Image. U sistema di u servitore hà una sorta di installatore vigoroso, chì mostra una indipendenza eccessiva chì ùn pò micca esse disattivata shoving the partition system UEFI in unu di i dischi, spoiling all the beauty. Per quessa, hè stallatu solu in u modu UEFI. Ùn offre micca opzioni.

Ùn simu cuntenti cù questu.

PerchèSfurtunatamente, u boot UEFI hè assai pocu cumpatibile cù u software di boot RAID, perchè Nimu ùn ci offre riservazioni per a partizione UEFI ESP. Ci sò ricette in Internet chì suggerenu di mette a particione ESP in una unità flash in un portu USB, ma questu hè un puntu di fallimentu. Ci sò ricette chì utilizanu u software mdadm RAID 1 cù a versione di metadata 0.9 chì ùn impediscenu micca chì u UEFI BIOS veda sta partizione, ma questu vive finu à u mumentu felice quandu u BIOS o un altru sistema operatore in hardware scrive qualcosa à l'ESP è si scurdate di sincronizà. à altri specchi.

Inoltre, u boot UEFI dipende da a NVRAM, chì ùn si move micca cù i dischi à u novu sistema, perchè face parte di a scheda madre.

Dunque, ùn reinventeremu micca una nova rota. Avemu digià una bicicletta di missiavu pronta, testata in u tempu, issa chjamata Legacy / BIOS boot, chì porta u fieru nome di CSM in sistemi compatibili UEFI. Pigliaremu solu da u scaffale, lubricate, pompate i pneumatici è sguassate cù un pannu umitu.

A versione desktop di Ubuntu ùn pò ancu esse installata bè cù u bootloader Legacy, ma quì, cum'è dicenu, almenu ci sò opzioni.

È cusì, cullemu u hardware è carica u sistema da u Ubuntu Live bootable flash drive. Avemu bisognu di scaricà i pacchetti, cusì avemu stallatu a reta chì travaglia per voi. Se ùn funziona micca, pudete caricate i pacchetti necessarii nantu à una unità flash in anticipu.

Andemu in l'ambiente Desktop, lanciamu l'emulatore di terminal, è andemu:

#sudo bash

Cumu…?A linea sopra hè u trigger canonicu per holiwars nantu à sudo. C bоpiù opportunità venenu èоrispunsabilità maiò. A quistione hè se pudete piglià nantu à sè stessu. Parechje persone pensanu chì l'usu di sudo in questu modu hè almenu micca attentu. Tuttavia:

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

Perchè micca ZFS ...?Quandu installemu u software in u nostru urdinatore, essenzialmente prestemu u nostru hardware à i sviluppatori di stu software per guidà.
Quandu avemu fiducia in stu software cù a sicurità di i nostri dati, pigghiamu un prestitu uguale à u costu di restaurà questi dati, chì avemu da pagà un ghjornu.

Da questu puntu di vista, ZFS hè una Ferrari, è mdadm + lvm hè più cum'è una bicicletta.

Sugettitivamente, l'autore preferisce prestu una bicicletta à creditu à individui scunnisciuti invece di una Ferrari. Quì, u prezzu di u prublema ùn hè micca altu. Ùn ci hè bisognu di diritti. Più simplice di e regule di trafficu. U parcheghju hè liberu. A capacità cross-country hè megliu. Pudete sempre attaccà i gammi à una bicicletta, è pudete riparà una bicicletta cù e vostre mani.

Perchè allora BTRFS...?Per avvià u sistema operatore, avemu bisognu di un sistema di fugliale chì hè supportatu in Legacy / BIOS GRUB fora di a scatula, è à u stessu tempu sustene snapshots live. Avemu aduprà per a partizione /boot. Inoltre, l'autore preferisce aduprà sta FS per / (root), senza scurdà di nutà chì per qualsiasi altru software pudete creà partizioni separati in LVM è muntate in i cartulari necessarii.

Ùn guardemu micca imaghjini di macchine virtuali o basa di dati nantu à questu FS.
Questa FS serà usata solu per creà snapshots di u sistema senza disattivà è poi trasferisce queste snapshots à un discu di salvezza utilizendu manda / riceve.

Inoltre, l'autore generalmente preferisce mantene un minimu di software direttamente nantu à u hardware è eseguisce tutti l'altri software in macchine virtuali chì utilizanu cose cum'è trasmette GPU è controller PCI-USB Host à KVM via IOMMU.

L'unica cosa chì resta nantu à u hardware sò l'almacenamiento di dati, a virtualizazione è a copia di salvezza.

Sè avete fiducia in ZFS più, allora, in principiu, per l'applicazione specificata sò intercambiabili.

Tuttavia, l'autore ignora deliberatamente e funzioni integrate di mirroring / RAID è redundancy chì ZFS, BRTFS è LVM anu.

Cum'è un argumentu supplementu, BTRFS hà a capacità di trasfurmà e scritture aleatorii in sequenziali, chì hà un effettu estremamente pusitivu nantu à a veloce di sincronizà snapshots / backups in u HDD.

Scannà tutti i dispositi:

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

Fighjemu un ochju intornu:

#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

Disposizione di discu

SSD NVMe

Ma ùn li marcaremu in ogni modu. Tuttu u listessu, u nostru BIOS ùn vede micca sti unità. Dunque, andaranu interamente à u software RAID. Ùn avemu mancu creà sezioni quì. Se vulete seguità u "canon" o "principalmente", crea una grande partizione, cum'è un HDD.

SATA HDD

Ùn ci hè bisognu di inventà qualcosa di speciale quì. Creemu una sezione per tuttu. Creemu una particione perchè u BIOS vede sti dischi è pò ancu pruvà à boot da elli. Puderemu ancu installà GRUB nantu à sti dischi più tardi per chì u sistema pò fà di colpu.

#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

SSD SATA

Hè quì chì e cose diventanu interessanti per noi.

Prima, i nostri dischi sò 2 TB di dimensione. Questu hè in u intervallu accettabile per MBR, chì hè ciò chì useremu. Se necessariu, pò esse rimpiazzatu cù GPT. I dischi GPT anu una strata di cumpatibilità chì permette à i sistemi compatibili MBR di vede i primi partizioni 4 si sò situati in i primi 2 terabytes. A cosa principal hè chì a partizione di boot è a partizione bios_grub in questi dischi deve esse à u principiu. Questu permette ancu di boot da GPT Legacy / BIOS drives.

Ma questu ùn hè micca u nostru casu.

Quì avemu da creà dui sezzioni. U primu serà 1 GB in grandezza è utilizatu per RAID 1 / boot.

U sicondu serà utilizatu per RAID 6 è pigliarà tuttu u spaziu liberu rimanente eccettu per una piccula zona micca allocata à a fine di u discu.

Chì ghjè sta zona micca marcata?Sicondu e fonti nantu à a reta, i nostri SSD SATA anu à bordu un cache SLC dinamicamente espansibile chì varieghja da 6 à 78 gigabytes. Avemu 6 gigabytes "for free" per via di a diffarenza trà "gigabytes" è "gibibytes" in a scheda di dati di l'unità. I 72 gigabytes restanti sò attribuiti da u spaziu inutilizatu.

Quì si deve esse nutatu chì avemu un cache SLC, è u spaziu hè occupatu in modu 4 bit MLC. Chì per noi significa in modu efficace chì per ogni 4 gigabyte di spaziu liberu avemu solu 1 gigabyte di cache SLC.

Multiplicà 72 gigabyte per 4 è uttene 288 gigabyte. Questu hè u spaziu liberu chì ùn avemu micca marcatu per permette à e unità di fà un usu pienu di a cache SLC.

Cusì, riceveremu in modu efficace finu à 312 gigabytes di cache SLC da un totale di sei unità. Di tutti i dischi, 2 seranu utilizati in RAID per a redundanza.

Questa quantità di cache ci permetterà raramente in a vita reale di scontru una situazione induve una scrittura ùn và à a cache. Questu cumpensu assai bè u più tristu svantaghju di a memoria QLC - a velocità di scrittura estremamente bassa quandu e dati sò scritti sguassendu a cache. Se i vostri carichi ùn currispondenu micca à questu, allora vi ricumandemu chì pensate duramente quantu durà u vostru SSD sottu una tale carica, tenendu in contu u TBW da a scheda di dati.

#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

Crià Arrays

Prima, avemu bisognu di rinominà a macchina. Questu hè necessariu perchè u nome di l'ospite hè parte di u nome di l'array in un locu in mdadm è affetta qualcosa in qualchì locu. Di sicuru, l'arrays ponu esse rinominati più tardi, ma questu hè un passu innecessariu.

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

SSD NVMe

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

Perchè -assume-pulite...?Per evità l'inizializazione di array. Per i dui livelli RAID 1 è 6 questu hè validu. Tuttu pò travaglià senza inizializazione s'ellu hè un novu array. Inoltre, l'inizializazione di l'array SSD dopu a creazione hè una perdita di risorse TBW. Utilizemu TRIM / DISCARD induve pussibule in array SSD assemblati per "inizializà".

Per i matrici SSD, RAID 1 DISCARD hè supportatu fora di a scatula.

Per SSD RAID 6 DISCARD arrays, duvete attivà in i paràmetri di u modulu di u kernel.

Questu deve esse fattu solu se tutti i SSD utilizati in u nivellu 4/5/6 arrays in stu sistema anu supportu di travagliu per discard_zeroes_data. Calchì volta vi scontru stranu drives chì dicenu à u kernel chì sta funzione hè supportata, ma in fattu ùn hè micca quì, o a funzione ùn hè micca sempre travagliatu. À u mumentu, u supportu hè dispunibule quasi in ogni locu, però, ci sò vechji unità è firmware cù errori. Per quessa, u supportu DISCARD hè disattivatu per difettu per RAID 6.

Attenzione, u cumandimu seguitu distruggerà tutte e dati nantu à l'unità NVMe "inizializandu" l'array cù "zeri".

#blkdiscard /dev/md0

Se qualcosa va male, pruvate à specificà un passu.

#blkdiscard --step 65536 /dev/md0

SSD SATA

#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

Perchè cusì grande...?L'aumentu di u chunk-size hà un effettu pusitivu nantu à a velocità di lettura aleatoria in blocchi finu à chunk-size inclusive. Questu succede perchè una operazione di a dimensione adatta o più chjuca pò esse cumpletata interamente in un solu dispositivu. Dunque, l'IOPS da tutti i dispositi hè riassuntu. Sicondu statistiche, 99% di IO ùn supera 512K.

RAID 6 IOPS per scrittura sempre menu o uguale à l'IOPS di una unità. Quandu, cum'è una lettura aleatoria, IOPS pò esse parechje volte più grande di quellu di una unità, è quì a dimensione di u bloccu hè di primura impurtante.
L'autore ùn vede micca u puntu di pruvà à ottimisà un paràmetru chì hè male in RAID 6 by-design è invece ottimisimu ciò chì RAID 6 hè bonu.
Cumpensaremu a povira scrittura aleatoria di RAID 6 cù una cache NVMe è trucchi di thin-provisioning.

Ùn avemu micca ancu attivatu DISCARD per RAID 6. Allora ùn avemu micca "inizializà" sta matrice per avà. Avemu da fà questu dopu, dopu avè installatu u SO.

SATA HDD

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

LVM nantu à NVMe RAID

Per a rapidità, vulemu mette u sistema di fugliale radicali in NVMe RAID 1 chì hè /dev/md0.
Tuttavia, avemu sempre bisognu di sta matrice rapida per altri bisogni, cum'è swap, metadata è LVM-cache è LVM-thin metadata, cusì creeremu un LVM VG nantu à questu array.

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

Creemu una partizione per u sistema di schedarii radicali.

#lvcreate -L 128G --name root root

Creemu una partizione per scambià secondu a dimensione di a RAM.

#lvcreate -L 32G --name swap root

installazione OS

In tuttu, avemu tuttu ciò chì hè necessariu per installà u sistema.

Lanciate l'assistente di installazione di u sistema da l'ambiente Ubuntu Live. Installazione normale. Solu in u stadiu di selezzione di discu per a stallazione, avete bisognu di specificà i seguenti:

  • /dev/md1, - puntu di muntagna /boot, FS - BTRFS
  • /dev/root/root (aka /dev/mapper/root-root), - puntu di muntagna / (root), FS - BTRFS
  • /dev/root/swap (aka /dev/mapper/root-swap), - aduprà cum'è partizione di swap
  • Installa u bootloader in /dev/sda

Quandu selezziunate BTRFS cum'è u sistema di fugliale radicali, l'installatore creà automaticamente dui volumi BTRFS chjamati "@" per / (radica), è "@home" per /home.

Cuminciamu a stallazione ...

A stallazione finisce cù una finestra di dialogu modale chì indica un errore in l'installazione di u bootloader. Sfortunatamente, ùn puderete micca esce da stu dialogu cù i mezi standard è cuntinuà a stallazione. Scugnemu da u sistema è accede di novu, finendu in un desktop Ubuntu Live pulito. Aprite u terminal, è torna:

#sudo bash

Crea un ambiente chroot per cuntinuà a stallazione:

#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

Cunfiguremu a reta è u nome d'ospite in chroot:

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

Andemu in l'ambiente chroot:

#chroot /mnt/chroot

Prima di tuttu, daremu i pacchetti:

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

Cuntrollamu è riparà tutti i pacchetti chì sò stati installati stortu per via di l'installazione incompleta di u sistema:

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

Se qualcosa ùn funziona, pudete avè bisognu di edità prima /etc/apt/sources.list

Ajustemu i paràmetri per u modulu RAID 6 per attivà TRIM / DISCARD:

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

Facciamu un pocu i nostri arrays:

#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

Chì era..?Avemu creatu un inseme di regule udev chì farà u seguente:

  • Stabilite a dimensione di u cache di bloccu per RAID 2020 per esse adattatu per 6. U valore predeterminatu, pare, ùn hè micca cambiatu da a creazione di Linux, è ùn hè micca adattatu per un bellu pezzu.
  • Riserva un minimu di IO per a durata di i cuntrolli di array / sincronizzazioni. Questu hè per prevene i vostri arrays da esse chjappu in un statu di sincronizazione eterna sottu carica.
  • Limite l'IO massimu durante i cuntrolli / sincronizazione di arrays. Questu hè necessariu per chì a sincronizazione / verificazione di i RAID SSD ùn fritte micca e vostre unità à un crisp. Questu hè soprattuttu veru per NVMe. (Ricurdate di u radiatore? Ùn era micca scherzu.)
  • Proibite i dischi di piantà a rotazione di spindle (HDD) via APM è stabilisce u timeout di sonnu per i controller di discu à 7 ore. Pudete disattivà completamente l'APM se i vostri unità ponu fà (-B 255). Cù u valore predeterminatu, i drive si fermanu dopu à cinque seconde. Allora l'OS vole resettate a cache di u discu, i dischi giraranu di novu, è tuttu ricuminciarà di novu. I dischi anu un numeru massimu limitatu di rotazioni di spindle. Un ciclu predeterminatu cusì simplice pò facilmente tumbà i vostri dischi in un paru d'anni. Ùn sò micca tutti i discu soffrenu di questu, ma i nostri sò "laptop", cù i paràmetri predeterminati adattati, chì facenu chì u RAID pare un mini-MAID.
  • Installa readahead nantu à i dischi (rotanti) 1 megabyte - dui blocchi consecutivi / chunk RAID 6
  • Disattivate a lettura in avanti nantu à i matrici stessi.

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

Perchè hè questu ..?Cercheremu a partizione /boot per UUID. A denominazione di l'array puderia teoricamente cambià.

Cercheremu e sezioni rimanenti per nomi LVM in a notazione /dev/mapper/vg-lv, perchè identificanu partizioni abbastanza unicu.

Ùn avemu micca aduprà UUID per LVM perchè L'UUID di volumi LVM è i so snapshots ponu esse listessi.Muntà /dev/mapper/root-root.. duie volte?Iè. Esattamente. Caratteristica di BTRFS. Stu sistema di schedariu pò esse muntatu parechje volte cù diversi subvols.

A causa di sta stessa funzione, ricumandemu micca di creà snapshots LVM di volumi BTRFS attivi. Pudete avè una sorpresa quandu reboot.

Rigenerate a cunfigurazione mdadm:

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

Ajustemu i paràmetri LVM:

#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

Chì era..?Avemu attivatu l'espansione automatica di e piscine sottili LVM à ghjunghje à u 90% di u spaziu occupatu da u 5% di u voluminu.

Avemu aumentatu u numeru massimu di blocchi di cache per a cache LVM.

Avemu impeditu à LVM di circà i volumi LVM (PV) nantu à:

  • Dispositivi chì cuntenenu cache LVM (cdata)
  • i dispositi in cache cù a cache LVM, sguassendu a cache ( _corig). In questu casu, u dispositivu in cache stessu serà sempre scansatu attraversu a cache (solu ).
  • Dispositivi chì cuntenenu metadata di cache LVM (cmeta)
  • tutti i dispositi in VG cù l'imaghjini di nome. Eccu averemu l'imaghjini di discu di e macchine virtuali, è ùn vulemu micca chì LVM nantu à l'ospitu attivà volumi chì appartenenu à u SO invitatu.
  • tutti i dispusitivi in ​​VG cù u nome di salvezza. Quì averemu copie di salvezza di l'imaghjini di a macchina virtuale.
  • tutti i dispositi chì u nome finiscinu cù "gpv" (volume fisicu invitatu)

Avemu attivatu u supportu DISCARD quandu liberate u spaziu liberu in LVM VG. Attenti. Questu farà chì l'eliminazione di LV da u SSD richiede assai tempu. Questu hè sopratuttu appiicatu à SSD RAID 6. In ogni casu, secondu u pianu, avemu aduprà a pruvista magre, perchè questu ùn ci impedisce micca in tuttu.

Aghjurnà l'imagine initramfs:

#update-initramfs -u -k all

Installa è cunfigurà grub:

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

Quale discu duvete sceglie?Tutti quelli chì sò sd*. U sistema deve esse capace di boot da qualsiasi unità SATA o SSD chì funziona.

Perchè anu aghjustatu os-prober ..?Per l'indipendenza eccessiva è e mani ghjoculi.

Ùn funziona micca bè se unu di i RAID hè in un statu degradatu. Pruvate di circà l'OS in partizioni chì sò utilizati in macchine virtuali chì funzionanu nantu à questu hardware.

Sè avete bisognu, pudete lascià, ma tenite in mente tutte e sopra. Vi cunsigliu di circà ricette per sbarazzarsi di mani cattive in linea.

Cù questu avemu finitu a stallazione iniziale. Hè ora di riavvià in u sistema operativu novu installatu. Ùn vi scurdate di sguassà u live CD / USB bootable.

#exit
#reboot

Selezziunate qualsiasi di i SSD SATA cum'è u dispositivu di boot.

LVM nantu à SSD SATA

À questu puntu, avemu digià avviatu in u novu sistema operativu, cunfiguratu a reta, apt, hà apertu l'emulatore di terminal, è curria:

#sudo bash

Cuntinuemu.

"Inizializà" l'array da SATA SSD:

#blkdiscard /dev/md2

Se ùn funziona micca, pruvate:

#blkdiscard --step 65536 /dev/md2
Crea LVM VG nantu à SSD SATA:

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

Perchè un altru VG..?In fatti, avemu digià un VG chjamatu root. Perchè ùn aghjunghje micca tuttu in un VG?

Se ci sò parechji PV in un VG, allora per chì u VG sia attivatu currettamente, tutti i PV deve esse presente (in linea). L'eccezzioni hè LVM RAID, chì deliberatamente ùn usemu micca.

Vulemu veramente chì s'ellu ci hè un fallimentu (leghjite a perdita di dati) nantu à qualsiasi di l'array RAID 6, u sistema operatore s'avviarà normalmente è ci darà l'uppurtunità di risolve u prublema.

Per fà questu, à u primu livellu di astrazione, isolaremu ogni tipu di "media" fisicu in un VG separatu.

Scientificamente parlante, diverse matrici RAID appartenenu à diversi "domini di affidabilità". Ùn deve micca creà un puntu cumunu supplementu di fallimentu per elli cunglite in un VG.

A prisenza di LVM à u nivellu di "hardware" ci permetterà di taglià arbitrariamente pezzi di diverse array RAID cumminendu in modu diffirenti. Per esempiu - run à u listessu tempu bcache + LVM thin, bcache + BTRFS, LVM cache + LVM thin, una cunfigurazione ZFS cumplessa cù cache, o qualsiasi altra mistura infernale per pruvà à paragunà tuttu.

À u nivellu di "hardware", ùn avemu micca aduprà nunda altru chè boni vechji volumi LVM "grossi". L'eccezzioni à sta regula pò esse a partizione di salvezza.

Pensu chì da questu mumentu, parechji lettori avianu digià principiatu à suspettà qualcosa di a pupa di nidificazione.

LVM nantu à HDD SATA

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

Novu VG di novu ..?Vulemu veramente chì se l'array di discu chì useremu per a copia di salvezza di dati falla, u nostru sistema operatore continuarà à travaglià nurmale, mentre mantene l'accessu à e dati non-backup cum'è di solitu. Dunque, per evità i prublemi di attivazione di VG, creamu un VG separatu.

Configurazione di cache LVM

Creemu un LV in NVMe RAID 1 per aduprà cum'è un dispositivu di cache.

#lvcreate -L 70871154688B --name cache root

Perchè ci hè tantu pocu...U fattu hè chì i nostri SSD NVMe anu ancu una cache SLC. 4 gigabytes di "liberu" è 18 gigabytes di dinamica per via di u spaziu liberu occupatu in u MLC 3-bit. Quandu sta cache hè esaurita, i SSD NVMe ùn saranu micca assai più veloci di u nostru SSD SATA cù cache. In realtà, per questu mutivu, ùn hà micca sensu per noi di fà a partizione di cache LVM assai più grande di duie volte a dimensione di a cache SLC di l'unità NVMe. Per l'unità NVMe utilizati, l'autore cunsidereghja raghjone per fà 32-64 gigabytes di cache.

A dimensione di partizione data hè necessaria per urganizà 64 gigabytes di cache, metadati di cache, è copia di salvezza di metadati.

Inoltre, aghju nutatu chì dopu un chjusu di u sistema bruttu, LVM marcarà a cache sana cum'è brutta è sincronizerà di novu. Inoltre, questu serà ripetutu ogni volta chì lvchange hè utilizatu nantu à stu dispusitivu finu à chì u sistema hè riavviatu. Dunque, ricumandemu di ricreà immediatamente a cache cù u script adattatu.

Creemu un LV in SATA RAID 6 per aduprà cum'è un dispositivu in cache.

#lvcreate -L 3298543271936B --name cache data

Perchè solu trè terabyte ..?Cusì, se ne necessariu, pudete aduprà SATA SSD RAID 6 per qualchì altra necessità. A dimensione di u spaziu in cache pò esse aumentata dinamicamente, nantu à a mosca, senza firmà u sistema. Per fà questu, avete bisognu di firmà temporaneamente è riattivate a cache, ma u vantaghju distintivu di LVM-cache sopra, per esempiu, bcache hè chì questu pò esse fattu nantu à a mosca.

Creemu un novu VG per caching.

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

Andemu à creà un LV nant'à u dispusitivu cached.

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

Quì avemu pigliatu immediatamente tuttu u spaziu liberu in /dev/data/cache per chì tutte l'altri partizioni necessarii sò stati creati immediatamente in /dev/root/cache. Se avete creatu qualcosa in u locu sbagliatu, pudete spustà cù pvmove.

Creemu è attivemu a cache:

#lvcreate -y -L 64G -n cache cache /dev/root/cache
#lvcreate -y -L 1G -n cachemeta cache /dev/root/cache
#lvconvert -y --type cache-pool --cachemode writeback --chunksize 64k --poolmetadata cache/cachemeta cache/cache
#lvconvert -y --type cache --cachepool cache/cache cache/cachedata

Perchè cusì chunksize ..?Per mezu di esperimenti pratichi, l'autore hà sappiutu sapè chì u megliu risultatu hè ottinutu se a dimensione di u bloccu di cache LVM coincide cù a dimensione di u blocu magre LVM. Inoltre, più chjuca hè a dimensione, u megliu a cunfigurazione eseguisce in una registrazione aleatoria.

64k hè a dimensione minima di bloccu permessa per LVM thin.

Attenti à a scrittura..!Iè. Stu tipu di cache deferisce a sincronizazione di scrittura à u dispusitivu cache. Stu significa chi s'è u cache hè persu, vi pò perde dati nant'à u dispusitivu cached. In seguitu, l'autore vi dicerà chì misure, in più di NVMe RAID 1, ponu esse pigliate per cumpensà stu risicu.

Stu tipu di cache hè statu sceltu intenzionalmente per cumpensà a scarsa prestazione di scrittura aleatoria di RAID 6.

Cuntrollamu ciò chì avemu:

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

Solu [cachedata_corig] deve esse situatu in /dev/data/cache. Se qualcosa hè sbagliatu, allora utilizate pvmove.

Pudete disattivà a cache se ne necessariu cun un cumandamentu:

#lvconvert -y --uncache cache/cachedata

Questu hè fattu in linea. LVM simpricimenti sincronizà a cache à u discu, sguassà, è rinomina cachedata_corig torna à cachedata.

Configurazione di LVM thin

Stimemu circa quantu spaziu avemu bisognu per i metadati sottili di LVM:

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

Arrotonda finu à 4 gigabyte: 4294967296B

Multiplicà per dui è aghjunghje 4194304B per LVM PV metadata: 8594128896B
Creemu una partizione separata nantu à NVMe RAID 1 per mette i metadati sottili di LVM è a so copia di salvezza nantu à questu:

#lvcreate -L 8594128896B --name images root

Perchè..?Quì a quistione pò esse: perchè mette LVM thin metadata separatamente si sarà sempre in cache in NVMe è travaglià rapidamente.

Ancu s'è a rapidità hè impurtante quì, hè luntanu da u mutivu principale. A cosa hè chì a cache hè un puntu di fallimentu. Qualcosa puderia succede, è se a metadata sottile di LVM hè in cache, pruvucarà tuttu per esse persu. Senza metadata cumpleta, serà quasi impussibile di assemblà volumi sottili.

Trascendendu i metadata à un voluminu separatu non-cache, ma veloce, guarantimu a sicurità di i metadata in casu di perdita di cache o corruzzione. In questu casu, tutti i danni causati da a perdita di cache seranu localizzati in volumi sottili, chì simplificà u prucessu di ricuperazione per ordini di grandezza. Cù una alta probabilità, questi danni seranu restaurati cù logs FS.

Inoltre, se una snapshot di un voluminu sottile hè stata presa prima, è dopu chì a cache hè stata sincronizata cumplettamente almenu una volta, allora, per via di u disignu internu di LVM thin, l'integrità di l'istantanea serà garantita in casu di perdita di cache. .

Creemu un novu VG chì serà rispunsevuli di thin-provisioning:

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

Creemu una piscina:

#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T images/thin-pool
Perchè -Z yIn più di ciò chì questu modu hè in realtà destinatu - per impedisce chì e dati da una macchina virtuale sguassate à un'altra macchina virtuale quandu si ridistribuisce u spaziu - u zeroing hè ancu utilizatu per aumentà a velocità di scrittura aleatoria in blocchi più chjuchi di 64k. Ogni scrittura menu di 64k in una zona precedentemente micca allocata di u voluminu sottile diventerà 64K allineatu à u bordu in a cache. Questu permetterà l'operazione per esse realizatu interamente à traversu u cache, bypassing u dispusitivu cached.

Movemu i LV à i PV currispondenti:

#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

Cuntrollamu:

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

Creemu un voluminu magre per i testi:

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

Stallaremu pacchetti per teste è monitoraghju:

#apt-get install sysstat fio

Eccu cumu pudete osservà u cumpurtamentu di a nostra cunfigurazione di almacenamiento in tempu reale:

#watch 'lvs --rows --reportformat basic --quiet -ocache_dirty_blocks,cache_settings cache/cachedata && (lvdisplay cache/cachedata | grep Cache) && (sar -p -d 2 1 | grep -E "sd|nvme|DEV|md1|md2|md3|md0" | grep -v Average | sort)'

Eccu cumu pudemu pruvà a nostra cunfigurazione:

#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

Attentu! Risorsa!Stu codice hà da eseguisce 36 teste diverse, ognuna chì dura 4 seconde. A mità di e teste sò per a registrazione. Pudete arregistrà assai in NVMe in 4 seconde. Finu à 3 gigabyte per seconda. Dunque, ogni corsa di testi di scrittura pò manghjà finu à 216 gigabyte di risorse SSD da voi.

Lettura è scrittura mischiata ?Iè. Hè sensu per eseguisce e teste di lettura è scrittura separatamente. Inoltre, hè sensu per assicurà chì tutti i cache sò sincronizati in modu chì una scrittura precedente ùn hà micca affettatu a lettura.

I risultati varieranu assai durante u primu lanciamentu è i successivi cum'è a cache è u voluminu sottile si riempie, è ancu secondu chì u sistema hà sappiutu sincronizà i cache pieni durante l'ultimu lanciu.

Frà l'altri cose, ricumandemu di misurà a vitezza nantu à un voluminu magre già pienu da quale hè stata appena presa una foto. L'autore hà avutu l'uppurtunità di osservà cumu a scrittura aleatoria accelerà bruscamente immediatamente dopu a creazione di a prima snapshot, soprattuttu quandu a cache ùn hè micca cumplettamente piena. Questu succede per via di a semantica di scrittura di copia in scrittura, l'allineamentu di u cache è i blocchi di volumi sottili, è u fattu chì e scritture aleatorii à RAID 6 si trasformanu in letture aleatorii da RAID 6 seguite da scrive à a cache. In a nostra cunfigurazione, a lettura aleatoria da RAID 6 hè finu à 6 volte (u numeru di SSD SATA in l'array) più veloce di scrittura. Perchè i blocchi per CoW sò attribuiti sequenziale da una piscina sottile, allora a registrazione, per a maiò parte, diventa ancu sequenziale.

Tramindui sti funziunalità pò esse usatu à u vostru vantaghju.

Cache istantanee "coerenti".

Per riduce u risicu di perdita di dati in casu di dannu / perdita di cache, l'autore prupone di intruduce a pratica di rotazione di snapshots per guarantiscenu a so integrità in questu casu.

Prima, perchè i metadati di u voluminu magre residenu in un dispositivu uncached, i metadati seranu coherenti è e pussibuli pèrdite seranu isolate in blocchi di dati.

U ciculu di rotazione di i snapshot chì seguita guarantisci l'integrità di e dati in l'istantanee in casu di perdita di cache:

  1. Per ogni voluminu sottile cù u nome <name>, crea una snapshot cù u nome <name>.cached
  2. Fixemu u sogliu di migrazione à un valore altu raghjone: #lvchange --quiet --cachesettings "migration_threshold=16384" cache/cachedata
  3. In u ciclu cuntrollemu u numeru di blocchi brutti in a cache: #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' finu à ottene zero. Se u cero manca per troppu longu, pò esse creatu da cambià temporaneamente u cache à u modu di scrittura. Tuttavia, tenendu in contu e caratteristiche di velocità di i nostri array SSD SATA è NVMe, è ancu di a so risorsa TBW, puderà catturà rapidamente u mumentu senza cambià u modu di cache, o u vostru hardware manghjarà cumplettamente a so risorsa sana. uni pochi di ghjorni. A causa di limitazioni di risorse, u sistema hè, in principiu, incapace di esse sottu à 100% di carica di scrittura tuttu u tempu. I nostri SSD NVMe sottu 100% di carica di scrittura esauriranu completamente a risorsa 3-4 ghjorni. I SSD SATA durà solu duie volte più. Per quessa, assumeremu chì a maiò parte di a carica va à a lettura, è avemu scontri relativamente brevi di attività estremamente alta cumminata cù una carica bassa in media per a scrittura.
  4. Appena avemu pigliatu (o fattu) un cero, rinominamu <name>.cached à <name>.committed. U vechju <name>.committed hè sguassatu.
  5. Opcionalmente, se u cache hè 100% pienu, pò esse ricreatu da un script, cusì sguassate. Cù un cache mezzu viotu, u sistema travaglia assai più veloce quandu scrive.
  6. Pone u limitu di migrazione à zero: #lvchange --quiet --cachesettings "migration_threshold=0" cache/cachedata Questu impediscerà temporaneamente a cache di sincronizà cù i media principali.
  7. Aspittemu finu à chì assai cambiamenti s'acumulanu in a cache #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' o u timer si spegnerà.
  8. Ripetemu di novu.

Perchè difficultà cù u sogliu di migrazione...?A cosa hè chì in a pratica reale, una registrazione "aleatoriu" ùn hè micca cumplettamente casuale. Se avemu scrittu qualcosa à un settore di 4 kilobytes in grandezza, ci hè una alta probabilità chì in i prossimi minuti un record serà fattu à u stessu o unu di i settori vicini (+- 32K).

Fixendu u limitu di migrazione à cero, posponemu a sincronizazione di scrittura in u SSD SATA è aggregate parechji cambiamenti à un bloccu 64K in a cache. Questu salva significativamente a risorsa di SATA SSD.

Induve hè u codice..?Sfurtunatamente, l'autore si cunsidereghja insufficiente cumpetente in u sviluppu di scripts bash perchè hè 100% autodidatta è pratica u sviluppu guidatu da "google", per quessa crede chì u codice terribili chì esce da e so mani ùn deve esse usatu da nimu. altru.

Pensu chì i prufessiunali in questu campu seranu capace di rapprisintà indipindentamente tutta a logica descritta sopra, se ne necessariu, è, forsi, ancu bè cuncepimentu cum'è un serviziu di sistema, cum'è l'autore hà pruvatu à fà.

Un tali schema di rotazione di snapshot simplice ci permetterà micca solu di avè constantemente una snapshot cumplettamente sincronizzata nantu à u SSD SATA, ma ci permetterà ancu, utilizendu l'utilità thin_delta, di sapè quale blocchi sò stati cambiati dopu a so creazione, è cusì localizà i danni nantu à i volumi principali, simplificà assai a ricuperazione.

TRIM/DISCARD in libvirt/KVM

Perchè l'almacenamiento di dati serà utilizatu per KVM chì esegue libvirt, allora saria una bona idea d'insignà à i nostri VMs micca solu per piglià u spaziu liberu, ma ancu per liberà ciò chì ùn hè più necessariu.

Questu hè fattu da l'emulazione di u supportu TRIM / DISCARD nantu à i dischi virtuali. Per fà questu, avete bisognu di cambià u tipu di cuntrollu in virtio-scsi è edità u 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>

Tali DISCARD da i OS di l'ospiti sò processati currettamente da LVM, è i blocchi sò liberati currettamente in u cache è in a piscina fina. In u nostru casu, questu succede principarmenti in una manera ritardata, quandu sguassate a prossima snapshot.

Backup BTRFS

Aduprate scripts pronti cù estremu prudenza è à u so propiu risicu. L'autore hà scrittu stu codice ellu stessu è solu per ellu stessu. Sò sicuru chì parechji utilizatori Linux sperimentati anu arnesi simili, è ùn ci hè bisognu di copià quelli di l'altru.

Creemu un voluminu nantu à u dispusitivu di salvezza:

#lvcreate -L 256G --name backup backup

Formatemu in BTRFS:

#mkfs.btrfs /dev/backup/backup

Creemu punti di muntagna è muntemu e sottosezzioni radicali di u sistema di fugliale:

#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

Creemu repertorii per i backups:

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

Creemu un repertoriu per i script di salvezza:

#mkdir /root/btrfs-backup

Copiemu u script:

Un saccu di codice bash spaventoso. Aduprate à u vostru propiu risicu. Ùn scrive micca lettere arrabbiate à l'autore ...#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

Chì faci ancu ..?Contene un inseme di cumandamenti simplici per creà snapshots BTRFS è copià à un altru FS utilizendu BTRFS mandà / riceve.

U primu lanciu pò esse relativamente longu, perchè ... À u principiu, tutti i dati seranu copiati. Ulteriori lanciamenti seranu assai veloci, perchè ... Solu i cambiamenti seranu copiati.

Un altru script chì metteremu in cron:

Qualchì più codice bash#cat >/root/btrfs-backup/cron-daily.sh << EOF
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

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

BACKUP_SCRIPT="$SCRIPT_DIR/btrfs-backup.sh"
RETENTION="-60 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

Chì face..?Crea è sincronizza snapshots incrementali di i volumi BTRFS listati nantu à a copia di salvezza FS. Dopu questu, sguassate tutte e foto create 60 ghjorni fà. Dopu à u lanciu, i snapshots datati di i volumi listati appariscenu in i subdirectory /backup/btrfs/back/remote/.

Demu i diritti di esecuzione di codice:

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

Cuntrollamu è mettemu in u 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 thin backup

Creemu una piscina fina nantu à u dispusitivu di salvezza:

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

Installemu ddrescue, perchè... scripts utilizanu stu strumentu:

#apt-get install gddrescue

Creemu un cartulare per i scripts:

#mkdir /root/lvm-thin-backup

Copiemu i script:

Un saccu di bash à l'internu ...#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

Chì faci...?Contene un inseme di cumandamenti per manipulà i snapshots sottili è sincronizà a diffarenza trà dui snapshots sottili ricevuti via thin_delta à un altru dispositivu di bloccu utilizendu ddrescue è blkdiscard.

Un altru script chì metteremu in cron:

Un pocu di più bash#cat >/root/lvm-thin-backup/cron-daily.sh << EOF
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

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

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

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

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

EOF

Chì faci...?Utiliza l'script precedente per creà è sincronizà e copie di salvezza di i volumi sottili elencati. U script lasciarà snapshots inattivi di i volumi listati, chì sò necessarii per seguità i cambiamenti da l'ultima sincronizazione.

Stu script deve esse editatu, specificendu a lista di volumi sottili per i quali deve esse fatte copie di salvezza. I nomi dati sò solu per scopi illustrativi. Se vulete, pudete scrive un script chì sincronizà tutti i volumi.

Demu i diritti:

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

Cuntrollamu è mettemu in u 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

U primu lanciu serà longu, perchè ... volumi sottili seranu cumplettamente sincronizzati copiendu tuttu u spaziu utilizatu. Grazie à i metadati sottili di LVM, sapemu chì blocchi sò in realtà in usu, cusì solu i blocchi di volumi sottili usati seranu copiati.

I corsi successivi copianu i dati in modu incrementale grazie à u seguimentu di u cambiamentu via metadata sottile LVM.

Videmu ciò chì hè accadutu:

#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

Chì ci hà da fà cù i pupi di nidificazione?

Hè assai prubabile, datu chì i volumi lògichi LVM LV ponu esse volumi fisici LVM PV per altri VG. LVM pò esse recursive, cum'è pupi di nidificazione. Questu dà a LVM una flessibilità estrema.

PS

In u prossimu articulu, pruveremu di utilizà parechji sistemi di almacenamentu mobili simili / KVM cum'è a basa per creà un cluster di almacenamiento / vm geo-distribuitu cù redundanza in parechji cuntinenti utilizendu desktop di casa, Internet di casa è rete P2P.

Source: www.habr.com

Add a comment