Migrer son OS (Linux) vers un RAID1 sans réinstallation

Rédigé par Fenix - - 2 commentaires

Pour tout un tas de raison, et notamment par manque de place dans sa tour lors de sa précédente refonte, l'OS de mon serveur à la maison tournait depuis un bon moment sur un disque unique. J'ai profité d'une nouvelle refonte de printemps pour repasser sur un RAID1, sans tout réinstaller bien sûr !

Mon serveur, qui fera sûrement l'objet d'un article un de ces jours (si ça peut donner des idées), est bien chargé : a son heure de gloire, il accueillait 14 disques (mécaniques et SSD confondus), sans compter une période avec 6 ou 7 disques USB supplémentaires pour diverses raisons. Mais tout ce petit monde consomme pas mal, et a surtout bien souffert lors de précédents montages audacieux (cette tour me sert pour mon auto-hébergement, mes archivages, mes besoins domestiques (NAS, vidéosurveillance, etc), et mes tests). Du coup, j'ai souhaité revenir à un schéma plus simple, faire du ménage et reconsolider ce qui devait l'être, en l'occurence l'OS (ici, une Debian 9 couplée avec Proxmox 5).

Je vais tenter, dans cet article, de détailler les différentes étapes qui m'ont permis de revenir sur un RAID1, sans réinstallation, avec un downtime raisonnable de 15 min environ. Ces manipulations sont valables pour Debian, mais doivent être valables à peu de choses près pour d'autres distributions.

Disclaimer : je ne suis en aucun cas responsable de la perte de vos services ou données en cas de fausses manipulations ! Cet article illustre un cas spécifique, qu'il est nécessaire de comprendre et d'adapter en fonction de vos besoins.

 

Etat initial

 

Rapide aperçu du point de départ :

  • 8 disques de 4To pour le NAS et les services, gérés par ZFS, mais hors scope ici ;
  • 1 disque de 250G pour l'OS, partitionné avec du LVM et identifié en tant que sdc ;
  • Le serveur tourne sous Proxmox 5 / Debian 9 et héberge une quinzaine de conteneurs/VM.

J'exclus les SSD qui me servaient de cache pour mon pool ZFS : après refonte de mes services, je n'ai plus autant de besoins en I/O et je les réintègrerai une prochaine fois.

L'objectif est donc :

  • Toujours les disques de 4To, inchangés ;
  • 2 disques de 160Go de récup qui me serviront ici pour mon nouveau RAID1 (+ LVM).

Dans nos prérequis, nous aurons simplement besoin :

  • De nos 2 disques pour le RAID1, donc ;
  • D'un LiveCD Ubuntu/Debian/whatever (je prendrai ici une Xubuntu, parce que c'est ce que j'avais sur une clé USB déjà dispo) ;
  • D'une plage de maintenance (si vous hébergez d'autres personnes).

Enfin, mon schéma de partitionnement est actuellement le suivant :

root@orion:~# lsblk
NAME                    MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sdc                       8:0    0 149.1G  0 disk  
└─sda1                    8:1    0 149.1G  0 part  
  ├─vg_source-lv_root   253:0    0    20G  0 lvm   /
  ├─vg_source-lv_swap1  253:1    0    10G  0 lvm   [SWAP]
  ├─vg_source-lv_home   253:2    0    10G  0 lvm   /home
  ├─vg_source-lv_tmp    253:3    0    10G  0 lvm   /tmp
  ├─vg_source-lv_var    253:4    0    10G  0 lvm   /var
  └─vg_source-lv_boot   253:5    0     1G  0 lvm   /boot

 

Préparation

 

Création du RAID

 

