ZFS ZVOL vs Dataset: La decisión que cambia tu dolor futuro

¿Te fue útil?

Puedes usar ZFS durante años sin pensar nunca en la diferencia entre un dataset y un zvol.
Luego virtualizas algo importante, añades instantáneas “por si acaso”, la replicación se convierte en un requisito de junta,
y de repente tu plataforma de almacenamiento desarrolla opiniones. Opiniones fuertes.

La elección zvol vs dataset no es académica. Cambia cómo se moldea el IO, qué puede hacer la caché, cómo se comportan las instantáneas,
cómo falla la replicación y qué perillas de ajuste existen. Elegir mal no solo te deja con peor rendimiento: te deja
deuda operativa que se compone cada trimestre.

Datasets y zvols: qué son realmente (no lo que dicen en Slack)

Dataset: un sistema de archivos con superpoderes ZFS

Un dataset de ZFS es un sistema de archivos ZFS. Tiene semántica de archivos: directorios, permisos, propiedad, atributos extendidos.
Puede exportarse por NFS/SMB, montarse localmente y manipularse con herramientas normales. ZFS añade su propia capa de funciones:
instantáneas, clones, compresión, sumas de comprobación, cuotas/reservas, afinado de recordsize y toda la seguridad transaccional que
te hace dormir un poco mejor.

Cuando pones datos en un dataset, ZFS controla cómo coloca “registros” de tamaño variable (bloques, pero no bloques de tamaño fijo como
los sistemas de archivos tradicionales). Eso importa porque cambia la amplificación, la eficiencia de la caché y los patrones de IO. La perilla clave es
recordsize.

Zvol: un dispositivo de bloques tallado por ZFS

Un zvol es un volumen ZFS: un dispositivo de bloques virtual expuesto como /dev/zvol/pool/volume. No entiende archivos.
Tu sistema de archivos invitado (ext4, XFS, NTFS) o tu motor de base de datos ve un disco y escribe bloques. ZFS almacena esos bloques como objetos
con un tamaño de bloque fijo controlado por volblocksize.

Los zvols existen para casos donde el consumidor requiere un dispositivo de bloques: LUNs iSCSI, discos de VM, algunos runtimes de contenedores,
algunos hipervisores y, ocasionalmente, pilas de aplicaciones que insisten en dispositivos crudos.

La traducción al mundo real

  • Dataset = “ZFS es el sistema de archivos; los clientes hablan protocolos de archivos; ZFS ve los archivos y puede optimizar en torno a ellos.”
  • Zvol = “ZFS proporciona un disco falso; otra cosa construye un sistema de archivos; ZFS ve bloques y adivina.”

ZFS es extremadamente bueno en ambos, pero se comportan de forma distinta. El dolor viene de asumir que se comportan igual.

Un chiste corto, porque el almacenamiento necesita humildad: si quieres empezar un debate acalorado en un datacenter, saca niveles RAID.
Si quieres acabarlo, menciona “zvol volblocksize” y observa a todos revisando notas en silencio.

Reglas de decisión: cuándo usar un dataset y cuándo un zvol

Posición por defecto: los datasets son la opción aburrida — y la aburrida gana

Si tu carga puede consumir almacenamiento como un sistema de archivos (montaje local, NFS, SMB), usa un dataset. Obtienes operaciones más simples:
inspección más fácil, copia/restauración más sencilla, permisos claros y menos casos límite relacionados con tamaños de bloque y TRIM/UNMAP.
También obtienes el comportamiento de ZFS afinado para archivos por defecto.

Los datasets también son más fáciles de depurar porque tus herramientas siguen hablando “archivo”. Puedes medir fragmentación a nivel de archivo, mirar
directorios, razonar sobre metadatos y mantener un modelo mental limpio.

Cuando un zvol es la herramienta correcta

Usa un zvol cuando el consumidor requiera un dispositivo de bloques:

  • Discos de VM (especialmente para hipervisores que quieren volúmenes crudos, o cuando quieres instantáneas ZFS del disco virtual)
  • Objetivos iSCSI (los LUNs son por definición de bloque)
  • Algunas configuraciones en clúster que replican dispositivos de bloque o requieren semánticas SCSI
  • Aplicaciones legacy que solo soportan “poner la base de datos en un dispositivo crudo” (raro, pero sucede)

El modelo zvol es potente: las instantáneas de un disco de VM son rápidas, los clones son instantáneos, la replicación funciona y puedes comprimir y
sumar-check todo.

Pero: los dispositivos de bloque multiplican la responsabilidad

Cuando usas un zvol, ahora eres responsable del apilamiento entre un sistema de archivos invitado y ZFS. La alineación importa. El tamaño de bloque importa.
Las barreras de escritura importan. El comportamiento Trim/UNMAP importa. Las opciones de sync se vuelven una cuestión de política, no un detalle de ajuste.

