+++

title = "mdadm + LVM + ext4 vers BTRFS sans larme"
date = 2015-09-28
aliases = [ "post/2015/09/28/mdadm-LVM-ext4-vers-BTRFS-sans-larme"]
[taxonomies]
tags = [ "système", "lvm", "btrfs" ]
+++

ais avec un paquet de lubrifiant quand même…

<!-- more -->

Il y a quelques années, j'ai installé mon serveur personnel avec le top du top du *state of the art* de la folie du buzz des Interwebz : RAID logiciel avec `mdadm(8)`, du volume logique comme s'il en pleuvait avec `lvm(8)` et du système de fichiers de bobo en goguette avec `ext4(5)`. Bref, de la pure folie avec de la stabilité à tous les étages, avec de la farfeluterie complètement conformiste partout. Et du fun. Beaucoup de fun.

> Cette opération a été réalisée avec succès sur une Debian Jessie et 3 ArchLinux pas Jessie.

# La tronche de la babasse

> Il s'agit d'une reconstitution, toute ressemblance avec des personnes réelles seraient complètement faite exprès.

Du coup, ça donnait une machine goupillée à peu près comme ça :

```bash
# fdisk -l /dev/sd?

Disque /dev/sda : 20 GiB, 21474836480 octets, 41943040 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : dos
Identifiant de disque : 0xc51f3b7e

Device     Boot Start      End  Sectors Size Id Type
/dev/sda1  *     2048 41940991 41938944  20G fd Linux raid autodetect

Disque /dev/sdb : 20 GiB, 21474836480 octets, 41943040 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : dos
Identifiant de disque : 0x67c9a5c7

Device     Boot Start      End  Sectors Size Id Type
/dev/sdb1        2048 41940991 41938944  20G fd Linux raid autodetect
```

Donc une seule grosse partition et un RAID en `/dev/md0`. Sur lequel on va construire un magnifique LVM :

```
# lvs
  LV   VG     Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  home vgroot -wi-ao----   4,66g                                                    
  opt  vgroot -wi-ao---- 244,00m                                                    
  root vgroot -wi-ao---- 952,00m                                                    
  srv  vgroot -wi-ao----   4,66g                                                    
  swap vgroot -wi-ao---- 952,00m                                                    
  tmp  vgroot -wi-ao---- 952,00m                                                    
  usr  vgroot -wi-ao----   2,79g                                                    
  var  vgroot -wi-ao----   2,79g                                                    
```

Voilà, ça te donne une petite idée de commet que c'était gaullé.

# À la batmobile Robin !

