LVM болон Матрешка хоёр юугаараа ижил төстэй вэ?

Өдрийн төрөл.
Би md RAID + LVM ашиглан KVM-д зориулсан өгөгдөл хадгалах системийг бий болгох практик туршлагаа олон нийттэй хуваалцахыг хүсч байна.

Хөтөлбөрт дараахь зүйлс орно.

  • NVMe SSD-ээс md RAID 1 бүтээх.
  • SATA SSD болон ердийн хөтчүүдээс md RAID 6-г угсарч байна.
  • SSD RAID 1/6 дээр TRIM/DISCARD үйлдлийн онцлогууд.
  • Нийтлэг диск дээр ачаалах боломжтой md RAID 1/6 массив үүсгэх.
  • BIOS-д NVMe дэмжлэг байхгүй үед системийг NVMe RAID 1 дээр суулгаж байна.
  • LVM кэш болон LVM нимгэн ашиглах.
  • BTRFS агшин зуурын зургийг ашиглах, нөөцлөхөд илгээх/хүлээн авах.
  • BTRFS загварын нөөцлөлтөд LVM-ийн нимгэн хормын хувилбарууд болон thin_delta-г ашиглаж байна.

Хэрэв та сонирхож байвал муурыг үзээрэй.

Өргөдлийн маягт

Зохиогч нь энэ нийтлэлээс материал/жишээ/код/зөвлөгөө/өгөгдөл ашиглах, ашиглаагүйгээс гарах үр дагаварт хариуцлага хүлээхгүй. Энэ материалыг уншсан эсвэл ямар нэгэн байдлаар ашигласнаар та эдгээр үйлдлийн бүх үр дагаврыг хариуцна. Боломжит үр дагаварт дараахь зүйлс орно.

  • Шарсан NVMe SSD.
  • Бичлэгийн нөөц бүрэн дуусч, SSD хөтчүүдийн эвдрэл.
  • Нөөц хуулбарыг оруулаад бүх хөтчүүд дээрх бүх өгөгдлийг бүрэн алдах.
  • Компьютерийн техник хангамж эвдэрсэн.
  • Цаг хугацаа, мэдрэл, мөнгө үрсэн.
  • Дээр дурдаагүй бусад үр дагавар.

Төмөр

Боломжтой байсан:

Intel Core i2013 / Haswell-тэй иж бүрэн Z87 чипсет бүхий 7 оны эх хавтан.

  • Процессор 4 цөм, 8 утас
  • 32 GB 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 форматтай 7 ТБ багтаамжтай 1000 ширхэг HGST Travelstar 1K2.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 синхрончлолын үед шаржигнуур болтол нь хуурна.

PCIe 8 2х үүрэнд суулгасан 2 x NVMe SSD-д зориулсан StarTech PEX2M3.0E8 адаптер. Энэ нь дахин хэлэхэд зүгээр л HBA, гэхдээ NVMe-д зориулагдсан. Суурилуулсан PCIe шилжүүлэгчтэй тул эх хавтангаас PCIe салаалах дэмжлэг шаарддаггүй гэдгээрээ хямд адаптеруудаас ялгаатай. Энэ нь x1 PCIe 1.0 оролттой байсан ч гэсэн PCIe-тэй хамгийн эртний системд ч ажиллах болно. Мэдээжийн хэрэг, зохих хурдаар. Тэнд RAID байхгүй. Усан онгоцон дээр суурилуулсан BIOS байхгүй. Тиймээс таны систем NVMe-ээр ачаалж сурахгүй, энэ төхөөрөмжийн ачаар NVMe RAID-ээс хамаагүй бага.

Энэ бүрэлдэхүүн хэсэг нь системд зөвхөн нэг үнэгүй 8x PCIe 3.0 байгаатай холбоотой бөгөөд хэрэв 2 үнэгүй слот байгаа бол үүнийг хоёр пенни PEX4M2E1 эсвэл аналогоор амархан сольж болох бөгөөд үүнийг хаанаас ч 600 үнээр худалдаж авах боломжтой. рубль.

Бүх төрлийн техник хангамж эсвэл суурилуулсан чипсет/BIOS RAID-ээс татгалзаж, бүх өгөгдлийг хадгалахын зэрэгцээ SSD/HDD-ээс бусад системийг бүхэлд нь солих боломжтой болсон. Та цоо шинэ/өөр техник хангамж руу шилжихдээ суулгасан үйлдлийн системийг хүртэл хадгалах боломжтой. Хамгийн гол нь SATA болон PCIe портууд байдаг. Энэ нь амьд CD эсвэл ачаалах боломжтой флаш диск шиг, зөвхөн маш хурдан бөгөөд бага зэрэг том хэмжээтэй.

