TL;DR — Resumo Rápido

Snapshots ZFS protegem dados no Linux com copy-on-write sem custo inicial. Aprenda a criar, reverter, clonar e replicar datasets com zfs send/receive e sanoid.

Os snapshots ZFS são uma das ferramentas de proteção de dados mais poderosas disponíveis no Linux. Ao contrário das abordagens tradicionais de backup que copiam datasets inteiros, os snapshots ZFS aproveitam a semântica de copy-on-write (COW) para capturar o estado exato de um sistema de arquivos em um ponto no tempo — instantaneamente e sem custo inicial de espaço. Este guia cobre desde os fundamentos do ZFS até pipelines de snapshots automatizados com sanoid e syncoid.

Pré-requisitos

  • Ubuntu 22.04/24.04 LTS (ou qualquer distro com OpenZFS 2.1+)
  • Um ou mais dispositivos de bloco para testes
  • Acesso com sudo
  • Familiaridade básica com nomes de dispositivos Linux (/dev/sd*, /dev/vd*)

Conceitos Fundamentais do ZFS

Copy-on-Write (COW): O ZFS nunca sobrescreve dados ativos no mesmo lugar. Quando um bloco é modificado, o ZFS escreve a nova versão em um local livre e atualiza atomicamente o ponteiro. O bloco antigo permanece intacto — é isso que os snapshots exploram.

Pools e Datasets: Um pool (zpool) é o contêiner de armazenamento de nível superior formado por um ou mais vdevs. Um dataset (zfs create) é um sistema de arquivos montável dentro de um pool.

Checksums: Cada bloco carrega um checksum de 256 bits. Na leitura, o ZFS verifica o checksum e pode se auto-reparar a partir de uma cópia redundante se o bloco primário estiver corrompido.


Instalando ZFS no Ubuntu

sudo apt update
sudo apt install zfsutils-linux -y
zfs --version

Criando Pools

# Espelho (equivalente a RAID-1)
sudo zpool create tank mirror /dev/sdb /dev/sdc

# RAIDZ1 — 1 disco de paridade, tolera 1 falha
sudo zpool create tank raidz /dev/sdb /dev/sdc /dev/sdd

# RAIDZ2 — 2 discos de paridade, tolera 2 falhas (recomendado para >=6 discos)
sudo zpool create tank raidz2 /dev/sd{b,c,d,e,f,g}
zpool status tank
zpool list

Gerenciamento de Datasets

# Dataset com compressão LZ4
zfs create -o compression=lz4 tank/data

# Ponto de montagem explícito
zfs set mountpoint=/srv/data tank/data

# Compressão zstd para melhor razão
zfs set compression=zstd tank/data

# Ajuste de recordsize para bancos de dados
zfs set recordsize=16K tank/postgres    # PostgreSQL
zfs set recordsize=128K tank/mysql      # MySQL InnoDB

# Quotas e reservas
zfs set quota=500G tank/data
zfs set reservation=100G tank/data

Propriedades de monitoramento:

Propriedade Significado
used Espaço consumido pelo dataset + seus snapshots
available Espaço livre que o dataset ainda pode usar
referenced Espaço apenas do dataset ativo (exclui snapshots)
compressratio Razão de compressão alcançada (ex. 2.14x)

Fundamentos de Snapshots

Criando Snapshots

# Snapshot único
zfs snapshot tank/data@2026-03-22

# Snapshot recursivo
zfs snapshot -r tank@2026-03-22

# Com timestamp do shell
zfs snapshot tank/data@$(date +%Y-%m-%dT%H%M)

Listando Snapshots

zfs list -t snapshot
zfs list -t snapshot -o name,used,referenced,creation

Revertendo (Rollback)

zfs rollback tank/data@2026-03-22

# Se existirem snapshots mais recentes
zfs rollback -r tank/data@2026-03-21

Acessar Conteúdo de um Snapshot sem Reverter

ls /srv/data/.zfs/snapshot/
# Restaurar um arquivo individual
cp /srv/data/.zfs/snapshot/2026-03-22/importante.sql /srv/data/restaurado.sql

