Outils pour utilisateurs

Outils du site


Panneau latéral

Mycélium

Documentation

Travaux

Membres

Wiki

documentation:technique:lxc

LXC

Introduction

LXC est utilisé sur notre serveur dans le but de séparer les différents services que nous allons proposer. Cette documentation fait suite aux différents ateliers réalisés pour découvrir et se former sur LXC.

LXC signifie Linux Containers, en français, des conteneurs Linux. Plus d'informations peuvent être trouvées sur leur site Internet. Enfin, voici quelques pages de manuel utiles pour comprendre plus en détails ce sur quoi repose LXC et les fonctionnalités du noyau Linux utilisées :

  • kernel namespaces(7)
  • kernel capabilities(7)
  • cgroups(7)

Installation

Sous Debian Stretch, il suffit d'installer le paquet lxc.

apt install lxc

D'autres paquets peuvent être nécessaire en fonction du backend choisi, ce qui correspond en gros au système de fichier qui contiendra les conteneurs, ou à la configuration réseau.

Configuration par défaut

Il est possible de définir une configuration par défaut qui sera incluse dans chaque nouveau conteneur. Cela est particulièrement pratique pour la configuration réseau, souvent la même pour tous. Ce fichier en question est /etc/lxc/default.conf.

Configuration réseau

Il y a plusieurs façon de configurer le réseau au sein des conteneurs.

La plus classique étant de passer par un bridge (ou pont en français) créé sur l'hôte spécifiquement pour les conteneurs. Par cette méthode, on peut également différencier 2 façons de faire :

  • faire de la redirection de ports depuis l'hôte vers les conteneurs (plus communément appelé NAT),

FIXME On n'a pas fait ça. Ça serait bien de regrouper uniquement les procédures réalisées, et de séparer les idées non réalisées.

  • coupler le bridge avec une interface réseau existante.

Elles ont toutes les deux leurs avantages et inconvénients, tout dépend de ce que l'on veut faire.

Bridge avec NAT

Intérêt

Cette méthode a l'avantage de ne pas exposer les conteneurs sur le réseau. Toutes les connexions arrivent d'abord sur l'hôte, qui sera en frontal, et où on aura donc pris le soin de mettre en place un pare-feu. Cela est intéressant quand chaque conteneur a une fonction bien spécifique, ou fournit un service différent.

Afin d'atteindre un conteneur, il faudra ajouter une règle pour rediriger tel port arrivant sur l'hôte vers le port de tel conteneur. Par exemple, si un conteneur est chargé de faire serveur Web, on redirigera les ports 80 et 443 arrivant sur l'hôte vers ce conteneur.

Mise en place

Activation de l'IP forward

Il faut tout d'abord activer l'IP forward sur l'hôte. Ceci permet d'activer la redirection d'une connexion, nécessaire pour la suite. Pour le faire de manière permanente (à noter que ce sera effectif qu'au rechargement de sysctl), on peut le faire avec la commande :

echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/99-local-ip-forward.conf

Celle-ci va créer le fichier 99-local-ip-forward dans le dossier /etc/sysctl.d, une bonne pratique pour étendre les différentes configurations. On peut également l'activer immédiatement (à noter qu'au prochain redémarrage, la valeur par défaut sera réutilisé), avec la commande :

echo '1' > /proc/sys/net/ipv4/ip_forward
Création du pont

Pour créer une nouvelle interface réseau virtuelle, le pont (ou bridge, pour varier), sous Debian, on peut se limiter à créer le fichier /etc/network/interfaces.d/local-bridge-lxc avec le contenu suivant :

auto lxcbr0
iface lxcbr0 inet static
    bridge_ports none
    bridge_fd 0
    bridge_maxwait 0
    address 192.168.100.1
    netmask 255.255.255.0

L'adresse IP de l'interface est définie par address, et caractérisera la plage IP utilisée pour ce réseau. Elle est donc à adapter en fonction des réseaux déjà existants. Il reste plus qu'à activer cette nouvelle interface, en exécutant :

ifup lxcbr0

Exemples de règles iptables NAT

Première règle de NAT pour que nos conteneurs sur le réseau 10.0.3.0/24 puissent se connecter à internet via l'interface eth0 sur l'hôte :

iptables -t nat -A POSTROUTING -s 10.0.3.0/24 -o eth0 -j MASQUERADE

Ensuite on aimerait rediriger les bon ports en fonction du service correspondant. Par exemple, 80 et 443 vers le conteneur qui fait du web en 10.0.3.10 :

iptables -t nat -A PREROUTING -j DNAT -i eth0 -p tcp --dport 80 --to-destination 10.0.3.10:80
iptables -t nat -A PREROUTING -j DNAT -i eth0 -p tcp --dport 443 --to-destination 10.0.3.10:443

Jetons maintenant un oeil à nos règles de NAT:

iptables -t nat -L
TODO

→ règle iptables POSTROUTING

→ configuration par défaut LXC pour cette interface

lxc-net

lxc-net est un script se présentant sous la forme d'un service, qui automatise la configuration réseau comme vu précédemment en offrant en plus du DHCP et un DNS pour les conteneurs, en se basant sur dnsmasq. Il se charge donc de créer l'interface bridge, configurer son adresse, et en plus de configurer dnsmasq afin de faciliter l'adressage et l'accès aux conteneurs. Il n'y a cependant pas énormément de documentation là-dessus, voir par exemple le wiki Debian.

Intérêt

