Introdução ao ZFS
O ZFS (Zettabyte File System) é um sistema de arquivos desenvolvido originalmente pela Sun Microsystems e, posteriormente, adotado e aprimorado pela comunidade OpenZFS. Ele combina um sistema de arquivos e um gerenciador de volumes em uma única solução, eliminando a necessidade de ferramentas separadas para manipular discos e partições.
Por sua robustez, confiabilidade e facilidade de administração, o ZFS é amplamente utilizado em servidores, soluções de armazenamento empresarial e sistemas que exigem alta disponibilidade e integridade de dados.
O ZFS está disponível nas distribuições Linux e no FreeBSD com o nome OpenZFS, a versão aberta e mantida pela comunidade após a descontinuação do ZFS original pela Oracle. Embora o ZFS não esteja disponível por padrão na maioria das distribuições Linux, o OpenZFS pode ser instalado facilmente em sistemas como Ubuntu, Debian, Fedora, Arch Linux, Gentoo, NixOS, Void Linux e Proxmox. Além disso, o FreeBSD tem suporte nativo ao OpenZFS, sendo um dos sistemas mais populares para sua utilização.
Uma das principais características do ZFS é seu design Copy-On-Write (COW), que garante que os dados nunca sejam sobrescritos diretamente. Sempre que um dado é modificado, uma nova cópia é criada e, só depois, as referências antigas são descartadas. Isso reduz significativamente o risco de corrupção de dados.
ZFS também é conhecido por sua integração com software RAID, permitindo a criação de pools de armazenamento que podem conter discos organizados em diferentes níveis de redundância, como espelhamento (mirror), RAID-Z1, RAID-Z2 e RAID-Z3. Diferente de soluções tradicionais de RAID, o ZFS verifica periodicamente a integridade dos dados com checksums embutidos e pode corrigir automaticamente erros caso haja redundância suficiente no pool.
Outro grande diferencial do ZFS é seu suporte nativo a snapshots e clones, o que permite criar cópias instantâneas do estado atual do sistema de arquivos sem ocupar espaço adicional até que novas mudanças sejam feitas. Isso é útil para backups, testes e recuperação de dados.
Além disso, o ZFS oferece suporte para compressão transparente, deduplicação (embora com alto custo de RAM), e pode ser expandido com discos adicionais sem interromper a operação. Seu gerenciamento é simples, feito principalmente através dos comandos zpool (para gerenciar pools de armazenamento) e zfs (para manipular sistemas de arquivos e datasets).
O ZFS possui excelentes recursos para nosso, porém, esses recursos não substituem a necessidade de backups.
Os snapshots, clones e espelhamento ajudam a proteger os dados, mas apenas enquanto houver espaço suficiente no armazenamento. Mesmo com todas essas funcionalidades avançadas, é essencial realizar backups regulares e testá-los periodicamente para garantir que possam ser restaurados quando necessário.
ZFS e cenários de aplicação
O ZFS é um sistema de arquivos poderoso, mas seu uso precisa ser bem planejado. Embora seja excelente para alguns cenários, pode não ser a melhor escolha para outros.
A seguir, podemos conferir os cenários que ele pode ser usado:
O ZFS é perfeito para servidores de armazenamento de arquivos, backups e compartilhamento de dados (Storages como NAS). Ele é utilizado no TrueNAS. Ambientes com servidores Web e Banco de dados (PostgreSQL e MySQL) podem se beneficiar do ZFS, principalmente com snapshots e compressão (com os devidos ajustes adequados). Se você precisa de snapshots frequentes e rollback rápido, o ZFS é uma boa escolha também.
Se você precisa fazer o Streaming de mídias e/ou trabalha com grandes volumes de dados, o uso de compressão e cache inteligente melhora a leitura de arquivos grandes.
Abaixo podemos conferir os cenários que ele pode não se comportar tão bem:
Sistemas com pouca memória RAM disponível podem enfrentar desafios significativos, especialmente quando lidam com grandes volumes de dados e um alto número de operações de leitura e escrita. O impacto no desempenho também dependerá da quantidade e do tamanho dos discos no pool, bem como das funcionalidades ativadas no ZFS. Para um funcionamento eficiente, recomenda-se um mínimo de 8GB de RAM, pois o ZFS faz uso intensivo da memória para cache e otimização das operações. Em ambientes com pouca RAM, o desempenho pode ser prejudicado, resultando em lentidão e dificuldades para lidar com cargas de trabalho mais exigentes.
No caso de máquinas virtuais (VMs), por exemplo, a falta de otimizações pode resultar em latência elevada e travamentos. Aplicações que exigem gravação síncrona em disco também podem enfrentar problemas sem um SSD dedicado para o ZFS Intent Log (ZIL), já que o desempenho pode ser afetado.
Em desktops comuns, o ZFS pode consumir mais recursos do que o necessário para um uso cotidiano, tornando-se uma escolha desnecessária, a menos que haja um motivo específico, como a necessidade de snapshots frequentes ou a garantia de integridade dos dados. Da mesma forma, para armazenamentos externos simples via USB ou SATA, o uso do ZFS pode ser um exagero, pois sistemas de arquivos mais leves, como Ext4 ou XFS, costumam ser mais práticos e eficientes para esse tipo de uso.
O ZFS é uma excelente opção de sistema de arquivos, mas não funciona bem "fora da caixa" para todos os cenários. Para rodar VMs nele por exemplo, é necessários efetuar ajustes específicos, como limitar o consumo de RAM pelo ARC, escolher um tipo de pool mais adequado (mirror ao invés de RAIDZ), otimizar o recordsize, adicionar um SSD para o ZIL e ajustar configurações de sincronização.
O uso do ZFS em servidores de e-mail pode trazer diversos benefícios, mas sua eficiência depende diretamente do formato de armazenamento utilizado nos e-mails. No caso de formatos como Maildir, onde cada e-mail é armazenado como um arquivo separado, o ZFS se beneficia bastante de sua capacidade de compressão, deduplicação e integridade de dados, além de permitir snapshots eficientes para recuperação rápida. No entanto, em formatos como mbox/mdbox, onde múltiplas mensagens são armazenadas dentro de um mesmo arquivo, essas vantagens podem ser reduzidas.
O formato mdbox/mbox, apresenta alguns desafios específicos ao ser usado com ZFS. Como ele armazena várias mensagens dentro de arquivos de storage bins e realiza operações periódicas de reorganização, mesmo que os e-mails antigos não sejam modificados diretamente, os arquivos de metadados e índices são constantemente atualizados. Essas modificações ocorrem por diversas razões, como mudanças em flags de e-mails, movimentação de mensagens entre pastas, processos automáticos de expurgo e repack, além da atualização dos índices para otimizar a performance do servidor. Como consequência, em backups incrementais ou snapshots do ZFS, esses arquivos são frequentemente marcados como modificados, mesmo que apenas pequenas partes tenham sido alteradas. Isso pode levar a um consumo maior de espaço de armazenamento e a backups incrementais menos eficientes.
Além disso, a deduplicação do ZFS pode não ser tão eficaz no mdbox, pois as mensagens podem ser armazenadas de forma fragmentada dentro dos arquivos e os índices mudam constantemente, reduzindo a repetição de blocos idênticos. Da mesma forma, o uso de snapshots perde eficiência, já que pequenas alterações nos arquivos de metadados podem fazer com que grandes blocos de dados sejam preservados em cada snapshot, aumentando o consumo de espaço ao longo do tempo.
Para minimizar esses impactos, algumas estratégias podem ser adotadas, como evitar a criação de snapshots em intervalos muito curtos, utilizar compressão no ZFS para reduzir o impacto do crescimento dos arquivos de índice e avaliar a viabilidade do formato Maildir caso a estrutura do servidor permita a mudança. O Maildir, por armazenar cada e-mail em um arquivo separado, lida melhor com snapshots e backups incrementais, evitando a necessidade de copiar grandes quantidades de dados quando apenas alguns e-mails são modificados.
Embora o ZFS continue sendo uma excelente escolha para servidores de e-mail, é essencial compreender o impacto do formato de armazenamento utilizado. Para ambientes que fazem uso do mdbox, é necessário um planejamento cuidadoso para evitar desperdício de espaço e garantir a eficiência dos backups e snapshots.
Vantagens e Desvantagens
O ZFS combina gerenciamento de volume, RAID e sistema de arquivos em uma única camada, reduzindo a complexidade operacional. Com poucos comandos, é possível criar pools de armazenamento, definir níveis de redundância, habilitar compressão, gerenciar pontos de montagem e configurar quotas. Desde sua liberação pública em 2005, o ZFS tem sido amplamente utilizado em grandes empresas e pequenas infraestruturas. Sua arquitetura foi testada extensivamente, garantindo um nível elevado de confiabilidade e desempenho.
O ZFS foi projetado com foco na proteção contra corrupção de dados, utilizando checksums nos metadados e mecanismos como Copy-On-Write (COW). Caso um erro seja detectado e haja redundância, ele pode ser corrigido automaticamente. O ZFS também permite a adição de novos dispositivos ao pool, gerenciamento eficiente de cache e suporte a grandes volumes de dados. Ele pode lidar com exabytes de armazenamento, tornando-se uma solução robusta para infraestruturas de qualquer porte.
Embora o ZFS ofereça muitos benefícios, é importante lembrar que nem tudo são flores. Ele também apresenta algumas desvantagens e particularidades que devem ser consideradas. A seguir, vou destacar alguns pontos críticos para que você possa planejar e utilizar o ZFS de forma eficiente e consciente.
Quando o pool de armazenamento atinge 80% ou mais da sua capacidade total, o desempenho do ZFS se deteriora significativamente. Isso ocorre porque o sistema precisa trabalhar mais para encontrar blocos livres para gravação. A recomendação é expandir o pool antes de atingir esse limite.
Após adicionar discos a um pool, não é possível removê-los, ou seja, uma decisão errada no design do armazenamento pode ser irreversível, exigindo a criação de um novo pool e a migração manual dos dados. No ZFS, não é possível alterar o tipo de redundância (por exemplo, de RAIDZ para um espelhamento ou de RAIDZ-1 para RAIDZ-2) após a criação do pool. A única exceção é a conversão de um disco único para um mirror. Caso seja necessário alterar o nível de redundância, a única solução é recriar o pool e restaurar os dados a partir de um backup.
Arquitetura usada pelo ZFS
O ZFS é um sistema de arquivos e gerenciador de volumes integrado que organiza o armazenamento de forma hierárquica. Ele funciona através de três conceitos principais: pools (zpool), vdevs (dispositivos virtuais) e datasets (sistemas de arquivos e volumes). Essa estrutura permite uma gestão eficiente do armazenamento, garantindo integridade dos dados e alta flexibilidade.
Storage Pool - ZPOOL
O pool de armazenamento (ou zpool) é a unidade básica de armazenamento no ZFS e é formado por um ou mais vdevs (dispositivos virtuais). Um vdev pode ser formado por um único disco ou um conjunto de discos. Ao contrário de sistemas tradicionais que usam partições fixas, o ZFS trata o pool como um recurso dinâmico, onde o espaço pode ser expandido conforme necessário.
Um zpool é um conjunto de vdevs, e cada vdev pode ser composto por um ou mais discos físicos. Se um vdev falhar completamente e não houver redundância suficiente, todo o pool será perdido. Essa estrutura é fundamental para entender como projetar pools resilientes e com bom desempenho.
O zpool representa o espaço de armazenamento combinado dos vdevs, e os sistemas de arquivos criados dentro dele podem crescer até ocupar todo o espaço disponível. O ZFS trata o pool de forma dinâmica, diferentemente de sistemas tradicionais baseados em partições fixas. Isso significa que o espaço pode ser expandido com a adição de novos vdevs, mas não pode ser reduzido, ou seja, uma vez que um vdev é adicionado a um pool, ele não pode ser removido.
Um zpool pode conter HDDs e SSDs no mesmo pool, mas a maneira como isso é feito pode impactar diretamente o desempenho e a eficiência do sistema. O ZFS permite essa mistura, mas é preciso entender como os discos são organizados para evitar gargalos e desperdício de recursos.
A imagem abaixo, fornecida pelo usuário Scytob e publicada no Reddit em r/zfs, ilustra de forma mais clara a relação entre Disco, VDEV, ZPOOL e Datasets (Scytob, 2024).