ХүндэлдэгҮгүй бол та юу болохыг мэдэж байгаа - заримдаа та бүх массивыг яаралтай авч явах хэрэгтэй болдог. Гэхдээ би өгөгдлийг алдахыг хүсэхгүй байна. Үүнийг хийхийн тулд дурдсан бүх зөөвөрлөгчийг стандарт хайрцагны 5.25 булан дахь слайд дээр байрлуулахад тохиромжтой.

Мэдээжийн хэрэг, Linux дээр SSD кэш хийх янз бүрийн аргуудыг туршиж үзэхэд зориулагдсан.

Техник хангамжийн довтолгоо нь уйтгартай байдаг. Үүнийг асаана уу. Энэ нь ажилладаг эсвэл болохгүй. Мөн mdadm-тэй бол үргэлж сонголтууд байдаг.

Програм хангамж

Өмнө нь Debian 8 Jessie-г тоног төхөөрөмж дээр суулгасан бөгөөд энэ нь EOL-тэй ойролцоо юм. RAID 6 нь дээр дурдсан HDD-ээс LVM-тэй хослуулсан. Энэ нь kvm/libvirt дээр виртуал машинуудыг ажиллуулсан.

Учир нь Зохиогч нь зөөврийн ачаалах боломжтой SATA/NVMe флаш дискийг бүтээхэд зохих туршлагатай бөгөөд ердийн тохиромжтой загварыг эвдэхгүйн тулд Ubuntu 18.04-ийг зорилтот системээр сонгосон бөгөөд энэ нь аль хэдийн хангалттай тогтворжсон боловч 3 жилийн хугацаатай хэвээр байна. ирээдүйд дэмжлэг үзүүлнэ.

Дээр дурдсан систем нь бидэнд хэрэгтэй бүх техник хангамжийн драйверуудыг агуулдаг. Бидэнд гуравдагч талын программ хангамж, драйверууд хэрэггүй.

Суулгахад бэлтгэж байна

Системийг суулгахын тулд бидэнд Ubuntu Desktop Image хэрэгтэй. Серверийн систем нь зарим төрлийн хүчирхэг суулгагчтай бөгөөд энэ нь идэвхгүй болгох боломжгүй хэт бие даасан байдлыг харуулж, UEFI системийн хуваалтыг дискний аль нэг рүү түлхэж, бүх гоо сайхныг сүйтгэдэг. Үүний дагуу үүнийг зөвхөн UEFI горимд суулгасан болно. Ямар ч сонголт санал болгодоггүй.

Бид үүнд сэтгэл хангалуун бус байна.

Яагаад?Харамсалтай нь UEFI ачаалах нь RAID ачаалах программ хангамжтай маш тааруу нийцдэг, учир нь... Хэн ч бидэнд UEFI ESP хуваалтын захиалгыг санал болгодоггүй. ESP хуваалтыг USB порт дахь флаш диск дээр байрлуулахыг санал болгодог онлайн жор байдаг боловч энэ нь бүтэлгүйтлийн цэг юм. UEFI BIOS-ийг энэ хуваалтыг харахаас сэргийлдэггүй mdadm RAID 1 программ хангамжийн 0.9 мета өгөгдлийн хувилбарыг ашигладаг жорууд байдаг боловч BIOS эсвэл өөр техник хангамжийн үйлдлийн систем нь ESP-д ямар нэгэн зүйл бичиж, бусадтай синхрончлохоо мартдаг аз жаргалтай мөч хүртэл амьдардаг. толь.

Нэмж дурдахад, UEFI ачаалах нь NVRAM-аас хамаардаг бөгөөд энэ нь дискний хамт шинэ систем рүү шилжихгүй. эх хавтангийн нэг хэсэг юм.

Тиймээс бид шинэ дугуй зохион бүтээхгүй. Бидэнд UEFI-тэй нийцтэй систем дээр CSM гэсэн бардам нэрийг агуулсан, одоо Legacy/BIOS ачаалах гэж нэрлэгддэг бэлэн, цаг хугацаагаар шалгагдсан өвөөгийн дугуй аль хэдийн бий. Бид зүгээр л тавиураас аваад, тосолж, дугуйг нь шахаж, чийгтэй даавуугаар арчих болно.

Ubuntu-ийн ширээний хувилбарыг Legacy bootloader-ээр зөв суулгах боломжгүй ч энд тэдний хэлснээр ядаж л сонголтууд байдаг.

Тиймээс бид техник хангамжийг цуглуулж, Ubuntu Live ачаалах боломжтой флаш дискнээс системийг ачаална. Бид багцуудыг татаж авах шаардлагатай тул танд тохирох сүлжээг тохируулах болно. Хэрэв энэ нь ажиллахгүй бол та шаардлагатай багцуудыг флаш диск рүү урьдчилан ачаалж болно.

Бид Ширээний орчинд орж, терминал эмуляторыг ажиллуулж, унтраах болно:

#sudo bash

