ZFS rollback: La forma segura de deshacer errores sin daños colaterales

¿Te fue útil?

Algunos incidentes no empiezan por una falla de disco o un panic del kernel. Empiezan con un sistema perfectamente sano y un comando bien intencionado: un ajuste de configuración, una actualización de paquete, una “limpieza” que borra el directorio equivocado. De repente tu aplicación está rota, tus datos están raros y los interesados hacen los ruidos que hacen los humanos cuando se dan cuenta de que se cancelaron sus planes del fin de semana.

El rollback de ZFS es una de las pocas herramientas en producción que puede devolver el tiempo con precisión quirúrgica. También es una de las maneras más fáciles de vaporizar snapshots equivocados, romper cadenas de replicación o revertir un dataset dejando sistemas dependientes en un estado sutilmente corrupto. Esta es la forma segura: minimizar el radio de impacto, preservar evidencia y evitar que tu yo futuro necesite terapia.

Qué hace realmente el rollback (y qué destruye)

zfs rollback mueve el dataset “vivo” de vuelta al contenido exacto de un snapshot. No “fusiona” ni “deshace” de manera suave. Rebobina el puntero head del dataset, lo que implícitamente descarta los cambios hechos después de ese snapshot.

Aquí viene la parte que suele morder a la gente: por defecto, ZFS no te permite hacer rollback por encima de snapshots que tengan snapshots más nuevos detrás de ellos a menos que se lo indiques. Si usas -r (recursivo) o -R (recursivo más destructivo), le estás pidiendo explícitamente a ZFS que destruya snapshots y clones dependientes que sean “más nuevos” que el snapshot objetivo. Eso puede ser la decisión correcta. También puede ser el momento exacto en que cortas la historia de tu replicación y el equipo de backups deja de contestarte las llamadas.

Operativamente, el rollback debe tratarse como una demolición controlada: se puede hacer de forma segura, pero solo si ya verificaste qué está conectado a aquello que vas a mover.

La familia de snapshots importa

Los snapshots forman una línea de tiempo. El rollback rebobina a un punto anterior. Si tienes snapshots después de ese punto, esos snapshots se refieren a bloques que representan historia posterior al objetivo. Cuando haces rollback con flags destructivos, ZFS está borrando el futuro que ya no quieres. Eso no es “peligroso”, es simplemente definitivo.

Rollback no es una restauración de archivos

Si solo necesitas unos pocos archivos o un directorio, montar o explorar un snapshot es más seguro que revertir todo el dataset. El rollback es para “el dataset está mal ahora, y queremos que vuelva exactamente a como estaba”. La recuperación a nivel de fichero es para “lamento un comando, no toda mi personalidad”.

Una cita para pegar sobre tu terminal

Idea parafraseada (Gene Kim, autor sobre confiabilidad/DevOps): “La mejora viene de hacer el trabajo visible y reducir el coste de recuperación.” El rollback reduce el coste de recuperación—si lo mantienes visible y controlado.

Datos interesantes y contexto histórico

  • ZFS incluyó snapshots desde el inicio (desarrollo de Solaris a principios de los 2000), cuando muchos sistemas de archivos todavía trataban el “backup” como problema de otro.
  • Los snapshots son esencialmente gratuitos al crearlos (solo metadata al momento de creación). Se vuelven “caros” después solo cuando se retienen bloques que divergen.
  • El rollback es instantáneo para metadata, pero el impacto operativo no lo es: los servicios ven un cambio de estado repentino, las cachés quedan obsoletas y las aplicaciones pueden necesitar pasos de recuperación.
  • Los clones existen porque el rollback es demasiado brusco: un clone es una rama escribible desde un snapshot, pensada para pruebas seguras y recuperaciones selectivas.
  • La replicación ZFS (send/receive) se basa en snapshots, lo que significa que las decisiones de rollback pueden romper cadenas incrementales si borras snapshots que el receptor espera.
  • “Used by snapshots” confunde a casi todo el mundo al principio: no es el “tamaño del snapshot”, es “cuánto se liberaría si ese snapshot desapareciera”.
  • Se introdujeron los holds en ZFS para evitar borrados accidentales de snapshots críticos, especialmente en entornos automatizados donde hay scripts de “limpieza”.
  • Los bookmarks existen por higiene de replicación: registran un punto de envío sin mantener todos los bloques fijados como un snapshot completo.
  • El rollback de la pool raíz se volvió un patrón operacional común con entornos de arranque (boot environments) —notablemente en illumos y algunas configuraciones Linux— haciendo que “actualizar y luego revertir” sea menos aterrador.