VDEVs - Virtual Devices
Os vdevs (dispositivos virtuais) são os blocos de construção do ZFS, eles ficam dentro do ZPOOL e podem ser compostos por um ou mais discos e determinam o nível de redundância do pool. Cada vdev dentro de um pool é tratado como uma unidade de armazenamento independente.
A integridade dos dados é garantida no nível do vdev, não no nível do pool. Isso significa que se um único vdev falhar completamente e não houver redundância suficiente, todo o pool será perdido.
Tipos de VDEVs:
- Single-disk vdev: Sem redundância, qualquer falha de disco pode resultar na perda total dos dados.
- Mirror vdev: Similar ao RAID 1, os dados são duplicados entre os discos.
- RAID-Z1, RAID-Z2, RAID-Z3: Equivalente ao RAID 5, 6 e 7, respectivamente. Usa paridade para oferecer tolerância a falhas, com a capacidade de perder 1, 2 ou até 3 discos sem perda de dados.
- Stripe: Funciona como RAID 0, sem redundância, apenas distribuindo os dados entre os discos para maior velocidade.
- Pool híbrido: Utiliza SSDs como cache para otimizar desempenho.
Uma vez que um VDEV é adicionado ao Pool, não será mais possível remover ele. Isso significa que a estrutura do pool está essencialmente fixa após a adição de um VDEV. Se você adicionar um Mirror VDEV a um pool, esse pool permanecerá com a configuração de mirror e não poderá ser convertido para RAIDZ2 ou qualquer outro tipo de redundância.
Adicionar um novo VDEV de um tipo diferente que seja diferente de um já existente no pool pode comprometer a integridade e desempenho. Por exemplo, se um pool inicialmente criado com vdevs RAIDZ-2 receber um novo vdev configurado como Mirror com menos discos, isso pode resultar em um ponto fraco no pool e levar a problemas de performance.
A única exceção a essa regra é quando um single-disk VDEV é convertido em um mirror (adicionando um segundo disco ao mesmo VDEV), ou quando um mirror é expandido para um triple-mirror. Mas transformações entre mirror e RAIDZ não são suportadas.
Abaixo podemos conferir exemplos de criação de vários tipos de pool:
# Pool com apenas um disco:
zpool create tank /dev/sdX
# Pool com mirror (espelhamento):
zpool create tank mirror /dev/sdX /dev/sdY
# Pool com stripe (Raid 0):
zpool create tank /dev/sdX /dev/sdY
# Pool com raidz2 (RAID 6):
zpool create tank raidz2 /dev/sdW /dev/sdX /dev/sdY /dev/sdZ
O nome "tank" é apenas um exemplo tradicionalmente usado para nomear um pool ZFS. Ele não tem nenhum significado especial. Você pode escolher qualquer nome para o seu pool, mas caso queira algo mais genérico, "tank" é utilizado nesses casos.
Datasets
Os Datasets (File Systems e Volumes) são as entidades lógicas onde os dados são armazenados dentro do pool. O ZFS permite criar diferentes tipos de datasets, cada um com suas configurações específicas.
Os tipos de Datasets são:
File System
Usado para armazenar arquivos e diretórios.Volume - ZVOL
Emula um dispositivo de bloco, útil para máquinas virtuais e iSCSI.Snapshot
Captura o estado de um dataset em um determinado momento.Clone
Uma cópia gravável de um snapshot existente.
Abaixo podemos ver alguns exemplos dos tipos de datasets mencionados acima:
# Criando um dataset do tipo File System chamado 'home_users':
zfs create tank/home_users
# Criando um dataset do tipo Volume:
zfs create -V 10G tank/volume1
## Se quiser formatar o volume como um sistema de arquivos ext4, por exemplo:
mkfs.ext4 /dev/zvol/tank/volume1
# Criando um snapshot do dataset chamado 'home_users':
zfs snapshot tank/home_users@snapshot1
# Criando um clone de um snapshot existente:
zfs clone tank/home_users@snapshot1 tank/home_users_clone
File System
Um dataset do tipo filesystem é basicamente um sistema de arquivos criado dentro de um pool. Diferente de sistemas tradicionais, como EXT4 ou NTFS, onde um disco ou partição precisa ser formatado, no ZFS você pode criar vários filesystems dentro do mesmo zpool, e cada um funciona de forma independente.
Esse tipo de dataset é usado quando se precisa organizar e gerenciar diferentes conjuntos de dados dentro de um mesmo pool de armazenamento, mantendo controle individual sobre cada um deles. Esse tipo de dataset é bom para quando temos usos distintos, como backups, projetos, uso pessoal por usuários, cada um com configurações próprias. Aplicar quotas para evitar que um dataset consuma todo o pool. Ativar compressão, criptografia ou permissões personalizadas por dataset. Exportar apenas alguns datasets via NFS ou SMB, sem expor todo o pool.
Por exemplo, imagine que você tem um pool chamado mypool. Se quiser criar um novo sistema de arquivos dentro dele, basta executar:
zfs create mypool/mydataset
Isso cria um filesystem chamado mydataset, que pode ser acessado como uma pasta dentro do sistema, geralmente em /mypool/mydataset. Esse filesystem não é uma partição separada, mas sim um espaço independente dentro do pool, com regras próprias.
O ZFS armazena os dados em blocos lógicos chamados de registros (ou records). O tamanho máximo desses blocos pode ser definido pelo parâmetro recordsize, que determina o tamanho máximo dos blocos de dados gravados no disco dentro de um dataset do tipo filesystem. O valor padrão do recordsize é 128K, mas ele pode ser ajustado dependendo do tipo de workload (carga de trabalho).
Cada bloco de até 128K (ou o valor configurado) pode armazenar um único arquivo ou parte de um arquivo, mas nunca múltiplos arquivos diferentes. Se um arquivo for maior que o recordsize (por exemplo, 1MB com recordsize=128K), o ZFS dividirá o arquivo em vários blocos de 128K. No caso de um arquivo de 1MB, seriam usados 8 blocos de 128K. Se um arquivo for menor que o recordsize (por exemplo, 10K com recordsize=128K), o ZFS alocará um bloco menor (10K, nesse caso) e não desperdiçará o espaço restante. Isso é possível porque o ZFS usa tamanho de bloco dinâmico, ou seja, ele não força que o bloco tenha exatamente 128K se o arquivo for menor.
Se o ZFS já ajusta os blocos dinamicamente, por que reduzir manualmente o recordsize? A resposta está na forma como os dados são gravados e lidos, especialmente em workloads que realizam muitas operações de escrita e leitura de pequenos blocos, como bancos de dados, logs e caches.
Quando o recordsize é maior que o tamanho típico das escritas (por exemplo, 128K para escritas de 16K), o ZFS não agrupa automaticamente essas escritas em blocos maiores, a menos que sejam sequenciais e contíguas. Cada escrita pequena será armazenada como um bloco separado do tamanho correspondente (16K, no exemplo). Isso pode levar a um aumento no número de blocos e, consequentemente, a um maior uso de metadados. Para leituras subsequentes, o sistema pode precisar buscar muitos blocos pequenos, o que pode aumentar a latência, especialmente em discos mecânicos (HDDs), onde o tempo de busca é maior.
Continuar a correção abaixo:
Exemplo prático:
Vamos imaginar um banco de dados que escreve blocos de 16K, enquanto o ZFS está configurado com recordsize=128K. Como o banco de dados está constantemente modificando pequenas partes dos arquivos, o ZFS não agrupará automaticamente essas escritas em blocos de 128K, a menos que as escritas sejam sequenciais e contíguas. Em vez disso, cada escrita de 16K será armazenada como um bloco separado de 16K.
- Se houver muitas escritas aleatórias de 16K, o dataset pode ficar altamente fragmentado, com muitos blocos pequenos espalhados pelo disco.
- Quando o sistema precisar fazer uma leitura grande, ele terá que buscar muitos blocos pequenos, o que pode aumentar a latência.
- O ARC (Adaptive Replacement Cache), que é o cache de memória do ZFS, pode ser menos eficiente, pois terá que gerenciar muitos blocos pequenos em vez de blocos maiores.
- Operações de scrubbing e recuperação podem levar mais tempo, pois haverá mais blocos para verificar e consolidar.
Fragmentação em discos mecânicos vs. SSDs/NVMe:
- Discos mecânicos (HDDs): A fragmentação pode ser um problema significativo, pois os cabeçotes do disco precisam se mover fisicamente para acessar blocos espalhados, o que aumenta a latência e reduz o desempenho.
- SSDs e NVMe: A fragmentação não é um problema relevante, pois esses dispositivos não têm partes móveis e o tempo de acesso a blocos espalhados é praticamente o mesmo que para blocos sequenciais. No entanto, o gerenciamento de muitos blocos pequenos ainda pode impactar o desempenho devido ao aumento de metadados e operações de I/O.
Conclusão:
Ajustar o recordsize para um valor menor (por exemplo, 16K) em workloads que realizam muitas escritas pequenas pode melhorar o desempenho e reduzir a fragmentação. Isso ocorre porque o ZFS alocará blocos do tamanho adequado para as escritas, evitando a criação de muitos blocos pequenos e melhorando a eficiência das operações de leitura e escrita.
Resumo das correções:
- Agrupamento de escritas: O ZFS não agrupa automaticamente escritas menores em blocos de 128K, a menos que sejam escritas sequenciais e contíguas.
- Fragmentação: A fragmentação pode ser um problema em discos mecânicos, mas não é relevante em SSDs e NVMe devido à ausência de partes móveis.
- Ajuste do
recordsize: Reduzir orecordsizepara corresponder ao tamanho típico das escritas pode melhorar o desempenho em workloads com muitas operações de pequenos blocos.
Com essas correções, o texto agora reflete com precisão o comportamento do ZFS e o impacto do recordsize no desempenho e na fragmentação. 😊
Volumes
Um volume (ZVOL) é um dispositivo de bloco virtual criado dentro de um pool de armazenamento. Diferente de um dataset do tipo filesystem, que armazena arquivos diretamente, um ZVOL funciona como um disco virtual que pode ser formatado com qualquer sistema de arquivos, como EXT4, NTFS, XFS ou até usado como swap.
Os volumes no ZFS são úteis em situações onde você precisa de um bloco de armazenamento bruto, em vez de um sistema de arquivos diretamente gerenciado pelo ZFS. Os ZVOLs são comumente usados como discos virtuais para KVM, VirtualBox e VMware, oferecendo melhor desempenho e snapshots eficientes. Se você precisar expor um dispositivo de bloco para outro sistema via rede, um ZVOL pode ser usado como um target iSCSI.
Para criar um volume de 20GB dentro do pool mypool:
zfs create -V 20G mypool/meuvolume
Isso cria um dispositivo de bloco que pode ser acessado como /dev/zvol/mypool/meuvolume.
Se for necessário formatá-lo com EXT4, por exemplo:
mkfs.ext4 /dev/zvol/mypool/meuvolume
Snapshot
Um snapshot captura o estado exato de um dataset ou volume em um determinado momento, preservando os blocos de dados e metadados sem permitir modificações diretas. Os snapshots no ZFS são sempre somente leitura. Quando um snapshot é criado, ele não ocupa espaço adicional imediatamente, pois apenas mantém referências aos blocos existentes. No entanto, conforme os dados no dataset original são modificados ou excluídos, os blocos antigos precisam ser mantidos pelo snapshot para garantir a consistência, o que faz com que o snapshot passe a consumir espaço em disco.
Como os snapshots são imutáveis, qualquer alteração nos dados armazenados dentro deles não é permitida diretamente. Se for necessário modificar um snapshot, podemos criar um clone gravável (writable) a partir de um snapshot, que se torna um novo dataset independente, compartilhando inicialmente os mesmos blocos do snapshot original.
Outro método é reverter o dataset ao estado salvo pelo snapshot, é possível usar o comando rollback, o que desfaz todas as alterações feitas após a criação do snapshot. Isso pode causar perda de dados recentes, então deve ser feito com cuidado.
Resilvering
Quando um disco é substituído ou um novo é adicionado para substituir um disco defeituoso, o ZFS inicia automaticamente o resilvering. Diferente dos RAID tradicionais, que copiam blocos inteiros de um disco para outro, o ZFS apenas reconstrói os dados necessários, ou seja, ele resilveriza apenas os blocos que contêm dados e não o disco inteiro. Isso reduz significativamente o tempo necessário para concluir o processo (mesmo assim pode demorar de minutos até dias dependendo da quantidade de dados). Ao mesmo tempo que o processo de resilvering é mais rápido no ZFS em comparação ao RAID tradicional, o resilvering é tratado como um processo de baixa prioridade pelo sistema operacional, ou seja, em um sistema muito ocupado, a operação de resilvering pode demorar mais.
O resilvering pode ser iniciado automaticamente ou manualmente com os comandos:
# O comando abaixo substitui um disco 'failed_disk' por um novo disco chamado 'new_disk'
zpool replace <pool_name> <failed_disk> <new_disk>
# Para adicionar um disco a um 'mirror':
zpool attach <pool_name> <existing_disk> <new_disk>
Para acompanhar o status do resilvering, use o comando abaixo:
zpool status
Scrub
O scrub no ZFS é um processo de verificação e correção de integridade de dados dentro de um pool de armazenamento. Ele percorre todos os blocos do pool, comparando os checksums armazenados com os dados efetivos nos discos. Se forem detectadas inconsistências ou corrupções silenciosas, e se o pool tiver redundância (como em mirrors ou RAIDZ), o ZFS automaticamente tenta corrigir os erros usando cópias saudáveis dos dados.
Diferente de um fsck (usado em sistemas de arquivos tradicionais para checar e reparar falhas), o scrub do ZFS ocorre enquanto o sistema está em uso, sem a necessidade de desmontar o pool. Ele é especialmente útil para detectar bit rot (degradação silenciosa dos dados), garantindo que arquivos corrompidos sejam identificados e corrigidos antes que causem problemas.
Como foi dito acima, o ZFS já verifica a integridade dos dados durante operações normais de leitura, corrigindo automaticamente blocos corrompidos quando há cópias redundantes disponíveis. Isso ocorre porque o ZFS armazenha checksums para cada bloco de dados e metadados, ao acessar um dado, ele compara o checksum armazenado com o bloco lido do disco. Se houver um erro de integridade, e o sistema tiver redundância disponível, o ZFS automaticamente substitui o bloco corrompido por uma cópia íntegra de outro disco.
No entanto, a execução manual do scrub ainda é necessária porque os dados que não são acessados ou são acessados raramente, não são verificados. A corrupção silenciosa dos dados (bit rot) pode ocorrer ao longo do tempo devido a falhas de hardware ou degradação magnética nos discos. Como esses erros não causam falhas diretas no funcionamento do sistema, eles podem passar despercebidos por anos. O scrub permite detectar e corrigir esses problemas antes que o dano se torne irreversível.
Se o ZFS detectar um bloco corrompido em uma leitura normal e não houver cópias redundantes disponíveis, os dados podem ser perdidos. O scrub ajuda a identificar setores defeituosos antecipadamente, permitindo que medidas preventivas sejam tomadas antes que ocorra uma falha crítica. Se um pool foi criado sem mirrors ou RAIDZ, o ZFS não tem cópias redundantes para restaurar automaticamente blocos corrompidos, nesse caso, o scrub ainda pode ser útil na identificação de dados corrompidos, isso faz com que o usuário possa tomar medidas antes que os dados sejam perdidos.
# Podemos iniciar o scrub com o comando abaixo:
zpool scrub <pool>
# Para monitorar o scrub, podemos usar o comando abaixo:
zpool status
Como o ZFS realiza verificação contínua dos dados durante operações normais de leitura, o scrub não é necessário o tempo todo. No entanto, é recomendado agendá-lo periodicamente, dependendo da criticidade dos dados. Por exemplo, servidores de armazenamento podem rodar um scrub semanalmente ou mensalmente para garantir a integridade dos dados ao longo do tempo.
O ZFS armazena os checksums de cada bloco de dados no próprio sistema de arquivos, especificamente nos metadados do pool. Esses checksums não são armazenados junto com os blocos de dados, mas sim em estruturas separadas, o que garante que qualquer corrupção nos dados seja detectada durante o scrub.
Quando o scrub é executado, ele lê os blocos de dados no disco e os compara com os checksums armazenados nos metadados do ZFS. Se houver discrepância, o ZFS tenta recuperar os dados de cópias redundantes e reescrevê-los corretamente no disco.
O Bit rot (também chamado de data degradation ou data decay) é um fenômeno em que os dados armazenados em um disco ou outro meio de armazenamento se corrompem lentamente ao longo do tempo, sem nenhuma falha aparente no hardware. Isso pode acontecer devido a vários fatores físicos e eletrônicos, como degradação magnética dos discos, falhas em células de memória flash, interferências eletromagnéticas ou erros aleatórios na leitura/escrita de dados.
O grande problema do bit rot é que ele ocorre silenciosamente, sem gerar alertas óbvios, e pode passar despercebido até que o dado corrompido seja acessado. Em sistemas de arquivos tradicionais (como EXT4, NTFS ou XFS), a corrupção pode permanecer indetectável até que o usuário tente abrir um arquivo e descubra que ele está danificado.
Copy-On-Write (COW) no ZFS
O Copy-On-Write (COW) significa que, sempre que um bloco de dados precisa ser modificado, ele não é sobrescrito no local original, como ocorre em sistemas de arquivos tradicionais. Em vez disso, o ZFS grava a nova versão do bloco em um local diferente no disco e, apenas após a gravação ser concluída com sucesso, o ponteiro do sistema de arquivos é atualizado para apontar para o novo bloco.
Isso garante que os dados nunca fiquem em um estado inconsistente. Se uma falha (por exemplo, queda de energia) ocorrer no meio de uma gravação, o arquivo continuará apontando para os blocos antigos e válidos, evitando corrupção. Na prática o COW funciona da seguinte maneira:
- Um novo bloco de dados é gravado em um local livre no disco, sem sobrescrever o bloco original.
- Os metadados do sistema de arquivos são atualizados para apontar para o novo bloco.
- O antigo bloco fica disponível para reutilização, mas não é apagado imediatamente.
- Se um snapshot estiver presente, o antigo bloco permanecerá no disco até que o snapshot seja removido, pois ele ainda é referenciado.
Esse comportamento do ZFS garante proteção contra corrupção de dados já que as operações são atômicas, um arquivo nunca fica em um estado inválido. Os snapshots são mais eficientes, já que os blocos antigos são preservados, os snapshots no ZFS são quase instantâneos e consomem pouco espaço até que os dados sejam modificados.
O COW é essencial para a criação eficiente de snapshots. Quando um snapshot é feito, ele simplesmente preserva as referências para os blocos antigos. Se novos dados forem escritos, apenas os blocos modificados ocuparão espaço adicional, pois o sistema sempre grava novas versões ao invés de sobrescrever. Isso significa que o espaço ocupado por um snapshot corresponde apenas à quantidade de dados que mudou desde sua criação.
Além de todo benefício que o COW pode fornecer, ele também traz algumas implicações como: Fragmentação e Consumo de espaço.
Fragmentação
Como blocos antigos são mantidos até que não sejam mais referenciados (por exemplo, por snapshots), o ZFS pode sofrer com fragmentação interna ao longo do tempo, especialmente em sistemas com muitas gravações e alterações frequentes.Consumo de espaço
Snapshots mantêm referências a blocos antigos, o que significa que dados "apagados" ou modificados continuam ocupando espaço até que os snapshots sejam removidos. Isso pode levar a um aumento no uso de espaço em sistemas com muitos snapshots.
O ZFS não usa inodes no sentido tradicional, como em sistemas de arquivos como EXT4, XFS ou NTFS. Em vez disso, ele utiliza uma estrutura mais dinâmica e flexível, baseada em dnodes e block pointers, que são organizados em árvores B-Tree. Essa abordagem permite maior escalabilidade e confiabilidade, além de eliminar problemas comuns em sistemas de arquivos tradicionais, como a falta de inodes.
Os Dnodes no ZFS armazenam metadados sobre arquivos e diretórios, incluindo permissões, tamanho, timestamps e referências para os blocos de dados. Diferente dos inodes de sistemas de arquivos tradicionais, os dnodes são alocados dinamicamente, evitando um limite fixo e permitindo maior escalabilidade.
Cada dnode contém block pointers, que são ponteiros para os blocos onde os dados reais estão armazenados. Esses ponteiros também incluem um checksum embutido, que verifica a integridade dos dados. Sempre que um bloco de dados é lido, o ZFS compara o checksum armazenado com um novo checksum gerado no momento da leitura. Se houver alguma diferença, significa que o bloco foi corrompido.
Caso o ZFS detecte corrupção e o pool tenha redundância (como em um mirror ou RAIDZ), ele recupera automaticamente os dados a partir de uma cópia válida. Se não houver redundância, o sistema alerta o usuário para evitar o uso de dados corrompidos.
Diferente de sistemas tradicionais, onde os checksums ficam armazenados junto com os blocos de dados (permitindo erros silenciosos caso um bloco seja alterado), no ZFS os checksums são armazenados separadamente nos metadados do dnode. Isso impede que um erro afete tanto os dados quanto sua verificação, garantindo detecção e correção confiáveis contra corrupção de dados, bit rot e falhas de disco.
O ZIL (FS Intent Log) é usado para garantir a consistência de operações síncronas. Ele registra as alterações antes de serem aplicadas ao sistema de arquivos, o que melhora a confiabilidade sem depender de uma estrutura de inodes tradicional. O ZIL é particularmente útil em cenários onde a integridade dos dados é crítica, como em servidores de banco de dados.
Fragmentação
No ZFS, a fragmentação ocorre devido ao seu mecanismo de Copy-On-Write (COW). Como o ZFS nunca sobrescreve blocos de dados existentes, cada nova escrita aloca um novo espaço no disco, enquanto os blocos antigos permanecem ocupados até serem liberados (por exemplo, após a exclusão de um snapshot). Isso pode levar à dispersão dos dados pelo disco, resultando em fragmentação.
Quando falamos de fragmentação em ZFS temos que entender que ele ocorre de forma diferente dos sistemas de arquivos tradicionais. Em sistemas como EXT4, NTFS e XFS, a fragmentação ocorre porque os arquivos podem ser gravados de forma fragmentada em diferentes partes do disco ao longo do tempo. Já no ZFS, a fragmentação acontece porque os blocos modificados são sempre gravados em novas áreas do disco, espalhando os dados.
A fragmentação pode afetar principalmente HDDs mecânicos, pois a leitura sequencial se torna mais difícil devido ao maior deslocamento do cabeçote. Em SSDs, isso geralmente não é um problema, pois o tempo de acesso a blocos dispersos é insignificante.
O ZFS fornece uma métrica de fragmentação no nível do pool, que pode ser consultada com:
zpool list -o name,fragmentation
Isso mostra a porcentagem de fragmentação do pool. Um valor alto (acima de 70-80%) pode indicar impacto no desempenho, especialmente em discos mecânicos. Diferente de sistemas tradicionais, o ZFS não possui um comando de desfragmentação. Em vez disso, existem algumas estratégias para minimizar seus efeitos.
Sempre evite encher o pool acima de 80% da capacidade, já que o ZFS precisa de espaço livre para alocar novos blocos de forma eficiente, quando o pool está quase cheio, a fragmentação aumenta e o desempenho pode cair drasticamente. Como a fragmentação afeta menos os SSDs, pois o tempo de acesso aos blocos espalhados é insignificante comparado aos HDDs, é recomendado usar discos SSD ou NVMe.
Se a fragmentação estiver severamente afetando o desempenho, a única solução definitiva é criar um novo pool e copiar os dados para ele. Isso reorganiza os blocos de forma eficiente. Se a fragmentação estiver impactando a leitura em HDDs, adicionar um cache SSD pode ajudar a reduzir o impacto.
Deduplicação
A deduplicação (ou apenas Dedup como é popularmente chamado) é uma técnica de otimização de armazenamento que evita a gravação de blocos de dados idênticos mais de uma vez. Em vez de armazenar várias cópias do mesmo conteúdo, o sistema mantém apenas uma versão única e cria referências para ela sempre que os mesmos dados forem encontrados novamente.
Isso pode economizar espaço em disco, especialmente em ambientes onde há muitas duplicações de arquivos, como em backups, máquinas virtuais e sistemas de arquivos compartilhados.
A deduplicação é feita em nível de bloco, não de arquivos inteiros. Isso significa que partes de arquivos podem ser identificadas como duplicadas e armazenadas apenas uma vez. O funcionamento básico ocorre em três etapas:
- Sempre que um novo bloco de dados é gravado, o ZFS gera um hash (checksum) para ele.
- O ZFS consulta a DDT (Deduplication Table) para ver se um bloco com o mesmo checksum já existe.
- Agora existem duas possibilidades, uma caso o checksum já exista e outra caso não exista:
- Se o bloco já existir, em vez de gravá-lo novamente, o ZFS apenas cria uma referência para ele.
- Se for um bloco único, ele é armazenado normalmente e seu hash é adicionado à DDT.
A deduplicação permite economizar espaço em disco, já que reduz o uso de disco ao evitar gravações redundantes. Pode prolongar a vida útil de SSDs ao reduzir gravações repetitivas. No entanto, a deduplicação pode consumir muita memória RAM e CPU, dependendo do volume de dados armazenados, pois a DDT precisa ser armazenada e consultada constantemente. Se a DDT crescer além da memória disponível, o sistema será forçado a acessá-la no disco, causando lentidão extrema e degradação do desempenho.
Vale ressaltar que o problema da deduplicação não está apenas na quantidade de arquivos duplicados, mas sim no crescimento da DDT. Mesmo com poucos arquivos idênticos, se houver um grande número de blocos únicos, a DDT pode ultrapassar a RAM disponível, forçando o sistema a acessá-la via disco, o que degrada severamente o desempenho.
A recomendação oficial do OpenZFS é evitar a deduplicação, a menos que seja estritamente necessário. Caso você realmente queira usar deduplicação, é recomendados que se tenha pelo menos 1,25 GiB de RAM por TiB de armazenamento, para assim evitar problemas (fora memória disponível para outras tarefas).
Pontos importantes sobre a deduplicação são:
O ZFS não "reverte" a deduplicação automaticamente, ou seja, mesmo se desativada, os dados já deduplicados continuam nesse estado até serem regravados. Isso significa que, se o sistema estiver sofrendo por falta de RAM devido à deduplicação, desligá-la não resolverá o problema imediatamente. Para remover a deduplicação, seria necessário reescrever os dados ou recriar o pool, algo inviável em muitos cenários.
Ativar a deduplicação não afeta retroativamente os arquivos que já estavam armazenados no pool antes da ativação. Isso significa que, se um pool já contém arquivos duplicados antes da deduplicação ser ativada, esses dados continuarão ocupando espaço duplicado até que sejam regravados ou removidos.
Em sistemas de arquivos, os conceitos de nível de bloco e nível de arquivo referem-se à maneira como os dados são gerenciados e acessados pelo sistema operacional.
No nível de bloco, os dados são manipulados diretamente em blocos de armazenamento dentro do disco, sem conhecimento direto sobre os arquivos que estão sendo armazenados. Isso ocorre em dispositivos de bloco, como discos rígidos, SSDs e volumes ZFS.
No nível de arquivo, os dados são manipulados e acessados como arquivos individuais, com o sistema de arquivos gerenciando a organização, permissões e acesso a esses arquivos. Esse é o comportamento de sistemas tradicionais como EXT4, NTFS e o próprio ZFS quando usado como dataset do tipo filesystem.
Vamos criar um pool chamado tank com um vdev em mirror usando os discos vdb, vdc e vdd, onde vdb e vdc formam o espelhamento e vdd é configurado como um spare (reserva):
# Criar um pool do tipo mirror com disco de spare:
$ sudo zpool create tank mirror /dev/vdb /dev/vdc spare /dev/vdd
# Após a criação, podemos conferir se tudo foi configurado corretamente:
$ sudo zpool status
pool: tank
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
vdb ONLINE 0 0 0
vdc ONLINE 0 0 0
spares
vdd AVAIL
errors: No known data errors
Para testar o funcionamento do spare, podemos simular uma falha em um dos discos do mirror. Isso faz o ZFS detectar a falha e substituir automaticamente o disco com "defeito" pelo spare (vdd), iniciando o resilvering. O spare só entra automaticamente se o ZFS detectar que um disco está FAULTED.
# Torne o disco vdb offline para simular uma falha:
$ sudo zpool offline tank vdb
# Verifique novamente o status do pool:
$ sudo zpool status
pool: tank
state: DEGRADED
status: One or more devices has been taken offline by the administrator.
Sufficient replicas exist for the pool to continue functioning in a
degraded state.
action: Online the device using 'zpool online' or replace the device with
'zpool replace'.
scan: none requested
config:
NAME STATE READ WRITE CKSUM
tank DEGRADED 0 0 0
mirror-0 DEGRADED 0 0 0
vdb OFFLINE 0 0 0
vdc ONLINE 0 0 0
spares
vdd AVAIL
errors: No known data errors
# Substitua o vdb pelo vdd:
$ sudo zpool replace tank vdb vdd
# Verifique novamente o status do pool:
$ sudo zpool status
pool: tank
state: DEGRADED
status: One or more devices has been taken offline by the administrator.
Sufficient replicas exist for the pool to continue functioning in a
degraded state.
action: Online the device using 'zpool online' or replace the device with
'zpool replace'.
scan: resilvered 332K in 0 days 00:00:00 with 0 errors on Wed Mar 5 20:17:14 2025
config:
NAME STATE READ WRITE CKSUM
tank DEGRADED 0 0 0
mirror-0 DEGRADED 0 0 0
spare-0 DEGRADED 0 0 0
vdb OFFLINE 0 0 0
vdd ONLINE 0 0 0
vdc ONLINE 0 0 0
spares
vdd INUSE currently in use
errors: No known data errors
# Agora vamos remover o disco com 'defeito':
$ sudo zpool detach tank vdb
# Verifique novamente o status do pool:
$ sudo zpool status
pool: tank
state: ONLINE
scan: resilvered 332K in 0 days 00:00:00 with 0 errors on Wed Mar 5 20:17:14 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
vdd ONLINE 0 0 0
vdc ONLINE 0 0 0
errors: No known data errors
Após a troca do disco vdb, podemos adicionar o novo disco como spare:
$ sudo zpool add tank spare /dev/vdb
No ZFS, um vdev inteiro não pode ser removido, mas um disco individual pode ser removido de certos tipos de vdevs, dependendo da configuração.
zpool detach: Remove um disco de um mirror, mantendo o pool funcional.zpool remove: Pode ser usado para remover um spare, cache ou log device, mas não remove discos de um RAIDZ ou um vdev inteiro.
Isso mostrará todas as features suportadas pela versão do OpenZFS em uso: zpool upgrade -
Fontes
https://openzfs.readthedocs.io/en/latest/
https://openzfs.github.io/openzfs-docs/
https://openzfs.org/wiki/Main_Page
https://openzfs.github.io/openzfs-docs/man/master/7/zfsconcepts.7.html#Deduplication
https://www.zfshandbook.com/docs/advanced-zfs/deduplication/
https://openzfs.github.io/openzfs-docs/Basic%20Concepts/Checksums.html