Dawan Proxmox VE — TSSR

Chapitre 4 — Cluster, Ceph et haute disponibilité

Ateliers — chapitre 4

Infrastructure : 3 nœuds — pxe2<N>1 (le vôtre, depuis le chapitre 1), pxe2<N>2 et pxe2<N>3, joignables par leurs URL, https://pxe2<N>1.<ville>.pm.dawan.ovh et suivantes, données par le formateur. Sur chacun : disque /dev/sdb (70 Go) réservé à Ceph, et cinq cartes réseau.

Réseaux internes (stagiaire N ; site 44 Nantes, 75 Paris, 67 Strasbourg) : ens19 → cluster Corosync 10.<site>.<N+10>.x ; ens20 → Ceph cluster 10.<site>.<N+20>.x ; ens21 → Ceph public 10.<site>.<N+30>.x ; ens22 → migration 10.<site>.<N+40>.x. Nœud 1 en .11, nœud 2 en .12, nœud 3 en .13. Ces réseaux ne sortent pas : ni passerelle, ni NAT.

Les captures et les sorties proviennent du lab d'exemple, monté comme le vôtre : site 59, stagiaire 1, Proxmox VE 9.2.21. Ses adresses suivent donc le même plan : vmbr0 en 10.59.1.x, Corosync en 10.59.11.x, et ainsi de suite. Remplacez 59 par votre site et 1 par votre numéro.


État du lab en fin de chapitre :

  • Cluster cluster-tp de 3 nœuds, quorate, Link 0 sur vmbr1 et Link 1 sur vmbr0. VM 120 migrée à froid, puis à chaud avec ses disques locaux, et éteinte sur pxe2<N>2 (ateliers 2 et 3)
  • Migration d'un conteneur en --restart mesurée, perte et retour du quorum éprouvés (ateliers 3 et 4) ; CT 330 supprimé
  • Réseaux internes adressés : ens20 (Ceph cluster), ens21 (Ceph public), ens22 (migration, déclaré dans Datacenter → Options)
  • Ceph Tentacle : 3 MON, 3 MGR, 3 OSD sur sdb, pool ceph-vm (3/2) déclaré en stockage ; VM 300 vm-ha-test dessus, migrée à chaud
  • (Atelier 6) VM 300 en ressource HA, basculement automatique constaté après une panne brutale ; maintenance du nœud 1 éprouvée

Préparation à la mise en cluster

Contexte

Votre nœud pxe2<N>1 va créer le cluster ; pxe2<N>2 et pxe2<N>3, livrés pour ce chapitre, vont le rejoindre. Avant de les assembler, deux préparations :

  • Nettoyer pxe2<N>1. À la création du cluster, la configuration de /etc/pve devient commune aux trois nœuds : chaque stockage déclaré sur le vôtre sera proposé aux deux autres. Les objets de test des chapitres précédents occupent aussi la mémoire et le disque dont Ceph aura besoin.
  • Mettre pxe2<N>2 et pxe2<N>3 à jour. Ils sortent d'installation, comme votre premier nœud au chapitre 1 : dépôts enterprise actifs, apt update en erreur, aucune mise à jour. Les trois nœuds d'un cluster doivent tourner sur la même version.

Résultat à obtenir : pxe2<N>1 sans objet de test, zfs-vms limité à ce nœud, tous ses stockages active. pxe2<N>2 et pxe2<N>3 sur le dépôt no-subscription, à jour, vides de machines. Et la même version de Proxmox VE sur les trois.

Ce que vous devez faire

  1. Sur pxe2<N>1 : supprimer les objets de test encore présents, limiter le stockage zfs-vms à ce nœud, vérifier que tous les stockages sont active.
  2. Sur pxe2<N>2, puis sur pxe2<N>3, chacun par sa propre interface web : désactiver les deux dépôts enterprise, ajouter le dépôt no-subscription, mettre à jour, redémarrer si le noyau a changé.
  3. Vérifier : même version sur les trois nœuds, aucune machine sur pxe2<N>2 et pxe2<N>3.
Cliquez pour vous aider

Étape 1 — Nettoyer pxe2<N>1

Ce qui doit avoir disparu Pourquoi
Les objets de test : VM 140 (chapitre 3, atelier 4), CT 260 (atelier 5), CT 311 et 312 (atelier 2) Ils occupent de la mémoire et du disque dont Ceph aura besoin
Tout stockage dont le serveur n'existe plus (nfs-partage, chapitre 3, atelier 5) Il reste inactive dans pvesm status, et sa déclaration deviendrait commune aux trois nœuds
Les snapshots de test sur les machines qui restent Ils retiennent de l'espace dans le stockage (chapitre 3, §4.7)
Ce qui reste Pourquoi
Le pont vmbr1 sur ens19, avec son adresse C'est le lien Corosync du cluster (atelier 1)
Le CT 200 et la VM vide 290 du chapitre 1, les VM 100 à 110 du chapitre 2 Elles servent encore ; la VM 290 porte le droit du comptable
Le pool datapool et le stockage zfs-vms Ils peuvent rester, limités à pxe2<N>1
Le pont vmbr9, isolé Sans port ni adresse, il ne gêne rien

Dans le Shell de pxe2<N>1 (interface web de pxe2<N>1 → le nœud pxe2<N>1 → Shell) :

qm list          # les VM du nœud : il ne doit rester que 100 à 110, et la 290
pct list         # les conteneurs : il ne doit rester que le CT 200
pvesm status     # tous les stockages en active, plus de nfs-partage

Supprimez ce qui dépasse : la machine → More → Remove, ou qm destroy <vmid> --purge et pct destroy <ctid> --purge. Un stockage en trop : Datacenter → Storage → le stockage → Remove, ou pvesm remove <id>.

Limiter zfs-vms à votre nœud. Le pool datapool n'existe que sur pxe2<N>1. Déclaré pour tous les nœuds (Nodes : All (No restrictions)), zfs-vms serait proposé à pxe2<N>2 et pxe2<N>3, qui n'ont pas ce pool.

Via l'interface : Datacenter → Storage → zfs-vms → Edit → Nodes : pxe2<N>1 → OK.

Équivalent CLI, dans le Shell de pxe2<N>1 :

pvesm set zfs-vms --nodes pxe2<N>1                 # le stockage n'existe que sur ce nœud
grep -A6 "zfspool: zfs-vms" /etc/pve/storage.cfg   # la ligne nodes apparaît

Résultat attendu (pxe211) :

zfspool: zfs-vms
    pool datapool/vms
    content rootdir,images
    mountpoint /datapool/vms
    nodes pxe211
    sparse 1

La ligne nodes pxe211 limite le stockage à ce nœud. sparse 1 est la case Thin provision du stockage ; elle est absente si elle n'a pas été cochée.

Étape 2 — Dépôts et mise à jour de pxe2<N>2, puis de pxe2<N>3

C'est la procédure du chapitre 1, atelier 3, sur chacun des deux nouveaux nœuds. Ils ne sont pas encore en cluster : chacun s'administre par sa propre interface web, avec son URL.

Les sorties ci-dessous sont celles du chapitre 1, sur pxe211 juste après son installation : les nœuds pxe2<N>2 et pxe2<N>3 sortent de la même installation. Le nombre de paquets à mettre à jour et les versions dépendent du jour.

1. Lire l'état de départ. Interface web de pxe2<N>2 → le nœud → Updates → Repositories.

Le bandeau Status avertit : The enterprise repository is enabled, but there is no active subscription! Deux dépôts Proxmox sont cochés : pve-enterprise (fichier pve-enterprise.sources) et ceph-squid en enterprise (fichier ceph.sources). Tous deux pointent vers enterprise.proxmox.com, réservé aux abonnés.

2. Désactiver les deux dépôts enterprise. Sélectionnez la ligne https://enterprise.proxmox.com/debian/pve → Disable.

Puis la ligne https://enterprise.proxmox.com/debian/ceph-squid → Disable. Oublier la seconde laisse apt update en erreur.

Dans le Shell de pxe2<N>2 :

apt update   # relire les dépôts

Résultat attendu, si ceph-squid est resté en enterprise :

Err:6 https://enterprise.proxmox.com/debian/ceph-squid trixie InRelease
  401  Unauthorized [IP: 51.91.38.34 443]

401 Unauthorized : le serveur refuse l'accès, faute d'abonnement. Disable ne supprime rien : il ajoute la ligne Enabled: false au fichier du dépôt.

3. Ajouter le dépôt no-subscription. Même page → Add → Repository : No-Subscription → Add.

Équivalent CLI, dans le Shell de pxe2<N>2 :

# Dépôt no-subscription de PVE 9, au format DEB822
nano /etc/apt/sources.list.d/proxmox.sources   # un fichier neuf

Le contenu de proxmox.sources, à taper dans nano, puis Ctrl + O, Entrée et Ctrl + X :

Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg

Dans le Shell de pxe2<N>2 :

cat /etc/apt/sources.list.d/proxmox.sources   # relire le fichier créé

Le bandeau passe à You get updates for Proxmox VE. Un avertissement jaune s'ajoute : The no-subscription repository is not recommended for production use! Ce dépôt convient au lab ; en production, on prend un abonnement.

4. Mettre à jour. Dans le Shell de pxe2<N>2 :

apt update            # relire la liste des paquets : plus aucune erreur 401
apt full-upgrade -y   # appliquer toutes les mises à jour
pveversion            # version de Proxmox VE et noyau en cours
ls /boot/vmlinuz-*    # les noyaux installés

Résultat attendu au chapitre 1 (fin de apt update) :

Get:5 http://download.proxmox.com/debian/pve trixie/pve-no-subscription amd64 Packages [390 kB]
181 packages can be upgraded. Run 'apt list --upgradable' to see them.

Si pveversion affiche un running kernel plus ancien que le dernier vmlinuz installé, un nouveau noyau attend. Redémarrez alors le nœud (bouton Reboot de son interface, ou reboot dans son Shell), puis reconnectez-vous.

Recommencez les points 1 à 4 sur pxe2<N>3, par son interface web.

Le dépôt Ceph enterprise reste désactivé, sans dépôt Ceph de remplacement : c'est l'installation de Ceph, à l'atelier 5, qui écrit le bon dépôt.

Étape 3 — Vérifier

Dans le Shell de chacun des trois nœuds :

pveversion   # la même version partout

Dans le Shell de pxe2<N>2, puis de pxe2<N>3 :

qm list    # rien : un nœud qui rejoint un cluster doit être vide de VM
pct list   # et de conteneurs
apt update 2>&1 | grep -i "401\|error"   # rien : plus d'erreur de dépôt

Résultat attendu (sur pxe211, pxe212 et pxe213) : pve-manager/9.2.21/4f6e0ac86f9e8c7f (running kernel: 7.0.14-20-pve) partout.


Atelier 1 — Constitution du cluster 3 nœuds

Contexte

Jusqu'ici, chaque nœud vivait seul. Le cluster les réunit en une seule entité, administrée depuis n'importe lequel d'entre eux. C'est le socle du chapitre : sans cluster, ni Ceph, ni haute disponibilité, ni migration.

Vous le montez à trois nœuds. C'est le minimum sérieux : à trois, la perte d'un nœud laisse deux voix sur trois, et le quorum tient.

Les nœuds se parlent par Corosync. Ce trafic est court mais sensible au délai : on lui donne son propre réseau, vmbr1, créé au chapitre 3. Le réseau d'administration, vmbr0, sert de lien de secours.

Résultat à obtenir : un cluster cluster-tp de trois nœuds, quorate, dont le lien principal passe par vmbr1.

Le cluster de l'atelier : trois nœuds, deux liens Corosync, quorum de deux voix sur trois

Ce que vous allez construire. Chaque nœud a deux adresses Corosync : une sur vmbr1 (Link 0, prioritaire), une sur vmbr0 (Link 1, secours).

