Las interrupciones de almacenamiento rara vez empiezan como “todo está caído”. Empiezan con alguien en Slack diciendo: “¿por qué la app… se queda pegada?” Luego tus checkpoints de base de datos tardan más, las colas se alargan y de repente tus SLOs parecen una pista de esquí.
ZFS es excelente manteniendo la integridad de los datos. También es excelente escondiendo las señales tempranas dentro de unos contadores que no estás graficando. Esto trata sobre esos contadores: los gráficos que te dicen “algo va mal” mientras aún tienes tiempo para arreglarlo sin una sala de crisis.
Qué significa “latencia” en ZFS (y por qué le importa a tu app)
La mayoría de los equipos grafican el rendimiento (throughput) porque es gratificante: números grandes, dashboards coloridos, fácil de mostrar a la dirección. La latencia es el número que realmente perjudica a los usuarios. Una I/O lenta puede bloquear una transacción, bloquear un hilo trabajador y amplificarse en una cola que tarda minutos en deshacerse.
ZFS añade sus propias capas. No es una crítica; es la realidad de copy-on-write, checksums, compresión y grupos de transacciones. Tu I/O no solo “llega al disco”. Pasa por:
- Ruta de la aplicación y del sistema de ficheros (syscalls, VFS)
- Intención/log de ZFS para semánticas síncronas (ZIL/SLOG)
- ARC (caché en RAM) y opcional L2ARC (caché en flash)
- DMU / asignación de metaslabs (dónde van los bloques)
- colas de vdev (el punto donde “esto parece estar bien” se convierte en “¿por qué todo espera?”)
- dispositivos físicos (incluyendo sus estados de firmware)
Cuando alguien dice “ZFS está lento”, tradúcelo. Pregunta: ¿lecturas lentas o escrituras lentas? ¿síncronas o asíncronas? ¿IO aleatoria pequeña o secuencial grande? ¿el conjunto caliente cabe en ARC o no? Así eliges los gráficos y la solución correctos.
Un punto práctico más: la latencia promedio es mentirosa. Quieres percentiles (p95, p99) y contexto de profundidad de cola. Un sistema puede tener “baja latencia promedio” mientras el p99 está quemando tu app.
Chiste #1: La latencia promedio es como la temperatura promedio: va bien hasta que te das cuenta de que la cabeza está en el horno y los pies en el congelador.
Datos e historia interesantes (los útiles)
- ZFS nació en Sun Microsystems con el objetivo de diseño de que la integridad de los datos prime sobre todo, por eso los checksums y copy-on-write son características innegociables.
- El “ZIL” existe incluso sin un SLOG: ZIL es el log dentro del pool, y SLOG es un dispositivo separado que puede contener registros ZIL para acelerar escrituras sync.
- Los TXGs (transaction groups) son el latido: ZFS agrupa cambios y los vacía periódicamente. Cuando los vaciados se vuelven lentos, la latencia se comporta raro—y luego de forma catastrófica.
- ARC no es “solo una caché”: ARC interactúa con la presión de memoria, metadatos y el prefetch; puede trasladar carga desde discos a RAM de formas sorprendentes.
- L2ARC solía ser más arriesgado: las implementaciones antiguas podían consumir mucha RAM para metadatos y el calentamiento podía decepcionar. Los sistemas modernos mejoraron, pero no es gratis.
- La compresión puede reducir la latencia cuando convierte lecturas aleatorias en menos I/O a dispositivo—hasta que la CPU se convierte en el cuello de botella o el recordsize se desalineé con los patrones de acceso.
- RAIDZ cambia la historia de las escrituras: las escrituras aleatorias pequeñas en RAIDZ pueden incurrir en overhead de lectura-modificación-escritura, que aparece como mayor latencia y colas en los dispositivos.
- Los scrubs son operativamente obligatorios, pero compiten por I/O. Si no mitigás su impacto, tus usuarios lo harán por ti vía tickets furiosos.
- Los vdevs especiales cambiaron la economía de metadatos: poner metadatos (y opcionalmente bloques pequeños) en SSDs rápidos puede mejorar dramáticamente la latencia para cargas intensivas en metadatos.
Una cita, porque sobrevive a cada incidente de almacenamiento: “La esperanza no es una estrategia.”
— James Cameron
Los gráficos que detectan el desastre temprano
Monitorear latencia no es un solo gráfico. Es un pequeño conjunto de gráficos que cuentan una historia coherente. Si tu herramienta de monitoreo solo soporta unos paneles, elige los de abajo. Si puedes hacer más, haz más. Estás comprando tiempo.
1) Latencia por pool y vdev (lectura/escritura) con percentiles
Quieres latencia de lectura y escritura por vdev, no solo el promedio del pool. Los pools esconden asesinatos. Un dispositivo degradado, un SSD lento, un fallo de HBA, y el gráfico del pool parece “un poco peor”, mientras un vdev está en llamas.
Qué detecta: un único dispositivo fallando, stalls de GC de firmware, inanición de colas, un problema de controlador que afecta solo a un camino.
Cómo falla: si solo graficas promedios del pool, perderás la etapa del “manzana mala” y descubrirás el problema en la etapa “todo agotó el tiempo”.
2) Señales de profundidad de cola / tiempo de espera
La latencia sin profundidad de cola es como humo sin alarma de incendio. ZFS tiene colas internas; los discos tienen colas; el OS tiene colas. Cuando la profundidad de cola sube, la latencia sube y el throughput a menudo se estabiliza. Esta es tu firma temprana de desastre.
Qué detecta: saturación, throttling, cambios bruscos de workload, interferencia de scrub/resilver, un cambio de propiedad de dataset que aumenta tamaño de IO o comportamiento sync.
3) Latencia de escrituras sync (salud de ZIL/SLOG)
Las bases de datos y NFS a menudo fuerzan semánticas sync. Si tu SLOG es lento o está mal configurado, los usuarios aprenden palabras nuevas. Grafica:
- sync write latency (p95/p99)
- sync write ops per second
- latencia y utilización del dispositivo SLOG
Qué detecta: desgaste del SLOG, caché de dispositivo deshabilitada, requisitos de protección contra pérdida de energía no cumplidos, eliminación accidental del SLOG, o un SSD “rápido” que se queda bloqueado bajo carga sync.
4) Tiempo de commit de TXG y presión de “dirty data”
Cuando ZFS no puede vaciar datos sucios lo suficientemente rápido, todo se atrasa. Monitorea:
- TXG sync time (o proxies como “time blocked in txg”)
- tamaño de dirty data
- eventos de write throttle
Qué detecta: discos lentos, pools sobrecomprometidos, desajustes de recordsize, rarezas de unidades SMR, matemáticas RAIDZ bajo carga de escritura aleatoria.
5) Ratio de aciertos de ARC con contexto (y los misses que importan)
El ratio de aciertos de ARC es un clásico métrico de vanidad. Un alto ratio puede ocultar latencia si los misses están en el camino crítico (misses de metadata, o lecturas aleatorias que machacan un vdev lento). Grafica:
- tamaño ARC y tamaño objetivo
- ARC hit ratio
- hits de metadata vs datos (si puedes)
- tasa de evicciones
Qué detecta: presión de memoria, cambios en densidad de contenedores, una actualización del kernel que cambia el comportamiento del ARC, o una nueva carga que expulsa la caché.
6) Fragmentación y comportamiento de asignación de metaslab (desastres en cámara lenta)
La fragmentación no es dolor instantáneo; es dolor futuro. Cuando el espacio libre baja y la fragmentación sube, la asignación se vuelve más lenta y el IO más aleatorio. Grafica:
- porcentaje de espacio libre del pool
- porcentaje de fragmentación
- tamaño promedio de bloque escrito (si está disponible)
Qué detecta: mitos de “estamos bien con 20% libre”, acaparamiento de snapshots y cargas que churnean bloques pequeños.
7) Superposición del impacto de scrub/resilver
Los scrubs y resilvers son necesarios. También consumen mucho I/O. Tu monitoreo debería anotar cuándo se ejecutan. De lo contrario tratarás “presión de I/O esperada” como “regresión de rendimiento misteriosa”, o peor, desactivarás scrubs y te felicitarás por la mejora.
8) Errores que preceden los picos de latencia
Grafica contadores de:
- errores de checksum
- errores de lectura/escritura
- timeouts y resets de enlace (desde logs del OS)
Los incidentes de latencia a menudo empiezan con reintentos “inocentes”. Los reintentos no son inocentes; son multiplicación de I/O con mala actitud.
Guión de diagnóstico rápido (primero / segundo / tercero)
Esta es la secuencia “mi pager está gritando”. Está optimizada para velocidad y corrección, no para elegancia.
Primero: decide si es latencia de dispositivo, colas de ZFS o cambio de workload
- Mira la latencia de lectura/escritura por vdev. ¿Un vdev está fuera de escala?
- Mira IOPS vs throughput. ¿La carga pasó de secuencial a aleatoria?
- Revisa la tasa de escrituras sync. ¿Algo cambió a semánticas sync?
Segundo: confirma si el pool está bloqueado por flushes de TXG o por escrituras sync
- Si la latencia sync es alta y el SLOG está saturado: estás en el mundo ZIL/SLOG.
- Si las escrituras async son lentas y el dirty data es alto: estás en el mundo TXG/flush.
- Si las lecturas son lentas con bajos aciertos de ARC: estás en el terreno del working-set de caché.
Tercero: busca las causas “aburridas” que siempre ganan
- Un dispositivo está fallando (SMART, contadores de error, timeouts).
- Un scrub/resilver está en marcha y compite por recursos.
- Un pool está demasiado lleno o demasiado fragmentado.
- Un cambio reciente: recordsize, compresión, sync, logbias, special vdev, volblocksize, configuración de la base de datos.
Si no puedes responder “qué vdev está lento” en cinco minutos, tu monitorización no está terminada. Arregla eso antes de que el próximo incidente lo arregle por ti.
Tareas prácticas: comandos, salidas y decisiones (12+)
Estas son tareas ejecutables que puedes hacer en un sistema Linux típico con ZFS. El objetivo no es memorizar comandos; es conectar la salida con una decisión. Copia/pega con intención.
Task 1: Identify the pool and its topology
cr0x@server:~$ sudo zpool status -v
pool: tank
state: ONLINE
scan: scrub repaired 0B in 02:11:34 with 0 errors on Sun Dec 22 03:10:12 2025
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
sdf ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
nvme0n1 ONLINE 0 0 0
nvme1n1 ONLINE 0 0 0
logs
nvme2n1 ONLINE 0 0 0
errors: No known data errors
Qué significa: Tienes RAIDZ2 para capacidad, un vdev espejado especial o rápido (aquí mostrado como mirror-1), y un dispositivo de log separado.
Decisión: Cuando la latencia suba, comprobarás cada uno de esos componentes por separado. Si la latencia sync sube, el dispositivo logs se vuelve sospechoso inmediatamente.
Task 2: Watch per-vdev latency and queue behavior in real time
cr0x@server:~$ sudo zpool iostat -v tank 1
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 5.21T 9.33T 812 604 98.6M 41.2M
raidz2-0 5.01T 9.33T 740 520 92.1M 38.0M
sda - - 98 70 11.8M 5.2M
sdb - - 110 74 12.0M 5.4M
sdc - - 96 68 11.5M 5.1M
sdd - - 99 69 11.6M 5.1M
sde - - 112 75 12.1M 5.6M
sdf - - 225 164 33.1M 11.6M
mirror-1 210G 1.59T 72 84 6.5M 3.2M
nvme0n1 - - 36 42 3.2M 1.6M
nvme1n1 - - 36 42 3.3M 1.6M
logs - - - - - -
nvme2n1 - - 0 180 0 2.1M
-------------------------- ----- ----- ----- ----- ----- -----
Qué significa: Estás viendo distribución. Un disco (sdf) está haciendo mucho más trabajo, lo cual puede ser normal (efectos de layout) o sospechoso (hot spot, errores, o un hermano lento causando desequilibrio).
Decisión: Si un único dispositivo muestra trabajo desproporcionado o cambios de rendimiento bajo carga, correlaciona con logs del kernel y SMART para ese dispositivo. Si las escrituras sync suben, revisa el dispositivo de log.
Task 3: Get latency at the block layer (are devices stalling?)
cr0x@server:~$ iostat -x 1 3
Linux 6.6.44 (server) 12/26/2025 _x86_64_ (32 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
4.12 0.00 1.88 6.05 0.00 87.95
Device r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 8.2 6.0 1024.0 512.0 185.1 0.9 22.4 18.1 28.3 0.9 12.3
sdf 32.1 25.8 8192.0 2048.0 356.7 7.8 118.6 101.2 140.8 1.1 98.7
nvme2n1 0.0 220.0 0.0 2304.0 20.9 0.5 2.3 0.0 2.3 0.1 2.6
Qué significa: sdf está saturado (%util cerca de 100) con alto await y una cola grande (avgqu-sz). Esa es tu fábrica de latencia.
Decisión: Trátalo como un dispositivo probablemente fallando, un problema de path, o un hot spot de workload. Pasa de ZFS a evidencia del OS y hardware.
Task 4: Check for ZFS health events and recent changes
cr0x@server:~$ sudo zpool events -v | tail -n 20
TIME CLASS
Dec 26 2025 10:42:18.911482 ereport.fs.zfs.io
pool = tank
vdev = /dev/sdf
errno = 5
error = Input/output error
Dec 26 2025 10:42:19.002114 ereport.fs.zfs.checksum
pool = tank
vdev = /dev/sdf
errors = 3
Qué significa: ZFS está registrando problemas de I/O y checksum para /dev/sdf. Picos de latencia y errores son amigos.
Decisión: Inicia la planificación de reemplazo. Si ves timeouts/resets, considera cableado/HBA. No “tunes” para salir de un dispositivo que está muriendo.
Task 5: Pull SMART/NVMe health (confirm the hardware story)
cr0x@server:~$ sudo smartctl -a /dev/sdf | egrep -i 'Reallocated|Pending|Offline|CRC|Power_On|Temperature|error'
Power_On_Hours 0x0032 092 092 000 Old_age Always - 35621
Reallocated_Sector_Ct 0x0033 089 089 010 Pre-fail Always - 24
Current_Pending_Sector 0x0012 098 098 000 Old_age Always - 3
UDMA_CRC_Error_Count 0x003e 199 199 000 Old_age Always - 12
SMART Error Log Version: 1
ATA Error Count: 7
Qué significa: Sectores reubicados y pendientes más errores CRC. La unidad y/o el enlace se están comportando mal. Esto no es un “quizás”.
Decisión: Reemplaza el disco y revisa cableado/backplane/HBA por problemas CRC. Si los CRC suben en múltiples discos, sospecha del path, no solo del disco.
Task 6: Confirm if you’re bottlenecked by sync writes (ZIL/SLOG)
cr0x@server:~$ sudo zfs get -o name,property,value -s local,default sync,logbias tank
NAME PROPERTY VALUE
tank logbias latency
tank sync standard
Qué significa: No estás forzando sync siempre, pero aplicaciones que llaman a fsync() o usan O_DSYNC seguirán generando escrituras sync. logbias=latency es típico para bases de datos/NFS.
Decisión: Si la latencia sync es alta y tienes un SLOG, valida su salud y adecuación. Si no tienes SLOG y tu carga es muy sync-heavy, añade uno (correctamente).
Task 7: Verify that a SLOG exists and is actually in use
cr0x@server:~$ sudo zpool status tank | sed -n '/logs/,$p'
logs
nvme2n1 ONLINE 0 0 0
Qué significa: Un vdev de log está presente. Eso no prueba que esté bien; prueba que lo intentaste.
Decisión: Si la latencia sync es mala, benchmarkea u observa la latencia de nvme2n1 bajo presión y confirma que tiene características de protección contra pérdida de energía adecuadas para tu perfil de riesgo.
Task 8: Look at ARC behavior (is the cache helping or thrashing?)
cr0x@server:~$ arcstat 1 3
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
10:55:01 812 96 11 38 4 58 7 8 33 128G 144G
10:55:02 790 210 27 120 15 82 10 8 10 128G 144G
10:55:03 805 240 30 150 19 82 10 8 9 128G 144G
Qué significa: La tasa de misses está subiendo rápido. Si esto se alinea con picos de latencia, tu working set puede haber superado ARC, o una nueva carga está expulsando datos útiles.
Decisión: Investiga qué cambió (deploy, patrón de consultas, nuevos tenants). Considera añadir RAM, optimizar patrones de acceso o usar un vdev especial para metadatos si los misses de metadatos dominan.
Task 9: Check pool fullness and fragmentation (slow-motion latency bombs)
cr0x@server:~$ sudo zpool list -o name,size,alloc,free,capacity,fragmentation,health
NAME SIZE ALLOC FREE CAPACITY FRAG HEALTH
tank 14.5T 13.2T 1.3T 91% 62% ONLINE
Qué significa: 91% lleno y 62% fragmentado. ZFS puede funcionar así, pero no funcionará felizmente. La asignación se complica, el IO se vuelve más aleatorio y la latencia aumenta.
Decisión: Libera espacio. Añade vdevs (de la forma correcta), elimina snapshots/datos antiguos o mueve datos. No tunees alrededor de un pool casi lleno; eso es negación con gráficos.
Task 10: Identify datasets with risky properties for latency
cr0x@server:~$ sudo zfs get -r -o name,property,value recordsize,compression,atime,sync,primarycache,secondarycache tank/app
NAME PROPERTY VALUE
tank/app recordsize 128K
tank/app compression lz4
tank/app atime off
tank/app sync standard
tank/app primarycache all
tank/app secondarycache all
tank/app/db recordsize 128K
tank/app/db compression lz4
tank/app/db atime off
tank/app/db sync standard
tank/app/db primarycache all
tank/app/db secondarycache all
Qué significa: Valores sensatos, pero recordsize=128K puede ser incorrecto para algunos patrones de BD (especialmente muchas I/O aleatorias de 8–16K). Un recordsize incorrecto puede inflar read-modify-write y amplificar la latencia.
Decisión: Si tu carga es aleatoria de bloques pequeños, considera un dataset ajustado a esa carga (a menudo 16K) y valida con pruebas reales de I/O. No cambies recordsize en caliente sin un plan: afecta a bloques escritos nuevos.
Task 11: Find whether scrub/resilver is stealing your lunch
cr0x@server:~$ sudo zpool status tank
pool: tank
state: ONLINE
scan: scrub in progress since Fri Dec 26 09:58:41 2025
3.12T scanned at 1.25G/s, 1.88T issued at 780M/s, 5.21T total
0B repaired, 36.15% done, 01:29:13 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
sdf ONLINE 0 0 0
errors: No known data errors
Qué significa: Hay un scrub en progreso. Incluso en un sistema sano, los scrubs elevan la latencia al consumir I/O y ranuras de cola.
Decisión: Si esto es un incidente de latencia en producción, considera pausar el scrub durante la hora pico y reprogramarlo. Pero no “resuelvas la latencia” evitando scrubs permanentemente. Así se consigue corrupción silenciosa y una mala semana.
Task 12: Check snapshot pressure (space and performance side-effects)
cr0x@server:~$ sudo zfs list -t snapshot -o name,used,refer,creation -S used | head
NAME USED REFER CREATION
tank/app/db@hourly-2025-12-26-10 78G 1.2T Fri Dec 26 10:00 2025
tank/app/db@hourly-2025-12-26-09 74G 1.2T Fri Dec 26 09:00 2025
tank/app/db@hourly-2025-12-26-08 71G 1.2T Fri Dec 26 08:00 2025
tank/app/db@hourly-2025-12-26-07 69G 1.2T Fri Dec 26 07:00 2025
tank/app/db@hourly-2025-12-26-06 66G 1.2T Fri Dec 26 06:00 2025
tank/app/db@hourly-2025-12-26-05 64G 1.2T Fri Dec 26 05:00 2025
tank/app/db@hourly-2025-12-26-04 62G 1.2T Fri Dec 26 04:00 2025
tank/app/db@hourly-2025-12-26-03 61G 1.2T Fri Dec 26 03:00 2025
tank/app/db@hourly-2025-12-26-02 59G 1.2T Fri Dec 26 02:00 2025
Qué significa: Los snapshots están consumiendo espacio serio. Snapshotting frecuente con churn aumenta la fragmentación y reduce el espacio libre, ambos degradan la latencia.
Decisión: Aplica retenciones que reflejen necesidades del negocio, no ansiedad. Si necesitas snapshots frecuentes, planifica capacidad y layout de vdevs para ello.
Task 13: Validate whether a “tuning” change actually helped (fio)
cr0x@server:~$ fio --name=randread --directory=/tank/app/test --rw=randread --bs=16k --iodepth=32 --numjobs=4 --size=4g --time_based --runtime=30 --group_reporting
randread: (groupid=0, jobs=4): err= 0: pid=21144: Fri Dec 26 10:58:22 2025
read: IOPS=42.1k, BW=658MiB/s (690MB/s)(19.3GiB/30001msec)
slat (nsec): min=500, max=220000, avg=1120.4, stdev=820.1
clat (usec): min=85, max=14200, avg=302.5, stdev=190.2
lat (usec): min=87, max=14203, avg=304.0, stdev=190.4
clat percentiles (usec):
| 1.00th=[ 120], 5.00th=[ 150], 10.00th=[ 170], 50.00th=[ 280],
| 90.00th=[ 470], 95.00th=[ 560], 99.00th=[ 900], 99.90th=[ 3100]
Qué significa: Tienes datos de percentiles de latencia. p99 en ~900us puede ser aceptable; p99.9 en 3.1ms puede preocupar para OLTP. La cola importa.
Decisión: Compara antes/después de cambios de tuning. Si p99 empeoró mientras el promedio mejoró, no “optimizaste”, solo moviste el dolor a la cola donde viven los incidentes.
Task 14: Check for kernel-level IO errors and resets
cr0x@server:~$ sudo dmesg -T | egrep -i 'reset|timeout|blk_update_request|I/O error|nvme|ata' | tail -n 20
[Fri Dec 26 10:42:16 2025] ata7.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
[Fri Dec 26 10:42:16 2025] ata7.00: failed command: READ DMA EXT
[Fri Dec 26 10:42:16 2025] blk_update_request: I/O error, dev sdf, sector 983742112 op 0x0:(READ) flags 0x0 phys_seg 8 prio class 0
[Fri Dec 26 10:42:17 2025] ata7: hard resetting link
[Fri Dec 26 10:42:18 2025] ata7: SATA link up 6.0 Gbps (SStatus 133 SControl 300)
Qué significa: El OS está viendo resets de enlace y errores de I/O. Esto se alinea con los eventos de ZFS y el stall mostrado por iostat.
Decisión: Reemplaza hardware sospechoso e inspecciona el path físico. También espera que los picos de latencia se correlacionen con estos resets; anótalos en los gráficos si puedes.
Chiste #2: Cuando el firmware de un SSD empieza a hacer garbage-collecting en medio de un incidente, es como tu conserje pasando la aspiradora durante un simulacro de incendio—técnicamente trabajando, emocionalmente poco útil.
Tres mini-historias corporativas desde el terreno
Mini-historia 1: El incidente causado por una suposición errónea
Una empresa SaaS mediana corrió PostgreSQL sobre volúmenes respaldados por ZFS. Tenían buen hardware, monitorización decente y la creencia confiada: “NVMe es rápido, así que las escrituras sync no pueden ser el problema.” Graficaban throughput y CPU y lo llamaban observabilidad.
Entonces lanzaron una nueva función: más transacciones pequeñas, más commits, más fsyncs. En horas, la latencia p99 de la API se duplicó. La base de datos no cayó. Simplemente empezó a moverse como una persona caminando por cemento húmedo. Los ingenieros persiguieron planes de consulta, pools de conexiones, pausas de GC—cualquier cosa menos el almacenamiento, porque el almacenamiento era “NVMe”.
El gráfico que faltaba era la latencia de escrituras sync. Una vez lo añadieron, la forma fue obvia: una sierra limpia de comportamiento normal punteada por picos feos. Esos picos coincidían con la actividad del ZIL y stalls del dispositivo. Su SLOG “rápido” era un NVMe de consumo sin protección contra pérdida de energía, y bajo carga sync sostenida se quedaba bloqueado periódicamente.
Reemplazaron el SLOG por un dispositivo enterprise diseñado para latencia consistente, y movieron algunos datasets críticos a sync=standard con ajustes de durabilidad a nivel de aplicación, en lugar de forzar sync en todas partes. El incidente terminó rápido—después de una larga desviación por todos los sistemas excepto el culpable.
La suposición errónea no fue “NVMe es rápido”. Fue “rápido significa consistente”. La monitorización de latencia existe para castigar esa creencia antes que lo hagan los clientes.
Mini-historia 2: La optimización que salió mal
Un equipo de plataforma interno empresarial quiso reducir I/O de disco. Vieron que su pool hacía muchas búsquedas de metadata y decidieron “acelerarlo” añadiendo un dispositivo L2ARC. Provisiónaron un SSD grande, activaron L2ARC y vieron crecer la caché. ¿Victoria, verdad?
En una semana, empezaron a ver picos periódicos de latencia en servicios de solo lectura. Los gráficos eran confusos: el throughput estaba estable, la CPU moderada y el ARC hit ratio parecía correcto. Pero la latencia de cola era peor. Los usuarios se quejaban de lentitud intermitente que nunca aparecía en los promedios.
El fallo fue sutil: el L2ARC era enorme y su overhead de metadatos en RAM no era trivial. Bajo presión de memoria de otros servicios, el kernel reclamó memoria; ARC se redujo; la tasa de evicción aumentó; y el sistema osciló entre “caché caliente” y “caché frío”. Cada oscilación creó una ráfaga de lecturas de disco, colas y picos de latencia en la cola.
Lo arreglaron ajustando el tamaño del L2ARC, protegiendo memoria disponible del sistema y cambiando el enfoque a un vdev especial para metadatos (que redujo misses en el camino crítico) en lugar de intentar cachear el problema del working-set. La optimización no fue estúpida—fue incompleta. Trató “más caché” como un bien universal en lugar de un intercambio.
Mini-historia 3: La práctica aburrida que salvó el día
Un equipo de servicios financieros usaba ZFS para un conjunto de APIs orientadas al cliente. Su cultura era agresivamente poco romántica: cada cambio tenía un plan de rollback, cada pool tenía ventanas de scrub semanales y cada dashboard tenía algunos paneles que nadie miraba hasta que importaban.
Uno de esos paneles era latencia por vdev con anotaciones para scrubs y deploys. Otro era un contador simple: errores de checksum por dispositivo. Era aburrido. Se mantuvo plano. La gente lo olvidó.
Un martes por la tarde, el contador de errores de checksum empezó a subir en un solo disco. La latencia aún no era mala. El throughput parecía bien. No hubo quejas de clientes. El ingeniero on-call reemplazó el disco esa misma noche porque el runbook decía, básicamente, “no discutas con errores de checksum”.
Dos días después, el proveedor confirmó un problema de lote con ese modelo de disco. Otros equipos descubrieron el problema durante resilvers y apagones. Este equipo lo descubrió en un gráfico plano volviéndose ligeramente no plano. El ahorro no fue heroico; fue procedimental. Su práctica “aburrida” convirtió un incidente futuro en un ticket de mantenimiento.
Errores comunes: síntoma → causa raíz → solución
1) Síntoma: p99 de latencia de escritura se dispara, pero el throughput parece normal
Causa raíz: un único dispositivo que se queda atascado (GC de firmware, unidad fallando, resets de enlace) mientras el promedio del pool lo oculta.
Solución: grafica latencia por vdev; confirma con iostat -x y logs del kernel; reemplaza el dispositivo o arregla el path. No “tunees ZFS” primero.
2) Síntoma: commits de la base de datos se vuelven lentos tras una “actualización de almacenamiento”
Causa raíz: SLOG ausente, lento o no apropiado para necesidades de durabilidad sync; o dataset cambió a sync=always accidentalmente.
Solución: verifica que el pool tenga un vdev de log; valida latencia de escrituras sync; asegúrate de que el dispositivo SLOG esté diseñado para escrituras de baja latencia consistentes y comportamiento ante pérdida de energía; revierte cambios accidentales de propiedades.
3) Síntoma: la latencia empeora durante backups/snapshots
Causa raíz: churn de snapshots aumenta fragmentación y reduce espacio libre; lecturas de backup colisionan con I/O de producción.
Solución: programa backups y scrubs; usa límites de ancho de banda donde sea posible; mejora la retención; añade capacidad para mantener pools cómodamente por debajo de “llenado de pánico”.
4) Síntoma: lecturas lentas solo después de un deploy o incorporación de un tenant
Causa raíz: el working set ya no cabe en ARC, o aumentaron los misses de metadata; ARC está thrashing por presión de memoria.
Solución: añade memoria disponible; identifica workloads ruidosos; considera un vdev especial para metadatos; no añadas L2ARC enorme sin plan de RAM.
5) Síntoma: “todo se vuelve más lento” cuando corre un scrub
Causa raíz: el scrub compite con producción; pool cerca de saturación; colas de vdev llenas.
Solución: ejecuta scrubs fuera de horas punta; si tu plataforma lo soporta, limita la tasa de scrub; asegúrate de suficientes spindles/IOPS para ambos. Si tu pool no puede scrubear sin afectar usuarios, está infra-dimensionado.
6) Síntoma: alta latencia con baja utilización de dispositivo
Causa raíz: colas por encima de la capa de bloque (bloqueos internos de ZFS, bloqueo por TXG sync, saturación de CPU, reclaim de memoria), o I/O es síncrono y serializado.
Solución: revisa CPU y presión de memoria; busca crecimiento del tiempo de TXG sync; verifica carga sync y SLOG; confirma que tu workload no esté accidentalmente single-threaded en la capa de almacenamiento.
7) Síntoma: rendimiento degrada en meses sin incidente obvio
Causa raíz: pool llenándose, fragmentación subiendo, snapshots acumulándose; la asignación se vuelve cara y los patrones de IO empeoran.
Solución: planificación de capacidad con umbrales impuestos (alertas al 70/80/85%); retención de snapshots; añade vdevs antes de que el pool se convierta en generador de quejas.
Listas de verificación / plan paso a paso
Checklist A: Construye un dashboard de latencia que sea realmente operativo
- Latencia por vdev lectura/escritura (p50/p95/p99 si es posible).
- Utilización por vdev y profundidad de cola (o el proxy más cercano disponible).
- Latencia de escrituras sync y IOPS sync.
- Presión de flush TXG: dirty data, tiempo de sync de txg, indicadores de throttling de escritura.
- Tamaño ARC, objetivo, tasa de misses, tasa de evicción (no solo hit ratio).
- Capacidad del pool y fragmentación.
- Estado de scrub/resilver con anotaciones.
- Contadores de error: checksum, errores de lectura/escritura, timeouts de I/O, resets de enlace.
Regla: Cada gráfico debe responder una pregunta que te harás a las 3 a.m. Si no lo hace, elimínalo.
Checklist B: Pasos de respuesta a incidentes (15 minutos para claridad)
- Ejecuta
zpool status -vy confirma salud, errores, actividad de scrub/resilver. - Ejecuta
zpool iostat -v 1y localiza el peor vdev/dispositivo. - Ejecuta
iostat -x 1para confirmar saturación de dispositivo o picos de await. - Revisa
zpool events -vydmesgpor resets/timeouts/errores. - Revisa propiedades de datasets que influyen en latencia (
sync,logbias,recordsize,compression). - Decide: fallo de hardware, cambio de workload, o presión de capacidad/fragmentación.
- Mitiga: mueve carga, pausa scrub, reduce presión sync o reemplaza dispositivo.
Checklist C: Higiene preventiva que paga la renta
- Alerta en umbrales de capacidad de pool y tendencia de fragmentación.
- Scrubea regularmente, pero prográmalo y observa su impacto.
- Rastrea contadores de error por dispositivo y reemplaza temprano.
- Mantén suficiente espacio libre para que ZFS asigne eficientemente.
- Valida cambios con un benchmark pequeño y comparación de latencia cola, no solo promedios.
Preguntas frecuentes
1) ¿Cuál es el gráfico de latencia ZFS más importante?
Latencia por vdev (lecturas y escrituras). Los promedios del pool ocultan la etapa temprana donde un dispositivo está arruinando el día de todos.
2) ¿Por qué necesito percentiles? ¿No basta la latencia promedio?
Los promedios ocultan el comportamiento de la cola. Los usuarios sienten p99. Las bases de datos sienten p99. Tu canal de incidentes es básicamente un sistema de reporte p99.
3) ¿Agregar un SLOG siempre reduce la latencia?
No. Reduce latencia para escrituras síncronas si el dispositivo SLOG tiene latencia de escritura baja y consistente. Un SLOG malo puede empeorar las cosas.
4) ¿Cómo sé si mi carga es heavy en sync?
Mide. Busca muchas operaciones de escritura sync y alta latencia sync; correlaciónalo con latencia de commits de la BD, comportamiento sync de NFS o aplicaciones que llamen a fsync().
5) ¿Puede un pool estar “sano” y aun así tener terrible latencia?
Absolutamente. Salud es corrección y disponibilidad. Latencia es rendimiento. Un pool puede estar ONLINE mientras un disco se queda intermitentemente atascado.
6) ¿Un pool casi lleno es realmente tan malo? Aún tenemos espacio libre.
Sí, es tan malo. Por encima de ~80–85% de capacidad (dependiendo de la carga), la asignación se complica, la fragmentación sube y la latencia de cola se vuelve peligrosa.
7) ¿Debo desactivar scrubs para mantener baja la latencia?
No. Los scrubs son cómo encuentras corrupción silenciosa y problemas latentes de disco. Programálos y gestiona su impacto; no pretendas que la entropía no existe.
8) ¿La compresión ayuda o perjudica la latencia?
Ambas cosas, depende de la carga. La compresión puede reducir I/O y mejorar la latencia, pero añade coste de CPU y puede cambiar los patrones de tamaño de I/O. Mide con tus datos.
9) ¿Por qué veo alta latencia pero baja %util en discos?
Porque el cuello de botella puede estar por encima del disco: bloqueo TXG sync, reclaim de memoria que reduce ARC, saturación de CPU o un path síncrono serializado.
10) ¿Cuál es la forma más rápida de detectar un disco moribundo antes de que falle?
Grafica latencia por dispositivo y contadores de error. Un disco lento a menudo se vuelve inconsistente antes de volverse muerto.
Próximos pasos que puedes hacer esta semana
- Añade paneles por vdev (lectura/escritura, percentiles si es posible). Si no puedes, al menos separa métricas de vdev/dispositivo de las métricas del pool.
- Anota scrubs, resilvers y despliegues en la misma línea de tiempo que la latencia. Adivinar sale caro.
- Escribe un runbook de 1 página usando el “Guión de diagnóstico rápido” arriba e incluye los comandos exactos que tu equipo ejecutará.
- Configura alertas de capacidad que avisen antes del pánico: comienza a advertir al 70–75%, y hace page en un umbral que tu carga pueda tolerar.
- Ejecuta un test fio (con cuidado, en un dataset seguro) y registra p95/p99. Eso será tu línea base de “normal”.
- Practica un drill de reemplazo: identifica un disco, simula la falla en proceso (no físicamente), confirma que puedes interpretar
zpool statusy proceder sin improvisar.
El objetivo no es construir una catedral de observabilidad perfecta. El objetivo es ver el próximo desastre cuando aún sea lo suficientemente pequeño como para aplastarlo.