Proxmox Backup «No space left on device»: por qué falla aunque parezca haber espacio libre

¿Te fue útil?

Tienes mucho espacio libre. df -h lo confirma. El gráfico de almacenamiento en la interfaz se ve bien. Luego un trabajo de copia explota con
No space left on device y empiezas a negociar con el universo.

La moraleja: “sin espacio” rara vez significa “no quedan bytes”. Significa que se alcanzó algún límite: bytes, inodos, metadatos, headroom de ZFS, cuotas,
espacio temporal, crecimiento de snapshots o reglas del almacén de chunks de PBS. Este es el mapa de ese territorio, escrito por quien lo ha visto arder en producción.

Qué significa realmente “No space left on device”

En Linux, ENOSPC es el código de error detrás del mensaje. No significa “el almacenamiento está físicamente lleno.”
Significa: “el kernel rechazó una escritura porque el sistema de archivos, el dispositivo de bloques o una cuota/límite dijo que no.”
La negativa puede ocurrir por varias razones:

  • Se han agotado los bytes en el sistema de archivos o pool objetivo.
  • Se han agotado los inodos (común en ext4/xfs con millones de ficheros pequeños; PBS puede crear muchos chunks).
  • Se ha agotado el espacio de metadatos (dispositivos especiales de ZFS, nodos btree, límites de journal, o simplemente fragmentación y holgura).
  • Bloques reservados (los sistemas ext reservan bloques; ZFS necesita headroom).
  • Cuotas / project quotas / cuotas de dataset alcanzadas antes de que “el disco” entero se llene.
  • Amplificación copy-on-write (las snapshots convierten eliminaciones en “todavía usadas”, y las sobreescrituras en nuevas asignaciones).
  • Un sistema de archivos diferente al que crees (directorio tmp en una partición pequeña; rootfs de contenedor vs almacenamiento montado).

Proxmox añade sus propios matices. Las copias implican ficheros temporales, snapshots y (si usas Proxmox Backup Server) un almacén de chunks que se comporta
más como un archivo dirigido por contenido que como una carpeta de tar. Así que puedes tener 2 TB “libres” y aún así no poder asignar los próximos 128 KB.

Primer chiste (corto, porque tu ventana de backup no se alarga): el espacio libre es como la disponibilidad de una sala de reuniones—siempre “disponible” hasta que intentas reservarla.

Guion de diagnóstico rápido

Cuando las copias fallan con “no space”, quieres una secuencia corta y brutal. No navegues por paneles. No adivines. Comprueba las tres restricciones que
suelen mentir: bytes, inodos y headroom/cuotas.

1) Identifica dónde falló la escritura (¿datastore PBS? ¿NFS? ¿directorio local?)

  • Mira el log del trabajo de Proxmox: ¿menciona una ruta bajo /var/lib/vz, un recurso montado o un datastore PBS?
  • En PBS, los errores suelen aparecer en el visor de tareas y en journalctl con contexto “chunk” o “datastore”.

2) Comprueba bytes e inodos en el sistema de archivos objetivo

  • df -h (bytes)
  • df -i (inodos)

3) Si interviene ZFS, revisa la salud y capacidad del pool como si te importara

  • zpool list y zpool get autoexpand,ashift
  • zfs list -o space para el dataset que aloja el datastore/backups
  • Si el pool supera el 80–85%, trátalo como “efectivamente lleno” para cargas intensivas de escritura.

4) Si es PBS: ejecuta prune y garbage collection, luego vuelve a comprobar

  • Prune elimina referencias de snapshots; GC libera chunks no referenciados. Normalmente necesitas ambos.
  • Si prune funciona pero GC no puede asignar metadatos, aún estás “lleno” de la forma que importa.

5) Verifica directorios temporales y puntos de montaje

  • Las copias pueden escribir ficheros temporales en /var/tmp, /tmp o en un tmpdir configurado.
  • Si /tmp es un pequeño tmpfs, jobs grandes de vzdump pueden fallar incluso con terabytes libres en el destino.

6) Si es un destino remoto (NFS/SMB): verifica cuotas y exports en el servidor

  • “El cliente muestra espacio libre” no es un contrato legalmente vinculante.
  • Cuotas, snapshots o políticas de reserva en el NAS pueden devolver ENOSPC mientras la share parece amplia.

Los modos reales de fallo (y por qué tu espacio libre miente)

Modo de fallo A: agotamiento de inodos (sí, en 2025)

Los inodos son las “ranuras de archivo” del sistema de archivos. Si se agotan no puedes crear ficheros nuevos—aunque tengas gigabytes libres.
Los datastores PBS pueden crear muchos ficheros (chunks, índices, metadatos). Si pones un datastore en ext4 con una relación de inodos pobre,
o lo has ejecutado años con mucha rotación, la presión de inodos se vuelve real.