Хэрхэн…?Дээрх мөр нь sudo-ийн тухай holiwars-д зориулсан каноник гох юм. C bоилүү их боломжууд гарч ирдэгоилүү их хариуцлага. Та үүнийг өөртөө авч чадах эсэх нь асуулт юм. Олон хүмүүс sudo-г ийм байдлаар ашиглах нь наад зах нь болгоомжтой биш гэж боддог. Гэсэн хэдий ч:

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

Яагаад ZFS болохгүй гэж?Бид компьютер дээрээ программ хангамж суулгахдаа үндсэндээ энэ программ хангамжийг хөгжүүлэгчдэд жолоодохын тулд техник хангамжаа зээлдүүлдэг.
Бид энэ программ хангамжид өгөгдлийнхөө аюулгүй байдалд итгэдэг бол бид энэ өгөгдлийг сэргээх зардалтай тэнцэх хэмжээний зээл авдаг бөгөөд бид хэзээ нэгэн цагт төлөх ёстой болно.

Энэ үүднээс авч үзвэл ZFS бол Ferrari, mdadm+lvm бол унадаг дугуйтай илүү төстэй юм.

Субъектив талаас нь авч үзвэл зохиолч Ферраригийн оронд үл мэдэгдэх хүмүүст дугуй зээлж өгөхийг илүүд үздэг. Тэнд асуудлын үнэ өндөр биш байна. Эрх хэрэггүй. Замын хөдөлгөөний дүрмээс ч хялбар. Машины зогсоол үнэгүй. Улс хоорондын ур чадвар илүү. Унадаг дугуйнд хөлөө үргэлж холбож болно, мөн унадаг дугуйг өөрийн гараар засаж болно.

Яагаад BTRFS...?Үйлдлийн системийг ачаалахын тулд бидэнд Legacy/BIOS GRUB-д дэмжигдсэн файлын систем хэрэгтэй бөгөөд үүний зэрэгцээ шууд хормын хувилбаруудыг дэмждэг. Бид үүнийг /boot хуваалтад ашиглах болно. Нэмж дурдахад зохиогч энэ FS-ийг / (root)-д ашиглахыг илүүд үздэг бөгөөд бусад програм хангамжийн хувьд та LVM дээр тусдаа хуваалт үүсгэж, шаардлагатай лавлах хэсэгт холбож болно гэдгийг мартаж болохгүй.

Бид энэ FS дээр виртуал машин эсвэл мэдээллийн сангийн ямар ч зургийг хадгалахгүй.
Энэхүү FS нь системийг унтраахгүйгээр зөвхөн агшин зуурын агшин зуурын зургийг үүсгэж, илгээх/хүлээн авах аргыг ашиглан нөөц диск рүү шилжүүлэхэд ашиглагдана.

Нэмж дурдахад, зохиогч ерөнхийдөө техник хангамж дээр хамгийн бага програм хангамжийг хадгалахыг илүүд үздэг бөгөөд GPU болон PCI-USB хост хянагчуудыг IOMMU-ээр дамжуулан KVM руу дамжуулах гэх мэт зүйлсийг ашиглан виртуал машин дээр бусад бүх програм хангамжийг ажиллуулахыг илүүд үздэг.

Техник хангамж дээр үлдсэн цорын ганц зүйл бол өгөгдөл хадгалах, виртуалчлал, нөөцлөлт юм.

Хэрэв та ZFS-д илүү их итгэдэг бол зарчмын хувьд заасан програмын хувьд тэдгээрийг сольж болно.

Гэсэн хэдий ч зохиогч ZFS, BRTFS болон LVM-д байдаг суулгасан толин тусгал / RAID болон нэмэлт функцүүдийг зориудаар үл тоомсорлодог.

Нэмэлт аргумент болгон BTRFS нь санамсаргүй бичвэрүүдийг дараалсан бичвэр болгон хувиргах чадвартай бөгөөд энэ нь HDD дээрх агшин зуурын зураг/нөөцлөлтийг синхрончлох хурдад маш эерэг нөлөө үзүүлдэг.

Бүх төхөөрөмжийг дахин хайцгаая:

#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 хатуу диск

Энд онцгой зүйл зохион бүтээх шаардлагагүй. Бид бүх зүйлд нэг хэсэг үүсгэх болно. 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 TB хэмжээтэй байна. Энэ нь MBR-ийн зөвшөөрөгдөх хэмжээнд байгаа бөгөөд үүнийг бидний ашиглах болно. Шаардлагатай бол GPT-ээр сольж болно. GPT дискүүд нь MBR нийцтэй системүүд эхний 4 терабайт дотор байрласан тохиолдолд эхний 2 хуваалтыг харах боломжийг олгодог нийцтэй байдлын давхаргатай байдаг. Хамгийн гол нь эдгээр дискнүүдийн ачаалах хэсэг болон bios_grub хуваалтууд эхэнд байх ёстой. Энэ нь танд GPT Legacy/BIOS хөтчүүдээс ачаалах боломжийг олгодог.