Un modelo mental que evita el pánico

Cuando estás en medio de un incidente, no quieres poesía. Quieres un modelo que puedas ejecutar.

Piensa en tres capas:

  1. Capa de datos (ZFS): datasets, snapshots, clones, holds, bookmarks.
  2. Capa de consistencia (apps): bases de datos, colas de mensajes, ficheros que deben coincidir entre sí, WAL/redo logs, semántica de recuperación tras crash.
  3. Capa de dependencia (ops): replicación, backups, expectativas del monitoreo, consumidores de rutas montadas.

El rollback es puramente la capa 1. Tu incidente suele estar causado por la capa 2 o 3. Por eso “rollback arregló los archivos” a veces todavía te deja con un sistema roto: el mundo de la aplicación incluye cachés, estado externo e invariantes transaccionales.

Regla general: si una aplicación no tolera una pérdida de energía en cualquier momento, no tolerará rollback sin coordinación explícita. ZFS rebobina con gusto; tu base de datos explicará con gusto por qué está molesta.

Valores por defecto seguros: clonar primero, revertir después

Si no recuerdas nada más: no hagas rollback primero si no estás 100% seguro. Clona el snapshot, móntalo en un lugar inocuo, compara, extrae y solo entonces considera el rollback.

El rollback es ideal para:

  • Revertir una mala actualización de paquete o un cambio de configuración en un dataset dedicado o en un entorno de arranque.
  • Deshacer operaciones de archivos destructivas cuando el estado actual del dataset no vale la pena preservar.
  • Restaurar una imagen de servicio conocida como buena cuando la aplicación es sin estado o tiene su propia recuperación por journaling.

El rollback es arriesgado para:

  • Bases de datos con dependencias externas (réplicas, PITR, envío de binlog/WAL).
  • Datasets usados por múltiples servicios donde solo uno está “roto”.
  • Sistemas con cadenas de replicación estrictas donde la eliminación de snapshots rompe incrementales.

Broma #1: El rollback es como una máquina del tiempo: funciona de maravilla hasta que te das cuenta de que también borraste la línea temporal donde anotaste qué cambiaste.

Tareas prácticas con comandos, salidas y decisiones

Estos son movimientos operativos reales que puedes ejecutar bajo presión. Cada tarea incluye: comando, qué significa la salida y la decisión que tomas a partir de ello.

Tarea 1: Confirma la salud de la pool antes de tocar nada

cr0x@server:~$ zpool status -x
all pools are healthy

Significado: no hay errores conocidos de dispositivo ni vdevs degradados. Si ves “DEGRADED” o errores de checksum, tu problema podría ser hardware o corrupción, no “ups cambié un archivo”.

Decisión: Si no está saludable, para y estabiliza: scrub, reemplaza discos o al menos captura la salida de estado para las notas del incidente antes de cualquier rollback.

Tarea 2: Identifica el dataset exacto detrás del punto de montaje

cr0x@server:~$ zfs list -o name,mountpoint -S mountpoint
NAME                 MOUNTPOINT
tank                 /tank
tank/app             /srv/app
tank/app/logs        /srv/app/logs
tank/db              /var/lib/postgresql

Significado: Ahora sabes qué dataset corresponde a una ruta. La gente hace rollback de “tank” cuando quería “tank/app”. Ahí inventas nuevos incidentes.

Decisión: Apunta al dataset más pequeño que contenga el estado roto.

Tarea 3: Enumera snapshots del dataset y encuentra tu candidato

cr0x@server:~$ zfs list -t snapshot -o name,creation,used -s creation tank/app
NAME                          CREATION                USED
tank/app@autosnap_2025-12-26  Fri Dec 26 01:00 2025   120M
tank/app@autosnap_2025-12-26_02-00  Fri Dec 26 02:00 2025   8M
tank/app@pre_upgrade          Fri Dec 26 02:12 2025   0B
tank/app@post_upgrade         Fri Dec 26 02:20 2025   35M

Significado: Nombres de snapshots y tiempos de creación. USED es cuánto espacio único se liberaría si el snapshot se borrara (no “tamaño del contenido del snapshot”).

Decisión: Elige el snapshot que coincida con tu “último buen estado”. Prefiere snapshots explícitos como @pre_upgrade sobre los periódicos cuando estén disponibles.

Tarea 4: Comprueba clones dependientes (rollback puede estar bloqueado o ser destructivo)

