ZFS rara vez “cae” en una conflagración dramática. Se vuelve más lento. Silenciosamente. El gráfico se mueve. La latencia se estira.
Las aplicaciones empiezan a agotar tiempos. Alguien abre un ticket sobre “lentitud intermitente”. Y entonces —porque el universo odia la humildad— tu
siguiente despliegue aterriza encima del problema y se lleva la culpa por todo.
El truco es detectar la degradación del rendimiento de ZFS mientras sigue siendo una ventana de mantenimiento, no un postmortem. Esta es una guía de campo para
leer los registros y la verdad adyacente (mensajes del kernel, errores de dispositivos, flujos de eventos de ZFS) para detectar lentitudes pronto y decidir
qué hacer después—rápido, con precisión y sin rituales de culto al cargo.
La mentalidad: los registros son una línea de tiempo, no una sensación
Los “registros” de ZFS son plurales. Está el flujo de eventos de ZFS, el buffer de anillo del kernel, el journal de systemd, los registros SMART/dispositivo,
y la propia idea de ZFS sobre la salud del pool. El objetivo no es coleccionar más texto. El objetivo es alinear las líneas de tiempo:
qué se volvió más lento, cuándo y qué más cambió.
Esta es la postura operativa que te mantiene fuera de problemas:
- Prefiere latencia sobre throughput. Los usuarios sienten la latencia del percentil 99. Los paneles que sólo muestran MB/s te mentirán.
- Asume que ZFS es honesto sobre la integridad de datos y conservador respecto al rendimiento. Cuando se ralentiza, suele estar protegiéndote de algo peor.
- Sospecha de narrativas “empezó después de X”. Los problemas de ZFS a menudo incuban durante semanas: un disco débil, un recordsize mal dimensionado, una ruta de escrituras síncronas que olvidaste que existía.
- Correlaciona a nivel de dispositivo. La mayoría de “problemas de rendimiento de ZFS” son latencia del dispositivo, encolamiento o una ruta de escritura síncrona haciendo exactamente lo que le pediste.
Una línea de registro es una pista, no un veredicto. Aún tienes que reconciliarla con la realidad: zpool iostat, arcstat, iostat,
y lo que tus aplicaciones realmente están haciendo.
Hechos interesantes y contexto histórico (para que dejes de adivinar)
- ZFS nació en la era de Solaris con un modelo de integridad de datos end-to-end—checksums por todas partes—porque la “corrupción silenciosa” ya existía, aunque no fuera un tema popular.
- El intent log (ZIL) no es una caché de escritura. Es un mecanismo para reproducir la semántica síncrona después de un crash. La mayoría de las escrituras nunca viven en “el log” a largo plazo.
- SLOG es un dispositivo, no una característica mágica. Añadir un dispositivo de log separado (SLOG) sólo ayuda a las escrituras síncronas y puede perjudicar si es lento o está mal configurado.
- Los scrubs fueron diseñados como auditoría proactiva, no como una herramienta de “reparar cuando está roto”. Son cómo ZFS demuestra que tus datos siguen siendo tuyos.
- El comportamiento de resilver evolucionó. Los resilvers modernos de OpenZFS pueden ser secuenciales y más inteligentes sobre qué copiar, pero aún pagas en contención de I/O.
- La sintonía de ARC/L2ARC tiene una larga historia de malos consejos. Muchas “guías de rendimiento” de hace una década optimizaban para cargas y ratios RAM-disco distintos.
- ashift es para siempre. Una suposición equivocada del tamaño de sector al crear el pool puede inmovilizarte en amplificación de escritura—silenciosamente costosa, ruidosamente dolorosa.
- La compresión se convirtió en estándar en operaciones ZFS porque la CPU se abarató y el I/O no. Pero la ganancia depende de la forma de tus datos, no de tus esperanzas.
Qué significa realmente “ZFS lento”: el mapa de cuellos de botella
“ZFS está lento” es como decir “la ciudad está congestionada”. ¿Qué calle? ¿Qué hora? ¿Qué carril cerrado?
En la práctica, las lentitudes de ZFS se agrupan en unas pocas categorías. Tus registros normalmente apuntarán a una:
1) Latencia de dispositivo y recuperación de errores
Un disco marginal puede bloquear un vdev. En RAIDZ y mirrors, el hijo más lento a menudo se convierte en el coche marcando el ritmo.
Los logs del kernel de Linux pueden mostrar reinicios de enlace, timeouts de comandos o eventos de “cola congelada”. ZFS puede mostrar errores de lectura/escritura/checksum.
Incluso si el disco “se recupera”, los costes de reintento se pagan en tiempo real por tu aplicación.
2) Ruta de escritura síncrona: dolor ZIL/SLOG
Si tu carga hace escrituras síncronas (bases de datos, NFS, cierto almacenamiento de VMs, cualquier cosa que llame a fsync mucho),
entonces la latencia del ZIL importa. Con un SLOG, tu latencia síncrona suele ser la latencia del SLOG.
Sin SLOG, las escrituras síncronas golpean el pool y heredan la latencia del pool. Los registros no dirán “fsync es tu problema” con esas palabras,
pero el patrón aparece: aumento de await, ráfagas alineadas con txg sync, y muchas quejas durante periodos de commits intensos.
3) Picos en el tiempo de sync de transaction group (txg)
ZFS agrupa cambios en transaction groups. Cuando un txg se confirma (“sync”), el sistema puede ver tormentas cortas de I/O de escritura.
Si el tiempo de sync crece, todo lo que depende de esos commits se vuelve más lento. Esto puede aparecer como pausas periódicas, NFS “no responde”,
o picos de latencia en la aplicación cada pocos segundos.
4) Problemas de metadatos y fragmentación
La fragmentación no es una falta moral; es física más tiempo. Ciertas cargas (imágenes de VM, bases de datos, escrituras aleatorias pequeñas)
pueden convertir el pool en un festival caro de seeks. Los logs de ZFS no imprimirán “estás fragmentado”, pero tus patrones de iostat sí lo harán,
y los tiempos de scrub/resilver empeorarán.
5) Presión de memoria: thrash de ARC
Cuando la tasa de aciertos del ARC cae, las lecturas van al disco. Eso no es automáticamente malo—a veces el conjunto de trabajo simplemente es mayor que la RAM.
Pero un colapso súbito del ARC puede ocurrir tras un despliegue hambriento de memoria, un cambio en la densidad de contenedores o una mala configuración de L2ARC.
La señal suele ser: más lecturas de disco, mayor latencia y un kernel que se ve… ocupado.
Una idea parafraseada a menudo atribuida a John Allspaw encaja aquí: La fiabilidad viene de aprender y adaptarse, no de pretender que podemos predecirlo todo.
(idea parafraseada).
ZFS es adaptable. Tu trabajo es aprender lo que te está diciendo antes de que empiece a gritar.
Guía rápida de diagnóstico (primeras/segundas/terceras comprobaciones)
Si estás de guardia, no tienes tiempo para danza interpretativa. Necesitas una secuencia que reduzca el espacio de búsqueda.
Esta guía asume Linux + OpenZFS, pero la lógica se aplica más ampliamente.
Primero: ¿está el pool sano ahora mismo?
- Ejecuta
zpool status -x. Si dice cualquier cosa distinta a “all pools are healthy”, detente e investiga eso primero. - Revisa
zpool events -ven busca de fallos de dispositivo recientes, reinicios de enlace o errores de checksum. - Busca scrubs/resilvers en ejecución. Un pool “sano” puede seguir lento si se está reconstruyendo.
Segundo: ¿es un problema de dispositivo o de carga/Sync?
- Ejecuta
zpool iostat -v 1y observa la distribución de latencia por vdev. ¿Un disco lento? ¿Un mirror lento? Ese es tu sospechoso. - Ejecuta
iostat -x 1y revisaawait,svctm(si está presente) y%util. Await alto + util alta = saturación de dispositivo/cola. - Comprueba si la latencia se correlaciona con ráfagas de escrituras síncronas: busca escrituras altas con throughput relativamente bajo pero await alto.
Tercero: confirma el modo de fallo con logs y contadores
- Journal/kernel:
journalctl -kpara timeouts, reinicios, errores NCQ, errores de transporte, comandos abortados. - SMART:
smartctlpara sectores reasignados, sectores pendientes, Offline_Uncorrectable, CRC errors (a menudo cable/backplane). - Estadísticas de ZFS: comportamiento ARC (
arcstatsi está disponible), mensajes de txg sync (según tu build), e historial de eventos.
Regla de una frase: si puedes nombrar el componente más lento, normalmente puedes arreglar el outage.
Si no puedes, sigues adivinando—sigue estrechando.
Tareas prácticas: comandos, salidas y decisiones (12+)
Estas son las tareas que ejecuto en producción cuando ZFS se ralentiza. Cada una incluye qué significa la salida y qué decisión tomar después.
Copiar/pegar está permitido. Entrar en pánico no lo está.
Tarea 1: Comprobación rápida de salud del pool
cr0x@server:~$ sudo zpool status -x
all pools are healthy
Significado: No hay fallos conocidos, no hay vdevs degradados, ni errores activos. Esto no garantiza rendimiento, pero elimina una gran clase de emergencias.
Decisión: Pasa al diagnóstico de latencia (zpool iostat, iostat) en lugar de operaciones de reparación.
Tarea 2: Estado completo con contadores de error y trabajo en curso
cr0x@server:~$ sudo zpool status
pool: tank
state: ONLINE
status: One or more devices has experienced an unrecoverable error. An
attempt was made to correct the error. Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
using 'zpool clear' or replace the device with 'zpool replace'.
scan: scrub repaired 0B in 02:14:33 with 0 errors on Mon Dec 23 03:12:18 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-SAMSUNG_SSD_860-1 ONLINE 0 0 0
ata-SAMSUNG_SSD_860-2 ONLINE 0 0 3
errors: No known data errors
Significado: El pool está online, pero un dispositivo tiene errores de checksum. ZFS los corrigió usando redundancia, pero ahora tienes un olor a fiabilidad y rendimiento.
Decisión: Investiga esa ruta de dispositivo (SMART, cableado, backplane, HBA). No hagas “zpool clear” como terapia; limpia sólo después de entender por qué ocurrieron los errores.
Tarea 3: Vigilar latencia por vdev en vivo
cr0x@server:~$ sudo zpool iostat -v 1
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 4.12T 3.15T 210 980 23.1M 61.4M
mirror-0 2.06T 1.57T 105 510 11.6M 30.7M
ata-SAMSUNG_SSD_860-1 - - 60 250 6.7M 15.2M
ata-SAMSUNG_SSD_860-2 - - 45 260 4.9M 15.5M
-------------------------- ----- ----- ----- ----- ----- -----
Significado: Una carga balanceada en el mirror se ve aproximadamente simétrica a lo largo del tiempo. Si un miembro muestra muchas menos ops pero mayor latencia (no mostrado en esta vista básica),
o si las ops de un vdev colapsan mientras la demanda del pool permanece, eso es una pista de que el dispositivo está bloqueándose o reintentando errores.
Decisión: Si el desequilibrio persiste, correlaciona con kernel y SMART; considera offlining/reemplazando el dispositivo sospechoso si los errores coinciden.
Tarea 4: Añadir columnas de latencia (donde se soporte)
cr0x@server:~$ sudo zpool iostat -v -l 1
capacity operations bandwidth total_wait disk_wait
pool alloc free read write read write read write read write
-------------------------- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
tank 4.12T 3.15T 220 1020 24.0M 63.2M 3ms 28ms 2ms 24ms
mirror-0 2.06T 1.57T 110 520 12.0M 31.6M 2ms 30ms 2ms 27ms
ata-SAMSUNG_SSD_860-1 - - 55 260 6.1M 15.8M 2ms 8ms 2ms 7ms
ata-SAMSUNG_SSD_860-2 - - 55 260 5.9M 15.8M 2ms 90ms 2ms 85ms
-------------------------- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
Significado: Un disco tiene picos de disk_wait (85–90ms) mientras el otro se mantiene bajo. Ese es tu “coche marcando el ritmo”.
Decisión: Extrae evidencia del kernel + SMART. Si es un cable/ruta HBA, arréglalo. Si es el SSD en sí, programa el reemplazo antes de que “se recupere” en tu siguiente outage.
Tarea 5: Comprobar contención por scrub/resilver
cr0x@server:~$ sudo zpool status tank
pool: tank
state: ONLINE
scan: resilver in progress since Thu Dec 26 08:11:02 2025
312G scanned at 1.24G/s, 48.2G issued at 192M/s, 7.11T total
48.2G resilvered, 0.68% done, 10:27:11 to go
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
errors: No known data errors
Significado: Hay un resilver en curso. Tu pool está haciendo lecturas/escrituras adicionales, y la latencia normalmente empeorará.
Decisión: Si esto es un sistema de producción expuesto a usuarios, decide si limitar el resilver/scrub (donde sea posible),
o desplazar temporalmente la carga. También confirma que la falla original está totalmente resuelta—no dejes que un segundo disco falle durante el resilver.
Tarea 6: Leer el flujo de eventos recientes de ZFS
cr0x@server:~$ sudo zpool events -v | tail -n 30
TIME CLASS
Dec 26 2025 08:10:58.123456789 ereport.fs.zfs.vdev.io
pool = tank
vdev_path = /dev/disk/by-id/ata-SAMSUNG_SSD_860-2
vdev_guid = 1234567890123456789
errno = 5
size = 131072
offset = 9876543210
flags = 0x180
Dec 26 2025 08:10:58.223456789 ereport.fs.zfs.vdev.checksum
pool = tank
vdev_path = /dev/disk/by-id/ata-SAMSUNG_SSD_860-2
vdev_guid = 1234567890123456789
Significado: ZFS está registrando errores de I/O y problemas de checksum contra un dispositivo específico.
Decisión: Trata esto como triage de ruta de hardware: SMART, cables, HBA, chasis. Si se repite, reemplaza el dispositivo.
Si se detiene al recolocar un cable, sigue vigilando; los errores CRC intermitentes suelen volver.
Tarea 7: Revisar logs del kernel por reinicios de transporte y timeouts
cr0x@server:~$ sudo journalctl -k --since "2 hours ago" | egrep -i "ata|nvme|scsi|reset|timeout|error" | tail -n 40
Dec 26 09:01:14 server kernel: ata7.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
Dec 26 09:01:14 server kernel: ata7.00: failed command: READ FPDMA QUEUED
Dec 26 09:01:14 server kernel: ata7: hard resetting link
Dec 26 09:01:18 server kernel: ata7: link is slow to respond, please be patient (ready=0)
Dec 26 09:01:20 server kernel: ata7: SATA link up 6.0 Gbps (SStatus 133 SControl 300)
Dec 26 09:01:20 server kernel: ata7.00: configured for UDMA/133
Significado: Eventos de reinicio de enlace. Incluso cuando “se recuperan”, el tiempo de reintento crea picos de latencia y puede bloquear un vdev.
Decisión: Revisa cableado/backplane, alimentación y firmware del HBA. Si es una bahía de disco única, mueve el disco a otro slot para aislar la ruta del chasis.
Tarea 8: Triage SMART (dispositivos SATA/SAS)
cr0x@server:~$ sudo smartctl -a /dev/sdb | egrep -i "Reallocated|Pending|Offline_Uncorrectable|CRC_Error_Count|Power_On_Hours"
9 Power_On_Hours 0x0032 094 094 000 Old_age Always - 23874
197 Current_Pending_Sector 0x0012 100 100 000 Old_age Always - 8
198 Offline_Uncorrectable 0x0010 100 100 000 Old_age Offline - 2
199 UDMA_CRC_Error_Count 0x003e 200 200 000 Old_age Always - 0
Significado: Sectores pendientes y Offline_Uncorrectable son problemas reales de medio. Un CRC count en cero sugiere que esto no es “sólo un cable”.
Decisión: Planifica el reemplazo. Si el pool es redundante, reemplaza proactivamente. Si es disco único (no lo hagas), haz backup primero y luego reemplaza cuanto antes.
Tarea 9: Salud NVMe y registro de errores
cr0x@server:~$ sudo nvme smart-log /dev/nvme0 | egrep -i "critical_warning|media_errors|num_err_log_entries|percentage_used"
critical_warning : 0x00
media_errors : 12
num_err_log_entries : 398
percentage_used : 87%
Significado: Errores de medio y un alto porcentaje de uso pueden correlacionar con latencia creciente e inminente fallo.
Decisión: Si este NVMe es un SLOG o un vdev especial, trátalo como urgente—esos roles pueden degradar el rendimiento drásticamente cuando el dispositivo falla.
Tarea 10: Identificar cargas pesadas en sync vía propiedades de dataset
cr0x@server:~$ sudo zfs get -o name,property,value -s local sync,logbias,primarycache,recordsize tank/app tank/vm
NAME PROPERTY VALUE
tank/app sync standard
tank/app logbias latency
tank/app primarycache all
tank/app recordsize 128K
tank/vm sync always
tank/vm logbias latency
tank/vm primarycache metadata
tank/vm recordsize 16K
Significado: sync=always fuerza semántica síncrona incluso si la app no la pide. Eso puede ser correcto, o puede ser un incidente de rendimiento autoinfligido.
Decisión: Verifica por qué está sync=always. Si es para una base de datos que ya gestiona durabilidad, podrías estar pagando doble. Si es para NFS/VMs, mantenlo y apuesta por un SLOG adecuado.
Tarea 11: Confirmar presencia de SLOG y diseño básico
cr0x@server:~$ sudo zpool status tank | sed -n '1,80p'
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
logs
nvme-SAMSUNG_MZVLB1T0-1 ONLINE 0 0 0
errors: No known data errors
Significado: Existe un SLOG de un solo dispositivo. Eso es común, pero también es un punto único de rendimiento y (según tu tolerancia) riesgo para la latencia de escrituras síncronas.
Decisión: Para cargas síncronas críticas, prefiere SLOGs en espejo. Y asegúrate de que el SLOG realmente tenga baja latencia en condiciones seguras ante pérdida de energía.
Tarea 12: Comprobar si el sistema está ahogado por colas de I/O
cr0x@server:~$ iostat -x 1 3
Linux 6.5.0 (server) 12/26/2025 _x86_64_ (32 CPU)
Device r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await %util
sda 12.0 340.0 480 14560 83.2 18.4 52.6 3.1 54.4 99.2
sdb 10.0 332.0 420 14400 85.7 1.2 3.7 2.8 3.8 34.5
nvme0n1 0.0 25.0 0 2048 163.8 0.4 15.8 0.0 15.8 40.1
Significado: sda está al 99% de uso con una cola profunda y await alto, mientras sdb está bien. En un mirror, eso puede arrastrar al vdev.
NVMe muestra await moderado; si ese es tu SLOG, 15ms puede ser demasiado lento para expectativas de “fsync rápido”.
Decisión: Investiga por qué sda está lento: errores, firmware, thermal throttling, problemas de controlador. Si es miembro de un mirror, considera offline temporal para ver si la latencia mejora (con conciencia del riesgo).
Tarea 13: Revisar comportamiento del ARC (si arcstat está disponible)
cr0x@server:~$ arcstat 1 5
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
09:12:01 3120 980 31 220 7 710 23 50 1 96.2G 96.0G
09:12:02 2980 940 31 240 8 650 22 50 1 96.2G 96.0G
09:12:03 3050 970 32 210 7 710 23 50 1 96.2G 96.0G
09:12:04 3105 995 32 230 7 715 23 50 1 96.2G 96.0G
09:12:05 3002 960 32 220 7 690 23 50 1 96.2G 96.0G
Significado: Una tasa de misses ~31–32% puede ser aceptable o terrible según tu storage y carga. Si miss% salta de repente respecto al baseline,
los discos verán más lecturas y la latencia subirá.
Decisión: Compáralo con la línea base de la semana pasada. Si ARC está limitado (c igual a arcsz) y tienes RAM libre, considera aumentar el máximo de ARC.
Si ARC está siendo reducido por otra cosa, arregla la presión de memoria en lugar de “tunear ZFS” hasta dejarlo en una esquina.
Tarea 14: Revisar compresión del dataset y I/O lógico vs físico
cr0x@server:~$ sudo zfs get -o name,property,value compression,compressratio tank/app
NAME PROPERTY VALUE
tank/app compression lz4
tank/app compressratio 1.62x
Significado: La compresión funciona y probablemente ahorra I/O. Si compressratio es ~1.00x, estás pagando sobrecarga de CPU sin beneficio de I/O (generalmente pequeño con lz4, pero no cero).
Decisión: Si la CPU es un cuello de botella y los datos son incompresibles, considera desactivar la compresión en ese dataset. Si no, deja lz4 como está; es uno de los pocos “por defecto” que realmente merece la pena.
Tarea 15: Averiguar quién está pegando al pool ahora mismo
cr0x@server:~$ sudo iotop -oPa
Total DISK READ: 45.20 M/s | Total DISK WRITE: 112.30 M/s
PID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
18342 be/4 postgres 2.10 M/s 65.40 M/s 0.00 % 84.21 % postgres: checkpointer
20111 be/4 root 0.00 B/s 28.20 M/s 0.00 % 62.10 % zfs send -w tank/app@snap
9321 be/4 libvirt-qemu 1.10 M/s 12.80 M/s 0.00 % 20.33 % qemu-system-x86_64
Significado: Tienes un checkpointer haciendo escrituras intensas, un zfs send empujando datos y VMs leyendo/escribiendo. Esto es un mapa de contención.
Decisión: Si la latencia es visible para usuarios, pausa o reprograma la transferencia masiva (zfs send) o limita su velocidad. No discutas con la física.
Broma #1: El almacenamiento es el único lugar donde “está bien en promedio” se acepta justo hasta el momento en que deja de estarlo.
Tres mini-historias corporativas (anonimizadas, dolorosamente plausibles)
Mini-historia 1: El incidente causado por una suposición equivocada
Una empresa SaaS mediana ejecutaba Postgres de clientes sobre almacenamiento de VMs respaldado por ZFS. Había sido estable durante meses, y el equipo estaba orgulloso:
SSDs en espejo, compresión activada, scrubs semanales, monitorización básica. Lo único que no monitorizaron fue la latencia de escrituras síncronas. Porque, en su cabeza,
“los SSDs son rápidos”.
Llegó un nuevo requisito de cumplimiento: asegurar semánticas de durabilidad para un subconjunto de cargas. Un ingeniero puso sync=always en el dataset que alojaba
las imágenes de VM. La suposición era simple: “Esto será más seguro y sólo un poco más lento.” Tenían media razón.
A la mañana siguiente, los clientes reportaron timeouts esporádicos. El pool parecía sano. La CPU estaba bien. La red estaba bien. Los gráficos de throughput estaban bien.
Pero la latencia de escritura del percentil 99 se disparó. Los logs del kernel no mostraban nada dramático. Los logs de ZFS no mostraban errores. Todos empezaron a mirar la capa de aplicación,
porque eso es lo que haces cuando el almacenamiento no confiesa.
El arma humeante estaba en zpool iostat -l: el dispositivo SLOG (un NVMe de consumo sin protección ante pérdida de energía) tenía latencia de escritura alta y errática bajo carga sinc.
No estaba “roto”. Simplemente le pidieron que proporcionara commits de baja latencia consistentes y educadamente se negó.
La solución fue aburrida y cara: reemplazar el SLOG por un dispositivo diseñado para latencia sostenida en escrituras síncronas y ponerlo en espejo.
El postmortem dejó una lección digna de tatuaje: no cambies las semánticas de sync sin medir la ruta de sync.
Mini-historia 2: La optimización que salió mal
Un equipo de plataforma interno de una empresa ejecutaba un pool ZFS para artefactos de CI e imágenes de contenedores. Eran principalmente archivos grandes, muchas lecturas paralelas
y escrituras grandes ocasionales. El sistema estaba “bien”, pero una iniciativa de rendimiento bien intencionada exigió “más throughput”.
Alguien encontró una nota de tuning antigua y decidió que el pool debía usar un “special vdev” separado para metadatos para acelerar el recorrido de directorios y lecturas pequeñas.
Añadieron un par de SSDs pequeños y rápidos como special vdev. Los benchmarks iniciales fueron geniales. La dirección sonrió. Todos siguieron con su trabajo.
Meses después, el rendimiento se volvió raro. No sólo más lento—con picos. Durante horas pico de CI, las builds se detenían por segundos.
zpool status seguía verde. Pero zpool iostat -v -l contaba una historia más fea: el special vdev se convirtió en el cuello de botella de latencia.
Esos “SSDs pequeños y rápidos” ahora estaban siendo muy escritos, se estaban desgastando y a veces se estaban limitando.
El problema no fue la característica. Fue el dimensionamiento y el pensamiento sobre el ciclo de vida. Metadatos y bloques pequeños pueden ser un imán de I/O.
Cuando el special vdev hace picos, todo el pool se siente tambaleado. Los logs del kernel mostraban advertencias NVMe leves, no suficientes para disparar alertas,
pero suficientes para explicar las paradas cuando se correlacionaban con los picos de latencia.
El plan de remediación: reemplazar el special vdev por dispositivos apropiadamente durables, ampliar capacidad para reducir amplificación de escritura,
y añadir monitorización específica para latencia y desgaste del special vdev. La moraleja: cada estructura de aceleración se vuelve una dependencia.
Mini-historia 3: La práctica aburrida pero correcta que salvó el día
Una entidad de servicios financieros ejecutaba ZFS como backend NFS sirviendo directorios home y salidas de build compartidas. Nada sexy. Sin tunings heroicos.
Lo que sí tenían era disciplina: scrubs mensuales, alertas en cambios de zpool status, y un runbook que obligaba a los ingenieros a comprobar
errores de transporte del kernel antes de tocar las perillas de ZFS.
Un martes, la latencia subió. Los usuarios lo notaron. El de guardia siguió el runbook: comprobar salud del pool, eventos y logs del kernel.
En minutos encontró reinicios repetidos de enlace SATA en una bahía de discos. Aún no había errores de ZFS—sólo reintentos.
Reemplazaron el cable/componente del backplane en una micro-ventana programada, antes de que el disco empezara a tirar errores de checksum.
La latencia volvió a la línea base. No fue necesario resilver. Ningún riesgo de datos. Ningún fin de semana consumido por arrepentimiento.
La práctica que los salvó no fue genial. Fue consistencia: scrubs para detectar problemas latentes, y correlación de logs para atrapar degradación de la ruta de hardware temprano.
Lo aburrido está subestimado en ingeniería de almacenamiento porque funciona.
Broma #2: Si quieres una carrera emocionante en almacenamiento, ignora tu calendario de scrubs; el pager te creará la emoción por ti.
Errores comunes: síntoma → causa raíz → solución
1) “El pool está ONLINE pero la latencia es horrible”
Síntoma: zpool status parece limpio; las aplicaciones hacen timeout; iostat muestra await alto.
Causa raíz: Reintentos de dispositivo, reinicios de enlace o un solo disco lento arrastrando un mirror/RAIDZ vdev.
Solución: Revisa journalctl -k por reinicios/timeouts; revisa SMART/NVMe. Reemplaza el dispositivo sospechoso o repara la ruta de transporte. No ajustes ZFS para compensar hardware que miente.
2) “Cada pocos segundos tenemos una pausa”
Síntoma: Picos periódicos de latencia; NFS se traba; bases de datos muestran stalls de commit.
Causa raíz: Txg sync tardando demasiado, a menudo porque el pool está saturado, la fragmentación es alta o un dispositivo lento está bloqueando flushes.
Solución: Usa zpool iostat -l para identificar el vdev lento y reduce la carga de escritura concurrente. Si es intensivo en sync, arregla la latencia del SLOG o reconsidera sync=always.
3) “Añadimos un SLOG y el rendimiento empeoró”
Síntoma: Carga intensiva en sync se vuelve más lenta tras añadir dispositivo de log.
Causa raíz: El SLOG tiene peor latencia que el pool o sufre throttling; un SLOG único se convierte en cuello.
Solución: Verifica con iostat -x y zpool iostat -l. Reemplaza por dispositivo de baja latencia y protección ante pérdida de energía, idealmente en espejo. Si la carga es mayormente async, quita el SLOG y deja de esperar magia.
4) “Los errores de checksum siguen apareciendo, pero los scrubs los reparan”
Síntoma: Los contadores CKSUM aumentan; los scrubs reparan; no hay errores de datos visibles—aún.
Causa raíz: A menudo cableado/backplane/HBA (errores CRC), a veces fallo de medio en el disco.
Solución: Revisa contadores SMART CRC y logs de transporte del kernel. Reasienta/reemplaza cable/backplane; actualiza firmware; reemplaza disco si los indicadores de medio son malos. Luego haz un scrub y confirma que los contadores se mantengan estables.
5) “El resilver terminará en 2 horas… durante los próximos 3 días”
Síntoma: ETA de resilver crece; el pool está lento.
Causa raíz: Carga competitiva + pool fragmentado + dispositivo lento. El resilver compite por I/O y puede ser depriorizado o starveado por tus aplicaciones.
Solución: Reduce la carga, programa resilver en horas de baja actividad cuando sea posible, y busca un dispositivo débil que prolongue el proceso. Confirma que ashift y diseño de vdev no estén causando amplificación de escritura patológica.
6) “La tasa de aciertos del ARC se desplomó tras desplegar algo no relacionado”
Síntoma: Aumento súbito de lecturas de disco; latencia sube; cambios en uso de memoria.
Causa raíz: Presión de memoria por nuevos servicios, densidad de contenedores o comportamiento del page cache del kernel; ARC limitado por configuración o exprimido por otros consumidores.
Solución: Mide memoria, no adivines. Si tienes RAM disponible, aumenta el tope de ARC. Si no, reduce la presión de memoria o mueve la carga. No añadas L2ARC como sustituto de no tener suficiente RAM a menos que entiendas los patrones de lectura/escritura.
7) “Afinamos recordsize y ahora las escrituras son más lentas”
Síntoma: Tras cambiar recordsize, el throughput baja y la latencia sube.
Causa raíz: Desajuste de recordsize con la carga (por ejemplo, demasiado grande para bloques aleatorios de DB, demasiado pequeño para streaming secuencial).
Solución: Ajusta recordsize por dataset y tipo de carga. Imágenes de VM y bases de datos suelen preferir bloques más pequeños (p. ej., 16K), mientras archivos secuenciales grandes se benefician de bloques mayores (128K–1M según uso). Valida con trazas reales de I/O, no con sensaciones.
Listas de verificación / plan paso a paso
Checklist A: Cuando los usuarios reportan “lentitud intermitente”
- Confirma si es latencia de almacenamiento: revisa p95/p99 a nivel de app y wait I/O en hosts.
- Ejecuta
zpool status -x. Si no está sano, trátalo como incidente. - Ejecuta
zpool statusy busca scrub/resilver en curso. - Ejecuta
zpool iostat -v -l 1durante 60–120 segundos. Identifica el vdev/dispositivo más lento por latencia. - Ejecuta
journalctl -kfiltrado por reinicios/timeouts. Confirma si el dispositivo lento tiene errores coincidentes. - Revisa SMART/NVMe del dispositivo sospechoso.
- Decide: aislar (offline/reemplazar), reparar la ruta (cable/backplane/HBA), o reducir la contención de carga.
Checklist B: Cuando se sospechan escrituras síncronas (bases de datos/NFS/VMs)
- Revisa propiedades del dataset
syncylogbiaspara los datasets relevantes. - Confirma si tienes un SLOG y cuál es (single vs mirror).
- Mide la latencia del SLOG usando
iostat -xen el dispositivo SLOG durante la ventana de lentitud. - Si la latencia del SLOG es peor que la del pool, no lo debatas: reemplaza o retíralo según las necesidades de sync.
- Si no existe SLOG y la latencia sync es dolorosa, considera añadir un SLOG en espejo apropiado—después de validar que la carga es realmente sync-heavy.
Checklist C: Cuando aparecen errores pero el pool “sigue funcionando”
- Captura la salida de
zpool statusyzpool events -vpara el registro del incidente. - Revisa logs del kernel alrededor de los mismos timestamps por problemas de transporte.
- Revisa indicadores SMART/NVMe y contadores de errores de medio.
- Arregla la ruta o reemplaza hardware. Sólo entonces limpia errores con
zpool clear. - Ejecuta un scrub tras la remediación y confirma que los contadores de error se mantengan planos.
Checklist D: Baseline para detectar regresiones
- Registra baseline de
zpool iostat -v -ldurante horas “conocidas buenas”. - Registra baseline de estadísticas ARC (hit rate, tamaño ARC, indicadores de presión de memoria).
- Rastrea duración de scrubs y resilvers (son advertencias tempranas de fragmentación y envejecimiento de dispositivos).
- Alerta sobre errores de transporte del kernel, no sólo sobre fallos de ZFS.
Preguntas frecuentes
1) ¿Son suficientes los registros de ZFS para diagnosticar problemas de rendimiento?
No. ZFS te dirá sobre señales de integridad (errores, fallos, eventos), pero el diagnóstico de rendimiento necesita contexto de dispositivo y kernel.
Siempre empareja eventos de ZFS con logs del kernel y iostat/zpool iostat.
2) Si zpool status está limpio, ¿puedo descartar hardware?
Rotundamente no. Muchos problemas de hardware/transporte aparecen como reintentos y reinicios de enlace mucho antes de que ZFS incremente un contador.
Los logs del kernel y SMART a menudo muestran los “pre-síntomas”.
3) ¿Agregar un SLOG siempre mejora el rendimiento?
Sólo para escrituras síncronas. Para cargas asíncronas es mayormente irrelevante. Y un SLOG lento puede empeorar el rendimiento síncrono.
Trata al SLOG como un componente crítico de latencia, no como una casilla para marcar.
4) ¿Cuál es la forma más rápida de detectar un único disco malo en un mirror?
Usa zpool iostat -v -l 1 y busca un miembro con latencia de espera de disco dramáticamente mayor.
Luego confirma con journalctl -k y logs SMART/NVMe.
5) ¿Los errores de checksum siempre significan que el disco se está muriendo?
A menudo es la ruta: cable, backplane, HBA, firmware. Los errores SMART CRC y los reinicios de transporte del kernel son tu pista.
Los errores de medio (pending/reallocated/uncorrectable) implican el disco más directamente.
6) ¿Por qué el pool se ralentiza durante un scrub si los scrubs son “background”?
Los scrubs son background en intención, no en física. Consumen I/O real y pueden elevar la latencia.
Si los scrubs causan dolor a usuarios, prográmalos mejor, limita su velocidad donde sea posible y verifica que tu pool tenga margen de rendimiento.
7) ¿Debo poner sync=disabled para arreglar la latencia?
Eso no es arreglar; es negociar con la realidad y esperar que no lo note. Estás cambiando garantías de durabilidad por velocidad.
Si los datos importan, arregla la ruta de sync (SLOG/latencia de dispositivo) en su lugar.
8) ¿La alta fragmentación siempre es la razón de las lentitudes?
No. La fragmentación es común, pero el culpable habitual primero es la latencia del dispositivo o un pool degradado/reconstruyéndose.
La fragmentación tiende a mostrarse como una tendencia a largo plazo: scrubs/resilvers más largos, I/O aleatorio más caro, y latencia más fácil de activar.
9) ¿Cuándo debo limpiar errores de ZFS con zpool clear?
Después de haber arreglado la causa subyacente y capturado la evidencia. Limpiar demasiado pronto borra tu rastro y facilita repetir el incidente.
10) ¿Qué pasa si ZFS está lento pero iostat muestra %util bajo?
Entonces el cuello de botella puede estar en otro lugar: CPU (compresión/cifrado), presión de memoria, throttling, o un stall en la ruta de sync.
También confirma que estás midiendo los dispositivos correctos (multipath, capas dm-crypt, HBAs).
Conclusión: próximos pasos prácticos
Los outages de rendimiento de ZFS suelen ser fallos de hardware en cámara lenta, sorpresas de escrituras síncronas o contención por reconstrucción/scrub que nadie trató como un evento de producción.
La buena noticia: puedes verlos venir—si miras en los lugares correctos y mantienes una línea base.
Haz lo siguiente:
- Establece línea base de
zpool iostat -v -lyiostat -xdurante horas saludables, y guarda esos números donde tu yo futuro los encuentre. - Alerta sobre errores de transporte del kernel (reinicios, timeouts) además de cambios en el estado del pool ZFS.
- Audita datasets por configuraciones de
synce identifica qué cargas son realmente sync-heavy. - Decide si tu SLOG (si existe) está realmente a la altura: baja latencia, seguro ante pérdida de energía y, idealmente, en espejo para entornos críticos.
- Mantén scrubs programados y monitorizados. No porque sea divertido, sino porque es cómo capturas temprano la “corrupción silenciosa y hardware débil”.
Tu objetivo no es crear el sistema ZFS perfecto. Es hacer que las lentitudes sean previsibles, diagnosables y solucionables—antes de que se conviertan en cortes de servicio con una invitación a reunión.