LXC
LXC est l'acronyme de l'anglicisme LinuX Containers, est un système de virtualisation, utilisant l'isolation comme méthode de cloisonnement au niveau du système d'exploitation. Il est utilisé pour faire fonctionner des environnements Linux isolés les uns des autres dans des conteneurs partageant le même noyau. Le conteneur apporte une virtualisation de l'environnement d'exécution (processeur, mémoire vive, réseau, système de fichier…) et non pas de la machine. Pour cette raison, on parle de « conteneur » et non de « machine virtuelle ». Veillez à ne pas confondre LXC et LXD, en effet, LXD est une surcouche logicielle à LXC. LXD est développé par Canonical pour simplifier la manipulation de vos conteneurs.
Installation
Création de notre premier container LXC (root)
Pour créer un container avec pour nom1) container_xenial, pour la distribution2) Ubuntu, sous la release3) Xenial, ayant une architecture4) amd64, nous utiliserons cette commande :
sudo lxc-create -t download -n container_xenial -- -d ubuntu -r xenial -a amd64
(...) Download complete Copy /var/cache/lxc/container_xenial/rootfs-amd64 to /var/lib/lxc/container_xenial/rootfs ... Copying rootfs to /var/lib/lxc/container_xenial/rootfs ... Generating locales (this might take a while)... fr_FR.UTF-8... done Generation complete. Creating SSH2 RSA key; this may take some time ... 2048 SHA256:oZjCPZs+eRqXx2y3WCX3sNR+fnxQypD1887jGnQ0jD8 root@home (RSA) Creating SSH2 DSA key; this may take some time ... 1024 SHA256:fCNCpbXq4Z7KYZ0Xdztu9ti+u4rijgWg/nZ46M0A3HY root@home (DSA) Creating SSH2 ECDSA key; this may take some time ... 256 SHA256:AT1ceBEITRDgga9czOlupGrRUT7T1DKl3PD0k9ZXlyU root@home (ECDSA) Creating SSH2 ED25519 key; this may take some time ... 256 SHA256:BPcu2IHpyQoHIvpjIgzPMgaGDrz1TAaUlUnLrwznGXs root@home (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: Sun Jul 22 09:54:56 UTC 2018. Universal Time is now: Sun Jul 22 09:54:56 UTC 2018. ## # The default user is 'ubuntu' with password 'ubuntu'! # Use the 'sudo' command to run tasks as root in the container. ##
Pour lister notre container fraîchement créé on utilisera :
sudo lxc-ls --fancy
beaver@mysweethome:~$ sudo lxc-ls --fancy NAME STATE AUTOSTART GROUPS IPV4 IPV6 container_xenial STOPPED 0 - 10.0.3.58 - beaver@mysweethome:~$ cat /etc/lxc/default.conf lxc.network.type = veth lxc.network.link = lxcbr0 lxc.network.flags = up lxc.network.hwaddr = 00:16:3e:xx:xx:xx beaver@mysweethome:~$ dpkg -l bridge-utils Souhait=inconnU/Installé/suppRimé/Purgé/H=à garder | État=Non/Installé/fichier-Config/dépaqUeté/échec-conFig/H=semi-installé/W=attend-traitement-déclenchements |/ Err?=(aucune)/besoin Réinstallation (État,Err: majuscule=mauvais) ||/ Nom Version Architecture Description +++-=======================================-========================-========================-=================================================================================== ii bridge-utils 1.5-9ubuntu1 amd64 Utilities for configuring the Linux Ethernet bridge
Pour démarrer notre container portant le nom de container_xenial nous utiliserons :
sudo lxc-start -n container_xenial
On vérifie l'état de notre container :
beaver@mysweethome:~$ sudo lxc-ls --fancy NAME STATE AUTOSTART GROUPS IPV4 IPV6 container_xenial RUNNING 0 - 10.0.3.58 -
Accéder à son container LXC (root)
Méthode SSH (root)
Deux solutions s'offrent maintenant à nous pour accéder à notre container, nous pouvons utiliser la commande lxc-console, ou bien, nous pouvons utiliser la commande ssh :
## # The default user is 'ubuntu' with password 'ubuntu'! # Use the 'sudo' command to run tasks as root in the container. ##
beaver@mysweethome:~$ ssh ubuntu@10.0.3.58 ubuntu@10.0.3.58 password: mot de passe **ubuntu** par défaut. Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-130-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage Last login: Sun Jul 22 12:07:48 2018 ubuntu@container_xenial:~$
Méthode lxc-console (root)
Deux solutions s'offrent maintenant à nous pour accéder à notre container, nous pouvons utiliser la commande ssh, ou bien, nous pouvons utiliser la commande lxc-console :
## # The default user is 'ubuntu' with password 'ubuntu'! # Use the 'sudo' command to run tasks as root in the container. ##
beaver@mysweethome:~$ sudo lxc-console -n container_xenial [sudo] Mot de passe de beaver : Connected to tty 1 Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself container_xenial login : ubuntu Mot de passe : ubuntu par défaut Dernière connexion : dimanche 22 juillet 2018 à 12:20:18 UTC de 10.0.3.1 sur pts/4 Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-130-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage ubuntu@container_xenial:~$
Le chemin absolu de votre container container_xenial se trouve dans :
/var/lib/lxc/container_xenial/rootfs
La configuration de votre container container_xenial se trouve dans :
/var/lib/lxc/container_xenial/config
Et non dans :
/etc/lxc/default.conf
Destruction de votre container LXC (root)
Rien de plus simple, vous devez déjà stopper votre container container_xenial :
sudo lxc-stop -n container_xenial
Et ensuite, nous passons à la destruction :
sudo lxc-destroy -n container_xenial
Configuration de LXC pour une utilisation unprivileged
Pour pouvoir utiliser LXC sans sudo, et donc par conséquent, minimiser le risque qu'un attaquant arrive à avoir accès à votre hôte système à cause de l'utilisation de sudo, nous allons déjà récupérer le subgid ainsi que le subguid de notre utilisateur courant :
grep -h $USER /etc/sub{g,u}id
Retournera :
beaver:100000:65536 beaver:100000:65536
Veillez de garder en tête ces deux lignes, maintenant, nous allons devoir stopper les services lxcfs.service, lxc-net.service, lxc.service :
sudo systemctl stop lxcfs.service lxc-net.service lxc.service
Veuillez maintenant créer dans le dossier caché .config/ un dossier portant le nom lxc :
mkdir -p ~/.config/lxc
Puis nous créons un fichier default.conf :
touch ~/.config/lxc/default.conf
Veuillez maintenant éditer le fichier ~/.config/lxc/default.conf, et y ajouter ces lignes :
lxc.network.type = veth lxc.network.link = lxcbr0 lxc.network.flags = up lxc.network.hwaddr = 00:16:xx:xx:xx:xx ## À modifier par une adresse MAC fictive !. lxc.id_map = u 0 100000 65536 ## À modifier par votre propre subguid !. lxc.id_map = g 0 100000 65536 ## À modifier par votre propre subgid !.
Ou bien dans un terminal :
echo -e 'lxc.network.type = veth\nlxc.network.link = lxcbr0\nlxc.network.flags = up\nlxc.network.hwaddr = 00:16:xx:xx:xx:xx ## À modifier par une adresse MAC fictive !.\nlxc.id_map = u 0 100000 65536 ## À modifier par votre propre subguid !.\nlxc.id_map = g 0 100000 65536 ## À modifier par votre propre subgid !.' | tee --append ~/.config/lxc/default.conf
Maintenant, nous modifions le fichier lxc-usernet dans /etc/lxc, et on y insère ça :
nom_de_votre_utilisateur_hôte veth lxcbr0 10
Ou bien dans un terminal:
echo $USER veth lxcbr0 10 | sudo tee --append /etc/lxc/lxc-usernet
Créons maintenant l'emplacement où on va recevoir nos containers LXC, et attribuons y les bonnes permissions :
mkdir -p ~/.local ~/.local/share
chmod -R a+rx ~/.local
Nous devons maintenant créer un fichier 80-lxc-userns.conf dans /etc/sysctl.d/, pour se faire, dans un terminal :
sudo touch /etc/sysctl.d/80-lxc-userns.conf
Ensuite, nous ajoutons à notre fichier 80-lxc-userns.conf :
kernel.unprivileged_userns_clone=1
Ou bien dans un terminal :
echo 'kernel.unprivileged_userns_clone=1' | sudo tee --append /etc/sysctl.d/80-lxc-userns.conf
Ensuite, vous risquez d'avoir ce type d'erreur au démarrage de votre container :
lxc-start: start.c: print_top_failing_dir: 102 Permission denied - could not access /home/$USER. Please grant it 'x' access, or add an ACL for the container root. lxc-start: sync.c: __sync_wait: 51 invalid sequence number 1. expected 2 lxc-start: start.c: __lxc_start: 1172 failed to spawn 'nom_de_votre_container'
Pour y remédier :
chmod a+x /home/$USER/
Ou :
Dans notre exemple, le subuid est 100000. Veuillez le remplacer par le votre. Pour le récupérer, veuillez saisir :
cat /etc/subuid | grep $USER
Et :
cd $HOME && sudo setfacl -m u:100000:x . .local .local/share
À ce stade, il est préférable de redémarrer votre machine pour être certain, que les modifications apportées soient effectives :
sudo reboot
Création de notre premier container LXC (unprivileged)
Essayons maintenant, après avoir redémarré notre machine, de créer un container unprivileged :
lxc-create -t download -n container_unprivileged -- -d ubuntu -r xenial -a amd64
Retournera :
beaver@mysweethome:~$ lxc-create -t download -n container_unprivileged -- -d ubuntu -r xenial -a amd64 Using image from local cache Unpacking the rootfs --- You just created an Ubuntu xenial amd64 (20180722_07:42) container. To enable SSH, run: apt install openssh-server No default root or user password are set by LXC.
Pour lister notre container récemment créé, veuillez ouvrir un terminal avec pour contenu :
lxc-ls --fancy
beaver@mysweethome:~$ lxc-ls --fancy NAME STATE AUTOSTART GROUPS IPV4 IPV6 container_unprivileged STOPPED 0 - 10.0.3.58 -
Vous noterez qu'il n'y a ni mot de passe attribué, ni rien, impossible donc de se connecter à notre container container_unprivileged ni via la méthode ssh, ni via la méthode lxc-console. Voici un moyen pour attribuer un mot de passe à l'utilisateur ubuntu. Nous allons déjà démarrer notre container fraîchement installé :
lxc-start -n container_unprivileged
Ensuite, nous exécutons cette commande :
lxc-attach -n container_unprivileged
Ensuite :
root@container_unprivileged:/# passwd ubuntu Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully
À ce stade, vous allez pouvoir utiliser la commande passwd ubuntu et ainsi, définir le mot de passe que vous voulez à votre utilisateur ubuntu ! .
Le chemin absolu de votre container container_unprivileged se trouve dans :
/home/$USER/.local/lxc/container_unprivileged/rootfs
Et non plus dans :
/var/lib/lxc/container_name/rootfs
La configuration de votre container container_unprivileged se trouve dans :
/home/$USER/.local/lxc/container_unprivileged/config
Et non plus dans :
/var/lib/lxc/container_name/config
La configuration de votre LXC unprivileged se trouve dans :
/home/$USER/.config/lxc/default.conf
Et non plus dans :
/etc/lxc/default.conf
Accéder à son container LXC (unprivileged)
Méthode lxc-console (unprivileged)
Une solution s'offre maintenant à nous pour accéder à notre container, la commande lxc-console. Nous devons d'abord démarrer notre container :
lxc-start -n container_unprivileged
Puis ensuite :
lxc-console -n container_unprivileged
beaver@mysweethome:~$ lxc-console -n container_unprivileged Connected to tty 1 Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself container_unprivileged login : ubuntu Mot de passe : mot de passe qu on a pu définir toute à l heure. Dernière connexion : dimanche 22 juillet 2018 à 12:20:18 UTC de 10.0.3.1 sur pts/4 Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-130-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage ubuntu@container_unprivileged:~$
sudo lxc-trucmuche
mais juste :
lxc-trucmuche
.
Destruction de votre container LXC (unprivileged)
Rien de plus simple, vous devez déjà stopper votre container container_unprivileged :
lxc-stop -n container_unprivileged
Et ensuite, nous passons à la destruction :
lxc-destroy -n container_unprivileged
Backup de votre container LXC
Création de votre backup via tar
Il est relativement aisé, de backup un container LXC, pour se faire, veuillez ouvrir un terminal.
Ensuite nous devons déjà stopper notre container LXC :
sudo((Container unprivileged ou non ?)) lxc-stop -n nom_de_mon_container
Ensuite, on se déplacera dans le dossier /var/lib/lxc/nom_de_votre_container/ ou bien, si vous êtes sur un container unprivileged, dans: /home/$USER/.local/lxc/nom_de_votre_container/ :
sudo -i && cd /var/lib/lxc/nom_de_votre_container/
Ou bien :
sudo -i && cd /home/$USER/.local/lxc/nom_de_votre_container/
Ensuite, nous utilisons la commande tar avec son option --numeric-owner, qui est ici très importante. Elle va permettre de garder les uid/gid intactes lors de l'extraction. Nous utilisons aussi l'outil gzip et son option -96), qui vous offrira, une compression maximale.
GZIP=-9 tar --numeric-owner -czvf mon_container.tar.gz ./*
Vous voilà maintenant en possession d'un backup de votre container, passons maintenant à sa restauration.
Restauration de votre backup via tar
Pour une utilisation root
Nous allons devoir stopper les services lxcfs.service, lxc-net.service, lxc.service. Pour se faire, veuillez ouvrir un terminal, avec pour contenu :
sudo -i && systemctl stop lxcfs.service lxc-net.service lxc.service
Il vous faudra ensuite créer un dossier portant le nom de votre container.
Pour se faire, veuillez saisir :
mkdir -p /var/lib/lxc/nom_de_votre_container
Nous y attribuons les permissions adéquates :
chmod a+rx /var/lib/lxc/nom_de_votre_container
Ensuite, nous nous déplaçons dans le dossier fraîchement créé :
cd /var/lib/lxc/nom_de_votre_container
Nous passons à l'extraction de notre archive, portant le nom mon_container.tar.gz :
tar --numeric-owner -xzvf mon_container.tar.gz
C'est terminé, il n'y a plus qu'à redémarrer lxcfs.service, lxc-net.service, lxc.service :
systemctl start lxcfs.service lxc-net.service lxc.service && exit
Et démarrer ensuite votre container :
sudo lxc-start -n nom_de_votre_container
Pour une utilisation unprivileged
Nous allons devoir stopper les services lxcfs.service, lxc-net.service, lxc.service. Pour se faire, veuillez ouvrir un terminal, avec pour contenu :
sudo systemctl stop lxcfs.service lxc-net.service lxc.service
Créons maintenant l'emplacement où on va recevoir notre container LXC, et attribuons y les bonnes permissions :
mkdir -p ~/.local/share/lxc/nom_de_votre_container
chmod a+rx ~/.local/share/lxc/nom_de_votre_container
Passons maintenant à l'extraction de notre archive, portant le nom mon_container.tar.gz .
Nous allons déjà nous déplacer dans notre dossier fraîchement créé :
cd ~/.local/share/lxc/nom_de_votre_container
Et ensuite, nous passons à l'extraction de notre archive, portant le nom mon_container.tar.gz :
tar --numeric-owner -xzvf mon_container.tar.gz
C'est terminé, il n'y a plus qu'à redémarrer lxcfs.service, lxc-net.service, lxc.service :
sudo systemctl start lxcfs.service lxc-net.service lxc.service
Et démarrer ensuite votre container :
lxc-start -n nom_de_votre_container
Méthode lxc-snapshot
Il existe un outil dédié à LXC pour backup votre container, il se prénomme lxc-snapshot.
Il faut tout d'abord, éteindre notre container :
sudo((container unprivileged ou non ?)) lxc-stop -n nom_de_mon_container
Ensuite nous utilisons lxc-snapshot :
sudo((container unprivileged ou non ?)) lxc-snapshot -n nom_de_mon_container
beaver@mysweethome:~$ sudo lxc-snapshot -n container_xenial lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3405 Snapshot of directory-backed container requested. lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3406 Making a copy-clone. If you do want snapshots, then lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3407 please create an aufs or overlayfs clone first, snapshot that lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3408 and keep the original container pristine.
Pour connaitre le chemin absolu de votre snapshot, vous utiliserez :
sudo((container unprivileged ou non?)) lxc-snapshot -L -n nom_de_mon_container
beaver@mysweethome:~$ sudo lxc-snapshot -L -n container_xenial snap0 (/var/lib/lxc/container_xenial/snaps) 2018:07:28 10:25:48
Pour restaurer un container depuis votre snapshot vous utiliserez :
sudo((container unprivileged ou non?)) lxc-snapshot -r snapX -n nom_de_mon_container