cr0x@server:~$ zfs list -t snapshot -o name,clones tank/app@pre_upgrade
NAME                    CLONES
tank/app@pre_upgrade    tank/app-test

Significado: Hay un clone tank/app-test basado en ese snapshot. Algunas operaciones de rollback que destruyen snapshots pueden requerir destruir clones dependientes.

Decisión: Si existen clones, prefiere “clonar y restaurar archivos” en lugar de rollback, o planifica explícitamente el destino del clone.

Tarea 5: Verifica si existen snapshots más nuevos que serían destruidos

cr0x@server:~$ zfs list -t snapshot -o name -s creation tank/app | tail -n 5
tank/app@autosnap_2025-12-26_02-00
tank/app@pre_upgrade
tank/app@post_upgrade
tank/app@autosnap_2025-12-26_03-00
tank/app@autosnap_2025-12-26_04-00

Significado: Si haces rollback a @pre_upgrade con flags de destrucción recursiva, todo lo posterior está en la picota.

Decisión: Si esos snapshots posteriores son necesarios para replicación o auditoría, no los destruyas; clona en su lugar.

Tarea 6: Crea un snapshot de seguridad ahora mismo (sí, incluso si las cosas están rotas)

cr0x@server:~$ zfs snapshot tank/app@before_rollback_2025-12-26T0235
cr0x@server:~$ zfs list -t snapshot -o name,creation | grep before_rollback
tank/app@before_rollback_2025-12-26T0235  Fri Dec 26 02:35 2025

Significado: Has preservado el estado actual roto. Esto es tu forense y “deshacer el deshacer”.

Decisión: Si el rollback sale mal, puedes volver a este punto o extraer evidencia.

Tarea 7: Poner un hold en snapshots críticos para que la automatización no los borre en medio del incidente

cr0x@server:~$ zfs hold incident tank/app@before_rollback_2025-12-26T0235
cr0x@server:~$ zfs holds tank/app@before_rollback_2025-12-26T0235
NAME                                      TAG       TIMESTAMP
tank/app@before_rollback_2025-12-26T0235  incident  Fri Dec 26 02:36 2025

Significado: El snapshot no puede ser destruido hasta que se libere el hold.

Decisión: Usa holds cuando existan trabajos de limpieza, o cuando varias personas estén “ayudando”. Es más barato que discutir.

Tarea 8: Clona el snapshot para inspeccionar y recuperar sin tocar prod

cr0x@server:~$ zfs clone tank/app@pre_upgrade tank/app_recover
cr0x@server:~$ zfs set mountpoint=/mnt/app_recover tank/app_recover
cr0x@server:~$ zfs mount tank/app_recover
cr0x@server:~$ zfs list -o name,mountpoint,mounted tank/app_recover
NAME              MOUNTPOINT        MOUNTED
tank/app_recover  /mnt/app_recover  yes

Significado: Ahora tienes una rama escribible con el contenido antiguo. Puedes hacer diffs, copiar o ejecutar comprobaciones sin arriesgar el dataset en vivo.

Decisión: Si puedes arreglar prod copiando un puñado de archivos desde el clone, haz eso y evita el rollback por completo.

Tarea 9: Compara propiedades del dataset que podrían afectar el comportamiento después del rollback

cr0x@server:~$ zfs get -H -o property,value compression,recordsize,atime,xattr,acltype tank/app
compression  lz4
recordsize   128K
atime        off
xattr        sa
acltype      posixacl

Significado: Las propiedades impactan rendimiento y semántica. El rollback no cambia propiedades (no son por-snapshot), pero si alguien “arregló” algo cambiando una propiedad después del snapshot, el rollback no lo deshará.

Decisión: Si el incidente fue causado por un cambio de propiedad, corrige la propiedad en lugar de hacer rollback de datos. O gestiona las propiedades como configuración versionada.

Tarea 10: Comprueba la presión de espacio (los snapshots pueden bloquear liberaciones; el rollback puede amplificarlo)

cr0x@server:~$ zfs list -o name,used,avail,refer,mounted tank
NAME  USED  AVAIL  REFER  MOUNTED
tank  8.21T  640G  96K    yes

Significado: Solo 640G disponibles. Si creas clones, recibes streams o mantienes muchos snapshots, podrías llegar al 100% y provocar colapso de rendimiento o fallos de asignación.

Decisión: Si el espacio libre es escaso, evita operaciones que aumenten el espacio referenciado (clones grandes, receives masivos). Considera borrar snapshots no críticos (con cuidado) o añadir capacidad antes de hacer recuperaciones “ingeniosas”.

