Ubuntu 24.04: Bloqueos de disco bajo carga — ajustes de tiempo que evitan paradas completas (caso #90)

¿Te fue útil?

Cuando un disco se vuelve lento, tu sistema no debería volverse filosófico al respecto. Aun así, bajo I/O intenso, máquinas con Ubuntu 24.04 pueden parecer “colgadas” incluso cuando la CPU está inactiva y la memoria está bien: porque el kernel está esperando educadamente a un almacenamiento que dejó de ser educado.

Esto no es solo “rendimiento”. Es vivibilidad. La diferencia entre un pico de latencia y una parada total del servicio suele ser una mano de timeouts, comportamientos de colas y rutas de recuperación que configuraste —o heredaste por accidente—.

Cómo se ve realmente un “bloqueo de disco” en Ubuntu 24.04

“Bloqueo” es una palabra imprecisa, así que afínala. En este caso, la máquina no está caída. Está atrapada esperando la finalización de I/O. Eso significa:

  • El acceso SSH funciona, pero comandos como ls o df se congelan al tocar montajes afectados.
  • El promedio de carga sube, pero el uso de CPU parece aburrido. Son tareas ejecutables esperando I/O bloqueado, no una tormenta de cómputo.
  • Las unidades de systemd dejan de responder a stop/restart. Están atascadas en sueño ininterrumpible (estado D).
  • Los registros del kernel mencionan timeouts, reseteos, “blocked for more than 120 seconds” o esperas del journal del sistema de archivos.

El objetivo no es “hacer que los discos nunca se pongan lentos”. El objetivo es: cuando los discos se pongan lentos o desaparezcan, el sistema se recupere rápido, falle las peticiones rápidamente y no se quede clavado intentando ser útil.

Una verdad operacional: el kernel puede esperar más tiempo del que tu negocio puede permitir. Tu trabajo es alinear esos relojes.

Guion de diagnóstico rápido

Cuando producción se está derritiendo, no empieces editando sysctls. Empieza respondiendo tres preguntas: qué está atascado, dónde está atascado y por qué la recuperación no está ocurriendo.

Primero: confirma que es espera de I/O e identifica el dispositivo

  • Comprueba iowait y tareas bloqueadas.
  • Encuentra qué(s) montaje(s) y qué dispositivo(s) de bloque están involucrados.
  • Busca mensajes evidentes del kernel sobre reseteos/timeouts.

Segundo: decide si estás en territorio de “pico de latencia” o “falla de ruta/dispositivo”

  • Pico de latencia: el I/O se completa finalmente; las colas se acumulan; puede que los timeouts no se disparen.
  • Falla: los comandos se cuelgan indefinidamente; multipath puede estar haciendo cola para siempre; el controlador puede reintentar durante minutos.

Tercero: comprueba qué política está empeorando el bloqueo

  • Multipath: queue_if_no_path puede convertir un destello SAN transitorio en un bloqueo de la aplicación.
  • Timeouts de dispositivo: los timeouts SCSI o NVMe determinan cuánto tiempo el kernel sigue intentando antes de reportar error o resetear.
  • Comportamiento del sistema de archivos: commits del journal y operaciones de metadatos pueden serializar y bloquear trabajo no relacionado.
  • Timeouts de servicio: systemd puede esperar demasiado antes de fallar rápido o reiniciar.

Consigue los hechos rápido, luego gira la perilla correcta. Bajo presión, a la gente le encanta tocar perillas al azar. Así terminas con un sistema que falla más rápido de lo que se recupera.

Hechos y contexto que cambian cómo depuras

Aquí tienes algunos puntos concretos—algunos históricos—que explican por qué los problemas de “bloqueo de disco” se comportan así:

  1. El I/O de bloque en Linux puede bloquear en sueño ininterrumpible (estado D), lo que significa que las señales no matan al proceso. Por eso kill -9 parece impotente.
  2. El manejo de errores SCSI es intencionalmente paciente. Intenta recuperar sin pérdida de datos, lo cual es estupendo—hasta que tus apps necesitan una falla rápida.
  3. El umbral por defecto de advertencia de “tarea bloqueada” (a menudo 120s) no es un timeout; es una queja. El trabajo puede quedarse bloqueado mucho después de que veas la advertencia.
  4. Multipath fue diseñado para sobrevivir telas de conexión inestables. Características como “queue when no paths” buscaban preservar escrituras durante pérdida de ruta, pero pueden congelar el espacio de usuario.
  5. NCQ y colas profundas (SATA/SAS) mejoraron el rendimiento, pero las colas grandes pueden amplificar la latencia de cola bajo contención. Un comando lento puede quedarse delante de muchos otros.
  6. NVMe trajo informes de errores rápidos y resets de controlador comparado con el comportamiento antiguo de SATA, pero la política de reset/reconexión sigue importando, especialmente con peculiaridades de PCIe.
  7. El journaling de Ext4 existe para mantener metadata consistente. Bajo bloqueos de almacenamiento, los commits del journal pueden bloquear operaciones que parecen no relacionadas, como crear un archivo en otro directorio.
  8. Las políticas de caché de escritura han sido campo de batalla de fiabilidad durante décadas: las cachés rápidas ocultan latencia hasta que no lo hacen, y entonces lo exponen como picos gigantes.
  9. La virtualización añadió capas de colas (capa de bloque del invitado, colas virtio, colas HBA del host, colas del arreglo). La latencia cola se compone a través de capas.

Chequeo de realidad seco-humorístico: los discos no “se cuelgan”. Entablan una relación a largo plazo con tu kernel, y tu kernel no cree en rendirse rápido.

Timeouts: el modelo que necesitas en la cabeza

No existe un único “timeout de disco”. Hay varios temporizadores y políticas que se apilan, a veces multiplicativamente:

  • Timeouts de comando a nivel de dispositivo (SCSI device_timeout / timeout por dispositivo; timeouts de controladores NVMe).
  • Recuperación de transporte/enlace (reseteos de enlace SAS, eventos de fibra FC, timeouts de sesión iSCSI, comportamiento de retransmisión TCP).
  • Política del mapper (comportamiento de colas dm-multipath, fast_io_fail_tmo, dev_loss_tmo).
  • Comportamiento de la capa RAID (timeouts de mdraid; firmware del controlador; caché de escritura).
  • Timeouts del sistema de archivos/journal (no siempre explícitos, pero intervalos de commit y comportamientos de sync).
  • Timeouts de aplicación/servicio (timeouts de unidades systemd, timeouts de peticiones cliente, timeouts de sentencias de base de datos).

Cuando la ruta de disco está rota, el kernel puede seguir reintentando, remapeando y esperando. Eso puede ser el valor por defecto correcto para la integridad de datos. En producción, tienes que decidir: ¿prefieres esperar o prefieres fallar? Para una escritura de base de datos, esperar puede ser más seguro. Para un nodo API sin estado, fallar rápido y reprogramar puede ser el objetivo.

Una cita que debería estar en cada rotación on-call: La esperanza no es una estrategia. — General Gordon R. Sullivan

El truco es elegir valores de timeout que encajen con el tiempo de recuperación de tu entorno. Si tu failover SAN tarda 15–30 segundos, no configures una política que bloquee indefinidamente. Si el firmware de tu SSD ocasionalmente necesita 5 segundos para recuperarse, no pongas timeouts a 1 segundo y causes resets constantes.

Tareas prácticas (comandos, qué significa la salida y qué decides)

Quieres comandos reales, no sensaciones. Estas tareas están ordenadas más o menos de “seguras y rápidas” a “esto cambia el comportamiento”. Ejecútalas en Ubuntu 24.04; la mayoría requieren root.

Task 1: Confirmar alto iowait y presión de la cola de ejecución

cr0x@server:~$ mpstat -P ALL 1 5
Linux 6.8.0-xx-generic (server)  12/31/2025  _x86_64_  (16 CPU)

12:00:01 AM  CPU   %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
12:00:02 AM  all   2.10  0.00  1.20   41.30 0.00  0.20   0.00   0.00    0.00  55.00

Significado: iowait en 40%+ sugiere que las CPU están inactivas porque esperan almacenamiento, no porque el sistema esté “ocupado”.

Decisión: Pasa a identificar el dispositivo. No ajustes CPU. No persigas el “promedio de carga” aún.

Task 2: Identificar procesos atascados en estado D

cr0x@server:~$ ps -eo pid,stat,comm,wchan:32 | awk '$2 ~ /D/ {print}'
23144 D    postgres  io_schedule
28901 D    rsync     ext4_sync_file

Significado: Estos procesos están bloqueados en rutas de espera de I/O del kernel.

Decisión: Mapéalos a sistemas de archivos/dispositivos; no pierdas tiempo intentando matarlos.

Task 3: Ver qué montaje es lento tocando metadata

cr0x@server:~$ sudo timeout 3s stat /var/lib/postgresql || echo "stat timed out"
stat timed out

Significado: Incluso una operación de metadata se bloquea. Eso apunta a bloqueo a nivel de sistema de archivos en ese montaje.

Decisión: Identifica qué dispositivo de bloque respalda ese montaje.

Task 4: Mapear un montaje a su dispositivo de bloque

cr0x@server:~$ findmnt -no SOURCE,TARGET,FSTYPE /var/lib/postgresql
/dev/mapper/mpatha /var/lib/postgresql ext4

Significado: Esto es un dispositivo dm-multipath, no un simple /dev/sdX.

Decisión: Revisa la política de multipath y la salud de las rutas antes de tocar los pernos de ext4.

Task 5: Buscar mensajes del kernel sobre timeouts/resets

cr0x@server:~$ dmesg -T | egrep -i 'tim(e|ed) out|abort|reset|blk_update_request|I/O error|blocked for more'
[Wed Dec 31 00:01:12 2025] sd 3:0:0:1: timing out command, waited 180s
[Wed Dec 31 00:01:12 2025] blk_update_request: I/O error, dev dm-2, sector 81234567 op 0x1:(WRITE)
[Wed Dec 31 00:03:14 2025] INFO: task jbd2/dm-2-8:123 blocked for more than 120 seconds.

Significado: El kernel esperó 180s antes de declarar que un comando hizo timeout; el hilo del journal de ext4 está bloqueado.

Decisión: Tu presupuesto de vivibilidad se está gastando en la capa SCSI/dispositivo. Ajusta timeouts y/o el comportamiento de multipath.

Task 6: Comprobar la cola por dispositivo y los ajustes del planificador

cr0x@server:~$ lsblk -o NAME,TYPE,SIZE,MODEL,HCTL,STATE,SCHED,ROTA
NAME            TYPE  SIZE MODEL            HCTL       STATE SCHED    ROTA
sda             disk  1.8T ST2000NM000A      0:0:0:0    running mq-deadline    1
mpatha          mpath 2.0T                   -          running none           1

Significado: Almacenamiento rotacional + elecciones de planificador influyen la latencia bajo carga, pero no arreglarán la pérdida de ruta. El mapper muestra none porque la capa dm difiere el scheduling.

Decisión: Tenlo en cuenta más adelante; primero estabiliza el comportamiento de fallo con timeouts.

Task 7: Medir latencia y profundidad de cola

cr0x@server:~$ iostat -x 1 5
Device            r/s   w/s   rkB/s   wkB/s  await  aqu-sz  %util
sda              5.0  85.0    80.0  2400.0  180.0   32.0   99.8
dm-2             0.0  90.0     0.0  2400.0  185.0   31.5   99.9

Significado: await ~180ms con tamaño de cola ~32 a casi 100% de utilización. Bajo fallo, puede ver await subir a segundos y no bajar jamás.

Decisión: Si esto es un pico, mejora el rendimiento/colas. Si es un bloqueo, céntrate en failover y timeouts.

Task 8: Confirmar estado de multipath y si está haciendo cola

cr0x@server:~$ sudo multipath -ll
mpatha (3600508b400105e210000900000490000) dm-2 HP,MSA2040
size=2.0T features='1 queue_if_no_path' hwhandler='0' wp=rw
|-+- policy='service-time 0' prio=1 status=active
| `- 3:0:0:1 sdb 8:16 active ready running
`-+- policy='service-time 0' prio=1 status=enabled
  `- 4:0:0:1 sdc 8:32 failed faulty running

Significado: queue_if_no_path está habilitado; una ruta falló. Si todas las rutas fallan, I/O hará cola en vez de fallar.

Decisión: Decide si tu carga prefiere escrituras en cola (riesgo de bloqueo de la aplicación) o fallo rápido (riesgo de errores de escritura pero mejor vivibilidad del servicio).

Task 9: Inspeccionar timeouts de dm-multipath (fast fail y pérdida de dispositivo)

cr0x@server:~$ sudo cat /sys/block/dm-2/dm/uuid
mpath-3600508b400105e210000900000490000

cr0x@server:~$ sudo cat /sys/block/dm-2/queue/io_timeout
0

Significado: io_timeout de 0 típicamente significa “usar por defecto / sin timeout explícito aquí”, que a menudo equivale a “esperar mucho tiempo en otra parte”.

Decisión: Prefiere políticas explícitas: establece valores fast fail en multipath y asegúrate de que los timeouts SCSI no sean absurdos para tus SLAs.

Task 10: Verificar el timeout del dispositivo SCSI en efecto

cr0x@server:~$ sudo cat /sys/block/sdb/device/timeout
180

Significado: 180 segundos por comando es una eternidad en la tierra de las peticiones. Un solo comando atascado puede inmovilizar la cola.

Decisión: Para muchos entornos, 30–60 segundos es un techo más razonable, pero solo si tu almacenamiento puede recuperarse en esa ventana.

Task 11: Identificar el transporte (SAS/iSCSI/NVMe) para elegir las perillas correctas

cr0x@server:~$ lsblk -S -o NAME,TRAN,TYPE,MODEL,SERIAL
NAME TRAN TYPE MODEL            SERIAL
sdb  sas  disk HP LOGICAL VOLUME 600508b4...
sdc  sas  disk HP LOGICAL VOLUME 600508b4...

Significado: Esto es almacenamiento SAS, probablemente vía controlador RAID o caja SAN, no NVMe.

Decisión: La sintonía de timeout SCSI y las políticas de multipath importan más que los ajustes de reset de NVMe aquí.

Task 12: Buscar dolor a nivel de sistema de archivos (errores ext4, journal, remount)

cr0x@server:~$ sudo dmesg -T | egrep -i 'ext4|jbd2|remount|buffer i/o error' | tail -n 20
[Wed Dec 31 00:03:14 2025] INFO: task jbd2/dm-2-8:123 blocked for more than 120 seconds.
[Wed Dec 31 00:03:18 2025] EXT4-fs (dm-2): Delayed block allocation failed for inode 262145 at logical offset 0 with max blocks 16 with error 5

Significado: ext4 está viendo errores de I/O y el hilo del journal está bloqueado. Las operaciones del sistema de archivos se irán en cadena.

Decisión: Arregla primero la recuperación subyacente de I/O. El tuning del sistema de archivos no vencerá bloques faltantes.

Task 13: Ver los timeouts de systemd y el comportamiento de stop-job (vivibilidad de servicios)

cr0x@server:~$ systemctl show postgresql --property=TimeoutStartUSec,TimeoutStopUSec,KillMode
TimeoutStartUSec=1min 30s
TimeoutStopUSec=1min 30s
KillMode=control-group

Significado: systemd esperará 90 segundos antes de declarar fallo de start/stop. Pero si el proceso está en estado D, puede ignorar las señales de terminación.

Decisión: No puedes “systemd-izar” un bloqueo de I/O del kernel. Pero puedes mantener servicios front-end saludables aislando unidades dependientes de almacenamiento.

Task 14: Confirmar si el kernel está inundado con advertencias de tareas bloqueadas

cr0x@server:~$ sudo sysctl kernel.hung_task_timeout_secs
kernel.hung_task_timeout_secs = 120

Significado: Esto es control de ruido diagnóstico, no una solución. Cambiarlo cambia cuándo recibes advertencias, no cuándo vuelve el I/O.

Decisión: No “arregles” el incidente silenciando la alarma. Úsala para correlacionar en el tiempo los bloqueos con problemas de ruta.

Task 15: Capturar rápidamente un trace de pila de tareas bloqueadas

cr0x@server:~$ echo w | sudo tee /proc/sysrq-trigger
w

Significado: El kernel volcará las pilas de tareas bloqueadas a dmesg/journal. Es desagradable, pero te dice qué capa está esperando (dm, scsi, filesystem, etc.).

Decisión: Usa esto para demostrar si estás atascado en colas de multipath, EH de SCSI o esperas del journal del sistema de archivos.

Task 16: Vigilar atributos udev para configuración persistente de timeouts

cr0x@server:~$ udevadm info --query=all --name=/dev/sdb | egrep 'ID_MODEL=|ID_SERIAL=|ID_WWN=|DEVPATH='
E: DEVPATH=/devices/pci0000:00/0000:00:1f.2/host3/target3:0:0/3:0:0:1/block/sdb
E: ID_MODEL=LOGICAL_VOLUME
E: ID_SERIAL=600508b400105e210000900000490000
E: ID_WWN=0x600508b400105e210000900000490000

Significado: Puedes emparejar dispositivos específicos (WWN) para aplicar reglas udev que establezcan timeouts de forma consistente tras reinicios.

Decisión: Si ajustas timeouts, hazlos persistentes vía udev o configuración de multipath—no con escrituras ad-hoc en sysfs.

Sí, son muchos comandos. Pero estar de guardia no es el momento para “simplemente intentar un reboot”. Los reinicios están bien; el misterio es caro.

Ajustes de tiempo que previenen paradas completas

Hablaremos de los ajustes que determinan si un disco lento provoca “algunos errores” o “todo el nodo deja de responder”. La elección correcta depende de si el almacenamiento es local, RAID, SAN multipath, iSCSI o NVMe. Pero la forma del problema es la misma: limita cuánto tiempo esperas antes de fallar y asegúrate de que el failover ocurra dentro de ese límite.

1) Timeout de comando de disco SCSI: /sys/block/sdX/device/timeout

Para dispositivos SCSI (que incluye la mayoría de SAS, FC, iSCSI y LUNs SAN), cada dispositivo de bloque expone un timeout en segundos.

cr0x@server:~$ sudo cat /sys/block/sdb/device/timeout
180

Qué hace: cuánto tiempo espera el kernel por un comando antes de declararlo timed out y entrar en manejo de errores (EH). EH puede incluir reintentos, resets y recuperación del bus.

Por qué causa bloqueos: si permites que un solo comando espere 180 segundos, todo lo que esté detrás puede amontonarse. Algunos dispositivos/rutas serializan ciertos comandos; obtienes bloqueo por cabeza de línea.

Qué hacer: elige un valor que sea más largo que la jitter transitoria pero más corto que “hemos perdido la trama”. Para muchos entornos SAN empresariales, 30–60 segundos es un techo común. Para discos SATA de consumo inestables o SMR bajo presión de escritura, puede que necesites más—aunque eso es señal de que compraste el disco equivocado.

cr0x@server:~$ echo 60 | sudo tee /sys/block/sdb/device/timeout
60

Decisión operacional: si reducir esto hace que veas errores durante carga normal, tu almacenamiento no cumple expectativas. No lo “arregles” subiendo timeouts; arregla la ruta de almacenamiento o la carga.

2) Hacer persistente el ajuste de timeout con reglas udev

Las escrituras a sysfs desaparecen en reboot y al reprobe del dispositivo. Usa reglas udev para fijar timeouts según WWN/serial/model.

cr0x@server:~$ sudo tee /etc/udev/rules.d/60-scsi-timeout.rules >/dev/null <<'EOF'
ACTION=="add|change", SUBSYSTEM=="block", KERNEL=="sd[a-z]*", ENV{ID_WWN}=="0x600508b400105e210000900000490000", ATTR{device/timeout}="60"
EOF
cr0x@server:~$ sudo udevadm control --reload-rules
cr0x@server:~$ sudo udevadm trigger --subsystem-match=block --action=change

Significado: futuros add/change aplicarán el timeout automáticamente.

Decisión: haz esto solo después de probar que el nuevo timeout no rompe el comportamiento legítimo de failover.

3) dm-multipath: evitar hacer cola indefinidamente cuando las rutas desaparecen

Multipath es el acelerador clásico de “bloqueo de disco bajo carga”. Si todas las rutas fallan y pones I/O en cola, las aplicaciones se bloquean. No reciben error, no reintentan inteligentemente; simplemente se quedan ahí. Eso puede ser aceptable para algunas pilas de almacenamiento; es veneno para servicios sin estado.

Concepto clave: poner en cola oculta la falla. La falla oculta se convierte en un bloqueo a nivel de nodo.

Mira las características actuales:

cr0x@server:~$ sudo multipath -ll | sed -n '1,4p'
mpatha (3600508b400105e210000900000490000) dm-2 HP,MSA2040
size=2.0T features='1 queue_if_no_path' hwhandler='0' wp=rw

Qué cambiar: En muchos entornos de producción, quieres fallo rápido cuando todas las rutas están abajo, además de una ventana de reintento acotada.

  • Deshabilita la cola indefinida (evita queue_if_no_path a menos que tengas una razón clara).
  • Usa fast_io_fail_tmo para que I/O falle rápido cuando las rutas estén abajo.
  • Usa dev_loss_tmo para decidir cuánto tiempo seguir intentando recuperar una ruta antes de rendirse.

Ejemplo conceptual de snippet de configuración de multipath (ajusta para tu entorno):

cr0x@server:~$ sudo tee /etc/multipath.conf >/dev/null <<'EOF'
defaults {
    find_multipaths yes
    user_friendly_names yes
    flush_on_last_del yes
}

devices {
    device {
        vendor "HP"
        product "MSA"
        no_path_retry 12
        fast_io_fail_tmo 5
        dev_loss_tmo 30
        features "0"
    }
}
EOF
cr0x@server:~$ sudo systemctl restart multipathd

Significado: con fast_io_fail_tmo 5, I/O puede reportar error rápido cuando no hay rutas (después de 5 segundos). Con dev_loss_tmo 30, las rutas se consideran perdidas después de 30 segundos.

Decisión: Si tu failover de almacenamiento toma 20–25 segundos, dev_loss_tmo 30 puede funcionar. Si toma 2 minutos, o estás mal configurado o vives peligrosamente, y los timeouts deben reflejar la realidad.

Segundo chiste corto: la cola de multipath es como poner quejas de clientes en un cajón etiquetado “más tarde”. Eventualmente te quedas sin cajones.

4) Específicos de iSCSI: recuperación de sesión vs vivibilidad de la app

Si tus LUNs llegan por iSCSI, tienes timeouts adicionales: retransmisiones TCP, reemplazo de sesión iSCSI y multipath. iSCSI puede ser muy sólido, pero solo si eliges una postura operativa: fallo rápido o “mantener las escrituras hasta que el mundo sane”.

Comprueba el estado de la sesión:

cr0x@server:~$ sudo iscsiadm -m session
tcp: [1] 10.10.10.20:3260,1 iqn.2001-04.com.example:storage.lun1 (non-flash)

Significado: tienes una sesión iSCSI activa. Si los bloqueos de almacenamiento se correlacionan con caídas/reconexiones de sesión, ajusta iSCSI y multipath en conjunto.

Decisión: No pongas multipath para fallar en 5 segundos si iSCSI tarda 30 segundos en restablecerse y realmente quieres que sobreviva.

5) NVMe: los reseteos de controlador son rápidos, pero no mágicos

En NVMe local, los bloqueos son normalmente distintos: fallos de firmware, eventos AER de PCIe, estrangulamiento térmico o peculiaridades de power management. No tienes timeouts SCSI; tienes comportamiento de controlador NVMe y lógica de reset del driver.

Comprueba errores y reseteos NVMe:

cr0x@server:~$ sudo dmesg -T | egrep -i 'nvme|AER|reset|timeout' | tail -n 20
[Wed Dec 31 00:02:01 2025] nvme nvme0: I/O 123 QID 6 timeout, aborting
[Wed Dec 31 00:02:02 2025] nvme nvme0: reset controller

Significado: el driver está abortando y reseteando activamente. Eso suele ser mejor que esperar 180 segundos, pero los resets aún pueden bloquear el sistema de archivos si ocurren con frecuencia.

Decisión: Si los reseteos son frecuentes, trátalo primero como problema de hardware/firmware. Ajustar timeouts no sustituye a un dispositivo estable.

6) Sistema de archivos y opciones de montaje: no confundas síntomas con causas

Bajo verdaderos bloqueos de dispositivo, las opciones del sistema de archivos son secundarias. Aun así, algunas elecciones afectan qué tan rápido sienten las aplicaciones el dolor:

  • Intervalo de commit de ext4 afecta con qué frecuencia la metadata se fuerza al disco. Commit más bajo puede aumentar la presión de sync; commit más alto puede aumentar la ventana de recuperación y picos de latencia.
  • barriers / caché de escritura son manejados correctamente por stacks modernos, pero cachés mal reportadas o flushes deshabilitados pueden convertir bloqueos en corrupción.
  • noatime reduce escrituras de metadata; no arreglará un bloqueo, pero puede reducir presión de fondo.

Opinión: no “montes” para solucionar una falla de ruta. Arregla la ruta. Luego optimiza.

7) Timeouts a nivel de servicio: contener el radio de explosión

No siempre puedes evitar que el almacenamiento se vaya, especialmente con almacenamiento en red. Puedes evitar que tome todo el nodo como rehén diseñando para fallos parciales:

  • Mantén servicios críticos fuera de montajes cuestionables (sí, incluso si son “solo logs”).
  • Usa TimeoutStopSec y políticas Restart de systemd apropiadamente, pero recuerda que procesos en estado D no pueden ser matados limpiamente.
  • Prefiere timeouts a nivel de aplicación. Si tu llamada a la base de datos se bloquea para siempre, todo tu threadpool se convierte en una pieza de museo.

Tres mini-historias corporativas desde las trincheras

1) El incidente causado por una suposición equivocada: “El SAN hará failover instantáneo”

Una empresa mediana migró un conjunto de servicios con estado a un nuevo clúster respaldado por SAN. El equipo de almacenamiento prometió rutas redundantes y “failover automático”. El equipo de plataforma oyó “instantáneo”. Esa fue la palabra equivocada para escuchar.

Los nodos Linux estaban configurados con dm-multipath y, porque alguien leyó un blog de mejores prácticas de una era en la que la pérdida de escritura era el villano, los dispositivos tenían queue_if_no_path. La suposición era: si una ruta cae, multipath reencaminará y la app no lo notará. Pensaban como ingenieros de almacenamiento. La aplicación se comportó como una aplicación: se bloqueó.

Un switch del top-of-rack se reinició durante una ventana de mantenimiento que se alargó. Ambas rutas activas desaparecieron brevemente—no lo suficiente como para disparar pánico en el SAN, pero sí lo bastante como para que los nodos Linux pusieran en cola una montaña de escrituras. Los procesos de la base de datos pasaron a estado D. La capa API, esperando respuestas de la base de datos, llenó sus propias colas. Los balanceadores vieron “TCP sano”, pero las peticiones caducaron en el cliente. Parecía una caída de la aplicación. Fue una caída de vivibilidad por almacenamiento.

La solución fue aburrida y políticamente incómoda: acordar un objetivo de tiempo de recuperación para pérdida de ruta de almacenamiento, luego configurar multipath para fallar I/O dentro de esa ventana en vez de ponerlo en cola indefinidamente. También añadieron timeouts aguas arriba para que las peticiones de usuario no esperaran a un kernel atascado para siempre. El próximo reinicio de switch causó errores, no una parada total—y el sistema se recuperó más rápido porque la falla fue visible y acotada.

2) La optimización que se volvió en contra: “Aumentar profundidad de cola para potenciar throughput”

Un equipo de analítica tenía un batch nocturno que golpeaba un conjunto RAID. Un empuje de rendimiento bien intencionado aumentó la profundidad de cola y permitió más I/O pendiente. Los números de throughput mejoraron en benchmark. El equipo celebró y se fue a comer. Clásico.

Bajo carga real, las colas profundas amplificaron la latencia de cola. Cuando el arreglo inició tareas internas de mantenimiento (garbage collection, chequeos de paridad, lo que el firmware llamó su crisis de mediana edad), operaciones I/O individuales se volvieron lentas. Con una cola profunda, las operaciones lentas se acumularon. Cuando el sistema se dio cuenta, había cientos de solicitudes esperando, y procesos no relacionados empezaron a bloquearse en operaciones de metadata. La máquina no estaba “lenta”. Estaba intermitentemente inservible.

Intentaron “arreglarlo” aumentando los timeouts SCSI para que el kernel no reportara errores. Eso redujo errores visibles pero aumentó la duración de los bloqueos. El batch tardó más, los dashboards de negocio se retrasaron, y el on-call empezó a desarrollar opiniones sobre analítica.

La recuperación fue contraintuitiva: reducir la profundidad de cola, aceptar un throughput máximo ligeramente menor y obtener latencia predecible. También programaron el mantenimiento del arreglo fuera de las ventanas de batch. El sistema dejó de hacer la rutina “bien por 50 minutos, muerto por 5”, que es el peor tipo de teatro de fiabilidad.

3) La práctica aburrida pero correcta que salvó el día: “Hacer timeouts explícitos y probar failover”

Una firma de servicios financieros ejecutaba nodos Ubuntu con LUNs multipath para un clúster pequeño pero crítico. Nada glamoroso—solo I/O constante, SLAs estrictos y una cultura que desconfiaba de las heroicidades.

Tenían una práctica simple: los timeouts eran configuración, no folklore. Para cada clase de almacenamiento, documentaban los tiempos de failover esperados y ajustaban fast_io_fail_tmo, dev_loss_tmo y el device/timeout SCSI para alinearlos con eso. Además realizaban un ejercicio trimestral: desconectar una ruta, desconectar todas las rutas brevemente y verificar que los servicios o bien fallaran rápido o bien sobrevivieran—según el contrato del servicio.

Un día un problema de nube superior causó caídas de ruta intermitentes. En nodos sin esta disciplina, eso habría sido un desastre de colas silencioso. Aquí, la capa multipath falló I/O lo bastante rápido como para que la lógica de reintento de la aplicación entrara en acción. Los errores subieron, pero el clúster se mantuvo vivo. Los operadores tuvieron algo sobre lo que alertar y una ventana para redirigir tráfico.

El postmortem fue deliciosamente aburrido. Sin misterio. Sin “kernel colgado”. Solo un modo de falla conocido comportándose dentro de límites conocidos. Eso es lo que quieres: aburrimiento con recibos.

Errores comunes (síntomas → causa raíz → arreglo)

1) Síntoma: SSH funciona, pero ls en un directorio cuelga

Causa raíz: el directorio está en un sistema de archivos cuyo dispositivo de bloque subyacente está bloqueado; las lecturas de metadata esperan la finalización de I/O.

Arreglo: identifica el montaje con findmnt, luego inspecciona logs del kernel y timeouts de dispositivo. Si es multipath, comprueba colas y pérdida de rutas. Si es disco local, busca resets de controlador y errores hardware.

2) Síntoma: promedio de carga enorme, CPU mayormente inactiva

Causa raíz: muchas tareas están bloqueadas en espera de I/O (estado D), contadas en el promedio de carga.

Arreglo: usa ps con wchan, iostat -x y sysrq w para volcados de pila. Apunta a la capa de almacenamiento, no al scheduling de CPU.

3) Síntoma: systemd no puede detener un servicio; stop job cuelga para siempre

Causa raíz: procesos en sueño ininterrumpible; las señales no los terminarán mientras el kernel espera I/O.

Arreglo: arregla la ruta de I/O. Para contención, considera aislar el montaje, hacer failover o reiniciar el nodo si la recuperación es imposible. No pierdas una hora afinando modos de kill de systemd.

4) Síntoma: no hay errores, solo largos bloqueos durante eventos SAN

Causa raíz: multipath está encolando I/O cuando las rutas desaparecen (queue_if_no_path), ocultando fallas a las apps.

Arreglo: deshabilita la cola indefinida y establece fast_io_fail_tmo/dev_loss_tmo a valores acotados alineados con el comportamiento de failover del fabric.

5) Síntoma: “EXT4-fs error” intermitente seguido de remount read-only

Causa raíz: el dispositivo subyacente devuelve errores de I/O o hace timeout; el sistema de archivos se protege remonteándose como solo lectura.

Arreglo: trata el almacenamiento como defectuoso. Revisa cableado, logs HBA, salud del arreglo, SMART/NVMe. No “arregles” con opciones de montaje.

6) Síntoma: ajustar timeouts “arregló” bloqueos pero ahora ves errores I/O aleatorios

Causa raíz: redujiste timeouts por debajo del tiempo que tu almacenamiento necesita para recuperarse; ahora operaciones lentas se tratan como fallos.

Arreglo: mide el tiempo real de failover/recuperación y sitúa los timeouts ligeramente por encima. Si la recuperación es inaceptablemente lenta, arregla la ruta de almacenamiento en vez de ocultarla.

7) Síntoma: todo se congela durante rotación de logs o backups

Causa raíz: presión sincrónica de metadata (fsync storms), o saturación de un único dispositivo con escrituras; la contención del journal bloquea operaciones no relacionadas.

Arreglo: limita la velocidad de backups, mueve logs fuera del volumen crítico, usa ionice, reduce concurrencia y verifica que el dispositivo no esté sufriendo GC interno o picos de escritura SMR.

8) Síntoma: máquinas virtuales se congelan, el host parece bien

Causa raíz: colas en el hypervisor o backend de almacenamiento; el invitado ve I/O bloqueado pero las métricas del host lo ocultan.

Arreglo: mide en cada capa: iostat del invitado, estadísticas de bloque del host, latencia del arreglo. Alinea timeouts end-to-end; no dejes que el invitado espere más de lo que el host puede recuperar.

Listas de verificación / plan paso a paso

Paso a paso: estabilizar un nodo que “se cuelga” bajo carga de disco

  1. Confirma que es almacenamiento: comprueba mpstat por iowait y ps por tareas en estado D.
  2. Mapea el dolor: usa findmnt para mapear directorios afectados a dispositivos.
  3. Lee la historia del kernel: dmesg por timeouts, reseteos, fallos de ruta y mensajes del sistema de archivos.
  4. Decide la clase: disco local vs SAN multipath vs iSCSI vs NVMe. No apliques consejos SAN a NVMe ni viceversa.
  5. Mide latencia y colas: iostat -x para ver si estás saturado o fallando.
  6. Revisa la política de multipath: busca queue_if_no_path y el estado de rutas; confirma expectativas de tiempo de failover.
  7. Establece comportamiento de fallo acotado: ajusta multipath fast_io_fail_tmo/dev_loss_tmo y timeouts SCSI basados en tiempo de recuperación medido.
  8. Hazlo persistente: reglas udev para timeout SCSI; /etc/multipath.conf para la política dm.
  9. Contén el radio de explosión: asegúrate de que servicios críticos tengan timeouts de petición sensatos; mueve escrituras no críticas (logs, temp) fuera del montaje crítico si es posible.
  10. Prueba: simula pérdida de ruta en una ventana de mantenimiento. Si no has probado el failover, estás ejecutando una teoría.

Lista: Valores a elegir (orientación, no dogma)

  • Mide primero: cuánto tarda realmente un failover de ruta en tu entorno? Usa eso como base.
  • SCSI device/timeout: a menudo 30–60s para LUNs SAN en telas estables; más largo si tu arreglo lo requiere (pero pregunta por qué).
  • Multipath fast_io_fail_tmo: 5–15s si prefieres error rápido; más largo si quieres ride-through.
  • Multipath dev_loss_tmo: 30–120s dependiendo de expectativas de recuperación de ruta.
  • Evita la cola indefinida a menos que tu pila de aplicaciones esté diseñada explícitamente para tolerarla.

Lista: Qué evitar

  • No “resuelvas” bloqueos aumentando timeouts a ciegas. Solo puedes aumentar la duración de las interrupciones.
  • No desactives mecanismos de seguridad (flushes/barriers) para perseguir números de benchmark.
  • No asumas que el failover de almacenamiento es instantáneo. Rara vez lo es y frecuentemente no es consistente.
  • No ignores procesos en estado D. Son el kernel agitando una bandera roja, no un bug de aplicación.

Preguntas frecuentes

1) ¿Por qué kill -9 no termina un proceso atascado?

Porque está en sueño ininterrumpible (estado D) esperando la finalización de I/O del kernel. El kernel no lo programará para manejar la señal hasta que el I/O vuelva o falle.

2) ¿Es kernel.hung_task_timeout_secs un timeout real que arregla bloqueos?

No. Controla cuándo el kernel te avisa sobre tareas bloqueadas. Es útil para correlación, no para remediación.

3) ¿Debería deshabilitar queue_if_no_path en multipath?

En muchos entornos de producción: sí, salvo que tengas una razón documentada para encolar indefinidamente (y un plan sobre qué hace la app mientras está bloqueada). Prefiere fallo acotado con ventanas explícitas de reintento.

4) ¿Cuál es un valor razonable de timeout SCSI?

Razonable es “ligeramente por encima de tu tiempo de recuperación de almacenamiento probado”. En la práctica, muchos entornos SAN se sitúan en el rango 30–60s; algunos requieren más. Si necesitas 180s, pregunta qué escenario lo requiere y si tus servicios pueden permitírselo.

5) Si bajo los timeouts, ¿perderé datos?

Los timeouts más bajos pueden convertir largas esperas en errores I/O. Si eso pone en riesgo datos depende de la aplicación y el sistema de archivos. Las bases de datos suelen preferir errores explícitos a bloqueos indefinidos, pero debes asegurarte de que tu stack maneje fallos de escritura correctamente.

6) Mi sistema “se cuelga” solo durante backups. ¿Es un problema de timeouts?

A menudo es saturación y colas más que fallo de ruta. Comprueba iostat -x por utilización al 100% y await alto. Luego reduce concurrencia de backups, aplica ionice o mueve backups a una ruta menos crítica.

7) ¿Cómo sé si es el disco, el controlador o el SAN?

Empieza con dmesg. Reseteos de controlador, errores de enlace y fallos de ruta dejan huellas. Luego correlaciona con multipath -ll (rutas), timeouts de dispositivo y métricas de latencia (iostat). Si el mapper tiene todas las rutas abajo y está encolando, no es culpa de ext4.

8) ¿Cambiar el planificador de I/O arregla bloqueos?

Los planificadores pueden mejorar equidad y latencia bajo carga, especialmente en medios rotacionales. No arreglarán una ruta perdida o un dispositivo que deja de responder. Trata el tuning del planificador como fase dos.

9) ¿Debo reiniciar un nodo que tiene muchas tareas en estado D?

Si la recuperación del almacenamiento no está ocurriendo y el nodo está efectivamente bloqueado, sí—un reinicio puede ser la ruta más rápida para restaurar servicio. Pero aún necesitas arreglar el comportamiento de timeout/failover subyacente o volverás a reiniciar más tarde.

10) ¿Pueden los timeouts de systemd protegerme de bloqueos de disco?

Protegen de servicios que se cuelgan en espacio de usuario. No te protegen de espera de I/O del kernel de forma fiable. Úsalos para higiene, no como estrategia de fiabilidad de almacenamiento.

Próximos pasos que puedes hacer esta semana

Si máquinas Ubuntu 24.04 “se cuelgan” bajo carga de disco, el kernel normalmente está haciendo exactamente lo que le dijiste: esperar. Tu trabajo es fijar expectativas—explícitamente—sobre cuánto tiempo está permitido esperar antes de que la recuperación o el fallo entren en acción.

  1. Ejecuta el guion de diagnóstico rápido en un nodo afectado y captura dmesg, iostat -x, multipath -ll y un volcado sysrq de tareas bloqueadas.
  2. Elige un presupuesto de vivibilidad (segundos, no minutos) para pérdida de ruta de almacenamiento y alinea timeouts SCSI y ajustes de failover de multipath a ese presupuesto.
  3. Haz persistentes esos ajustes con reglas udev y /etc/multipath.conf.
  4. Prueba la falla: desconecta una ruta, luego desconecta todas las rutas brevemente en una ventana controlada. Verifica que el comportamiento coincida con lo que tus servicios toleran.
  5. Sólo después de que la vivibilidad sea estable, afina el rendimiento: profundidad de cola, planificación y moldeado de carga.

El estado final que quieres no es “sin errores”. Es “los errores ocurren rápido, predecible y recuperablemente”, sin convertir tu nodo en una costosa app de meditación.

← Anterior
ZFS canmount: la opción que evita sorpresas al arrancar
Siguiente →
Tasas de acierto de caché ZFS: cuándo importan y cuándo no

Deja un comentario