Гэхдээ энэ нь бидний хэрэг биш юм.

Энд бид хоёр хэсэг үүсгэх болно. Эхнийх нь 1 ГБ хэмжээтэй байх ба RAID 1 /boot-д ашиглагддаг.

Хоёр дахь нь RAID 6-д ашиглагдах бөгөөд дискний төгсгөлд хуваарилагдаагүй жижиг хэсгээс бусад бүх сул зайг эзэлнэ.

Энэ тэмдэглэгээгүй газар юу вэ?Сүлжээний эх сурвалжийн мэдээлснээр манай SATA SSD нь 6-аас 78 гигабайтын хэмжээтэй динамикаар өргөтгөх боломжтой SLC кэштэй. Драйверын мэдээллийн хуудсан дээрх "гигабайт" ба "гибибайт" хоёрын ялгаанаас болж бид 6 гигабайтыг "үнэгүй" авдаг. Үлдсэн 72 гигабайтыг ашиглагдаагүй зайнаас хуваарилдаг.

Энд бид SLC кэштэй бөгөөд 4 битийн MLC горимд зай эзэлдэг гэдгийг тэмдэглэх нь зүйтэй. Энэ нь бидний хувьд 4 гигабайт хоосон зай тутамд зөвхөн 1 гигабайт SLC кэш авна гэсэн үг юм.

72 гигабайтыг 4-өөр үржүүлээд 288 гигабайт авна. Энэ бол хөтчүүдэд SLC кэшийг бүрэн ашиглах боломжийг олгохын тулд бид тэмдэглэхгүй хоосон зай юм.

Тиймээс бид нийт зургаан хөтчөөс 312 гигабайт хүртэлх SLC кэшийг үр дүнтэй авах болно. Бүх хөтчүүдээс 2-ыг нь RAID-д нөөцлөхөд ашиглах болно.

Энэ хэмжээний кэш нь бодит амьдрал дээр бичих нь кэш рүү орохгүй байх тохиолдол маш ховор тохиолддог. Энэ нь QLC санах ойн хамгийн гунигтай сул талыг маш сайн нөхдөг - кэшийг тойрон өгөгдөл бичих үед бичих хурд маш бага. Хэрэв таны ачаалал үүнтэй тохирохгүй бол мэдээллийн хуудаснаас TBW-ийг харгалзан SSD ийм ачаалалд хэр удаан үргэлжлэх талаар сайн бодохыг зөвлөж байна.

#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 нөөцийг дэмий үрэх болно. Бид угсарсан SSD массивуудыг "эхлүүлэх" тулд боломжтой бол TRIM/DISCARD ашигладаг.

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% нь 512К-ээс хэтрэхгүй байна.

RAID нь бичихэд 6 IOPS-тэй үргэлж нэг хөтөчийн IOPS-ээс бага буюу тэнцүү байна. Санамсаргүй уншсан тохиолдолд IOPS нь нэг хөтчийнхээс хэд дахин их байж болох бөгөөд энд блокийн хэмжээ чухал ач холбогдолтой юм.
Зохиогч нь RAID 6-ийн дизайны хувьд муу параметрийг оновчтой болгохыг оролдох нь утгагүй бөгөөд оронд нь RAID 6-г юугаараа сайн болохыг оновчтой болгодог.
Бид RAID 6-ийн санамсаргүй бичих мууг NVMe кэш болон нимгэн хангамжийн аргуудаар нөхөх болно.

Бид RAID 6-д DISCARD-г хараахан идэвхжүүлээгүй байна. Тиймээс бид энэ массивыг одоогоор "эхлүүлэхгүй". Бид үүнийг дараа нь үйлдлийн систем суулгасны дараа хийх болно.

SATA хатуу диск

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

NVMe RAID дээрх LVM

Хурдны хувьд бид root файлын системийг /dev/md1 гэсэн NVMe RAID 0 дээр байрлуулахыг хүсч байна.
Гэсэн хэдий ч своп, мета өгөгдөл болон LVM-кэш, LVM-нимгэн мета өгөгдөл зэрэг бусад хэрэгцээнд энэ хурдан массив хэрэгтэй хэвээр байх тул бид энэ массив дээр LVM VG үүсгэх болно.

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

Эх файлын системд зориулсан хуваалт үүсгэцгээе.

#lvcreate -L 128G --name root root

RAM-ийн хэмжээгээр солих хуваалт үүсгэцгээе.

#lvcreate -L 32G --name swap root

OS суулгах

Ерөнхийдөө системийг суулгахад шаардлагатай бүх зүйл бидэнд байна.

