Шта ЛВМ и Матрјошка имају заједничко?

Добар дан.
Желео бих да поделим са заједницом своје практично искуство изградње система за складиштење података за КВМ користећи мд РАИД + ЛВМ.

Програм ће укључивати:

  • Изградња мд РАИД 1 са НВМе ССД-а.
  • Састављање мд РАИД 6 са САТА ССД-а и обичних дискова.
  • Карактеристике рада ТРИМ/ДИСЦАРД на ССД РАИД 1/6.
  • Креирање мд РАИД 1/6 низа за покретање на уобичајеном скупу дискова.
  • Инсталирање система на НВМе РАИД 1 када нема подршке за НВМе у БИОС-у.
  • Коришћење ЛВМ кеша и ЛВМ танке.
  • Коришћење БТРФС снимака и слање/примање за резервну копију.
  • Коришћење ЛВМ танких снимака и танких_делта за резервне копије у БТРФС стилу.

Ако сте заинтересовани, погледајте кат.

Изјава

Аутор не сноси никакву одговорност за последице коришћења или некоришћења материјала/примера/кода/савета/података из овог чланка. Читањем или коришћењем овог материјала на било који начин преузимате одговорност за све последице ових радњи. Могуће последице укључују:

  • Пржени НВМе ССД дискови.
  • Потпуно потрошен ресурс за снимање и квар ССД дискова.
  • Потпуни губитак свих података на свим дисковима, укључујући резервне копије.
  • Неисправан рачунарски хардвер.
  • Потрошено време, живци и новац.
  • Све друге последице које нису горе наведене.

Гвожђе

Доступни су били:

Матична плоча из 2013. године са З87 чипсетом, заједно са Интел Цоре и7 / Хасвелл.

  • Процесор 4 језгра, 8 нити
  • 32 ГБ ДДР3 РАМ
  • 1 к 16 или 2 к 8 ПЦИе 3.0
  • 1 к 4 + 1 к 1 ПЦИе 2.0
  • 6 к 6 ГБпс САТА 3 конектора

САС адаптер ЛСИ САС9211-8И је прешао на ИТ / ХБА режим. Фирмвер са РАИД-ом је намерно замењен ХБА фирмвером да би:

  1. Можете избацити овај адаптер у било ком тренутку и заменити га било којим другим на који наиђете.
  2. ТРИМ/Дисцард је нормално радио на дисковима, јер... у РАИД фирмверу ове команде уопште нису подржане, а ХБА, генерално, није брига које се команде преносе преко магистрале.

Чврсти дискови - 8 комада ХГСТ Травелстар 7К1000 капацитета 1 ТБ у фактору 2.5, као за лаптопове. Ови дискови су раније били у РАИД 6 низу. Они ће такође имати користи у новом систему. За чување локалних резервних копија.

Додатно додато:

6 комада САТА ССД модел Самсунг 860 КВО 2ТБ. Ови ССД дискови захтевали су велику запремину, присуство СЛЦ кеш меморије, поузданост и ниску цену. Потребна је подршка за одбацивање/нула, што се проверава линијом у дмесг-у:

kernel: ata1.00: Enabling discard_zeroes_data

2 комада НВМе ССД модела Самсунг ССД 970 ЕВО 500ГБ.

За ове ССД-ове важна је насумична брзина читања/писања и капацитет ресурса за ваше потребе. Радијатор за њих. Неопходно. Апсолутно. У супротном, пржите их док не постану хрскаве током прве РАИД синхронизације.

СтарТецх ПЕКС8М2Е2 адаптер за 2 к НВМе ССД инсталиран у ПЦИе 3.0 8к слот. Ово је, опет, само ХБА, али за НВМе. Од јефтиних адаптера се разликује по томе што не захтева подршку за ПЦИе бифуркацију са матичне плоче због присуства уграђеног ПЦИе прекидача. Радиће чак и у најстаријем систему са ПЦИе, чак и ако је к1 ПЦИе 1.0 слот. Наравно, одговарајућом брзином. Тамо нема РАИД-ова. На плочи нема уграђеног БИОС-а. Дакле, ваш систем неће магично научити да се покреће помоћу НВМе, а још мање да ради НВМе РАИД захваљујући овом уређају.

Ова компонента је настала искључиво због присуства само једног бесплатног 8к ПЦИе 3.0 у систему, а, ако постоје 2 слободна слота, лако се може заменити са два пенија ПЕКС4М2Е1 или аналога, који се могу купити било где по цени од 600 рубља.

Одбацивање свих врста хардвера или уграђених чипсета/БИОС РАИД-ова направљено је намерно, како би се у потпуности могао заменити цео систем, са изузетком самих ССД/ХДД, уз очување свих података. Идеално, тако да можете сачувати чак и инсталирани оперативни систем када пређете на потпуно нови/другачији хардвер. Главна ствар је да постоје САТА и ПЦИе портови. То је као ливе ЦД или флеш диск за покретање, само веома брз и мало гломазан.

