← Retour
Informatique

Revue technique — Mise en place et upgrade d'un cluster Proxmox 2 nœuds

Cédrix · 20/05/2026

1/ 7 j  ·  1/ 14 j  ·  1/ 30 j  lecteurs

Périmètre : déploiement d’un cluster Proxmox VE à 2 nœuds avec arbitre QDevice, puis upgrade major version (PVE 8 → 9, Debian 12 → 13) Période couverte : 2026-04-30 → 2026-05-19 Statut final : opérationnel, quorum stable à 3 votes, kernel 7.0.2-4-pve actif sur les deux nœuds Document : revue technique pour relecture par les pairs


1. Synthèse exécutive

Un cluster Proxmox VE a été déployé entre deux serveurs HP identiques (node-a, node-b) le 30 avril 2026, puis renforcé par un arbitre externe (QDevice) hébergé sur un Raspberry Pi (arbiter-01). Le 19 mai 2026, les deux nœuds ont été migrés en place de PVE 8.4 / Debian 12 vers PVE 9.1 / Debian 13, sans interruption longue des charges de travail (seul le reboot final de chaque nœud a impacté les guests, ~3-5 min).

Points forts :

  • Cluster quorate à 3 votes, résilient à la perte d’un nœud
  • Upgrade major réussi des deux nœuds avec stratégie in-place
  • Procédure désormais documentée et reproductible

Points d’attention :

  • Le join du second nœud a été effectué manuellement (4 étapes) plutôt que via pvecm add, en raison d’une contrainte SSH non-interactif. Cette procédure manuelle est plus risquée et mériterait d’être ré-évaluée.
  • Le dépôt fournisseur matériel (MCP/HPE) n’est plus compatible Debian 13 et reste désactivé. Risque à moyen terme sur la gestion du matériel (RAID, firmware).
  • Le premier reboot post-upgrade a démarré sur l’ancien kernel — un update-grub manuel a été nécessaire avant le second reboot.

Recommandations principales : voir section 6.


2. Contexte et architecture

2.1 Qu’est-ce qu’un cluster Proxmox ?

Proxmox VE (Virtual Environment) est un hyperviseur open source basé sur Debian, KVM et LXC. Un cluster Proxmox regroupe plusieurs nœuds (serveurs) pour partager une configuration commune, migrer des machines virtuelles d’un nœud à l’autre, et offrir de la haute disponibilité (HA).

Trois briques techniques sont au cœur du cluster :

  • pmxcfs (Proxmox Cluster File System) : un système de fichiers FUSE monté sur /etc/pve/. Tout fichier écrit dans ce répertoire est automatiquement répliqué sur tous les nœuds. C’est l’unique source de vérité pour la configuration du cluster.
  • corosync : la couche réseau qui assure la communication temps-réel entre les nœuds (élection de leader, propagation des écritures, détection des pannes).
  • Le quorum : un cluster ne peut prendre de décisions (démarrer une VM, écrire dans /etc/pve/) que si une majorité de nœuds est joignable. C’est le mécanisme qui évite le split-brain — une situation où deux moitiés du cluster, séparées par une coupure réseau, prendraient des décisions contradictoires.

2.2 Le problème spécifique d’un cluster à 2 nœuds

Avec 2 nœuds, la majorité requise est 2/2. Si un nœud tombe, il ne reste qu’un vote, et le cluster perd le quorum : /etc/pve/ passe en lecture seule, les VMs ne peuvent plus démarrer, et la migration est bloquée.

La solution standard est d’ajouter un tiers-arbitre (QDevice) qui apporte un troisième vote sans héberger de VMs. Le quorum passe alors à 2/3, et la perte d’un nœud devient tolérable. C’est cette architecture qui a été retenue ici.

2.3 Infrastructure cible

Rôle Hôte IP Matériel OS
Nœud Proxmox 1 node-a 10.0.0.10 HP avec contrôleur Smart Array P440ar Debian 13 / PVE 9.1.16
Nœud Proxmox 2 node-b 10.0.0.11 HP avec contrôleur Smart Array P440ar Debian 13 / PVE 9.1.16
QDevice (arbitre) arbiter-01 10.0.0.20 Raspberry Pi Raspbian 11

