I/O wait al 100% en Proxmox: localizar la VM/CT ruidosa y detener los congelamientos del host

¿Te fue útil?

Tu nodo Proxmox está “arriba”, pero no está vivo. La interfaz web va lenta. SSH tarda una eternidad en mostrar un carácter. Las VMs se pausan como si estuvieran reflexionando sobre su existencia. top dice que la CPU está “idle”, sin embargo la máquina es inusable porque wa está clavado al 100%.

Esta es la clásica situación de rehenes por almacenamiento. El trabajo no es contemplar el load average hasta que confiese. El objetivo es identificar qué VM/contenedor está martillando el almacenamiento (o qué disco está fallando), probarlo con evidencia y aplicar una solución que detenga los congelamientos a nivel host—sin adivinar y sin “reiniciar como estrategia de monitoreo”.

Qué significa realmente 100% I/O wait (y qué no significa)

I/O wait es la CPU diciéndote: “Estoy ejecutable, pero estoy bloqueada esperando la finalización de una E/S.” En un host Proxmox eso suele significar que el kernel espera E/S de bloque (discos, SSD, NVMe, SAN, Ceph, vdevs de ZFS) y todas las capas superiores (procesos QEMU, cargas LXC, journald, pvestatd, incluso la interfaz web) quedan atascadas detrás del mismo cuello de botella.

Un iowait alto no es inherentemente “malo” durante una gran escritura secuencial a un array sano. Lo que es malo es la combinación de iowait alto y bloqueos visibles por el usuario. Eso típicamente proviene de una de estas causas:

  • Explosión de latencia: la demanda de IOPS excede lo que el almacenamiento puede servir, la profundidad de cola sube y todo comienza a esperar.
  • Patología del dispositivo: un disco empieza a hacer timeouts, reinicios o remapear sectores; la capa de bloque espera y tu hipervisor también.
  • Amplificación de escrituras: escrituras pequeñas aleatorias más capas copy-on-write (ZFS, QCOW2, thin provisioning) más semántica sync = dolor.
  • Cargas en competencia: trabajos de backup, scrubs, resilvers y “alguien ejecutando fio en producción” (sí, sucede).

Dos aclaraciones importantes:

  • 100% iowait no significa que la CPU esté “ocupada”. Significa que tus hilos ejecutables están bloqueados en E/S. Puedes tener una CPU tranquila y un nodo completamente congelado.
  • El load average puede dispararse mientras el uso de CPU se mantiene bajo. Las tareas atrapadas en sueño ininterrumpible (a menudo mostradas como estado D) siguen contando para la carga.

Realidad cruda: si la latencia de almacenamiento pasa de 1–5 ms a 500–5000 ms, tu host se vuelve un drama de un solo hilo sin importar cuántos núcleos pagaste.

Guion rápido de diagnóstico (primero/segundo/tercero)

Este es el flujo de “detener la hemorragia”. Puedes hacerlo en 5–15 minutos, incluso con el host lento.

Primero: confirma que es latencia de almacenamiento, no CPU o RAM

  1. Comprueba iowait y la cola de ejecución (top o vmstat).
  2. Revisa latencia por disco y utilización (iostat -x). Si un dispositivo está ~100% util con await alto, encontraste el punto de estrangulamiento.
  3. Busca tareas bloqueadas (dmesg “blocked for more than” o ps por estado D). Esa es la firma de iowaits que congelan el sistema.

Segundo: identifica el invitado ruidoso (VM/CT) que causa la carga

  1. Encuentra qué PID de QEMU está haciendo E/S (pidstat -d, iotop).
  2. Relaciona ese PID con el VMID (la línea de comando de QEMU incluye -id, o qm list + argumentos del proceso).
  3. Revisa estadísticas por invitado en Proxmox (pvesh get /nodes/..., estadísticas de qm monitor y métricas de almacenamiento).

Tercero: elige la acción de contención de menor riesgo

  1. Limitar I/O (preferido): establece límites de disco para la VM (qm set) o límites cgroup IO para LXC.
  2. Pausar/suspender el invitado (rápido, reversible): qm suspend o qm stop --skiplock si es necesario.
  3. Matar el trabajo específico de backup/scrub/resilver: detén el trabajo que está quemando el array, no todo el nodo.

Regla práctica: si el nodo se está congelando, tu primer objetivo es recuperar el control, no tener la razón en un sentido filosófico.