ХуморИначе, знате шта се дешава - понекад морате хитно да понесете цео низ са собом да га однесете. Али не желим да изгубим податке. Да бисте то урадили, сви поменути медији су погодно смештени на слајдовима у лежиштима од 5.25 стандардног кућишта.

Па, и, наравно, за експериментисање са различитим методама ССД кеширања у Линуку.

Хардверске рације су досадне. Укључите га. Или ради или не. А са мдадм-ом увек постоје опције.

Софтвер

Раније је Дебиан 8 Јессие био инсталиран на хардверу, који је близу ЕОЛ-а. РАИД 6 је састављен од горе наведених ХДД-ова упарених са ЛВМ-ом. Покренуо је виртуелне машине у квм/либвирт.

Јер Аутор има одговарајуће искуство у креирању преносивих САТА/НВМе флеш дискова за покретање система, а такође, да не би нарушио уобичајени апт шаблон, као циљни систем је изабран Убунту 18.04, који је већ довољно стабилизован, али има још 3 године рада. подршку у будућности.

Поменути систем садржи све хардверске драјвере који су нам потребни из кутије. Не треба нам никакав софтвер или драјвери треће стране.

Припрема за уградњу

Да бисмо инсталирали систем, потребан нам је Убунту Десктоп Имаге. Серверски систем има неку врсту снажног инсталатера, који показује претерану независност која се не може онемогућити гурањем УЕФИ системске партиције на један од дискова, кварећи сву лепоту. Сходно томе, инсталира се само у УЕФИ режиму. Не нуди никакве опције.

Нисмо задовољни овим.

Зашто?Нажалост, УЕФИ покретање је изузетно лоше компатибилно са РАИД софтвером за покретање, јер... Нико нам не нуди резервације за УЕФИ ЕСП партицију. На мрежи постоје рецепти који предлажу постављање ЕСП партиције на флеш диск у УСБ порт, али ово је тачка неуспеха. Постоје рецепти који користе софтвер мдадм РАИД 1 са метаподацима верзије 0.9 који не спречавају УЕФИ БИОС да види ову партицију, али то траје до срећног тренутка када БИОС или неки други хардверски ОС запише нешто у ЕСП и заборави да га синхронизује са другим огледала.

Поред тога, УЕФИ покретање зависи од НВРАМ-а, који се неће померити заједно са дисковима на нови систем, јер је део матичне плоче.

Дакле, нећемо поново измишљати нови точак. Већ имамо готов, временски тестиран дедин бицикл, који се сада зове Легаци/БИОС боот, који носи поносно име ЦСМ на системима компатибилним са УЕФИ. Само ћемо га скинути са полице, подмазати, напумпати гуме и обрисати влажном крпом.

Десктоп верзија Убунту-а такође не може да се правилно инсталира са Легаци боотлоадер-ом, али овде, како кажу, барем постоје опције.

И тако, прикупљамо хардвер и учитавамо систем са Убунту Ливе флеш диска за покретање. Мораћемо да преузмемо пакете, тако да ћемо поставити мрежу која ради за вас. Ако не ради, можете унапред учитати потребне пакете на флеш диск.

Улазимо у окружење радне површине, покрећемо емулатор терминала и крећемо:

#sudo bash

Како…?Горња линија је канонски окидач за холиваре о судоу. Ц бодолазе веће прилике иовећа одговорност. Питање је да ли можете то да преузмете на себе. Многи људи мисле да коришћење судоа на овај начин барем није опрезно. Међутим:

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

Зашто не ЗФС...?Када инсталирамо софтвер на наш рачунар, у суштини свој хардвер позајмљујемо програмерима овог софтвера за вожњу.
Када овом софтверу поверимо сигурност наших података, узимамо кредит једнак трошку враћања ових података, који ћемо једног дана морати да отплатимо.

Са ове тачке гледишта, ЗФС је Ферари, а мдадм+лвм је више као бицикл.

Субјективно, аутор више воли да позајми бицикл на кредит непознатим лицима уместо Ферарија. Тамо цена питања није висока. Нема потребе за правима. Једноставније од саобраћајних правила. Паркинг је бесплатан. Способност за трчање је боља. Увек можете причврстити ноге на бицикл, а можете поправити бицикл својим рукама.

Зашто онда БТРФС...?Да бисмо покренули оперативни систем, потребан нам је систем датотека који је подржан у Легаци/БИОС ГРУБ-у из кутије, а у исто време подржава снимке уживо. Користићемо га за /боот партицију. Поред тога, аутор више воли да користи овај ФС за / (роот), не заборављајући да напомене да за било који други софтвер можете креирати засебне партиције на ЛВМ-у и монтирати их у потребне директоријуме.

