Clones ZFS: copias instantáneas con dependencias ocultas (lee esto primero)

¿Te fue útil?

Los clones ZFS son la clase de función que hace parecer a los ingenieros de almacenamiento magos: crea una “copia” de un sistema de archivos o volumen al instante, sin mover datos, y empieza a escribir en ella como si siempre hubiera existido. La primera vez que lo usas para una plantilla de VM, un entorno CI o una copia forense, parece que has engañado a la física.

Luego intentas limpiar snapshots, recuperar espacio o replicar el dataset… y aprendes la otra mitad del truco: los clones son instantáneos porque no son independientes. Un clone es un hijo escribible de un snapshot, y esa dependencia oculta acabará mostrándose en algún pager. Este artículo trata de asegurarse de que se muestre en una incidencia, no en un apagón de fin de semana.

Qué es realmente un clone ZFS

Un snapshot de ZFS es una vista de solo lectura en un punto del tiempo de un dataset (sistema de archivos) o volumen (zvol). Cuesta casi nada inicialmente porque solo registra metadatos; los bloques se comparten hasta que divergen.

Un clone de ZFS es un dataset o zvol escribible creado a partir de un snapshot. Ese “a partir de un snapshot” no es un detalle; es todo el contrato. Un clone empieza la vida compartiendo bloques con su snapshot de origen. A medida que escribes en el clone, ZFS usa copy-on-write (CoW): escribe nuevos bloques en otra parte, actualiza metadatos y el clone se desvincula del snapshot.

Los clones tienen dos propiedades que los operadores deberían tatuarse en su runbook mental:

  1. Un clone depende de su snapshot de origen. No puedes destruir el snapshot mientras el clone exista (a menos que hagas un baile de promoción, que cambia el árbol genealógico).
  2. La contabilidad de espacio se vuelve “compartida”. Puedes llenar un pool “sin llenar nada” hasta que, de repente, lo hiciste. Los números no mienten, pero requieren interpretación.

Una broma operativa que sigue funcionando porque es demasiado precisa: Los clones ZFS son como adoptar un gato; es instantáneo, pero ahora heredaste una dependencia a largo plazo que no presupuestaste.

Anatomía del clone: dataset vs zvol

ZFS puede clonar ambos:

  • Sistemas de archivos (datasets): montados en un punto de montaje, contienen archivos y directorios.
  • Volúmenes (zvols): dispositivos de bloque, a menudo usados para discos de VM, LUNs iSCSI, dispositivos crudos de bases de datos.

El mecanismo de clone es el mismo. El impacto operativo difiere porque los clones de zvol se usan con frecuencia en pilas de virtualización donde los patrones de “plantilla” y “linked clone” son comunes, y donde la amplificación de escritura puede aparecer rápidamente bajo cargas aleatorias intensas.

Qué significa realmente “instantáneo”

La creación del clone es instantánea porque ZFS no copia bloques. Crea un nuevo dataset y apunta sus metadatos a los mismos bloques referenciados por el snapshot. Si esperas que eso se comporte como una copia independiente, estás a punto de aprender sobre contadores de referencias, usedbysnapshots y por qué un snapshot que “no necesitas” todavía está evitando la recuperación de espacio.

La dependencia oculta: “no puedes borrar ese snapshot”

La sorpresa clásica se ve así:

  • Creas el snapshot pool/prod@app-2025-12-25.
  • Creas el clone pool/dev/app-test a partir de ese snapshot.
  • Semanas después, intentas borrar snapshots antiguos para recuperar espacio.
  • ZFS se niega a destruir el snapshot porque tiene clones dependientes.

Esto no es ZFS siendo terco; es ZFS previniendo corrupción. El snapshot de origen contiene referencias a bloques de los que el clone todavía puede depender. Si ZFS te permitiera borrar el snapshot, podría liberar bloques que el clone todavía necesita. ZFS resuelve esto haciendo cumplir la dependencia.

Por qué esto importa más allá de “no puedo limpiar”

En producción, las dependencias de clones tienden a manifestarse como:

  • Rotura de la política de retención de snapshots. Tu regla “conservar 14 días” silenciosamente se vuelve “conservar 14 días a menos que haya un clone, entonces conservar para siempre”.
  • La recuperación de espacio se paraliza. Los equipos siguen borrando archivos, pero el uso del pool no baja porque los bloques siguen referenciados por snapshots que no se pueden eliminar.
  • Complejidad en la replicación. Los clones pueden complicar los flujos de zfs send si no planificas la topología de datasets/snapshots.
  • Caos por promociones. Alguien “promociona” un clone para romper dependencias y cambia qué dataset se considera producción, y de repente tu modelo mental de “qué es prod” está equivocado.