Ubuntu Live орчноос систем суулгах шидтэнг ажиллуулна уу. Ердийн суурилуулалт. Зөвхөн суулгах дискийг сонгох үе шатанд та дараахь зүйлийг зааж өгөх хэрэгтэй.

  • /dev/md1, - холбох цэг /ачаалах, FS - BTRFS
  • /dev/root/root (aka /dev/mapper/root-root), - холбох цэг / (root), FS - BTRFS
  • /dev/root/swap (aka /dev/mapper/root-swap), - swap хуваалт болгон ашиглах
  • /dev/sda дээр ачаалагчийг суулгана уу

Та BTRFS-ийг үндсэн файлын системээр сонгоход суулгагч автоматаар / (root) -д "@", / home-д "@" гэсэн нэртэй хоёр BTRFS боть үүсгэх болно.

Суулгацаа эхлүүлцгээе...

Суулгац нь ачаалагчийг суулгахад алдаа гарсныг харуулсан модаль харилцах цонхоор дуусах болно. Харамсалтай нь та стандарт хэрэгслээр энэ харилцах цонхноос гарч, суулгалтыг үргэлжлүүлэх боломжгүй. Бид системээс гараад дахин нэвтэрч, цэвэр 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-ийг засах хэрэгтэй

TRIM/DISCARD-ийг идэвхжүүлэхийн тулд RAID 6 модулийн параметрүүдийг тохируулцгаая:

#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 онд хангалттай байхаар тохируулна уу. Анхдагч утга нь Линуксыг үүсгэснээс хойш өөрчлөгдөөгүй бөгөөд удаан хугацаанд хангалтгүй байсан бололтой.
  • Массив шалгах/синхрончлолын хугацаанд хамгийн багадаа IO-г нөөцөл. Энэ нь таны массивууд ачааллын дор мөнхийн синхрончлолын төлөвт гацахаас сэргийлэх зорилготой юм.
  • Массивыг шалгах/синхрончлох үед хамгийн их IO-г хязгаарлах. Энэ нь SSD RAID-г синхрончлох/шалгах нь таны хөтчүүдийг хурцадмал болгохгүйн тулд зайлшгүй шаардлагатай. Энэ нь ялангуяа NVMe-ийн хувьд үнэн юм. (Радиаторыг санаж байна уу? Би тоглоогүй.)
  • APM-ээр дамжуулан дискний эргэлтийг (HDD) зогсоохыг хориглож, дискний хянагчдад ажиллах хугацааг 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-ээр хайх болно. Массивын нэршил онолын хувьд өөрчлөгдөж болно.

Бид үлдсэн хэсгүүдийг /dev/mapper/vg-lv тэмдэглэгээнд LVM нэрээр хайх болно, учир нь Тэд хуваалтыг маш өвөрмөц байдлаар тодорхойлдог.

Учир нь бид LVM-д UUID ашигладаггүй LVM эзлэхүүний UUID болон тэдгээрийн хормын хувилбарууд ижил байж болно.Mount /dev/mapper/root-root.. хоёр удаа?Тиймээ. Яг. BTRFS-ийн онцлог. Энэ файлын системийг өөр өөр дэд фонтойгоор хэд хэдэн удаа холбож болно.

Үүнтэй ижил функцийн улмаас би идэвхтэй BTRFS ботьуудын LVM агшин зуурын зургийг хэзээ ч үүсгэхгүй байхыг зөвлөж байна. Та дахин ачаалах үед гэнэтийн зүйл хүлээж магадгүй юм.

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

Энэ юу байсан юм..?Бид эзэлсэн зайны 90%-д эзлэхүүний 5%-д хүрэхэд LVM нимгэн усан сангуудыг автоматаар өргөтгөх боломжийг идэвхжүүлсэн.

Бид LVM кэшэд зориулсан кэш блокуудын дээд тоог нэмэгдүүлсэн.

Бид LVM-ээс LVM эзлэхүүнийг (PV) хайхаас сэргийлсэн:

  • LVM кэш (cdata) агуулсан төхөөрөмжүүд
  • LVM кэш ашиглан кэш хийсэн төхөөрөмжүүд, кэшийг тойрч гарах ( _corig). Энэ тохиолдолд кэштэй төхөөрөмж өөрөө кэшээр дамжуулан сканнердсан хэвээр байх болно (зүгээр л ).
  • LVM кэш мета өгөгдөл (cmeta) агуулсан төхөөрөмжүүд
  • нэрийн зураг бүхий VG бүх төхөөрөмжүүд. Энд бид виртуал машинуудын дискний дүрстэй байх бөгөөд хост дээрх LVM нь зочин үйлдлийн системд хамаарах эзлэхүүнийг идэвхжүүлэхийг хүсэхгүй байна.
  • нэрийн нөөцтэй VG бүх төхөөрөмжүүд. Энд бид виртуал машины зургийн нөөц хуулбарыг авах болно.
  • нэр нь "gpv"-ээр төгссөн бүх төхөөрөмж (зочны физик хэмжээ)

