Ի՞նչ ընդհանրություններ ունեն LVM-ն և Matryoshka-ն:

Բարի օր:
Ես կցանկանայի համայնքի հետ կիսվել KVM-ի համար տվյալների պահպանման համակարգ կառուցելու իմ գործնական փորձով, օգտագործելով md RAID + LVM:

Ծրագիրը կներառի.

  • Md RAID 1-ի կառուցում NVMe SSD-ից:
  • md RAID 6-ի հավաքում SATA SSD-ից և սովորական կրիչներից:
  • TRIM/DISCARD գործողության առանձնահատկությունները SSD RAID 1/6-ում:
  • Բեռնվող md RAID 1/6 զանգվածի ստեղծում ընդհանուր սկավառակների վրա:
  • Համակարգի տեղադրում NVMe RAID 1-ում, երբ BIOS-ում NVMe աջակցություն չկա:
  • Օգտագործելով LVM քեշ և LVM բարակ:
  • Օգտագործելով BTRFS snapshots և ուղարկեք/ստացեք պահուստավորման համար:
  • Օգտագործելով LVM բարակ snapshots և thin_delta BTRFS ոճի կրկնօրինակումների համար:

Եթե ​​դուք հետաքրքրված եք, խնդրում ենք տեսնել կատու:

Հայտարարություն

Հեղինակը որևէ պատասխանատվություն չի կրում սույն հոդվածից նյութեր/օրինակներ/կոդ/խորհուրդներ/տվյալներ օգտագործելու կամ չօգտագործելու հետևանքների համար: Այս նյութը որևէ կերպ կարդալով կամ օգտագործելով՝ դուք պատասխանատվություն եք կրում այդ գործողությունների բոլոր հետևանքների համար: Հնարավոր հետևանքները ներառում են.

  • Տապակած NVMe SSD-ներ:
  • Ամբողջովին սպառված ձայնագրման ռեսուրսը և SSD կրիչների ձախողումը:
  • Բոլոր սկավառակների վրա բոլոր տվյալների ամբողջական կորուստ, ներառյալ պահուստային պատճենները:
  • Համակարգչի անսարք սարքավորում:
  • Վատ ժամանակ, նյարդեր և փող.
  • Ցանկացած այլ հետևանք, որը վերը նշված չէ:

Iron

Հասանելի էին.

Մոտ 2013 թվականի մայր տախտակ Z87 չիպսեթով, ամբողջական Intel Core i7 / Haswell-ով:

  • Պրոցեսոր 4 միջուկ, 8 թել
  • 32 ԳԲ DDR3 RAM
  • 1 x 16 կամ 2 x 8 PCIe 3.0
  • 1 x 4 + 1 x 1 PCIe 2.0
  • 6 x 6 GBps SATA 3 միակցիչներ

SAS ադապտեր LSI SAS9211-8I-ը միացվեց IT / HBA ռեժիմին: RAID-ով միացված որոնվածը միտումնավոր փոխարինվել է HBA որոնվածով՝

  1. Դուք կարող եք ցանկացած պահի դուրս նետել այս ադապտերը և այն փոխարինել ցանկացած այլ ադապտերով, որին հանդիպել եք:
  2. TRIM/Discard-ը սովորաբար աշխատում էր սկավառակների վրա, քանի որ... RAID որոնվածում այս հրամաններն ընդհանրապես չեն աջակցվում, և HBA-ին, ընդհանուր առմամբ, չի հետաքրքրում, թե ինչ հրամաններ են փոխանցվում ավտոբուսի միջոցով:

Կոշտ սկավառակներ - 8 հատ HGST Travelstar 7K1000 1 ՏԲ տարողությամբ 2.5 ֆակտորով, ինչպես նոութբուքերի համար։ Այս կրիչներն ավելի վաղ եղել են RAID 6 զանգվածում: Դրանք նաև կիրառություն կունենան նոր համակարգում։ Տեղական կրկնօրինակները պահելու համար:

Հավելյալ ավելացվել է.

6 հատ SATA SSD մոդել Samsung 860 QVO 2TB: Այս SSD-ները պահանջում էին մեծ ծավալ, ցանկալի էր SLC քեշի առկայությունը, հուսալիությունը և ցածր գին: Պահանջվում էր մերժել/զրոյի աջակցություն, որը ստուգվում է dmesg տողով.

kernel: ata1.00: Enabling discard_zeroes_data

2 հատ NVMe SSD մոդել Samsung SSD 970 EVO 500GB.

Այս SSD-ների համար կարևոր են պատահական կարդալու/գրելու արագությունը և ձեր կարիքների համար ռեսուրսների հզորությունը: Ռադիատոր նրանց համար: Պարտադիր։ Բացարձակապես։ Հակառակ դեպքում, RAID-ի առաջին համաժամացման ժամանակ տապակել դրանք մինչև խրթխրթան:

StarTech PEX8M2E2 ադապտեր 2 x NVMe SSD-ի համար, որը տեղադրված է PCIe 3.0 8x բնիկում: Սա, կրկին, պարզապես HBA է, բայց NVMe-ի համար: Այն տարբերվում է էժան ադապտերներից նրանով, որ ներկառուցված PCIe անջատիչի առկայության պատճառով չի պահանջում PCIe bifurcation աջակցություն մայրական տախտակից։ Այն կաշխատի նույնիսկ ամենահին համակարգում PCIe-ով, նույնիսկ եթե այն x1 PCIe 1.0 բնիկ է: Բնականաբար, համապատասխան արագությամբ։ Այնտեղ RAID-ներ չկան: Ինքնաթիռում ներկառուցված BIOS չկա: Այսպիսով, ձեր համակարգը կախարդական կերպով չի սովորի բեռնել NVMe-ով, առավել ևս չի սովորի NVMe RAID-ը այս սարքի շնորհիվ:

Այս բաղադրիչը բացառապես պայմանավորված էր համակարգում միայն մեկ անվճար 8x PCIe 3.0 առկայությամբ, և եթե կան 2 անվճար սլոտներ, այն հեշտությամբ կարելի է փոխարինել երկու կոպեկ PEX4M2E1 կամ անալոգներով, որոնք կարելի է գնել ցանկացած վայրում 600 գնով։ ռուբլի։

Բոլոր տեսակի ապարատային կամ ներկառուցված չիպսեթների/BIOS RAID-ների մերժումը կատարվել է միտումնավոր, որպեսզի հնարավոր լինի ամբողջությամբ փոխարինել ամբողջ համակարգը, բացառությամբ հենց SSD/HDD-ի՝ պահպանելով բոլոր տվյալները: Իդեալում, այնպես որ դուք կարող եք պահպանել նույնիսկ տեղադրված օպերացիոն համակարգը բոլորովին նոր/տարբեր սարքավորում տեղափոխվելիս: Գլխավորն այն է, որ կան SATA և PCIe պորտեր։ Այն նման է կենդանի CD-ի կամ bootable flash drive-ի, միայն շատ արագ և մի փոքր ծավալուն:

ՀումորՀակառակ դեպքում, դուք գիտեք, թե ինչ է տեղի ունենում, երբեմն շտապ անհրաժեշտ է ամբողջ զանգվածը ձեզ հետ վերցնել, որպեսզի խլեն: Բայց ես չեմ ուզում կորցնել տվյալները: Դա անելու համար նշված բոլոր կրիչները հարմար տեղակայվում են ստանդարտ պատյանի 5.25 անցքերում գտնվող սլայդների վրա:

Դե, և, իհարկե, Linux-ում SSD քեշավորման տարբեր մեթոդների փորձարկումների համար:

Սարքավորումների արշավանքները ձանձրալի են: Միացնել այն. Այն կամ աշխատում է, կամ չի ստացվում: Իսկ mdadm-ի հետ միշտ տարբերակներ կան։

Ծրագրեր