Tarea 11: Ver qué está fijando espacio mediante snapshots

cr0x@server:~$ zfs list -t snapshot -o name,used,refer -S used tank/app | head
NAME                                   USED  REFER
tank/app@autosnap_2025-12-25_23-00     88G   612G
tank/app@autosnap_2025-12-26_00-00     74G   618G
tank/app@autosnap_2025-12-26_01-00     120M  620G
tank/app@before_rollback_2025-12-26T0235 0B  621G

Significado: Los snapshots antiguos con valores grandes en USED están reteniendo muchos bloques. Eso suele ser “esperado”, pero es la razón por la que terminas con “df dice espacio, ZFS dice no”.

Decisión: Si la capacidad es el cuello de botella, borra u offloadea los snapshots que retienen más espacio—después de verificar que no sean necesarios para replicación o cumplimiento.

Tarea 12: Simula el impacto del rollback listando lo que sería destruido

cr0x@server:~$ zfs list -t snapshot -o name -s creation tank/app | awk '/@pre_upgrade/{flag=1}flag{print}'
tank/app@pre_upgrade
tank/app@post_upgrade
tank/app@autosnap_2025-12-26_03-00
tank/app@autosnap_2025-12-26_04-00
tank/app@before_rollback_2025-12-26T0235

Significado: Esto es el “futuro” relativo a @pre_upgrade. Si haces rollback con flags de destrucción, estos están en alcance.

Decisión: Si cualquier snapshot listado es necesario (ancla de replicación, punto de auditoría, “before_rollback”), no lo destruyas. Usa recuperación basada en clones o un enfoque más quirúrgico.

Tarea 13: Realiza el rollback (dataset único), solo después de hacerlo aburrido

cr0x@server:~$ sudo systemctl stop app.service
cr0x@server:~$ zfs rollback tank/app@pre_upgrade
cr0x@server:~$ sudo systemctl start app.service
cr0x@server:~$ systemctl status --no-pager app.service
● app.service - Example App
     Loaded: loaded (/etc/systemd/system/app.service; enabled)
     Active: active (running)

Significado: Se detuvo el servicio para evitar escrituras durante el rollback. El rollback tuvo éxito y el servicio volvió.

Decisión: Si el servicio sigue fallando, ahora estás en territorio de consistencia de aplicación (migraciones, cachés, deriva de esquema). Pasa a la recuperación a nivel de aplicación, no a más maniobras de ZFS.

Tarea 14: Si debes destruir snapshots más nuevos durante el rollback, hazlo explícito y comprende el radio de impacto

cr0x@server:~$ zfs rollback -r tank/app@pre_upgrade
cr0x@server:~$ zfs list -t snapshot -o name -s creation tank/app | tail -n 3
tank/app@autosnap_2025-12-26_01-00
tank/app@autosnap_2025-12-26_02-00
tank/app@pre_upgrade

Significado: Los snapshots más nuevos han desaparecido. Eso puede incluir anclas de replicación. Por eso verificas primero.

Decisión: Acepta esto solo si has confirmado que puedes resembrar la replicación y tienes preservado un snapshot “before_rollback” (posiblemente en otro sistema) por si lo necesitas después.

Tarea 15: Valida implicaciones de replicación comprobando bookmarks (si se usan)

cr0x@server:~$ zfs list -t bookmark -o name,creation tank/app
NAME                         CREATION
tank/app#replica_base_01      Fri Dec 20 03:00 2025
tank/app#replica_base_02      Wed Dec 25 03:00 2025

Significado: Los bookmarks pueden preservar puntos de envío incluso si los snapshots se eliminan. Si tu estrategia de replicación depende de bookmarks, tienes más flexibilidad.

Decisión: Si tienes un bookmark adecuado, podrías mantener incrementales vivos. Si no, planifica un re-seed completo tras un rollback destructivo.

Tarea 16: Comprueba restricciones relacionadas con el cifrado antes de clonar o enviar

cr0x@server:~$ zfs get -H -o property,value encryption,keylocation,keystatus tank/app
encryption   aes-256-gcm
keylocation  file:///etc/zfs/keys/tank_app.key
keystatus    available

Significado: Los datasets cifrados necesitan que las claves estén cargadas para operaciones de montaje/receive dependiendo de tu diseño. El rollback en sí no “necesita” claves de la misma manera, pero montar clones sí.

Decisión: Asegura que el material de llaves esté disponible antes de clonar/montar para recuperación. Si faltan claves, arregla la gestión de llaves primero—hacer rollback a ciegas no recuperará llaves.

