SSD Nodes Learn 🎉 VPS dès $5.50/mois
Guides Matt ConnorPar Matt Connor

À quelle fréquence lancer un scrub ZFS sur un VPS ?

Un scrub ZFS vérifie chaque bloc alloué. Sur un pool VPS à disque unique, il détecte les corruptions sans pouvoir les réparer : voici la fréquence adaptée.

Ce que fait réellement un scrub ZFS

Un scrub ZFS lit chaque bloc alloué du pool, recalcule sa somme de contrôle et compare le résultat à la somme de contrôle stockée dans le pointeur de bloc parent. Si les deux valeurs diffèrent, ZFS répare le bloc à partir des données redondantes disponibles dans le pool. Rien d’autre dans ZFS n’effectue ce contrôle. Les lectures ordinaires vérifient uniquement les blocs que vous consultez effectivement. Un fichier que vous n’avez pas ouvert depuis deux ans reste donc non vérifié jusqu’à ce qu’un scrub le lise.

Un scrub n’est pas fsck, la passe de réparation hors ligne dont les autres systèmes de fichiers ont besoin. Il n’y a pas de phase de réparation structurelle, car ZFS ne laisse jamais le format sur disque dans un état incohérent : chaque écriture est effectuée à un nouvel emplacement, puis l’uberblock, le pointeur racine du pool, est mis à jour en dernier. Un scrub ne lit pas non plus l’intégralité du périphérique. Il lit uniquement les blocs alloués. C’est pourquoi le scrub d’un pool presque vide prend quelques minutes, tandis que celui du même pool rempli à 80% prend beaucoup plus de temps.

Le scrub s’exécute avec la priorité d’E/S la plus faible disponible dans ZFS. Sous Linux, zfs_vdev_scrub_max_active vaut 2 par défaut. Au plus deux lectures de scrub sont donc en cours par vdev (périphérique virtuel, c’est-à-dire le groupe de disques que ZFS traite comme une seule unité). zfs_scrub_min_time_ms vaut 750 par défaut. Il s’agit de la durée minimale pendant laquelle le thread de synchronisation consacre du temps au scrub entre les flushes des groupes de transactions, c’est-à-dire les commits périodiques dans lesquels ZFS regroupe les écritures. Sur une machine inactive, le scrub utilise tout le disque. En charge, il se met en retrait. Avec un pool composé d’un ou deux périphériques, il n’a nulle part où se mettre en retrait. C’est pourquoi la planification est plus importante dans ce cas que sur un grand châssis équipé de soixante disques.

Pourquoi scruber un pool qui ne peut pas se réparer lui-même ?

Cette phrase détermine tout le reste sur un petit pool. Sans redondance, un scrub détecte la corruption, mais ne peut pas la corriger. Un disque virtuel unique dans un VPS constitue un pool sans miroir ni parité. ZFS lit le bloc défectueux, échoue au contrôle de checksum, le compte dans la colonne CKSUM, indique le fichier concerné, puis s’arrête là, car aucune seconde copie ne permet de le reconstruire.

Deux exceptions partielles méritent d’être connues. Par défaut, ZFS stocke une copie supplémentaire des métadonnées (redundant_metadata=all), dans une autre zone du périphérique. Un scrub peut donc réparer une entrée de répertoire ou un pointeur de bloc endommagé, même sur un pool à un seul périphérique. Par ailleurs, un dataset avec copies=2 conserve deux copies de ses blocs de données, au prix d’une consommation d’espace doublée. Aucune de ces protections ne fonctionne si le périphérique devient indisponible. La documentation de la propriété copies met précisément en garde contre ce cas : ne créez pas un pool striped, ne définissez pas copies=2, puis ne croyez pas disposer d’une redondance.

Sur un pool à un seul périphérique, le scrub vous apporte donc une seule chose : une notification précoce et fiable. Il transforme une corruption silencieuse en nom de fichier dans zpool status -v, alors que votre backup contient encore une version intacte de ce fichier. C’est un argument en faveur des backups, pas contre les scrubs. Si la différence entre une image à un instant donné et une véritable copie stockée hors du serveur n’est pas encore claire, commencez par pourquoi un snapshot de VPS n’est pas un backup, car le résultat d’un scrub n’est utile que si une autre copie intacte existe.

