ZFS : chemins de périphériques manquants — utiliser by-id et WWN intelligemment

Cet article vous a aidé ?

Votre pool ZFS est sain depuis des mois, puis un redémarrage le transforme en scène de crime : DEGRADED, un disque « UNAVAIL », et le nom du périphérique dans zpool status
a l’air d’avoir été tiré au sort par un générateur aléatoire. Les données sont probablement intactes. Le problème vient du nommage.

C’est l’écart entre « ça marchait en labo » et « ça tient en production » : des chemins de périphériques persistants. Si votre pool référence /dev/sdX,
vous avez déjà choisi que votre prochaine panne sera instructive.

Pourquoi /dev/sdX est un piège (et pourquoi ça revient)

/dev/sdX n’est pas une identité. C’est un numéro de siège. Linux attribue ces lettres selon l’ordre de découverte, et l’ordre de découverte change :
nouveau firmware HBA, entraînement d’un autre slot PCIe, un disque lent qui répond plus tard après un événement d’alimentation, temporisations multipath, réinitialisations d’enceinte, etc.
Votre disque n’est pas devenu un autre disque. Le noyau les a juste découverts dans un ordre différent.

ZFS est parfaitement content d’utiliser le chemin que vous lui avez donné. Si vous avez créé le pool comme mirror /dev/sda /dev/sdb,
ZFS enregistrera ces chaînes. Plus tard, si /dev/sda pointe maintenant vers un autre disque, vous avez deux problèmes :
ZFS ne trouve plus l’ancien, et vous pourriez « corriger » le mauvais disque par accident. Le premier provoque un pool dégradé. Le second provoque une mise à jour de CV.

La solution est d’arrêter d’utiliser des noms éphémères et de commencer à utiliser des identifiants stables : /dev/disk/by-id et, plus précisément, les identifiants basés sur WWN quand disponibles.
Ceux-ci sont conçus pour survivre aux redémarrages, à la réénumération et à la plupart des réagencements matériels.

Blague n°1 : Utiliser /dev/sdX en production, c’est comme étiqueter des serveurs « celui près de la fenêtre ». Ça marche jusqu’à ce que quelqu’un déplace le bureau.

Faits intéressants et un peu d’histoire

  • Fait 1 : ZFS est né chez Sun Microsystems et a été conçu autour de l’idée que le stockage ment ; il vérifie les données de bout en bout avec des checksums.
  • Fait 2 : Les noms de périphériques Linux comme /dev/sda proviennent du sous-système SCSI disque, même pour les disques SATA et USB routés via des couches d’émulation SCSI.
  • Fait 3 : WWN (World Wide Name) est un concept d’identifiant globalement unique issu des écosystèmes Fibre Channel/SAS, repris ensuite pour le SATA via des standards et adaptateurs.
  • Fait 4 : Les liens symboliques de udev sous /dev/disk/by-* existent précisément parce que l’énumération des périphériques par le noyau n’est pas stable entre les démarrages.
  • Fait 5 : ZFS stocke des labels sur le disque (quatre labels par membre vdev dans les implémentations typiques), c’est pourquoi les pools peuvent souvent être importés même lorsque les chemins changent.
  • Fait 6 : Les noms « by-path » encodent le chemin de connexion physique (bus PCI, port HBA, emplacement dans l’enceinte) et sont stables jusqu’à ce que vous déplaciez des câbles ou des HBA.
  • Fait 7 : Aux débuts du stockage grand public, les numéros de série des disques étaient parfois dupliqués ou formatés bizarrement par des puces intermédiaires ; le WWN se comporte généralement mieux.
  • Fait 8 : Dans les environnements multipath, on expose souvent à la fois des nœuds par chemin et un périphérique consolidé via mapper ; choisir le mauvais peut provoquer des « flappings » de périphériques dans ZFS.

Ce que vous devriez utiliser : by-id, WWN, et quand by-path est acceptable

Choisir une identité stable : symlinks by-id basés sur WWN

Sur la plupart des systèmes Linux modernes, vous trouverez des liens symboliques sous /dev/disk/by-id. Pour SAS/SATA/NVMe, vous obtenez typiquement plusieurs variantes :
vendor/model/serial, et souvent une entrée basée sur WWN. Les entrées basées sur WWN ressemblent couramment à :
wwn-0x5000cca2... (SATA/SAS) ou nvme-eui.000000... / nvme-uuid.... (NVMe).

Pour ZFS, préférez les formes WWN/EUI/UUID car elles sont conçues pour être globalement uniques et sont moins susceptibles d’être corrompues par un bridge USB-SATA ou un HBA capricieux.
Si vous n’avez que des symlinks vendor+serial, cela peut encore convenir, mais vous devriez valider l’unicité sur tout le châssis.

Quand by-path est utile

/dev/disk/by-path vous indique où le disque est branché. C’est de l’or opérationnel quand vous devez « trouver le disque physique à retirer »
dans un datacenter bruyant à 3 h du matin. Mais ce n’est pas une identité si vous prévoyez de déplacer le disque vers un autre port de contrôleur. C’est une adresse.

J’utilise by-path pour le dépannage et le cartographie des emplacements, et by-id/WWN pour l’appartenance au pool. Cette séparation garde les humains sains d’esprit et les pools stables.