Бид LVM VG дээр сул зай гаргах үед DISCARD дэмжлэгийг идэвхжүүлсэн. Болгоомжтой байгаарай. Энэ нь SSD дээрх LV-г устгахад нэлээд цаг хугацаа шаардагдана. Энэ нь ялангуяа SSD RAID 6-д хамаатай. Гэсэн хэдий ч төлөвлөгөөний дагуу бид нимгэн хангамжийг ашиглах тул энэ нь бидэнд огт саад болохгүй.

Initramfs зургийг шинэчилье:

#update-initramfs -u -k all

Grub-г суулгаж тохируулах:

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

Аль дискийг сонгох вэ?Бүх хүмүүс sd*. Систем нь ямар ч ажиллаж байгаа SATA диск эсвэл SSD-ээс ачаалах боломжтой байх ёстой.

Тэд яагаад os-prober нэмсэн..?Хэт их бие даасан байдал, хөгжилтэй гаруудын хувьд.

Хэрэв RAID-ийн аль нэг нь муудсан төлөвт байгаа бол энэ нь зөв ажиллахгүй. Энэ техник хангамж дээр ажилладаг виртуал машинуудад ашиглагддаг хуваалтууд дээр үйлдлийн систем хайхыг оролддог.

Хэрэв танд хэрэгтэй бол орхиж болно, гэхдээ дээр дурдсан бүх зүйлийг санаарай. Би онлайнаар дэггүй гараас салах жор хайхыг зөвлөж байна.

Ингэснээр бид анхны суулгацыг дуусгасан. Шинээр суулгасан үйлдлийн системээ дахин ачаалах цаг болжээ. Ачаалах боломжтой Live CD/USB-г устгахаа бүү мартаарай.

#exit
#reboot

SATA SSD-ийн аль нэгийг ачаалах төхөөрөмж болгон сонгоно уу.

SATA SSD дээрх LVM

Энэ үед бид шинэ үйлдлийн системээ аль хэдийн ачаалж, сүлжээгээ тохируулж, терминалын эмуляторыг нээж, ажиллуулсан:

#sudo bash

Үргэлжлүүлье.

SATA SSD-ээс массивыг "эхлүүлэх":

#blkdiscard /dev/md2

Хэрэв энэ нь ажиллахгүй бол оролдоно уу:

#blkdiscard --step 65536 /dev/md2
SATA SSD дээр LVM VG үүсгэх:

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

Яагаад өөр VG..?Үнэн хэрэгтээ, бид аль хэдийн root нэртэй 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 хэмжээнээс өөр зүйлийг ашиглахгүй. Энэ дүрмийн үл хамаарах зүйл нь нөөц хуваалт байж болно.

Энэ мөчид олон уншигчид үүрлэсэн хүүхэлдэйтэй холбоотой ямар нэг зүйлийг сэжиглэж эхэлсэн гэж би бодож байна.

SATA HDD дээрх LVM

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

Дахиад шинэ VG..?Хэрэв бидний өгөгдөл нөөцлөхөд ашиглах дискний массив амжилтгүй болбол манай үйлдлийн систем хэвийн ажиллаж, нөөцлөгдсөн бус өгөгдөлд хандах хандалтыг хэвийн байлгахыг бид үнэхээр хүсч байна. Тиймээс VG идэвхжүүлэх асуудлаас зайлсхийхийн тулд бид тусдаа VG үүсгэдэг.

LVM кэшийг тохируулж байна

NVMe RAID 1 дээр LV үүсгэн үүнийг кэш төхөөрөмж болгон ашиглацгаая.

#lvcreate -L 70871154688B --name cache root

Яагаад ийм бага байгаа юм бэ...?Баримт нь манай NVMe SSD нь SLC кэштэй байдаг. 4 битийн MLC-д хоосон зай эзэлснээс болж 18 гигабайт "үнэгүй", 3 гигабайт динамик. Энэ кэш дууссаны дараа NVMe SSD нь манай кэштэй SATA SSD-ээс хурдан ажиллахгүй. Үнэндээ энэ шалтгааны улмаас LVM кэш хуваалтыг NVMe дискний SLC кэшээс хоёр дахин том болгох нь утгагүй юм. Ашигласан NVMe хөтчүүдийн хувьд зохиогч 32-64 гигабайт кэш хийх нь зүйтэй гэж үзэж байна.

Өгөгдсөн хуваалтын хэмжээ нь 64 гигабайт кэш, кэш мета өгөгдөл, мета өгөгдлийн нөөцлөлтийг зохион байгуулахад шаардлагатай.

