“QEMU exited with code 1” es la manera en que Proxmox encoge de hombros mientras su sistema de alertas grita. No es la causa raíz. Es una luz de estado: algo falló al arrancar la VM, y Proxmox está mostrando la parte menos útil de la historia.
La solución casi nunca es “reiniciar el nodo” (aunque sí, a veces funciona, como darle la vuelta al portátil para mejorar el Wi‑Fi). La solución es leer la línea de log correcta, en el lugar correcto, y entender qué subsistema bloqueó realmente a QEMU: almacenamiento, red, permisos, configuración, características del kernel, o un bloqueo antiguo desde el martes pasado.
Qué significa realmente «exit code 1» en Proxmox
Proxmox inicia una VM construyendo una línea de comando para QEMU, y luego se la pasa a qemu-system-* (normalmente vía el wrapper /usr/bin/kvm o directamente) bajo un contexto de servicio. Si QEMU devuelve inmediatamente 1, Proxmox imprime el banner genérico “QEMU exited with code 1”. Esa línea no es la falla; es el epílogo.
Piensa en capas: ¿qué componente rechazó el arranque?
- Capa de configuración: sintaxis de VM inválida, claves obsoletas, combinación de dispositivos imposible, archivo de disco ausente, tipo de controlador incorrecto, direcciones PCI duplicadas.
- Capa de permisos / seguridad: denegación de AppArmor/SELinux, propiedad/permisos incorrectos en imágenes de disco, fallo al crear dispositivo tap por privilegios.
- Capa de almacenamiento: zvol de ZFS ocupado, fallo de activación de LVM-thin, errores de mapeo Ceph/RBD, handles NFS obsoletos, sesión iSCSI caída, tiempos de espera de bloqueo.
- Capa de kernel / virtualización: KVM no disponible, virtualización anidada ausente, incompatibilidad de flags CPU, hugepages/NUMA fijadas pero no disponibles.
- Capa de red: bridge ausente, reglas de firewall interfiriendo con tap, desajuste de MTU no suele causar fallo de arranque pero los fallos al crear tap sí lo hacen.
- Capa de recursos: falta de RAM, descriptores de archivo agotados, inotify agotado, límites de procesos, espacio lleno en almacenamiento usado para logs o estado.
El movimiento profesional es encontrar la primera línea de error concreta que QEMU imprimió. Todo lo demás es teatro.
Una cita que vale la pena poner en la pared:
“La esperanza no es una estrategia.” — Gen. H. Norman Schwarzkopf
Puedes reiniciar el nodo y confiar en la esperanza. O puedes rastrear la falla, arreglarla de una vez y dormir tranquilo.
Guía de diagnóstico rápido (revisa 1/2/3)
1) Empieza por el journal para el VMID y la marca temporal exacta
Si haces solo una cosa: captura la línea de log justo antes de que QEMU muera.
- Busca: “
cannot open”, “Permission denied”, “Device or resource busy”, “failed to get”, “could not set up”, “lock timeout”, “invalid argument”. - Decisión: si el error nombra un archivo/ruta/dispositivo, estás en el terreno de almacenamiento/permisos. Si nombra un bridge/tap, estás en red. Si menciona KVM, CPU o accel, estás en kernel/virtualización.
2) Confirma si existe un bloqueo obsoleto o un proceso QEMU zombi
Proxmox tiene un mecanismo de bloqueos; QEMU tiene su propio ciclo de vida de PID; los backends de almacenamiento a veces dejan dispositivos “ocupados” tras un crash.
- Busca:
lock filepresente,qm listmuestra en ejecución mientras no lo está, antiguoqemu-system-x86_64aún vivo, zvol de ZFS abierto. - Decisión: si hay un bloqueo obsoleto, quítalo de forma segura (tras confirmar que la VM no está realmente en ejecución). Si existe un proceso QEMU, no inicies un segundo; mata el PID correcto y limpia.
3) Valida que el backend del que depende la VM (almacenamiento + red) esté sano
“Código 1” a menudo significa que la configuración de la VM está bien y el mundo debajo no lo está.
- Almacenamiento: revisa salud del pool, thinpool, estado de Ceph, montaje NFS, espacio libre/inodos.
- Red: verifica que el bridge exista, que la creación de tap funcione, que el firewall no falle al cargar reglas.
- Decisión: si el backend está degradado, arregla el backend primero. Iniciar VMs sobre una base rota es la manera de convertir un incidente en un cambio de carrera.
Broma #1: El código de salida 1 es la forma de QEMU de decir “No estoy enfadado, solo estoy decepcionado.”
Dónde vive el error real: logs y procesos
Capas de Proxmox que emiten pistas
- pvedaemon / pveproxy: logs de tareas UI, fallos de API, contexto de autenticación.
- qemu-server: construye la línea de comando de QEMU; registra por qué se negó a continuar.
- systemd + journald: línea temporal canónica; muestra stderr de QEMU, errores de tap, denegaciones de permisos.
- pila de almacenamiento: ZFS, LVM, Ceph, NFS, iSCSI, multipath; cada uno con sus propios logs y comandos.
- anillo del kernel: fallos KVM, errores I/O, VFIO, denegaciones AppArmor, problemas de bridge.
Cómo leer un log de tarea de Proxmox como un adulto
El “Visor de tareas” de la UI es decente para marcas temporales y mensajes de alto nivel. El problema es que a menudo trunca la línea exacta de stderr de QEMU que necesitabas. Trátalo como un índice, no como la fuente de la verdad. Cuando veas “QEMU exited with code 1”, pivota inmediatamente a journalctl y al config de la VM y a los objetos de almacenamiento.
Lo que estás buscando
Quieres la primera línea de fallo que nombre un recurso. Ejemplos de errores “buenos”:
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'
Los errores “malos” son envoltorios genéricos. Ignóralos. Sigue desplazándote hacia arriba.
Tareas prácticas: comandos, salidas, decisiones (12+)
Todo lo siguiente está diseñado para ejecutarse en un nodo Proxmox con paquetes habituales. Reemplaza 101 por tu VMID y ajusta nombres de almacenamiento.
Task 1: Extraer el último intento de arranque de una VM desde 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
Qué significa: tienes un recurso específico: una ruta zvol está ocupada. Eso es almacenamiento, no “Proxmox actuando raro”.
Decisión: deja de mirar la configuración de la VM; investiga quién mantiene el zvol abierto (Tarea 7) y si la VM está medio arrancada (Tarea 2).
Task 2: Comprobar si Proxmox cree que la VM está en ejecución y si existe un PID QEMU
cr0x@server:~$ qm status 101
status: stopped
cr0x@server:~$ pgrep -a -f "qemu-system.*-id 101"
Qué significa: si qm status dice stopped pero aún ves un proceso QEMU, tienes un estado obsoleto o un intento de arranque previo que no murió correctamente.
Decisión: si existe QEMU, inspecciónalo (Tarea 3) y apágalo limpiamente o mátalo tras confirmar que es el correcto.
Task 3: Inspeccionar la línea de comando exacta de QEMU que Proxmox intentó ejecutar
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 \
...
Qué significa: ahora puedes reproducir o razonar sobre fallos: ruta de disco, modo de caché, backend aio, tipo de máquina, configuración netdev.
Decisión: si una opción parece sospechosa (por ejemplo, aio=io_uring en un kernel antiguo), tienes un experimento concreto: cambia una cosa y reintenta.
Task 4: Leer la configuración de la VM en busca de errores de parseo y divergencias
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
Qué significa: la configuración se guarda en pmxcfs y debe ser consistente en todo el clúster. Errores pequeños (especialmente en líneas args:) pueden provocar fallos fatales en QEMU.
Decisión: si ves ajustes exóticos editados a mano, planifica revertir a valores por defecto temporalmente para aislar el problema.
Task 5: Seguir los logs de qemu-server para el 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
Qué significa: confirma que es QEMU el que falla, no un bug del scheduler o un problema de autenticación de la API.
Decisión: pivota a la investigación a nivel de almacenamiento (Tareas 6–9).
Task 6: Verificar la salud del pool ZFS y errores recientes
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
Qué significa: si ves errores de lectura/escritura/checksum, tu “code 1” podría ser el primer síntoma de inestabilidad en almacenamiento. Pool sano significa buscar zvol ocupado/holders/bloqueos.
Decisión: si el pool está degradado, detén el churn de VMs y arregla el pool primero (reemplazar disco, resilver, scrub).
Task 7: Encontrar qué proceso mantiene un zvol o dispositivo de disco abierto
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
Qué significa: el disco está ocupado porque un proceso QEMU ya lo tiene abierto. Podría ser una instancia previa de la VM, un trabajo de backup, o una migración atascada.
Decisión: inspecciona el PID 4121, confirma que es seguro terminarlo, y luego detenlo limpiamente (Tarea 8). No borres bloqueos sin entender quién mantiene el dispositivo.
Task 8: Parar un proceso VM atascado (primero suave, luego forzar)
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
Qué significa: si el proceso desaparece tras TERM, perfecto. Si se queda, puede estar en estado de I/O no interrumpible (estado D), lo que apunta de nuevo al almacenamiento.
Decisión: si está en estado D, no abuses de kill -9 y lo llames “arreglado”. Investiga la ruta de I/O (NFS/iSCSI/Ceph). Si es un proceso bloqueado normal, un kill controlado puede ser aceptable tras validación.
Task 9: Comprobar bloqueos de VM en Proxmox y eliminarlos de forma segura
cr0x@server:~$ qm config 101 | grep -i lock
lock: backup
cr0x@server:~$ qm unlock 101
unlocking VM 101
Qué significa: Proxmox puede bloquear una VM durante backup, migración, snapshot, etc. Si el bloqueo permanece tras un job fallido, los arranques pueden fallar o comportarse de forma impredecible.
Decisión: desbloquea solo tras confirmar que la operación relacionada no está realmente en ejecución (revisa logs de backup, tareas en curso y procesos). Desbloquear a mitad de un backup provoca snapshots parciales y reuniones incómodas.
Task 10: Confirmar espacio libre de almacenamiento y disponibilidad de inodos
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
Qué significa: un /var/log casi lleno (o el fs raíz) puede causar que QEMU falle cuando intenta escribir estado, logs o sockets. Los inodos también importan, especialmente en montajes con ext4.
Decisión: si el uso es alto, rota logs, expande datasets o mueve servicios muy verbosos. No “borres logs al azar” a menos que quieras eliminar la evidencia que necesitas.
Task 11: Comprobar disponibilidad de KVM y si la virtualización está realmente habilitada
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
Qué significa: la ausencia de /dev/kvm o fallos aquí pueden provocar que QEMU salga temprano, a veces con mensajes engañosos. En algunos sistemas QEMU seguirá ejecutándose sin KVM, pero las configuraciones de Proxmox pueden asumir funciones de KVM.
Decisión: si KVM no está disponible, verifica BIOS/UEFI VT-x/AMD-V, módulos del kernel (kvm_intel/kvm_amd), y si estás dentro de un hipervisor sin virtualización anidada.
Task 12: Buscar denegaciones de AppArmor que bloqueen a 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
Qué significa: QEMU está siendo bloqueado por un perfil de seguridad al intentar abrir una imagen de disco. Esa es una causa raíz clara.
Decisión: arregla la ruta de almacenamiento y las expectativas del perfil AppArmor (a menudo asegurando que el almacenamiento esté configurado vía Proxmox, montado bajo la ruta correcta y no como un montaje ad-hoc), o ajusta la política si sabes exactamente lo que haces.
Task 13: Validar bridges y prerrequisitos para la creación de 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
Qué significa: la ausencia de vmbr0 o la imposibilidad de crear dispositivos tap pueden hacer que QEMU salga al instante. Si tap101i0 ya existe inesperadamente, puede ser una interfaz sobrante de un intento de arranque fallido.
Decisión: si falta el bridge, arregla la red del host. Si el tap existe pero la VM está detenida, elimina el tap obsoleto (con cuidado) tras confirmar que ningún proceso lo usa.
Task 14: Buscar activación fallida de almacenamiento en 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
Qué significa: si la activación falla o el thinpool está lleno, QEMU puede fallar al abrir el dispositivo de bloque. La provisión fina puede mentir hasta que ya no puede.
Decisión: si el thinpool está cerca del 100% o la metadata se agotó, necesitas liberar espacio o ampliar el pool antes de arrancar cualquier cosa.
Los sospechosos habituales: patrones de fallo y cómo demostrarlos
1) Problemas con la ruta de almacenamiento: “cannot open …” casi siempre es literal
Cuando QEMU no puede abrir el disco, sale. Sin disco, no hay VM. Causas incluyen:
- ZFS zvol retenido por un proceso persistente
- handle obsoleto de NFS tras failover del servidor
- fallo de mapeo Ceph/RBD o desajuste de autenticación
- LVM-thin sin espacio o metadata llena
- Permisos incorrectos en un almacenamiento montado como directorio
Demuéstralo comprobando: la ruta exacta en qm showcmd, existencia del dispositivo/archivo, y la salud del backend (comandos ZFS/LVM/Ceph/NFS).
2) Bloqueos y concurrencia: Proxmox te protege… hasta que no
Proxmox usa bloqueos para evitar que dos operaciones modifiquen una VM simultáneamente (backup + start, snapshot + migración, etc.). Tras crashes o jobs fallidos, los bloqueos pueden permanecer.
Demuéstralo leyendo la config de la VM para una entrada lock: y comprobando tareas en ejecución en el journal. Elimina bloqueos solo cuando estés seguro de que la operación relacionada está muerta.
3) Configuración de red: fallos de tap/bridge matan la VM temprano
Si QEMU no puede crear o adjuntar la interfaz tap, sale con código 1. Causas comunes: bridge ausente, sintaxis rota en /etc/network/interfaces, scripts de firewall fallando, o capacidades/privilegios mal configurados.
Demuéstralo comprobando ip link show, presencia de vmbrX, y líneas de journald que mencionen tap, tun, bridge o vhost.
4) Características del kernel y aceleradores: KVM, VFIO, hugepages
QEMU es flexible, pero las configuraciones típicas de Proxmox asumen KVM y ciertas características CPU. Si intentas passthrough de GPU (VFIO), los modos de fallo se multiplican: grupos IOMMU, peculiaridades de reset del dispositivo, permisos en /dev/vfio/*, problemas con ROM.
Demuéstralo correlacionando stderr de QEMU con mensajes del kernel (journalctl -k, dmesg), y validando que los dispositivos existen y están asignados al driver correcto.
5) Flags de “optimización” que muerden: backends AIO, modos de caché, discard
Opciones como aio=io_uring y modos de caché agresivos pueden ser fantásticas—hasta que se encuentran con un kernel antiguo, un sistema de ficheros raro, o un backend de almacenamiento que no soporta lo pedido. Entonces QEMU sale inmediatamente y te quedas discutiendo con una línea de configuración que alguien copió de un blog de benchmarks.
Broma #2: Nada es más permanente que un ajuste de rendimiento “temporal” añadido un viernes.
Tres micro-historias corporativas (errores, reveses, victorias aburridas)
Incidente #1: La suposición equivocada (y un bloqueo que no era el problema)
Una empresa mediana operaba un clúster Proxmox para servicios internos. Una mañana, una VM crítica no arrancaba: “QEMU exited with code 1.” El ingeniero de guardia vio lock: backup en la config de la VM y asumió lo obvio: bloqueo obsoleto. Ejecutó qm unlock, y luego pulsó “Start” en la UI varias veces porque la UI está ahí y la impaciencia es un recurso renovable.
Siguió fallando. Ahora la situación era peor: habían eliminado un bloqueo legítimo mientras un trabajo de snapshot del lado del almacenamiento aún estaba activo en el servidor NFS. Ese trabajo no era visible como tarea de Proxmox porque lo dispararon scripts del equipo de almacenamiento. QEMU fallaba porque el archivo qcow2 estaba temporalmente bloqueado en el lado NFS y devolvía metadatos inconsistentes durante la ventana de snapshot.
El “code 1” fue solo el último dominó. La pista real estaba en el log del kernel: mensajes intermitentes de “stale file handle” y timeouts del servidor NFS alrededor de los intentos de arranque. Pero esas líneas nunca se comprobaron porque la teoría del bloqueo parecía ordenada.
La solución fue aburrida: dejar de intentar arrancar la VM durante la ventana de snapshot del almacenamiento, montar NFS con opciones razonables para su entorno, y añadir una comprobación previa en los runbooks operativos: validar que el backend de almacenamiento no esté en mantenimiento antes de limpiar bloqueos. También cambiaron la política: los bloqueos de Proxmox solo se limpian tras confirmar que no hay operaciones relacionadas en ejecución en ninguna parte del stack.
Después, el equipo añadió un pequeño script que imprime señales de “preparación de almacenamiento” (responsividad NFS, salud de Ceph, estado ZFS) junto a las acciones de arranque de VM. No evitó todos los incidentes. Evitó que repitieran el mismo, que es el KPI real.
Incidente #2: La optimización que falló (io_uring se enfrentó a la realidad)
Otra organización quería mejor rendimiento de disco para una base de datos. Alguien leyó que io_uring era el futuro y desplegó aio=io_uring y ajustes de caché en una flota de VMs vía automatización. El cambio parecía inocuo: un parámetro por VM.
Una semana después, tras un retraso en la actualización del kernel en un subconjunto de nodos, una migración aterrizó una VM en un nodo más antiguo. La VM empezó a fallar con “QEMU exited with code 1.” El log mostraba “invalid argument” alrededor de la definición del drive. No era obvio porque la VM arrancaba bien en otros nodos.
La causa raíz: la combinación kernel/QEMU más antigua no soportaba el backend AIO elegido para esa ruta de almacenamiento. El parámetro era válido en builds más nuevos pero efectivamente sin sentido en el entorno antiguo. El clúster se convirtió en un campo de minas de compatibilidad: las configs de VM asumían características que no eran uniformes entre nodos.
La solución no fue abandonar la optimización de rendimiento. Fue dejar de fingir que el clúster era homogéneo cuando no lo era. Impusieron baselines de versión de nodo, añadieron una comprobación tipo CI que rechaza cambios de config que requieren funciones no soportadas en algún nodo del clúster, y limitaron la optimización a un pool de nodos etiquetados como “conocidos buenos”.
Las mejoras de rendimiento permanecieron. Las interrupciones sorpresa no. La lección no fue “no optimices”. Fue “optimiza como si fueras de guardia para los casos límite”.
Incidente #3: La práctica aburrida que salvó el día (disciplina del journal)
Un tercer equipo tenía una política: cada arranque fallido de VM debe diagnosticarse desde los logs antes de que nadie reinicie nada. Sonaba pedante. Lo era, en el mejor sentido.
Durante un evento de energía, un nodo volvió con un estado de red ligeramente diferente. Un puñado de VMs no logró arrancar con “QEMU exited with code 1.” La gente estaba lista para reiniciar el nodo otra vez, asumiendo “los bridges no subieron correctamente”.
El de guardia siguió la política: journalctl -t pve-qemu-server más journalctl -k. El error fue preciso: la creación de dispositivos tap falló porque el sistema alcanzó un límite de procesos por usuario en un caso extraño provocado por un agente de monitorización que se bifurcaba agresivamente durante el arranque. Reiniciar el nodo habría enmascarado temporalmente el problema y garantizado su recurrencia.
Ajustaron los límites apropiados en systemd, arreglaron la configuración del agente de monitorización, y reiniciaron solo los servicios afectados. Las VMs arrancaron, el incidente terminó, y el equipo no añadió “reiniciarlo otra vez” al runbook.
La práctica aburrida —tratar los logs como evidencia primaria— evitó un bucle de conjeturas. También produjo un informe de incidente limpio con una causa raíz real. A los auditores les encanta eso. A los ingenieros que disfrutan dormir también.
Errores comunes: síntoma → causa raíz → solución
1) Síntoma: “Device or resource busy” en un zvol o disco
Causa raíz: proceso QEMU antiguo aún mantiene el dispositivo abierto; proceso de backup/migración lo mantiene; ruta de I/O del kernel atascada.
Solución: encuentra el holder con lsof / fuser, detén la VM o el proceso conflictivo, y reintenta. Si el holder está en estado D, investiga la salud del backend de almacenamiento (NFS/Ceph/iSCSI) en lugar de jugar al whack-a-mole con PIDs.
2) Síntoma: “Permission denied” al abrir una imagen de disco en almacenamiento por directorio
Causa raíz: permisos/propietario incorrectos en la ruta de la imagen; almacenamiento montado fuera de los puntos esperados por Proxmox; denegación AppArmor.
Solución: asegura que el almacenamiento esté configurado vía Proxmox, confirma el punto de montaje correcto (/mnt/pve/<storage>), corrige permisos de archivos, revisa denegaciones de AppArmor y alinea rutas.
3) Síntoma: “could not create tap device” / “Operation not permitted”
Causa raíz: bridge ausente, scripts de firewall fallando, capacidades cambiadas, o interfaz tap sobrante causando colisiones.
Solución: verifica que vmbr0 exista y esté UP; revisa logs de firewall; elimina tap obsoleto solo tras confirmar que ningún proceso lo usa; valida /etc/network/interfaces y recarga la red con cautela.
4) Síntoma: El arranque falla solo en un nodo
Causa raíz: deriva de nodo: diferentes versiones de kernel/QEMU, flags CPU faltantes, conectividad de almacenamiento diferente, montajes obsoletos, multipath roto.
Solución: compara versiones de nodo y configuraciones clave, estandariza paquetes, valida acceso a almacenamiento desde ese nodo, y evita flags de configuración que requieran funciones más nuevas a menos que el clúster sea uniforme.
5) Síntoma: “kvm: failed to initialize” o “failed to get KVM”
Causa raíz: virtualización deshabilitada en BIOS/UEFI, módulos del kernel faltantes, ejecución dentro de una VM sin virtualización anidada, o permisos en /dev/kvm.
Solución: habilita VT-x/AMD-V, carga los módulos, asegura que la virtualización anidada esté habilitada si procede, valida propiedad/grupo de /dev/kvm.
6) Síntoma: “Cannot access storage … (500)”
Causa raíz: error del plugin de almacenamiento de Proxmox: objetivo NFS/Ceph inalcanzable, fallos de autenticación, montaje obsoleto, keyrings faltantes.
Solución: confirma que el almacenamiento está online desde el nodo (estado de montaje, salud de ceph), arregla autenticación, remonta, y solo entonces reintenta el arranque de la VM.
7) Síntoma: “invalid argument” en opciones de drive/net
Causa raíz: opción QEMU incompatible con la versión de QEMU del nodo; línea args: malformada; AIO/cache no soportado por el backend.
Solución: simplifica: elimina args personalizados, revierte a valores por defecto, y vuelve a añadir cambios de uno en uno. Estandariza versiones de QEMU en los nodos del clúster.
8) Síntoma: La VM arranca desde CLI pero no desde UI/API
Causa raíz: diferencias en contexto de permisos, variables de entorno, o hooks en tiempo de tarea (firewall, scripts pre-start) fallando.
Solución: reproduce con qm start e inspecciona logs de tarea; revisa scripts hook y firewall; confirma que se usa el mismo usuario/contexto.
Listas de verificación / plan paso a paso
Paso a paso: de “code 1” a la causa raíz en menos de 10 minutos
- Captura la marca temporal del arranque fallido (el log de tarea de la UI sirve).
- Extrae líneas de journald alrededor de ese momento para
pve-qemu-servery mensajes del kernel. Identifica la primera cadena de error concreta. - Ejecuta
qm showcmdpara la VM y localiza rutas de disco, configuración netdev y opciones inusuales. - Comprueba el estado de bloqueo de la VM en la config; desbloquea solo tras confirmar que la operación relacionada no se está ejecutando.
- Verifica la salud del backend:
- ZFS:
zpool status - LVM:
lvsy uso del pool - Ceph: salud del clúster y mapeo RBD básico
- NFS: responsividad de montaje y errores del kernel
- ZFS:
- Busca restos: PID QEMU existente, interfaz tap obsoleta, holder de zvol persistente.
- Haz un cambio a la vez, reintenta y revisa logs inmediatamente.
Checklist: almacenamiento primero, porque falla de forma más cara
- La ruta de disco existe y es accesible desde el nodo que arranca la VM.
- Ningún proceso mantiene abierto el dispositivo/archivo de imagen inesperadamente.
- La salud del pool es correcta (no hay vdevs degradados, ni errores de lectura/escritura).
- El espacio libre es razonable, incluyendo metadata de thinpool y particiones raíz/log.
- No hay handles NFS obsoletos ni problemas de sesión iSCSI en los logs del kernel.
Checklist: cordura en redes
- El bridge existe y está UP (
ip link show vmbr0). - Los dispositivos tap se crean/eliminan correctamente; no hay colisiones por nombres tap obsoletos.
- Los scripts de firewall no están fallando (errores en journald).
Checklist: compatibilidad de versiones y funciones
- Las versiones de QEMU son consistentes entre nodos del clúster, o la config de la VM evita funciones específicas de nodos.
- KVM está disponible y habilitado (
/dev/kvmexiste, módulos cargados). - Los dispositivos de passthrough están asignados correctamente (VFIO/IOMMU) si se usan.
Datos interesantes y contexto histórico (cosas que te ayudan a depurar)
- QEMU nació en 2003 como un emulador de CPU rápido y creció hasta convertirse en la pieza clave de virtualización en ecosistemas Linux.
- KVM llegó al kernel Linux en 2007, transformando a QEMU de “emulación pura” a virtualización asistida por hardware en x86.
- Las configs de VM de Proxmox viven en un sistema de archivos de clúster (pmxcfs) almacenado bajo
/etc/pve, por eso las ediciones se replican y el split‑brain duele. - Exit code 1 es intencionalmente genérico: QEMU lo usa a menudo para “fallo al inicializar o parsear argumentos”, que puede significar desde disco ausente hasta opción no soportada.
- Los dispositivos virtio existen porque emular hardware real es caro: virtio es una interfaz paravirtual diseñada para reducir overhead y mejorar rendimiento.
- io_uring se masificó en Linux alrededor de 2019+ y sigue evolucionando; mezclar kernels y versiones de QEMU puede hacer que opciones “válidas” sean inválidas en algunos nodos.
- Los zvols de ZFS son dispositivos de bloque respaldados por datasets, y pueden estar “ocupados” por holders que no verás en la UI de Proxmox—las herramientas a nivel de proceso importan.
- LVM-thin puede sobreaprovisionar, lo cual es genial hasta que no lo es; las condiciones de falta de espacio aparecen como fallos de VM en vez de advertencias amables.
- Los dispositivos tap son una característica del kernel Linux, y los fallos al crearlos suelen ser problemas de privilegios/capacidades, no “un bug de Proxmox”.
Preguntas frecuentes
¿Por qué Proxmox solo muestra “QEMU exited with code 1”?
Porque Proxmox informa el estado de salida de QEMU, no el detalle de stderr subyacente. El error accionable suele estar en journald bajo pve-qemu-server o en los logs del kernel.
¿Dónde está el mejor lugar para encontrar la línea de error real?
journalctl -t pve-qemu-server alrededor de la marca temporal de arranque, más journalctl -k para denegaciones a nivel kernel y problemas de dispositivo.
¿Es seguro ejecutar qm unlock cada vez que una VM no arranca?
No. Desbloquear es seguro solo tras probar que la operación relacionada (backup/migración/snapshot) no se está ejecutando en ningún sitio. De lo contrario, arriesgas corrupción o snapshots inconsistentes.
Mi VM arranca en el nodo A pero falla en el nodo B. ¿Qué debo sospechar primero?
Deriva de nodo: diferentes versiones de QEMU/kernel, diferencias de acceso a almacenamiento (montaje ausente en el nodo B), o políticas de seguridad distintas. Compara la salida de qm showcmd y comprueba la accesibilidad del almacenamiento desde el nodo B.
¿Puede un /var/log o filesystem raíz casi lleno causar fallo al arrancar QEMU?
Sí. QEMU y Proxmox necesitan escribir logs, sockets y estado de runtime. Un filesystem lleno puede manifestarse como fallos extraños de arranque, a veces aún reportados como “code 1”.
¿“Device or resource busy” siempre significa una VM en ejecución?
A menudo, pero no siempre. También puede significar un proceso de backup, una instancia QEMU atascada, o bloqueo en el lado del almacenamiento (especialmente en NFS/Ceph). Usa lsof/fuser para probarlo.
¿Cómo reproduzco el fallo de forma segura sin adivinar?
Usa qm showcmd <vmid> para ver la línea de comando QEMU exacta, y luego céntrate en el recurso que falla mencionado en los logs (ruta de disco, interfaz tap, KVM). No vayas deambulando por opciones de configuración al azar.
¿Es buena idea añadir args: personalizados a las configs de Proxmox?
Sólo si aceptas la carga operativa: compatibilidad entre nodos, pruebas en upgrades, y que el “tú del futuro” lo depure a las 3 a.m. Los valores por defecto existen por una razón.
¿Cuál es la forma más rápida de saber si esto es almacenamiento vs red vs KVM?
Lee la primera cadena de error concreta. Errores de ruta de disco apuntan a almacenamiento. Errores de tap/bridge apuntan a red. Errores KVM/VFIO apuntan a kernel/virtualización.
Conclusión: próximos pasos prácticos
Cuando Proxmox dice “QEMU exited with code 1”, no lo trates como un misterio. Trátalo como un puntero a evidencia que aún no has recogido. Tu trabajo es extraer la primera línea de error específica y luego validar el subsistema que nombra.
Próximos pasos que puedes hacer hoy:
- Estandariza un runbook: journal primero, luego bloqueos/procesos, y después salud del backend.
- Reduce la deriva del clúster: alinea versiones de kernel/QEMU entre nodos o limita las funciones de VM.
- Audita los ajustes de “rendimiento” en las configs de VM y elimina los que no puedas justificar bajo condiciones de incidente.
- Añade un hábito: cada “code 1” tiene una nota de causa raíz. No un workaround. Una nota.
Si haces eso de forma consistente, “QEMU exited with code 1” deja de ser un incidente y pasa a ser un paso rutinario de diagnóstico. Exactamente donde debe estar.