Guion de diagnóstico rápido

Cuando el rollback está sobre la mesa, normalmente te estás haciendo una de dos preguntas: “¿Puedo rebobinar de forma segura?” y “Si rebobino, realmente arreglará el sistema?” Este guion está optimizado para velocidad y mínimo daño colateral.

Primero: Confirma que estás arreglando la capa correcta

  1. ¿El estado de fallo está puramente en disco? Archivos faltantes, configuración equivocada, artefacto de despliegue corrupto. Si sí, ZFS puede ayudar directamente.
  2. ¿El fallo está en el mundo externo de la aplicación? Incompatibilidad de esquema de base de datos, secretos cacheados, API downstream incompatible, mensajes encolados. Si sí, el rollback puede ser irrelevante o dañino.
  3. ¿Es realmente hardware o salud de la pool? Si las lecturas fallan o la latencia es enorme, el rollback no cambiará la física.

Segundo: Identifica la unidad mínima segura de rollback

  1. Mapea puntos de montaje a datasets (zfs list -o name,mountpoint).
  2. Elige el dataset más específico que contenga el problema.
  3. Comprueba si existen datasets hijos; no hagas rollback accidentalmente de hijos que no deban moverse.

Tercero: Comprueba las restricciones de “no romper el futuro”

  1. Cadena de replicación: ¿Borrar snapshots más nuevos romperá envíos incrementales?
  2. Clones: ¿Hay clones dependientes que bloquearán o serán destruidos?
  3. Espacio: ¿Tienes un margen de espacio libre seguro para clonar/migrar si hace falta?
  4. Coordinación: ¿Puedes detener escritores limpiamente? Si no, estás haciendo rollback sobre un objetivo en movimiento.

Chequeo rápido de cuellos de botella si las cosas están lentas (común en incidentes con muchos snapshots)

cr0x@server:~$ zpool iostat -v 1 5
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        8.21T   640G    120    980  32.1M  210M
  raidz2-0                  8.21T   640G    120    980  32.1M  210M
    sda                         -      -     15    130  4.0M   28.0M
    sdb                         -      -     14    126  3.9M   27.5M
    sdc                         -      -     46    340  12.2M  72.1M
    sdd                         -      -     45    340  12.0M  72.0M
--------------------------  -----  -----  -----  -----  -----  -----

Significado: Carga desigual por disco puede sugerir un disco fallando, un vdev caliente o patrones de IO patológicos. La alta churn de snapshots más espacio libre bajo también puede convertir escrituras en miseria.

Decisión: Si IO es el cuello de botella, estabiliza el rendimiento (espacio libre, pausa de jobs pesados, planificación de scrubs) antes de hacer grandes operaciones de snapshot.

Tres micro-historias corporativas desde las trincheras

Micro-historia 1: El incidente causado por una suposición equivocada

Una empresa mediana operaba una flota de servidores de aplicación con ZFS para estado local: configuraciones, archivos pequeños y algunos artefactos “temporales” que nunca fueron temporales. Tenían la costumbre de snapshotear toda la pool tank cada hora porque era fácil. Y, para ser justos, funcionó durante meses.

Entonces un ingeniero intentó revertir un deploy fallido. Vieron tank@pre_deploy y asumieron que hacer rollback de tank desharía el cambio ordenadamente. Lo deshizo. También revirtió datasets no relacionados: el directorio spool de una cola de mensajes y el estado de un agente de monitoreo. El spool ahora contenía mensajes que ya se habían procesado. El agente de monitoreo olvidó lo que había visto. El sistema no se cayó. Mintió.

Lo realmente caro fue la latencia: el incidente no se anunció con un estruendo. Apareció como trabajo duplicado, métricas inconsistentes y preguntas de “¿por qué la cola está re-reproduciendo?” tres horas después. Todos tuvieron que reconstruir lo sucedido a partir de logs—logs que también estaban en ZFS y se habían revertido.

La solución no fue mágica. Dividieron los datasets para que la unidad de rollback coincidiera con la unidad de propiedad: tank/app, tank/queue, tank/monitoring. También dejaron de tratar el rollback a nivel de pool como una herramienta normal. Ahora “rollback” requiere nombrar el dataset explícitamente en el plan de cambios.

Micro-historia 2: La optimización que salió mal

Otra organización quiso recuperaciones más rápidas. Su idea: mantener snapshots más frecuentes, conservarlos más tiempo y confiar en rollback para la mayoría de “ups” operativos. Ajustaron su tooling de autosnap para conservar muchos snapshots por día. A los managers les gustó porque sonaba resiliente.