Una matriz de decisión simple que puedes defender

  • ¿Necesitas NFS/SMB o archivos locales? Dataset.
  • ¿Necesitas LUN iSCSI o bloque crudo para hipervisor? Zvol.
  • ¿Necesitas visibilidad por archivo y restaurar un único archivo fácilmente? Dataset.
  • ¿Necesitas clones instantáneos de VM desde una imagen base? Zvol (o un dataset con archivos sparse, pero conoce tu tooling).
  • ¿Necesitas una instantánea consistente de una aplicación que maneja su propio sistema de archivos? Zvol (y coordinar flush/quiesce).
  • ¿Intentas “optimizar rendimiento” sin conocer patrones de IO? Dataset, luego mide. El ajuste heroico viene después.

Recordsize vs volblocksize: donde se decide el rendimiento

Datasets: recordsize es el tamaño máximo de un bloque de datos que ZFS usará para archivos. Archivos secuenciales grandes (backups,
medios, logs) prefieren recordsize grandes como 1M. Bases de datos y IO aleatorio prefieren valores pequeños (16K, 8K) porque reescribir una región pequeña no fuerza una gran rotación de bloques.

Zvols: volblocksize es fijo en la creación. Elegir mal y no puedes cambiarlo después sin reconstruir el zvol.
Eso no es “molesto”. Es “vamos a programar una migración en Q4 porque los gráficos de latencia parecen una sierra.”

Instantáneas: aparentemente similares, operativamente diferentes

Hacer una instantánea de un dataset captura el estado del sistema de archivos. Hacer una instantánea de un zvol captura bloques crudos. En ambos casos, ZFS usa copy-on-write,
así que la instantánea es barata al crearla y costosa más tarde si sigues reescribiendo bloques referenciados por instantáneas.

Con zvols, ese coste es más fácil de activar, porque los discos de VM reescriben bloques constantemente: actualizaciones de metadatos, churn de journales,
limpieza del sistema de archivos, incluso “no estar pasando nada” puede significar que algo está reescribiendo. Mantener instantáneas demasiado tiempo se convierte en un impuesto.

Cuotas, reservas y la trampa del thin-provisioning

Los datasets te dan quota y refquota. Los zvols te dan un tamaño fijo, pero puedes crear volúmenes sparse
y fingir que tienes más espacio del real. Eso es una decisión de negocio que se disfraza de función de ingeniería.

El thin-provisioning está bien cuando tienes monitorización, alertas y supervisión adulta. Es un desastre cuando se usa para evitar decir
“no” en una cola de tickets.

Segundo chiste corto (y el último): El thin provisioning es como pedir pantalones una talla menor como “motivación.”
A veces funciona, pero la mayoría de las veces simplemente no puedes respirar.

Modos de fallo que solo conoces en producción

Amplificación de escritura por bloques mal dimensionados

Un dataset con recordsize=1M respaldando una base de datos que hace escrituras aleatorias de 8K puede causar amplificación dolorosa: cada pequeña
actualización toca un registro grande. ZFS tiene lógica para manejar escrituras más pequeñas (y almacenará bloques más pequeños en algunos casos), pero no confíes en que te salve de un ajuste inadecuado. Mientras tanto, un zvol con volblocksize=128K sirviendo un sistema de archivos de VM que escribe bloques de 4K está igualmente desajustado.

Síntoma: buen throughput en benchmarks, latencia de cola miserable en cargas reales.

Semántica sync: donde la latencia se esconde

ZFS respeta las escrituras síncronas. Si una aplicación (o hipervisor) emite escrituras sync, ZFS debe confirmarlas de forma segura—es decir, en almacenamiento estable, no solo en RAM. Sin un dispositivo SLOG dedicado (rápido y protegido contra pérdida de energía), las cargas con muchas escrituras sync pueden tener como cuello de botella la latencia del pool principal.

Los consumidores de zvol suelen usar escrituras sync más agresivamente que los protocolos de archivos. Las VMs y bases de datos tienden a preocuparse por la durabilidad.
Los clientes NFS pueden emitir escrituras sync dependiendo de las opciones de montaje y del comportamiento de la aplicación. En cualquier caso, si los picos de latencia se correlacionan
con carga de escrituras sync, el debate “zvol vs dataset” se convierte en “¿entendemos nuestra ruta de escrituras sync?”

TRIM/UNMAP y el mito de “el espacio libre vuelve automáticamente”

Los datasets pueden liberar bloques cuando se eliminan archivos. Los zvols dependen de que el invitado emita TRIM/UNMAP (y de que tu stack lo haga pasar).
Sin ello, tu zvol parece lleno para siempre, las instantáneas se inflan y empiezas a culpar a la “fragmentación ZFS” por lo que es básicamente ausencia de señalización de recolección de basura.

Explosión de retención de instantáneas

Mantener instantáneas horarias durante 90 días de un zvol de VM se siente responsable hasta que te das cuenta de que estás reteniendo cada bloque modificado por cada actualización de Windows, ejecución de gestor de paquetes y rotación de logs. Las matemáticas se ponen feas rápido. Los datasets también sufren esto, pero el churn de VM es un tipo especial de entusiasmo.