2.4 État final du cluster

Name:             cluster-prod
Config Version:   3
Transport:        knet
Secure auth:      on
Expected votes:   3
Total votes:      3
Quorum:           2
Flags:            Quorate Qdevice

Nodeid      Votes    Qdevice  Name
0x00000001      1    A,V,NMW  10.0.0.10 (node-a)
0x00000002      1    A,V,NMW  10.0.0.11 (node-b)
0x00000000      1             Qdevice (arbiter-01)

Lecture du tableau : trois votes au total, quorum à 2. Les flags A,V,NMW signifient Alive, Voting, Not-Master-Wins — chaque nœud est actif, dispose d’un droit de vote, et accepte l’arbitrage du QDevice en cas d’égalité.


3. Phase 1 — Création du cluster (2026-04-30)

3.1 Initialisation sur node-a

La création du cluster se fait depuis un seul nœud, ici node-a. Une seule commande :

pvecm create cluster-prod

Cette commande génère la clé d’authentification corosync (/etc/corosync/authkey), écrit la configuration initiale dans /etc/pve/corosync.conf, et démarre les services. À ce stade, le cluster existe mais ne contient qu’un seul nœud.

3.2 Join manuel de node-b

Normalement, on ajoute un nœud à un cluster existant en exécutant pvecm add <IP du premier nœud> depuis le futur nouveau nœud. La commande négocie l’authentification, copie la authkey, met à jour corosync.conf, et démarre les services dans le bon ordre.

Pourquoi cela n’a pas pu être utilisé ici ? pvecm add demande interactivement le mot de passe root du nœud cible. Dans le contexte d’opération (SSH non-interactif piloté depuis un poste distant), il n’était pas possible de fournir ce mot de passe. Le join a donc été reconstitué manuellement, en quatre étapes qui reproduisent ce que pvecm add fait en interne.

Étape 1 — Confiance SSH node-bnode-a

Le nouveau nœud doit pouvoir se connecter en SSH sans mot de passe au nœud existant. On ajoute la clé publique de node-b aux clés autorisées de node-a :

# Récupérer la clé publique de node-b
ssh node-b 'cat /root/.ssh/id_rsa.pub'

# L'ajouter dans les authorized_keys de node-a
ssh node-a "echo '<clé>' >> /root/.ssh/authorized_keys"

Étape 2 — Déclarer node-b dans corosync.conf sur node-a

On édite /etc/pve/corosync.conf pour ajouter le second nœud dans la liste, en incrémentant config_version. Corosync utilise ce numéro pour détecter et propager les changements de configuration.

nodelist {
  node { name: node-a  nodeid: 1  ring0_addr: 10.0.0.10  quorum_votes: 1 }
  node { name: node-b  nodeid: 2  ring0_addr: 10.0.0.11  quorum_votes: 1 }
}

Le fichier vivant dans /etc/pve/ est répliqué automatiquement, mais corosync lit en réalité /etc/corosync/corosync.conf au démarrage. Il faut donc le copier explicitement et signaler le rechargement :

cp /etc/pve/corosync.conf /etc/corosync/corosync.conf
corosync-cfgtool -R

Étape 3 — Configurer node-b

Sur le nouveau nœud, on récupère la clé d’authentification corosync depuis node-a (la confiance SSH étant déjà établie) et on écrit une corosync.conf identique :

# Depuis node-b
scp root@10.0.0.10:/etc/corosync/authkey /etc/corosync/authkey
chmod 400 /etc/corosync/authkey

Sans cette authkey partagée, les deux nœuds parlent corosync sans pouvoir se reconnaître mutuellement.

Étape 4 — Démarrer les services dans le bon ordre

C’est l’étape la plus piégeuse. pmxcfs (qui sert /etc/pve/) et corosync (qui communique avec les autres nœuds) ont une dépendance d’ordre stricte : pmxcfs doit démarrer en premier. Cette contrainte est codée en dur dans l’unit systemd (Before=corosync.service). Si on inverse, pmxcfs démarre en mode standalone (sans cluster) et il faut tout recommencer.