Hechos y contexto interesantes (lo que explica las rarezas)

  • El iowait de Linux es una categoría de contabilidad de CPU, no una métrica de almacenamiento. Depende de lo que el planificador piensa que la CPU podría haber estado haciendo mientras estaba bloqueada, así que no es un número directo de “utilización de disco”.
  • El estado “D” (sueño ininterrumpible) ha sido el villano desde los primeros Unix. Los procesos esperando E/S pueden volverse efectivamente irremovibles hasta que la E/S termine o el dispositivo se reinicie.
  • ZFS fue diseñado primero por integridad de datos. Su modelo copy-on-write hace que “escrituras sincronizadas pequeñas en pools fragmentados” sea un tema recurrente en postmortems de rendimiento.
  • Las snapshots QCOW2 son cómodas pero pueden multiplicar la latencia. Cada escritura puede recorrer árboles de metadatos, y las cadenas largas de snapshots envejecen mal.
  • Los “slow ops” de Ceph suelen ser un sistema de aviso temprano. Cuando los OSDs o la red están infelices, la latencia sube mucho antes del fallo total; ignorar slow ops es básicamente optar por tiempo de inactividad.
  • Las barreras y flushes de escritura existen porque la pérdida de datos es peor que la lentitud. Si tu almacenamiento miente sobre durabilidad (caché mal configurada, sin protección contra pérdida de energía), tendrás un sistema rápido hasta el día que no.
  • Los eventos de “reconstrucción” son eventos de rendimiento. Resilver de RAID, scrubs de ZFS y backfill de Ceph cambian los patrones de I/O y pueden dejar sin recursos a cargas de primer plano si no se tunean.
  • Los hipervisores amplifican los problemas de almacenamiento. Un SSD moribundo puede bloquear docenas de invitados porque sus E/S comparten el mismo kernel y cola de bloque.
  • La capa de bloque ha evolucionado mucho. Multi-queue (blk-mq) y los planificadores modernos mejoran el throughput, pero no pueden arreglar un dispositivo que devuelve 2 segundos de latencia.

Tareas prácticas: comandos, salidas, decisiones (12+)

Estos son comandos reales que puedes ejecutar en un host Proxmox. Cada tarea incluye qué buscar y qué decisión tomar después.

Tarea 1: Confirma iowait y tareas bloqueadas rápidamente

cr0x@server:~$ top -b -n1 | head -n 15
top - 11:24:31 up 47 days,  3:12,  2 users,  load average: 54.12, 49.88, 41.03
Tasks: 412 total,   3 running, 409 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.2 us,  0.6 sy,  0.0 ni,  0.1 id, 98.0 wa,  0.0 hi,  0.1 si,  0.0 st
MiB Mem : 128642.5 total,  12211.7 free,  44210.2 used,  72220.6 buff/cache
MiB Swap:  8192.0 total,   8170.5 free,     21.5 used.  84044.3 avail Mem

Qué significa: La CPU está esperando en su mayor parte. La carga es masiva. Eso es consistente con latencia de almacenamiento o I/O atascada.

Decisión: Pasa a latencia por dispositivo (iostat -x) y a I/O por proceso (pidstat/iotop). No persigas el ajuste de CPU.

Tarea 2: Ver la cola de ejecución y la tendencia de iowait

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2 38      0 1249876  89244 72133840 0    0   118  9432  712 1843  1  1  0 98  0
 1 41      0 1249804  89244 72133912 0    0   104 10288  680 1721  1  1  0 98  0
 2 39      0 1249812  89244 72133980 0    0   112  9816  705 1802  1  1  0 98  0
 1 40      0 1249820  89244 72134012 0    0    96 11024  690 1760  1  1  0 98  0

Qué significa: La columna b (procesos bloqueados) es enorme. Esa es la representación numérica de tu congelamiento del host.

Decisión: Revisa la utilización de disco y await. Si un único dispositivo es el cuello de botella, aíslalo. Si está distribuido, sospecha saturación del backend (Ceph/red) o un patrón de carga (escrituras sync, backup).

Tarea 3: Encuentra el dispositivo caliente con iostat extendido

cr0x@server:~$ iostat -x 1 3
Linux 6.8.12-4-pve (server) 	12/26/2025 	_x86_64_	(32 CPU)

Device            r/s     w/s   rkB/s   wkB/s  rrqm/s  wrqm/s  %rrqm  %wrqm r_await w_await aqu-sz  rareq-sz wareq-sz svctm  %util
nvme0n1         12.0  2100.0   512.0 89200.0     0.0   220.0   0.0    9.5    3.2  740.5  1555.2     42.7     42.5  0.45  99.9
nvme1n1         10.0    14.0   480.0   620.0     0.0     1.0   0.0    6.7    2.8    4.1     0.1     48.0     44.3  0.18   0.4

Qué significa: nvme0n1 está al 99.9% de util con ~740 ms de await de escritura y una cola masiva. Eso no es “ocupado”; eso es “sufriendo”.

Decisión: Identifica qué carga genera esas escrituras. También revisa los logs del kernel y SMART del dispositivo. Una latencia tan alta puede ser sobrecarga, pero también un disco que está muriendo.

Tarea 4: Confirma si el kernel reporta errores de E/S o reinicios