À éviter

  • Évitez : /dev/sdX en production. Même sur des serveurs « simples ». Surtout sur des serveurs « simples ».
  • Évitez : les nœuds « disque entier » sans partition si vous êtes dans un environnement où des outils peuvent écrire des métadonnées (certains installateurs, certains outils RAID).
  • Évitez : de mélanger des périphériques mapper multipath et des périphériques bruts dans le même pool.
  • Évitez : de compter sur /dev/disk/by-label ou les labels de système de fichiers pour l’identification des vdev ZFS ; ce n’est pas leur usage.

Comment ZFS se souvient des périphériques (et ce que signifie vraiment « chemin de périphérique manquant »)

ZFS ne fait pas que faire confiance à une chaîne de chemin. Il écrit la configuration du pool et les labels vdev sur les disques eux-mêmes. C’est pourquoi vous pouvez déplacer un pool sur un autre hôte,
l’importer, et ZFS peut souvent deviner ce qui appartient où. Mais le chemin reste important car c’est ce que ZFS essaie en premier, et ce que les opérateurs voient dans les alertes.

Une situation « chemin de périphérique manquant » tombe généralement dans l’un de ces cas :

  • Chemin changé, disque présent : Le disque est sain, mais l’OS le présente sous un autre nœud. Classique permutation /dev/sdX.
  • Disque entièrement absent : Problèmes HBA, backplane, alimentation, câblage, mauvaise configuration multipath, ou disque effectivement mort.
  • Disque présent mais refusé : Incompatibilité de taille de secteur, table de partitions obsolète, mauvais disque de remplacement, ou mauvais nœud de périphérique (ex. un seul chemin d’un dispositif multipath).
  • Permissions/temporisation udev : Tentatives d’import en tout début de boot, règles udev manquantes dans initramfs, ou couches de chiffrement non ouvertes.

Votre travail est de décider rapidement dans quel seau vous vous trouvez. Ensuite vous pouvez soit relabéliser les chemins (sans danger) soit traiter le matériel comme coupable (nécessaire).

Une citation à coller sur un post‑it (idée paraphrasée) : L’espoir n’est pas une stratégie — souvent attribuée à la culture ingénierie et opérations.
En stockage, c’est littéralement douloureux.

Mode d’emploi pour un diagnostic rapide

Voici l’ordre que j’utilise quand le pager dit « ZFS DEGRADED » et que quelqu’un demande déjà si on doit basculer. L’objectif est de trouver le goulot rapidement :
est-ce du nommage, de la connectivité, ou un disque qui flanche ?

Premier : confirmer ce que ZFS considère comme manquant

  • Exécutez zpool status -P pour forcer l’affichage des chemins complets et capturer le nom exact affiché « UNAVAIL ».
  • Vérifiez si l’entrée manquante est un disque brut, une partition, ou un périphérique mapper.

Deuxième : confirmer si l’OS voit le disque via des IDs stables

  • Listez /dev/disk/by-id et /dev/disk/by-path.
  • Utilisez lsblk -o NAME,SIZE,MODEL,SERIAL,WWN,HCTL,TYPE,MOUNTPOINTS pour relier identité et topologie.

Troisième : décider s’il s’agit d’un « glissement de chemin » ou d’une « perte matérielle »

  • Si le WWN existe et correspond à votre inventaire/notes, il s’agit probablement d’un glissement de nommage. Utilisez zpool online ou zpool replace avec le chemin by-id correct.
  • Si le WWN est absent ou le disque manque dans lsblk, vérifiez les logs du noyau (dmesg) et l’état du contrôleur.

Quatrième : arrêter d’aggraver la situation

  • Ne commencez pas à retirer des disques en vous basant sur /dev/sdX.
  • Ne lancez pas zpool clear comme « solution ». Cela n’efface que les erreurs ; cela ne fait pas réapparaître les disques.

Cinquième : choisir l’action la plus petite et sûre

  • Pour un simple glissement de chemin : mettez à jour ZFS vers le chemin stable via replace (même remplacer un périphérique par lui‑même, en utilisant le nom by-id).
  • Pour une défaillance matérielle réelle : remplacez par un nouveau disque et laissez resilver. Si des erreurs de checksum apparaissent ailleurs, traitez le pool comme contaminé et lancez un scrub.

Tâches pratiques : commandes, sorties et décisions (12+)

Ce sont des choses réelles que vous exécutez sur la console. Chacune inclut ce que la sortie vous dit et la décision qu’elle doit déclencher.
Servez‑vous en comme éléments de construction ; ne les copiez pas en scripts sans comprendre l’environnement (multipath et chiffrement changent les règles).

Task 1: Check pool health with full paths

cr0x@server:~$ sudo zpool status -P
  pool: tank
 state: DEGRADED
status: One or more devices could not be opened.  Sufficient replicas exist for
        the pool to continue functioning in a degraded state.
config:

        NAME                                      STATE     READ WRITE CKSUM
        tank                                      DEGRADED     0     0     0
          mirror-0                                DEGRADED     0     0     0
            /dev/sda2                             UNAVAIL      0     0     0  cannot open
            /dev/disk/by-id/wwn-0x5000c500a1b2c3d4-part2  ONLINE       0     0     0

errors: No known data errors

Ce que ça signifie : ZFS manque /dev/sda2. L’autre côté du miroir est présent. Ça sent fortement le glissement de chemin.
Décision : Ne remplacez pas le matériel tout de suite. Trouvez d’abord quel disque était /dev/sda et rattachez ZFS à un chemin by-id.

Task 2: Confirm the disk exists under by-id