# Supprimer la base de données standalone existante sur node-b
rm /var/lib/pve-cluster/config.db*

# Démarrage dans l'ordre
systemctl start pve-cluster
sleep 3
systemctl start corosync
sleep 10
pvecm status

Au démarrage, pmxcfs détecte que corosync est actif, rejoint le CPG (Closed Process Group — un canal de communication garanti ordonné), et réplique le contenu de /etc/pve/ depuis node-a. Le cluster est alors à 2 nœuds.

3.3 Analyse — Join manuel

Avantages : maîtrise complète des étapes, pas de dépendance à un canal interactif, utile en cas de debug.

Inconvénients :

  • Procédure invasive (suppression de config.db*)
  • Risque élevé en cas d’erreur d’ordre ou de copie de corosync.conf
  • Pas de validation intégrée comme dans pvecm add

Alternative non explorée : pvecm add peut être scripté avec sshpass ou via un fichier expect, ou en passant temporairement par une console SSH interactive (ssh -t). Cette piste devrait être préférée pour les déploiements futurs.


4. Phase 2 — QDevice (tiers-arbitre)

4.1 Justification

Comme expliqué en 2.2, un cluster à 2 nœuds est fragile vis-à-vis du quorum. L’ajout d’un QDevice transforme un quorum 2/2 en quorum 2/3, ce qui rend le cluster tolérant à la perte d’un nœud.

Concrètement, le QDevice est un démon (corosync-qnetd) qui tourne sur une machine externe. Les nœuds Proxmox embarquent un client (corosync-qdevice) qui dialogue avec ce démon par TLS et lui demande un vote. Le QDevice répond en fonction de la connectivité qu’il observe — si un nœud isolé tente de prendre le pouvoir, il refuse de voter pour lui, ce qui empêche le split-brain.

4.2 Choix de l’hôte arbitre

Un Raspberry Pi (arbiter-01, 10.0.0.20, Raspbian 11) a été retenu. Le démon corosync-qnetd est très léger (consommation négligeable) et n’a pas besoin d’être sur du matériel haut de gamme. Le seul vrai critère est la disponibilité réseau et l’indépendance par rapport aux nœuds Proxmox (pas dans le même rack ou la même alimentation, idéalement).

4.3 Installation

Sur arbiter-01 : installer le serveur QDevice.

apt install corosync-qnetd
systemctl enable --now corosync-qnetd

Pré-requis SSHpvecm qdevice setup (étape suivante) opère via SSH depuis node-a vers arbiter-01. Il faut donc une confiance SSH root sans mot de passe :

# Récupérer la clé root de node-a et l'ajouter sur arbiter-01
NODE_A_KEY=$(ssh node-a 'cat /root/.ssh/id_rsa.pub')
ssh arbiter-01 "echo '$NODE_A_KEY' >> /root/.ssh/authorized_keys"

# Pré-remplir known_hosts sur node-a pour éviter l'invite "yes/no"
ssh node-a 'ssh-keyscan -H 10.0.0.20 >> /root/.ssh/known_hosts'

Sur les deux nœuds Proxmox : installer le client QDevice.

apt install corosync-qdevice

Depuis node-a : lancer la configuration automatique. Une seule commande suffit pour configurer les deux nœuds en même temps.

pvecm qdevice setup 10.0.0.20

pvecm qdevice setup orchestre tout :

  • initialise la PKI NSS (certificats TLS) sur le serveur qnetd
  • génère et fait signer les certificats sur chaque nœud
  • démarre et active corosync-qdevice sur les deux nœuds
  • met à jour corosync.conf (passage à config_version: 3)

À l’issue, pvecm status affiche les 3 votes et le flag Qdevice.

4.4 Analyse

Cette phase s’est déroulée sans incident. pvecm qdevice setup est une commande robuste qui gère l’ensemble du workflow — contrairement à l’ajout de nœud, ici il n’y a pas eu besoin de procédure manuelle.