cr0x@server:~$ dmesg -T | tail -n 30
[Thu Dec 26 11:23:12 2025] nvme nvme0: I/O 332 QID 4 timeout, aborting
[Thu Dec 26 11:23:12 2025] nvme nvme0: Abort status: 0x371
[Thu Dec 26 11:23:13 2025] nvme nvme0: resetting controller
[Thu Dec 26 11:23:16 2025] EXT4-fs warning (device dm-3): ext4_end_bio:351: I/O error 10 writing to inode 262148 starting block 11534336)
[Thu Dec 26 11:23:18 2025] task jbd2/dm-3-8:219 blocked for more than 120 seconds.
[Thu Dec 26 11:23:18 2025]       Tainted: P           O       6.8.12-4-pve #1

Qué significa: Timeouts y reinicios de controlador no son problemas de sintonía de carga. Son problemas de “hardware o firmware que se está derritiendo”. La advertencia de tarea bloqueada explica el congelamiento.

Decisión: Si ves timeouts/reinicios, trata el dispositivo como sospechoso de inmediato: reduce E/S, migra invitados fuera y planifica el reemplazo. No pases una hora afinando planificadores en un disco que está haciendo timeouts activos.

Tarea 5: Revisa SMART/NVMe salud (tríaje rápido)

cr0x@server:~$ smartctl -a /dev/nvme0n1 | egrep -i 'critical_warning|media_errors|num_err_log_entries|percentage_used|power_on|temperature'
Critical Warning:                   0x00
Temperature:                       73 Celsius
Percentage Used:                   89%
Power On Hours:                    31211
Media and Data Integrity Errors:   18
Error Information Log Entries:     294

Qué significa: Alto desgaste (Percentage Used), errores de medios y un contador de errores creciente apuntan a un dispositivo próximo al retiro.

Decisión: Prioriza evacuar VMs críticas. Planifica una ventana de reemplazo. Si esto es un mirror ZFS/RAID, inicia un reemplazo controlado en lugar de esperar un fallo dramático en horas pico.

Tarea 6: Identifica qué procesos están haciendo E/S de disco ahora

cr0x@server:~$ pidstat -d 1 5
Linux 6.8.12-4-pve (server) 	12/26/2025 	_x86_64_	(32 CPU)

11:25:44 AM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
11:25:45 AM     0      2911      0.00  68420.00  11200.00   98765  qemu-system-x86
11:25:45 AM     0      4187      0.00  10240.00   1800.00   12001  vzdump
11:25:45 AM     0      1332      0.00    220.00     12.00     210  pvestatd

Qué significa: Un proceso QEMU es el principal escritor; vzdump también está activo (backup). iodelay es enorme, lo que significa que el proceso pasa mucho tiempo esperando la finalización de E/S.

Decisión: Mapea el PID 2911 al VMID. Si hay backups en ejecución, decide si pausar/detenerlos para restaurar la capacidad de respuesta del host.

Tarea 7: Mapear un PID de QEMU a un VMID

cr0x@server:~$ ps -p 2911 -o pid,cmd --no-headers
2911 /usr/bin/kvm -id 113 -name vm113-db01,debug-threads=on -m 16384 -smp 8,sockets=1,cores=8 -drive file=/dev/zvol/rpool/data/vm-113-disk-0,if=none,id=drive-scsi0,cache=none,aio=io_uring,discard=on,format=raw

Qué significa: Es la VM 113. El disco es un ZVOL. El modo de caché es none, I/O asíncrono es io_uring. Nada de eso importa si el dispositivo está haciendo timeouts, pero sí importa si sólo estás saturando.

Decisión: Extrae estadísticas de la VM 113 y decide: limitar, pausar o migrar. Mientras tanto, confirma si la VM 113 también participa en el trabajo de backup.

Tarea 8: Revisa indicadores de throughput y latencia por VM a nivel Proxmox

cr0x@server:~$ qm status 113 --verbose
status: running
name: db01
cpus: 8
memory: 16384
uptime: 192773
net0: virtio=DE:AD:BE:EF:11:30,bridge=vmbr0
diskread: 0.00
diskwrite: 68.42
diskread_bytes: 0
diskwrite_bytes: 73408602112

Qué significa: Proxmox informa alto throughput de escritura en disco. No muestra latencia, pero confirma el “quién”.

Decisión: Contén la VM 113. Si es una base de datos o una canalización de logs, puede estar haciendo fsyncs frecuentes que castigan un pool degradado.

Tarea 9: Comprueba si un trabajo de backup es el culpable secundario

cr0x@server:~$ pgrep -af vzdump
4187 /usr/bin/perl /usr/bin/vzdump --all 1 --mode snapshot --compress zstd --storage backup-nfs --mailnotification failure
4231 /usr/bin/pigz -p 4

Qué significa: Se está ejecutando un vzdump en todo el nodo. El modo snapshot aún puede generar lecturas intensas y escrituras de metadatos, especialmente con QCOW2 o datasets ZFS muy activos.

Decisión: Si el nodo se congela, detén el backup primero (es carga discrecional) antes de matar invitados de producción.

