Cualquier discusión sobre almacenamiento en una sala de chat corporativa termina, tarde o temprano, con una captura de pantalla de zfs list y la afirmación segura de que “ZFS está mintiendo”. No es así. Simplemente hace la contabilidad con reglas distintas de las que tu cerebro aprendió con ext4, VMFS o aquella interfaz SAN que redondea todo a “más o menos un montón”.
Este artículo trata sobre dos campos que parecen pequeños—logicalused y used—y por qué marcan la diferencia entre una guardia tranquila y un incidente escalado. Iremos lo bastante profundo para satisfacer a quien lee zdb por diversión, pero con la practicidad necesaria para diagnosticar una crisis de espacio mientras alguien de Finanzas pregunta por qué “pagamos discos que no usamos”.
Por qué importan estos dos números
En ZFS, “¿cuánto espacio está usado?” no es una sola pregunta. Son al menos tres:
- ¿Cuánto ocuparían mis datos si se almacenaran sin compresión y sin compartir bloques con instantáneas/clones?
- ¿Cuánto espacio físico está realmente asignado en disco ahora mismo?
- ¿Cuánto espacio puedo liberar eliminando este dataset, archivo, instantánea o clon?
logicalused y used son las dos primeras preguntas. Confundirlas y vas a:
- Dimensionar mal los pools (comprar de más o, peor, de menos).
- Eliminar lo equivocado bajo presión (el clásico “borramos el dataset y no se liberó nada”).
- Echarle la culpa a ZFS por tu propio malentendido (una orgullosa tradición en TI).
Un chiste corto, como manda la tradición: los informes de almacenamiento ZFS son como las cuentas de un restaurante—si no entiendes las partidas, acusarás al camarero de robo. El camarero solo hace las matemáticas que no pediste ver.
Definiciones: used vs logicalused
Qué significa used
used es la cantidad de espacio que ese dataset ha asignado en el pool, medida en espacio real en disco. Incluye los efectos de la compresión, copias, sobrecarga de paridad (indirectamente, porque la asignación es en espacio real del pool), y comprende bloques referenciados únicamente por este dataset y bloques compartidos con instantáneas/clones dependiendo de qué propiedad estés leyendo.
En términos simples: used es la asignación física del pool atribuida al namespace de ese dataset, según la contabilidad de ZFS.
Qué significa logicalused
logicalused es el tamaño lógico de los datos almacenados en ese dataset—lo que obtendrías si sumaras los tamaños de archivo (o tamaños lógicos de bloque) antes de la compresión. Está pensado para responder: “¿Qué tan grande es el dato, conceptualmente?” y no “¿Cuánto disco costó?”.
En términos simples: logicalused es el tamaño aparente desde el punto de vista de ZFS.
Por qué divergen
La diferencia entre ellos se explica sobre todo por:
- Compresión:
logicalusedsigue “grande”,usedse reduce. - Instantáneas y clones: la eliminación puede no liberar
usedsi los bloques siguen siendo referenciados en otro lugar. - Reservas: el espacio puede estar “no disponible” sin estar “usado por datos”.
- Copias, recordsize/volblocksize, padding: la sobrecarga y la granularidad de asignación pueden hacer que
usedsea mayor de lo esperado.
El modelo de contabilidad de espacio (qué cuenta realmente ZFS)
ZFS es un sistema de archivos copy-on-write con almacenamiento en pool. Esa sola frase explica por qué tu intuición de sistemas de archivos tradicionales falla.
Bloques, referencias y por qué la eliminación no siempre recupera espacio
En ZFS, los bloques se liberan cuando desaparece la última referencia. Un archivo en un dataset referencia bloques. Una instantánea también referencia bloques (un conjunto de referencias en un punto en el tiempo). Un clon referencia bloques también. Hasta que cada objeto que referencia deje de hacerlo, los bloques permanecen asignados.
Así que puedes borrar el archivo—y aun así no liberar ni un byte—porque la instantánea conserva los bloques antiguos. Eso no es “sobrecarga de instantánea”, es la instantánea haciendo su trabajo: preservar datos antiguos.
“Usado por dataset” vs “usado por instantáneas” es contabilidad, no física
ZFS expone una familia de propiedades para desglosar el uso. La clave es entender que algunas propiedades responden “qué se le puede atribuir a este dataset” y otras responden “qué es exclusivo de este dataset”.
Si recuerdas una cosa para una guardia: used no es equivalente a “espacio que se liberará si destruyo este dataset”. Para eso quieres usedbydataset, usedbysnapshots, usedbychildren, usedbyrefreservation, y, a menudo, logicalused más logicalusedbydataset.
La compresión es la razón más clara por la que lo lógico y lo físico difieren
La compresión cambia cuántos sectores físicos se asignan, pero no cambia lo que las aplicaciones creen que escribieron. Tu base de datos aún escribió 1 TB de páginas; ZFS pudo haber almacenado 300 GB porque comprimió bien. Justo por eso existe logicalused: mantiene la visión de “lo que la app cree haber consumido”, incluso cuando se guarda más barato.
Contexto histórico y datos interesantes
Esto no es trivia por la trivia misma; explica por qué ZFS informa lo que informa.
- ZFS fue diseñado para acabar con la reparación de sistemas de archivos como ritual. Checksums, copy-on-write e integridad de extremo a extremo fueron objetivos centrales, y el modelo de contabilidad siguió: instantáneas inmutables y bloques compartidos son características, no casos marginales.
- El evangelismo temprano de ZFS promovió “las instantáneas son baratas”. Cierto para metadatos y bloques sin cambios. Pero los bloques cambiados se acumulan, y la contabilidad del espacio tuvo que explicar esa realidad.
- “Almacenamiento en pool” fue un cambio filosófico. Los sistemas de archivos tradicionales vivían en particiones/LUNs fijas. ZFS movió las restricciones al pool, por eso los datasets pueden tener cuotas/reservas independientes pero compartir el mismo asignador físico.
- La familia
logicalusedllegó para hacer visible la compresión. Los operadores necesitaban separar “huella de la aplicación” de “huella en disco”, especialmente para planificación de capacidad y reparto de costes. - Copy-on-write es por qué existen fragmentación y sobrecarga de asignación. ZFS evita sobrescribir en el lugar; escribe nuevos bloques y cambia punteros. La contabilidad del espacio tiene que manejar múltiples versiones de bloques y la churn de asignaciones de corta duración.
- La estandarización de OpenZFS importa. Propiedades como
usedby*ylogicalused*están ampliamente disponibles ahora, pero builds de proveedores antiguos y forks de la era illumos variaban—lo que condujo a muchas historias de “pero mi sistema no muestra esa propiedad”. - Los tamaños de registro grandes fueron una elección deliberada de rendimiento. Los valores por defecto de recordsize en ZFS (p. ej., 128K) se eligieron para hacer IO secuencial eficiente, pero también afectan cuánto espacio físico se asigna para escrituras pequeñas y cuán comprimible es el dato.
- La contabilidad del espacio se convirtió en un campo de batalla de soporte. Los proveedores de almacenamiento y los equipos de plataforma internos aprendieron a la fuerza que una sola columna “Used” genera tickets. Las propiedades detalladas existen porque los operadores exigieron respuestas, no sensaciones.
Cómo la compresión cambia la historia
La compresión es la razón más habitual por la que logicalused eclipsa a used. También es la razón por la que la planificación de capacidad en ZFS puede parecer magia a quien no ha vivido un pool llenándose a las 3 a. m.
Ejemplo: la base de datos que “usaba 10 TB” en un pool de 4 TB
He visto el mensaje de pánico: “El dataset dice 10 TB usados pero el pool solo tiene 4 TB—ZFS está corrupto.” No, está comprimido. logicalused sigue el tamaño lógico; used sigue la asignación real. Si tus datos se comprimen 3:1, los números lógicos pueden ser mayores que la capacidad del pool y aun así estar perfectamente sanos.
La relación de compresión no es una promesa
En el momento en que cambia tu carga de trabajo, tu “espacio libre” cambia de una forma que se siente injusta. Los logs comprimen bien hasta que dejan de hacerlo. Las imágenes de VM comprimen bien hasta que alguien activa cifrado de disco completo dentro del invitado. Las copias de seguridad comprimen bien hasta que tu software de backup empieza a aplicar su propia compresión y cifrado.
Planificar capacidad con la relación de compresión de ayer es como presupuestar con el clima de ayer: funciona hasta que necesitas que funcione.
Segundo chiste corto: la compresión es como hacer la maleta—todo cabe hasta que añades los zapatos.
Instantáneas, clones y el recaudador
Las instantáneas son la razón por la que ZFS puede ser tu mejor amigo y tu mentiroso más convincente. No mienten, pero muestran cuánto desconoces sobre los datos “eliminados”.
Las instantáneas mantienen los bloques vivos
Cuando haces una instantánea de un dataset, estás congelando un conjunto de punteros a bloques. Cambios posteriores asignan nuevos bloques; los bloques antiguos permanecen referenciados por la instantánea. Por eso:
- Borrar un archivo puede no reducir mucho
used(o nada). - Destruir instantáneas antiguas puede liberar de golpe enormes cantidades de espacio.
usedbysnapshotspuede crecer rápidamente en cargas con mucho churn (VMs, bases de datos, espacios de trabajo CI).
Los clones son propiedad compartida con papeleo
Un clon es un dataset escribible que empieza como una instantánea. Comparte bloques hasta que diverge. Esto complica la recuperación de espacio porque ahora hay múltiples hijos referenciando la misma ascendencia. Si destruyes el origen pensando que liberarás espacio, puede que descubras que el clon se ha convertido en el propietario principal de esos bloques.
La consecuencia práctica
En respuesta a incidentes, las instantáneas son el primer lugar donde buscar “espacio que no se va”. En los informes de capacidad, las instantáneas son la razón por la que nunca debes tratar “used del dataset” como equivalente a “coste”.
Reservas, cuotas, refquota: los contratos ocultos
La contabilidad del espacio no es solo física; es política. ZFS te permite hacer promesas (reservas) e imponer límites (cuotas). Esas promesas y límites aparecen de maneras que sorprenden a quienes solo miran used.
Quota vs refquota (y por qué importa)
quota limita un dataset y sus descendientes. refquota limita solo el espacio referenciado por el propio dataset (no los hijos). Esta distinción importa cuando tu “dataset de proyecto” es un padre con muchos hijos.
Si quieres evitar que un único dataset se salga de control mientras permites que los hijos crezcan independientemente, refquota es la herramienta. Si quieres capar todo un subtree, quota es la herramienta.
Reservation vs refreservation
reservation reserva espacio para un dataset y sus descendientes. refreservation reserva espacio solo para el propio dataset. Las reservas reducen lo que el pool reporta como disponible aunque el dataset no haya escrito realmente esos datos todavía.
Aquí es de donde vienen los incidentes “¿por qué el pool está lleno?”: el pool no está lleno de datos; está lleno de promesas.
Refreservation aparece como usedbyrefreservation
Cuando alguien establece refreservation por “seguridad de rendimiento” y lo olvida, se convierte en un asesino silencioso de capacidad. El espacio se asigna lógicamente en términos contables, haciendo que el pool parezca ajustado y provocando fallos de asignación antes de lo esperado.
Tareas prácticas: comandos + interpretación
Estos son los comandos a los que realmente recurro cuando alguien dice “el espacio ZFS está mal”. Cada tarea incluye qué buscas y cómo interpretarlo.
Tarea 1: Comparar used vs logicalused de un dataset
cr0x@server:~$ zfs list -o name,used,logicalused,avail,refer,logicalrefer -H tank/app
tank/app 320G 950G 1.2T 310G 920G
Interpretación: El dataset contiene ~950G de datos lógicos pero solo cuesta ~320G de espacio físico del pool—la compresión y/o el compartido de bloques están pagando el alquiler. Si el pool está bajo, eliminar este dataset podría liberar solo alrededor de lo que indica used (y posiblemente menos si instantáneas/clones comparten bloques).
Tarea 2: Obtener el desglose de uso (para zanjar la discusión)
cr0x@server:~$ zfs list -o name,used,usedbydataset,usedbysnapshots,usedbychildren,usedbyrefreservation -H tank/app
tank/app 320G 180G 120G 0B 20G
Interpretación: 120G se atribuyen a instantáneas, 20G estan ocupados por refreservation. Si intentas recuperar espacio, eliminar instantáneas puede ser más eficaz que borrar archivos.
Tarea 3: Listar instantáneas con impacto en espacio
cr0x@server:~$ zfs list -t snapshot -o name,used,refer,logicalused -s used -H tank/app
tank/app@daily-2025-12-20 40G 310G 920G
tank/app@daily-2025-12-21 35G 312G 925G
tank/app@daily-2025-12-22 25G 315G 930G
Interpretación: El used de la instantánea es el espacio mantenido de forma única por esa instantánea (aproximadamente: los bloques que se liberarían si se destruyera, suponiendo que no haya clones). Ordena por used para encontrar las más costosas.
Tarea 4: Comprobar ajustes de compresión y ratio observado
cr0x@server:~$ zfs get -o name,property,value -H compression,compressratio,logicalused,used tank/app
tank/app compression zstd
tank/app compressratio 2.96x
tank/app logicalused 950G
tank/app used 320G
Interpretación: Un ratio ~3x explica la brecha. Si compressratio está cerca de 1.00x pero logicalused sigue siendo enorme, busca instantáneas/clones o sobrecarga de asignación.
Tarea 5: Confirmar si tratas con un volumen (zvol) vs filesystem
cr0x@server:~$ zfs get -H -o name,property,value type,volblocksize,recordsize tank/vm-001
tank/vm-001 type volume
tank/vm-001 volblocksize 16K
tank/vm-001 recordsize -
Interpretación: Los volúmenes tienen comportamiento distinto: escrituras aleatorias pequeñas, padding y elecciones de blocksize pueden cambiar los patrones de uso físico y el crecimiento por instantáneas.
Tarea 6: Detectar reservas y por qué “avail” es pequeño
cr0x@server:~$ zfs get -H -o name,property,value reservation,refreservation,quota,refquota tank/app
tank/app reservation none
tank/app refreservation 50G
tank/app quota none
tank/app refquota none
Interpretación: Esa refreservation de 50G aparecerá en usedbyrefreservation y reducirá el espacio libre del pool incluso si el dataset está mayormente vacío.
Tarea 7: Confirmar salud del pool y espacio libre real (no ignores el margen)
cr0x@server:~$ zpool list -o name,size,alloc,free,frag,capacity,health
NAME SIZE ALLOC FREE FRAG CAPACITY HEALTH
tank 7.25T 6.70T 550G 48% 92% ONLINE
Interpretación: 92% de capacidad es territorio de “empiecen a cancelar reuniones”. Incluso si los datasets muestran “avail”, la fragmentación a nivel de pool y las necesidades del asignador pueden hacer que las escrituras fallen antes de lo que la gente espera.
Tarea 8: Mostrar los datasets principales por used físico
cr0x@server:~$ zfs list -o name,used,logicalused,compressratio -S used | head -n 10
NAME USED LOGICALUSED COMPRESSRATIO
tank/vm 2.4T 2.6T 1.08x
tank/backups 1.9T 6.1T 3.21x
tank/home 980G 1.1T 1.12x
tank/app 320G 950G 2.96x
Interpretación: Empieza por lo que cuesta espacio físico, no por lo que parece grande lógicamente. Las 6.1T lógicas de backups son solo 1.9T reales; las VMs son caras porque no se comprimen mucho.
Tarea 9: Identificar datasets con muchas instantáneas rápidamente
cr0x@server:~$ zfs list -o name,used,usedbysnapshots,logicalused -S usedbysnapshots | head -n 10
NAME USED USEDBYSNAPSHOTS LOGICALUSED
tank/vm 2.4T 820G 2.6T
tank/app 320G 120G 950G
tank/home 980G 40G 1.1T
Interpretación: usedbysnapshots es tu señal de “espacio clavado por la historia”. Valores altos significan churn más instantáneas; ajusta la retención o la cadencia, no solo el tamaño del dataset.
Tarea 10: Comprobar si un dataset tiene clones que dependen de instantáneas
cr0x@server:~$ zfs get -H -o name,property,value clones tank/app@daily-2025-12-20
tank/app@daily-2025-12-20 clones tank/app-clone-qa
Interpretación: No puedes destruir esa instantánea sin lidiar con el clon. Si alguien dice “borramos instantáneas pero el espacio no se liberó”, los clones son un sospechoso principal.
Tarea 11: Estimar cuánto liberarías destruyendo una instantánea (lógica de simulación)
cr0x@server:~$ zfs list -t snapshot -o name,used -s used -H tank/app | tail -n 5
tank/app@daily-2025-11-30 2G
tank/app@daily-2025-12-01 3G
tank/app@daily-2025-12-02 4G
tank/app@daily-2025-12-03 9G
tank/app@daily-2025-12-04 15G
Interpretación: El used de la instantánea es una primera aproximación de “lo que podrías recuperar”, pero recuerda: los clones pueden impedir la reclamación, y eliminar una instantánea puede desplazar la contabilidad a otras instantáneas.
Tarea 12: Destruir instantáneas con seguridad usando un patrón (y verificar)
cr0x@server:~$ zfs destroy -n -v tank/app@daily-2025-12-0{1,2,3}
would destroy tank/app@daily-2025-12-01
would destroy tank/app@daily-2025-12-02
would destroy tank/app@daily-2025-12-03
cr0x@server:~$ zfs destroy -v tank/app@daily-2025-12-0{1,2,3}
will destroy tank/app@daily-2025-12-01
will destroy tank/app@daily-2025-12-02
will destroy tank/app@daily-2025-12-03
cr0x@server:~$ zfs list -o name,used,avail -H tank/app
tank/app 250G 1.3T
Interpretación: Usa -n primero. Luego ejecuta. Luego verifica. En producción, la diferencia entre héroe y titular es un dry run.
Tarea 13: Comprobar espacio “atascado” por refreservation
cr0x@server:~$ zfs list -o name,usedbyrefreservation,refreservation -H tank/app
tank/app 20G 50G
cr0x@server:~$ zfs set refreservation=none tank/app
cr0x@server:~$ zfs list -o name,used,avail -H tank/app
tank/app 230G 1.4T
Interpretación: Acabas de recuperar “espacio de política”. Confirma con el equipo propietario antes de quitar reservas; a veces existen para tolerancia a picos legítima.
Tarea 14: Comparar tamaños aparentes de archivos con números lógicos de ZFS (comprobación de coherencia)
cr0x@server:~$ df -hT /tank/app
Filesystem Type Size Used Avail Use% Mounted on
tank/app zfs 1.5T 310G 1.2T 21% /tank/app
cr0x@server:~$ du -sh /tank/app
910G /tank/app
Interpretación: du es una vista a través del namespace del sistema de archivos y puede estar sesgado por archivos dispersos, permisos y cambios en vivo. Trátalo como evidencia de apoyo, no como la verdad absoluta. Las propiedades de ZFS suelen ser más consistentes para la contabilidad.
Tarea 15: Si sospechas archivos sparse en VMs o bases de datos
cr0x@server:~$ ls -lh /tank/vm/images/vm-001.img
-rw------- 1 root root 500G Dec 25 10:11 /tank/vm/images/vm-001.img
cr0x@server:~$ du -h /tank/vm/images/vm-001.img
120G /tank/vm/images/vm-001.img
Interpretación: Ese archivo es sparse: el tamaño lógico es 500G, el consumo físico es 120G. logicalused tiende a alinearse con la visión “500G”, mientras que used se alinea con la “realidad de 120G”, modulada por compresión e instantáneas.
Minicuentos del mundo corporativo en producción
Minicuento 1: El incidente causado por una suposición equivocada
El equipo de almacenamiento recibió un pager por “pool al 95%” un viernes por la tarde, del tipo de sincronización que sugiere que el universo tiene calendario y sentido del humor. El propietario de la aplicación señaló logicalused: su dataset “tenía varios terabytes”, por lo tanto eran los villanos. Se ofrecieron a borrar un lote de exports antiguos. Todos aplaudieron; nadie comprobó las instantáneas.
Se borraron los exports. du se desplomó. Slack se llenó de pulgares arriba. El pool no se movió. El siguiente trabajo intensivo en escrituras golpeó ENOSPC en una hora y tumbó una canalización de ingestión. Ya no era solo un ticket; era un incidente con ejecutivos.
Al final hicimos lo adulto: ejecutamos zfs list -o usedby* y ordenamos instantáneas por used. El dataset tenía una política agresiva de instantáneas—cada 15 minutos—para “rollback fácil”, y la carga reescribía archivos grandes constantemente. Las instantáneas no eran baratas. Acaparaban los bloques de ayer como un conservador de museo con presupuesto de almacenamiento.
La solución no fue heroica. Reducimos la frecuencia de instantáneas, acortamos la retención y destrujimos un conjunto de instantáneas de alto impacto después de confirmar que no dependían clones. El espacio volvió, la ingestión se reanudó, y la lección clave del postmortem quedó en negrita: “Borrar archivos no es un plan de recuperación de espacio cuando existen instantáneas”.
Lo que dolió no fue la complejidad técnica; fue la suposición equivocada de que borrar archivos equivale a recuperar espacio. En ZFS, las referencias importan más que la intención.
Minicuento 2: La optimización que salió mal
Un equipo de plataforma quiso mejorar el rendimiento de VMs y decidió “optimizar instantáneas” cambiando el dataset de VM a un tamaño de bloque más pequeño y subiendo la frecuencia de instantáneas, asumiendo que bloques más pequeños significarían deltas más pequeños. La teoría sonaba plausible en una reunión. La teoría suele hacerlo.
En la práctica, los bloques más pequeños aumentaron la sobrecarga de metadatos y convirtieron las escrituras en una lluvia de asignaciones. La carga de VM—muchas escrituras aleatorias—produjo un flujo constante de nuevos bloques. Las instantáneas capturaron los antiguos. El uso de espacio por instantáneas creció más rápido, no más lento. El ratio de compresión también empeoró porque bloques más pequeños y más aleatorios no se comprimen igual.
La primera señal no fue un panel; fue latencia. El pool se fragmentó y se puso ocupado. Luego fue capacidad: usedbysnapshots se convirtió en el término dominante. El equipo intentó borrar “instantáneas antiguas”, pero clones de flujos CI mantenían referencias, así que las grandes liberaciones nunca llegaron.
El plan de recuperación fue poco glamuroso: revertir la cadencia de instantáneas a algo sensato, reevaluar tamaños de bloque por carga de trabajo y dejar de clonar desde instantáneas con retención larga. La verdadera optimización no fue “más perillas”, fue alinear la política (instantáneas) con el churn de la carga y entender que logicalused no es una factura.
Minicuento 3: La práctica aburrida pero correcta que salvó el día
Una organización distinta tenía una regla: cada alerta de capacidad tenía un “snapshot de contabilidad de espacio” obligatorio—cuatro comandos pegados en el ticket: zpool list, zfs list -o usedby* en los datasets principales, listado de instantáneas ordenado por used, y una comprobación de reservas/cuotas. Era tan aburrido que los ingenieros se quejaban de burocracia. También fue la razón por la que sus incidentes terminaban rápido.
Una noche, un pool empezó a subir su uso inesperadamente. El on-call siguió la lista, descubrió un único dataset con usedbyrefreservation disparándose, y encontró que un job de automatización había aplicado una gran refreservation para “proteger rendimiento” durante una migración. La migración terminó; la reserva quedó.
Quitaron la reserva tras confirmar que ya no era necesaria. El espacio libre del pool se recuperó al instante. No hubo purgas de instantáneas, ni eliminaciones riesgosas, ni drama. La corrección fue literalmente un cambio de propiedad y una nota en el runbook.
El comentario del on-call parafraseable fue para enmarcar: “No arreglamos almacenamiento; arreglamos contabilidad.” Eso es lo que son la mayoría de los incidentes de espacio en ZFS.
Guía de diagnóstico rápido
Este es el flujo de triaje cuando alguien dice “nos quedamos sin espacio” o “los números de ZFS no cuadran”. Ejecútalo en orden; está diseñado para encontrar el cuello de botella rápido, no para saciar la curiosidad.
Primero: ¿el pool está realmente ajustado?
cr0x@server:~$ zpool list -o name,size,alloc,free,capacity,frag,health
NAME SIZE ALLOC FREE CAPACITY FRAG HEALTH
tank 7.25T 6.70T 550G 92% 48% ONLINE
Decisión: Si la capacidad supera ~80–85% en muchos pools (y especialmente por encima de 90%), asume riesgo de rendimiento y de asignación. No debatas aún los números por dataset; estabiliza el pool.
Segundo: ¿qué datasets consumen más espacio físico?
cr0x@server:~$ zfs list -o name,used,avail,logicalused,compressratio -S used | head -n 15
Decisión: Enfócate en used para alivio inmediato, no en logicalused. El pool solo puede asignar físico.
Tercero: ¿el espacio está clavado por instantáneas/clones?
cr0x@server:~$ zfs list -o name,used,usedbysnapshots,usedbydataset,usedbychildren -S usedbysnapshots | head -n 15
cr0x@server:~$ zfs list -t snapshot -o name,used -s used | tail -n 20
Decisión: Si usedbysnapshots es grande, mira la retención/cadencia de instantáneas y los clones. La destrucción de instantáneas suele ser la palanca de recuperación más segura—tras confirmar dependencias.
Cuarto: ¿las reservas hacen que “free” parezca menor de lo que es?
cr0x@server:~$ zfs list -o name,usedbyrefreservation,refreservation -S usedbyrefreservation | head -n 15
Decisión: Si las reservas dominan, no estás sin disco; estás sin disco no prometido. Eso es una discusión de políticas y a menudo una solución rápida.
Quinto: ¿la compresión está ocultando riesgo de crecimiento?
cr0x@server:~$ zfs get -o name,property,value -H compressratio,compression tank | head
Decisión: Si tu plan depende de que la compresión se mantenga alta, asume que puede bajar en cuanto la carga cambie (cifrado, medios ya comprimidos, cambios en VMs). Añade margen.
Errores comunes (síntomas y soluciones)
Error 1: Tratar logicalused como consumo físico
Síntoma: Pánico de “dataset más grande que el pool”, o reparto interno que factura equipos por terabytes que no costaron realmente.
Solución: Usa used (físico) para capacidad y coste. Usa logicalused para huella de aplicación y tendencias de crecimiento. Cuando haya duda, muestra ambos, más compressratio.
Error 2: Borrar archivos para recuperar espacio cuando existen instantáneas
Síntoma: du baja, el espacio libre del pool no. Los usuarios juran que borraron “centenares de gigabytes”. Lo hicieron. Las instantáneas lo mantuvieron.
Solución: Comprueba usedbysnapshots. Lista instantáneas por used. Confirma clones. Destruye instantáneas según la política de retención tras validar requisitos de restauración.
Error 3: Olvidar refreservations
Síntoma: “Free” del pool es bajo pero los datasets no parecen grandes. usedbyrefreservation es significativo. Nuevas asignaciones fallan antes de lo esperado.
Solución: Inventaría refreservation/reservation y valida cada una. Elimina o reajusta. Documenta por qué existe.
Error 4: Ignorar clones al limpiar instantáneas
Síntoma: zfs destroy falla por clones, o la eliminación de instantáneas tiene éxito pero libera menos de lo esperado.
Solución: Comprueba la propiedad clones en las instantáneas. Decide si los clones siguen siendo necesarios; si lo son, acepta el espacio clavado o migra los datos del clon a otro sitio.
Error 5: Malinterpretar refer vs used
Síntoma: Alguien dice “refer del dataset es pequeño, así que es pequeño”, mientras used es enorme por hijos/instantáneas/reservas.
Solución: Usa zfs list -o usedby* y decide si el coste está en el propio dataset, en sus instantáneas, en sus hijos o en reservas.
Error 6: Operar pools demasiado llenos por “ZFS tiene instantáneas y compresión”
Síntoma: Degradación de rendimiento, asignaciones erráticas, tiempos de scrub/resilver alargados, y luego un pequeño pico causa ENOSPC.
Solución: Mantén margen. Crea alertas en base a la capacidad del pool, no solo a avail del dataset. Trata 90% como umbral de emergencia para la mayoría de pools en producción.
Error 7: Planificación de capacidad basada en una semana de compressratio
Síntoma: El pool “se llena repentinamente” tras un cambio de carga (cifrado, nuevos tipos de datos), pese a crecimiento lógico estable.
Solución: Rastrea crecimiento lógico y físico a lo largo del tiempo. Asume que la compresión puede retroceder. Usa ratios conservadores para previsiones.
Listas de verificación / plan paso a paso
Lista para disputa de espacio (terminar discusiones, no amistades)
- Captura
zpool listpara la verdad a nivel pool: capacidad, libre, fragmentación. - Captura
zfs list -o used,logicalused,compressratiopara los datasets principales ordenados porused. - Para los 3 principales datasets, captura
zfs list -o usedbydataset,usedbysnapshots,usedbychildren,usedbyrefreservation. - Lista instantáneas del principal infractor ordenadas por
used. - Comprueba clones en cualquier instantánea de alto
used. - Revisa reservas/cuotas:
reservation,refreservation,quota,refquota. - Decide acción: destruir instantáneas, quitar reservas, eliminar datasets o ampliar el pool.
- Tras cambios, vuelve a capturar los mismos comandos y adjunta al ticket para cerrarlo.
Plan de recuperación de emergencia (cuando estás por encima del 90%)
- Congela churn no esencial: pausa grandes ejecuciones CI, deshabilita restauraciones pesadas de pruebas, difiere jobs por lotes.
- Destruye primero las instantáneas de mayor impacto (tras confirmar que no hay clones y requisitos de restauración).
- Quita reservas accidentales y cuotas obsoletas que estén bloqueando escrituras.
- Si debes borrar datos, apunta a datasets con alto
usedbydataset(más exclusivo) en lugar de los dominados por uso de instantáneas. - Una vez estable, ajusta retención/cadencia de instantáneas para igualar el churn y planifica expansión con margen.
Plan de informes de capacidad (evitar guerras de facturación)
- Reporta ambos, físico y lógico:
usedylogicalused. - Incluye
compressratioy desgloses de instantáneas (usedbysnapshots). - Para chargeback, factura por
usedfísico, pero muestra lo lógico como “señal de demanda”. - Revisa reservas trimestralmente; trátalas como contratos con un responsable.
Preguntas frecuentes
1) ¿Qué número debo usar para planificación de capacidad: used o logicalused?
Usa used para “¿se llenará el pool?” porque refleja la asignación física. Usa logicalused para “¿qué tan grande es la huella de la aplicación?” y para predecir lo dolorosa que puede ser una regresión de compresión.
2) ¿Por qué logicalused excede el tamaño del pool?
Porque ignora la compresión y puede reflejar archivos sparse o datos que se comprimen bien. Reporta tamaño lógico, no coste en disco. Si used cabe y el pool tiene espacio libre, no es un error.
3) Borré 500 GB y no se liberó nada. ¿Qué pasó?
Probablemente instantáneas (o clones) siguen referenciando los bloques borrados. Comprueba usedbysnapshots, lista instantáneas ordenadas por used, y comprueba la propiedad clones en las instantáneas antes de borrarlas.
4) ¿Destruir una instantánea siempre libera su cantidad de used?
No siempre. El used de una instantánea es una estimación del espacio único sostenido por esa instantánea, pero referencias compartidas y clones pueden cambiar lo que se libera y cómo se desplaza la contabilidad a otras instantáneas.
5) ¿Cuál es la diferencia entre refer y used?
refer es la cantidad de datos accesibles a través del dataset (aprox. “lo que ves”). used incluye espacio atribuible a instantáneas, hijos y reservas según el contexto. En caso de duda, usa el desglose usedby*.
6) ¿Por qué avail de un dataset es diferente del espacio libre del pool?
avail del dataset está limitado por cuotas/reservas y límites del padre. El espacio libre del pool es físico. Además, con alto llenado del pool, el espacio efectivo asignable puede ser menor que el “free” por fragmentación y necesidades del asignador.
7) ¿Es siempre buena una alta compressratio?
Es buena para capacidad y normalmente aceptable para rendimiento, pero puede crear riesgo de planificación si asumes que persistirá. Un cambio en la carga puede bajar la compresión rápidamente y acelerar el crecimiento físico.
8) ¿Cómo aparecen las reservas en “used” si no se escribió ningún dato?
Las reservas reducen el espacio disponible y aparecen en la contabilidad vía usedbyrefreservation (y propiedades relacionadas). Son promesas de preasignación deliberadas, no bloques de datos.
9) ¿Cuál es la forma más rápida de encontrar qué está clavando espacio?
Ejecuta zfs list -o usedbydataset,usedbysnapshots,usedbychildren,usedbyrefreservation en los datasets más grandes por used. Uno de esos ítems suele decirte dónde está atascado el espacio.
10) ¿Puedo “desfragmentar” ZFS para recuperar espacio?
La fragmentación afecta principalmente a rendimiento y eficiencia de asignación, no a la corrección de la contabilidad. La forma de “recuperar espacio” es eliminar referencias (borrar instantáneas/clones/datos) o añadir capacidad, no perseguir un botón mítico de desfragmentación.
Conclusión
logicalused y used no son verdades enfrentadas. Son dos lentes: una te dice cuán grandes son los datos en principio, la otra te dice cuánto cuestan en disco. La mayoría de las peleas en producción ocurren cuando alguien insiste en que solo puede existir una verdad.
Cuando diagnosticás capacidad, empieza por la realidad del pool (zpool list), luego encuentra quién está pagando la factura física (used), después pregunta quién está clavando la historia (usedbysnapshots) y quién firmó contratos (refreservation). Haz eso consistentemente y dejarás de discutir los números de ZFS—porque finalmente los estarás leyendo.