Sorpresa en replicación: los datasets son más amigables para la lógica incremental

La replicación ZFS funciona tanto para datasets como para zvols, pero la replicación de zvol puede ser más grande y sensible al churn de bloques.
Un pequeño cambio en un sistema de archivos invitado puede reescribir bloques por todas partes. Tu send incremental puede parecer sospechosamente un send completo, y tu enlace WAN te enviará la carta de renuncia.

Fricción de herramientas: los humanos son parte del sistema

La mayoría de los equipos tienen mayor músculo operativo alrededor de sistemas de archivos que de dispositivos de bloque. Saben cómo comprobar permisos, cómo copiar
archivos, cómo montar e inspeccionar. Los flujos de trabajo con zvol te empujan a herramientas diferentes: tablas de particiones, sistemas de archivos invitados, comprobaciones a nivel de bloque.
La fricción aparece a las 3 a.m., no en la reunión de diseño.

Datos e historia interesantes para usar en reviews de diseño

  1. ZFS introdujo la suma de comprobación de extremo a extremo como característica central, no como añadido; cambió cómo la gente discutía la “corrupción silenciosa.”
  2. Copy-on-write no era nuevo cuando llegó ZFS, pero ZFS lo hizo operativo y mainstream para pilas de almacenamiento general.
  3. Los zvols fueron diseñados para integrarse con ecosistemas de bloque como iSCSI y plataformas de VM, mucho antes de que “hiperconvergente” fuera una palabra de ventas.
  4. Los valores por defecto de recordsize se eligieron para cargas de archivos de propósito general, no para bases de datos; los valores por defecto son política embebida en código.
  5. Volblocksize es inmutable después de crear el zvol en la mayoría de implementaciones comunes; ese detalle único impulsa muchas migraciones.
  6. El ARC (Adaptive Replacement Cache) hizo que el comportamiento de caché de ZFS sea distinto del de muchos sistemas de archivos tradicionales; no es “solo page cache.”
  7. El L2ARC llegó como caché de segundo nivel, pero nunca reemplazó la necesidad de dimensionar la RAM correctamente; principalmente cambia tasas de acierto, no hace milagros.
  8. Los dispositivos SLOG se convirtieron en un patrón estándar porque la latencia de escrituras síncronas domina ciertas cargas; “SSD rápido” sin protección contra pérdida de energía no es un SLOG.
  9. Send/receive de replicación dio a ZFS un primitivo de backup integrado; no es “rsync”, es un flujo de transacciones de bloques.

Tareas prácticas: comandos, salidas y qué decidir

Estos no son comandos “bonitos de demo”. Son los que ejecutas cuando intentas elegir entre un dataset y un zvol, o cuando intentas probarte que tomaste la decisión correcta.

Tarea 1: Inventario de lo que realmente tienes

cr0x@server:~$ zfs list -o name,type,used,avail,refer,mountpoint -r tank
NAME                         TYPE   USED  AVAIL  REFER  MOUNTPOINT
tank                         filesystem  1.12T  8.44T   192K  /tank
tank/vm                      filesystem   420G  8.44T   128K  /tank/vm
tank/vm/web01                volume      80.0G  8.44T  10.2G  -
tank/vm/db01                 volume     250G   8.44T   96.4G  -
tank/nfs                     filesystem  320G  8.44T   320G  /tank/nfs

Significado: Tienes tanto datasets (filesystem) como zvols (volume). Los zvols no tienen mountpoint.

Decisión: Identifica qué cargas están en volúmenes y pregunta: ¿realmente necesitan bloque, o fue solo inercia?

Tarea 2: Comprobar recordsize del dataset (y si coincide con la carga)

cr0x@server:~$ zfs get -o name,property,value recordsize tank/nfs
NAME      PROPERTY    VALUE
tank/nfs  recordsize  128K

Significado: Este dataset usa registros de 128K, un buen valor general.

Decisión: Si este dataset aloja bases de datos o imágenes de VM como archivos, considera 16K o 32K; si aloja backups, considera 1M.

Tarea 3: Comprobar volblocksize del zvol (la perilla “no se puede cambiar después”)

cr0x@server:~$ zfs get -o name,property,value volblocksize tank/vm/db01
NAME         PROPERTY     VALUE
tank/vm/db01 volblocksize 8K

Significado: Este zvol usa bloques de 8K—comúnmente razonable para IO aleatorio de bases de datos y muchos sistemas de archivos de VM.

Decisión: Si ves 64K/128K aquí para discos de arranque generales, espera amplificación de escritura y considera reconstruir correctamente.

Tarea 4: Comprobar la política sync, porque controla durabilidad vs latencia

cr0x@server:~$ zfs get -o name,property,value sync tank/vm
NAME     PROPERTY  VALUE
tank/vm  sync      standard

Significado: ZFS respetará las escrituras síncronas pero no forzará que todas las escrituras sean síncronas.