Нећемо чувати никакве слике виртуелних машина или база података на овом ФС.
Овај ФС ће се користити само за креирање снимака система без искључивања, а затим преношење ових снимака на резервни диск помоћу слања/примања.

Поред тога, аутор генерално преферира да задржи минимум софтвера директно на хардверу и покрене сав други софтвер на виртуелним машинама користећи ствари попут прослеђивања ГПУ-а и ПЦИ-УСБ Хост контролера на КВМ преко ИОММУ-а.

Једине ствари које су остале на хардверу су складиштење података, виртуелизација и резервна копија.

Ако више верујете ЗФС-у, онда су, у принципу, за наведену апликацију они заменљиви.

Међутим, аутор намерно игнорише уграђене функције пресликавања/РАИД-а и редундантности које имају ЗФС, БРТФС и ЛВМ.

Као додатни аргумент, БТРФС има могућност да насумично уписивање претвори у секвенцијално, што изузетно позитивно утиче на брзину синхронизовања снимака/бекапа на ХДД-у.

Хајде да поново скенирамо све уређаје:

#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

Распоред диска

НВМе ССД

Али нећемо их ни на који начин обележавати. Свеједно, наш БИОС не види ове дискове. Дакле, они ће у потпуности прећи на софтверски РАИД. Нећемо чак ни креирати одељке тамо. Ако желите да пратите „канон“ или „принципијелно“, направите једну велику партицију, као што је ХДД.

САТА ХДД

Не треба овде ништа посебно измишљати. Направићемо један одељак за све. Направићемо партицију јер БИОС види ове дискове и можда чак покуша да се покрене са њих. Чак ћемо касније инсталирати и ГРУБ на ове дискове како би систем то одједном могао да уради.

#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

САТА ССД

Овде ствари постају интересантне за нас.

Прво, наши дискови су величине 2 ТБ. Ово је у оквиру прихватљивог опсега за МБР, што ћемо користити. Ако је потребно, може се заменити ГПТ-ом. ГПТ дискови имају слој компатибилности који омогућава системима компатибилним са МБР-ом да виде прве 4 партиције ако се налазе унутар прва 2 терабајта. Главна ствар је да партиција за покретање и партиција биос_груб на овим дисковима треба да буду на почетку. Ово вам чак омогућава и покретање са ГПТ Легаци/БИОС диск јединица.

Али ово није наш случај.

Овде ћемо направити два одељка. Први ће бити величине 1 ГБ и користиће се за РАИД 1 /боот.

Други ће се користити за РАИД 6 и заузеће сав преостали слободни простор осим мале недодељене области на крају диска.

Шта је ово необележено подручје?Према изворима на мрежи, наши САТА ССД дискови имају динамички прошириву СЛЦ кеш меморију величине од 6 до 78 гигабајта. Добијамо 6 гигабајта „бесплатно“ због разлике између „гигабајта“ и „гибибајта“ у таблици података диск јединице. Преостала 72 гигабајта се додељују из неискоришћеног простора.

Овде треба напоменути да имамо СЛЦ кеш, а простор је заузет у 4-битном МЛЦ режиму. Што за нас ефективно значи да ћемо на свака 4 гигабајта слободног простора добити само 1 гигабајт СЛЦ кеша.

Помножите 72 гигабајта са 4 и добићете 288 гигабајта. Ово је слободан простор који нећемо означавати како бисмо дозволили дисковима да у потпуности искористе СЛЦ кеш меморију.

Тако ћемо ефективно добити до 312 гигабајта СЛЦ кеша са укупно шест дискова. Од свих дискова, 2 ће се користити у РАИД-у за редундантност.

Ова количина кеша ће нам омогућити да изузетно ретко у стварном животу наиђемо на ситуацију да запис не иде у кеш меморију. Ово изузетно добро компензује најтужнији недостатак КЛЦ меморије – изузетно ниску брзину писања када се подаци записују заобилазећи кеш меморију. Ако ваша оптерећења не одговарају овоме, онда вам препоручујем да добро размислите колико дуго ће ваш ССД издржати под таквим оптерећењем, узимајући у обзир ТБВ из листа са подацима.

#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

Креирање низова

Прво, морамо преименовати машину. Ово је неопходно јер је име хоста део имена низа негде унутар мдадм-а и негде утиче на нешто. Наравно, низови се могу касније преименовати, али ово је непотребан корак.

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

НВМе ССД

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

Зашто -претпоставити-чистити...?Да бисте избегли иницијализацију низова. За оба РАИД нивоа 1 и 6 ово важи. Све може да ради без иницијализације ако је нови низ. Штавише, иницијализација ССД низа након креирања је губитак ТБВ ресурса. Користимо ТРИМ/ДИСЦАРД где је то могуће на састављеним ССД низовима да бисмо их „иницијализовали“.

За ССД низове, РАИД 1 ДИСЦАРД је подржан из кутије.

За ССД РАИД 6 ДИСЦАРД низове, морате га омогућити у параметрима модула кернела.

