2 points par GN⁺ 2024-03-13 | 1 commentaires | Partager sur WhatsApp
  • Plutôt que de reconfigurer un nouvel ordinateur portable depuis zéro, l’auteur a exposé l’intégralité du disque de l’ancien portable via NVMe over TCP afin de le cloner tel quel par le réseau
  • L’environnement existant utilisait un chiffrement complet du disque et un disque de 512 Go ; le nouveau portable ayant un NVMe de 1 To, il a fallu, après le clonage, étendre les partitions, LUKS et BTRFS
  • Pour exporter le disque, au lieu de systemd-storagetm.service, les deux portables ont été démarrés sur un GRML rescue CD, puis configurés avec nvmet-tcp et /sys/kernel/config/nvmet
  • La copie proprement dite a été effectuée avec dd ; comme le nouveau portable n’avait pas de port Ethernet et utilisait uniquement le WiFi, le clonage des 512 Go a pris environ 7 h 30, à une vitesse d’environ 18 à 20 Mo/s
  • Après le clonage, l’auteur a ajusté le système pour utiliser tout le To disponible via parted, growpart, cryptsetup resize et un redimensionnement BTRFS, et a pu retrouver presque à l’identique l’environnement de l’ancien portable

Exporter l’ancien disque via NVMe over TCP

  • Pour éviter de répéter toute la procédure de configuration du nouveau portable, l’auteur a choisi, sur suggestion d’un collègue, de copier l’intégralité du disque de l’ancien portable

  • Deux obstacles se présentaient au départ

    • Il n’avait pas l’outil permettant d’ouvrir l’ancien portable et de connecter le nouveau disque en USB
    • L’ancien portable utilisait un chiffrement complet du disque avec un disque de 512 Go, tandis que le nouveau portable avait un NVMe de 1 To, ce qui imposait de redimensionner LUKS
  • Le flux de travail s’est déroulé en trois étapes : exposition du disque, copie, puis extension de la capacité

    • Exporter le disque depuis l’ancien portable avec nvmet-tcp
    • Copier ce disque depuis le nouveau portable
    • Étendre la partition à l’ensemble du To disponible
    • Redimensionner LUKS
    • Enfin, redimensionner le disque racine BTRFS
  • Utiliser GRML au lieu de systemd-storagetm.service

    • La méthode la plus simple aurait été d’utiliser systemd-storagetm.service
    • On peut l’invoquer en démarrant sur storage-target-mode.target avec rd.systemd.unit=storage-target-mode.target
    • Cependant, cette approche nécessite d’inclure les services réseau dans l’image initrd de dracut, et la configuration du WiFi dans ce mode étant fastidieuse, elle a été écartée
    • À la place, les deux portables ont été démarrés sur un GRML rescue CD, puis l’ancien portable a exporté son disque NVMe au moyen du module Linux nvmet-tcp
    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
    
    • Avec cette configuration, le périphérique cible est exposé en NVMe over TCP
    • Sur le nouveau portable, il faut découvrir puis connecter le périphérique exporté
    nvme discover -t tcp -a <ip> -s 4420
    nvme connectl-all -t tcp -a <> -s 4420
    
    • Ensuite, nvme list permet de vérifier le périphérique connecté au nouveau portable et de lancer la copie du disque

Copie du disque et redimensionnement

  • Copier 512 Go avec dd

    • La copie du disque racine a été effectuée avec la commande dd
    • Le nouveau portable n’ayant pas de port Ethernet, seul le WiFi a été utilisé, et la copie complète des 512 Go a pris environ 7 h 30
    • Le débit était d’environ 18 à 20 Mo/s
    • D’autres options auraient consisté à créer les partitions et le système de fichiers initiaux puis à copier le disque racine avec rsync, ou à utiliser le mécanisme de transfert propre à BTRFS
    dd if=/dev/nvme2n1 of=/dev/nvme0n1 status=progress bs=40M
    
  • Étendre les partitions, LUKS et BTRFS

    • parted a détecté que la table de partitions ne correspondait pas à la taille du disque et, après confirmation, l’a corrigée automatiquement
    • Pour étendre la deuxième partition, cloud-guest-utils a été installé et growpart utilisé
    growpart /dev/nvem0n1 p2
    
    • À l’étape suivante, cryptsetup a servi à augmenter la taille du conteneur LUKS
    cryptsetup luksOpen /dev/nvme0n1p2 ENC
    cryptsetup resize ENC
    
    • Après redémarrage sur le disque, le bon fonctionnement a été vérifié, puis la taille du système de fichiers BTRFS a été ajustée après connexion
    • BTRFS doit être monté pour être redimensionné, il n’était donc pas possible de le faire depuis l’environnement live
    btfs fielsystem resize max /
    
    • Au final, le nouveau portable offre un environnement donnant l’impression de continuer à utiliser l’ancien
    • En général, il faut environ une à deux semaines pour s’adapter complètement à un nouveau portable, mais cette méthode a permis de réduire ce délai
    • En bonus, l’auteur a aussi appris comment exporter un disque via NVMe over TCP

1 commentaires

 
GN⁺ 2024-03-13
Avis de Hacker News
  • Dans le scénario de l’auteur, on finit simplement par faire une copie séquentielle de blocs avec dd(1), donc l’intérêt d’utiliser NVMe/TCP est très limité. Les commandes complexes peuvent être remplacées par un simple netcat
    Ordinateur portable cible : $ nc -l -p 1234 | dd of=/dev/nvme0nX bs=1M
    Ordinateur portable source : $ nc x.x.x.x 1234
    Le dd côté cible sert à bufferiser les écritures pour les rendre plus rapides et efficaces. Ajouter gzip/gunzip côté source/cible accélère énormément les choses quand le disque n’est pas plein et contient beaucoup de blocs de zéros. C’est personnellement ma méthode préférée pour imager des PC par le réseau, et je l’ai utilisée de nombreuses fois
    Sur du GigE, la compression devient souvent le goulot d’étranglement ; il vaut donc mieux passer --fast à gzip, et mieux encore, utiliser lz4/unlz4 au lieu de gzip/gunzip, ce qui est plus rapide. Il y a quelque temps, j’ai imagé via GigE un nouveau portable Windows équipé d’un NVMe de 1 To ; cela a pris environ 20 minutes, et comme l’espace libre se compressait presque entièrement en zéros, l’image obtenue faisait 20 Go. En général, je garde cette image lz4 en sauvegarde, puis quelques années plus tard, quand je donne le portable, je restaure avec unlz4 | dd, ce qui est très pratique
    Cela dit, je ne connaissais pas le module du noyau Linux nvme-tcp ; on en apprend tous les jours. Cela semble plus utile pour monter un système de fichiers sur un NVMe distant que pour un accès brut via dd
    En outre, la taille maximale du buffer de pipe sous Linux est de 64 ko, donc l’argument dd bs=X n’a techniquement pas besoin d’être plus grand. Cela dit, bs=1M ne fait pas de mal : il regroupe les lectures de 64 ko jusqu’à atteindre 1 Mo, et reste prêt si la taille des pipes augmente à l’avenir. Certaines versions de netcat ont une option de taille de bloc d’E/S, ce qui rend dd bs=X inutile, mais le netcat présent sur les disques de récupération est généralement une version qui n’a pas ce genre d’option

    • Le buffer de pipe de Linux peut être augmenté, et il me semble que le maximum par défaut est généralement autour de 1 Mo. C’est un peu délicat à faire en ligne de commande, mais un exemple d’implémentation possible se trouve ici : https://unix.stackexchange.com/a/328364
    • C’est un peu moins propre, mais utiliser pv des deux côtés à la place de dd évite de se soucier de la bonne taille de bloc, et affiche aussi un joli graphe de progression
    • Il y a environ 9 ans, j’ai fait du conseil pour une entreprise qui avait subi un piratage interne : un cofondateur mécontent avait mis en place une sorte de dead man’s switch qui copiait les 20 premiers Mo de tous les disques vers un bucket, puis les écrasait avec des zéros. Pour récupérer les données, il a fallu reconstruire les tables de partitions avec testdisk, mais avant cela je ne voulais pas toucher aux disques endommagés ; j’ai donc copié environ 40 To avec une clé de récupération, netcat et des disques
      Sur certains serveurs, tous les emplacements RAID physiques étaient occupés, donc impossible d’utiliser un emplacement disque supplémentaire ; en gros, j’ai utilisé dd if=/dev/sdc bs=xxx | gzip | nc -l -p 8888 et la commande inverse de l’autre côté. Étonnamment, cela a bien fonctionné. Un point d’attention : essayer d’aligner la combinaison dd bs sur la taille de secteur, car la bonne valeur avait un gros impact sur le débit de dd
    • Cette utilisation de dd peut provoquer une corruption. Pour éviter les blocs tronqués, il faut iflag=fullblock, et même si cela peut relever d’une habitude appliquée aveuglément, conv=sync ne fait pas de mal. Personnellement, je préfère simplement nc -l -p 1234 > /dev/nvme0nX
    • Pour la plupart des gens, le réseau local ne sera probablement pas plus rapide que la vitesse de transfert du SSD. Cela dit, pour ceux qui disposent d’un tel environnement, je me demande s’il existe un outil de clonage de périphériques bloc à E/S concurrentes
      Ajouter pv dans le pipeline permet de voir l’heure estimée de fin, mais peut avoir un léger impact sur les performances
  • Merci à AWS/Annapurna/Nitro/Lightbits d’avoir apporté NVMe-over-TCP à Linux
    https://www.techtarget.com/searchstorage/news/252459311/Ligh...
    « Le consortium NVM Express a ratifié NVMe/TCP comme couche de transport de liaison en novembre 2018. Cette norme a évolué à partir d’une base de code initialement soumise à NVM Express par l’équipe d’ingénierie de Lightbits. »
    https://www.lightbitslabs.com/blog/linux-distributions-nvme-...
    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...

  • Cela a l’air bien plus fastidieux que : nbdkit file /dev/nvme0n1, nbdcopy nbd://otherlaptop localfile

    • Cette approche est en réalité bien meilleure : nbdcopy peut gérer les fichiers creux, ajuster le nombre de connexions et de threads au nombre de cœurs, forcer un flush avant de terminer, et afficher une barre de progression. Pour les disques non chiffrés, TLS est aussi pris en charge
  • J’ai récemment dû installer xubuntu sur un nouveau portable. Avant, je clonais, mais cette fois je voulais remettre un peu d’ordre dans certains réglages
    Le transfert à 10 Gb/s via un câble USB-C s’est révélé vraiment utile, car l’autre option n’était que le WiFi
    Quand on branche les ordinateurs l’un à l’autre, un réseau temporaire se forme, et il suffit de transférer avec rsync. À vue de nez, le lien était saturé, donc utiliser un autre protocole ne semblait pas avoir beaucoup d’intérêt. Apprendre quelque chose de nouveau, c’est bien sûr toujours appréciable, mais peut-être pas au moment où l’on clone un portable

    • Je me demande si ça a simplement marché du premier coup. La dernière fois que j’ai essayé une connexion directe autre qu’Ethernet, c’était dans les années 90, donc je pose vraiment la question
    • J’ai essayé aussi, mais pour que le réseau fonctionne, il m’a fallu acheter un câble Thunderbolt 4 à plus de 30 dollars. Un simple câble USB3-C standard ne suffisait pas
      Le transfert lui-même était extrêmement rapide : 1 To transféré en quelques minutes. Cette fois, je n’ai pas utilisé de chiffrement, ce qui a rendu les choses beaucoup plus simples
    • Je me demande s’il a démarré sur un disque live puis transféré tout le système de fichiers, ou s’il a d’abord installé un système de base avant de ne transférer que les fichiers
  • Je ne comprends pas pourquoi il n’a pas simplement envoyé btrfs par le réseau. Il suffit de créer d’abord un snapshot btrfs, puis de faire btrfs send => nc => network => nc => btrfs receive, et seuls les blocs utilisés sont transférés

    • Dès que j’ai vu qu’il utilisait btrfs, c’est aussi la première chose qui m’est venue à l’esprit. J’utilise constamment btrfs send/receive via SSH, et ça fonctionne très bien. Il aurait aussi été facile de lancer un serveur SSH depuis une session live GRML
      Il y a toutefois un point d’attention. Avec btrfs, on ne peut pas envoyer des snapshots de façon récursive ; donc s’il y a beaucoup de snapshots récursifs, il est relativement difficile de reproduire la même structure sur le nouveau disque. Cela peut arriver avec Docker/LXD/Incus. J’aime btrfs, mais pour le send/receive récursif, ZFS fait mieux
  • J’ai récemment dû copier environ 200 Go de fichiers en WiFi. J’ai utilisé rsync pour éviter de devoir recommencer depuis le début en cas d’échec de connexion, et pour éviter toute perte, mais cela a pris au moins 6 heures. Je me demande s’il existait une meilleure méthode
    Et je me demande aussi quelles garanties offre la méthode avec dd. Faut-il comparer le md5 du périphérique bloc obtenu ?

    • 6 heures pour transférer 200 Go en WiFi, ce n’est pas un débit impressionnant pour un transfert local. Il aurait probablement fallu utiliser un câble Ethernet
      Le WiFi a beaucoup plus de causes possibles de goulot d’étranglement. Rien que brancher un des appareils au routeur par câble et laisser l’autre en sans-fil peut déjà beaucoup aider
    • S’il y avait énormément de petits fichiers, le fait que rsync ne transfère qu’un fichier à la fois a très probablement été le goulot d’étranglement. On peut découper la liste des fichiers avec xargs/parallel et lancer plusieurs instances de rsync, ou utiliser quelque chose comme rclone, qui prend en charge nativement le transfert parallèle
    • 6 heures, ça fait environ 10 Mo/s, donc il y avait sans doute moyen d’aller beaucoup plus vite. Je me demande s’il a utilisé la compression avec -z. S’il avait pu utiliser Ethernet, la plupart des appareils auraient approché les 100 Mo/s, soit environ 35 minutes
    • Si le transport de rsync était SSH, c’est souvent lui le goulot d’étranglement. Historiquement, OpenSSH a eu d’étranges limitations de performance, et il a parfois fallu des patchs peu connus pour les contourner. Si le CPU n’est pas le facteur limitant, activer la compression peut aussi aider
    • Le WiFi partage le médium qu’est l’air avec tous les autres appareils sans fil. Lorsqu’il détecte une collision, il s’arrête puis attend pendant une durée aléatoire
      « En réseau informatique, l’accès multiple avec écoute de porteuse et évitement de collision (CSMA/CA) est une méthode d’accès multiple au réseau qui utilise l’écoute de porteuse, mais tente d’éviter les collisions en ne commençant la transmission qu’après que le canal a été détecté comme “libre”. Lors de la transmission, un nœud envoie l’intégralité des données du paquet
      C’est particulièrement important dans les réseaux sans fil, où le CSMA/CD, une méthode de détection de collision, ne peut pas être utilisé parce qu’un émetteur sans fil rend son récepteur insensible pendant l’émission d’un paquet, le désactivant de fait
      Le CSMA/CA est peu fiable à cause du problème du nœud caché
      Le CSMA/CA est un protocole qui fonctionne au niveau de la couche liaison de données. »
      https://en.wikipedia.org/wiki/Carrier-sense_multiple_access_...
  • Cette approche a sans doute ses avantages, mais quand j’ai migré un portable par le passé, j’ai lancé l’installateur des deux côtés puis combiné dd et nc. De mémoire, j’avais aussi ajouté gzip pour transférer plus vite les grandes zones nulles
    Si le nouveau portable n’avait pas de port Ethernet, ma méthode bricolée aurait peut-être été un peu plus rapide grâce à la compression. Avec un lien réseau rapide, elle n’aurait sans doute pas atteint la limite ajoutée par la compression

    • Avec un chiffrement complet du disque, à moins d’avoir demandé à LUKS de laisser passer TRIM, la méthode décrite par l’auteur ne produit en pratique que des données aléatoires
  • Pourquoi ne pas simplement utiliser Clonezilla ? Il ne copie que les blocs de données réels et peut aussi redimensionner automatiquement les partitions. C’est toujours ce que je fais
    Bien sûr, en général, je retire le disque NVMe du portable et je le branche sur une station d’accueil rapide

    • Clonezilla est excellent. Il fait une seule chose et réussit généralement du premier coup. Mon seul reproche, c’est qu’à cause de la courbe d’apprentissage initiale, il faut bricoler un peu
      Je ne suis pas encore au point de lui faire totalement confiance en le laissant tourner sans surveillance. Une sauvegarde n’est pas équivalente à sauvegarde plus restauration, donc il est recommandé d’expérimenter. Clonezilla peut aussi rencontrer des problèmes lorsqu’il recrée des partitions sur un disque très différent de l’original
  • Cela fait des décennies que je n’ai pas réellement « installé » un système d’exploitation sur un desktop ou un portable : j’ai toujours copié les fichiers puis ajusté uniquement ce qui était nécessaire. En général, je profite de l’occasion pour créer un nouveau système de fichiers et transférer les fichiers avec rsync, afin de mettre à jour des paramètres comme le type de système de fichiers, la taille des blocs, le chiffrement, etc.
    Cela dit, si l’on est du genre à planifier à l’avance, une approche plus déclarative comme NixOS, où l’on ne copie que la configuration et où le reste est réinstallé automatiquement, me semble préférable

  • En connectant directement les appareils en WiFi, sans point d’accès intermédiaire, on pourrait probablement doubler la vitesse de transfert. Dans cette situation, cela aurait valu la peine d’essayer