ZFS en images : pool, vdev, dataset, zvol, COW, checksum¶
ZFS est à la fois un gestionnaire de volumes et un système de fichiers : il remplace le contrôleur RAID, LVM et ext4 en une seule couche qui connaît chaque bloc et sait vérifier qu'il n'est pas corrompu. Après cette page, vous savez lire un zpool status et un zfs list et vous comprenez pourquoi ZFS exige un HBA et non un contrôleur RAID.
La pile ZFS en un schéma¶
flowchart TB
subgraph POOL["Pool tank"]
direction TB
V1["vdev mirror-0<br/>disque A + disque B"]
V2["vdev mirror-1<br/>disque C + disque D"]
end
POOL --> DS1["dataset tank/iso<br/>(système de fichiers)"]
POOL --> ZV1["zvol tank/vm-101-disk-0<br/>(périphérique bloc)"]
POOL --> DS2["dataset tank/subvol-102-disk-0<br/>(conteneur LXC)"]
ZV1 --> VM["VM 101 voit un disque /dev/sda"]
| Objet | Rôle | Équivalent VMware / classique | Commande pour le voir |
|---|---|---|---|
| Disque | Support physique, désigné par /dev/disk/by-id/ |
Disque derrière le contrôleur | ls -l /dev/disk/by-id/ |
| vdev | Groupe de disques avec sa redondance (mirror, RAIDZ, dRAID) | Groupe RAID | zpool status tank |
| Pool | Ensemble de vdevs ; les données sont réparties sur tous les vdevs | Datastore VMFS (côté capacité) | zpool list |
| Dataset | Système de fichiers ZFS, avec ses propriétés (compression, quota) | Dossier d'un datastore | zfs list -t filesystem |
| Zvol | Volume bloc ZFS, utilisé pour les disques de VM | Fichier VMDK | zfs list -t volume |
| Snapshot | Image figée d'un dataset ou zvol, instantanée | Snapshot de VM (sans fichier delta) | zfs list -t snapshot |
Sur Proxmox VE, le stockage de type ZFS (zfspool) crée un zvol par disque de VM (tank/vm-101-disk-0) et un dataset par volume de conteneur (tank/subvol-102-disk-0).
Règle d'or
La redondance existe au niveau du vdev, jamais au niveau du pool. Si un vdev entier est perdu, tout le pool est perdu. Un pool de deux mirrors survit à la perte d'un disque par mirror, pas à celle des deux disques d'un même mirror.
Copy-on-write : on n'écrase jamais¶
ZFS n'écrit jamais par-dessus un bloc en place. Il écrit la nouvelle version ailleurs, puis bascule le pointeur parent en une seule opération atomique.
flowchart LR
A["1. Bloc B1 en place<br/>pointé par la racine"] --> B["2. Nouvelle version B1'<br/>écrite dans un espace libre"]
B --> C["3. Pointeurs parents réécrits<br/>jusqu'à la racine (uberblock)"]
C --> D["4. B1 libéré,<br/>sauf si un snapshot le référence"]
Conséquences pratiques :
- Pas de fsck : après une coupure de courant, le pool est soit dans l'état d'avant, soit dans l'état d'après une transaction complète.
- Snapshots instantanés et gratuits à la création : un snapshot conserve simplement les anciens blocs au lieu de les libérer. Il grossit au fil des modifications.
- Fragmentation et besoin d'espace libre : ZFS a besoin de place pour écrire les nouvelles versions. Au-delà de 80 % de remplissage, les performances chutent (voir Sizing ZFS).
Checksums et auto-réparation¶
Chaque bloc a une somme de contrôle stockée dans son bloc parent, pas à côté de lui. ZFS détecte donc aussi une écriture fantôme ou un bloc lu au mauvais endroit.
flowchart TB
R["Lecture d'un bloc"] --> C{"Checksum correct ?"}
C -- oui --> OK["Donnée renvoyée à la VM"]
C -- non --> RED{"Copie saine disponible ?<br/>(mirror, parité RAIDZ)"}
RED -- oui --> FIX["Donnée saine renvoyée<br/>bloc défectueux réécrit<br/>compteur CKSUM +1"]
RED -- non --> ERR["Erreur remontée<br/>Permanent errors dans zpool status"]
Le scrub applique ce contrôle à tous les blocs du pool, y compris ceux qu'aucune VM ne lit jamais. Proxmox VE en planifie un par mois (voir Scrub, SMART, alertes ZED).
Ce que ZFS apporte et ce qu'il demande¶
| Apporte | Demande |
|---|---|
| Intégrité vérifiée de bout en bout | Un accès direct aux disques : HBA ou contrôleur en mode IT/HBA, pas de RAID matériel |
| Snapshots et clones instantanés | De la RAM pour le cache ARC (voir RAM et ARC) |
| Compression transparente (lz4, zstd) | De garder 20 % d'espace libre |
Réplication incrémentale entre nœuds (zfs send) |
Des disques de même taille dans un vdev |
| Pas de contrôleur propriétaire à remplacer | Une topologie choisie au départ : elle se modifie peu après coup |
Recommandations MSP¶
- Les architectures mono-nœud ZFS et ZFS répliqué 2 nœuds + QDevice reposent sur ce modèle. Le disque système (rpool) et le pool de VM (tank) sont séparés dès que le budget le permet.
- Les disques sont toujours désignés par leur identifiant
/dev/disk/by-id/. - Les snapshots ZFS ne remplacent pas PBS : ils vivent sur les mêmes disques que les données.
Pièges vus en support
- ZFS posé sur un volume de RAID matériel : ZFS ne voit qu'un disque, ne peut plus s'auto-réparer et le contrôleur masque les erreurs. Configuration non supportée par le MSP.
- Confondre « pool » et « vdev » : ajouter un disque seul à un pool redondant (
zpool add) crée un vdev sans redondance qui met tout le pool en danger. - Croire qu'un snapshot est une sauvegarde : la perte du pool emporte les snapshots.
- Laisser un pool à 95 % : écritures très lentes, voire impossibles, et suppression de fichiers elle-même difficile.
Testez-vous¶
-
Un pool contient deux vdevs mirror de deux disques. Combien de disques pouvez-vous perdre au maximum sans perdre de données, et à quelle condition ?
Réponse
Deux disques, à condition qu'ils appartiennent à deux mirrors différents. La perte des deux disques d'un même mirror détruit le vdev, donc le pool.
-
Quel objet ZFS Proxmox VE crée-t-il pour le disque d'une VM sur un stockage ZFS ?
Réponse
Un zvol, par exemple
tank/vm-101-disk-0, visible aveczfs list -t volume. -
Pourquoi un snapshot ZFS se crée-t-il instantanément ?
Réponse
Grâce au copy-on-write : le snapshot fige les pointeurs existants et empêche seulement la libération des anciens blocs. Aucune donnée n'est copiée à sa création.
-
La colonne CKSUM d'un disque passe à 3 dans un mirror, sans autre erreur. Les VM ont-elles reçu des données corrompues ?
Réponse
Non. ZFS a détecté trois blocs incorrects, a lu la copie saine sur l'autre disque et a réparé les blocs. Il faut tout de même chercher la cause : voir RB-07.