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 :

# 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'

Maintenant, 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

Maintenant, 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
Metadata, 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ï !