Promoción: la vía de escape (y el arma peligrosa)

zfs promote hace que un clone pase a ser el dataset “principal”, y su origen se convierta conceptualmente en un hijo clone. Es como rompes la dependencia de un snapshot de origen para poder borrarlo. También es la forma en que accidentalmente inviertes una línea de descendencia y confundes replicación, monitorización y personas.

La promoción es legítima y a menudo necesaria. Pero debe ser una acción planeada con resultados explícitos, no un comando desesperado copiado de un foro mientras el pool está al 99%.

Datos interesantes y contexto histórico

Seis a diez puntos breves que importan más que la trivia porque explican por qué los clones se comportan como lo hacen:

  1. Los snapshots ZFS son baratos gracias a CoW. ZFS nunca sobrescribe en el lugar; escribe nuevos bloques y actualiza punteros, lo que hace que los snapshots consistentes sean una consecuencia natural del diseño.
  2. Los clones se diseñaron para aprovisionamiento rápido. Los primeros adoptantes de ZFS usaron clones para dev/test y plantillas de VM mucho antes de que “infraestructura como código” fuera generalizada.
  3. El espacio se comparte por contadores de referencia. Un bloque puede ser referenciado por el sistema de archivos activo, uno o más snapshots y uno o más clones; solo se libera cuando desaparece la última referencia.
  4. “Usado” en ZFS es contextual. Existe “usado por dataset”, “usado por snapshots”, “usado por hijos” y “usado lógico”; tu pool se llena según la realidad física, no según el número que mires en un panel.
  5. Los clones preceden a muchos productos modernos de “copy data management”. La idea—copiar instantáneamente y divergir al escribir—es el mismo principio detrás de muchos sistemas comerciales de snapshot/clone.
  6. La línea de descendencia de clones es explícita en propiedades. ZFS almacena la propiedad origin en los clones; puedes consultarla y automatizar en torno a ella (y deberías).
  7. Promover cambia la ascendencia, no la validez de los datos. Reordena qué snapshot se considera “origen” para efectos de dependencia; no reescribe todo el dataset.
  8. Clones y snapshots no son copias de seguridad. Son excelentes herramientas de recuperación local, pero comparten el mismo pool, dominio de fallo y a menudo el mismo riesgo de “ups, destruimos el pool”.
  9. Los clones de ZVOL cambiaron la economía de VMs. Los linked clones permiten desplegar cientos de VMs desde una imagen dorada con almacenamiento mínimo—hasta que los patrones de escritura convirtieron “mínimo” en “sorpresa”.

Cuándo los clones son la herramienta adecuada (y cuándo no)

Usos adecuados

  • Plantillas de VM / imágenes doradas: aprovisiona discos de VM al instante; paga solo por la divergencia.
  • Entornos CI: crea datasets de prueba rápidamente y destrúyelos tras la ejecución.
  • Forense: crea una copia escribible de un snapshot para reproducir problemas sin tocar prod.
  • Sandboxes para ciencia de datos: da a los analistas un dataset escribible desde un snapshot estable sin duplicar terabytes.
  • Migraciones riesgosas: clona un dataset y ensaya cambios; si sale mal, destruye el clone.

Usos inadecuados (o que requieren guardarraíles)

  • Entornos “temporales” de larga duración que sobreviven a las ventanas de retención de snapshots. Así un clone de prueba semanal se convierte en un ancla de espacio de tres años.
  • “Clone como backup”. Si el pool muere, tanto el original como el clone mueren juntos. Los clones reducen el radio de explosión de errores humanos, no del fallo de hardware.
  • Autoservicio de desarrolladores sin límites. Los desarrolladores crearán clones con nombres creativos, los olvidarán y tu limpieza de snapshots se convertirá en terapia de equipo.

Segunda broma, porque el almacenamiento necesita ligereza: Los clones son “gratis” del mismo modo que lo son los cachorros gratis—el coste inicial es cero, pero el calendario de limpieza ahora es tu vida.

Tres micro-historias del mundo empresarial

1) Incidente causado por una suposición incorrecta: “Borrar el snapshot liberará espacio”

