Aller au contenu
Conteneurs & Orchestration medium

Debuguer une VM Incus bloquée au boot (emergency mode)

17 min de lecture

logo incus

Votre VM Incus apparaît RUNNING dans incus list, mais incus exec et SSH ne répondent plus ? Quand l'agent invité est mort, c'est que l'OS de la VM n'a pas fini de booter : elle est très probablement bloquée en emergency mode. La réponse courte : on ne passe plus par incus exec (qui exige l'agent), on capture la console série avec incus console, et si cela ne suffit pas, on monte le disque de la VM depuis l'hôte pour lire son journal systemd hors-ligne. Ce guide déroule ce diagnostic de bout en bout, jusqu'à un cas réel où un durcissement a briqué le boot EFI.

  • Distinguer un agent mort d'un simple souci SSH : pourquoi une VM RUNNING reste injoignable.
  • Capturer la console série d'une VM qui ne répond plus, malgré l'absence de vrai TTY.
  • Monter le disque d'une VM stoppée depuis l'hôte (ZFS, dir, qcow2) pour lire son journal.
  • Lire le journalctl hors-ligne d'un boot échoué avec journalctl -D.
  • Analyser un cas réel où un sysctl de durcissement a cassé le montage /boot/efi.
  • Mettre en place les filets de sécurité : snapshots, journald persistant, break-glass root.
  • Un hôte Incus avec au moins une VM (pas un conteneur).
  • Un accès root sur l'hôte (les opérations de montage disque l'exigent).
  • Des notions de systemd (cibles, unités) et de partitionnement Linux.

Vous redémarrez une VM, puis plus rien. incus list la montre pourtant bien démarrée :

Fenêtre de terminal
incus list <vm>
# +------+---------+------+------+-----------------+-----------+
# | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
# +------+---------+------+------+-----------------+-----------+
# | <vm> | RUNNING | | | VIRTUAL-MACHINE | 0 |
# +------+---------+------+------+-----------------+-----------+

Notez l'absence d'adresse IPv4 : l'OS n'a pas configuré son réseau. Une tentative d'exécution confirme le diagnostic :

Fenêtre de terminal
incus exec <vm> -- whoami
# Error: VM agent isn't currently running

Le RUNNING d'Incus signifie seulement que QEMU fait tourner la machine. Il ne dit rien sur l'état du système invité. Ici, l'agent (incus-agent) n'a jamais démarré : l'OS s'est arrêté en cours de route. Ce n'est pas un problème SSH, c'est un boot qui n'aboutit pas (brick ou hang).

Pourquoi les réflexes habituels échouent sur une VM

Section intitulée « Pourquoi les réflexes habituels échouent sur une VM »

Sur un conteneur Incus, le dépannage est direct. Sur une VM, plusieurs commandes habituelles tombent à plat, car elles supposent un invité fonctionnel ou un vrai terminal.

CommandeSur une VM bloquéePourquoi
incus exec <vm>VM agent isn't currently runningexige l'agent, donc un OS booté
incus console <vm> --show-loglog série vide ou partielle tampon série n'est pas peuplé comme le log d'un conteneur
incus info <vm> --show-logpeu exploitable pour une VMpas le détail du boot systemd
incus console <vm> en pipeinappropriate ioctl for devicepas de vrai TTY dans un pipe

L'incus exec est mort avec l'agent. Le --show-log, très utile pour un conteneur, ne donne pas le journal interne du boot d'une VM : il faut donc une autre approche. Et rediriger incus console dans un pipe échoue, car la commande réclame un pseudo-terminal.

Quand vous voulez simplement voir l'écran de la VM (le message d'erreur du boot), attachez la console série. Le piège : incus console exige un pseudo-terminal, donc une redirection naïve échoue. On force un pty avec script :

Fenêtre de terminal
timeout 14 script -qec 'incus console <vm>' /dev/null </dev/null 2>&1 | tail -45
  • script -qec '...' /dev/null exécute la commande dans un pty sans enregistrer de fichier (-q silencieux, -e propage le code de sortie, -c lance la commande).
  • timeout 14 coupe au bout de 14 secondes : assez pour capturer l'écran courant.
  • tail -45 ne garde que les dernières lignes, là où s'affiche l'état final.

Ce que vous lirez, selon la panne :

You are in emergency mode. After logging in, type "journalctl -xb" to view
system logs, "systemctl reboot" to reboot, or "exit" to continue bootup.

ou un start job qui ne se termine pas :

[*** ] A start job is running for /boot/efi (1min 30s / no limit)

ou encore un kernel panic. Pour détacher la console interactive proprement, tapez Ctrl+a puis q.

Niveau 2 : lire le journal hors-ligne en montant le disque

Section intitulée « Niveau 2 : lire le journal hors-ligne en montant le disque »

C'est le bon réflexe. Plutôt que de lutter avec une console aveugle, on stoppe la VM, on monte son disque depuis l'hôte et on lit son journal systemd tranquillement. La marche à suivre dépend du backend de stockage.

Identifiez d'abord le driver :

Fenêtre de terminal
incus storage list
# +---------+--------+-------------+---------+
# | NAME | DRIVER | DESCRIPTION | USED BY |
# +---------+--------+-------------+---------+
# | default | zfs | | 12 |
# +---------+--------+-------------+---------+

Sur ZFS, le disque de la VM est un zvol. Une fois la VM stoppée, ce zvol est en volmode=none : aucun device /dev/zdN n'est exposé. On l'expose, on lit ses partitions avec kpartx, puis on monte la racine en lecture seule :

