Administration ZFS, partie I — les VDEV

Article d’origine : « ZFS Administration, Part I- VDEVs » publié le 04/12/2012. Licence : CC BY-NC-SA 3.0 US.

Ceci est le premier billet d’une longue série sur comment administrer vos système de fichiers et pools ZFS (zpool). Vous devriez commencer par lire comment installer ZFS sur votre système GNU/Linux pour revenir ensuite à ce billet.

Introduction aux périphériques virtuels

Pour commencer, il faut comprendre le concept des périphériques virtuels (ou VDEV) du fait que ZFS les utilise considérablement en interne. Si vous êtes déjà familier avec RAID, alors ce concept n’est pas nouveau pour vous bien que vous ne vous y référiez pas forcément en tant que « VDEV ». En gros, c’est un meta-périphérique qui représente un ou plusieurs périphériques physiques. Avec du RAID logiciel sous Linux, vous pourriez avoir un périphérique « /dev/md0 » qui représente une grappe RAID-5 de quatre disques. Dans ce cas, « /dev/md0 » serait votre « VDEV ».

Il y a sept types de VDEV dans ZFS :

  1. disk (par défaut) — les disques physiques de votre système ;
  2. file — un chemin absolu vers des fichiers/images pré-alloués ;
  3. mirror — miroir RAID-1 logiciel standard ;
  4. raidz1/2/3 — niveaux de RAID logiciel non standards à base de parité distribuée ;
  5. spare — disques durs marqués comme « remplacement à chaud » (hot spare) pour le RAID logiciel ZFS ;
  6. cache — périphérique utilisé pour un cache de lecture adaptatif de niveau deux (L2ARC) ;
  7. log — un journal séparé (SLOG) appelé « ZFS Intent Log » ou ZIL.

Il est important de noter que les VDEV sont toujours entrelacés (striped) dynamiquement. Tout cela aura plus de sens au fur et à mesure des commandes présentées ci-dessous. Cela dit, supposons que nous ayons quatre disques dans un entrelacement ZFS. La taille de l’entrelacement est calculée par le nombre de disques et la taille des disques dans la grappe. Si d’autres disques sont ajoutés, la taille de l’entrelacement peut être ajustée au besoin pour le disque additionnel, d’où la nature dynamique de l’entrelacement.

Quelques avertissements au niveau d’un zpool

Je me sentirais un peu mal de ne pas mentionner ces mises en garde à propos de ZFS :

  • Une fois qu’un périphérique est ajouté à un VDEV, il ne peut plus être enlevé ;
  • Vous ne pouvez pas réduire un zpool, seulement l’agrandir ;
  • RAID-0 est plus rapide que RAID-1, qui est plus rapide que RAIDZ-1, qui est plus rapide que RAIDZ-2, qui est plus rapide que RAIDZ-3 ;
  • Les disques de remplacement (hot spare) ne sont pas ajoutés dynamiquement à moins d’activer l’option qui est désactivée par défaut ;
  • Un zpool ne se redimensionnera pas dynamiquement lorsque des disque de plus grande capacité sont ajoutés à moins d’activer l’option avant de remplacer le premier disque. Option qui est aussi désactivée par défaut ;
  • Un zpool saura profiter du « format avancé » des secteurs 4K des disques si et seulement si le disque le signale ;
  • La déduplication est extrêmement onéreuse et causera des dégradations de performance s’il n’y a pas assez de RAM installée. Elle s’applique à tout un pool et n’est pas locale aux systèmes de fichiers ;
  • D’un autre côté, la compression est extrêmement bon marché d’un point de vue processeur, pourtant elle est désactivée par défaut ;
  • ZFS souffre grandement de la fragmentation et des zpools pleins « ressentiront » la dégradation de performance ;
  • ZFS supporte le chiffrement nativement mais ce n’est pas du Logiciel Libre. Le chiffrement est propriétaire sous copyright d’Oracle.

Pour les exemples suivants, nous partons du principe que nous avons quatre disques : /dev/sde, /dev/sdf, /dev/sdg et /dev/sdh qui sont tous des clés USB de 8 Go. Entre chacune des commandes, si vous les suivez, soyez sûr d’appliquer l’étape de nettoyage entre chaque section.

