Contenu

Mise en place de ZFS sur un NAS perso

Contexte

Mon NAS actuel commence à se faire vieux, plus de 10 ans maintenant, c’est un QNAP TS-412 possédant 4 disques WD Red 2To.

J’ai donc décidé de le remplacer par un nouveau serveur de type desktop avec du raid logiciel, sous Linux.

Pourquoi ne pas tout mettre sur du cloud public ? C’est une idée que j’avais envisagé mais avec un débit de 4mbit/s en descendant et de 0,8mbit/s en montant j’en ai pour un moment à uploader quelques To de données :-). Je réfléchirai de nouveau à cette migration dans plusieurs années quand la fibre optique sera installée chez moi.

J’ai donc acquis une petite configuration bureautique : Ryzen 3, 8Go de RAM, SSD NVMe de 60 Go pour le système et 3 disques WD Red de 3 To. Je n’ai que 4 ports SATA sur la carte mère, ça me laisse 1 port de spare au cas où (il est possible de dédier un SSD à du cache sur ZFS afin d’accélérer les perfs, je mettrai cela en place si j’ai des problèmes de perfs avec la rapidité d’ouverture de mes photos).

à la base, je pensais partir sur un mix LVM + mdadm et puis j’ai découvert ZFS, technologie qui me semblait intéressante. Je me suis dit que c’était l’occasion de tester.

ZFS a l’avantage de pouvoir faire des snapshots assez rapidement (grâce au copy-on-write ), c’est une des fonctionnalités que je souhaite tester et ça permettrait de me prémunir à minima d’un potentiel ransmware.

J’ai aussi lu que le partage de datasets ZFS via Samba et NFS était natif, si j’arrive à mettre ça en place, ça m’évitera de configurer 2 logiciels en plus.

En ce moment, on entend pas mal parler de problèmes entre ZFS et les disques WD Red qui utilisent la technologie SMR. Les disques que je viens d’acheter ne disposent pas de cette technologie, je suis donc pas concerné.

Installation des drivers

ZFS est sous license CDDL. Cette license étant incompatible avec celle du kernel, les modules noyau ne sont pas directement intégrés, il faut donc les installer à part.

La distribution GNU/Linux installée chez moi est la dernière Debian stable et comme les paquets de Debian stable ont tendance à ne pas être up-to-date, j’ai décidé d’installer les paquets qui viennent des backports :

1
2
3
4
5
6
echo deb http://ftp.fr.debian.org/debian buster-backports main contrib non-free | sudo tee -a /etc/apt/sources.list
sudo apt-get update
sudo apt-get install dpkg-dev build-essential
sudo apt-get install -t buster-backports linux-image-amd64 linux-headers-amd64
sudo systemctl reboot
sudo apt-get install -t buster-backports zfs-dkms zfsutils-linux

Si tout s’est bien passé, les modules zfs sont chargés :

1
2
3
4
5
6
7
8
9
 ✘ yohan@mycroft  ~  lsmod|grep zfs
zfs                  4268032  0
zunicode              335872  1 zfs
zlua                  176128  1 zfs
zavl                   16384  1 zfs
icp                   335872  1 zfs
zcommon               106496  2 zfs,icp
znvpair               102400  2 zfs,zcommon
spl                   126976  5 zfs,icp,znvpair,zcommon,zavl

Le système de layering sur ZFS

Vous trouverez une définition plus complète directement sur la doc d’Oracle, mais pour résumer on peut dire que sur ZFS, un pool est composé de vdevs et met à disposition des datasets.

un vdev peut être un disque physique (SSD ou mécanique), un mirror (un équivalent du RAID-1), un RAID-Z (équivalent d’un RAID-5 ou plus suivant la configuration) ou encore des fichiers (ça peut servir dans le cadre de prototypage). Un vdev peut aussi être de type Spare, Log ou Cache.

Un dataset est un terme générique qui définit un élément d’un pool. Il peut être de type filesystem, volume, snapshot ou clone.

Dans mon cas, je vais créer un seul vdev, de type RAIDZ-1, composé des 3 disques dur de 3 To, sur lequel je baserai mon pool data qui sera composé de plusieurs datasets, 1 filesystem par type de données (Vidéos, Photos, Documents, Jeux Vidéos …).

Création du pool

Rien de plus simple pour créer à la fois les vdevs et le pool, le tout est fait par une seule commande :

1
sudo zpool create data raidz1 /dev/sda /dev/sdb /dev/sdc
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
 yohan@mycroft  ~  sudo zpool status
  pool: data
 state: ONLINE
  scan: none requested
config:

        NAME        STATE     READ WRITE CKSUM
        data        ONLINE       0     0     0
          raidz1-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
            sdc     ONLINE       0     0     0

errors: No known data errors

Le tour est joué ! Il ne reste plus qu’à créer les datasets. On remarquera que le pool est monté directement :

1
2
3
 yohan@mycroft  ~  sudo zfs list
NAME   USED  AVAIL     REFER  MOUNTPOINT
data   543K  5,27T      128K  /data

Je créé mon dataset de type filesystem Documents en activant la compression de type lz4 :

1
sudo zfs create -o compress=lz4 data/Documents