Ово би требало да се уради само ако сви ССД дискови који се користе у низовима нивоа 4/5/6 у овом систему имају радну подршку за дисцард_зероес_дата. Понекад наиђете на чудне дискове који говоре кернелу да је ова функција подржана, али је у ствари нема или функција не ради увек. Тренутно је подршка доступна скоро свуда, међутим, постоје стари дискови и фирмвер са грешкама. Из тог разлога, подршка ДИСЦАРД је подразумевано онемогућена за РАИД 6.

Пажња, следећа команда ће уништити све податке на НВМе драјвовима „иницијализацијом“ низа „нулама“.

#blkdiscard /dev/md0

Ако нешто крене наопако, покушајте да наведете корак.

#blkdiscard --step 65536 /dev/md0

САТА ССД

#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

Зашто тако велики...?Повећање величине комада има позитиван ефекат на брзину насумично читања у блоковима до укључујући величину комада. Ово се дешава зато што се једна операција одговарајуће величине или мање може у потпуности обавити на једном уређају. Дакле, ИОПС са свих уређаја се сумира. Према статистикама, 99% ИО не прелази 512К.

РАИД 6 ИОПС по запису увек мањи или једнак ИОПС једног диска. Када, као насумично читање, ИОПС може бити неколико пута већи од оног на једном диску, и овде је величина блока од кључног значаја.
Аутор не види смисао у покушају да оптимизује параметар који је лош у РАИД 6 дизајну и уместо тога оптимизује оно у чему је РАИД 6 добар.
Надокнадићемо лоше насумично уписивање РАИД-а 6 са НВМе кеш меморијом и триковима танког обезбеђивања.

Још увек нисмо омогућили ДИСЦАРД за РАИД 6. Тако да за сада нећемо „иницијализовати“ овај низ. То ћемо урадити касније, након инсталирања ОС-а.

САТА ХДД

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

ЛВМ на НВМе РАИД-у

Ради брзине, желимо да поставимо основни систем датотека на НВМе РАИД 1 који је /дев/мд0.
Међутим, и даље ће нам требати овај брзи низ за друге потребе, као што су размена, метаподаци и ЛВМ-кеш и ЛВМ-танки метаподаци, тако да ћемо креирати ЛВМ ВГ на овом низу.

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

Хајде да направимо партицију за основни систем датотека.

#lvcreate -L 128G --name root root

Хајде да направимо партицију за размену према величини РАМ-а.

#lvcreate -L 32G --name swap root

инсталација ОС-а

Укупно имамо све што је потребно за инсталирање система.

Покрените чаробњак за инсталацију система из Убунту Ливе окружења. Нормална инсталација. Само у фази одабира дискова за инсталацију, потребно је да наведете следеће:

  • /дев/мд1, - тачка монтирања /боот, ФС - БТРФС
  • /дев/роот/роот (ака /дев/маппер/роот-роот), - тачка монтирања / (роот), ФС - БТРФС
  • /дев/роот/свап (ака /дев/маппер/роот-свап), - користите као свап партицију
  • Инсталирајте покретач на /дев/сда

Када изаберете БТРФС као основни систем датотека, инсталатер ће аутоматски креирати два БТРФС волумена под називом "@" за / (роот) и "@хоме" за /хоме.

Почнимо са инсталацијом...

Инсталација ће се завршити модалним оквиром за дијалог који указује на грешку при инсталацији покретача. Нажалост, нећете моћи да изађете из овог дијалога стандардним средствима и наставите са инсталацијом. Одјављујемо се из система и поново се пријављујемо, завршавајући на чистој Убунту Ливе радној површини. Отворите терминал и поново:

#sudo bash

Креирајте цхроот окружење да бисте наставили инсталацију:

#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

Хајде да конфигуришемо мрежу и име хоста у цхроот-у:

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

Идемо у цхроот окружење:

#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

Ако нешто не успе, можда ћете морати прво да уредите /етц/апт/соурцес.лист

Хајде да прилагодимо параметре за РАИД 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

Шта је то..?Направили смо скуп удев правила која ће урадити следеће:

  • Подесите величину кеша блока за РАИД 2020 да буде адекватна за 6. Подразумевана вредност се, изгледа, није променила од стварања Линукса и није била адекватна већ дуже време.
  • Резервишите минимум ИО-а за време провера/синхронизација низа. Ово је да спречите да се ваши низови заглаве у стању вечне синхронизације под оптерећењем.
  • Ограничите максимални ИО током провера/синхронизације низова. Ово је неопходно како синхронизација/провера ССД РАИД-ова не би спржила ваше дискове до оштрине. Ово посебно важи за НВМе. (Сећате се радијатора? Нисам се шалио.)
  • Забраните дисковима да зауставе ротацију вретена (ХДД) преко АПМ-а и подесите временско ограничење спавања за контролере дискова на 7 сати. Можете у потпуности да онемогућите АПМ ако ваши дискови то могу (-Б 255). Са подразумеваном вредношћу, дискови ће се зауставити након пет секунди. Затим ОС жели да ресетује кеш диска, дискови ће се поново покренути и све ће почети изнова. Дискови имају ограничен максимални број ротација вретена. Такав једноставан подразумевани циклус може лако да убије ваше дискове за неколико година. Не пате сви дискови од овога, али наши су „лаптоп” са одговарајућим подразумеваним подешавањима, због којих РАИД изгледа као мини-МАИД.
  • Инсталирајте реадахеад на дискове (ротирајући) 1 мегабајт - два узастопна блока/комад РАИД 6
  • Онемогућите читање унапред на самим низовима.

