LXC (Linux Container) est un outil de virtualisation léger. Il permet de faire s'exécuter une distribution complète avec ses services et ses applications sur notre serveur, de façon isolée et sans ajout au système hôte susceptible d'en perturber le fonctionnement.
Dans le cadre du projet , on utilise cette technologie pour virtualiser un maximum de services: sauvegardes, bases de données, services web, vidéo, etc…
Vous pouvez bien sûr l'utiliser dans un autre contexte, moyennant sans doute quelques adaptations.
Pour toutes les manipulations à suivre, on se positionne en root
via:
$ sudo -i [sudo] Mot de passe de <moââ> : #
Le prompt en #
vous indique que vous avez des droits d'administrateur.
La commande d'installation est la suivante:
# apt-get install lxc debootstrap libpam-cgfs python3-lxc dnsmasq-base bridge-utils lxc-dev
avec:
lxc
, debootstrap
: briques de baselibpam-cgfs
: pour les container «unprivileged»python3-lxc
: pour ce fabriquer des petits outils en Pythondnsmasq-base
, bridge-utils
: pour les aspects réseau des containerslxc-dev
: on pourrait en avoir besoin, en particulier avec l'utilisation d'ansibleCe point est important, en particulier lorsque l'OS du système est défini sur un espace réduit ou fragile (OS sur une clé USB par exemple, qui cumule: réduit et fragile).
En effet, LXC travaille par défaut dans des répertoires dans /var
, à la racine du système.
Dans ce contexte (/var
sur clé système), il paraît nécessaire de modifier les emplacements utilisés et les faire pointer vers un disque dur.
Si vous n'êtes pas concernés (assez d'espace sur votre HDD système par exemple), vous pouvez ignorer les propositions ci-dessous.
Les dossiers utilisés par LXC en standard sont les suivants:
/var/lib/lxc
: emplacement par défaut pour les containers/var/lib/lxcsnap
: emplacement par défaut pour les snapshots/var/cache/cache/lxc
: emplacement par défaut du cache des images de containersPour les containers «non privilégiés» (i.e. associés à un utilisateur):
$HOME/.local/share/lxc
: emplacement par défaut pour les containers non privilégiés$HOME/.local/share/lxcsnap
: emplacement par défaut pour les snapshots non privilégiés$HOME/.cache/lxc
: emplacement par défaut du cache pour les containers non privilégiés
☛ Le chemin par défaut des containers, aussi appelé lxcpath
, peut être remplacé sur la ligne de commande avec l'option -P
, ou bien une fois pour toutes en définissant lxc.lxcpath = /new/path
dans le fichier /etc/lxc/lxc.conf
(ou $HOME/.config/lxc/lxc.conf
pour les containers non privilégiés).
☛ Le répertoire snapshot est toujours snap
ajouté à lxcpath
(il suit donc toujourslxcpath
).
☛ Le cache des images est malheureusement codé en dur et ne peut pas être facilement déplacé sans dépendre de bind-mounts ou de liens symboliques.
☛ La configuration par défaut utilisée pour tous les containers au moment de la création est tirée de
/etc/lxc/default.conf
($HOME/.config/lxc/default.conf
pour les containers non privilégié).
☛ Les modèles ou templates – des scripts appelés lors de la création des containers – sont stockés dans /usr/share/lxc/templates
.
Ainsi, par configuration quand on peut, ou en modifiant du code dans le cas contraire, on va faire pointer ces dossiers par défaut dans une zone du disque dur qu'on a réservée à la virtualisation: en conséquence, ce tutoriel Gestion d'un disque avec LVM est un préalable ici.
Le tutoriel cité au-dessus nous a permis de définir un point de montage /mnt/env-lxc
, avec un Volume Logique LVM sous-jacent sur notre disque dédié /dev/sda
de virtualisation.
Nous allons donc établir les «correspondances» ci-après, et décrire ensuite leur mise en œuvre:
Configuration des chemins | ||
---|---|---|
Containers «privilégié» ⇒ Fichier de config system: /etc/lxc/lxc.conf ⇒ Ficher de config container (par défaut): /etc/lxc/default.conf |
||
Chemin d'origine | Chemin cible | Modalité de configuration |
/var/lib/lxc | /mnt/env-lxc/lxc | via /etc/lxc/lxc.conf |
/var/lib/lxcsnap | /mnt/env-lxc/lxcsnap | Implicite |
/var/cache/lxc | /mnt/env-lxc/cache | Changer les scripts template ou lien symbolique ![]() |
Containers «non privilégié» ⇒ Fichier de config system: ~/.config/lxc/lxc.conf ⇒ Ficher de config container (par défaut): ~/.config/lxc/default.conf |
||
Chemin d'origine | Chemin cible | Modalité de configuration |
~/.local/share/lxc | /mnt/raid_data/users/<user>/.local/share/lxc | Définition d'un compte <user> et son $HOME. Ouvrir éventuellement la possibilité pour les utilisateurs de créer des CT (comptes utilisateurs sur le RAID) ![]() |
~/.local/share/lxcsnap | /mnt/raid_data/users/<user>/.local/share/lxcsnap | Implicite |
~/.cache/lxc | /mnt/raid_data/users/<user>/.cache/lxc | Définition d'un compte <user> et son $HOME. |
/etc/lxc/lxc.conf
. # SI NON LVM : Chemin par défaut des containers "privilégiés" lxc.lxcpath = /mnt/env-lxc/lxc # SI LVM: Virtual Group (VG) par défaut des containers "privilégiés" lxc.bdev.lvm.vg = VGVirtu
# rm /var/cache/lxc # ln -s /mnt/env-lxc/cache/ /var/cache/lxc ## Vous assurer que c'est bon: lien symbolique # ls -als /var/cache/lxc 0 lrwxrwxrwx 1 root root 19 oct. 24 23:59 /var/cache/lxc -> /mnt/env-lxc/cache/
admin
qu'on a déjà défini (mais n'importe quel compte utilisateur suffit). Le répertoire $HOME est localisé sur l'espace RAID dans /mnt/raid_data/users/admin
.
Ceci implique que les containers «non privilégiés» qui seront créés sous le compte admin
vont se retrouver dans l'espace RAID. Mais uniquement s'ils sont créés en mode DIR
.
C'est pourquoi il est plus intéressant de créer systématiquement les containers en mode LVM
(on verra comment plus tard), pour une certaine … cohérence d'ensemble.
On se logue en
admin
et on passe donc les commandes suivantes pour définir tout ça:
$ mkdir -p ~/.local/share/lxc ~/.cache/lxc ~/.config/lxc
$ cp /etc/lxc/lxc.conf ~/.config/lxc/lxc.conf
On édite le fichier et on le modifie en supprimant lxcpath: les containers en DIR iront par défaut sur le RAID dans /mnt/raid_data/users/admin/.local/share/lxc
, ceux en LVM iront dans un LV sur le disque dédié à la virtualisation:
$ nano ~/.config/lxc/lxc.conf # SI LVM: Virtual Group (VG) par défaut des containers "non privilégiés" lxc.bdev.lvm.vg = VGVirtu
admin
le propriétaire: on l'adaptera toute à l'heure aux CT «non privilégiés»… $ cp /etc/lxc/default.conf ~/.config/lxc/default.conf $ sudo chown admin:admin ~/.config/lxc/default.conf
Il n'est pas inutile de rappeler l'illustration suivante (issue du vieux tuto VHS):
Schématiquement, les containers LXC constituent entre-eux un réseau isolé de «machines» qui peuvent dialoguer sur leur propre réseau et avec l'extérieur de ce réseau.
Ce réseau peut être vu comme un «LAN LXC» avec les concept associés:
Ces éléments se configurent…
Ce Lien (un peu daté mais toujours d'actualité) expose les possibilités de «raccordement» réseau des containers LXC.
Parmi les options qu'il présente, on choisit ici l'option «veth».
Présentons le schéma ci-dessous, qu'on «explique» rapidement ensuite:
En vocabulaire de tous les jours, un pont est un passage entre deux rives; en matière d'informatique, un bridge est un lien entre deux interfaces réseau. …pfff
Sur ce schéma:
eth0
sont les interfaces réseau des containers LXCveth–
sont des interfaces virtuelles, «appairées» avec les eth0
dnsmasq
est l'outil qu'on a installé, qui est un serveur à faible empreinte mémoire faisant DNS, TFTP, PXE, annonces de routeurs et DHCP.lxcbr0
et br0
sont des bridges qui permettent de faire le lien entre les interfaces, virtuelles des containers…ens—
qui constitue l'interface réseau physique de la machine hôte.
Le bridge lxcbr0
permet aux containers de «sortir» sur le réseau local (et par suite sur internet). Il est isolé en ce sens que:
dnsmasq
(en 10.0.3.x ici)iptables
et les «NATage» de ces ports (consiste à autoriser les flux entrants depuis tel port sur l'hôte à destination de tel port d'un container identifié par son adresse IP).
On ajoute br0
: on veut s'accorder la possibilité de présenter nos containers comme des machines à part entière sur notre réseau local, de telle manière qu'ils obtiennent leur adresse IP depuis la box / le routeur de ce réseau, et qu'ils soient vus et accessibles sur ce réseau. C'est l'objet du bridge br0
qui permet le lien entre les interfaces réseau des container et l'interface réseau de l'hôte et qui permet de «court-circuiter» dnsmasq
et de se raccorder directement à la box/routeur.
dnsmasq est un outil (qu'on a installé ci-dessus) léger qui fait fonction à la fois de serveur d'adresses DHCP et de serveur de noms DNS.
Sa configuration, dans le cadre de LXC est définie dans le fichier /etc/default/lxc-net
. Dans la livraison Debian de LXC, ce fichier est vide. Dans celle de Ubuntu, tout est «pré-rempli». On va donc se fabriquer le notre sur cette base :
# Laissez USE_LXC_BRIDGE à "true" si vous voulez utiliser lxcbr0 pour vos containers LXC # Définissez sur "false" si vous utiliserez virbr0 ou un autre logiciel existant bridge, # ou Mavlan, sur l'interface réseau de votre hôte. USE_LXC_BRIDGE="true" # Si vous changez le LXC_BRIDGE pour autre chose que lxcbr0, alors # vous devrez également mettre à jour votre fichier /etc/lxc/default.conf ainsi # que le fichier de configuration (/var/lib/lxc/<container>/config) pour tous # les containers déjà créés en utilisant la configuration par défaut pour refléter # le nouveau nom de la passerelle. # Les paramètre ci-dessous sont les valeurs par défaut utilisées par dnsmaq. # Décommentez-les et valorisez-les autrement si vous souhaitez les changer #LXC_BRIDGE="lxcbr0" #LXC_ADDR="10.0.3.1" #LXC_NETMASK="255.255.255.0" #LXC_NETWORK="10.0.3.0/24" #LXC_DHCP_RANGE="10.0.3.2,10.0.3.254" #LXC_DHCP_MAX="253" # Dé-commentez la ligne suivante si vous voulez utiliser un fichier de configuration # du dnsmasq pour lxcbr0 # Par exemple, vous pouvez utiliser 'dhcp-host=mail1,10.0.3.100' pour avoir # le container 'mail1' qui obtient toujours l'adresse IP 10.0.3.100. LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf # Dé-commentez la ligne suivante si vous voulez que le dnsmasq de lxcbr0 résolve le # domaine en ".lxc". Vous pouvez alors ajouter 'server=/lxc/10.0.3.1' à /etc/dnsmasq.conf # après quoi'container1.lxc' sera résolu sur votre host. LXC_DOMAIN="lxc"
Et donc en complément, on définit le fichier «DNS / DHCP» /etc/lxc/dnsmasq.conf
(référencé dans le fichier ci-dessus) avec:
server=/lxc/10.0.3.1 # ===> N'ajoutez pas nécessairement les lignes ci-dessous: on pourra le faire au fur et à mesure des besoins # Fixer toujours la même adresse à un container en fonction de son nom # cid 1 -> 49: containers term dhcp-host=lxc-term01,10.0.3.11 dhcp-host=lxc-term02,10.0.3.12 dhcp-host=lxc-term03,10.0.3.13 # cid 50 -> 99: containers web dhcp-host=lxc-proxy,10.0.3.50 dhcp-host=lxc-web01,10.0.3.51 dhcp-host=lxc-web02,10.0.3.52 dhcp-host=lxc-web03,10.0.3.53 # cid 100 -> 149; containers gui dhcp-host=lxc-gui01,10.0.3.101 dhcp-host=lxc-gui02,10.0.3.102 dhcp-host=lxc-gui03,10.0.3.103 # cid 150 -> 199; containers divers dhcp-host=lxc-guac,10.0.3.151 dhcp-host=lxc-gitlab,10.0.3.152 dhcp-host=lxc-docker,10.0.3.153 dhcp-host=lxc-kodi, 10.0.3.154
Pour prendre en compte les changements, il s'agit de redémarrer le service réseau de LXC:
# systemctl restart lxc-net.service
Il s'agit de définir le pont br0
sur l'hôte. Pour ce faire, on modifie le fichier de configuration des interfaces réseau /etc/network/interfaces
comme suit:
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The primary network interface # Modif <machin> - 2019.09.14 == Configurer l'hôte comme bridge #allow-hotplug enp3s0 #iface enp3s0 inet dhcp auto br0 iface br0 inet dhcp bridge_ports enp3s0 bridge_fd 0 bridge_maxwait 0
Il est possible que l'interface physique «native» ne soit pas enp3s0
comme ici sur votre machine: il faudra adapter. La ligne iface enp3s0 inet dhcp
qu'il faudra commenter doit être la bonne, identifiée à l'installation.
La commande suivante liste les interfaces réseau disponibles; elle peut vous aider à trouver le bon nom, en considérant les VHS avec deux cartes réseaux… :
ls /sys/class/net/
Passer la commande suivante pour prise en compte du changement:
# systemctl restart networking.service
Les containers peuvent s'adresser les uns aux autres par leur nom: lorsque dhclient
à l'intérieur d'un container demande une adresse IP, il inclut également son nom d'hôte dans la requête. dnsmasq
, agissant en tant que serveur DHCP et DNS simultanément, affecte une adresse IP au container et ajoute également une entrée à sa table DNS. Ainsi, chaque container est capable de résoudre l'adresse IP de tous les autres container de manière transparente via DNS.
L'hôte, par contre, n'est pas capable par défaut de résoudre les adresses IP des containers. Pour régler ce problème, nous devons utiliser le démon dnsmasq
local comme serveur DNS primaire sur l'hôte.
Ajoutez la ligne suivante au fichier /etc/dhcp/dhclient.conf
de l'hôte :
prepend domain-name-servers 10.0.3.1 ;
et redémarrez le service réseau:
# systemctl restart networking.service
Vour pourrez alors constater que le serveur dnsmasq
apparaît dans la liste des serveurs DNS sur l'hôte:
$ cat /etc/resolv.conf domain local search local nameserver 10.0.3.1 nameserver 192.168.1.1
Maintenant quand une application sur l'hôte appelle une machine par son nom, la requête DNS est d'abord envoyée au démon dnsmasq
local. Si la requête est le nom d'un des containers, alors dnsmasq
répondra avec son adresse IP par lui-même en utilisant sa table DNS locale. Pour tous les autres noms d'hôtes, il agit comme proxy DNS et envoie les requêtes au serveur DNS amont spécifié dans /etc/resolv.conf. Et il est assez «intelligent» pour ne pas envoyer des demandes récursivement à lui-même…
De cette façon, et depuis la console de l'hôte, les commandes suivantes ne vous «enverront pas balader»:
$ ping -c 4 lxc-proxy $ ssh toto@lxc-term01.lxc
On va mettre en place ici les éléments de configuration, dont hériteront dès leur création l'ensemble des containers LXC.
Le fichier concerné est /etc/lxc/default.conf
pour les containers privilégiés, dont le contenu lxc.network.type = empty
est remplacer par:
lxc.net.0.type = veth lxc.net.0.link = lxcbr0 #lxc.net.0.link = br0 lxc.net.0.flags = up lxc.net.0.hwaddr = 00:16:3e:xx:xx:xx
Si vos conteneurs LXC doivent contenir des serveurs / services sensibles aux attaques, vous ne voudriez pas qu'un serveur compromis compromette tout le reste du système. Ne pas donner les privilèges super-utilisateur au container permet de limiter ce risque. C'est le but des containers «non privilégiés» … qui sont un peu «velus» à configurer sous Debian.
On va le faire sans trop d'explication – pas sûr de tout comprendre moi-même – mais l'essentiel est que ça fonctionne au bout…
Rappel: On est logé en
admin
$ sudo sh -c 'echo "kernel.unprivileged_userns_clone=1" > /etc/sysctl.d/80-lxc-userns.conf'
Prise en compte sans redémarrer:
$ sudo sysctl --system
admin
à utiliser le bridge dédié LXC lxcbr0
, mais aussi le bridge «direct» br0
, pour 10 CT (en tout, c'est parfaitement arbitraire):$ sudo nano /etc/lxc/lxc-usernet admin veth lxcbr0 5 admin veth br0 5
subuids
et subgids
de notre utilisateur courant (le retour peut-être différent chez vous bien sûr): $ cat /etc/s*id | grep ^$USER admin:231072:65536 admin:231072:65536
~/.config/lxc/default.conf
selon: lxc.net.0.type = veth lxc.net.0.link = lxcbr0 #lxc.net.0.link = br0 lxc.net.0.flags = up lxc.net.0.hwaddr = 00:16:3e:xx:xx:xx # Ajout {g,u}id pour containers "unprivileged" lxc.idmap = u 0 231072 65536 lxc.idmap = g 0 231072 65536
.local
et .local/share
: Permission refusée - Impossible d'accéder à /home/$USER/.local
. Veuillez lui accorder l'accès x, ou ajouter une ACL pour la racine du container.» acl
doit avoir été installé): $ sudo setfacl -m u:231072:x .local .local/share
où 231072
correspond au uid
de votre utilisateur (le même que plus haut)
#lxc.group = onboot #lxc.group = bddserver lxc.start.auto = 1 lxc.start.delay = 5 lxc.start.order = 103
Pour des CT «privilégiés», il n'y a pas de problème particulier: il existe un service dans systemd
appelé lxc-autostart
qui s'occupe de cela. Lorsque systemd
démarre le service LXC, lxc-autostart
est appelé. Mais il est appelé en tant que root
, donc même si vous avez “lxc.start.auto = 1” dans votre configuration, votre container «non privilégié» n'est pas lancé.
La solution consiste à définir un «cron au reboot» associé à l'utilisateur propriétaire: En tant qu'utilisateur propriétaire des containers «non privilégié», lancez:
admin@wasabi $ crontab -e
et ajoutez la ligne suivante :
@reboot lxc-autostart -g "onboot,"
Ainsi, lxc-autostart
sera lancé au démarrage avec l'utilisateur admin
et pourra pointer les CT en démarrage automatique: Par exemple ici, dans l'ordre, ceux qui appartiennent au groupe onboot
, puis ceux qui n'ont pas de groupe défini. Vous pouvez jongler avec les groupes de containers que vous aurez défini.
La configuration est maintenant terminée (le § suivant consiste à vérifier).
C'est sans doute le moment de re-démarrer la machine, histoire de bien prendre en compte tout cela:
$ sudo reboot
Pour vérifier l'ensemble de ces configurations – leur exactitude et leur bonne prise en compte par le système – on propose de réaliser les opérations et les contrôles qui suivent.
L'environnement nécessaire ici est celui de root
.
Si vous n'y êtes pas, positionnez-vous avec des privilèges :
$ sudo -i [sudo] Mot de passe de <moââ> : #
Ce qu'on va faire ici:
ssh
et faire les manipulations nécessaires pour l'atteindre depuis un poste client sur le LANOn y va…
☛ On créé donc en tant que root
(donc «privilégié») un CT nommé lxc-term01
d'après le template debian
qu'on stocke sur l'espace de l'environnement LXC ( par défaut car pas de paramètre '-B':
# lxc-create -n lxc-term01 -t debian
L'outil va chercher ce qui va bien sur internet et construit une image minimale Debian, avec toutes les librairies et paquets utiles. La sortie à l'écran du processus de création est longue et doit ressembler et se terminer comme:
Cliquer pour voir/cacher le résultat
Cliquer pour voir/cacher le résultat
root@wasabi:~# lxc-create -n lxc-term01 -t debian debootstrap est /usr/sbin/debootstrap Checking cache download in /var/cache/lxc/debian/rootfs-stable-amd64 ... Downloading debian minimal ... I: Target architecture can be executed I: Retrieving InRelease I: Checking Release signature I: Valid Release signature (key id 6D33866EDD8FFA41C0143AEDDCC9EFBF77E11517) I: Retrieving Packages I: Validating Packages ... ... I: Validating util-linux 2.33.1-0.1 I: Retrieving liblzma5 5.2.4-1 I: Validating liblzma5 5.2.4-1 I: Retrieving zlib1g 1:1.2.11.dfsg-1 I: Validating zlib1g 1:1.2.11.dfsg-1 I: Chosen extractor for .deb packages: dpkg-deb I: Extracting libacl1... I: Extracting adduser... I: Extracting apt... ... ... I: Extracting util-linux... I: Extracting liblzma5... I: Extracting zlib1g... I: Installing core packages... I: Unpacking required packages... I: Unpacking libacl1:amd64... I: Unpacking adduser... I: Unpacking apt... ... ... I: Unpacking util-linux... I: Unpacking liblzma5:amd64... I: Unpacking zlib1g:amd64... I: Configuring required packages... I: Configuring debian-archive-keyring... I: Configuring libaudit-common... ... ... I: Configuring mount... I: Configuring sysvinit-utils... I: Configuring libc-bin... I: Unpacking the base system... I: Unpacking libdns-export1104... I: Unpacking libisc-export1100:amd64... ... ... I: Unpacking sensible-utils... I: Unpacking libwrap0:amd64... I: Unpacking ucf... I: Configuring the base system... I: Configuring lsb-base... I: Configuring net-tools... ... ... I: Configuring openssh-client... I: Configuring openssh-sftp-server... I: Configuring openssh-server... I: Configuring libc-bin... I: Configuring systemd... I: Base system installed successfully. Download complete. Copying rootfs to /mnt/env-lxc/lxc/lxc-term01/rootfs...Generating locales (this might take a while)... fr_FR.UTF-8... done fr_FR.UTF-8... done Generation complete. update-rc.d: error: cannot find a LSB script for checkroot.sh update-rc.d: error: cannot find a LSB script for umountfs Failed to disable unit, unit hwclock.sh.service does not exist. update-rc.d: error: cannot find a LSB script for hwclockfirst.sh Creating SSH2 RSA key; this may take some time ... 2048 SHA256:vxn3Au37ElGjg9FFV6QwykaNmmbTw6JBAF5r3qcB6HY root@wasabi (RSA) Creating SSH2 ECDSA key; this may take some time ... 256 SHA256:YZnTllCVeMNrrec6S7+7DKkSUcE9E053DFuV2xeeL0s root@wasabi (ECDSA) Creating SSH2 ED25519 key; this may take some time ... 256 SHA256:F2ar5grOHeM90DvRpPifu7No+qJfRVuNaN+agaMCzzA root@wasabi (ED25519) invoke-rc.d: could not determine current runlevel invoke-rc.d: policy-rc.d denied execution of start. Current default time zone: 'Etc/UTC' Local time is now: Tue Oct 29 19:25:30 UTC 2019. Universal Time is now: Tue Oct 29 19:25:30 UTC 2019.
Vous pourrez noter au passage que le serveur ssh est pré-installer dans ce modèle.
☛ On vérifie:
/mnt/env-lxc
lxc
contient la config du container lxc-term01
(que vous pouvez consulter: cat /mnt/env-lxc/lxc/lxc-term01/config), le dossier rootfs
contient l'arborescence d'un système linux root@wasabi:~# tree -L 3 /mnt/env-lxc/ /mnt/env-lxc/ ├── cache │ └── debian │ └── rootfs-stable-amd64 ├── lost+found └── lxc └── lxc-term01 ├── config └── rootfs 7 directories, 1 file
☛ On ajoute … rien car pour notre exemple, le serveur ssh est déjà installé.
# lxc-ls -f NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED lxc-term01 STOPPED 0 - - - false
# lxc-start -n lxc-term01 -d
root@wasabi:~# lxc-ls -f NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED lxc-term01 RUNNING 0 - 10.0.3.11 - false
Notez son adresse IP: elle correspond bien à ce que l'on a configuré dans le serveur DHCP dnsmasq
pour un CT nommé lxc-term01
.
ssh
est déjà installé par défaut dans le modèle Debian qu'on utilise: # lxc-attach -n lxc-term01 root@lxc-term01:~# dpkg-query -l | grep openssh ii openssh-client 1:7.9p1-10 amd64 secure shell (SSH) client, for secure access to remote machines ii openssh-server 1:7.9p1-10 amd64 secure shell (SSH) server, for secure access from remote machines ii openssh-sftp-server 1:7.9p1-10 amd64 secure shell (SSH) sftp server module, for SFTP access from remote machines
ssh
est bien à l'écoute, et on sort du CT: root@lxc-term01:~# apt update && apt upgrade -y
Il se trouve que, au moment de la manipulation, justement ssh
avait besoin d'une mise à jour (c'est un «hasard»).
root@lxc-term01:~# ss -l | grep ssh tcp LISTEN 0 128 0.0.0.0:ssh 0.0.0.0:* tcp LISTEN 0 128 [::]:ssh [::]:*
ssh
il nous faut un compte dans le CT: root@lxc-term01:~# adduser toto Adding user `toto' ... Adding new group `toto' (1000) ... Adding new user `toto' (1000) with group `toto' ... Creating home directory `/home/toto' ... Copying files from `/etc/skel' ... Nouveau mot de passe : Retapez le nouveau mot de passe : passwd: password updated successfully Changing the user information for toto Enter the new value, or press ENTER for the default Full Name []: Room Number []: Work Phone []: Home Phone []: Other []: Is the information correct? [Y/n] y
root@lxc-term01:~# exit exit root@wasabi:~#
On est donc revenu sur l'hôte (gardez en mémoire le mot de passe que vous avez donné à < toto >).
☛ Il s'agit maintenant d’ouvrir un port sur l'hôte qui va nous permettre d'atteindre le serveur ssh
du CT. On utilise pour ce faire les éléments suivants, via la commande iptables
:
Ouvrir & fermer et Voir les @:ports NATés:
Ouvrir: sudo iptables -t nat -A PREROUTING -p tcp -i <interface> --dport <portHost> -j DNAT --to-destination <@IP:Port Destination> Exemple: sudo iptables -t nat -A PREROUTING -p tcp -i br0 --dport 60080 -j DNAT --to-destination 10.0.3.59:80 Fermer: sudo iptables -t nat -D PREROUTING -p tcp -i <interface> --dport <portHost> -j DNAT --to-destination <@IP:Port Destination> Exemple: sudo iptables -t nat -D PREROUTING -p tcp -i br0 --dport 60080 -j DNAT --to-destination 10.0.3.59:80 Liste: sudo iptables -t nat -L sudo iptables -t nat -S
ssh
du CT via le port 10221
de l'hôte: # iptables -t nat -A PREROUTING -p tcp -i br0 --dport 10221 -j DNAT --to-destination 10.0.3.11:22
ssh
(PutTTY sous Windows par exemple): ssh -p 10221 toto@wasabi
Où -p
permet de préciser le port NATé sur la machine serveur qui est ici < wasabi >. Vous devriez pouvoir voir ceci:
cram28@paprika:~$ ssh -p 10221 toto@wasabi The authenticity of host '[wasabi]:10221 ([192.168.1.3]:10221)' can't be established. ECDSA key fingerprint is SHA256:YZnTllCVeMNrrec6S7+7DKkSUcE9E053DFuV2xeeL0s. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '[wasabi]:10221,[192.168.1.3]:10221' (ECDSA) to the list of known hosts. toto@wasabi's password: Linux lxc-term01 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. toto@lxc-term01:~$
Notre test est parfaitement concluant… On peut sortir du container avec
exit
.
☛ … reste à faire le ménage . On va virer tout ça et s'assurer de ce qui reste
# iptables -t nat -D PREROUTING -p tcp -i br0 --dport 10221 -j DNAT --to-destination 10.0.3.11:22
# lxc-stop -n lxc-term01
# lxc-destroy -n lxc-term01
# tree -L 3 /mnt/env-lxc/ /mnt/env-lxc/ ├── cache │ └── debian │ └── rootfs-stable-amd64 ├── lost+found └── lxc 5 directories, 0 files
Le cache est maintenu, le reste a bien disparu.
Ce qu'on va faire ici est quasiment le même chose, SAUF QUE:
br0
pour une connexion directement au réseau local et on va le définir dans un volume logique LVM avec un modèle Ubuntu.Ci-dessous les étapes:
lxc-gitlab
dans un volume logique LVM de même nom, sur un modèle Ubuntu. On notera que l'installation vous posera sans doute des questions, et que … Ubuntu est bien «une grosse vache» # lxc-create -n lxc-gitlab -t ubuntu -B lvm --lvname lxc-gitlab
Notez bien en fin d'installation:
## # The default user is 'ubuntu' with password 'ubuntu'! # Use the 'sudo' command to run tasks as root in the container. ##
rootfs
vide (car est sensé être dans LVM): # tree -L 3 /mnt/env-lxc/ /mnt/env-lxc/ ├── cache │ ├── debian │ │ └── rootfs-stable-amd64 │ └── xenial │ └── rootfs-amd64 ├── lost+found └── lxc └── lxc-gitlab ├── config └── rootfs 9 directories, 1 file
On note que le cache est enrichi avec Ubuntu Xenial
.
# lsblk -o name,model,type,size,fstype,state,mountpoint /dev/sda NAME MODEL TYPE SIZE FSTYPE STATE MOUNTPOINT sda Maxtor_6V250F0 disk 233,8G running └─sda1 part 233,8G LVM2_member ├─VGVirtu-env--lxc lvm 10G ext4 running /mnt/env-lxc └─VGVirtu-lxc--gitlab lvm 1G ext4 running
# lxc-ls -f NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED lxc-gitlab STOPPED 0 - - - false
br0
au lieu de lxcbr0
en inversant les lignes commentées dans le fichier de configuration du CT: # nano /mnt/env-lxc/lxc/lxc-gitlab/config ... # Network configuration lxc.net.0.type = veth #lxc.net.0.link = lxcbr0 # <== commenter lxc.net.0.link = br0 # <== dé-commenter lxc.net.0.flags = up lxc.net.0.hwaddr = 00:16:3e:6c:30:9b ...
# lxc-start -n lxc-gitlab -d # lxc-ls -f NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED lxc-gitlab RUNNING 0 - 192.168.1.13 - false
Notez son adresse IP: elle correspond bien à une adresse du LAN (enfin selon votre réseau local) allouée par votre routeur.
Vous pouvez donc également consulter l'interface de celui-ci, par exemple sur l'interface web d'un routeur Tomato où on retrouve bien «nos petits»: adresses MAC, IP, nom réseau de la machine:
ssh
. On peut donc se connecter directement en ssh
depuis un poste client sur le réseau: cram28@paprika:~$ ssh ubuntu@lxc-gitlab The authenticity of host 'lxc-gitlab (192.168.1.13)' can't be established. ECDSA key fingerprint is SHA256:GJfod5FsTPcwSVNqmTMBfYX1Le6tlHUOtxri1E4Vcoc. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'lxc-gitlab,192.168.1.13' (ECDSA) to the list of known hosts. ubuntu@lxc-gitlab's password: Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.19.0-6-amd64 x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. To run a command as administrator (user "root"), use "sudo <command>". See "man sudo_root" for details. ubuntu@lxc-gitlab:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 16.04.6 LTS Release: 16.04 Codename: xenial ubuntu@lxc-gitlab:~$
# lxc-stop -n lxc-gitlab
# lxc-destroy -n lxc-gitlab
# tree -L 3 /mnt/env-lxc/ /mnt/env-lxc/ ├── cache │ ├── debian │ │ └── rootfs-stable-amd64 │ └── xenial │ └── rootfs-amd64 ├── lost+found └── lxc 7 directories, 0 files
Le cache est maintenu, le reste a bien disparu.
# lsblk -o name,model,type,size,fstype,state,mountpoint /dev/sda NAME MODEL TYPE SIZE FSTYPE STATE MOUNTPOINT sda Maxtor_6V250F0 disk 233,8G running └─sda1 part 233,8G LVM2_member └─VGVirtu-env--lxc lvm 10G ext4 running /mnt/env-lxc
Ça fonctionne…
Mais ATTENTION
: c'est pour «la beauté du geste» car ouvrir sur le net un container privilégié, construit et lancé avec des droits
root
, n'est certainement pas une bonne idée (en tous les cas, pas tout nu comme cela…) !
Les CT «privilégiés» sont manipulés depuis le compte root
, depuis un autre compte via sudo
éventuellement; les CT «non privilégiés» sont associés à un compte banalisé, comme on l'a vu dans leurs éléments de configuration (mapping {g,u}id
notamment).
Donc on se connecte sur le serveur avec le compte admin
qu'on a déjà défini, à partir duquel on travaille:
admin@wasabi:~$
On ne peut pas, depuis ce compte, créer directement un container «non privilégié» en mode LVM: Il faut des droits root
pour créer le Volume Logique associé au CT, droits que notre utilisateur banalisé n'a pas.
Cette option – CT «non privilégié» + LVM – n'est certes pas impossible, mais il faut prévoir des choses avant en root
et ce n'est pas le lieu ici… On va donc se contenter de vérifier les raccordements réseau isolé/exposé, en mode DIR
, c'est à dire avec l'arborescence du CT dans le dossier de l'utilisateur.
Au passage, on va utilisé le modèle download
qui permet d'aller chercher une image sur un serveur internet de la distribution qu'on veut mettre dans notre container (images a priori plus «fraîches»).
Et du coup, on va en profiter pour fignoler notre configuration. En effet, le template download
télécharge l'image choisie dans un répertoire temporaire /tmp
… sur la clé donc… Faut changer cela !
Le modèle de CT lxc-download
utilise le dossier /tmp
pour stocker temporairement des données de construction. Pour éviter cela:
tmp
dans l'environnement de virtualisation LXC: $ sudo mkdir -p /mnt/env-lxc/tmp $ sudo chmod 777 /mnt/env-lxc/tmp
$ sudo sed -i "s|^DOWNLOAD_TEMP=|DOWNLOAD_TEMP=\"/mnt/env-lxc/tmp\"|g" /usr/share/lxc/templates/lxc-download
Dorénavant, les données temporaires, lors de la construction des containers utilisant ce modèle, n'iront plus sur la clé système.
Allez:
$ lxc-create -t download -n lxc-web01 -- -d centos -r 8 -a amd64 Downloading the image index Downloading the rootfs Downloading the metadata The image cache is now ready Unpacking the rootfs --- You just created a Centos 8 x86_64 (20191030_20:33) container.
$ sudo tree -L 3 /mnt/env-lxc/ /mnt/env-lxc/ ├── cache │ ├── debian │ │ └── rootfs-stable-amd64 │ └── xenial │ └── rootfs-amd64 ├── lost+found ├── lxc └── tmp 8 directories, 0 files
$ tree -a -L 5 . ├── .cache │ └── lxc │ └── download │ └── centos │ └── 8 ├── .config │ └── lxc │ ├── default.conf │ └── lxc.conf ├── .local │ └── share │ ├── lxc │ │ └── lxc-web01 │ │ ├── config │ │ └── rootfs .. ..
dnsmasq
lui attribue ( 10.0.3.51
ici pour un CT nommé lxc-web01
): $ lxc-start -n lxc-web01 -d $ lxc-ls -f
On va pas se refaire un CT… On va juste changer la façon dont lxc-web01
se connecte au réseau: passer de «réseau de containers» à «réseau local». Pour ce faire:
$ lxc-stop -n lxc-web01
lxcbr0
(bridge lxc
) et activant br0
(bridge LAN): $ nano .local/share/lxc/lxc-web01/config ... # Network configuration lxc.net.0.type = veth #lxc.net.0.link = lxcbr0 # <== commenter lxc.net.0.link = br0 # <== activer ...
$ lxc-start -n lxc-web01 -d $ lxc-info -n lxc-web01 -i IP: 192.168.1.41
Bon, la config est pas mal… .
Au cours de la mise en œuvre des services dans le cadre de , on aura l'occasion d'utiliser des éléments de configuration, en particulier dans la configuration de tel ou tel container.
Il est important de noter que les modèles et les distributions choisis sont parfois «un peu vides» et qu'on obtient pas directement ce que l'on veut. Par exemple Fedora en release 31 ne contient pas de client DHCP, le container ne sait donc pas obtenir dynamiquement d'adresse réseau…