Stratis e Virtual Data Optimizer (VDO): la compressione online e deduplica integrata in LVM su Red Hat Enterprise Linux 9 che non sapevate di avere

Come avevamo menzionato alcune settimane fa, la nuova release di RHEL porta con sè diverse novità in vari ambiti, tra cui la sicurezza, ma anche lato storage vi sono delle differenze che potrebbero essere sfuggite a chiunque non sia andato a leggere le release notes.

Cominciamo col dire che purtroppo, RHEL 9 non supporterà il filesystem di nuova generazione btrfs nonostante esso sia oggetto di nuove e frequenti migliorie e da anni implementato di default su SUSE Linux Enterprise e persino su Fedora stessa, che rappresenta il futuro di ciò che saranno le prossime release Red Hat, nonostante esse vengano adesso forkate da Centos Stream.

Non sappiamo se avverrà un dietro front nelle prossime versioni ma, alla base della scelta, sembra esserci la volontà di offrire Stratis, il nuovo demone di configurazione filesystem e volumi scritto in Rust che combina tecnologie Linux già mature e presenti da più di un decennio come device mapper, XFS e lvm e che, attualmente, è presente nella release come technology preview.

Esso è un’interessante implementazione, per quanto ancora neonata, di feature e concetti normalmente afferenti soltanto a filesystem avanzati come ZFS e btrfs, i quali mettono in tavola tecnologie come compressione trasparente, deduplica dei dati, copy-on-write, snapshotting e creazione di raid software.

Stratis è ancora un progetto work in progress e non offre ancora tutte le feature appena listate. Alcune delle feature non ancora offerte da Stratis sono compressione trasparente e data deduplication ma, se queste dovessero servirvi adesso e non potete o volete utilizzare i fileystem appena menzionati, si può far affidamento a Virtual Data Optimizer (VDO), già presente nelle precedenti release di Red Hat, ora parte integrante del gestore dei volumi linux (LVM).

Purtroppo le due tecnologie non sono, al momento, combinabili tra di loro ed è ancora assente la possibilità di poter avere un checksumming di ogni blocco dati per assicurare l’assoluta integrità dei dati nel tempo e prevenire problemi di bit-rot, feature presente in btrfs e ZFS, ma si tratta sicuramente di un passo nella direzione giusta che risponde alla moderna esigenza di avere qualcosa di più di un semplice filesystem.

Tra gli obiettivi di Stratis c’è, comunque, l’idea di avere una gestione da riga di comando facile e intuitiva. Scettici? Vediamoli brevemente all’opera in uno scenario di esempio.

La situazione da cui partiamo è quella di un’istanza virtualizzata di Red Hat Enterprise Linux 9 appena installata, con 3 dischi virtuali aggiuntivi vuoti:

[root@server redhat]# lsblk
NAME          MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
vda           252:0    0   70G  0 disk 
├─vda1        252:1    0    1G  0 part /boot
└─vda2        252:2    0   69G  0 part 
  ├─rhel-root 253:0    0 44.3G  0 lvm  /
  ├─rhel-swap 253:1    0  3.1G  0 lvm  [SWAP]
  └─rhel-home 253:2    0 21.6G  0 lvm  /home
vdb           252:16   0  250G  0 disk 
vdc           252:32   0  250G  0 disk 
vdd           252:48   0  250G  0 disk 

Se volessimo iniziare a testare compressione e deduplica, quindi creando un lvm con VDO, andremo, molto banalmente, a creare il physical volume su uno dei dischi per permetterci, subito dopo, di poter aggiungere un volume group e, infine, un logical volume che creeremo con VDO dal momento che, ricordiamo, adesso è parte integrante di LVM e basterà quindi usare una variante del solito comando lvcreate, che vi sarà sicuramente già familiare.

Scriveremo poi un filesystem e lo monteremo in una cartella qualunque per poterlo efffettivamente utilizzare.

Nella pratica:

[root@server redhat]# pvcreate /dev/vdb
  Physical volume "/dev/vdb" successfully created.

[root@server redhat]# vgcreate vg-mmul /dev/vdb
  Volume group "vg-mmul" successfully created

[root@server redhat]# lvcreate --type vdo --name vdo-mmul --size=249G --virtualsize=2490G vg-mmul
    The VDO volume can address 246 GB in 123 data slabs, each 2 GB.
    It can grow to address at most 16 TB of physical storage in 8192 slabs.
    If a larger maximum size might be needed, use bigger slabs.
  Logical volume "vdo-mmul" created.