Decisión: Si alguien configuró sync=disabled “por rendimiento”, programa una conversación de riesgo y un plan de reversión.

Tarea 5: Ver estado de compresión y ratio (esto a menudo decide el coste)

cr0x@server:~$ zfs get -o name,property,value,source compression,compressratio tank/vm/db01
NAME         PROPERTY       VALUE   SOURCE
tank/vm/db01 compression    lz4     local
tank/vm/db01 compressratio  1.62x   -

Significado: LZ4 está activado y ayudando.

Decisión: Mantenlo. Si la compresión está desactivada en discos de VM, actívala salvo que tengas un cuello de botella de CPU demostrado.

Tarea 6: Comprobar cuántas instantáneas estás arrastrando

cr0x@server:~$ zfs list -t snapshot -o name,used,refer -S used | head
NAME                               USED  REFER
tank/vm/db01@hourly-2025-12-24-23  8.4G  96.4G
tank/vm/db01@hourly-2025-12-24-22  7.9G  96.4G
tank/vm/web01@hourly-2025-12-24-23 2.1G  10.2G
tank/nfs@daily-2025-12-24          1.4G  320G

Significado: La columna USED es el espacio de instantánea único a esa instantánea.

Decisión: Si las instantáneas horarias de VM consumen varios gigabytes, acorta la retención o reduce la frecuencia; las instantáneas no son gratis.

Tarea 7: Identificar “espacio retenido por instantáneas” en un zvol

cr0x@server:~$ zfs get -o name,property,value usedbysnapshots,usedbydataset,logicalused tank/vm/db01
NAME         PROPERTY         VALUE
tank/vm/db01 usedbysnapshots  112G
tank/vm/db01 usedbydataset    96.4G
tank/vm/db01 logicalused      250G

Significado: Las instantáneas están reteniendo más espacio que los datos vivos actuales.

Decisión: Tu “política de backup” ahora es una política de planificación de capacidad. Corrige la retención y considera el TRIM/UNMAP desde el invitado.

Tarea 8: Comprobar salud del pool y errores primero (afinar rendimiento en un pool enfermo es comedia)

cr0x@server:~$ zpool status -v tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 02:14:33 with 0 errors on Sun Dec 22 03:10:11 2025
config:

        NAME                        STATE     READ WRITE CKSUM
        tank                        ONLINE       0     0     0
          mirror-0                  ONLINE       0     0     0
            ata-SSD1                ONLINE       0     0     0
            ata-SSD2                ONLINE       0     0     0

errors: No known data errors

Significado: Pool sano, scrub limpio.

Decisión: Si ves errores de suma de comprobación o vdevs degradados, detente. Arregla hardware/ruteo antes de debatir zvol vs dataset.

Tarea 9: Vigilar IO en tiempo real por dataset/zvol

cr0x@server:~$ zpool iostat -v tank 2 3
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        1.12T  8.44T    210    980  12.4M  88.1M
  mirror-0                  1.12T  8.44T    210    980  12.4M  88.1M
    ata-SSD1                    -      -    105    490  6.2M   44.0M
    ata-SSD2                    -      -    105    490  6.2M   44.1M
--------------------------  -----  -----  -----  -----  -----  -----

Significado: Ves IOPS de lectura/escritura y ancho de banda; esto te dice si estás limitado por IOPS o por throughput.

Decisión: Altas IOPS de escritura con bajo ancho de banda sugiere escrituras pequeñas aleatorias—volblocksize y la ruta sync importan mucho.

Tarea 10: Comprobar presión del ARC (porque la RAM es tu primera capa de almacenamiento)

cr0x@server:~$ arcstat 1 3
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  size     c
12:20:01   532    41      7    12   2     29   5      0   0  48.1G  52.0G
12:20:02   611    58      9    16   2     42   7      0   0  48.1G  52.0G
12:20:03   590    55      9    15   2     40   7      0   0  48.1G  52.0G

Significado: Las tasas de miss del ARC son bajas; la caché está saludable.

Decisión: Si miss% es consistentemente alto bajo carga, añadir RAM a menudo supera cambios ingeniosos en el layout de almacenamiento.

Tarea 11: Comprobar si un zvol es sparse (thin) y si es seguro

cr0x@server:~$ zfs get -o name,property,value refreservation,volsize,used tank/vm/web01
NAME          PROPERTY        VALUE
tank/vm/web01 refreservation  none
tank/vm/web01 volsize         80G
tank/vm/web01 used            10.2G

Significado: Sin reservation: esto es efectivamente thin desde la perspectiva de “espacio garantizado”.

Decisión: Si ejecutas VMs críticas, establece refreservation para garantizar espacio o acepta el riesgo de fallos por pool lleno.

Tarea 12: Confirmar ashift (tu línea base de alineación de sector físico)

cr0x@server:~$ zdb -C tank | grep -E 'ashift|vdev_tree' -n | head
45:        vdev_tree:
67:            ashift: 12

