Hyper-V virtuális diszkek egyszerű deduplikált mentése

Nagyobb lélegzetű VM módosításkor (OS / alkalmazás update, bonyolultabb install) az ember természetesen készít egy VM snapshotot, amiből kényelmes és gyors visszaállni szükség esetén. Néha viszont igény lehet arra is, hogy ezeket a snapshotokat elmentsük / elarchiváljuk hosszabb ideig, tovább, mint ameddig a Hyper-V snapshotok általában megmaradnak.

Természetesen a VM export mindig egy lehetőség, de ez (nekem) kicsit körülményes nagyobb diszkterülettel rendelkező VM-eknél: kell extra hely az exportnak, majd azt be kell tömöríteni, körülményes megoldani a deduplikációt, szóval kerestem egy másik megoldást. Biztosan van ennél sokkal elegánsabb módszer, ez most egy fapados, ámde gyors és hatékony megoldás.

1. Kitrimmeljük a virtuális diszket, hogy ami üres a filerendszerben, az a VHD-ban is lehessen üres. Őszintén, nem tudom, hogy ez a gyakorlatban mit jelent, egyszerűen hozzászoktam az LVM pool köteteknél, hogy ezt néha illik megcsinálni. De tény, hogy kisebbek a tömörített diszkimage-k így.

Ha a guest OS linux, akkor például

[ rc0 ]-[root@vm42a]-[~] # fstrim -av
/var/www: 41.6 GiB (44658724864 bytes) trimmed on /dev/sdc1
/var/lib/mysql: 8.2 GiB (8808497152 bytes) trimmed on /dev/sdb1
/: 18.9 GiB (20269465600 bytes) trimmed on /dev/sda2

2. Megállítjuk a VM-et. Ez nyilván nem kötelező - én szeretem, ha teljesen konzisztens a mentés, de enélkül is működik.

3. Készítünk HyperV-ben egy snapshotot. Ez befagyasztja a virtuális diszk image-n a módosításokat, és egy új fileban gyűjti a módosításokat, amíg meg nem szüntetjük a snapshotot. Ezt az állapotot fogjuk kihasználni a mentéshez.

4. Visszaindíthatjuk a VM-et, ha előbb megállítottuk. A VHD-nk már változatlan marad.

Van a Hyper-V szerverünkön WSL, ami egy nagyon minimalista linuxot futtat. Erre feltelepítjük a borgbackupot, ami egy kiváló backup alkalmazás (egyetlen probléma vele, hogy nem tud elegánsan pull backupot, de most ez nem létkérdés).

Most a példában egy távoli backup szervert használunk, amivel kapcsolatban teljesen minimális igényeink vannak:

  • szintén legyen rajta borgbackup, hogy serve módban tudjon futni

  • SSH-n férjen hozzá a Hyper-V szerver (WSL-ből), tehát tegyük be a WSL user publikus SSH kulcsát

  • legyen rajta egy borg-os backup repo

5. Ráküldjük a "befagyasztott" VHD-kra a borg-ot:

borg create --progress -C zstd backupsrv:/mnt/backup/vm42a/vm::{now:%Y%m%d}-vm42a-vm /mnt/d/Hyper-V/VHD/vm42a_root.vhdx /mnt/d/Hyper-V/VHD/vm42a_www.vhdx /mnt/d/Hyper-V/VHD/vm42a_mysql.vhdx

Lényegében csak megadjuk a cél repo-t és a VHD-k elérését, nincs benne semmi extra.

6. Eldobjuk a Hyper-V snapshotot (ez simán mehet online), ilyenkor az ideiglenes diszk image-ben összegyűlt változásokat bemergeli a fő VHD-be, és innen megint az frissül.

Az igazi jóság ebben az, hogy amikor másodszor küldjük rá ugyanezt egy következő karbantartásnál (ugyanígy befagyasztva a VHD-kat), akkor a backup repo-ba már csak az előző mentéshez képest változott diszktartalom mentődik, egyetlen gyors lépéssel. A repo-ból vissza tudjuk szedni bármelyik image állapotot, mégis csak kevés helyet foglal, nem kell külön exportálni, a tömörítés / deduplikálás / és akár titkosítás egyetlen lépésben történik.

Nem részleteztem ki a borg működését konkrétan, de szívesen segítek ha van kérdés.

Tudom, nem egy nagy wasistdas, de hátha segítség valakinek.

Hozzászólások

Szerkesztve: 2022. 06. 30., cs – 09:17

Engem érdekelne, hogy hogy működnek ezek a megoldások. (Nem a szakterületem, úgyhogy nézzétek el ha láma a kérdés.) Főleg a deduplikáció: simán végigolvassa az egész diszket, egy nagy fájlként kezeli, és ilyen gördülő hash implementáció van benne, mint például az rsync-ben? Vagy van ezen a területen valami koncepcionális újdonság?

