como espelhar unilateralmente um pool zfs inteiro para outro pool zfs

como espelhar unilateralmente um pool zfs inteiro para outro pool zfs

Eu tenho um pool zfs contendo vários zvols e conjuntos de dados, alguns dos quais também estão aninhados. Todos os conjuntos de dados e zvols são capturados periodicamente pelo zfs-auto-snapshot. Todos os conjuntos de dados e zvols também possuem alguns instantâneos criados manualmente.

Eu configurei um pool remoto no qual, devido à falta de tempo, a cópia inicial na rede local de alta velocidade via zfs send -R não foi concluída (alguns conjuntos de dados estão faltando, alguns conjuntos de dados têm instantâneos desatualizados ou ausentes).

Agora o pool está fisicamente remoto por meio de uma conexão de velocidade lenta e preciso sincronizar periodicamente o pool remoto com o pool local, o que significa que os dados presentes no pool local devem ser copiados para o pool remoto, os dados perdidos do pool local devem ser excluídos do pool remoto e os dados presentes no pool remoto, mas não no pool local, devem ser excluídos do pool remoto, por dados que significam 'zvols', 'datasets' ou 'snapshots'.

Se eu estivesse fazendo isso entre dois sistemas de arquivos regulares usando rsync, seria "-axPHAX --delete" (é o que eu realmente faço para fazer backup de alguns sistemas).

Como configuro uma tarefa de sincronização para que os zvols e conjuntos de dados do pool remoto (incluindo seus instantâneos) possam estar sincronizados com zvols, conjuntos de dados e instantâneos locais?

Eu gostaria de evitar a transferência por ssh, devido ao baixo desempenho de rendimento do ssh; Eu preferiria mbuffer ou iscsi.

Responder1

Isenção de responsabilidade: como nunca usei zvols, não posso dizer se eles são diferentes na replicação dos sistemas de arquivos ou instantâneos normais. Presumo que sim, mas não acredite apenas na minha palavra.


Sua pergunta é na verdade várias perguntas, tento respondê-las separadamente:

Como replicar/espelhar o pool completo para um local remoto

Você precisa dividir a tarefa em duas partes: primeiro, a replicação inicial deve ser concluída, depois a replicação incremental é possível,contanto que você não mexa nos snapshots de replicação. Para habilitar a replicação incremental, você precisa preservar os últimos instantâneos de replicação, tudo antes disso pode ser excluído. Se você excluir o instantâneo anterior, zfs recvreclamará e abortará a replicação. Neste caso você terá que começar tudo de novo, então tente não fazer isso.

Se você só precisa das opções corretas, são elas:

  • zfs send:
    • -R: envia tudo em um determinado pool ou conjunto de dados (replicação recursiva, necessária o tempo todo, inclui -p). Além disso, ao receber, todos os instantâneos de origem excluídos são excluídos no destino.
    • -I: inclui todos os instantâneos intermediários entre o último instantâneo de replicação e o instantâneo de replicação atual (necessário apenas com envios incrementais)
  • zfs recv:
    • -F: expanda o pool de destino, incluindo a exclusão de conjuntos de dados existentes que são excluídos na origem
    • -d: descarte o nome do pool de origem e substitua-o pelo nome do pool de destino (o restante dos caminhos do sistema de arquivos será preservado e, se necessário, também criado)
    • -u: não monte o sistema de arquivos no destino

Se você preferir um exemplo completo, aqui está um pequeno script:

#!/bin/sh

# Setup/variables:

# Each snapshot name must be unique, timestamp is a good choice.
# You can also use Solaris date, but I don't know the correct syntax.
snapshot_string=DO_NOT_DELETE_remote_replication_
timestamp=$(/usr/gnu/bin/date '+%Y%m%d%H%M%S')
source_pool=tank
destination_pool=tank
new_snap="$source_pool"@"$snapshot_string""$timestamp"
destination_host=remotehostname

# Initial send:

# Create first recursive snapshot of the whole pool.
zfs snapshot -r "$new_snap"
# Initial replication via SSH.
zfs send -R "$new_snap" | ssh "$destination_host" zfs recv -Fdu "$destination_pool"

# Incremental sends:

# Get old snapshot name.
old_snap=$(zfs list -H -o name -t snapshot -r "$source_pool" | grep "$source_pool"@"$snapshot_string" | tail --lines=1)
# Create new recursive snapshot of the whole pool.
zfs snapshot -r "$new_snap"
# Incremental replication via SSH.
zfs send -R -I "$old_snap" "$new_snap" | ssh "$destination_host" zfs recv -Fdu "$destination_pool"
# Delete older snaps on the local source (grep -v inverts the selection)
delete_from=$(zfs list -H -o name -t snapshot -r "$source_pool" | grep "$snapshot_string" | grep -v "$timestamp")
for snap in $delete_from; do
    zfs destroy "$snap"
done

Use algo mais rápido que SSH

