« QEMU exited with code 1 » est la manière dont Proxmox hausse les épaules pendant que votre pager hurle. Ce n’est pas une cause racine. C’est un voyant : quelque chose a échoué au démarrage de la VM, et Proxmox rapporte la partie la moins utile de l’histoire.
La solution n’est presque jamais « redémarrer le nœud » (même si oui, cela marche parfois, comme retourner votre portable pour améliorer le Wi‑Fi). La solution consiste à lire la bonne ligne de log, au bon endroit, et à comprendre quel sous‑système a réellement bloqué QEMU : stockage, réseau, permissions, configuration, fonctionnalités du noyau, ou un verrou périmé depuis mardi dernier.
Ce que signifie vraiment « exit code 1 » dans Proxmox
Proxmox lance une VM en construisant une ligne de commande QEMU, puis en la passant à qemu-system-* (généralement via le wrapper /usr/bin/kvm ou directement) dans un contexte de service. Si QEMU retourne immédiatement 1, Proxmox affiche la bannière générique « QEMU exited with code 1 ». Cette ligne n’est pas la panne ; c’est l’épilogue.
Pensez en couches : quel composant a refusé le lancement ?
- Couche configuration : syntaxe de config VM invalide, clés obsolètes, combinaison de périphériques impossible, fichier de disque manquant, mauvais type de contrôleur, adresses PCI dupliquées.
- Couche permissions / sécurité : refus AppArmor/SELinux, propriété/permissions incorrectes sur les images disque, échec de création d’un périphérique tap pour cause de privilèges.
- Couche stockage : zvol ZFS occupé, échec d’activation LVM‑thin, erreurs de map Ceph/RBD, handles NFS périmés, session iSCSI morte, délais d’attente de verrou.
- Couche noyau / virtualisation : KVM non disponible, virtualisation imbriquée absente, incompatibilité des flags CPU, hugepages/NUMA demandés mais non disponibles.
- Couche réseau : bridge manquant, règles de pare‑feu perturbant le tap, discordance MTU n’est généralement pas une panne de démarrage mais les échecs de création de tap le sont.
- Couche ressources : manque de RAM, descripteurs de fichiers épuisés, inotify saturé, limites de processus, espace disque saturé pour les logs ou l’état.
Le geste professionnel est de trouver la première erreur concrète imprimée par QEMU. Tout le reste, c’est du théâtre.
Une citation à garder :
« L’espoir n’est pas une stratégie. » — Gen. H. Norman Schwarzkopf
Vous pouvez redémarrer le nœud et espérer. Ou vous pouvez tracer la panne, la corriger une fois, et dormir.
Playbook de diagnostic rapide (vérifier 1/2/3)
1) Commencez par le journal pour le VMID et l’horodatage exacts
Si vous ne faites qu’une chose : capturez la ligne de log juste avant la mort de QEMU.
- Recherchez : «
cannot open», «Permission denied», «Device or resource busy», «failed to get», «could not set up», «lock timeout», «invalid argument». - Décision : si l’erreur nomme un fichier/chemin/périphérique, vous êtes en terrain stockage/permissions. Si elle nomme un bridge/tap, vous êtes en terrain réseau. Si elle mentionne KVM, CPU ou accel, vous êtes en terrain noyau/virt.
2) Confirmez s’il existe un verrou périmé ou un processus QEMU zombie
Proxmox a un mécanisme de verrou ; QEMU a son cycle de vie PID ; les backends de stockage gardent parfois des périphériques « occupés » après un crash.
- Recherchez :
lock fileprésent,qm listaffiche en cours alors que ce n’est pas le cas, ancienqemu-system-x86_64toujours vivant, zvol ZFS maintenu ouvert. - Décision : s’il y a un verrou périmé, supprimez‑le en toute sécurité (après avoir confirmé que la VM n’est vraiment pas en cours). Si un processus QEMU existe, ne lancez pas un second ; tuez le bon PID et nettoyez.
3) Validez que le backend dont dépend la VM (stockage + réseau) est sain
« Code 1 » signifie souvent que la config VM est correcte et que le monde en dessous ne l’est pas.
- Stockage : vérifiez la santé du pool, thinpool, état Ceph, montage NFS, espace libre/inodes.
- Réseau : vérifiez que le bridge existe, que la création de tap fonctionne, que le pare‑feu ne faille pas au chargement des règles.
- Décision : si le backend est dégradé, réparez le backend en premier. Lancer des VMs sur un substrat cassé, c’est transformer un incident en changement de carrière.
Blague n°1 : Exit code 1 est la façon pour QEMU de dire « Je ne suis pas en colère, je suis juste déçu. »
Où se trouve la vraie erreur : journaux et processus
Couches Proxmox qui émettent des indices
- pvedaemon / pveproxy : journaux de tâches UI, échecs API, contexte d’authentification.
- qemu-server : construit la ligne de commande QEMU ; journalise pourquoi il a refusé d’avancer.
- systemd + journald : chronologie canonique ; montre stderr de QEMU, erreurs de tap, refus de permission.
- pile stockage : ZFS, LVM, Ceph, NFS, iSCSI, multipath ; chacun a ses propres logs et commandes.
- anneau du noyau : échecs KVM, erreurs I/O, VFIO, refus AppArmor, problèmes de bridge.
Comment lire un journal de tâche Proxmox comme un adulte
Le « Task viewer » de l’UI est correct pour les horodatages et messages haut niveau. Le problème est qu’il tronque souvent la ligne stderr exacte de QEMU dont vous aviez besoin. Traitez‑le comme un index, pas comme la source de vérité. Quand vous voyez « QEMU exited with code 1 », pivotez immédiatement vers journalctl et la config de la VM et les objets de stockage.
Ce que vous traquez
Vous voulez la première ligne d’erreur concrète qui nomme une ressource. Exemples de « bonnes » erreurs :
could not open disk image /dev/zvol/rpool/data/vm-101-disk-0: Device or resource busyfailed to create tun device: Operation not permittedkvm: failed to initialize: No such file or directoryCannot access storage 'ceph-rbd' (500)unable to parse value of 'net0'
Les erreurs « mauvaises » sont des enveloppes génériques. Ignorez‑les. Remontez dans les logs.
Tâches pratiques : commandes, sorties, décisions (12+)
Tout ce qui suit est prévu pour être exécuté sur un nœud Proxmox avec les paquets typiques. Remplacez 101 par votre VMID et ajustez les noms de stockage.
Tâche 1 : Récupérer la dernière tentative de démarrage d’une VM depuis journald
cr0x@server:~$ journalctl -u pvedaemon -u pveproxy -u pvescheduler --since "15 min ago" | tail -n 120
Dec 26 10:21:33 pve01 pvedaemon[2214]: starting task UPID:pve01:00005A2B:0001B8F2:676D1E5D:qmstart:101:root@pam:
Dec 26 10:21:34 pve01 pvedaemon[2214]: VM 101 qmp command failed - got timeout
Dec 26 10:21:34 pve01 pvedaemon[2214]: VM 101 - unable to open disk image '/dev/zvol/rpool/data/vm-101-disk-0': Device or resource busy
Dec 26 10:21:34 pve01 pvedaemon[2214]: VM 101 - QEMU exited with code 1
Ce que ça signifie : vous avez une ressource spécifique : un chemin zvol est occupé. C’est du stockage, pas « Proxmox qui fait des siennes ».
Décision : cessez de regarder la config VM ; cherchez qui garde le zvol ouvert (Tâche 7) et si la VM est à moitié démarrée (Tâche 2).
Tâche 2 : Vérifier si Proxmox pense que la VM tourne, et si un PID QEMU existe
cr0x@server:~$ qm status 101
status: stopped
cr0x@server:~$ pgrep -a -f "qemu-system.*-id 101"
Ce que ça signifie : si qm status dit stopped mais que vous voyez encore un processus QEMU, vous avez un état périmé ou une tentative de démarrage précédente qui n’est pas morte proprement.
Décision : si QEMU existe, inspectez‑le (Tâche 3) et arrêtez‑le proprement ou tuez‑le après avoir confirmé que c’est le bon.
Tâche 3 : Inspecter la ligne de commande QEMU exacte que Proxmox a tenté d’exécuter
cr0x@server:~$ qm showcmd 101 --pretty
/usr/bin/kvm \
-id 101 \
-name 'app-prod-01,debug-threads=on' \
-machine type=pc-q35-8.1+pve0 \
-m 8192 \
-smp 4,sockets=1,cores=4,maxcpus=4 \
-drive if=none,id=drive-scsi0,format=raw,file=/dev/zvol/rpool/data/vm-101-disk-0,cache=none,aio=io_uring,discard=on \
-device virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5 \
-netdev tap,id=net0,ifname=tap101i0,script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown,vhost=on \
-device virtio-net-pci,mac=BC:24:11:AA:BB:CC,netdev=net0,bus=pci.0,addr=0x12 \
...
Ce que ça signifie : vous pouvez maintenant reproduire ou raisonner sur les échecs : chemin du disque, mode de cache, backend aio, type de machine, configuration netdev.
Décision : si une option semble suspecte (ex. aio=io_uring sur un noyau ancien), vous avez une expérience concrète : changez une chose, retentez.
Tâche 4 : Lire la configuration VM pour erreurs de parse et dérive
cr0x@server:~$ cat /etc/pve/qemu-server/101.conf
boot: order=scsi0;net0
cores: 4
memory: 8192
name: app-prod-01
net0: virtio=BC:24:11:AA:BB:CC,bridge=vmbr0,firewall=1
scsi0: rpool:vm-101-disk-0,discard=on,cache=none,aio=io_uring
scsihw: virtio-scsi-pci
Ce que ça signifie : la config est stockée dans pmxcfs et doit être cohérente à l’échelle du cluster. Les petites coquilles (surtout dans les lignes args:) peuvent faire échouer QEMU de façon brutale.
Décision : si vous voyez des paramètres exotiques modifiés manuellement, prévoyez de revenir temporairement aux valeurs par défaut pour isoler le problème.
Tâche 5 : Suivre les logs de qemu-server pour le VMID
cr0x@server:~$ journalctl -t pve-qemu-server -S "30 min ago" | grep -E "VM 101|101" | tail -n 80
Dec 26 10:21:34 pve01 pve-qemu-server[58312]: VM 101 - start failed: unable to open disk image '/dev/zvol/rpool/data/vm-101-disk-0': Device or resource busy
Dec 26 10:21:34 pve01 pve-qemu-server[58312]: VM 101 - failed to run /usr/bin/kvm: exit code 1
Ce que ça signifie : confirme que c’est QEMU qui échoue, pas un bug du scheduler ou un problème d’API/auth.
Décision : pivotez vers une investigation au niveau stockage (Tâches 6–9).
Tâche 6 : Vérifier la santé du pool ZFS et les erreurs récentes
cr0x@server:~$ zpool status -x
all pools are healthy
cr0x@server:~$ zpool status rpool
pool: rpool
state: ONLINE
status: Some supported features are not enabled on the pool.
action: Enable all features using 'zpool upgrade'. Once this is done,
the pool may no longer be accessible by software that does not support the features.
scan: scrub repaired 0B in 00:12:41 with 0 errors on Thu Dec 26 09:10:05 2025
config:
NAME STATE READ WRITE CKSUM
rpool ONLINE 0 0 0
nvme0n1 ONLINE 0 0 0
errors: No known data errors
Ce que ça signifie : si vous voyez des erreurs read/write/checksum, votre « code 1 » peut être le premier symptôme d’une instabilité de stockage. Un pool sain signifie cherchez des zvol occupés/hold/locks.
Décision : si le pool est dégradé, stoppez le churn de VM et réparez le pool d’abord (remplacez disque, resilver, scrub).
Tâche 7 : Trouver quel processus tient un zvol ou périphérique disque ouvert
cr0x@server:~$ ls -l /dev/zvol/rpool/data/vm-101-disk-0
lrwxrwxrwx 1 root root 10 Dec 26 10:20 /dev/zvol/rpool/data/vm-101-disk-0 -> ../../zd16
cr0x@server:~$ lsof /dev/zd16 | head
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
qemu-syst 4121 root 15u BLK 230,16 0t0 123 /dev/zd16
Ce que ça signifie : le disque est occupé parce qu’un processus QEMU l’a déjà ouvert. Cela peut être une instance VM précédente, un job de sauvegarde, ou une migration bloquée.
Décision : inspectez le PID 4121, confirmez qu’il est sûr de le terminer, puis arrêtez‑le proprement (Tâche 8). Ne supprimez pas les verrous à l’aveugle tant que vous n’avez pas identifié le détenteur du périphérique.
Tâche 8 : Arrêter un processus VM bloqué (préférer gracieux, puis forcer)
cr0x@server:~$ qm stop 101
trying to stop VM 101...
VM 101 stopped
cr0x@server:~$ kill -TERM 4121
cr0x@server:~$ sleep 2; ps -p 4121 -o pid,cmd
PID CMD
Ce que ça signifie : si le processus disparaît après TERM, parfait. S’il reste, il peut être bloqué en I/O non interruptible (état D), ce qui renvoie au stockage.
Décision : s’il est en état D, n’abusez pas de kill -9 et appelez cela « réglé ». Examinez le chemin I/O (NFS/iSCSI/Ceph). S’il s’agit d’un processus normal bloqué, un kill contrôlé peut être acceptable après validation.
Tâche 9 : Vérifier les verrous VM Proxmox et les supprimer en sécurité
cr0x@server:~$ qm config 101 | grep -i lock
lock: backup
cr0x@server:~$ qm unlock 101
unlocking VM 101
Ce que ça signifie : Proxmox peut verrouiller une VM pendant une sauvegarde, migration, snapshot, etc. Si le verrou reste après un job échoué, les démarrages peuvent échouer ou se comporter de façon imprévisible.
Décision : ne déverrouillez qu’après confirmation que l’opération liée n’est réellement pas en cours (vérifiez logs de sauvegarde, tâches en cours et processus). Déverrouiller en plein milieu d’une sauvegarde provoque des snapshots partiels et des réunions gênantes.
Tâche 10 : Confirmer l’espace libre et les inodes sur le stockage
cr0x@server:~$ df -hT /var/lib/vz /var/log
Filesystem Type Size Used Avail Use% Mounted on
rpool/ROOT/pve-1 zfs 96G 74G 22G 78% /
rpool/var-log zfs 10G 9.8G 256M 98% /var/log
cr0x@server:~$ df -i /var/log
Filesystem Inodes IUsed IFree IUse% Mounted on
rpool/var-log 524288 11234 513054 3% /var/log
Ce que ça signifie : un /var/log presque plein (ou la racine) peut empêcher QEMU d’écrire état, logs ou sockets. Les inodes comptent aussi, surtout sur des montages ext4.
Décision : si l’usage est élevé, tournez les logs, étendez les datasets, ou déplacez les services verbeux. Ne « supprimez pas des logs au hasard » à moins de vouloir effacer les preuves nécessaires.
Tâche 11 : Vérifier la disponibilité de KVM et si la virtualisation est activée
cr0x@server:~$ ls -l /dev/kvm
crw-rw---- 1 root kvm 10, 232 Dec 26 08:02 /dev/kvm
cr0x@server:~$ kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used
cr0x@server:~$ dmesg | tail -n 20
[ 112.345678] kvm: VMX supported
[ 112.345689] kvm: Nested virtualization enabled
Ce que ça signifie : l’absence de /dev/kvm ou des échecs ici peuvent conduire QEMU à sortir tôt, parfois avec des messages trompeurs. Sur certains systèmes QEMU peut tourner sans KVM mais les configs Proxmox peuvent supposer des fonctionnalités KVM.
Décision : si KVM est indisponible, vérifiez le BIOS/UEFI VT‑x/AMD‑V, les modules noyau (kvm_intel/kvm_amd), et si vous êtes dans un hyperviseur sans nested virt.
Tâche 12 : Chercher des refus AppArmor qui bloquent QEMU
cr0x@server:~$ journalctl -k --since "30 min ago" | grep -i apparmor | tail -n 20
Dec 26 10:21:34 pve01 kernel: audit: type=1400 apparmor="DENIED" operation="open" profile="pve-qemu-kvm" name="/mnt/pve/nfs-share/images/101/vm-101-disk-0.qcow2" pid=58345 comm="qemu-system-x86" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Ce que ça signifie : QEMU est bloqué par un profil de sécurité lorsqu’il tente d’ouvrir une image disque. C’est une cause racine nette.
Décision : corrigez le chemin de stockage et les attentes du profil AppArmor (souvent en vous assurant que le stockage est configuré via Proxmox, monté sous le bon chemin, et non monté ad‑hoc), ou ajustez la politique si vous savez exactement ce que vous faites.
Tâche 13 : Valider les prérequis de création de bridge et tap
cr0x@server:~$ ip link show vmbr0
4: vmbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 5a:1e:4c:00:11:22 brd ff:ff:ff:ff:ff:ff
cr0x@server:~$ ip tuntap show | head
tap101i0: tap persist vnet_hdr
Ce que ça signifie : l’absence de vmbr0 ou l’impossibilité de créer des taps peut provoquer un arrêt instantané de QEMU. Si tap101i0 existe déjà de façon inattendue, il peut s’agir d’une interface résiduelle d’un démarrage échoué.
Décision : si le bridge est manquant, réparez le réseau hôte. Si un tap existe mais que la VM est arrêtée, supprimez le tap périmé (prudemment) après avoir confirmé qu’aucun processus ne l’utilise.
Tâche 14 : Vérifier l’activation échouée du stockage LVM‑thin
cr0x@server:~$ lvs -a -o +devices
LV VG Attr LSize Pool Origin Data% Meta% Devices
pve/data pve twi-aotz-- <1.82t 78.12 2.34 /dev/sda3(0)
vm-101-disk-0 pve Vwi-a-tz-- 64.00g data 91.02 /dev/sda3(12345)
cr0x@server:~$ lvchange -ay pve/vm-101-disk-0
1 logical volume(s) in volume group "pve" now active
Ce que ça signifie : si l’activation échoue ou si le thinpool est plein, QEMU peut échouer à ouvrir le périphérique bloc. La thin provisioning peut mentir jusqu’à ce qu’elle ne puisse plus.
Décision : si le thinpool est proche de 100% ou si les métadonnées sont épuisées, il faut libérer de l’espace ou étendre le pool avant de démarrer quoi que ce soit.
Les coupables habituels : schémas de panne et comment les prouver
1) Problèmes de chemin de stockage : « cannot open … » est presque toujours littéral
Quand QEMU ne peut pas ouvrir le disque, il sort. Pas de disque, pas de VM. Causes :
- ZFS zvol tenu ouvert par un processus traînard
- handle NFS périmé après bascule de serveur
- échec de mapping Ceph/RBD ou mismatch d’auth
- LVM‑thin à court d’espace ou métadonnées pleines
- Permissions erronées sur un stockage monté comme répertoire
Prouvez‑le en vérifiant : le chemin exact dans qm showcmd, l’existence du device/fichier, et la santé du backend (commandes ZFS/LVM/Ceph/NFS).
2) Verrouillage et concurrence : Proxmox vous protège… jusqu’à ce que non
Proxmox utilise des verrous pour éviter que deux opérations ne modifient une VM simultanément (backup + start, snapshot + migration, etc.). Après crashs ou jobs échoués, des verrous peuvent rester.
Prouvez‑le en lisant la config VM pour une entrée lock: et en vérifiant les tâches en cours dans le journal. Supprimez les verrous uniquement lorsque vous êtes sûr que l’opération liée est morte.
3) Configuration réseau : échecs tap/bridge tuent la VM tôt
Si QEMU ne peut pas créer ou attacher le tap, il sort avec code 1. Causes courantes : bridge manquant, syntaxe cassée dans /etc/network/interfaces, scripts de pare‑feu qui échouent, ou capacités/privilèges altérés.
Prouvez‑le en vérifiant ip link show, présence de vmbrX, et lignes journald mentionnant tap, tun, bridge ou vhost.
4) Fonctionnalités noyau et accélérateurs : KVM, VFIO, hugepages
QEMU est flexible, mais les configs VM typiques de Proxmox partent du principe que KVM et certains flags CPU sont disponibles. Si vous tentez un passthrough GPU (VFIO), les modes d’échec se multiplient : groupes IOMMU, problèmes de reset de périphérique, permissions sur /dev/vfio/*, ROM problématiques.
Prouvez‑le en corrélant les stderr QEMU avec les messages noyau (journalctl -k, dmesg), et en validant que les périphériques existent et sont liés au bon driver.
5) Flags « d’optimisation » qui mordent : backends AIO, modes de cache, discard
Des options comme aio=io_uring et des modes de cache agressifs peuvent être fantastiques — jusqu’à ce qu’elles rencontrent un noyau ancien, un système de fichiers bizarre, ou un backend de stockage qui ne supporte pas ce que vous demandez. Alors QEMU quitte immédiatement et vous vous disputez avec une ligne de config copiée d’un billet de blog.
Blague n°2 : Rien n’est plus permanent qu’un réglage de performance « temporaire » ajouté un vendredi.
Trois mini‑histoires d’entreprise (erreurs, retours de flamme, victoires ennuyeuses)
Incident n°1 : La mauvaise hypothèse (et un verrou qui n’était pas le problème)
Une entreprise de taille moyenne gérait un cluster Proxmox pour des services internes. Un matin, une VM critique ne démarrait pas : « QEMU exited with code 1 ». L’ingénieur d’astreinte a vu lock: backup dans la config VM et a supposé l’évidence : verrou périmé. Ils ont fait qm unlock, puis ont cliqué « Start » dans l’UI plusieurs fois parce que l’UI est là et l’impatience est une ressource renouvelable.
Cela a encore échoué. La situation était pire : ils avaient retiré un verrou légitime alors qu’un job de snapshot côté stockage était toujours actif sur le serveur NFS. Ce job n’était pas visible comme tâche Proxmox car il était déclenché par des scripts de l’équipe stockage. QEMU échouait parce que le fichier qcow2 était temporairement verrouillé côté NFS et retournait des métadonnées incohérentes pendant la fenêtre de snapshot.
Le « code 1 » n’était que le dernier domino. L’indice réel était dans le log noyau : messages intermittents « stale file handle » et timeouts NFS autour des tentatives de démarrage. Mais ces lignes n’ont pas été vérifiées car la théorie du verrou semblait satisfaisante.
La correction fut ennuyeuse : ne pas tenter de démarrer la VM pendant la fenêtre de snapshot du stockage, monter NFS avec des options sensées pour leur environnement, et ajouter une vérification pré‑vol dans les runbooks opérationnels : valider que le backend stockage n’est pas en maintenance avant de supprimer des verrous. Ils ont aussi changé la politique : les verrous Proxmox ne sont supprimés qu’après confirmation qu’aucune opération liée n’est en cours quelque part dans la pile.
Ensuite, l’équipe a ajouté un petit script qui affiche des signaux de « readiness stockage » (réactivité NFS, santé Ceph, statut ZFS) lors des actions de démarrage VM. Cela n’a pas empêché tous les incidents, mais a évité la répétition du même incident, ce qui est le vrai KPI.
Incident n°2 : L’optimisation qui a mal tourné (io_uring rencontre la réalité)
Une autre organisation voulait améliorer les performances disque pour une base de données. Quelqu’un a lu que io_uring était l’avenir et a déployé aio=io_uring et quelques réglages de cache sur une flotte de VMs via l’automatisation. Le changement semblait anodin : un seul paramètre par config VM.
Une semaine plus tard, après qu’une mise à jour du noyau ait été retardée sur un sous‑ensemble de nœuds, une migration a posé une VM sur un nœud plus ancien. La VM a commencé à échouer avec « QEMU exited with code 1 ». Le log montrait « invalid argument » autour de la définition du drive. Ce n’était pas évident car la VM démarrée correctement sur d’autres nœuds.
La cause racine : le combo noyau/QEMU plus ancien ne supportait pas le backend AIO choisi pour ce chemin de stockage. Le paramètre était valide sur les builds plus récents mais sans sens dans l’ancien environnement. Le cluster est devenu un champ de mines de compatibilité : les configs VM supposaient des fonctionnalités non uniformes entre nœuds.
La solution n’était pas d’abandonner l’optimisation. C’était d’arrêter de faire comme si le cluster était homogène quand il ne l’était pas. Ils ont imposé des baselines de version des nœuds, ajouté un contrôle de type CI qui rejette les changements de config VM nécessitant des fonctionnalités non supportées sur un nœud du cluster, et limité l’optimisation à un pool de nœuds labellisés « known‑good ».
Les gains de performance sont restés. Les pannes surprises ont disparu. La leçon n’était pas « ne pas optimiser », mais « optimisez comme si vous seriez d’astreinte pour les cas limites ».
Incident n°3 : La pratique ennuyeuse qui a sauvé la mise (discipline des journaux)
Une troisième équipe avait pour politique que chaque échec de démarrage de VM soit diagnostiqué à partir des logs avant que quiconque ne redémarre quoi que ce soit. Cela paraissait pédant. Ça l’était, dans le bon sens.
Pendant un incident d’alimentation, un nœud est revenu avec un état réseau légèrement différent. Quelques VMs ont échoué à démarrer avec « QEMU exited with code 1 ». Les gens étaient prêts à redémarrer le nœud de nouveau, en supposant que « les bridges ne sont pas montés correctement ».
La personne d’astreinte a suivi la politique : journalctl -t pve-qemu-server puis journalctl -k. L’erreur était précise : échec de création du périphérique tap parce que le système avait atteint une limite de processus par utilisateur dans un coin bizarre déclenché par un agent de monitoring forkant massivement au démarrage. Redémarrer le nœud aurait masqué temporairement le problème et garanti une récurrence.
Ils ont relevé les limites systemd appropriées, corrigé la config de l’agent de monitoring, et redémarré uniquement les services affectés. Les VMs ont démarré, l’incident est clos, et l’équipe n’a pas ajouté « rebooter encore » au runbook.
La pratique ennuyeuse — considérer les logs comme preuve primaire — a évité une boucle de tâtonnements. Elle a aussi produit un rapport d’incident propre avec une vraie cause racine. Les auditeurs aiment ça. Et les ingénieurs qui aiment dormir aussi.
Erreurs courantes : symptôme → cause racine → correctif
1) Symptôme : « Device or resource busy » sur un zvol ou disque
Cause racine : ancien processus QEMU garde le périphérique ouvert ; job de sauvegarde/migration le tient ; chemin I/O bloqué dans le noyau.
Correctif : trouvez le détenteur avec lsof / fuser, arrêtez la VM ou le processus fautif, puis réessayez. Si le détenteur est en état D, investiguez la santé du backend stockage (NFS/Ceph/iSCSI) plutôt que de jouer au whack‑a‑mole avec les PIDs.
2) Symptôme : « Permission denied » à l’ouverture d’une image disque sur un stockage en répertoire
Cause racine : permissions/propriété incorrectes sur le chemin de l’image ; stockage monté en dehors des points attendus par Proxmox ; refus AppArmor.
Correctif : assurez‑vous que le stockage est configuré via Proxmox, confirmez le point de montage (/mnt/pve/<storage>), corrigez les permissions des fichiers, vérifiez les refus AppArmor et alignez les chemins.
3) Symptôme : « could not create tap device » / « Operation not permitted »
Cause racine : bridge manquant, scripts de pare‑feu qui échouent, capacités modifiées, ou interface tap résiduelle causant des collisions.
Correctif : vérifiez que vmbr0 existe et est up ; consultez les logs du pare‑feu ; supprimez le tap périmé seulement après confirmation qu’aucun processus ne l’utilise ; validez /etc/network/interfaces et rechargez le réseau prudemment.
4) Symptôme : Échec de démarrage seulement sur un nœud
Cause racine : dérive des nœuds : versions noyau/QEMU différentes, flags CPU manquants, connectivité stockage différente, montages périmés, multipath cassé.
Correctif : comparez les versions et configs clés des nœuds, standardisez les paquets, validez l’accès au stockage depuis ce nœud, et évitez les flags de config nécessitant des fonctionnalités plus récentes sauf si le cluster est uniforme.
5) Symptôme : « kvm: failed to initialize » ou « failed to get KVM »
Cause racine : virtualisation désactivée dans le BIOS/UEFI, modules noyau manquants, exécution à l’intérieur d’une VM sans nested virt, ou permissions sur /dev/kvm.
Correctif : activez VT‑x/AMD‑V, chargez les modules, assurez‑vous que nested virt est activé en amont, validez la propriété/groupe de /dev/kvm.
6) Symptôme : « Cannot access storage … (500) »
Cause racine : erreur du plugin de stockage Proxmox : cible NFS/Ceph inaccessible, échec d’auth, montage périmé, keyrings manquants.
Correctif : confirmez que le stockage est en ligne depuis le nœud (état du montage, santé ceph), réparez l’auth, remontez, puis retentez le démarrage VM.
7) Symptôme : « invalid argument » dans les options drive/net
Cause racine : option QEMU incompatible avec la version QEMU du nœud ; mauvaise ligne args: ; backend ne supporte pas AIO/cache demandé.
Correctif : simplifiez : retirez les args personnalisés, revenez aux valeurs par défaut, puis réintroduisez les changements un par un. Standardisez les versions QEMU au travers du cluster.
8) Symptôme : La VM démarre en CLI mais pas via l’UI/API
Cause racine : différences de contexte de permission, variables d’environnement, ou hooks au moment de la tâche (firewall, scripts pre‑start) qui échouent.
Correctif : reproduisez via qm start et inspectez les logs de tâche ; vérifiez les scripts hook et le pare‑feu ; confirmez que le même user/contexte est utilisé.
Listes de contrôle / plan pas à pas
Pas à pas : de « code 1 » à la cause racine en moins de 10 minutes
- Capturez l’horodatage de l’échec de démarrage (le log de tâche UI suffit).
- Récupérez les lignes journald autour de ce moment pour
pve-qemu-serveret les messages noyau. Identifiez la première chaîne d’erreur concrète. - Exécutez
qm showcmdpour la VM et localisez les chemins disque, la config netdev, et les options inhabituelles. - Vérifiez le statut de verrou VM dans la config ; ne déverrouillez qu’après confirmation que l’opération liée n’est pas en cours.
- Vérifiez la santé du backend :
- ZFS :
zpool status - LVM :
lvset utilisation du pool - Ceph : santé du cluster et bases du mapping RBD
- NFS : réactivité du montage et erreurs noyau
- ZFS :
- Cherchez les restes : PID QEMU existant, interface tap périmée, détenteur zvol traînant.
- Faites un changement à la fois, retentez, et revérifiez les logs immédiatement.
Checklist : stockage d’abord, car c’est là que ça coûte le plus
- Le chemin disque existe et est accessible depuis le nœud qui démarre la VM.
- Aucun processus ne tient le périphérique bloc/fichier image ouvert de façon inattendue.
- La santé du pool est OK (pas de vdevs dégradés, pas d’erreurs read/write).
- L’espace libre est raisonnable, y compris metadata thinpool et partitions racine/log.
- Pas de handles NFS périmés ni de problèmes de session iSCSI dans les logs noyau.
Checklist : sanity réseau
- Le bridge existe et est up (
ip link show vmbr0). - Les périphériques tap sont créés/supprimés proprement ; pas de collisions de noms tap résiduels.
- Les scripts pare‑feu ne plantent pas (erreurs journald).
Checklist : compatibilité versions et fonctionnalités
- Les versions QEMU sont consistantes à travers les nœuds du cluster, ou la config VM évite les fonctionnalités spécifiques à un nœud.
- KVM est disponible et activé (
/dev/kvmexiste, modules chargés). - Les périphériques passthrough sont liés correctement (VFIO/IOMMU) si utilisés.
Faits intéressants et contexte historique (éléments qui aident au débogage)
- QEMU a démarré en 2003 comme émulateur CPU rapide et est devenu la référence de virtualisation dans les écosystèmes Linux.
- KVM est arrivé dans le noyau Linux en 2007, transformant QEMU d’« émulation pure » à virtualisation assistée matériellement sur x86.
- Les configs VM de Proxmox vivent dans un système de fichiers de cluster (pmxcfs) sous
/etc/pve, d’où la réplication des modifications et la sensibilité au split‑brain. - Exit code 1 est volontairement générique : QEMU l’utilise souvent pour « failed to initialize or parse arguments », ce qui peut signifier n’importe quoi, du disque manquant à l’option non supportée.
- Les périphériques virtio existent parce qu’émuler du matériel réel coûte cher : virtio est une interface paravirtuelle conçue pour réduire l’overhead et améliorer les performances.
- io_uring s’est démocratisé dans Linux autour de 2019+ et continue d’évoluer ; mélanger noyaux et versions QEMU peut rendre des options valides invalides sur certains nœuds.
- Les zvols ZFS sont des périphériques bloc backés par des datasets, et ils peuvent être « occupés » par des détenteurs que vous ne verrez pas dans l’UI Proxmox — les outils au niveau processus sont essentiels.
- LVM‑thin peut sur‑allouer, ce qui est génial jusqu’à ce que non ; les conditions d’espace épuisé se manifestent par des pannes VM étranges plutôt que des avertissements clairs.
- Les périphériques tap sont une fonctionnalité du noyau Linux, et les échecs de création sont souvent des problèmes de privilèges/capacités, pas un « bug Proxmox ».
FAQ
Pourquoi Proxmox n’affiche‑t‑il que « QEMU exited with code 1 » ?
Parce que Proxmox rapporte le statut de sortie de QEMU, pas le détail stderr sous‑jacent. L’erreur exploitable se trouve typiquement dans journald sous pve-qemu-server ou dans les logs noyau.
Où se trouve la meilleure ligne pour trouver la vraie erreur ?
journalctl -t pve-qemu-server autour de l’horodatage du démarrage, plus journalctl -k pour les refus et problèmes de périphériques au niveau noyau.
Est‑il sûr d’exécuter qm unlock chaque fois qu’une VM ne démarre pas ?
Non. Le déverrouillage n’est sûr qu’après avoir prouvé que l’opération liée (sauvegarde/migration/snapshot) n’est active nulle part. Sinon, vous risquez corruption ou snapshots incohérents.
Ma VM démarre sur le nœud A mais échoue sur le nœud B. Que suspecter en premier ?
Dérive de nœud : versions QEMU/noyau différentes, accès stockage manquant sur le nœud B, ou politiques de sécurité différentes. Comparez la sortie de qm showcmd et vérifiez la joignabilité du stockage depuis le nœud B.
Un /var/log
Oui. QEMU et Proxmox doivent écrire des logs, sockets et états runtime. Un système de fichiers plein peut se traduire par des échecs de démarrage étranges, parfois encore rapportés comme « code 1 ».
« Device or resource busy » signifie‑t‑il toujours une VM en cours d’exécution ?
Souvent, mais pas toujours. Cela peut aussi signifier un job de sauvegarde, une instance QEMU coincée, ou un verrou côté stockage (surtout sur NFS/Ceph). Utilisez lsof/fuser pour prouver.
Comment reproduire l’échec en toute sécurité sans deviner ?
Utilisez qm showcmd <vmid> pour voir la ligne de commande QEMU exacte, puis concentrez‑vous sur la ressource mentionnée dans les logs (chemin disque, interface tap, KVM). Ne parcourez pas au hasard les options.
Est‑ce une bonne idée d’ajouter des args: personnalisés aux configs Proxmox ?
Seulement si vous acceptez la charge opérationnelle : compatibilité des nœuds, tests d’upgrade, et que le vous‑de‑la‑nuit devra le déboguer à 3h du matin. Les valeurs par défaut existent pour une raison.
Quelle est la façon la plus rapide de savoir si c’est stockage vs réseau vs KVM ?
Lisez la première chaîne d’erreur concrète. Les erreurs de chemin disque pointent vers le stockage. Les erreurs tap/bridge pointent vers le réseau. Les erreurs KVM/VFIO pointent vers le noyau/fonctionnalités virt.
Conclusion : étapes pratiques suivantes
Quand Proxmox dit « QEMU exited with code 1 », ne traitez pas cela comme un mystère. Traitez‑le comme un pointeur vers des preuves que vous n’avez pas encore collectées. Votre travail consiste à extraire la première ligne d’erreur spécifique, puis à valider le sous‑système qu’elle nomme.
Étapes que vous pouvez faire aujourd’hui :
- Standardisez un runbook : journald d’abord, puis verrous/processus, puis santé du backend.
- Réduisez la dérive du cluster : alignez les versions noyau/QEMU sur les nœuds ou contraignez les fonctionnalités VM.
- Auditez les réglages « performance » dans les configs VM et retirez ceux que vous ne pouvez pas justifier en cas d’incident.
- Ajoutez une habitude : chaque « code 1 » obtient une note de cause racine. Pas un contournement. Une note.
Si vous faites cela de façon consistante, « QEMU exited with code 1 » cessera d’être un incident et redeviendra une étape de diagnostic routinière. Là où elle doit être.