ZFS no FreeBSD e Linux: quanto de RAM ele consome
Veja o que o ZFS entrega em uma VPS, como o ARC consome RAM e quando checksums, snapshots, send/receive e compressão compensam o custo.
O que o ZFS oferece e o que exige
O ZFS no FreeBSD e no Linux usa atualmente a mesma base de código, o OpenZFS, por isso as funcionalidades são iguais nos dois sistemas. Um servidor com ZFS obtém dados com checksums, snapshots que não ocupam espaço até os dados serem alterados, replicação com zfs send e compressão que requer apenas a definição de uma propriedade. O que ele exige é memória: o ARC (adaptive replacement cache) utiliza por predefinição uma parte significativa da RAM, e numa VPS (virtual private server) com 2 GB ou 4 GB essa memória é precisamente a que a sua aplicação pretendia utilizar.
Este guia avalia o ZFS numa VPS alugada com um ou dois discos virtuais, e não numa máquina de armazenamento com quarenta baias de discos. As funcionalidades que continuam úteis nesse cenário são as que justificam o seu tempo. Vale a pena conhecer as que não se aplicam antes de criar um pool.
OpenZFS no FreeBSD e no Linux: uma base de código, duas formas de empacotamento
O FreeBSD inclui o ZFS no sistema base desde o FreeBSD 7.0, em 2008, inicialmente como funcionalidade experimental. Desde o OpenZFS 2.0, em dezembro de 2020, o FreeBSD e o Linux compilam a partir da mesma árvore de código-fonte. Por isso, zfs e zpool comportam-se da mesma forma nos dois sistemas, e um pool criado num sistema pode ser importado no outro.
A razão pela qual o ZFS é um pacote no Linux e faz parte do sistema base no FreeBSD é o licenciamento. O OpenZFS está sob a CDDL (common development and distribution license). O kernel Linux está sob a GPL (general public license) versão 2. O projeto do kernel considera as duas licenças incompatíveis. Por isso, o código do ZFS não é integrado no Linux mainline, e cada distribuição decide como o disponibiliza. O FreeBSD não tem esse conflito, portanto o ZFS já está incluído. Essa é toda a explicação prática: uma diferença de empacotamento, sem necessidade de tomar partido.
A SSD Nodes não oferece imagens do FreeBSD. Portanto, num servidor alugado aqui, aplica-se a parte deste guia relativa ao Linux. Se executar o FreeBSD noutro local, um servidor FreeBSD obtém o ZFS sem ser necessário compilar um módulo ou sobreviver a uma atualização do kernel.
Instalar o ZFS e criar um pool
No Ubuntu, o módulo vem incluído nos pacotes do kernel, por isso só precisa de instalar os comandos.
sudo apt update
sudo apt install -y zfsutils-linux
zfs versionzfs version apresenta duas linhas: a versão do userland e a versão do módulo do kernel. Uma única linha significa que o módulo não foi carregado. O pacote está no componente universe, que as imagens Ubuntu Server ativam por predefinição; se o apt não o encontrar, execute primeiro sudo add-apt-repository universe.
No Debian, os pacotes estão no componente contrib e o módulo é compilado na sua máquina pelo DKMS (dynamic kernel module support). Adicione contrib à linha Components: em /etc/apt/sources.list.d/debian.sources, execute sudo apt update e, em seguida:
sudo apt install -y linux-headers-$(dpkg --print-architecture) zfs-dkms zfsutils-linuxA instalação compila o módulo e apresenta Building initial module for 6.12.0-..., o que demora alguns minutos. Tenha presente o que isto significa: cada atualização do kernel recompila o módulo, e uma compilação que falhe deixa o pool sem ser importado até corrigir o problema.
No FreeBSD, nada é instalado. Ative o serviço e inicie-o.
sysrc zfs_enable=YES
service zfs startAgora, o pool. Consulte primeiro os caminhos estáveis dos dispositivos, porque /dev/vdb é atribuído pela ordem de deteção e pode mudar quando liga outro volume.
ls -l /dev/disk/by-id/
sudo zpool create -o ashift=12 tank /dev/disk/by-id/virtio-abc123def456
zpool status tankzpool status deve apresentar state: ONLINE, com o seu dispositivo listado em tank. ashift=12 fixa o menor bloco do pool em 4 KiB, o que corresponde aos SSD atuais e não pode ser alterado depois da criação.
A maioria das imagens alugadas arranca a partir de uma raiz ext4, por isso o ZFS é usado aqui como um pool de dados num segundo volume, e não como o sistema de ficheiros raiz. Confirme que o dispositivo é realmente o que pensa antes de o utilizar, porque confirmar o disco NVMe que lhe foi vendido demora um minuto, enquanto uma reconstrução demora uma tarde.
As somas de verificação só reparam dados quando o pool tem redundância
Cada bloco que o ZFS grava inclui uma soma de verificação, que é validada em cada leitura. A deteção funciona sempre. A reparação precisa de uma segunda cópia.
Num pool com um único disco, o ZFS informa-o do problema e fica por aí. zpool status -v apresenta-o desta forma:
status: One or more devices has experienced an error resulting in data
corruption.
action: Restore the file in question if possible. Otherwise restore the
entire pool from backup.
errors: Permanent errors have been detected in the following files:
/tank/data/archive.tarO ficheiro danificado é identificado. O ext4 teria devolvido esses bytes sem qualquer aviso, por isso esta informação já é útil. O ZFS continua sem conseguir reparar o ficheiro, porque não existe uma segunda cópia no pool a partir da qual possa fazer a reparação.
Com um mirror, a mesma leitura é servida pelo lado correto, o bloco danificado é regravado e o evento aparece na coluna CKSUM de zpool status. Isto é autorreparação e requer dois dispositivos.
sudo zpool create -o ashift=12 tank mirror /dev/disk/by-id/DISK1 /dev/disk/by-id/DISK2Numa VPS, o armazenamento do anfitrião já é normalmente redundante, muitas vezes com RAID 10 no hypervisor. Isto protege contra a falha de um disco. Não informa quando um bloco é devolvido incorretamente, porque o array não tem forma de saber qual das cópias está correta. O ZFS sabe, porque compara os dados com uma soma de verificação que ele próprio gravou.
Se tiver um único disco virtual e quiser alguma capacidade de reparação, sudo zfs set copies=2 tank/important armazena duas cópias de cada bloco desse dataset no mesmo disco. Isto duplica o espaço utilizado pelo dataset, permite sobreviver a um bloco danificado e não ajuda quando o volume inteiro desaparece.
Um scrub lê todos os dados do pool e valida-os.
sudo zpool scrub tank
zpool status tankUm pool saudável termina com uma linha como scan: scrub repaired 0B in 00:04:11 with 0 errors. Agende esta operação; uma vez por mês é suficiente para um pool pequeno.
systemctl list-unit-files 'zfs-scrub*'
sudo systemctl enable --now zfs-scrub-monthly@tank.timerDatasets são a unidade de política
Um dataset é um sistema de ficheiros dentro do pool. Criá-lo é barato, por isso crie um por tarefa. As propriedades são herdadas do pool, o que permite definir um valor predefinido uma vez e substituí-lo onde for necessário.
sudo zfs create tank/data
sudo zfs create tank/pg
sudo zfs set compression=lz4 tank
sudo zfs set atime=off tank
sudo zfs set quota=20G tank/data
sudo zfs set recordsize=16K tank/pg
zfs get -r compression,compressratio,quota tankA compressão é a propriedade que muitas pessoas deixam desativada por precaução, mas essa abordagem está errada. lz4 consome uma pequena quantidade de CPU e reduz os bytes que têm de chegar ao disco. Assim, em dados compressíveis, normalmente acelera as leituras e as escritas. zstd comprime mais, à custa de mais CPU, e é adequada para logs e arquivos que raramente são lidos novamente. Verifique os resultados efetivos com zfs get compressratio tank e lembre-se de que a taxa considera apenas os dados escritos depois de a propriedade ser definida.
recordsize é o maior bloco que um dataset escreve, com 128K por predefinição. Uma base de dados que escreve páginas de 8 KiB em registos de 128 KiB transforma uma pequena escrita numa leitura do registo inteiro, numa alteração e numa nova escrita. Defina recordsize=16K no dataset da base de dados antes de carregar os dados, porque a propriedade só se aplica aos blocos escritos posteriormente.
quota impede que um dataset preencha o pool. Um pool ZFS perto de 100% de utilização fica lento e difícil de limpar, por isso deixe espaço livre de forma deliberada.
Os snapshots não consomem espaço até os dados serem alterados
O ZFS nunca substitui um bloco em uso. Grava um bloco novo e atualiza os ponteiros. É isso que significa copy-on-write. Um snapshot é uma indicação para manter os blocos para os quais este dataset aponta neste momento. Por isso, a criação é instantânea e não consome espaço.
sudo zfs snapshot tank/data@2026-08-11
zfs list -t snapshot -o name,used,refer -r tank/dataA coluna USED de um snapshot mostra o espaço ocupado apenas por esse snapshot. Começa perto de zero e cresce quando altera ou elimina dados, porque os blocos antigos já não podem ser libertados.
Para recuperar um ficheiro, não é necessária uma etapa de restauro.
ls /tank/data/.zfs/snapshot/
cp /tank/data/.zfs/snapshot/2026-08-11/notes.txt /tank/data/notes.txtO diretório .zfs fica oculto, inclusive para ls -a, até executar sudo zfs set snapdir=visible tank/data. Crie o snapshot antes de precisar dele. Sem um snapshot, um rm -rf acidental encaminha-o para o caminho de recuperação do ext4, que começa por desmontar o disco e só piora a partir daí.
O rollback elimina tudo o que foi gravado desde o snapshot.
sudo zfs rollback tank/data@2026-08-11A operação é recusada quando existem snapshots mais recentes. -r elimina esses snapshots mais recentes para prosseguir. Confirme o nome do dataset duas vezes antes de premir Enter.
Um snapshot não é uma cópia de segurança. Fica no mesmo pool, no mesmo volume e no mesmo servidor. Uma falha do volume ou um zpool destroy elimina os snapshots juntamente com os dados. Os snapshots protegem contra o seu próprio rm e contra uma atualização com problemas. Isto cobre muitos incidentes reais, mas não protege contra nada que aconteça ao próprio pool. O caso completo é explicado aqui: porque um snapshot de VPS não é uma cópia de segurança.
Enviar e receber: replicação com um comando
zfs send transforma um snapshot num fluxo de bytes na saída padrão, e zfs receive transforma esse fluxo novamente num dataset. A primeira cópia é um envio completo.
sudo zfs snapshot tank/data@daily-2026-08-11
sudo zfs send tank/data@daily-2026-08-11 | ssh backup.example.com "sudo zfs recv -F backup/data"Depois disso, envie apenas o que mudou entre dois snapshots.
sudo zfs snapshot tank/data@daily-2026-08-12
sudo zfs send -i tank/data@daily-2026-08-11 tank/data@daily-2026-08-12 | ssh backup.example.com "sudo zfs recv backup/data"O lado que recebe ainda tem de manter o snapshot a partir do qual está a enviar. Quando isso não acontece, a receção termina com cannot receive incremental stream: most recent snapshot of backup/data does not match incremental source, porque o ZFS não tem uma base à qual aplicar a diferença. Envie a partir de um snapshot que exista nos dois lados ou recomece com um envio completo.
Conceda permissões no destino em vez de usar root remoto: sudo zfs allow -u backupuser create,mount,receive backup/data.
Isto é uma cópia de segurança externa real, com uma condição. O destino tem de ser um pool ZFS, porque o armazenamento de objetos não pode receber um fluxo. Quando o destino é um armazenamento compatível com S3 ou um host Linux simples, use uma ferramenta que comunique com esse destino. as cópias de segurança restic a partir de uma VPS abrange esse cenário.
Por que o ZFS usa tanta RAM? O ARC
O ARC (adaptive replacement cache) é a cache de leitura do ZFS. Fica na memória do kernel, e não na page cache normal do Linux, por isso free -h não o apresenta em buff/cache. É contabilizado como memória em uso. Um servidor ZFS que parece estar quase cheio normalmente tem uma cache aquecida, e isso explica a maioria dos relatos de que o "ZFS consumiu a RAM".
O limite predefinido é deliberadamente elevado. O OpenZFS 2.3 define o tamanho máximo do ARC como o maior valor entre a RAM menos 1 GiB e 5/8 da RAM. O OpenZFS 2.2 e anteriores usavam metade da RAM no Linux, enquanto o FreeBSD já usava a regra mais recente. Execute zfs version para saber qual se aplica ao seu sistema.
The data behind this chart
[
{
"label": "2 GB VPS",
"openzfs_2_2_linux_gib": 1,
"openzfs_2_3_gib": 1.25
},
{
"label": "4 GB VPS",
"openzfs_2_2_linux_gib": 2,
"openzfs_2_3_gib": 3
},
{
"label": "8 GB VPS",
"openzfs_2_2_linux_gib": 4,
"openzfs_2_3_gib": 7
},
{
"label": "16 GB VPS",
"openzfs_2_2_linux_gib": 8,
"openzfs_2_3_gib": 15
}
]Estes valores correspondem à regra predefinida documentada aplicada a tamanhos comuns de instâncias, e não a medições de um servidor em execução. Numa instância com 4 GB, a regra da versão 2.3 permite um ARC de 3 GiB. O mesmo servidor com a versão 2.2 fica limitado a 2 GiB. Uma instância com 2 GB, usando a regra da versão 2.3, ainda permite 1.25 GiB. A sua aplicação recebe o que restar.
Leia os valores reais no seu próprio servidor, em vez de confiar na tabela:
grep -E '^(size|c_max) ' /proc/spl/kstat/zfs/arcstats
arc_summary | head -n 20A terceira coluna apresenta bytes. c_max é o limite máximo atualmente aplicado, e size é a quantidade que o ARC detém neste momento.
O ARC devolve memória. O kernel sinaliza pressão de memória e o ARC diminui. O problema está no momento em que isso acontece, porque a redução é desencadeada por essa pressão. Assim, um processo que peça várias centenas de MiB de uma só vez pode encontrar o OOM (out of memory) killer enquanto o ARC ainda está a libertar memória. Num servidor com 2 GB que execute uma base de dados e um servidor web, isto não é raro. O manual do OpenZFS diz o mesmo sobre alterações manuais: reduzir o limite "não fará o ARC diminuir sem pressão de memória que provoque essa redução".
Como limitar o ARC numa VPS pequena
Determine primeiro a memória necessária para a carga de trabalho. Some o que a base de dados e a aplicação precisam, reserve uma margem para o sistema operativo e atribua o restante ao ARC. Numa instância com 4 GB que execute Postgres e uma aplicação web, começar com 512 MiB a 1 GiB de ARC é uma escolha razoável.
Aplique o limite imediatamente, em bytes. Este valor corresponde a 1 GiB.
echo 1073741824 | sudo tee /sys/module/zfs/parameters/zfs_arc_maxFaça com que a configuração persista após um reboot.
echo 'options zfs zfs_arc_max=1073741824' | sudo tee /etc/modprobe.d/zfs.conf
sudo update-initramfs -uO passo do initramfs é importante porque o módulo pode ser carregado a partir do initramfs antes de o sistema de ficheiros raiz ser montado. Nesse caso, nunca leria o ficheiro que acabou de criar. Depois do reboot, confirme o valor com a linha c_max de arcstats.
Há duas ressalvas indicadas no próprio manual. Não é possível repor o valor em 0 enquanto o sistema está em execução. Para desfazer esta configuração, edite o ficheiro e faça reboot. Além disso, reduzir o valor não diminui imediatamente um ARC grande.
No FreeBSD, o mesmo limite é um sysctl em vfs.zfs.arc. Execute sysctl vfs.zfs.arc para ver os valores atuais e o nome exato usado pela sua versão. Depois, escreva o valor máximo em /boot/loader.conf.
Há mais duas regras de memória para um servidor pequeno. Mantenha a deduplicação desativada, porque a tabela de deduplicação fica na memória e a regra prática frequentemente publicada é de 1 a 3 GB de RAM por TB de dados únicos. Não coloque swap num zvol, que é um dispositivo de bloco criado a partir do pool, porque fazer swap através do sistema de ficheiros que está a tentar libertar memória pode bloquear a máquina. Mantenha a swap numa partição normal ou num ficheiro de swap fora do pool.
Quando ext4 ou XFS com restic são a melhor opção
O ZFS é útil num servidor com memória disponível e um segundo volume. Fora desse cenário, um sistema de ficheiros simples combinado com uma ferramenta de backup adequada é melhor. Escolha ext4 ou XFS quando:
- A instância tem 2 GB ou 4 GB de RAM e a carga de trabalho precisa de toda essa memória.
- Existe um único disco virtual e não há uma segunda cópia, pelo que o ZFS permite detetar problemas, mas não corrigi-los.
- O destino dos backups é um armazenamento de objetos ou um host Linux simples, pelo que nenhum deles pode receber um fluxo
zfs send. - Executa Debian com DKMS e não pode correr o risco de uma atualização do kernel deixar o módulo por compilar.
- Precisa do ZFS no sistema de ficheiros raiz e as imagens do fornecedor apenas disponibilizam ext4.
Mantenha o ZFS quando tem um volume de dados separado, memória disponível (8 GB ou mais é confortável) e um plano que use snapshots e zfs send, em vez de apenas os ativar. Nos restantes casos, ext4 com o restic a gravar backups encriptados e deduplicados num armazenamento que o servidor não controla cobre praticamente as mesmas necessidades sem consumir memória adicional.
Modos de falha e as mensagens que verá
O pool desaparece depois de um reboot. zpool status mostra no pools available. O serviço de importação lê /etc/zfs/zpool.cache, por isso um pool ausente nesse ficheiro nunca é importado no boot. sudo zpool import lista o que pode ser importado, sudo zpool import tank recupera-o e sudo zpool set cachefile=/etc/zfs/zpool.cache tank torna essa configuração persistente. Um pool que não foi exportado corretamente de outro sistema mostra cannot import 'tank': pool may be in use from other system. sudo zpool import -f tank ignora essa condição depois de confirmar que nenhum outro host o tem importado.
modprobe: FATAL: Module zfs not found in directory /lib/modules/6.12.0-... no Debian depois de uma atualização do kernel. O DKMS não compilou para o novo kernel, normalmente porque os headers correspondentes não estão instalados. dkms status mostra o que foi compilado para cada kernel. sudo apt install -y linux-headers-$(uname -r) e sudo dkms autoinstall recompilam o módulo. sudo zpool import tank recupera o pool.
O pool está cheio, mas eliminou os ficheiros. Os dados eliminados continuam no disco enquanto um snapshot ainda fizer referência a eles, por isso du e df apresentam valores diferentes. zfs list -o space -r tank separa a utilização em USEDDS e USEDSNAP. Um USEDSNAP elevado confirma a causa. Destrua os snapshots antigos com sudo zfs destroy tank/data@2026-06-01 para libertar o espaço.
A contagem de CKSUM aumenta em zpool status. Algo abaixo do ZFS devolveu dados inválidos. Num mirror, a contagem é um aviso e o bloco foi reparado. Num pool com um único disco, o ficheiro perdeu-se. zpool status -v identifica-o. Restaure esse ficheiro a partir de uma cópia de segurança que não esteja neste pool.
O servidor está lento e a usar swap. Limite o ARC conforme indicado acima. Em seguida, execute arc_summary e verifique a taxa de acertos. Um ARC demasiado pequeno para conter o conjunto de trabalho faz com que todas as leituras sejam feitas no disco. Nesse caso, um sistema de ficheiros comum que use a page cache teria um desempenho melhor.
FAQ
Quanta RAM o ZFS precisa numa VPS?
O ZFS funciona numa instância com 2 GB. A questão real é saber quanta RAM sobra para a aplicação. Sem ajustes, o OpenZFS 2.3 permite que a ARC cresça até ao maior valor entre a RAM menos 1 GiB e 5/8 da RAM. Assim, uma máquina com 4 GB pode atribuir 3 GiB à cache. Defina zfs_arc_max para um valor que a sua carga de trabalho possa disponibilizar e confirme-o lendo a linha c_max a partir de /proc/spl/kstat/zfs/arcstats.
Um snapshot do ZFS é uma cópia de segurança?
Não. Um snapshot fica no mesmo pool que os dados. Sobrevive a um rm com problemas e a uma atualização falhada, mas perde-se se o pool ou a instância se perderem. Transforme-o numa cópia de segurança enviando-o para outra máquina com zfs send ou executando uma ferramenta de backup que grave os dados num armazenamento que este servidor não controle.
O ZFS funciona da mesma forma no FreeBSD e no Linux?
Desde o OpenZFS 2.0, em dezembro de 2020, usam a mesma base de código, os mesmos comandos e o mesmo formato em disco, e os pools podem ser movidos entre os dois sistemas. A diferença está no empacotamento. O FreeBSD inclui o ZFS no sistema base. No Linux, cada distribuição decide como o disponibiliza: o Ubuntu compila o módulo nos pacotes do kernel, enquanto o Debian o compila na sua máquina com DKMS. Por isso, uma atualização do kernel pode deixá-lo sem o módulo até a compilação terminar com sucesso.
O ZFS consegue reparar corrupção numa VPS com um disco?
Deteta a corrupção e identifica o ficheiro, mas não consegue repará-la, porque a reparação precisa de uma segunda cópia do bloco. zfs set copies=2 num dataset fornece essa segunda cópia, duplicando o espaço utilizado. Isto resolve um bloco danificado, mas não um volume perdido. Um mirror entre dois volumes é a solução que efetivamente permite a recuperação.
A compressão torna o servidor mais lento?
lz4 normalmente torna-o mais rápido. Os blocos comprimidos implicam menos bytes escritos e menos bytes lidos, e o custo de CPU por bloco é pequeno comparado com o tempo de disco poupado. Defina compression=lz4 na raiz do pool para que todos os datasets o herdem e verifique zfs get compressratio tank depois de terem sido escritos dados reais.