Chaque nœud a une voix ; le cluster décide avec deux voix sur trois. Cliquez sur un lien ou sur le quorum pour lire le résultat obtenu.

Arborescence attendue

Cluster « cluster-tp »   (quorum : 2 voix sur 3)
├── pxe2<N>1   ← nœud fondateur, garde ses VM et conteneurs
│   ├── Link 0 : 10.<site>.<N+10>.11  (vmbr1, réseau Corosync)
│   └── Link 1 : 10.<site>.<N>.11     (vmbr0, secours)
├── pxe2<N>2   ← rejoint le cluster, vierge de machines
│   ├── Link 0 : 10.<site>.<N+10>.12
│   └── Link 1 : 10.<site>.<N>.12
└── pxe2<N>3   ← rejoint ensuite, vierge de machines
    ├── Link 0 : 10.<site>.<N+10>.13
    └── Link 1 : 10.<site>.<N>.13

Ce que vous devez faire

  1. Préparer le réseau des deux nouveaux nœuds (la préparation ci-dessus est faite) : pont vmbr1. Vérifier que les trois se joignent sur le réseau Corosync.
  2. Créer le cluster depuis pxe2<N>1, avec le Link 0 sur vmbr1 et le Link 1 sur vmbr0.
  3. Faire adhérer pxe2<N>2, puis pxe2<N>3, l'un après l'autre.
  4. Vérifier : trois nœuds, trois voix, Quorate: Yes, deux liens connectés.

⚠️ On joint les nœuds un par un. On attend que le premier soit stable avant de joindre le second.

Cliquez pour vous aider

Étape 0 — Le réseau Corosync des trois nœuds

Les dépôts et les mises à jour sont faits (préparation à la mise en cluster). Il reste à donner aux deux nouveaux nœuds leur accès au réseau Corosync.

1. Pont vmbr1, sur pxe2<N>2 et pxe2<N>3. Celui du chapitre 3 n'existe que sur votre premier nœud.

Nœud vmbr0 (administration) vmbr1 (Corosync, sur ens19)
pxe2<N>1 10.<site>.<N>.11 10.<site>.<N+10>.11/24 — déjà créé au chapitre 3
pxe2<N>2 10.<site>.<N>.12 10.<site>.<N+10>.12/24
pxe2<N>3 10.<site>.<N>.13 10.<site>.<N+10>.13/24

Avant tout Apply, le filet du chapitre 3 (atelier 1, étape 1 bis).

Dans le Shell de chaque nœud dont vous modifiez le réseau :

# Copie de la configuration réseau qui fonctionne, puis retour automatique dans 10 minutes
cp /etc/network/interfaces /root/interfaces.avant
systemd-run --on-active=10min --unit=filet-reseau sh -c "cp /root/interfaces.avant /etc/network/interfaces && ifreload -a"   # si l'accès est perdu, restaurer la copie dans 10 min

Résultat attendu :

Running timer as unit: filet-reseau.timer
Will run service as unit: filet-reseau.service

Une fois l'accès et les pings vérifiés, annulez-le sur chacun : systemctl stop filet-reseau.timer.

Network → Create → Linux Bridge : Name vmbr1, IPv4/CIDR l'adresse de ce nœud-là, Gateway vide, Bridge ports ens19, Comment COROSYNC → Create → Apply Configuration.

Création de vmbr1 sur le deuxième nœud