cr0x@server:~$ ls -l /dev/disk/by-id/ | sed -n '1,12p'
total 0
lrwxrwxrwx 1 root root  9 Dec 26 02:10 ata-SAMSUNG_MZ7KM960HAHP-00005_S3Z1NX0K123456 -> ../../sdb
lrwxrwxrwx 1 root root 10 Dec 26 02:10 ata-SAMSUNG_MZ7KM960HAHP-00005_S3Z1NX0K123456-part2 -> ../../sdb2
lrwxrwxrwx 1 root root  9 Dec 26 02:10 wwn-0x5002538d4098abcd -> ../../sdb
lrwxrwxrwx 1 root root 10 Dec 26 02:10 wwn-0x5002538d4098abcd-part2 -> ../../sdb2
lrwxrwxrwx 1 root root  9 Dec 26 02:10 wwn-0x5000c500a1b2c3d4 -> ../../sdc
lrwxrwxrwx 1 root root 10 Dec 26 02:10 wwn-0x5000c500a1b2c3d4-part2 -> ../../sdc2

Ce que ça signifie : Vous avez des poignées stables. Le /dev/sda2 manquant est probablement devenu /dev/sdb2 ou /dev/sdc2.
Décision : Identifiez quel WWN appartient au membre vdev manquant (via les labels ZFS ou les enregistrements antérieurs), puis rattachez en utilisant ce chemin by-id.

Task 3: Tie device nodes to WWN/serial/topology in one view

cr0x@server:~$ lsblk -o NAME,SIZE,MODEL,SERIAL,WWN,HCTL,TYPE,MOUNTPOINTS
NAME   SIZE MODEL              SERIAL          WWN                HCTL       TYPE MOUNTPOINTS
sdb  893.8G SAMSUNG MZ7KM960   S3Z1NX0K123456  0x5002538d4098abcd 1:0:0:0    disk
├─sdb1   1G                                      0x5002538d4098abcd 1:0:0:0  part
└─sdb2 892G                                      0x5002538d4098abcd 1:0:0:0  part
sdc  893.8G SAMSUNG MZ7KM960   S3Z1NX0K654321  0x5000c500a1b2c3d4  2:0:0:0    disk
├─sdc1   1G                                      0x5000c500a1b2c3d4 2:0:0:0  part
└─sdc2 892G                                      0x5000c500a1b2c3d4 2:0:0:0  part

Ce que ça signifie : Vous pouvez maintenant parler en identités (WWN/serial) et points physiques (HCTL).
Décision : Si vous avez un runbook ou des notes d’actifs mappant WWN à emplacement, c’est ici que vous arrêtez de deviner.

Task 4: Look for kernel-level storage errors fast

cr0x@server:~$ dmesg -T | egrep -i 'sd[a-z]|nvme|ata|sas|scsi|reset|I/O error|timed out' | tail -n 20
[Thu Dec 26 02:09:51 2025] sd 2:0:0:0: [sdc] tag#13 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_OK cmd_age=0s
[Thu Dec 26 02:09:51 2025] sd 2:0:0:0: [sdc] tag#13 Sense Key : Not Ready [current]
[Thu Dec 26 02:09:51 2025] sd 2:0:0:0: [sdc] tag#13 Add. Sense: Logical unit not ready, cause not reportable
[Thu Dec 26 02:09:52 2025] sd 2:0:0:0: [sdc] tag#21 timing out command, waited 180s
[Thu Dec 26 02:10:04 2025] scsi 2:0:0:0: rejecting I/O to offline device

Ce que ça signifie : Ce n’est pas « juste du nommage ». Le chemin disque/contrôleur est malade : temporisations et « offline device ».
Décision : Traitez comme matériel/connectivité. Vérifiez câblage/backplane/HBA, et planifiez un remplacement. Ne vous contentez pas de le remettre en ligne en espérant.

Task 5: Query ZFS events to see recent device changes

cr0x@server:~$ sudo zpool events -v | tail -n 25
TIME                           CLASS
Dec 26 02:10:06.912726000      resource.fs.zfs.statechange
  pool = tank
  vdev_guid = 11801824156334312345
  vdev_path = /dev/sda2
  vdev_state = UNAVAIL
  vdev_ashift = 12
Dec 26 02:10:07.102938000      resource.fs.zfs.statechange
  pool = tank
  vdev_guid = 9938450195345123456
  vdev_path = /dev/disk/by-id/wwn-0x5000c500a1b2c3d4-part2
  vdev_state = ONLINE
  vdev_ashift = 12

Ce que ça signifie : ZFS croit que /dev/sda2 était un vrai chemin vdev. Vous apprenez aussi ashift (important lors d’un remplacement).
Décision : Si vous prévoyez un replace, faites correspondre ashift. Utilisez aussi ces événements pour la chronologie d’incident ; ils sont souvent plus clairs que le bruit de syslog.

Task 6: Locate the missing vdev by GUID in on-disk labels

cr0x@server:~$ sudo zdb -l /dev/disk/by-id/wwn-0x5002538d4098abcd | sed -n '1,40p'
------------------------------------
LABEL 0
------------------------------------
    version: 5000
    name: 'tank'
    state: 0
    txg: 1923481
    pool_guid: 8012456789012345678
    vdev_tree:
        type: 'disk'
        id: 0
        guid: 11801824156334312345
        path: '/dev/sda2'
        phys_path: 'pci-0000:3b:00.0-sas-0x5000c500d00dbeef-lun-0'