Tarea 10: Detener o pausar el backup limpiamente (contención)

cr0x@server:~$ kill -TERM 4187
cr0x@server:~$ tail -n 5 /var/log/vzdump/vzdump.log
INFO: vzdump job finished
ERROR: job aborted by signal
INFO: cleanup temporary directory '/var/tmp/vzdumptmp4187'

Qué significa: Abortaste el backup. Eso debería reducir la presión de I/O rápidamente, pero si el array/dispositivo está enfermo aún puedes seguir atascado.

Decisión: Vuelve a comprobar iostat -x. Si el await baja y el host se recupera, has ganado tiempo para hacer un análisis de causa raíz sin que los usuarios te llenen de mensajes.

Tarea 11: Limitar la VM ruidosa (contención preferida)

cr0x@server:~$ qm set 113 --scsi0 rpool:vm-113-disk-0,iops=800,mbps=40
update VM 113: -scsi0 rpool:vm-113-disk-0,iops=800,mbps=40

Qué significa: Estás limitando la tasa de disco de la VM, dando al host y a otras VMs una oportunidad para respirar. No es una “solución” de rendimiento, es control del radio de impacto.

Decisión: Si la limitación estabiliza la latencia, mantenla mientras investigas la carga del invitado (por ejemplo, logging descontrolado, oleada de checkpoints de BD) y la salud del almacenamiento.

Tarea 12: Para contenedores LXC, encuentra el mayor escritor y mapea el CTID

cr0x@server:~$ iotop -oPa -n 5
Total DISK READ:         0.00 B/s | Total DISK WRITE:      92.15 M/s
  PID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN  IO>    COMMAND
 8432 be/4 root        0.00 B/s   68.42 M/s  0.00 % 99.99 % [kvm]
 9211 be/4 root        0.00 B/s   18.11 M/s  0.00 % 95.00 % [kworker/u64:3]
10222 be/4 root        0.00 B/s    4.10 M/s  0.00 % 60.00 % [lxcfs]

Qué significa: QEMU es el monstruo. Pero si vieras un proceso de contenedor aquí, el siguiente paso sería mapearlo usando cgroups o correlacionando mounts y PIDs.

Decisión: Si es un contenedor, usa pct status y pct config más estadísticas cgroup I/O para localizar y limitar.

Tarea 13: Comprueba la salud del pool ZFS y trabajos de mantenimiento que roban I/O

cr0x@server:~$ zpool status -v
  pool: rpool
 state: DEGRADED
status: One or more devices has experienced an unrecoverable error.  An attempt was made to correct the error.
action: Replace the device using 'zpool replace'.
  scan: scrub in progress since Thu Dec 26 09:12:02 2025
        2.31T scanned at 652M/s, 1.98T issued at 559M/s, 6.12T total
        0B repaired, 32.35% done, 2:11:44 to go
config:

        NAME                        STATE     READ WRITE CKSUM
        rpool                       DEGRADED     0     0     0
          mirror-0                  DEGRADED     0     0     0
            nvme0n1                 FAULTED      2    18     0  too many errors
            nvme1n1                 ONLINE       0     0     0

errors: No known data errors

Qué significa: El pool está degradado, se está ejecutando un scrub y un NVMe está faulted. Esa es una receta perfecta para picos de latencia y bloqueos del host.

Decisión: Detén o pospone el scrub si está dañando la disponibilidad, luego reemplaza el dispositivo fallido. Disponibilidad primero; el trabajo de integridad se reanuda cuando el sistema puede respirar.

Tarea 14: Ver qué datasets/zvols de ZFS están más activos

cr0x@server:~$ zfs iostat -v rpool 1 3
                  capacity     operations     bandwidth
pool            alloc   free   read  write   read  write
--------------  -----  -----  -----  -----  -----  -----
rpool           5.01T  1.11T    120   2200  4.8M  89.2M
  rpool/ROOT    18.2G  97.8G      2     18   64K  2.1M
  rpool/data    4.99T  1.01T    118   2182  4.7M  87.1M
    vm-113-disk-0  420G  80.0G     12   1620 512K  68.4M
    vm-105-disk-0  210G  30.0G      8    260 384K  11.2M

Qué significa: Puedes ver el zvol más caliente: vm-113-disk-0. Eso confirma el invitado ruidoso con telemetría a nivel de almacenamiento.

Decisión: Enfócate en la carga de VM 113 y considera mover su disco a un pool menos contendidos, cambiar el patrón de escrituras (tuneo de BD) o implementar throttles sostenidos.

Tarea 15: Si Ceph está involucrado, comprueba salud y slow ops