Un scrub qui ne détecte rien constitue également un résultat. Il vous indique que les données auxquelles vous allez faire confiance sont intactes, ce qu’il est important de savoir avant une restauration ou une migration.

À quelle fréquence faut-il effectuer un scrub sur un petit pool VPS ?

Une fois par mois est la fréquence recommandée par défaut, et c’est celle que les paquets utilisent déjà. Debian et Ubuntu installent une tâche cron qui effectue un scrub des pools sains le deuxième dimanche de chaque mois. Le système periodic de FreeBSD utilise un seuil exprimé en jours, et daily_scrub_zfs_default_threshold vaut 35 par défaut, ce que le manuel décrit comme cinq semaines.

Effectuer un scrub chaque semaine sur un petit pool très sollicité coûte généralement plus que cela ne rapporte. Avec un ou deux périphériques, le scrub utilise la même file d’attente que votre application, et aucun périphérique supplémentaire ne peut absorber cette charge. Sur un VPS, le quota d’I/O est limité : les lectures consommées par le scrub sont des lectures dont votre base de données ne dispose pas. En contrepartie, un scrub hebdomadaire vous donne au mieux trois semaines d’avance pour détecter un défaut que vous ne pouvez de toute façon pas réparer. Ce compromis n’est pertinent que lorsque le scrub coûte peu de ressources.

Mesurez sa durée, puis décidez. Effectuez un scrub manuellement et surveillez le temps nécessaire.

  1. Exécutez sudo zpool scrub tank un soir où la charge est faible et notez la durée totale à partir de zpool status.
  2. S’il se termine largement en moins d’une heure et que le serveur est inactif pendant la nuit, une fréquence hebdomadaire reste acceptable.
  3. S’il dure plusieurs heures alors que le pool traite du trafic, conservez une fréquence mensuelle et laissez la tâche fournie par le paquet s’en charger.
  4. Mesurez à nouveau sa durée chaque fois que le pool augmente sensiblement, car la durée du scrub dépend des données allouées, et non de la capacité du disque.

Quel que soit votre choix, notez-le avec vos autres tâches récurrentes d’administration du serveur. Le scrub doit figurer dans la même liste que les mises à niveau des paquets et la rotation des journaux : consultez une checklist mensuelle de maintenance d’un serveur Linux.

Démarrer, mettre en pause et arrêter un scrub

sudo zpool scrub tank
sudo zpool status tank

La mise en pause et l’arrêt sont deux opérations différentes. Choisir la mauvaise peut vous faire perdre plusieurs heures de travail.

sudo zpool scrub -p tank
sudo zpool scrub tank
sudo zpool scrub -s tank

-p met le scrub en pause. L’état et la progression de la pause sont régulièrement synchronisés sur le disque. Un scrub en pause survit donc à un export ou à un redémarrage : le pool revient avec le scrub toujours en pause, dans l’attente de votre intervention. Relancer zpool scrub reprend l’opération depuis le dernier point de contrôle écrit sur le disque. -s arrête le scrub. Le prochain scrub que vous démarrerez recommencera depuis le début. Utilisez -p lorsque vous avez besoin du disque pendant une heure. Utilisez -s lorsque vous voulez supprimer le scrub.

Deux autres options méritent d’être connues. -w attend la fin du scrub avant de rendre la main. C’est ce qu’il faut utiliser dans un script afin que l’étape suivante ne démarre pas trop tôt. -e effectue un scrub uniquement sur les fichiers dont zpool status -v a signalé des erreurs de données connues. C’est la méthode rapide pour vérifier qu’un fichier restauré depuis une sauvegarde est maintenant intact.

ZFS n’exécute qu’un scrub ou un resilver à la fois par pool, car ces deux opérations sollicitent fortement les entrées-sorties. Si un périphérique est en cours de resilver, votre scrub attend son tour.