El equipo de almacenamiento de una empresa mediana operaba un clúster de virtualización respaldado por ZFS. Tenían una política ordenada: snapshots horarios por 48 horas, diarios por dos semanas. Funcionó—hasta que no funcionó. El pool subió de 70% a 88% en un mes, luego llegó al 94% en un fin de semana, y el lunes por la mañana llegaron VMs lentas y paneles enojados.

El on-call hizo lo obvio: borrar snapshots antiguos. Los comandos destroy empezaron a fallar con “snapshot has dependent clones”. Ese mensaje parece inofensivo hasta que te das cuenta de que significa “tu política de retención es ahora ficción”. La suposición fue que los snapshots eran el único objeto de retención. En realidad, la tubería de aprovisionamiento de VM había cambiado silenciosamente a “linked clones del snapshot de anoche” para acelerar la creación de entornos. Nadie le dijo a almacenamiento, porque desde la perspectiva de la tubería era una mejora de rendimiento.

Intentaron borrar los clones, pero esos clones estaban en uso: alguien había repurposed VMs “de prueba” a “producción temporal” durante un incidente anterior. Los clones ya no eran descartables. Los snapshots de origen quedaron fijados, lo que fijó bloques, lo que fijó espacio.

El incidente terminó con una clasificación forzada: identificar qué clones importaban, migrar los importantes a datasets independientes, promocionar cuando correspondiera y luego restablecer un programa de snapshots sensato. La corrección del postmortem no fue “borrar más snapshots”. Fue gobernanza: cada clone obtuvo un TTL y el sistema de aprovisionamiento etiquetó clones con un propietario y fecha de expiración. Al final, almacenamiento recibió un informe diario de clones dependientes que bloqueaban la eliminación de snapshots.

2) Una optimización que salió mal: “Activemos dedup también”

Otra organización amaba la eficiencia. Descubrieron los clones y los usaron por todas partes: bases de datos de desarrolladores, entornos QA, refrescos de staging. El uso del pool bajó, el aprovisionamiento fue más rápido y todos se felicitaron.

Luego alguien dijo la frase que ha arruinado muchas buenas semanas: “Si los clones ahorran espacio, dedup ahorrará aún más.” Activaron dedup en un dataset que contenía imágenes de VM clonadas y zvols de bases de datos. En los primeros días, los números parecían geniales. En las semanas siguientes, la presión de memoria empeoró. Los fallos de ARC subieron. La latencia se volvió esporádica en horas punta. Eventualmente, la caja desarrolló la costumbre de pausar bajo carga como si reflexionara sobre decisiones de vida.

Las tablas de dedup son hambrientas. Los clones ya comparten bloques eficientemente cuando derivan de la misma línea de snapshots; dedup añade sobrecarga global de contabilidad de bloques. Para su carga—muchas VMs similares pero divergentes con muchas escrituras aleatorias—dedup incrementó la rotación de metadatos e hizo cada escritura más cara. El “espacio ahorrado” era real, pero lo cambiaron por rendimiento predecible y simplicidad operativa.

La corrección fue dolorosa: migrar fuera de datasets con dedup, reprovisionar con solo clones y aceptar que “eficiente” tiene múltiples dimensiones. Los clones fueron la optimización correcta; dedup era la optimización correcta para una carga y presupuesto de hardware diferentes.

3) Una práctica aburrida pero correcta que salvó el día: “Los clones tienen propietarios y expiración”

Un equipo de plataforma empresarial trató los clones como recursos de producción, no trucos mágicos. Su regla fue aburrida: cada clone debía tener un propietario, referencia de ticket y una fecha de expiración. No en una hoja de cálculo—almacenado como propiedades de usuario de ZFS directamente en el dataset.

Cuando un pool empezó a subir, no adivinaron. Ejecutaron un script: listar todos los clones, sus snapshots de origen y sus fechas de expiración. La mayoría eran legítimos. Un puñado había caducado y no se usaba. Esos se destruyeron primero, lo que desancló snapshots, lo que liberó espacio. No hizo falta pelea.

Más tarde, una canalización de despliegue falló porque no podía destruir snapshots antiguos. El on-call siguió la salida del script y encontró un único clone de larga vida creado para una investigación de incidente meses antes. El propietario se había movido de equipo. El dataset seguía existiendo porque nadie quería borrar “por si acaso”. El equipo contactó al nuevo responsable del servicio, acordaron replicar los artefactos necesarios y luego destruyeron el clone y reanudaron operaciones normales.

Esta es la verdad poco sexy: un inventario aburrido vence a las características de almacenamiento ingeniosas. Los clones son poderosos, pero la única manera sostenible de usarlos a escala es hacerlos visibles, con propietario y gestionados en su ciclo de vida.