cr0x@server:~$ ceph -s
  cluster:
    id:     3f0c2c2d-7f8b-4d17-9e21-2a7d3c3b2a91
    health: HEALTH_WARN
            2 osds down
            154 slow ops, oldest one blocked for 37 sec, osd.12 has slow ops

  services:
    mon: 3 daemons, quorum mon1,mon2,mon3
    mgr: mgr1(active)
    osd: 12 osds: 10 up, 10 in

  data:
    pools:   6 pools, 256 pgs
    objects: 4.12M objects, 15 TiB
    usage:   46 TiB used, 18 TiB / 64 TiB avail
    pgs:     12 pgs degraded, 9 pgs undersized

Qué significa: Ceph advierte sobre slow ops y OSDs caídos. Eso se manifestará como iowait en nodos hipervisores que usan RBD, porque las lecturas/escrituras bloquean en el clúster.

Decisión: Un problema de Ceph supera al problema de la VM. Estabiliza el clúster (OSDs, red, límites de backfill) antes de culpar a un invitado.

Cómo encontrar la VM o contenedor ruidoso (de verdad)

“Vecino ruidoso” es una forma educada de decir “un invitado se está comiendo el subsistema de almacenamiento y todos los demás pagan la factura.” En Proxmox tienes tres ángulos prácticos para encontrarlo:

  1. Ángulo del proceso: ¿qué PID está haciendo E/S? (qemu-system-x86, herramientas de backup, zfs, ceph-osd).
  2. Ángulo del objeto de almacenamiento: ¿qué volumen está más caliente? (nombre ZVOL, imagen RBD, LV de LVM, archivo qcow2).
  3. Ángulo del invitado en Proxmox: ¿qué VMID/CTID reporta alto throughput de disco?

Ángulo del proceso: QEMU suele ser el culpable

En un nodo típico, cada VM se mapea a un proceso qemu-system-x86. Si ese proceso está escribiendo 60–200 MB/s en un dispositivo que no puede sostenerlo, el iowait sube. Si el dispositivo empieza a hacer timeouts, el host se congela. Tu objetivo es ligar la E/S a un VMID rápido.

Cuando el host está lento, evita comandos “ancho” costosos. Prefiere consultas estrechas:

  • pidstat -d 1 5 es barato y te da una lista ordenada.
  • ps -p PID -o cmd te da el VMID rápido.
  • iostat -x te dice si es saturación o patología.

Un chiste, como premio: Si tu host está al 100% de iowait, tu CPU no está “idle”. Está practicando mindfulness mientras los discos hacen pánico.

Ángulo del objeto de almacenamiento: mapear volúmenes calientes a invitados

Dependiendo de tu backend de almacenamiento, “lo caliente” se ve distinto:

  • ZFS zvol: rpool/data/vm-113-disk-0 (maravillosamente obvio).
  • QCOW2 en almacenamiento por directorio: un archivo como /var/lib/vz/images/113/vm-113-disk-0.qcow2.
  • LVM-thin: un LV como /dev/pve/vm-113-disk-0.
  • Ceph RBD: una imagen como vm-113-disk-0 en un pool.

El truco es trabajar hacia atrás: identifica el dispositivo caliente, luego el volumen lógico caliente, luego el VMID, luego la carga dentro del invitado.

Ángulo del invitado en Proxmox: estadísticas rápidas por invitado

Proxmox puede mostrar throughput de disco por invitado, lo cual es útil pero no suficiente. El throughput no es el villano; la latencia sí. Aun así, el throughput por invitado es una gran lista de “a quién interrogar”.

cr0x@server:~$ qm list
 VMID NAME         STATUS     MEM(MB)    BOOTDISK(GB) PID
 105  app01        running     8192              120  2144
 113  db01         running     16384             500  2911
 127  ci-runner01  running     4096               80  3382

Qué significa: Tienes los VMIDs y PIDs; ahora puedes cruzarlo con la salida de pidstat/iotop.

Decisión: Elige el invitado con el QEMU PID más caliente, luego verifica a nivel de almacenamiento qué volumen está impactando. No “apagues al azar la VM más grande” a menos que disfrutes de outages innecesarios.

Modos de fallo de backends de almacenamiento: ZFS, Ceph, LVM-thin, NFS/iSCSI

ZFS en Proxmox: los sospechosos habituales

ZFS es excelente diciendo la verdad sobre los datos. Es menos tolerante con cargas que son heavy en sync y aleatorias en SSDs de consumo. En Proxmox, los incidentes de rendimiento de ZFS tienden a caer en estos grupos:

  • Vdev degradado o dispositivo fallando: picos de latencia y timeouts, especialmente bajo carga de escritura.
  • Contención por scrub/resilver: trabajos en segundo plano compiten con los invitados por I/O y pueden dejar sin recursos a cargas sensibles a latencia.
  • Presión de escrituras sync: bases de datos y algunos sistemas de archivos emiten flushes frecuentes; sin un SLOG apropiado (y con expectativas correctas), las escrituras se serializan.
  • Fragmentación y bloques pequeños: pools con mucho churn pueden degradar la E/S aleatoria, especialmente en HDDs.

Operativamente, ZFS es amigable porque te da zpool status y zfs iostat que son realmente útiles durante un incidente. Úsalos.

Ceph: cuando la red forma parte de tu disco

Con Ceph, un iowait alto en el hipervisor puede no tener nada que ver con discos locales. Puede ser:

  • OSDs caídos o inestables causando PGs degradados y slow ops.
  • Tormentas de backfill/recovery saturando red o discos.
  • Uso desigual de OSDs (hotspot) por problemas CRUSH o pocas imágenes grandes.
  • Problemas de red (drops, MTU mismatch, agotamiento de buffers) transformando “almacenamiento” en ciudad de retransmisiones.

Si Ceph dice “slow ops”, escucha. iowait es solo el mensajero. No lo dispares; arregla el clúster.

LVM-thin: el dolor de la metadata es real

LVM-thin puede ser rápido y sencillo. También puede arruinarte la tarde cuando la metadata del thin-pool se queda corta o el pool se llena. Cuando el thin provisioning está cerca de capacidad, puedes ver parones súbitos, pausas de asignación y picos de latencia en los invitados.

Regla práctica: mantén los thin pools cómodamente por debajo del 80–85% salvo que tengas monitoreo fuerte y un procedimiento probado de ampliación.

NFS/iSCSI: “el disco está bien” (en el host de otra gente)

Los fallos de almacenamiento en red son geniales porque te permiten discutir con otro equipo mientras tu nodo se congela.

Atento a:

  • Saturación de un único punto de montaje: un head NFS se convierte en cuello de botella.
  • Congestión de red: microbursts pueden inflar la latencia dramáticamente.
  • Timeouts de HBA/controlador en iSCSI/Fibre Channel que aparecen en logs del kernel y tareas bloqueadas.

Tres micro-historias corporativas desde el frente

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

Tenían un clúster Proxmox modesto con mezcla de apps web y una sola VM de base de datos “importante”. El almacenamiento era mirrors ZFS locales sobre NVMe. Todo había sido estable durante meses, así que la suposición se solidificó en dogma: “NVMe significa que el almacenamiento no puede ser el cuello de botella”.

Una mañana el nodo empezó a congelarse. El equipo persiguió CPU, luego RAM, luego red. Reiniciaron algunos servicios. Incluso culparon a la versión del kernel. Mientras tanto, el iowait se mantenía en 90–100% y las VMs tartamudeaban. Nadie miró dmesg al principio porque “el hardware es nuevo”.

Cuando alguien finalmente ejecutó dmesg -T, era un muro de timeouts NVMe y reinicios de controlador. El disco no estaba “lento”. Efectivamente desaparecía y reaparecía bajo carga, creando largos bloqueos de I/O que clavaban procesos en estado D. La VM de la base de datos no fue la causa raíz; solo fue la carga que desencadenó las fallas.

La solución fue aburrida: evacuar VMs críticas, reemplazar el NVMe y actualizar firmware en las unidades restantes. El postmortem fue más interesante: su monitorización sólo miraba throughput y espacio, no latencia ni tasas de error. Habían confundido “interfaz rápida” con “dispositivo fiable”.

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

Otra organización quiso backups más rápidos. Cambiaron el horario de vzdump para ejecutarlo con más frecuencia y subieron la compresión al máximo porque el almacenamiento “era caro”. Además activaron más snapshots en discos QCOW2 porque facilitaba el rollback a los desarrolladores.

Al principio parecía un éxito: los tamaños de backup bajaron y las restauraciones “iban bien”. Luego, unas semanas después, aparecieron quejas de rendimiento durante horas de oficina. No constantes, pero sí lo suficiente para ser molesto. El gráfico mostraba picos de latencia recurrentes, y cada pico coincidía con los backups.

Esto fue lo que pasó: la combinación de QCOW2 con muchas snapshots y la compresión agresiva de backups creó una tormenta perfecta de lecturas aleatorias y churn de metadatos. El trabajo de backup no sólo leía; obligaba al almacenamiento a navegar metadatos complejos de snapshots mientras otras VMs realizaban escrituras normales. Bajo carga, el host pasaba más tiempo esperando E/S que haciendo trabajo.

La solución fue revertir la “optimización”: reducir cadenas de snapshots, pasar VMs clave a raw cuando procediera, limitar la concurrencia de backups y programar backups pesados fuera de horas de producción. La compresión se mantuvo, pero no a costa de latencia en producción. Aprendieron que “optimizar por tamaño de backup” puede ser indistinguible de “optimizar por outages”.

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

Un equipo que gestionaba un clúster Proxmox para servicios internos tenía una regla simple: cada cambio en el backend de almacenamiento requería una línea base de latencia y un plan de rollback. No uno largo. Una página con “números antes”, “números después” y “cómo deshacerlo”.

Una tarde, el iowait subió en un nodo. El on-call no debatió teoría. Ejecutaron las mismas comprobaciones base que siempre: iostat -x, zpool status, zfs iostat y una rápida búsqueda de backups. En cinco minutos vieron: scrub en ejecución, un vdev con latencia elevada y un zvol de una sola VM dominando escrituras.