Нэмж хэлэхэд, бохир систем унтарсны дараа LVM кэшийг бүхэлд нь бохир гэж тэмдэглэж, дахин синхрончлох болно гэдгийг би анхаарна уу. Үүнээс гадна, системийг дахин ачаалах хүртэл энэ төхөөрөмж дээр lvchange-г ашиглах бүрт энэ нь давтагдах болно. Тиймээс би тохирох скриптийг ашиглан кэшийг нэн даруй дахин үүсгэхийг зөвлөж байна.

SATA RAID 6 дээр LV үүсгэн үүнийг кэш төхөөрөмж болгон ашиглацгаая.

#lvcreate -L 3298543271936B --name cache data

Яагаад гуравхан терабайт гэж?Тиймээс шаардлагатай бол SATA SSD RAID 6-г бусад хэрэгцээнд ашиглаж болно. Кэшийн зайны хэмжээг системийг зогсоохгүйгээр динамикаар нэмэгдүүлэх боломжтой. Үүнийг хийхийн тулд та кэшийг түр зогсоож, дахин идэвхжүүлэх хэрэгтэй, гэхдээ LVM-кэш, жишээлбэл 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

Хоёроор үржүүлж, LVM PV мета өгөгдөлд 4194304B нэмнэ: 8594128896B
LVM нимгэн мета өгөгдөл болон тэдгээрийн нөөц хуулбарыг байрлуулахын тулд NVMe RAID 1 дээр тусдаа хуваалт үүсгэцгээе:

#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
Яагаад -З жЭнэ горим нь яг юунд зориулагдсанаас гадна орон зайг дахин хуваарилах үед нэг виртуал машинаас өгөгдөл нөгөө виртуал машин руу урсахаас сэргийлэхийн тулд - тэглэх нь 64к-ээс бага хэмжээтэй блокуудад санамсаргүй бичих хурдыг нэмэгдүүлэхийн тулд нэмэлт хэрэглэгддэг. Нимгэн эзэлхүүний өмнө нь хуваарилагдаагүй хэсэгт 64к-аас бага хэмжээтэй бичих нь кэш дэх 64К ирмэгтэй зэрэгцэх болно. Энэ нь кэшэд хадгалагдсан төхөөрөмжийг тойрч гарах ажиллагааг бүхэлд нь кэшээр гүйцэтгэх боломжийг олгоно.

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 өөр тест хийх болно. Туршилтын тал хувь нь бичлэг хийх зориулалттай. Та 4 секундын дотор NVMe дээр маш их бичлэг хийх боломжтой. Секундэд 3 гигабайт хүртэл. Тиймээс бичих тест бүр нь танаас 216 гигабайт хүртэлх SSD нөөцийг идэж болно.

Унших, бичих хосолсон уу?Тиймээ. Унших, бичих тестийг тусад нь явуулах нь утга учиртай. Нэмж дурдахад, бүх кэшийг синхрончлох нь зүйтэй бөгөөд ингэснээр өмнө нь бичсэн бичиг нь уншихад нөлөөлөхгүй.

Кэш болон нимгэн эзэлхүүнийг дүүргэх тусам эхний болон дараагийн ачааллын үед үр дүн нь ихээхэн ялгаатай байх болно, мөн систем сүүлийн эхлүүлэх үед дүүргэсэн кэшийг синхрончилж чадсан эсэхээс хамаарна.

Бусад зүйлсийн дотор би хурдыг яг л агшин зуурын зургийг авсан бүрэн нимгэн эзэлхүүн дээр хэмжихийг зөвлөж байна. Зохиогч анхны агшин зуурын зургийг үүсгэсний дараа санамсаргүй бичлэг хэрхэн огцом хурдасч байгааг, ялангуяа кэш бүрэн дүүрэн хийгээгүй үед ажиглах боломжтой болсон. Энэ нь бичихэд хуулах семантик, кэш болон нимгэн эзэлхүүний блокуудыг зэрэгцүүлэх, RAID 6-д санамсаргүй бичих нь RAID 6-аас санамсаргүй уншигдах, дараа нь кэш рүү бичих зэрэгтэй холбоотой юм. Бидний тохиргоонд RAID 6-аас санамсаргүй унших нь бичихээс 6 дахин (массив дахь SATA SSD-ийн тоо) илүү хурдан байдаг. Учир нь CoW-д зориулсан блокуудыг нимгэн усан сангаас дараалан хуваарилдаг бөгөөд дараа нь бичлэг нь ихэнх тохиолдолд дараалсан болж хувирдаг.

Эдгээр хоёр функцийг таны давуу тал болгон ашиглаж болно.

"Нэгдмэл" агшин зуурын зургийг кэш

Кэш гэмтсэн / алдагдсан тохиолдолд өгөгдөл алдагдах эрсдэлийг бууруулахын тулд зохиогч энэ тохиолдолд бүрэн бүтэн байдлыг баталгаажуулахын тулд агшин зуурын зургийг эргүүлэх практикийг нэвтрүүлэхийг санал болгож байна.