Se você tiver uma conexão suficientemente segura, por exemplo, túnel IPSec ou OpenVPN e uma VLAN separada que só existe entre remetente e destinatário, você pode mudar de SSH para alternativas não criptografadas como mbuffercomo descrito aqui, ou você pode usar SSH com criptografia fraca/sem criptografia e compactação desabilitada,que é detalhado aqui. Também havia um site sobre como recompilar o SSH para ser muito mais rápido, mas infelizmente não me lembro do URL - irei editá-lo mais tarde, se o encontrar.

Para conjuntos de dados muito grandes e conexões lentas, também pode ser útil fazer a primeira transmissão via disco rígido (usar disco criptografado para armazenar zpool e transmiti-lo em pacote lacrado por correio, correio ou pessoalmente). Como o método de transmissão não importa para envio/recebimento, você pode canalizar tudo para o disco, exportar o pool, enviar o disco para seu destino, importar o pool e então transmitir todos os envios incrementais via SSH.

O problema com instantâneos confusos

Conforme declarado anteriormente, se você excluir/modificar seus instantâneos de replicação, receberá a mensagem de erro

cannot send 'pool/fs@name': not an earlier snapshot from the same fs

o que significa que seu comando estava errado ou você está em um estado inconsistente onde deve remover os instantâneos e começar tudo de novo.

Isto tem várias implicações negativas:

  1. Você não pode excluir um instantâneo de replicação até que o novo instantâneo de replicação tenha sido transferido com êxito. Como esses instantâneos de replicação incluem o estado de todos os outros instantâneos (mais antigos), o espaço vazio dos arquivos e instantâneos excluídos só será recuperado se a replicação for concluída. Isso pode levar a problemas de espaço temporários ou permanentes no seu pool, que você só pode corrigir reiniciando ou concluindo o procedimento de replicação completo.
  2. Você terá muitos snapshots adicionais, o que torna o comando list mais lento (exceto no Oracle Solaris 11, onde isso foi corrigido).
  3. Talvez seja necessário proteger os instantâneos contra remoção (acidental), exceto pelo próprio script.

Existe uma solução possível para esses problemas, mas eu mesmo não tentei. Você poderia usar o zfs bookmark, um novo recurso do OpenSolaris/illumos criado especificamente para esta tarefa. Isso libertaria você do gerenciamento de instantâneos. A única desvantagem é que, atualmente, ele funciona apenas para conjuntos de dados únicos, não de forma recursiva. Você teria que salvar uma lista de todos os seus conjuntos de dados antigos e novos e, em seguida, fazer um loop sobre eles, marcá-los, enviá-los e recebê-los e, em seguida, atualizar a lista (ou um pequeno banco de dados, se preferir).

Se você tentar a rota dos favoritos, ficaria interessado em saber como funcionou para você!

Responder2

Pessoalmente, eu faria uma lista de zvols, conjuntos de dados etc. no servidor remoto quenãotenha snapshots atualizados e atualize-os com o zfs send, mesmo que isso seja demorado e use muita largura de banda.

Então eu poderia continuar usando zfs senda partir de então e não ter que reinventar a roda escrevendo meu próprio código de sincronização. rsyncé bom para sistemas de arquivos mais antigos, mas zfs sendé muito melhor para zfs - ele sabeexatamentequais blocos foram alterados no instantâneo e enviaapenaseles, enquanto o rsync precisa comparar arquivos individuais e/ou carimbos de data/hora entre servidores locais e remotos. o mesmo se aplica btrfs senda pools btrfs.

Se você tiver apenas um pequeno número de instantâneos que precisam ser atualizados, isso poderá ser feito manualmente. Caso contrário, para fazer isso automaticamente, você precisa de uma lista dos instantâneos locais mais recentes versus instantâneos remotos e de um script para comparar versões e, em seguida, zfs sendinstantâneos locais que estão desatualizados no servidor rmeote.

Isso será suficiente se você se preocupar apenas com o instantâneo mais recente de cada conjunto de dados. Se você se preocupa com todos os snapshots anteriores, obviamente seu script também terá que lidar com eles... e isso se torna MUITO mais complicado. Em alguns casos, pode ser necessário reverter no servidor remoto para poder reenviar os instantâneos intermediários/ausentes.

Se você deseja uma conexão segura com o servidor remoto, você realmente não tem escolha a não ser usar ssh- ou talvez configurar um túnel com openvpnou algo assim e usar netcat.

Responder3

Dê uma olhada no `zrepl', no FreeBSD, que pode tornar a sua vida, e a de qualquer pessoa, muito mais fácil. Foi apresentado há poucos dias durante o BSDCan2018 em Ottawa. Parece promissor e pode ser uma solução para seus problemas

Responder4

zrep é uma ótima solução completa E possui documentação + ganchos sobre como obter transferências mais rápidas do que simplesmente transferências SSH

https://github.com/bolthole/zrep

também é multiplataforma: compatível com Linux, freebsd e solaris/illumos

informação relacionada