La señal: df -h se ve bien, df -i está al 100%. Las copias fallan en llamadas de “create” o “write”.

Consejo con opinión: para PBS, prefiere ZFS (con headroom razonable) o XFS con planificación. ext4 está bien hasta que deja de estarlo—y ese día será
un viernes por la noche.

Modo de fallo B: comportamiento de pool ZFS “lleno” (se pone feo antes del 100%)

ZFS es copy-on-write. Excelente para integridad y snapshots, y ocasionalmente terrible para “necesito anexar muchos datos ahora”.
Cuando el pool sube en utilización, las asignaciones requieren más actualizaciones de metadatos, más búsquedas y aparece fragmentación. El rendimiento cae en picado.
Eventualmente, llegas a un punto donde el pool no puede asignar bloques del tamaño necesario de forma fiable. Puedes ver ENOSPC o paradas de transaction group.

La trampa específica: la gente trata ZFS como ext4—lo llenan al 95% y esperan que se comporte. No lo hará.
Si te importa la fiabilidad y copias predecibles, mantén pools ZFS cómodamente por debajo de la zona de peligro. Mi regla: empieza a preocuparte al 80%, actúa al 85%.

Modo de fallo C: cuotas/reservas de dataset (el pool está bien; tu dataset no)

Puedes tener un pool ZFS con 10 TB libres y un dataset con quota=1T que está lleno. Igual en XFS con project quotas.
Proxmox y PBS suelen ser instalados por humanos que estaban “siendo ordenados” y pusieron cuotas “para que las copias no se comieran todo.”
Luego se olvidan. La cuota recuerda.

Además, las reservas funcionan al revés: un dataset puede reservar espacio y dejar a otros datasets sin él. Si tu destino de backup deja de poder escribir, revisa tanto cuota como reserva.

Modo de fallo D: snapshots reteniendo espacio como rehén

Las snapshots no son una segunda copia. Son una promesa: “los bloques antiguos siguen disponibles.” Cuando borras o sobrescribes datos tras tomar una snapshot,
los bloques antiguos siguen referenciados. Tu “espacio libre” no vuelve. Esto aparece en ZFS como USEDDS/USEDREFRESERV/USEDSNAP.

En PBS, prune elimina referencias de snapshots del catálogo de backups; garbage collection borra chunks que ya no están referenciados.
Si solo haces prune pero nunca GC, el uso de disco no bajará mucho. Si GC no puede ejecutarse por falta de espacio, entras en un callejón: necesitas espacio para liberar espacio.

Modo de fallo E: espacio temporal, tmpfs y “escribiendo donde no crees”

Las copias en Proxmox VE (vzdump) suelen escribir al almacenamiento objetivo, pero también pueden preparar datos, crear logs y usar espacio temporal.
Si tu /tmp es un pequeño tmpfs (común), o /var está en un disco root pequeño, tu backup puede fallar mucho antes de que se llene el disco real.

Este es uno de esos problemas que resultan insultantes. El destino de backup tiene espacio. Tu disco root no. El mensaje de error no te dice cuál es el problema.
Bienvenido a las operaciones.

Modo de fallo F: thin provisioning y sobreasignación (LVM-thin, ZVOLs, SANs)

El thin provisioning hace que todo parezca espacioso hasta que deja de serlo. Las pools LVM-thin pueden alcanzar 100% de uso en datos o metadatos.
Backends SAN/NAS pueden sobreasignar, y la primera escritura que necesite bloques reales falla. Algunos entornos devuelven ENOSPC; otros devuelven errores de E/S.

Lo peligroso: puedes tener “espacio libre” dentro de un disco de VM mientras la pool thin que lo aloja está sin espacio. Las copias que hacen snapshot y leen
un disco no siempre fallarán; las que escriben en la misma pool estresada sí.

Modo de fallo G: el almacenamiento remoto miente (quirks de NFS/SMB, snapshots servidor, cuotas)

Los clientes NFS cachean atributos. SMB a veces omite y dice medias verdades. Y el servidor puede imponer cuotas o políticas de reserva invisibles al cliente.
Si tu nodo Proxmox dice “No space left on device” mientras la UI del NAS muestra “2 TB libres”, cree al error e investiga restricciones del lado servidor.

Modo de fallo H: overhead del chunk store de PBS y “espacio que no puedes usar”

PBS almacena datos como chunks e índices con verificación. Eso trae overhead:
metadatos, checksums, índices, logs, además de espacio “de trabajo” adicional para GC.
Si dimensionas PBS “según el tamaño bruto de backups”, eventualmente descubrirás el concepto de “holgura operacional”, típicamente durante un backup fallido.

