No notas los detalles internos de ZFS cuando todo está sano. Los notas a las 02:17, cuando la latencia se dispara,
las réplicas empiezan a agotar tiempo, y alguien pregunta si “añadir caché” lo arreglará. (No lo arreglará. No así.)
Este es el glosario que desearías haber tenido antes de que hicieras que ese pool “simplemente funcione”, lo pusieras en producción
y descubrieras que tu modelo mental era mayormente intuición. Definiremos los grandes sustantivos—VDEV, TXG, ARC, SPA—y luego los usaremos
para tomar decisiones, depurar cuellos de botella y evitar los clásicos outages autoinducidos.
Hechos interesantes e historia (las partes que realmente importan)
- ZFS comenzó en Sun a principios de los años 2000 como respuesta al desorden de “sistema de archivos + gestor de volúmenes + herramienta RAID”. La suposición de diseño: las pilas de almacenamiento deben ser un sistema coherente.
- Copy-on-write no era nuevo, pero ZFS lo llevó a lo operativo mainstream: cada cambio escribe nuevos bloques y luego cambia punteros atómicamente. Por eso puede hacer snapshots consistentes sin congelar el sistema.
- El nombre “Zettabyte” fue aspiracional en una época en que los pools de varios terabytes parecían enormes. Hoy el nombre suena menos a marketing y más a advertencia.
- OpenZFS es una continuación comunitaria después de la era de adquisiciones de Sun. Características como vdevs especiales y L2ARC persistente evolucionaron públicamente, impulsadas por el dolor de operadores reales.
- Checksumming de todo no era la norma en sistemas de archivos de consumo entonces. ZFS hizo de “la corrupción silenciosa es un fallo de almacenamiento, no un problema de la aplicación” una postura operativa.
- ARC se volvió un patrón: una caché adaptativa gestionada por el sistema de archivos que entiende bloques, compresión y metadatos. No es solo “RAM como caché de disco”. Es un motor de políticas con opiniones.
- TXGs son el compromiso entre “sincronizar todo” y “bufferizar para siempre”. El modelo de transaction group es la razón por la que ZFS puede ser rápido y consistente—hasta que tu carga de trabajo lo convierte en un atasco.
- RAID-Z no es RAID por hardware. La paridad la calcula ZFS, con conciencia de tamaños de bloque y sumas de comprobación. Es mejor en muchos sentidos, pero no puedes pretender que la matemática de la paridad sea gratis.
- El valor por defecto “recordsize 1M” no se eligió para bases de datos. Es un valor optimizado para throughput en IO secuencial grande. Si ejecutas escrituras aleatorias de 8K y nunca lo cambias, no eres desafortunado—estás mal configurado.
Glosario esencial: VDEV, TXG, ARC, SPA (con las implicaciones reales)
VDEV (Virtual Device): la unidad de rendimiento y fallo
Un VDEV es el bloque constructivo de ZFS para el almacenamiento de un pool. La gente dice casualmente “mi pool tiene 12 discos,”
pero ZFS escucha: “mi pool tiene estos vdevs.” Y los vdevs son los que determinan:
IOPS, latencia, y a menudo tu radio de impacto.
Un vdev puede ser un disco único (no lo hagas), un mirror, RAID-Z, un archivo (de verdad, no lo hagas), un vdev especial para metadatos,
un log vdev (SLOG), o un dispositivo de caché (L2ARC).
La regla operativa: los vdevs añaden rendimiento; los discos dentro de un vdev añaden redundancia (y a veces ancho de banda).
En un pool formado por múltiples vdevs, ZFS stripea las asignaciones entre vdevs. Más vdevs suele significar más paralelismo.
Pero dentro de un vdev RAID-Z, las pequeñas escrituras aleatorias aún pagan un impuesto de paridad y tienden a serializarse más de lo que te gustaría.
Los vdevs mirror son el caballo de batalla para cargas sensibles a la latencia. Los vdevs RAID-Z son para capacidad y throughput secuencial.
Si ejecutas cargas mixtas, elige deliberadamente en lugar de dejar que compras lo decidan por ti.
TXG (Transaction Group): cómo ZFS convierte el caos en un commit atómico
Un TXG es un lote de cambios en memoria que ZFS finalmente compromete en almacenamiento estable. Piénsalo como
“el conjunto de bloques sucios que escribiremos juntos y luego declararemos durables.”
ZFS cicla los TXGs por estados: open (aceptando cambios), quiescing (deteniendo nuevos cambios),
y syncing (escribiendo a disco). El cambio es periódico y basado en presión.
Si tu pool está sano, esto es invisible. Si tu pool está sobrecargado, lo verás como:
picos de latencia en escritura, tormentas de sync, y aplicaciones bloqueadas en fsync().
El comportamiento de TXG es la razón por la que puedes tener alto throughput pero pésima latencia tail. El pool puede estar “ocupado sincronizando”
y tu carga de trabajo se ve forzada a esperar. Tu monitorización debe separar “estamos escribiendo” de “estamos bloqueados esperando
a terminar de escribir”.
ARC (Adaptive Replacement Cache): RAM como política, no solo caché
El ARC es la caché en memoria de ZFS para bloques usados frecuentemente y recientemente—datos y metadatos.
No es un LRU tonto. Es adaptativa: intenta balancear patrones de acceso “recientes” y “frecuentes”.
ARC también es un actor político en tu sistema. Compite con las aplicaciones por memoria. Si se lo permites,
se comerá la RAM hasta que el kernel lo detenga. Eso no es un bug; es el trato:
memoria sin usar es rendimiento desperdiciado. Pero en producción, “sin usar” rara vez es cierto—tu base de datos, JVM y page cache
también tienen hambre.
ARC tiene varias poblaciones importantes:
listas MFU/MRU (frecuente/reciente),
metadatos,
buffers anónimos,
y buffers sucios aguardando el sync de un TXG.
Cuando alguien dice “la tasa de acierto de ARC es baja,” la pregunta útil es: baja para qué clase, bajo qué carga?
SPA (Storage Pool Allocator): el cerebro del pool
El SPA es el subsistema interno que coordina el pool: gestión de vdevs, asignaciones,
metaslabs, mapas de espacio, y la máquina de estados de alto nivel que hace que “un pool” sea algo coherente.
Si ZFS fuera una empresa, el SPA sería el equipo de operaciones que realmente programa el trabajo.
Rara vez tocas el SPA directamente, pero ves sus decisiones por todas partes: cómo se asignan bloques entre vdevs,
cómo se rastrea el espacio libre, por qué ocurre fragmentación, y por qué algunos pools envejecen como vino y otros como leche.
Una cita que vale la pena tener en la pared, porque los fallos de almacenamiento casi siempre son fallos de coordinación:
“La esperanza no es una estrategia.”
— General Gordon R. Sullivan (citada frecuentemente en ingeniería y operaciones)
Glosario extendido con lo que tropezarás en producción
Pool
Un pool es el objeto de almacenamiento de nivel superior. Agrega vdevs. No puedes reducirlo eliminando
un vdev RAID-Z. Planifica en consecuencia. Tu yo del futuro no se impresionará con “simplemente migraremos después.”
Dataset
Un dataset es un sistema de archivos con sus propias propiedades: compresión, recordsize, cuota, reserva,
comportamiento de sync y más. Los datasets son cómo evitas que una carga de trabajo envenene a otra—si realmente los usas.
Zvol
Un zvol es un dispositivo de bloque respaldado por ZFS. Úsalo para iSCSI, discos de VM, y cosas que demandan
semántica de bloque. Ajusta volblocksize para la carga de trabajo. Déjalo mal y descubrirás formas nuevas y emocionantes de desperdiciar IOPS.
Recordsize y volblocksize
El recordsize es el tamaño máximo de bloque para archivos en un dataset. Un recordsize grande ayuda al throughput secuencial y a la compresión. Un recordsize pequeño ayuda al IO aleatorio y reduce la amplificación de escritura en actualizaciones pequeñas.
El volblocksize es el tamaño de bloque para zvols. Es fijo al crear el zvol.
Si almacenas páginas de base de datos de 8K en un zvol con volblocksize de 128K, le pides a ZFS que haga trabajo extra.
Metaslab
Un metaslab es una región de espacio dentro de un vdev usada para asignaciones. La fragmentación de metaslabs es una
historia común de “mi pool está 70% lleno y todo está lento”. SPA y las clases de metaslab deciden dónde van los bloques;
si estás casi lleno, esas decisiones se constriñen y se vuelven costosas.
Scrub y resilver
Un scrub verifica sumas de comprobación y repara desde la redundancia. Un resilver reconstruye
la redundancia después de reemplazar un dispositivo. Ambos compiten con tu carga por IO. Limítalos apropiadamente,
pero no los saltes. El scrub es como encuentras errores latentes antes de que se conviertan en pérdida de datos.
SLOG y ZIL
El ZIL es el intent log dentro del pool para escrituras síncronas. El SLOG es un dispositivo de log
opcional separado para acelerar esas escrituras síncronas. SLOG no hace que las escrituras asíncronas sean más rápidas. Hace que las síncronas
sean menos miserables al darles una zona de aterrizaje de baja latencia.
El SLOG debe ser fiable y seguro ante pérdidas de energía. Si pones flash “rápido pero frágil” como SLOG, estás construyendo
una mentira en tu modelo de durabilidad. Y ZFS operacionalizará fielmente esa mentira.
L2ARC
L2ARC es una caché de segundo nivel en dispositivos rápidos (normalmente SSD/NVMe). Cachea lecturas, no escrituras.
Históricamente también costaba memoria para indexar; las implementaciones modernas mejoraron persistencia y comportamiento, pero aún
no es gratis. L2ARC no sustituye suficiente RAM ni una configuración sensata de datasets.
Ashift
ashift es el exponente del tamaño de sector que usa ZFS para un vdev. El consejo canónico para producción:
configúralo correctamente al crear el pool, porque cambiarlo luego es efectivamente “reconstruir el pool.”
Un ashift erróneo es una fuga lenta que se convierte en inundación bajo carga.
Broma #1: Configurar ashift mal es como comprarse zapatos una talla menos—técnicamente puedes caminar, pero te arrepentirás en las escaleras.
Compresión
La compresión ahorra espacio y a menudo mejora rendimiento convirtiendo IO en CPU, y IO suele ser el cuello de botella.
Pero si tu CPU ya está al tope, la compresión puede ser la gota final. Mide antes de declararte victorioso.
Copy-on-write y fragmentación
Copy-on-write significa que los bloques se reescriben en otro sitio, no se sobrescriben en su lugar. Eso es genial para consistencia y
snapshots, pero puede fragmentar. La fragmentación empeora a medida que el pool se llena y churnas datos con snapshots.
“ZFS es lento cuando está lleno” es un meme porque suele ser cierto en maneras específicas.
Un modelo mental usable: del syscall al disco giratorio
Lecturas: el camino feliz (cuando está feliz)
Llega una lectura. ZFS revisa ARC. Si el bloque está en ARC, terminas rápido. Si no, ZFS programa lecturas a los vdevs,
recupera bloques, verifica sumas de comprobación, descomprime (si es necesario), y opcionalmente popula ARC (y quizá L2ARC con el tiempo).
La latencia viene dada por: tasa de aciertos de caché, profundidad de cola del vdev, latencia del dispositivo, y cuán dispersos están los bloques.
Los mirrors pueden servir lecturas desde cualquiera de los lados, mejorando a menudo el paralelismo. Las lecturas en RAID-Z pueden ir bien, pero las lecturas pequeñas y aleatorias
compiten con la disposición de paridad y suelen tener mayor amplificación de IO en reparación/scrub.
Escrituras: donde TXG y ZIL deciden tu destino
Una escritura asíncrona va a memoria (buffers sucios en ARC). Más tarde, el sync del TXG la escribe a disco. Si el sistema cae antes
del sync del TXG, esas escrituras asíncronas se pierden. Ese es el contrato. Las apps que se preocupan llaman a fsync() o usan escrituras síncronas.
Una escritura síncrona debe comprometerse de forma que sobreviva a un fallo. ZFS usa el ZIL: registra la intención rápidamente, reconoce,
y luego el sync del TXG escribe los bloques reales y libera los registros del log. Si tienes un SLOG, las escrituras de log van allí.
Si no, van al pool principal, y tu vdev más lento se convierte en la latencia de sync.
La conclusión operacional: la latencia de escritura síncrona suele ser un problema de “dispositivo de log y latencia del pool”, no de ancho de banda bruto.
Puedes tener 5 GB/s de throughput secuencial y aún así 20 ms de fsync que destrozan una base de datos.
Gestión de espacio: SPA, metaslabs y por qué “80% lleno” no es solo un número
El SPA divide cada vdev en metaslabs y rastrea el espacio libre mediante mapas de espacio. Cuando los pools están más vacíos,
las asignaciones son baratas: elige una gran región libre, escribe. A medida que los pools se llenan y fragmentan, las asignaciones se convierten en:
encontrar suficientes segmentos, lidiar con extensiones libres dispersas, actualizar metadatos y pagar más seeks y más gestión.
Por eso la planificación de capacidad es planificación de rendimiento. Si tratas el “espacio libre” solo como una línea presupuestaria, ZFS
eventualmente cobrará sus intereses en latencia.
Tareas prácticas: comandos, significado de la salida y qué decidir
Esto no son trucos de salón. Son los comandos que ejecutas cuando alguien dice “el almacenamiento está lento,” y quieres
responder con evidencia en lugar de sensaciones.
Tarea 1: Identificar la salud del pool y señales de alarma inmediatas
cr0x@server:~$ zpool status -v
pool: tank
state: ONLINE
scan: scrub repaired 0B in 02:14:19 with 0 errors on Wed Dec 24 03:00:12 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
/dev/disk/by-id/ata-A ONLINE 0 0 0
/dev/disk/by-id/ata-B ONLINE 0 0 0
errors: No known data errors
Qué significa: El estado y los contadores de error te dicen si estás depurando rendimiento o
perdiendo activamente redundancia/integridad de datos. Los resultados del scrub importan: bytes reparados significan que tu redundancia arregló corrupción.
Decisión: Si ves DEGRADED, contadores READ/WRITE/CKSUM en aumento, o un resilver activo,
deja de tunear y empieza a estabilizar. La depuración de rendimiento viene después de detener la hemorragia.
Tarea 2: Ver throughput y tendencias de latencia a nivel vdev
cr0x@server:~$ zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 1.20T 2.40T 320 980 45.2M 110M
mirror-0 1.20T 2.40T 320 980 45.2M 110M
ata-A - - 160 490 22.6M 55.1M
ata-B - - 160 490 22.6M 55.0M
-------------------------- ----- ----- ----- ----- ----- -----
Qué significa: Ves operaciones/bandwidth por vdev y por disco. Los mirrors reparten lecturas entre lados;
las escrituras van a ambos. Si un disco muestra latencia notablemente mayor en iostat -x (tarea siguiente), puede arrastrar el mirror.
Decisión: Si un vdev está saturado (altas ops, bajo bandwidth, latencia en aumento), añade vdevs (más paralelismo)
o cambia las características de la carga (recordsize, comportamiento de sync). Si un disco se comporta mal, reemplázalo.
Tarea 3: Confirmar latencia de dispositivo y colas al nivel del SO
cr0x@server:~$ iostat -x 1 3
Linux 6.8.0 (server) 12/26/2025 _x86_64_ (16 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
6.20 0.00 2.10 18.40 0.00 73.30
Device r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 95.0 280.0 12.3 34.8 352.1 7.80 25.6 8.2 31.4 1.1 41.0
sdb 92.0 275.0 12.1 34.6 353.0 8.10 27.4 8.5 33.2 1.1 43.5
Qué significa: await y avgqu-sz muestran latencia y profundidad de cola.
Un %iowait alto sugiere que la CPU espera por almacenamiento. Un %util alto significa que los dispositivos están ocupados.
Decisión: Si await es alto y %util está al máximo, estás limitado por almacenamiento.
Si %iowait es bajo pero las apps son lentas, busca en otro lado (bloqueos, red, CPU).
Tarea 4: Revisar propiedades de datasets que cambian directamente el comportamiento de IO
cr0x@server:~$ zfs get -o name,property,value -s local,received recordsize,compression,atime,sync,logbias tank/app
NAME PROPERTY VALUE
tank/app recordsize 128K
tank/app compression zstd
tank/app atime off
tank/app sync standard
tank/app logbias latency
Qué significa: Estos son los controles que deciden si ZFS hace IO de 128K, comprime,
actualiza tiempos de acceso, y trata las escrituras síncronas con una preferencia por latencia.
Decisión: Para bases de datos, considera recordsize más pequeño (a menudo 16K o 8K según el tamaño de página de la BD),
mantiene atime=off salvo que lo necesites realmente, y ten cautela con cambios a sync. “sync=disabled” no es tuning;
es negociar con la física usando fraude contable.
Tarea 5: Inspeccionar comportamiento del ARC (Linux)
cr0x@server:~$ awk 'NR==1 || /^(size|c |c_min|c_max|hits|misses|mfu_hits|mru_hits|prefetch_data_hits|prefetch_data_misses)/' /proc/spl/kstat/zfs/arcstats
13 1 0x01 204 33728 11970458852 6427389332172
size 4.20G
c 6.00G
c_min 1.00G
c_max 24.0G
hits 132948210
misses 21928411
mfu_hits 90128210
mru_hits 42820000
prefetch_data_hits 1428000
prefetch_data_misses 6180000
Qué significa: size es el tamaño actual del ARC, c es el objetivo, y los contadores hits/misses
indican si las lecturas son amigables con caché. Las fallas de prefetch pueden indicar cargas que vencen las heurísticas secuenciales.
Decisión: Si los misses dominan y tu carga es intensiva en lectura, puede que necesites más RAM, mejor localidad,
o un layout distinto (mirrors, vdev especial para metadatos). Si ARC es enorme y las apps están intercambiando, limita ARC.
Tarea 6: Comprobar datos sucios de ZFS y presión de TXG (Linux)
cr0x@server:~$ awk '/(dirty data|max dirty data|dirty data sync)/{print}' /proc/spl/kstat/zfs/arcstats
dirty data 812345678
max dirty data 4294967296
dirty data sync 0
Qué significa: Datos sucios son escrituras pendientes. Si dirty data se acerca al máximo y se mantiene allí,
el pool no puede vaciar lo suficiente. Ahí es cuando el sync de TXG empieza a limitar a los escritores.
Decisión: Si dirty data es crónicamente alto, estás sobrecargando el pool. Reduce la tasa de escritura,
mejora la latencia de escritura de los vdevs (más vdevs, dispositivos más rápidos), o ajusta la carga (escrituras secuenciales mayores, compresión).
Tarea 7: Identificar dolor de escrituras síncronas y si hay SLOG
cr0x@server:~$ zpool status tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-A ONLINE 0 0 0
ata-B ONLINE 0 0 0
logs
nvme-SLOG ONLINE 0 0 0
Qué significa: Una sección logs significa que tienes un dispositivo de log separado. Sin él,
las escrituras síncronas golpean los vdevs principales y heredan su latencia.
Decisión: Si tienes una carga intensa en sync (bases de datos, NFS con sync, almacenamiento de VM),
considera un SLOG seguro ante pérdida de energía. Si ya tienes uno y sync sigue lento, valida que no sea el cuello de botella.
Tarea 8: Ver uso de espacio por dataset y presión de snapshots
cr0x@server:~$ zfs list -o name,used,avail,refer,compressratio -r tank
NAME USED AVAIL REFER RATIO
tank 1.20T 2.40T 128K 1.45x
tank/app 620G 2.40T 410G 1.62x
tank/app@daily-1 80G - 390G 1.60x
tank/logs 110G 2.40T 110G 1.05x
Qué significa: Los snapshots consumen espacio por bloques cambiados. Si used crece pero refer se mantiene estable,
snapshots (o clones) están reteniendo historial.
Decisión: Si el pool se está llenando y el rendimiento decrece, audita la retención de snapshots.
Conserva los snapshots necesarios, elimina los que no necesitas, y deja de fingir que “retención infinita” es gratis.
Tarea 9: Comprobar fragmentación del pool y margen de capacidad
cr0x@server:~$ zpool list -o name,size,alloc,free,frag,cap,dedup,health
NAME SIZE ALLOC FREE FRAG CAP DEDUP HEALTH
tank 3.60T 1.20T 2.40T 18% 33% 1.00x ONLINE
Qué significa: frag es una heurística, pero es direccionalmente útil. cap muestra el grado de llenado.
A medida que cap sube más allá de ~70–80% en pools ocupados, las asignaciones se vuelven más difíciles y la latencia suele aumentar.
Decisión: Si estás por encima de ~80% y la latencia importa, planifica expansión de capacidad o migración ahora.
“Esperaremos hasta 95%” es como terminas depurando metaslab bajo fuego.
Tarea 10: Inspeccionar ashift y layout de vdev (y detectar errores irreversibles temprano)
cr0x@server:~$ zdb -C tank | egrep 'vdev|ashift|path' | head -n 20
vdev_tree:
type: 'root'
id: 0
guid: 1234567890123456789
children[1]:
type: 'mirror'
id: 0
ashift: 12
children[2]:
type: 'disk'
path: '/dev/disk/by-id/ata-A'
type: 'disk'
path: '/dev/disk/by-id/ata-B'
Qué significa: ashift: 12 significa sectores de 4K. Si tienes discos nativos 4K/8K pero ashift es demasiado pequeño,
has forzado comportamiento de read-modify-write que te perseguirá.
Decisión: Si ashift está mal, presupuestar una reconstrucción/migración. No hay un botón mágico para “arreglar ashift en sitio”.
Tarea 11: Verificar que la compresión ayuda (no solo está “habilitada”)
cr0x@server:~$ zfs get -o name,property,value,source compression,compressratio tank/app
NAME PROPERTY VALUE SOURCE
tank/app compression zstd local
tank/app compressratio 1.62x -
Qué significa: La ratio muestra ahorro real. Una ratio cercana a 1.00x significa que tus datos son incomprimibles
o ya están comprimidos (archivos multimedia, blobs encriptados).
Decisión: Si la ratio está ~1.00x y la CPU está sobrecargada, considera compresión más ligera o ninguna. Si la ratio es buena,
la compresión probablemente te esté comprando margen en IO.
Tarea 12: Detectar un scrub/resilver que te está robando el presupuesto de IO
cr0x@server:~$ zpool status -x
pool 'tank' is healthy
cr0x@server:~$ zpool status tank | sed -n '1,12p'
pool: tank
state: ONLINE
scan: scrub in progress since Thu Dec 25 03:00:12 2025
540G scanned at 610M/s, 120G issued at 140M/s, 1.20T total
0B repaired, 9.77% done, 0:02:13 to go
Qué significa: Un scrub en progreso compite por lecturas (y a veces por escrituras para reparaciones).
La tasa “issued” es la útil; refleja lo que realmente se está empujando a los dispositivos.
Decisión: Si estás en un incidente de rendimiento, puedes pausar o programar scrubs fuera de pico
(según controles de la plataforma). Pero no “resuelvas” rendimiento dejando de scrubear nunca.
Tarea 13: Confirmar mountpoints y evitar extraños doble-mount accidentales
cr0x@server:~$ zfs get -o name,property,value mountpoint,canmount tank/app
NAME PROPERTY VALUE
tank/app mountpoint /srv/app
tank/app canmount on
Qué significa: Datasets mal montados crean el tipo de outage donde escribes datos en el lugar equivocado,
y luego “restauras” desde un snapshot que nunca lo capturó.
Decisión: Estandariza mountpoints y aplícalos en el aprovisionamiento. Trata los mounts ad-hoc como cambios gestionados.
Tarea 14: Monitorizar IO en tiempo real por ZFS y atrapar el proceso abusón
cr0x@server:~$ zpool iostat -w -v tank 1
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 1.20T 2.40T 110 2200 12.1M 280M
mirror-0 1.20T 2.40T 110 2200 12.1M 280M
ata-A - - 55 1100 6.0M 140M
ata-B - - 55 1100 6.1M 140M
-------------------------- ----- ----- ----- ----- ----- -----
Qué significa: El modo -w añade estadísticas de latencia en algunas plataformas/builds; aun sin él,
puedes ver tormentas de escritura. Combínalo con herramientas a nivel de proceso (pidstat, iotop) para hallar la fuente.
Decisión: Si un trabajo inunda con escrituras y empuja el sync del TXG, limita su tasa, aíslalo en su propio dataset,
o muévelo a un pool diferente. Los pools compartidos premian a los abusones y castigan a los demás.
Broma #2: L2ARC es como un “Centro de Excelencia” corporativo—genial en papel, caro en reuniones, y no arreglará tu organigrama.
Guía de diagnóstico rápido (primero/segundo/tercero)
Primero: determina si es salud, capacidad o contención
- Salud:
zpool status -v. ¿Hay errores, dispositivos degradados, resilvers o scrubs? Arregla la salud antes de tunear. - Margen de capacidad:
zpool list. Si estás por encima de ~80% en un pool ocupado, asume que las asignaciones se están volviendo costosas. - ¿Es realmente almacenamiento?
iostat -xpara latencia y utilización de dispositivos. Await/cola alta = contención de almacenamiento.
Segundo: identifica si el dolor viene de lecturas o escrituras
- Mezcla a nivel de pool:
zpool iostat -v 1para ver operaciones y ancho de banda de lectura/escritura. - Sospecha de escrituras síncronas: Si las apps se bloquean en commits/fsync, comprueba presencia de SLOG y propiedades dataset
sync/logbias. - Ángulo de caché: Estadísticas ARC para hits/misses; si las lecturas fallan en ARC y golpean discos lentos, la latencia sigue.
Tercero: valida que el layout coincide con la carga
- Tipo de VDEV: Mirrors para IO aleatorio de baja latencia; RAID-Z para capacidad y throughput secuencial. Si elegiste RAID-Z para una granja de VMs con escrituras aleatorias, el pool está haciendo exactamente lo que pediste.
- Tamaños de bloque: Revisa
recordsizey (para zvols)volblocksize. La desalineación crea amplificación de escritura y presión de TXG. - Vdev especial: Si los metadatos están calientes y tienes rust lento, un vdev especial puede ayudar—pero solo si entiendes las implicaciones de redundancia.
Errores comunes: síntomas → causa raíz → solución
1) “Todo es lento cuando el pool alcanza ~85%”
Síntomas: Latencia de escritura en aumento, pausas impredecibles, scrub/resilver tardan una eternidad, operaciones de metadatos se sienten pegajosas.
Causa raíz: Fragmentación de metaslabs + opciones de asignación restringidas a alta capacidad; el churn de copy-on-write lo empeora.
Solución: Mantén margen (expansión de capacidad antes), reduce churn (disciplina en retención de snapshots), considera añadir vdevs para paralelismo. No apuntes a 95% de uso en pools críticos para rendimiento.
2) “Los commits de la base de datos tardan 20–80 ms, pero el throughput parece bien”
Síntomas: Latencia p99 alta, hilos bloqueados en fsync, TPS colapsa durante ráfagas.
Causa raíz: Cuello de botella en la ruta de escritura síncrona: sin SLOG, SLOG lento, o latencia del vdev principal; las escrituras de log se serializan.
Solución: Usa un SLOG adecuado y seguro ante pérdida de energía para cargas intensas en sync; valida sync y logbias del dataset; asegúrate de que la latencia del vdev no sea patológica.
3) “Añadimos L2ARC y empeoró”
Síntomas: Mayor presión de memoria, stalls ocasionales, sin mejora en tasa de aciertos.
Causa raíz: Overhead de indexación de L2ARC + cacheo del conjunto de trabajo equivocado; RAM insuficiente deja al ARC ya hambriento.
Solución: Añade RAM primero, afina la localidad de la carga, mide tasas de aciertos de ARC antes/después. Usa L2ARC cuando el conjunto de trabajo sea mayor que la RAM pero aún cacheable y de lectura intensiva.
4) “Las escrituras aleatorias son terribles en nuestro nuevo RAID-Z brillante”
Síntomas: IOPS muy por debajo de lo esperado, latencia alta a bajo ancho de banda, CPU aparenta estar ociosa.
Causa raíz: Sobrecoste de paridad RAID-Z y amplificación de escritura en pequeñas escrituras aleatorias; el sync de TXG se convierte en cuello de botella.
Solución: Usa vdevs mirror para cargas de escritura aleatoria; o aisla la carga, ajusta recordsize/volblocksize, y asegúrate de no forzar escrituras síncronas innecesariamente.
5) “Deshabilitamos sync para ‘arreglar’ latencia y luego perdimos datos”
Síntomas: Rendimiento mejora; tras un crash, transacciones recientes faltan o están corruptas a nivel de aplicación.
Causa raíz: Cambiaste las semánticas de durabilidad. ZFS honró tu petición y reconoció las escrituras antes de que fueran estables.
Solución: Vuelve a sync a standard; usa SLOG y hardware adecuado; arregla el verdadero cuello de botella de latencia en lugar de reescribir el contrato.
6) “El scrub mata el rendimiento cada semana”
Síntomas: Picos de latencia previsibles durante ventanas de scrub, timeouts en servicios IO-intensivos.
Causa raíz: El scrub compite por IO con cargas sensibles a latencia; no hay limitación/planificación adecuada.
Solución: Programa scrubs fuera de pico, ajusta comportamiento de scrub si tu plataforma lo permite, y aísla cargas entre pools/clases de vdev cuando sea necesario.
Tres micro-historias corporativas (anonimizadas, dolorosamente reales)
Incidente causado por una suposición errónea: “Un pool es un pool”
Una empresa mediana migró una flota de hosts de VM a un nuevo appliance de almacenamiento respaldado por ZFS. Procurement había optimizado
por capacidad utilizable, así que el diseño fue “unos pocos vdevs RAID-Z anchos con muchos discos.” En papel: genial.
En la práctica: albergaba cientos de discos de VM haciendo pequeñas lecturas/escrituras aleatorias, con ráfagas periódicas intensas en sync.
La suposición que causó el incidente fue simple: “Más discos significa más IOPS.” Eso es verdad cuando añades vdevs,
no cuando añades discos dentro de un vdev RAID-Z y luego le pides que se comporte como un conjunto mirror. Durante la primera gran ventana de parches,
el pool recibió presión sostenida de escritura, los TXGs empezaron a sincronizar continuamente, y la latencia de IO de los guests pasó de
“bien” a “llamar al comandante de incidentes.”
Los dashboards no mentían. El throughput agregado era alto. Eso lo hacía confuso: el ancho de banda parecía sano,
pero las VMs morían. La métrica faltante era la latencia tail en escrituras síncronas. Las cargas no eran limitadas por ancho de banda;
eran dependientes de latencia de commit. Cada fsync estaba esperando detrás del trabajo de paridad y la cola del vdev.
La solución no fue “tuneo.” Fue arquitectura. Añadieron un pool mirror dedicado para almacenamiento sensible a latencia de VMs
y mantuvieron RAID-Z para backups y datos secuenciales. También revisaron defaults de dataset: tamaños de bloque más pequeños donde era apropiado,
y nadie volvió a tocar sync=disabled sin una aceptación de riesgo por escrito.
Optimización que salió mal: vdev especial como botón mágico de velocidad
Otra organización tenía un gran pool en mirrors HDD que servía millones de archivos pequeños. Los metadatos estaban calientes.
Alguien leyó sobre vdevs especiales y propuso: “Pon metadatos en SSD y todo será más rápido.” Verdadero, con matices.
Los matices no se discutieron. Añadieron un vdev especial con menos redundancia que el pool principal porque era “solo metadatos.”
Funcionó de inmediato. Los traveses de directorio se aceleraron, cargas intensivas en stat se calmaron, y el equipo declaró victoria.
Un mes después, el dispositivo especial empezó a lanzar errores intermitentes. ZFS reaccionó correctamente: la integridad de metadatos no es opcional.
Si pierdes el vdev especial y no tiene redundancia suficiente, no solo pierdes rendimiento—puedes perder el pool.
El incidente no se convirtió en titular de pérdida de datos porque el dispositivo no murió por completo. Pero tuvieron un susto operativo caro:
ventana de mantenimiento de emergencia, escalada al proveedor, y una conversación tensa sobre “por qué pusimos datos críticos del pool en un único punto de fallo?”
La optimización fallida no fue “los vdevs especiales son malos.” Fue tratar una característica de rendimiento como si fuera un cache. Los vdevs especiales pueden almacenar metadatos y a veces bloques pequeños. Eso los hace estructurales. Estructural significa que la redundancia debe coincidir con las expectativas del pool. Reconstruyeron el vdev especial como mirror, documentaron el dominio de fallo, y solo entonces lo desplegaron ampliamente.
Práctica aburrida pero correcta que salvó el día: scrubs consistentes + disciplina de reemplazo
Un equipo SaaS corría pools ZFS en servidores commodity. Nada glamuroso: vdevs mirror, margen conservador,
y un calendario de scrubs regular. También tenían un hábito que parece obsesivo hasta que te salva:
si un disco muestra contadores de error en aumento, se reemplaza antes de que “falle por completo.”
Una semana, un scrub reportó bytes reparados en un pool que por lo demás estaba sano. Ninguna aplicación se había quejado.
Nadie lo había notado. Ese es el punto: los errores sectoriales latentes no envían una invitación en el calendario.
El scrub había encontrado discrepancias en sumas, leído desde el mirror, reparado y registrado.
El equipo trató los bytes reparados como un sistema de aviso temprano de hardware. Revisaron tendencias de error del dispositivo al nivel del SO,
cambiaron el disco en una ventana planificada, y resilverizaron mientras el pool seguía sano y sin estrés.
El reemplazo fue aburrido. El incidente que no ocurrió habría sido emocionante.
Un mes después, otro disco en otro servidor falló en horas pico. Ese pool se mantuvo online porque los mirrors más la práctica proactiva
hicieron que nunca estuvieran al borde. Nadie fuera del equipo lo notó.
Así es el trabajo de fiabilidad: éxito que no puedes mostrar en una captura de pantalla.
Listas de verificación / plan paso a paso
Paso a paso: diseña un pool que no te avergüence después
- Clasifica las cargas: lectura aleatoria intensiva, escritura aleatoria intensiva, secuencial, sync-heavy, metadatos intensivos. No las promedies hasta perder significado.
- Elige tipo de vdev por carga: mirrors para baja latencia; RAID-Z para capacidad y throughput secuencial. Las cargas mixtas merecen separación vía datasets o pools separados.
- Planifica número de vdevs para IOPS: ¿necesitas más IOPS? añade vdevs, no discos dentro de un único vdev RAID-Z.
- Decide sobre SLOG: solo si tienes escrituras síncronas significativas. Elige dispositivos seguros ante pérdida de energía; mirror SLOG si tu modelo de riesgo lo exige.
- Decide sobre vdev especial: solo si metadatos/bloques pequeños son el cuello de botella. Igualar redundancia con la importancia del pool.
- Configura ashift correctamente al crear. Trátalo como irreversible, porque a efectos prácticos lo es.
- Establece defaults de dataset:
compression=zstd(a menudo),atime=off(común), recordsize por carga, y cuotas/reservas donde haga falta. - Política de margen de capacidad: define un umbral duro (por ejemplo 75–80%) donde debes expandir o migrar.
- Cadencia operativa: scrubs programados, alertas en errores, y procedimientos documentados de reemplazo.
Paso a paso: cuando heredas un pool y no confías en él
- Ejecuta
zpool status -vy registra contadores de error y estado de scrub como baseline. - Ejecuta
zpool listy anota capacidad y fragmentación. - Ejecuta
zpool iostat -v 1 10durante carga normal para entender lo “normal.” Guarda la salida. - Audita propiedades de dataset:
zfs get -rpararecordsize,sync,compression,atime, cuotas/reservas. - Haz inventario de dispositivos especiales: SLOG, L2ARC, vdev especial. Confirma redundancia y salud.
- Inspecciona ashift vía
zdb -C. Si está mal, regístralo como deuda técnica con un plan. - Revisa retención y patrones de crecimiento de snapshots. Elimínalos responsablemente, pero no dejes que consuman silenciosamente el pool.
- Implementa alertas: cambios de salud del pool, deltas en contadores de error, umbrales de capacidad, fallos de scrub, y latencia inusual.
Preguntas frecuentes
1) ¿Un VDEV es básicamente un grupo RAID?
Funcionalmente, sí: un vdev mirror se parece a RAID1, RAID-Z se parece a RAID de paridad. Operacionalmente, la diferencia importante es:
los vdevs son la unidad contra la que ZFS stripea. Añade vdevs para aumentar IOPS/paralelismo.
2) ¿Por qué cae el rendimiento de ZFS cuando el pool está lleno?
Porque las asignaciones se vuelven restringidas y fragmentadas. El SPA tiene menos buenas opciones, los metadatos crecen, y las escrituras se convierten en
IO más disperso. Los pools casi llenos son pools costosos.
3) ¿Qué significa exactamente que TXG sincronice para mis aplicaciones?
Sincronizar TXG es cuando ZFS vacía datos sucios a disco. Si el pool no puede seguir el ritmo, ZFS limita a los escritores, y tu app lo percibe como latencia.
Las apps intensivas en sync lo sienten más porque requieren commits durables.
4) ¿ARC reemplaza la page cache de Linux?
No exactamente. ZFS usa ARC para caché gestionada por ZFS. El kernel sigue teniendo sus propios mecanismos de page cache, pero ZFS no es un sistema de archivos típico
en cómo gestiona bloques cacheados. La preocupación práctica es la competencia por memoria: debes asegurar que las aplicaciones también tengan RAM suficiente.
5) ¿Cuándo debo añadir un SLOG?
Cuando tu carga emite una cantidad significativa de escrituras síncronas (bases de datos, NFS con semántica sync, almacenamiento de VM que hace flushes),
y la latencia importa. Si tu carga es mayormente escrituras asíncronas en streaming, un SLOG no ayudará.
6) ¿Vale la pena L2ARC?
A veces. Si tu conjunto de trabajo es mayor que la RAM, es intensivo en lecturas y cacheable, L2ARC puede ayudar. Si eres intensivo en escrituras, estás corto de RAM,
o tu carga es aleatoria con poca reutilización, a menudo no hace nada o empeora las cosas.
7) ¿Cuál es la diferencia entre recordsize y volblocksize?
recordsize aplica a archivos en datasets y se puede cambiar. volblocksize aplica a zvols y es fijo al crear.
Elige tamaños de bloque que coincidan con el IO que hace realmente tu aplicación.
8) ¿Puedo cambiar el nivel RAID-Z o quitar un vdev después?
Asume “no” para la planificación de producción. Algunas implementaciones ofrecen características de expansión, pero eliminar vdevs y cambiar nivel RAID no
es algo en lo que debas apostar tu negocio. Diseña como si vivieras con la decisión.
9) ¿Los scrubs dañan los SSDs o acortan su vida dramáticamente?
Los scrubs leen todo el pool y pueden causar escrituras si hay reparaciones. Eso es desgaste, sí—pero la alternativa es no saber que hay corrupción latente hasta que necesites los datos.
La frecuencia de scrub es una decisión de riesgo, no una superstición.
10) ¿Debo habilitar dedup?
Solo si tienes una carga probada que favorece dedup y suficiente memoria/CPU para soportarla. En la mayoría de entornos generales, dedup es un impuesto de rendimiento y complejidad que no compensa.
Conclusión: próximos pasos que puedes hacer esta semana
ZFS no es “complicado.” Es honesto. Expone la realidad de que el almacenamiento es un sistema coordinado: geometría de vdev,
temporización de TXG, comportamiento de ARC y política de asignación del SPA aparecen finalmente en tus gráficas de latencia.
Siguientes pasos prácticos:
- Ejecuta comandos base:
zpool status -v,zpool list,zpool iostat -v, y guarda las salidas como tu “conocido bueno”. - Audita propiedades de dataset para tus tres cargas principales; corrige desajustes evidentes (recordsize, atime, compresión).
- Establece una política de margen de capacidad y aplícala con alertas.
- Si tienes cargas intensivas en sync, valida tu historia de SLOG: o tienes uno bueno, o aceptas la latencia.
- Programa scrubs, monitoriza reparaciones y reemplaza discos sospechosos temprano. Lo aburrido es la meta.
Si recuerdas una cosa: el pool no es la unidad de rendimiento. El vdev lo es. Y los TXGs siempre están haciendo tic-tac en background,
esperando cobrar lo que asumiste durante el diseño.