Fenêtre de terminal
incus stop <vm> --force
# Identifier le zvol du disque (suffixe .block)
zfs list -t volume | grep <vm>
Z=<pool>/virtual-machines/<vm>.block
# Exposer le zvol comme device bloc
sudo zfs set volmode=dev "$Z"
# kpartx cree les mappings de partitions (/dev/mapper/zd0p1, zd0p2...)
sudo kpartx -av /dev/zd0
# Monter la racine en lecture seule (p2 = ext4 racine, p1 = EFI vfat)
sudo mkdir -p /mnt/vm
sudo mount -o ro /dev/mapper/zd0p2 /mnt/vm

Après diagnostic, nettoyez dans l'ordre inverse :

Fenêtre de terminal
sudo umount /mnt/vm
sudo kpartx -d /dev/zd0
sudo zfs set volmode=none "$Z"

Une fois la racine montée, lisez le journal du boot échoué. Sur un disque monté, le « boot courant » n'est pas forcément le dernier : listez les boots, puis ciblez l'offset voulu.

Fenêtre de terminal
# Lister les boots enregistres
sudo journalctl -D /mnt/vm/var/log/journal --list-boots
# IDX BOOT ID FIRST ENTRY LAST ENTRY
# -1 a1b2... 2026-06-29 09:14 2026-06-29 09:31
# 0 c3d4... 2026-06-29 09:32 2026-06-29 09:32 <- le boot echoue
# Lire les erreurs de ce boot
sudo journalctl -D /mnt/vm/var/log/journal -b 0 -p err --no-pager
# Trouver la cause directement
sudo journalctl -D /mnt/vm/var/log/journal -b 0 --no-pager \
| grep -iE 'Dependency failed|Failed to mount|emergency'

Le grep final remonte presque toujours la chaîne de causalité : une unité qui échoue, une dépendance non satisfaite, puis la bascule en emergency.

Étude de cas : un durcissement qui brique le boot EFI

Section intitulée « Étude de cas : un durcissement qui brique le boot EFI »

Voici un cas réel, reproductible, qui illustre toute la chaîne. Le journal hors-ligne révèle ceci :

systemd[1]: Mounting boot-efi.mount - /boot/efi...
mount[420]: mount: /boot/efi: unknown filesystem type 'vfat'.
systemd[1]: boot-efi.mount: Mount process exited, code=exited, status=32
systemd[1]: Failed to mount boot-efi.mount - /boot/efi.
systemd[1]: Dependency failed for local-fs.target - Local File Systems.
systemd[1]: Reached target emergency.target - Emergency Mode.

La racine du problème : un durcissement avait posé kernel.modules_disabled=1 via un drop-in /etc/sysctl.d/. Or ce sysctl est un interrupteur à sens unique : une fois à 1, plus aucun module noyau ne peut être chargé, et on ne peut pas revenir à 0 sans reboot.

systemd applique les sysctl très tôt au boot, via systemd-sysctl. Son ordonnancement par rapport au montage de /boot/efi n'est pas garanti : les deux convergent vers sysinit.target sans ordre mutuel strict. Si kernel.modules_disabled=1 est appliqué avant que le montage de /boot/efi ne déclenche le chargement du module vfat, et si ce module n'est pas déjà chargé, alors le montage échoue. Pas de vfat, pas d'EFI montée, local-fs.target en échec, et bascule en emergency mode.

Avant toute opération risquée sur une VM, prenez un snapshot. C'est votre marche arrière :

Fenêtre de terminal
# Avant un changement de boot risque
incus snapshot create <vm> avant-durcissement
# Revenir en arriere si la VM ne boote plus
incus snapshot restore <vm> avant-durcissement

Côté accès, ne verrouillez jamais root sans laisser une voie de secours. L'emergency mode est précisément le moment où vous en avez besoin :

  • un compte de récupération local avec mot de passe,
  • ou un mot de passe GRUB documenté pour éditer la ligne de commande noyau au boot.

Le meilleur debug est celui qu'on n'a pas à faire. Trois réflexes évitent la majorité de ces blocages :

  1. Journald persistant dès le départ

    Sur vos VM de lab, activez Storage=persistent (ou créez /var/log/journal/) dès la création. Sans cela, le journal du boot échoué part en fumée au reboot.

  2. Tester les changements de boot sur une VM jetable

    Tout ce qui touche au boot (/etc/fstab, ligne de commande noyau, sysctl à sens unique) se teste sur une VM jetable protégée par un snapshot, jamais directement sur une machine qui compte.

  3. Trouver le fautif par la trace, pas par reboots à l'aveugle

    Privilégiez le dry-run de votre configuration (état convergé sans reboot) pour repérer un changement dangereux avant qu'il ne brique le boot, plutôt que d'enchaîner les redémarrages au hasard.

  • Une VM RUNNING sans agent n'a pas fini de booter : ce n'est pas un souci SSH.
  • incus exec exige l'agent ; sur une VM bloquée, il renvoie VM agent isn't currently running.
  • Pour une VM, --show-log donne un log série souvent vide : on capture la console série (incus console, détacher avec Ctrl+a q), forcée dans un pty via script.
  • Le bon réflexe : stopper la VM, monter son disque depuis l'hôte (ZFS via volmode=dev + kpartx, dir via losetup -fP, qcow2 via qemu-nbd) et lire le journal avec journalctl -D.
  • volmode=dev masque les partitions du zvol, d'où le recours à kpartx.
  • Un sysctl à sens unique comme kernel.modules_disabled=1 posé trop tôt peut casser un montage (/boot/efi en vfat) et provoquer l'emergency mode.
  • Snapshots, journald persistant et break-glass root sont vos trois filets de sécurité.

FAQ : questions fréquentes sur le debug d'une VM Incus

Section intitulée « FAQ : questions fréquentes sur le debug d'une VM Incus »

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn