2 pontos por GN⁺ 2024-03-13 | 1 comentários | Compartilhar no WhatsApp
  • Em vez de configurar um novo notebook do zero, foi exposto o disco inteiro do notebook antigo via NVMe over TCP e ele foi clonado pela rede tal como estava
  • O ambiente antigo usava criptografia de disco completo e um disco de 512 GB; como o novo notebook tinha um NVMe de 1 TB, foi necessário expandir partições, LUKS e BTRFS após a clonagem
  • Para exportar o disco, em vez de usar systemd-storagetm.service, os dois notebooks foram inicializados com o GRML rescue CD e configurados com nvmet-tcp e /sys/kernel/config/nvmet
  • A cópia em si foi feita com dd; como o novo notebook não tinha porta Ethernet e foi usado apenas Wi-Fi, a clonagem de 512 GB levou cerca de 7 horas e 30 minutos, com velocidade em torno de 18–20 MB/s
  • Após a clonagem, foram usados parted, growpart, cryptsetup resize e redimensionamento do BTRFS para ajustar o sistema e usar todo o 1 TB, permitindo continuar com praticamente o mesmo ambiente do notebook antigo

Exportando o disco antigo com NVMe over TCP

  • Para evitar repetir o processo de configuração do novo notebook, foi escolhida, por sugestão de um colega, a abordagem de copiar o disco inteiro do notebook antigo

  • Antes de começar, havia dois obstáculos

    • Não havia uma ferramenta para abrir o notebook antigo e conectar o novo disco via USB
    • O notebook antigo usava criptografia de disco completo e um disco de 512 GB; como o novo notebook tinha um NVMe de 1 TB, seria necessário redimensionar o LUKS
  • O fluxo de trabalho seguiu três etapas: expor o disco, copiar e expandir a capacidade

    • Exportar o disco do notebook antigo com nvmet-tcp
    • Copiar esse disco no novo notebook
    • Expandir a partição para usar todo o 1 TB
    • Redimensionar o LUKS
    • Por fim, redimensionar o disco raiz em BTRFS
  • Usando GRML em vez de systemd-storagetm.service

    • A forma mais simples seria usar systemd-storagetm.service
    • Isso pode ser chamado especificando rd.systemd.unit=storage-target-mode.target e inicializando em storage-target-mode.target
    • No entanto, essa abordagem exige incluir serviços de rede na imagem initrd do dracut e, nesse modo, configurar Wi-Fi é trabalhoso, então ela foi descartada
    • Em vez disso, os dois notebooks foram inicializados com o GRML rescue CD e, no notebook antigo, o disco NVMe foi exportado usando o módulo nvmet-tcp do Linux
    modprobe nvmet-tcp
    cd /sys/kernel/config/nvmet
    mkdir ports/0
    cd ports/0
    echo "ipv4" > addr_adrfam
    echo 0.0.0.0 > addr_traaddr
    echo 4420 > addr_trsvcid
    echo tcp > addr_trtype
    cd /sys/kernel/config/nvmet/subsystems
    mkdir testnqn
    echo 1 >testnqn/allow_any_host
    mkdir testnqn/namespaces/1
    cd testnqn
    
    
    # replace the device name with the disk you want to export
    echo "/dev/nvme0n1" > namespaces/1/device_path
    echo 1 > namespaces/1/enable
    ln -s "../../subsystems/testnqn" /sys/kernel/config/nvmet/ports/0/subsystems/testnqn
    
    • Com essa configuração, o dispositivo de destino é exposto como NVMe over TCP
    • No novo notebook, o dispositivo exportado é descoberto e conectado
    nvme discover -t tcp -a <ip> -s 4420
    nvme connectl-all -t tcp -a <> -s 4420
    
    • Depois disso, é possível verificar o dispositivo conectado ao novo notebook em nvme list e prosseguir com a cópia do disco

Cópia do disco e redimensionamento

  • Copiando 512 GB com dd

    • A cópia do disco raiz foi feita com o comando dd
    • Como o novo notebook não tinha porta Ethernet e foi usado apenas Wi-Fi, a cópia completa de 512 GB levou cerca de 7 horas e 30 minutos
    • A velocidade de transferência ficou em torno de 18–20 MB/s
    • Outras opções seriam criar as partições e o sistema de arquivos iniciais e depois copiar o disco raiz com rsync, ou usar a transferência nativa do sistema de arquivos BTRFS
    dd if=/dev/nvme2n1 of=/dev/nvme0n1 status=progress bs=40M
    
  • Expandindo partições, LUKS e BTRFS

    • O parted detectou que a tabela de partições não correspondia ao tamanho do disco e, após pedir confirmação para corrigir, fez o ajuste automaticamente
    • Para expandir a segunda partição, foi instalado cloud-guest-utils e usado growpart
    growpart /dev/nvem0n1 p2
    
    • Na etapa seguinte, o tamanho do contêiner LUKS foi aumentado com cryptsetup
    cryptsetup luksOpen /dev/nvme0n1p2 ENC
    cryptsetup resize ENC
    
    • Depois de reinicializar pelo disco, o funcionamento normal foi confirmado e, após o login, o sistema de arquivos BTRFS foi redimensionado
    • Como o BTRFS exige que o sistema esteja montado para redimensionamento, não foi possível tentar isso a partir de uma inicialização live
    btfs fielsystem resize max /
    
    • Como resultado, no novo notebook foi obtido um ambiente que parecia continuar usando o notebook antigo
    • Em geral, adaptar-se completamente a um novo notebook leva cerca de 1 a 2 semanas, mas esse método reduziu esse tempo
    • Além disso, ficou o aprendizado de como exportar um disco via NVMe over TCP