Réserve : la dépendance SSH root sans mot de passe entre node-a et arbiter-01 est une surface d’attaque. À envisager : restreindre la clé à une commande spécifique via command= dans authorized_keys, ou utiliser un compte non-root + sudo.


5. Phase 3 — Upgrade PVE 8 → 9 (2026-05-19)

5.1 Contexte de l’upgrade

Cette phase a consisté à faire passer les deux nœuds d’une version majeure à la suivante : PVE 8.4 → PVE 9.1, ce qui implique également le passage de Debian 12 (Bookworm) à Debian 13 (Trixie). C’est un upgrade lourd : changement du noyau, de quasi tous les paquets système, et des dépôts APT.

Proxmox fournit un outil de pré-vérification, pve8to9, qui scanne le système et signale les obstacles avant l’upgrade (paquets incompatibles, configuration à migrer, etc.). C’est l’équivalent d’une checklist générée automatiquement.

5.2 État avant / après

Nœud PVE avant PVE après OS avant OS après Kernel après
node-a 8.4.19 9.1.16 Debian 12 Bookworm Debian 13 Trixie 7.0.2-4-pve
node-b 8.4.19 9.1.16 Debian 12 Bookworm Debian 13 Trixie 7.0.2-4-pve

5.3 Pré-requis identifiés par pve8to9

Les deux nœuds présentaient exactement les mêmes pré-requis (matériel identique, même historique d’installation).

Niveau Problème Solution appliquée
FAIL Méta-paquet systemd-boot installé apt remove --purge systemd-boot systemd-boot-efi
WARN Bootloader EFI removable non géré par GRUB debconf-set-selections + réinstallation grub-efi-amd64
NOTICE mcp.list référence une suite stretch/current incompatible Dépôt désactivé pendant l’upgrade (renommé .disabled)
NOTICE LVM autoactivation activée sur local-lvm pve-lvm-disable-autoactivation --assume-yes

Petit aparté sur systemd-boot : c’est un bootloader minimaliste, alternative à GRUB pour les systèmes EFI. Le paquet systemd-boot était installé sur les deux nœuds, mais il n’était pas le bootloader actif — les machines démarraient en GRUB (Boot0017 → /boot/efi/EFI/proxmox/). La présence du paquet sans utilisation réelle est une situation héritée qui aurait pu faire prendre des décisions à pve8to9 sur le mauvais bootloader. La désinstallation est sans risque dans ce cas précis, mais cette nuance mérite d’être vérifiée systématiquement avant toute désinstallation similaire.

5.4 Procédure appliquée

Procédure identique sur node-a et node-b, exécutée séquentiellement (un nœud à la fois pour préserver le quorum pendant les reboots) :

# 1. Fix systemd-boot (FAIL bloquant)
apt remove --purge systemd-boot systemd-boot-efi -y

# 2. Fix GRUB EFI removable
echo 'grub-efi-amd64 grub2/force_efi_extra_removable boolean true' \
    | debconf-set-selections -v -u
DEBIAN_FRONTEND=noninteractive apt install --reinstall grub-efi-amd64 -y

# 3. Désactiver le dépôt fournisseur (MCP)
mv /etc/apt/sources.list.d/mcp.list /etc/apt/sources.list.d/mcp.list.disabled

# 4. Mise à jour Debian 12 complète (pré-upgrade)
apt update && DEBIAN_FRONTEND=noninteractive apt full-upgrade -y

# 5. Migrer LVM autoactivation
/usr/share/pve-manager/migrations/pve-lvm-disable-autoactivation --assume-yes

# 6. Bascule des sources vers Trixie
sed -i 's/bookworm/trixie/g' /etc/apt/sources.list
sed -i 's/bookworm/trixie/g' /etc/apt/sources.list.d/pve-install-repo.list
sed -i 's/bookworm/trixie/g' /etc/apt/sources.list.d/pve-enterprise.list
sed -i 's/bookworm/trixie/g' /etc/apt/sources.list.d/ceph.list
apt update