Нэгдүгээрт, нимгэн эзэлхүүнтэй мета өгөгдөл нь кэшгүй төхөөрөмж дээр байрладаг тул мета өгөгдөл нь тогтвортой байх бөгөөд болзошгүй алдагдлыг өгөгдлийн блок дотор тусгаарлах болно.

Дараах агшин зуурын зургийг эргүүлэх мөчлөг нь кэш алдагдсан тохиолдолд агшин зуурын агшин дахь өгөгдлийн бүрэн бүтэн байдлыг баталгаажуулдаг.

  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 килобайт хэмжээтэй секторт ямар нэг зүйл бичсэн бол дараагийн хэдэн минутын дотор ижил эсвэл хөрш (+- 32К) секторт бичлэг хийх магадлал өндөр байна.

Шилжилтийн босгыг тэг болгосноор бид SATA SSD дээр бичих синхрончлолыг хойшлуулж, кэш дэх нэг 64К блок болгон хэд хэдэн өөрчлөлтийг нэгтгэдэг. Энэ нь SATA SSD-ийн нөөцийг ихээхэн хэмнэдэг.

Код хаана байна..?Харамсалтай нь зохиолч өөрийгөө 100% бие даан суралцаж, "google-д суурилсан хөгжүүлэлт" дадлага хийдэг тул bash скрипт боловсруулахад хангалтгүй гэж үздэг тул түүний гараас гарч буй аймшигт кодыг хэн ч ашиглах ёсгүй гэж тэр үзэж байна. өөр.

Энэ салбарын мэргэжилтнүүд шаардлагатай бол дээр дурдсан бүх логикийг бие даан дүрсэлж, магадгүй зохиогчийн оролдсон шиг үүнийг системийн үйлчилгээ болгон сайхан зохиож чадна гэж би бодож байна.

Ийм энгийн агшин зуурын зургийг эргүүлэх схем нь SATA SSD дээр нэг агшин зуурын зургийг байнга бүрэн синхрончлох боломжийг олгодог төдийгүй thin_delta хэрэгслийг ашиглан үүнийг үүсгэсний дараа аль блокууд өөрчлөгдсөнийг олж мэдэх, улмаар гэмтлийг нутагшуулах боломжийг олгоно. үндсэн боть, ихээхэн хялбаршуулсан сэргээх .

libvirt/KVM-д TRIM/DISCARD

Учир нь Мэдээллийн хадгалалт нь libvirt-ийг ажиллуулж байгаа KVM-д ашиглагдах тул манай 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>

Зочин үйлдлийн системүүдийн ийм DISCARD-уудыг LVM зөв боловсруулж, блокуудыг кэш болон нимгэн бассейнд зөв чөлөөлдөг. Манай тохиолдолд энэ нь дараагийн агшин зуурын зургийг устгах үед ихэвчлэн хойшлогдсон байдлаар тохиолддог.

BTRFS нөөцлөлт

Бэлэн скриптүүдийг ашиглана уу туйлын болгоомжтой болон өөрийн эрсдэлд. Зохиогч энэ кодыг өөрөө болон зөвхөн өөртөө зориулж бичсэн. Олон туршлагатай Линукс хэрэглэгчид ижил төстэй хэрэгсэлтэй байдаг бөгөөд хэн нэгнийхийг хуулбарлах шаардлагагүй гэдэгт би итгэлтэй байна.

Нөөц төхөөрөмж дээр эзлэхүүн үүсгэцгээе:

#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 илгээх/хүлээн авах аргыг ашиглан BTRFS агшин зуурын зураг үүсгэх, өөр FS рүү хуулах энгийн командуудыг агуулсан.

Эхний хөөргөх хугацаа харьцангуй урт байж магадгүй, учир нь... Эхэндээ бүх өгөгдлийг хуулах болно. Цаашдын хөөргөлтүүд маш хурдан байх болно, учир нь... Зөвхөн өөрчлөлтийг хуулах болно.

Бидний 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

Энэ юу хийдэг вэ..?Нөөц FS дээр жагсаасан BTRFS ботьуудын өсөлттэй агшин зургийг үүсгэж, синхрончилдог. Үүний дараа 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 логик эзлэхүүн нь бусад VG-ийн LVM PV физик эзлэхүүн байж болно гэдгийг харгалзан үзэх магадлалтай. LVM нь үүрлэсэн хүүхэлдэй шиг рекурсив байж болно. Энэ нь LVM-д туйлын уян хатан байдлыг өгдөг.

PS

Дараагийн өгүүллээр бид гэрийн ширээний компьютер, гэрийн интернет болон P2P сүлжээг ашиглан хэд хэдэн тивд илүүдэлтэй, гео-тархлагдсан санах ой/vm кластер үүсгэх үндэс болгон ижил төстэй хөдөлгөөнт хадгалах систем/KVM ашиглахыг хичээх болно.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх