ZFS (Português)

From ArchWiki
Status de tradução: Esse artigo é uma tradução de ZFS. Data da última tradução: 2020-01-10. Você pode ajudar a sincronizar a tradução, se houver alterações na versão em inglês.

ZFS é um sistema de arquivos avançado criado pela Sun Microsystems (atualmente propriedade da Oracle) e lançado para OpenSolaris em novembro de 2005.

Características do ZFS incluem: armazenamento em "pools" (gerenciamento integrado de volumes - zpool), cópia em gravação, snapshots, verificação da integridade de dados e reparo automático (scrubbing - esfregar), RAID-Z, tamanho de arquivo máximo de 16 exabytes, e um máximo de armazenamento de 256 quadrilhões de zettabytes sem limite de números de sistema de arquivos (datasets - conjuntos de dados) ou arquivos[1]. (Conteúdo em inglês). O ZFS está licenciado sob a Common Development and Distribution License (CDDL).

Descrito como "A última palavra em sistemas de arquivos" (Conteúdo em inglês), o ZFS é estável, rápido, seguro e à prova de futuro. Tendo a licença como CDDL, e, portanto, incompatível com a GPL, não é possível que o ZFS seja distribuído junto ao Kernel Linux. Esta necessidade, no entanto, não impede que um módulo do Kernel nativo de Linux seja distribuído por terceiros, como é o caso com o zfsonlinux.org (ZOL - ZFS no Linux/ZNL).

ZNL é um projeto fundado pelo Lawrence Livermore National Laboratory para desenvolver um módulo nativo do Kernel do Linux para a necessidade de armazenamento maciço de dados em supercomputadores.

Nota:

Devido à incompatibilidade potencialmente ilegais entre CDDL do ZFS e GPL do Kernel Linux, o desenvolvimento do ZFS não é suportado pelo Kernel, como mostrado nas seguintes páginas: ([2],CDDL-GPL,ZFS no Linux).

Como resultado:

  • O projeto ZFSonLinux deve acompanhar as versões do Kernel Linux. Após tornar um lançamento de uma versão estável do ZFSonLinux, os mantenedores do ZFS no Arch, fazem o lançamento junto à versão do Kernel.
  • Essa situação às vezes bloqueia o processo normal de atualização sem interrupção por dependências não satisfeitas, porque a nova versão do Kernel, proposta por atualização, não é suportada pelo ZFSonLinux

Instalação

Geral

Atenção: A não ser que você utilize as versões DKMS dos pacotes, os módulos do Kernel ZFS e SPL estarão amarrados a uma versão específica do Kernel. Não será possível aplicar nenhuma atualização do Kernel até que pacotes atualizados sejam subidos para o AUR ou o repositório não-oficial archzfs.
Dica: Você pode fazer o downgrade da sua versão do Linux para uma no repositório do archzfs se sua versão for mais nova.

Instale do repositório não-oficial archzfs ou, como alternativa, do AUR:

Estas versões têm dependências do pacote zfs-utils.

Teste a instalação rodando zpool status na linha de comando. Se aparecer um erro com "insmod", tente depmod -a.

ZFS na raiz

Veja Instalação.

DKMS

Usuários podem utilizar o DKMS para reconstruir o módulo do ZFS automaticamente com cada atualização do Kernel.

Instale zfs-dkmsAUR ou zfs-dkms-gitAUR e aplique as instruções de pós-instalação dadas por estes pacotes.

Dica: Adicione uma entrada de IgnorePkg em pacman.conf para impedir que estes pacotes sejam atualizados em uma atualização regular.

Experimentos com ZFS

Usuários que tenham o desejo de realizar experimentos com ZFS em dispositivos de blocos virtuais (conhecidos no ZFS como VDEVs) que podem ser arquivos simples como ~/zfs0.img, ~/zfs1.img, ~/zfs2.img, etc. sem a possibilidade de perda real de dados devem ver o artigo Experimenting with ZFS. Tarefas comuns como construir um array (conjunto) em RAIDZ, propositalmente corromper dados e então recuperá-los, obter snapshots de datasets, etc. são cobertos nele.

Configuração

ZFS é considerado como um sitema de arquivos com "administração zero" pelos seus criadores; portanto, configurar o ZFS é um processo bem direto. A configuração é feita com 2 comandos: zfs e zpool.

Inicialização automática