Destruindo Snapshots

zfs destroy tank/data@2026-03-20
# Faixa de snapshots
zfs destroy tank/data@2026-03-01%2026-03-15

Clones: Snapshots Graváveis

Um clone é um dataset gravável derivado de um snapshot, ideal para ambientes de staging.

# Criar um clone
zfs clone tank/data@2026-03-22 tank/data-staging

# Ponto de montagem
zfs set mountpoint=/srv/staging tank/data-staging

# Promover o clone a independente
zfs promote tank/data-staging

Send/Receive: Replicação ZFS

Envio Completo Inicial

# Cópia local
zfs send tank/data@2026-03-22 | zfs receive backup/data

# Por SSH com compressão
zfs send -c tank/data@2026-03-22 | ssh backup-host zfs receive backup/data

Envios Incrementais

# -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 = inclui snapshots intermediários
zfs send -cI tank/data@2026-03-20 tank/data@2026-03-22 | \
  ssh backup-host zfs receive -F backup/data

Retomar Transferências Interrompidas

zfs get receive_resume_token backup/data
zfs send -t <token> | ssh backup-host zfs receive -s backup/data

Referência de Flags de Replicação

Flag Efeito
-c Comprime o stream
-i Incremental entre dois snapshots
-I Incremental incluindo snapshots intermediários
-R Replica dataset recursivamente
-s Salva estado de retomada no receptor
-v Saída detalhada

Snapshots Automatizados com 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 o Timer do Systemd

sudo systemctl enable --now sanoid.timer
sudo sanoid --take-snapshots --verbose
sudo sanoid --prune-snapshots --verbose

Syncoid para Replicação

syncoid tank/data backup-host:backup/data
syncoid --recursive tank backup-host:backup

Scrubbing e Auto-reparação

sudo zpool scrub tank
zpool status tank | grep -A5 scrub
echo "0 2 1 * * root /sbin/zpool scrub tank" | sudo tee /etc/cron.d/zfs-scrub

ZFS vs. Alternativas

Recurso ZFS Btrfs LVM + ext4 XFS
Copy-on-write Sim Sim Não Não
RAID integrado Sim (RAIDZ) Sim (limitado) Via LVM Não
Snapshots nativos Sim Sim Via LVM Não
Replicação send/receive Sim (nativo) Sim Não Não
Checksums / auto-reparação Sim Sim (limitado) Não Não
Compressão Sim (lz4, zstd) Sim Não Não
Cache ARC/L2ARC Sim Não Não Não
Maturidade em produção (Linux) Alta (OpenZFS) Média Muito alta Muito alta

Padrões de Produção

Boot Environments

sudo zfs snapshot -r rpool/ROOT/ubuntu@before-upgrade

Docker no ZFS

echo '{"storage-driver": "zfs"}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
zfs set recordsize=128K tank/docker

Recordsize para Bancos de Dados

Banco de Dados recordsize recomendado Motivo
PostgreSQL 8K ou 16K Coincide com página de 8K
MySQL InnoDB 16K Coincide com página InnoDB
MySQL MyISAM 128K Favorece varreduras sequenciais
MongoDB 16K Página WiredTiger padrão
SQLite 4K Coincide com página padrão

Casos Especiais e Advertências

  • Nunca importe o mesmo pool em dois hosts simultaneamente: causa split-brain e corrupção.
  • Deduplicação raramente vale a pena: Requer ~5 GB de RAM por TB de dados únicos.
  • Swap no ZFS: Evite usar um zvol ZFS como swap — podem ocorrer deadlocks sob pressão extrema de memória.

Resumo

  • Snapshots ZFS são cópias instantâneas e eficientes em espaço baseadas em copy-on-write.
  • Use zfs snapshot para snaps manuais e sanoid para gerenciamento automatizado por políticas.
  • zfs send | zfs receive replica datasets eficientemente — apenas blocos alterados trafegam pela rede.
  • O scrubbing mensal detecta corrupção silenciosa antes que se propague.
  • Snapshots no mesmo pool não substituem backups fora do pool — sempre replique para um host separado.

Artigos Relacionados