Significado: ashift=12 significa sectores de 4K. Generalmente correcto para SSDs y HDDs modernos.

Decisión: Si ashift es incorrecto (demasiado pequeño), el rendimiento puede quedar dañado permanentemente; reconstruyes el pool, no lo “tuneas.”

Tarea 13: Evaluar tamaño de envío de instantáneas antes de replicar por un enlace pequeño

cr0x@server:~$ zfs send -nvP tank/vm/db01@hourly-2025-12-24-23 | head
send from @hourly-2025-12-24-22 to tank/vm/db01@hourly-2025-12-24-23 estimated size is 18.7G
total estimated size is 18.7G

Significado: La replicación incremental sigue siendo 18.7G—el churn de bloques es alto.

Decisión: Reduce frecuencia/retención de instantáneas, mejora TRIM del invitado o cambia arquitectura (almacenamiento de apps basado en dataset) si es posible.

Tarea 14: Comprobar si TRIM está habilitado en el pool

cr0x@server:~$ zpool get -o name,property,value autotrim tank
NAME  PROPERTY  VALUE
tank  autotrim  on

Significado: El pool está haciendo trim de bloques liberados hacia los SSDs.

Decisión: Si autotrim está off en pools SSD, considera activarlo—especialmente si dependes de que los invitados zvol devuelvan espacio.

Tarea 15: Comprobar propiedades por dataset que cambian comportamiento de forma sigilosa

cr0x@server:~$ zfs get -o name,property,value atime,xattr,primarycache,logbias tank/vm
NAME     PROPERTY      VALUE
tank/vm  atime         off
tank/vm  xattr         sa
tank/vm  primarycache  all
tank/vm  logbias       latency

Significado: atime off reduce escrituras de metadatos; xattr=sa almacena xattrs de forma más eficiente; logbias=latency favorece latencia sync.

Decisión: Para zvols de VM, logbias=latency suele ser razonable. Si logbias=throughput aparece, valida que no fuera un ajuste por imitación.

Guía de diagnóstico rápido (encuentra el cuello de botella en minutos)

Cuando el rendimiento es malo, el debate zvol vs dataset a menudo se convierte en una distracción. Usa esta secuencia para localizar el límite real rápidamente.

Primero: prueba que el pool no esté enfermo

  1. Ejecuta: zpool status -v
    Busca: vdevs degradados, errores de suma de comprobación, resilver en progreso, scrub lento.
    Interpretación: Si el pool está malsano, todo lo demás es ruido.
  2. Ejecuta: dmesg | tail (y los logs específicos del SO)
    Busca: resets de enlace, timeouts, errores NVMe, problemas de HBA.
    Interpretación: Un camino de disco intermitente parece “picos de latencia aleatorios.”

Segundo: clasifica el IO (pequeño aleatorio vs grande secuencial, sync vs async)

  1. Ejecuta: zpool iostat -v 2
    Busca: IOPS altas con MB/s bajos (aleatorio) vs MB/s altos (secuencial).
    Interpretación: El IO aleatorio tensiona la latencia, el secuencial tensiona el ancho de banda.
  2. Ejecuta: zfs get sync tank/... y revisa configuraciones de la aplicación
    Busca: cargas sync sin SLOG o en medios lentos.
    Interpretación: Las escrituras sync expondrán la ruta duradera más lenta.

Tercero: comprueba memoria y caché antes de comprar hardware

  1. Ejecuta: arcstat 1
    Busca: miss% alto, ARC sin crecer, presión de memoria.
    Interpretación: Si fallas caché constantemente, estás forzando lecturas desde disco que podrías evitar.
  2. Ejecuta: zfs get primarycache secondarycache tank/...
    Busca: alguien configuró caché solo para metadatos “para ahorrar RAM.”
    Interpretación: Eso puede ser válido en algunos diseños, pero a menudo es autolesión accidental.

Cuarto: valida tamaño de bloque e impuesto de instantáneas

  1. Ejecuta: zfs get recordsize tank/dataset o zfs get volblocksize tank/volume
    Interpretación: Desajuste = amplificación = latencia de cola.
  2. Ejecuta: zfs get usedbysnapshots tank/...
    Interpretación: Si las instantáneas retienen espacio masivo, también aumentan trabajo de metadatos y asignación.

Tres micro-historias corporativas (anonimizadas, pero dolorosamente reales)

Micro-historia 1: Un incidente causado por una suposición errónea (“un zvol es básicamente un dataset”)

Una empresa SaaS mediana migró de un SAN legacy a ZFS. El ingeniero de almacenamiento—inteligente, rápido, un poco demasiado confiado—estandarizó en zvols
para todo “porque los discos de VM son volúmenes, y eso es lo que hacía el SAN.” El almacenamiento tipo NFS también se movió a sistemas de archivos ext4 respaldados por zvols
montados en clientes Linux. Funcionó en pruebas. Incluso funcionó en producción por un tiempo.