Уредимо /етц/фстаб:

#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

Зашто је то..?Тражићемо /боот партицију према УУИД-у. Именовање низа би се теоретски могло променити.

Преостале одељке ћемо тражити по ЛВМ именима у /дев/маппер/вг-лв нотацији, јер они идентификују партиције сасвим јединствено.

Не користимо УУИД за ЛВМ јер УУИД ЛВМ волумена и њихових снимака могу бити исти.Монтирати /дев/маппер/роот-роот.. двапут?Да. Баш тако. Карактеристике БТРФС. Овај систем датотека се може монтирати неколико пута са различитим субволовима.

Због ове исте функције, препоручујем да никада не правите ЛВМ снимке активних БТРФС волумена. Можда ћете добити изненађење када поново покренете систем.

Хајде да поново генеришемо мдадм конфигурацију:

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

Хајде да прилагодимо ЛВМ подешавања:

#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% запремине.

Повећали смо максималан број кеш блокова за ЛВМ кеш.

Спречили смо ЛВМ да тражи ЛВМ запремине (ПВ) на:

  • уређаји који садрже ЛВМ кеш (цдата)
  • уређаји кеширани користећи ЛВМ кеш, заобилазећи кеш ( _цориг). У овом случају, сам кеширани уређај ће и даље бити скениран кроз кеш меморију (само ).
  • уређаји који садрже ЛВМ кеш метаподатке (цмета)
  • сви уређаји у ВГ са именом слике. Овде ћемо имати слике дискова виртуелних машина и не желимо да ЛВМ на хосту активира волумене који припадају гостујућем ОС-у.
  • сви уређаји у ВГ са резервном копијом имена. Овде ћемо имати резервне копије слика виртуелне машине.
  • сви уређаји чије се име завршава са „гпв“ (физички волумен за госте)

Омогућили смо ДИСЦАРД подршку приликом ослобађања слободног простора на ЛВМ ВГ. Бити пажљив. Ово ће учинити брисање ЛВ-ова на ССД-у прилично дуготрајним. Ово се посебно односи на ССД РАИД 6. Међутим, по плану ћемо користити танку провизију, тако да нас то уопште неће ометати.

Хајде да ажурирамо инитрамфс слику:

#update-initramfs -u -k all

Инсталирајте и конфигуришите груб:

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

Које дискове изабрати?Сви који су сд*. Систем мора бити у могућности да се покрене са било ког САТА уређаја који ради или ССД-а.

Зашто су додали ос-пробер..?За претерану независност и разигране руке.

Не ради исправно ако је један од РАИД-ова у деградираном стању. Покушава да тражи ОС на партицијама које се користе у виртуелним машинама које раде на овом хардверу.

Ако вам затреба, можете га оставити, али имајте на уму све горе наведено. Препоручујем да потражите рецепте за уклањање несташних руку на мрежи.

Овим смо завршили почетну инсталацију. Време је да се поново покренете на новоинсталирани ОС. Не заборавите да уклоните Ливе ЦД/УСБ за покретање.

#exit
#reboot

Изаберите било који САТА ССД као уређај за покретање.

ЛВМ на САТА ССД-у

У овом тренутку, већ смо покренули нови ОС, конфигурисали мрежу, апт, отворили емулатор терминала и покренули:

#sudo bash

Хајде да наставимо.

„Иницијализујте“ низ са САТА ССД-а:

#blkdiscard /dev/md2

Ако не ради, покушајте:

#blkdiscard --step 65536 /dev/md2
Направите ЛВМ ВГ на САТА ССД-у:

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

Зашто још један ВГ..?У ствари, већ имамо ВГ под називом роот. Зашто не додати све у један ВГ?

Ако постоји неколико ПВ-а у ВГ-у, онда да би ВГ био исправно активиран, сви ПВ-ови морају бити присутни (онлине). Изузетак је ЛВМ РАИД, који намерно не користимо.

Заиста желимо да ако дође до квара (губитак података за читање) на било ком од РАИД 6 низова, оперативни систем ће се нормално покренути и дати нам прилику да решимо проблем.

