Diagnosticar disk IO lento en Linux con iostat e iotop
Identifica cuellos de botella de disco en Linux usando iostat e iotop. Métricas %util, await, r/s, w/s explicadas con ejemplos prácticos para sysadmins.
Aplicación lenta, load average alto y CPU mostrando 20% de uso casi
siempre apuntan al mismo culpable: el disco. El síntoma clásico es una
query MySQL que normalmente corre en 50ms pasar a tardar 8 segundos
sin cambio en el plan de ejecución, o un deploy de Node.js que
demoraba 30 segundos quedar trabado en 5 minutos en npm install.
Antes de provisionar más CPU o RAM, necesitas confirmar que el cuello
de botella es IO de disco. CPU baja con load alto es la primera señal —
los procesos están en estado D (uninterruptible sleep) esperando
operaciones de disco. Este tutorial muestra cómo usar iostat e
iotop para confirmarlo en 5 minutos e identificar exactamente
qué proceso está saturando tu almacenamiento.
La persona aquí es el sysadmin Linux que ya hizo lo básico (top,
htop, free) y necesita cavar más profundo. Tiempo estimado de
ejecución: 10-15 minutos para recopilar evidencia concluyente.
Prerrequisitos
Necesitas una máquina Linux (Ubuntu 22.04+, Debian 12+, RHEL 9+
o similar) con acceso sudo o root. Las herramientas vienen en paquetes
separados que no forman parte de la instalación mínima por defecto.
sysstat iotop root o CAP_NET_ADMIN 5.4+ Confirma también que CONFIG_TASK_IO_ACCOUNTING está habilitado en el
kernel — sin esto, iotop muestra valores en cero. Verifica con:
grep CONFIG_TASK_IO_ACCOUNTING /boot/config-$(uname -r)
La salida debe ser CONFIG_TASK_IO_ACCOUNTING=y. En kernels custom o
contenedores restringidos puede aparecer como # CONFIG_TASK_IO_ACCOUNTING is not set — en ese caso, usa pidstat -d como alternativa.
Instalando las herramientas
La mayoría de las distribuciones no incluyen sysstat ni iotop en la
instalación base. Ocupan menos de 5 MB combinados.
Instala sysstat (que provee iostat, sar, pidstat, mpstat):
sudo apt update
sudo apt install -y sysstatEn RHEL/Rocky/Alma:
sudo dnf install -y sysstatInstala iotop:
sudo apt install -y iotopEn RHEL/Rocky/Alma:
sudo dnf install -y iotopConfirma las versiones instaladas:
iostat -V
iotop --versionVersiones mínimas recomendadas: sysstat 12.0+ e iotop 0.6+. Versiones
muy antiguas tienen bugs conocidos en el cálculo de %util y en la columna
svctm.
Primera lectura con iostat
iostat muestra estadísticas agregadas por dispositivo de bloque. La
primera ejecución muestra promedios desde el boot — descarta esos números
y observa las lecturas subsiguientes.
Ejecuta iostat en modo extendido con intervalo de 2 segundos:
iostat -xz 2 5Flags importantes:
-x— extendido, muestra todas las columnas relevantes (await, %util)-z— omite dispositivos sin actividad (reduce ruido)2 5— 5 muestras de 2 segundos cada una
La primera muestra es el promedio desde el boot y debe ser ignorada. Analiza desde la segunda en adelante.
Identifica el dispositivo de interés en la columna Device. En VPS
modernas será algo como vda, sda o nvme0n1. Las particiones
(vda1, nvme0n1p1) también aparecen pero quieres el dispositivo
padre para ver la actividad total.
Interpretando las métricas
Las columnas que importan para diagnóstico están concentradas en 6 campos. Ignora el resto hasta dominar estos.
| Métrica | Significado | Umbral de alerta |
|---|---|---|
r/s | Lecturas por segundo (IOPS de lectura) | Depende del disco |
w/s | Escrituras por segundo (IOPS de escritura) | Depende del disco |
rkB/s | Throughput de lectura en KB/s | Compara con el spec del disco |
wkB/s | Throughput de escritura en KB/s | Compara con el spec del disco |
await | Latencia promedio por solicitud en ms | >20ms sospechoso, >100ms crítico |
%util | % del tiempo con solicitudes pendientes | >80% saturación en HDD |
En discos rotacionales (HDD), %util cerca del 100% indica saturación
real. En SSDs y NVMes que procesan IO en paralelo, %util del 100%
puede ocurrir con 10% del ancho de banda real en uso. Usa await y compara
rkB/s + wkB/s contra el spec del disco para evaluar saturación real en
medios modernos.
La regla práctica: si await está por encima de 20ms en un SSD o por encima
de 100ms en un NVMe, tienes latencia anormal. En HDDs, valores de
50-100ms ya son esperados, pero por encima de 200ms indica sobrecarga.
Ejemplo de salida saludable
Device r/s w/s rkB/s wkB/s await %util
nvme0n1 142 89 8520 4310 0.42 12.30
0.42ms de latencia en un NVMe — normal. 12% util y ~12 MB/s combinados — disco respirando bien.
Ejemplo de salida con cuello de botella
Device r/s w/s rkB/s wkB/s await %util
vda 890 1240 45200 78900 148.6 99.80
148ms de await es crítico — algo está haciendo mucho IO sincronizado
o el disco está saturado. %util en 99.8% en un disco rotacional
confirma saturación. 2.130 IOPS combinados en un disco que normalmente
hace 200 IOPS sostenidos es evidencia de batch job mal comportado o
swap thrashing.
Encontrando el proceso culpable con iotop
iostat te dice QUE hay cuello de botella. iotop te dice QUIÉN lo está causando.
Ejecuta iotop en modo interactivo:
sudo iotop -oFlags:
-o— muestra solo procesos con IO activo (oculta los en cero)- Tecla
r— invierte la ordenación - Tecla
o— alterna modo “only active” - Tecla
q— sale
Identifica las columnas DISK READ y DISK WRITE. Los procesos en el tope
de la lista son los mayores consumidores de IO en el momento.
La columna IO> muestra el porcentaje del tiempo que el proceso pasó
esperando IO. Valores por encima del 30% sostenidos indican proceso
IO-bound — no se volverá más rápido con más CPU.
Para capturar evidencia sin dejar iotop corriendo indefinidamente,
usa modo batch:
sudo iotop -o -b -n 5 -d 2 > /tmp/iotop-snapshot.txtEsto captura 5 snapshots de 2 segundos y sale. Útil para recopilar evidencia durante una ventana de lentitud reportada y analizar después.
En contenedores o kernels sin TASK_IO_ACCOUNTING, usa pidstat -d 2 5 (viene en sysstat). Muestra IO por proceso usando contadores
diferentes que no dependen del mismo flag de kernel.
Verificación
Para confirmar que tu hipótesis de cuello de botella de disco es correcta, combina 3 evidencias:
iostat -xz 2 5mostrandoawaitalto y%utilalto sostenidosiotop -oapuntando proceso específico en el tope de la listatopohtopmostrando procesos en estadoD(uninterruptible sleep) — columnaSoSTATE
ps -eo pid,state,comm | awk '$2 == "D"'
Si esta lista tiene procesos diferentes del PID que iotop mostró,
probablemente son víctimas (esperando que el disco sea liberado por el culpable).
Si es el propio culpable, está haciendo IO síncrono pesado.
Resolución de problemas
iotop retorna “Could not run iotop as a non-root user”
iotop necesita privilegios para leer estadísticas de procesos
ajenos. Ejecuta con sudo. Si quieres permitirlo para un usuario
específico sin sudo cada vez, da la capability:
sudo setcap 'cap_net_admin+eip' $(which iotop)
iostat muestra %util del 100% pero la aplicación no está lenta
Caso clásico de SSD/NVMe donde %util perdió significado. Observa
rkB/s + wkB/s y compara con el ancho de banda nominal del disco. Si está
por debajo del 50% del ancho de banda spec, no es saturación real.
Latencia alta intermitente que iostat no captura
iostat muestra promedios en un intervalo. Picos de latencia sub-segundo
quedan escondidos en el promedio. Usa iostat -x 1 (intervalo 1s) durante la
ventana problemática, o bpftrace para capturar latencias de bloque
individuales.
Si iotop muestra kswapd0 o [kswapd] en el tope, tu sistema está en
swap thrashing — sin memoria RAM, el kernel está moviendo páginas al
disco constantemente. La solución no es optimizar IO; es agregar RAM o
encontrar la fuga de memoria. Verifica free -h y ajusta
vm.swappiness.
Próximos pasos
Con el cuello de botella identificado, los caminos comunes son:
- Aplicar tuning de IO scheduler —
mq-deadlinepara workloads transaccionales,nonepara NVMe puro - Habilitar recopilación histórica con
sar(parte desysstat) para análisis de tendencia a lo largo de semanas - Investigar con
bpftraceoperfpara capturar stack traces de los syscalls de IO más lentos - Evaluar migración a almacenamiento NVMe si el workload exige IOPS sostenidos por encima de 10k
Si estás poniendo una aplicación IO-intensiva en producción, una VPS Hostini con almacenamiento NVMe local ya entrega latencia consistente sub-1ms — lo que elimina la mayor fuente de variabilidad en diagnósticos de disco.
Preguntas frecuentes
¿%util del 100% siempre significa que el disco es el cuello de botella?
No. En SSDs y NVMe, %util refleja solamente si hay alguna solicitud en vuelo, no saturación real. Un NVMe puede mostrar 100% util y aún estar usando 5% del ancho de banda real. Confía en await, IOPS y throughput antes de concluir saturación en medios modernos.
¿Cuál es la diferencia entre await y svctm en iostat?
await es el tiempo total que una solicitud pasa en el sistema (cola + servicio), en milisegundos. svctm intentaba medir solo el tiempo de servicio, pero el cálculo era incorrecto en kernels modernos y fue removido en versiones recientes de sysstat. Usa await como métrica principal de latencia.
iotop muestra cero IO pero el sistema está lento — ¿por qué?
iotop necesita CONFIG_TASK_IO_ACCOUNTING habilitado en el kernel. En contenedores y algunos kernels personalizados aparece en cero. Confirma con cat /proc/self/io — si el archivo no existe o está vacío, el accounting está deshabilitado y necesitas usar pidstat -d o bpftrace.
¿Por qué await alto pero %util bajo?
Generalmente indica disco remoto con latencia de red (NFS, iSCSI, almacenamiento en la nube) o throttling del hipervisor en entornos virtualizados. El disco local no está saturado, pero cada solicitud demora porque va por la red. Verifica el tipo de almacenamiento y métricas de red.
iostat -x muestra rrqm/s y wrqm/s altos — ¿es malo?
No, es lo opuesto. rrqm/s y wrqm/s son solicitudes fusionadas por el kernel antes de ir al disco — significa que el IO scheduler está combinando operaciones secuenciales en batches mayores y más eficientes. Valores altos aquí suelen indicar workload secuencial bien optimizado.
¿Puedo ejecutar iotop en producción sin impacto?
Sí, el overhead de iotop es bajo (~1-2% CPU en servidores ocupados). Usa iotop -o -b -n 5 -d 2 para capturar 5 snapshots de 2 segundos en modo batch y salir — ideal para recopilar evidencia sin dejar el proceso corriendo indefinidamente.