La réplication échoue au pire moment : juste après que vous ayez promis à l’entreprise que le nœud DR était « entièrement synchronisé ». Puis apparaît une ligne rouge—replication failed—et soudain votre plan n’est plus qu’une capture d’écran dans une présentation.
Ceci est un guide pratique sur le terrain pour la réplication Proxmox VE lorsqu’elle se casse : ce qui se passe réellement sous le capot, comment diagnostiquer rapidement le goulet d’étranglement, et comment récupérer sans transformer une petite panne en un week-end prolongé.
Ce que la « réplication » Proxmox fait réellement (et ce qu’elle ne fait pas)
Dans Proxmox VE, la « réplication » n’est pas un miroir magique au niveau bloc pour tout ce que vous pouvez stocker. C’est un travail planifié qui—lorsque vous utilisez un stockage basé sur ZFS—crée des snapshots de disque VM et les transfère d’un nœud source vers un nœud cible en utilisant ZFS send/receive. Pour des pools ZFS locaux, c’est fiable, rapide et relativement ennuyeux. Quand ce n’est pas le cas, c’est parce qu’une des couches en dessous a cessé d’être ennuyeuse.
Sous le capot, une exécution typique de réplication ressemble à ceci :
- Proxmox coordonne le travail (par VM, selon le calendrier).
- Des snapshots ZFS sont créés pour les disques VM (datasets ou zvols selon votre configuration).
- Un envoi ZFS incrémental est effectué depuis le dernier snapshot réussi jusqu’au nouveau snapshot.
- Le flux passe par SSH vers le nœud cible.
- Le destinataire effectue un ZFS receive dans son dataset local.
- Proxmox enregistre le succès/l’échec et purge les anciens snapshots de réplication.
Ce que ce n’est pas :
- Ce n’est pas un mécanisme HA de basculement à lui seul. Il fournit des données à un nœud ; HA décide où exécuter la VM.
- Ce n’est pas une réplication continue. C’est périodique ; votre RPO est au mieux l’intervalle du planning, plus tout retard accumulé par le job.
- Ce n’est pas un substitut aux sauvegardes. La réplication réplique volontiers la corruption, la suppression et les « oups ».
- Ce n’est pas indépendant du stockage. Si vous n’utilisez pas un stockage compatible ZFS replication, vous êtes dans un univers de dépannage différent.
Une citation, parce qu’elle capture toujours la réalité en production : « L’espoir n’est pas une stratégie. » —idée paraphrasée souvent attribuée aux responsables fiabilité en exploitation.
Faits intéressants et contexte historique
- Les snapshots ZFS sont peu coûteux car ce sont des références méta, pas des copies complètes—jusqu’à ce que vous modifiiez des blocs, auquel cas l’utilisation d’espace augmente avec la divergence.
- zfs send/receive remonte aux premiers jours de ZFS sur Solaris et est devenu populaire car c’était une primitive de réplication streamable et portable avec cohérence intégrée.
- Les envois incrémentaux exigent un snapshot commun des deux côtés ; le supprimer d’un côté ou de l’autre casse la chaîne.
- La réplication Proxmox a toujours été « orientée stockage » : elle est construite autour de la sémantique ZFS, pas d’une copie générique de disque.
- SSH fait partie de votre pipeline de stockage pour la réplication ZFS ; la gestion des clés et les clés d’hôte peuvent casser le « stockage » d’une manière très non-stockage.
- Les resume tokens (fonction ZFS) peuvent permettre de reprendre des receives interrompus sans tout recommencer, mais ils créent aussi des états déroutants si vous ne les reconnaissez pas.
- ZFS peut détecter la corruption silencieuse avec des checksums, mais la réplication peut tout de même propager une corruption logique (comme la suppression propre d’un fichier de base de données).
- Les conventions de nommage des snapshots de réplication comptent car les outils attendent des motifs ; un nettoyage ad-hoc des snapshots peut faire paraître Proxmox « erroné » alors que ZFS est en réalité correct.
- La dérive du temps est un vieil ennemi : planification, ordre des jobs, corrélation des logs et même la validation de certificats sont tous rendus plus difficiles par un NTP négligé.
Playbook de diagnostic rapide (vérifier 1/2/3)
C’est l’ordre « arrêter de deviner ». Vous essayez d’identifier le goulet d’étranglement en quelques minutes, pas en lisant tous les logs depuis mardi dernier.
1) L’échec est-il dans le plan de contrôle (Proxmox) ou dans le plan de données (ZFS/SSH/réseau) ?
- Si le job ne démarre pas, ne parvient pas à résoudre les nœuds, ou signale des problèmes d’autorisation : plan de contrôle.
- Si le job démarre mais échoue en cours de flux, stagne, ou signale des erreurs ZFS receive : plan de données.
2) Confirmer l’état du job de réplication et la dernière erreur
- Consultez les logs des tâches et le journal du worker de réplication.
- Extraire l’erreur ZFS réelle (dataset exists, no space, invalid stream, etc.).
3) Valider les trois prérequis ennuyeux
- SSH fonctionne en non interactif depuis la source vers la cible pour root (ou l’utilisateur configuré).
- Les pools ZFS sont sains aux deux extrémités et ont de l’espace libre / headroom.
- Un snapshot commun existe pour la réplication incrémentale.
4) Si c’est lent/bloqué plutôt que « failed », isoler le débit
- Est-ce limité par le réseau ? (iperf3, erreurs d’interface, duplex, mismatch MTU)
- Est-ce limité par le disque ? (zpool iostat, contention txg sync)
- Est-ce limité par le CPU ? (compression, chiffrement, goulot monocœur)
Règle de décision : si vous ne pouvez pas nommer le goulet d’étranglement après 10 minutes, vous ne vérifiez pas les bonnes choses—vous lisez.
Pourquoi la réplication casse : les vrais modes de défaillance
1) Rupture de la chaîne de snapshots (le classique)
La réplication incrémentale ZFS dépend de : « send depuis le snapshot A vers le snapshot B ». Cela nécessite que le snapshot A existe à la fois sur la source et sur la cible. Si quelqu’un supprime des snapshots sur la cible pour « économiser de l’espace » ou exécute un prune agressif, votre prochain envoi incrémental échoue car il n’y a pas de base commune.
Ce mode d’échec est courant car ça ressemble à du ménage. Les gens voient des snapshots, supposent qu’ils sont « temporaires », et les nettoient. Ensuite la réplication exige le seul snapshot que vous venez de supprimer.
2) Incohérence du dataset cible (mauvais endroit, mauvais type, mauvais nom)
zfs receive est pointilleux dans le bon sens. Si le dataset de destination existe mais ne correspond pas aux attentes (mismatch de type : dataset vs zvol, propriétés incompatibles, sémantique de point de montage différente), receive peut échouer. Proxmox attend certaines structures de dataset sous un storage ID. Des modifications manuelles sur la cible peuvent faire que le prochain receive entre en collision avec la réalité.
3) Manque d’espace (et pas seulement l’espace vu par df -h)
ZFS a besoin de headroom pour le copy-on-write, les métadonnées et le comportement des transaction groups. Un pool à 95% d’utilisation n’est pas « correct ». C’est un pool qui prépare une petite opéra appelée ENOSPC.
Surveillez aussi :
- quota/reservation sur les datasets
- refquota/refreservation
- classes d’allocation spéciales (special vdev plein)
- comportement de slop space
4) Échecs SSH et gestion des clés (le stockage se fait agresser dans une ruelle)
La réplication utilise SSH. Cela signifie que les changements de clé d’hôte, les chiffres resserrés, les clés révoquées, de nouvelles politiques de jump-host, ou un mot de passe root rotatif peuvent casser la réplication avec des erreurs qui ressemblent à du « stockage » mais ne le sont pas.
Blague #1 : SSH est comme un badge d’entreprise—tout fonctionne jusqu’à ce que la Sécurité « améliore » ça cinq minutes avant votre fenêtre de maintenance.
5) Problèmes de chemin réseau : MTU, pertes, routage asymétrique
zfs send est un flux régulier. Si le réseau perd des paquets, vous verrez des blocages, des resets, ou des flux corrompus. Si le MTU est mal appairé (un côté en 9000, l’autre non), vous pouvez avoir de la fragmentation, des performances étranges, ou des échecs selon le chemin.
6) Problèmes de santé du pool : degraded, erreurs, I/O lente
Si un pool est dégradé, en resilvering, ou génère des erreurs de checksum, la réplication peut échouer ou devenir glaciaire. Proxmox rapportera « failed », mais le vrai problème est le sous-système de stockage qui suffoque.
7) Flags de fonctionnalités ZFS et incompatibilités de version
Si le pool cible ne supporte pas une fonctionnalité utilisée dans le stream d’envoi (ou si vous utilisez des envois raw/encryptés sans support correspondant), receive peut échouer. Cela compte lorsque vous répliquez entre des nœuds sur des versions ZFS différentes ou avec des ensembles de feature flags différents activés.
8) Problèmes de clé de chiffrement et envois/receives raw
Les datasets chiffrés peuvent se répliquer en tant que stream raw (données conservées chiffrées) ou en tant que stream déchiffré (requérant des clés). Si votre politique a changé en vol, ou si les clés ne sont pas chargées sur la cible quand nécessaire, vous verrez des erreurs du type « cannot mount » ou « key not loaded ».
9) Ordonnanceur et contention de verrous
Les jobs de réplication peuvent entrer en conflit avec des sauvegardes, des opérations intensives en snapshots, un scrub/resilver, ou d’autres pics d’I/O. Parfois l’échec n’est qu’un timeout ou un problème de verrou. Parfois c’est un simple « trop de jobs en même temps » déguisé en complexité.
10) État de receive corrompu ou incomplet (resume tokens, datasets partiels)
Un receive interrompu peut laisser un état partiel. ZFS moderne peut émettre un resume token pour que vous puissiez continuer. Mais si le receive a été interrompu et que quelqu’un a ensuite « réparé » manuellement en supprimant des snapshots/datasets, vous pouvez aboutir à un enchevêtrement qui nécessite un nettoyage soigné.
Tâches pratiques : commandes, sorties et décisions
Ce sont des tâches réelles que vous pouvez exécuter sur des nœuds Proxmox. Chacune inclut : commande, sortie d’exemple, ce que cela signifie, et la décision que vous prenez.
Task 1: Confirm replication jobs and last status
cr0x@server:~$ pvesr status
JobID Guest Target Status Last Sync
local-zfs:101 101 pve02 ok 2025-12-26 09:10:02
local-zfs:102 102 pve02 failed 2025-12-26 08:55:14
Signification : Le job de la VM 102 a échoué ; vous disposez d’un horodatage pour corrélation.
Décision : Récupérez le log de tâche spécifique pour cette fenêtre temporelle et cet ID VM/job avant de toucher quoi que ce soit.
Task 2: Read the Proxmox task log for the failed replication
cr0x@server:~$ grep -R "local-zfs:102" /var/log/pve/tasks/active /var/log/pve/tasks/index 2>/dev/null | tail -n 5
/var/log/pve/tasks/index:UPID:pve01:0000A3F1:0B7C9E2A:676D22E2:pvesr:local-zfs:102:root@pam:
cr0x@server:~$ cat /var/log/pve/tasks/UPID:pve01:0000A3F1:0B7C9E2A:676D22E2:pvesr:local-zfs:102:root@pam:
starting replication job 'local-zfs:102'
command: /usr/bin/ssh -o BatchMode=yes pve02 -- zfs receive -o readonly=on -u -F rpool/replica/vm-102-disk-0
cannot receive incremental stream: most recent snapshot of rpool/replica/vm-102-disk-0 does not match incremental source
TASK ERROR: command 'ssh ... zfs receive ...' failed: exit code 1
Signification : Mismatch de snapshot incrémental. Quelqu’un a supprimé ou modifié des snapshots d’un côté, ou le dataset a divergé.
Décision : Vérifiez les snapshots des deux côtés ; prévoyez un nouvel envoi complet (ou un rebase) plutôt que des retries aveugles.
Task 3: Inspect snapshots on the source dataset
cr0x@server:~$ zfs list -t snapshot -o name,creation -s creation rpool/data/vm-102-disk-0 | tail -n 8
rpool/data/vm-102-disk-0@replicate_2025-12-26_08-00-01 Fri Dec 26 08:00 2025
rpool/data/vm-102-disk-0@replicate_2025-12-26_08-30-01 Fri Dec 26 08:30 2025
rpool/data/vm-102-disk-0@replicate_2025-12-26_08-45-01 Fri Dec 26 08:45 2025
rpool/data/vm-102-disk-0@replicate_2025-12-26_09-00-01 Fri Dec 26 09:00 2025
Signification : La source a des snapshots de réplication qui continuent. Bien.
Décision : Comparez avec la cible. Si la cible manque le snapshot de base, vous aurez besoin d’un re-seed complet ou d’un restore du snapshot correspondant.
Task 4: Inspect snapshots on the target dataset
cr0x@server:~$ ssh pve02 -- zfs list -t snapshot -o name,creation -s creation rpool/replica/vm-102-disk-0 | tail -n 8
rpool/replica/vm-102-disk-0@replicate_2025-12-26_07-30-01 Fri Dec 26 07:30 2025
rpool/replica/vm-102-disk-0@replicate_2025-12-26_08-00-01 Fri Dec 26 08:00 2025
Signification : La cible manque des snapshots plus récents que la source attend comme base pour les incrémentaux (ou le job attend un snapshot plus récent).
Décision : Déterminez le dernier snapshot commun et si l’état enregistré par Proxmox correspond à la réalité. Si l’état est incohérent, re-seed.
Task 5: Verify SSH non-interactive access and host key sanity
cr0x@server:~$ ssh -o BatchMode=yes -o ConnectTimeout=5 pve02 -- "echo ok && hostname"
ok
pve02
Signification : SSH fonctionne sans prompt. Cela élimine la classe d’échecs « il attend un mot de passe/confirmation de clé d’hôte ».
Décision : Si cela échoue, réparez SSH d’abord. Ne touchez pas à ZFS tant que la connectivité du plan de contrôle n’est pas propre.
Task 6: Check pool health on both nodes
cr0x@server:~$ zpool status -x
all pools are healthy
cr0x@server:~$ ssh pve02 -- zpool status -x
all pools are healthy
Signification : Pas d’erreurs évidentes de pool.
Décision : Si vous voyez « DEGRADED », « too many errors », ou un resilvering en cours, traitez cela comme un incident stockage d’abord ; la réplication est un symptôme.
Task 7: Check free space and dataset quotas (the ZFS way)
cr0x@server:~$ zfs list -o name,used,avail,refer,mountpoint rpool | head -n 5
NAME USED AVAIL REFER MOUNTPOINT
rpool 3.21T 620G 192K /rpool
cr0x@server:~$ ssh pve02 -- zfs list -o name,used,avail,refer,mountpoint rpool | head -n 5
NAME USED AVAIL REFER MOUNTPOINT
rpool 3.79T 110G 192K /rpool
Signification : La cible n’a que 110G disponibles. C’est limite et risqué.
Décision : Si la cible est serrée, arrêtez d’essayer de « forcer » la réplication. Libérez de l’espace ou étendez le pool avant le re-seed ; sinon vous créerez des receives partiels et une prolifération de snapshots.
Task 8: Identify if the target has a resume token (interrupted receive)
cr0x@server:~$ ssh pve02 -- zfs get -H -o name,property,value receive_resume_token rpool/replica/vm-102-disk-0
rpool/replica/vm-102-disk-0 receive_resume_token -
Signification : Pas de resume token. La cible n’attend pas la reprise d’un flux partiel.
Décision : Si vous voyez une longue valeur de token, décidez de reprendre (préférable) ou d’abandonner/rollback (plus risqué) selon la politique et le temps.
Task 9: Run a manual dry-run of incremental send size (capacity planning)
cr0x@server:~$ zfs send -nPv -i rpool/data/vm-102-disk-0@replicate_2025-12-26_08-00-01 rpool/data/vm-102-disk-0@replicate_2025-12-26_09-00-01
send from @replicate_2025-12-26_08-00-01 to rpool/data/vm-102-disk-0@replicate_2025-12-26_09-00-01 estimated size is 18.4G
total estimated size is 18.4G
Signification : Le delta est d’environ 18.4G. Utile pour décider si la bande passante et l’espace cible sont adéquats.
Décision : Si le delta estimé est énorme, planifiez la réplication en dehors des heures de pointe ou augmentez l’intervalle ; de gros deltas signifient souvent que votre planning est trop espacé ou que des jobs échouent répétitivement.
Task 10: Measure network throughput quickly
cr0x@server:~$ iperf3 -c pve02 -t 10
Connecting to host pve02, port 5201
[ 5] 0.00-10.00 sec 8.76 GBytes 7.52 Gbits/sec 0 sender
[ 5] 0.00-10.00 sec 8.75 GBytes 7.52 Gbits/sec receiver
Signification : ~7.5 Gbit/s effectif. Pas parfait pour du 10G, mais probablement correct sauf si vos deltas sont énormes.
Décision : Si vous voyez 200–800 Mbit/s sur un lien 10G, arrêtez de blâmer ZFS. Vérifiez MTU, erreurs, routage et congestion.
Task 11: Inspect interface errors and MTU
cr0x@server:~$ ip -s link show dev bond0
2: bond0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc noqueue state UP mode DEFAULT group default qlen 1000
RX: bytes packets errors dropped missed mcast
91234567890 81234567 0 0 0 0
TX: bytes packets errors dropped carrier collsns
82345678901 72345678 0 0 0 0
cr0x@server:~$ ssh pve02 -- ip link show dev bond0 | head -n 2
2: bond0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
Signification : Mismatch de MTU. Cela peut rendre la réplication lente ou fragile selon le chemin.
Décision : Standardisez le MTU de bout en bout (y compris les switches). Ne faites pas de « half-jumbo » et n’espérez pas que ça marche.
Task 12: Check Proxmox and system logs around the failure
cr0x@server:~$ journalctl -u pvedaemon -u pveproxy -u pvescheduler --since "2025-12-26 08:45" --until "2025-12-26 09:05" | tail -n 30
Dec 26 08:55:14 pve01 pvescheduler[1123]: starting replication job local-zfs:102
Dec 26 08:55:18 pve01 pvedaemon[1109]: VM 102: replication job failed: exit code 1
Signification : Confirme l’horodatage et que c’est un échec au niveau du job, pas un glitch d’UI.
Décision : Si vous voyez des retries répétés, des timeouts, ou des jobs qui se chevauchent, vous devrez peut-être ajuster les plannings ou la concurrence.
Task 13: Validate the target dataset exists and is the expected type
cr0x@server:~$ ssh pve02 -- zfs list -o name,type,volsize,used,avail rpool/replica/vm-102-disk-0
NAME TYPE VOLSIZE USED AVAIL
rpool/replica/vm-102-disk-0 volume 128G 91G 110G
Signification : La cible est un zvol (« volume »). C’est cohérent avec des disques VM stockés en zvols.
Décision : Si le type est « filesystem » mais que vous attendez « volume », arrêtez et corrigez la disposition des datasets—forcer des receives dans le mauvais type est une façon de créer des désastres créatifs.
Task 14: Perform a controlled full re-seed (manual ZFS send/receive)
cr0x@server:~$ zfs snapshot rpool/data/vm-102-disk-0@replicate_reseed_2025-12-26_09-30
cr0x@server:~$ zfs send -Pv rpool/data/vm-102-disk-0@replicate_reseed_2025-12-26_09-30 | ssh pve02 -- zfs receive -u -F rpool/replica/vm-102-disk-0
send from rpool/data/vm-102-disk-0@replicate_reseed_2025-12-26_09-30 estimated size is 92.1G
total estimated size is 92.1G
TIME SENT SNAPSHOT
00:00:10 5.62G rpool/data/vm-102-disk-0@replicate_reseed_2025-12-26_09-30
Signification : Vous écrasez/replacez la cible pour l’aligner sur l’état du snapshot source, en utilisant -F pour forcer le rollback sur le dataset cible.
Décision : Utilisez -F uniquement quand vous êtes absolument certain que la cible est une réplique et n’héberge pas une VM en cours d’exécution. Si cette cible est « active », vous êtes sur le point de détruire l’état actif du disque.
Task 15: After re-seed, validate snapshot alignment and replication readiness
cr0x@server:~$ ssh pve02 -- zfs list -t snapshot -o name -s creation rpool/replica/vm-102-disk-0 | tail -n 3
rpool/replica/vm-102-disk-0@replicate_2025-12-26_08-00-01
rpool/replica/vm-102-disk-0@replicate_2025-12-26_09-00-01
rpool/replica/vm-102-disk-0@replicate_reseed_2025-12-26_09-30
Signification : La cible possède maintenant le snapshot de reseed et les précédents (selon ce qui a été envoyé). Vous disposez d’une base commune à nouveau.
Décision : Réactivez la réplication Proxmox pour cette VM/job et surveillez la prochaine exécution incrémentale. Si elle échoue encore, vous avez probablement un problème systématique (espace, prune incohérent, collisions de planning).
Task 16: Check for ZFS receive errors that hint at feature/encryption mismatch
cr0x@server:~$ ssh pve02 -- zpool get -H -o value feature@encryption rpool
active
Signification : Le pool cible supporte le flag de fonctionnalité encryption.
Décision : Si c’est « disabled » ou « inactive » tandis que la source utilise des datasets chiffrés, attendez-vous à des échecs de receive. Alignez le support des features ZFS ou ajustez le mode d’envoi.
Plans de récupération qui n’engendrent pas de nouveaux problèmes
Il y a deux grandes stratégies de récupération : réparer la chaîne ou re-seed. Le mauvais choix fait perdre du temps ; le choix imprudent risque une perte de données.
Plan A: Repair the snapshot chain (when you can)
Utilisez ceci lorsque la cible possède encore un snapshot commun, mais que l’état Proxmox est confus ou qu’un snapshot récent manque en raison d’un job interrompu.
- Confirmez le dernier snapshot commun présent des deux côtés.
- Ne supprimez rien « pour nettoyer » tant que vous ne savez pas ce que Proxmox attend.
- S’il y a un resume token, essayez de reprendre avant de re-seeder.
- Exécutez un send incrémental manuel en utilisant les noms explicites de snapshots pour prouver la viabilité.
L’avantage : bande passante et temps minimaux. L’inconvénient : cela demande de la discipline et une inspection soignée.
Plan B: Full re-seed (the blunt instrument that works)
Utilisez ceci lorsque la chaîne est cassée, que des snapshots ont été supprimés de façon incohérente, ou que le dataset cible a divergé.
- Assurez-vous que le dataset cible n’est pas utilisé par une VM en cours.
- Assurez-vous d’avoir suffisamment d’espace libre sur le pool cible (headroom réel).
- Prenez un nouveau snapshot « reseed » sur la source.
- Envoyez-le avec un receive forcé dans le dataset replica.
- Vérifiez les snapshots et réactivez la réplication planifiée.
Blague #2 : Un re-seed, c’est comme réinstaller votre OS pour réparer un pilote—efficace, légèrement embarrassant, et parfois le meilleur emploi du temps.
Quand arrêter et escalader
Arrêtez d’« essayer des choses » et escaladez en incident stockage si vous voyez :
- augmentation des erreurs de pool, erreurs de checksum, ou timeouts de devices répétés
- vitesse de réplication qui s’effondre pendant que
zpool iostatmontre de longs waits - le pool cible est presque plein et la fragmentation est élevée
- scrub/resilver en cours durant les fenêtres de réplication
Trois mini-histoires du monde corporate (anonymisées, plausibles, instructives)
Mini-histoire 1 : La mauvaise hypothèse qui a cassé le DR
L’organisation avait deux clusters Proxmox : une primaire et une « DR chaude ». La réplication tournait toutes les heures, et tout était vert depuis des mois. Le stockage était ZFS des deux côtés, générations hardware différentes, même schéma de noms de dataset. Tout le monde dormait tranquille.
Puis un nouvel ingénieur est arrivé et a fait ce que font les personnes consciencieuses : il a nettoyé ce qui ressemblait à de l’encombrement. Sur le nœud DR, il a vu un tas de snapshots nommés comme des artefacts de réplication et a supposé qu’ils étaient de vieux restes. Il les a purgés via un script rapide. Ça a libéré de l’espace. Les dashboards sont restés verts pendant un moment parce que rien n’a tourné immédiatement.
Le cycle de réplication suivant a échoué pour un tiers des VMs. Les erreurs disaient que les snapshots base incrémentaux ne correspondaient pas. L’ingénieur (essayant d’aider) a effacé plus de snapshots, pensant que Proxmox les recréerait. Voici l’hypothèse : « les snapshots de réplication sont jetables ». Ils ne le sont pas. Ils sont la chaîne.
La récupération n’était pas techniquement difficile—des re-seeds complets ont tout réglé—mais opérationnellement c’était moche. Plusieurs grosses VMs ont nécessité des envois complets sur un lien déjà chargé en heures ouvrées. L’équipe a dû limiter et reprogrammer les jobs, et le RPO DR a été mauvais pendant une journée. Le postmortem avait une leçon en gras : ne jamais purger manuellement des snapshots de réplication sauf si vous refaites volontairement un re-seed.
Mini-histoire 2 : L’optimisation qui s’est retournée contre eux
Une autre entreprise a voulu réduire le temps de réplication. Quelqu’un a remarqué que les réglages de compression différaient entre les pools. Ils voyaient aussi du headroom CPU sur les nœuds. Super : activer une compression agressive, augmenter la fréquence de réplication, et regarder les deltas rapetisser.
Ils ont modifié les propriétés ZFS sur les datasets source pour un mode de compression plus lourd. Sur le papier : moins de bande passante, réplication plus rapide, stockage plus petit. En pratique : pendant les heures de pointe, la contention CPU a frappé l’hyperviseur et a augmenté la latence VM. Pas beaucoup—juste assez pour rendre quelques services sensibles à la latence instables. Les graphiques réseau semblaient meilleurs, les graphiques stockage semblaient meilleurs, et les graphiques applicatifs semblaient pires.
Puis le retour de flamme s’est accentué : les jobs de réplication ont commencé à se chevaucher avec les jobs de backup. Les deux étaient intensifs en snapshots. Le système a passé plus de temps à snapshotter, prune et sync les txgs qu’à réellement déplacer des données. La réplication échouait de façon intermittente à cause de timeouts et de contention de verrous, ce qui augmentait les deltas, ce qui allongeait la réplication, ce qui causait plus de chevauchements. Une belle boucle de rétroaction.
La correction a été ennuyeuse : réduire la compression à un réglage équilibré, séparer fenêtres de réplication et de backup, et appliquer des limites de concurrence. Ils ont gardé une partie des gains, perdu la latence auto-infligée, et regagné de la prévisibilité—la vraie monnaie en exploitation.
Mini-histoire 3 : La pratique ennuyeuse qui a sauvé la mise
Une entreprise financière avait l’habitude qui semblait paranoïaque : chaque mois, ils effectuaient un test DR contrôlé pour un échantillon tournant de VMs. Pas un big bang. Juste un échantillon rotatif. Ils vérifiaient que les datasets répliqués étaient présents, que la VM pouvait booter, et que les contrôles applicatifs passaient.
Un mois, le test a échoué. La VM ne démarrainait pas sur le nœud DR car le dataset répliqué était présent mais incomplet. Le statut du job de réplication était « ok » pour la dernière exécution, mais un receive partiel antérieur avait laissé le dataset dans un état incohérent « a l’air présent ». Personne ne l’avait remarqué parce que la primaire allait bien et que les dashboards aiment mentir par omission.
Parce qu’ils testaient, ils l’ont trouvé avant que ça importe. Ils ont mis en pause les nouveaux jobs de réplication, corrigé la flakiness réseau sous-jacente, et re-seedé une poignée de disques affectés. L’incident est resté un ticket, pas une une.
C’est le secret : un drill DR récurrent et ennuyeux vous force à valider toute la chaîne—ZFS, SSH, état Proxmox, et bootabilité. Et ça vous oblige aussi à tenir des runbooks à jour, parce que vous les utilisez réellement.
Erreurs courantes (symptôme → cause racine → correctif)
1) « Most recent snapshot does not match incremental source »
Symptôme : La réplication échoue avec des erreurs de mismatch incrémental.
Cause racine : Chaîne de snapshots rompue—snapshots supprimés sur cible/source, ou dataset cible divergé à cause de modifications manuelles.
Correctif : Identifiez le dernier snapshot commun ; si aucun, effectuez un re-seed complet contrôlé avec un nouveau snapshot et un receive forcé. Arrêtez de supprimer des snapshots « jusqu’à ce que ça marche ».
2) « cannot receive: destination exists » ou « dataset already exists »
Symptôme : Receive échoue immédiatement.
Cause racine : Le dataset cible existe mais n’est pas la cible répliquée attendue, ou vos flags de receive ne correspondent pas (manque -F là où c’est approprié).
Correctif : Vérifiez le type de dataset et la structure prévue. Si c’est une vraie réplique, utilisez un zfs receive -F contrôlé. Sinon, renommez ou reconfigurez le layout de stockage pour éviter les collisions.
3) « No space left on device » pendant le receive
Symptôme : Le job échoue en cours de flux, laissant parfois un état partiel.
Cause racine : Pool/dataset cible plein, quotas, ou headroom insuffisant provoquant ENOSPC sous la pression du COW.
Correctif : Libérez de l’espace correctement (supprimez de vieilles sauvegardes, étendez le pool, ajustez les quotas). Ensuite nettoyez les receives partiels et re-seedez si nécessaire.
4) Réplication « bloquée » ou très lente, sans échouer
Symptôme : Les jobs s’exécutent pendant des heures, se mettent en file d’attente.
Cause racine : Contention I/O avec les backups/scrubs, effondrement du débit réseau, ou disques lents sur la cible.
Correctif : Mesurez : iperf3, zpool iostat, et erreurs d’interface. Séparez les fenêtres, limitez la concurrence, et évitez les scrubs pendant les pics de réplication.
5) « Host key verification failed » ou prompts de mot de passe dans les logs
Symptôme : Réplication échoue immédiatement ; les logs mentionnent SSH.
Cause racine : Changement de clés d’hôte, clés manquantes, ou BatchMode qui échoue.
Correctif : Réparez la confiance SSH et les clés. Confirmez que ssh -o BatchMode=yes fonctionne. Puis relancez la réplication.
6) Statut de réplication vert, mais échec de boot sur DR
Symptôme : Vous tentez de démarrer une VM répliquée et elle panique ou le disque est manquant/corrompu.
Cause racine : Dataset réplique incomplet, mal monté, clés de chiffrement non chargées, ou mauvais mapping de dataset reçu.
Correctif : Validez les propriétés du dataset, l’état des clés de chiffrement, et effectuez des tests de boot périodiques. En cas de doute, re-seedez les disques affectés.
Listes de contrôle / plan étape par étape
Checklist : Avant de tenter la récupération
- Confirmez quel nœud est source et quel nœud est cible pour le job défaillant.
- Confirmez que le dataset cible n’est pas utilisé activement par une VM en cours.
- Capturez le log d’échec (log de tâche + erreur ZFS exacte). Ne comptez pas sur la mémoire.
- Vérifiez la connectivité SSH en BatchMode.
- Vérifiez la santé des pools et l’espace libre des deux côtés.
- Listez les snapshots des deux côtés et localisez le dernier snapshot commun.
Étapes : Réparer la réplication incrémentale (préférée quand possible)
- Identifiez le dernier snapshot commun (orthographe exacte).
- Estimez la taille d’envoi avec
zfs send -nPv -i. - Exécutez un send/receive incrémental manuel pour valider que la chaîne fonctionne.
- Redémarrez le job de réplication Proxmox et surveillez la prochaine exécution.
- Après succès, révisez la rétention des snapshots pour que le snapshot base ne soit pas prématurément pruné.
Étapes : Re-seed complet (quand la chaîne est cassée)
- Stoppez ou mettez en pause le job de réplication (pour éviter une course).
- Assurez-vous que la cible a assez de headroom ; étendez ou nettoyez d’abord.
- Créez un nouveau snapshot « reseed » sur la source.
- Envoyez le snapshot complet à la cible avec receive forcé (
-F) seulement si c’est sûr. - Vérifiez que le snapshot cible existe et correspond.
- Réactivez la réplication Proxmox et surveillez.
Checklist : Après la récupération (ne pas sauter)
- Exécutez encore un cycle de réplication réussi pour la VM.
- Confirmez que l’espace du pool cible est stable (pas en tendance de remplissage).
- Confirmez que les plannings ne se chevauchent pas fortement avec backups/scrubs.
- Effectuez un test de boot DR pour au moins une VM récupérée si la politique le permet.
- Documentez la cause racine en un paragraphe compréhensible par un on-call fatigué.
FAQ
1) La réplication Proxmox est-elle la même chose qu’une sauvegarde ?
Non. La réplication conserve une copie nearline des disques VM sur un autre nœud, typiquement pour un basculement rapide. Les sauvegardes sont des archives ponctuelles conçues pour la restauration et la rétention longue. Vous voulez les deux.
2) Pourquoi la réplication échoue après que j’ai « nettoyé de vieux snapshots » ?
Parce que la réplication incrémentale exige un snapshot commun sur les deux nœuds. Supprimer des snapshots de réplication casse la chaîne. Si vous devez pruner, faites-le via les politiques Proxmox ou soyez prêt à re-seeder.
3) Puis-je cliquer sur « Retry » jusqu’à ce que ça marche ?
Vous pouvez, mais c’est comme transformer une rupture de chaîne en un backlog de file d’attente. Retry est acceptable après avoir corrigé la cause racine (SSH, espace, MTU). Si l’erreur indique un mismatch incrémental, les retries ne recréeront pas les snapshots manquants.
4) Quel est le correctif « gros marteau » le plus sûr ?
Un re-seed complet vers le dataset cible, exécuté délibérément : vérifiez que la cible n’est pas en cours d’utilisation, assurez l’espace, snapshottez la source, zfs send vers zfs receive -F. Le marteau est sûr quand vous savez exactement ce que vous écrasez.
5) Comment savoir si le réseau est le problème ?
Mesurez-le. Utilisez iperf3, vérifiez les erreurs d’interface avec ip -s link, et confirmez que le MTU correspond de bout en bout. Si le débit est faible et que des erreurs/paquets perdus existent, la réplication est innocente.
6) La compression ZFS aide-t-elle la réplication ?
Parfois. Elle peut réduire les octets envoyés, mais augmente l’utilisation CPU et peut amplifier la contention pendant les périodes chargées. Optimisez pour la prévisibilité d’abord, la vitesse ensuite.
7) Les datasets chiffrés peuvent-ils se répliquer proprement ?
Oui, mais vous devez aligner les attentes : un envoi raw chiffré garde les données chiffrées ; un envoi déchiffré nécessite les clés chargées et peut changer le comportement. Des features ZFS mismatched ou des clés manquantes casseront les receives.
8) Pourquoi la réplication affiche « ok » mais la réplique ne boote pas ?
Parce que « ok » signifie généralement que le dernier job a retourné le succès—pas que vous avez validé la bootabilité. Des datasets partiels, un mauvais mapping de destination, ou des problèmes de clés peuvent subsister. Testez le boot périodiquement.
9) Dois-je répliquer chaque VM aussi fréquemment que possible ?
Non. La réplication a un coût : snapshots, I/O, pruning, et contention de jobs. Classez les VMs par besoins RPO et par taille. Adaptez le planning à la réalité.
10) Quelle est la chose à automatiser en priorité ?
Alerter sur : échecs de réplication, pool cible >80% d’utilisation, augmentation des erreurs d’interface, et snapshots récents manquants sur la cible. Les humains sont bons pour réparer, mauvais pour remarquer une dérive lente.
Prochaines étapes à faire réellement
Si la réplication a échoué aujourd’hui, faites ceci dans l’ordre :
- Récupérez le log de tâche exact et extrayez la ligne d’erreur ZFS/SSH.
- Vérifiez SSH BatchMode et la santé des pools des deux côtés.
- Vérifiez le headroom cible et la présence des snapshots ; trouvez le dernier snapshot commun.
- Si la chaîne est intacte, réparez les incrémentaux. Si elle est cassée, re-seedez délibérément.
- Après la récupération, corrigez la politique qui a causé le problème : purge de snapshots, tendance d’espace, chevauchement d’horaires, mismatch MTU, ou gestion des clés.
L’objectif de la réplication n’est pas de rendre les dashboards verts. C’est de rendre l’échec ennuyeux. Quand la réplication casse, traitez-la comme n’importe quel autre pipeline de production : plan de contrôle d’abord, plan de données ensuite, et pas de « nettoyage » tant que vous n’avez pas prouvé ce qui manque réellement.