Comment lire l’état de zpool pendant un scrub

Exécutez sudo zpool status tank et interprétez vos propres valeurs au lieu de les comparer à celles d’un autre système. Pendant un scrub, la ligne scan: contient le nombre d’éléments analysés, le nombre d’éléments envoyés, le total, le nombre d’éléments réparés, le pourcentage d’avancement et l’estimation du temps restant.

Scanned correspond à la phase des métadonnées : ZFS parcourt l’arborescence des blocs et collecte les adresses à lire. Issued correspond à la phase des données : les lectures sont effectivement envoyées au périphérique, dans l’ordre du disque. Le scrub trié explique la présence de ces deux compteurs, et issued est celui qui suit la progression réelle. Au début, scanned peut être très en avance sur issued et l’estimation du temps restant est peu fiable. Évaluez-la après les 10 premiers pour cent.

Repaired compte les octets réécrits à partir d’une copie valide. Sur un pool sans redondance, cette valeur reste à zéro, quelle que soit la découverte du scrub. Cela confirme sous forme chiffrée le point précédent, que vous pouvez suivre directement.

Lisez ensuite les colonnes de chaque périphérique. READ et WRITE comptent les erreurs d’E/S signalées par le périphérique lui-même. CKSUM compte les blocs dont la vérification de checksum a échoué, et CKSUM est la colonne qu’un scrub est censé renseigner. Une valeur CKSUM non nulle sur un périphérique qui semble sain est réelle : les données ont été lues, mais elles étaient incorrectes.

La dernière ligne donne le verdict. errors: No known data errors indique que le scrub a réussi. Toute autre valeur signifie qu’il faut exécuter sudo zpool status -v tank, qui affiche la liste complète des erreurs de données depuis le dernier scrub terminé, y compris les noms des fichiers concernés. Restaurez ces fichiers depuis la sauvegarde, exécutez sudo zpool clear tank pour réinitialiser les compteurs, puis relancez le scrub. Chaque scrub terminé reconstruit cette liste : un nom de fichier absent après un scrub complet sans erreur a donc réellement disparu.

Quel job de scrub périodique est configuré sur votre machine ?

Ne partez pas du principe qu’il en existe un, ni qu’il n’y en a qu’un seul. Le mécanisme varie selon la plateforme et le package. Le format du pool est identique partout, ce qui fait facilement oublier que les outils associés ne le sont pas. La façon dont ZFS est fourni sur FreeBSD par rapport à Linux est la différence importante ici.

Sur FreeBSD, le job utilise le système periodic. Définissez ces paramètres dans /etc/periodic.conf :

daily_scrub_zfs_enable="YES"
daily_scrub_zfs_pools="tank"
daily_scrub_zfs_default_threshold="35"

daily_scrub_zfs_pools est une liste de noms de pools séparés par des espaces. Si cette valeur est vide, tous les pools sont scrub. daily_scrub_zfs_default_threshold indique le nombre de jours entre deux scrubs lorsqu’aucun seuil spécifique n’est défini pour un pool. Le manuel indique 35 comme valeur par défaut. Le job daily s’exécute chaque jour ; il ne démarre un scrub qu’une fois le seuil dépassé.

Sous Linux, cela dépend du package ZFS de votre distribution. Certains systèmes utilisent même les deux mécanismes simultanément. Il existe des systemd timers propres à chaque pool, zfs-scrub-monthly@tank.timer et zfs-scrub-weekly@tank.timer, qui s’activent pool par pool. Debian et Ubuntu fournissent également /etc/cron.d/zfsutils-linux, qui exécute un script lançant un scrub sur chaque pool ONLINE le deuxième dimanche du mois. Vérifiez ce qui est déjà présent avant d’ajouter quoi que ce soit :

systemctl list-timers 'zfs-*'
ls /etc/cron.d/ | grep -i zfs
sudo zpool history tank | grep scrub

zpool history est la réponse fiable, car il enregistre les scrubs réellement démarrés par le pool, avec leurs dates. Deux scrubs par mois signifient que les deux mécanismes sont actifs et que l’un d’eux doit être désactivé. Pour activer un timer :