Un simple pool

Commençons par créer un simple zpool avec les quatre disques. Je peux créer un zpool nommé « tank » avec la commande suivante :

# zpool create tank sde sdf sdg sdh

Ici j’utilise quatre VDEV disk. Notez que je n’utilise pas les chemins complets vers les périphériques bien que je le pourrais. Étant donné que les VDEV sont toujours entrelacés dynamiquement, c’est effectivement un RAID-0 entre quatre disques (sans redondance). Nous devrions aussi vérifier l’état du zpool :

# zpool status tank
  pool: tank
 state: ONLINE
 scan: none requested
config:

    NAME        STATE     READ WRITE CKSUM
    tank        ONLINE       0     0     0
      sde       ONLINE       0     0     0
      sdf       ONLINE       0     0     0
      sdg       ONLINE       0     0     0
      sdh       ONLINE       0     0     0

errors: No known data errors

Supprimons le zpool et créons-en un nouveau. Lancez cette commande avant de continuer si vous suivez les instructions dans votre propre terminal :

# zpool destroy tank

Un simple miroir zpool

Dans l’exemple suivant, je souhaite faire un miroir avec les quatre disques (/dev/sde, /dev/sdf, /dev/sdg et /dev/sdh). Aussi, plutôt que d’utiliser le VDEV disk, j’utiliserai « mirror ». La commande est la suivante :

# zpool create tank mirror sde sdf sdg sdh
# zpool status tank
  pool: tank
 state: ONLINE
 scan: none requested
config:

    NAME        STATE     READ WRITE CKSUM
    tank        ONLINE       0     0     0
      mirror-0  ONLINE       0     0     0
        sde     ONLINE       0     0     0
        sdf     ONLINE       0     0     0
        sdg     ONLINE       0     0     0
        sdh     ONLINE       0     0     0

errors: No known data errors

Notez que « mirror-0 » est dorénavant le VDEV et qu’il supervise chaque périphérique physique. Comme mentionné plus tôt, ceci est analogue au périphérique « /dev/md0 » en RAID logiciel sous Linux et représentant les quatre périphériques physiques. Nettoyons notre zpool et créons-en un autre.

# zpool destroy tank

VDEV imbriqués

Les VDEV peuvent être imbriqués. Un parfait exemple est un RAID-1+0 standard (communément appelé « RAID-10 »). C’est un entrelacement de miroirs. Afin de spécifier les VDEV imbriqués, je les mets simplement sur la ligne de commande dans l’ordre (l’emphase est de mon fait) :

# zpool create tank mirror sde sdf mirror sdg sdh
# zpool status
  pool: tank
 state: ONLINE
 scan: none requested
config:

    NAME        STATE     READ WRITE CKSUM
    tank        ONLINE       0     0     0
      mirror-0  ONLINE       0     0     0
        sde     ONLINE       0     0     0
        sdf     ONLINE       0     0     0
      mirror-1  ONLINE       0     0     0
        sdg     ONLINE       0     0     0
        sdh     ONLINE       0     0     0

errors: No known data errors

Le premier VDEV est « mirror-0 » et il gère /dev/sde ainsi que /dev/sdf. Cela a été fait en appelant « mirror sde sdf ». Le second VDEV est « mirror-1 » et il gère /dev/sdg ainsi que /dev/sdh. Cela a été fait en appelant « mirror sdg sdh ». Comme les VDEV sont toujours entrelacés dynamiquement, « mirror-0 » et « mirror-1 » sont entrelacés, d’où la création d’une configuration RAID-1+0. N’oubliez pas de nettoyer avant de continuer :

# zpool destroy tank

VDEV fichiers