Да бисмо то урадили, на првом нивоу апстракције изоловаћемо сваку врсту физичког „медија“ у посебан ВГ.

Научно говорећи, различити РАИД низови припадају различитим „доменима поузданости“. Не би требало да им стварате додатну заједничку тачку неуспеха тако што ћете их трпати у један ВГ.

Присуство ЛВМ-а на „хардверском“ нивоу ће нам омогућити да произвољно исечемо делове различитих РАИД низова комбинујући их на различите начине. На пример - трчи истовремено бцацхе + ЛВМ танак, бцацхе + БТРФС, ЛВМ кеш + ЛВМ танак, сложена ЗФС конфигурација са кешовима, или било која друга паклена мешавина да покушате и упоредите све.

На нивоу „хардвера“, нећемо користити ништа друго осим добрих старих „дебелих“ ЛВМ волумена. Изузетак од овог правила може бити резервна партиција.

Мислим да су до овог тренутка многи читаоци већ почели да сумњају у нешто о лутки за гнежђење.

ЛВМ на САТА ХДД-у

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

Опет нови ВГ..?Заиста желимо да ако дисковни низ који ћемо користити за прављење резервних копија података не успе, наш оперативни систем настави да ради нормално, уз одржавање приступа подацима без резервне копије као и обично. Стога, да бисмо избегли проблеме са активацијом ВГ-а, креирамо посебан ВГ.

Подешавање ЛВМ кеша

Хајде да направимо ЛВ на НВМе РАИД 1 да бисмо га користили као уређај за кеширање.

#lvcreate -L 70871154688B --name cache root

Зашто је тако мало...?Чињеница је да наши НВМе ССД-ови такође имају СЛЦ кеш меморију. 4 гигабајта „слободног“ и 18 гигабајта динамичког због слободног простора заузетог у 3-битном МЛЦ-у. Када се ова кеш меморија исцрпи, НВМе ССД-ови неће бити много бржи од нашег САТА ССД-а са кешом. У ствари, из тог разлога, нема смисла да ЛВМ кеш партицију направимо много већом од двоструке величине СЛЦ кеша НВМе диска. За коришћене НВМе драјвове, аутор сматра да је разумно направити 32-64 гигабајта кеш меморије.

Дата величина партиције је потребна за организовање 64 гигабајта кеша, метаподатака кеша и резервне копије метаподатака.

Поред тога, напомињем да ће након гашења прљавог система, ЛВМ означити цео кеш као прљав и поново ће се синхронизовати. Штавише, ово ће се понављати сваки пут када се лвцханге користи на овом уређају док се систем поново не покрене. Стога препоручујем да одмах поново направите кеш користећи одговарајућу скрипту.

Хајде да направимо ЛВ на САТА РАИД 6 да бисмо га користили као кеширани уређај.

#lvcreate -L 3298543271936B --name cache data

Зашто само три терабајта?Тако да, ако је потребно, можете користити САТА ССД РАИД 6 за неке друге потребе. Величина кешираног простора може се повећавати динамички, у ходу, без заустављања система. Да бисте то урадили, потребно је да привремено зауставите и поново омогућите кеш меморију, али карактеристична предност ЛВМ-кеша у односу на, на пример, бцацхе је та што се то може урадити у ходу.

Хајде да направимо нови ВГ за кеширање.

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

Хајде да направимо ЛВ на кешираном уређају.

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

Овде смо одмах заузели сав слободан простор на /дев/дата/цацхе тако да су све остале потребне партиције одмах креиране на /дев/роот/цацхе. Ако сте креирали нешто на погрешном месту, можете га преместити помоћу пвмове.

Хајде да креирамо и омогућимо кеш:

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

Зашто таква величина..?Кроз практичне експерименте, аутор је успео да сазна да се најбољи резултат постиже ако се величина ЛВМ кеш блока поклапа са величином ЛВМ танког блока. Штавише, што је мања величина, то је боља конфигурација у насумичном снимању.

64к је минимална дозвољена величина блока за ЛВМ танки.

Будите опрезни при писању..!Да. Овај тип кеш меморије одлаже синхронизацију писања на кеширани уређај. То значи да ако се кеш меморија изгуби, можете изгубити податке на кешираном уређају. Касније ће вам аутор рећи које мере, поред НВМе РАИД 1, могу бити предузете да се надокнади овај ризик.

Овај тип кеш меморије је намерно изабран да би се компензовале лоше перформансе насумичног писања РАИД 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)

Само [цацхедата_цориг] треба да се налази на /дев/дата/цацхе. Ако нешто није у реду, користите пвмове.

Можете онемогућити кеш ако је потребно једном командом:

#lvconvert -y --uncache cache/cachedata

Ово се ради на мрежи. ЛВМ ће једноставно синхронизовати кеш са диском, уклонити га и преименовати цацхедата_цориг назад у цацхедата.

Подешавање ЛВМ танке