Tareas prácticas: comandos, salidas, interpretación

A continuación hay tareas prácticas que puedes ejecutar en un sistema OpenZFS típico (Linux o illumos). Los comandos asumen que tienes privilegios. Las salidas son representativas; las tuyas diferirán.

Tarea 1: Listar snapshots y clones juntos

cr0x@server:~$ zfs list -t filesystem,snapshot,volume -o name,type,used,refer,origin -r tank/app
NAME                          TYPE      USED  REFER  ORIGIN
tank/app                      filesystem 12.3G  9.8G  -
tank/app@daily-2025-12-20      snapshot   0B    9.8G  -
tank/app@daily-2025-12-21      snapshot   0B    10.1G -
tank/app@daily-2025-12-22      snapshot   0B    10.1G -
tank/app-clone-qa             filesystem 3.1G  11.0G tank/app@daily-2025-12-21

Interpretación: El clone tiene la propiedad origin apuntando a un snapshot. Ese snapshot de origen ahora está protegido contra destrucción a menos que elimines o promociones el clone.

Tarea 2: Crear un snapshot (rápido y seguro)

cr0x@server:~$ zfs snapshot tank/app@pre-change-001
cr0x@server:~$ zfs list -t snapshot -o name,creation -r tank/app | tail -n 3
NAME                          CREATION
tank/app@daily-2025-12-22      Mon Dec 22 01:00 2025
tank/app@pre-change-001        Thu Dec 25 09:14 2025

Interpretación: El snapshot es instantáneo y consistente a nivel ZFS.

Tarea 3: Crear un clone a partir de un snapshot

cr0x@server:~$ zfs clone tank/app@pre-change-001 tank/app-clone-dev
cr0x@server:~$ zfs get origin,mountpoint tank/app-clone-dev
NAME               PROPERTY    VALUE                    SOURCE
tank/app-clone-dev  origin      tank/app@pre-change-001  -
tank/app-clone-dev  mountpoint  /tank/app-clone-dev      default

Interpretación: El clone es un dataset real con sus propias propiedades, punto de montaje, cuotas, y una dependencia firme en el snapshot de origen.

Tarea 4: Demostrar la dependencia: intentar destruir el snapshot de origen

cr0x@server:~$ zfs destroy tank/app@pre-change-001
cannot destroy snapshot tank/app@pre-change-001: snapshot has dependent clones

Interpretación: Ese snapshot está fijado. Tu política de retención acaba de encontrarse con la realidad.

Tarea 5: Encontrar clones dependientes de un snapshot

cr0x@server:~$ zfs list -t filesystem,volume -o name,origin -r tank | grep 'tank/app@pre-change-001'
tank/app-clone-dev  tank/app@pre-change-001

Interpretación: Un simple grep sirve, pero para grandes entornos querrás consultas scriptadas usando zfs get -H.

Tarea 6: Cuantificar “qué está usando espacio realmente” con desglose de uso

cr0x@server:~$ zfs list -o name,used,usedbysnapshots,usedbychildren,usedbydataset -r tank/app | head
NAME          USED  USEDBYSNAPSHOTS  USEDBYCHILDREN  USEDBYDATASET
tank/app      12.3G 2.4G             3.1G            6.8G

Interpretación: Si usedbysnapshots es grande, eliminar snapshots ayudaría—salvo que los clones lo impidan. Si usedbychildren es grande, clones (u otros datasets hijos) están consumiendo espacio.

Tarea 7: Comprobar salud del pool y margen de espacio libre (porque CoW lo necesita)

cr0x@server:~$ zpool status tank
  pool: tank
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0

errors: No known data errors
cr0x@server:~$ zpool list tank
NAME  SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tank  7.25T  6.68T   576G        -         -    41%    92%  1.00x  ONLINE  -

Interpretación: 92% de capacidad es zona de peligro para archivos CoW. Los entornos con muchos clones pueden llegar aquí porque “no copiamos nada” se convierte en “escribimos muchos datos divergentes”.

Tarea 8: Identificar la línea de clones y prepararse para promover

cr0x@server:~$ zfs get -r -o name,property,value origin tank/app tank/app-clone-dev
NAME              PROPERTY  VALUE
tank/app           origin    -
tank/app@pre-change-001  origin    -
tank/app-clone-dev  origin    tank/app@pre-change-001

Interpretación: Solo los clones tienen una origin. Los snapshots no.

Tarea 9: Promover un clone para romper la dependencia (con cuidado)