Comme mentionné, des fichiers pré-alloués peuvent être utilisés pour configurer des zpools sur votre système de fichiers ext4 (ou autre). Il est à noter que cela est uniquement destiné à des fins de tests et non pas pour stocker des données de production. Utiliser des fichiers est une très bonne façon d’avoir un bac à sable où vous pouvez tester des ratios de compression, la taille de la table de déduplication ou d’autres choses sans réellement engager des données de production. Quand on crée des VDEV file, on ne peut pas utiliser de chemins relatifs et on doit utiliser des chemins absolus. De plus, les fichiers images doivent être préalloués et non pas partiellement alloués ou avoir une allocation fine et dynamique. Voyons comment ça marche :

# for i in {1..4}; do dd if=/dev/zero of=/tmp/file$i bs=1G count=4 &> /dev/null; done
# zpool create tank /tmp/file1 /tmp/file2 /tmp/file3 /tmp/file4
# zpool status tank
  pool: tank
 state: ONLINE
 scan: none requested
config:

    NAME          STATE     READ WRITE CKSUM
    tank          ONLINE       0     0     0
      /tmp/file1  ONLINE       0     0     0
      /tmp/file2  ONLINE       0     0     0
      /tmp/file3  ONLINE       0     0     0
      /tmp/file4  ONLINE       0     0     0

errors: No known data errors

Ici nous avons créé un RAID-0. Nous avons utilisé des fichiers pré-alloués en utilisant /dev/zero et faisant une taille de 4 Go chacun. De ce fait la taille de notre zpool a un espace utilisable de 16 Go. Chaque fichier, tout comme notre premier exemple utilisant des disques, est un VDEV. Bien sûr, vous pouvez traiter les fichiers comme des disques et les mettre dans une configuration de type miroir, RAID-1+0, RAIDZ-1 (voir ci-dessous), etc.

# zpool destroy tank

Pools hybrides

Ce dernier exemple devrait vous montrer les pools complexes que vous pouvez configurer en utilisant différents VDEV. En utilisant nos quatre VDEV file de l’exemple précédent et nos quatre VDEV disk (/dev/sde jusqu’à /dev/sdh), créons un pool hybride avec des disques pour un cache et un journal. Encore une fois, j’ai mis en gras les VDEV imbriqués pour plus de clarté :

# zpool create tank mirror /tmp/file1 /tmp/file2 mirror /tmp/file3 /tmp/file4 log mirror sde sdf cache sdg sdh
# zpool status tank
  pool: tank
 state: ONLINE
 scan: none requested
config:

    NAME            STATE     READ WRITE CKSUM
    tank            ONLINE       0     0     0
      mirror-0      ONLINE       0     0     0
        /tmp/file1  ONLINE       0     0     0
        /tmp/file2  ONLINE       0     0     0
      mirror-1      ONLINE       0     0     0
        /tmp/file3  ONLINE       0     0     0
        /tmp/file4  ONLINE       0     0     0
    logs
      mirror-2      ONLINE       0     0     0
        sde         ONLINE       0     0     0
        sdf         ONLINE       0     0     0
    cache
      sdg           ONLINE       0     0     0
      sdh           ONLINE       0     0     0

errors: No known data errors

Il se passe beaucoup de choses ici, décortiquons tout ça. Premièrement, nous créons un RAID-1+0 en utilisant nos quatre fichiers images préalloués. Remarquez les VDEV « mirror-0 » et « mirror-1 » et ce qu’ils gèrent. Deuxièmement, nous créons un troisième VDEV nommé « mirror-2 » qui n’est en fait pas utilisé pour stocker des données dans le pool mais qui est utilisé comme ZFS Intent Log ou ZIL. Nous verrons le ZIL plus en détail dans un autre billet. Ensuite nous créons deux VDEV pour cacher les données nommés « sdg » et « sdh ». Ce sont des VDEV disk standards que nous avons déjà vus. Cependant, ils sont aussi gérés par le VDEV de « cache ». Ici nous avons donc utilisé six des septs VDEV listés plus haut, le seul manquant est le « spare ».

Prendre en compte l’indentation vous aidera à voir quel VDEV gère quoi. Le pool « tank » est composé des VDEV « mirror-0 » et « mirror-1 » pour du stockage persistant à long terme. Le ZIL est géré par « mirror-2 » qui est composé de /dev/sde et /dev/sdf. Le VDEV de cache en lecture seule est géré par deux disques, /dev/sdg et /dev/sdh. Ni les « logs » ni le « cache » ne sont du stockage à long terme pour le pool, d’où la création d’une configuration de type « pool hybride ».