Même si on pourrait être tenté de n'utiliser que lxc-net vu ce que cela semble simplifier, son usage est néanmoins à modérer ! Il faut avoir conscience qu'avec ce script, on délègue un bon nombre de configurations réseaux vitales pour l'accès au conteneur. En d'autres termes, il ne vaut mieux pas que ce script se casse la figure ou que son comportement change du jour au lendemain, sinon on risque de perdre gros ! Pour relativiser ce qu'il semble simplifier, on se rend compte que créer son interface bridge avec une bonne documentation n'est pas si insurmontable. Cette étape est d'ailleurs à réaliser qu'une seule fois, et permets une plus grande maîtrise et souplesse.

Enfin, une fois de plus, il est bon de se questionner sur ce que l'on veut faire avant tout, afin de voir s'il est adapté et nécessaire. Pour une utilisation sur son poste personnel, orientée développement par exemple, ce script apporte un bon nombre d'avantages et de facilités, notamment en ce qui concerne le DHCP et le DNS (création et accès à des conteneur à la volée). Par contre, dans le cas d'un serveur en production, comme à Mycélium, le DHCP est inutile voir dangereux : on préférera donner à chaque conteneur une IP fixe, afin d'être sûr de l'atteindre !

Mise en place

1. Créer un fichier /etc/default/lxc-net, contenant les variables suivantes adaptées à vos envies et besoins :

# Active l'utilisation de lxc-net
USE_LXC_BRIDGE="true"
# Nom de l'interface bridge qui sera créé
LXC_BRIDGE="lxcbr0"
# IP de l'interface bridge
LXC_ADDR="10.0.3.1"
# Masque de sous-réseau de l'interface bridge
LXC_NETMASK="255.255.255.0"
# Adresse du réseau, utilisé pour les règles iptables
LXC_NETWORK="10.0.3.0/24"
# Plage d'IP servies par le DHCP
LXC_DHCP_RANGE="10.0.3.11,10.0.3.254"
# Nombre d'IP au sein de la plage définie ci-dessus
LXC_DHCP_MAX="244"
# Extension de la configuration de dnsmasq
LXC_DHCP_CONFILE=""
# Domaine des conteneurs sur le réseau
LXC_DOMAIN=

Pour information, ce fichier contient tous les paramètres offerts par lxc-net pour personnaliser ses fonctionnalités. Il est en cherché et sourcé s'il existe par /etc/default/lxc.

2. Redémarrer le service lxc-net pour prendre en compte les modifications, ou juste créer l'interface si elle n'existait pas encore :

  systemctl restart lxc-net.service

… et l'activer si besoin, pour les futurs (re)démarrage :

  systemctl enable lxc-net.service

3. On peut désormais vérifier le bon fonctionnement du script et ce qu'il est censé configurer :

  • est-ce que l'interface bridge a bien été créé ?
  ip addr
  • est-ce que le serveur DNS a bien été lancé et écoute sur la bonne interface ?
  ps aux | grep dnsmasq
  netstat -ntlp
  • est-ce que le service s'est bien exécuté ?
  systemctl status lxc-net.service

4. Enfin, il reste à adapter la configuration par défaut des conteneurs (dans /etc/lxc/default.conf) pour s'attacher à cette nouvelle interface bridge, avec au moins :

  lxc.network.type = veth
  lxc.network.link = lxcbr0
  lxc.network.flags = up

Utilisation

Création d'un conteneur

Pour créer un conteneur, cela se fait avec la commande lxc-create. Un man lxc-create vous apportera toutes les informations nécessaires sur l'utilisation des différents paramètres et options.

Si l'on veut créer un conteneur nommé pouet, en Debian Jessie, et en utilisant le backend par défaut :

lxc-create -n pouet -t debian -- -r jessie

Le conteneur est désormais créé, il est stocké par défaut dans le dossier /var/lib/lxc/pouet. On y trouve principalement un dossier rootfs, contenant le système de fichier du conteneur (c'est à ça qu'on se rapproche du chroot), et un fichier config. C'est ce dernier qu'il va faudra modifier pour adapter sa configuration, comme lui définir une adresse IP par exemple. Pour connaître l'ensemble des valeurs possibles, un man lxc.container.conf apportera encore beaucoup d'informations.

Optimisations

Par défaut, le conteneur sera crée avec une interface réseau eth0, configurée en DHCP. Si la configuration réseau est définie de manière statique (dans le fichier de configuration du conteneur par exemple), il est bon de modifier la configuration de eth0 pour éviter qu'il cherche inutilement du DHCP. Pour ce faire, avant de démarrer le conteneur, il faudra modifier le fichier /var/lib/lxc/pouet/rootfs/etc/network/interfaces et remplacer dhcp par manual dans la ligne définissant eth0. On devrait donc avoir au final :

iface eth0 inet manual

Accès à un conteneur

Une fois le conteneur créé, il va falloir le démarrer avec la commande lxc-start. Dans l'exmple du conteneur toto :

lxc-create -n toto

Par défaut, à partir de LXC 2.0, le conteneur se lance en arrière plan. Si ce n'est pas le cas, il faudra passer l'option -d, et au contraire, si vous voulez voir le démarrage au premier-plan, il faudra passer l'option -F (attention, vous allez atterrir sur une console).

L'un des façons rapides de s'attacher à un conteneur, sans avoir besoin de s'identifier, comme une sorte de chroot au final, se fait avec la commande lxc-attach :

lxc-attach -n toto

Attention, vous serez néanmoins dans un environnement restreint. Pour se connecter au conteneur, comme on le ferait pour n'importe quelle machine physique, il y a toujours le SSH, s'il est configuré, ou alors la commande lxc-console :

lxc-console -n toto
documentation/technique/lxc.txt · Dernière modification: 2018/09/09 21:26 par cacatoes