# 7. Upgrade vers PVE 9 / Debian 13
DEBIAN_FRONTEND=noninteractive apt \
    -o Dpkg::Options::='--force-confold' \
    -o Dpkg::Options::='--force-confdef' \
    full-upgrade -y

# 8. Mise à jour de GRUB et reboot
update-grub
reboot

Les étapes 1 à 5 préparent le terrain sur Debian 12 (paquets propres, dépôts cohérents). L’étape 6 modifie les sources APT pour pointer vers Trixie. L’étape 7 fait le travail de bascule proprement dit — c’est elle qui prend du temps et qui peut générer des incidents.

5.5 Incidents rencontrés

Incident 1 — base-files bloqué sur prompt interactif

Lors d’un upgrade Debian, certains paquets contiennent des fichiers de configuration qui ont pu être modifiés localement (ici /etc/issue). dpkg demande alors interactivement s’il faut garder la version locale ou la remplacer par celle du paquet. En mode non-interactif (DEBIAN_FRONTEND=noninteractive seul), cette question reste suspendue en attente de réponse et bloque l’upgrade.

La solution est d’ajouter explicitement la politique à dpkg : --force-confold (conserver l’existant) combiné à --force-confdef (utiliser le défaut quand pas d’arbitrage clair). Ces options ont été ajoutées à apt via -o Dpkg::Options::='...'.

Incident 2 — Kernel 6.8.x conservé après le premier reboot

Sur les deux nœuds, le premier reboot post-upgrade a démarré sur l’ancien kernel 6.8.x au lieu du nouveau 7.0.2-4-pve. Le système était officiellement en PVE 9 / Debian 13, mais tournait sur un ancien noyau, ce qui est une situation incohérente.

Cause : Proxmox dispose d’un outil dédié (proxmox-boot-tool) qui gère la synchronisation entre les kernels installés et le bootloader. Sur ces deux nœuds, cet outil n’était pas configuré (absence de /etc/kernel/proxmox-boot-uuids) — c’est GRUB qui gère le boot directement. Le grub.cfg présent dans la partition EFI redirige vers /boot/grub/grub.cfg via une directive configfile, mais ce dernier n’avait pas été régénéré automatiquement à la fin de l’upgrade.

Solution : un update-grub manuel pour régénérer la configuration, puis un second reboot.

# Vérifier que l'entrée par défaut pointe sur le nouveau kernel
grep 'vmlinuz' /boot/grub/grub.cfg | head -1
# Attendu : linux /boot/vmlinuz-7.0.2-4-pve ...
reboot

Incident 3 — pve8to9 exécuté sans --full

L’option --full active des vérifications supplémentaires, notamment sur la compatibilité cgroup v2 pour chaque conteneur. Sur node-a (42 guests), ce check aurait été long. Le choix a été fait de ne pas l’exécuter. Aucun problème de cgroup n’a été constaté en post-upgrade, mais c’était un pari — sur un environnement avec des conteneurs anciens (LXC pré-Debian 11), ce pari aurait pu se retourner.

5.6 Stratégie guests sur node-a — in-place

42 guests étaient actifs sur node-a au moment de l’upgrade.

Choix retenu : upgrade in-place. Les guests sont restés actifs pendant tout apt full-upgrade (le passage de paquets sur l’hôte n’affecte pas les VMs/conteneurs en cours d’exécution), et n’ont été interrompus que par le reboot final (~3-5 min par nœud).

Alternative non retenue : migration live vers node-b avant upgrade de node-a, puis retour après. Cela aurait permis un upgrade sans aucune interruption visible côté guests, mais aurait significativement allongé la fenêtre globale (deux migrations massives en plus). Sur 42 guests dont certains sont gros, on parle d’une à plusieurs heures de migration supplémentaire.

Les 17 guests avec onboot=0 ne sont pas redémarrés automatiquement après le reboot — comportement attendu et intentionnel. Ce flag indique explicitement qu’un guest ne doit démarrer que sur action humaine.

5.7 Statut post-upgrade du dépôt fournisseur (MCP/HPE)