Las primeras señales fueron sutiles: ventanas de backup más largas. La replicación empezó a perder su RPO, pero solo en ciertos volúmenes.
Luego un pool que había estado estable meses golpeó un precipicio de capacidad. “Tenemos 30% libre,” dijo alguien, señalando el dashboard del pool. “¿Entonces por qué no podemos crear un nuevo disco VM?”

La respuesta fueron las instantáneas. Los zvols se instantaneaban cada hora, y los sistemas de archivos invitados estaban churnando bloques constantemente. Los archivos eliminados dentro de los invitados no se traducían en bloques liberados a menos que TRIM atravesara toda la pila. No lo hizo, porque los OS invitados no estaban configurados y la ruta del hipervisor no lo pasaba limpio.

Mientras tanto, la carga tipo NFS ejecutándose dentro del ext4 invitado no tenía razón de estar dentro de un zvol. Querían semántica de archivos pero construyeron una tarta de capas file-on-block-on-ZFS. La respuesta en on-call fue borrar “instantáneas viejas” hasta que el pool dejó de gritar, lo que funcionó brevemente y luego se convirtió en un ritual de emergencia.

La solución no fue glamorosa: migrar datos tipo NFS a datasets exportados directamente, implementar retención sensata para instantáneas de zvols, y validar TRIM extremo a extremo. Tomó un mes de migración cuidadosa deshacer un diseño basado en la suposición errónea de que “volumen vs sistema de archivos es solo empaquetado.”

Micro-historia 2: Una optimización que salió mal (“set sync=disabled, está bien”)

Otra organización, cercana a finanzas y extremadamente alérgica al downtime, ejecutaba un clúster de bases de datos virtualizado. La latencia subía en horas pico. Alguien buscó en foros, encontró las palabras mágicas sync=disabled, y propuso un remedio rápido. El cambio se hizo en la jerarquía de zvol que respaldaba los discos VM.

La latencia mejoró inmediatamente. Los gráficos se veían geniales. El equipo declaró victoria y siguió con otros incendios. Durante unas semanas todo estuvo tranquilo, que es exactamente cómo el riesgo te enseña a ignorarlo.

Luego hubo un evento de energía: no un apagado limpio, no un failover ordenado—solo un momento donde el plan UPS se encontró con la realidad y la realidad ganó. El hipervisor volvió. Varias VMs arrancaron. Algunas no. La base de datos sí, pero revirtió más transacciones de las que gustaron, y al menos un sistema de archivos requirió reparación.

La revisión del incidente fue incómoda porque nadie pudo decir, con la cara seria, que no habían cambiado durabilidad por rendimiento. Lo habían hecho. Eso es lo que hace esa opción. La reversión fue restaurar sync=standard y añadir un SLOG apropiado con protección contra pérdida de energía. La solución a largo plazo fue cultural: ningún “arreglo de rendimiento” que cambie la semántica de durabilidad sin aceptación de riesgo escrita y una prueba que simule pérdida de energía.

Micro-historia 3: La práctica aburrida pero correcta que salvó el día (probar tamaño de send y disciplina de instantáneas)

Un gran equipo de plataforma interna gestionaba dos datacenters con replicación ZFS entre ellos. Tenían el hábito, que parecía tedioso:
antes de incorporar una nueva carga, ejecutarían un “ensayo de replicación” de una semana con instantáneas y zfs send -nvP para estimar tamaños incrementales. También aplicaban políticas de retención como adultos: retención corta para volúmenes con churn, más larga para datasets con datos estables.

Un equipo de producto solicitó “instantáneas horarias por seis meses” para una flota de VMs. El equipo de plataforma no discutió filosóficamente. Hicieron el ensayo. Los incrementales eran enormes y erráticos, y el enlace WAN se habría saturado regularmente. En vez de decir “no”, ofrecieron una alternativa aburrida: diario con retención larga, horario corto con retención breve, más backups a nivel de aplicación para los datos críticos. También movieron algunos datos fuera de discos VM a datasets exportados por NFS, porque eran datos de archivos fingiendo ser datos de bloque.

Meses después, una interrupción en un sitio forzó un failover. La replicación estaba al día, la recuperación fue predecible y el postmortem fue deliciosamente poco eventful. El crédito fue para una práctica que nadie quería hacer porque no era “ingeniería”, era “proceso.”
Ahorró el día de todos.

Errores comunes: síntomas → causa raíz → corrección

1) El almacenamiento de VM es lento y con picos, especialmente durante actualizaciones

  • Síntomas: picos de latencia en cola, interfaces congeladas, arranques lentos, paradas periódicas de IO.
  • Causa raíz: volblocksize del zvol desajustado al tamaño de IO del invitado; instantáneas retenidas demasiado tiempo; escrituras sync bloqueándose en medios lentos.
  • Corrección: reconstruir zvols con volblocksize sensato (a menudo 8K o 16K para VMs generales), reducir retención de instantáneas, validar SLOG para cargas sync-heavy.