[root@server redhat]# mkfs.xfs /dev/vg-mmul/vdo-mmul -K
meta-data=/dev/vg-mmul/vdo-mmul  isize=512    agcount=4, agsize=16090880 blks
         =                       sectsz=4096  attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=64363520, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=31427, version=2
         =                       sectsz=4096  sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

[root@server redhat]# mount /dev/vg-mmul/vdo-mmul /MMUL_VDO

[root@server redhat]# df -hT /MMUL_VDO
Filesystem                     Type      Size  Used Avail Use% Mounted on
/dev/mapper/vg--mmul-vdo--mmul xfs       246G  1.8G  244G   1% /MMUL_VDO

Come avrete notato, con –virtualsize ci è stato possibile presentare un volume più grande di quanto non sia realmente, cosa che abbiamo fatto poiché le dimensioni dei file che il sistema operativo vede continueranno a essere quelle naturali, anche se nella realtà essi non occuperanno così tanto dal momento che verranno compressi e deduplicati. Non è possibile prevedere in anticipo gli aspetti quantitativi della cosa in quanto non è generalmente possibile conoscere in anticipo quali dati verranno scritti, per cui, in questo caso, abbiamo seguito il suggerimento di Red Hat di presentare un volume 10 volte più grande di quanto non sia realmente, che sarà quindi di 2,5TB:

[root@server redhat]# df -hT /MMUL_VDO
Filesystem                     Type      Size  Used Avail Use% Mounted on
/dev/mapper/vg--mmul-vdo--mmul xfs       2.5T   18G  2.5T   1% /MMUL_VDO

Creeremo adesso un file di esempio, con dati random, di 400MB:

[root@server redhat]# dd if=/dev/urandom of=/MMUL_VDO/mmul-test-file bs=4M status=progress count=100
419430400 bytes (419 MB, 400 MiB) copied, 55 s, 7.6 MB/s 
100+0 records in
100+0 records out
419430400 bytes (419 MB, 400 MiB) copied, 55.3566 s, 7.6 MB/s

E lo copieremo per un numero arbitrario di volte per far si che la deduplica entri in gioco ed eviti di scrivere nuovamente gli stessi dati ripetuti. Possiamo scegliere un numero arbitrario per testare il concetto e, volendo fare le cose in grande (ma non troppo), proveremo a generare 20.000 copie:

[root@server MMUL_VDO]# time for i in {1..20000}; do cp /MMUL_VDO/mmul-test-file /MMUL_VDO/mmul-test-file-$i; done

real	0m33.949s
user	0m8.389s
sys	0m25.799s

[root@server MMUL_VDO]# du --max-depth=1 -h /mnt
7.7T	/mnt

[root@server MMUL_VDO]# df -hT /MMUL_VDO
Filesystem                     Type      Size  Used Avail Use% Mounted on
/dev/mapper/vg--mmul-vdo--mmul xfs       2.5T   18G  2.5T   1% /MMUL_VDO

[root@server mnt]# vdostats --human-readable
Device                     Size      Used Available Use% Space saving%
vg--mmul-vpool0-vpool    249.0G      3.6G    245.4G   1%           74%

Alcune cose avranno sicuramente colto la vostra attenzione: abbiamo scritto 7,7 terabyte di dati in 33 secondi (la nostra macchina è un comune desktop con dischi rotanti), il df continua a mostrare 18GB usati come all’inizio e, si, abbiamo 20.000 copie dello stesso file al ‘prezzo’ di una, in quanto tutte uguali. Il risparmio di spazio sarebbe stato simile anche se i file avessero avuto delle differenze, purché minime, merito della deduplicazione dei dati a livello di blocco.

Dubbi? Non possiamo mostrarvi qui l’intero output di ls, ma possiamo darvi un assaggio mostrandovi le ultime 10 righe:

[root@server MMUL_VDO]# ls -lh1v /MMUL_VDO | tail
-rw-r--r--. 1 root root 400M Sep  2 16:50 mmul-test-file-19991
-rw-r--r--. 1 root root 400M Sep  2 16:50 mmul-test-file-19992
-rw-r--r--. 1 root root 400M Sep  2 16:50 mmul-test-file-19993
-rw-r--r--. 1 root root 400M Sep  2 16:50 mmul-test-file-19994
-rw-r--r--. 1 root root 400M Sep  2 16:50 mmul-test-file-19995
-rw-r--r--. 1 root root 400M Sep  2 16:50 mmul-test-file-19996
-rw-r--r--. 1 root root 400M Sep  2 16:50 mmul-test-file-19997
-rw-r--r--. 1 root root 400M Sep  2 16:50 mmul-test-file-19998
-rw-r--r--. 1 root root 400M Sep  2 16:50 mmul-test-file-19999
-rw-r--r--. 1 root root 400M Sep  2 16:50 mmul-test-file-20000

Si, i file sono tutti lì, tutti e 20 mila da 400MB l’uno, che fanno 7,7TB in totale. Interessante, no? Gli use case per questa feature sono facilmente individuabili in ogni situazione in cui abbiamo file che tendono a ripetersi e a differire di poco tra loro, oppure file che incorporano lunghe sequenze che si ripetono.

Spostandoci, invece, su Stratis, si può iniziare molto facilmente in pochi secondi e, ricordiamo, non è al momento possibile combinarlo con il VDO, per cui useremo gli altri dischi della macchina virtuale che avevamo lasciato ancora inutilizzati.

Ciò che faremo è installare i due pacchetti, abilitare il servizio e creare un semplice pool, che faremo diventare un jbod di due dischi nel comando successivo per simulare un aggiunta avvenuta a posteriori. Come si può poi notare, troveremo già il tutto formattato in xfs:

[root@server mnt]# dnf install -y stratis-cli stratisd 
Updating Subscription Management repositories.
Last metadata expiration check: 3:04:50 ago on Fri 02 Sep 2022 02:26:48 PM CEST.
Package stratis-cli-2.4.3-2.el9.noarch is already installed.
Package stratisd-2.4.2-3.el9.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!

[root@server mnt]# systemctl enable --now stratisd

[root@server mnt]# lsblk
NAME                      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
(...)
vdc                       252:32   0  250G  0 disk 
vdd                       252:48   0  250G  0 disk 

[root@server mnt]# stratis pool create MMUL_POOL /dev/vdc

[root@server mnt]# stratis pool list
Name                           Total Physical   Properties                                   UUID
MMUL_POOL   250 GiB / 52.11 MiB / 249.95 GiB      ~Ca,~Cr   535999d9-0f9d-485f-aba8-e0a69ab78e4d

[root@server mnt]# stratis pool add-data MMUL_POOL /dev/vdd

[root@server mnt]# stratis blockdev list MMUL_POOL
Pool Name    Device Node   Physical Size   Tier
MMUL_POOL   /dev/vdc            250 GiB   Data
MMUL_POOL   /dev/vdd            250 GiB   Data


[root@server redhat]# mount /dev/stratis/MMUL_POOL/filesystem1 /MMUL_POOL

[root@server redhat]# df -hT /MMUL_POOL
Filesystem                                                                                      Type  Size  Used Avail Use% Mounted on
/dev/mapper/stratis-1-535999d90f9d485faba8e0a69ab78e4d-thin-fs-1b6de4f44e524a79a531ff3f7f4a8f56 xfs   1.0T  7.9G 1016G   1% /MMUL_POOL

Ed ecco che, come annunciato, nello spazio di un minuto abbiamo creato un setup Stratis con più dischi, senza dover chiamare in causa altre utility come lvm o mdadm e senza dover attendere una lunga inizializzazione. Il nostro setup, infatti, è istantaneamente disponibile e può diventare anche parecchio complesso prevedendo, ad esempio, interi dischi come cache per casi d’uso avanzati.

Se tutto ciò vi ha incuriosito, vista la complessità dell’argomento, vi rimandiamo all’esaustiva documentazione ufficiale, preannunciandovi soltanto che esso vi offrirà diverse feature che ricorderanno in tutto e per tutto ZFS con il quale non è ancora in parità di feature ma, se il progetto continua come ci aspettiamo, il gap dovrebbe colmarsi quanto prima e, perché no, potremmo vedere presto delle funzionalità che non avevamo ancora visto su nessun filesystem, grazie alla facile espandibilità con cui è stato pensato.

Non è, comunque, un gioco a somma zero, poiché tra le tante cose che il mondo open-source ci regala, ve n’è una che non finiremo mai di apprezzare: la possibilità di scegliere.

Tags: , ,