LVM et Snapshot
LVM est un outil super puissant de gestion des volumes logiques. Cela remplace, d'une certaine façon, le partitionnement des disques. C'est quand même différent en pratique mais on ne va pas voir les détails ici ; allez plutôt lire ce qui est listé dans sources_et_liens.
Il faut bien différencier
- le volume physique (PV) qui est la partition où on va installer nos volumes, par exemple /dev/sda
- le groupe de volume (VG) qui va être un contenant des volumes proprement dit
- le volume logique (LV), qui est un emplacement sur la partition, à l'intérieur d'un VG.
Commandes utiles
Afficher les informations
lvs
(en liste) oulvdisplay
(plus complet) pour afficher des informations à propos des LV.lvs
seul va lister tous les volumes logiques du système.vgs
(en liste) ouvgdisplay
(plus complet) pour afficher des informations à propos des VG.
Lorsqu'on fait vgs
, on obtient ce genre d'information :
VG #PV #LV #SN Attr VSize VFree groska 1 24 1 wz--n- 1,80t 1,09t
- PV indique le nombre de volume physique (ici, un)
- LV le nombre de volume logique
- VSize la taille totale du groupe de volume sur le disque dur
- VFree indique combien d'espace n'est pas utilisé dans le VG par des LV : c'est donc ce qu'on peut exploiter.
Créer/supprimer un volume
Voir les tutos listés plus bas, ou le début de la procédure d'installation avec Xen vu que c'est ça qu'on fait.
En résumé, une fois qu'on a son PV (pvcreate /dev/sda3
) et VG (vgcreate NOM_VG /dev/sda3
), soit on créé la VM via Xen (xen-create-image etc
) soit on créé avec les outils LVM :
lvcreate -n NOM_LV -L TAILLE NOM_VG
- NOM_LV : nom qu'on donne au volume logique
- TAILLE : taille, par exemple 500m, 10g ou 1t
- NOM_VG : nom du groupe de volume dans lequel le LV va être.
Si le volume est à utiliser pour du stockage, il faut le formater et lui attribuer un système de fichier :
mkfs.ext4 /dev/NOM_VG/NOM_LV
Vérifier que tout va bien en la montant :
mkdir /mnt/lv mount /dev/NOM_VG/NOM_LV /mnt/lv
L'ajouter dans le système où elle sera montée (donc depuis une VM si ce n'est pas depuis le système hôte, et dans ce cas ce sera /dev/xvdXX
), dans /etc/fstab pour que ce soit monté au démarrage :
/dev/NOM_VG/NOM_LV /mnt/lv ext4 defaults 0 2
Pour supprimer un volume, s'assurer qu'il est démonté, puis simplement :
lvremove /dev/NOM_VG/NOM_LV
Redimensionnement
Vérifier la place occupée sur le volume et restant sur le disque avant de bidouiller.
Éteindre les VM qui peuvent faire appel au volume ou, si ça ne marche pas avec des vm, démonter le volume.
Il y a deux commandes possibles : lvresize
qui a des risques non négligeable de créer des soucis, et lvextend
qui demande plus de manipulation mais est plus sécurisé.
Il faut que la taille du volume soit en rapport avec la table de partition du volume.
lvextend : augmenter
On commence par augmenter la taille du volume. On peut soit dire combien on veut ajouter (–size
, soit donner tout de suite la taille finale à laquelle on veut arriver (-size
) :
lvextend --size +40G /dev/vg0/foo
Ou pour donner la taille finale voulue :
lvextend --size 120G /dev/vg0/foo
Un message “successfully resized” doit apparaître.
Vérifier la nouvelle taille avec lvdisplay
lvdisplay /dev/vg0/foo
Vérifier ensuite qu'il n'y a pas de souci avec le volume en question, sinon l'étape suivante va foirer :
fsck -f /dev/mapper/vg0-foo
fsck
préfère passer par /dev/mapper, faites-lui plaisir.
Lancer ensuite la prise en compte du redimensionnement :
resize2fs /dev/vg0/foo
Sources :
lvresize : augmenter ou réduire
lvresize
est plus puissant car il permet d'étendre ou de réduire. Mais si on réduit en dessous du dernier bit utilisé sur le volume, on va avoir droit à un volume corrompu1).
Il faut d'abord réduire la taille du système de fichier, puis réduire la partition elle-même, sans quoi la partition se corrompt.
Si la partition est en ext2, 3 ou 4, on utilise resize2fs.
Pour connaître la taille minimale de la partition :
resize2fs -P /nom/de/la/partition
Pour réduire à 50G par exemple :
resize2fs /nom/de/la/partition 50G
Utiliser lvresize
(dans l'exemple, on réduit à 100Go) :
lvresize -r -L 100g /dev/mapper/svg-ca
En théorie, avec l'options -r, pas besoin de faire resize2fs
avant, lvresize
s'occupera de redimensionner le système de fichier puis ensuite la partition. L'option -L indique la taille finale que l'on souhaite obtenir.
Pourquoi sur “mapper” ?
Avec LVM en version 1, c'est bien /dev/mvg/Vol1 qui aurait été affiché. Depuis la version 2, LVM utilise le périphérique mapper, ce qui permet pas mal de choses (comme chiffrer les volumes logiques, etc). Pour simplifier, disons que ces deux notations « /dev/mvg/Vol1 » et « /dev/mapper/mvg-Vol1 » sont synonymes. Dans la pratique, il est conseillé quand même d'utiliser plutôt la forme « /dev/mvg/Vol1 », certaines commandes ne passeront pas autrement.
Source : Ubuntu
Snapshot
L'un des gros intérêt de LVM est le snapshot. Cela va prendre l’instantané d'un volume à un moment donné ; on peut ensuite revenir à cet état antérieur. Un snapshot, c'est comme un point de contrôle/sauvegarde rapide dans un jeu vidéo.
- <Shepeng> Quand tu fais un snapshot, il le lie au disque d'origine et y note les modifications effectuées. Le disque continue à vivre sa vie, mais tout ce qui est modifié dessus est noté sur le snapshot. Quand tu supprime le snapshot, c'est comme supprimer ces notes, elles sont perdues, tu ne peux plus revenir en arrière. Quand tu veux revenir au point de départ, il va appliquer toutes les modifications à l'envers sur le disque d'origine, en utilisant les données du snapshot, puis le snapshot étant devenu inutile, il le supprime aussi.
- <Shepeng> Non. Il représente l'état initial de Lirria. Considère-le en lecture seule. Tu en fais une copie, ça permet juste de ne pas interompre Lirria pendant toute la durée de la copie.
- <Zatalyz> je crois que je commence à voir. Donc, le snapshot va rester là, en lecture seule, pendant qu'on fait des bidouilles sur Lirria. Si on se rend compte qu'on a fait une mauvaise bidouille, on peut dire “retour à l'état du snapshot”, c'est ça ?
- <Shepeng> Oui
- <Zatalyz> Mais on peut aussi se dire que nos bidouilles sont bien, dans ce cas on détruit le snapshot ou on le met à jour avec un nouveau snapshot. C'est ça aussi ?
- <Shepeng> oui. Deux cas d'utilisation typique : copie d'une VM en production, et test d'une nouveauté/mise à jour avec possibilité de retour arrière.
- <Zatalyz> ok. Donc… Je reviens à Spofu et Lirria. Je fais mon snapshot de Lirria… Puis je créé Spofu, et je lui dit de se mettre dans l'état du snapshot de Lirria ?
- <Shepeng> Oui, puis tu supprime le snapshot. Le fait de copier le snapshot au lieu du disque initial assure de copier l'état initial
- <Zatalyz> Ok, ça devient plus clair, merci :)
Avant de créer un snapshot, il faut s'assurer qu'il aura ce qu'il faut d'espace. Pas besoin de le faire aussi gros que le volume d'origine ! Le plus simple est de vérifier la taille du volume d'origine avec df
ou ncdu
(depuis la VM, pas depuis l'hyperviseur) et de compter un peu plus de place.
# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda2 30G 2.1G 26G 8% /
Donc, ici, prévoir un snapshot de 10Go sera largement assez pour démarrer.
lvcreate -L 10g -s -n lv_test_20110617 /dev/volume_groupe/lv_test
Va créer un snapshot du LV “lv_test” à la taille de 10Go qui va avoir comme nom “lv_test_20110617”. Attention, la taille d'utilisation du snapshot évolue avec l'utilisation. Si ce snapshot se retrouve rempli à 100%, il devient alors inutilisable (état “INACTIVE”) mais pas d’inquiétude car il n'y a pas d’impact pour le LV d'origine4). Attention ! Le snapshot se remplit à mesure que l'état initial du disque est modifié : il enregistre tout ce qui a été fait, pour le défaire et revenir à l'état antérieur si on lui demande. L'espace peut donc se remplir !
Lien : https://wiki.archlinux.org/index.php/LVM#Snapshots
Lors de la création d'un volume logique, l'option -s créé un snapshot d'un volume existant.
Un snapshot conserve toutes les modifications apportées au LV d'origine, afin de pouvoir les rejouer à l'envers, soit à la volée si on utilise le snapshot comme périphérique, soit lors d'un merge. Ansi il est vide au départ et se remplit au fur et à mesure que des modifications sont apportées au LV d'origine.
Si le volume logique est utilisé pour une VM, il vaut mieux éteindre la VM, faire le snapshot, puis rallumer la VM. Cela évitera d'avoir des incohérences lié à ce qui est stocké dans la RAM, le cache disque etc… De même, si une écriture se fait durant le snapshot, cela pourrait amener des incohérences.
Cela reste un risque faible (le snapshot est relativement rapide) mais éteindre la VM évitera de potentiels problèmes.
Utilisation du snapshot pour cloner une VM
Ici je vais expliquer comment dupliquer une VM en utilisant des snapshots pour réduire le temps d'inactivité. Le cas pratique est la copie de Lirria pour faire Spofu.
Création du snapshot
La création du snapshot sert pour deux raisons :
- La copie d'un disque en train d'être modifié risque fortement d'amener à des incohérences. Par exemple, un fichier créé alors que le répertoire qui le contient est déjà copié ne sera pas accessible.
- La copie d'une partition complète est longue, et pendant la copie la VM l'utilisant est à l'arrêt. Le snapshot permet de réduire ce temps d'arrêt.
root@groska:~# xl shutdown lirria root@groska:~# lvcreate -s -L 10G -n liria-disk-snap /dev/groska/liria-disk root@groska:~# xl create /etc/xen/liria.cfg
La création du snapshot prenant quelques secondes, la VM est arrêté moins d'une minute.
Copie du LV
Le snapshot contenant l'état du LV figé au moment de sa création, il suffit de le copier, on peut utiliser dd sur une partition de même taille que la partition d'origine.
On pourrait aussi vouloir faire une copie du système de fichier, en montant les partitions et en utilisant cp ou tar. Je n'ai pas testé dans ce cas précis, mais c'est envisageable, et peut accélérer la copie.
On va préparer la création de spofu en créant également le LV destiné au swap. On se place dans un screen afin de pouvoir se déconnecter sans avoir à attendre la fin de la copie.
root@groska:~# screen -DR root@groska:~# lvcreate -L 100G -n spofu-disk groska root@groska:~# lvcreate -L 4G -n spofu-swap groska root@groska:~# mkswap /dev/groska/spofu-swap root@groska:~# dd if=/dev/groska/liria-disk-snap of=/dev/groska/spofu-disk
La dernière commande étant très longue, on peut aller faire autre chose.
Création de la VM
On va reprendre la configuration et les données de lirria, en modifiant ce qui est nécessaire, à savoir l'adresse IP, et le nom. Que ce soit le nom d'hôte dans la VM, ou le nom de la VM dans XEN.
root@groska:~# cp /etc/xen/liria.cfg /etc/xen/spofu.cfg root@groska:~# sed s/192.168.20.36/192.168.20.39/g -i /etc/xen/spofu.cfg root@groska:~# sed s/lirria/spofu/g -i /etc/xen/spofu.cfg
On peut vérifier à la main que tout soit bien.
root@groska:~# mount /dev/groska/spofu-disk /mnt/target root@groska:~# sed s/192.168.20.36/192.168.20.39/g -i /mnt/target/etc/network/interfaces root@groska:~# sed s/lirria/spofu/g -i /mnt/target/etc/hostname root@groska:~# umount /mnt/target
J'ai mis ici une version avec sed qui me paraît plus lisible. Le but étant de remplacer l'adresse IP par une nouvelle, et de corriger les noms. Le reste de la configuration ne change pas. On peut noter qu'en remplaçant les noms dans le fichier de config XEN, j'ai également modifié les disques utilisés. Il peut être bon de vérifier que les noms des partitions LV dans ce fichier sont corrects.
Il ne reste plus qu'à lancer la VM:
root@groska:~# xl create /etc/xen/spofu.cfg
Notez que dans le cas exact de la création de spofu, j'ai également diminué la taille de la mémoire allouée à la VM, pour des raisons de mémoire disponible sur groska.
Pour une mise à jour de spofu à partir de liria, ou une réinitialisation, il n'est pas besoin de tout refaire. Seules la copie et la modification de la partition sont nécessaires.
Ainsi, pas besoin de toucher au fichier spofu.cfg ou de re-créer des LV.
Alternative : copier le clone sur un autre serveur
En cours de test. Copier une VM est très long, ce n'est pas forcément la façon la plus rapide de procéder, mais parfois, c'est utile.
Une fois le snapshot créé, le copier (= en faire un clone) pour pouvoir relancer la VM de base rapidement.
Dans l'exemple ici, on va cloner liria pour en faire spofu, et envoyer spofu sur un autre serveur.
On commence par éteindre liria, faire son snapshot, puis copier ce dernier (sur le même disque dur) avant de relancer liria. Copiez avec dd
avant de relancer liria, sinon le snapshot va enregistrer les modifications et c'est le bazar. Copiez tout le volume ; même si, techniquement, un snapshot plus petit (avec uniquement les données écrites) devrait aussi marcher, nos tests n'ont pas été concluants. Pensez bien à créer le volume logique sur le serveur de destination avant de commencer le transfert, sinon il peut y avoir des erreurs pour “manque de place” (même s'il a y a la place).
Sur le serveur de destination (nuxru), on prépare l'arrivée :
screen -DR lvcreate -L 50G -n spofu-disk groska lvcreate -L 4G -n spofu-swap groska mkswap /dev/nuxru/spofu-swap
Sur le serveur d'origine (groska) :
screen -DR xl shutdown lirria lvcreate -s -L 50G -n liria-disk-snap /dev/groska/liria-disk lvcreate -L 50G -n spofu-disk groska dd if=/dev/groska/liria-disk-snap of=/dev/groska/spofu-disk xl create /etc/xen/liria.cfg
Ensuite, on vérifie que nos deux serveurs peuvent communiquer via ssh, on installe pv
si ce n'est pas fait (cela permet de suivre la progression de l'échange).
La commande suivante est à exécuter depuis le serveur primaire vers le serveur secondaire (toujours sous screen ou tmux pour qu'une déconnexion ssh ne casse pas la commande) :
dd if=/dev/groska/spofu-disk bs=4096 | pv | ssh root@192.168.0.20 dd of=/dev/nuxru/spofu-disk bs=4096
Il faut ensuite vérifier que le transfert s'est bien passé et donc comparer le checksum des deux volumes :
md5sum /dev/groska/spofu-disk md5sum /dev/nuxru/spofu-disk
Le swap a été créé plus haut ; il suffit de copier le fichier /etc/xen/liria.cfg
sur le nouveau serveur, sous le nom spofu.cfg
, en adaptant le chemin pour les partitions et, si besoin, le réseau. Lancer ensuite la vm.
xl create -c /etc/xen/spofu.cfg
Autre usage des snapshots : utilisation du merge
Une autre utilisation possible du snapshot est de tester quelque chose et de revenir en arrière si ça se passe mal. Dans ce cas, on va commencer comme à l'étape 1. Après avoir relancée la VM dont on a fait un snapshot, on peut faire les modifications et tester. Si tout va bien, on efface simplement le snapshot, sinon il faut revenir en arrière.
On arrête donc la VM, puis on merge le snapshot, afin d'appliquer à l'envers toutes les modifications effectuées. Cette étape peut être un peu longue, en tout cas plus que la création ou la suppression du snapshot.
root@groska:~# lvconvert --merge /dev/groska/liria-disk-snap
Le snapshot, devenu inutile, est détruit dans l'opération.
Problèmes divers
LVS liste des disques qui ont disparus
Cas typique : vous voulez lancer une VM avec Xen et la réponse ressemble à ça :
# xl create /etc/xen/etherpad2.cfg Parsing config from /etc/xen/etherpad2.cfg libxl: error: libxl_device.c:381:libxl__device_disk_set_backend: Disk vdev=xvda2 failed to stat: /dev/nuxru/etherpad2-disk: No such file or directory libxl: error: libxl_create.c:946:initiate_domain_create: Unable to set disk defaults for disk 0 libxl: error: libxl.c:1575:libxl__destroy_domid: non-existant domain 2 libxl: error: libxl.c:1534:domain_destroy_callback: unable to destroy guest with domid 2 libxl: error: libxl.c:1463:domain_destroy_cb: destruction of domain 2 failed
La commande lvs
liste pourtant bien ceci :
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert etherpad2-disk nuxru owi-aos--- 25.00g etherpad2-swap nuxru -wi-a----- 1.00g etherpad2_snap_2019-05-07 nuxru swi-a-s--- 25.00g etherpad2-disk 79.15 etherpad2_snap_2020-02-20 nuxru swi-a-s--- 25.00g etherpad2-disk 0.00
(Ici notre groupe de volumes logique s'appelle nuxru, et la VM “etherpad” ne répond plus).
Pourtant, un ls
sur le groupe logique montre qu'il manque des disques :
# ls -l /dev/nuxru/
total 0
lrwxrwxrwx 1 root root 7 Feb 20 11:19 etherpad2-swap -> ../dm-9
Il y a encore le swap… mais pas le disque ou les snapshots.
Ici, la commande dmsetup ls
est notre alliée :
# dmsetup ls nuxru-etherpad2_snap_2020--02--20-cow (254:14) nuxru-etherpad2--disk (254:11) nuxru-etherpad2_snap_2020--02--20 (254:15) nuxru-etherpad2_snap_2019--05--07 (254:13) nuxru-etherpad2_snap_2019--05--07-cow (254:12) nuxru-etherpad2--disk-real (254:10) nuxru-etherpad2--swap (254:9)
dmsetup ls
va lister des volumes utilisés et à quoi ils correspondent. On trouve aussi ces volumes quand on fait ls /dev/
, tout ce qui commence par “dm-” : ce sont nos volumes utilisés par LVM.
Le deuxième chiffre entre parenthèse correspond à celui du “dm” qu'on cherche. Par exemple, ici, on cherche où est passé la partie “disk” : c'est nuxru-etherpad2–disk (254:11) ce qui correspond à /dev/dm-11
En cas de doute, on peut monter temporairement le disque en question :
mkdir /media/test
mount /dev/dm-11 /media/test
ls /media/test/home/etherpad
umount /media/test
Il reste à refaire le lien symbolique (reprenez bien le terme listé dans lvs) :
cd /dev/nuxru/
ln -s ../dm-11 etherpad2-disk
Il faut aussi remettre les snapshots en place, qui ont sauté aussi à cette occasion. Ici, il y a une subtilité, car nous avons deux dm qui peuvent correspondre pour la même date (attention c'est dans le désordre quand tout est listé) :
nuxru-etherpad2_snap_2020--02--20-cow (254:14) nuxru-etherpad2_snap_2020--02--20 (254:15) nuxru-etherpad2_snap_2019--05--07 (254:13) nuxru-etherpad2_snap_2019--05--07-cow (254:12)
Il ne faut pas faire un lien vers les volumes se terminant en -cow
, mais sur les autres (et toujours faire attention à la façon dont c'est noté !).
ln -s ../dm-15 etherpad2_snap_2020-02-20 ln -s ../dm-13 etherpad2_snap_2019-05-07
Après ça, la VM peut être relancée.
Attention, si le lien vers un volume logique a sauté, ce ne sera probablement pas le seul. Vérifier la concordance entre tous les volumes listés dans lvs
et ceux réellement liés dans ls -l /dev/nuxru
.
Si jamais vous avez des disques listés comme “real”, comme dans l'exemple ci-dessous, liez vers le dm sans ce “real” :
# dmsetup ls nuxru-kuckla--disk (254:4) nuxru-kuckla--disk-real (254:3) nuxru-kuckla--swap (254:2)
#ls -l total 0 lrwxrwxrwx 1 root root 7 Feb 20 11:19 kuckla-disk -> ../dm-4 lrwxrwxrwx 1 root root 7 Feb 20 11:19 kuckla-swap -> ../dm-2
Donc, s'il y avait besoin, ce serait ln -s ../dm-4 kuckla-disk
(et on oublie le dm-3).
Impossible de refaire un snapshot
Après un merge, et malgré un reboot, il y a parfois un souci, et l'erreur suivante apparait lorsqu'on tente de refaire un snapshot du volume :
Snapshots of an origin that has a merging snapshot are not supported.
lvs
monntre un pourcentage de “data” sur le volume qu'on tente de faire en snapshot, alors que ce n'est pas un snaphot.
Cela viendrait d'une incohérence dans le potage. Pour corriger ça, une petite mise à jour des données de LVM via
lvchange --refresh <<VG_NAME>>
Cette fois lvs
va montrer les volumes correctement, et le snapshot est possible.
Sources et liens
- LVM sur le wiki Ubuntu, français
- LVM sur le wiki archlinux, anglais
- Manpage de LVM (uniquement en anglais)
- Guide pratique de LVM, français