Le dépôt HPE MCP (stretch/current) reste désactivé. Il ne supporte pas Debian 13 Trixie — la suite stretch/current était déjà obsolète sous Debian 12 et HPE n’a pas publié de version Trixie au moment de l’upgrade.

Impact actuel : nul. Les outils HPE (ssacli notamment, pour piloter le contrôleur Smart Array) restent fonctionnels parce qu’ils étaient déjà installés (paquets gelés à la version Debian 12).

Risque : pas de mise à jour des outils HPE (correctifs de sécurité, support de nouveau firmware). À ré-évaluer périodiquement.


6. Recommandations

6.1 Court terme

  1. Documenter une procédure officielle de join non-interactif — soit via sshpass/expect pour pvecm add, soit en formalisant la procédure manuelle en 4 étapes utilisée ici. À ce jour, le seul savoir-faire est dans ce document.
  2. Surveiller le dépôt HPE pour une version Trixie — mettre en place un check mensuel ou un abonnement aux releases HPE MCP.

6.2 Moyen terme

  1. Restreindre la clé SSH node-aarbiter-01 — actuellement, accès root complet. Utiliser une restriction command="..." ou un compte dédié pour limiter la surface d’attaque.
  2. Évaluer le passage à proxmox-boot-tool — l’absence de gestion de l’ESP par cet outil a causé l’incident kernel post-upgrade. Standardiser sa mise en place éviterait ce type de surprise lors des prochains upgrades.
  3. Préparer une stratégie de migration live pour les futurs upgrades — avec 42 guests sur un nœud, l’in-place reste viable, mais une approche par migration live offrirait du zéro-downtime applicatif et serait alignée avec ce qu’on attendrait d’un cluster HA.

6.3 Long terme

  1. Envisager un troisième nœud Proxmox plutôt qu’un QDevice — un Pi en arbitre est fonctionnel mais ne contribue pas aux capacités de calcul/stockage. Un troisième nœud apporterait à la fois la résilience de quorum et plus de marge de manœuvre pour le HA et les migrations.
  2. Mettre en place une supervision corosync — surveillance de pvecm status, des flags Quorate/Qdevice, et alerting sur perte de quorum ou désynchronisation NMW.

7. Annexes

7.1 Services Proxmox impliqués

Service Rôle Ordre de démarrage
pve-cluster (pmxcfs) Filesystem FUSE partagé /etc/pve/ 1 (en premier)
corosync Couche réseau du cluster (knet, authkey, CPG) 2
corosync-qdevice Client QDevice (vote externe) 3
pvedaemon API Proxmox locale 4
pveproxy Interface web HTTPS (port 8006) 5

7.2 Commandes de vérification

pvecm status        # état du cluster, quorum, flags
pvecm nodes         # liste des nœuds et leur état
ls /etc/pve/nodes/  # répertoires répliqués via pmxcfs
corosync-cfgtool -s # état des liens corosync

7.3 Glossaire

Terme Définition
CPG Closed Process Group. Canal de communication corosync qui garantit l’ordre et la livraison des messages entre les nœuds.
ESP EFI System Partition. Partition FAT contenant le bootloader EFI.
HA High Availability. Mécanisme Proxmox qui redémarre automatiquement les VMs/CT d’un nœud tombé sur un autre nœud du cluster.
NMW Not-Master-Wins. Mode d’arbitrage du QDevice : il ne se déclare jamais maître, il vote pour ceux qui restent connectés.
PKI NSS Infrastructure à clés publiques utilisée par corosync-qnetd pour signer les certificats TLS des clients.
Pmxcfs Proxmox Cluster File System. FS FUSE qui sert /etc/pve/ et le réplique en temps réel via corosync.
Quorum Majorité requise pour que le cluster autorise une écriture ou un changement d’état.
Split-brain Situation où deux moitiés d’un cluster, séparées par une coupure réseau, prennent des décisions contradictoires.
Partager : ✉ Mail X in 🐘
Commentaires

Aucun commentaire pour l'instant. Soyez le premier !

Laisser un commentaire
Un code de vérification sera envoyé à votre adresse email.