Хајде да грубо проценимо колико нам је простора потребно за ЛВМ танке метаподатке:

#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 гигабајта: 4294967296Б

Помножите са два и додајте 4194304Б за ЛВМ ПВ метаподатке: 8594128896Б
Хајде да направимо засебну партицију на НВМе РАИД 1 да бисмо на њу поставили ЛВМ танке метаподатке и њихову резервну копију:

#lvcreate -L 8594128896B --name images root

За шта..?Овде се може поставити питање: зашто постављати ЛВМ танке метаподатке одвојено ако ће они и даље бити кеширани на НВМе и брзо ће радити.

Иако је брзина овде важна, то је далеко од главног разлога. Ствар је у томе што је кеш тачка грешка. Нешто би му се могло догодити, а ако се ЛВМ танки метаподаци кеширају, то ће довести до тога да се све потпуно изгуби. Без комплетних метаподатака биће готово немогуће саставити танке томове.

Премештањем метаподатака у засебан не-кеширани, али брзи волумен, гарантујемо безбедност метаподатака у случају губитка или оштећења кеша. У овом случају, сва оштећења узрокована губитком кеша биће локализована унутар танких волумена, што ће поједноставити процедуру опоравка за редове величине. Са великом вероватноћом, ова оштећења ће бити надокнађена коришћењем ФС дневника.

Штавише, ако је претходно направљен снимак танког волумена, а након тога је кеш у потпуности синхронизован барем једном, онда ће, због унутрашњег дизајна ЛВМ танке, интегритет снимка бити загарантован у случају губитка кеша. .

Хајде да направимо нови ВГ који ће бити одговоран за танко обезбеђивање:

#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К поравнато по ивицама у кешу. Ово ће омогућити да се операција у потпуности изврши кроз кеш меморију, заобилазећи кеширани уређај.

Померимо ЛВ на одговарајуће ПВ:

#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 секунде. До 3 гигабајта у секунди. Дакле, свако покретање тестова писања може појести до 216 гигабајта ССД ресурса од вас.

Читање и писање мешано?Да. Има смисла водити тестове читања и писања одвојено. Штавише, има смисла осигурати да су сви кешови синхронизовани тако да претходно направљено уписивање не утиче на читање.

Резултати ће се значајно разликовати током првог покретања и наредних како се кеш и танки волумен попуњавају, а такође и у зависности од тога да ли је систем успео да синхронизује кеш меморије попуњене током последњег покретања.

Између осталог, препоручујем мерење брзине на већ пуној танкој запремини са које је управо направљен снимак. Аутор је имао прилику да посматра како се насумично уписивање нагло убрзава одмах након креирања првог снимка, посебно када кеш још није потпуно пун. Ово се дешава због семантике писања копирај на уписивање, поравнања кеша и танких блокова запремине и чињенице да се насумично уписивање у РАИД 6 претвара у насумично читање из РАИД 6 праћено уписом у кеш. У нашој конфигурацији, насумично читање са РАИД 6 је до 6 пута (број САТА ССД-ова у низу) брже од писања. Јер блокови за ЦоВ се додељују секвенцијално из танког скупа, тада се снимање, углавном, такође претвара у секвенцијално.

Обе ове функције се могу користити у своју корист.

Кеширајте „кохерентне“ снимке

Да би се смањио ризик од губитка података у случају оштећења/губитка кеша, аутор предлаже да се уведе пракса ротирања снимака како би се гарантовао њихов интегритет у овом случају.

Прво, пошто се метаподаци танког волумена налазе на некешираном уређају, метаподаци ће бити доследни и могући губици ће бити изоловани унутар блокова података.

Следећи циклус ротације снимака гарантује интегритет података унутар снимака у случају губитка кеша:

  1. За сваки танки волумен са именом <наме>, направите снимак са именом <наме>.цацхед
  2. Поставимо праг миграције на разумно високу вредност: #lvchange --quiet --cachesettings "migration_threshold=16384" cache/cachedata
  3. У петљи проверавамо број прљавих блокова у кешу: #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' док не добијемо нулу. Ако нула недостаје предуго, може се креирати привременим пребацивањем кеша у режим писања. Међутим, узимајући у обзир карактеристике брзине наших САТА и НВМе ССД низова, као и њихов ТБВ ресурс, или ћете моћи брзо да ухватите тренутак без промене кеш режима, или ће ваш хардвер у потпуности појести цео свој ресурс у неколико дана. Због ограничења ресурса, систем, у принципу, не може да буде испод 100% оптерећења писања све време. Наши НВМе ССД-ови под оптерећењем писања од 100% ће у потпуности исцрпити ресурсе КСНУМКС-КСНУМКС дана. САТА ССД дискови ће трајати само два пута дуже. Стога ћемо претпоставити да највећи део оптерећења иде на читање, а имамо релативно краткотрајне рафале изузетно високе активности у комбинацији са малим оптерећењем у просеку за писање.
  4. Чим ухватимо (или направимо) нулу, преименујемо <наме>.цацхед у <наме>.цоммиттед. Стари <наме>.цоммиттед је избрисан.
  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К) сектора.