Quelques petits prérequis avant de commencer :
* tu peux tenter de faire tous tes changement sur les disques déjà présents dans la machine. Juste, si ça merde, t'as vraiment l'air con. Donc, tu vas utiliser un disque externe pour tout faire (ça ne changera pas grand chose au fait que si ça merde, t'auras l'air con, mais disons que tu améliores un peu tes chances).
* Ça marche mais à une condition : `btrfs-convert(8)` transforme les partitions ''ext4'' et partition ''btrfs'' mais seulement si le ''Block Size'' est à 4096 octets sur le système de fichiers d'origine. En dessous, ça marche pas. Si tu tombes sur une partoche comme ça, va falloir procéder autrement (et ça fait bien chier…).
* C'est ce que j'appellerais une migration à « tiède » (parce que c'est pas vraiment à chaud et c'est pas vraiment à froid non plus). Tu peux tout faire sur un SysRescueCD (mais c'est pas recommandé parce qu'il peut y avoir un écart de version ''btrfs'' entre SysRescCD et l'OS de base, qui produit des résultats… curieux…).

Bref, en route pour l'aventure. Première chose, faire les modifs sur les systèmes de fichiers qu'on peut faire à tiède (genre `/home` ou `/srv`) :

```
# umount /home
# btrfs-convert /dev/vgroot/home 
creating btrfs metadata.
creating ext2fs image file.
cleaning up system chunk.
conversion complete.
# mount /dev/vgroot/home /home
# mount | grep btrfs
/dev/mapper/vgroot-home on /home type btrfs (rw,relatime,space_cache)
```

Il n'y a plus qu'à modifier le `/etc/fstab` pour refléter les changements. Tu peux faire pareil pour tout le reste (mon conseil personnel, c'est de débrancher le câble réeau et de passer en init 1 pour faire le reste). La seule partition qui reste à boucler, c'est donc `/` qui va exiger par contre de redémarrer sur un boot CD quelconque.

Une fois que tu as tout converti, je ne saurais que trop te conseiller de balancer un coup d'upgrade de `grub` histoire de pas te retrouver dans les choux (à adapter en fonction de la kernaille et des détails autour bien évidemment). Je te passe les détails parce que je pense que tu es un grand garçon maintenant et que tu peux faire ça tout seul, si, si, j'insiste.

# Résultat à l'étape de montagne

Si ça reboote correctement après le coup de SysRescCD, --tu peux aller faire un Loto-- tu devrais obtenir une machine parfaitement fonctionnelle avec du ''btrfs'' à tous les étages, mais toujours dans du LVM et toujours sur du RAID (ce qui, reconnaissons-le, est un peu con-con). T'obtiens un truc à peu près comme ça :

```
# mount | grep btrfs
/dev/mapper/vgroot-root on / type btrfs (ro,relatime,space_cache)
/dev/mapper/vgroot-usr on /usr type btrfs (rw,relatime,space_cache)
/dev/mapper/vgroot-srv on /srv type btrfs (rw,relatime,space_cache)
/dev/mapper/vgroot-tmp on /tmp type btrfs (rw,relatime,space_cache)
/dev/mapper/vgroot-home on /home type btrfs (rw,relatime,space_cache)
/dev/mapper/vgroot-var on /var type btrfs (rw,relatime,space_cache)
```

Du coup, on va transférer tout ça sur un autre disque. Là encore, je te recommande fortement de débrancher la machine parce que malheureusement, l'opération n'est pas complètement chaude (elle est tiède, humide et un peu poisseuse…).

Première étape : créer un snapshot en lecture seule de l'ensemble des partitions en questions. Ça ressemble vaguement à ça :

```
# btrfs subvolume snapshot -r /usr /usr/BACKUP
Create a readonly snapshot of '/usr' in '/usr/BACKUP'
```

Une fois, que c'est fait, il suffit de créer un gros volume ''btrfs'' sur un autre disque dur (ici `/dev/sdc`) :

```
# mkfs.btrfs -L ROOT /dev/sdc
Btrfs v3.17
See http://btrfs.wiki.kernel.org for more information.

Turning ON incompat feature 'extref': increased hardlink limit per file to 65536
fs created label ROOT on /dev/sdc
        nodesize 16384 leafsize 16384 sectorsize 4096 size 20.00GiB
# mount LABEL=ROOT /mnt 
```

Il ne reste maintenant qu'à faire du ''send/receive'' entre les disques du serveur et le disque externe :
```
# btrfs send /BACKUP | btrfs receive /mnt/
At subvol /BACKUP
At subvol BACKUP
# mv /mnt/BACKUP /mnt/__ro_root/
```

Et ainsi de suite pour toutes les autres partitions !

# Tu snap, tu snap, tu snap, tu snap à droite, tu snap et t'y es

Et à partir de ce moment, ça va être la fête du slip au snapshot. Tu dois donc avoir un truc de ce genre : 
```
# btrfs sub list -a /mnt
ID 257 gen 10 top level 5 path __ro_root
ID 259 gen 17 top level 5 path __ro_usr
ID 260 gen 17 top level 5 path __ro_var
ID 261 gen 20 top level 5 path __ro_home
ID 262 gen 23 top level 5 path __ro_srv
```

Donc on va snapper comme des connards :

```
# cd /mnt
# btrfs sub snap __ro_root __root
Create a snapshot of '__ro_root' in './__root'
# rmdir __root/usr/
# btrfs sub snap __ro_usr __root/usr
Create a snapshot of '__ro_usr' in '__root/usr'
# btrfs sub snap __ro_var __root/var
Create a snapshot of '__ro_var' in '__root/var'
```

Pour `/home` et `/srv`, on va procéder un peu différemment, en faisant un snapshot à la racine du volume ''btrfs'' :

```
# btrfs sub snap __ro_home __home
Create a snapshot of '__ro_home' in './__home'
# btrfs sub snap __ro_srv __srv
Create a snapshot of '__ro_srv' in './__srv'
```

aintenant, nous allons maintenant nous arranger pour que `__root` soit le volume par défaut et modifier le `/etc/fstab` dans ce sous-volume :
```
# btrfs sub set-default 263 /mnt
# umount /mnt
# mount LABEL=ROOT /mnt
# mount -o subvol=__home LABEL=ROOT /mnt/home
# mount -o subvol=__srv LABEL=ROOT /mnt/srv
```

aintenant, tu peux chrooter dans `/mnt` (après avoir monté en bind les `/dev`, `/sys`, `/run` et `/proc`) et modifier le `/etc/fstab` :

```
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
LABEL=ROOT      /               btrfs   defaults        0       1
LABEL=ROOT      /home           btrfs   defaults,subvol=__home  0       2
LABEL=ROOT      /srv            btrfs   defaults,subvol=__srv   0       2
tmpfs           /tmp            tmpfs   nodev,nosuid,size=256M  0       0
/dev/sr0        /media/cdrom0   udf,iso9660 user,noauto     0       0
```

Deux remarques avant de continuer : plus de `/tmp`, tu peux très bien te faire un petit sous-volume pour le gérer, mais franchement autant le mettre en RAM si ta machine le permet ; plus de swap non plus : il n'y a plus de partition sur le disque, on ne peut donc pas dédier une partition de swap. Les `swapfiles` ne sont pas gérés par ''btrfs'' pour le moment. Personnellement, je trouve qu'on s'en passe bien, à condition d'avoir suffisamment de RAM pour tenir la route bien entendu…

Une fois que tu as fait tout ça, tu peux remettre un coup de `grub-mkconfig` et `grub-install`, croiser les doigts et rebooter directement sur le disque externe. À partir de maintenant, la température de l'opération devrait remonter pas mal (plus besoin de reboot, plus besoin de limiter les lectures/écritures).

# C'est le mimi, c'est le rara, c'est le miracle !

La magie opère immédiatement :

```
# btrfs sub list -a /
ID 257 gen 27 top level 5 path <FS_TREE>/__ro_root
ID 259 gen 30 top level 5 path <FS_TREE>/__ro_usr
ID 260 gen 31 top level 5 path <FS_TREE>/__ro_var
ID 261 gen 33 top level 5 path <FS_TREE>/__ro_home
ID 262 gen 34 top level 5 path <FS_TREE>/__ro_srv
ID 263 gen 43 top level 5 path <FS_TREE>/__root
ID 266 gen 42 top level 263 path __root/usr
ID 267 gen 42 top level 263 path __root/var
ID 268 gen 42 top level 5 path <FS_TREE>/__home
ID 269 gen 42 top level 5 path <FS_TREE>/__srv
```

Il s'agit maintenant de tout rebasculer sur les disques nominaux. On va donc casser les petites fesses de LVM :

```
# vgchange -an
  0 logical volume(s) in volume group "vgroot" now active
```

Et fister `mdadm` :

```
# mdadm --stop /dev/md0
mdadm: stopped /dev/md0
```

On va maintenant convertir à notre nouvelle religion les anciens disques (et en profiter pour remettre de la redondance) :

```
# btrfs device add -f /dev/sda / ## le -f sert à indiquer que oui, on va bien lui casser les fesses (d'où la lettre)
# btrfs device add -f /dev/sdb / 
# btrfs balance start -dconvert=raid1 -mconvert=raid1 /
```

Après de longues minutes d'attente (tu peux jouer les voyeurs avec `btrfs balance status /`), tu vas obtenir un magnifique RAID1 avec 3 disques :

```
# btrfs fi df /
Data, RAID1: total=2.00GiB, used=895.21MiB
System, RAID1: total=32.00MiB, used=16.00KiB
etadata, RAID1: total=1.00GiB, used=55.45MiB
GlobalReserve, single: total=32.00MiB, used=0.00B
# btrfs fi sh /
Label: 'ROOT'  uuid: 4cc2f675-d607-4674-8522-92de9065eff5
        Total devices 3 FS bytes used 950.68MiB
        devid    1 size 20.00GiB used 1.03GiB path /dev/sdc
        devid    2 size 20.00GiB used 2.03GiB path /dev/sda
        devid    3 size 20.00GiB used 3.00GiB path /dev/sdb

Btrfs v3.17
```

Et il suffira d'en retirer un :

```
# btrfs device del /dev/sdc /
```

Et voilà, la magie a opéré ! Même niveau de sécurité, mais plein de fonctionnalités en prime, et surtout, la classe ''btrfs'' à portée de groin.

Banzaï !