Segundo chiste, porque solo tenemos dos: un sistema de backup sin holgura es como un paracaídas empaquetado exactamente al volumen de la bolsa—técnicamente impresionante, operacionalmente fatal.

Modo de fallo I: el sistema de archivos root está lleno (y arrastra tu trabajo de backup)

Incluso si las copias escriben a un montaje separado, el sistema aún necesita espacio para logs, journal, ficheros temporales, locks y a veces
metadatos de snapshot. Si /var/log o el journal llenan el root, verás una cascada de fallos no relacionados.
Las copias son solo lo primero que notas.

Modo de fallo J: “borrado pero aún abierto”

Trampa clásica Unix: un proceso mantiene un fichero abierto; lo borras; el espacio no se libera hasta que el proceso lo cierra.
Entonces limpias, ves que el espacio libre no cambia, y la siguiente copia aún falla.
PBS y componentes de Proxmox suelen comportarse bien, pero loggers, depuradores o agentes de terceros pueden mantener ficheros grandes abiertos.

Una cita operativa para tener en mente, idea parafraseada de James Hamilton (AWS): “Mide todo lo que puedas y automatiza el resto.”
Si no tienes alertas para uso de inodos, capacidad de ZFS y metadatos de thin-pool, estás eligiendo sorpresas.

Hechos interesantes y breve historia (lo que explica la rareza actual)

  1. ENOSPC es más antiguo que la mayoría de tus servidores. El código de error data de los primeros Unix; “device” significaba el almacenamiento de respaldo del sistema de archivos, no solo discos.
  2. Los inodos se diseñaron cuando los discos eran pequeños. Los primeros sistemas pre-asignaban tablas de inodos; quedarse sin inodos antes que sin bytes es una característica heredada que se niega a morir.
  3. Los sistemas ext reservan bloques por defecto. Tradicionalmente ~5% reservado para root para mantener el sistema vivo y reducir fragmentación; sorprende en volúmenes de datos.
  4. ZFS necesita headroom para copy-on-write. Alta utilización incrementa fragmentación y presión de metadatos; “100% lleno” no es un objetivo práctico.
  5. El thin provisioning popularizó “parecía libre”. Las plataformas VM normalizaron el overcommit; los administradores aprendieron que “asignado” y “usado” no son lo mismo.
  6. PBS prioriza deduplicación, no ficheros legibles. Su chunk store cambia ficheros humanos por integridad y eficiencia; la limpieza requiere prune + GC, no solo borrar ficheros.
  7. La garbage collection suele necesitar espacio temporal. Muchos sistemas requieren algo de espacio libre para reorganizar metadatos y liberar bloques con seguridad; ejecutarlo hasta “cero” puede bloquear la limpieza.
  8. El cache de atributos de NFS puede engañar al monitoreo. La visión del cliente sobre el espacio libre y la aplicación de políticas del servidor pueden divergir, especialmente con cuotas y snapshots.
  9. “Libre” en un sistema de archivos no es todo usable. Entre bloques reservados, tamaños de unidad de asignación y metadatos, puedes estar “libre” pero incapaz de asignar los extent necesarios.

Tareas prácticas: comandos, salidas, qué significan y la decisión que tomas

Estas son las comprobaciones que ejecuto cuando alguien dice “las copias fallan, pero hay espacio.” Cada tarea incluye: un comando, un fragmento realista de salida,
lo que significa y la acción que tomas.

Task 1: Encuentra la ruta que falló en los logs de tarea de Proxmox

cr0x@server:~$ journalctl -u pvedaemon -u pvescheduler --since "2 hours ago" | tail -n 30
Dec 26 01:12:19 pve01 pvescheduler[1883]: starting new backup job: vzdump 101 102 --storage pbs01 --mode snapshot
Dec 26 01:13:44 pve01 vzdump[22109]: ERROR: Backup of VM 101 failed - write error: No space left on device
Dec 26 01:13:44 pve01 vzdump[22109]: INFO: Failed at: /var/tmp/vzdumptmp12345
Dec 26 01:13:44 pve01 pvedaemon[1765]: VM 101 qmp command failed - backup aborted

Significado: La falla ocurrió al escribir en /var/tmp, no en el destino de backup. Esa es tu primera bifurcación.

Decisión: Revisa el filesystem root y el espacio temporal, no la capacidad del PBS.

Task 2: Comprueba uso de bytes en todos los sistemas montados

cr0x@server:~$ df -hT
Filesystem                        Type   Size  Used Avail Use% Mounted on
/dev/mapper/pve-root              ext4    96G   95G   0G 100% /
tmpfs                             tmpfs  32G  1.2G   31G   4% /run
rpool/ROOT/pve-1                  zfs     96G   95G   0G 100% /
rpool/data                        zfs    1.8T  1.1T  700G  62% /rpool/data
192.0.2.10:/exports/pbsstore      nfs4    20T   15T  5.0T  75% /mnt/pbsstore