Ce que ça signifie : Vous avez trouvé le disque que ZFS considère comme /dev/sda2. Le label enregistre même l’ancien chemin.
Décision : Ce disque est le membre manquant. Vous pouvez maintenant le rattacher sous un chemin stable sans deviner quel sdX il est aujourd’hui.

Task 7: Replace a device with itself to update the path to by-id

cr0x@server:~$ sudo zpool replace tank /dev/sda2 /dev/disk/by-id/wwn-0x5002538d4098abcd-part2
invalid vdev specification
use '-f' to override the following errors:
/dev/disk/by-id/wwn-0x5002538d4098abcd-part2 is part of active pool 'tank'

Ce que ça signifie : ZFS vous protège d’une opération ambiguë. Vous « remplacez » avec un périphérique déjà dans le pool.
Décision : Utilisez -f intentionnellement lors de l’astuce « replace-with-self » pour réécrire le chemin stocké vers le symlink stable.

cr0x@server:~$ sudo zpool replace -f tank /dev/sda2 /dev/disk/by-id/wwn-0x5002538d4098abcd-part2

Ce que ça signifie : Pas de nouvelle, bonne nouvelle. ZFS a accepté la nouvelle correspondance de chemin.
Décision : Relancez zpool status -P et confirmez que le pool référence désormais des entrées by-id partout.

Task 8: Bring a device online after transient loss

cr0x@server:~$ sudo zpool online tank /dev/disk/by-id/wwn-0x5000c500a1b2c3d4-part2
bringing device online

Ce que ça signifie : ZFS va tenter de reprendre les I/O. Si le chemin sous-jacent échoue encore, il tombera de nouveau.
Décision : Si le disque revient régulièrement offline, cessez de le traiter comme transitoire. Escaladez au matériel et planifiez un remplacement.

Task 9: Watch resilver progress like you mean it

cr0x@server:~$ sudo zpool status -P tank
  pool: tank
 state: DEGRADED
status: One or more devices is currently being resilvered.
config:

        NAME                                              STATE     READ WRITE CKSUM
        tank                                              DEGRADED     0     0     0
          mirror-0                                        DEGRADED     0     0     0
            /dev/disk/by-id/wwn-0x5002538d4098abcd-part2  ONLINE       0     0     0  (resilvering)
            /dev/disk/by-id/wwn-0x5000c500a1b2c3d4-part2  ONLINE       0     0     0

scan: resilver in progress since Thu Dec 26 02:14:03 2025
        128G / 892G scanned at 1.12G/s, 6.5G / 892G issued at 58.1M/s, 0% done, 04:14:23 to go

Ce que ça signifie : Issued est ce qui est réellement écrit. Si scanned est rapide mais issued est lent, vous êtes limité par les écritures, pas par les lectures.
Décision : Si le temps de resilver est énorme, envisagez d’alléger la charge, de vérifier les disques SMR, ou d’investiguer un throttling du contrôleur.

Task 10: Confirm that every vdev now uses stable paths

cr0x@server:~$ sudo zpool status -P | egrep '/dev/(sd|vd|xvd)'

Ce que ça signifie : L’absence de sortie est l’objectif : cela veut dire que vous ne référencez pas de nœuds éphémères.
Décision : Si vous voyez encore /dev/sd*, planifiez une maintenance contrôlée pour les réécrire via replace-with-self.

Task 11: Identify whether you’re accidentally using a single path in a multipath setup

cr0x@server:~$ lsblk -o NAME,TYPE,SIZE,WWN,PKNAME | egrep 'mpath|dm-|sd[a-z] '
sda  disk  1.8T 0x600508b1001c2d3e4f5a6b7c8d9e0001
dm-2 mpath 1.8T 0x600508b1001c2d3e4f5a6b7c8d9e0001
sdb  disk  1.8T 0x600508b1001c2d3e4f5a6b7c8d9e0001

Ce que ça signifie : Le même WWN apparaît sur plusieurs nœuds sd* (chemins différents), et aussi sur dm-2 comme périphérique multipath.
Décision : Pour ZFS en multipath, vous voulez généralement le périphérique mapper consolidé (ex. /dev/mapper/mpath*) ou un chemin DM cohérent,
pas une des voies brutes /dev/sd*. Le mélange est la cause de l’intermittence « périphérique retiré ».

Task 12: Show udev properties for a specific disk (why did by-id change?)

cr0x@server:~$ udevadm info --query=property --name=/dev/sdb | egrep 'ID_SERIAL=|ID_WWN=|ID_MODEL=|ID_PATH='
ID_MODEL=SAMSUNG_MZ7KM960HAHP-00005
ID_SERIAL=SAMSUNG_MZ7KM960HAHP-00005_S3Z1NX0K123456
ID_WWN=0x5002538d4098abcd
ID_PATH=pci-0000:3b:00.0-sas-0x5000c500d00dbeef-lun-0

Ce que ça signifie : udev vous indique le WWN et le chemin physique. Si ID_WWN est absent, vous êtes peut‑être derrière un bridge qui ne le rapporte pas.
Décision : Si le WWN est manquant, utilisez l’entrée by-id la plus stable disponible, et vérifiez l’unicité sur tous les disques.

Task 13: Verify partition tables and ensure you’re using the correct partition

cr0x@server:~$ sudo sgdisk -p /dev/disk/by-id/wwn-0x5002538d4098abcd
Disk /dev/disk/by-id/wwn-0x5002538d4098abcd: 1875385008 sectors, 894.3 GiB
Sector size (logical/physical): 512/4096 bytes
Disk identifier (GUID): 7A2B2C0D-9D2A-4B4A-8C31-2E1DA1A0C9B8
Partition table holds up to 128 entries
Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         2099199   1024.0 MiB  EF00  EFI System
   2         2099200      1875384319   893.3 GiB   BF01  ZFS