sudo systemctl enable --now zfs-scrub-monthly@tank.timer

L’espace libre compte plus que n’importe quel paramètre

La durée d’un scrub sur un petit pool dépend de la quantité de données allouées et de leur dispersion. Remplir le pool aggrave ces deux facteurs.

OpenZFS recommande de conserver plus de 10% d’espace libre dans le pool. En dessous de ce seuil, les metaslabs, c’est-à-dire les blocs dans lesquels l’allocator travaille, commencent à passer sous un seuil de 4% d’espace libre. L’allocator passe alors de first-fit à best-fit. best-fit consomme beaucoup plus de CPU. La latence d’écriture augmente, la fragmentation s’accentue et le scrub suivant est encore plus lent, car la même quantité de données est maintenant lue sous la forme d’un plus grand nombre de lectures plus petites.

Le premier levier n’est donc pas un paramètre. Il consiste à supprimer des données. Sur un serveur ZFS, les anciens snapshots sont généralement en cause, suivis par les images et couches Docker qui n’ont jamais été supprimées et les paquets du kernel laissés par les mises à niveau. Exécutez zfs list -o space avant toute autre action, car cette commande distingue l’espace occupé par les snapshots de celui occupé par les données actives.

Passons ensuite brièvement aux paramètres. Sous Linux, vous pouvez lire leurs valeurs actuelles :

cat /sys/module/zfs/parameters/zfs_scrub_min_time_ms
cat /sys/module/zfs/parameters/zfs_vdev_scrub_max_active

FreeBSD expose les mêmes paramètres via sysctl. Trouvez les vôtres avec sysctl -a | grep scrub. Les augmenter termine le scrub plus rapidement, mais ralentit vos applications. Les réduire produit l’effet inverse. Sur un pool équipé d’un ou deux périphériques, aucun réglage ne permet d’obtenir les deux avantages, car il n’y a qu’une seule file d’attente à répartir. Un paramètre corrige rarement un problème de conception. Si un scrub mensuel provoque des ralentissements, la conclusion est généralement simple : le pool est trop rempli ou le périphérique est trop lent. Un paramètre ne fait que déplacer le problème.

La durée d’un scrub préfigure celle d’un resilver

Un resilver parcourt les mêmes données qu’un scrub : il lit les blocs alloués, les vérifie et écrit les blocs manquants sur le périphérique de remplacement. La durée de votre scrub est donc l’estimation la plus fiable de la durée d’une reconstruction, ainsi que de la période pendant laquelle le pool fonctionnera avec une redondance réduite.

ZFS planifie le resilver de manière plus agressive que le scrub. Une reconstruction se termine donc généralement plus vite qu’un scrub du même pool. Considérez la durée du scrub comme une limite supérieure prudente. Si le scrub prend neuf heures, prévoyez une fenêtre de reconstruction de cet ordre. Gardez à l’esprit qu’une deuxième défaillance de périphérique pendant cette fenêtre entraîne la perte du pool. C’est l’argument pratique en faveur des paires en miroir plutôt que d’un seul groupe raidz large, car raidz, la disposition avec parité que ZFS utilise à la place de RAID 5, reconstruit les données en lisant tous les périphériques encore disponibles.

Sur un pool composé d’un seul périphérique, il n’y a aucun resilver. Si le périphérique tombe en panne, le pool est perdu avec lui. Votre temps de récupération correspond au temps de restauration. Mesurez donc la restauration. Une restauration que vous n’avez jamais exécutée ne constitue pas un plan de récupération.

Ce qui change lorsque vous louez le disque

Sur un VPS, le périphérique bloc est virtuel. L’hyperviseur présente un volume. En dessous, il peut s’agir d’un stockage NVMe local ou d’un volume réseau répliqué avec son propre mécanisme de parité. Deux conséquences en découlent pour les scrubs.