Նախկինում Debian 8 Jessie-ն տեղադրվել էր սարքավորման վրա, որը մոտ է EOL-ին։ RAID 6-ը հավաքվել է վերը նշված HDD-ներից՝ զուգակցված LVM-ի հետ: Այն աշխատում էր վիրտուալ մեքենաներով kvm/libvirt-ով:

Որովհետեւ Հեղինակն ունի շարժական bootable SATA/NVMe ֆլեշ կրիչներ ստեղծելու համապատասխան փորձ, ինչպես նաև, որպեսզի չխախտի սովորական հարմար ձևանմուշը, որպես թիրախային համակարգ ընտրվել է Ubuntu 18.04-ը, որն արդեն բավականաչափ կայունացված է, բայց դեռ ունի 3 տարի: աջակցություն ապագայում:

Նշված համակարգը պարունակում է մեզ անհրաժեշտ բոլոր ապարատային դրայվերները առանց տուփի: Մեզ պետք չեն որևէ երրորդ կողմի ծրագրակազմ կամ դրայվեր:

Պատրաստվում է տեղադրմանը

Համակարգը տեղադրելու համար մեզ անհրաժեշտ է Ubuntu Desktop Image: Սերվերային համակարգն ունի մի տեսակ աշխույժ տեղադրող, որը ցույց է տալիս չափազանց անկախություն, որը հնարավոր չէ անջատել՝ UEFI համակարգի բաժանումը սկավառակներից մեկի վրա դնելով, փչացնելով ողջ գեղեցկությունը: Համապատասխանաբար, այն տեղադրվում է միայն UEFI ռեժիմում: Ոչ մի տարբերակ չի առաջարկում:

Սա մեզ չի գոհացնում:

Ինչու?Ցավոք, UEFI boot-ը չափազանց վատ է համատեղելի boot software RAID-ի հետ, քանի որ... Ոչ ոք մեզ չի առաջարկում վերապահումներ UEFI ESP բաժանման համար: Ինտերնետում կան բաղադրատոմսեր, որոնք առաջարկում են ESP բաժանումը տեղադրել USB պորտում ֆլեշ կրիչի վրա, բայց սա ձախողման կետ է: Կան բաղադրատոմսեր, որոնք օգտագործում են mdadm RAID 1 ծրագրաշարը մետատվյալների 0.9 տարբերակով, որոնք չեն խանգարում UEFI BIOS-ին տեսնել այս բաժանումը, բայց այն ապրում է մինչև այն երջանիկ պահը, երբ BIOS-ը կամ այլ ապարատային ՕՀ-ն ինչ-որ բան գրում է ESP-ին և մոռանում այն ​​համաժամեցնել այլի հետ: հայելիներ.

Բացի այդ, UEFI-ի բեռնումը կախված է NVRAM-ից, որը սկավառակների հետ միասին չի տեղափոխվի նոր համակարգ, քանի որ մայր տախտակի մի մասն է:

Այսպիսով, մենք նոր անիվ չենք հայտնագործի: Մենք արդեն ունենք պատրաստի, ժամանակի փորձարկված պապիկի հեծանիվ, որն այժմ կոչվում է Legacy/BIOS boot, որը կրում է CSM հպարտ անունը UEFI-ի հետ համատեղելի համակարգերում: Մենք պարզապես այն կհանենք դարակից, կյուղենք, կպցնենք անվադողերը և կսրբենք այն խոնավ շորով:

Ubuntu-ի աշխատասեղանի տարբերակը նույնպես չի կարող պատշաճ կերպով տեղադրվել Legacy bootloader-ով, բայց այստեղ, ինչպես ասում են, գոնե տարբերակներ կան։

Եվ այսպես, մենք հավաքում ենք ապարատը և բեռնում համակարգը Ubuntu Live bootable ֆլեշ կրիչից: Մենք պետք է ներբեռնենք փաթեթներ, ուստի մենք կստեղծենք այն ցանցը, որն աշխատում է ձեզ համար: Եթե ​​դա չի աշխատում, կարող եք նախապես բեռնել անհրաժեշտ փաթեթները ֆլեշ կրիչի վրա:

Մենք մտնում ենք Desktop միջավայր, գործարկում ենք տերմինալի էմուլյատորը և դուրս ենք գալիս.

#sudo bash

Ինչպե՞ս…Վերևի տողը սուդոյի մասին հոլիվարների կանոնական ձգանն է: Գ բоավելի մեծ հնարավորություններ են գալիս ևоավելի մեծ պատասխանատվություն: Հարցն այն է, թե արդյոք դուք կարող եք դա վերցնել ձեր վրա: Շատերը կարծում են, որ սուդոն այս կերպ օգտագործելը առնվազն զգույշ չէ: Այնուամենայնիվ.

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

Ինչու ոչ ZFS...Երբ մենք ծրագրակազմ ենք տեղադրում մեր համակարգչում, մենք, ըստ էության, մեր սարքավորումը տրամադրում ենք այս ծրագրաշարի մշակողներին՝ վարելու համար:
Երբ մենք վստահում ենք այս ծրագրաշարին մեր տվյալների անվտանգությունը, մենք վարկ ենք վերցնում, որը հավասար է այս տվյալների վերականգնման արժեքին, որը մի օր ստիպված կլինենք մարել:

Այս տեսանկյունից ZFS-ը Ferrari է, իսկ mdadm+lvm-ն ավելի շատ հեծանիվ է հիշեցնում։

Սուբյեկտիվորեն հեղինակը գերադասում է Ferrari-ի փոխարեն վարկով հեծանիվ տալ անհայտ անձանց: Այնտեղ թողարկման գինը բարձր չէ։ Իրավունքների կարիք չկա. Ավելի պարզ, քան երթևեկության կանոնները: Ավտոկանգառն անվճար է։ Միջերկրական կարողությունը ավելի լավ է: Դուք միշտ կարող եք ոտքեր կցել հեծանիվին, իսկ հեծանիվը կարող եք վերանորոգել ձեր սեփական ձեռքերով։

Ինչու՞ այդ դեպքում BTRFS...Օպերացիոն համակարգը բեռնելու համար մեզ անհրաժեշտ է ֆայլային համակարգ, որն ապահովված է Legacy/BIOS GRUB-ում առանց տուփի, և միևնույն ժամանակ աջակցում է կենդանի նկարներ: Մենք այն կօգտագործենք /boot բաժանման համար: Բացի այդ, հեղինակը նախընտրում է օգտագործել այս FS-ը / (արմատ) համար՝ չմոռանալով նշել, որ ցանկացած այլ ծրագրաշարի համար կարող եք ստեղծել առանձին բաժիններ LVM-ում և տեղադրել դրանք անհրաժեշտ գրացուցակներում:

Մենք չենք պահի վիրտուալ մեքենաների կամ տվյալների բազաների որևէ պատկեր այս FS-ում:
Այս FS-ը կօգտագործվի միայն համակարգի snapshot-ներ ստեղծելու համար՝ առանց այն անջատելու, և այնուհետև այս snapshot-ները փոխանցել պահուստային սկավառակի վրա՝ օգտագործելով ուղարկել/ստանալ:

Բացի այդ, հեղինակը սովորաբար նախընտրում է նվազագույնը ծրագրային ապահովում ուղղակիորեն սարքաշարի վրա պահել և գործարկել բոլոր մյուս ծրագրաշարերը վիրտուալ մեքենաներում՝ օգտագործելով GPU-ների և PCI-USB հյուրընկալող կարգավորիչների փոխանցումը KVM-ին IOMMU-ի միջոցով:

Սարքավորման վրա մնացել են միայն տվյալների պահպանումը, վիրտուալացումը և կրկնօրինակումը:

Եթե ​​դուք ավելի շատ վստահում եք ZFS-ին, ապա, սկզբունքորեն, նշված հավելվածի համար դրանք փոխարինելի են:

Այնուամենայնիվ, հեղինակը միտումնավոր անտեսում է ներկառուցված mirroring/RAID և ավելորդության առանձնահատկությունները, որոնք ունեն ZFS, BRTFS և LVM:

Որպես լրացուցիչ փաստարկ՝ BTRFS-ն ունի պատահական գրառումները հաջորդականների վերածելու հնարավորություն, ինչը չափազանց դրական է ազդում HDD-ի վրա snapshot/backup-ների համաժամացման արագության վրա։

Եկեք վերասկանավորենք բոլոր սարքերը.

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

Եկեք նայենք շուրջը.

#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

Սկավառակի դասավորություն

NVMe SSD- ն

Բայց մենք դրանք ոչ մի կերպ չենք նշի: Միեւնույն է, մեր BIOS-ը չի տեսնում այս կրիչներ: Այսպիսով, նրանք ամբողջությամբ կգնան ծրագրային RAID-ին: Մենք այնտեղ նույնիսկ բաժիններ չենք ստեղծի: Եթե ​​ցանկանում եք հետևել «կանոնին» կամ «հիմնականում», ստեղծեք մեկ մեծ բաժին, ինչպես HDD-ը:

SATA HDD

Այստեղ առանձնահատուկ բան հորինելու կարիք չկա։ Մենք կստեղծենք մեկ բաժին ամեն ինչի համար: Մենք կստեղծենք բաժանում, քանի որ BIOS-ը տեսնում է այս սկավառակները և նույնիսկ կարող է փորձել բեռնել դրանցից: Մենք նույնիսկ GRUB-ը կտեղադրենք այս սկավառակների վրա ավելի ուշ, որպեսզի համակարգը հանկարծ կարողանա դա անել:

#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

Այստեղ է, որ մեզ համար ամեն ինչ հետաքրքիր է դառնում:

Նախ, մեր կրիչներն ունեն 2 ՏԲ չափս: Սա MBR-ի համար ընդունելի տիրույթում է, ինչը մենք կօգտագործենք: Անհրաժեշտության դեպքում այն ​​կարող է փոխարինվել GPT-ով: GPT սկավառակներն ունեն համատեղելիության շերտ, որը թույլ է տալիս MBR-համատեղելի համակարգերին տեսնել առաջին 4 բաժանմունքները, եթե դրանք գտնվում են առաջին 2 տերաբայթի սահմաններում: Հիմնական բանը այն է, որ boot partition-ը և bios_grub-ը այս սկավառակների վրա պետք է լինեն սկզբում: Սա նույնիսկ թույլ է տալիս բեռնել GPT Legacy/BIOS կրիչներից:

Բայց սա մեր դեպքը չէ։

Այստեղ մենք կստեղծենք երկու բաժին: Առաջինը կլինի 1 ԳԲ չափով և կօգտագործվի RAID 1 /boot-ի համար:

Երկրորդը կօգտագործվի RAID 6-ի համար և կզբաղեցնի մնացած բոլոր ազատ տարածքը, բացառությամբ սկավառակի վերջում գտնվող փոքր չհատկացված տարածքի:

Ո՞րն է այս չնշված տարածքը:Համաձայն ցանցի աղբյուրների, մեր SATA SSD-ներն ունեն դինամիկ ընդլայնվող SLC քեշ, որը տատանվում է 6-ից մինչև 78 գիգաբայթ չափերով: Մենք ստանում ենք 6 գիգաբայթ «անվճար» սկավառակի տվյալների թերթիկում «գիգաբայթ» և «գիբիբայթ» տարբերության պատճառով: Մնացած 72 գիգաբայթը հատկացված է չօգտագործված տարածքից։

Այստեղ պետք է նշել, որ մենք ունենք SLC քեշ, և տարածքը զբաղված է 4 բիթ MLC ռեժիմով։ Ինչը մեզ համար արդյունավետորեն նշանակում է, որ յուրաքանչյուր 4 գիգաբայթ ազատ տարածության համար մենք կստանանք ընդամենը 1 գիգաբայթ SLC քեշ:

72 գիգաբայթը բազմապատկեք 4-ով և ստացեք 288 գիգաբայթ: Սա այն ազատ տարածքն է, որը մենք չենք նշի, որպեսզի թույլ տանք, որ կրիչներն ամբողջությամբ օգտագործեն SLC քեշը:

Այսպիսով, մենք արդյունավետորեն կստանանք մինչև 312 գիգաբայթ SLC քեշ ընդհանուր վեց կրիչից: Բոլոր սկավառակներից 2-ը RAID-ում կօգտագործվեն ավելորդության համար:

Քեշի այս քանակությունը մեզ թույլ կտա շատ հազվադեպ իրական կյանքում հանդիպել այնպիսի իրավիճակի, երբ գրությունը չի գնում քեշ: Սա չափազանց լավ փոխհատուցում է QLC հիշողության ամենատխուր թերությունը՝ գրելու չափազանց ցածր արագությունը, երբ տվյալները գրվում են՝ շրջանցելով քեշը: Եթե ​​ձեր բեռները չեն համապատասխանում դրան, ապա խորհուրդ եմ տալիս լավ մտածել այն մասին, թե որքան ժամանակ կծառայի ձեր SSD-ը նման ծանրաբեռնվածության տակ՝ հաշվի առնելով տվյալների թերթիկի TBW-ն:

#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

Զանգվածների ստեղծում

Նախ, մենք պետք է վերանվանենք մեքենան: Սա անհրաժեշտ է, քանի որ հյուրընկալողի անունը mdadm-ի ներսում ինչ-որ տեղ զանգվածի անվան մասն է և ինչ-որ տեղ ազդում է ինչ-որ բանի վրա: Իհարկե, զանգվածները կարող են հետագայում վերանվանվել, բայց սա ավելորդ քայլ է։

#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

Ինչու՞ -ենթադրել-մաքուր...Զանգվածների սկզբնավորումից խուսափելու համար: Երկու RAID 1 և 6 մակարդակների համար սա վավեր է: Ամեն ինչ կարող է աշխատել առանց սկզբնավորման, եթե դա նոր զանգված է: Ավելին, SSD զանգվածի ստեղծման ժամանակ սկզբնավորելը TBW ռեսուրսի վատնում է: Հնարավորության դեպքում մենք օգտագործում ենք TRIM/DISCARD հավաքված SSD զանգվածների վրա՝ դրանք «նախաձեռնելու» համար:

SSD զանգվածների համար RAID 1 DISCARD-ն ապահովված է առանց տուփի:

SSD RAID 6 DISCARD զանգվածների համար դուք պետք է այն միացնեք միջուկի մոդուլի պարամետրերում:

Դա պետք է արվի միայն այն դեպքում, եթե այս համակարգում 4/5/6 մակարդակի զանգվածներում օգտագործվող բոլոր SSD-ները աշխատանքային աջակցություն ունեն discard_zeroes_data-ին: Երբեմն հանդիպում եք տարօրինակ կրիչներ, որոնք միջուկին ասում են, որ այս ֆունկցիան աջակցվում է, բայց իրականում այն ​​չկա, կամ ֆունկցիան միշտ չէ, որ աշխատում է։ Այս պահին աջակցությունը հասանելի է գրեթե ամենուր, այնուամենայնիվ, կան հին կրիչներ և որոնվածը սխալներով: Այս պատճառով RAID 6-ի համար DISCARD աջակցությունը լռելյայն անջատված է:

Ուշադրություն, հետևյալ հրամանը կկործանի NVMe կրիչների բոլոր տվյալները՝ զանգվածը «նախաձեռնելով» «զրոյով»:

#blkdiscard /dev/md0

Եթե ​​ինչ-որ բան սխալ է, փորձեք նշել քայլը:

#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

Ինչու՞ այդքան մեծ...Հատվածի չափի մեծացումը դրական է ազդում բլոկների պատահական ընթերցման արագության վրա մինչև կտորի չափը ներառյալ: Դա տեղի է ունենում, քանի որ համապատասխան չափի կամ ավելի փոքր գործողությունը կարող է ամբողջությամբ ավարտվել մեկ սարքի վրա: Հետևաբար, բոլոր սարքերից IOPS-ն ամփոփված է: Վիճակագրության համաձայն, IO-ի 99%-ը չի գերազանցում 512K-ը:

RAID 6 IOPS մեկ գրելու համար միշտ մեկ սկավառակի IOPS-ից պակաս կամ հավասար: Երբ, որպես պատահական ընթերցում, IOPS-ը կարող է մի քանի անգամ ավելի մեծ լինել, քան մեկ սկավառակի, և այստեղ բլոկի չափը առանցքային նշանակություն ունի:
Հեղինակը իմաստ չի տեսնում փորձել օպտիմալացնել RAID 6-ի նախագծման մեջ վատ պարամետրը և փոխարենը օպտիմալացնում է այն, ինչում լավ է RAID 6-ը:
Մենք կփոխհատուցենք RAID 6-ի վատ պատահական գրությունը NVMe քեշով և բարակ տրամադրման հնարքներով:

Մենք դեռ չենք միացրել DISCARD-ը RAID 6-ի համար: Այսպիսով, մենք առայժմ չենք «նախաձեռնարկի» այս զանգվածը: Մենք դա կանենք ավելի ուշ՝ ՕՀ-ն տեղադրելուց հետո:

SATA HDD

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

LVM NVMe RAID-ում

Արագության համար մենք ցանկանում ենք արմատային ֆայլային համակարգը տեղադրել NVMe RAID 1-ի վրա, որը /dev/md0 է:
Այնուամենայնիվ, այս արագ զանգվածը մեզ դեռ պետք կգա այլ կարիքների համար, ինչպիսիք են փոխանակումը, մետատվյալները և LVM-cache-ը և LVM-thin մետատվյալները, այնպես որ մենք կստեղծենք LVM VG այս զանգվածում:

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

Եկեք ստեղծենք բաժանում արմատային ֆայլային համակարգի համար:

#lvcreate -L 128G --name root root

Եկեք ստեղծենք միջնորմ՝ փոխանակման համար՝ ըստ RAM-ի չափի։

#lvcreate -L 32G --name swap root

ՕՀ-ի տեղադրում

Ընդհանուր առմամբ, մենք ունենք այն ամենը, ինչ անհրաժեշտ է համակարգը տեղադրելու համար։

Գործարկեք համակարգի տեղադրման մոգը Ubuntu Live միջավայրից: Նորմալ տեղադրում. Միայն տեղադրման համար սկավառակներ ընտրելու փուլում դուք պետք է նշեք հետևյալը.

  • /dev/md1, - mount point /boot, FS - BTRFS
  • /dev/root/root (aka /dev/mapper/root-root), - տեղադրման կետ / (root), FS - BTRFS
  • /dev/root/swap (aka /dev/mapper/root-swap), - օգտագործել որպես փոխանակման միջնորմ
  • Տեղադրեք bootloader-ը /dev/sda-ում

Երբ դուք ընտրում եք BTRFS-ը որպես արմատային ֆայլային համակարգ, տեղադրողը ավտոմատ կերպով կստեղծի երկու BTRFS հատոր՝ «@» անունով / (արմատ) և «@home»՝ /home-ի համար:

Սկսենք տեղադրումը...

Տեղադրումը կավարտվի մոդալ երկխոսության տուփով, որը ցույց է տալիս բեռնիչի տեղադրման սխալը: Ցավոք, դուք չեք կարողանա դուրս գալ այս երկխոսությունից՝ օգտագործելով ստանդարտ միջոցներ և շարունակել տեղադրումը: Մենք դուրս ենք գալիս համակարգից և նորից մուտք ենք գործում՝ հայտնվելով մաքուր Ubuntu Live աշխատասեղանի մեջ: Բացեք տերմինալը և կրկին.

#sudo bash

Ստեղծեք chroot միջավայր՝ տեղադրումը շարունակելու համար.

#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

Եկեք կարգավորենք ցանցը և հոսթի անունը chroot-ում.

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

Եկեք անցնենք chroot միջավայրին.

#chroot /mnt/chroot

Առաջին հերթին մենք կառաքենք փաթեթները.

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

Եկեք ստուգենք և շտկենք բոլոր փաթեթները, որոնք սխալ տեղադրվել են համակարգի թերի տեղադրման պատճառով.

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

Եթե ​​ինչ-որ բան չի ստացվում, դուք կարող եք նախ խմբագրել /etc/apt/sources.list

Եկեք կարգավորենք RAID 6 մոդուլի պարամետրերը՝ TRIM/DISCARD-ը միացնելու համար.

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

Եկեք մի փոքր շտկենք մեր զանգվածները.

#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

Ի՞նչ էր դա...Մենք ստեղծել ենք udev կանոնների մի շարք, որոնք կանեն հետևյալը.

  • Սահմանեք, որ RAID 2020-ի բլոկի քեշի չափը համարժեք լինի 6 թ.-ի համար: Լռելյայն արժեքը, կարծես թե, չի փոխվել Linux-ի ստեղծումից հետո և երկար ժամանակ համարժեք չէ:
  • Պահպանեք նվազագույն IO զանգվածների ստուգման/համաժամացման տևողության համար: Սա թույլ է տալիս կանխել ձեր զանգվածները ծանրաբեռնվածության տակ հավերժական համաժամացման վիճակում:
  • Սահմանափակեք առավելագույն IO-ն զանգվածների ստուգման/համաժամացման ժամանակ: Սա անհրաժեշտ է, որպեսզի SSD RAID-ների համաժամացումը/ստուգումը չփխրեցնի ձեր կրիչները: Սա հատկապես ճիշտ է NVMe-ի համար: (Հիշու՞մ եք ռադիատորի մասին, չէի կատակում):
  • Արգելեք սկավառակների դադարեցնել spindle rotation-ը (HDD) APM-ի միջոցով և սահմանել սկավառակի կարգավորիչների քնի ժամանակի 7 ժամ: Դուք կարող եք ամբողջությամբ անջատել APM-ը, եթե ձեր կրիչները կարողանան դա անել (-B 255): Լռելյայն արժեքով սկավառակները կդադարեն հինգ վայրկյանից հետո: Այնուհետև ՕՀ-ն ցանկանում է վերականգնել սկավառակի քեշը, սկավառակները նորից կպտտվեն, և ամեն ինչ նորից կսկսվի: Սկավառակներն ունեն լիսեռի պտտումների սահմանափակ առավելագույն քանակ: Նման պարզ լռելյայն ցիկլը կարող է հեշտությամբ սպանել ձեր սկավառակները մի քանի տարվա ընթացքում: Ոչ բոլոր սկավառակներն են տուժում դրանից, բայց մերը «նոութբուք» է, համապատասխան լռելյայն կարգավորումներով, որոնք RAID-ին նմանեցնում են մինի MAID-ի:
  • Տեղադրեք ընթերցանությունը սկավառակների վրա (պտտվող) 1 մեգաբայթ - երկու հաջորդական բլոկ/կտոր RAID 6
  • Անջատեք ընթերցանությունը հենց զանգվածների վրա:

Եկեք խմբագրենք /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

Ինչու է դա..?Մենք կփնտրենք /boot բաժինը UUID-ի միջոցով: Զանգվածի անվանումը տեսականորեն կարող է փոխվել:

Մնացած բաժինները մենք կփնտրենք LVM անուններով /dev/mapper/vg-lv նշումով, քանի որ նրանք առանձնացնում են բաժանմունքները միանգամայն եզակի:

Մենք չենք օգտագործում UUID LVM-ի համար, քանի որ LVM ծավալների UUID-ը և դրանց ակնթարթային նկարները կարող են նույնը լինել:Mount /dev/mapper/root-root.. երկու անգամ:Այո՛։ Հենց այդպես. BTRFS-ի առանձնահատկությունը. Այս ֆայլային համակարգը կարող է մի քանի անգամ տեղադրվել տարբեր ենթահոլովակների հետ:

Այս նույն հատկանիշի շնորհիվ ես խորհուրդ եմ տալիս երբեք չստեղծել LVM-ի ակտիվ BTRFS ծավալների նկարներ: Դուք կարող եք անակնկալ ստանալ, երբ վերագործարկեք:

Եկեք վերականգնենք mdadm կազմաձևը.

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

Եկեք կարգավորենք 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

Ի՞նչ էր դա...Մենք հնարավորություն ենք տվել LVM-ի բարակ լողավազանների ավտոմատ ընդլայնումը՝ ծավալի 90%-ով զբաղեցրած տարածքի 5%-ին հասնելու դեպքում:

Մենք ավելացրել ենք LVM քեշի քեշի բլոկների առավելագույն քանակը:

Մենք թույլ չենք տվել LVM-ին որոնել LVM ծավալներ (PV) հետևյալում.

  • LVM քեշ պարունակող սարքեր (cdata)
  • սարքեր, որոնք պահվում են LVM քեշի միջոցով՝ շրջանցելով քեշը ( _corig): Այս դեպքում քեշավորված սարքն ինքը դեռ սկանավորվելու է քեշի միջոցով (պարզապես )
  • սարքեր, որոնք պարունակում են LVM քեշի մետատվյալներ (cmeta)
  • բոլոր սարքերը VG-ում անվան պատկերներով: Այստեղ մենք կունենանք վիրտուալ մեքենաների սկավառակի պատկերներ, և մենք չենք ուզում, որ LVM-ը հոսթի վրա ակտիվացնի հյուր ՕՀ-ին պատկանող ծավալները:
  • VG-ի բոլոր սարքերը, որոնց անունը կրկնօրինակում է: Այստեղ մենք կունենանք վիրտուալ մեքենայի պատկերների կրկնօրինակներ:
  • բոլոր սարքերը, որոնց անունը վերջանում է «gpv»-ով (հյուրի ֆիզիկական ծավալ)

LVM VG-ում ազատ տարածք ազատելիս մենք միացրել ենք DISCARD աջակցությունը: Զգույշ եղիր. Սա SSD-ի վրա LV-ների ջնջումը բավականին ժամանակատար կդարձնի: Սա հատկապես վերաբերում է SSD RAID 6-ին: Այնուամենայնիվ, ըստ պլանի, մենք կօգտագործենք thin provisioning, այնպես որ դա մեզ բոլորովին չի խանգարի:

Եկեք թարմացնենք initramfs պատկերը.

#update-initramfs -u -k all

Տեղադրեք և կարգավորեք grub-ը.

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

Ո՞ր սկավառակներն ընտրել:Բոլոր նրանք, ովքեր սդ*. Համակարգը պետք է կարողանա բեռնել ցանկացած աշխատող SATA սկավառակից կամ SSD-ից:

Ինչու են ավելացրել os-prober...Չափազանց անկախության և խաղային ձեռքերի համար:

Այն ճիշտ չի աշխատում, եթե RAID-ներից մեկը գտնվում է դեգրադացված վիճակում: Այն փորձում է որոնել ՕՀ-ն այն միջնորմների վրա, որոնք օգտագործվում են այս սարքաշարի վրա աշխատող վիրտուալ մեքենաներում:

Եթե ​​ձեզ անհրաժեշտ է, կարող եք թողնել այն, բայց հիշեք վերը նշված բոլորը: Խորհուրդ եմ տալիս առցանց փնտրել չարաճճի ձեռքերից ազատվելու բաղադրատոմսեր։

Դրանով մենք ավարտեցինք նախնական տեղադրումը: Ժամանակն է վերագործարկել նոր տեղադրված ՕՀ-ում: Մի մոռացեք հեռացնել bootable Live CD/USB-ը:

#exit
#reboot

Ընտրեք SATA SSD-ներից որևէ մեկը որպես բեռնման սարք:

LVM SATA SSD-ի վրա

Այս պահին մենք արդեն գործարկվել ենք նոր ՕՀ-ում, կարգավորել ենք ցանցը, բացել ենք տերմինալի էմուլյատորը և գործարկել.

#sudo bash

Շարունակենք.

«Նախաձեռնել» զանգվածը SATA SSD-ից.

#blkdiscard /dev/md2

Եթե ​​դա չի աշխատում, ապա փորձեք.

#blkdiscard --step 65536 /dev/md2
Ստեղծեք LVM VG SATA SSD-ով.

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

Ինչու՞ մեկ այլ VG...Փաստորեն, մենք արդեն ունենք VG անունով արմատ: Ինչու չավելացնել ամեն ինչ մեկ VG-ի մեջ:

Եթե ​​VG-ում կան մի քանի PV-ներ, ապա VG-ն ճիշտ ակտիվացնելու համար պետք է ներկա լինեն բոլոր PV-ները (առցանց): Բացառություն է LVM RAID-ը, որը մենք միտումնավոր չենք օգտագործում:

Մենք իսկապես ցանկանում ենք, որ եթե RAID 6 զանգվածներից որևէ մեկում խափանում (կարդալ տվյալների կորուստ) լինի, օպերացիոն համակարգը նորմալ բեռնվի և մեզ հնարավորություն տա լուծել խնդիրը:

Դա անելու համար վերացականության առաջին մակարդակում մենք կմեկուսացնենք յուրաքանչյուր տեսակի ֆիզիկական «մեդիա» առանձին VG-ի մեջ:

Գիտականորեն տարբեր RAID զանգվածներ պատկանում են տարբեր «հուսալիության տիրույթների»: Դուք չպետք է ստեղծեք նրանց համար ձախողման լրացուցիչ ընդհանուր կետ՝ դրանք խցկելով մեկ VG-ի մեջ:

LVM-ի առկայությունը «ապարատային» մակարդակում մեզ թույլ կտա կամայականորեն կտրել տարբեր RAID զանգվածների կտորներ՝ դրանք համատեղելով տարբեր ձևերով: Օրինակ - վազել միաժամանակ bcache + LVM thin, bcache + BTRFS, LVM cache + LVM thin, բարդ ZFS կոնֆիգուրացիա քեշերով կամ ցանկացած այլ դժոխային խառնուրդ՝ փորձել և համեմատել այդ ամենը:

«Ապարատային» մակարդակում մենք այլ բան չենք օգտագործի, բացի լավ հին «հաստ» LVM ծավալներից: Այս կանոնից բացառություն կարող է լինել պահեստային բաժանումը:

Կարծում եմ, այս պահին շատ ընթերցողներ արդեն սկսել էին ինչ-որ բան կասկածել բնադրող տիկնիկի մասին։

LVM SATA HDD-ի վրա

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

Նոր VG նորից...Մենք իսկապես ցանկանում ենք, որ եթե սկավառակի զանգվածը, որը մենք կօգտագործենք տվյալների կրկնօրինակման համար, ձախողվի, մեր օպերացիոն համակարգը շարունակի աշխատել նորմալ՝ միաժամանակ պահպանելով մուտքը ոչ պահուստային տվյալներին, ինչպես միշտ: Հետեւաբար, VG-ի ակտիվացման խնդիրներից խուսափելու համար մենք ստեղծում ենք առանձին VG:

LVM քեշի կարգավորում

Եկեք ստեղծենք LV NVMe RAID 1-ում, որպեսզի այն օգտագործենք որպես քեշավորման սարք:

#lvcreate -L 70871154688B --name cache root

Ինչու՞ է այդքան քիչ...Փաստն այն է, որ մեր NVMe SSD-ները նույնպես ունեն SLC քեշ: 4 գիգաբայթ «անվճար» և 18 գիգաբայթ դինամիկ՝ 3-բիթանոց MLC-ում զբաղեցրած ազատ տարածության շնորհիվ: Երբ այս քեշը սպառվի, NVMe SSD-ները շատ ավելի արագ չեն լինի, քան մեր SATA SSD-ը քեշով: Իրականում, այս պատճառով, մեզ համար անիմաստ է LVM քեշի բաժանումը շատ ավելի մեծ դարձնել, քան NVMe սկավառակի SLC քեշի չափը երկու անգամ: Օգտագործված NVMe կրիչների համար հեղինակը խելամիտ է համարում 32-64 գիգաբայթ քեշ պատրաստելը։