Постављањем прага миграције на нулу, одлажемо синхронизацију писања на САТА ССД и агрегирамо неколико измена у један блок од 64К у кешу. Ово значајно штеди ресурс САТА ССД-а.

Где је шифра..?Нажалост, аутор себе сматра недовољно компетентним у развоју басх скрипти јер је 100% самоук и практикује „гуглао“ развој, па сматра да ужасан код који излази из његових руку нико не би требало да користи друго.

Мислим да ће професионалци у овој области моћи самостално да прикажу сву горе описану логику, ако је потребно, и, можда, чак и лепо дизајнирају као системски сервис, као што је аутор покушао да уради.

Оваква једноставна шема ротације снимака ће нам омогућити не само да стално имамо један снимак потпуно синхронизован на САТА ССД-у, већ ће нам такође омогућити да, користећи услужни програм тхин_делта, сазнамо који су блокови промењени након његовог креирања и тако локализујемо оштећење на главне количине, што увелико поједностављује опоравак.

ТРИМ/ДИСЦАРД у либвирт/КВМ

Јер складиште података ће се користити за КВМ који покреће либвирт, онда би било добро да научимо наше ВМ не само да заузимају слободан простор, већ и да ослободе оно што више није потребно.

Ово се ради емулацијом ТРИМ/ДИСЦАРД подршке на виртуелним дисковима. Да бисте то урадили, потребно је да промените тип контролера у виртио-сцси и уредите кмл.

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

Такве ДИСЦАРД-ове из гостујућих ОС-а исправно обрађује ЛВМ, а блокови се исправно ослобађају и у кешу и у танком базену. У нашем случају, то се дешава углавном са закашњењем, приликом брисања следећег снимка.

БТРФС Бацкуп

Користите готове скрипте са екстремно опрез и на сопствени ризик. Аутор је овај код написао сам и искључиво за себе. Сигуран сам да многи искусни корисници Линука имају сличне алате и нема потребе да копирате туђе.

Хајде да направимо волумен на уређају за резервну копију:

#lvcreate -L 256G --name backup backup

Хајде да га форматирамо у БТРФС:

#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

Копирајмо скрипту:

Много страшног басх кода. Користите на властиту одговорност. Не пишите љута писма аутору...#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

Шта то уопште ради..?Садржи скуп једноставних команди за креирање БТРФС снимака и њихово копирање на други ФС користећи БТРФС слање/примање.

Прво лансирање може бити релативно дуго, јер... На почетку ће сви подаци бити копирани. Даља лансирања ће бити веома брза, јер... Само промене ће бити копиране.

Још једна скрипта коју ћемо ставити у црон:

Још мало басх кода#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

Шта ради..?Креира и синхронизује инкременталне снимке наведених БТРФС волумена на резервном ФС-у. Након овога брише све слике направљене пре 60 дана. Након покретања, датирани снимци наведених томова ће се појавити у поддиректоријумима /бацкуп/бтрфс/бацк/ремоте/.

Хајде да дамо права на извршавање кода:

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

Хајде да га проверимо и ставимо у црон:

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

ЛВМ танка резервна копија

Хајде да направимо танак скуп на уређају за резервну копију:

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

Хајде да инсталирамо ддресцуе, јер... скрипте ће користити овај алат:

#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

Шта ради...?Садржи скуп команди за манипулисање танким снимцима и синхронизацију разлике између два танка снимка примљена преко тхин_делта на други блок уређај помоћу ддресцуе и блкдисцард.

Још једна скрипта коју ћемо ставити у црон:

Још мало#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

Хајде да га проверимо и ставимо у црон:

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

Прво лансирање ће бити дуго, јер... танки волумени ће бити потпуно синхронизовани копирањем целог искоришћеног простора. Захваљујући ЛВМ танким метаподацима, знамо који су блокови заправо у употреби, тако да ће се копирати само стварно коришћени блокови танког волумена.

Наредна покретања ће копирати податке постепено захваљујући праћењу промена преко ЛВМ танких метаподатака.

Да видимо шта се десило:

#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

Какве ово везе има са луткама?

Највероватније, с обзиром да ЛВМ ЛВ логички волумени могу бити ЛВМ ПВ физички волумени за друге ВГ. ЛВМ може бити рекурзиван, као лутке за гнежђење. Ово даје ЛВМ-у изузетну флексибилност.

ПС

У следећем чланку покушаћемо да користимо неколико сличних мобилних система за складиштење/КВМ као основу за креирање гео-дистрибуираног складишта/вм кластера са редундансом на неколико континената користећи кућне десктопе, кућни Интернет и П2П мреже.

Извор: ввв.хабр.цом

Додај коментар