Ceci est une ancienne révision du document !
Table des matières
Version : 2020.01
Dernière mise-à-jour : 2020/08/10 14:44
DOF101 - La Virtualisation par Isolation
Contenu du Module
- DOF101 - La Virtualisation par Isolation
- Contenu du Module
- LAB #1 - Utilisation de l'Infrastructure
- 1.1 - Formations en Face-à-Face Pédagogique (FFP)
- 1.2 - Formations à Distance (FAD)
- Linux, MacOS et Windows 10 muni du client ssh
- Windows 7 et Windows 10 sans client ssh
- Lancement de la Machine Virtuelle Debian_9
- 1.3 - Connexion à la Machine Virtuelle
- Linux, MacOS, Windows 10 muni du client ssh et FAD
- Windows 7 et Windows 10 sans client ssh en FFP
- Présentation de la Virtualisation par Isolation
- Historique
- Présentation des Namespaces
- Présentation des CGroups
- LAB #2 - Travailler avec les CGroups
- 2.1 - Limitation de la Mémoire
- 2.2 - Le Paquet cgroup-tools
- La commande cgcreate
- La Commande cgexec
- La Commande cgdelete
- La Commande cgexec
- Présentation de Linux Containers
- LAB #3 - Travailler avec LXC
- 3.1 - Installation
- 3.2 - Création d'un Conteneur Simple
- 3.3 - Démarrage d'un Conteneur Simple
- 3.4 - S'attacher à un Conteneur Simple
- 3.5 - Commandes LXC de Base
- La Commande lxc-console
- La Commande lxc-stop
- La Commande lxc-execute
- La Commande lxc-info
- La Commande lxc-freeze
- La Commande lxc-unfreeze
- Autres commandes
- 3.6 - Création d'un Conteneur Non-Priviligié
- User Namespaces
- Création d'un Utilisteur Dédié
- Création du Mappage
- Création du Conteneur
- Contrôle du Mappage
- 3.7 - Création d'un Conteneur Ephémère
- La Commande lxc-copy
- 3.8 - Sauvegarde des Conteneurs
- La Commande lxc-snapshot
LAB #1 - Utilisation de l'Infrastructure
1.1 - Formations en Face-à-Face Pédagogique (FFP)
Si vous suivez cette formation en Centre de Formation, vous avez besoin d'importer la machine virtuelle qui vous a été fournie.
Ouvrez VirtualBox et importez la machine virtuelle Debian_9 :
Fichier > Importer un appareil virtuel ...
La machine virtuelle a été configurée ainsi :
Machine | Nom d'hôte | Adresse IP | Redirection de Port |
---|---|---|---|
Debian_9 | debian9 | 10.0.2.15 | 2022 |
Démarrez ensuite la machine virtuelle Debian_9.
1.2 - Formations à Distance (FAD)
Vous disposez d'un serveur dédié, pré-installé, pré-configuré et hébergé dans le cloud.
Connectez-vous en ssh à votre serveur dédié :
Linux, MacOS et Windows 10 muni du client ssh
Ouvrez un terminal ou CMD et tapez la commande suivante :
$ ssh -l desktop serverXX.ittraining.network
où XX représente le numéro de votre serveur dédié. Entrez ensuite le mot de passe qui vous a été fourni.
Windows 7 et Windows 10 sans client ssh
Ouvrez putty et utilisez les informations suivantes pour vous connecter à votre serveur dédié :
- Host Name –> serverXX.ittraining.network
- Port –> 22
Au prompt, connectez-vous en tant que desktop avec le mot de passe qui vous a été fourni.
Lancement de la Machine Virtuelle Debian_9
La machine virtuelle a été configurée ainsi :
Machine | Nom d'hôte | Adresse IP | Redirection de Port |
---|---|---|---|
Debian_9 | debian9 | 10.0.2.15 | 2022 |
Pour lancer la machine Debian_9, utilisez la commande suivante à partir de votre serveur dédié :
desktop@serverXX:~$ VBoxManage startvm Debian_9 --type headless Waiting for VM "Debian_9" to power on... VM "Debian_9" has been successfully started.
1.3 - Connexion à la Machine Virtuelle
Les noms d'utilisateurs et les mots de passe sont :
Utilisateur | Mot de Passe |
---|---|
trainee | trainee |
root | fenestros |
Vous devez vous connecter à la machine virtuelle Debian_9 d'une des deux façons suivantes :
Linux, MacOS, Windows 10 muni du client ssh et FAD
Ouvrez un terminal et tapez la commande suivante pour vous connecter à la machine Debian_9 :
$ ssh -l trainee localhost -p 2022
Windows 7 et Windows 10 sans client ssh en FFP
Ouvrez putty et utilisez les informations suivantes pour vous connecter à Debian_9 :
- Host Name –> localhost
- Port –> 2022
Présentation de la Virtualisation par Isolation
Un isolateur est un logiciel qui permet d'isoler l'exécution des applications dans des containers, des contextes ou des zones d'exécution.
Historique
- 1979 - chroot - l'isolation par changement de racine,
- 2000 - BSD Jails - l'isolation en espace utilisateur,
- 2004 - Solaris Containers - l'isolation par zones,
- 2005 - OpenVZ - l'isolation par partitionnement du noyau sous Linux,
- 2008 - LXC - LinuX Containers - l'isolation en utilisant des namespaces et des CGroups avec liblxc,
- 2013 - Docker - l'isolation en utilisant des namespaces et des CGroups avec libcontainer,
- 2014 - LXD - LinuX Container Daemon - l'isolation en utilisant des namespaces et des CGroups avec liblxc.
Présentation des Namespaces
Les espaces de noms permettent de regrouper des processus dans un même espace et d'attribuer des droits sur des ressources par espace. Ceci permet l'exécution de plusieurs init, chacun dans un namespace, afin de recréer un environnement pour les processus qui doivent être isolés.
Présentation des CGroups
Les Groupes de Contrôles (Control Groups) aussi appelés CGroups, sont une nouvelle façon de contrôler et de limiter des ressources. Les groupes de contrôle permettent l'allocation de ressources, même d'une manière dynamique pendant que le système fonctionne, telles le temps processeur, la mémoire système, la bande réseau, ou une combinaison de ces ressources parmi des groupes de tâches (processus) définis par l'utilisateur et exécutés sur un système.
Les CGroups sont organisés de manière hiérarchique, comme des processus. Par contre, la comparaison entre les deux démontre que tandis que les processus se trouvent dans une arborescence unique descandant tous du processus init et héritant de l'environnement de leurs parents, les CGroups peuvent être multiples donnant lieu à des arborescences ou hiérarchies multiples qui héritent de certains attributs de leurs groupes de contrôle parents.
Ces hiérarchies multiples et séparés sont necéssaires parce que chaque hiérarchie est attaché à un ou plusieurs sous-système(s) aussi appelés des Contrôleurs de Ressources ou simplement des Contrôleurs. Les contrôleurs disponibles sont :
- blkio - utilisé pour établir des limites sur l'accès des entrées/sorties à partir et depuis des périphériques blocs,
- cpu - utilisé pour fournir aux tâches des groupes de contrôle accès au CPU grâce au planificateur,
- cpuacct - utilisé pour produire des rapports automatiques sur les ressources CPU utilisées par les tâches dans un groupe de contrôle,
- cpuset - utilisé pour assigner des CPU individuels sur un système multicoeur et des noeuds de mémoire à des tâches dans un groupe de contrôle,
- devices - utilisé pour autoriser ou pour refuser l'accès des tâches aux périphériques dans un groupe de contrôle,
- freezer - utilisé pour suspendre ou pour réactiver les tâches dans un groupe de contrôle,
- memory - utilisé pour établir les limites d'utilisation de la mémoire par les tâches d'un groupe de contrôle et pour génèrer des rapports automatiques sur les ressources mémoire utilisées par ces tâches,
- net_cls - utilisé pour repérer les paquets réseau avec un identifiant de classe (classid) afin de permettre au contrôleur de trafic Linux, tc, d'identifier les paquets provenant d'une tâche particulière d'un groupe de contrôle.
- perf_event - utilisé pour permettre le monitoring des CGroups avec l'outil perf,
- hugetlb - utilisé pour limiter des ressources sur des pages de mémoire virtuelle de grande taille.
Les hiérarchies ont des points de montage dans le répertoire /sys/fs/cgroup :
trainee@debian9:~$ su - Mot de passe : fenestros root@debian9:~# ls -l /sys/fs/cgroup/ total 0 dr-xr-xr-x 2 root root 0 mai 26 08:52 blkio lrwxrwxrwx 1 root root 11 mai 26 08:52 cpu -> cpu,cpuacct lrwxrwxrwx 1 root root 11 mai 26 08:52 cpuacct -> cpu,cpuacct dr-xr-xr-x 2 root root 0 mai 26 08:52 cpu,cpuacct dr-xr-xr-x 2 root root 0 mai 26 08:52 cpuset dr-xr-xr-x 5 root root 0 mai 26 08:52 devices dr-xr-xr-x 2 root root 0 mai 26 08:52 freezer dr-xr-xr-x 2 root root 0 mai 26 08:52 memory lrwxrwxrwx 1 root root 16 mai 26 08:52 net_cls -> net_cls,net_prio dr-xr-xr-x 2 root root 0 mai 26 08:52 net_cls,net_prio lrwxrwxrwx 1 root root 16 mai 26 08:52 net_prio -> net_cls,net_prio dr-xr-xr-x 2 root root 0 mai 26 08:52 perf_event dr-xr-xr-x 5 root root 0 mai 26 08:52 pids dr-xr-xr-x 5 root root 0 mai 26 08:52 systemd
Systemd organise les processus dans chaque CGroup. Par exemple tous les processus démarrés par le serveur Apache se trouveront dans le même CGroup, y compris les scripts CGI. Ceci implique que la gestion des ressources en utilisant des hiérarchies est couplé avec l'arborescence des unités de Systemd.
En haut de l'arborescence des unités de Systemd se trouve la tranche root - -.slice, dont dépend :
- le system.slice - l'emplacement des services système,
- le user.slice - l'emplacement des sessions des utilisateurs,
- le machine.slice - l'emplacement des machines virtuelles et conteneurs.
En dessous des tranches peuvent se trouver :
- des scopes - des processus crées par fork,
- des services - des processus créés par une Unité.
Les slices peuvent être visualisés avec la commande suivante :
root@debian9:~# systemctl list-units --type=slice UNIT LOAD ACTIVE SUB DESCRIPTION -.slice loaded active active Root Slice system-getty.slice loaded active active system-getty.slice system.slice loaded active active System Slice user-1000.slice loaded active active User Slice of trainee user-112.slice loaded active active User Slice of lightdm user.slice loaded active active User and Session Slice LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 6 loaded units listed. Pass --all to see loaded but inactive units, too. To show all installed unit files use 'systemctl list-unit-files'.
L'arborescence des unités de Systemd est la suivante :
root@debian9:~# systemd-cgls Control group /: -.slice ├─user.slice │ ├─user-112.slice │ │ ├─user@112.service │ │ │ ├─dbus.service │ │ │ │ └─539 /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation │ │ │ ├─init.scope │ │ │ │ ├─527 /lib/systemd/systemd --user │ │ │ │ └─528 (sd-pam) │ │ │ └─gvfs-daemon.service │ │ │ └─547 /usr/lib/gvfs/gvfsd │ │ └─session-c1.scope │ │ ├─524 lightdm --session-child 18 21 │ │ ├─532 /usr/sbin/lightdm-gtk-greeter │ │ ├─534 /usr/lib/at-spi2-core/at-spi-bus-launcher --launch-immediately │ │ ├─541 /usr/bin/dbus-daemon --config-file=/usr/share/defaults/at-spi2/accessibility.conf --nofork --print-address 3 │ │ └─543 /usr/lib/at-spi2-core/at-spi2-registryd --use-gnome-session │ └─user-1000.slice │ ├─session-2.scope │ │ ├─668 sshd: trainee [priv] │ │ ├─679 sshd: trainee@pts/0 │ │ ├─680 -bash │ │ ├─689 su - │ │ ├─690 -su │ │ ├─708 systemd-cgls │ │ └─709 systemd-cgls │ └─user@1000.service │ └─init.scope │ ├─670 /lib/systemd/systemd --user │ └─671 (sd-pam) ├─init.scope │ └─1 /sbin/init └─system.slice ├─lightdm.service │ ├─410 /usr/sbin/lightdm │ ├─425 /usr/lib/xorg/Xorg :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch │ └─588 lightdm --session-child 14 21 ├─anacron.service lines 1-39
En utilisant Systemd, plusieurs ressources peuvent être limitées :
- CPUShares - par défault 1024,
- MemoryLimit - limite exprimée en Mo ou en Go. Pas de valeur par défaut,
- BlockIOWeight - valeur entre 10 et 1000. Pas de valeur par défaut,
- StartupCPUShares - comme CPUShares mais uniquement appliqué pendant le démarrage,
- StartupBlockIOWeight - comme BlockIOWeight mais uniquement appliqué pendant le démarrage,
- CPUQuota - utilisé pour limiter le temps CPU, même quand le système ne fait rien.
Important : Consultez le manuel systemd.resource-control(5) pour voir les paramètres CGroup qui peuvent être passés à systemctl.
LAB #2 - Travailler avec les CGroups
2.1 - Limitation de la Mémoire
Pour travailler avec les CGroups dans Debian 9, il convient d'installer les outils nécessaires :
root@debian9:~# apt-get install libcgroup1 cgroup-tools
Commencez ensuite par créer le script hello-world.sh qui servira à générer un processus pour travailler avec les CGroups :
root@debian9:~# vi hello-world.sh root@debian9:~# cat hello-world.sh #!/bin/bash while [ 1 ]; do echo "hello world" sleep 60 done
Rendez le script exécutable et testez-le :
root@debian9:~# chmod u+x hello-world.sh root@debian9:~# ./hello-world.sh hello world hello world ^C
Créez maintenant un CGroup dans le sous-système memory appelé helloworld :
root@debian9:~# mkdir /sys/fs/cgroup/memory/helloworld
Par défaut, ce CGroup héritera de l'ensemble de la mémoire disponible. Pour éviter cela, créez maintenant une limite de 40000000 octets pour ce CGroup :
root@debian9:~# echo 40000000 > /sys/fs/cgroup/memory/helloworld/memory.limit_in_bytes root@debian9:~# cat /sys/fs/cgroup/memory/helloworld/memory.limit_in_bytes 39997440
Important - Notez que les 40 000 000 demandés sont devenus 39 997 440 ce qui correspond à un nombre entier de pages mémoire du noyau de 4Ko. ( 39 997 440 / 4096 = 9 765 ).
Lancez maintenant le script helloworld.sh :
root@debian9:~# ./hello-world.sh & [1] 1012 root@debian9:~# hello world root@debian9:~# ps aux | grep hello-world root 1012 0.0 0.1 11172 2868 pts/0 S 10:24 0:00 /bin/bash ./hello-world.sh root 1015 0.0 0.0 12784 968 pts/0 S+ 10:25 0:00 grep hello-world
Notez l'héritage par défaut :
root@debian9:~# ps -ww -o cgroup 1012 CGROUP 6:devices:/user.slice,3:pids:/user.slice/user-1000.slice/session-2.scope,1:name=systemd:/user.slice/user-1000.slice/session-2.scope
Insérer le PID de notre script dans le CGroup helloworld :
root@debian9:~# echo 1012 > /sys/fs/cgroup/memory/helloworld/cgroup.procs
Notez maintenant l'héritage de la limitation de la mémoire - 2:memory:/helloworld :
root@debian9:~# ps -ww -o cgroup 1012 CGROUP 6:devices:/user.slice,3:pids:/user.slice/user-1000.slice/session-2.scope,2:memory:/helloworld,1:name=systemd:/user.slice/user-1000.slice/session-2.scope
Constatez ensuite l'occupation mémoire réelle :
root@debian9:~# cat /sys/fs/cgroup/memory/helloworld/memory.usage_in_bytes 319488
Tuez le script hello-world.sh :
root@debian9:~# kill 1012 root@debian9:~# ps aux | grep hello-world root 1038 0.0 0.0 12784 936 pts/0 S+ 10:33 0:00 grep hello-world [1]+ Complété ./hello-world.sh
Créez un second CGroup beaucoup plus restrictif :
root@debian9:~# mkdir /sys/fs/cgroup/memory/helloworld1 root@debian9:~# echo 6000 > /sys/fs/cgroup/memory/helloworld1/memory.limit_in_bytes root@debian9:~# cat /sys/fs/cgroup/memory/helloworld1/memory.limit_in_bytes 4096
Relancez le script hello-world.sh et insérez-le dans le nouveau CGroup :
root@debian9:~# ./hello-world.sh & [1] 1042 root@debian9:~# hello world root@debian9:~# echo 1042 > /sys/fs/cgroup/memory/helloworld1/cgroup.procs
Attendez la prochaine sortie de hello world sur le canal standard puis constatez que le script s'arrête :
root@debian9:~# hello world [1]+ Processus arrêté ./hello-world.sh
Consultez en suite la fin du fichier /var/log/messages :
root@debian9:~# tail /var/log/messages Jul 28 10:39:26 debian9 kernel: [ 1501.775169] [<ffffffffabe6253d>] ? __do_page_fault+0x4bd/0x4f0 Jul 28 10:39:26 debian9 kernel: [ 1501.775171] [<ffffffffabfc2950>] ? SyS_brk+0x160/0x180 Jul 28 10:39:26 debian9 kernel: [ 1501.775175] [<ffffffffac41a358>] ? page_fault+0x28/0x30 Jul 28 10:39:26 debian9 kernel: [ 1501.775176] Task in /helloworld1 killed as a result of limit of /helloworld1 Jul 28 10:39:26 debian9 kernel: [ 1501.775180] memory: usage 4kB, limit 4kB, failcnt 17 Jul 28 10:39:26 debian9 kernel: [ 1501.775180] memory+swap: usage 0kB, limit 9007199254740988kB, failcnt 0 Jul 28 10:39:26 debian9 kernel: [ 1501.775181] kmem: usage 0kB, limit 9007199254740988kB, failcnt 0 Jul 28 10:39:26 debian9 kernel: [ 1501.775181] Memory cgroup stats for /helloworld1: cache:0KB rss:4KB rss_huge:0KB mapped_file:0KB dirty:0KB writeback:0KB inactive_anon:0KB active_anon:0KB inactive_file:0KB active_file:0KB unevictable:0KB Jul 28 10:39:26 debian9 kernel: [ 1501.775188] [ pid ] uid tgid total_vm rss nr_ptes nr_pmds swapents oom_score_adj name Jul 28 10:39:26 debian9 kernel: [ 1501.775219] [ 1042] 0 1042 2795 732 10 3 0 0 hello-world.sh
Important - Notez la trace Task in /helloworld1 killed as a result of limit of /helloworld1.
2.2 - Le Paquet cgroup-tools
Le paquet cgroup-tools installe des commandes dites de facilité dont :
La commande cgcreate
Cette commande permet la création d'un CGroup :
root@debian9:~# cgcreate -g memory:helloworld2 root@debian9:~# ls -l /sys/fs/cgroup/memory/helloworld2/ total 0 -rw-r--r-- 1 root root 0 juil. 28 11:09 cgroup.clone_children --w--w--w- 1 root root 0 juil. 28 11:09 cgroup.event_control -rw-r--r-- 1 root root 0 juil. 28 11:09 cgroup.procs -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.failcnt --w------- 1 root root 0 juil. 28 11:09 memory.force_empty -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.kmem.failcnt -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.kmem.limit_in_bytes -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.kmem.max_usage_in_bytes -r--r--r-- 1 root root 0 juil. 28 11:09 memory.kmem.slabinfo -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.kmem.tcp.failcnt -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.kmem.tcp.limit_in_bytes -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.kmem.tcp.max_usage_in_bytes -r--r--r-- 1 root root 0 juil. 28 11:09 memory.kmem.tcp.usage_in_bytes -r--r--r-- 1 root root 0 juil. 28 11:09 memory.kmem.usage_in_bytes -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.limit_in_bytes -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.max_usage_in_bytes -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.move_charge_at_immigrate -r--r--r-- 1 root root 0 juil. 28 11:09 memory.numa_stat -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.oom_control ---------- 1 root root 0 juil. 28 11:09 memory.pressure_level -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.soft_limit_in_bytes -r--r--r-- 1 root root 0 juil. 28 11:09 memory.stat -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.swappiness -r--r--r-- 1 root root 0 juil. 28 11:09 memory.usage_in_bytes -rw-r--r-- 1 root root 0 juil. 28 11:09 memory.use_hierarchy -rw-r--r-- 1 root root 0 juil. 28 11:09 notify_on_release -rw-r--r-- 1 root root 0 juil. 28 11:09 tasks
Il n'existe cependant pas de commande pour affecter une limitation de la mémoire :
root@debian9:~# echo 40000000 > /sys/fs/cgroup/memory/helloworld2/memory.limit_in_bytes
La Commande cgexec
Cette commande permet d'insérer la limitation dans le CGroup et de lancer le script en une seule ligne :
root@debian9:~# cgexec -g memory:helloworld2 ./hello-world.sh & [2] 1860 root@debian9:~# hello world root@debian9:~#
La Commande cgdelete
Une fois le script terminé, cette commande permet de supprimer le cgroup :
root@debian9:~# ps aux | grep *.sh root 1073 0.0 0.1 11172 2868 pts/0 S 11:18 0:00 /bin/bash ./hello-world.sh root 1076 0.0 0.0 528 4 pts/0 R+ 11:18 0:00 grep hello-world.sh root@debian9:~# kill 1073 root@debian9:~# ps aux | grep *.sh root 1078 0.0 0.0 12784 920 pts/0 S+ 11:18 0:00 grep hello-world.sh [1]+ Complété cgexec -g memory:helloworld2 ./hello-world.sh root@debian9:~# cgdelete memory:helloworld2 root@debian9:~# ls -l /sys/fs/cgroup/memory/helloworld2/ ls: impossible d'accéder à '/sys/fs/cgroup/memory/helloworld2/': Aucun fichier ou dossier de ce type
La Commande cgexec
Afin de les rendre persistents, il convient de créer les CGroups dans le fichier /etc/cgconfig.conf :
root@debian9:~# vi /etc/cgconfig.conf root@debian9:~# cat /etc/cgconfig.conf group helloworld2 { cpu { cpu.shares = 100; } memory { memory.limit_in_bytes = 40000; } }
Important - Notez la création de deux limitations, une de 40 000 octets de mémoire et l'autre de 100 cpu.shares. Cette dernière est une valeur exprimée sur 1 024, où 1 024 représente 100% du temps CPU. La limite fixée est donc equivalente à 9,77% du temps CPU.
Créez donc les deux CGroups concernés :
root@debian9:~# cgcreate -g memory:helloworld2 root@debian9:~# ls -l /sys/fs/cgroup/memory/helloworld2/ total 0 -rw-r--r-- 1 root root 0 juil. 28 12:47 cgroup.clone_children --w--w--w- 1 root root 0 juil. 28 12:47 cgroup.event_control -rw-r--r-- 1 root root 0 juil. 28 12:47 cgroup.procs -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.failcnt --w------- 1 root root 0 juil. 28 12:47 memory.force_empty -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.kmem.failcnt -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.kmem.limit_in_bytes -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.kmem.max_usage_in_bytes -r--r--r-- 1 root root 0 juil. 28 12:47 memory.kmem.slabinfo -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.kmem.tcp.failcnt -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.kmem.tcp.limit_in_bytes -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.kmem.tcp.max_usage_in_bytes -r--r--r-- 1 root root 0 juil. 28 12:47 memory.kmem.tcp.usage_in_bytes -r--r--r-- 1 root root 0 juil. 28 12:47 memory.kmem.usage_in_bytes -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.limit_in_bytes -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.max_usage_in_bytes -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.move_charge_at_immigrate -r--r--r-- 1 root root 0 juil. 28 12:47 memory.numa_stat -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.oom_control ---------- 1 root root 0 juil. 28 12:47 memory.pressure_level -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.soft_limit_in_bytes -r--r--r-- 1 root root 0 juil. 28 12:47 memory.stat -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.swappiness -r--r--r-- 1 root root 0 juil. 28 12:47 memory.usage_in_bytes -rw-r--r-- 1 root root 0 juil. 28 12:47 memory.use_hierarchy -rw-r--r-- 1 root root 0 juil. 28 12:47 notify_on_release -rw-r--r-- 1 root root 0 juil. 28 12:47 tasks
root@debian9:~# cgcreate -g cpu:helloworld2 root@debian9:~# ls -l /sys/fs/cgroup/cpu/helloworld2/ total 0 -rw-r--r-- 1 root root 0 juil. 28 12:48 cgroup.clone_children -rw-r--r-- 1 root root 0 juil. 28 12:48 cgroup.procs -r--r--r-- 1 root root 0 juil. 28 12:48 cpuacct.stat -rw-r--r-- 1 root root 0 juil. 28 12:48 cpuacct.usage -r--r--r-- 1 root root 0 juil. 28 12:48 cpuacct.usage_all -r--r--r-- 1 root root 0 juil. 28 12:48 cpuacct.usage_percpu -r--r--r-- 1 root root 0 juil. 28 12:48 cpuacct.usage_percpu_sys -r--r--r-- 1 root root 0 juil. 28 12:48 cpuacct.usage_percpu_user -r--r--r-- 1 root root 0 juil. 28 12:48 cpuacct.usage_sys -r--r--r-- 1 root root 0 juil. 28 12:48 cpuacct.usage_user -rw-r--r-- 1 root root 0 juil. 28 12:48 cpu.cfs_period_us -rw-r--r-- 1 root root 0 juil. 28 12:48 cpu.cfs_quota_us -rw-r--r-- 1 root root 0 juil. 28 12:48 cpu.shares -r--r--r-- 1 root root 0 juil. 28 12:48 cpu.stat -rw-r--r-- 1 root root 0 juil. 28 12:48 notify_on_release -rw-r--r-- 1 root root 0 juil. 28 12:48 tasks
Appliquez le contenu du fichier /etc/cgconfig.conf grâce à l'utilisation de la commande cgconfigparser :
root@debian9:~# cgconfigparser -l /etc/cgconfig.conf root@debian9:~# cat /sys/fs/cgroup/memory/helloworld2/memory.limit_in_bytes 36864 root@debian9:~# cat /sys/fs/cgroup/cpu/helloworld2/cpu.shares 100
Présentation de Linux Containers
LAB #3 - Travailler avec LXC
3.1 - Installation
Les outils indispensables à l'utilisation des Linux Containers sous Debian sont inclus dans le paquet lxc :
root@debian9:~# apt update root@debian9:~# apt install lxc
L'installation de ce paquet va créer les répertoires /usr/share/lxc/config contenant les fichiers de configurations des gabarits ainsi que le répertoire /usr/share/lxc/templates contenant fichiers de gabarits pour la création des conteneurs :
root@debian9:~# ls /usr/share/lxc config hooks lxc.functions lxc-patch.py __pycache__ selinux templates root@debian9:~# ls /usr/share/lxc/config alpine.common.conf centos.userns.conf debian.userns.conf gentoo.userns.conf oracle.common.conf slackware.userns.conf ubuntu-cloud.userns.conf alpine.userns.conf common.conf fedora.common.conf nesting.conf oracle.userns.conf sparclinux.common.conf ubuntu.common.conf archlinux.common.conf common.conf.d fedora.userns.conf opensuse.common.conf plamo.common.conf sparclinux.userns.conf ubuntu.lucid.conf archlinux.userns.conf common.seccomp gentoo.common.conf opensuse.userns.conf plamo.userns.conf ubuntu-cloud.common.conf ubuntu.userns.conf centos.common.conf debian.common.conf gentoo.moresecure.conf openwrt.common.conf slackware.common.conf ubuntu-cloud.lucid.conf userns.conf root@debian9:~# ls /usr/share/lxc/templates lxc-alpine lxc-archlinux lxc-centos lxc-debian lxc-fedora lxc-openmandriva lxc-oracle lxc-slackware lxc-sshd lxc-ubuntu-cloud lxc-altlinux lxc-busybox lxc-cirros lxc-download lxc-gentoo lxc-opensuse lxc-plamo lxc-sparclinux lxc-ubuntu
3.2 - Création d'un Conteneur Simple
Créez un conteneur simple en utilsant la comande suivante :
root@debian9:~# lxc-create -n lxc-bb -t busybox chmod: impossible d'accéder à '/var/lib/lxc/lxc-bb/rootfs/bin/passwd': Aucun fichier ou dossier de ce type setting root password to "root" Failed to change root password
Important - Notez l'utilisation de l'option -n qui permet d'associer un nom au conteneur ainsi que l'option -t qui indique le gabarit à utiliser. Notez aussi que le gabarit est référencé par le nom du fichier dans le répertoire /usr/share/lxc/templates sans son préfix lxc-.
Le backingstore ( méthode de stockage) utilisé par défaut est dir ce qui implqiue que le rootfs du conteneur se trouve sur disque dans le répertoire /var/lib/lxc/ :
root@debian9:~# ls /var/lib/lxc/ lxc-bb root@debian9:~# ls /var/lib/lxc/lxc-bb/ config rootfs root@debian9:~# ls /var/lib/lxc/lxc-bb/rootfs bin dev etc home lib lib64 mnt proc root sbin selinux sys tmp usr var
Il est à noter que LXC peut également utiliser des backingstores de type :
- ZFS
- Brtfs
- LVM
- Loop
- rbd (CephFS)
3.3 - Démarrage d'un Conteneur Simple
Pour démarrer le conteneur, il convient d'utiliser la commande lxc-start :
root@debian9:~# lxc-start --name lxc-bb
3.4 - S'attacher à un Conteneur Simple
Pour s'attacher au conteneur démarré, il convient d'utiliser la commande lxc-attach :
root@debian9:~# lxc-attach --name lxc-bb BusyBox v1.22.1 (Debian 1:1.22.0-19+b3) built-in shell (ash) Enter 'help' for a list of built-in commands. ~ # passwd /bin/sh: passwd: not found ~ # which passwd ~ #
Important - Notez l'absence de la commande passwd dans le conteneur, ce qui explique l'erreur lors de la création de celui-ci.
Pour sortir du conteneur, il convient d'utiliser la commande exit ou bien la combinaison de touches <Ctrl+d> :
~ # [Ctrl+d] ~ # root@debian9:~#
Le fait de sortir du conteneur ne l'arrête pas pour autant, comme il peut être constaté par l'utilisation de la commande lxc-ls :
~ # root@debian9:~# [Entrée] root@debian9:~# lxc-ls --running lxc-bb root@debian9:~# lxc-ls -f --running NAME STATE AUTOSTART GROUPS IPV4 IPV6 lxc-bb RUNNING 0 - - -
3.5 - Commandes LXC de Base
La Commande lxc-console
Pour lancer une console attachée à un TTY dans le conteneur, il convient d'utiliser la commande lxc-console :
root@debian9:~# lxc-console --name lxc-bb Connected to tty 1 Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself lxc-bb login: root Password: Login incorrect lxc-bb login: trainee Password: Login incorrect lxc-bb login:
Important - Notez que pour des raisons évidentes, le conteneur BusyBox ne sait pas gérer de logins.
Pour sortir de la console, il faut utiliser la combinaison de touches <Ctrl+a> <q> :
lxc-bb login: [Ctrl+a] [q] root@debian9:~#
La Commande lxc-stop
Pour arrêter le conteneur, utilisez la commande lxc-stop :
root@debian9:~# lxc-ls --running lxc-bb root@debian9:~# lxc-stop --name lxc-bb root@debian9:~# lxc-ls --running root@debian9:~#
La Commande lxc-execute
La commande lxc-execute démarre un conteneur (qui doit être créé mais arrêté), exécute la commande passée en argument grâce aux caractères – puis arrête le conteneur :
root@debian9:~# lxc-execute -n lxc-bb -- uname -a init.lxc.static: initutils.c: mount_fs: 36 failed to mount /proc : Device or resource busy Linux lxc-bb 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86_64 GNU/Linux root@debian9:~# lxc-ls --running root@debian9:~#
La Commande lxc-info
Cette commande donne des informations sur un conteneur :
root@debian9:~# lxc-info -n lxc-bb Name: lxc-bb State: STOPPED
La Commande lxc-freeze
La commande lxc-freeze met en pause tous les processus du conteneur :
root@debian9:~# lxc-start -n lxc-bb root@debian9:~# lxc-ls --running lxc-bb root@debian9:~# lxc-info -n lxc-bb Name: lxc-bb State: RUNNING PID: 3906 CPU use: 0.00 seconds BlkIO use: 0 bytes Memory use: 664.00 KiB KMem use: 340.00 KiB root@debian9:~# lxc-freeze -n lxc-bb root@debian9:~# lxc-info -n lxc-bb Name: lxc-bb State: FROZEN PID: 3906 CPU use: 0.00 seconds BlkIO use: 0 bytes Memory use: 664.00 KiB KMem use: 340.00 KiB
La Commande lxc-unfreeze
La commande lxc-unfreeze annule l'effet d'une commande lxc-freeze précédente :
root@debian9:~# lxc-unfreeze -n lxc-bb root@debian9:~# lxc-info -n lxc-bb Name: lxc-bb State: RUNNING PID: 3906 CPU use: 0.00 seconds BlkIO use: 0 bytes Memory use: 664.00 KiB KMem use: 340.00 KiB
Autres Commandes
Les autres commandes dont il faut avoir une connaissance sont :
Commande | Description |
---|---|
lxc-destroy | Permet de détruire complètement un conteneur |
lxc-autostart | Permet de rebooter, tuer ou arrêter les conteneurs dont le drapeau lxc.start.auto est fixé dans le fichier /var/lib/<nom_conteneur>/config |
lxc-cgroup | Permet de manipuler à chaud les CGroups pour un conteneur donné |
lxc-device | Permet de rajouter à chaud les devices à un conteneur |
lxc-usernsexec | Permet d'exécuter des commandes en tant que root dans un conteneur non-priviligié |
lxc-wait | Permet d'attendre à ce qu'un conteneur ait atteint un certain état avnt de continuer |
3.6 - Création d'un Conteneur Non-Priviligié
User Namespaces
Un conteneur priviligié est un conteneur lancé par l'utilisateur root tandis qu'un conteneur non-priviligié est lancé par un utilisteur autre que root. Un conteneur priviligié est moins sécurisé qu'un conteneur non-priviligié mais ne necéssite pas la gestion du mappage d'UID.
Le mappage d'UID est une fonctionalité du noyau Linux appelée user namespaces ou encore userns. Cette fonctionalité permet de mapper une plage d'UID de la machine hôte vers un utilisateur dont l'UID est 0 dans un autre espace de noms.
Création d'un Utilisteur Dédié
Commencez par créer l'utilisteur lxcnp dédié à la gestion des conteneurs non-priviligiés :
root@debian9:~# useradd -c "Utilisateur LXC Non-Priviligié" -s /bin/bash -m lxcnp root@debian9:~# passwd lxcnp Entrez le nouveau mot de passe UNIX : trainee Retapez le nouveau mot de passe UNIX : trainee passwd: password updated successfully
Les informations concernant le mappage des UID et GID se trouvent dans les fichiers /etc/subuid et /etc/subgid :
root@debian9:~# grep lxcnp /etc/sub{uid,gid} /etc/subuid:lxcnp:165536:65536 /etc/subgid:lxcnp:165536:65536
Important - Ces informations indiquent que nous avons 65 536 UID et 65 536 GID disponibles pour le mappage vers l'UID et le GID 165 536.
Création du Mappage
La valeur de kernel.unprivileged_userns_clone doit être 1, or actuellement elle est de 0 :
root@debian9:~# cat /proc/sys/kernel/unprivileged_userns_clone 0
Fixez donc la valeur à 1 et appliquez la modification avec la commande sysctl –system :
root@debian9:~# echo "kernel.unprivileged_userns_clone=1" > /etc/sysctl.d/80-lxc-userns.conf root@debian9:~# cat /etc/sysctl.d/80-lxc-userns.conf kernel.unprivileged_userns_clone=1 root@debian9:~# sysctl --system * Applying /etc/sysctl.d/80-lxc-userns.conf ... kernel.unprivileged_userns_clone = 1 * Applying /etc/sysctl.d/99-sysctl.conf ... * Applying /etc/sysctl.conf ...
Connectez-vous ensuite en tant que l'utilisateur lxcnp :
root@debian9:~# su - lxcnp lxcnp@debian9:~$
Créez le répertoire ~/.config/lxc :
lxcnp@debian9:~$ mkdir -p ~/.config/lxc
Créez trois entrées dans le fichier ~/.config/lxc/default.conf afin d'y inclure la configuration du fichier /etc/lxc/default.conf et mapper l'UID et le GID :
lxcnp@debian9:~$ echo "lxc.include = /etc/lxc/default.conf" >> ~/.config/lxc/default.conf lxcnp@debian9:~$ echo "lxc.id_map = u 0 165536 65536" >> ~/.config/lxc/default.conf lxcnp@debian9:~$ echo "lxc.id_map = g 0 165536 65536" >> ~/.config/lxc/default.conf lxcnp@debian9:~$ cat ~/.config/lxc/default.conf lxc.include = /etc/lxc/default.conf lxc.id_map = u 0 165536 65536 lxc.id_map = g 0 165536 65536
Déconnectez-vous et reconnectez-vous en tant que l'utilisateur lxcnp :
lxcnp@debian9:~$ exit déconnexion root@debian9:~# su - lxcnp lxcnp@debian9:~$
Création du Conteneur
Créez maintenant un conteneur non-priviligié appelé lxc-bb-np à partir du gabarit busybox :
lxcnp@debian9:~$ lxc-create -n lxc-bb-np -t busybox WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied chmod: impossible d'accéder à '/home/lxcnp/.local/share/lxc/lxc-bb-np/rootfs/bin/passwd': Aucun fichier ou dossier de ce type setting root password to "root" Failed to change root password lxcnp@debian9:~$ ls -l /home/lxcnp/.local/share/lxc/lxc-bb-np/rootfs/ total 60 drwxr-xr-x 2 165536 165536 4096 juil. 29 13:11 bin drwxr-xr-x 4 165536 165536 4096 juil. 29 13:11 dev drwxr-xr-x 3 165536 165536 4096 juil. 29 13:11 etc drwxr-xr-x 2 165536 165536 4096 juil. 29 13:11 home drwxr-xr-x 2 165536 165536 4096 juil. 29 13:11 lib drwxr-xr-x 2 165536 165536 4096 juil. 29 13:11 lib64 drwxr-xr-x 2 165536 165536 4096 juil. 29 13:11 mnt drwxr-xr-x 2 165536 165536 4096 juil. 29 13:11 proc drwxr-xr-x 2 165536 165536 4096 juil. 29 13:11 root drwxr-xr-x 2 165536 165536 4096 juil. 29 13:11 sbin drwxr-xr-x 2 165536 165536 4096 juil. 29 13:11 selinux drwxr-xr-x 2 165536 165536 4096 juil. 29 13:11 sys drwxr-xr-x 2 165536 165536 4096 juil. 29 13:11 tmp drwxr-xr-x 7 165536 165536 4096 juil. 29 13:11 usr drwxr-xr-x 3 165536 165536 4096 juil. 29 13:11 var
Contrôle du Mappage
Démarrez le conteneur :
lxcnp@debian9:~$ lxc-start -n lxc-bb-np lxcnp@debian9:~$ lxc-ls -f --running NAME STATE AUTOSTART GROUPS IPV4 IPV6 lxc-bb-np RUNNING 0 - - -
Attachez-vous au conteneur et contrôlez l'UID de l'utilisateur des processus dans le conteneur :
lxcnp@debian9:~$ lxc-attach -n lxc-bb-np WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied WARN: could not reopen tty: Permission denied BusyBox v1.22.1 (Debian 1:1.22.0-19+b3) built-in shell (ash) Enter 'help' for a list of built-in commands. / # ps aux PID USER COMMAND 1 root init 4 root /bin/syslogd 7 root /bin/getty -L tty1 115200 vt100 8 root init 9 root /bin/sh 10 root ps aux / #
Détachez-vous du conteneur et sortez du compte lxcnp :
/ # exit lxcnp@debian9:~$ exit déconnexion root@debian9:~#
Dernièrement, vérifiez l'UID de l'utilisateur des processus appartenant au conteneur :
root@debian9:~# ps aux | grep 165536 165536 3450 0.0 0.0 4832 256 ? Ss 13:17 0:00 init 165536 3462 0.0 0.0 4836 100 ? Ss 13:17 0:00 /bin/syslogd 165536 3465 0.0 0.0 4832 256 pts/0 Ss+ 13:17 0:00 /bin/getty -L tty1 115200 vt100 165536 3466 0.0 0.0 4832 108 pts/2 Ss+ 13:17 0:00 init root 3485 0.0 0.0 12784 932 pts/0 S+ 13:22 0:00 grep 165536
3.7 - Création d'un Conteneur Ephémère
Par défaut les conteneurs LXC sont permenants. Il est possible de créer un conteneur éphémère, c'est-à-dire un conteneur où toutes les données sont détruites à l'arrêt de celui-ci, en utilisant la commande lxc-copy ainsi que l'option de cette commande –epheremal ou -e.
La Commande lxc-copy
Notez que le containeur d'origine doit être arrêté lors de l'utilisation de la commande lxc-copy :
root@debian9:~# lxc-ls -f --running NAME STATE AUTOSTART GROUPS IPV4 IPV6 lxc-bb RUNNING 0 - - - root@debian9:~# lxc-copy -e -N lxc-bb-eph -n lxc-bb lxc-copy: lxccontainer.c: do_lxcapi_clone: 3079 error: Original container (lxc-bb) is running
Arrêtez donc le conteneur lxc-bb puis créez la copie :
root@debian9:~# lxc-stop -n lxc-bb root@debian9:~# lxc-ls -f --running root@debian9:~# lxc-copy -e -N lxc-bb-eph -n lxc-bb Created lxc-bb-eph as clone of lxc-bb
Attachez-vous au conteneur lxc-bb-eph :
root@debian9:~# lxc-attach lxc-bb-eph lxc-attach: missing container name, use --name option root@debian9:~# lxc-attach -n lxc-bb-eph BusyBox v1.22.1 (Debian 1:1.22.0-19+b3) built-in shell (ash) Enter 'help' for a list of built-in commands. ~ #
Créez un fichier de contrôle appelé testdata :
~ # ls -l total 4 -rw-r--r-- 1 root root 51 Jul 28 13:47 hi.sh ~ # pwd /root ~ # echo "test" > testdata ~ # ls -l total 8 -rw-r--r-- 1 root root 51 Jul 28 13:47 hi.sh -rw-r--r-- 1 root root 5 Jul 29 15:14 testdata ~ #
Déconnectez-vous du conteneur puis attachez-vous de nouveau :
~ # exit root@debian9:~# lxc-attach -n lxc-bb-eph BusyBox v1.22.1 (Debian 1:1.22.0-19+b3) built-in shell (ash) Enter 'help' for a list of built-in commands. ~ # ls -l total 8 -rw-r--r-- 1 root root 51 Jul 28 13:47 hi.sh -rw-r--r-- 1 root root 5 Jul 29 15:14 testdata ~ #
Important - Notez que le fichier testdata est toujours présent.
Déconnectez-vous de nouveau et arrêtez le conteneur :
~ # exit root@debian9:~# lxc-stop -n lxc-bb-eph root@debian9:~# lxc-ls lxc-bb root@debian9:~# lxc-start -n lxc-bb-eph lxc-start: log.c: log_open: 300 failed to open log file "/var/lib/lxc/lxc-bb-eph/lxc-bb-eph.log" : No such file or directory lxc-start: tools/lxc_start.c: main: 317 Executing '/sbin/init' with no configuration file may crash the host
Important - Notez que le conteneur lxc-bb-eph a été détruit.
3.8 - Sauvegarde des Conteneurs
Un conteneur LXC peut être sauvegardé de trois façons différentes :
- utiliser la commande tar ou cpio pour créer un archive du répertoire rootfs et du fichier config associés au conteneur
- utiliser la commande lxc-copy sans l'option -e
- utiliser la commande lxc-snapshot
La Commande lxc-snapshot
Cette commande permet de gérer des instantanées des conteneurs. A noter que les conteneurs doivent être arrêtés avant de prendre une instantanée :
root@debian9:~# lxc-ls -f --running root@debian9:~# lxc-snapshot -n lxc-bb lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3407 Snapshot of directory-backed container requested. lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3408 Making a copy-clone. If you do want snapshots, then lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3409 please create an aufs or overlayfs clone first, snapshot that lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3410 and keep the original container pristine.
Les snapshots sont stockés dans le sous-répertoire snaps du répertoire /var/lib/lxc/<nom_conteneur>/. Le premier s'appelle snap0 :
root@debian9:~# ls -l /var/lib/lxc/lxc-bb total 12 -rw-r--r-- 1 root root 1102 juil. 28 13:04 config -rw-r--r-- 1 root root 0 juil. 28 13:14 lxc-bb.log drwxr-xr-x 17 root root 4096 juil. 28 15:50 rootfs drwxr-xr-x 3 root root 4096 juil. 29 17:34 snaps root@debian9:~# ls -l /var/lib/lxc/lxc-bb/snaps/ total 4 drwxrwx--- 3 root root 4096 juil. 29 17:34 snap0 root@debian9:~# ls -l /var/lib/lxc/lxc-bb/snaps/snap0/ total 12 -rw-r--r-- 1 root root 1110 juil. 29 17:34 config drwxr-xr-x 17 root root 4096 juil. 28 15:50 rootfs -rw-r--r-- 1 root root 19 juil. 29 17:34 ts
L'horodatage de la création du snapshot est stocké dans le fichier ts :
root@debian9:~# cat /var/lib/lxc/lxc-bb/snaps/snap0/ts 2020:07:29 17:34:36root@debian9:~#
En comparant la taille du rootfs du conteneur d'origine ainsi que de son snapshot, on peut constater que les deux sont identiques :
root@debian9:~# du -sh /var/lib/lxc/lxc-bb/rootfs/ 792K /var/lib/lxc/lxc-bb/rootfs/ root@debian9:~# du -sh /var/lib/lxc/lxc-bb/snaps/snap0/rootfs/ 792K /var/lib/lxc/lxc-bb/snaps/snap0/rootfs/
Pour restaurer un conteneur identique à l'original, il convient d'utiliser de nouveau la commande lxc-snapshot :
root@debian9:~# lxc-snapshot -r snap0 -n lxc-bb -N lxc-bb-snap0 root@debian9:~# lxc-ls lxc-bb lxc-bb-snap0 root@debian9:~# lxc-start -n lxc-bb-snap0 root@debian9:~# lxc-attach -n lxc-bb-snap0 BusyBox v1.22.1 (Debian 1:1.22.0-19+b3) built-in shell (ash) Enter 'help' for a list of built-in commands. ~ # exit root@debian9:~#
<html>
Copyright © 2020 Hugh Norris
</html>