Significado: Root está lleno. También observa que el ejemplo mixto muestra cómo la gente confunde montajes; céntrate en el montaje relevante para la ruta que falló.

Decisión: Libera espacio en / (logs, caches) o mueve el tmpdir a un filesystem mayor.

Task 3: Comprueba agotamiento de inodos (el asesino silencioso)

cr0x@server:~$ df -i
Filesystem                        Inodes   IUsed   IFree IUse% Mounted on
/dev/mapper/pve-root             6553600 6553201     399  100% /
192.0.2.10:/exports/pbsstore    134217728 210345 134007383    1% /mnt/pbsstore

Significado: El filesystem root prácticamente no tiene inodos libres. Eso puede romper instalación de paquetes, rotación de logs y creación de ficheros temporales para backups.

Decisión: Identifica directorios con muchos inodos (a menudo /var/log, /var/lib o almacenamiento de contenedores) y limpia o amplía.

Task 4: Encuentra rápidamente rutas con muchos inodos

cr0x@server:~$ sudo du --inodes -x -d 2 /var | sort -n | tail -n 10
1200    /var/cache
8421    /var/tmp
15300   /var/log
1204500 /var/lib
1209800 /var

Significado: /var/lib consume inodos como hobby. En Proxmox eso puede ser imágenes de contenedores, caches o directorios sueltos.

Decisión: Profundiza en /var/lib para hallar los culpables; considera reubicar rutas con muchas escrituras a un filesystem mayor.

Task 5: Confirma dónde vzdump prepara datos temporales