Տրված բաժանման չափը պահանջվում է 64 գիգաբայթ քեշ, քեշի մետատվյալների և մետատվյալների կրկնօրինակում կազմակերպելու համար։

Բացի այդ, ես նշում եմ, որ կեղտոտ համակարգի անջատումից հետո, LVM-ը կնշի ամբողջ քեշը որպես կեղտոտ և նորից կհամաժամացվի: Ավելին, սա կկրկնվի ամեն անգամ, երբ lvchange-ն օգտագործվում է այս սարքում, մինչև համակարգը նորից վերագործարկվի: Ուստի խորհուրդ եմ տալիս անմիջապես վերստեղծել քեշը՝ օգտագործելով համապատասխան սցենարը:

Եկեք ստեղծենք LV SATA RAID 6-ի վրա՝ այն որպես քեշավորված սարք օգտագործելու համար:

#lvcreate -L 3298543271936B --name cache data

Ինչու՞ ընդամենը երեք տերաբայթ...Որպեսզի, անհրաժեշտության դեպքում, կարողանաք օգտագործել SATA SSD RAID 6-ը որոշ այլ կարիքների համար: Քեշավորված տարածքի չափը կարող է մեծանալ դինամիկ, թռիչքի ժամանակ, առանց համակարգը դադարեցնելու: Դա անելու համար դուք պետք է ժամանակավորապես դադարեցնեք և նորից միացնեք քեշը, սակայն LVM-cache-ի տարբերակիչ առավելությունը, օրինակ, bcache-ի նկատմամբ այն է, որ դա կարելի է անել անմիջապես:

Եկեք ստեղծենք նոր VG քեշավորման համար:

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

Եկեք ստեղծենք LV քեշավորված սարքի վրա:

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

Այստեղ մենք անմիջապես գրավեցինք /dev/data/cache-ի ողջ ազատ տարածքը, որպեսզի մնացած բոլոր անհրաժեշտ բաժանմունքները ստեղծվեն անմիջապես /dev/root/cache-ում: Եթե ​​ինչ-որ բան սխալ տեղում եք ստեղծել, կարող եք այն տեղափոխել pvmove-ի միջոցով:

Եկեք ստեղծենք և միացնենք քեշը.

#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

Ինչու՞ էդքան մեծություն...Գործնական փորձերի միջոցով հեղինակը կարողացել է պարզել, որ լավագույն արդյունքը ձեռք է բերվում, եթե LVM քեշի բլոկի չափը համընկնում է LVM բարակ բլոկի չափի հետ։ Ավելին, որքան փոքր է չափը, այնքան ավելի լավ է կոնֆիգուրացիան կատարվում պատահական ձայնագրության մեջ:

64k-ը LVM thin-ի համար թույլատրված նվազագույն բլոկի չափն է:

Զգույշ եղեք գրել..!Այո՛։ Քեշի այս տեսակը հետաձգում է գրելու համաժամացումը քեշավորված սարքի վրա: Սա նշանակում է, որ քեշը կորցնելու դեպքում դուք կարող եք կորցնել տվյալները պահված սարքի վրա: Ավելի ուշ հեղինակը ձեզ կպատմի, թե բացի NVMe RAID 1-ից, ինչ միջոցներ կարելի է ձեռնարկել այս ռիսկը փոխհատուցելու համար:

Քեշի այս տեսակն ընտրվել է միտումնավոր՝ RAID 6-ի պատահական գրելու վատ կատարողականությունը փոխհատուցելու համար:

Եկեք ստուգենք, թե ինչ ենք ստացել.

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

Միայն [cachedata_corig]-ը պետք է գտնվի /dev/data/cache-ում: Եթե ​​ինչ-որ բան այն չէ, ապա օգտագործեք pvmove-ը:

Անհրաժեշտության դեպքում կարող եք անջատել քեշը մեկ հրամանով.

#lvconvert -y --uncache cache/cachedata

Սա արվում է առցանց: LVM-ը պարզապես կհամաժամեցնի քեշը սկավառակի հետ, կհեռացնի այն և կվերանվանի cachedata_corig-ը նորից քեշի տվյալների:

LVM-ի բարակ կարգավորում

Եկեք մոտավորապես գնահատենք, թե որքան տարածք է մեզ անհրաժեշտ 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"

Կլորացրեք մինչև 4 գիգաբայթ՝ 4294967296B

Բազմապատկեք երկուսով և ավելացրեք 4194304B LVM PV մետատվյալների համար՝ 8594128896B
Եկեք ստեղծենք առանձին բաժին NVMe RAID 1-ի վրա՝ դրա վրա LVM-ի բարակ մետատվյալները և դրանց կրկնօրինակը տեղադրելու համար.

#lvcreate -L 8594128896B --name images root

Ինչի համար..?Այստեղ կարող է հարց առաջանալ՝ ինչու՞ առանձին տեղադրել LVM-ի բարակ մետատվյալները, եթե դրանք դեռ կքեշվեն NVMe-ում և արագ կաշխատեն։

Թեև արագությունն այստեղ կարևոր է, այն հեռու է հիմնական պատճառից։ Բանն այն է, որ քեշը ձախողման կետ է։ Նրա հետ ինչ-որ բան կարող է պատահել, և եթե LVM-ի բարակ մետատվյալները պահվում են քեշում, դա կհանգեցնի նրան, որ ամեն ինչ ամբողջությամբ կկորչի: Առանց ամբողջական մետատվյալների, գրեթե անհնար կլինի բարակ ծավալներ հավաքել:

Մետատվյալները տեղափոխելով առանձին ոչ քեշավորված, բայց արագ ծավալ, մենք երաշխավորում ենք մետատվյալների անվտանգությունը քեշի կորստի կամ կոռուպցիայի դեպքում: Այս դեպքում քեշի կորստի հետևանքով առաջացած բոլոր վնասները տեղայնացվելու են բարակ ծավալների ներսում, ինչը կհեշտացնի վերականգնման ընթացակարգը մեծության կարգերով: Մեծ հավանականությամբ այս վնասները կվերականգնվեն FS տեղեկամատյանների միջոցով:

Ավելին, եթե նախկինում նկարահանվել է բարակ ծավալի լուսանկար, և դրանից հետո քեշը ամբողջությամբ համաժամացվել է առնվազն մեկ անգամ, ապա LVM thin-ի ներքին դիզայնի շնորհիվ ակնթարթային նկարի ամբողջականությունը երաշխավորված կլինի քեշի կորստի դեպքում։ .

Եկեք ստեղծենք նոր VG, որը պատասխանատու կլինի բարակ մատակարարման համար.

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

Եկեք ստեղծենք լողավազան.

#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T images/thin-pool
Ինչու -Z yԻ հավելումն այն բանի, ինչի համար իրականում նախատեսված է այս ռեժիմը` կանխելու համար մեկ վիրտուալ մեքենայի տվյալների արտահոսքը մյուս վիրտուալ մեքենային տարածք վերաբաշխելիս, զրոյացումը լրացուցիչ օգտագործվում է 64k-ից փոքր բլոկներում պատահական գրելու արագությունը մեծացնելու համար: 64k-ից պակաս ցանկացած գրություն բարակ ծավալի նախկինում չբաշխված տարածքի վրա կդարձնի 64K եզրով հավասարեցված քեշում: Սա թույլ կտա գործողությունն ամբողջությամբ կատարել քեշի միջոցով՝ շրջանցելով պահված սարքը։

LV-ները տեղափոխենք համապատասխան PV-ներ.

#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

Եկեք ստուգենք.

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

Եկեք ստեղծենք բարակ ծավալ թեստերի համար.

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

Մենք կտեղադրենք փաթեթներ թեստերի և մոնիտորինգի համար.

#apt-get install sysstat fio

Ահա թե ինչպես կարող եք իրական ժամանակում դիտարկել մեր պահեստավորման կոնֆիգուրացիայի պահվածքը.

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

Ահա թե ինչպես մենք կարող ենք ստուգել մեր կոնֆիգուրացիան.

#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

Զգույշ. Ռեսուրս!Այս կոդը կգործարկի 36 տարբեր թեստեր, որոնցից յուրաքանչյուրը կաշխատի 4 վայրկյան: Թեստերի կեսը ձայնագրման համար է։ Դուք կարող եք շատ բան ձայնագրել NVMe-ով 4 վայրկյանում: Մինչև 3 գիգաբայթ վայրկյանում: Այսպիսով, գրելու թեստերի յուրաքանչյուր վազք կարող է ձեզնից ուտել մինչև 216 գիգաբայթ SSD ռեսուրս:

Կարդալն ու գրելը խառնվե՞լ են:Այո՛։ Իմաստ ունի կարդալ և գրել թեստերն առանձին-առանձին անցկացնել: Ավելին, իմաստ ունի ապահովել, որ բոլոր քեշերը համաժամանակացվեն այնպես, որ նախկինում կատարված գրառումը չազդի ընթերցման վրա:

Արդյունքները մեծապես կտարբերվեն առաջին գործարկման և հաջորդների ժամանակ, քանի որ քեշը և բարակ ծավալը լցվում են, ինչպես նաև կախված նրանից, թե արդյոք համակարգին հաջողվել է համաժամացնել վերջին գործարկման ժամանակ լցված քեշերը:

Ի թիվս այլ բաների, ես խորհուրդ եմ տալիս արագությունը չափել արդեն լրիվ բարակ ծավալի վրա, որից հենց նոր լուսանկար է արվել: Հեղինակը հնարավորություն ուներ դիտելու, թե ինչպես են պատահական գրությունները կտրուկ արագանում առաջին նկարը ստեղծելուց անմիջապես հետո, հատկապես, երբ քեշը դեռ ամբողջությամբ լցված չէ: Դա տեղի է ունենում պատճենահանման վրա գրելու իմաստաբանության, քեշի և բարակ ծավալային բլոկների հավասարեցման, և այն փաստի, որ RAID 6-ում պատահական գրառումը վերածվում է RAID 6-ից պատահական ընթերցման, որին հաջորդում է քեշի գրություն: Մեր կոնֆիգուրացիայում RAID 6-ից պատահական ընթերցումը մինչև 6 անգամ (զանգվածում SATA SSD-ների թիվը) ավելի արագ է, քան գրելը: Որովհետեւ CoW-ի համար բլոկները հաջորդաբար բաժանվում են բարակ լողավազանից, այնուհետև ձայնագրությունը, մեծ մասամբ, նույնպես վերածվում է հաջորդականության:

Այս երկու հատկանիշները կարող են օգտագործվել ձեր օգտին:

Քեշի «համահունչ» նկարները

Քեշի վնասման/կորստի դեպքում տվյալների կորստի ռիսկը նվազեցնելու համար հեղինակն առաջարկում է ներդնել պտտվող snapshot-ների պրակտիկան՝ այս դեպքում դրանց ամբողջականությունը երաշխավորելու համար:

Նախ, քանի որ փոքր ծավալի մետատվյալները գտնվում են չքեշավորված սարքի վրա, մետատվյալները կլինեն հետևողական, և հնարավոր կորուստները կմեկուսացվեն տվյալների բլոկների մեջ:

Պատկերների պտտման հետևյալ ցիկլը երաշխավորում է տվյալների ամբողջականությունը պատկերների ներսում՝ քեշի կորստի դեպքում.

  1. <name> անունով յուրաքանչյուր բարակ հատորի համար ստեղծեք պատկեր <name>.cached անունով:
  2. Եկեք միգրացիայի շեմը դնենք ողջամիտ բարձր արժեքի. #lvchange --quiet --cachesettings "migration_threshold=16384" cache/cachedata
  3. Հանգույցում մենք ստուգում ենք քեշի կեղտոտ բլոկների քանակը. #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' մինչև չստանանք զրո: Եթե ​​զրոն շատ երկար ժամանակ բացակայում է, այն կարող է ստեղծվել՝ քեշը ժամանակավորապես անցնելով գրառման ռեժիմին: Այնուամենայնիվ, հաշվի առնելով մեր SATA և NVMe SSD զանգվածների արագության բնութագրերը, ինչպես նաև դրանց TBW ռեսուրսը, դուք կամ կկարողանաք արագ բռնել պահը առանց քեշի ռեժիմը փոխելու, կամ ձեր սարքավորումն ամբողջությամբ կխլի իր ողջ ռեսուրսը: մի քանի օր. Ռեսուրսների սահմանափակումների պատճառով համակարգը, սկզբունքորեն, չի կարող մշտապես լինել 100% գրելու բեռի տակ: Մեր NVMe SSD-ները 100% գրելու ծանրաբեռնվածության տակ ամբողջությամբ կսպառեն ռեսուրսը 3-4 օր. SATA SSD-ները միայն երկու անգամ ավելի երկար կծառայեն: Հետևաբար, մենք կենթադրենք, որ բեռի մեծ մասը գնում է ընթերցանությանը, և մենք ունենք չափազանց բարձր ակտիվության համեմատաբար կարճաժամկետ պոռթկումներ՝ զուգորդված միջինում գրելու համար ցածր բեռի հետ:
  4. Հենց որ մենք բռնեցինք (կամ պատրաստեցինք) զրո, մենք վերանվանում ենք <name>.cached-ը <name>.committed: Հին <name>.committed-ը ջնջված է:
  5. Ցանկության դեպքում, եթե քեշը 100%-ով լի է, այն կարող է վերստեղծվել սկրիպտի միջոցով՝ այդպիսով մաքրելով այն: Կիսադատարկ քեշի դեպքում համակարգը շատ ավելի արագ է աշխատում գրելիս:
  6. Սահմանեք միգրացիայի շեմը զրոյի՝ #lvchange --quiet --cachesettings "migration_threshold=0" cache/cachedata Սա ժամանակավորապես կկանխի քեշի համաժամացումը հիմնական մեդիայի հետ:
  7. Մենք սպասում ենք, մինչև քեշում բավականին շատ փոփոխություններ կուտակվեն #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' կամ ժամաչափը կանջատվի:
  8. Կրկին կրկնում ենք.

Ինչո՞ւ դժվարություններ միգրացիոն շեմի հետ կապված...Բանն այն է, որ իրական պրակտիկայում «պատահական» ձայնագրությունն իրականում ամբողջովին պատահական չէ: Եթե ​​մենք ինչ-որ բան գրենք 4 կիլոբայթ մեծությամբ հատվածի վրա, ապա մեծ հավանականություն կա, որ հաջորդ երկու րոպեների ընթացքում ձայնագրություն կկատարվի նույն կամ հարևան (+- 32K) սեկտորներից մեկի վրա։

Միգրացիայի շեմը զրոյական դնելով, մենք հետաձգում ենք գրելու համաժամացումը SATA SSD-ի վրա և մի քանի փոփոխություններ ենք միավորում քեշի մեկ 64K բլոկի մեջ: Սա զգալիորեն խնայում է SATA SSD-ի ռեսուրսը:

Որտեղ է կոդը..Ցավոք, հեղինակն իրեն անբավարար կոմպետենտ է համարում bash սցենարների մշակման հարցում, քանի որ նա 100% ինքնուսույց է և զբաղվում է «google»-ի վրա հիմնված մշակմամբ, հետևաբար կարծում է, որ իր ձեռքից դուրս եկած սարսափելի ծածկագիրը չպետք է օգտագործի ոչ ոք: ուրիշ.

Կարծում եմ, որ այս ոլորտի մասնագետները անհրաժեշտության դեպքում կկարողանան ինքնուրույն պատկերել վերը նկարագրված ողջ տրամաբանությունը և, գուցե, նույնիսկ գեղեցիկ ձևավորել որպես համակարգված ծառայություն, ինչպես փորձել է անել հեղինակը:

Պատկերի պտտման նման պարզ սխեման թույլ կտա մեզ ոչ միայն անընդհատ ունենալ մեկ լուսանկար ամբողջությամբ համաժամանակացված SATA SSD-ի վրա, այլ նաև թույլ կտա մեզ, օգտագործելով thin_delta ծրագիրը, պարզել, թե որ բլոկներն են փոխվել դրա ստեղծումից հետո, և այդպիսով տեղայնացնել վնասը: հիմնական ծավալները՝ զգալիորեն պարզեցնելով վերականգնումը։

TRIM/DISCARD libvirt/KVM-ում

Որովհետեւ տվյալների պահեստը կօգտագործվի KVM-ի libvirt-ի գործարկման համար, ապա լավ գաղափար կլինի մեր VM-ներին սովորեցնել ոչ միայն ազատ տարածք գրավել, այլ նաև ազատել այն, ինչ այլևս անհրաժեշտ չէ:

Դա արվում է վիրտուալ սկավառակների վրա TRIM/DISCARD աջակցության նմանակմամբ: Դա անելու համար դուք պետք է փոխեք վերահսկիչի տեսակը virtio-scsi-ի և խմբագրեք 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>

Հյուր ՕՀ-ների նման ՈՒՂԻՂՆԵՐԸ ճիշտ են մշակվում LVM-ի կողմից, և բլոկները ճիշտ են ազատվում ինչպես քեշում, այնպես էլ բարակ լողավազանում: Մեր դեպքում դա տեղի է ունենում հիմնականում ուշացումով, հաջորդ նկարը ջնջելիս։

BTRFS կրկնօրինակում

Օգտագործեք պատրաստի սցենարներ հետ ծայրահեղ զգուշություն և սեփական ռիսկով. Հեղինակն ինքն է գրել այս ծածկագիրը և բացառապես իր համար։ Համոզված եմ, որ Linux-ի շատ փորձառու օգտատերեր ունեն նմանատիպ գործիքներ, և կարիք չկա կրկնօրինակել մեկ ուրիշին:

Եկեք ստեղծենք ծավալ պահեստային սարքի վրա.

#lvcreate -L 256G --name backup backup

Եկեք այն ձևաչափենք BTRFS-ում.

#mkfs.btrfs /dev/backup/backup

Եկեք ստեղծենք տեղադրման կետեր և տեղադրենք ֆայլային համակարգի արմատային ենթաբաժինները.

#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

Եկեք ստեղծենք դիրեկտորիաներ կրկնօրինակների համար.

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

Եկեք ստեղծենք պահուստային սկրիպտների գրացուցակ.

#mkdir /root/btrfs-backup

Եկեք պատճենենք սցենարը.

Շատ սարսափելի bash ծածկագիր: Օգտագործեք ձեր ռիսկով: Զայրացած նամակներ մի գրեք հեղինակին...#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

Ի՞նչ է դա անում նույնիսկ...Պարունակում է մի շարք պարզ հրամաններ՝ BTRFS-ի նկարներ ստեղծելու և դրանք մեկ այլ FS-ում պատճենելու համար՝ օգտագործելով BTRFS ուղարկել/ստանալ:

Առաջին մեկնարկը կարող է համեմատաբար երկար լինել, քանի որ... Սկզբում բոլոր տվյալները կպատճենվեն: Հետագա գործարկումները շատ արագ կլինեն, քանի որ... Միայն փոփոխությունները կպատճենվեն:

Մեկ այլ սցենար, որը մենք կտեղադրենք cron-ում.

Եվս մի քանի 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

Ինչ է այն անում..?Ստեղծում և համաժամացնում է BTRFS-ի թվարկված ծավալների աստիճանական նկարները պահուստային FS-ում: Դրանից հետո այն ջնջում է 60 օր առաջ ստեղծված բոլոր նկարները։ Գործարկումից հետո թվարկված հատորների թվագրված նկարները կհայտնվեն /backup/btrfs/back/remote/ ենթագրքերում:

Եկեք կոդի կատարման իրավունք տանք.

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

Եկեք ստուգենք այն և դնենք այն 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 բարակ կրկնօրինակում

Եկեք ստեղծենք բարակ լողավազան պահուստային սարքի վրա.

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

Եկեք տեղադրենք ddrescue, քանի որ... սցենարները կօգտագործեն այս գործիքը.

#apt-get install gddrescue

Եկեք ստեղծենք գրացուցակ սկրիպտների համար.

#mkdir /root/lvm-thin-backup

Եկեք պատճենենք սցենարները.

Ներսում շատ բարկություն...#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

Ինչ է այն անում...?Պարունակում է մի շարք հրամաններ՝ բարակ նկարները շահարկելու և thin_delta-ի միջոցով ստացված երկու բարակ նկարահանումների միջև տարբերությունը համաժամեցնելու համար մեկ այլ բլոկ սարքի՝ օգտագործելով ddrescue և blkdiscard:

Մեկ այլ սցենար, որը մենք կտեղադրենք cron-ում.

Մի քիչ էլ բաշ#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

Ինչ է այն անում...?Օգտագործում է նախորդ սցենարը՝ թվարկված բարակ ծավալների կրկնօրինակներ ստեղծելու և համաժամացնելու համար: Սցենարը կթողնի թվարկված հատորների ոչ ակտիվ պատկերներ, որոնք անհրաժեշտ են վերջին համաժամացման պահից ի վեր փոփոխությունները հետևելու համար:

Այս սցենարը պետք է խմբագրվի՝ նշելով բարակ հատորների ցանկը, որոնց համար պետք է կրկնօրինակներ պատրաստվեն։ Տրված անունները միայն պատկերային նպատակներով են: Ցանկության դեպքում կարող եք գրել սցենար, որը կհամաժամացնի բոլոր հատորները:

Եկեք իրավունքներ տանք.

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

Եկեք ստուգենք այն և դնենք այն 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

Առաջին մեկնարկը երկար կլինի, քանի որ... բարակ ծավալները լիովին կհամաժամանակացվեն՝ պատճենելով ամբողջ օգտագործված տարածքը: LVM բարակ մետատվյալների շնորհիվ մենք գիտենք, թե որ բլոկներն են իրականում օգտագործվում, ուստի միայն իրականում օգտագործված բարակ ծավալային բլոկները կպատճենվեն:

Հետագա գործարկումները աստիճանաբար պատճենելու են տվյալները LVM-ի բարակ մետատվյալների միջոցով հետագծման փոփոխության շնորհիվ:

Տեսնենք, թե ինչ եղավ.

#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

Սա ի՞նչ կապ ունի բնադրող տիկնիկների հետ։

Ամենայն հավանականությամբ, հաշվի առնելով, որ LVM LV տրամաբանական ծավալները կարող են լինել LVM PV ֆիզիկական ծավալներ այլ VG-ների համար: LVM-ն կարող է ռեկուրսիվ լինել, ինչպես բնադրող տիկնիկները: Սա LVM-ին տալիս է ծայրահեղ ճկունություն:

PS

Հաջորդ հոդվածում մենք կփորձենք օգտագործել մի քանի նմանատիպ բջջային պահեստավորման համակարգեր/KVM որպես հիմք մի քանի մայրցամաքներում ավելորդությամբ աշխարհաբաշխված պահեստավորման/vm կլաստերի ստեղծման համար՝ օգտագործելով տնային աշխատասեղանները, տնային ինտերնետը և P2P ցանցերը:

Source: www.habr.com

Добавить комментарий