cr0x@server:~$ zfs promote tank/app-clone-dev
cr0x@server:~$ zfs get origin tank/app-clone-dev tank/app
NAME              PROPERTY  VALUE                   SOURCE
tank/app-clone-dev  origin    -                       -
tank/app            origin    tank/app-clone-dev@pre-change-001  -

Interpretación: Tras la promoción, el clone ahora es la línea “principal”; el dataset original puede convertirse en un clone dependiendo del grafo de snapshots. Esto es comportamiento correcto, y también por qué las promociones deben registrarse en el control de cambios.

Tarea 10: Destruir el snapshot antiguo tras la promoción (si procede)

cr0x@server:~$ zfs destroy tank/app@pre-change-001
cr0x@server:~$ zfs list -t snapshot -r tank/app | grep pre-change-001
cr0x@server:~$ echo $?
1

Interpretación: El snapshot ha desaparecido. El espacio solo se recupera si no existen otras referencias.

Tarea 11: Crear un clone de zvol para un flujo de trabajo de disco de VM

cr0x@server:~$ zfs create -V 80G -o volblocksize=16K tank/vm/golden
cr0x@server:~$ zfs snapshot tank/vm/golden@v1
cr0x@server:~$ zfs clone tank/vm/golden@v1 tank/vm/vm-123-disk0
cr0x@server:~$ ls -l /dev/zvol/tank/vm/vm-123-disk0
brw-rw---- 1 root disk 230, 128 Dec 25 09:33 /dev/zvol/tank/vm/vm-123-disk0

Interpretación: Ahora tienes un dispositivo de bloque respaldado por un clone. Perfecto para aprovisionamiento rápido—hasta que olvides que los snapshots no se pueden rotar mientras existan clones de discos de VM que dependan de ellos.

Tarea 12: Comprobar compresión y espacio lógico vs físico

cr0x@server:~$ zfs get compressratio,logicalused,used tank/app-clone-dev
NAME              PROPERTY       VALUE  SOURCE
tank/app-clone-dev  compressratio  1.45x  -
tank/app-clone-dev  logicalused    14.9G  -
tank/app-clone-dev  used           3.1G   -

Interpretación: logicalused refleja el tamaño lógico sin comprimir; used es el espacio físico consumido por este dataset y sus descendientes. Con clones, “used” no es “único”.

Tarea 13: Mostrar uso único vs compartido para un dataset (estimación rápida)

cr0x@server:~$ zfs list -o name,used,refer,logicalrefer tank/app tank/app-clone-dev
NAME              USED  REFER  LOGICALREFER
tank/app          12.3G  9.8G   13.9G
tank/app-clone-dev 3.1G  11.0G  15.1G

Interpretación: refer es la cantidad accesible desde ese dataset; los clones pueden mostrar un refer grande porque referencian bloques compartidos. No significa que consuman de forma única tanto espacio.

Tarea 14: Usar holds para fijar intencionalmente un snapshot (dependencia controlada)

cr0x@server:~$ zfs snapshot tank/app@forensics-keep
cr0x@server:~$ zfs hold case-INC123 tank/app@forensics-keep
cr0x@server:~$ zfs destroy tank/app@forensics-keep
cannot destroy 'tank/app@forensics-keep': snapshot is held
cr0x@server:~$ zfs holds tank/app@forensics-keep
NAME                  TAG           TIMESTAMP
tank/app@forensics-keep  case-INC123  Thu Dec 25 09:41 2025

Interpretación: Los holds son una forma deliberada de evitar la eliminación. Comparados con las dependencias de clones, los holds son explícitos y fáciles de auditar.

Tarea 15: Liberar el hold y destruir el snapshot

cr0x@server:~$ zfs release case-INC123 tank/app@forensics-keep
cr0x@server:~$ zfs destroy tank/app@forensics-keep

Interpretación: Esta es la ruta de limpieza que quieres: control explícito del ciclo de vida.

Tarea 16: Comprobación de saneamiento de replicación: listar snapshots a enviar

cr0x@server:~$ zfs list -t snapshot -o name -s creation -r tank/app | tail -n 5
tank/app@daily-2025-12-21
tank/app@daily-2025-12-22
tank/app@pre-change-001
tank/app@daily-2025-12-23
tank/app@daily-2025-12-24

Interpretación: Si hay clones involucrados, asegúrate de que tu plan de send/receive coincida con el grafo de snapshots que deseas preservar. El enfoque “correcto” varía según si quieres replicar clones, promocionar en el destino o conservar solo las primarias.

