Las instantáneas (snapshots) de ZFS son una de esas funciones que parecen hacer trampa—hasta que silenciosamente se convierten en una bomba de espacio. No “ocupan espacio” al crearlas (por lo general), no rompen nada cuando las olvidas (al principio) y no piden atención hasta que el pool está al 97% y la latencia de escritura se vuelve una película de terror.
Este artículo trata la retención de instantáneas como una política operativa, no como un debate filosófico. Cubriremos cuánto cuestan realmente las instantáneas, por qué “guardarlas todas” es una trampa, cómo clones y retenciones convierten la limpieza en una escena del crimen, y cómo construir una política de retención que sobreviva a la realidad corporativa: múltiples equipos, prioridades en conflicto y la ocasional automatización con más confianza que sabiduría.
Por qué ocurren las bombas de espacio
En producción, los desbordes por instantáneas casi nunca provienen de lo que piensas. La gente culpa a “demasiadas instantáneas”, pero el número rara vez es el problema. El problema es la tasa de cambio, la duración de retención y los anclajes ocultos que impiden la eliminación: clones, retenciones (holds), dependencias de replicación y snapshots “temporales” que se volvieron permanentes por negligencia.
Una instantánea de ZFS es una referencia puntual a bloques. Es barato crearla porque es metadato y referencias—hasta que el dataset cambia. Cuando los bloques se sobrescriben o eliminan en el sistema en vivo, la instantánea todavía referencia los bloques antiguos, así que ZFS debe conservarlos. Con el tiempo, las instantáneas se convierten en un museo de bloques sobrescritos. Los museos son agradables. Los museos también necesitan edificios.
Hay dos mentiras operativas que causan la mayoría de las bombas de espacio:
- Miente #1: “Las instantáneas son gratis.” Son gratis para tomarlas, no gratis para conservarlas.
- Miente #2: “Si el dataset sólo tiene 2 TB, no puede consumir 10 TB.” Con instantáneas, absolutamente puede—porque las instantáneas preservan versiones históricas de bloques.
Un chiste corto, como limpiador de paladar: Una política de retención de instantáneas es como usar hilo dental—todos están de acuerdo en que es importante, y todos suponen que otra persona lo está haciendo.
Datos interesantes y contexto histórico
Algo de contexto ayuda porque las instantáneas ZFS no fueron diseñadas como una “función de producto de backup”. Fueron diseñadas como un primitivo de sistema de archivos con consecuencias.
- Las instantáneas ZFS son construcciones metadata copy-on-write, no copias a nivel de bloque. La “copia” ocurre después, cuando el dataset en vivo cambia.
- El ZFS original salió de Sun Microsystems a mediados de los 2000 con la idea radical de que los sistemas de archivos deberían gestionar volúmenes e integridad juntos.
- Las instantáneas en implementaciones LVM tradicionales a menudo tenían acantilados de rendimiento al llenarse; las instantáneas ZFS evitan ese mecanismo específico pero aún pueden causar fragmentación y crecimiento de metadatos.
- ZFS introdujo send/receive como primitiva de replicación de primera clase—los incrementales dependen de la genealogía de instantáneas, lo que significa que la retención interactúa con la replicación más de lo que la gente espera.
- El “espacio usado por instantáneas” no es un solo número; ZFS lo desglosa en espacio referenciado, lógico vs físico y “usado por instantáneas”, lo que confunde tanto dashboards como humanos por igual.
- Los clones son instantáneas escriturables, y pueden bloquear la eliminación de instantáneas, a menudo descubiertos sólo durante la limpieza a las 2 a.m.
- ZFS soporta holds de usuario sobre instantáneas específicamente para que la limpieza automática no pueda borrar puntos de recuperación críticos—una medida anti-peligrosa que puede convertirse en un ancla.
- Recordsize y compresión afectan el coste de retención. Los patrones de cambio en registros grandes pueden mantener vivos más bloques históricos de lo que intuimos.
- La mayoría de los pools mueren por estar demasiado llenos, no por una sola falla de disco. Alta utilización amplifica la contención de asignación y la fragmentación; las instantáneas son un acelerante frecuente.
El modelo de espacio de las instantáneas (qué cuenta realmente ZFS)
Para mantener la retención sensata, necesitas entender qué está contando ZFS—y qué no. ZFS te da varias vistas diferentes de “usado”:
Referenciado vs usado vs lógico
Referenciado significa la cantidad de datos que el dataset (o instantánea) representaría si fuera lo único en existencia. Es una medida de contenido, no de coste.
Usado significa bloques únicos atribuidos a ese dataset o instantánea en el contexto de todo lo demás. Para las instantáneas, esto puede ser engañoso: el “used” de una instantánea son los bloques mantenidos únicamente por ella, pero esos bloques pueden estar compartidos entre varias instantáneas. La vista más accionable en operaciones suele ser el desglose a nivel de dataset: usedbydataset, usedbysnapshots, usedbychildren, usedbyrefreservation.
Lógico puede exceder lo físico debido a la compresión. Eso es genial—hasta que alguien presupone capacidad con números lógicos y se sorprende por la realidad física.
Por qué eliminar archivos no libera espacio (cuando hay instantáneas)
Eliminar un archivo quita sus referencias en el dataset en vivo. Si una instantánea aún referencia los bloques antiguos, esos bloques permanecen asignados. Desde la silla del operador, parece que “rm no funciona.” Funciona. Tus instantáneas solo están acaparando.
Por qué “simplemente borrar instantáneas antiguas” a veces tampoco libera espacio
Porque hay dos anclajes más:
- Clones: si algún clone depende de una instantánea, esa instantánea no puede destruirse hasta que el clone sea promovido o destruido.
- Retenciones (holds): una instantánea puede estar retenida por un administrador o automatización y rechazará la eliminación hasta que se libere la retención.
Además, incluso cuando eliminas instantáneas, el espacio puede no aparecer inmediatamente si miras las métricas equivocadas, o si estás en una carga donde los metadatos y bloques indirectos dominan. ZFS es honesto, pero no siempre inmediatamente legible.
Segundo chiste corto (y el último, por las reglas): La contabilidad de espacio de ZFS es el único lugar donde “usado” puede significar “tal vez”, “depende” y “sí, pero no de la forma que quieres”.
Construir una política de retención que no te traicione
Una política de retención es un contrato entre tus objetivos de recuperación y la realidad de capacidad. Si no puedes decir contra qué te proteges—borrados accidentales, ransomware, despliegues malos, corrupción silenciosa, error de operador—retendrás de más hasta quedarte sin pool.
Empieza por objetivos de recuperación, no por sensaciones
Hay tres perillas para definir:
- RPO (Recovery Point Objective): cuánto dato puedes permitir perder. Esto determina la frecuencia de instantáneas (cada hora, cada 15 minutos, etc.).
- RTO (Recovery Time Objective): qué tan rápido necesitas recuperar. Esto influye en cuántas instantáneas conservas localmente para devoluciones rápidas.
- Horizonte histórico: hasta qué punto necesitas retroceder por errores de evolución lenta (configuración mala, deriva de datos). Esto impulsa instantáneas diarias/semanales/mensuales y la retención fuera de sitio.
Una política de inicio práctica para muchos workloads mixtos podría ser:
- Cada 15 minutos: conservar 24 horas
- Por hora: conservar 7 días
- Diaria: conservar 30 días
- Semanal: conservar 12 semanas
- Mensual: conservar 12 meses (a menudo sólo fuera de sitio)
Esto no es una plantilla universal; es un punto de partida para la conversación que fuerza los trade-offs a la luz.
Planificación de capacidad: reserva margen para instantáneas
En producción, “pool al 80%” no es una vibra; es un límite. Por encima de ~80–85% (dependiendo de recordsize, ashift, fragmentación, workload), la asignación se vuelve más difícil y el rendimiento extraño. Las instantáneas facilitan la deriva hacia arriba porque son invisibles hasta que no lo son.
En lugar de preguntar “¿Cuántas instantáneas podemos mantener?”, pregunta:
- ¿Cuál es nuestro churn diario (cuánto dato cambia por día)?
- ¿Cuánto tiempo retenemos instantáneas de alta frecuencia?
- ¿Cuánto de ese churn debe permanecer local vs replicado/fuera de sitio?
Si un dataset tiene 2 TB de datos activos pero churnea 300 GB/día (bases de datos, artefactos de CI, imágenes de VM), entonces “conservar 30 instantáneas diarias” no es “conservar 2 TB más un poco.” Es potencialmente “conservar hasta ~9 TB de bloques históricos sobrescritos,” menos efectos de compresión/dedupe. Esa es la aritmética que los operadores deberían presentar a la dirección antes de que pongan una nueva iniciativa en el mismo pool.
Retención por niveles: rollback rápido local vs historial largo remoto
Conservar historial profundo localmente es caro y a menudo innecesario. Usa instantáneas locales para ventanas de rollback rápidas (horas a días) y usa objetivos de replicación (otro pool, otro sitio) para historial más largo donde la capacidad y las presiones de rendimiento son diferentes.
Dos cautelas:
- La replicación incremental depende de cadenas de instantáneas. Si eliminas una instantánea que la transmisión incremental remota espera, puedes forzar un reenvío completo—doloroso en ancho de banda y tiempo.
- Los objetivos de replicación tienen su propia historia de retención. “Replicamos todo” no es una política de retención; es una forma de reproducir tus errores en otro sitio.
Límites por dataset: no instantanees el cajón de trastos
Si haces instantáneas de un dataset que contiene tanto “config crítica” como “cache regenerable”, tus costes de retención serán dominados por el churn de la cache. Separa datasets según líneas de retención y churn:
- Separa bases de datos de logs y archivos temporales.
- Separa imágenes de VM de caches de ISO y artefactos de build.
- Separa directorios home de carpetas de descargas gigantes (sí, eso existe).
Como SRE, he visto fallar la retención porque la política era correcta pero aplicada al límite de dataset equivocado. El sistema de archivos estaba estructurado como un cajón de trastos, y las instantáneas hicieron lo que se les dijo: preservar la historia de todo, incluidas las basuras.
Nombres, etiquetas y capacidad de descubrimiento
La retención de instantáneas es en parte psicología. Si nadie puede decir para qué sirve una instantánea, nadie la borrará. Si nadie puede decir qué instantáneas son seguras, la limpieza se vuelve una negociación política.
Usa un esquema de nombres que codifique la intención
Un esquema viable incluye:
- Marca de tiempo en formato ordenable (UTC es tu amigo)
- Clase de frecuencia (15m, hourly, daily, weekly)
- Creator o sistema (cron, backup, operator)
- Referencia opcional a ticket/cambio para snapshots manuales
Patrones de ejemplo (elige uno y cúmplelo):
pool/app@auto-2025-12-25T1200Z-hourlypool/app@manual-INC12345-2025-12-25T1200Z
Las retenciones no son un cubo de basura
Las retenciones (holds) existen para prevenir la eliminación. Eso es útil cuando un incidente está en curso o una investigación necesita un estado congelado. No es un mecanismo de retención. Las retenciones deberían tener:
- Una cadena de motivo que incluya quién/por qué
- Un proceso de expiración (revisar retenciones semanalmente)
- Un propietario documentado
Clones: trátalos como recursos de producción
Los clones son brillantes para entornos de prueba rápidos y refrescos de BD. También son la razón número uno por la que “destruir instantáneas antiguas” falla durante una limpieza de emergencia. Si permites clonación ad-hoc, debes inventariar clones y o bien:
- Promover clones para que ya no dependan de la cadena original de instantáneas, o
- Restringir la clonación a pipelines controlados con expiración
Patrones de automatización (y lo que rompen)
La automatización es la única forma en que la retención funciona a escala. También es cómo accidentalmente destruyes tu mejor punto de recuperación o mantienes instantáneas para siempre porque no se manejó un código de salida.
Dos modos de automatización: “basado en cuenta” vs “basado en tiempo”
Basado en cuenta significa “mantener las últimas N.” Es simple pero peligroso: si las instantáneas se detienen por una semana, podrías mantener una semana con huecos y borrar tu último buen punto conocido porque está “antiguo”.
Basado en tiempo significa “conservar todo más reciente que X.” Se alinea con las expectativas humanas y el lenguaje RPO/RTO. Es algo más difícil de implementar correctamente cuando tienes múltiples frecuencias.
Usa políticas jerárquicas, no una regla gigante
La retención funciona mejor en capas:
- Instantáneas de alta frecuencia, retención corta (rollback rápido)
- Instantáneas de baja frecuencia, retención media
- Instantáneas de archivo, retención larga (a menudo remota)
Ensayos en seco y rieles de seguridad
En producción, la limpieza debería soportar:
- Listado en modo dry-run de candidatas
- Eliminación en lotes acotados (para evitar largas pausas de txg y pánico)
- Registro de acciones y motivos
- Negativa a operar si el pool está degradado (no quieres añadir estrés)
Tres mini-historias del mundo corporativo
1) Incidente causado por una suposición errónea: “Las instantáneas no cuentan”
La empresa tenía un servicio NFS respaldado por ZFS usado por una docena de equipos internos. El panel de almacenamiento mostraba el dataset primario en un tamaño razonable, y el pool había estado bien durante meses. Entonces, durante un fin de semana largo, un job por lotes reescribió datos—mismo tamaño total, bloques diferentes. El martes por la mañana, el pool estaba al 98% y la latencia de NFS parecía un sismógrafo.
El on-call hizo el baile normal de limpieza: limpiar archivos de log viejos, eliminar exports temporales, incluso borrar algunos directorios grandes “obvios”. El espacio no cedió. En ese punto la historia suele convertirse en señalamiento de dedos: “ZFS miente”, “el monitor está mal”, “alguien montó el pool equivocado”. Ninguno era cierto.
El culpable real fue una política de retención que existía solo en una página wiki. Se tomaban instantáneas por hora y nunca se destruían porque el job de limpieza falló silenciosamente tras una pequeña actualización de SO que cambió el formato de salida de un comando. La suposición errónea fue que “las instantáneas son metadata y no importan.” Importaban—porque el churn del job por lotes estaba siendo preservado cada hora durante meses.
La recuperación fue complicada pero didáctica. Identificaron qué datasets tenían mayor usedbysnapshots, pausaron el job ruidoso y eliminaron instantáneas en lotes mientras vigilaban la utilización del pool y la latencia. También añadieron monitorización sobre el recuento de instantáneas y el espacio usado por instantáneas, además de una alerta cuando el job de retención falla. El cambio más valioso, sin embargo, fue cultural: la retención de instantáneas pasó a ser una configuración controlada por cambios, no un “probablemente está corriendo” dejado al azar.
2) Optimización que salió mal: “Hagamos snapshots cada 5 minutos”
Un equipo de plataforma quería rollback casi instantáneo para una flota de agentes de build y entornos de prueba. Alguien propuso: “Tomemos instantáneas cada cinco minutos y guárdelas por dos semanas.” En una presentación se veía increíble: restauraciones rápidas, bajo esfuerzo de ingeniería, riesgo mínimo. Se ignoró con educación el hecho de que los agentes de build generan y eliminan enormes cantidades de datos.
Funcionó—por poco tiempo. Las restauraciones fueron rápidas y los desarrolladores felices. Luego el pool comenzó a fragmentarse. La asignación se volvió más pesada, las escrituras síncronas se ralentizaron y la sobrecarga de metadatos creció. El recuento de instantáneas creció a miles por dataset, y listar instantáneas se volvió tan lento que su automatización fallaba por timeout intermitentemente. La “optimización” se convirtió en auto-sabotaje.
El fallo no fue porque las instantáneas sean malas. Fue porque instantáneas de alta frecuencia en datos de alto churn y bajo valor son un pésimo trade-off. El equipo finalmente separó el dataset: configuración crítica y estado pequeño recibieron instantáneas agresivas, mientras que el workspace de build pasó a un dataset con retención mínima (o ninguna), además de un almacén de artefactos separado con una política de ciclo de vida real. El rendimiento se recuperó, las operaciones de snapshot volvieron a ser fiables y la capacidad de rollback se mantuvo para los datos que realmente la merecían.
La lección: la frecuencia de instantáneas no es una medalla de seriedad. Es una función de coste. Trátala como tal.
3) Una práctica aburrida pero correcta que salvó el día: “Simulacros trimestrales y disciplina de retenciones”
En otra organización, el equipo de almacenamiento no era llamativo. Tenían una revisión de políticas programada cada trimestre. Probaban restauraciones desde instantáneas y desde objetivos replicados. Mantenían una lista pequeña de “instantáneas doradas” usadas para auditorías y lanzamientos, y controlaban las retenciones como un permiso de estacionamiento: necesitas un motivo, un propietario y expira a menos que se renueve.
Entonces llegó un despliegue malo y corrompió un dataset de manera sutil—no destrucción total, más bien “todo parece bien hasta que corre el job de facturación”. El equipo de aplicación quiso revertir, pero el incidente se descubrió días después. Aquí es donde las políticas ad-hoc suelen fallar: las instantáneas “útiles” ya se fueron y las restantes son demasiado recientes.
Pero la práctica aburrida rindió frutos. El equipo de almacenamiento tenía instantáneas diarias por 30 días localmente, y mensuales retenidas por un año en el objetivo de replicación. Encontraron una instantánea diaria limpia de antes de la ventana de corrupción, la validaron en un entorno clonado y restauraron con mínimo drama. El negocio nunca conoció los detalles, y así sabes que la operación se hizo bien.
La conclusión no es “guarda todo.” Es “guarda lo que tu negocio realmente necesita y demuestra que puedes restaurarlo.” Las instantáneas que no se han restaurado son activos teóricos. En incidentes, la teoría es cara.
Tareas prácticas: comandos e interpretación
A continuación hay tareas prácticas que puedes ejecutar en un sistema ZFS. Los comandos se muestran con un formato de prompt consistente; ajusta nombres de pool/dataset para tu entorno.
Tarea 1: Obtener una vista de alto nivel de la salud y capacidad del pool
cr0x@server:~$ zpool status -v
pool: tank
state: ONLINE
scan: scrub repaired 0B in 02:31:44 with 0 errors on Sun Dec 22 02:31:45 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
errors: No known data errors
Interpretación: Si el pool está degradado, retrasa eliminaciones agresivas de instantáneas o reordenamientos de replicación; no quieres añadir carga. También comprueba la recencia del scrub—scrubs antiguos más alta utilización es un cóctel de riesgo.
Tarea 2: Ver espacio del pool y señales de fragmentación
cr0x@server:~$ zpool list -o name,size,alloc,free,cap,health
NAME SIZE ALLOC FREE CAP HEALTH
tank 36.2T 29.8T 6.4T 82% ONLINE
Interpretación: En ~80% de capacidad, empieza a prestar atención. Si estás por encima de 85–90%, tu ventana de limpieza de instantáneas ya es una zona de riesgo en producción.
Tarea 3: Mostrar desglose de espacio del dataset incluyendo instantáneas
cr0x@server:~$ zfs list -o name,used,available,usedbydataset,usedbysnapshots,usedbychildren,mountpoint tank/app
NAME USED AVAIL USEDBYDATASET USEDBYSNAPSHOTS USEDBYCHILDREN MOUNTPOINT
tank/app 8.2T 5.9T 2.1T 5.7T 420G /tank/app
Interpretación: Esta es la firma clásica de “bomba de espacio”: el dataset solo usa 2.1T, las instantáneas están reteniendo 5.7T. Borrar archivos no ayudará hasta que se poden las instantáneas.
Tarea 4: Listar instantáneas con used y refer
cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -s creation tank/app | tail -n 6
tank/app@auto-2025-12-24T1800Z-hourly 12.3G 2.1T Wed Dec 24 18:00 2025
tank/app@auto-2025-12-24T1900Z-hourly 10.9G 2.1T Wed Dec 24 19:00 2025
tank/app@auto-2025-12-24T2000Z-hourly 11.7G 2.1T Wed Dec 24 20:00 2025
tank/app@auto-2025-12-24T2100Z-hourly 14.2G 2.1T Wed Dec 24 21:00 2025
tank/app@auto-2025-12-24T2200Z-hourly 13.8G 2.1T Wed Dec 24 22:00 2025
tank/app@auto-2025-12-24T2300Z-hourly 15.1G 2.1T Wed Dec 24 23:00 2025
Interpretación: used aquí es espacio incremental único. Si estos valores son grandes y consistentes, tu churn es alto. Si hacen picos, busca reescrituras por lotes, compactaciones o rotaciones de logs que reescriben archivos grandes.
Tarea 5: Encontrar los peores datasets por sobrecarga de instantáneas
cr0x@server:~$ zfs list -r -o name,usedbydataset,usedbysnapshots -s usedbysnapshots tank | head -n 10
NAME USEDBYDATASET USEDBYSNAPSHOTS
tank 128K 0B
tank/home 640G 120G
tank/vm 3.1T 2.8T
tank/app 2.1T 5.7T
tank/app/db 1.4T 3.9T
tank/app/logs 180G 1.1T
tank/ci 900G 4.4T
tank/ci/workspace 700G 4.2T
tank/backup 1.9T 900G
Interpretación: Los villanos suelen ser obvios: workspaces de CI, logs, imágenes de VM. La solución rara vez es “borrar instantáneas a ciegas.” Es “dejar de hacer instantáneas de basura volátil o reducir su retención.”
Tarea 6: Comprobar retenciones que bloquean la eliminación
cr0x@server:~$ zfs holds tank/app@auto-2025-12-01T0000Z-daily
NAME TAG TIMESTAMP
tank/app@auto-2025-12-01T0000Z-daily audit-freeze Thu Dec 4 09:12 2025
Interpretación: Esta instantánea no se eliminará hasta que se libere la retención. La etiqueta te dice quién/por qué—si tu proceso es lo suficientemente maduro como para requerir etiquetas significativas.
Tarea 7: Liberar una retención (con cuidado)
cr0x@server:~$ sudo zfs release audit-freeze tank/app@auto-2025-12-01T0000Z-daily
Interpretación: Liberar retenciones debe auditarse. Si lo haces ad-hoc durante un incidente de espacio, anota qué liberaste y por qué. Tu yo futuro agradecerá esa pista.
Tarea 8: Descubrir clones que impiden la destrucción de instantáneas
cr0x@server:~$ zfs get -H -o name,value clones tank/app@auto-2025-11-15T0000Z-daily
tank/app@auto-2025-11-15T0000Z-daily tank/dev/app-test
Interpretación: Esa instantánea tiene un clone dependiente. No puedes destruir la instantánea hasta manejar el clone.
Tarea 9: Promover un clone para eliminar dependencia en la instantánea origen
cr0x@server:~$ sudo zfs promote tank/dev/app-test
Interpretación: La promoción cambia la genealogía: el clone se convierte en primario y el origen pasa a depender. Puede ser correcto cuando un entorno dev accidentalmente se volvió de larga vida y necesitas liberar la cadena de instantáneas vieja. Hazlo intencionalmente; no es un cambio cosmético.
Tarea 10: Eliminar instantáneas de forma segura en un lote acotado
cr0x@server:~$ zfs list -t snapshot -o name -s creation tank/app | head -n 5
NAME
tank/app@auto-2025-10-01T0000Z-daily
tank/app@auto-2025-10-02T0000Z-daily
tank/app@auto-2025-10-03T0000Z-daily
tank/app@auto-2025-10-04T0000Z-daily
cr0x@server:~$ sudo zfs destroy tank/app@auto-2025-10-01T0000Z-daily
cr0x@server:~$ sudo zfs destroy tank/app@auto-2025-10-02T0000Z-daily
Interpretación: En un incidente de pool lleno, eliminar miles de instantáneas de una vez puede producir operaciones de larga duración y poner nerviosa a la gente. Haz lotes, observa el impacto y evita empeorar la latencia mientras intentas recuperar espacio.
Tarea 11: Eliminar un rango con nombres de instantáneas (cuando corresponda)
cr0x@server:~$ sudo zfs destroy -n tank/app@auto-2025-10-01T0000Z-daily%auto-2025-10-31T0000Z-daily
would destroy tank/app@auto-2025-10-01T0000Z-daily
would destroy tank/app@auto-2025-10-02T0000Z-daily
...
would destroy tank/app@auto-2025-10-31T0000Z-daily
cr0x@server:~$ sudo zfs destroy tank/app@auto-2025-10-01T0000Z-daily%auto-2025-10-31T0000Z-daily
Interpretación: Usa -n primero. La eliminación por rango es poderosa y peligrosa; es cómo limpias correctamente en minutos o destruyes tu ventana de recuperación en segundos.
Tarea 12: Medir churn con bytes escritos (aproximación)
cr0x@server:~$ zfs get -o name,property,value -s local,received,default written tank/app
NAME PROPERTY VALUE
tank/app written 14.8T
Interpretación: written es una pista útil de cuánto dato se ha escrito en el dataset (no exactamente “churn”, pero correlacionado). Si se dispara, tus costes de retención seguirán la misma tendencia.
Tarea 13: Comprobar cuotas y reservas que hacen que el espacio parezca “desaparecido”
cr0x@server:~$ zfs get -o name,property,value quota,refquota,reservation,refreservation tank/app
NAME PROPERTY VALUE
tank/app quota none
tank/app refquota none
tank/app reservation none
tank/app refreservation 500G
Interpretación: Un refreservation puede reservar espacio incluso cuando intentas recuperar. No es malo; es cómo garantizas espacio para un dataset. Pero durante un incidente, puede sorprenderte.
Tarea 14: Ver qué instantáneas están referenciadas por bookmarks o lógica de replicación (verificaciones de saneamiento)
cr0x@server:~$ zfs list -t bookmark -o name,creation -s creation tank/app
NAME CREATION
tank/app#replica-2025-12-20T0000Z Sat Dec 20 00:00 2025
tank/app#replica-2025-12-21T0000Z Sun Dec 21 00:00 2025
Interpretación: Los bookmarks pueden usarse para anclar replicación incremental sin mantener una instantánea completa en el emisor. Si los usas, intégralos deliberadamente en la historia de retención—no te tropieces con ellos durante una limpieza.
Tarea 15: Validar que la eliminación de instantáneas realmente redujo usedbysnapshots
cr0x@server:~$ zfs list -o name,usedbydataset,usedbysnapshots tank/app
NAME USEDBYDATASET USEDBYSNAPSHOTS
tank/app 2.1T 5.7T
cr0x@server:~$ sudo zfs destroy tank/app@auto-2025-10-01T0000Z-daily%auto-2025-10-15T0000Z-daily
cr0x@server:~$ zfs list -o name,usedbydataset,usedbysnapshots tank/app
NAME USEDBYDATASET USEDBYSNAPSHOTS
tank/app 2.1T 4.9T
Interpretación: Bien: usedbysnapshots bajó. Si no, probablemente eliminaste instantáneas que no retenían mucho espacio único, o estás bloqueado por clones/retenciones en otro lugar, o el churn continúa.
Guía de diagnóstico rápido
Este es el playbook de “acércate a un pool estresado y encuentra el cuello de botella rápido”. Está ordenado para tiempo-hasta-señal, no por pureza académica.
Primero: ¿El pool está simplemente demasiado lleno o no está sano?
cr0x@server:~$ zpool list -o name,cap,alloc,free,health
NAME CAP ALLOC FREE HEALTH
tank 92% 33.3T 2.9T ONLINE
cr0x@server:~$ zpool status -x
all pools are healthy
Interpretación: Si estás >90% utilizado, trata todo como urgente. El rendimiento y el comportamiento de asignación de ZFS se degradan conforme el espacio libre disminuye. Si el pool está degradado, evita operaciones disruptivas grandes y céntrate en reducción de riesgo rápida.
Segundo: ¿Quién está consumiendo espacio—dataset, instantáneas, hijos, reservas?
cr0x@server:~$ zfs list -o name,used,available,usedbydataset,usedbysnapshots,usedbychildren,usedbyrefreservation -r tank | head -n 20
NAME USED AVAIL USEDBYDATASET USEDBYSNAPSHOTS USEDBYCHILDREN USEDBYREFRESERVATION
tank 29.8T 6.4T 128K 0B 29.8T 0B
tank/app 8.2T 5.9T 2.1T 5.7T 420G 0B
tank/ci 5.5T 5.9T 900G 4.4T 200G 0B
tank/vm 5.9T 5.9T 3.1T 2.8T 0B 0B
Interpretación: Decide dónde actuar. Si usedbysnapshots domina, podar ayuda. Si usedbydataset domina, necesitas borrado real o migración. Si usedbyrefreservation es grande, revisa reservas.
Tercero: ¿Qué impide la eliminación de instantáneas?
Comprueba retenciones y clones para cualquier instantánea que pretendas borrar.
cr0x@server:~$ zfs holds tank/ci@auto-2025-11-01T0000Z-daily
no datasets available
cr0x@server:~$ zfs get -H -o value clones tank/ci@auto-2025-11-01T0000Z-daily
-
Interpretación: Si hay retenciones o clones, tu plan de limpieza debe incluir liberar retenciones o promover/destruir clones. Si no, perderás tiempo “borrando” instantáneas que no pueden borrarse.
Cuarto: ¿El churn sigue en curso?
Si estás podando mientras un workload está reescribiendo terabytes, estás tapando un barco con un agujero. Pausa el job churny si es posible, o reduce temporalmente la carga de escritura.
cr0x@server:~$ zfs get -o name,property,value written tank/ci/workspace
NAME PROPERTY VALUE
tank/ci/workspace written 92.4T
Interpretación: Valores altos de written no prueban churn actual, pero son una pista de que este dataset es una máquina de churn y no debería tener retención profunda de alta frecuencia.
Quinto: Si la queja es latencia, confirma la presión de I/O por separado
Los incidentes de espacio en ZFS a menudo aparecen como incidentes de latencia. No asumas que es “sólo la red” o “sólo la app.” Confirma que el pool está bajo estrés I/O antes de hacer cambios que lo aumenten.
cr0x@server:~$ zpool iostat -v 5 3
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 29.8T 6.4T 88 2100 8.2M 310M
raidz2-0 29.8T 6.4T 88 2100 8.2M 310M
sda - - 22 520 2.0M 78M
sdb - - 23 530 2.1M 79M
sdc - - 21 520 2.0M 76M
sdd - - 22 530 2.1M 77M
-------------------------- ----- ----- ----- ----- ----- -----
Interpretación: Si el pool está saturado, la eliminación de instantáneas y otras operaciones pesadas de metadatos pueden empeorar la latencia cola. Haz operaciones en lotes y programa la limpieza en horas de baja carga cuando sea posible—a menos que ya estés dentro del radio del desastre.
Errores comunes, síntomas, soluciones
Error 1: “Lo guardaremos todo, el almacenamiento es barato”
Síntomas: La utilización del pool sube constantemente a pesar de “sin crecimiento” en datos visibles; la limpieza se vuelve trabajo de emergencia; las restauraciones se vuelven más lentas porque el sistema siempre está cerca del lleno.
Solución: Define objetivos de recuperación y limita la retención local. Mueve historial largo a un objetivo de replicación separado con su propio plan de capacidad.
Error 2: Hacer instantáneas de datasets de alto churn (CI, logs, caches) con la misma política que bases de datos
Síntomas: usedbysnapshots eclipsa a usedbydataset; miles de instantáneas; fragmentación creciente y latencia de escritura en aumento.
Solución: Separa datasets por clase de churn. Aplica instantáneas agresivas solo a estado de alto valor y bajo churn. Para datos churny, conserva retención corta o ninguna; confía en políticas de ciclo de vida de artefactos a un nivel superior.
Error 3: Ignorar retenciones hasta que se vuelven permanentes
Síntomas: El job de retención “tiene éxito” pero el recuento de instantáneas nunca baja; zfs destroy da errores; los operadores descubren “retenciones misteriosas” durante un incidente.
Solución: Disciplina operativa: las retenciones requieren propietario/motivo/expiración. Ejecuta un informe semanal de instantáneas retenidas y revísalas.
Error 4: Permitir clones sin propiedad del ciclo de vida
Síntomas: La eliminación de instantáneas falla por clones dependientes; entornos dev/test viejos impiden limpieza; el equipo de almacenamiento se convierte en el propietario reacio de clones abandonados.
Solución: Rastrea clones como recursos de primera clase. Impone expiración o exige promoción con propiedad explícita antes de que un clone pueda vivir más allá de una ventana corta.
Error 5: Usar “mantener las últimas N” sin proteger contra huecos
Síntomas: Tras una caída en la creación de instantáneas, la limpieza borra instantáneas más antiguas y deja solo las nuevas—destruyendo la capacidad de revertir más allá de la ventana de la caída.
Solución: Prefiere retención basada en tiempo. Si usas basada en cuenta, implementa “edad mínima para borrar” y salvaguardas de “ventana mínima de historial”.
Error 6: Borrar instantáneas en una enorme operación durante carga pico
Síntomas: Latencia aumentada; zfs destroy de larga duración; timeouts de aplicaciones; operadores entran en pánico y abortan a medias.
Solución: Borra en lotes, mide el impacto y prioriza las instantáneas que retienen más espacio único. Programa borrados masivos en horas de baja carga cuando sea posible.
Error 7: No monitorizar fallos de la automatización de retención
Síntomas: Todo parece bien hasta que no lo está; los recuentos de instantáneas suben silenciosamente; scripts de limpieza fallan tras cambios en SO/herramientas.
Solución: Alerta sobre “último éxito del job de retención” y sobre recuentos/espacio de instantáneas que excedan umbrales. Trata la retención como un servicio de producción.
Listas de verificación / plan paso a paso
Paso a paso: Diseñar una política de retención que encaje con la realidad
- Clasifica datasets por valor de negocio y churn: estado crítico, estado importante, regenerable, caches/logs.
- Define RPO/RTO por clase (no por punto de montaje del sistema de archivos).
- Elige frecuencias de instantáneas que casen con el RPO: p. ej., 15m para estado crítico, hourly/daily para menos crítico.
- Configura ventanas de retención local con margen: guarda menos localmente de lo que emocionalmente quieres, más remotamente de lo que actualmente haces.
- Planifica capacidad usando estimaciones de churn: presupuestar explícitamente margen para instantáneas (revisar trimestralmente).
- Define convenciones de nombres y haz que la automatización las imponga.
- Define la política de retenciones: motivos permitidos, etiquetas requeridas, expiración, reportes.
- Define la política de clones: quién puede crear, dónde, por cuánto tiempo y qué pasa al expirar.
- Automatiza creación y poda de instantáneas con dry-run y registros.
- Prueba restauraciones trimestralmente: tanto rollback simple como workflow de recuperación completo.
Paso a paso: Limpieza de emergencia cuando el pool está casi lleno
- Detén la hemorragia: pausa jobs de alto churn, pausa CI descontrolada, detén tormentas de logs, deshabilita escrituras no esenciales.
- Confirma la presión:
zpool list,zfs listcon desglose de instantáneas. - Identifica a los principales ofensores: datasets con mayor
usedbysnapshots. - Comprueba bloqueadores: retenciones y clones en las instantáneas más antiguas.
- Borra en lotes comenzando por instantáneas menos probables de necesitarse (hourly antiguas antes que daily/weekly, salvo que la política diga lo contrario).
- Revisar tras cada lote: capacidad del pool, latencia y métricas de snapshot-used.
- Documenta lo que hiciste y por qué; luego arregla la automatización/política que lo permitió.
Preguntas frecuentes (FAQ)
1) ¿Las instantáneas ZFS consumen espacio inmediatamente?
Normalmente no: crear una instantánea es principalmente metadata. El coste de espacio aparece a medida que el dataset en vivo cambia y se retienen bloques antiguos.
2) ¿Por qué al borrar archivos no se libera espacio en mi sistema ZFS?
Si existen instantáneas, los bloques borrados/sobrescritos pueden seguir siendo referenciados por esas instantáneas. Liberar espacio requiere eliminar instantáneas (o mover datos a un nuevo dataset sin esas instantáneas).
3) ¿Cuál es la mejor métrica para ver el impacto de las instantáneas?
Usa zfs list con usedbydataset y usedbysnapshots. Te dice si las instantáneas son el consumidor dominante. El used a nivel de instantánea es útil para patrones de churn pero puede engañar cuando muchas instantáneas comparten bloques.
4) ¿Es seguro eliminar instantáneas?
Operativamente, sí—si entiendes qué puntos de recuperación pierdes y si no rompes expectativas de replicación. El acto técnico de borrar es seguro; la consecuencia de negocio puede ser irreversible.
5) ¿Por qué no puedo destruir una instantánea? Dice que está ocupada.
Razones comunes: tiene una retención (hold) o tiene clones dependientes. Comprueba con zfs holds y zfs get clones. Quita retenciones o maneja clones (destruir/promover) antes de reintentar.
6) ¿Debería conservar instantáneas en el mismo pool que los datos de producción?
Para ventanas de rollback cortas, sí. Para historial largo, normalmente es mejor replicar a otro pool o sistema. Un único pool es un único dominio de falla y de capacidad—las instantáneas no cambian eso.
7) ¿Cuántas instantáneas son “demasiadas”?
No hay un número universal. Demasiadas son cuando listar/gestionar instantáneas se vuelve lento, los jobs de retención hacen timeout o el espacio retenido por instantáneas se come el margen. Los datasets de alto churn llegan a “demasiadas” más rápido.
8) ¿Influyen la compresión y el recordsize en la retención de instantáneas?
Sí. La compresión cambia la huella física; recordsize y patrones de escritura influyen cuánto dato antiguo debe preservarse. Reescrituras de registros grandes pueden hacer cara la retención incluso si “el tamaño de archivo no cambió”.
9) ¿Puedo confiar en las instantáneas como mi único backup?
No si te importa la disponibilidad frente a fallos de hardware, pérdida del pool o incidentes de sitio. Las instantáneas son excelentes para rollback rápido y recuperación local; backups/replicación dan separación y supervivencia.
10) ¿Por qué al eliminar instantáneas no se redujo inmediatamente el uso del pool?
Razones comunes: eliminaste instantáneas que no retenían mucho espacio único; clones/retenciones aún anclan las partes caras; el workload sigue churneando; o miras métricas del dataset/pool equivocadas. Revisa usedbysnapshots y verifica bloqueadores.
Conclusión
Las instantáneas ZFS son un superpoder. El precio es que el tiempo se convierte en consumidor de almacenamiento. Si no pones límites al tiempo—frecuencia, retención e intención—tu pool eventualmente pagará la factura con intereses, usualmente durante una semana en la que no podías permitir drama.
La política que evita bombas de espacio no es complicada: alinea las instantáneas con objetivos de recuperación, separa datos churny, automatiza la poda con rieles de seguridad y mantén retenedores/clones con correa. El resto es disciplina operativa: monitoriza lo que importa, ensaya restauraciones y trata la retención como infraestructura de producción—no como un script esperanzado en cron.