Limitó la VM, pausó el scrub y migró dos invitados sensibles a latencia fuera del nodo. El host se recuperó de inmediato. Luego reemplazaron el SSD sospechoso en una ventana planificada.

Sin heroísmos. Sin adivinanzas. La parte aburrida—el hábito de mantener una línea base y una breve lista de verificación de incidentes—evitó el espiral de “deberíamos reiniciarlo” y mantuvo el impacto en usuarios contenido.

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

  • Síntoma: iowait 100%, nodo “congelado”, load average enorme.
    Causa raíz: Tareas bloqueadas por timeouts/reinicios de disco (problema de hardware/firmware).
    Solución: Revisa dmesg, ejecuta smartctl, evacua invitados, reemplaza/actualiza firmware del dispositivo. Detén scrubs/resilvers durante el incidente.
  • Síntoma: Sólo durante backups el nodo se vuelve irresponsive.
    Causa raíz: Concurrencia de vzdump demasiado alta, QCOW2 con muchas snapshots, almacenamiento de backup lento o cuello de botella NFS.
    Solución: Reduce concurrencia de backups, escalona trabajos, limita I/O, considera discos raw para VMs calientes, asegúrate que el objetivo de backup tiene IOPS y ancho de banda de red suficientes.
  • Síntoma: Una VM es lenta, las demás también se degradan.
    Causa raíz: Vecino ruidoso saturando la cola de almacenamiento compartida (single vdev, SSD único, o metadata de thin pool).
    Solución: Limita la VM, muévela a almacenamiento más rápido/aislado, arregla la carga del invitado (tormentas de logs, checkpoints de BD).
  • Síntoma: VMs con Ceph tienen pausas aleatorias de varios segundos.
    Causa raíz: Slow ops en Ceph por OSDs caídos/backfill/recovery o problemas de red.
    Solución: Atiende la salud de Ceph primero: restaura OSDs, ajusta recovery/backfill, verifica MTU y drops en la red, reduce temporalmente la I/O de clientes.
  • Síntoma: Picos de latencia durante scrub/resilver de ZFS.
    Causa raíz: Trabajo en segundo plano compitiendo con I/O de invitados; mirror/RAID degradado amplifica el problema.
    Solución: Programa scrubs fuera de horas, considera ajustar prioridad de scrub y no ejecutes scrubs con el pool degradado salvo que sea necesario.
  • Síntoma: Mucho espacio libre, pero la I/O es pésima; las escrituras pequeñas son especialmente malas.
    Causa raíz: Carga de escrituras sync (fsync) sin diseño apropiado; SSDs de consumo pueden ahogarse con escrituras sync sostenidas; presión de transaction group en ZFS.
    Solución: Verifica la configuración de la app invitada (journaling, parámetros de durabilidad de BD), asegura hardware adecuado para cargas sync y evita “simplemente desactivar sync en ZFS” a menos que aceptes explícitamente pérdida de datos.

Listas de verificación / plan paso a paso

Checklist de contención del incidente (10–30 minutos)

  1. Ejecuta top y vmstat para confirmar alto iowait y tareas bloqueadas.
  2. Ejecuta iostat -x 1 3 para identificar el dispositivo más caliente y observar await/util.
  3. Revisa dmesg -T | tail en busca de timeouts, reinicios y errores de E/S.
  4. Identifica procesos con mayor I/O con pidstat -d o iotop.
  5. Relaciona PID QEMU pesado con VMID vía ps y/o qm list.
  6. Detén cargas discrecionales primero: backups (vzdump), scrubs/resilvers, jobs por lotes.
  7. Limita la VM/CT ruidosa (límites I/O) en vez de apagarla, si es posible.
  8. Si hay errores de hardware: migra invitados críticos fuera del nodo y marca el dispositivo para reemplazo.
  9. Vuelve a comprobar iostat -x: el await debería bajar rápido si eliminaste la presión.
  10. Registra lo que hiciste y por qué. El futuro tú es un interesado.

Checklist de causa raíz (mismo día)

  1. ¿Fue fallo de dispositivo, saturación del backend o un pico de carga?
  2. ¿Qué invitado o proceso del host fue el mayor contribuidor?
  3. ¿Qué cambió recientemente (backups, snapshots, kernel/firmware, nueva carga)?
  4. ¿Tienes métricas de latencia (no sólo throughput) por dispositivo y por backend?
  5. ¿Tu layout de almacenamiento es apropiado (single vdev para muchas VMs, thin pool casi lleno, Ceph degradado)?
  6. ¿Necesitas límites I/O por VM por defecto en almacenamiento compartido?

