TL;DR — Resumen Rápido
Snapshots ZFS protegen datos Linux con copy-on-write sin costo. Aprende a crear, revertir, clonar y replicar datasets con zfs send/receive y sanoid.
Los snapshots ZFS son una de las herramientas de protección de datos más potentes disponibles en Linux. A diferencia de los enfoques tradicionales de backup que copian datasets completos, los snapshots ZFS aprovechan la semántica de copy-on-write (COW) para capturar el estado exacto de un sistema de archivos en un momento dado — de forma instantánea y sin costo inicial de espacio. Esta guía cubre desde los fundamentos de ZFS hasta pipelines de snapshots automatizados con sanoid y syncoid.
Requisitos Previos
- Ubuntu 22.04/24.04 LTS (o cualquier distro con OpenZFS 2.1+)
- Uno o más dispositivos de bloque para pruebas (discos reales o archivos loopback)
- Acceso con
sudo - Familiaridad básica con nombres de dispositivos Linux (
/dev/sd*,/dev/vd*)
Conceptos Fundamentales de ZFS
Copy-on-Write (COW): ZFS nunca sobreescribe datos activos en el mismo lugar. Cuando se modifica un bloque, ZFS escribe la nueva versión en una ubicación libre y actualiza atómicamente el puntero. El bloque antiguo permanece intacto — esto es lo que aprovechan los snapshots.
Pools y Datasets: Un pool (zpool) es el contenedor de almacenamiento de nivel superior formado por uno o más vdevs (dispositivos virtuales: espejos, franjas RAIDZ). Un dataset (zfs create) es un sistema de archivos montable dentro de un pool.
Checksums: Cada bloque lleva un checksum de 256 bits. En la lectura, ZFS verifica el checksum y puede auto-repararse desde una copia redundante si el bloque primario está corrupto, eliminando la corrupción silenciosa de datos.
Instalación de ZFS en Ubuntu
sudo apt update
sudo apt install zfsutils-linux -y
zfs --version
Creación de Pools
# Espejo (equivalente a RAID-1)
sudo zpool create tank mirror /dev/sdb /dev/sdc
# RAIDZ1 — 1 disco de paridad, tolera 1 fallo
sudo zpool create tank raidz /dev/sdb /dev/sdc /dev/sdd
# RAIDZ2 — 2 discos de paridad, tolera 2 fallos (recomendado para >=6 discos)
sudo zpool create tank raidz2 /dev/sd{b,c,d,e,f,g}
zpool status tank
zpool list
Gestión de Datasets
# Dataset con compresión LZ4
zfs create -o compression=lz4 tank/data
# Punto de montaje explícito
zfs set mountpoint=/srv/data tank/data
# Compresión zstd para mejor ratio
zfs set compression=zstd tank/data
# Ajuste de recordsize para bases de datos
zfs set recordsize=16K tank/postgres # PostgreSQL
zfs set recordsize=128K tank/mysql # MySQL InnoDB
# Cuotas y reservaciones
zfs set quota=500G tank/data
zfs set reservation=100G tank/data
Propiedades clave de monitoreo:
| Propiedad | Significado |
|---|---|
used | Espacio consumido por el dataset + sus snapshots |
available | Espacio libre que el dataset puede usar |
referenced | Espacio del dataset activo (excluye snapshots) |
compressratio | Ratio de compresión logrado (ej. 2.14x) |
Fundamentos de Snapshots
Crear Snapshots
# Snapshot único
zfs snapshot tank/data@2026-03-22
# Snapshot recursivo
zfs snapshot -r tank@2026-03-22
# Con timestamp del shell
zfs snapshot tank/data@$(date +%Y-%m-%dT%H%M)
Listar Snapshots
zfs list -t snapshot
zfs list -t snapshot -o name,used,referenced,creation
Revertir (Rollback)
zfs rollback tank/data@2026-03-22
# Si existen snapshots más recientes
zfs rollback -r tank/data@2026-03-21
Acceder al Contenido de un Snapshot sin Revertir
ls /srv/data/.zfs/snapshot/
# Restaurar un archivo individual
cp /srv/data/.zfs/snapshot/2026-03-22/importante.sql /srv/data/restaurado.sql
Eliminar Snapshots
zfs destroy tank/data@2026-03-20
# Rango de snapshots
zfs destroy tank/data@2026-03-01%2026-03-15
Clones: Snapshots Escribibles
Un clon es un dataset escribible derivado de un snapshot, ideal para entornos de staging.
# Crear un clon
zfs clone tank/data@2026-03-22 tank/data-staging
# Punto de montaje
zfs set mountpoint=/srv/staging tank/data-staging
# Promover el clon a independiente
zfs promote tank/data-staging
Send/Receive: Replicación ZFS
Envío Completo Inicial
# Copia local
zfs send tank/data@2026-03-22 | zfs receive backup/data
# Por SSH con compresión
zfs send -c tank/data@2026-03-22 | ssh backup-host zfs receive backup/data
Envíos Incrementales
# -i = incremento único
zfs send -ci tank/data@2026-03-21 tank/data@2026-03-22 | \
ssh backup-host zfs receive -F backup/data
# -I = incluye snapshots intermedios
zfs send -cI tank/data@2026-03-20 tank/data@2026-03-22 | \
ssh backup-host zfs receive -F backup/data
Reanudar Transferencias Interrumpidas
# Obtener token de reanudación
zfs get receive_resume_token backup/data
# Reanudar el envío
zfs send -t <token> | ssh backup-host zfs receive -s backup/data
Referencia de Flags de Replicación
| Flag | Efecto |
|---|---|
-c | Comprime el stream |
-i | Incremental entre dos snapshots |
-I | Incremental incluyendo snapshots intermedios |
-R | Replica dataset recursivamente |
-s | Guarda estado de reanudación en el receptor |
-v | Salida detallada |
Snapshots Automatizados con Sanoid
Instalar Sanoid
sudo apt install sanoid -y
Configurar Políticas
# /etc/sanoid/sanoid.conf
[tank/data]
use_template = production
recursive = yes
[template_production]
hourly = 24
daily = 30
monthly = 3
autosnap = yes
autoprune = yes
Habilitar el Timer de Systemd
sudo systemctl enable --now sanoid.timer
# Prueba manual
sudo sanoid --take-snapshots --verbose
sudo sanoid --prune-snapshots --verbose
Syncoid para Replicación
syncoid tank/data backup-host:backup/data
syncoid --recursive tank backup-host:backup
Scrubbing y Auto-reparación
# Iniciar scrub
sudo zpool scrub tank
# Verificar estado
zpool status tank | grep -A5 scrub
# Programar scrubs mensuales
echo "0 2 1 * * root /sbin/zpool scrub tank" | sudo tee /etc/cron.d/zfs-scrub
ZFS vs. Alternativas
| Característica | ZFS | Btrfs | LVM + ext4 | XFS |
|---|---|---|---|---|
| Copy-on-write | Sí | Sí | No | No |
| RAID integrado | Sí (RAIDZ) | Sí (limitado) | Vía LVM | No |
| Snapshots nativos | Sí | Sí | Vía LVM | No |
| Replicación send/receive | Sí (nativo) | Sí | No | No |
| Checksums / auto-reparación | Sí | Sí (limitado) | No | No |
| Compresión | Sí (lz4, zstd) | Sí | No | No |
| Caché ARC/L2ARC | Sí | No | No | No |
| Madurez en producción (Linux) | Alta (OpenZFS) | Media | Muy alta | Muy alta |
Patrones de Producción
Boot Environments
# Crear entorno de arranque antes de actualizar
sudo zfs snapshot -r rpool/ROOT/ubuntu@before-upgrade
Docker sobre ZFS
echo '{"storage-driver": "zfs"}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
zfs set recordsize=128K tank/docker
Recordsize para Bases de Datos
| Base de Datos | recordsize recomendado | Razón |
|---|---|---|
| PostgreSQL | 8K o 16K | Coincide con página de 8K |
| MySQL InnoDB | 16K | Coincide con página InnoDB |
| MySQL MyISAM | 128K | Favorece escaneos secuenciales |
| MongoDB | 16K | Página WiredTiger por defecto |
| SQLite | 4K | Coincide con página por defecto |
Casos Especiales y Advertencias
- Nunca importes el mismo pool en dos hosts simultáneamente: causa split-brain y corrupción.
- snapshot hold vs. destroy: Usa
zfs holdpara anclar un snapshot durante un send activo. - Deduplicación raramente vale la pena: Requiere ~5 GB de RAM por TB de datos únicos.
- Swap en ZFS: Evita usar un zvol ZFS como swap — pueden ocurrir deadlocks bajo presión extrema de memoria.
Resumen
- Los snapshots ZFS son copias instantáneas y eficientes en espacio basadas en copy-on-write.
- Usa
zfs snapshotpara snaps manuales y sanoid para gestión automatizada por políticas. zfs send | zfs receivereplica datasets eficientemente — solo los bloques cambiados viajan por la red.- El scrubbing mensual detecta corrupción silenciosa antes de que se propague.
- Los snapshots en el mismo pool no sustituyen los backups fuera del pool — siempre replica a un host separado.