Migrer une installation Linux

(image générée par IA)

Dans la mesure où tu as installé les pilotes génériques lors du déploiement de ta distro, Linux se contrefout du matériel sur lequel il tourne et c’est probablement pour ça qu’il existe depuis plus longtemps des LiveCD pour utiliser les distros Linux que des WinPe.

Pour faire simple, migrer une install Linux d’une machine à une autre c’est :

  • Recopier (tout sauf /proc, /sys et, /dev) le contenu du disque dur de la machine source vers le disque dur vide d’une machine cible démarrée avec un LiveCD.
  • Chroot et bind /proc, /sys et, /dev depuis le LiveCD vers le disque dur.
  • Modifier le fstab et mettre à jour Grub.

De cette manière, tu peux réaliser des migrations d’une machine à un autre que ce soit du physique -> vm, vm -> physique, vm -> vm.

La migration

Dans Linux – Le b.a.-ba du shell, je t’ai pas parlé des dossiers /proc, /sys et /dev pour ne pas trop te noyer d’informations (il y a encore beaucoup de choses à ce sujet). Le contenu de ces dossiers est créé au démarrage du système ; c’est un système de fichiers virtuel volatile.
/proc correspond aux processus en cours d’exécution, /sys à une interface avec le noyau et /dev aux périphériques vus par le système.

Pour faire simple, on va migrer la vm source vers l’autre vm destination (qui est une vm totalement vide sans installation). Oué je me suis pas foulé pour les noms de machine.

Préparation de la vm destination

On va démarrer notre machine destination sur un LiveCD de la même version de la distribution que l’on migre, changer la disposition du clavier et enfin, installer et paramétrer les outils nécessaires ou utiles (vim, rsync, openssh-server) à la migration.

En fait c’est mieux mais c’est pas obligatoire d’utiliser un LiveCD de la même version. Par contre t’éviteras absolument de mélanger 32 et 64 bits.

# En console
user@debian:~$ sudo -i
root@debian:~# hostname destination
root@debian:~# echo "destination" > /etc/hostname
[...]
root@destination:~# apt install vim openssh-server rsync
root@destination:~# sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
root@destination:~# systemctl restart ssh
root@destination:~# passwd

# Et voilà plus besoin de tout retaper à la main, on reprend en ssh
antoine@dressing:~$ ssh root@destination

Partitionnement

Là va falloir que tu créé tes partitions à l’identique (je fais un sed pour frimer mais surtout pour limiter la verbosité) alors relève l’existant sur la source.

root@source:~# fdisk -l | sed -n "9,13p"
Device     Boot   Start      End  Sectors  Size Id Type
/dev/sda1          2048   976895   974848  476M 82 Linux swap / Solaris
/dev/sda2  *     976896  1953791   976896  477M 83 Linux
/dev/sda3       1953792 41940991 39987200 19,1G 8e Linux LVM

root@source:~# lvs
  LV      VG      Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lv_home vg_main -wi-ao---- <1,91g                                                    
  lv_root vg_main -wi-ao---- 17,16g

Cherche sur quel disque tu vas bosser et ouvre fdisk pour ce disque.

root@destination:~# fdisk -l | grep "/dev"
Disk /dev/sda: 20 GiB, 21474836480 bytes, 41943040 sectors
Disk /dev/loop0: 984.42 MiB, 1032241152 bytes, 2016096 sectors

# Ton disque est /dev/sda alors
root@destination:~# fdisk /dev/sda

Créé une table de partition gpt et une première partition de 80 Mo de type BIOS boot si tu boot en mode BIOS (c’est pas nécessaire si t’es en UEFI).

Command (m for help): g # créé une table de partition GPT
Created a new GPT disklabel (GUID: 23E71E7F-E36C-F54B-9028-36FEE57A4761).

Command (m for help): n # créé la partition de boot bios (je suis en GPT sans EFI, alors il faut une partition en début de disque)
Partition number (1-128, default 1): 
First sector (2048-41943006, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-41943006, default 41940991): +80M

Created a new partition 1 of type 'Linux filesystem' and of size 80 MiB.

Command (m for help): t # règle le format de la parition
Selected partition 1
Partition type or alias (type L to list all): 4 # c'est le format BIOS boot. J'ai utilisé "L" qui m'a listé les formats dans `less`.
Changed type of partition 'Linux filesystem' to 'BIOS boot'.

Créé ensuite ta swap.

Command (m for help): n # créé la parition de la swap
Partition number (1-128, default 2): 
First sector (165888-41943006, default 165888): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-41943006, default 41940991): +476M

Created a new partition 2 of type 'Linux filesystem' and of size 476 MiB.

Command (m for help): t
Partition number (1,2, default 2): 2
Partition type or alias (type L to list all): 19 # c'est le format Linux swap.
Changed type of partition 'Linux filesystem' to 'Linux swap'.

Puis /boot. Par défaut fdisk créé des partitions Linux filesystem alors celle là tu touches pas au type.

Command (m for help): n # créé la partition /boot
Partition number (3-128, default 3): 3
First sector (1140736-41943006, default 1140736): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1140736-41943006, default 41940991): +477M

Created a new partition 3 of type 'Linux filesystem' and of size 477 MiB.

Enfin, créé ton lvm et applique les modifications.

Command (m for help): n # créé la partition LVM (pas touche au format de /boot c'est déjà bien reglé)
Partition number (4-128, default 4): 4
First sector (2117632-41943006, default 2117632): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2117632-41943006, default 41940991): 

Created a new partition 4 of type 'Linux filesystem' and of size 19 GiB.

Command (m for help): t
Partition type or alias (type L to list all): 43
# n'oublie pas que "L" te permet de less la liste et donc que la liste est potentiellement plus longue que ce que tu as à l'écran.

Changed type of partition 'Linux filesystem' to 'Linux LVM'.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Tu as créé tes partitions à la bonne taille, tu peux formater la partition de swap et /boot. Ne formate pas la première partition /dev/sda1 elle n’est là que pour gérer la table de partition gpt (elle est nécessaire pour utiliser gpt sur une installation non UEFI).

# Formatage de la swap
root@destination:~# mkswap /dev/sda2
Setting up swapspace version 1, size = 476 MiB (499118080 bytes)
no label, UUID=fa566364-1bde-4fd7-b6de-0fda58ab5761

# Formatage de /boot
root@destination:~# mkfs.ext4 /dev/sda3
mke2fs 1.47.0 (5-Feb-2023)
Creating filesystem with 488448 1k blocks and 121920 inodes
Filesystem UUID: da53ae9a-40a7-4669-bd91-590620ad50d6
Superblock backups stored on blocks: 
        8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done 

Un peu de LVM

Maintenant tu vas pouvoir créer tes éléments lvm : le Volume Group et les Logical Volumes. Utilise un lv linéaire (-L) pour la /home parce que tu la définie avec une taille fixe et un lv striped (-l) pour la / pour lui attribuer tout l’espace libre restant.

# créé le Volume Group
root@destination:~# vgcreate vg_main /dev/sda4
  Physical volume "/dev/sda4" successfully created.
  Volume group "vg_main" successfully created
  
# créé le Logical Volume linéaire lv_home
root@destination:~# lvcreate -L 2G vg_main -n lv_home
  Logical volume "lv_home" created.
  
# créé le LV striped lv_root
root@destination:~# lvcreate -l +100%FREE vg_main -n lv_root
  Logical volume "lv_root" created.

Formate alors tes partitions lvm.

# Fais un effort de compréhension, on l'a vu juste au dessus
root@destination:~# mkfs.ext4 /dev/vg_main/lv_home
mke2fs 1.47.0 (5-Feb-2023)
Creating filesystem with 524288 4k blocks and 131072 inodes
Filesystem UUID: 39135a06-293e-4cd7-8849-47f02e283a2d
Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376, 294912

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done 

# Meehhh
root@destination:~# mkfs.ext4 /dev/vg_main/lv_root 
mke2fs 1.47.0 (5-Feb-2023)
Creating filesystem with 4453376 4k blocks and 1114112 inodes
Filesystem UUID: f8ef3138-0492-4402-a12a-35ee117a90e3
Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
        4096000

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

Montage des partitions

Pour commencer à préparer le rsync du système de source il faut monter notre future /. Perso, je vais monter mon lv_root dans /mnt/root mais tu peux le monter où tu veux tant que tu gères la cohérence pour la suite. Créé alors les réceptacles des dossiers /boot, /home, /dev, /proc et, /sys.

# Créé le point de montage
root@destination:~# mkdir /mnt/root

# Monte lv_root dessus
root@destination:~# mount /dev/vg_main/lv_root /mnt/root

# Créé tes dossiers
rLinux filesystemoot@destination:~# mkdir /mnt/root/boot /mnt/root/home /mnt/root/dev/ /mnt/root/proc/ /mnt/root/sys/

Monte alors tes partitions /boot et /home.

root@destination:~# mount /dev/sda3 /mnt/root/boot
root@destination:~# mount /dev/vg_main/lv_home /mnt/root/home

Montage bind

Vu que le LiveCD a peuplé les dossiers /dev, /proc et, /sys de façon adaptée pour destination, tu vas les réutiliser dans notre future /. Pour ça, tu vas faire un montage bind des existants vers /mnt/root/... et tu adaptes. Si tu veux te faire une fausse idée des montages bind, tu peux imaginer ça comme un mélange entre un lien physique et un raccourci. Le but est de partager un dossier à plusieurs endroits.

root@destination:~# mount -o bind /dev /mnt/root/dev
root@destination:~# mount -o bind /proc /mnt/root/proc
root@destination:~# mount -o bind /sys /mnt/root/sys

Migration de l’OS source

La transplantation de l’OS de source vers destination est prête ! Mais ne récupère pas /dev, /proc et, /sys et tant qu’à faire ne récupère pas non plus /lost+found.

root@destination:~# rsync -avz source:/ /mnt/root/ --exclude=/dev --exclude=/proc --exclude=/sys --exclude=/lost+found

Sur des machines un peu dodues, tu pourras préfixer ta commande par un time pour connaître après coup combien de temps l’opération a duré. Également, tu pourras exclure tes dossiers de données lourds pour gagner du temps et les rsync après.

Entre dans le terrier de lapin : le chroot

Passons maintenant du LiveCD au système que l’on vient de recopier depuis source sur destination.

root@destination:~# chroot /mnt/root/
root@destination:/# 

# Quoi ? C'est tout ?!

A partir de là, on est sur la copie de l’OS de source mais sur le hardware de destination.

root@destination:/# cat /etc/hostname 
source

Il va falloir être méticuleux : ne surtout pas oublier de modifier le hostname et l’adresse IP de la machine pour ne pas avoir de doublon. ARP Storm quand tu nous guette… Parce que ta nouvelle machine va probablement devoir cohabiter quelques temps avec l’ancienne toujours en prod, le temps par exemple de faire les derniers rsync. Bon moi mes vm sont en DHCP alors je ne passe que sur le hostname.

root@destination:/# echo "source-new" > /etc/hostname
root@destination:/# hostname source-new

Partitions et UUID

A partir de là il te reste deux choses à traiter : fstab et grub.
Dans fstab ce qui va nous déranger ce sont les UUID, il connaît ceux des partitions de source mais maintenant tu veux qu’il présente ceux de destination.

# UUID de source
root@destination:/# grep UUID /etc/fstab 
# device; this may be used with UUID= as a more robust way to name devices
UUID=f96c7db6-9354-48ce-af9b-04df025da015 /boot           ext4    defaults        0       2
UUID=b8bce0d7-4e4d-4fc0-b8b5-bcf6c67dace1 none            swap    sw              0       0

# UUID de destination
root@destination:/# lsblk -o NAME,SIZE,TYPE,MOUNTPOINTS,UUID
NAME                  SIZE TYPE MOUNTPOINTS UUID
loop0               984.4M loop             
sda                    20G disk             
|-sda1                 80M part             b8bce0d7-4e4d-4fc0-b8b5-bcf6c67dace1
|-sda2                476M part             f96c7db6-9354-48ce-af9b-04df025da015
|-sda3                477M part /boot       90icDI-eyvU-7L4H-W214-YaM2-kPQh-w1pwLh
`-sda4                 19G part             
  |-vg_main-lv_home     2G lvm  /home       6390fdc8-b9dc-46c1-80d9-c7442302a1d4
  `-vg_main-lv_root    17G lvm  /           0071373a-3160-480a-a977-fbe68728d824
sr0                   1.4G rom

Tu as deux possibilités pour la suite :

  • modifier le fstab pour remplacer les UUID de source par celles de destination,
  • modifier les UUID de destination pour reprendre celles de source.

Pour la première possibilité, bah tu t’armes de sed ou de vi et puis tu remplaces en faisant gaffe de ne pas te tromper. Je pense que c’est la meilleure solution mais j’ai envie d’explorer la seconde : swaplabel permet de modifier l’UUID d’une partition de swap et, tune2fs permet de modifier un UUID d’un système de fichiers ext.

# Applique l'UUID source de ta swap
root@destination:/# swaplabel --uuid b8bce0d7-4e4d-4fc0-b8b5-bcf6c67dace1 /dev/sda2

# Applique l'UUID source de ta boot
# d'abord, démontes la partition et check le filesystem
root@destination:/# umount /dev/sda3
root@destination:/# e2fsck -f /dev/sda3
e2fsck 1.47.0 (5-Feb-2023)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/sda3: 352/121920 files (0.6% non-contiguous), 100770/488448 blocks

# puis, modifie l'UUID et remonte la (oublie pas que t'es chroot !)
root@destination:/# tune2fs -U f96c7db6-9354-48ce-af9b-04df025da015 /dev/sda3
tune2fs 1.47.0 (5-Feb-2023)
Setting the UUID on this filesystem could take some time.
Proceed anyway (or wait 5 seconds to proceed) ? (y,N) y<proceeding>
root@destination:/# mount /dev/sda3 /boot

Bon là t’as la pression, il faut vérifier les UUID…

# La swap
root@destination:/# blkid /dev/sda2
/dev/sda2: UUID="b8bce0d7-4e4d-4fc0-b8b5-bcf6c67dace1" TYPE="swap" PARTUUID="2fbbab31-45a1-6843-b01c-c2ecddf9e990"

# /boot
root@destination:/# blkid /dev/sda3
/dev/sda3: UUID="f96c7db6-9354-48ce-af9b-04df025da015" BLOCK_SIZE="1024" TYPE="ext4" PARTUUID="0d734c03-66c5-fe4b-a95f-aece8d7ef253"

A ce moment j’ai fait un peu d’huile parce que lsblk présentait toujours les anciens UUID.

Reconfiguration de Grub

Tu dois maintenant régénérer la configuration de grub et l’installer.

# Ecris la conf de grub dans son fichier
root@destination:/# grub-mkconfig > /boot/grub/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.1.0-18-amd64
Found initrd image: /boot/initrd.img-6.1.0-18-amd64
Warning: os-prober will not be executed to detect other bootable partitions.
Systems on them will not be added to the GRUB boot configuration.
Check GRUB_DISABLE_OS_PROBER documentation entry.
done

# Et installe le pépère
root@destination:/# grub-install /dev/sda
Installing for i386-pc platform.
Installation finished. No error reported.

Pour finir, redémarre la machine en éjectant le LiveCD (la console attendra que tu valides la bonne éjection du CD).

root@destination:/# exit
exit
root@destination:~# reboot

Profit !

Contrôle que tout va bien parce que normalement c’est fini, ta machine est migrée.

root@source-new:~# lsblk -o NAME,SIZE,TYPE,MOUNTPOINTS,UUID
NAME                 SIZE TYPE MOUNTPOINTS UUID
sda                   20G disk             
├─sda1                80M part             
├─sda2               476M part [SWAP]      b8bce0d7-4e4d-4fc0-b8b5-bcf6c67dace1
├─sda3               477M part /boot       f96c7db6-9354-48ce-af9b-04df025da015
└─sda4                19G part             12dmBX-Qa6C-pjPj-nTo4-hrAi-fIso-OW7f8G
  ├─vg_main-lv_home    2G lvm  /home       39135a06-293e-4cd7-8849-47f02e283a2d
  └─vg_main-lv_root   17G lvm  /           f8ef3138-0492-4402-a12a-35ee117a90e3
sr0                 1024M rom              
root@source-new:~# 
root@source-new:~# 
root@source-new:~# 
root@source-new:~# 
root@source-new:~# df -h
Sys. de fichiers            Taille Utilisé Dispo Uti% Monté sur
udev                          961M       0  961M   0% /dev
tmpfs                         197M    572K  197M   1% /run
/dev/mapper/vg_main-lv_root    17G    1,1G   15G   7% /
tmpfs                         984M       0  984M   0% /dev/shm
tmpfs                         5,0M       0  5,0M   0% /run/lock
/dev/mapper/vg_main-lv_home   2,0G     24K  1,8G   1% /home
/dev/sda3                     437M     59M  351M  15% /boot
tmpfs                         197M       0  197M   0% /run/user/0

Conclusion

Dans cet article tu auras vu quelques notions intéressantes. Je t’ai fait jouer avec du lvm et tu as même pu voir que pour utiliser des partitions gpt sur une machine non UEFI il te faut créer une petite partition au tout début du disque.

Tu auras aussi pu modifier les UUID de tes partoches mais surtout : tu sauras comment migrer n’importe quelle installation Linux d’un hardware à un autre. Tant que le disque de ta source est lisible tu pourras toujours sauver ton installation sans avoir à tout reconfigurer.

Malgré mes choix dans cet article, je te recommande vivement de modifier les UUID dans le fstab plutôt que de modifier ceux des partitions. Si tu te vautres, c’est plus simple de rsync à nouveau le fichier que de recréer les partoches.

Comme d’hab, j’ai pu écrire des énormités. Si t’en vois une et que le cœur t’en dit, n’hésite pas à me l’indiquer.

Laisser un commentaire