Checklist de prevención (esta semana)

  1. Establece límites de I/O sensatos para cargas “no confiables” (CI, ingestion de logs, cualquier cosa controlada por desarrolladores).
  2. Programa backups y scrubs fuera de horas pico; limita la concurrencia.
  3. Monitorea latencia y errores: await por disco, errores SMART, slow ops Ceph, estados degradados ZFS.
  4. Mantén el sprawl de snapshots bajo control; podar snapshots QCOW2 y evita cadenas largas.
  5. Planifica holgura en el almacenamiento (IOPS y capacidad). Operar al límite no es optimizar costos; es elegir confiabilidad.

Preguntas frecuentes

1) ¿Por qué Proxmox “se congela” cuando el almacenamiento es lento?
Porque el host y los invitados comparten el mismo kernel y las mismas rutas de I/O. Cuando la E/S de bloque se atasca, servicios críticos (incluyendo QEMU y demonios del sistema) quedan bloqueados en estado D y el nodo se vuelve poco responsivo.
2) ¿100% iowait siempre es un problema de disco?
No. Es un problema de “la finalización de E/S tarda”. Puede ser disco local, controlador RAID, clúster Ceph, servidor NFS, ruta iSCSI o incluso presión severa de memoria causando swap I/O. Pero casi siempre es “latencia en la ruta de almacenamiento”.
3) ¿Cuál es la forma más rápida de encontrar la VM ruidosa?
Usa pidstat -d o iotop para encontrar el PID QEMU con más I/O, luego mapea ese PID al VMID mediante la línea de comandos del proceso (-id) o qm list.
4) ¿Debería simplemente reiniciar el host Proxmox?
Sólo si aceptas downtime de invitados y no puedes recuperar el control. Los reinicios ocultan evidencia y no arreglan dispositivos fallando o backends saturados. Si ves timeouts en dmesg, un reinicio puede comprar minutos, no una solución.
5) ¿Puedo arreglar esto cambiando el planificador de I/O?
A veces ayuda en los márgenes. No solucionará timeouts, hardware fallando o un backend incapaz de cumplir IOPS/latencia requeridos. Diagnostica primero. Ajusta después.
6) ¿Es seguro poner sync=disabled en ZFS para reducir iowait?
Es “seguro” sólo si estás cómodo perdiendo escrituras recientes ante una pérdida de energía o fallo. Para muchas bases de datos y sistemas de archivos, eso no es un riesgo teórico. Si lo haces, documentalo como un trade-off explícito de durabilidad.
7) ¿Por qué los backups causan tanto dolor?
Los backups son deceptivamente pesados: leen mucho, tocan metadatos y pueden interactuar mal con snapshots y capas copy-on-write. Si el destino de backup es lento, el origen también puede atascarse.
8) ¿Cómo evito que una VM derribe el nodo?
Usa limitación de I/O por disco por VM, separa cargas de alto I/O en almacenamiento dedicado y aplica políticas de backup/scrub. Además, monitoriza latencia y errores para detectar degradación antes de que se convierta en congelamiento.
9) ¿Y si varios dispositivos muestran await alto?
Entonces el cuello de botella puede estar por encima de la capa de dispositivo: un controlador compartido, un thin pool, Ceph/red o congestión de writeback a nivel sistema. Confirma con herramientas específicas del backend (ZFS/Ceph) y buscando un proceso dominante.
10) ¿Cómo sé si es saturación o un disco moribundo?
La saturación normalmente muestra alta util y await elevado pero sin timeouts/reinicios en dmesg. Un disco moribundo suele mostrar timeouts, reinicios, errores de E/S y errores SMART que aumentan con el tiempo.

Conclusión: siguientes pasos que realmente reducen incidentes

No “arreglas iowait”. Arreglas la ruta de almacenamiento y el comportamiento de carga que generó una latencia inaceptable. Empieza con el guion rápido: demuestra que es latencia de I/O, identifica el invitado ruidoso, contiene el radio de impacto y luego decide si estás ante saturación o fallo.

Pasos prácticos:

  1. Añade límites I/O por VM para los sospechosos habituales (CI, ingestión de logs, cargas batch).
  2. Haz visible la latencia: await/util de iostat, estado de pools ZFS, slow ops de Ceph, recuentos de errores SMART.
  3. Deja de tratar los backups como “trabajo gratis”. Limita concurrencia y prográmalos como mantenimiento—porque lo son.
  4. Reemplaza dispositivos moribundos pronto. Esperar al fallo total no es valentía; es papeleo.

Un último chiste secundario: Lo único peor que una VM vecina ruidosa es una silenciosa—porque puede ya estar atrapada en estado D y reteniendo a tu host en silencio.

Cita (idea parafraseada): Gene Kranz: “Sé duro y competente.” En términos de operaciones: mide primero, luego actúa con decisión.

← Anterior
Debian 13: SSHFS vs NFS — elige el que no se cuelgue aleatoriamente (y configúralo bien) (caso #21)
Siguiente →
WordPress “Database Needs Repair”: qué significa y cómo arreglarlo de forma segura

Deja un comentario