Lo que no modelaron fue la amplificación de escritura bajo presión de espacio. Los snapshots retienen bloques antiguos; los borrados no liberan espacio hasta que los snapshots caen; el espacio libre de la pool se redujo; las asignaciones se fragmentaron; el rendimiento degradó. El equipo de plataforma notó mayor latencia en picos de escritura, pero parecía un problema de aplicación porque la pool estaba “saludable”.

Entonces ocurrió un incidente real: una migración de esquema mala. Quisieron hacer rollback del dataset de la base de datos. Pero no pudieron facilmente, porque el receptor de replicación esperaba una cadena de snapshots que ahora abarcaba una gran línea de tiempo, y la pool tenía poco espacio para clonar e investigar. Su diseño de “recuperaciones más rápidas” los forzó a la recuperación más lenta posible: re-seed completo más reconciliación a nivel de aplicación.

Después mantuvieron los snapshots frecuentes, pero acortaron la retención en los datasets más calientes, introdujeron holds solo para snapshots pre-cambio y aplicaron una política mínima de espacio libre. Su mejor optimización terminó siendo una alerta aburrida: “pool < 20% libre”.

Micro-historia 3: La práctica aburrida pero correcta que salvó el día

Un servicio relacionado con pagos (sin nombres, sin drama) corría en ZFS con control de cambios estricto. Antes de cualquier deploy, su pipeline tomaba un snapshot llamado @pre_change_$ticket. El snapshot se sujetaba con una etiqueta y se replicaba automáticamente a un sistema secundario. Nada sofisticado. Solo consistencia.

Una noche una dependencia actualizó con un cambio sutil en una configuración por defecto. El servicio empezó a rechazar peticiones válidas. SRE fue paginado, y en minutos tuvieron una decisión clara: el problema comenzó en el despliegue, y su snapshot pre-cambio existía, estaba retenido y ya estaba fuera de host.

Ni siquiera hicieron rollback de inmediato. Clonaron @pre_change, compararon configuraciones y encontraron el cambio de default. Parchearon el config en caliente. No fue necesario rollback, no se rompió la cadena de replicación y el informe de incidente tuvo una línea de tiempo clara porque también existía el snapshot del estado roto.

No fue glamoroso. Fue el equivalente a cepillarse los dientes en sistemas. Y funcionó.

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

1) “Rollback falló: el dataset tiene clones dependientes”

Síntomas: Errores del comando rollback que mencionan clones o “dataset is busy” o dependencias de clone.

Causa raíz: Un snapshot que intentas retroceder es el origen de un clone, o el dataset está actualmente montado y en uso activo.

Solución: Lista clones del snapshot, decide si conservarlos y pivota a recuperación basada en clones si no puedes destruirlos. Detén servicios y desmonta si solo está “ocupado”. Usa zfs list -t snapshot -o name,clones y lsof/fuser en el punto de montaje si hace falta.

2) “Hicimos rollback y la app sigue rota”

Síntomas: Los archivos parecen correctos, pero persisten errores de aplicación; la base de datos se queja; cachés no coinciden.

Causa raíz: Estado a nivel de aplicación fuera del dataset: cambios de esquema, colas externas, dependencias remotas o expectativas de journaling.

Solución: Trata el rollback solo como el primer paso. Coordina la recuperación de la aplicación: recuperación de crash de la base de datos, logs undo/redo, comprobaciones de versión de esquema, limpieza de cachés o revertir solo el dataset de artefactos en lugar de la base de datos.

3) “Rollback destruyó snapshots y la replicación ahora está atascada”

Síntomas: zfs send incremental falla; el receptor se queja por snapshots faltantes; herramientas de replicación fallan tras el rollback.

Causa raíz: Rollback destructivo (-r/-R) borró snapshots que eran la base de los incrementales.

Solución: Re-seed la replicación con un envío completo, o usa bookmarks si tu estrategia las soporta. Para el futuro: nunca destruyas snapshots usados como anclas de replicación; reténlos hasta que el receptor confirme.

4) “No recuperó espacio tras borrar datos”

Síntomas: Borras gigabytes, pero zfs list muestra poco cambio; la pool sigue llena; las escrituras se enlentecen.

Causa raíz: Los snapshots están reteniendo los bloques borrados.

Solución: Identifica qué snapshots tienen alto USED y poda según requisitos de retención/replicación. Considera dividir datasets para que directorios de alta rotación no fijen espacio en todo el servicio.

5) “Hicimos rollback del dataset equivocado”

Síntomas: Servicios no relacionados retroceden; logs desaparecen; el monitoreo muestra viajes en el tiempo; aparecen varios equipos.

Causa raíz: El mapeo mountpoint→dataset fue asumido, no verificado. O se ejecutó rollback a nivel de pool.

Solución: Siempre mapea el punto de montaje al dataset y haz rollback solo de ese dataset. Usa nombres de dataset explícitos en los runbooks. Si necesitas deshacer cambios en múltiples datasets, haz snapshots coordinados (ver listas de verificación) y revierte como un conjunto coordinado.

6) “Rollback completado, pero permisos/ACL se comportan raro”

Síntomas: Errores de acceso o cambios en la evaluación de ACL tras rollback; los archivos “se ven” bien pero se comportan diferente.

Causa raíz: Propiedades del dataset (tipo de ACL, modo xattr) o manejo de ACL a nivel de SO cambiaron. Los snapshots no revierten propiedades del dataset.

Solución: Compara salidas de zfs get contra la línea base; restaura propiedades vía gestión de configuración. Trata las propiedades como código.

7) “Rollback en dataset cifrado falla al montar clone”

Síntomas: El clone existe pero no se monta; estado de clave no disponible; errores de tooling relacionados con claves.

Causa raíz: Claves no cargadas, keylocation incorrecto o flujo operativo que asume claves presentes en el host de recuperación.

Solución: Asegura que las claves estén cargadas y accesibles en el host donde clonas/montas. Verifica con zfs get keystatus. Si replicás datasets cifrados, ten un plan de gestión de claves que funcione durante incidentes.

8) “Usamos rollback para recuperar un archivo y empeoramos todo”

Síntomas: Un archivo faltante se convierte en un rollback completo del servicio, perdiendo escrituras legítimas desde el momento del snapshot.

Causa raíz: Usar rollback de dataset cuando necesitabas restauración a nivel de archivo.

Solución: Monta/explora el snapshot o clónalo y copia rutas específicas de vuelta. Rollback es el último recurso para reversiones amplias, no tu herramienta predeterminada de undelete.

Broma #2: Si tu plan de rollback es “simplemente haremos rollback”, felicidades—has inventado una estrategia de backups con la confianza de una galleta de la fortuna.

Listas de verificación / plan paso a paso

Checklist A: Plan “Necesito restaurar unos pocos archivos” (sin rollback)

  1. Identifica el dataset de la ruta (zfs list -o name,mountpoint).
  2. Lista snapshots alrededor del tiempo del incidente.
  3. Crea un snapshot del estado actual del incidente y retenlo.
  4. Clona el snapshot objetivo a un dataset de recuperación.
  5. Copiar archivos desde el clone al vivo (preservando propiedad/ACLs).
  6. Valida el comportamiento de la app. Conserva el clone hasta estar seguro.

Checklist B: Plan “Revertir este dataset con seguridad”

  1. Detén escritores. Para systemd service, modo mantenimiento de la app, o al menos bloquea escrituras.
  2. Confirma la salud de la pool. Si está degradada, no añadas más caos.
  3. Confirma los límites del dataset. No hagas rollback de la pool salvo que quieras asumir todos los problemas.
  4. Snapshot del estado actual. Ponle un nombre claro y aplica un hold.
  5. Revisa clones. Si existen clones dependientes, decide si el rollback es factible.
  6. Comprueba consecuencias de “snapshots más nuevos”. Determina si puedes mantenerlos o debes destruirlos.
  7. Considera un ensayo clonado primero. Si no estás seguro, clona y prueba el arranque de la app en el clone.
  8. Rollback. Usa la forma menos destructiva que funcione. Evita -R salvo que sea necesario.
  9. Arranca servicios y valida. Valida no solo “servicio activo”, sino corrección y sanidad de datos.
  10. Limpiar responsablemente. Libera holds cuando sea seguro, elimina clones temporales y documenta el snapshot usado.

Checklist C: Rollback coordinado entre múltiples datasets

Aquí es donde los equipos se queman. Estado multi-dataset (app + db + cola) necesita snapshots coordinados y rollback coordinado, o tendrás “internamente consistente pero mutuamente inconsistente”.

  1. Detén toda la pila o ponla en modo quiescente.
  2. Crea un snapshot en cada dataset con el mismo token de nombre (ejemplo: @pre_change_TICKET).
  3. Sujeta esos snapshots bajo una etiqueta “incident” o “change”.
  4. Al revertir, haz rollback del conjunto en un orden definido (usualmente primero cola/consumidores, luego db, luego app) y valida cada capa.

Preguntas frecuentes

1) ¿El rollback de ZFS borra datos permanentemente?

El rollback descarta los cambios del dataset vivo hechos después del snapshot. Si además destruyes snapshots más nuevos (con -r/-R), entonces sí, esa historia se pierde a menos que esté replicada en otro lado.

2) ¿Cuál es la diferencia entre rollback y clonar un snapshot?

El rollback rebobina el dataset existente en sitio. Un clone crea un nuevo dataset escribible basado en el snapshot. Los clones son más seguros cuando dudas, necesitas recuperación de archivos o quieres probar arranque/app sin tocar producción.

3) ¿Puedo hacer rollback de solo un directorio?

No. El rollback se aplica a un dataset. Si quieres “solo un directorio”, usa un navegador de snapshots (como .zfs/snapshot donde esté disponible) o clona y copia el directorio de vuelta.

4) ¿Por qué el rollback está bloqueado por “existen snapshots más nuevos”?

ZFS evita la destrucción accidental de la línea de tiempo de snapshots. Puedes sobrescribirlo, pero ZFS quiere que admitas explícitamente que estás borrando el futuro.

5) ¿El rollback restaurará propiedades del dataset como compression o recordsize?

No. Las propiedades no forman parte del estado por snapshot como los contenidos de archivos. Si un cambio de propiedad causó el problema, corrige la propiedad directamente y versiona la política en la gestión de configuración.

6) ¿Cómo interactúa el rollback con la replicación?

La replicación depende de la continuidad de snapshots. Si borras snapshots que fueron enviados (o que se esperaban como base incremental), puedes romper incrementales y requerir un re-seed completo. Usa holds para anclas de replicación y planifica el rollback para no borrarlos a la ligera.

7) ¿Es seguro el rollback para bases de datos?

Depende. Si la base de datos puede recuperarse desde una imagen consistente por crash y si coordinas con réplicas, herramientas PITR y migraciones de esquema. Si no puedes articular esas dependencias, prefiere clonar y validar o métodos de restauración nativos de la base de datos.

8) ¿Cuál es la forma de “deshacer” más segura si no estoy seguro qué cambió?

Toma un snapshot del estado actual (y reténlo), luego clona un snapshot conocido bueno y compara. Si el diff muestra un conjunto pequeño de archivos, restaura esos. El rollback es para cuando estás seguro de que todo el dataset debe rebobinar.

9) ¿Cuándo debo usar holds?

Usa holds para cualquier snapshot que no deba desaparecer: snapshots pre-cambio, snapshots de evidencia de incidente, anclas de replicación y snapshots por cumplimiento. Libera holds deliberadamente cuando el periodo de riesgo haya pasado.

10) ¿El rollback requiere desmontar el dataset?

No siempre, pero detener escritores es el requisito real. En la práctica, detén el servicio y asegúrate de que nadie esté escribiendo activamente. Si el dataset está ocupado, desmonta o identifica el proceso que lo mantiene.

Conclusión: próximos pasos que puedes hacer

El rollback es una herramienta afilada. Puede salvar una noche, un trimestre o tu credibilidad. Pero la forma segura no es “teclear rollback más rápido”. La forma segura es reducir la incertidumbre y estrechar el radio de impacto.

Haz lo siguiente:

  • Divide datasets por propiedad y dominio de rollback. Si dos servicios comparten un dataset, tu riesgo de rollback ya está incorporado.
  • Estandariza snapshots pre-cambio con holds. Hazlos automáticos y aburridos, y réplicalos si puedes.
  • Practica recuperación clonando primero. Haz que “clonar, diff, copiar de vuelta” sea la memoria muscular por defecto.
  • Documenta tu política de flags destructivos. ¿Cuándo se permite -r? ¿Cuándo está prohibido? ¿Quién lo firma?
  • Haz un game day: rompe una configuración, recupérala con snapshots y repítelo bajo condiciones de “poco espacio”. Ese es el verdadero examen.

Si tu respuesta a incidentes depende de heroicidades, no tienes una respuesta a incidentes. Tienes una cita recurrente con el caos. El rollback de ZFS, hecho con seguridad, es cómo cancelas esa cita.

← Anterior
Debian 13: el nuevo nombre de interfaz rompió la red — nombres estables que sobreviven reinicios (caso #7)
Siguiente →
WannaCry: el ransomware que recordó a todos que existen los parches

Deja un comentario