2. Faire vivre le cluster : migration, quorum, Corosync
Le cluster est formé et répond d'une seule voix. Cette section en montre la vie courante : déplacer des machines d'un nœud à l'autre, voir le quorum à l'œuvre sur un nœud isolé. Elle montre aussi comment lire la configuration de Corosync et de pmxcfs, et diagnostiquer une panne.
2.1 Migration de VMs entre nœuds
La migration est l'une des raisons principales de construire un cluster. Elle permet de déplacer une VM d'un nœud à l'autre, pour des raisons de maintenance, d'équilibrage de charge, ou en cas de panne imminente détectée.
La migration à chaud (live migration) déplace la VM sans l'arrêter. La mémoire vive est transférée en temps réel entre les deux nœuds, et la VM continue de fonctionner pendant toute l'opération.
Sur un stockage partagé (comme Ceph), seule la mémoire voyage. Sur un stockage local, c'est possible aussi avec l'option --with-local-disks, mais Proxmox copie alors les disques en même temps : c'est beaucoup plus long.
La migration à froid s'applique à une VM arrêtée : Proxmox déplace sa configuration et, si besoin, copie ses disques sur le nœud cible. C'est le comportement par défaut de qm migrate quand on ne demande pas --online.
Dans le Shell du nœud (interface web → votre nœud → Shell) :
# Migration à chaud — la VM 300 reste active pendant le déplacement vers pxe212
# Prerequis : un stockage partage — Ceph dans nos ateliers (atelier 5)
qm migrate 300 pxe212 --online
# Migration à froid — la VM doit être arrêtée d'abord (la VM 120 de l'atelier 2)
qm shutdown 120 # l'arrêter
qm migrate 120 pxe212 # puis la migrer
# Les conteneurs n'ont PAS de migration à chaud : --restart les arrête,
# les déplace et les redémarre, avec quelques secondes de coupure
pct migrate 200 pxe213 --restart
Sortie réelle d'une migration à chaud. La commande qm migrate 951 pxe211 --online est lancée depuis pxe212, sur une VM de test de 512 Mo sans disque, avec le réseau de migration par défaut :
2026-10-07 18:13:43 conntrack state migration not supported or disabled, active connections might get dropped
2026-10-07 18:13:44 starting migration of VM 951 to node 'pxe211' (10.59.1.11)
2026-10-07 18:13:44 starting VM 951 on remote node 'pxe211'
2026-10-07 18:13:45 start remote tunnel
2026-10-07 18:13:45 ssh tunnel ver 1
2026-10-07 18:13:45 starting online/live migration on unix:/run/qemu-server/951.migrate
2026-10-07 18:13:45 set migration capabilities
2026-10-07 18:13:45 migration downtime limit: 100 ms
2026-10-07 18:13:45 migration cachesize: 64.0 MiB
2026-10-07 18:13:45 set migration parameters
2026-10-07 18:13:45 start migrate command to unix:/run/qemu-server/951.migrate
2026-10-07 18:13:46 average migration speed: 528.8 MiB/s - downtime 2 ms
2026-10-07 18:13:46 migration completed, transferred 3.7 MiB VM-state
2026-10-07 18:13:46 migration status: completed
2026-10-07 18:13:48 migration finished successfully (duration 00:00:05)
La séquence se lit ligne à ligne. La première ligne prévient que l'état des connexions suivies par le nœud (conntrack) n'est pas transféré : des connexions actives de la VM peuvent être coupées.
Puis une VM « coquille » démarre sur le nœud cible et un tunnel s'ouvre entre les deux nœuds. La mémoire de la VM d'origine y est recopiée pendant qu'elle continue de tourner.
Les pages modifiées pendant la copie sont renvoyées, jusqu'à ce que le reste à transférer tienne dans la downtime limit — 100 ms. La VM est alors figée ce court instant (ici downtime 2 ms), les dernières pages passent, et elle repart sur le nœud cible.
Seules les pages de mémoire réellement utilisées voyagent. Cette VM de test, qui n'a démarré aucun système, n'en a transféré que 3,7 Mio.
Une VM Debian en service en transfère autant que sa mémoire occupée. Aucune ligne ne parle de disque : sur un stockage partagé, les deux nœuds voient déjà le même.
Et l'adresse entre parenthèses est celle par laquelle passe la migration. Ce n'est pas celle du réseau Corosync.
Par quel réseau passe la migration ? Par défaut, par l'adresse principale du nœud cible, celle de vmbr0 : le réseau d'administration.
Sur le lab, pendant l'atelier, avant tout réglage (atelier 2), le journal indiquait starting migration of VM 120 to node 'pxe212' (10.59.1.12), l'adresse vmbr0 du lab (10.<site>.<N>.12 chez vous). Le réseau Corosync (10.59.11.x) n'était pas utilisé.
On donne à la migration son propre réseau dans Datacenter → Options → Migration Settings. Sur le lab (atelier 5), avec migration: network=10.59.41.11/24,type=secure, le journal a changé dès la migration suivante.
Dans le Shell de pxe211 :
# Migration à chaud de la VM 300 vers pxe212 (atelier 5)
qm migrate 300 pxe212 --online
use dedicated network address for sending migration traffic (10.59.41.12)
starting migration of VM 300 to node 'pxe212' (10.59.41.12)
average migration speed: 2.0 GiB/s - downtime 16 ms
migration completed, transferred 552.6 MiB VM-state
Cette VM Debian en service a transféré 553 Mio de mémoire, contre 3,1 Mio pour la VM de test sans système.
La bascule a duré 16 ms. Aucun disque n'a voyagé : il est sur Ceph.
Et un disque local ? Une VM dont un disque est sur local-lvm refuse la migration à chaud sans option.
Sur le lab : can't live migrate attached local disks without with-local-disks option. Avec --with-local-disks, le disque est recopié pendant la migration, ce qui la rallonge d'autant.
Pourquoi pas de migration à chaud pour un conteneur ? Une VM, c'est un processus QEMU dont on sait copier la mémoire.
Un conteneur, ce sont des dizaines de processus du noyau de l'hôte, avec leurs fichiers ouverts et leurs connexions : rien qu'on puisse transporter tel quel vers un autre noyau. pct migrate --online répond donc par une erreur, et --restart est la seule migration « avec le conteneur en marche ».
La migration est également accessible depuis l'interface graphique : clic droit sur la VM → Migrate. L'interface propose automatiquement les nœuds disponibles dans le cluster et indique si une migration à chaud est possible selon le stockage utilisé.
2.2 Le quorum à l'épreuve : un nœud isolé
Le §1.1 a posé la règle : sans majorité, un nœud se bloque de lui-même. Voici ce qu'on observe sur le cluster monté.
Ce que voit un nœud qui a perdu le quorum. Sur le lab, en arrêtant Corosync sur pxe213 (systemctl stop corosync), puis en le relançant :
Dans le Shell de pxe213 :
systemctl stop corosync # couper Corosync sur ce nœud
pvecm status # le nœud ne parle plus à Corosync
touch /etc/pve/essai-lecture-seule # écrire dans /etc/pve
systemctl start corosync # retour à la normale
Résultat attendu :
Cluster information
-------------------
Name: cluster-tp
Config Version: 3
Transport: knet
Secure auth: on
Cannot initialize CMAP service
touch: cannot touch '/etc/pve/essai-lecture-seule': Permission denied
Pendant ce temps, sur pxe211, pvecm status affichait Nodes: 2, Total votes: 2, Quorate: Yes : la partition de deux nœuds continue. Le nœud isolé, lui, passe /etc/pve en lecture seule.
Après systemctl start corosync, il retrouve les trois voix et l'écriture. C'est le cas à trois nœuds du schéma du quorum (§1.1) : la majorité continue, le nœud isolé se fige.
Où voir le quorum sur votre cluster :
| Notion | Où la voir |
|---|---|
| L'état d'ensemble | Datacenter → Summary : bloc Status, Quorate: Yes, et le nombre de nœuds en ligne |
| Votes, quorum, partition | pvecm status : lignes Expected votes, Total votes, Quorum, Quorate |
| Les membres et leur voix | pvecm nodes ; Datacenter → Cluster |
| La configuration de Corosync | /etc/pve/corosync.conf (lecture seule ici : il ne s'édite pas à la main sur un nœud isolé) |
2.3 Corosync et pmxcfs sur le cluster monté
Le §1.1 a expliqué pourquoi Corosync a un réseau à lui et deux liens. Sur le cluster assemblé, on lit maintenant ce que pvecm a écrit : la configuration de Corosync, l'état de ses deux liens, ses ports, et le système de fichiers qu'il réplique.
corosync.conf ne s'édite jamais directement sur un nœud isolé. Le fichier vit dans /etc/pve/, un système de fichiers répliqué : toute modification se propage à l'ensemble du cluster. Et surtout, le champ config_version doit être incrémenté à chaque changement — c'est lui qui indique aux autres nœuds qu'une nouvelle version existe.
L'oublier laisse le cluster avec deux configurations divergentes, chacune se croyant à jour. Une erreur ici peut faire perdre le quorum à tout le cluster d'un coup ; la manipulation se fait toujours sur un cluster sain, jamais en pleine panne.
Dans le Shell du nœud (interface web → votre nœud → Shell) :
cat /etc/pve/corosync.conf # la configuration Corosync écrite par pvecm
Résultat attendu, sur pxe211 (cluster de 3 nœuds, deux liens) ; extrait, les blocs logging et quorum et les lignes secondaires de totem sont omis :
nodelist {
node {
name: pxe211
nodeid: 1
quorum_votes: 1
ring0_addr: 10.59.11.11
ring1_addr: 10.59.1.11
}
(pxe212 et pxe213 : le même bloc, nodeid 2 et 3, adresses en .12 et .13)
}
totem {
cluster_name: cluster-tp
config_version: 3
link_mode: passive
secauth: on
}
Chaque nœud a une adresse par lien : ring0_addr pour le Link 0 (vmbr1), ring1_addr pour le Link 1 (vmbr0). link_mode: passive : un seul lien sert à la fois, le plus prioritaire.
config_version: 3 : la création, puis deux jonctions. C'est ce numéro qu'il faut incrémenter à chaque modification manuelle.
Dans le Shell du nœud :
# État des liens Corosync vus par ce nœud
corosync-cfgtool -s
Résultat attendu sur pxe211 :
Local node ID 1, transport knet
LINK ID 0 udp
addr = 10.59.11.11
status:
nodeid: 1: localhost
nodeid: 2: connected
nodeid: 3: connected
LINK ID 1 udp
addr = 10.59.1.11
status:
nodeid: 1: localhost
nodeid: 2: connected
nodeid: 3: connected
Un bloc par lien, et pour chacun l'état vers chaque autre nœud. connected partout : les deux chemins fonctionnent.
Les ports, et ce qui doit passer entre les nœuds. Corosync écoute en UDP, un port par lien.
Dans le Shell du nœud :
ss -ulnp | grep corosync # les ports UDP ouverts par Corosync
Résultat attendu sur pxe211 :
UNCONN 0 0 10.59.11.11:5405 0.0.0.0:* users:(("corosync",pid=4355,fd=33))
UNCONN 0 0 10.59.1.11:5406 0.0.0.0:* users:(("corosync",pid=4355,fd=34))
5405 sur l'adresse du Link 0, 5406 sur celle du Link 1. Entre les nœuds doivent donc passer l'UDP de Corosync (5405 et suivants, un port par lien). Il faut aussi le SSH (TCP 22), que Proxmox utilise pour certaines opérations entre nœuds, comme la migration.
Sous le capot : pmxcfs. /etc/pve n'est pas un dossier ordinaire : c'est un système de fichiers en espace utilisateur (FUSE). Sa copie de référence est une petite base SQLite, /var/lib/pve-cluster/config.db, gardée en mémoire.
Dans le Shell du nœud :
mount | grep /etc/pve # un montage FUSE
ls -la /var/lib/pve-cluster/config.db # la base qui le porte
ln -s /etc/pve/storage.cfg /etc/pve/lien-essai # un lien symbolique : refusé
touch /etc/pve/essai-chmod # un fichier d'essai
chmod 600 /etc/pve/essai-chmod # un changement de droits : refusé
rm -f /etc/pve/essai-chmod # retirer le fichier d'essai
Résultat attendu sur pxe211 :
/dev/fuse on /etc/pve type fuse (rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other)
-rw------- 1 root root 69632 Oct 6 19:32 /var/lib/pve-cluster/config.db
ln: failed to create symbolic link '/etc/pve/lien-essai': Function not implemented
chmod: changing permissions of '/etc/pve/essai-chmod': Operation not permitted
Ces restrictions sont voulues : les droits se règlent par les chemins, pas par des attributs de fichier. Elles garantissent aussi qu'un même numéro de VM ne peut pas être créé deux fois dans le cluster.
Chaque écriture attend tous les nœuds. Une modification de configuration est diffusée par Corosync à tous les nœuds, y compris l'émetteur. Chacun l'écrit sur son disque (fsync) avant qu'elle soit confirmée.
Un seul nœud au disque système lent ralentit donc tout le cluster. pveperf mesure ce débit.
Dans le Shell du nœud :
pveperf /var/lib/pve-cluster # la ligne FSYNCS/SECOND
Résultat attendu sur pxe211 (disque virtuel du lab) : FSYNCS/SECOND: 511.54. Quelques dizaines de fsync/s désignent un support trop lent pour un nœud de cluster.
2.4 Diagnostiquer le cluster
Premier réflexe : pvecm status, puis les journaux. Mais Quorate: Yes ne veut pas dire « cluster en bonne santé » : c'est une mesure binaire, assez de voix ou pas. Un cluster peut être quorate et inutilisable si un service au-dessus est bloqué.
| Service | Son rôle | Ses journaux |
|---|---|---|
corosync |
Communication, quorum, liens | journalctl -u corosync |
pve-cluster |
pmxcfs, le montage /etc/pve |
journalctl -u pve-cluster |
pvestatd |
Les statistiques des VM et des stockages | journalctl -u pvestatd |
pve-ha-lrm, pve-ha-crm |
La haute disponibilité (§6) | journalctl -u pve-ha-lrm -u pve-ha-crm |
pveproxy, pvedaemon |
L'interface web et l'API | journalctl -u pveproxy -u pvedaemon |
Ajoutez -f pour suivre en direct, par exemple pendant une jonction.
Dans le Shell du nœud :
journalctl -u corosync --no-pager -n 12 # les 12 dernières lignes
Résultat sur pxe211, au moment où pxe213 rejoint (extrait) :
corosync[4355]: [QUORUM] Sync joined[1]: 3
corosync[4355]: [TOTEM ] A new membership (1.d) was formed. Members joined: 3
corosync[4355]: [QUORUM] Members[3]: 1 2 3
corosync[4355]: [MAIN ] Completed service synchronization, ready to provide service.
corosync[4355]: [KNET ] rx: host: 3 link: 1 is up
corosync[4355]: [KNET ] pmtud: Global data MTU changed to: 1397
Le nœud 3 entre dans l'appartenance (Members[3]: 1 2 3), puis ses liens sont vus un par un.
Les pannes courantes :
pvecm status affiche Cannot initialize CMAP service. Corosync ne tourne pas sur ce nœud (vu au §2.2). Remède : systemctl status corosync, journalctl -u corosync -n 100 ; vérifier /etc/pve/corosync.conf.
/etc/pve/... : Permission denied. Le nœud a perdu le quorum : /etc/pve est en lecture seule. Remède : Rétablir le réseau ou Corosync ; ne rien forcer.
'/etc/pve/nodes/<nœud>/pve-ssl.pem' does not exist. Le nœud n'a pas pu écrire son certificat, faute de quorum. Remède : D'abord le quorum, puis pvecm updatecerts (-f pour forcer la régénération) et systemctl restart pveproxy.
Sur le lab : sur un nœud dont le certificat existe, pvecm updatecerts ne dit rien et rend la main (code 0).
Les pièges :
- Forcer
pvecm expecteden routine. La commande abaisse le nombre de voix attendues et contourne la protection contre le split-brain. Elle n'a sa place qu'en urgence documentée. - Un cluster à deux nœuds sans QDevice en production : perdre un nœud fige l'autre.
- Un bond mal réglé sous Corosync (§1.1).
- Oublier de sauvegarder
/var/lib/pve-cluster/config.db: c'est la base de/etc/pve. Une copie régulière permet de la reconstruire.
Réponse
**Aucun n'a le quorum.** Il faut plus de la moitié des voix, soit 2 sur 2 : chaque nœud isolé n'en a qu'une. Pour éviter le *split-brain*, `/etc/pve` passe alors en lecture seule des deux côtés, et toute modification de configuration est refusée. Avec trois nœuds, la partie qui en garde deux conserve le quorum : c'est la raison du troisième nœud (ou d'un QDevice).2.5 Sortir un nœud du cluster
Le cas le plus fréquent en salle : sur le nœud 3, on clique Create Cluster au lieu de Join Cluster. Le nœud fonde alors un cluster à lui seul : son pvecm status a l'air sain (Quorate: Yes), mais il affiche Nodes: 1 et Expected votes: 1. Dans cet état, pvecm add refuse de rejoindre le vrai cluster.
La réparation suit une procédure officielle de Proxmox, Separate a Node Without Reinstalling. Sur le nœud, on arrête le système de fichiers du cluster et Corosync, on efface leur configuration, puis on le joint de nouveau au vrai cluster. Elle demande un nœud sans VM ni conteneur, et elle se fait avec le formateur.
Ne « réparez » jamais un nœud isolé par pvecm expected 1 : il retrouverait le droit d'écrire seul dans /etc/pve, au risque du split-brain (§2.2).
À retenir : la migration à chaud déplace une VM sans l'arrêter, sur un réseau qu'on peut lui dédier. Le quorum (plus de la moitié des voix) empêche le split-brain : sans lui, /etc/pve passe en lecture seule.
Corosync (transport knet) porte ce dialogue ; il supporte plusieurs liens et ne s'édite pas à la main sur un nœud isolé.
▶ À pratiquer maintenant — Préparation à la mise en cluster, puis Atelier 1 et Atelier 2, puis Atelier 3 et Atelier 4
Nettoyer le premier nœud et mettre les deux nouveaux à jour. Puis assembler les trois nœuds en cluster, et déplacer une machine de l'un à l'autre. D'abord à froid, pour voir ce que la migration transporte réellement, puis allumée, avec ses disques locaux, et enfin un conteneur.
Pour finir, priver un nœud de ses deux voisins et observer ce que le quorum lui interdit.
Proxmox VE — TSSR