====== 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 [[http://www.linuxcontainers.org/|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 //[[https://wiki.debian.org/fr/BridgeNetworkConnections|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 [[http://www.thekelleys.org.uk/dnsmasq/doc.html|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 [[https://wiki.debian.org/LXC/SimpleBridge#Using_lxc-net|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