Ce que ça signifie : Vous pouvez confirmer quelle partition est le membre ZFS (ici, code de partition BF01).
Décision : Si vous pointez par erreur ZFS sur le disque entier alors que votre standard est des partitions (ou l’inverse), arrêtez‑vous et corrigez avant de remplacer.

Task 14: Import a pool when paths changed (safe mode first)

cr0x@server:~$ sudo zpool import
   pool: tank
     id: 8012456789012345678
  state: DEGRADED
 action: The pool can be imported despite missing or damaged devices.
 config:

        tank                                      DEGRADED
          mirror-0                                DEGRADED
            11801824156334312345                  UNAVAIL  cannot open
            wwn-0x5000c500a1b2c3d4-part2           ONLINE

Ce que ça signifie : ZFS peut voir le pool en lisant les labels, même si un vdev est manquant. Notez qu’il affiche un GUID au lieu d’un chemin pour le chemin manquant.
Décision : Importez en lecture seule si vous n’êtes pas sûr de regarder les bons disques, surtout dans des environnements de stockage partagés.

cr0x@server:~$ sudo zpool import -o readonly=on -d /dev/disk/by-id tank
cannot import 'tank': one or more devices is currently unavailable

Ce que ça signifie : Même en scannant explicitement by-id, quelque chose manque suffisamment pour bloquer l’import (la politique dépend de la topologie vdev).
Décision : N’importez pas de force sans comprendre la redondance. Trouvez le périphérique manquant via câblage/logs HBA ou confirmez que vous avez des répliques suffisantes.

Trois mini-récits d’entreprise tirés du terrain

Mini-récit 1 : L’incident causé par une mauvaise hypothèse

Une entreprise de taille moyenne gérait une plateforme VM sur quelques serveurs de stockage ZFS. Rien d’exotique : étagères SAS, vdevs en miroir, monitoring décent.
Le pool avait été créé pendant un « week-end de migration urgente », ce qui est souvent la source de la dette technique. Les vdevs avaient été ajoutés en utilisant /dev/sdX.

Des mois plus tard, ils ont ajouté un nouveau HBA et déplacé un câble d’étagère pour ranger le rack. Le redémarrage suivant est arrivé avec un pool dégradé et un membre de vdev « manquant ».
L’ingénieur d’astreinte a vu /dev/sdc manquant et a supposé que c’était « le troisième disque dans ce châssis », parce que les humains aiment penser en ordres.
Ils ont retiré ce qu’ils croyaient être le bon disque, l’ont remplacé, et ont lancé zpool replace avec le nouveau /dev/sdc.

Le système a accepté la commande. Bien sûr : /dev/sdc existait. Il n’était juste pas le disque qu’ils pensaient. Le « disque manquant » était toujours présent,
renommé en /dev/sdf après le changement de contrôleur. Pendant ce temps, ils avaient physiquement retiré un côté de miroir parfaitement sain et l’avaient remplacé par un disque vierge.
Un bref moment, le resilver a démarré tandis que le disque original restant supportait seul le vdev.

Le rebondissement suivant était prévisible et cruel : pendant le resilver, le disque original restant a lancé des erreurs de lecture. Vieillesse, secteurs latents, peu importe.
Maintenant, la seule copie bonne de certains blocs était sur le disque retiré. Le résultat n’a pas été une perte totale du pool, mais des images VM corrompues et une semaine de nettoyage.
Le postmortem a été franc : le déclencheur n’était pas une « panne disque », c’était « nous avons traité /dev/sdX comme une identité ».

Ils ont reconstruit la pratique opérationnelle autour du nommage WWN et ajouté une règle : personne ne touche à un chariot tant que le WWN affiché sur la console ne correspond pas au WWN sur l’étiquette physique.
Ça a ralenti les remplacements de cinq minutes. Ça les a sauvés d’eux‑mêmes pour toujours.

Mini-récit 2 : L’optimisation qui s’est retournée contre eux

Un autre lieu avait un ingénieur qui aimait les systèmes ordonnés. Il voulait que les noms vdev ZFS reflètent les numéros de slot physiques, alors il a standardisé sur /dev/disk/by-path.
C’était joli dans zpool status : on pouvait pointer une lampe torche vers le rack et trouver le disque rapidement.

Puis l’approvisionnement a remplacé le HBA SAS par un modèle plus récent parce que l’ancien était en « fin de vie ». Même fournisseur, même type de câble, mêmes étagères. L’équipe matériel a fait la mise à niveau.
Soudain, chaque symlink by-path a changé parce que les adresses PCI et l’énumération de l’expander SAS ont changé. Rien n’était faux avec les disques. Les « adresses » avaient changé.

L’import ZFS a commencé à échouer de façon intermittente en early boot parce que l’initramfs n’avait pas les règles udev mises à jour et parce que ces noms by-path n’étaient pas créés encore.
Les opérations ont essayé de colmater avec des pauses dans les scripts de démarrage. Ce n’est pas de l’ingénierie ; c’est de la superstition.