(pxe212, lab d'exemple). La fenêtre Create: Linux Bridge remplie : vmbr1, 10.59.11.12/24, ens19, COROSYNC. Pas de passerelle : ce réseau ne sort pas.

Derrière, les cinq cartes du nœud : ens19 est libre, ens18 porte déjà vmbr0. Les cartes ens20 à ens22 serviront à Ceph et à la migration, à l'atelier 5.

2. Vérifier que les trois se voient, depuis pxe2<N>1 :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Les deux autres nœuds, sur le réseau Corosync
ping -c 3 10.<site>.<N+10>.12
ping -c 3 10.<site>.<N+10>.13   # puis le troisième

Résultat attendu (pxe211 vers 10.59.11.12, puis 10.59.11.13) :

3 packets transmitted, 3 received, 0% packet loss, time 2046ms
rtt min/avg/max/mdev = 0.394/0.575/0.727/0.137 ms
3 packets transmitted, 3 received, 0% packet loss, time 2046ms
rtt min/avg/max/mdev = 0.393/0.535/0.679/0.116 ms

Moins d'une milliseconde : c'est ce que Corosync attend.

N'allez pas plus loin tant qu'un ping échoue. Un cluster monté sur un réseau incomplet perd son quorum sans raison visible. Le diagnostic est bien plus pénible une fois les nœuds liés.

Les nœuds qui rejoignent doivent être vierges de machines. Une VM ou un conteneur présent sur pxe2<N>2 ou pxe2<N>3 bloque la jonction.

Vérifiez avec qm list et pct list. Le nœud fondateur, lui, garde ses machines : elles font partie du cluster dès sa création.

Étape 1 — Créer le cluster depuis pxe21

Sur pxe2<N>1 : Datacenter → Cluster → Create Cluster.

Fenêtre Create Cluster à l'ouverture

À l'ouverture, Link 0 est pré-rempli avec l'adresse de vmbr0. Si vous validez tel quel, le cluster dialogue par le réseau d'administration. Il faut changer ce champ.

1. Le nom : 15 caractères au plus.

Nom de cluster refusé car trop long

Le nom formation-cluster (17 caractères) est refusé : le champ passe en rouge, Create reste grisé. L'infobulle indique : The maximum length for this field is 15.

La commande pvecm create applique la même limite. Nommez le cluster cluster-tp.

2. Link 0 : l'adresse de vmbr1. Ouvrez la liste du champ.

Liste des adresses proposées pour le Link 0

La liste affiche chaque adresse avec son interface et son commentaire. Choisissez la ligne vmbr1, commentaire COROSYNC. Le commentaire saisi à la création du pont sert ici à ne pas se tromper.

3. Link 1 : le secours. Cliquez Add.

Fenêtre Create Cluster prête : deux liens

Add crée le Link 1 et le remplit seul avec l'adresse de vmbr0. Le texte le rappelle : lower numbers have higher priority. Corosync passe par le Link 0 ; il bascule sur le Link 1 si le premier tombe.

Cliquez Create.

Journal de la création du cluster

Le journal de la tâche : génération de la clé Corosync (/etc/corosync/authkey), écriture de /etc/pve/corosync.conf, redémarrage de Corosync et du système de fichiers du cluster, puis TASK OK.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Équivalent CLI, pour référence
pvecm create cluster-tp --link0 10.<site>.<N+10>.11 --link1 10.<site>.<N>.11

Vérifiez que le cluster dialogue par le bon réseau :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Les adresses de chaque lien, telles qu'écrites dans la configuration
grep -E "name|ring" /etc/pve/corosync.conf

Résultat attendu :

    name: pxe211
    ring0_addr: 10.59.11.11
    ring1_addr: 10.59.1.11
  cluster_name: cluster-tp

ring0_addr est l'adresse du Link 0 : elle doit être sur 10.<site>.<N+10>.x. ring1_addr, celle du Link 1, est l'adresse de vmbr0.

Étape 2 — Récupérer les informations de jointure

Sur pxe2<N>1 : Datacenter → Cluster → Join Information → Copy Information.

Fenêtre Cluster Join Information du nœud fondateur

Le nœud fondateur fournit trois choses : son adresse, l'empreinte de son certificat, et un bloc encodé qui contient les deux. Derrière, la liste des nœuds montre déjà les colonnes Link 0 et Link 1. Gardez le texte copié : il sert pour les deux autres nœuds.

Étape 3 — Joindre pxe22 au cluster

Sur pxe2<N>2 : Datacenter → Cluster → Join Cluster. Collez le bloc dans Information, puis saisissez le mot de passe root de pxe2<N>1 (proxmoxx).

Join Cluster, pas Create Cluster. Sur les nœuds 2 et 3, un clic sur Create Cluster fonde un second cluster, à un seul nœud. Son pvecm status affiche alors Nodes: 1, Config Version: 1, Expected votes: 1, et la jonction devient impossible (authentication key '/etc/corosync/authkey' already exists).

La réparation, sans réinstaller : cours, §2.5.

Fenêtre Cluster Join, liens encore vides

Peer Address et Fingerprint se remplissent seuls à partir du bloc collé. Mais les champs Link 0 et Link 1 restent vides et passent en rouge.

À droite, Proxmox rappelle l'adresse du pair pour chaque lien : peer's link address. Choisissez pour chaque lien l'adresse de ce nœud sur le même réseau.

Fenêtre Cluster Join prête

Link 0 : 10.<site>.<N+10>.12, en face du pair …11. Link 1 : l'adresse vmbr0 du nœud. Le bouton s'intitule Join 'cluster-tp' : il confirme le cluster visé.

Cliquez Join 'cluster-tp'.

Journal de la jonction, figé en cours de route

Le journal s'arrête sur stopping pve-cluster service, sans TASK OK. C'est normal : le service qui sert l'interface redémarre, et la page perd sa connexion.

Attendez une minute, puis rechargez la page. Le nœud apparaît alors dans le cluster.

Pour la ligne de commande, deux adresses sur deux réseaux différents. pvecm add <adresse> désigne le nœud fondateur, sur son interface d'administration.

--link0 address= désigne le nœud qui rejoint, sur le réseau Corosync. Ce n'est pas le même réseau, et c'est normal.

Étape 4 — Joindre pxe23 au cluster

Recommencez l'étape 3 sur pxe2<N>3, avec les mêmes informations de jointure. Sur le lab, ce nœud a été joint en ligne de commande, pour vérifier la méthode :

Dans le Shell du nœud 3 (pxe2<N>3) :

# Sur pxe2<N>3 : la jonction au fondateur, avec ses deux liens. pvecm demande le mot de passe
# root du fondateur (proxmoxx), puis fait accepter l'empreinte de son certificat (yes)
pvecm add 10.<site>.<N>.11 --link0 address=10.<site>.<N+10>.13 --link1 address=10.<site>.<N>.13

Résultat attendu ; le mot de passe tapé ne s'affiche pas :

Please enter superuser (root) password for '10.59.1.11':
Establishing API connection with host '10.59.1.11'
The authenticity of host '10.59.1.11' can't be established.
X509 SHA256 key fingerprint is …
Are you sure you want to continue connecting (yes/no)? yes
Login succeeded.
check cluster join API version
Request addition of this node
Join request OK, finishing setup locally
stopping pve-cluster service
backup old database to '/var/lib/pve-cluster/backup/config-1791307887.sql.gz'
waiting for quorum...OK
(re)generate node files
generate new node certificate
merge authorized SSH keys
generated new node certificate, restart pveproxy and pvedaemon services
successfully added node 'pxe213' to cluster.

C'est la suite du journal que l'interface n'a pas pu afficher à l'étape 3 : attente du quorum, nouveau certificat, échange des clés SSH entre nœuds.

Étape 5 — Vérifier l'état du cluster

Rechargez l'interface : les trois nœuds apparaissent sous Datacenter (cluster-tp).

Vue Cluster : trois nœuds et leurs deux liens

Config Version: 3 : la configuration a changé trois fois (création, puis deux jonctions). Chaque nœud a une voix, et ses deux adresses : Link 0 sur 10.59.11.x (vmbr1), Link 1 sur 10.59.1.x (vmbr0). En bas, les trois tâches : Create Cluster, puis deux Join Cluster, toutes OK.

Dans le Shell de chaque nœud du cluster :

# Le quorum, puis l'état de chaque lien Corosync
pvecm status
corosync-cfgtool -s   # l'état de chaque lien Corosync

Résultat sur pxe211 (pvecm status, extrait) :

Name:             cluster-tp
Config Version:   3
Transport:        knet
Secure auth:      on

Quorum information
------------------
Nodes:            3
Quorate:          Yes

Votequorum information
----------------------
Expected votes:   3
Highest expected: 3
Total votes:      3
Quorum:           2
Flags:            Quorate

Membership information
----------------------
    Nodeid      Votes Name
0x00000001          1 10.59.11.11 (local)
0x00000002          1 10.59.11.12
0x00000003          1 10.59.11.13

Quorum: 2 : il faut deux voix sur trois pour que le cluster décide. La section Membership affiche les adresses du Link 0, pas les noms : c'est la preuve que Corosync passe bien par vmbr1. Pour les noms, pvecm nodes.

Résultat sur pxe211 (corosync-cfgtool -s) :

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

Les deux liens sont connected vers les deux autres nœuds. Si le Link 0 tombe, le cluster continue par le Link 1.

Validation finale

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Le quorum, puis le nombre de membres
pvecm status | grep Quorate   # le quorum
pvecm nodes | grep -c pxe   # nombre de nœuds membres

Résultat attendu : Quorate: Yes, puis 3.


Atelier 2 — Migration à froid

Contexte

Le premier bénéfice tangible d'un cluster, c'est de pouvoir déplacer une VM d'un nœud à l'autre. À froid — VM éteinte — l'opération est simple et sans risque : Proxmox copie le disque vers le nœud cible puis y recrée la VM. C'est la brique que Ceph rendra ensuite possible à chaud, sans arrêt.

Résultat à obtenir : une VM éteinte migrée avec succès d'un nœud vers un autre, et la compréhension de ce que Proxmox a dû copier faute de stockage partagé.

Les quatre étapes d'une migration à froid, d'après le journal du lab

Ce que Proxmox fait quand vous cliquez Migrate sur une VM éteinte. Il inventorie les disques, crée le volume sur la cible, copie le disque en entier, puis supprime l'original. Cliquez sur une étape pour lire la ligne de journal correspondante.

Arborescence attendue

VM de test (éteinte)
pxe2<N>1  ──[ migration à froid ]──▶  pxe2<N>2
        (copie du disque, puis recréation sur la cible)   ← 4 Gio copiés, même vide

Ce que vous devez faire

  1. Disposer d'une VM de test éteinte sur l'un des nœuds (en recréer une au besoin).
  2. Lancer la migration à froid depuis l'interface, vers un autre nœud du cluster.
  3. Observer ce qui se passe : sans stockage partagé, Proxmox recopie l'intégralité du disque sur le nœud cible. Notez le temps que cela prend — c'est exactement ce que Ceph supprimera à l'atelier suivant.
Cliquez pour vous aider

Étape 0 — Créer une VM de test

Les VM 101 et 102 du chapitre 2 sont toujours là, sur votre nœud — mais elles servent aux ateliers suivants, et les deux nœuds qui vous ont rejoint sont vides. Créez donc une VM dédiée à l'exercice, la 120. Deux façons de faire, selon le temps dont vous disposez — les deux permettent de faire l'atelier en entier.

Option A — VM sans système Option B — VM avec Debian
Durée environ une minute une vingtaine de minutes
Ce que vous pourrez montrer le disque et la mémoire changés de serveur, la VM jamais redémarrée la même chose, plus un service qui ne s'interrompt pas pendant la bascule
Il vous faut rien l'ISO Debian, encore présente dans local depuis le chapitre 1

Si vous hésitez, prenez l'option B. Refaire une installation n'est pas du temps perdu : c'est le geste que vous répéterez le plus souvent en production.

Et la migration à chaud d'une machine qui rend réellement un service est autrement plus convaincante qu'un écran de firmware. L'option A, elle, va droit à la migration.

Deux règles valables dans les deux cas. Elles ne sont pas des détails : chacune empêche la migration si on la néglige.

  • Le lecteur d'ISO doit être vide au moment de migrer. Le stockage local n'est pas partagé : chaque nœud a le sien.

    Une VM dont le lecteur pointe vers une ISO de local sur pxe2<N>1 refusera de partir, puisque le fichier n'existe pas sur la cible. En option A on ne monte rien ; en option B on détache l'ISO une fois l'installation finie.

  • Le type de CPU doit rester générique. Le type host expose le processeur réel du nœud, et la VM ne peut alors migrer que vers un serveur au processeur identique. Le type par défaut x86-64-v2-AES présente un CPU commun aux trois nœuds — c'est lui qui rend la migration possible.


Option A — une VM sans système, en une minute

Pourquoi ça suffit. Ce que la migration déplace, c'est le disque quand la VM est éteinte et la mémoire quand elle tourne.

Une VM sans système a bien les deux : elle démarre sur son firmware, affiche No bootable device, et reste un processus vivant avec sa mémoire. Le mécanisme démontré est exactement le même.

En interface graphique. Sur pxe2<N>1, bouton Create VM en haut à droite :

Onglet Champ Valeur
General Node pxe2<N>1
VM ID 120
Name vm-migration
OS Storage / ISO image Do not use any media
Guest OS — Type Linux
Guest OS — Version 7.x - 2.6 Kernel
System Machine Default (i440fx)
BIOS Default (SeaBIOS)
SCSI Controller VirtIO SCSI single
Qemu Agent ✓
Disks Bus/Device SCSI / 0
Storage local-lvm
Disk size (GiB) 4
CPU Sockets / Cores 1 / 2
Type x86-64-v2-AES (surtout pas host)
Memory Memory (MiB) 1024
Network Bridge vmbr0
Model VirtIO (paravirtualized)
Confirm Start after created ☐

→ Finish

En ligne de commande :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# créer la VM 120, sans système
qm create 120 \
  --name vm-migration \
  --memory 1024 \
  --cores 2 \
  --cpu x86-64-v2-AES \
  --ostype l26 \
  --scsihw virtio-scsi-single \
  --scsi0 local-lvm:4 \
  --net0 virtio,bridge=vmbr0 \
  --agent 1

qm start 120   # la démarrer
qm status 120   # vérifier qu'elle tourne

Résultat attendu : status: running. La console affiche No bootable device ou l'invite du firmware — c'est normal, la VM occupe bien un disque et de la mémoire.

Attention à l'uptime de Proxmox. qm status 120 --verbose | grep uptime compte la vie du processus QEMU, pas celle du système. Après une migration à chaud, la VM tourne dans un nouveau processus, sur le nœud cible : le compteur repart de zéro, sans qu'il y ait eu redémarrage.

Sur le lab : uptime: 20 avant la bascule, uptime: 16 juste après. Pour prouver qu'une VM n'a pas redémarré, il faut le demander à son système (uptime -s dans la VM), ce que seule l'option B permet.


Option B — une VM avec Debian, comme en production

C'est l'installation du chapitre 2, en version minimale : ni bureau graphique ni serveur web, juste le système et de quoi répondre au réseau.

1. Vérifier que l'ISO est toujours là

Dans le Shell du nœud (interface web → votre nœud → Shell) :

ls -lh /var/lib/vz/template/iso/   # les ISO présentes sur le stockage local

Résultat attendu : l'ISO Debian téléchargée au chapitre 2. Si elle a disparu, reprenez-la : votre serveur → local → ISO Images → Download from URL.

2. Créer la VM — mêmes valeurs que l'option A, avec deux différences : l'ISO dans le lecteur, et un disque de 12 Go pour loger le système.

Onglet Champ Valeur
OS Storage / ISO image local / l'ISO Debian
Disks Disk size (GiB) 12

Tout le reste est identique — x86-64-v2-AES compris.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Relevez d'abord le nom exact de l'ISO avec la commande ci-dessus
qm create 120 \
  --name vm-migration \
  --memory 2048 \
  --cores 2 \
  --cpu x86-64-v2-AES \
  --ostype l26 \
  --scsihw virtio-scsi-single \
  --scsi0 local-lvm:12 \
  --ide2 local:iso/<nom-exact-de-l-iso>,media=cdrom \
  --net0 virtio,bridge=vmbr0 \
  --boot 'order=ide2;scsi0' \
  --agent 1

qm start 120   # démarrer sur l'ISO pour installer Debian

3. Installer Debian depuis la console.

Allez au plus simple : langue et clavier, nom de machine vm-migration, mot de passe root, un utilisateur. Partitionnement assisté — tout dans une seule partition.

Et surtout, à l'écran Sélection des logiciels : décochez tout sauf Utilitaires usuels du système. Sans environnement de bureau, l'installation tient en une dizaine de minutes.

4. Après le redémarrage, dans la VM, installer l'agent invité — c'est lui qui permettra à Proxmox d'afficher l'adresse IP de la machine :

Dans la VM (sa Console, ou en SSH) :

apt update                         # la liste des paquets
apt install -y qemu-guest-agent    # installer l'agent invité
# Lancer l'agent maintenant ; il redémarrera seul à chaque démarrage (VM créée avec --agent enabled=1)
systemctl start qemu-guest-agent
ip -br addr   # l'adresse IP de la VM

5. Détacher l'ISO — à ne pas oublier

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm set 120 --ide2 none,media=cdrom   # vider le lecteur CD de la VM
qm config 120 | grep ide2   # vérifier : plus d'ISO

Par l'interface : VM 120 → Hardware → CD/DVD Drive → Edit → Do not use any media → OK.

C'est l'oubli le plus fréquent de cet atelier. Tant que le lecteur pointe vers local:iso/..., la fenêtre Migrate affiche Cannot migrate VM with local CD/DVD et refuse de partir. Le fichier ISO existe sur pxe2<N>1, pas sur la cible : local n'est pas partagé.

Résultat attendu : qm agent 120 ping ne renvoie rien (c'est le signe qu'il répond), et la ligne IPs de l'onglet Summary affiche l'adresse de la VM. Notez-la : elle vous servira pour le ping continu de l'étape 2.

Étape 1 — Migration à froid depuis l'interface

Si la VM est allumée, éteignez-la d'abord : VM 120 → Shutdown.

VM 120 → Migrate (bouton en haut à droite).

Fenêtre Migrate bloquée par une ISO locale

L'ISO Debian est restée dans le lecteur. La fenêtre le détecte avant toute tentative : Cannot migrate VM with local CD/DVD, et le bouton Migrate reste grisé. Détachez l'ISO (étape 0, option B, point 5), puis rouvrez la fenêtre.

En ligne de commande, la même VM est refusée avec un message plus précis.

Dans le Shell du nœud 1 :

# Tenter la migration vers le nœud 2, ISO encore attachée
qm migrate 120 pxe2<N>2
found local disk 'local:iso/debian-13.6.0-amd64-netinst.iso' (attached)
can't migrate local disk 'local:iso/debian-13.6.0-amd64-netinst.iso': local cdrom image
ERROR: migration aborted (duration 00:00:00): Problem found while scanning volumes - can't migrate VM - check log

Fenêtre Migrate prête

Lecteur vide, la fenêtre ne garde qu'un avertissement : Migration with local disk might take long, suivi du disque et de sa taille. Mode : Offline, puisque la VM est éteinte.

Choisissez Target node pxe2<N>2, puis Migrate. Le disque atterrit sur le stockage de même nom du nœud cible : local-lvm.

Journal de la migration à froid

Le journal complet : disque local repéré, volume créé sur la cible, copie, puis suppression du volume source.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Équivalent CLI
qm migrate 120 pxe2<N>2

Résultat attendu (option A, disque de 4 Gio) :

starting migration of VM 120 to node 'pxe212' (10.59.1.12)
found local disk 'local-lvm:vm-120-disk-0' (attached)
copying local disk images
4294967296 bytes (4.3 GB, 4.0 GiB) copied, 4.97538 s, 863 MB/s
successfully imported 'local-lvm:vm-120-disk-0'
  Logical volume "vm-120-disk-0" successfully removed.
migration finished successfully (duration 00:00:06)

Sur le lab (10.59.1.x : remplacez par votre réseau). Deux constats. Les 4 Gio ont traversé le réseau, alors que le disque est vide : sans stockage partagé, Proxmox copie le volume entier.

Et la copie est passée par 10.59.1.12, l'adresse vmbr0 de la cible : le réseau d'administration. L'atelier 5 supprime la copie grâce à Ceph, et envoie la migration sur son propre réseau.

Validation finale

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# qm list ne montre que les VM du nœud local : on interroge pxe2<N>2 par l'API
pvesh get /nodes/pxe2<N>2/qemu --output-format text | grep 120

Résultat attendu : une ligne pour la VM 120, stopped, vm-migration. Dans l'arbre de gauche, la VM apparaît sous pxe2<N>2.


Atelier 3 — Migrer sans stockage partagé : VM allumée et conteneur

Contexte

À l'atelier 2, la VM 120 a changé de nœud éteinte. En production, on déplace plutôt des machines en service, pour vider un nœud avant une intervention. Sans stockage partagé, deux cas se présentent, et ils ne coûtent pas la même chose :

  • une VM allumée peut migrer à chaud, à condition de demander la copie de ses disques locaux (--with-local-disks) ;
  • un conteneur ne migre jamais à chaud : il est arrêté, déplacé, puis redémarré (--restart). Son service est coupé pendant l'opération.

On mesure les deux, et on les compare à la migration à froid de l'atelier 2.

Résultat à obtenir : la VM 120, allumée, migrée de pxe2<N>2 vers pxe2<N>3 sans être arrêtée. Un conteneur neuf, le CT 330, est migré de pxe2<N>1 vers pxe2<N>2 avec --restart, et la durée de sa coupure est mesurée au ping.

Les deux refus sont expliqués (VM sans --with-local-disks, conteneur avec --online). En fin d'atelier, la VM 120 est éteinte sur pxe2<N>2 et le CT 330 supprimé.

Trois façons de déplacer une machine sans stockage partagé : VM éteinte, VM allumée avec ses disques locaux, conteneur avec --restart

Les trois cas côte à côte, avec ce qui voyage et ce qui reste en service. Sans Ceph, le disque voyage toujours. Cliquez sur un cas pour lire la ligne de journal obtenue sur le lab.

Arborescence attendue

pxe2<N>2  ── VM 120 allumée ──[ --online --with-local-disks ]──▶  pxe2<N>3
          (disque recopié pendant que la VM tourne, puis mémoire)

pxe2<N>1  ── CT 330 « ct-migration » ──[ --restart ]──▶  pxe2<N>2
          (arrêt, copie du disque, redémarrage)          ← mesuré par un ping depuis pxe2<N>3

Fin d'atelier : VM 120 éteinte, de retour sur pxe2<N>2 ; CT 330 supprimé

Ce que vous devez faire

  1. Démarrer la VM 120 sur pxe2<N>2, puis tenter de la migrer à chaud vers pxe2<N>3, sans option. Lire le refus.
  2. Relancer la migration avec la copie des disques locaux. Lire le journal : qu'est-ce qui voyage, dans quel ordre, et combien de temps la VM est-elle figée ?
  3. Créer sur pxe2<N>1 un petit conteneur Debian, le CT 330, en adresse fixe 10.<site>.<N>.60, et le démarrer.
  4. Lancer depuis pxe2<N>3 un ping continu vers ce conteneur.
  5. Tenter une migration à chaud du conteneur vers pxe2<N>2, puis le migrer avec --restart. Compter les réponses perdues au ping.
  6. Remettre en état : supprimer le CT 330, éteindre la VM 120 et la ramener sur pxe2<N>2.
Cliquez pour vous aider

Sur le lab (pxe211 à pxe213, réseau 10.59.1.x). Chez vous, les nœuds s'appellent pxe2<N>1 à pxe2<N>3 et le réseau est 10.<site>.<N>.x.

Étape 1 — La VM allumée refuse de partir

En ligne de commande.

Dans le Shell de pxe2<N>2 :

qm start 120                        # démarrer la VM
qm migrate 120 pxe2<N>3 --online    # migration à chaud, sans autre option

Résultat attendu :

found local disk 'local-lvm:vm-120-disk-0' (attached)
can't migrate local disk 'local-lvm:vm-120-disk-0': can't live migrate attached local disks without with-local-disks option
ERROR: Problem found while scanning volumes - can't migrate VM - check log

Le disque est sur local-lvm, que chaque nœud possède en propre : la cible ne le voit pas. En ligne de commande, Proxmox refuse de déplacer une VM en service sans qu'on lui demande explicitement de recopier ce disque.

Étape 2 — Migration à chaud avec les disques locaux

En interface graphique. VM 120 → Migrate.

Fenêtre Migrate d'une VM allumée dont le disque est local

La fenêtre indique Mode : Online, puisque la VM tourne. Elle ajoute un champ Target storage (Current layout : le disque garde le stockage de même nom sur la cible) et prévient : Migration with local disk might take long.

L'interface ajoute d'elle-même la copie du disque : elle ne propose pas de case à cocher. Choisissez Target node pxe2<N>3, puis Migrate.

En ligne de commande, la copie du disque se demande avec l'option --with-local-disks.

Dans le Shell de pxe2<N>2 :

qm migrate 120 pxe2<N>3 --online --with-local-disks   # recopier le disque, puis la mémoire

Résultat attendu (extrait) :

starting migration of VM 120 to node 'pxe213' (10.59.1.13)
found local disk 'local-lvm:vm-120-disk-0' (attached)
starting VM 120 on remote node 'pxe213'
starting storage migration
mirror-scsi0: transferred 1.0 GiB of 4.0 GiB (25.12%) in 1s
mirror-scsi0: transferred 4.0 GiB of 4.0 GiB (100.00%) in 4s, ready
switching mirror jobs to actively synced mode
starting online/live migration on unix:/run/qemu-server/120.migrate
average migration speed: 1.0 GiB/s - downtime 3 ms
migration completed, transferred 4.9 MiB VM-state
mirror-scsi0: Completed successfully.
migration finished successfully (duration 00:00:14)

Le journal se lit en trois temps :

Temps Lignes Ce qui se passe
① Le disque starting storage migration, mirror-scsi0 … Le disque est recopié vers la cible (drive mirror) pendant que la VM tourne ; les écritures en cours sont recopiées aussi (actively synced mode)
② La mémoire starting online/live migration, downtime 3 ms Comme à chaud sur un stockage partagé : la mémoire passe, puis la VM est figée 3 ms et bascule
③ La fin Completed successfully, duration 00:00:14 La copie du disque est close ; l'ancien volume est supprimé sur la source

14 secondes au lieu de 6 pour la migration à froid de l'atelier 2, mais la VM n'a jamais été arrêtée. Avec un vrai disque de 100 Gio, c'est la copie du disque qui dicterait la durée : c'est ce que Ceph supprimera à l'atelier 5.

L'uptime affiché par Proxmox repart de zéro après la bascule (uptime: 16 sur pxe2<N>3). Ce n'est pas un redémarrage : ce compteur suit le processus QEMU, et la VM tourne désormais dans un nouveau processus, sur la cible.

Étape 3 — Créer un conteneur à déplacer

En interface graphique. Sur pxe2<N>1, Create CT :

Onglet Champ Valeur
General CT ID / Hostname 330 / ct-migration
Unprivileged container / Nesting ✓ / ✓
Password celui du lab
Template Storage / Template local / debian-13-standard_…
Disks Storage / Disk size local-lvm / 4
CPU / Memory Cores / Memory 1 / 512
Network Bridge / IPv4 / Gateway vmbr0 / 10.<site>.<N>.60/24 / 10.<site>.<N>.1
Confirm Start after created ✓

En ligne de commande.

Dans le Shell de pxe2<N>1 :

# Un conteneur Debian minimal, en adresse fixe
pct create 330 local:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst \
  --hostname ct-migration --memory 512 --cores 1 \
  --rootfs local-lvm:4 \
  --net0 name=eth0,bridge=vmbr0,ip=10.<site>.<N>.60/24,gw=10.<site>.<N>.1 \
  --unprivileged 1 --features nesting=1 \
  --password
pct start 330     # le démarrer
pct status 330    # status: running

--password sans valeur demande le mot de passe au clavier. --features nesting=1 évite l'avertissement Systemd 257 detected. You may need to enable nesting., obtenu sans cette option : le système Debian 13 du conteneur en a besoin.

Étape 4 — Un ping continu pour mesurer la coupure

Dans le Shell de pxe2<N>3 (interface web de pxe2<N>3 → Shell) :

ping -i 0.5 10.<site>.<N>.60    # une requête toutes les 0,5 s ; laisser tourner

Étape 5 — Migrer le conteneur

Dans le Shell de pxe2<N>1 :

pct migrate 330 pxe2<N>2 --online     # essai de migration à chaud
pct migrate 330 pxe2<N>2 --restart    # arrêt, déplacement, redémarrage

En interface graphique : CT 330 → Migrate → Target node pxe2<N>2.

Fenêtre Migrate d'un conteneur allumé

Pour un conteneur allumé, la fenêtre impose Mode : Restart Mode : aucune option ne permet de le déplacer sans l'arrêter.

Résultat attendu :

ERROR: migration aborted (duration 00:00:00): lxc live migration is currently not implemented
shutdown CT 330
starting migration of CT 330 to node 'pxe212' (10.59.1.12)
found local volume 'local-lvm:vm-330-disk-0' (in current VM config)
4294967296 bytes (4.3 GB, 4.0 GiB) copied, 5.95972 s, 721 MB/s
successfully imported 'local-lvm:vm-330-disk-0'
start container on target node
migration finished successfully (duration 00:00:11)

Arrêtez le ping (Ctrl+C) et lisez sa fin. Sur le lab, les numéros icmp_seq sautaient de 9 à 31 : 21 réponses perdues à 0,5 s d'intervalle, soit environ 10 secondes sans service. C'est le temps d'arrêter le conteneur, de copier ses 4 Gio et de le redémarrer.

Pourquoi pas à chaud ? Une VM est un seul processus, dont on sait copier la mémoire. Un conteneur, ce sont les processus du noyau de l'hôte, avec leurs fichiers ouverts et leurs connexions : rien qu'on puisse transporter vers un autre noyau (cours, §2.1).

Étape 6 — Remettre en état

Dans le Shell de pxe2<N>2 :

pct stop 330                 # arrêter le conteneur
pct destroy 330 --purge      # le supprimer

Dans le Shell de pxe2<N>3 :

qm stop 120                  # la VM 120 n'a pas de système : un arrêt brutal suffit
qm migrate 120 pxe2<N>2      # migration à froid, retour sur pxe2<N>2

Si vous avez installé Debian dans la VM 120 (option B de l'atelier 2), préférez qm shutdown 120. Sans système, qm shutdown attend une réponse qui ne vient pas, puis échoue sur got timeout.

Validation finale

Contrôle Résultat attendu
Migration à chaud sans option refusée : can't live migrate attached local disks without with-local-disks option
Migration à chaud avec --with-local-disks réussie, downtime de quelques millisecondes, disque recopié d'abord
Conteneur avec --online refusé : lxc live migration is currently not implemented
Conteneur avec --restart réussi, une dizaine de secondes de coupure au ping
État final VM 120 éteinte sur pxe2<N>2 ; plus de CT 330

Atelier 4 — Le quorum à l'épreuve

Contexte

Sur le lab, un nœud isolé s'est figé tandis que les deux autres continuaient (cours, §2.2). On va plus loin : on prive votre nœud pxe2<N>1 de ses deux voisins, l'un après l'autre, et l'on observe ce qu'il peut encore faire.

La panne est simulée en arrêtant Corosync sur les voisins, depuis leur propre Shell. Elle est donc réversible : on relance Corosync, et tout revient. On ne coupe aucun nœud et l'on ne touche à aucun réseau : un nœud éteint ne se rallume pas depuis l'interface web.

Résultat à obtenir : l'état du quorum sur pxe2<N>1 avec trois, deux, puis une seule voix. La preuve qu'à deux voix sur trois, le cluster écrit encore. À une voix, /etc/pve passe en lecture seule, la création et le démarrage de VM sont refusés, mais la VM 101 continue de tourner.

Les événements correspondants sont lus dans le journal de Corosync. Enfin, le quorum revient sans rien forcer.

Le nœud 1 perd ses voisins un par un : quorate à trois puis à deux voix, figé à une voix

Les trois étapes de l'atelier, vues depuis pxe2<N>1. Le quorum reste fixé à deux voix ; seul change le nombre de voix présentes. Cliquez sur une étape pour lire le résultat.

Arborescence attendue

Cluster « cluster-tp »   (3 voix attendues, quorum = 2)
├── pxe2<N>1   ← on observe ici : la VM 101 y tourne
├── pxe2<N>2   ← Corosync arrêté en premier   → 2 voix sur 3 : quorate
└── pxe2<N>3   ← Corosync arrêté ensuite      → 1 voix sur 3 : figé
Retour : Corosync relancé sur pxe2<N>2, puis pxe2<N>3 → 3 voix

Ce que vous devez faire

  1. Relever l'état de départ sur pxe2<N>1 : pvecm status, et l'uptime de la VM 101 (démarrez-la si besoin).
  2. Arrêter Corosync sur pxe2<N>2. Sur pxe2<N>1 : relever le quorum, puis tenter une écriture dans /etc/pve.
  3. Arrêter Corosync sur pxe2<N>3. Sur pxe2<N>1 : relever le quorum, tenter une écriture, créer une VM, démarrer une VM éteinte, et vérifier que la VM 101 tourne toujours.
  4. Lire le journal de Corosync sur pxe2<N>1.
  5. Relancer Corosync sur pxe2<N>2, puis sur pxe2<N>3, et vérifier le retour au quorum.

Ne jamais utiliser pvecm expected 1 pour « débloquer » le nœud resté seul. La commande abaisse le nombre de voix attendues : le nœud isolé se croit majoritaire.

Si les autres nœuds tournent toujours de leur côté, deux parties du cluster écrivent en même temps : c'est le split-brain (cours, §2.4). Ici, la bonne réponse est de rétablir Corosync.

Cliquez pour vous aider

Sur le lab (pxe211 à pxe213). Chez vous, les nœuds s'appellent pxe2<N>1 à pxe2<N>3. Ouvrez trois onglets, un Shell par nœud : l'interface web de pxe2<N>1 restera utilisable pour lire, pas pour modifier.

Étape 1 — L'état de départ

Dans le Shell de pxe2<N>1 :

qm start 101                                           # la VM 101 doit tourner ; si elle tourne déjà, qm le dit, sans conséquence
qm status 101 --verbose   # état et durée de fonctionnement ; à lire : status, uptime
pvecm status   # les voix du cluster ; à lire : Nodes, Expected votes, Total votes, Quorum, Quorate

Résultat attendu (les lignes qui comptent) :

status: running
uptime: 271
Nodes:            3
Quorate:          Yes
Expected votes:   3
Total votes:      3
Quorum:           2

Trois voix attendues, trois présentes ; il en faut deux (Quorum: 2) pour décider.

Étape 2 — Un voisin perdu : deux voix sur trois

Dans le Shell de pxe2<N>2 :

systemctl stop corosync    # ce nœud ne parle plus au cluster

Dans le Shell de pxe2<N>1 :

pvecm status   # deux voix sur trois ; à lire : Nodes, Total votes, Quorum, Quorate
touch /etc/pve/essai-2-voix        # écrire dans /etc/pve
echo "code : $?"                   # 0 : écriture acceptée
rm /etc/pve/essai-2-voix           # retirer le fichier d'essai

Résultat attendu (les lignes qui comptent) :

Nodes:            2
Quorate:          Yes
Total votes:      2
Quorum:           2
code : 0

Deux voix sur trois, c'est encore la majorité : le cluster continue sans rien perdre. Dans l'interface web, pxe2<N>2 apparaît avec une croix rouge.

Arbre du Datacenter : pxe212 et pxe213 marqués d'une croix rouge

L'arbre de l'interface de pxe2<N>1 après l'étape 3 : les deux voisins portent une croix rouge, leurs machines restent listées. Ce que l'interface ne montre pas d'un coup d'œil, c'est que pxe2<N>1 a perdu le quorum : il faut le lire dans pvecm status, ou dans Datacenter → Summary.

Étape 3 — Le second voisin perdu : une voix sur trois

Dans le Shell de pxe2<N>3 :

systemctl stop corosync   # le second voisin quitte le cluster

Dans le Shell de pxe2<N>1 :

pvecm status   # une voix sur trois ; à lire : Nodes, Expected votes, Total votes, Quorum, Quorate
touch /etc/pve/essai-1-voix                               # écrire dans /etc/pve
qm create 199 --name essai-sans-quorum --memory 256      # créer une VM
qm start 105                                              # démarrer une VM éteinte
qm status 101 --verbose   # la VM qui tournait ; à lire : status, uptime

Résultat attendu (les lignes qui comptent) :

Nodes:            1
Quorate:          No
Expected votes:   3
Total votes:      1
Quorum:           2 Activity blocked
touch: cannot touch '/etc/pve/essai-1-voix': Permission denied
cluster not ready - no quorum?
cluster not ready - no quorum?
status: running
uptime: 286
Ce qu'on tente Réponse Pourquoi
Écrire dans /etc/pve Permission denied Le nœud minoritaire passe la configuration commune en lecture seule
Créer une VM cluster not ready - no quorum? Une création écrit une configuration dans /etc/pve
Démarrer une VM cluster not ready - no quorum? Le démarrage est refusé : la même VM pourrait être lancée ailleurs, par la partie majoritaire
La VM 101 déjà lancée status: running, uptime qui continue Rien ne l'arrête : le quorum protège la configuration, pas les machines qui tournent

Étape 4 — Ce que dit le journal

Dans le Shell de pxe2<N>1 :

journalctl -u corosync --no-pager -n 8    # les 8 derniers événements de Corosync

Résultat attendu :

[QUORUM] This node is within the non-primary component and will NOT provide any services.
[QUORUM] Members[1]: 1
[MAIN  ] Completed service synchronization, ready to provide service.
[KNET  ] link: host: 3 link: 0 is down
[KNET  ] host: host: 3 (passive) best link: 1 (pri: 1)
[KNET  ] link: host: 3 link: 1 is down
[KNET  ] host: host: 3 (passive) best link: 1 (pri: 1)
[KNET  ] host: host: 3 has no active links
  • non-primary component : ce nœud est du côté minoritaire, il ne rendra plus de service de cluster.
  • Members[1]: 1 : il ne voit plus que lui-même (le nœud n°1).
  • link: 0 is down, puis link: 1 is down : les deux liens vers le nœud 3 tombent l'un après l'autre. Avec un seul lien perdu, Corosync aurait basculé sur l'autre (best link: 1) sans perdre le nœud.

Étape 5 — Revenir au quorum

Dans le Shell de pxe2<N>2, puis dans celui de pxe2<N>3 :

systemctl start corosync   # le nœud revient dans le cluster

Dans le Shell de pxe2<N>1, après le premier redémarrage puis après le second :

pvecm status   # les voix revenues ; à lire : Nodes, Total votes, Quorate

Résultat attendu (les lignes qui comptent) :

Nodes:            2
Quorate:          Yes
Total votes:      2
[…]
Nodes:            3
Quorate:          Yes
Total votes:      3

Dès que pxe2<N>2 revient, le journal annonce This node is within the primary component and will provide service. : avec deux voix, pxe2<N>1 retrouve l'écriture. Aucune VM 199 n'a été créée pendant la panne (ls /etc/pve/qemu-server/ ne la montre pas).

Validation finale

Dans le Shell de pxe2<N>1 :

pvecm status | grep Quorate                       # Quorate: Yes
corosync-cfgtool -s | grep -c connected           # 4 : deux liens vers deux voisins
touch /etc/pve/essai                              # /etc/pve accessible en écriture ?
echo "code : $?"                                  # 0 : oui
rm /etc/pve/essai                                 # retirer le fichier d'essai

Résultat attendu : Quorate: Yes, 4, code : 0. Le cluster est revenu à son état de départ, sans rien forcer.


Atelier 5 — Déploiement de Ceph Tentacle

Contexte

À l'atelier 2, migrer une VM a coûté la copie de tout son disque. Ceph supprime cette copie.

C'est un stockage distribué : chaque donnée existe en trois exemplaires, un par nœud. Le disque d'une VM est donc déjà partout, et seule sa mémoire doit voyager.

Ceph a besoin de deux réseaux à lui. Le réseau public transporte le trafic entre les VM et Ceph. Le réseau cluster transporte la réplication entre les disques.

Vos cartes ens20 et ens21 sont là pour eux. La carte ens22, elle, portera la migration à chaud.

Résultat à obtenir : Ceph sain (HEALTH_OK) sur les trois nœuds, un pool répliqué déclaré en stockage, et une VM migrée à chaud par le réseau de migration.

Le Ceph de l'atelier : trois démons par nœud et trois réseaux internes

Ce que vous allez déployer. Sur chaque nœud, un moniteur, un manager et un OSD.

En dessous, les trois réseaux internes, chacun sur sa carte. Cliquez sur un réseau ou sur un type de démon pour lire son rôle et le résultat obtenu.

Arborescence attendue

Réseaux internes (une adresse par nœud : .11, .12, .13)
├── ens20 → Ceph cluster  10.<site>.<N+20>.x   réplication entre OSD
├── ens21 → Ceph public   10.<site>.<N+30>.x   VM ↔ Ceph, moniteurs
└── ens22 → migration     10.<site>.<N+40>.x   mémoire des VM migrées
Ceph Tentacle (20.2)
├── Monitors : 1 par nœud   (quorum de Ceph, distinct de celui de Corosync)
├── Managers : 1 par nœud   (1 actif, 2 en attente)
├── OSD      : 1 par nœud, sur /dev/sdb
└── pool « ceph-vm » (3 copies, 2 minimum) → stockage RBD partagé
VM 300 « vm-ha-test » sur ceph-vm  ──[ migration à chaud ]──▶  pxe2<N>2   ← seule la mémoire voyage

Ce que vous devez faire

  1. Adresser ens20, ens21 et ens22 sur les trois nœuds.
  2. Installer Ceph sur les trois nœuds, puis l'initialiser sur les réseaux dédiés.
  3. Créer un Monitor et un Manager par nœud, puis un OSD par nœud sur /dev/sdb.
  4. Vérifier HEALTH_OK, puis créer un pool répliqué déclaré en stockage.
  5. Désigner le réseau de migration, puis migrer à chaud une VM posée sur Ceph. Comparez avec l'atelier 2.

⚠️ Ceph exige un disque totalement vierge pour ses OSD. Si un pool ZFS occupe sdb, il faudra le détruire d'abord (étape 4 bis).

Cliquez pour vous aider

Étape 0 — Adresser les réseaux de Ceph et de migration

Ces trois réseaux n'ont pas besoin de pont : aucune VM ne s'y branche. L'adresse se pose directement sur la carte.

Carte Rôle pxe2<N>1 pxe2<N>2 pxe2<N>3 Comment
ens20 Ceph cluster 10.<site>.<N+20>.11/24 ….12/24 ….13/24 CEPH-CLUSTER
ens21 Ceph public 10.<site>.<N+30>.11/24 ….12/24 ….13/24 CEPH-PUBLIC
ens22 Migration 10.<site>.<N+40>.11/24 ….12/24 ….13/24 MIGRATION

Avant tout Apply, le filet du chapitre 3 (atelier 1, étape 1 bis).

Dans le Shell de chaque nœud dont vous modifiez le réseau :

# Copie de la configuration réseau qui fonctionne, puis retour automatique dans 10 minutes
cp /etc/network/interfaces /root/interfaces.avant
systemd-run --on-active=10min --unit=filet-reseau sh -c "cp /root/interfaces.avant /etc/network/interfaces && ifreload -a"   # si l'accès est perdu, restaurer la copie dans 10 min

Une fois l'accès et les pings vérifiés, annulez-le sur chacun : systemctl stop filet-reseau.timer.

Sur chaque nœud : Network → double-clic sur la carte → IPv4/CIDR, Autostart coché, Comment → OK. Une fois les trois cartes faites : Apply Configuration.

Édition de la carte ens20

(pxe211). La fenêtre Edit: Network Device de ens20.

Pas de passerelle : ces réseaux ne sortent pas. Autostart coché : sans lui, la carte resterait éteinte au prochain démarrage.

Les cinq cartes adressées

Après Apply Configuration, les cinq cartes sont actives. ens20, ens21 et ens22 portent leur adresse en direct ; ens18 et ens19 la portent par leur pont (vmbr0, vmbr1).

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Depuis pxe2<N>1 : les deux autres nœuds, sur chacun des trois réseaux
ping -c 2 -q 10.<site>.<N+20>.12   # le nœud 2, réseau Ceph cluster
ping -c 2 -q 10.<site>.<N+20>.13   # le nœud 3
ping -c 2 -q 10.<site>.<N+30>.12   # le nœud 2, réseau Ceph public
ping -c 2 -q 10.<site>.<N+30>.13   # le nœud 3
ping -c 2 -q 10.<site>.<N+40>.12   # le nœud 2, réseau de migration
ping -c 2 -q 10.<site>.<N+40>.13   # le nœud 3

Remplacez <N+20>, <N+30> et <N+40> par leurs valeurs (21, 31 et 41 pour le stagiaire 1).

Résultat attendu : pour chaque ping, 2 packets transmitted, 2 received, 0% packet loss, puis une ligne rtt min/avg/max/mdev sous la milliseconde (de 0,36 à 0,71 ms en moyenne).

Étape 1 — Installer Ceph

Sur pxe2<N>1, par l'assistant. Le serveur → Ceph. Le panneau affiche Ceph is not installed on this node → Install Ceph.

Assistant Ceph, écran Info

L'assistant propose tentacle (20.2), mais le dépôt Enterprise (recommended). Sans abonnement, ce dépôt répond 401 et l'installation échoue. L'indice en bas le signale : The enterprise repository is enabled, but there is no active subscription!

Assistant Ceph prêt : Tentacle, No-Subscription

Repository passé sur No-Subscription. L'indice change : ce dépôt n'est pas le meilleur choix en production.

Pour le lab, c'est le bon. Cliquez Start tentacle installation.

Terminal de l'assistant : apt attend une réponse

L'onglet Installation est un vrai terminal. apt liste les paquets (27 à installer, 13 à mettre à jour), puis attend une réponse : Do you want to continue? [Y/n]. Cliquez dans le terminal, tapez y, puis Entrée.

Fin de l'installation

Les paquets en version 20.2.4-pve4, puis installed Ceph 20.2 Tentacle successfully!. Le bouton Next devient actif.

Sur pxe2<N>2 et pxe2<N>3, en ligne de commande — dans le Shell de chaque nœud :

# La question d'apt reçoit « y » par le tube
yes | pveceph install --version tentacle --repository no-subscription
ceph --version   # version de Ceph installée

Résultat attendu :

installed Ceph 20.2 Tentacle successfully!

reloading API to load new Ceph RADOS library...
ceph version 20.2.4 (a12e197e4613a9d6be90e8fb073ac4fc3656aee2) tentacle (stable)

apt failed during ceph installation (256) : lisez la ligne au-dessus. Sans le yes |, et sans terminal pour répondre, apt reçoit une réponse vide. Il abandonne : `Do you want to continue?

[Y/n] Abort.Ce n'est pas le dépôt : relancez avecyes |. Si la ligne au-dessus parle de401ou de dépôt introuvable, c'est bien le dépôt : relancez avec--repository no-subscription.pvecephréécrit lui-même/etc/apt/sources.list.d/ceph.sources; n'ajoutez pas de fichier.list` à côté.

Étape 2 — Initialiser Ceph sur ses réseaux

Avec l'assistant, cette étape suit l'installation : onglet Configuration. Si vous l'avez fermé, rouvrez Ceph sur pxe2<N>1 : le panneau affiche Ceph is not initialized → Configure Ceph.

Onglet Configuration rempli

Public Network : l'adresse de ens21 (10.44.31.11/24 sur le lab). Cluster Network : celle de ens20 (10.44.21.11/24).

Par défaut, le second vaut Same as Public Network : laissé ainsi, la réplication partagerait le réseau des VM. À droite, le premier moniteur sera pxe211. → Next.

Assistant terminé

Installation successful! et la suite à faire : installer Ceph sur les autres nœuds, créer les moniteurs, les OSD, les pools. → Finish.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Équivalent CLI, si vous n'avez pas utilisé l'assistant
pveceph init --network 10.<site>.<N+30>.0/24 --cluster-network 10.<site>.<N+20>.0/24
pveceph mon create   # le premier moniteur

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Ce que l'assistant a écrit, et ce qui tourne déjà
grep -E "network|mon_host|pool_default" /etc/pve/ceph.conf
ceph -s   # état du cluster Ceph

Résultat attendu (lab, pveceph init en ligne de commande, réseaux 10.59.x) :

    cluster_network = 10.59.21.0/24
    mon_host =  10.59.31.11
    osd_pool_default_min_size = 2
    osd_pool_default_size = 3
    public_network = 10.59.31.0/24
...
    health: HEALTH_OK
    mon: 1 daemons, quorum pxe211 (age 6s) [leader: pxe211]
    mgr: pxe211(active, since 5s)
    osd: 0 osds: 0 up, 0 in

Par l'assistant, les deux réseaux s'écrivent avec l'adresse du nœud (10.<site>.<N+20>.11/24) ; en ligne de commande, avec l'adresse du réseau (.0/24). Ceph comprend les deux de la même façon : le réseau entier.

L'assistant, comme pveceph mon create, a créé d'un coup le premier Monitor et le premier Manager. Le moniteur écoute sur le réseau public. Les valeurs par défaut des pools sont fixées : 3 copies, 2 au minimum.

Étape 3 — Monitors et Managers sur les deux autres nœuds

Le Monitor tient la carte du cluster Ceph ; il en faut une majorité pour que Ceph fonctionne. Le Manager collecte les statistiques ; un seul est actif, les autres attendent.

Sur pxe2<N>2 : Ceph → Monitor → section Monitor → Create → Create. Puis section Manager → Create → Create. Même chose sur pxe2<N>3.

Page Monitor après le deuxième moniteur

(pxe212). Deux moniteurs, running, Quorum : Yes, à l'écoute sur le port 6789 du réseau public.

Un seul manager pour l'instant, celui créé par l'assistant. La page a deux boutons Create : le premier pour les moniteurs, le second pour les managers.

Dans le Shell de chacun des deux autres nœuds (pxe2<N>2, puis pxe2<N>3) :

# Équivalent CLI, sur chaque nœud qui n'en a pas encore
pveceph mon create
pveceph mgr create   # un manager
ceph -s   # état du cluster Ceph

Résultat attendu, une fois les trois nœuds faits :

    health: HEALTH_WARN
            OSD count 0 < osd_pool_default_size 3

  services:
    mon: 3 daemons, quorum pxe211,pxe212,pxe213 (age 11s) [leader: pxe211]
    mgr: pxe211(active, since 34s), standbys: pxe212, pxe213
    osd: 0 osds: 0 up, 0 in

Ce HEALTH_WARN est attendu : les pools veulent 3 copies, et il n'y a encore aucun disque.

Étape 4 — Un OSD par nœud

L'OSD est le démon qui gère un disque. Sur chaque nœud : Ceph → OSD → Create: OSD.

Choix du disque de l'OSD

(pxe211). La liste ne propose que les disques libres. Sur ce nœud, sdc et sdd portent le pool ZFS du chapitre 3 : seul /dev/sdb reste.

Sa taille, 75.16 GB, correspond aux 70 Gio du disque, exprimés en Go. DB Disk : use OSD disk — tout sur le même disque, ce qui suffit au lab. → Create.

La liste des OSD ne se rafraîchit pas seule : cliquez Reload après la création.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Équivalent CLI, sur chaque nœud
pveceph osd create /dev/sdb

Résultat attendu (pxe212, fin) :

Running command: /bin/systemctl start ceph-osd@1
--> ceph-volume lvm activate successful for osd ID: 1
--> ceph-volume lvm create successful for: /dev/sdb

Les trois OSD

Un OSD par nœud, osd.0 à osd.2, tous up / in, type bluestore, 70 Gio chacun. La classe ssd vient du disque virtuel, que Ceph détecte comme non rotatif.

Étape 4 bis — Si pveceph osd create refuse le disque

Ceph exige un disque totalement vierge. La moindre signature — table de partition, LVM, ZFS, ancien OSD — fait échouer la création.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Le disque destiné à Ceph porte-t-il encore une signature ?
lsblk /dev/sdb
wipefs /dev/sdb   # signatures présentes sur le disque

Résultat attendu, disque vierge : lsblk ne montre que la ligne sdb 8:16 0 70G 0 disk, sans partition dessous, et wipefs n'affiche rien.

Si wipefs affiche des lignes, deux cas.

Cas A — un pool ZFS occupe le disque. Cela arrive si le pool du chapitre 3 a été monté sur sdb au lieu de sdc et sdd. On le démonte dans cet ordre :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# 1. Retirer le stockage côté Proxmox
pvesm remove zfs-vms

# 2. Détruire le pool — les données qu'il contient sont perdues
zpool destroy datapool

# 3. Vérifier
zpool list

Vérifiez d'abord que ce pool ne contient plus rien d'utile : zfs list et pvesm status disent ce qui y vit encore. Un disque de VM hébergé dessus serait perdu avec le pool. Déplacez-le d'abord avec Move Storage.

Cas B — le disque porte de vieilles signatures, d'une session précédente ou d'un autre usage :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

wipefs -a /dev/sdb   # effacer les signatures du disque
wipefs /dev/sdb   # vérifier : plus aucune signature
lsblk /dev/sdb   # le disque est libre

Relisez le nom du disque avant de valider wipefs -a. La commande efface sans confirmation ni retour possible. Si /dev/sda apparaît dans votre ligne, arrêtez-vous : c'est le système Proxmox.

Reprenez ensuite l'étape 4.

Étape 5 — Vérifier l'état de Ceph

Sur un nœud : Ceph (la page d'accueil du panneau).

Tableau de bord Ceph : HEALTH_OK

HEALTH_OK, No Warnings/Errors, version 20.2.4. Trois OSD Up et In. Tous les PG active+clean.

Trois moniteurs et trois managers, cochés. L'infobulle d'un manager montre son adresse : le réseau public.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

ceph -s   # état du cluster Ceph
ceph osd tree   # les OSD, par nœud

Résultat attendu :

  cluster:
    id:     e21ecf15-c9ac-4c0f-8621-bf4281df1e24
    health: HEALTH_OK

  services:
    mon: 3 daemons, quorum pxe211,pxe212,pxe213 (age 44s) [leader: pxe211]
    mgr: pxe211(active, since 67s), standbys: pxe212, pxe213
    osd: 3 osds: 3 up (since 17s), 3 in (since 22s)

  data:
    pools:   1 pools, 1 pgs
    objects: 2 objects, 577 KiB
    usage:   81 MiB used, 210 GiB / 210 GiB avail
    pgs:     1 active+clean

ID  CLASS  WEIGHT   TYPE NAME        STATUS  REWEIGHT  PRI-AFF
-1         0.20517  root default
-3         0.06839      host pxe211
 0    ssd  0.06839          osd.0        up   1.00000  1.00000
-5         0.06839      host pxe212
 1    ssd  0.06839          osd.1        up   1.00000  1.00000
-7         0.06839      host pxe213
 2    ssd  0.06839          osd.2        up   1.00000  1.00000

Le pool déjà présent (1 pools) s'appelle .mgr : le manager le crée pour ses propres données. 210 GiB : l'espace brut des trois disques, avant réplication.

Un HEALTH_WARN passager est normal pendant les premières minutes : moniteurs qui se synchronisent, OSD qui démarrent. ceph health detail en donne la raison exacte.

S'il persiste au-delà de cinq minutes, lisez-la avant d'aller plus loin. C'est souvent une horloge décalée entre nœuds (clock skew detected), que corrige la synchronisation NTP.

Étape 6 — Créer un pool Ceph pour les VM

Les écrans Ceph sont sous le nœud, pas sous le Datacenter. Sélectionnez un serveur, puis Ceph : vous y trouvez Configuration, Monitor, OSD, CephFS, Pools et Log. Un pool créé depuis un nœud existe pour les trois.

Sur pxe2<N>1 : Ceph → Pools → Create.

Fenêtre Create: Ceph Pool

Name ceph-vm. Size 3 : trois copies. PG Autoscaler Mode on : Ceph ajuste seul le découpage du pool.

Add as Storage coché : le pool devient aussitôt un stockage Proxmox. **Min.

Size n'apparaît qu'en cochant Advanced ; il vaut 2. Derrière, le pool .mgr existe déjà. → Create**.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Équivalent CLI : pool répliqué, déclaré aussitôt comme stockage
pveceph pool create ceph-vm --pg_autoscale_mode on --add_storages 1
pvesm status | grep ceph-vm   # le stockage ceph-vm est-il actif ?
ceph osd pool ls detail | grep ceph-vm   # taille, taille minimale et règle du pool

Résultat attendu :

ceph-vm           rbd     active        69698728               0        69698728    0.00%
pool 2 'ceph-vm' replicated size 3 min_size 2 crush_rule 0 object_hash rjenkins pg_num 128 pgp_num 128 autoscale_mode on ...

Environ 66 Gio utiles pour 210 Gio bruts : un tiers, puisque chaque donnée existe en trois exemplaires. Le pool part avec pg_num 128.

Relisez la même ligne quelques minutes plus tard : sur le lab, elle portait pg_num 100 pgp_num 100 pg_num_target 32. L'autoscaler a jugé 128 trop pour un pool presque vide, et réduit pas à pas vers 32 (ceph osd pool autoscale-status, colonne PG_NUM).

Étape 7 — Désigner le réseau de migration

Par défaut, une migration passe par le réseau d'administration : c'est ce qu'a montré l'atelier 2. On lui donne ens22.

Datacenter → Options → double-clic sur Migration Settings → Network : choisir l'adresse de ens22 → OK.

Réglage du réseau de migration

Type : secure — la mémoire voyage chiffrée dans un tunnel SSH. Network : la liste propose les adresses du nœud ; on prend celle de ens22. Le réglage vaut pour tout le cluster : chaque nœud utilisera son adresse dans ce réseau.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Le réglage, tel qu'enregistré pour tout le cluster
grep migration /etc/pve/datacenter.cfg

Résultat attendu : migration: network=10.59.41.11/24,type=secure (lab 10.59 : chez vous, 10.<site>.<N+40>.11/24).

Étape 8 — Migration à chaud via Ceph

1. Une VM sur Ceph. Clonez le template 100 du chapitre 2 directement sur le pool.

Template 100 → clic droit → Clone : VM ID 300, Name vm-ha-test, Mode Full Clone, Target Storage ceph-vm → Clone. Puis VM 300 → Cloud-Init : IP 10.<site>.<N>.85/24, Gateway 10.<site>.<N>.1 → Regenerate Image → Start.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Clone complet du template, son disque posé sur le pool Ceph
qm clone 100 300 --name vm-ha-test --full --storage ceph-vm
qm set 300 --ipconfig0 ip=10.<site>.<N>.85/24,gw=10.<site>.<N>.1   # son adresse fixe
qm start 300   # la démarrer

Résultat attendu : transferred 20.0 GiB of 20.0 GiB (100.00%) en une dizaine de secondes (9,6 s sur le lab), puis scsi0: ceph-vm:vm-300-disk-0 dans qm config 300.

2. L'agent invité.

Le template vient de l'image cloud Debian, qui n'a pas l'agent QEMU : qm agent 300 ping répond QEMU guest agent is not running. Installez-le comme au chapitre 2, depuis le Shell du nœud :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Dans la VM, par SSH avec l'utilisateur cloud-init du template
ssh devops@10.<site>.<N>.85                    # puis, dans la VM :
sudo apt-get update                            # la liste des paquets
sudo apt-get install -y qemu-guest-agent       # l'agent invité
sudo systemctl start qemu-guest-agent          # le lancer
exit                                           # retour au nœud
qm agent 300 ping                              # l'agent répond-il ?
echo "code : $?"                               # 0 : oui

Résultat attendu : code : 0. L'atelier 6 en a besoin.

3. La migration. Depuis un autre nœud, lancez un ping continu vers la VM : il mesurera la coupure.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Sur pxe2<N>3 : 300 pings, un toutes les 0,2 s
ping -i 0.2 -c 300 10.<site>.<N>.85

Puis VM 300 → Migrate.

Fenêtre Migrate d'une VM allumée

Mode : Online : la VM tourne, la migration sera à chaud. Il n'y a rien à cocher pour cela. Aucun avertissement de disque local : le disque est sur Ceph.

Conntrack state transporte l'état des connexions suivies par le pare-feu. Target node pxe2<N>2 → Migrate.

Journal de la migration à chaud

La première ligne confirme le réseau : use dedicated network address for sending migration traffic. Puis la VM démarre sur la cible, la mémoire est copiée, et la bascule ne dure que quelques dizaines de millisecondes (42 ms sur cette capture).

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Équivalent CLI
qm migrate 300 pxe2<N>2 --online

Résultat attendu (réseau de migration 10.59.41.x) :

use dedicated network address for sending migration traffic (10.59.41.12)
starting migration of VM 300 to node 'pxe212' (10.59.41.12)
starting VM 300 on remote node 'pxe212'
migration downtime limit: 100 ms
average migration speed: 2.0 GiB/s - downtime 16 ms
migration completed, transferred 552.6 MiB VM-state
migration finished successfully (duration 00:00:06)

Comparez avec l'atelier 2 : aucun disque copié, seulement 553 Mio de mémoire, par le réseau de migration. Côté ping :

300 packets transmitted, 299 received, 0.333333% packet loss, time 61926ms

Un paquet perdu sur 300 : 0,2 seconde de silence, au pire.

L'uptime affiché par Proxmox repart de zéro, et ce n'est pas un redémarrage. Il compte la vie du processus QEMU. Or la VM tourne désormais dans un nouveau processus, sur la cible.

Sur le lab : uptime: 42 avant, uptime: 8 après. Pour prouver que le système n'a pas redémarré, demandez-le à la VM : ssh devops@10.<site>.<N>.85 uptime -s. Sur le lab, elle répondait 2026-10-07 12:06:19 avant, et 2026-10-07 12:06:20 après (heure UTC) : la même date de démarrage, à l'arrondi près.

Validation finale

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Ceph sain, stockage actif, VM 300 en marche sur pxe2<N>2
ceph health                        # la santé de Ceph
pvesm status | grep ceph-vm   # le stockage ceph-vm est actif
pvesh get /nodes/pxe2<N>2/qemu/300/status/current --output-format json-pretty | grep '"status"'   # la VM 300 tourne-t-elle sur le nœud 2 ?
ssh devops@10.<site>.<N>.85 uptime -s   # depuis quand la VM tourne

Résultat attendu : HEALTH_OK ; ceph-vm rbd active ; "status" : "running" ; une date de démarrage antérieure à la migration.


Atelier 6 — Haute disponibilité

Contexte

La migration à chaud protège d'une maintenance planifiée. La haute disponibilité (HA) protège d'une panne subie.

Une VM déclarée ressource HA redémarre seule sur un autre nœud si le sien tombe. C'est possible parce que son disque est sur Ceph, donc accessible depuis les autres nœuds.

Résultat à obtenir : la VM 300 déclarée ressource HA, puis son redémarrage automatique sur un autre nœud après une panne brutale du sien. Ensuite, une mise en maintenance chronométrée du nœud 1, puis le retour.

Chronologie de la panne sur le lab, de la coupure au redémarrage de la VM

La panne de l'étape 2, telle qu'elle s'est déroulée sur le lab. La barre montre à quoi sert chaque période ; la plus longue est une attente volontaire. Cliquez sur un jalon pour lire la ligne de journal correspondante.

Trois nœuds ; le nœud de la VM 300 est coupé, les deux autres gardent le quorum et la VM repart sur un nœud restant grâce au stockage ceph-vm

Le scénario de l'atelier : le nœud qui porte la VM 300 est coupé. Les deux autres gardent le quorum (2 voix sur 3) et la VM est relancée sur l'un d'eux.

C'est possible parce que son disque est dans Ceph, lisible depuis les trois nœuds. Survolez un élément pour lire le résultat du lab.

Arborescence attendue

VM 300 « vm-ha-test » → ressource HA (état souhaité : started)
Panne brutale du nœud qui l'héberge
  ├── Corosync : 2 voix sur 3, le quorum tient
  ├── le nœud est déclaré mort, puis isolé (fence)
  └── la VM redémarre sur un nœud survivant   ← environ 4 min sur le lab

Ce que vous devez faire

  1. Déclarer la VM 300 en ressource HA, état souhaité started.
  2. Simuler une panne brutale du nœud qui l'héberge, et chronométrer : quand le nœud est-il déclaré mort, quand la VM redémarre-t-elle ?
  3. Comprendre le délai : pourquoi le cluster attend-il avant de relancer la VM ?
  4. Mettre le nœud 1 en maintenance, chronométrer la bascule et la coupure du ping, puis le sortir de maintenance et observer le retour.

💡 La HA n'est pas une migration sans coupure : la VM redémarre ailleurs. Il y a une interruption de quelques minutes. C'est le prix d'une panne que personne n'a prévue.

Cliquez pour vous aider

Étape 1 — Déclarer la VM 300 en ressource HA

Datacenter → HA → section Resources → Add.

Fenêtre Add: Resource remplie

VM 300 : la liste propose toutes les VM et tous les conteneurs du cluster, avec leur nœud. Max. Restart 3 : trois redémarrages sur place avant d'abandonner (1 par défaut).

Max. Relocate 1 : un déplacement vers un autre nœud. Request State started.

Failback et Auto-Rebalance sont cochés d'office ; ils n'agissent qu'avec des règles d'affinité. En haut, Arm HA / Disarm HA permet de suspendre toute la HA pendant une maintenance. → Add.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Équivalent CLI
ha-manager add vm:300 --state started --max_restart 3 --max_relocate 1
ha-manager status   # état de la HA

Résultat attendu :

quorum OK
master pxe212 (active, Wed Oct  7 14:13:21 2026)
fencing armed (CRM watchdog active)
lrm pxe211 (idle, watchdog standby, Wed Oct  7 14:13:24 2026)
lrm pxe212 (active, watchdog active, Wed Oct  7 14:13:21 2026)
lrm pxe213 (idle, watchdog standby, Wed Oct  7 14:13:24 2026)
service vm:300 (pxe212, started)

Lisez les lignes. Le master décide pour tout le cluster. Chaque nœud a un lrm qui exécute ses décisions.

Le lrm du nœud qui porte une ressource passe active, et son chien de garde (watchdog) s'arme : si ce nœud perd le cluster, le chien de garde le redémarre. Sur le lab, le master était lui aussi sur pxe212.

Étape 2 — Panne brutale du nœud de la VM

Moment clé de l'atelier. Lisez l'étape en entier avant d'agir. Le nœud que vous allez couper ne se rallumera pas seul : c'est le formateur qui le relancera, depuis l'hôte qui l'héberge.

Repérez le nœud de la VM 300 : celui de la ligne service vm:300 (…, started). Sur le lab, pxe212, où l'atelier 5 l'avait migrée.

Gardez Datacenter → HA ouvert sur un autre nœud. Puis, dans le Shell du nœud de la VM :

Dans le Shell du nœud qui porte la VM 300 :

# Coupure immédiate, sans arrêt propre : l'équivalent d'une panne de courant
echo o > /proc/sysrq-trigger

Pourquoi pas poweroff ? Un arrêt propre est une maintenance : le gestionnaire HA en est prévenu, et il applique sa politique d'arrêt (shutdown_policy).

On ne verrait pas la reprise sur panne. La coupure par sysrq ne prévient personne.

Page HA pendant l'attente : ressource en fence

(3 minutes après la panne). pxe212 porte une croix rouge dans l'arbre. Son lrm affiche old timestamp - dead?.

Le master est passé sur pxe213. La ressource vm:300 est en fence : le cluster s'assure que pxe212 ne fait plus tourner la VM.

Page HA après la reprise : VM démarrée sur pxe213

vm:300 started sur pxe213. En bas, la tâche VM 300 - Start sur pxe213, lancée par la HA, sans personne.

Chronologie sur le lab (panne à 14:13:35, ha-manager status toutes les 5 secondes depuis pxe213, ping toutes les secondes) :

Heure Délai Ce qui se passe
14:13:43 +8 s Total votes: 2 — le quorum tient (2 voix sur 3)
14:14:06 +31 s lrm pxe212 (old timestamp - dead?…), et le master aussi : il était sur pxe212
14:15:35 +2 min 00 pxe213 devient master
14:16:37 +3 min 02 service vm:300 (pxe212, fence)
14:16:43 +3 min 08 fencing: acknowledged → recovery → service vm:300 (pxe213, starting)
14:17:05 +3 min 30 service vm:300 (pxe213, started)
14:17:33 +3 min 58 la VM répond de nouveau au ping

Le journal du nouveau master détaille la fin de la séquence :

Dans le Shell du nœud devenu maître HA (celui qu'indique ha-manager status) :

# Sur le nouveau master
journalctl -u pve-ha-crm --since "-10min" --no-pager -n 12   # les 12 dernières lignes

Résultat attendu (pxe213, extrait) :

successfully acquired lock 'ha_manager_lock'
status change slave => master
node 'pxe212': state changed from 'online' => 'unknown'
service 'vm:300': state changed from 'started' to 'fence'
node 'pxe212': state changed from 'unknown' => 'fence'
successfully acquired lock 'ha_agent_pxe212_lock'
fencing: acknowledged - got agent lock for node 'pxe212'
node 'pxe212': state changed from 'fence' => 'unknown'
service 'vm:300': state changed from 'fence' to 'recovery'
recover service 'vm:300' from fenced node 'pxe212' to node 'pxe213'
service 'vm:300': state changed from 'recovery' to 'started'  (node = pxe213)

Pourquoi attendre ? Le nœud perdu est peut-être seulement coupé du réseau, VM toujours en marche.

Relancer la VM ailleurs tout de suite, ce serait deux exemplaires qui écrivent sur le même disque Ceph. Le cluster attend donc que le verrou du nœud perdu expire : à ce moment-là, son chien de garde l'a forcément redémarré.

got agent lock signifie exactement cela. Ici, l'attente a été plus longue d'une minute, parce que le master était sur le nœud mort : il a d'abord fallu en élire un nouveau.

La VM, elle, a redémarré : ssh devops@10.<site>.<N>.85 uptime -s répondait 2026-10-07 12:17:04 (UTC, soit 14:17:04 à Paris), l'heure de la reprise. Comparez avec l'atelier 5, où la migration à chaud gardait la VM en vie.

Le retour du nœud. Le formateur rallume la VM qui porte pxe212.

Sur le lab, le cluster avait retrouvé ses 3 voix moins d'une minute après, et Ceph son HEALTH_OK dans la foulée (3 OSD up). La VM 300 reste sur pxe213 : sans règle d'affinité, Failback n'a pas de nœud préféré où la ramener.

Étape 3 — Mettre le nœud 1 en maintenance, et chronométrer

On vide le nœud 1 pour une intervention. Avant : un ping continu vers la VM 300, depuis le Shell du nœud 2, pour mesurer la coupure.

Dans le Shell du nœud 2 :

ping -D -i 0.5 10.<site>.<N>.85   # ping horodaté toutes les 0,5 s

Dans le Shell du nœud 1 :

date +%T                                                    # l'heure
ha-manager crm-command node-maintenance enable pxe2<N>1     # puis le nœud 1 en maintenance
watch -n 2 "ha-manager status | grep -E 'lrm|service'"   # suivre les LRM et les services toutes les 2 s

Quand la VM 300 est started ailleurs, quittez watch (Ctrl+C) et relisez le journal.

Dans le Shell du nœud 1 :

journalctl -u pve-ha-crm -u pve-ha-lrm --since "-5min"   # le journal HA des 5 dernières minutes ; à lire : maintenance, vm:300, watchdog

Résultat attendu (les lignes qui comptent) :

14:24:20  (commande envoyée)
14:24:28 pve-ha-lrm: status change active => maintenance
14:24:33 pve-ha-crm: node 'pxe211': state changed from 'online' => 'maintenance'
14:24:33 pve-ha-crm: migrate service 'vm:300' to node 'pxe213' (running)
14:24:43 pve-ha-crm: service 'vm:300': state changed from 'migrate' to 'started'  (node = pxe213)
14:24:44 pve-ha-lrm: watchdog closed (disabled)
Mesure Sur le lab
Commande → VM 300 démarrée ailleurs 23 s
Commande → watchdog closed (disabled) sur le nœud 1 24 s
Coupure du ping une réponse manquée, environ 1 s

Deux constats. La maintenance migre à chaud (running) : la VM ne redémarre pas, contrairement à la panne de l'étape 2.

watchdog closed (disabled) signale que le nœud 1 n'a plus rien à protéger : on peut l'arrêter.

Étape 4 — Sortir de maintenance : le retour

Dans le Shell du nœud 1 :

date +%T                                                    # l'heure
ha-manager crm-command node-maintenance disable pxe2<N>1    # puis sortie de maintenance
watch -n 2 "ha-manager status | grep service"   # suivre les services toutes les 2 s

Résultat attendu :

14:25:14  (commande envoyée)
14:25:24 pve-ha-lrm: status change maintenance => active
14:25:33 pve-ha-crm: node 'pxe211': state changed from 'maintenance' => 'online'
14:25:33 pve-ha-crm: moving service 'vm:300' back to 'pxe211', node came back from maintenance.
14:25:53 pve-ha-crm: service 'vm:300': state changed from 'migrate' to 'started'  (node = pxe211)

La VM 300 est revenue sur le nœud 1, en 39 s, de nouveau à chaud : une réponse au ping manquée, comme à l'aller. C'est le comportement annoncé par la documentation. Le ping lancé sur le nœud 2 s'arrête par Ctrl+C : sur le lab, 240 packets transmitted, 238 received sur l'ensemble, les deux réponses manquées étant les deux bascules.

Validation finale

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Où tourne la VM 300, et le cluster a-t-il gardé son quorum ?
ha-manager status | grep vm:300
pvecm status | grep Quorate   # le cluster a-t-il gardé son quorum ?

Résultat attendu : service vm:300 (pxe2<N>1, started), puis Quorate: Yes.


Dépannage — Erreurs fréquentes

Create Cluster reste grisé, champ du nom en rouge. Nom de cluster de plus de 15 caractères. Remède : Un nom court : cluster-tp (atelier 1).

Le cluster dialogue par vmbr0. Link 0 laissé à sa valeur proposée. Remède : Choisir l'adresse de vmbr1 dans la liste du Link 0 (atelier 1).

pvecm add échoue EOF while reading password. Commande interactive lancée sans terminal. Remède : echo 'motdepasse' | pvecm add … --fingerprint "$FP".

Un nœud affiche Nodes: 1, Config Version: 1, Expected votes: 1, et pvecm add répond authentication key '/etc/corosync/authkey' already exists. Create Cluster cliqué sur ce nœud au lieu de Join Cluster : il a fondé son propre cluster. Remède : Le séparer sans le réinstaller, puis le joindre de nouveau (cours, §2.5).

apt failed during ceph installation (256), précédé de Abort.. Apt n'a pas eu de réponse à [Y/n]. Remède : yes | pveceph install --version tentacle --repository no-subscription.

apt failed during ceph installation, précédé d'une erreur 401. Dépôt Ceph enterprise sans abonnement. Remède : pveceph install --version tentacle --repository no-subscription.

Migration refusée « Cannot migrate VM with local CD/DVD ». ISO locale restée dans le lecteur. Remède : Détacher l'ISO : qm set <vmid> --ide2 none,media=cdrom.

La VM HA ne bascule pas après un poweroff. Arrêt propre traité comme une maintenance. Remède : Simuler la panne par echo o > /proc/sysrq-trigger.

HEALTH_WARN … POOL_TOO_MANY_PGS. Pool créé en ligne de commande, autoscaler en warn. Remède : pveceph pool set <pool> --pg_autoscale_mode on.

HEALTH_WARN avec le seul message noout flag(s) set. Le drapeau noout, posé pour une maintenance, est resté. Remède : ceph osd unset noout : HEALTH_OK une vingtaine de secondes plus tard.

systemctl start ceph-osd@0 échoue ; le journal dit OSD data directory /var/lib/ceph/osd/ceph-0 does not exist; bailing out. Cet OSD n'est pas sur ce nœud : les numéros suivent l'ordre de création des OSD, pas celui des nœuds. Le stop précédent n'a donc rien arrêté.

Remède : ceph osd tree : prendre le numéro affiché sous host <ce nœud>. Effacer l'échec avec systemctl reset-failed ceph-osd@0.

Start request repeated too quickly sur un service. Systemd bloque un service après plusieurs échecs rapprochés. Remède : Corriger la cause, puis systemctl reset-failed <service> avant de relancer.

Récapitulatif des commandes essentielles

Situation Commande
Créer / rejoindre un cluster pvecm create <nom> --link0 <ip-vmbr1> --link1 <ip-vmbr0> / pvecm add <ip-fondateur> --link0 address=<ip-vmbr1-local>
État du cluster / des liens pvecm status / corosync-cfgtool -s
Sortir un nœud du cluster sur le nœud : systemctl stop pve-cluster corosync, pmxcfs -l, effacer /etc/pve/corosync.conf et /etc/corosync/*, killall pmxcfs, systemctl start pve-cluster ; sur un autre nœud : pvecm delnode <nœud> (cours, §2.5)
Migrer une VM (froid / chaud) qm migrate <vmid> <nœud> / qm migrate <vmid> <nœud> --online
Installer / initialiser Ceph yes | pveceph install --version tentacle --repository no-subscription / pveceph init --network … --cluster-network …
Créer MON / MGR / OSD pveceph mon create / pveceph mgr create / pveceph osd create /dev/sdX
État Ceph ceph -s / ceph osd tree / ceph df
Ajouter une ressource HA ha-manager add vm:<vmid> --state started