Guía rápida de diagnóstico

Este es el playbook “está lento y el pool se está llenando” que realmente quiero que los ingenieros on-call sigan. No porque sea perfecto, sino porque fuerza las preguntas correctas en el orden correcto.

1) Primero: confirma que no es un problema de salud del pool o acantilado de capacidad

cr0x@server:~$ zpool status -x
all pools are healthy
cr0x@server:~$ zpool list -o name,size,alloc,free,cap,frag,health
NAME  SIZE  ALLOC  FREE  CAP  FRAG  HEALTH
tank  7.25T 6.68T 576G   92%  41%   ONLINE

Interpretación: Si CAP está por encima de ~85–90%, espera fragmentación y sobrecarga CoW que amplifiquen la latencia. Los clones aumentan la probabilidad de derivar aquí porque fomentan “aprovisionamiento rápido” sin igual enfoque en “recuperación rápida”.

2) Segundo: encuentra qué está fijando snapshots y bloqueando la eliminación

cr0x@server:~$ zfs list -t snapshot -o name,used,refer -r tank/app | head
NAME                     USED  REFER
tank/app@daily-2025-12-10 0B   8.9G
tank/app@daily-2025-12-11 0B   9.0G
cr0x@server:~$ zfs destroy tank/app@daily-2025-12-10
cannot destroy snapshot tank/app@daily-2025-12-10: snapshot has dependent clones

Interpretación: Ahora sabes por qué la retención no funciona. El siguiente paso es identificar los clones (o holds) responsables.

3) Tercero: mide a dónde va el espacio (dataset vs snapshots vs hijos)

cr0x@server:~$ zfs list -o name,used,usedbydataset,usedbysnapshots,usedbychildren -r tank/app
NAME      USED  USEDBYDATASET  USEDBYSNAPSHOTS  USEDBYCHILDREN
tank/app  12.3G 6.8G           2.4G             3.1G

Interpretación: Si usedbychildren es alto, probablemente tengas clones (u otros datasets hijos) consumiendo datos divergentes. Si usedbysnapshots es alto, los snapshots están reteniendo bloques—posiblemente porque los clones fuerzan su existencia.

4) Cuarto: identifica qué clones están “activos” vs abandonados

cr0x@server:~$ zfs list -t filesystem,volume -o name,origin,used,creation -r tank | grep -v 'origin\s*-' | head
tank/app-clone-qa     tank/app@daily-2025-12-21  3.1G  Mon Dec 22 02:10 2025
tank/vm/vm-123-disk0  tank/vm/golden@v1          9.4G  Thu Dec 25 09:33 2025

Interpretación: Crea rápidamente una lista “¿quién es el dueño de esto?”. Si no tienes metadatos de propiedad, estarás haciendo arqueología bajo presión.

5) Quinto: si el síntoma es rendimiento, comprueba I/O y presión de TXG

cr0x@server:~$ zpool iostat -v tank 1 5
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        6.68T   576G    820   2400   65.2M  210M
  mirror-0                  6.68T   576G    820   2400   65.2M  210M
    sda                         -      -    410   1200   32.6M  105M
    sdb                         -      -    410   1200   32.6M  105M
--------------------------  -----  -----  -----  -----  -----  -----

Interpretación: Los clones no hacen inherentemente lento el I/O, pero los entornos con muchos clones suelen implicar más snapshots, más metadatos y más escrituras aleatorias (especialmente con zvols de VM). Si el pool está casi lleno, la misma carga se vuelve más lenta.

Errores comunes: síntomas y soluciones

Error 1: Tratar los clones como copias independientes

Síntoma: Borras un snapshot y ZFS se niega: “snapshot has dependent clones.” O peor: tienes miedo de borrar cualquier cosa porque “podría romper el clone”.

Solución: Inventory de clones y sus orígenes. Decide si el clone es prescindible. Si es prescindible, destrúyelo. Si no, considera zfs promote (planificado) o migralo a un dataset independiente (send/receive, o copia completa) y luego elimina la dependencia.

Error 2: Expansión de clones sin TTL

Síntoma: La retención de snapshots nunca reduce; el uso del pool tiende a subir incluso después de borrar datos. “Temporales” tienen más antigüedad que algunos empleados.

Solución: Hacer cumplir expiración con propiedades de usuario (owner, ticket, expires). Informar sobre clones semanalmente. Destruir clones expirados automáticamente tras notificación.

Error 3: Promover un clone en medio de un incidente sin entender la línea