Ils ont finalement migré vers by-id basé sur WWN pour l’appartenance au pool et ont gardé by-path seulement pour des outils de cartographie humaine. L’« optimisation » visait la lisibilité dans ZFS,
mais elle avait transformé la config du pool en otage de la topologie du bus. Super pour des schémas ; catastrophique pour la fiabilité.

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une grande équipe d’entreprise gérait des pools ZFS pour les artefacts de build et les images de conteneurs. L’environnement était volontairement ennuyeux : vdevs en miroir, hot spares,
et une norme écrite : tous les pools utilisent des noms by-id basés sur WWN, partitions uniquement, et chaque remplacement inclut un scrub après le resilver.
Personne n’aimait ça. C’était du process.

Un week-end, un événement d’alimentation a fait rebondir un rack. Après le redémarrage, un serveur est revenu avec un pool dégradé et deux disques montrant des comportements étranges dans les logs du noyau.
L’astreinte a pu immédiatement identifier quels disques physiques étaient impliqués parce que leur runbook stockait les WWN et le mapping des emplacements dans l’enceinte.
Ils n’ont pas deviné. Ils n’ont pas « essayé quelques commandes ». Ils ont suivi la checklist.

Un disque était vraiment mort. L’autre était sain mais s’était réénuméré. Parce que le pool utilisait des chemins WWN stables, ZFS ne s’est pas embrouillé.
La seule action nécessaire a été de remplacer le disque mort et de laisser résilver. Le système a continué à servir tout le temps avec des performances prévisibles.

La victoire discrète était que rien de surprenant ne s’est produit. La direction n’en a jamais entendu parler. C’est le but d’une pratique ennuyeuse : des incidents qui n’ont jamais besoin de réunions.

Migrer un pool existant vers des chemins stables (sans drame)

Si vous avez créé votre pool avec /dev/sdX, vous pouvez le corriger sans reconstruire. La technique est simple : remplacez chaque membre vdev
par lui‑même, mais référencé via le chemin by-id stable. ZFS met à jour le chemin stocké, et la sortie future de zpool status arrêtera de mentir.

Règles avant de toucher la production

  • Confirmez l’unicité : Assurez‑vous que chaque nom by-id que vous prévoyez d’utiliser correspond à exactement un disque.
  • Privilégiez les partitions : Si vous standardisez sur -part2 (ou similaire), continuez ainsi. La cohérence compte pour l’automatisation et la sécurité.
  • Un disque à la fois : Surtout sur RAIDZ où une erreur est plus difficile à annuler, mais aussi sur les miroirs car la confiance humaine est traîtresse.
  • Capturez l’état : Sauvegardez la sortie de zpool status -P avant et après.

Une séquence de migration pratique

Commencez par lister le pool avec les chemins complets. Ensuite, pour chaque membre qui est un chemin brut /dev/sd*, trouvez le chemin by-id correspondant et lancez un replace forcé.
Exemple pour un membre mirror enregistré comme /dev/sda2 :

cr0x@server:~$ sudo zpool status -P tank
  pool: tank
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            /dev/sda2  ONLINE     0     0     0
            /dev/sdb2  ONLINE     0     0     0

Maintenant mappez /dev/sda2 à un ID stable :

cr0x@server:~$ readlink -f /dev/disk/by-id/wwn-0x5002538d4098abcd-part2
/dev/sda2

Puis remplacez‑par‑lui‑même pour réécrire le chemin stocké :

cr0x@server:~$ sudo zpool replace -f tank /dev/sda2 /dev/disk/by-id/wwn-0x5002538d4098abcd-part2

Répétez pour chaque membre /dev/sd* restant. Quand vous avez fini, zpool status -P devrait n’afficher que des chemins by-id.
Si vous voyez encore un /dev/sdX traîner, ne l’ignorez pas. C’est comme ça que les standards meurent : une exception à la fois.

Blague n°2 : Les pannes de stockage sont comme les soins dentaires — évitables avec un entretien régulier, mais les humains insistent pour apprendre par l’expérience.

Erreurs courantes : symptômes → cause → correctif

1) Le pool affiche UNAVAIL pour /dev/sdX après un redémarrage

Symptômes : zpool status affiche un /dev/sdX manquant ; les disques semblent « déplacés ».

Cause : Renumérotation des périphériques par le noyau ; ZFS a enregistré des noms instables.

Correctif : Identifiez le disque correct via WWN/serial (lsblk, zdb -l) et réécrivez les chemins avec zpool replace -f en utilisant by-id.

2) Remplacer un disque « fonctionne », mais le mauvais disque commence à resilver

Symptômes : Le resilver commence sur un disque que vous n’aviez pas l’intention d’utiliser ; un autre disque devient manquant ; panique.

Cause : Vous avez utilisé /dev/sdX et remplacé le mauvais nœud, ou vous avez mal identifié disque physique vs périphérique logique.

Correctif : Arrêtez. Confirmez les WWN et les labels ZFS. Utilisez zpool status -P, lsblk et zdb -l. Si nécessaire, offlinez le périphérique ciblé par erreur et réévaluez avant d’aller plus loin.

3) L’import du pool échoue en early boot mais fonctionne manuellement

Symptômes : Le système démarre sans le pool ; zpool import manuel réussit plus tard.

Cause : Les symlinks udev ne sont pas encore présents dans initramfs ; course entre la découverte des périphériques et le service d’import ; couches de chiffrement non ouvertes.

Correctif : Assurez-vous que l’initramfs inclut les règles udev et les modules nécessaires ; ordonnez les services pour que les blocs existent avant l’import ; pour les vdev chiffrés, assurez‑vous que zfs-load-key/cryptsetup s’exécutent avant import/mount.

4) Les périphériques font du flap ONLINE/OFFLINE sous charge

Symptômes : Les logs noyau montrent des temporisations ; ZFS marque le vdev offline ; il revient ; répétition.

Cause : Mauvais câble, backplane, problèmes de firmware HBA, ou utilisation d’un device single path dans un environnement multipath.

Correctif : Vérifiez dmesg, validez la configuration multipath, remplacez le câble/backplane suspect, mettez à jour le firmware si validé. Préférez les périphériques mapper multipath stables si le multipathing est utilisé.

5) Les noms by-id changent après une mise à jour de firmware

Symptômes : Le symlink by-id d’un disque semble différent qu’avant (formatage du serial, préfixe fournisseur).

Cause : Le firmware/les puces intermédiaires peuvent changer la manière dont les chaînes d’inquiry sont rapportées ; udev dérive les IDs depuis ces valeurs.

Correctif : Privilégiez les identifiants WWN/EUI ; validez avec udevadm info. Si les identifiants ont réellement changé, mettez à jour les chemins ZFS en utilisant replace-with-self vers la nouvelle forme stable.

6) Vous avez utilisé by-path, puis déplacé des câbles pendant la maintenance

Symptômes : Le pool démarre dégradé ; toutes les « adresses » semblent différentes ; les opérateurs insistent « les disques sont dans les mêmes emplacements ».

Cause : by-path encode la topologie de connexion ; déplacer un câble ou un HBA la change.

Correctif : Utilisez by-id/WWN pour l’appartenance au pool. Gardez by-path pour la cartographie/les workflows LED, pas comme identifiant autoritatif dans ZFS.

7) Le disque de remplacement rejoint le pool mais performe très mal pendant le resilver

Symptômes : Le resilver patine ; la latence explose ; le débit « issued » est faible.

Cause : Disque SMR dans une charge attendue pour CMR ; politique cache du contrôleur ; tailles de secteurs incompatibles provoquant read-modify-write ; charge de production élevée.

Correctif : Vérifiez le modèle de disque, la politique de cache et les tailles de secteurs. Envisagez d’utiliser une classe de disque connue pour le remplacement et limitez la charge pendant le resilver.

8) ZFS voit le disque mais refuse de l’utiliser sans -f

Symptômes : zpool replace se plaint que le périphérique fait partie d’un pool actif ou a des labels existants.

Cause : Vous remplacez par le même dispositif physique (réécriture de chemin), ou le disque a des labels ZFS obsolètes d’une membership précédente.

Correctif : Pour les réécritures de chemin, utilisez délibérément zpool replace -f. Pour des labels obsolètes sur un véritable disque de remplacement, effacez les labels avec zpool labelclear sur le bon périphérique avant de continuer.

Listes de contrôle / plan pas à pas

Checklist A: Créer un nouveau pool à la manière adulte

  1. Identifiez les disques par WWN/EUI/UUID, pas par /dev/sdX.
  2. Utilisez des partitions de manière cohérente (ex. -part2 pour le membre ZFS).
  3. Consignez une cartographie WWN → slot châssis/emplacement d’enceinte dans votre runbook.
  4. Créez le pool en utilisant les chemins /dev/disk/by-id/wwn-...-partN.
  5. Vérifiez immédiatement avec zpool status -P que ZFS a stocké des chemins by-id.
  6. Scrubez après la période de burn-in et périodiquement ; traitez les scrubs comme des alertes précoces, pas comme une hygiène optionnelle.

Checklist B: Après un reboot, le pool est dégradé avec un chemin manquant

  1. Exécutez zpool status -P et capturez la sortie.
  2. Vérifiez lsblk -o NAME,SIZE,MODEL,SERIAL,WWN,HCTL pour l’identité du disque manquant.
  3. Cherchez dans dmesg des erreurs I/O/temporisations. Si présentes, partez du principe matériel jusqu’à preuve du contraire.
  4. Utilisez zdb -l sur les disques by-id candidats pour faire correspondre le GUID/path du vdev.
  5. Si c’est un glissement de chemin : zpool replace -f vers le chemin by-id et confirmez le statut.
  6. Si c’est une perte matérielle : planifiez le remplacement ; ne « clear »z pas la physique.

Checklist C: Migration contrôlée de sdX vers by-id sur un pool existant

  1. Planifiez une fenêtre de maintenance si le pool est critique ; c’est sûr, mais la sécurité inclut du temps pour les humains.
  2. Exécutez zpool status -P et identifiez toutes les entrées /dev/sd*.
  3. Pour chacune, confirmez que le symlink by-id cible résout la même partition (readlink -f).
  4. Exécutez zpool replace -f pool oldpath new-by-id-path un périphérique à la fois.
  5. Après chaque changement, relancez zpool status -P et confirmez que le nouveau chemin est stocké.
  6. Quand c’est fini, greppez pour les références /dev/sd restantes et corrigez-les.
  7. Documentez la liste WWN dans votre runbook et, si vous en avez un, dans votre CMDB.

Checklist D: Remplacement de disque sans en faire un thriller

  1. Identifiez le disque défaillant par WWN dans la sortie ZFS, pas par la lettre du périphérique.
  2. Faites correspondre le WWN à un emplacement physique à l’aide de votre mapping d’enceinte.
  3. Mettez le membre vdev hors ligne (si encore ONLINE mais suspect) avant de retirer le matériel.
  4. Insérez le remplacement et confirmez que son WWN et sa taille correspondent aux attentes.
  5. Partitionnez de manière cohérente (ou répliquez la table de partitions d’un sibling sain).
  6. Exécutez zpool replace en utilisant des chemins by-id, puis surveillez le resilver jusqu’à la fin.
  7. Exécutez un scrub après le resilver et examinez sérieusement les éventuelles erreurs de checksum.