Premièrement, la redondance de la plateforme est invisible pour ZFS, qui ne peut pas l’utiliser. Si la plateforme corrige une erreur de support en dessous de votre instance, ZFS ne voit jamais le problème. Si la plateforme lui transmet un bloc incorrect, ZFS le détecte, mais ne peut pas le corriger, car la bonne copie se trouve de l’autre côté de cette limite.

Deuxièmement, vous ne pouvez généralement pas lire les données SMART (self-monitoring, analysis and reporting technology) du périphérique situé sous un disque virtuel. Les alertes précoces dont dépend la surveillance de l’état des disques sur un VPS peuvent donc être totalement indisponibles. Le compteur CKSUM de vos scrubs devient le principal signal dont vous disposez.

Pour que ZFS puisse corriger les erreurs au lieu de seulement les signaler, le pool doit contenir plusieurs périphériques dans la même instance. Il s’agit d’une décision d’architecture, pas d’un réglage. Choisir un VPS de stockage plutôt qu’un VPS standard vous donne la capacité nécessaire, mais la présence de deux périphériques indépendants dépend du plan. Exécutez lsblk et vérifiez la configuration avant de créer un mirror qui reposerait en réalité sur deux partitions d’un même volume. Nous louons des serveurs Linux et FreeBSD, pas une appliance ZFS administrée. Le calendrier des scrubs et les sauvegardes sont donc à votre charge. C’est le compromis : vous contrôlez entièrement le pool et vous assurez entièrement sa maintenance.

FAQ

À quelle fréquence faut-il effectuer un scrub sur un pool ZFS hébergé sur un VPS ?

Une fois par mois convient à la plupart des petits pools. Cette fréquence correspond aussi aux réglages par défaut des paquets : une tâche cron exécutée le deuxième dimanche sous Debian et Ubuntu, et un seuil par défaut de 35 jours dans le système periodic de FreeBSD. Une fréquence hebdomadaire n’est raisonnable qu’après avoir chronométré un scrub et vérifié qu’il se termine rapidement sur une machine par ailleurs inactive. Sur un pool actif avec un ou deux périphériques, un scrub hebdomadaire consomme réellement des entrées-sorties applicatives chaque semaine, pour fournir seulement quelques semaines d’avance supplémentaires dans la détection des problèmes.

Un scrub sur un pool ZFS constitué d’un seul disque est-il inutile ?

Non, à condition de bien comprendre ce qu’il permet. Sans redondance, un scrub détecte la corruption, mais ne peut pas la réparer, à l’exception des métadonnées, dont ZFS conserve par défaut une copie supplémentaire. Vous obtenez une liste identifiée des fichiers endommagés dans zpool status -v, suffisamment tôt pour les restaurer tant qu’une bonne copie existe encore ailleurs. La bonne réponse consiste à améliorer vos sauvegardes, puisque le scrub vous indique précisément quel fichier restaurer.

Puis-je mettre un scrub ZFS en pause et le terminer plus tard ?

Oui. zpool scrub -p tank le met en pause, et l’état ainsi que la progression de la pause sont écrits périodiquement sur le disque. Le scrub reste donc en pause après un export ou un redémarrage. Exécutez à nouveau zpool scrub tank pour reprendre à partir du dernier point de contrôle. N’utilisez pas zpool scrub -s tank pour cela : -s arrête le scrub, et le suivant recommence depuis le début.

Pourquoi mon scrub ZFS est-il si lent, et puis-je l’accélérer ?

La durée du scrub dépend de l’espace alloué et de la fragmentation, pas de la capacité du disque. Un pool rempli à plus de 90 % est lent, car les metaslabs disposant de moins de 4 % d’espace libre font passer l’allocateur de first-fit à best-fit. La fragmentation qui en résulte transforme alors le scrub en une multitude de petites lectures. Libérer de l’espace est généralement plus efficace que de modifier un paramètre. Vous pouvez augmenter zfs_scrub_min_time_ms ou zfs_vdev_scrub_max_active pour donner au scrub une part plus importante de la queue, mais sur un pool doté d’un ou deux périphériques, cette part est directement retirée aux applications.