2) El pool muestra mucho espacio libre, pero aparece comportamiento de “sin espacio”

  • Síntomas: fallan asignaciones, escrituras bloqueadas, no se pueden crear nuevos zvols, ENOSPC extraño en invitados.
  • Causa raíz: thin provisioning sin refreservation; instantáneas reteniendo espacio; pool demasiado lleno (ZFS necesita margen).
  • Corrección: aplicar reservas para zvols críticos, borrar/expirar instantáneas, mantener el pool por debajo de un umbral sensato y alertas de capacidad que incluyan crecimiento de instantáneas.

3) Incrementales de replicación son enormes para VMs basadas en zvol

  • Síntomas: send/receive que tarda eternamente, saturación de red, incumplimiento de RPO.
  • Causa raíz: churn del sistema de archivos invitado; falta de TRIM/UNMAP; intervalo de instantáneas mal elegido.
  • Corrección: habilitar y verificar TRIM desde el invitado hacia el zvol, ajustar cadencia de instantáneas, mover datos tipo archivo a datasets y probar tamaños estimados de send antes de fijar la política.

4) “Deshabilitamos sync y no pasó nada” (todavía)

  • Síntomas: latencia asombrosa; dashboards sospechosamente calmados; sin fallos inmediatos.
  • Causa raíz: se cambiaron las semánticas de durabilidad; estás reconociendo escrituras antes de que sean seguras.
  • Corrección: revertir a sync=standard o sync=always según corresponda; añadir un SLOG apropiado; probar escenarios de pérdida de energía y documentar aceptación de riesgo si insistes en “engañar a la física.”

5) Carga NFS funciona mal cuando está dentro de una VM en un zvol

  • Síntomas: cargas con muchos metadatos son lentas; backups y restauraciones son torpes; la resolución de problemas es dolorosa.
  • Causa raíz: apilamiento innecesario: carga de archivos colocada dentro de un sistema de archivos invitado encima de un zvol, perdiendo optimizaciones y visibilidad a nivel de archivo de ZFS.
  • Corrección: almacenar y exportar como dataset directamente; ajustar recordsize y atime; mantener la pila simple.

6) El rollback de instantánea “funciona” pero la app queda corrupta

  • Síntomas: después del rollback, el sistema de archivos se monta pero los datos de la aplicación son inconsistentes.
  • Causa raíz: desajuste de consistencia por crash; las instantáneas de zvol capturan bloques, no la quiescencia de la aplicación; las instantáneas de dataset también requieren coordinación para consistencia.
  • Corrección: quiescer aplicaciones (fsfreeze, flush de DB, hooks del agente de invitado del hipervisor) antes de crear instantáneas; validar procedimientos de restauración periódicamente.

Listas de verificación / plan paso a paso

Paso a paso: elegir dataset vs zvol para una nueva carga

  1. Identifica la interfaz que necesitas: protocolo de archivos (NFS/SMB/montaje local) → dataset; protocolo de bloque (iSCSI/disco VM) → zvol.
  2. Anota supuestos de patrón de IO: mayormente secuencial? mayormente aleatorio? ¿sync-heavy? Esto decide recordsize/volblocksize y necesidades de SLOG.
  3. Elige la capa más simple viable: evita file-on-block-on-ZFS a menos que sea imprescindible.
  4. Activa compresión lz4 por defecto salvo que se demuestre lo contrario.
  5. Decide la política de instantáneas desde el inicio: frecuencia y retención; no dejes que crezca como “sustituto de backup.”
  6. Decide expectativas de replicación: haz un ensayo con tamaños estimados de send si te importan RPO/RTO.
  7. Guardarraíles de capacidad: reservas para zvols críticos; cuotas para datasets; mantén margen en el pool.
  8. Documenta recuperación: cómo restaurar un archivo, una VM o una base de datos; incluye pasos de quiescing.

Lista: configurar un zvol para discos de VM (base de producción)

  • Crear con un volblocksize sensato (a menudo 8K o 16K; coincide con las realidades del invitado e hipervisor).
  • Habilitar compression=lz4.
  • Mantener sync=standard; añadir SLOG si la latencia sync importa.
  • Planear retención de instantáneas acorde al churn; probar zfs send -nvP para dimensionar replicación.
  • Verificar TRIM/UNMAP extremo a extremo si esperas recuperación de espacio.
  • Considerar refreservation para invitados críticos y prevenir catástrofes por pool lleno.

Lista: configurar un dataset para apps y almacenamiento de archivos

  • Elegir recordsize según IO: 1M para backups/media; más pequeño para patrones tipo BD.
  • Habilitar compression=lz4.
  • Desactivar atime salvo que realmente lo necesites.
  • Usar quota/refquota para evitar que “un tenant se coma el pool.”
  • Instantanear con retención, no acaparamiento.
  • Exportar vía NFS/SMB con ajustes de cliente sensatos; medir con cargas reales.

Preguntas frecuentes (FAQ)

1) ¿Un zvol siempre es más rápido que un dataset para discos de VM?