FAQ

1) Si ZFS stocke des labels sur le disque, pourquoi les chemins ont-ils de l’importance ?

Parce que les chemins sont ce que ZFS essaie en premier et ce sur quoi vous opérez. Les labels aident ZFS à trouver les pools, mais la chaîne de chemin est la réalité opérationnelle :
elle apparaît dans les alertes, les scripts et la prise de décision humaine. Faites‑la stable.

2) Dois‑je utiliser /dev/disk/by-id ou /dev/disk/by-uuid ?

Pour les vdevs ZFS, utilisez /dev/disk/by-id (style WWN/EUI/UUID). by-uuid réfère généralement aux UUID de système de fichiers ; ZFS n’est pas « un système de fichiers sur un block device » de cette manière.

3) Le vendor+serial dans by-id est‑il suffisant ?

Souvent oui, surtout pour des disques SAS/SATA d’entreprise. Mais WWN/EUI est généralement meilleur. Si vous êtes derrière des bridges USB ou des contrôleurs bas de gamme,
vendor+serial peut être peu fiable ou dupliqué. Validez l’unicité avant de lui faire confiance.

4) Qu’en est‑il du nommage NVMe ? /dev/nvme0n1 change aussi.

Exact. Le numéro de contrôleur NVMe peut bouger. Utilisez les entrées by-id comme nvme-eui.* ou nvme-uuid.* pour l’appartenance ZFS.
Traitez nvme0n1 comme sda : un surnom temporaire.

5) Puis‑je changer les chemins vdev sans faire de resilver ?

Remplacer un périphérique par lui‑même pour mettre à jour le chemin n’exige généralement pas de recopier les données si c’est vraiment le même périphérique.
ZFS peut quand même effectuer quelques vérifications. La clé est la justesse : confirmez l’identité d’abord (WWN + zdb -l).

6) Dois‑je utiliser des disques entiers ou des partitions pour les vdevs ZFS ?

Choisissez une norme et tenez‑vous y. Les partitions donnent une intention plus claire et réduisent les surprises avec des outils qui écrivent des métadonnées.
Les vdevs disque entier peuvent convenir dans des environnements contrôlés. Dans la réalité corporative mixte, les partitions sont généralement plus sûres.

7) Que signifie « cannot open » dans zpool status ?

Cela signifie que ZFS a tenté d’ouvrir le chemin qu’il a enregistré et a échoué. Cela peut être parce que le chemin n’existe plus (renommé),
que le périphérique a disparu, ou que les permissions/la disponibilité sont incorrectes durant le boot. L’étape suivante est de vérifier la visibilité OS (lsblk, dmesg, /dev/disk/by-id).

8) by-path est‑il parfois le bon choix pour ZFS ?

Rarement, et seulement si votre modèle opérationnel traite la connexion physique comme identité stable (backplane fixe, pas de mouvements de câbles, contrôleurs constants),
et que vous acceptez que la maintenance matérielle puisse réécrire les « identités ». La plupart des équipes n’opèrent pas ainsi. Utilisez WWN pour l’identité ; by-path pour la localisation.

9) Mon symlink by-id pointe vers un sdX différent après reboot. Est‑ce mauvais ?

C’est normal et c’est précisément pourquoi by-id existe. Le symlink suit l’identité du disque même quand l’attribution de lettres du noyau change.
ZFS devrait référencer le symlink, pas le sdX sous-jacent.

10) Puis‑je importer un pool en scannant uniquement /dev/disk/by-id ?

Oui, avec zpool import -d /dev/disk/by-id. Cela peut réduire l’ambiguïté sur des hôtes avec beaucoup de périphériques transitoires.
Ça ne résout pas le matériel manquant, mais ça aide à éviter d’importer le mauvais pool depuis le mauvais ensemble de disques.

Conclusion : prochaines étapes réalisables aujourd’hui

Retenez une chose : /dev/sdX n’est pas l’identité d’un disque. C’est l’humeur du noyau. ZFS se souviendra fidèlement de ce que vous lui dites,
ce qui est réconfortant jusqu’au moment où ça ne l’est plus.

Prochaines étapes pratiques :

  1. Exécutez zpool status -P sur chaque hôte et recherchez /dev/sd* (ou /dev/nvme*) dans les chemins vdev.
  2. Pour chaque entrée instable, mappez‑la à un symlink by-id basé WWN et effectuez un replace-with-self contrôlé avec zpool replace -f.
  3. Notez les mappings WWN → slot et gardez‑les accessibles pour l’astreinte.
  4. Mettez à jour vos standards de construction : les nouveaux pools ne sont créés qu’avec des chemins by-id/WWN, partitionnés de manière cohérente.
  5. Quand un pool se dégrade, suivez le playbook : identifier, vérifier, puis agir. Pas de devinettes. Pas de « clear and pray ».

Faites‑le une fois, correctement, et la prochaine fois qu’un shuffle de lettres de périphériques aura lieu, vous ne remarquerez presque rien. C’est le plus grand compliment que la production puisse offrir.

← Précédent
Ruée vers le métavers : comment « l’avenir » est devenu un mème du jour au lendemain
Suivant →
CPU Docker à 100 % : localiser le conteneur bruyant et le limiter correctement

Laisser un commentaire