Síntoma: Los scripts de replicación fallan, las etiquetas de monitorización cambian, o alguien descubre que el “original” ahora tiene una propiedad origin y ya no es el primario.

Solución: Antes de promover: captura zfs get origin en los datasets implicados, documenta resultados previstos y coordina con los propietarios de replicación. Tras promover: actualiza la documentación operativa y cualquier automatización que asuma roles de dataset.

Error 4: Esperar que la eliminación de snapshots recupere espacio inmediatamente

Síntoma: Destruyes snapshots y el pool sigue lleno. O borras archivos y nada cambia.

Solución: Comprueba clones dependientes, holds en snapshots y otros datasets que referencien los bloques. Usa usedbysnapshots y usedbychildren para entender quién está fijando espacio.

Error 5: Usar clones para bases de datos de larga vida sin vigilar la amplificación de escritura

Síntoma: El used del clone crece rápidamente, el rendimiento se vuelve errático y ves aumento de fragmentación con el tiempo.

Solución: Para cargas con muchas escrituras, los clones siguen siendo aceptables, pero trátalos como datasets reales con crecimiento real. Aplica cuotas, monitoriza used y el margen del pool, y considera actualizar clones desde snapshots nuevos periódicamente en lugar de mantenerlos para siempre.

Error 6: Confundir “refer” con “espacio único consumido”

Síntoma: Un clone muestra refer=10T y alguien entra en pánico asumiendo que consume 10T.

Solución: Enseña al equipo que refer es datos accesibles, no asignación física única. Usa desglose de uso y la asignación del pool para evaluar el riesgo real de capacidad.

Listas de verificación / plan paso a paso

Checklist A: Flujo seguro para crear clones en producción

  1. Crear un snapshot nombrado con marca temporal y propósito (p. ej., @template-v3 o @pre-change-INC123).
  2. Crear el clone con un nombre que codifique propietario/servicio.
  3. Establecer propiedades de usuario en el clone: owner, ticket, expiry.
  4. Aplicar cuotas/reservas donde corresponda para que los clones no devoren el pool silenciosamente.
  5. Documentar el snapshot de origen en el ticket; trátalo como una dependencia similar a la versión de esquema de una base de datos.
cr0x@server:~$ zfs snapshot tank/app@template-v3
cr0x@server:~$ zfs clone tank/app@template-v3 tank/app-clone-ci-4512
cr0x@server:~$ zfs set org.owner=ci-team tank/app-clone-ci-4512
cr0x@server:~$ zfs set org.ticket=CI-4512 tank/app-clone-ci-4512
cr0x@server:~$ zfs set org.expires=2026-01-05 tank/app-clone-ci-4512
cr0x@server:~$ zfs set quota=200G tank/app-clone-ci-4512

Checklist B: Limpieza segura cuando los snapshots no se eliminan

  1. Intentar destruir el snapshot y confirmar que el error son clones dependientes (no holds).
  2. Listar clones con el origen coincidente.
  3. Clasificar clones: prescindibles, que deben conservarse, propietario desconocido.
  4. Para clones prescindibles: destrúyelos primero.
  5. Para clones que deben conservarse: decidir entre promoción o migración a nueva línea.
  6. Tras eliminar la dependencia: destruir el snapshot, confirmar que las tendencias de espacio se recuperan.
cr0x@server:~$ zfs destroy tank/app@daily-2025-12-10
cannot destroy snapshot tank/app@daily-2025-12-10: snapshot has dependent clones
cr0x@server:~$ zfs list -t filesystem,volume -o name,origin -r tank | grep 'tank/app@daily-2025-12-10'
tank/app-clone-sandbox  tank/app@daily-2025-12-10
cr0x@server:~$ zfs get org.owner,org.expires tank/app-clone-sandbox
NAME                 PROPERTY    VALUE        SOURCE
tank/app-clone-sandbox  org.owner   alice        local
tank/app-clone-sandbox  org.expires 2025-12-01  local
cr0x@server:~$ zfs destroy tank/app-clone-sandbox
cr0x@server:~$ zfs destroy tank/app@daily-2025-12-10

Checklist C: Árbol de decisión para promoción (hazlo explícito)

  1. ¿Quieres que el clone se convierta en la línea principal? Si sí, la promoción es razonable.
  2. ¿La replicación o automatización asumirá que el dataset original es primario? Si sí, actualiza la automatización primero o elige migración en su lugar.
  3. ¿Necesitas preservar el historial de snapshots en el original? Si sí, revisa cuidadosamente los conjuntos de snapshots y prueba el comportamiento de send/receive en staging.
  4. ¿Tienes suficiente espacio libre? Las promociones son operaciones de metadatos, pero la limpieza que intentas puede requerir margen para completarse de forma segura.