Atualmente, por padrão, o módulo do Kernel não é carregado durante a inicialização (veja mais detalhes em https://github.com/zfsonlinux/zfs/issues/6083 - conteúdo em inglês). Para carregar automaticamente o zfs, veja Módulos de kernel#Carregamento automático de módulos com systemd.

Para que o ZFS faça juz à "administração zero",o serviço zfs-import-cache.service deve ser habilitado para importar as pools e o zfs-mount.service deve ser habilitado para montar o sistema de arquivos disponível nas pools. Um benefício disto é que não é necessário montar os sistemas ZFS no /etc/fstab. O zfs-import-cache.service importa as pools lendo o arquivo /etc/zfs/zpool.cache.

Para cada pool importada, é desejável que o serviço zfs-import-cache.service que foi importado automaticamente, execute o seguinte comando:

# zpool set cachefile=/etc/zfs/zpool.cache <pool>
Nota: À partir da versão 0.6.5.8 do ZNL, os arquivos das unidades de serviço do ZFS foram mudadas para que você explicitamente habilite quaisquer serviços do ZFS que você queira executar. Veja o conteúdo em inglês https://github.com/archzfs/archzfs/issues/72 para mais informações.

Habilite o serviço e o .target relevante para que as pools sejam automaticamente importadas durante a inicialização:

# systemctl enable zfs-import-cache
# systemctl enable zfs-import.target

Para montar os sistemas de arquivos ZFS, você possui 2 opções:

Usando zfs-mount.service

Para montar os sistemas de arquivos ZFS automaticamente durante o boot, você precisa habilitar os seguintes serviços e alvos.

# systemctl enable zfs-mount
# systemctl enable zfs.target

Usando zfs-mount-generator

Você também pode usar o zfs-mount-generator para criar unidades de montagem do systemd para seus sistemas de arquivos ZFS durante a inicialização. O systemd irá automaticamente montar os sistemas de arquivos baseados nas unidades de montagem sem a necessidade de usar zfs-mount.service para fazer isto. Para isto, você precisa:

  1. Criar o diretório /etc/zfs/zfs-list.cache.
  2. Habilitar o script do ZFS Event Daemon (ZED - servidor de evento do ZFS, chamado de ZEDLET) necessário para criar uma lista de sistemas de arquivos montáveis do ZFS.
    # ln -s /usr/lib/zfs/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d
  3. Habilitar e iniciar o ZFS Event Daemon. Este serviço é responsável por executar o script do passo anterior.
    # systemctl enable zfs-zed.service
    # systemctl enable zfs.target
    # systemctl start zfs-zed.service
  4. Você precisa criar um arquivo vazio com o nome baseado no nome da sua pool em /etc/zfs/zfs-list.cache. O ZEDLET irá apenas atualizar a lista de sistema(s) de arquivos se o arquivo da pool já existir.
    # touch /etc/zfs/zfs-list.cache/nome-da-pool
  5. Verifique o conteúdo de /etc/zfs/zfs-list.cache/nome-da-pool. Se estiver vazio, assegure-se que o zfs-zed.service está executando e só mude a propriedade canmount de quaisquer sistemas de arquivos ZFS executando:
    zfs set canmount=off zroot/fs1
    Esta mudança faz com que o ZFS crie um evento que é capturado pelo ZED, que, então, roda o ZEDLET para atualizar o arquivo em /etc/zfs/zfs-list.cache. Se o arquivo em /etc/zfs/zfs-list.cache for atualizado, você pode definir a propriedade canmount do sistema de arquivos de volta executando:
    zfs set canmount=on zroot/fs1

Você precisa acrescentar um arquivo em /etc/zfs/zfs-list.cache para cada pool ZFS no seu sistema. Assegure-se que as pools serão importadas habilitando zfs-import-cache.service e zfs-import.target conforme explicado acima.

Pools de Armazenamento

Não é necessário particionar os dispositivos antes de criar o sistema de arquivos ZFS. É recomendado apontar o ZFS para um disco inteiro (ex: `/dev/sdx` em vez de `/dev/sdx1`), que irá automaticamente criar uma tabela de partições GPT (conteúdo em inglês) e acrescentar uma partição reservada de 8 MB no final do disco para carregadores de inicialização legados. No entando, você pode especificar a partição ou um arquivo dentro do sistema de arquivos existente, se você deseja criar multiplos volumes com propriedades de redundância diferentes.

Nota: Se algum ou todos os dispositivos foram usados em um conjunto de RAID por software, é primordial apagar quaisquer informações de configuração antigas de RAID.
Atenção: Para #Discos com formatação avançada com tamanho de setor de 4KB, um ashift com valor 12 é recomendado para melhor desempenho. Discos com formatação avançada emulam um setor com tamanho de disco de 512 bytes para compatibilidade com sistemas legado. Uma vez que o pool foi criado, a única maneira de mudar a opção do ashift é recriar o pool. Usar um ashift de 12 também diminui a capacidade disponível. Veja 1.10 What’s going on with performance?, 1.15 How does ZFS on Linux handle [Advanced(Advanced) Format disks?], e ZFS and Advanced Format disks.

Identificando discos

ZFS no Linux recomenda utilizar IDs do dispositivo quando for criar pools de armazenamento com menos de 10 dispositivos. Use Nomeação persistente de dispositivo de bloco#by-id e by-path para identificar a lista de dispositivos que serão utilizados no pool ZFS.

Os IDs dos discos serão similares ao seguinte:

$ ls -lh /dev/disk/by-id/
lrwxrwxrwx 1 root root  9 Aug 12 16:26 ata-ST3000DM001-9YN166_S1F0JKRR -> ../../sdc
lrwxrwxrwx 1 root root  9 Aug 12 16:26 ata-ST3000DM001-9YN166_S1F0JTM1 -> ../../sde
lrwxrwxrwx 1 root root  9 Aug 12 16:26 ata-ST3000DM001-9YN166_S1F0KBP8 -> ../../sdd
lrwxrwxrwx 1 root root  9 Aug 12 16:26 ata-ST3000DM001-9YN166_S1F0KDGY -> ../../sdb
Atenção: Se você criar zpools utilizando nomes dos dispositivos como /dev/sda, /dev/sdb, etc. o ZFS pode não ser capaz de detectar zpools intermitentemente na inicialização.

Utilizando rótulos GPT

Rótulos de disco e UUIDs podem ser utilizados por montagens de ZFS usando partições GPT. Dispositivos ZFS possuem rótulos mas o Linux não é capaz de lê-los durante a inicialização. Ao contrário de partições MBR, partições GPT diretamente suportam tanto UUID quanto rótulos, independente do formato dentro da partição. Particionar ao invés de utilizar o disco todo para o ZFS oferece duas vantagens adicionais. O SO não precisa gerar números de partição falsos à partir de quaisquer dados que o ZFS possa ter escrito no setor de particionamento, e, se desejado, é possível provisionar excessivamente dispositivos SSD, e provisionar ligeiramente mais discos de eixo para assegurar que diferentes modelos com contagem de setores diferentes possam substituir espelhos no seu zpool. Isto permite muita organização e controle sobre o ZFS utilizando ferramentas e técnicas prontamente disponíveis com custo quase nulo.

Utilize o gdisk para particionar todo ou apenas uma parte do disco como uma única partição. O gdisk não nomeia automaticamente as partições. Algumas razões para preferir rótulos ao invés de UUID são: rótulos são fáceis de controlar, podem indicar o propósito de cada disco, são mais curtos e mais simples de digitar. Estas são vantagens quando o servidor está inoperante e há pressão para restabelecimento. Rótulos de partições do GPT possuem amplo espaço disponível e podem suportar a maioria dos caracteres internacionais (Entradas de Partição) permitindo que grandes pools de dados sejam rotulados de uma maneira organizada.

Discos particionados com GPT possuem rótulos e UUIDs que parecem com o seguinte:

$ ls -l /dev/disk/by-partlabel
lrwxrwxrwx 1 root root 10 Apr 30 01:44 zfsdata1 -> ../../sdd1
lrwxrwxrwx 1 root root 10 Apr 30 01:44 zfsdata2 -> ../../sdc1
lrwxrwxrwx 1 root root 10 Apr 30 01:59 zfsl2arc -> ../../sda1
$ ls -l /dev/disk/by-partuuid
lrwxrwxrwx 1 root root 10 Apr 30 01:44 148c462c-7819-431a-9aba-5bf42bb5a34e -> ../../sdd1
lrwxrwxrwx 1 root root 10 Apr 30 01:59 4f95da30-b2fb-412b-9090-fc349993df56 -> ../../sda1
lrwxrwxrwx 1 root root 10 Apr 30 01:44 e5ccef58-5adf-4094-81a7-3bac846a885f -> ../../sdc1
Dica: Para minimizar digitar e erros ao copiar/colar, defina uma variável local com o PARTUUID de destino: $ UUID=$(lsblk --noheadings --output PARTUUID /dev/sdXY)

Criando pools ZFS

Para criar uma pool com ZFS:

# zpool create -f -m <montagem> <pool> [raidz(2|3)|mirror] <ids>
Dica: É útil ler primeiro #Discos com formatação avançada para definir o valor correto de ashift durante a criação da pool
  • create: subcomando para criar a pool.
  • -m: O ponto de montagem da pool. Se não for especificado, então a pool será montada diretamente em /<pool>.
  • pool: É o nome da pool.
  • raidz(2|3)|mirror: Este é o tipo de dispositivo virtual que será criado à partir do conjunto de dispositivos de armazenamento, raidz possui um único disco de paridade, raidz2, 2 discos e raidz3 possui 3 discos de paridade, similares ao RAID5 e RAID6. Também há mirror, que é similar ao RAID1 ou RAID10, mas não é restrito à apenas 2 dispositivos. Se não especificado, cada dispositivo será acrescido como vdev, o que é similar ao RAID0. Após a criação, um dispositivo pode ser adicionado a cada vdev de dispositivo para transformar em um espelho (mirror), o que pode ser útil para migrar dados.
  • ids: O ID dos dispositivos ou partições para incluir na pool.

Criar pool com um único vdev em raidz:

# zpool create -f -m /mnt/dados bigdata \
        raidz \
            ata-ST3000DM001-9YN166_S1F0KDGY \
            ata-ST3000DM001-9YN166_S1F0JKRR \
            ata-ST3000DM001-9YN166_S1F0KBP8 \
            ata-ST3000DM001-9YN166_S1F0JTM1

Criar pool com dois vdevs em espelhados:

# zpool create -f -m /mnt/dados bigdata \
        mirror \
            ata-ST3000DM001-9YN166_S1F0KDGY \
            ata-ST3000DM001-9YN166_S1F0JKRR \
        mirror \
            ata-ST3000DM001-9YN166_S1F0KBP8 \
            ata-ST3000DM001-9YN166_S1F0JTM1

Discos com formatação avançada

Durante a criação da pool, ashift=12 deve sempre ser utilizado, exceto com SSDs que possuem setores com 8km onde ashift=13 é o correto. Um disco com vdev de tamanho 512 bytes usando setores de 4k não irá experienciar problemas de desempenho, mas um disco de 4k usando 512 irá. Já que ashift não pode ser mudado após a criação da pool, até uma pool com apenas discos de 512 bytes deve usar 4k pois pode ser necessário a substituição destes discos com outros de 4k, ou ainda a pool pode ser expandida acrescentando um vdev composto por discos de 4k. Como a detecção correta de discos de 4k não é confiável -o ashift=12 deve sempre ser utilizado durante a criação da pool, veja o conteúdo em inglês ZFS on Linux FAQ para mais detalhes.

Dica: Use blockdev(8) (parte do util-linux) como root para mostrar o tamanho do setor informado pelo ioctls do dispositivo: blockdev --getpbsz /dev/sdXY.

Crie uma pool com ashift=12 e um único vdev em raidz:

# zpool create -f -o ashift=12 -m /mnt/dados bigdata \
               raidz \
                  ata-ST3000DM001-9YN166_S1F0KDGY \
                  ata-ST3000DM001-9YN166_S1F0JKRR \
                  ata-ST3000DM001-9YN166_S1F0KBP8 \
                  ata-ST3000DM001-9YN166_S1F0JTM1

Criação de pool compatível com GRUB

Nota: Esta seção frequentemente fica desatualizada com atualizações de GRUB e ZFS. Consulte as páginas de manual para informação mais atual.

Por padrão, zpool create permite todas as opções em uma pool. Se /boot reside em um ZFS quando usando o GRUB, você deve habilitar apenas as opções suportadas pelo GRUB, caso não faça isso, o GRUB não conseguirá ler a pool. O GRUB 2.02 suporta as opções de leitura e gravação lz4_compress, hole_birth, embedded_data, extensible_dataset, e large_blocks, isto não condiz com todas as opções no ZFSonLinux 0.8.0, e deve ter as opções não adequadas desabilitadas. Pode-se inserir explicitamente o nome das opções habilitadas com o argumento -d para o comando zpool create, que desabilita todas as opções por padrão.

Você pode criar a pool com apenas as opções permitidas habilitadas:

# zpool create -d -o feature@allocation_classes=enabled \
                  -o feature@async_destroy=enabled      \
                  -o feature@bookmarks=enabled          \
                  -o feature@embedded_data=enabled      \
                  -o feature@empty_bpobj=enabled        \
                  -o feature@enabled_txg=enabled        \
                  -o feature@extensible_dataset=enabled \
                  -o feature@filesystem_limits=enabled  \
                  -o feature@hole_birth=enabled         \
                  -o feature@large_blocks=enabled       \
                  -o feature@lz4_compress=enabled       \
                  -o feature@project_quota=enabled      \
                  -o feature@resilver_defer=enabled     \
                  -o feature@spacemap_histogram=enabled \
                  -o feature@spacemap_v2=enabled        \
                  -o feature@userobj_accounting=enabled \
                  -o feature@zpool_checkpoint=enabled   \
                  $NOME_DA_POOL $VDEVS

Verificando status da pool

Se o comando for executado com sucesso, não será mostrada saída. Usando o comando mount mostrará que a pool está montada. Usando zpool status mostrará que a pool foi criada:

# zpool status -v
  pool: bigdata
 state: ONLINE
  scan: none requested
config:

        NAME                                       STATE     READ WRITE CKSUM
        bigdata                                    ONLINE       0     0     0
          -0                                       ONLINE       0     0     0
            ata-ST3000DM001-9YN166_S1F0KDGY-part1  ONLINE       0     0     0
            ata-ST3000DM001-9YN166_S1F0JKRR-part1  ONLINE       0     0     0
            ata-ST3000DM001-9YN166_S1F0KBP8-part1  ONLINE       0     0     0
            ata-ST3000DM001-9YN166_S1F0JTM1-part1  ONLINE       0     0     0

errors: No known data errors

Nesse momento, seria bom reiniciar a máquina para assegurar-se que a pool ZFS será montada durante a inicialização. É melhor lidar com todos os erros antes de transferir dados.

Importando por id uma pool criada

Eventualmente, uma pool pode falhar ao auto montar, então você precisará importar para trazer a pool de volta. Cuidado para evitar usar a solução óbvia.

Atenção: Não rode zpool import pool! Isto irá importar seus pools utilizando /dev/sd? que irá causar problemas a próxima vez que rearranjar seus drives. Que pode ser algo simples como reiniciar com um USB conectado na máquina.

Adapte algum dos comandos seguintes para importar sua pool para que as importações dela retenham a persistência com que foram criadas.

# zpool import -d /dev/disk/by-id         bigdata
# zpool import -d /dev/disk/by-partlabel  bigdata
# zpool import -d /dev/disk/by-partuuid   bigdata
Nota: Use a opção -l ao importar a pool que contenha chaves de conjuntos de dados criptografadas:
# zpool import -l -d /dev/disk/by-id bigdata

Finalmente, verifique o estado da pool:

# zpool status -v bigdata

Destruir uma pool de armazenamento

ZFS torna fácil destruir uma pool de armazenamento montada, removendo todos os metadados sobre o dispositivo ZFS.

Atenção: Este comando destrói qualquer dado contido no pool e/ou dataset.

Para destruir a pool:

# zpool destroy <pool>

Para destruir o dataset:

# zfs destroy <pool>/<dataset>

E agora, ao verificar o status:

# zpool status
no pools available

Exportar uma pool de armazenamento

Se uma pool de armazenamento precisar ser utilizada em outro sistema, primeiro necessitará ser importada. Também faz-se necessário exportar uma pool se ela foi importada à partir da archiso pois o hostid será diferente entre a ISO e o sistema inicializado. O comando zpool se recusará a importar quaisquer pools de armazenamento que não foram exportadas. É possível forçar a importação com a opção -f mas esta prática é considerada ruim.

Quaisquer tentativas de importar uma pool de armazenamento não exportadas resultará em um erro ao iniciar a pool de armazenamento informando estar sendo utilizada em outro sistema. Este erro pode ser produzido durante a inicialização, abruptamente abandonando o sistema na console busybox, necessitando da archiso para fazer o conserto, seja via exportação da pool, seja acrescentando zfs_force=1 aos parâmetros de inicialização do Kernel (o que não é ideal). Veja mais em #Durante a inicialização, a pool do ZFS não monta afirmando: "pool may be in use from other system".

Para exportar uma pool:

# zpool export <pool>

Estendendo uma pool existente

Um dispositivo (uma partição ou um disco) pode ser acrescentado a uma zpool existente:

# zpool add <pool> <id-do-dispositivo>

Para importar uma pool que consiste de múltiplos dispositivos:

# zpool import -d <id-do-dispositivo-1> -d <id-do-dispositivo-2> <pool>

Ou simplesmente:

# zpool import -d /dev/disk-by-id/ <pool>

Renomear uma pool

Renomear uma pool que já foi criada é feito em 2 passos:

# zpool export nome-antigo
# zpool import nome-antigo nome-novo

Definir um ponto de montagem diferente

O ponto de montagem para uma determinada zpool pode ser movido conforme desejado com um comando:

# zfs set mountpoint=/foo/bar nome-da-pool

Criando datasets

Usuários possuem a opção de criar um dataset sob uma zpool, diferente de manualmente criar diretórios sob a zpool. Datasets permitem um nível maior de controle (por exemplo quotas), além de snapshots. Para conseguir criar e montar um dataset, um diretório homônimo não deve existir na zpool. Para criar um dataset, use:

# zfs create <nome-da-zpool>/<nome-do-dataset>

Então é possível aplicar atributos específicos do ZFS ao dataset. Por exemplo, limite de quota para um diretório específico dentro de um dataset:

# zfs set quota=20G <nome-da-zpool>/<nome-do-dataset>/<diretório>

Para ver todos os comandos disponíveis no ZFS, veja zfs(8) ou zpool(8).

Criptografia nativa

ZFS oferece as seguintes opções suportadas de Criptografia: aes-128-ccm, aes-192-ccm, aes-256-ccm, aes-128-gcm, aes-192-gcm e aes-256-gcm. Quando a Criptografia é definida como on, aes-256-gcm será usada.

Os seguintes formatos de chave são suportados: passphrase, raw, hex.

É possível também especificar as iterações padrões do PBKDF2 quando usando passphrase com -o pbkdf2iters <n>, embora isto possa aumentar o tempo até terminar a descriptografia.

Nota:
  • Criptografia nativa no ZFS tornou-se disponível à partir da versão estável 0.8.0 ou mais nova. Anteriormente estavam disponíveis apenas em versões de desenvolvimento fornecidas por pacotes como zfs-linux-gitAUR, zfs-dkms-gitAUR ou outras versões de desenvolvimento. Usuários que estavam utilizando as versões de desenvolvimento devido à criptografia podem agora trocar pela versão estável se assim desejarem.
  • A suite padrão de criptografia foi mudada de aes-256-ccm para aes-256-gcm na versão 0.8.4.
  • Para importar uma pool com chaves, é necessário especificar a opção -l, sem esta opção, datasets criptografados ficarão indisponíveis até que as chaves sejam carregadas. Veja#Importando por id uma pool criada.

Para criar um dataset, incluíndo criptografia por senha, use:

# zfs create -o encryption=on -o keyformat=passphrase <nome-da-zpool>/<nome-do-dataset>

Para utilizar chave ao invés de senha, use:

# dd if=/dev/random of=/caminho/para/chave bs=1 count=32
# zfs create -o encryption=on -o keyformat=raw -o keylocation=file://of=/caminho/para/chave <nome-da-zpool>/<nome-do-dataset>

Para verificar o local da chave:

# zfs get keylocation <nome-da-zpool>/<nome-do-dataset>

Para mudar o local da chave:

# zfs set keylocation=file:///caminho/para/chave <nome-da-zpool>/<nome-do-dataset>

Você também pode manualmente carregar as chaves utilizando um dos seguintes comandos:

# zfs load-key <nome-da-zpool>/<nome-do-dataset> # Carrega uma chave para um dataset específico
# zfs load-key -a                                # Carrega todas as chaves
# zfs load-key -r zpool/dataset                  # Carrega todas as chaves em um dataset

Para montar um dataset criptografado criado:

# zfs mount <nome-da-zpool>/<nome-do-dataset>

Desbloquear durante a inicialização

É possível automaticamente desbloquear um dataset de uma pool durante a inicialização usando uma unidade do systemd. Por exemplo, criar o seguinte serviço para desbloquear qualquer dataset específico.

/etc/systemd/system/zfs-load-key@.service
[Unit]
Description=Carregar chaves de criptografia %I
Before=systemd-user-sessions.service
After=zfs-import.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/bash -c 'until (systemd-ask-password "Senha criptografada do ZFS para %I" --no-tty | zfs load-key %I); do echo "Tente novamente!"; done'

[Install]
WantedBy=zfs-mount.service

Habilite e inicie o serviço para cada dataset criptografado, e.g. systemctl enable zfs-load-key@pool0-dataset0 como o usuário root. Note o uso do -, que é um / escapado nas definições de unidade do systemd. Veja systemd-escape(1) para mais informações.

Nota: O Before=systemd-user-sessions.service garante que o systemd-ask-password seja invocado antes que os dispositivos locais de E/S sejam entregues para o ambiente de desktop.

Uma alternativa é carregar todas as chaves possíveis:

/etc/systemd/system/zfs-load-key.service
[Unit]
Description=Carregar chaves de criptografia
DefaultDependencies=no
After=zfs-import.target
Before=zfs-mount.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/zfs load-key -a

[Install]
WantedBy=zfs-mount.service

Habilite e inicie zfs-load-key.service.

Volume de swap

Atenção: Em sistemas com pressão de memória extremamente alto, usar um zvol como swap pode resultar em em travamento, independente da quantidade de swap disponível. Este problema está atualmente sendo investigado https://github.com/zfsonlinux/zfs/issues/7734

ZFS não permite o uso de arquivos de swap, mas usuários podem utilizar um volume de ZFS (ZVOL) como swap. É importante definir o tamanho de bloco do ZVOL para ser o mesmo do tamanho de página do sistema, que pode ser obtida com o comando getconf PAGESIZE (o padrão em x86_64 é 4KiB). Outra opção útil para manter o sistema rodando bem em situações de memória baixa é não fazer o cache dos dados do ZVOL.

Crie um volume ZFS de 8 GiB:

# zfs create -V 8G -b $(getconf PAGESIZE) \
              -o logbias=throughput -o sync=always\
              -o primarycache=metadata \
              -o com.sun:auto-snapshot=false <pool>/swap

Prepare-o como partição de swap:

# mkswap -f /dev/zvol/<pool>/swap
# swapon /dev/zvol/<pool>/swap

Para tornar permanente, edite o /etc/fstab. ZVOLs suportam "discard", que potencialmente pode ajudar o alocador de blocos do ZFS e reduzir a fragmentação para todos os outros datasets quando/se o swap não estiver cheio.

Acrescente uma linha no /etc/fstab:

/dev/zvol/<pool>/swap none swap discard 0 0

Listas de Controle de Acesso

Para utilizar Listas de Controle de Acesso (ACL) em um dataset:

# zfs set acltype=posixacl <nome-da-zpool>/<nome-do-dataset>
# zfs set xattr=sa         <nome-da-zpool>/<nome-do-dataset>

Definir xattr é recomendado por questões de desempenho, como é possível ver no conteúdo em inglês [3].

Pode ser preferível habilitar o ACL na zpool pois os datasets irão herdar os parâmetros de ACL. Configurar aclinherit=passthrough Pode ser desejado pois o modo padrão é restricted, vide [4] (conteúdo em inglês):

# zfs set aclinherit=passthrough <nome-da-zpool>
# zfs set acltype=posixacl       <nome-da-zpool>
# zfs set xattr=sa               <nome-da-zpool>

Bancos de dados

ZFS, diferente da maioria dos outros sistemas de arquivos, tem u, tamanho de registro variável, ou o que é comumente chamado de tamanho de bloco. Por padrão, o tamanho de registro "recordsize" no ZFS é 128KiB, o que significa que irá alocar blocos dinamicamente de qualquer tamanho entre 512B e 128KiB, dependendo do tamanho do arquivo sendo escrito. Isto frequentemente pode ajudar com fragmentation e acesso a arquivos, com o custo que o ZFS teria ao alocar novos blocos de 128KiB cada vez que apenas alguns bytes são escritos.

A maioria dos SGBDRs trabalham com blocos com tamanho de 8KiB por padrão. Apesar do tamanho de bloco ser regulável para MySQL/MariaDB, PostgreSQL, e Oracle database, todos os 3 usam o tamanho de bloco de 8KiB por padrão. Tanto para preocupações com desempenho e manter diferença mínima em snapshots (em questão de backups, é útil), geralmente é desejável realizar configurações no ZFS para acomodar os banco de dados utilizando comandos como:

# zfs set recordsize=8K <pool>/postgres

Estes SGBDRs também tendem a implementar o próprio algoritmo de cache, geralmente similar ao próprio ARC do ZFS. Para economizar memória, é melhor simplemsnte desabilitar o cache do ZFS para o arquivo de banco de dados e deixar com que o banco faça o próprio gerenciamento:

# zfs set primarycache=metadata <pool>/postgres

Se sua pool não possui dispositivos de log, o ZFS reserva espaço dos discos de dados das pools para seu log (ZIL). O ZFS utiliza isso para recuperação em casos de "crash", mas bancos de dados geralmente sincronizam seus arquivos de dados para o sistema de arquivos dentro das confirmações de transações de qualquer forma. O resultado final é que o ZFS fará a gravação dos dados duas vezes, isto pode impactar severamente o desempenho. Você pode gerenciar para que o ZFS não use o ZIL, neste caso, os dados serão gravados no sistema de arquivos uma vez. Configurando isto para sistemas de arquivos não destinados à bancos de dados ou para pools com dispositivos com log configurados podem impactar negativamente o desempenho, então cuidado:

# zfs set logbias=throughput <pool>/postgres

Isto também pode ser feito durante a criação do sistema de arquvios, por exemplo:

# zfs create -o recordsize=8K \
             -o primarycache=metadata \
             -o mountpoint=/var/lib/postgres \
             -o logbias=throughput \
              <pool>/postgres

Por favor perceba: estes tipos de parâmetros de refinamento são ideais para aplicações especializadas como sistemas de bancos de dados relacionais. Você pode prejudicar o desempenho do ZFS ao configurar um sistema de arquivos de propósito generalizado como o seu diretório /home.

/tmp

Se você quiser usar o ZFS para armazenar seu diretório /tmp, o que pode ser útil para armazenar conjuntos de arquivos arbitrariamente grandes ou simplesmente manter sua RAM livre de dados, geralmente você pode melhorar o desempenho de certas aplicações que escrevem no /tmp desabilitando a sincronização do sistema de arquivos. Isto faz com que o ZFS ignore as requisições de sincronização das aplicações (e.g. com fsync ou O_SYNC) e retorne imediatamente. Embora isso tenha sérias conseqüências de consistência de dados no lado de aplicações (nunca desative a sincronização para um banco de dados!), É menos provável que os arquivos em /tmp sejam importantes e afetados. Observe que isso não afeta a integridade do ZFS, apenas a possibilidade de que os dados esperados por um aplicativo no disco possam não ter sido gravados após um "crash".

# zfs set sync=disabled <pool>/tmp

Além disso, por motivos de segurança. você pode querer desabilitar setuid e devices no sistema de arquivos /tmp, o que impede alguns tipos de ataques de escalação de privilégios ou o uso de nós de dispositivos:

# zfs set setuid=off  <pool>/tmp
# zfs set devices=off <pool>/tmp

Combinar todos eles em um comando de criação é feito da seguinte forma:

# zfs create -o setuid=off -o devices=off -o sync=disabled -o mountpoint=/tmp <pool>/tmp

Por favor note, também. que se você deseja /tmp no ZFS, você precisará mascarar (desabilitar) o /tmp baseado em tmpfs automático do systemd, se não, o ZFS não será capaz de montar seu dataset durante a inicialização ou durante a etapa de importação:

# systemctl mask tmp.mount

Refinamento

Geral

Pools e datasets do ZFS podem ter ainda mais ajustes e refinamentos (tunings) utilizando parâmetros.

Nota: Todas as propriedades configuráveis, com exceção de quotas e reservas, herdam seu valor do dataset pai.

Para obter o status atual com os parâmetros da pool:

# zfs get all <pool>

Para obter o status atual com os parâmetros do dataset:

# zfs get all <pool>/<dataset>

Para desabilitar o tempo de acesso (atime), que é habilitado por padrão:

# zfs set atime=off <pool>

Para desabilitar o tempo de acesso (atime) em um dataset específico:

# zfs set atime=off <pool>/<dataset>

Uma alternativa a desabilitar o atime completamente, o relatime está disponível. Isto traz a semântica padrão do ext4/XFS ao ZFS, na qual o tempo de acesso somente é atualizado se o tempo de modificação ou tempo de criação é modificado, ou se o tempo existente de acesso não foi atualizado dentro das últimas 24 horas. É uma mistura entre atime=off e atime=on. Esta propriedade tem efeito se atime estiver on.

# zfs set atime=on    <pool>
# zfs set relatime=on <pool>

Compression é apenas compressão transparente de dados. ZFS suporta poucos algoritmos, atualmente lz4 é o padrão, gzip também está disponível para dados raramente escrítos e ainda assim altamente compressível; consulte mais detalhes na Wiki do OpenZFS (conteúdo em inglês) para mais detalhes.

Para habilitar compressão:

# zfs set compression=on <pool>

Para redefinir uma propriedade de uma pool ou dataset para o estado padrão, use zfs inherit:

# zfs inherit -rS atime <pool>
# zfs inherit -rS atime <pool>/<dataset>
Atenção: Usar a opção -r redefinirá recursivamente todos os datasets na zpool.

Esfregar

Quando dado é lido e o ZFS encontra erro, ele é silenciosamente reparado quando possível, reescrito de volta no disco e gera-se um log para que você possa obter uma visão geral de erros em suas pools. Não existe fsck ou ferramenta equivalenete para o ZFS. Ao invés disto, o ZFS suporta a opção de "esfregar". Isto percorre todos os dados na pool e verifica se todos os blocos podem ser lidos.

Para esfregar uma pool:

# zpool scrub <pool>

Para cancelar um esfregamento em execução:

# zpool scrub -s <pool>

Com que frequência devo fazer isto?

Da postagem no blog da Oracle Disk Scrub - Why and When?:

Esta pergunta é desafiadora até para o Supporte responder, porque como sempre a resposta correta é "Depende". Então antes que eu ofereça orientações gerais, aqui estão algumas dicas para lhe auxiliar a criar uma resposta mais apropriada para o seu padrão de uso.
  • Qual é a expiração do seu backup mais antigo? Você provavalmente deve esfregar seus dados pelo menos com a mesma frequência que as suas fitas mais antigas expiram para que você tenha um ponto de restauração que você saiba que é bom.
  • Com que frequência você experiencia falhas de disco? Embora o recrutamento de um disco hot-spare invoque um "resilver" -- um esfregamento direcionado apenas do VDEV que perdeu um disco -- você deve provavelmente esfregar pelo menos com a mesma frequência que você experiencia, em média, falhas de discos no seu ambiente.
  • Com que frequência o pedaço de dado mais antigo em seu disco é lido? Você deve esfregar ocasionalmente para que dados muito antigos e muito velhos não experienciem apodrecimento de bit "bit-rot" e morram sem que você perceba.
Se para qualquer uma das perguntas acima sua resposta seja "Não sei", a orientação geral é: você provavelmente deve esfregar sua zpool pelo menos uma vez por mês. É um agendamento que funciona bem para a maioria dos casos de uso, provê tempo suficiente para esfregamentos terminarem antes que outros sejam iniciados inclusive nos sistemas com maior carga, até mesmo deve concluir em zpools bem grandes (192 discos ou mais) antes que discos falhem.

No ZFS Administration Guide, de Aaron Toponce, ele aconselha esfregar discos de consumidores pelo menos uma vez por semana.

Iniciar com serviço ou timer

Usar um temporizador/serviço do systemd é possível para automaticamente esfregar pools.

Para realizar o esfregamento mensalmente de uma pool específica:

/etc/systemd/system/zfs-scrub@.timer
[Unit]
Description=Esfregar mensalmente a zpool em %i

[Timer]
OnCalendar=monthly
AccuracySec=1h
Persistent=true

[Install]
WantedBy=multi-user.target
/etc/systemd/system/zfs-scrub@.service
[Unit]
Description=Esfregar zpool em %i

[Service]
Nice=19
IOSchedulingClass=idle
KillSignal=SIGINT
ExecStart=/usr/bin/zpool scrub %i

[Install]
WantedBy=multi-user.target

Habilite e inicie a unidade zfs-scrub@pool-pra-esfregar.timer para esfregar mensalmente a pool especificada.

Cache em SSD

Você pode adicionar dispositivos SSD com a inteção de gravar logs (ZIL ou SLOG externo) e também como um cache de substituição adaptável da camada 2 (L2ARC). O processo para adicioná-los é muito semelhante à adição de um novo VDEV.

Todas as referências abaixo à identificação do dispositivo são os IDs em /dev/disk/by-id/*.

SLOG

Para adicionar um SLOG espelhado:

 # zpool add <pool> log mirror <identificação-do-dispositivo-1> <identificação-do-dispositivo-2>

Ou para acrescentar um único dispositivo SLOG (inseguro):

 # zpool add <pool> log <identificação-do-dispositivo>

Como o dispositivo SLOG armazena dado que não foi escrito na pool, é importante usar dispositivos que podem finalizar escritas quando a energia é perdida. Também é importante utilizar redundância, já que a falha em um único dispositivo pode causar perda de dados. Além do mais, o SLOG é apenas utilizado para sincronizar escritas, então pode não auxiliar com melhorias de desempenho.

L2ARC

Para acrescentar L2ARC:

 # zpool add <pool> cache <identificação-do-dispositivo>

Como cada bloco armazenado no L2ARC utiliza uma pequena quantidade de memória, geralmente só é útil em cargas onde o dado quente é *maior* que a quantidade total de memória que pode caber no computador, mas pequena suficiente para caber no L2ARC. O L2ARC também é limpo durante a reinicialização e é somente um cache de leitura, então a redundância é desnecessária. Não intuitivamente, L2ARC pode impactar no desempenho pois utiliza parte da memória que seria utilizada pelo ARC.

ZVOLs

Volumes de ZFS (ZVOLs) podem sofrer dos mesmos problemas relacionados à tamanho de blocos que SGBDRs, mas vale notar que o tamanho de registro padrão de ZVOLs já é 8KiB. Se possível, é melhor alinhar partições contidas em um ZVOL para o tamanho do seu recordsize (versões atuais de fdisk e gdisk por padrão automaticamente alinham segmentos de 1MiB, o que resolve), e tamanhos de blocos de sistema de arquivos para o mesmo tamanho. Mais do que isso, você pode ajustar o recordsize para acomodar os dados dentro do ZVOL conforme necessário (apesar que 8 KiB tende a ser um bom valor para a maioria dos sistemas de arquivos, mesmo ao utilizar blocos de 4 KiB naquele nível).

RAIDZ e discos físicos com Formatação Avançada

Cada bloco em um ZVOL possui seu próprio disco de paridade, e se você tiver mídias físicas com tamanhos de blocos de 4096B, 8192B ou assim por diante, a paridade precisa ser armazenada em blocos físicos inteiros, e isto pode drasticamente aumentar os requerimentos de espaço de um ZVOL, necessitando 2× ou mais capacidade de armazenamento do que a capacidade lógica do ZVOL. Definindo o recordsize como 16k ou 32k pode ajudar a reduzir drasticamente este efeito.

Veja ZFS on Linux issue #1807 para detalhes

Escalonador de E/S

Quando a pool é importada, para vdevs que ocupam to o disco, o escalonador de E/S de dispositivos de bloco é definido através do zfs_vdev_scheduler [5] (conteúdo em inglês). Os escalonadores mais comuns são noop, cfq, bfq, e deadline.

Em alguns casos, o escalonador não é mutável ao usar este método. Escalonadores que não podem ser mudados são: scsi_mq and none. Nestes casos, o escalonador permanece inalterado e uma mensagem de erro pode ser relatada nos logs. Definindo manualmente um dos escalonadores comuns através do zfs_vdev_scheduler pode resultar em desempenho mais consistente.

Solução de Problemas

Criação de uma zpool falha

Se o seguinte erro ocorrer, então é possível consertar.

# the Kernel failed to rescan the partition table: 16
# cannot label 'sdc': try using parted(8) and then provide a specific slice: -1

Uma razão para isto occorer é porque o ZFS expera que a criação de uma pool leve menos que 1 segundo (conteúdo em inglês). Esta é uma suposição razoável em condições normais, mas em muitas situações, pode levar mais tempo. Cada dispositivo precisará ser limpo novamente antes que alguma tentativa possa ser feita.

# parted /dev/sda rm 1
# parted /dev/sda rm 1
# dd if=/dev/zero of=/dev/sdb bs=512 count=1
# zpool labelclear /dev/sda

Uma criação com força bruta pode ser tentada repetidamente, e, com alguma sorte, a criação da ZPool levará menos que 1 segundo. Uma causa para lentidão na criação pode ser picos de leitura e gravações lentos no dispositivo. Causando leitura no disco em paralelo à criação da ZPool, é possível acelerar a velocidade do pico.

# dd if=/dev/sda of=/dev/null

Isto pode ser feito com múltiplos dispositivos salvando o comando acima para cada dispositivo de armazenamento em uma linha diferente e executando

# cat $ARQUIVO | parallel

Então, rode a criação da ZPool ao mesmo tempo.

ZFS está utilizando muita RAM

Por padrão, o ZFS realiza o cache de operações nos arquivos (ARC - conteúdo em inglês), chegando a utilizar até ⅔ da memória disponível na máquina. Para ajustar o tamanho do ARC, acrescente o seguinte conteúdo à lista de Parâmetros do kernel:

zfs.zfs_arc_max=536870912 # (para 512MiB)

No caso em que o valor padrão de zfs_arc_min (1/32 da memória do sistema) seja maior do que o especificado zfs_arc_max, também é necessário acrescentar o seguinte na lista de Parâmetros do kernel:

zfs.zfs_arc_min=268435456 # (para 256MiB, precisa ser inferior ao do zfs.zfs_arc_max)

Para uma descrição mais detalhada, assim como outras opções de configuração, veja gentoo-wiki:zfs#arc (Conteúdo em inglês).

Não contém um rótulo EFI

O seguinte erro irá ocorrer ao tentar criar o sistema de arquivos ZFS,

/dev/disk/by-id/<id> does not contain an EFI label but it may contain partition

Para supererar este erro, use -f junto ao comando zfs create.

Não encontrou hostid

Um erro que ocorre durante a inicialização com as seguintes linhas aparece antes da saída do scipt de inicialização:

ZFS: No hostid found on Kernel command line or /etc/hostid.

Este aviso ocorre pois o módulo do ZFS não tem acesso ao SPL hospedado. Existem duas soluções para isso. Ou insira a identificação do anfitrião (hostid) nos Parâmetros do kernel no gerenciador de inicialização, colocando spl.spl_hostid=0x00bab10c. Ou garanta que existe um hostid em /etc/hostid, então Gere novamente o initramfs. Que irá copiar o hostid para a imagem do initramfs.

Pool não encontrada ao iniciar de dispositivos SAS/SCSI

Caso você esteja iniciando à partir de um SAS/SCSI, você pode ocasionalmente ter problemas de inicialização nos quais a pool que seu sistema está tentando utilizar para inicialização não pode ser encontrada. Uma possível razão para isto é que seus dispositivos foram inicializados tarde demais durante o processo. Isso significa que o ZFS não pode encontrar nenhum dispositivo no instante que tentou montar a pool.

Neste caso, você deve forçar o driver SCSI a aguardar para que os dispositivos estejam disponíveis antes de continuar. Você pode fazer isto inserindo o seguinte em /etc/modprobe.d/zfs.conf:

/etc/modprobe.d/zfs.conf
options scsi_mod scan=sync

Depois, gere novamente o initramfs.

Isto funciona pois o gancho do ZFS irá copiar o arquivo em /etc/modprobe.d/zfs.conf para o initcpio, que será então utilizado ao ser construído.

Durante a inicialização, a pool do ZFS não monta afirmando: "pool may be in use from other system"

Pool não exportada

Se a nova instalação não inicializa pois a zpool não pôde ser importada. Faça chroot para a instalação e exporte apropriadamente a zpool. Veja #Conserto de emergência em chroot com archzfs.

Uma vez dentro do ambiente chroot, carrege o módulo ZFS e force a importação da zpool:

# zpool import -a -f

Agora exporte a pool

# zpool export <pool>

Para ver as pools disponíveis:

# zpool status

É necessário exportar a pool devido à forma que o ZFS utiliza o hostid para descobrir o sistema no qual a zpool foi criada. O hostid é gerado parcialmente baseado na configuração da rede. Durante a instalação na archiso, a configuração de rede pode estar diferente, gerando um hostid diferente daquele contido na nova instalação. Uma vez que o sistema de arquivos ZFS é exportado e então reimportado na nova instalação, a hostid é redefinida. Veja o conteúdo em inglês Re: Howto zpool import/export automatically? - msg#00227.

Se o ZFS reclamar "a pool pode já estar em uso por outro sistema" mesmo após reinicializar, faça a exportação apropriadamente como descrito acima, então gere novamente o initramfs no sistema normalmente inicializado.

hostid incorreta

Verifique duas vezes se a pool foi exportada corretamente. Exportar a zpool limpa a hostid que marca a posse. Então durante a primeira inicialização, a zpool deve montar corretamente, caso não, exite outro problema.

Reinicie novamente, se a pool do zfs não for montada, significa que a hostid ainda não está propriamente definida durante o início da etapa de inicialização e isto confunde o ZFS. Manualmente informe ao zfs o número correto, uma vez que a hostid esteja coerente entre as reinicializações, a zpool montará corretamente.

Inicie utilizando zfs_force e escreva a hostid.

$ hostid
0a0af0f8

Este número deve ser acrescentado aos Parâmetros do kernel como spl.spl_hostid=0x0a0af0f8. Outra solução é escrever a hostid dentro da imagem de initramfs, veja a explicação no guia de instalação.

Usuários podem sempre ignorar a verificação e acrescentar zfs_force=1 nos Parâmetros do kernel, mas não é aconselhável tornar esta a solução permanente.

Dispositivos possuem diferentes alinhamentos de setor

Uma vez que um dispositivo estiver com defeito, ele deve ser substituído o mais rapidamente possível, por um aparelho idêntico.

# zpool replace bigdata ata-ST3000DM001-9YN166_S1F0KDGY ata-ST3000DM001-1CH166_W1F478BD -f

Mas, neste exemplo, o seguinte erro ocorre:

cannot replace ata-ST3000DM001-9YN166_S1F0KDGY with ata-ST3000DM001-1CH166_W1F478BD: devices have different sector alignment

ZFS utiliza a opção ashift para se ajustar aos tamanhos de blocos físicos. Ao substituir o disco com defeito, ZFS tenta utilizar ashift=12, mas o discodefeituoso possivelmente utiliza outro valor de ashift (possivelmente ashift=9), e isto causa o erro acima.

Para Discos com Formatação Avançada com tamanho de bloco de 4KiB, um valor de ashift de 12 é recomendado para melhor desempenho. Veja os conteúdos em inglês 1.10 What’s going on with performance? e ZFS and Advanced Format disks.

Use zdb para descobrir o valor de ashift para a ZPool - zdb - então use o argumento -o para definir o ashift no dispositivo que substituirá:

# zpool replace bigdata ata-ST3000DM001-9YN166_S1F0KDGY ata-ST3000DM001-1CH166_W1F478BD -o ashift=9 -f

Verifique o status da zpool para confirmar:

# zpool status -v
pool: bigdata
state: DEGRADED
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
scan: resilver in progress since Mon Jun 16 11:16:28 2014
    10.3G scanned out of 5.90T at 81.7M/s, 20h59m to go
    2.57G resilvered, 0.17% done
config:

        NAME                                   STATE     READ WRITE CKSUM
        bigdata                                DEGRADED     0     0     0
        raidz1-0                               DEGRADED     0     0     0
            replacing-0                        OFFLINE      0     0     0
            ata-ST3000DM001-9YN166_S1F0KDGY    OFFLINE      0     0     0
            ata-ST3000DM001-1CH166_W1F478BD    ONLINE       0     0     0  (resilvering)
            ata-ST3000DM001-9YN166_S1F0JKRR    ONLINE       0     0     0
            ata-ST3000DM001-9YN166_S1F0KBP8    ONLINE       0     0     0
            ata-ST3000DM001-9YN166_S1F0JTM1    ONLINE       0     0     0

errors: No known data errors

Resilver de pool parado/preso/reiniciando/lento?

De acordo com o github do ZnL, este é um problema conhecido desde 2012 com ZFS-ZED, que faz com que o processo de resilver constantemente reinicie, as vezes fique parado/preso e geralmente lento em alguns hardwares. A mitigação mais simples é parar o zfs-zed.service até que o resilver complete.

Consertar inicialização lenta causada por falha na importação de pools indisponíveis no zpool.cache do initramfs

Seu tempo até inicializar pode ser significativamente impactado se a sua atualização do initramfs (ex: ao fazer a atualização do Kernel) quando você possui adicionais pools mas que não são permanentemente conectadas importadas porque estas pools serão acrescentadas ao zpool.cache e o ZFS tentará importar estas pools adicionais a cada inicialização, independentemente se você exportou e removeu do seu zpool.cache normal.

Se você perceber que o ZFS está tentando importar pools indisponíveis durante a inicialização, primeiro rode:

$ zdb -C

Para ver em seu zpool.cache pools que você não quer importadas durante a inicialização. Se este comando estiver mostrando pools adicionais, e não atualmente disponíveis, rode:

# zpool set cachefile=/etc/zfs/zpool.cache zroot

Para limpar o zpool.cache de quaisquer outras pools que não possuírem o nome zrool. Às vezes não é necessário redefinir o zpool.cache, mas simplesmente gerar o initramfs novamente

Dicas e truques

Embutir os pacotes do archzfs na archiso

Siga os passos da Archiso para criar uma imagem live completamente funcional de CD/DVD/USB do Arch Linux.

Habilite o repositório do archzfs:

~/archlive/pacman.conf
...
[archzfs]
Server = http://archzfs.com/$repo/x86_64
SigLevel = Optional TrustAll

Acrescente o grupo archzfs-linux à lista de pacotes a serem instalados (o repositório do archzfs fornece os pacotes apenas para a arquitetura x86_64).

~/archlive/packages.x86_64
...
archzfs-linux

Complete a compilação da ISO para finalmente criar a ISO.

Nota: Se você posteriormente tiver problemas ao rodar modprobe zfs, você deve incluir linux-headers no packages.x86_64.

Snapshots automáticos

Serviço de snapshots automáticos do ZFS para o Linux

O pacote zfs-auto-snapshot-gitAUR AUR fornece um script em shell para automatizar o gerenciamento de snapshots, com cada um recebendo o nome da data e rótulo (por hora, por dia, etc), fornecendo a obtenção rápida e conveniente de snapshots de todos os datasets do ZFS. O pacote também instala tarefas do cron para gerar snapshots a cada 15 minutos, hora, dia, semana e mês. Opcionalmente, ajuste o parâmetro --keep dos padrões dependendo da quantidade de tempo que você deseja que os snapshots existam (para o script mensal, a retenção é de até 1 ano).

Para impedir que um snapshots seja criado para um dataset específico, defina com.sun:auto-snapshot=false nele. Similarmente, tenha um controle mais refinado também definindo por rótulo, se, por exemplo, nenhum snapshot deva ser mantido para o período mensal definindo com.sun:auto-snapshot:monthly=false.

Nota: zfs-auto-snapshot-git não criará snapshots durante o esfregamento. É possível sobrescrever isto (editando a unidade do systemd fornecida) e removendo --skip-scrub na linha ExecStart.

Com o pacote já instalado, habilite e inicie os temporizadores selecionados (zfs-auto-snapshot-{frequent,daily,weekly,monthly}.timer).

zrepl

O pacote zrepl zreplAUR do AUR fornece um serviço de replicação automático, que pode ser também utilizado como um serviço para tirar snapshots, como o snapper.

Para detalhes em como configurar o daemon do zrepl, veja a documentação do zrepl. O arquivo de configuração deve estar em /etc/zrepl/zrepl.yml. Então, execute zrepl configcheck para ter certeza que a sintaxe do arquivo de configuração está correta. Finalmente, habilite zrepl.service.

Criando um compartilhamento

ZFS possui suporte para criares compartilhamentos (shares) por NFS ou SMB.

NFS

Assegure-se que NFS foi instalado/configurado, note que não há necessidade de editar o arquivo /etc/exports. Para compartilhar em cima de NFS, os serviços nfs-server.service e zfs-share.service deve ser iniciado.

Para tornar uma pool disponível na rede:

# zfs set sharenfs=on <nome-da-pool>

Para tornar um dataset disponível na rede:

# zfs set sharenfs=on <nome-da-pool>/<nome-do-dataset>

Para permitir acesso de leitura/escrita em um intervalo específico de IPs:

# zfs set sharenfs="rw=@192.168.1.100/24,rw=@10.0.0.0/24" <nome-da-pool>/<nome-do-dataset>

Para verificar se o dataset foi exportado com sucesso:

# showmount -e hostname
Export list for hostname:
/path/of/dataset 192.168.1.100/24

Para ver as exportações atualmente carregadas com mais detalhes, use:

# exportfs -v
/path/of/dataset
    192.168.1.100/24(sync,wdelay,hide,no_subtree_check,mountpoint,sec=sys,rw,secure,no_root_squash,no_all_squash)

Para ver a lista atual de compartilhamentos em NFS do ZFS:

# zfs get sharenfs

SMB

Ao compartilhar através de SMB, usar usershares em /etc/samba/smb.conf permitirá ao ZFS configurar e criar os compartilhamentos.

# [global]
#    usershare path = /var/lib/samba/usershares
#    usershare max shares = 100
#    usershare allow guests = yes
#    usershare owner only = no

Crie e defina permissões no diretório do usuário como root.

# mkdir /var/lib/samba/usershares
# chmod +t /var/lib/samba/usershares

Para tornar disponível uma pool na rede:

# zfs set sharesmb=on <nome-da-zpool>

Para tornar disponível um dataset na rede:

# zfs set sharesmb=on <nome-da-zpool>/<nome-do-dataset>

Para verificar se o dataset foi exportado com sucesso:

# smbclient -L localhost -U%
        Sharename       Type      Comment
        ---------       ----      -------
        IPC$            IPC       IPC Service (SMB Server Name)
        <nome-da-zpool>_<nome-do-dataset>        Disk      Comment: caminho/do/dataset
SMB1 disabled -- no workgroup available

Para ver a lista atual de compartilhamentos em SMB do ZFS:

# zfs get sharesmb

Criptografia no ZFS utilizando dm-crypt

A versão estável do ZFS no Linux não possuía suporte à criptografia (agora está disponível, veja #Criptografia nativa), mas zpools podem ser criados em dispositivos de bloco do dm-crypt. Já que a zpool é criada com a abstração plain-text (em texto simples, ou seja, não criptografado), é possível ter os dados criptografados e ainda aproveitar todas as vantagens do ZFS como deduplicação, compressão e robustez de dados.

dm-crypt, possivelmente através de LUKS, cria dispositivos em /dev/mapper e o nome é fixo. Então somente é necessário mudar o comando zpool create para apontar para aqueles nomes. A ideia é configurar o sistema para criar os dispositivos de bloco em /dev/mapper e importar as ZPools de lá. Como as ZPools podem ser criadas em múltiplos dispositivos (em RAID, espelhados, em faixas/striping, ...), é importante que todos os dispositivos estejam criptografados, caso não, a proteção poderá estar parcialmente perdida.

Por exemplo, uma ZPool criptografada pode ser criada usando somente dm-crypt (sem LUKS) com:

# cryptsetup --hash=sha512 --cipher=twofish-xts-plain64 --offset=0 \
             --key-file=/dev/sdZ --key-size=512 open --type=plain /dev/sdX enc
# zpool create zroot /dev/mapper/enc

No caso de uma pool para o sistema de arquivos do root, a linha dos HOOKS do /etc/mkinitcpio.conf precisa permitir o teclado para a senha, criar os dispositivos e carregar as pools, portanto, ficará similar ao seguinte:

HOOKS="... keyboard encrypt zfs ..."

Já que o nome /dev/mapper/enc é fixo, nenhum erro de importação ocorrerá.

Criar pools criptografadas funciona bem, no entanto, caso precise criptografar diretórios, por exemplo para proteger os diretórios pessoas dos usuários, o ZFS perde parte da funcionalidade.

ZFS enxergará o dado criptografado, não a abstração em texto simples, então a compressão e a deduplicação não funcionará. A razão é que o dado criptografado tem sempre alta entropia, fazendo com que a compressão seja ineficiente e até mesmo da mesma entrada, ocorrem saídas diferentes (graças ao salt), tornando a deduplicação impossível. Para reduzir sobrecarga desnecessária, é possível criar um subsistema de arquivos para cada diretório criptografado e usar eCryptfs nele.

Por exemplo, para ter o /home criptografado: (as duas senhas, de criptografia e login, devem ser a mesma).

# zfs create -o compression=off -o dedup=off -o mountpoint=/home/<nome-do-usuário> <zpool>/<nome-do-usuário>
# useradd -m <nome-do-usuário>
# passwd <nome-do-usuário>
# ecryptfs-migrate-home -u <nome-do-usuário>
<Faça o login e complete o procedimento com o ecryptfs-unwrap-passphrase>

Conserto de emergência em chroot com archzfs

Para entrar no sistema de arquivos ZFS à partir do sistema live para manutenção, existem duas opções:

  1. Construa uma archiso personalizada com ZFS como descrito em #Embutir os pacotes do archzfs na archiso.
  2. Inicialize na archiso oficial mais recente disponível, garanta acesso à rede, então habilite o repositório archzfs dentro do sistema live como de costume, sincronize o banco de dados de pacotes do pacman e instale o pacote archzfs-archiso-linux.

Para iniciar a recuperação, carregue o módulo do ZFS:

# modprobe zfs

Importe a pool:

# zpool import -a -R /mnt

Monte as partições de inicialização (se existir alguma):

# mount /dev/sda2 /mnt/boot
# mount /dev/sda1 /mnt/boot/efi

Faça o chroot para o sistema de arquivos ZFS:

# arch-chroot /mnt /bin/bash

Verifique a versão do Kernel:

# pacman -Qi linux
# uname -r

O comando uname mostrará a versão do Kernel na archiso. Se forem diferentes, execute depmod (no ambiente chroot) com a versão correta do Kernel da instalação do chroot:

# depmod -a 3.6.9-1-ARCH (versão obtida com pacman -Qi linux mas usando os módulos respectivos do Kernel dentro do /lib/modules no chroot)

Isto carregará os módulos corretos do Kernel para a versão do Kernel instalada durante a instalação do chroot.

Gere novamente o initramfs. Não deve haver erros.

Montagem com bind

Aqui, uma montagem com bind do /mnt/zfspool para /srv/nfs4/musica é criada. A configuração garante que a pool de ZFS esteja pronta antes que a montagem com bind seja criada.

fstab

Veja systemd.mount(5) para mais informações em como o systemd converte fstab em unidades de montagem com o systemd-fstab-generator(8), ambos os conteúdos são em inglês.

/etc/fstab
/mnt/zfspool		/srv/nfs4/musica		none	bind,defaults,nofail,x-systemd.requires=zfs-mount.service	0 0

Monitoração/envio de e-mails em eventos

Veja ZED: The ZFS Event Daemon para mais informações.

Um encaminhador de e-mail, como S-nail é necessário para conseguir isto. Teste para assegurar que está funcionando corretamente.

Descomente o seguinte no arquivo de configuração:

/etc/zfs/zed.d/zed.rc
 ZED_EMAIL_ADDR="root"
 ZED_EMAIL_PROG="mailx"
 ZED_NOTIFY_VERBOSE=0
 ZED_EMAIL_OPTS="-s '@SUBJECT@' @ADDRESS@"

Mude 'root' em ZED_EMAIL_ADDR="root" para o endereço de e-mail no qual deseja receber as notificações.

Se você está mantendo o seu mailrc no seu diretório pessoal (home), você pode informar o mail para obter de lá configurando o MAILRC:

/etc/zfs/zed.d/zed.rc
export MAILRC=/home/<usuário>/.mailrc

Isto funciona pois o ZED lê este arquivo, então o mailx enxergara esta variável de ambiente.

Se você quer receber um e-mail, não importa o estado de sua pool, você deve definir ZED_NOTIFY_VERBOSE=1. Você precisa fazer isto temporariamente para testar.

Habilite e inicie zfs-zed.service.

Com ZED_NOTIFY_VERBOSE=1, você pode testar ao executar um esfregamento como root: zpool scrub <nome-da-pool>.

Utilizar comandos de shell antes e depois de snapshots

Já que é tão barato gerar um snapshot, podemos utilizar isto como medida de segurança para comandos sensíveis como atualização de pacotes e sistema. Se tirarmos um snapshot antes e um depois, é possível analisar as diferenças entre estes snapshots para descobrir o que foi modificado no sistema de arquivos depois que o comando foi executado. Além disso, podemos também voltar caso o resultado não tenha sido desejado.

E.g.:

# zfs snapshot -r zroot@pre
# pacman -Syu
# zfs snapshot -r zroot@post
# zfs diff zroot@pre zroot@post
# zfs rollback zroot@pre

Um utilitário que automatiza a criação anterior e posterior de snapshots envolvendo um comando do shell é znp.

E.g.:

# znp pacman -Syu
# znp find / -name "algo*" -delete

E você conseguirá snapshots antes e depois do comando fornecido, e também a saída do comando é inserida em logs de arquivos para referência futura, para que saibamos qual comando criou o diff visto em um par de snapshots pré/pós.

Desbloquear remotamente root ZFS criptografado

A partir do PR #261, archzfs suporta desbloqueio por SSH de datasets nativamente criptografados. Esta seção descreve como utilizar esta opção, e é amplamente baseada em Dm-crypt/Specialties#Busybox based initramfs (built with mkinitcpio).

  1. Instale mkinitcpio-netconf para fornecer os hooks (ganchos) para montar a rede inicial no espaço de usuário.
  2. Escolha um servidor de SSH para usar no início do espaço do usuário. Opções mutualmente exclusivas são mkinitcpio-tinyssh ou mkinitcpio-dropbear.
    1. Se utilizar mkinitcpio-tinyssh, também é recomendado instalar tinyssh ou tinyssh-convert-gitAUR. Esta ferramenta converte uma hostkey do OpenSSH existente para o formato de chave do TinySSH, preservando a impressão digital da chave e evitando avisos de conexão. Os scripts de instalação do mkinitcpio do TinySSH e Dropbear automaticamente converterão hostkeys existentes ao gerar uma imagem nova de initpcio.
  3. Decida se irá utilizar uma chave de OpenSSH existente ou gerará uma nova (recomendado) para a máquina que se conectará e desbloqueará a máquina com ZFS criptografado. Copie a chave pública para /etc/tinyssh/root_key ou /etc/dropbear/root_key. Ao gerar a imagem de initcpio, este arquivo será adicionado às chaves autorizadas (authorized_keys) para o usuário root e somente é válida no ambiente initrd.

Decide whether to use an existing OpenSSH key or generate a new one (recommended) for the host that will be connecting to and unlocking the encrypted ZFS machine. Copy the public key into /etc/tinyssh/root_key or /etc/dropbear/root_key. When generating the initcpio image, this file will be added to authorized_keys for the root user and is only valid in the initrd environment.

  1. Acrescente o parâmetro do Kernel ip= à sua configuração do carregador de inicialização. A string ip é altamente configurável (conteúdo em inglês). Um exemplo simples com DHCP é mostrado abaixo.
    ip=:::::eth0:dhcp
  2. Edite /etc/mkinitcpio.conf para incluir os ganchos netconf, dropbear ou tinyssh, e zfsencryptssh antes do gancho zfs:
    HOOKS=(... netconf <tinyssh>|<dropbear> zfsencryptssh zfs ...)
  3. Gere novamente o initramfs.
  4. Reinicie e teste!

Mudando a porta do servidor de SSH

Por padrão, ambos mkinitcpio-tinyssh e mkinitcpio-dropbear escutam na porta 22. Para mudar isto.

Para TinySSH, copie /usr/lib/initcpio/hooks/tinyssh para /etc/initcpio/hooks/tinyssh, e encontre/modifique a seguinte linha na função run_hook():

/etc/initcpio/hooks/tinyssh
/usr/bin/tcpserver -HRDl0 0.0.0.0 <nova-porta> /usr/sbin/tinysshd -v /etc/tinyssh/sshkeydir &

Para Dropbear, copie /usr/lib/initcpio/hooks/dropbear para /etc/initcpio/hooks/dropbear e encontre/modifique a seguinte linha na função run_hook():

/etc/initcpio/hooks/tinyssh
 /usr/sbin/dropbear -E -s -j -k -p <nova-porta>

Gere novamente o initramfs.

Desbloquear à partir de uma máquina Windows usando PuTTY/Plink

Primeiro, precisamos usar puttygen.exe para importar e converter a chave de OpenSSH gerada mais cedo para o formato de chave privada do PuTTY .ppk. No exemplo abaixo chamado de zfs_abrir.ppk

O processo acima do mkinitcpio-netconf não configura um shell (mas não é necessário). No entanto, como não existe um shell, o PuTTY fechará imediatamente após uma conexão bem sucedida. Isto pode ser desabilitado na configuração de SSH do PuTTY (Connection -> SSH -> [X] Do not start a shell or command at all), mas ainda não permite enxergar a saída padrão (stdout) ou entrar a frase de criptografia. Em vez disso, usaremos o plink.exe com os seguintes parâmetros:

plink.exe -ssh -l root -i C:\caminho\pro\zfs_abrir.ppk <hostname>

O comando do plink pode ser inserido em um script em lotes para simplificar o uso.

Veja também