Lxc 2.0 - réseau virtuel et dossier partagé avec l'hôte sur debian

Ou comment «virtualiser» sur un pc qui ne virtualise pas en utilisant les conteneurs LXC.

Mon pc principal possède un serveur LAMP installé dans une machine virtualisée avec KVM assortie d'un partage de dossier avec l'hôte pour faciliter la gestion de certaines données. J'avais dans l'idée de mettre quelque chose de similaire en place sur mon pc secondaire, un vieux Acer avec un Celeron.

:( Problème : il ne supporte pas la virtualisation.

:) Solution : LXC

Il existe différentes sortes de virtualisation, LXC est plus proche d'un chroot avancé que d'une virtualisation complète. Du coup ça marche même avec mon Celeron bas de gamme.

Note : J'utilise ici LXC 2.0 sur Debian. La version précédente, LXC 1.0, n'intégrait pas de réseau prémâché.

Documentation source : https://wiki.debian.org/LXC.

 

Installer LXC

# apt install lxc

 

Activer le réseau

Par défaut lxc-net - qui permet de faciliter la mise en place d'un pont réseau simple  avec DHCP et NAT pour les conteneurs - n'est pas activé sur Debian. Pour activer cette option il faut créer un fichier nommé lxc-net dans /etc/default.

Exemple en utilisant l'éditeur de texte nano dans le terminal :

# nano /etc/default/lxc-net

Dans ce fichier on écrit ceci pour spécifier que l'on veut utiliser le pont réseau de LXC :

USE_LXC_BRIDGE="true"

 

Ensuite il faut éditer le fichier /etc/lxc/default.conf. Il contient ceci :

lxc.network.type = empty

Que l'on remplace par ceci :

lxc.network.type = veth
lxc.network.link = lxcbr0
lxc.network.flags = up
lxc.network.hwaddr = 00:16:3e:xx:xx:xx

Explications rapides :

  • lxc.network.type = veth -> indique que l'on crée une interface virtuelle attachée à un pont.
  • lxc.network.link = lxcbr0 -> indique à quel bridge est attaché l'interface, ici notre pont LXC "prémâché".
  • lxc.network.flags = up -> indique que l'interface s'active au démarrage du conteneur.
  • lxc.network.hwaddr = 00:16:3e:xx:xx:xx -> indique l'adresse MAC donnée à l'interface.

Cela crée un modèle pour tous les nouveaux conteneurs créés qui utiliseront ce réseau par défaut.

Il est nécessaire de démarrer ce réseau tout beau tout neuf :

# service lxc-net start

Et voilà, les conteneurs pourront accéder au réseau en utilisant le pont lxcbr0 créé par le service lxc-net. Par la suite le service lxc-net démarrera automatiquement à chaque démarrage de Debian.

 

Stockage des conteneurs

Par défaut les conteneurs sont stockés dans le répertoire /var/lib/lxc. On peut les laisser là ... ou pas.
Perso je préfère qu'ils soient placés dans mon /home/utilisateur situé sur une partition distincte. Pour cela je fais un lien symbolique depuis /var/lib/lxc vers un autre emplacement qui me convient.

Exemple concret : je crée un répertoire dans mon /home/utilisateur que je nomme Lxc (original n'est-ce pas ...) :

mkdir /home/utilisateur/Lxc

Ensuite je supprime le répertoire /var/lib/lxc :

# rm -r /var/lib/lxc

Puis je crée le lien symbolique qui le remplace :

# ln -s /home/utilisateur/Lxc/ /var/lib/lxc

 

Partage de dossier entre un conteneur et son hôte

Il faut tout d'abord créer le conteneur car c'est dans son fichier de configuration que l'on indique le partage et les chemins hôte-conteneur.

 

Créer un conteneur

Ici je crée un conteneur Debian, version Stretch. -n = le nom que l'on donne au conteneur (ici pouetpouet); -d = la distribution (debian) ; -r = la release (stretch) ; -a = l'architecture (amd64).

# lxc-create -n pouetpouet -t download -- -d debian -r stretch -a amd64

Ps : si on tape la commande sans préciser quelle distribution, release ou architecture on souhaite installer dans le conteneur, il nous est proposé une liste de ce qui est disponible suivi de questions pour indiquer nos choix.

Créer le partage

Il faut éditer le fichier de configuration du conteneur, avec nano dans l'exemple ci-après :

# nano var/lib/lxc/nom_du_conteneur/config

Et y ajouter ceci :

lxc.mount.entry = /chemin/du/dossier/sur/hôte chemin/du/dossier/dans/le/conteneur none rw,bind 0.0

Explications rapides :

  • none = signifie qu'il n'y a pas de partition de disque physique liée au point de montage.
  • rw = read write, autorise la lecture et l'écriture - mettre ro (read only) pour une lecture seule.
  • bind = monte un dossier dans un autre. Le contenu est disponible à 2 endroits différents, sur l'hôte et dans le conteneur dans ce cas-ci.
  • 0.0 = une histoire de dump et fsck à laquelle je n'ai pas véritablement tout compris ... en gros l'utilitaire dump sert à sauvegarder le système de fichier, fsck sert à tester un périphérique avant de le monter. 0 désactive le bazar.

 

Un exemple concret : dans mon conteneur j'ai installé un serveur LAMP puis un Dolibarr de secours qui est la copie de celui que j'utilise au quotidien sur mon pc principal. Cela me permet de pouvoir continuer à travailler en cas de défaillance du premier, par exemple si mon pc ne démarre plus pour un problème logiciel ou matériel, en chargeant simplement la dernière sauvegarde sur le pc de secours.
Pour faciliter le chargement de ma sauvegarde je place le dossier qui contient ces données sur l'hôte puis mets en place le partage avec le conteneur.

Je commence par créer sur l'hôte le dossier qui va accueillir les données auxquelles je veux pouvoir accéder aussi bien depuis le conteneur que depuis l'hôte.
Ici je le nomme Partage et le place dans mon /home/utilisateur :

mkdir /home/utilisateur/Partage

Dans ce dossier je copie mon dossier de sauvegarde de Dolibarr qui s'appelle documents - toutes les données de Dolibarr à sauvegarder sont dans un seul dossier, y compris les exports de la base de donnés, c'est pratique. J'ai donc un chemin sur l'hôte qui est /home/utilisateur/documents

Dans le conteneur, le Dolibarr est déjà installé, il a donc son dossier documents, là où il doit être, dans /var/www/html/dolibarr/documents. Dans le fichier de configuration du conteneur j'écris mon partage comme ceci :

lxc.mount.entry = /home/utilisateur/Partage/documents var/www/html/dolibarr/documents none rw,bind 0.0

 

L'épineuse question des droits

Dans mon exemple ci-dessus, les fichiers partagés entre le conteneur et l'hôte doivent (en principe) appartenir à l'utilisateur www-data (soit le serveur LAMP pour faire court). Sur l'hôte mon utilisateur ne se nomme bien évidemment pas www-data.

Admettons que mon nom d'utilisateur sur l'hôte soit toto.

Dans mon conteneur je crée un nouvel utilisateur du même nom, toto, qui aura également les mêmes uid et guid puisque je n'ai de chaque côté qu'un seul utilisateur créé et que par défaut le premier utilisateur a ses uid et guid = 1000.

# adduser toto

Puis je définis les droits d'accès et d'écriture comme ceci, toujours dans le conteneur :

chown -R www-data:toto /var/www/html/dolibarr/documents
chmod -R 775 /var/www/html/dolibarr/documents

Ainsi www-data sur le conteneur et toto sur l'hôte peuvent tous deux lire et écrire les fichiers dans le dossier partagé.