Preguntas frecuentes

1) ¿Cuál es la diferencia entre un snapshot y un clone en ZFS?

Un snapshot es de solo lectura y representa una vista en un punto del tiempo. Un clone es un dataset o zvol escribible creado a partir de un snapshot. El clone depende del snapshot hasta que destruyes el clone o cambias la línea mediante promoción.

2) ¿Por qué no puedo borrar un snapshot aunque no lo necesite?

Porque al menos un clone depende de él. Ese snapshot contiene referencias a bloques que el clone puede seguir usando. ZFS evita que lo borres para no liberar bloques en uso.

3) ¿Cómo encuentro qué clone está bloqueando la eliminación de un snapshot?

Lista datasets y volúmenes con su propiedad origin y empareja el nombre del snapshot.

cr0x@server:~$ zfs list -t filesystem,volume -o name,origin -r tank | grep 'tank/app@daily-2025-12-10'

4) ¿Los clones consumen espacio?

Consumen espacio a medida que divergen del snapshot de origen. Inicialmente comparten bloques, por lo que la creación es barata. Con el tiempo, las escrituras asignan nuevos bloques, y esos bloques son únicos para el clone (a menos que estén referenciados adicionalmente en otro lugar).

5) ¿Puedo replicar clones con zfs send?

Sí, pero necesitas un plan claro. Replicar un dataset que tiene clones puede requerir replicar los snapshots relevantes y preservar la línea esperada en el lado receptor. Si solo necesitas una copia independiente, considera enviar un stream de snapshot a un dataset nuevo y no recrear la topología de clones.

6) ¿Debería usar clones para entornos de bases de datos?

A menudo sí para refrescos rápidos, pero establece cuotas y monitoriza el crecimiento. Las bases de datos escriben muchos bloques nuevos; un clone puede volverse rápidamente “casi del tamaño completo” respecto a su origen según el churn. La ventaja es la velocidad de aprovisionamiento y la conveniencia de rollback, no el ahorro garantizado a largo plazo.

7) ¿Qué hace realmente zfs promote?

Cambia qué dataset se considera el origen en la relación de clones. Prácticamente, hace que el clone seleccionado sea independiente de su snapshot de origen, y reorganiza la ascendencia para que puedas eliminar dependencias. No “copia todos los datos”, pero sí cambia cómo se comportarán en adelante la eliminación de snapshots y la replicación.

8) ¿Los clones ZFS son seguros para usar en producción?

Sí—si gestionas el ciclo de vida y las dependencias. El riesgo no es la integridad de datos; ZFS hace exactamente lo que promete. El riesgo es operativo: retenciones ocultas, fijado de espacio y promociones sorpresa. Trata los clones como activos de primera clase con propietario y expiración.

9) ¿Por qué liberar archivos no liberó espacio del pool?

Porque los bloques borrados aún están referenciados por snapshots y/o clones. Comprueba usedbysnapshots, clones dependientes y holds en snapshots. El espacio se libera solo cuando desaparece la última referencia.

10) ¿Hay una alternativa más segura a los clones para “copiar” datos?

Si necesitas una copia independiente sin dependencias, haz una copia completa o usa zfs send | zfs receive hacia un dataset/pool separado. No es instantáneo, pero elimina la cadena de dependencias de bloques compartidos que introducen los clones.

Conclusión

Los clones ZFS son una de las mejores herramientas para “moverse rápido sin romper el almacenamiento” —hasta que los tratas como copias normales. Son instantáneos porque están vinculados. Ese vínculo es poderoso cuando lo controlas, y caro cuando olvidas que existe.

Si recuerdas solo tres cosas, que sean estas: los clones fijan snapshots, los snapshots fijados fijan espacio, y el espacio sin gestionar eventualmente fijará tu fin de semana. Pon propietarios y expiraciones en los clones, entiende la promoción antes de necesitarla y mantén suficiente margen libre para que CoW haga su trabajo. Así los clones seguirán siendo una superpotencia en lugar de una escena del crimen.

← Anterior
Disco lento en Ubuntu 24.04: planificador IO, profundidad de cola y cómo verificar mejoras
Siguiente →
Privación de IOPS en Docker: por qué un contenedor de DB hace que todo vaya lento

Deja un comentario