LXC sur Debian Wheezy
sam. 31 août 2013 by MarmotteLXC, pour Linux Containers, permet de lancer plusieurs environnements Linux sur une même machine, de manière isolée, comme le fait OpenVZ. Par rapport à des machines virtuelles, les performances sont donc bien meilleures, puisque les différents systèmes fonctionnent directement sur le noyau, sans couche de virtualisation intermédiaire. Cela implique aussi qu'on ne peut pas utiliser d'autre système que Linux dans LXC.
Il y a de nombreuses manières de mettre en place des containers LXC. Dans cette note, j'explique comment mettre en place des containers connectés à l'hôte par une interface réseau bridge virtuelle, et installés dans des volumes logiques lvm.
Attention : N'ayant encore jamais configuré de machine en utilisant le protocole IPv6, cette note d'installation se limite pour le moment à IPv4.
Préparation du système hôte¶
Installation¶
Sous Debian, il faut installer les paquets suivants :
$ sudo apt-get install --no-install-recommends lxc bridge-utils debootstrap iptables-persistent
Note : Le paquet
iptables-persistent
permet de charger automatiquement des règles iptables lors du démarrage de la machine. Cela nous servira pour définir les règles de NAT indispensables pour permettre la communication entre les containers et l'extérieur.
Configuration du réseau¶
La configuration du réseau au niveau du système hôte se fait en trois étapes :
- Création des interfaces bridge, sur lesquels les containers se connecteront
- Autorisation du NAT, afin de permettre aux containers de dialoguer avec l'extérieur du serveur
- Configuration d'un serveur DHCP, pour simplifier l'attribution d'adresses IP aux containers
Création des interfaces bridge¶
Pour permettre la création d'interfaces réseau bridge virtuelles, il faut activer le module dummy
du noyau, en précisant le nombre d'interfaces factices voulues.
Il suffit pour ça d'ajouter une ligne dans le fichier /etc/modules
.
dummy numdummies=1
Il faut ensuite ajouter une interface bridge virtuelle, dans le fichier /etc/network/interfaces
.
auto br0
iface br0 inet static
address 10.0.0.254
netmask 255.255.255.0
network 10.0.0.0
broadcast 10.0.0.255
bridge_ports dummy0
bridge_fd 0
bridge_maxwait 0
Note : S'il doit y avoir plusieurs réseaux LXC différents, il faut ajouter une interface bridge par réseau, en adaptant le nom des interfaces (
brX
etdummyX
), et les adresses IP. Il faut aussi augmenter le nombre d'interfaces factices en incrémentant la valeur du paramètrenumdummies
dans le fichier/etc/modules
.Note : Pour modifier le nombre d'interfaces factices à chaud, il est nécessaire de décharger, puis recharger le module dummy. Cette opération n'impacte pas les containers déjà lancés, puisque la présence de l'interface dummy est uniquement nécessaire lors de la création de l'interface bridge associée.
$ sudo rmmod dummy $ sudo modprobe dummy numdummies=2
Une fois le réseau configuré, il faut charger le module dummy
, puis monter la ou les interfaces bridge.
En cas de redémarrage du serveur, ces opérations seront évidemment exécutées automatiquement.
$ sudo modprobe dummy numdummies=1
$ sudo ifup br0
Autorisation du NAT¶
Il ne reste plus qu'à autoriser le NAT, ce qui permettra aux containers de dialoguer avec le reste du réseau.
Pour autoriser le NAT, il faut créer un nouveau fichier dans le répertoire /etc/sysctl.d/
, que je nomme habituellement lxc.conf
, contenant :
net.ipv4.conf.default.rp_filter = 1
net.ipv4.ip_forward = 1
Note : Le nom du fichier n'a pas d'importance, il doit juste se terminer par
.conf
pour être pris en compte.
Il faut ensuite recharger la configuration de sysctl
pour prendre en compte ces modifications à chaud.
$ sudo sysctl --system
Note : Les modifications ajoutées dans le fichier de configuration doivent être affichées dans la console. Si elles n'apparaissent pas, c'est qu'elles n'ont pas été prises en compte. L'erreur la plus courante est l'oubli de l'extension
.conf
dans le nom du fichier.
Il faut ensuite ajouter une règle iptables pour permettre les connexions sortantes des containers, dans le fichier /etc/iptables/rules.v4
.
-A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
Note : L'interface
eth0
est ici l'interface par laquelle sortiront les requêtes des containers vers l'extérieur du serveur.
Pour activer cette règle iptables, il suffit de lancer le script iptables-persistent
.
$ sudo service iptables-persistent start
Attribution des adresses IP aux containers¶
Pour simplifier la gestion des adresses IP des containers, je mets en place Dnsmasq sur le système hôte. Cela me permet de définir les IP des containers dans le fichier de configuration de DNSMasq, ce qui rend leur modification très simple lorsqu'un changement doit être apporté au niveau du réseau. La configuration de Dnsmasq pour LXC contient principalement une plage d'adresses IP par interface bridge, ainsi qu'une attribution d'IP pour chaque container.
interface=br0
domain=server
expand-hosts
dhcp-authoritative
dhcp-leasefile=/tmp/dhcp.leases
dhcp-range=interface:br0,10.0.0.1,10.0.0.200,255.255.255.0,12h
dhcp-host=00:00:00:00:00:01,10.0.0.1,frontend
dhcp-host=00:00:00:00:00:02,10.0.0.2,db
Configuration des cgroups¶
LXC utilise les cgroups pour l'isolation des ressources.
Il faut donc monter le système de fichiers spécifique cgroup, en ajoutant une ligne dans le fichier /etc/fstab
.
cgroup /sys/fs/cgroup cgroup defaults 0 0
On monte ensuite ce point de montage pour une prise en compte à chaud :
$ sudo mount /sys/fs/cgroup
Récupération du script de création de container¶
Le script de création de container distribué avec LXC sous Debian Wheezy est bugué, et crée des containers non fonctionnels.
Je me suis donc basé sur le script proposé par défaut par le projet LXC, auquel j'ai apporté quelques modifications.
Pour qu'il soit utilisable, il faut le déposer dans le répertoire /usr/share/lxc/templates/
, le nommer lxc-<template-name>
et le rendre exécutable.
Création d'un groupe de volumes lvm¶
Si on ne précise pas de nom, LXC utilise le groupe nommé lxc
par défaut.
Si vous créez un groupe de volumes spécifiquement pour LXC, il est donc préférable de lui donner ce nom.
Création d'un container¶
Le script de création de containers peut prendre un fichier de configuration en paramètre. Le contenu de ce fichier est ajouté au fichier de configuration du container pendant l'installation. Ça permet de prédéfinir une partie de la configuration.
Dans le fichier de configuration de base, je mets habituellement la configuration réseau, qui est absente du fichier de configuration par défaut, puisqu'elle diffère selon la manière de gérer le réseau dans les containers. Dans ce fichier, il faut principalement modifier le nom de l'interface bridge utilisée, et l'adresse matérielle du container.
# Network configuration
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.hwaddr = 00:00:00:00:00:00
Note : Si vous avez oublié d'ajuster les paramètres dans ce fichier avant de créer le container, il est bien sûr possible de modifier le fichier de configuration du container après son installation.
Nous pouvons maintenant lancer la création du container proprement dite.
Attention : Il ne faut pas mettre d'underscore dans le nom du container. Je ne sais pas si c'est le résultat d'un bug, mais quand j'ai essayé, les containers dont le nom contenait un underscore étaient inutilisables.
$ sudo lxc-create -t debian-marmotte -n <container-name> -f <BaseConfigFilePath> -B lvm --fstype ext4 --fssize 5G
Note : La valeur à donner au paramètre
-t
est le nom du template, sans le préfixlxc-
.Note : Si vous n'avez pas de groupe de volumes lvm nommé
lxc
, il faut préciser le nom du groupe de volumes à utiliser avec le paramètre--vgname
.Note : Si vous n'utilisez pas lvm, vous pouvez retirer tous les paramètres à partir de
-B lvm
. Le système sera alors placé directement dans le répertoire/var/lib/lxc/<container-name>/rootfs/
.
Une fois le container créé, vous pouvez vérifier la configuration, qui se trouve dans le fichier /var/lib/lxc/<container-name>/config
, et l'adapter si nécessaire.
Configurations supplémentaires¶
- Pour rediriger un port du serveur vers une machine LXC, ajouter une règle dans le fichier
/etc/iptables/rules.v4
-
Pour que le container soit lancé automatiquement lors du démarrage de la machine, il faut ajouter un lien symbolique vers son fichier de conf dans le répertoire
/etc/lxc/auto/
.$ sudo ln -s /var/lib/lxc/<container-name>/config /etc/lxc/auto/<container-name>.conf
-
Dans le cas de plusieurs réseaux LXC, s'ils ne doivent pas pouvoir se contacter entre eux, il est possible de bloquer les communications avec de simples règles iptables, dans le fichier
/etc/iptables/rules.v4
.-A FORWARD -i br0 -o br1 -j DROP -A FORWARD -i br1 -o br0 -j DROP
Attention : Il faut bien bloquer les paquets dans les deux sens. Bloquer la réponse à une requête n'empêche pas le traitement de cette requête par le serveur qui la recevrait.
Manipulation des containers¶
LXC propose quelques commandes permettant de manipuler les containers.
J'ai présenté la commande lxc-create
dans la partie précédente, qui permet de créer des containers.
Ce paragraphe passe en revue les autres commandes lxc souvent utilisées.
Démarrage¶
$ sudo lxc start <container-name> -d
Note : Le paramètre
-d
démarre le container en mode démon. Sans ce paramètre, le container démarrera dans le shell courant, et il sera lié. La fermeture du shell entraînera donc l'arrêt du container.
Arrêt¶
$ sudo lxc stop <container-name>
Connexion en console¶
$ sudo lxc console <container-name>
Note : La connexion en console sur un container est bien pratique quand ce container ne répond pas sur le réseau.
Problèmes rencontrés¶
Pas de réseau sur un container Debian Squeeze¶
Problème observé sur un container Debian Squeeze créé sur un hôte Debian Wheezy. Un autre serveur ayant déjà des containers Debian Squeeze dont l'hôte a été migré de Squeeze vers Wheezy ne présente pas ce dysfonctionnement. Je n'ai pas encore créé de nouveau container Debian Squeeze depuis la migration de l'hôte pour vérifier si ce problème survient.
Si le réseau ne fonctionne pas dans le container, le script /etc/init.d/networking
est peut être erroné.
Il suffit d'ajouter ces lignes au début du script pour créer le répertoire /dev/shm/network
dans le container, juste après le chargement du fichier /lib/lsb/init-functions
:
# Ensure /dev/shm/network exists
[ -d /dev/shm/network ] || mkdir /dev/shm/network
GNU/screen ne fonctionne pas dans le container¶
Problème observé sur un container Debian Wheezy créé sur un hôte Debian Wheezy. Sur un autre serveur, dont l'hôte et des containers ont été migrés de Squeeze vers Wheezy ne présente pas ce dysfonctionnement. Un nouveau container Debian Wheezy créé depuis la migration de l'hôte présente le même problème.
Si screen se ferme juste après avoir été lancé, c'est certainement que les droits du périphérique /dev/ptmx
sont erronés.
Il suffit de donner accès en lecture et écriture à ce périphérique pour résoudre le problème.
$ sudo chmod a+rw /dev/ptmx
Note : Cette manipulation n'est pas définitive, et doit être refaite après chaque relancement du container.
Note : Ce comportement semble résulter du paramètre
ptmxmode=000
présent dans le fichier/etc/mtab
, mais je n'ai pas encore trouvé comment le modifier. Dans un container Debian Wheezy migré depuis Debian Squeeze, le fichier/etc/mtab
contientptmxmode=666
à la place.