cr0x@server:~$ grep -R "tmpdir" -n /etc/vzdump.conf /etc/pve/* 2>/dev/null
/etc/vzdump.conf:2:tmpdir: /var/tmp

Significado: Tu directorio temporal de backup está en root. Está bien hasta que root sea pequeño o muy usado.

Decisión: Mueve tmpdir a un filesystem dedicado con espacio (y monitorízalo).

Task 6: Comprueba si /tmp es tmpfs y su tamaño

cr0x@server:~$ findmnt -no SOURCE,FSTYPE,SIZE,USED,AVAIL /tmp
tmpfs tmpfs 2.0G 1.9G 100M

Significado: /tmp es un tmpfs de 2 GB y está prácticamente lleno. Cualquier herramienta que use /tmp para preparación fallará rápidamente.

Decisión: Limpia el tmpfs, aumenta su tamaño o configura Proxmox para usar otra ubicación temporal.

Task 7: Si interviene PBS, comprueba uso del datastore desde PBS

cr0x@server:~$ proxmox-backup-manager datastore list
┌───────────┬───────────────┬───────────────┬─────────────┐
│ Name      │ Path          │ Comment       │ Maintenance │
╞═══════════╪═══════════════╪═══════════════╪═════════════╡
│ store1    │ /mnt/store1   │ main datastore│ false       │
└───────────┴───────────────┴───────────────┴─────────────┘

Significado: El datastore está en /mnt/store1. Ahora sabes qué filesystem importa.

Decisión: Revisa df e inodos en ese montaje; luego el estado de prune/GC de PBS.

Task 8: Comprueba bytes e inodos del filesystem del datastore en el host PBS

cr0x@server:~$ df -hT /mnt/store1
Filesystem     Type  Size  Used Avail Use% Mounted on
rpool/store1   zfs   8.0T  7.4T  600G  93% /mnt/store1

Significado: 93% en ZFS es “te gusta vivir peligrosamente.” GC y nuevas escrituras pueden fallar.

Decisión: Libera espacio inmediatamente (prune+GC, borra grupos viejos, añade capacidad). Luego aplica política de headroom.

Task 9: Desglose del espacio en pool y dataset ZFS (qué consume realmente)

cr0x@server:~$ zfs list -o name,used,avail,refer,usedsnap,usedds,usedrefreserv,logicalused -r rpool/store1
NAME           USED  AVAIL  REFER  USEDSNAP  USEDDS  USEDREFRESERV  LOGICALUSED
rpool/store1  7.40T   600G  7.10T     900G   6.50T            0B       12.8T

Significado: Las snapshots retienen 900G. Puede ser normal, o una retención descontrolada. El uso lógico muestra efectos de dedup/compression.

Decisión: Revisa la retención y si las snapshots se están limpiando (PBS prune) y los chunks liberando (GC). Considera añadir capacidad antes de ajustar.

Task 10: Comprueba capacidad del pool ZFS y señales de fragmentación

cr0x@server:~$ zpool list
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH
rpool  8.00T  7.45T   550G         -    61%    93%  1.00x  ONLINE

Significado: 93% de capacidad y 61% de fragmentación. Las escrituras serán dolorosas; la asignación de metadatos puede fallar incluso antes del 100%.

Decisión: Reduce la utilización. No intentes “optimizar” esto; haz espacio o añade vdevs.

Task 11: Comprueba cuotas y reservas de dataset (la pared invisible)

cr0x@server:~$ zfs get -o name,property,value -H quota,refquota,reservation,refreservation rpool/store1
rpool/store1	quota	7.5T
rpool/store1	refquota	none
rpool/store1	reservation	none
rpool/store1	refreservation	none

Significado: La cuota del dataset es 7.5T. Estás en 7.4T usado, así que prácticamente no tienes espacio aunque el pool tenga más en otros lugares.

Decisión: Incrementa la cuota (si es intencional) o libera espacio dentro de ella. Si la cuota fue una “medida de seguridad” olvidada, elimínala y pon monitorización.

Task 12: Simulación de prune en PBS (ver lo que se eliminaría)

cr0x@server:~$ proxmox-backup-manager prune-job run nightly --dry-run
Starting prune on datastore 'store1'
Group 'vm/101' - would keep 14 backups, remove 6 backups
Group 'vm/102' - would keep 14 backups, remove 4 backups
Prune dry-run completed successfully

Significado: La política de prune eliminaría algunas snapshots. Bien. Pero prune por sí solo no siempre libera espacio hasta que GC se ejecuta.

Decisión: Ejecuta prune de verdad en una ventana segura, luego ejecuta GC y confirma que el espacio bajó.

Task 13: Ejecuta garbage collection de PBS y lee el resultado

cr0x@server:~$ proxmox-backup-manager datastore gc store1
Starting garbage collection on datastore 'store1'
Removed 18432 unreferenced chunks (68.4 GiB)
GC finished in 00:12:09

Significado: Recuperaste ~68 GiB. Si recuperas casi nada, o la retención es muy agresiva, o la mayoría de los chunks aún están referenciados.

Decisión: Si el espacio sigue ajustado, reduce retención, mueve grupos a otro datastore o añade capacidad. No esperes milagros del GC.

Task 14: Detecta ficheros borrados pero aún abiertos que consumen espacio

cr0x@server:~$ sudo lsof +L1 | head -n 10
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NLINK    NODE NAME
rsyslogd  912 syslog  7w   REG  252,0 2147483648     0  53123 /var/log/syslog.1 (deleted)

Significado: Un log de 2 GB fue borrado pero aún está abierto por rsyslogd. El espacio no volverá hasta que el proceso lo cierre.

Decisión: Reinicia el proceso que lo mantiene abierto (con cuidado), o rota los logs correctamente. Luego vuelve a comprobar df.

Task 15: Para setups LVM-thin, comprueba datos y metadatos de la thin pool

cr0x@server:~$ sudo lvs -a -o +seg_monitor,metadata_percent,data_percent vg0
  LV              VG  Attr       LSize   Pool       Origin Data%  Meta%  Monitor
  thinpool        vg0 twi-aotz--  3.00t                      92.31  99.87 monitored
  thinpool_tmeta  vg0 ewi-aotz--  8.00g
  thinpool_tdata  vg0 lwi-aotz--  3.00t

Significado: Los metadatos de la thin pool están al 99.87%. Eso es una condición “a punto de explotar”. Las escrituras pueden fallar aunque Data% no sea 100%.

Decisión: Extiende los metadatos de la thin pool inmediatamente y deja de sobreasignar sin monitorización.

Task 16: Valida que tu montaje de destino de backup esté realmente montado

cr0x@server:~$ findmnt /mnt/pbsstore
TARGET        SOURCE                      FSTYPE OPTIONS
/mnt/pbsstore 192.0.2.10:/exports/pbsstore nfs4   rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2

Significado: Está montado. Si no lo estuviera, Proxmox podría haber estado escribiendo en el directorio vacío en root—llenándolo silenciosamente.

Decisión: Si no está montado, arregla automount/dependencias de systemd y limpia las escrituras locales accidentales.

Tres micro-historias del mundo corporativo (anonimizadas, plausibles y dolorosamente familiares)

Micro-historia 1: El incidente causado por una suposición equivocada

Una empresa mediana ejecutaba Proxmox VE con backups a una share NFS en un NAS respetable. El equipo ops miraba el panel del NAS:
terabytes libres, luces verdes, todos relajados. Luego, el lunes por la mañana: múltiples backups de VM fallaron con “No space left on device.”
La gente culpó inmediatamente a Proxmox, porque eso se hace cuando estás cansado.

La suposición equivocada fue sutil: asumieron que la vista del cliente sobre el espacio libre coincidía con la aplicación del servidor.
El NAS tenía cuotas por share habilitadas—configuradas meses antes durante una reorganización de almacenamiento. La share tenía capacidad física,
pero el límite de cuota se había alcanzado. NFS devolvió ENOSPC correctamente.

Peor aún, el equipo intentó “arreglarlo” borrando archivos de backup antiguos desde la share. La contabilidad de la cuota no cambió mucho porque el NAS también tenía snapshots,
y la política de retención de snapshots mantenía los bloques borrados durante semanas. La share parecía más vacía al listar archivos, pero la cuota permaneció bloqueada.

La solución final fue aburrida: aumentar la cuota de la share, reducir la retención de snapshots y alinear la política de retención de Proxmox con lo que hacían los snapshots del NAS.
El postmortem incluyó una nueva regla: cualquier destino de almacenamiento debe tener cuotas y snapshots documentados en el mismo sitio que la definición del job de backup.

Enseñanza operativa: cuando el backend dice que no, créelo. Luego verifica cuotas y snapshots del lado servidor, no solo df en el cliente.

Micro-historia 2: La optimización que salió mal

Otra organización decidió “optimizar” espacio de PBS ejecutando el datastore justo al borde. Tenían ahorros por dedup y se veía bien en papel.
Apuntaron a 95% de utilización porque “pagamos por cada terabyte”. Finanzas encantadas. El ingeniero de almacenamiento no tanto, pero fue sobrepasado.

El fallo no fue un evento limpio de “disco lleno”. Fue una degradación lenta: la garbage collection tardaba más y luego empezó a fallar intermitentemente.
Las ventanas de backup se ampliaron hasta solaparse. Los jobs nocturnos empezaron a pisarse entre sí. Finalmente, un conjunto de backups falló durante una ventana de parche crítico,
que es un gran momento para descubrir que no tienes un punto de restauración reciente.

La causa raíz no fue solo “disco lleno”. Fue el comportamiento del pool ZFS bajo alta fragmentación y baja holgura.
GC necesitaba crear y actualizar metadatos, y esas asignaciones se volvieron poco fiables. El sistema estaba técnicamente en línea, funcionalmente frágil.

La solución fue añadir capacidad y aplicar un umbral interno estricto: alertas al 75%, acción al 80–85% y prohibición de “lo subimos al 95% por una semana.”
La “semana” siempre se convertía en un trimestre.

Enseñanza operativa: los objetivos de utilización son objetivos de fiabilidad. Si presupuestas 95% de llenado, estás presupuestando modos de fallo que no puedes probar con seguridad.

Micro-historia 3: La práctica aburrida pero correcta que salvó el día

Un tercer equipo ejecutaba Proxmox con PBS en ZFS. Su práctica era ofensivamente aburrida: revisión semanal de capacidad, alertas en capacidad de pool ZFS y uso de inodos,
y un runbook permanente: prune, GC, confirmar espacio, y solo aumentar retención si queda holgura. También mantenían una pequeña cuota de dataset “de emergencia”
que podía aumentarse temporalmente durante incidentes.

Una noche, un desarrollador escribió accidentalmente logs en un directorio montado de backup desde un contenedor con un bind mount mal configurado.
PBS empezó a acumular ficheros basura junto a la ruta del datastore (no dentro). El trabajo de backup comenzó a fallar y la primera página despertó al on-call.

El on-call no adivinó. Siguió el runbook: comprobar puntos de montaje, df -i, uso de dataset ZFS. Encontró el directorio culpable,
paró el contenedor, limpió y ejecutó PBS GC. Las copias se reanudaron antes del turno de la mañana.

Sin heroicidades, sin “war room”, sin angustia existencial. Solo herramientas, umbrales y un runbook que asume que los humanos olvidarán dónde van realmente los ficheros.

Enseñanza operativa: lo “aburrido” es una función. Si tu sistema de backup necesita creatividad a las 2 a.m., no está diseñado; está improvisado.

Errores comunes: síntoma → causa raíz → solución

1) Síntoma: df muestra 30% libre; las copias fallan inmediatamente

Causa raíz: agotamiento de inodos en el filesystem objetivo (o en root/temp).

Solución: Ejecuta df -i. Si los inodos están llenos, borra ficheros con muchos inodos, rota logs o mueve el datastore PBS a un filesystem diseñado para muchos ficheros.

2) Síntoma: PBS prune se ejecutó, pero el espacio no volvió

Causa raíz: prune eliminó referencias de snapshots, pero los chunks permanecen hasta que la garbage collection los borre; o la mayoría de los chunks siguen referenciados por otros backups.

Solución: Ejecuta PBS GC. Si GC falla por baja holgura, libera espacio borrando grupos completos de backups o añade capacidad, luego vuelve a ejecutar GC.

3) Síntoma: pool ZFS al 92% y todo se vuelve lento, luego ENOSPC

Causa raíz: presión en asignación y metadatos de ZFS con alta utilización; fragmentación y overhead CoW.

Solución: Reduce la utilización del pool (borra datos, prune+GC, añade vdevs). Configura umbrales de alerta muy por debajo de “lleno”.

4) Síntoma: el log del job de Proxmox menciona /var/tmp o /tmp

Causa raíz: directorio temporal en un filesystem pequeño o tmpfs lleno.

Solución: Mueve tmpdir en /etc/vzdump.conf a un montaje más grande; limpia tmp; aumenta tmpfs si procede.

5) Síntoma: el pool tiene espacio, el dataset dice que no

Causa raíz: cuota/refquota de ZFS alcanzada; o quota de proyecto XFS.

Solución: Revisa cuotas y reservas. Aumenta/elimina la cuota o asigna un dataset dedicado dimensionado para los objetivos de retención.

6) Síntoma: “Borré backups antiguos” pero el uso de disco no cambió

Causa raíz: snapshots (ZFS o NAS) retienen bloques; o ficheros borrados pero aún abiertos; o chunks PBS siguen referenciados.

Solución: Revisa uso de snapshots, ejecuta prune+GC y comprueba lsof +L1 para ficheros borrados aún abiertos.

7) Síntoma: copias a NFS fallan, pero la UI del NAS muestra espacio

Causa raíz: cuota por share del servidor, política de reserva o retención de snapshots; a veces export mal configurado.

Solución: Revisa cuotas/snapshots en el NAS, no solo df del cliente. Confirma el montaje correcto con findmnt.

8) Síntoma: discos de VM en LVM-thin muestran “libre”, pero las copias fallan escribiendo en almacenamiento local

Causa raíz: metadatos de thin pool llenos (a menudo antes que los datos).

Solución: Monitoriza data_percent y metadata_percent; extiende metadatos; reduce snapshots; deja de sobreasignar sin alertas.

9) Síntoma: el filesystem root se llena repetidamente después de que lo “limpiaste”

Causa raíz: backups escribiendo en un directorio sin montar (el montaje falló), o logs que crecen, o ficheros temporales descontrolados.

Solución: Asegura que los montajes estén activos al arrancar; añade dependencias systemd; pon una comprobación de montaje en los scripts de backup.

Listas de verificación / plan paso a paso

Paso a paso: recuperarse de “No space left on device” hoy

  1. Detén la hemorragia. Pausa los horarios de backup para no convertir un problema de espacio en uno de espacio y carga.
  2. Localiza la ruta que falló. Desde el log del job, identifica si falló en root/temp, en el destino de backup o en el montaje del datastore.
  3. Comprueba bytes e inodos. Ejecuta df -hT y df -i en el montaje que falló y en /.
  4. Si root está lleno: limpia logs grandes, kernels antiguos, caches; arregla rotación de logs; considera mover directorios temporales.
  5. Si los inodos están llenos: borra basura con muchos inodos; encuentra los culpables con du --inodes; considera rediseñar el filesystem para PBS.
  6. Si el pool ZFS está >85%: libera espacio inmediatamente. Trátalo como urgente. Ejecuta prune+GC (PBS) y/o borra datasets antiguos.
  7. Si es PBS: ejecuta prune, luego garbage collection, luego vuelve a comprobar uso de dataset/pool.
  8. Si es almacenamiento remoto: revisa cuotas y snapshots en el servidor; confirma que el export no está capado.
  9. Vuelve a ejecutar una copia manualmente. Valida la solución con una sola VM antes de reactivar los horarios.

Prevenirlo: guardarraíles operativos que funcionan

  • SLOs de capacidad: Define un máximo de utilización objetivo (ZFS: 80–85% para PBS con muchas escrituras). Hazlo política, no consejo.
  • Alerta sobre inodos: el uso de inodos no es monitorización opcional para stores de backup con muchos ficheros.
  • Alerta sobre metadatos de thin pool: monitoriza metadata_percent. Trata 80% como una llamada telefónica, no un email.
  • Programa y muestra prune+GC: si GC no se ha ejecutado con éxito en días, estás acumulando riesgo.
  • Verificación de montajes: asegúrate de que los destinos de backup estén montados antes de ejecutar jobs; falla rápido si no lo están.
  • Separa rutas de escritura del sistema y del backup: no dejes que los backups dependan de un root pequeño para espacio temporal.

Qué evitar (porque parece ingenioso hasta que no lo es)

  • Ejecutar pools ZFS cerca del lleno porque “la dedup nos salvará.” Puede que sí, hasta que no, y entonces la falla no es lineal.
  • Usar cuotas como sustituto de la monitorización. Las cuotas están bien, pero no son observabilidad.
  • Borrar ficheros al azar en rutas de datastore PBS. Usa las herramientas PBS; el datastore no es un cajón de trastos.
  • Asumir que “df del cliente” refleja la verdad del servidor NFS.

FAQ

1) ¿Por qué Proxmox dice “No space left on device” cuando df muestra espacio libre?

Porque la escritura que falló puede estar golpeando otro filesystem (como /var/tmp), o te quedaste sin inodos, o se alcanzó una cuota,
o ZFS no puede asignar de forma fiable por alta utilización.

2) ¿Es esto un bug de Proxmox?

Normalmente no. Proxmox muestra el error del kernel. La confusión viene de los humanos (y las GUIs) que asumen que “espacio libre” es un único número,
cuando en realidad son varias restricciones superpuestas.

3) Para PBS, ¿por qué borrar backups antiguos no libera espacio de inmediato?

PBS es basado en chunks. Eliminar backups (prune) quita referencias; el espacio se libera cuando la garbage collection borra chunks no referenciados.
Si la mayoría de los chunks siguen referenciados por otros backups, el espacio no bajará mucho.

4) ¿Cuánto espacio libre debería mantener en un pool ZFS usado para PBS?

Mantén una holgura significativa. Para fiabilidad: intenta quedarte por debajo de ~80–85% usado. Si subes más, espera que GC y escrituras se vuelvan poco fiables bajo presión.
El número exacto depende de la carga y la disposición de vdevs, pero “95% lleno está bien” es fantasía.

5) ¿Puede ocurrir agotamiento de inodos en ZFS?

ZFS no tiene una tabla fija de inodos como ext4; aún puede alcanzar límites de metadatos de otras maneras, pero “df -i al 100%” es principalmente un problema de familias ext.
En ZFS, enfócate más en la capacidad del pool/dataset y el comportamiento de metadatos.

6) ¿Cuál es la diferencia entre prune y garbage collection en PBS?

Prune elimina backups del catálogo según la retención. Garbage collection elimina chunks en disco que ya no están referenciados por ningún backup restante.
A menudo necesitas ambos para recuperar espacio.

7) ¿Por qué fallan backups cuando el NAS dice que hay espacio?

Cuotas y snapshots. El NAS puede imponer una cuota por share o reservar capacidad. Los snapshots pueden mantener datos eliminados “en uso.”
Los clientes NFS/SMB también pueden cachear atributos; el servidor es la fuente de verdad.

8) ¿Cómo sé si Proxmox está escribiendo en un directorio sin montar?

Usa findmnt para confirmar que el montaje está activo. Si no lo está, la ruta es solo un directorio en root y las copias pueden llenar root silenciosamente.
También revisa timestamps y ficheros inesperados bajo el punto de montaje.

9) ¿Puede el thin provisioning causar ENOSPC durante backups aunque el destino de backup sea separado?

Sí, si la escritura es en almacenamiento local (ficheros temporales, logs) en la pool thin, o si la thin pool también está respaldando el datastore.
Además, la falta de metadatos en la thin pool puede romper escrituras en lugares sorprendentes.

10) ¿Simplemente debo añadir un disco más grande y listo?

A menudo sí—la capacidad es barata comparada con el tiempo de inactividad. Pero no te quedes ahí: añade monitorización para la restricción que te mordió (inodos, headroom ZFS,
cuotas, metadatos thin) o volverás aquí con un disco más grande y la misma sorpresa.

Conclusión: próximos pasos que deberías hacer realmente

“No space left on device” es una categoría de diagnóstico, no una medida. La solución casi nunca es “borra un fichero al azar y cruza los dedos.”
Encuentra dónde falló la escritura, luego comprueba la restricción que aplica allí: bytes, inodos, cuotas, headroom de ZFS, metadatos thin o políticas servidor.

Haz lo siguiente, en orden:

  1. Desde los logs, identifica la ruta exacta que falló y el host (nodo PVE vs servidor PBS).
  2. Ejecuta df -hT y df -i en ese filesystem y en /.
  3. Si interviene ZFS, trata >85% usado como un incidente y reduce la utilización.
  4. Si interviene PBS, ejecuta prune y luego GC; confirma el espacio recuperado con zfs list -o space o df.
  5. Añade monitorización para la restricción que falló, con umbrales que obliguen a actuar antes del precipicio.

El mejor sistema de backups es el que falla ruidosamente en staging y triunfa silenciosamente en producción. Diseñalo para que “espacio” sea una variable controlada, no una sorpresa.

← Anterior
Configuración de caché Cloudflare para WordPress que no rompe wp-admin
Siguiente →
Microcódigo: el «firmware» dentro de tu CPU que ya no puedes ignorar

Deja un comentario