# zpool destroy tank

Un exemple de la vraie vie

En production, les fichiers seraient des disques physiques et le ZIL ainsi que le cache seraient de rapides SSD. Voilà ma configuration zpool actuelle qui stocke ce blog (NdT : celui de l’auteur de l’article d’origine), entre autres choses :

# zpool status pool
  pool: pool
 state: ONLINE
 scan: scrub repaired 0 in 2h23m with 0 errors on Sun Dec  2 02:23:44 2012
config:

        NAME                  STATE     READ WRITE CKSUM
        pool                  ONLINE       0     0     0
          raidz1-0            ONLINE       0     0     0
            sdd               ONLINE       0     0     0
            sde               ONLINE       0     0     0
            sdf               ONLINE       0     0     0
            sdg               ONLINE       0     0     0
        logs
          mirror-1            ONLINE       0     0     0
            ata-OCZ-REVODRIVE_OCZ-33W9WE11E9X73Y41-part1    ONLINE       0     0     0
            ata-OCZ-REVODRIVE_OCZ-X5RG0EIY7MN7676K-part1  ONLINE       0     0     0
        cache
          ata-OCZ-REVODRIVE_OCZ-33W9WE11E9X73Y41-part2    ONLINE       0     0     0
          ata-OCZ-REVODRIVE_OCZ-X5RG0EIY7MN7676K-part2    ONLINE       0     0     0

errors: No known data errors

Remarquez que mes VDEV « logs » et « cache » sont des SSD OCZ Revodrive tandis que les quatre disques à plateaux sont dans un VDEV RAIDZ-1 (nous traiterons de RAIDZ dans le prochain billet). Quoi qu’il en soit, il faut remarquer que le nom des SSD est « ata-OCZ-REVODRIVE_OCZ-33W9WE11E9X73Y41-part1 », etc. Ils se trouvent dans /dev/disk/by-id/. La raison pour laquelle je les ai choisis à la place de « sdb » et « sdc » est que les périphériques de cache et de log ne stockent pas nécessairement les mêmes métadonnées ZFS. Ainsi, quand le pool est créé au démarrage, il se peut qu’ils ne soient pas intégrés dedans et qu’ils soient manquants. Ou la carte mère peut assigner les lettres des lecteurs dans un ordre différent. Cela n’est pas un problème avec le pool principal mais c’en est un gros sous GNU/Linux avec des périphériques de cache et de logs. En utilisant le nom du périphérique sous /dev/disk/by-id/, cela assure une plus grande persistence et unicité.

On peut remarquer aussi la simplicité de l’implémentation. Pour faire quelque chose de similaire avec LVM, RAID et ext4, il faudrait faire ce qui suit :

# mdadm -C /dev/md0 -l 0 -n 4 /dev/sde /dev/sdf /dev/sdg /dev/sdh
# pvcreate /dev/md0
# vgcreate /dev/md0 tank
# lvcreate -l 100%FREE -n videos tank
# mkfs.ext4 /dev/tank/videos
# mkdir -p /tank/videos
# mount -t ext4 /dev/tank/videos /tank/videos

Ce qui est fait ci-dessus a été fait avec ZFS en une seule commande (moins la création du volume logique, que nous verrons plus tard) au lieu de sept.

Conclusion

Ce billet devrait être un bon point de départ pour avoir une compréhension de base des zpool et VDEV. Tout le reste en découlera. Vous avez maintenant franchi le plus gros obstacle qui est de comprendre comment ZFS gère le stockage groupé. Nous devons encore voir les niveaux RAIDZ et nous devons approfondir les périphériques de cache et de log ainsi que les options de pool tels que la déduplication et la compression. Mais nous verrons tout cela dans d’autres billets. Ensuite nous pourrons nous intéresser aux jeux de données du système de fichiers ZFS, leurs options, leurs avantages et leurs défauts. Mais vous avez maintenant une longueur d’avance sur la partie essentielle des pools ZFS.