No. Un zvol puede ser excelente para discos de VM, pero “más rápido” depende del comportamiento sync, el tamaño de bloque, el churn de instantáneas y la ruta IO del hipervisor. Un dataset que aloje QCOW2/raw también puede rendir muy bien con el recordsize y caché adecuados. Mide, no vibes.

2) ¿Puedo cambiar volblocksize después?

Prácticamente: no. Trata volblocksize como inmutable. Si elegiste mal, la solución limpia es migrar a un nuevo zvol con el tamaño correcto y un corte controlado.

3) ¿Debería poner recordsize=16K para bases de datos en datasets?

A menudo razonable, pero no universal. Muchas bases de datos usan páginas de 8K; 16K puede ser un compromiso decente. Pero si tu carga es mayormente escaneos secuenciales o blobs grandes, recordsize mayor puede ayudar. Perfilá tu IO.

4) ¿Son las instantáneas ZFS backups?

Son un bloque poderoso, no una estrategia de backup. Las instantáneas no protegen contra pérdida del pool, errores operativos en el pool o corrupción replicada si replicás muy pronto. Usa instantáneas junto con replicación y/o almacenamiento de backup separado y retenciones.

5) ¿Por qué eliminar archivos dentro de una VM no libera espacio en el pool ZFS?

Porque ZFS ve un dispositivo de bloques. A menos que el invitado emita TRIM/UNMAP y la pila lo pase, ZFS no sabe qué bloques están libres dentro del sistema de archivos invitado.

6) ¿Debería usar dedup en zvols para ahorrar espacio?

Usualmente no. Dedup consume mucha RAM y es operativamente implacable. La compresión típicamente te da ganancias seguras con menos riesgo. Si quieres dedup, pruébalo con datos realistas y presupuestá RAM en serio.

7) ¿Un SLOG ayuda todas las escrituras?

No. Un SLOG ayuda las escrituras síncronas. Si tu carga es mayormente asíncrona, un SLOG no moverá mucho la aguja. Si tu carga es sync-heavy, un SLOG apropiado puede ser la diferencia entre “bien” y “todo en llamas.”

8) ¿Cuándo debería preferir datasets para contenedores?

Si tu plataforma de contenedores puede usar datasets ZFS directamente (común en muchas configuraciones Linux), los datasets suelen dar mejor visibilidad y operaciones más simples que meter almacenamiento de contenedores en discos VM sobre zvols. Mantén capas mínimas.

9) ¿Puedo usar sync=disabled con seguridad para discos VM si tengo UPS?

Un UPS reduce riesgo; no lo elimina. Existen kernel panics, resets de controladores, bugs de firmware y error humano. Si necesitas durabilidad, mantén semánticas sync correctas e ingeniería del camino de hardware (SLOG con protección) para soportarlo.

10) ¿Cuál es el mejor predeterminado: zvol o dataset?

Por defecto usa dataset a menos que el consumidor requiera bloque. Cuando necesites bloque, usa zvols intencionalmente: elige volblocksize, planifica instantáneas y confirma TRIM y comportamiento sync.

Próximos pasos que puedes hacer esta semana

Aquí está la ruta práctica que reduce dolor futuro sin convertir tu almacenamiento en un experimento científico.

  1. Inventario tu entorno: lista datasets vs volúmenes y mapea a cargas. Cualquier cosa “tipo archivo” viviendo dentro de un zvol es una bandera roja para investigar.
  2. Audita las perillas irreversibles: comprueba volblocksize en zvols y recordsize en datasets clave. Anota desajustes con patrones de carga.
  3. Mide el impuesto de instantáneas: identifica qué zvols/datasets tienen gran usedbysnapshots. Alinea la retención con la necesidad del negocio, no con la ansiedad.
  4. Valida comportamiento sync: encuentra cualquier sync=disabled y trátalo como solicitud de cambio que necesita aceptación de riesgo explícita. Si la latencia sync es un problema, ingeniería con SLOG, no pensamiento mágico.
  5. Corre un ensayo de replicación: usa zfs send -nvP para estimar incrementales durante una semana. Si los números son salvajes, arregla las causas de churn antes de prometer RPOs estrictos.

Una idea parafraseada de John Allspaw (operaciones/confiabilidad): Los incidentes nacen del trabajo normal en sistemas complejos, no de una mala persona teniendo un mal día. (idea parafraseada)

La elección zvol vs dataset es exactamente ese tipo de decisión de “trabajo normal”. Tómala deliberadamente. El tú del futuro seguirá teniendo incidentes,
pero serán del tipo interesante—los que puedes arreglar—en lugar del tipo lento y corrosivo causado por un primitivo de almacenamiento elegido hace años y defendido por orgullo.

← Anterior
Docker Compose: las variables de entorno te traicionan — errores de .env que rompen producción
Siguiente →
Volúmenes NFS de Docker con tiempo de espera: Opciones de montaje que realmente mejoran la estabilidad

Deja un comentario