FreeBSD 8.3 vient d’arriver, et en plus des traditionnels correctifs de sécurité, le support de ZFS v28 est annoncé. Une bonne occasion pour mettre à jour mon NAS.
Procédure d’upgrade
Rien de particulier ici, la procédure est classique :
# freebsd-update upgrade -r 8.3-RC2 # freebsd-update install # shutdown -r now # freebsd-update install # shutdown -r now
Pour les diverses propositions de modification des fichiers de configuration, un merge
a fonctionné sans problème.
J’en profite pour recompiler mon kernel, après avoir vérifié que les options contenues dans /etc/make.conf sont correctes :
CPUTYPE?=native MAKEOPTS="-j2"
Puis :
# cd /usr/src # make buildkernel # make installkernel # shutdown -r now
Upgrade ZFS
Une fois la machine démarrée avec le nouveau kernel, le pool ZFS peut être upgradé, comme indiqué dans le zpool status
:
# zpool status pool: data state: ONLINE status: The pool is formatted using an older on-disk format. The pool can still be used, but some features are unavailable. action: Upgrade the pool using 'zpool upgrade'. Once this is done, the pool will no longer be accessible on older software versions. scan: scrub repaired 0 in 1h34m with 0 errors on Mon Apr 23 18:28:43 2012 config: NAME STATE READ WRITE CKSUM data ONLINE 0 0 0 raidz1-0 ONLINE 0 0 0 ad4 ONLINE 0 0 0 ad6 ONLINE 0 0 0 ad8 ONLINE 0 0 0 ad10 ONLINE 0 0 0 errors: No known data errors
Le pool est ici en ZFS v15 :
# zpool get version data NAME PROPERTY VALUE SOURCE data version 15 local
Et le système supporte bien ZFS v28 :
# zpool upgrade -v This system is currently running ZFS pool version 28.
L’upgrade se fait en moins de 2 secondes et est transparante, mais elle empêche de pouvoir utiliser ce pool avec une version du système plus ancienne :
# zpool upgrade data This system is currently running ZFS pool version 28. Successfully upgraded 'data' from version 15 to version 28
Déduplication
L’intérêt de cette montée de version et de pouvoir utiliser, ou au moins tester, la déduplication intégrée à ZFS (ainsi que le très utile zfs diff
[6]).
La déduplication évite les doublons directement au niveau des blocs [1], permettant ainsi une économie d’espace disque. Mais cela implique le référencement des blocs dédupliqués, nécessitant plus ou moins de ressources mémoire supplémentaires [2].
Une estimation de la RAM requise peut être faite à partir des données déjà présentes dans le pool [3] avec zdb -S <pool_name>
:
# zdb -S data Simulated DDT histogram: bucket allocated referenced ______ ______________________________ ______________________________ refcnt blocks LSIZE PSIZE DSIZE blocks LSIZE PSIZE DSIZE ------ ------ ----- ----- ----- ------ ----- ----- ----- 1 9.34M 1.14T 1.14T 1.13T 9.34M 1.14T 1.14T 1.13T 2 198K 22.3G 22.3G 22.3G 409K 45.7G 45.7G 45.6G 4 9.05K 815M 815M 815M 45.8K 4.08G 4.08G 4.08G 8 1.28K 80.9M 80.9M 81.0M 12.9K 817M 817M 818M 16 323 7.62M 7.62M 7.69M 6.81K 155M 155M 156M 32 61 1.40M 1.40M 1.41M 2.57K 65.8M 65.8M 66.4M 64 45 581K 581K 595K 3.35K 46.5M 46.5M 47.5M 128 3 138K 138K 138K 620 28.0M 28.0M 28.0M 256 4 51K 51K 51.6K 1.43K 18.1M 18.1M 18.3M 1K 1 128K 128K 128K 1.37K 176M 176M 176M 64K 1 128K 128K 128K 79.5K 9.94G 9.94G 9.93G Total 9.55M 1.16T 1.16T 1.16T 9.89M 1.19T 1.19T 1.19T dedup = 1.03, compress = 1.00, copies = 1.00, dedup * compress / copies = 1.03
Dans mon cas, la déduplication concernerait 9,55M de blocs au total, et chaque bloc dédupliqué demande environ 320 octets de mémoire. On a donc : 9,55M*320 = 3056Mo requis par la déduplication. Cette mémoire est allouée avec les metadatas de l’ARC [4], et cette zone ne peut dépasser un quart de l’allocation mémoire de l’ARC.
Dans mon cas, les limites sont les suivantes :
$ sysctl vfs.zfs.arc_max vfs.zfs.arc_max: 3029393408 $ sysctl vfs.zfs.arc_meta_limit vfs.zfs.arc_meta_limit: 757348352
L’ARC est ici limité à un peu moins de 3 Go, et la partie réservée aux metadatas ne peut dépasser 722 Mo.
D’après les informations données par la table de déduplication simulée, la déduplication de toutes mes données consommerait quatre fois plus de RAM que l’espace reservé. il m’est donc impossible de mettre en place la déduplication sur une telle quantité de données, sans dégrader fortement les performances.
Il est en effet nécessaire que la table de dédiplication puisse être contenue en mémoire pour éviter de ralentir considérablement les accès disque.
Pour mesurer l’utilisation de la mémoire par ZFS, les scripts arc_summary.pl
et arcstat.pl
sont disponibles sur cette page.
Tests
Pour comparer un peu les performances de la déduplication et des différentes méthodes de compression intégrées dans ZFS, j’ai copié des données représentant plus ou moins mon utilisation disque (images ISO de divers OS, machines virtuelles, ou encore vidéos des aventures du service de Ron Swanson).
- Copie de référence sans compression particulière ni déduplication : 24min31s
data/tdedup 98.8G 1.38T 98.8G /data/tdedup
- Avec la déduplication : 50min00s
# zfs set deduplication=on data/tdedup
L’espace disque économisé et la mémoire consommée peuvent être obtenus avec la commande zpool -D
ou zpool -DD
:
dedup: DDT entries 771751, size 326 on disk, 163 in core bucket allocated referenced ______ ______________________________ ______________________________ refcnt blocks LSIZE PSIZE DSIZE blocks LSIZE PSIZE DSIZE ------ ------ ----- ----- ----- ------ ----- ----- ----- 1 735K 91.8G 91.8G 91.7G 735K 91.8G 91.8G 91.7G 2 18.4K 2.30G 2.30G 2.30G 38.3K 4.79G 4.79G 4.79G 4 741 92.6M 92.6M 92.6M 3.06K 392M 392M 391M 8 26 3.25M 3.25M 3.25M 270 33.8M 33.8M 33.7M 16 5 640K 640K 640K 101 12.6M 12.6M 12.6M 32 4 512K 512K 512K 176 22M 22M 22.0M 64 4 512K 512K 512K 382 47.8M 47.8M 47.7M 8K 1 128K 128K 128K 14K 1.75G 1.75G 1.75G Total 754K 94.2G 94.2G 94.1G 791K 98.8G 98.8G 98.8G
Ici, on peut voir que 98,8 Go sont référencés, pour 94,2 Go réellement alloués (ratio : 1.05).
La consommation mémoire est de 754K*320 = 230 Mo.
- Avec la compression ZLE : 22min46s
# zfs set compression=zle data/tdedup # zfs get compressratio data/tdedup NAME PROPERTY VALUE SOURCE data/tdedup compressratio 1.09x -
- Avec la compression LZJB : 25min57s
# zfs set compression=lzjb data/tdedup # zfs get compressratio data/tdedup NAME PROPERTY VALUE SOURCE data/tdedup compressratio 1.42x -
- Avec la compression gzip : 55min14s
# zfs set compression=gzip data/tdedup # zfs get compressratio data/tdedup NAME PROPERTY VALUE SOURCE data/tdedup compressratio 1.65x -
Au final, la déduplication n’est pas du tout avantageuse avec les données testées. L’espace économisé est plus faible qu’avec n’importe quelle compression, alors que le temps pris pour la copie a doublé. S’ajoute à cela la mémoire consommée, qui ne peut plus être utilisée pour le cache ZFS.
Concernant les différentes compressions disponibles, LZJB permet d’obtenir d’assez bons résultats, c’est d’ailleurs la compression ZFS par défaut.
Annexes
Plus ou moins lié au sujet abordé :
- Sous FreeBSD, un cp -r /source/path/.* /dest/path copie également le contenu du répertoire parent “..”. Pour éviter cela, utiliser cp -r /source/path/.[^.]* [5].
- Pour mesurer le débit global du pool ZFS :
zpool iostat 1
—
[1] : https://blogs.oracle.com/bonwick/entry/zfs_dedup
[2] : http://www.oracle.com/technetwork/articles/servers-storage-admin/o11-113-size-zfs-dedup-1354231.html
[3] : http://docs.oracle.com/cd/E23824_01/html/E24456/filesystem-6.html#fsdedup-1
[4] : http://hub.opensolaris.org/bin/view/Community+Group+zfs/dedup#HWhataretheperformanceimpactsofenablingdedup3F
[5] : http://forums.freebsd.org/showthread.php?t=18385
[6] : http://docs.oracle.com/cd/E19963-01/html/821-1448/gbscy.html#gkhwe