1 comentários

 
GN⁺ 2024-03-13
Comentários do Hacker News
  • No cenário do autor, no fim das contas ele só faz uma cópia serial de blocos com dd(1), então há pouca vantagem em usar NVMe/TCP. O comando complexo pode ser substituído por um simples netcat
    Notebook de destino: $ nc -l -p 1234 | dd of=/dev/nvme0nX bs=1M
    Notebook de origem: $ nc x.x.x.x 1234
    O dd no lado de destino serve para fazer buffer das escritas e torná-las mais rápidas e eficientes. Se adicionar gzip/gunzip na origem/destino, fica muito mais rápido quando o disco não está cheio e há muitos blocos zerados. Pessoalmente, é meu método preferido para criar imagens de PCs pela rede, e já fiz isso várias vezes
    Em GigE, a compressão muitas vezes vira o gargalo, então é bom passar --fast para o gzip; melhor ainda, usar lz4/unlz4 em vez de gzip/gunzip é mais rápido. Quando fiz a imagem de um notebook Windows novo com NVMe de 1 TB via GigE tempos atrás, levou uns 20 minutos; como o espaço vazio foi comprimido para quase zero, a imagem resultante ficou com 20 GB. Normalmente guardo essa imagem lz4 como backup e, alguns anos depois, quando vou doar o notebook, restauro com unlz4 | dd, o que é muito prático
    Porém eu não conhecia o módulo do kernel Linux nvme-tcp; todo dia se aprende algo novo. Isso parece mais útil para montar um sistema de arquivos em um NVMe remoto do que para acesso bruto com dd
    Além disso, o tamanho máximo do buffer de pipe no Linux é 64 kB, então tecnicamente o argumento dd bs=X não precisa ser maior que isso. Ainda assim, bs=1M não prejudica e agrega leituras de 64 kB até formar 1 MB, além de ficar preparado caso o tamanho do pipe aumente no futuro. Algumas versões do netcat têm opções de tamanho de bloco de entrada/saída, dispensando dd bs=X, mas o netcat em discos de recuperação geralmente é uma versão sem essas opções

    • O buffer de pipe do Linux pode ser aumentado, e pelo que sei o máximo padrão costuma ser em torno de 1 MB. Fazer isso pela linha de comando é um pouco trabalhoso, mas há um exemplo de implementação possível em https://unix.stackexchange.com/a/328364
    • Embora seja um pouco bagunçado, usar pv em vez de dd nos dois lados elimina a preocupação de especificar um tamanho de bloco adequado, e ainda mostra um gráfico de progresso agradável
    • Há uns 9 anos, prestei consultoria para uma empresa que tinha sofrido um ataque interno: um cofundador insatisfeito configurou algo como um dead man’s switch para copiar os primeiros 20 MB de todos os discos para algum bucket e depois sobrescrevê-los com zeros. Para recuperar os dados, tive de reconstruir as tabelas de partição com testdisk, mas antes não queria mexer nos discos danificados, então copiei cerca de 40 TB usando um pendrive de recuperação, netcat e drives
      Alguns servidores estavam com todos os slots físicos de RAID ocupados, então nem dava para usar slots de disco sobressalentes; usei algo como dd if=/dev/sdc bs=xxx | gzip | nc -l -p 8888 e o comando inverso do outro lado. Funcionou surpreendentemente bem. Um ponto de atenção é ajustar a combinação dd bs ao tamanho do setor, porque o tamanho adequado teve grande impacto na vazão do dd
    • Este uso de dd pode causar corrupção. Para evitar blocos truncados, é necessário iflag=fullblock; e, embora possa ser uma prática cega, conv=sync também não faz mal. Pessoalmente, prefiro simplesmente nc -l -p 1234 > /dev/nvme0nX
    • A maioria das redes locais provavelmente não é mais rápida que a taxa de transferência de um SSD. Ainda assim, para quem tem esse tipo de ambiente, fico curioso se existe uma ferramenta de clonagem de dispositivos de bloco com E/S concorrente
      Inserir pv no pipeline permite ver o tempo estimado de conclusão, mas pode afetar um pouco o desempenho
  • Agradeço à AWS/Annapurna/Nitro/Lightbits por trazerem NVMe-over-TCP para o Linux
    https://www.techtarget.com/searchstorage/news/252459311/Ligh...
    “O consórcio NVM Express ratificou o NVMe/TCP como camada de transporte de binding em novembro de 2018. O padrão evoluiu a partir de uma base de código originalmente enviada ao NVM Express pela equipe de engenharia da Lightbits.”
    https://www.lightbitslabs.com/blog/linux-distributions-nvme-...
    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...

  • Parece muito mais trabalhoso do que: nbdkit file /dev/nvme0n1, nbdcopy nbd://otherlaptop localfile

    • Esse método é de fato muito melhor, porque nbdcopy consegue lidar com arquivos esparsos, permite ajustar o número de conexões e threads ao número de núcleos, também consegue forçar flush antes de encerrar e permite ativar uma barra de progresso. Se a unidade não for criptografada, também oferece suporte a TLS
  • Recentemente precisei instalar xubuntu em um notebook novo. No passado eu clonava, mas desta vez queria reorganizar algumas configurações do zero
    Foi realmente útil fazer a transferência a 10 Gb/s por um cabo USB-C, já que a única outra opção era WiFi
    Ao conectar os computadores um ao outro, forma-se uma rede temporária e basta transferir com rsync. Pelo que parecia, o link estava saturado, então não parecia haver muito sentido em usar outro protocolo. Claro, aprender algo novo é bom, mas talvez não exatamente no momento de clonar um notebook

    • Fiquei curioso se simplesmente funcionou de cara. A última vez que tentei uma conexão direta que não fosse Ethernet foi nos anos 90, então estou perguntando sério
    • Eu também tentei, mas para fazer a rede funcionar precisei comprar um cabo Thunderbolt 4 de mais de 30 dólares. Um cabo USB3-C comum não foi suficiente
      A transferência em si foi incrivelmente rápida, movi 1 TB em poucos minutos. Desta vez não usei criptografia, então ficou muito mais simples
    • Fiquei curioso se você inicializou por um disco live e moveu o sistema de arquivos inteiro, ou se instalou um sistema básico e depois moveu apenas os arquivos
  • Não entendo por que não fizeram pipe do btrfs pela rede. Primeiro você cria um snapshot btrfs e faz btrfs send => nc => network => nc => btrfs receive; assim, só os blocos em uso são transferidos

    • Assim que vi que era btrfs, essa também foi a primeira coisa que me veio à cabeça. Uso btrfs send/receive por SSH o tempo todo e funciona muito bem. Também teria sido fácil subir um servidor SSH em uma sessão live do GRML
      Mas há um ponto de atenção. No btrfs não dá para enviar snapshots recursivamente, então, se houver muitos snapshots recursivos, espelhar a mesma estrutura no novo disco é relativamente difícil. Isso pode acontecer com Docker/LXD/Incus. Gosto do btrfs, mas send/receive recursivo é uma área em que o ZFS é melhor
  • Recentemente precisei copiar cerca de 200 GB de arquivos por WiFi. Usei rsync para não precisar recomeçar do zero em caso de falha de conexão e para não perder nada, mas levou pelo menos 6 horas. Fiquei pensando se haveria uma forma melhor
    Também queria saber que garantias o método com dd oferece. É preciso comparar o md5 do dispositivo de bloco resultante?

    • 6 horas para transferir 200 GB por WiFi não é uma taxa de transferência impressionante para uma transferência local. Acho que deveria ter usado um cabo Ethernet
      WiFi tem muito mais causas possíveis de gargalo de desempenho. Só de conectar pelo menos um dos dispositivos ao roteador por cabo e deixar o outro no wireless já ajuda bastante
    • Se eram muitos arquivos bem pequenos, é muito provável que o gargalo tenha sido o fato de o rsync transferir só um arquivo por vez. Dá para dividir a lista de arquivos com xargs/parallel e rodar várias instâncias de rsync, ou usar algo como rclone, que oferece suporte nativo a transferências paralelas
    • 6 horas dá algo em torno de 10 MB/s, então provavelmente dava para ser muito mais rápido. Fiquei curioso se você usou compressão com -z. Se pudesse usar Ethernet, na maioria dos dispositivos chegaria perto de 100 MB/s e levaria cerca de 35 minutos
    • Se o método de transferência do rsync era SSH, muitas vezes esse é o gargalo. Historicamente, o OpenSSH tinha algumas limitações estranhas de desempenho, e já houve casos em que era necessário um patch pouco conhecido para contorná-las. Se a CPU não for o gargalo, ativar a compressão também ajuda
    • WiFi compartilha o meio físico, o ar, com todos os outros dispositivos sem fio. Quando detecta colisões, ele para e espera por um tempo aleatório
      “Em redes de computadores, o acesso múltiplo com detecção de portadora e prevenção de colisão (CSMA/CA) é um método de acesso múltiplo a redes que usa detecção de portadora, mas tenta evitar colisões iniciando a transmissão somente depois que o canal é detectado como ‘ocioso’. Ao transmitir, os nós enviam os dados do pacote por inteiro
      Isso é particularmente importante em redes sem fio, nas quais não é possível usar o CSMA/CD, que é um método de detecção de colisão, porque transmissores sem fio dessensibilizam e desligam seus receptores durante a transmissão de pacotes
      O CSMA/CA não é confiável por causa do problema do nó oculto
      O CSMA/CA é um protocolo que opera na camada de enlace de dados.”
      https://en.wikipedia.org/wiki/Carrier-sense_multiple_access_...
  • Essa abordagem deve ter suas vantagens, mas quando migrei um notebook no passado, iniciei o instalador nos dois lados e combinei dd com nc. Pelo que me lembro, também adicionei gzip para transferir grandes regiões nulas mais rapidamente
    Se o notebook novo não tivesse porta Ethernet, meu método gambiarra talvez tivesse sido um pouco mais rápido por causa da compressão. Em um link de rede rápido, provavelmente ele não chegaria perto do limite adicional imposto pela compressão

    • Se houver criptografia de disco completo, a menos que você tenha instruído o LUKS a passar TRIM adiante, com o método descrito pelo autor você basicamente obtém apenas dados aleatórios
  • Não bastaria usar o Clonezilla? Ele copia apenas os blocos de dados reais e também consegue redimensionar partições automaticamente. Eu sempre faço assim
    Claro que, normalmente, eu removo o disco NVMe do notebook e coloco em um dock de alta velocidade

    • Clonezilla é excelente. Ele faz uma coisa e geralmente acerta na primeira tentativa. Minha única reclamação é que a curva inicial de aprendizado exige mexer em várias coisas
      Ainda não é algo em que eu confie totalmente para deixar rodando sem supervisão. Backup não é a mesma coisa que backup mais restauração, então é recomendável testar. O Clonezilla também pode ter problemas ao recriar partições em um disco muito diferente do original
  • Faz décadas que não “instalo” de fato um sistema operacional em um desktop ou notebook; sempre copio os arquivos e ajusto só o que for necessário. Normalmente aproveito a oportunidade para criar um novo sistema de arquivos e mover os arquivos com rsync, atualizando parâmetros como tipo de sistema de arquivos, tamanho de bloco, criptografia etc.
    Ainda assim, se você é do tipo que planeja com antecedência, uma abordagem mais declarativa, como NixOS, em que você copia apenas a configuração e reinstala automaticamente o restante, parece melhor

  • Se conectar os dispositivos diretamente por WiFi, sem um AP intermediário, provavelmente daria para dobrar a velocidade de transferência. Nesta situação, parece que valeria a pena tentar