Mad’eo, le tour est joué. 2 commandes pour faire ça, c’est assez rapide 🙂

Les snapshots

Un snapshot ZFS est la copie d’un dataset à l’instant T. Comme ZFS est basé sur du copy-on-write, les snapshots ne prennent pas beaucoup de place si il y a peu de modification dans le contenu du dataset. C’est notamment le cas de mon dataset Documents : il ne fait généralement que grossir. Et comme le contenu est important, il est tout aussi important de prendre soin des données qu’il y a dessus ! Bien évidemment, il ne faut pas non plus oublier l’adage RAID is not backup.

Depuis le paragraphe précédent, j’ai copié l’intégralité des Documents de mon ancien NAS. Je me retrouve avec quelques Go d’utilisés :

1
2
3
4
 ✘ yohan@mycroft  /data/Documents  sudo zfs list
NAME             USED  AVAIL     REFER  MOUNTPOINT
data            33,4G  5,24T      128K  /data
data/Documents  33,4G  5,24T     33,4G  /data/Documents

Note : j’ai gagné 3.6 Go grâce à la compression, le dossier d’origine faisait 37 Go, c’est toujours ça de pris.

On créé un snapshot sur le dataset Documents :

1
2
3
4
5
6
 ✘ yohan@mycroft  /data/Documents  sudo zfs snapshot data/Documents@20200619
 yohan@mycroft  /data/Documents  sudo zfs list -t all
NAME                      USED  AVAIL     REFER  MOUNTPOINT
data                     33,4G  5,24T      128K  /data
data/Documents           33,4G  5,24T     33,4G  /data/Documents
data/Documents@20200619     0B      -     33,4G  -

On remarque que le snapshot ne prend aucune place supplémentaire.

Maintenant simulons l’effet d’une malheureuse suppression sur une partie du dataset :

1
2
3
4
5
6
 yohan@mycroft  /data/Documents  rm -rf M*
 yohan@mycroft  /data/Documents  sudo zfs list -t all
NAME                      USED  AVAIL     REFER  MOUNTPOINT
data                     33,4G  5,24T      128K  /data
data/Documents           33,4G  5,24T      321M  /data/Documents
data/Documents@20200619  33,0G      -     33,4G  -

Comme le snapshot est toujours là, l’espace utilisé n’est pas libéré, si on voulait récuperer l’espace disque disponible, il faudrait aussi supprimer le snapshot.

Pour revert le snapshot, c’est simple :

1
2
3
4
5
6
 yohan@mycroft  /data/Documents  sudo zfs rollback data/Documents@20200619
 ✘ yohan@mycroft  /data/Documents  sudo zfs list -t all
NAME                      USED  AVAIL     REFER  MOUNTPOINT
data                     33,4G  5,24T      128K  /data
data/Documents           33,4G  5,24T     33,4G  /data/Documents
data/Documents@20200619   522K      -     33,4G  -

Le partage Samba

l’implémentation sous Linux de ZFS ne permet qu’à un partage samba d’être créé avec les ACL « Everyone:FullPermissions » sans accès guest. Si on souhaite modifier ce comportement, il faut directement configurer samba. Dans mon cas, je vais juste créer un user local samba que j’utiliserai pour accéder au partage Samba.

1
2
sudo apt-get install samba
sudo smbpasswd -a yohan

Depuis Windows :

1
2
3
4
5
PS C:\Users\yohan> Get-SmbConnection

ServerName   ShareName      UserName       Credential     Dialect NumOpens
----------   ---------      --------       ----------     ------- --------
192.168.1.32 data_Documents sherlock\yohan sherlock\yohan 3.1.1   2

Le partage NFS

Rien de plus, simple, il faut installer le paquet nfs-kernel-server et mettre la propriété sharenfs à on pour le dataset selectionné.

Note: dans ce cas c’est open-bar au regard des ACLs, mais il est tout à fait possible d’en mettre.

1
2
3
4
5
yohan@mycroft  ~  sudo apt-get install nfs-kernel-server
yohan@mycroft  ~  sudo zfs set sharenfs=on data/Documents
 yohan@mycroft  ~  sudo zfs get sharenfs data/Documents
NAME            PROPERTY  VALUE     SOURCE
data/Documents  sharenfs  on        local

Depuis un autre poste, on monte le partage NFS :

1
2
3
4
5
6
7
yohan@sherlock:/mnt/c/Users/yohan$ sudo showmount -e 192.168.1.32
Export list for 192.168.1.32:
/data/Documents *
yohan@sherlock ~  sudo mount -t nfs 192.168.1.32:/data/Documents /mnt/data
yohan@sherlock ~  ls !$
yohan@sherlock ~  ls /mnt/data
Dossier1 Dossier2

Et les perfs alors ?

Les performances sont intéressantes, j’ai réussi à saturer mon lien gigabyte en backupant un laptop sous SSD.

Conclusion

ZFS est un système de fichier bien sympa, facile à prendre en main et qui vaut le détour lorsqu’on met en place des solutions pérennes. Reste maintenant à combiner cela des systèmes de fichiers distribués comme Ceph par exemple … 🙂

Sources