Comme j'ai la chance d'avoir de la place dans la tour, je branche directement les deux disques, mais la manipulation peut également se faire avec un seul (on montera simplement le RAID1 avec un élément en missing, qu'on comblera après avoir retiré l'ancien disque de l'OS).
J'utilise ici l'outil mdadm, grand classique sous Linux, et mes 2 disques seront identifiés comme sda et sdb.

Avant toute chose, on prend soin de "zéroer" le superblock, qui peut contenir une ancienne configuration RAID :

mdadm --zero-superblock /dev/sda
mdadm --zero-superblock /dev/sdb

Pour le partitionnement, on peut utiliser à peu près ce qu'on veut (fdisk, parted...), le tout étant d'avoir au final une seule partition de type fd (pour "Linux RAID autodetect"). Je ne couvre pas cette section (j'avoue, j'ai la flemme de faire des screenshots... et ce n'est pas vraiment l'objet de cet article), je préfère vous renvoyer par exemple vers cette page du Wiki Archlinux pour avoir des explications assez complètes.

On assemble donc notre RAID1 avec nos 2 partitions créées (il s'appellera ici md0) :

mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sd[ab]1

S'il nous manque un disque pour le moment :

mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda1 missing

Et on ajoutera le second disque plus tard avec :

mdadm /dev/md0 --add /dev/sdb1

On vérifie l'état de notre RAID (il nous faut "UU" dans la ligne sous notre md0 fraîchement créé, sauf si vous n'avez qu'un disque pour le moment et auquel cas vous aurez "U_") :

root@orion:~# cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md0 : active raid1 sdb1[1] sda1[0]
      156289792 blocks [2/2] [UU]
      bitmap: 1/2 pages [4KB], 65536KB chunk
unused devices: <none>

Autre vue, plus détaillée (notez la ligne State : active) :

root@orion:~# mdadm -D /dev/md0
/dev/md1:
        Version : 0.90
  Creation Time : Fri Mar 16 21:46:44 2018
     Raid Level : raid1
     Array Size : 156289792 (149.05 GiB 160.04 GB)
  Used Dev Size : 156289792 (149.05 GiB 160.04 GB)
   Raid Devices : 2
  Total Devices : 2
Preferred Minor : 1
    Persistence : Superblock is persistent

  Intent Bitmap : Internal

    Update Time : Mon Jun  4 18:42:30 2018
          State : active
 Active Devices : 2
Working Devices : 2
 Failed Devices : 0
  Spare Devices : 0

           UUID : cbc953eb:9e534380:215cc7a0:65116968 (local to host lrdf-srv-proxmox1)
         Events : 0.1081

    Number   Major   Minor   RaidDevice State
       0       8        1        0      active sync   /dev/sda1
       1       8       17        1      active sync   /dev/sdb1

Et par précaution (même si normalement mdadm scanne tous les disques au démarrage pour trouver les potentiels RAID), nous allons l'ajouter au fichier de configuration qui va bien :

mdadm --detail --scan >> /etc/mdadm/mdadm.conf

(Au passage, il est impératif de superviser l'état de ses disques et des ses RAIDs. Pour ce dernier point, mdadm vous prévient quand il y a un problème, pensez à minima à renseigner une adresse mail dans le fichier mdadm.conf (et à configurer un postfix ou un ssmtp pour que votre serveur puisse envoyer des mails, ça peut paraître évident, mais...)). Et supervisez (je ne savais plus si je l'avais déjà mentionné).

 

Partitionnement

 

RAPPEL : ce schéma de partitionnement correspond à mes besoins, ma façon de travailler. Il faut adapter selon les vôtres !

J'aime LVM (parce qu'on peut redimensionner nos partitions facilement, entre autres), voici donc le découpage que j'utilise et que je vais réintégrer sur mon RAID1 :

/dev/mapper/vg_source-lv_boot 1G
/dev/mapper/vg_source-lv_root 10G
/dev/mapper/vg_source-lv_home 10G
/dev/mapper/vg_source-lv_var 10G
/dev/mapper/vg_source-lv_tmp 10G
/dev/mapper/vg_source-lv_swap1 16G

Création du physical volume (rappel : md0 est ici le RAID1 précédemment créé) :

pvcreate /dev/md0

Création du volume group :

vgcreate vg_dest /dev/md0

Création des logical volumes :

lvcreate vg_dest -n lv_boot -L 1G
lvcreate vg_dest -n lv_root -L 10G
lvcreate vg_dest -n lv_home -L 10G
lvcreate vg_dest -n lv_var -L 10G
lvcreate vg_dest -n lv_tmp -L 10G
lvcreate vg_dest -n lv_swap -L 16G

Formatage des volumes (je reste sur de l'EXT4 très classique pour l'OS, même si je teste aussi en ce moment de le migrer sur ZFS) :

mkfs.ext4 /dev/mapper/vg_dest-lv_boot
mkfs.ext4 /dev/mapper/vg_dest-lv_root
mkfs.ext4 /dev/mapper/vg_dest-lv_home
mkfs.ext4 /dev/mapper/vg_dest-lv_var
mkfs.ext4 /dev/mapper/vg_dest-lv_tmp
mkswap /dev/mapper/vg_dest-lv_swap

On laissera ce dernier swap inactif pour le moment.

 

Copie des fichiers

 

On va maintenant pouvoir copier notre OS. A noter que dans mon cas, je n'utilise pas le /var/lib/vz monté par Proxmox par défaut pour stocker mes VM. Si vous l'utilisez, il faudra arrêter vos VM avant la copie et vous ne pourrez les relancer qu'une fois le RAID1 booté correctement.
A noter également, toujours dans le cas de Proxmox, qu'il faudra exclure le contenu de /etc/pve, qui est géré directement par celui-ci et empêchera le service de redémarrer si le répertoire n'est pas vide au reboot.

Montage temporaire :

mkdir /tmp/{boot,home,root,var}
mount /dev/mapper/vg_dest-lv_var /tmp/var
mount /dev/mapper/vg_dest-lv_home /tmp/home
mount /dev/mapper/vg_dest-lv_boot /tmp/boot
mount /dev/mapper/vg_dest-lv_root /tmp/root

Copie (et on laisse mouliner) :

rsync -avzl --progress /var/ /tmp/var/
rsync -avzl --progress /home/ /tmp/home/
rsync -avzl --progress /boot/ /tmp/boot/
rsync -avzl --progress / /tmp/root/ --exclude=/var --exclude=/tmp --exclude=/home --exclude=/boot --exclude=/sys/* --exclude=/dev/* --exclude=/proc/* --exclude=/run --exclude=/nas --exclude=/mnt --exclude=/etc/pve/*

A ce moment-là, on pourra arrêter tous les services qui tournent (dans mon cas, les VM/conteneurs/samba/NFS...) et refaire une dernière passe de rsync (qui devrait être très rapide) pour être sûr de tout avoir à jour (en ajoutant un --delete pour purger les fichiers temporaires ou de lock).

 

Redémarrage sur un LiveCD

 

Le RAID1 est prêt, les partitions sont créées et les fichiers copiés : on peut redémarrer sur notre LiveCD. Au passage, je débranche l'ancien disque de l'OS, que je garde bien dans un coin au cas où.
Une fois booté, j'ai eu la mauvaise surprise de ne pas avoir mdadm d'installé... Grrr. Et comme c'est mon serveur qui porte les services réseaux, pas d'Internet sur ledit LiveCD. Je récupère donc le .deb qui va bien en 4G, et j'installe mdadm.

 

Montage temporaire et chroot

 

On va donc aller chercher notre RAID1, et monter nos partitions (pas besoin de monter nos nouveaux tmp et home, pour ces manipulations) :

mdadm --assemble --scan
mkdir -p /tmp/newroot/boot /tmp/newroot/var
mount /dev/mapper/vg_dest-lv_root /tmp/newroot/
mount /dev/mapper/vg_dest-lv_boot /tmp/newroot/boot
mount /dev/mapper/vg_dest-lv_var /tmp/newroot/var

Puis on prépare notre chroot :

mount --bind /dev /tmp/newroot/dev
mount --bind /proc /tmp/newroot/proc
mount --bind /sys /tmp/newroot/sys
chroot /tmp/newroot

 

Grub, initramfs et fstab

 

Nous allons donc maintenant modifier notre boot pour prendre en compte notre RAID1.

Déjà, on installe et met à jour la configuration de notre Grub pour tenir compte de notre nouveau partitionnement (sda et sdb sont toujours ici mes disques en RAID1) :

update-grub

Et on veille à bien installer Grub sur les 2 disques de notre grappe, pour que chacun puisse booter sans l'autre en cas de besoin :

grub-install /dev/sda
grub-install /dev/sdb

Ensuite, il va falloir modifier la configuration de l'initramfs pour lui dire d'utiliser le nouveau swap que nous avons créé au lieu de l'ancien :

vim /etc/initramfs-tools/conf.d/resume
     RESUME=/dev/mapper/vg_dest-lv_swap1
update-initramfs -u

Et pour finir, on va modifier notre fstab pour que nos montages se fassent dorénavant sur nos nouvelles partitions (on commentera les anciennes lignes, ci-dessous on ne garde que les nouvelles) :

UUID=77fc0f14-d504-4e9d-bc8e-26324758883a   /boot   ext4    defaults        0       2
UUID=ed7fff00-42e6-48aa-98e7-86164629401f   /       ext4    errors=remount-ro 0       1
UUID=da273eca-e6d0-4fc8-b7cd-62a43cfa70ca   /home   ext4    defaults        0       2
UUID=db2663c3-ffe8-4c23-8c69-e954cb79c771   /var    ext4    defaults        0       2
UUID=3a878d3b-f15e-4ea7-ba69-16a4d46d1194   /tmp    ext4    defaults        0       2
UUID=b328e475-ad86-4bfb-a801-0f4a9b17a785   none    swap    sw              0       0

Où l'UUID sur chaque ligne sera récupéré comme suit, pour chacun de nos volumes :

root@orion:~# blkid /dev/mapper/vg_dest-lv_root
/dev/mapper/vg_dest-lv_root: UUID="ed7fff00-42e6-48aa-98e7-86164629401f" TYPE="ext4"

 

Reboot

 

En théorie, on est prêt ! On peut éteindre le LiveCD et relancer notre serveur sur notre joli RAID1 (en vérifiant que le BIOS soit configuré pour booter dessus).
Si tout se passe bien, on démarre correctement. Une fois connecté, on vérifiera que tous nos volumes sont bien montés (df -h), que le swap est bien actif (free -h), et que nos services sont lancés.
Si non, et bien il faudra aller gratter un peu en fonction des cas !

Pour information et en cas de problème, si vous avez bien gardé le disque de votre ancien OS, il vous suffit de le rebrancher et de redémarrer dessus pour revenir à l'état initial (nous n'avons touché à aucune VM ni aucun service).

Au final, mon schéma de partitionnement est tel qu'espéré :

root@orion:~# lsblk
NAME                    MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda                       8:0    0 149.1G  0 disk  
└─sda1                    8:1    0 149.1G  0 part  
  └─md1                   9:1    0 149.1G  0 raid1
    ├─vg_orion-lv_root  253:0    0    20G  0 lvm   /
    ├─vg_orion-lv_swap1 253:1    0    10G  0 lvm   [SWAP]
    ├─vg_orion-lv_home  253:2    0    10G  0 lvm   /home
    ├─vg_orion-lv_tmp   253:3    0    10G  0 lvm   /tmp
    ├─vg_orion-lv_var   253:4    0    10G  0 lvm   /var
    └─vg_orion-lv_boot  253:5    0     1G  0 lvm   /boot
sdb                       8:16   0 149.1G  0 disk  
└─sdb1                    8:17   0 149.1G  0 part  
  └─md1                   9:1    0 149.1G  0 raid1
    ├─vg_orion-lv_root  253:0    0    20G  0 lvm   /
    ├─vg_orion-lv_swap1 253:1    0    10G  0 lvm   [SWAP]
    ├─vg_orion-lv_home  253:2    0    10G  0 lvm   /home
    ├─vg_orion-lv_tmp   253:3    0    10G  0 lvm   /tmp
    ├─vg_orion-lv_var   253:4    0    10G  0 lvm   /var
    └─vg_orion-lv_boot  253:5    0     1G  0 lvm   /boot

2 commentaires

#1  - Marmotte a dit :

Je pense que cette procédure peut être simplifiée. J'ai déjà migré des systèmes d'un PC à un autre en copiant simplement les LV sur le nouveau disque, sans problème.

Les différences dans l'exemple de cet article sont à partir du paragraphe nommé "Partitionnement".
Après avoir créé le PV et le VG, il suffit de créer des LV un légèrement plus grands que ceux d'origine (pour garder une marge de sécurité) depuis le live CD, puis de copier le système de fichier de l'ancien LV dessus (sudo cp /dev/old-vg/lvname /dev/new-vg/lvname). Après copie, la commande "lvresize -r ..." permet de remettre le LV à la taille du système de fichiers (pour éviter de gaspiller de l'espace disque).
Il ne reste alors qu'à remettre le bootloader en place en chroot et c'est terminé.

Répondre
#2  - Fenix a dit :

Oui en effet, on peut parfaitement modifier la procédure selon les besoins, mais dans l'exemple que tu donnes je ne suis pas sûr de comprendre le gain que ça apporte ? On doit toujours créer des LV de destination et copier les fichiers, donc quel est l'intérêt par rapport à ici ?
Sachant qu'en plus, après relecture, je m'aperçois que que tout le blabla sur LVM n'est pas forcément pertinent : je voulais situer le contexte et illustrer mon exemple, mais le coeur de la manipulation réside dans la création du RAID + de la remise en place du bootloader. Mon partitionnement perso n'a pas forcément grand intérêt, en fait :)

Répondre

Fil RSS des commentaires de cet article

Écrire un commentaire

Quelle est le deuxième caractère du mot ag0ltb ?