En ZFS, “snapshot indeleble” suele significar “snapshot con una dependencia que no notaste”. ZFS es implacablemente consistente: no eliminará historial que otra cosa todavía necesita—ya sea un clone, una etiqueta hold de una tubería de backups, una política de replicación o tu propia decisión anterior de usar snapshots como papelera.
Esta es una guía práctica de campo para hacer que esos snapshots desaparezcan de forma segura. Cubriremos qué bloquea realmente la eliminación, cómo demostrarlo con comandos y cómo limpiar sin convertir un pool sano en un desastre profesional. Me apoyaré en dos verdades de ZFS que aprendes en producción: los datos siempre tienen un propietario y la factura siempre llega.
Qué significa realmente “indeleble” en ZFS
Cuando la gente dice que “no puede borrar un snapshot de ZFS”, el sistema normalmente les está diciendo una de estas cosas:
- Existe un hold sobre el snapshot, por lo que ZFS se niega a destruirlo hasta que se libere el hold.
- Un clone depende de él (un dataset escribible creado a partir de un snapshot). ZFS no borrará el snapshot porque es literalmente el origen de un sistema de archivos en vivo.
- El snapshot está “ocupado” debido a operaciones en curso (send/receive, snapshotting u otra cosa que mantenga referencias).
- La replicación, las herramientas de backup o las políticas lo siguen recreando, por lo que parece que la eliminación “no funciona”.
- Estás borrando la cosa equivocada (por ejemplo, eliminaste un snapshot en la fuente, pero el destino todavía lo tiene; o destruiste un bookmark en lugar de un snapshot; o el nombre del snapshot tiene caracteres especiales y tu shell te engañó).
Y la otra queja común—“Borré snapshots, pero el espacio no se liberó”—no es indeleblidad. Es contabilidad. El espacio en ZFS no se libera hasta que la última referencia a los bloques desaparece, y esos bloques pueden seguir referenciados por snapshots más nuevos, clones o simplemente datos todavía presentes en el sistema de archivos activo. ZFS es muchas cosas, pero no es una trituradora mágica.
Primer chiste (como prometí, solo dos en total): los snapshots de ZFS son como los recibos—fáciles de acumular, difíciles de deshacerse y solo los necesitas cuando ya tomaste una decisión terrible.
Datos interesantes y breve historia: por qué ZFS se comporta así
Un poco de contexto hace que el comportamiento se sienta menos como sabotaje y más como ingeniería:
- Los snapshots de ZFS son vistas copy-on-write. No hay sobrescritura en sitio; los snapshots mantienen referencias a versiones antiguas de bloques. Por eso son instantáneos y por eso pueden “fijar” espacio.
- “Indeleble” a menudo es una característica. Los holds fueron diseñados específicamente para evitar que la automatización borre snapshots necesarios para cumplimiento, ventanas de backup o integridad de replicación.
- Los clones son sistemas de archivos reales. Un clone no es una “copia”, es un dataset que comparte bloques con su snapshot de origen. Eliminar el origen dejaría huérfano el linaje del clone.
- ZFS fue construido para ser su propio gestor de volúmenes. Por eso puede rastrear la propiedad de bloques a un nivel que hace que las dependencias de snapshots sean aplicables—y no negociables.
- Los snapshots pueden ser “retenidos” por sistemas remotos. Con replicación, el receptor puede mantener snapshots o requerirlos como bases incrementales. Tu “borrado” en la fuente no hace que el receptor lo olvide.
- El sistema de propiedades del dataset es parte del plano de control. Propiedades como
readonly,canmountymountpointcambian el comportamiento sin tocar datos; los holds y los orígenes de clones son metadatos con poder similar. - La herencia Solaris se nota. Muchos comportamientos de ZFS (incluida la rigidez en torno a invariantes) vienen de expectativas de almacenamiento empresarial: corrección primero, conveniencia después.
- La destrucción es transaccional. Los cambios en ZFS son atómicos; cuando se niega a destruir un snapshot, está protegiendo un grafo de referencias consistente en disco.
- Los bookmarks existen por una razón. Los bookmarks son punteros ligeros al grupo de transacciones de un snapshot, usados para preservar una base incremental sin mantener todo el metadata del snapshot. La gente los confunde con snapshots y se pregunta por qué el espacio no cambia.
Guion de diagnóstico rápido (primero, segundo, tercero)
Si estás en llamada y el almacenamiento te está despertando, no divagues. Haz esto, en este orden:
1) Confirma qué es “indeleble” y por qué ZFS se opone
Intenta el destroy y lee el error exacto. ZFS suele ser explícito. “snapshot has dependent clones” y “snapshot is held” no son sutiles.
2) Busca holds y dependencias de clones inmediatamente
Los holds y los clones explican la mayoría de los “por qué no se borra”. Revisa holds con zfs holds. Revisa clones con zfs get origin (o búsqueda inversa via zfs list -t all y grep).
3) Si el problema es espacio, encuentra qué lo consume realmente
Usa usedbysnapshots, usedbydataset y usedbychildren. Si los snapshots consumen espacio, determina qué snapshots son pesados y si están fijados por clones/holds.
4) Si la eliminación “funciona” pero los snapshots vuelven, sigue al creador
Eso suele ser un cron, un timer de systemd, un appliance de backup o una herramienta de replicación que cree ser responsable de la retención. Borrar síntomas no curará la enfermedad.
Mecánica central: holds, clones, datasets ocupados y replicación
Holds: el “no” educado
Un hold es una etiqueta en un snapshot que impide su destrucción. Un snapshot puede tener múltiples holds, típicamente uno por flujo de trabajo: “backup”, “replicate”, “legal”, “before-upgrade” y el infame “temp” que se vuelve permanente.
Detalle operativo clave: no “eliminas el hold”, lo liberas por nombre. Si hay varias etiquetas hold, debes liberarlas todas (o usar patrones con -r cuidadosamente). Aquí es donde zfs release es tu amigo, y también donde te puedes hacer daño liberando un hold que un sistema de backup espera.
Clones: la dependencia silenciosa
Los clones son datasets creados a partir de un snapshot. Mantienen el snapshot vivo porque el snapshot es el origen del clone. ZFS no destruirá el snapshot de origen hasta que destruyas el clone o lo “promuevas” (haciendo independiente al clone y cambiando la dirección de dependencia).
Problema real: los clones aparecen en lugares inesperados: pipelines de CI, entornos “temporales” de desarrolladores, plantillas de virtualización, refrescos de bases de datos de pruebas. Si tienes suerte, el clone está nombrado honestamente. Si no, se llama prod2 y todos fingen que no importa.
Snapshots ocupados y bloqueos operativos
ZFS puede reportar snapshots como ocupados si están involucrados en operaciones en curso. Causas comunes:
zfs send/zfs receiveen progreso- destrucciones de snapshots de larga duración (especialmente con muchos snapshots)
- herramientas que mantienen referencias al dataset abiertas más tiempo del esperado
“Ocupado” suele ser temporal, pero en entornos desordenados puede ser un estado permanente creado por bucles de automatización.
Replicación y bases incrementales
Las canalizaciones de replicación a menudo requieren un snapshot común entre fuente y destino para enviar incrementales. Algunas herramientas lo imponen colocando holds en snapshots hasta que el destino confirme la recepción, o reteniendo ciertos snapshots como “anclas”.
Operativamente, necesitas saber si el snapshot se mantiene porque ZFS lo dice (holds/clones) o porque tu herramienta lo dice (snapshots recreados, políticas de retención o restricciones remotas).
Tareas prácticas: comandos que realmente lo resuelven (con interpretación)
Las siguientes tareas están escritas para usarlas en consola, con suficiente interpretación para mantenerte fuera de problemas. Ajusta los nombres de dataset a tu entorno.
Task 1: Listar snapshots y ordenar por impacto de espacio
cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -s used tank/data
NAME USED REFER CREATION
tank/data@autosnap_2025-12-20 84G 1.2T Sat Dec 20 03:00 2025
tank/data@autosnap_2025-12-21 91G 1.2T Sun Dec 21 03:00 2025
tank/data@autosnap_2025-12-22 12G 1.2T Mon Dec 22 03:00 2025
Interpretación: USED aquí es “único a este snapshot dado todo lo demás que existe”. Si buscas espacio, ordena por used y empieza por los mayores culpables. Si tu lista de snapshots es enorme, limita a un subtree de dataset.
Task 2: Intentar destroy y capturar el error real
cr0x@server:~$ sudo zfs destroy tank/data@autosnap_2025-12-21
cannot destroy snapshot tank/data@autosnap_2025-12-21: snapshot is held
Interpretación: No adivines. La cadena de error te dice en qué rama del árbol de decisión estás: held, tiene clones dependientes, ocupado, etc.
Task 3: Mostrar holds en un snapshot
cr0x@server:~$ sudo zfs holds tank/data@autosnap_2025-12-21
NAME TAG TIMESTAMP
tank/data@autosnap_2025-12-21 backup Tue Dec 23 01:12 2025
tank/data@autosnap_2025-12-21 replicate Tue Dec 23 01:13 2025
Interpretación: Dos sistemas diferentes (o dos fases de uno) colocaron holds. Debes liberar ambas etiquetas antes de que destroy funcione. Además: estas etiquetas son pistas—encuentra a los propietarios antes de arrancarlas.
Task 4: Liberar una sola etiqueta hold con zfs release
cr0x@server:~$ sudo zfs release backup tank/data@autosnap_2025-12-21
Interpretación: Esto elimina solo el hold backup. Si la eliminación aún falla, hay al menos otra etiqueta, o un bloqueador completamente distinto.
Task 5: Liberar múltiples holds y luego destruir
cr0x@server:~$ sudo zfs release backup tank/data@autosnap_2025-12-21
cr0x@server:~$ sudo zfs release replicate tank/data@autosnap_2025-12-21
cr0x@server:~$ sudo zfs destroy tank/data@autosnap_2025-12-21
Interpretación: Claro y explícito vence a lo ingenioso. En producción prefiero dos comandos que pueda auditar sobre uno que “debería funcionar”.
Task 6: Encontrar clones que dependen de un snapshot (búsqueda por origin)
Esta es la forma más fiable: busca datasets cuyo origin coincida con tu snapshot.
cr0x@server:~$ zfs get -H -o name,value origin -r tank | grep 'tank/data@autosnap_2025-12-20'
tank/dev-jenkins-workspace tank/data@autosnap_2025-12-20
tank/vm-templates/ubuntu tank/data@autosnap_2025-12-20
Interpretación: Esos datasets son clones (o descendientes de clones) ligados a ese snapshot. El snapshot no morirá hasta que se gestionen estos.
Task 7: Confirmar que un dataset es un clone y ver su origin
cr0x@server:~$ zfs get origin tank/dev-jenkins-workspace
NAME PROPERTY VALUE SOURCE
tank/dev-jenkins-workspace origin tank/data@autosnap_2025-12-20 -
Interpretación: Este dataset depende de ese snapshot. Tus opciones son: destruir el clone, o promoverlo (si debe permanecer).
Task 8: Destruir un clone (y sus hijos) para desbloquear la destrucción del snapshot
cr0x@server:~$ sudo zfs destroy -r tank/dev-jenkins-workspace
Interpretación: -r destruye el dataset y todos sus descendientes. Eso es correcto para workspaces de CI y datasets efímeros de desarrollo. No es correcto para algo que alguien empezó a tratar silenciosamente como producción.
Task 9: Promover un clone para eliminar la dependencia sobre el snapshot origen
cr0x@server:~$ sudo zfs promote tank/vm-templates/ubuntu
Interpretación: La promoción invierte la dependencia para que el clone se vuelva el linaje “padre”. Después de la promoción, el snapshot original puede volverse destruible (sujeto a otros clones/holds). Promover cambia relaciones de snapshot; trátalo como una solicitud de cambio, no como una solución casual.
Task 10: Identificar espacio de snapshot vs espacio del dataset (por qué no se liberó espacio)
cr0x@server:~$ zfs list -o name,used,usedbysnapshots,usedbydataset,usedbychildren -r tank/data
NAME USED USEDBYSNAPSHOTS USEDBYDATASET USEDBYCHILDREN
tank/data 3.1T 1.4T 1.5T 0.2T
Interpretación: Los snapshots representan 1.4T aquí. Si borras snapshots y este número no baja, todavía tienes snapshots (tal vez en hijos), holds/clones impidiendo la eliminación, o estás borrando los que no poseen el espacio que te importa.
Task 11: Ver qué snapshots existen en descendientes (la trampa “yo lo borré”)
cr0x@server:~$ zfs list -t snapshot -r -o name,used -s used tank/data | tail -n 10
tank/data/projects@autosnap_2025-12-21 110G
tank/data/projects@autosnap_2025-12-22 95G
tank/data/home@autosnap_2025-12-21 70G
tank/data/home@autosnap_2025-12-22 68G
Interpretación: Puede que hayas destruido el snapshot en tank/data pero el uso pesado está en tank/data/projects y tank/data/home. Los snapshots son por dataset; la recursión importa.
Task 12: Destruir un snapshot recursivamente (con cuidado)
cr0x@server:~$ sudo zfs destroy -r tank/data@autosnap_2025-12-21
Interpretación: Esto destruye el snapshot con ese nombre en el dataset y todos los descendientes. Es potente y fácil de usar mal. Asegura que las convenciones de nombres de snapshots sean consistentes y que realmente quieras recursión.
Task 13: Encontrar snapshots que están hold en todo un árbol
ZFS no proporciona un único comando “listar todos los snapshots retenidos” con detalle completo de una sola vez, así que normalmente lo scriptamos con un plumbing seguro.
cr0x@server:~$ for s in $(zfs list -H -t snapshot -o name -r tank/data); do
> zfs holds "$s" 2>/dev/null | awk 'NR==1{next} {print $1" "$2}'
> done | head
tank/data@autosnap_2025-12-20 replicate
tank/data/projects@autosnap_2025-12-20 replicate
tank/data/projects@autosnap_2025-12-20 backup
Interpretación: Esto te dice qué snapshots están protegidos y por qué etiquetas. En un entorno desordenado, los nombres de las etiquetas son la piedra rosetta para averiguar qué sistema “posee” la retención.
Task 14: Verificar si la replicación/backup está recreando snapshots
Si los snapshots “vuelven”, revisa tiempos de creación y patrones. Esto es lo menos glamuroso pero lo más efectivo: prueba la fuente de la verdad.
cr0x@server:~$ zfs list -t snapshot -o name,creation -s creation tank/data | tail -n 5
tank/data@autosnap_2025-12-25_0000 Thu Dec 25 00:00 2025
tank/data@autosnap_2025-12-25_0100 Thu Dec 25 01:00 2025
tank/data@autosnap_2025-12-25_0200 Thu Dec 25 02:00 2025
tank/data@autosnap_2025-12-25_0300 Thu Dec 25 03:00 2025
tank/data@autosnap_2025-12-25_0400 Thu Dec 25 04:00 2025
Interpretación: Cadencia horaria grita automatización. Borrar sin arreglar el programador es como achicar un barco mientras haces más agujeros.
Task 15: Comprobar un send/receive en curso que pueda mantener cosas “ocupadas”
Esto depende del SO y las herramientas, pero normalmente puedes detectar streams ZFS activos vía la lista de procesos.
cr0x@server:~$ ps aux | egrep 'zfs (send|receive)|mbuffer|ssh .*zfs receive' | grep -v egrep
root 18244 2.1 0.0 17768 4100 ? Ss 03:02 0:01 zfs send -I tank/data@autosnap_2025-12-24 tank/data@autosnap_2025-12-25_0300
root 18245 0.8 0.0 10432 2820 ? S 03:02 0:00 ssh backup-target zfs receive -uF tank/replica/data
Interpretación: Si destruyes un snapshot que actualmente es la base de un send incremental, el trabajo puede fallar o reiniciarse y volver a colocar holds. Coordina con ventanas de replicación.
Task 16: Piensa en modo dry-run antes de comandos destructivos
ZFS no tiene un --dry-run universal para destroy. Tu “dry run” es inspección: lista holds, lista clones, lista dependientes, confirma nombres y confirma alcance (-r vs no).
cr0x@server:~$ zfs holds tank/data@autosnap_2025-12-20
cr0x@server:~$ zfs get -H -o name,value origin -r tank | grep 'tank/data@autosnap_2025-12-20' || true
cr0x@server:~$ zfs list -t snapshot -r -o name tank/data | grep '@autosnap_2025-12-20' | head
Interpretación: Esta secuencia responde: “¿Está retenido?”, “¿Hay clones?” y “¿Qué tocará exactamente la recursión?” Es aburrido. Funciona.
Tres mini-historias del mundo corporativo desde las trincheras
Mini-historia 1: Un incidente causado por una suposición errónea
La suposición: “Si el snapshot es antiguo, es seguro borrarlo.” Un administrador de almacenamiento (competente, cuidadoso, solo apurado) vio un pool al 90% y empezó a podar snapshots mayores a 30 días. El comando destroy falló en un subconjunto con “dependent clones”, así que siguió y borró lo que pudo. El espacio no recuperó lo suficiente. El pánico subió. Se hicieron más borrados.
Lo que no supieron: un equipo de desarrollo tenía un sandbox analítico “temporal” clonado desde un snapshot de producción de hace un mes. Se usaba para consultas ad-hoc, y alguien apuntó un dashboard interno a él porque “era rápido”. Sin ticket. Sin documentación. Solo una dependencia silenciosa pegada al snapshot como un percebe.
El camino en on-call se puso feo porque el error no decía “esto alimenta tus dashboards”. Simplemente decía “dependent clones”. El equipo intentó promover el clone sin entender las consecuencias, lo que reordenó el linaje y rompió un script de retención que asumía que los orígenes vivían en un solo lugar. De repente los incrementales de replicación no encontraban sus bases. Los trabajos fallaron. Las alertas se multiplicaron.
Lo que lo arregló no fue heroísmo; fue la jugada adulta: inventariar los clones, identificar propietarios, programar downtime para el sandbox y destruirlo o reubicarlo como un dataset con retención explícita. La lección: “antiguo” no es una clasificación de seguridad. La dependencia sí lo es.
Mini-historia 2: Una optimización que salió mal
La meta era noble: reducir el recuento de snapshots. Un equipo de plataforma cambió su política de “snapshots horarios por 7 días” a “horarios por 24 horas, luego diarios por 30 días”. También añadieron una característica de conveniencia: crear un clone del snapshot de la noche anterior para cada desarrollador que quisiera un entorno fresco. La creación de clones fue automática y rápida. Los desarrolladores encantados.
Dos meses después, el pool empezó a crecer de forma inexplicable. Estaban borrando snapshots según el calendario; los gráficos parecían conformes. Pero usedbysnapshots se mantenía alto. El ingeniero de almacenamiento indagó y encontró docenas de clones de larga vida creados de “la noche anterior”, algunos de los cuales se volvieron semi-permanentes porque se usaban para reproducir bugs, ejecutar benchmarks o guardar datos “por si acaso”.
La optimización salió mal porque la política de retención asumía que los snapshots eran el único mecanismo de fijación. Los clones transformaron silenciosamente “historial de snapshots de corta vida” en “retención de bloques de larga vida”, y el sistema hizo exactamente lo que se le dijo: proteger los bloques de origen del clone. La solución fue poner un ciclo de vida a los clones también: expiración automática, promoción automática (cuando corresponda) y exigir nombres y propietarios.
Es una historia clásica empresarial: optimizas una métrica (recuento de snapshots) y accidentalmente monetizas otra (retención de bloques). Al almacenamiento no le importa qué hoja de cálculo usas; te cobrará en terabytes.
Mini-historia 3: Una práctica aburrida pero correcta que salvó el día
En otro entorno, la limpieza de snapshots nunca fue emocionante—y por eso funcionó. Tenían una convención escrita: cada etiqueta hold debía incluir el nombre del sistema y el propósito (p. ej., backup:daily, replicate:dr, legal:case123). Cada clone debía incluir un prefijo de propietario y una fecha de expiración en el nombre del dataset. Cada cambio de retención requería una revisión simple por pares.
Entonces llegó un susto por ransomware. El equipo de seguridad quiso conservar snapshots más antiguos mientras investigaban. Las herramientas de backup empezaron a colocar holds por todas partes. El uso de almacenamiento subió. El pool se acercó a límites incómodos. Aquí es donde brilla la “práctica aburrida”: como las etiquetas tenían significado, el equipo de almacenamiento pudo ver qué holds eran por seguridad y cuáles por replicación. Liberaron selectivamente holds después de que cerró la ventana de investigación, sin romper la replicación DR.
También tenían un informe semanal (sí, un CSV aburrido) listando clones más viejos que su expiración. Cuando ocurrió el incidente, ya sabían qué era seguro eliminar. No hubo arqueología, ni adivinanzas, ni correos a medianoche “quién posee este dataset”.
El día se salvó por algo de lo que nadie se jacta: nombres consistentes, propiedad visible y una pista de auditoría. La característica de rendimiento más subestimada en ZFS es una organización que sabe lo que le pidió a ZFS.
Listas de verificación / plan paso a paso
Checklist A: Eliminar un snapshot bloqueado por holds (de forma segura)
- Intenta un destroy para capturar el mensaje de error exacto.
- Lista holds con
zfs holds. - Identifica el propietario de cada etiqueta hold (backup, replicación, cumplimiento).
- Pausa/coordina cualquier flujo que vaya a volver a añadir el hold.
- Libera holds con
zfs release <tag> <snapshot>para cada etiqueta. - Destruye el snapshot.
- Verifica la lista de snapshots y la contabilidad de espacio.
Checklist B: Eliminar un snapshot bloqueado por clones
- Confirma el error “has dependent clones” o encuentra orígenes que referencian el snapshot.
- Enumera clones con
zfs get origin -ry empata con el snapshot. - Para cada clone: decide destruir vs promover.
- Si destruyes: usa
zfs destroy -ren el dataset clone (no en el snapshot). - Si promueves: ejecuta
zfs promotey luego vuelve a comprobar dependencias. - Destruye el snapshot original cuando las dependencias hayan desaparecido.
Checklist C: El espacio no se libera tras la eliminación de snapshots
- Revisa
usedbysnapshotsen el subtree del dataset. - Identifica snapshots pesados mediante
zfs list -t snapshot -o used. - Revisa si quedan holds y clones.
- Confirma que eliminaste snapshots en los datasets correctos (la recursión importa).
- Busca otras referencias: snapshots más nuevos, clones o el propio dataset en vivo.
- Revisa el espacio libre a nivel de pool y reservations/refreservations si aplica.
Segundo chiste (y último): La forma más rápida de reducir el número de snapshots es rm -rf /, pero también es una gran forma de reducir el número de empleados.
Errores comunes (síntomas + soluciones)
Mistake 1: Liberar holds sin coordinar con replicación/backup
Síntoma: Los snapshots se eliminan bien, luego los trabajos de replicación fallan o los backups se quejan de bases incrementales faltantes.
Solución: Identifica por qué existe el hold. Si es un ancla de replicación, completa primero el ciclo de replicación o ajusta la estrategia de replicación para usar otra base. En algunos entornos, la solución correcta es detener brevemente el servicio de replicación, limpiar y luego reiniciar con una nueva base.
Mistake 2: Destruir recursivamente cuando querías un snapshot de un solo dataset
Síntoma: Un montón de datasets pierden snapshots a la vez. Los desarrolladores preguntan por qué desapareció su “punto de restauración”.
Solución: Antes de usar -r, lista snapshots en el subtree y confirma que los nombres son consistentes. Si el entorno usa nombres mixtos, evita destrucciones recursivas y apunta datasets explícitamente.
Mistake 3: Confundir USED del snapshot con “qué tan grande es el snapshot”
Síntoma: Borras un snapshot que muestra USED=0 y esperas que el espacio regrese; nada cambia, o borras los equivocados primero.
Solución: Entiende que USED es espacio único atribuible a ese snapshot. Un snapshot con bajo USED puede seguir siendo crítico operativamente como base incremental; un snapshot con alto USED es de donde recuperarás espacio.
Mistake 4: Olvidar que existen clones (o no reconocerlos)
Síntoma: Errores “dependent clones”, o el espacio no se libera a pesar de podar snapshots.
Solución: Busca datasets con un origin apuntando al snapshot. Decide destruir vs promover. Añade reglas de ciclo de vida para clones para que esto no se repita.
Mistake 5: Eliminar snapshots que la automatización recrea
Síntoma: Destruyes snapshots y reaparecen con nuevas marcas de creación.
Solución: Encuentra y modifica el scheduler/política que los crea. La eliminación de snapshots no es una política de retención; es una acción de limpieza. La retención vive en el motor de políticas.
Mistake 6: Ignorar reservations y refreservations de datasets
Síntoma: El pool sigue pareciendo lleno incluso después de eliminar snapshots significativos, o los datasets no pueden asignar espacio a pesar de que “libre” muestra en otro lugar.
Solución: Revisa las propiedades reservation y refreservation. Las reservas pueden hacer que el espacio parezca “no disponible”. Ajusta con cuidado—las reservas suelen estar para proteger cargas críticas.
Mistake 7: Combatir snapshots “ocupados” con fuerza en vez de paciencia y coordinación
Síntoma: Destroy falla con “dataset is busy” durante ventanas de replicación o backups.
Solución: Identifica pipelines activos de zfs send/receive. O espera a la finalización o coordina una parada. Reintentar destroy en bucle solo añade caos.
Preguntas frecuentes
1) ¿Qué hace realmente zfs release?
Elimina una etiqueta hold nombrada de un snapshot. Los holds impiden la destrucción del snapshot. Si un snapshot tiene múltiples holds, debes liberarlos todos (o los que queden aún bloquearán el destroy).
2) ¿Por qué ZFS permite holds en absoluto? Se siente como si me estuviera peleando.
Porque en operaciones reales, tanto la automatización como los humanos cometen errores. Los holds son barandillas: “este snapshot es requerido para backup/replicación/cumplimiento”. Sin ellos, un script de limpieza puede borrar tus puntos de recuperación más rápido de lo que tu respuesta a incidentes puede escribir.
3) Liberé holds y destruí el snapshot. ¿Por qué no recuperé espacio?
Porque esos bloques aún pueden estar referenciados por snapshots más nuevos, clones o el sistema de archivos en vivo. Usa zfs list con usedbysnapshots y ordena snapshots por used para encontrar donde está realmente fijado el espacio.
4) ¿Cuál es la diferencia entre un snapshot y un bookmark?
Un snapshot incluye metadata completa para la vista puntual en el tiempo. Un bookmark es una referencia ligera usada principalmente como base de replicación incremental. Destruir un bookmark no libera espacio de snapshot porque no es un snapshot; destruir un snapshot puede liberar espacio si los bloques ya no se referencian en otro lugar.
5) ¿Cómo sé si un snapshot se mantiene por clones?
Busca datasets cuyo origin sea igual a ese snapshot. Si existen, el snapshot es un origen y no puede destruirse hasta que esos clones se destruyan o promuevan.
6) ¿Es seguro usar zfs destroy -r en el nombre de un snapshot?
Puedes hacerlo si destruyes intencionalmente ese snapshot en un árbol de datasets bien entendido con nombres consistentes. Es peligroso si los datasets hijos tienen significados/propietarios distintos. “Recursivo” no es una bandera de conveniencia; es un multiplicador de alcance.
7) ¿Cuál es la forma más segura de limpiar snapshots en un entorno replicado?
Toma decisiones de retención en un solo lugar (fuente de verdad), coordina ventanas de replicación y evita eliminar las bases incrementales que la replicación necesita. En la práctica, eso significa: entiende las expectativas de tu herramienta de replicación, respeta las etiquetas hold que coloque y limpia en una ventana de cambio controlada cuando necesites romper el vidrio.
8) ¿Puedo forzar la destrucción de un snapshot retenido?
No en el sentido de “anular holds”. El método correcto es liberar los holds. Si no controlas los holds (p. ej., cumplimiento), tu trabajo real es gobernanza: averigua quién posee la política de hold y qué condiciones permiten la liberación.
9) ¿Por qué obtengo “snapshot has dependent clones” cuando no recuerdo haber creado clones?
Porque otra cosa lo hizo. Herramientas de virtualización, pipelines de CI, autoservicio de desarrolladores y algunos flujos de backup pueden crear clones. Los nombres de datasets y la propiedad origin te dirán qué está conectado—incluso si nadie lo recuerda.
10) ¿Cómo evito que vuelvan a ocurrir “snapshots indelebles”?
Estandariza etiquetas hold, implementa ciclo de vida de clones (expiración/propiedad) y haz los cambios de política de retención explícitos y revisados. Técnicamente, ZFS está haciendo lo correcto; operacionalmente, necesitas asegurarte de que las personas y sistemas adecuados sean los que pongan esas restricciones.
Conclusión
En ZFS, los snapshots no son indelebles. Son responsables. Si un snapshot no muere, es porque algo todavía depende de él—por diseño. La ruta práctica siempre es la misma: lee el error exacto, revisa holds, revisa clones y luego verifica si la automatización está recreando lo que estás borrando. Una vez que trates los snapshots como parte de un grafo de dependencias en lugar de “archivos viejos”, zfs release deja de ser un hechizo misterioso y se vuelve lo que es: una forma controlada de quitar un bloqueo de seguridad.
Haz las inspecciones aburridas primero, coordina con los propietarios de replicación/backup y sé explícito con el alcance. ZFS te acompañará a medias—justo después de confirmar que no estás a punto de borrar el único bote salvavidas.