Például olyan van már, hogy egy VM alatt például a fájlrendszer journal alapján (vagy valami ahhoz hasonló mechanizmus alapján) csinálnak inkrementális backupot? Például tegyük fel, hogy van egy VM-em amin rengeteg adat van, de nagy része read-only, a napi változások kicsik. Ebben az esetben is végig kell olvasni és processzálni kell minden adatot, vagy képes a VM csak a változásokból mentést csinálni a teljes adathalmat végigolvasása nélkül is?

Ez a borg-os megoldás egyszerű mint a szög: darabokra bontja a forrást, hash-t számol belőle, és ahol talál egyezést, ott csak hivatkozást tárol. A doksiból egy rövid részlet, pongyola gyorsfordításban:

Helytakarékos tárolás

A deduplikáció úgy csökkenti az eltárolt bájtok számát, hogy minden file-t változó hosszúságú darabokra (chunk) bont, és csak azokat adja hozzá a repo-hoz, amelyek még nem szerepeltek korábban. Egy darab akkor számít duplikáltnak, ha a hash értéke azonos. A deduplikációnál az egy repo-ban tárolt összes filerészletet figyelembe veszi: nem számít hogy másik szerverről jött, előző mentésből, ugyanabból a mentésből, vagy éppen ugyanabból a forrásfile-ból. Más deduplikációs megközelítésekkel összehasonlítva, a borg-nál nem függ a deduplikáció:

- azonos file/könyvtárnévtől: szabadon mozgathatod a filejaidat a könyvtárstruktúrában, akár másik szerverre is viheted, ha egy közös backup repo-t használnak.

- teljes file egyezéstől vagy időbélyegtől: ha egy nagy file kis része megváltozik, csak ez fog bekerülni a repo-ba - jó megoldás VM-ekhez vagy raw diszkterületekhez.

- abszolút pozíciótól fileon belül: megváltozhat a file felépítése, az azonos tartalmat továbbra is megtalálja a deduplikációs algoritmus.

 

Tehát a kérdéseidre a válasz borg esetében: végig kell olvasni a file-t mindenképp, és nem tud filerendszer journal-ból változást keresni. A btrfs send/receive megoldása valami hasonló, de azt nem ismerem jól.

Egy példa: Fogtam egy működő VM root diszkjét, ráküldve a borg-ot, már az első mentésben talált deduplikálható tartalmat (tehát VM diszken belüli ismétlődő részeket):

Duration: 11 minutes 59.51 seconds
------------------------------------------------------------------------------
                       Original size      Compressed size    Deduplicated size
This archive:               95.97 GB             77.03 GB             71.48 GB
All archives:               95.97 GB             77.04 GB             71.48 GB

                       Unique chunks         Total chunks
Chunk index:                   32712                35585

Ehhez a 35585 chunk-hoz a .cache könyvtár mindössze 2.8M lett, de ha ezt kitörlöm, viszonylag gyorsan újraépíti a repo-ból. 

Ezután matattam kicsit a VM-en, ráindítottam egy OS frissítést, és újra ráküldtem a mentést:

Duration: 6 minutes 10.05 seconds
------------------------------------------------------------------------------
                       Original size      Compressed size    Deduplicated size
This archive:               95.97 GB             77.11 GB              7.82 GB
All archives:              191.94 GB            154.15 GB             79.30 GB

                       Unique chunks         Total chunks
Chunk index:                   37774                71284

 

Ami nagyon tetszik a borg megoldásában, hogy bár azt is tudja, nem egyszerű full backup + inkrementális mentés, hiszen pl. a fenti mentések után simán kitörölhetem az első (~full) mentést, attól a másodikat teljes értékűen vissza tudom állítani, mert csak azok a részletek törlődnek a repo-ból, amik csak az első mentés részei, a közösek + a második mentés chunkjei benne maradnak a repo-ban.

Szerkesztve: 2022. 06. 30., cs – 17:23

Érdekes és elegáns megoldás. Köszi.

Hogy szoktad felosztani a diszket a különböző partíciók között? Érdemes lehet írni egy pici script-et, mely naponta lementi az aktuális disk foglaltságát egy fájlba és a számsorból szomszédos különbségeiből számol egy átlag + 3 szórást és ha ez plusz a jelenlegi max érték nagyobb mint a jelenlegi disk méret, akkor küld egy jelzést az admin-nak, hogy van esély a lemez kifogyásra. Daily cron-ba betehető és egyszerű.

átlag( diff ( data )) + 3 * szórás( diff( data )) + max( data ) > partíció méret -> riasztás