Llevaba años oyendo que ZFS era la mejor decisión que podías tomar para el almacenamiento de tu homelab. Tardé demasiado en hacer el salto porque siempre me parecía que era demasiado complejo, que necesitaba hardware específico, que era “cosa de empresas”. Todo eso era mentira, pero entiendo por qué creí que era verdad.
La funcionalidad que me terminó de convencer fue los snapshots. Y este post es básicamente un argumento de por qué deberías conocerlos aunque ya tengas algún sistema de backup funcionando.
Qué es un snapshot de ZFS (en términos simples)#
Un snapshot es una foto instantánea del estado de un dataset en un momento determinado. Ocupa casi cero espacio cuando lo creas porque no copia datos, solo registra qué bloques existían en ese momento. A medida que los datos cambian, el snapshot va guardando los bloques anteriores, por eso su tamaño crece con el tiempo.
La parte importante: son casi instantáneos. Hacer un snapshot de un dataset de 500GB tarda menos de un segundo. No hay copia de datos, no hay E/S de disco masiva, no hay impacto en el rendimiento del sistema. Es una operación de metadatos.
Esto los hace fundamentalmente distintos a cualquier sistema de backup tradicional. No tienes que esperar a las 3AM para que termine un rsync de 4 horas. Puedes hacer snapshots cada hora, cada 15 minutos, lo que necesites.
Conceptos básicos que necesitas entender#
Antes de los comandos, unos conceptos que se repiten:
Pool: el grupo de discos que forman tu almacenamiento ZFS. Puede ser un solo disco, un espejo RAID-1, un RAIDZ.
Dataset: una unidad lógica dentro del pool. Como una carpeta, pero con propiedades propias. Puedes tener datasets anidados.
Snapshot: la foto del estado de un dataset. Se nombra con dataset@nombre-snapshot.
Clone: un dataset nuevo creado a partir de un snapshot. Al principio comparte todos los bloques con el snapshot original.
Send/receive: sistema para enviar snapshots de un pool a otro, ya sea en el mismo servidor o en una máquina remota.
Instalación y configuración inicial#
En Debian/Ubuntu:
| |
Crear un pool con un solo disco (para pruebas, no para producción):
| |
Crear un pool en espejo (RAID-1) con dos discos:
| |
Ver el estado del pool:
| |
Ver los datasets:
| |
Por defecto, el pool en sí es un dataset. Si creas un dataset llamado datos dentro del pool:
| |
Snapshots: los comandos del día a día#
Crear un snapshot:
| |
El nombre después del @ es libre. Yo uso fechas, pero puedes usar lo que quieras.
Listar los snapshots de un dataset:
| |
Ver cuánto ocupa cada snapshot:
| |
El campo used es el espacio que ocupa el snapshot (los bloques que han cambiado desde que se creó). El campo referenced es el tamaño total de los datos que ese snapshot puede restaurar.
Borrar un snapshot:
| |
Rollback: volver atrás en el tiempo#
Aquí es donde los snapshots te salvan la vida. Has editado un archivo de configuración y ahora nada funciona. Has borrado una carpeta sin querer. Has hecho una actualización que salió mal.
Volver al estado del snapshot:
| |
Esto revierte el dataset al estado exacto cuando se hizo el snapshot. Todo lo que pasó después desaparece.
Importante: por defecto, no puedes hacer rollback a un snapshot si hay snapshots más recientes. Tienes que borrarlos primero, o usar el flag -r para borrarlos automáticamente:
| |
Ojo con el -r, porque borra los snapshots intermedios. Asegúrate de que realmente quieres volver a ese punto y no a uno más reciente.
Acceder a archivos del snapshot sin restaurar#
No siempre necesitas un rollback completo. A veces solo quieres recuperar un archivo concreto de hace dos horas.
ZFS monta los snapshots en un directorio especial dentro de cada dataset:
| |
Ahí verás todos los snapshots como carpetas normales. Puedes navegar dentro, copiar archivos concretos, ver el estado del directorio en ese momento. Sin restaurar nada, sin interrumpir el servicio.
Esta característica me ha salvado múltiples veces. Borré sin querer un archivo de configuración que había tardado horas en escribir. Con ZFS simplemente fui al directorio .zfs/snapshots/, copié el archivo de vuelta, y listo. 30 segundos de operación.
Automatización con sanoid#
Hacer snapshots a mano está bien para aprender, pero para producción necesitas automatización. Sanoid es la herramienta que uso para esto.
Instalar:
| |
Configurar en /etc/sanoid/sanoid.conf:
| |
Esta configuración mantiene 24 snapshots horarios, 30 diarios y 6 mensuales. Los más viejos se borran automáticamente.
Activar el timer de systemd para que corra cada hora:
| |
Desde ese momento, sanoid crea y limpia snapshots automáticamente. El comando sanoid --cron es el que hace el trabajo, y systemd lo llama según el schedule del timer.
Para ver el estado:
| |
ZFS send/receive: replicación a otro servidor#
Los snapshots locales te protegen de errores humanos y fallos de software, pero no de un fallo de disco o de que se te caiga el servidor al suelo. Para eso necesitas replicación offsite.
ZFS tiene un sistema de replicación incremental integrado: zfs send y zfs receive. La idea es simple: envías el snapshot inicial completo la primera vez, y después solo envías los cambios (incremental).
Primera vez (backup completo):
| |
Esto envía todo el contenido del snapshot al servidor remoto. Puede tardar mucho dependiendo del tamaño.
Después (incremental):
| |
Solo envía los bloques que cambiaron entre los dos snapshots. Normalmente esto es una fracción del tamaño total.
Para automatizar esto correctamente, la herramienta que más me gusta es syncoid (del mismo paquete que sanoid):
| |
Syncoid se encarga de toda la lógica: detecta qué snapshots existen en origen y destino, calcula el incremental correcto, lo envía. Puedes añadir esto a un cron o a un systemd timer.
En /etc/cron.d/syncoid-backup:
| |
Así cada noche a las 4AM se replica el dataset al servidor de backup.
ZFS en Proxmox#
Si usas Proxmox, ya tienes ZFS integrado de serie. Cuando configuras el almacenamiento de VMs en un pool ZFS, cada VM tiene su dataset y sus snapshots dentro de Proxmox.
Los snapshots de VMs en Proxmox con almacenamiento ZFS son casi instantáneos precisamente por esto. Proxmox llama a ZFS por debajo, y la operación es de metadatos. Cuando haces un snapshot de una VM de 100GB en Proxmox con ZFS, tarda 1-2 segundos. Con almacenamiento LVM tradicional, tardaría proporcionalmente al tamaño.
También puedes ver y gestionar los snapshots ZFS directamente desde la línea de comandos sin pasar por la interfaz de Proxmox:
| |
Y puedes usar syncoid para replicar VMs enteras a otro servidor Proxmox, cosa que es muy útil para tener una copia de tus VMs más importantes en otro nodo.
TrueNAS y ZFS#
TrueNAS está completamente construido sobre ZFS. Si tienes un NAS con TrueNAS (Scale o Core), ya estás usando ZFS aunque no lo hayas configurado explícitamente.
La interfaz web de TrueNAS expone la mayor parte de las funcionalidades de ZFS: puedes crear tareas periódicas de snapshots desde la web, configurar replicación a otro TrueNAS o servidor SSH, y ver el historial de snapshots de cada dataset.
Para replicación entre dos instancias de TrueNAS, hay asistentes que lo configuran todo. Seleccionas origen, destino, frecuencia, y TrueNAS genera y programa el syncoid por debajo.
Cuánto espacio consumen los snapshots#
Esta es la pregunta que más me hacían al principio. La respuesta es: depende de cuánto cambian tus datos.
Un snapshot de un dataset que no cambia nada ocupa prácticamente cero. El snapshot de un dataset de base de datos que recibe escrituras constantemente puede crecer rápido porque cada bloque modificado se mantiene en el snapshot anterior.
Para datasets de archivos estáticos (media, documentos, backups), los snapshots horarios de 24 horas van a ocupar muy poco espacio total, quizá un 5-10% extra del tamaño del dataset.
Para datasets con mucha actividad de escritura (bases de datos, logs), los snapshots crecen más rápido. Ahí tienes que calibrar cuántos snapshots mantener según el espacio disponible.
El comando para ver el uso de espacio del pool con detalle:
| |
Errores comunes cuando empiezas#
No usar nombres descriptivos en los snapshots. Al principio hacía snapshots con nombres tipo test1, prueba, backup. Semanas después no tenía ni idea de cuándo era cada uno ni por qué lo había creado. Ahora uso siempre timestamps o descripciones claras.
Olvidar que destroy es destructivo. zfs destroy mi-pool/datos borra el dataset completo con todos sus snapshots. No hay papelera. Si tienes datos importantes ahí, se van. Siempre verifico el nombre antes de ejecutar destroy.
No monitorizar el espacio del pool. ZFS no puede comprimir más allá del espacio físico disponible. Si el pool se llena al 80-90%, el rendimiento cae en picado. Configura alertas para el uso del pool.
Crear pools con un solo disco en producción. Para aprender está bien, pero para datos importantes siempre al menos un espejo con dos discos.
Mi configuración actual#
En mi homelab uso ZFS en el servidor principal para todos los datos que importan. Tengo sanoid configurado con snapshots horarios (24h), diarios (30 días) y mensuales (6 meses). Syncoid replica los datasets críticos a un segundo servidor cada noche.
El pool tiene un espejo de dos discos más un tercer disco como spare. Si falla un disco, ZFS degrada el espejo, me avisa, y el spare se incorpora automáticamente para reconstruir el espejo.
Para los datos más importantes (configuraciones, datos personales, proyectos activos), también hago un backup externo mensual con zfs send a un disco externo. Siguiendo la lógica 3-2-1: tres copias, en dos medios distintos, una offsite.
Empezar sin riesgo#
Si quieres probar ZFS sin comprometer datos importantes, la forma más segura es con un disco de sobra o incluso con archivos como “discos virtuales”:
| |
Así puedes experimentar con todos los comandos sin tocar datos reales. Cuando lo destruyas, simplemente borras el archivo y listo.
Una vez que ves en acción cómo funciona el rollback y el acceso a archivos históricos, entiendes por qué la gente que usa ZFS no quiere volver a ext4 o XFS para nada importante.