J'utilisais déjà les containers LXC depuis pas mal de temps, ce qui me semblait une solution intéressante pour une virtualisation légère, par rapport à du KVM et bien avant Docker (et tout le foin qu'on fait autour de ça).
J'ai donc une dizaine de containers LXC, que j'utilisais sur un disque externe, sous Ubuntu 14.04 LTS.
Depuis cette année, j'ai fait l'upgrade en Ubuntu 16.06 LTS, qui embarque maintenant LXD, le successeur de LXC. Malheureusement, la nouvelle version n'est pas strictement compatible avec l'ancienne, et il faut passer par une phase de migration.
Parmi les nouveautés de LXD, les containers peuvent maintenant être lancés en mode utilisateur (alors qu'auparavant cela se faisait généralement sous root).
Heureusement, il existe un script python, disponible sur le GitHub du projet, permettant de migrer.
Cependant, venant d'un upgrade 14.04 / 16.04, j'ai du quelque peu adapter les fichiers de configuration et l'installation.
Installation et activation LXD
Avant de pouvoir utiliser le script, il faut installer lxd et le client (lxc) :
$ sudo apt install lxd lxd-client
Puis lancer l'init
$ sudo lxd init
Transfert manuel
Comme dit plus haut, il n'est pas possible de récupérer directement un container LXC. Par contre, on peut procéder en 2 étapes :
- Créer un nouveau container LXD
- Remplacer l'arborescence rootfs du nouveau container LXDpar l'arborescence de l'ancien container LXC.
Par exemple, si je veux convertir un container wordpress, qui était stocké dans /var/lib/lxc/wordpress, les actions à faire sont :
lxc launch 3e4d9bea32dc wordpress # création du nouveau container LXD lxc stop wordpress # arrêt du container cd /var/lib/lxd/containers rm -rf wordpress/rootfs # on supprimer la nouvelle arborescence cp -R /var/lib/lxc/wordpress/rootfs wordpress/. # copie de l'ancien file system lxc config set wordpress security.privileged true # si l'ancien container était lancé en root lxc start wordpress
Dans l'exemple, j'utilise une image LXC déjà présente sur disque.
Adaptation de l'installation pour le script
Une fois le script récupéré sur GitHub, on peut tenter de le lancer, mais on se heurte vite à des soucis de librairie non connue (pylxd).
La solution est d'installer via pip. Souci : c'est le python 2.7 qui est utilisé, alors que le script demande python 3. Il faut donc tout d'abord installer pip3, puis relancer l'installation de pylxd:
$ sudo apt install python3-pip $ pip3 install --upgrade pip $ sudo pip3 install pylxd $ ls /usr/local/lib/python3.5/dist-packages cffi pbr-1.10.0.dist-info python_dateutil-2.5.3.dist-info cffi-1.8.3.dist-info pip requests_unixsocket _cffi_backend.cpython-35m-x86_64-linux-gnu.so pip-8.1.2.dist-info requests_unixsocket-0.1.5.dist-info cryptography pycparser ws4py cryptography-1.5.2.dist-info pycparser-2.17.dist-info ws4py-0.3.4.dist-info dateutil pylxd pbr pylxd-2.1.2.dist-info
A ce stade, on a tous les éléments pour lancer la migration.
Note : j'ai eu des soucis lors de l'installation de pylxd, avec la cryptographie.
build/temp.linux-x86_64-3.5/_openssl.c:434:30: fatal error: openssl/opensslv.h: Aucun fichier ou dossier de ce type compilation terminated. error: command 'x86_64-linux-gnu-gcc' failed with exit status 1 Failed building wheel for cryptography
en fait il manquait la libss-dev, ce qui a été résolu par :
$ sudo apt install libssl-dev
Modification des fichiers de configuration LXC
Une fois qu'on a réussi à installer les libs, j'ai remarqué que quelques paramètres des fichiers de configuration LXC posaient problème.
Pour chaque container à migrer, je mets en commentaires certains éléments :
Il s'agit notamment des paramètres :
- lxc.mount.entry pour les éléments ne concernant pas directement des fichiers ou répertoires (en clair, proc et sysfs)
- lxc.seccomp
- lxc.cap.drop
Par exemple :
#lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 #lxc.mount.entry = sysfs sys sysfs defaults 0 0 #lxc.seccomp = /usr/share/lxc/config/common.seccomp #lxc.cap.drop = sys_module #lxc.cap.drop = mac_admin #lxc.cap.drop = mac_override #lxc.cap.drop = sys_time
Une fois ces éléments mis en commentaires, on peut lancer la migration :
$ sudo /home/vliefooghe/bin/lxc-to-lxd openldap ==> Processing container: openldap Parsing LXC configuration Checking for existing containers Validating container name Validating container mode Validating container rootfs Processing network configuration Processing environment configuration Processing container boot configuration Processing container apparmor configuration Processing container seccomp configuration Processing container SELinux configuration Processing container capabilities configuration Converting container architecture configuration Creating the container Container is ready to use
La commande lxc list permet de lister les containers LXD existants :
$ lxc list +----------+---------+------------------+------+------------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +----------+---------+------------------+------+------------+-----------+ | mysql | RUNNING | 10.0.8.41 (eth0) | | PERSISTENT | 0 | +----------+---------+------------------+------+------------+-----------+ | opendj | STOPPED | | | PERSISTENT | 0 | +----------+---------+------------------+------+------------+-----------+ | openidm1 | STOPPED | | | PERSISTENT | 0 | +----------+---------+------------------+------+------------+-----------+ | openldap | STOPPED | | | PERSISTENT | 0 | +----------+---------+------------------+------+------------+-----------+ | tomcat | STOPPED | | | PERSISTENT | 0 | +----------+---------+------------------+------+------------+-----------+
On peut se connecter à la VM via la commande
$ lxc exec mysql -- /bin/bash
Le démarrage et l'arrêt se font via les commande lxc start / stop :
$ lxc start mysql $ lxc stop mysql
Accès réseau
Les containers LXD utilisent un nouveau device réseau : lxdbr0, à la différence des containers LXC qui utilisaient lxcbr0.
Il faut donc également modifier la configuration des nouveaux containers, via la commande lxc config, et changer lxcbr0 en lxdbr0 :
$ lxc config edit CONTAINER convert_net0: hwaddr: 00:16:3e:16:31:7e nictype: bridged parent: lxdbr0 type: nic
Répertoire partagé
A la mode LXC
Avec mes containers LXC, j'utilisais un répertoire partagé entre le host et les containers. Ceci était défini dans le fichier config du container :
lxc.mount = /var/lib/lxc/nginx/fstab
Le fichier fstab contenait :
# Shared folder /data/Xchange xchange none bind
Dans l'exemple, je montaint le répertoire /data/Xchange sur le host dans le répertoire /xchange du container.
A la mode LXD
Avec LXD, la syntaxe a changé. Il faut passer par la commande lxc config qui permet maintenant de gérer la configuration des containers
$ lxc config device add nginx sdb disk source=/data/www path=/opt/www
La commande va ajouter un device (add device) à mon container nginx, de type disk, avec la source /data/www sur la machine host, et le path /opt/www dans le container. Après avoir lancé la commande, on peut vérifier :
$ lxc exec nginx "df" Filesystem 1K-blocks Used Available Use% Mounted on /dev/sdb1 38314312 15403884 20941072 43% / none 492 0 492 0% /dev udev 4003468 0 4003468 0% /dev/fuse udev 4003468 0 4003468 0% /dev/net/tun /dev/sdb1 38314312 15403884 20941072 43% /dev/lxd /dev/sda1 330148460 292982708 20372152 94% /xchange /dev/sdb1 38314312 15403884 20941072 43% /dev/.lxd-mounts tmpfs 804824 36 804788 1% /run tmpfs 5120 0 5120 0% /run/lock tmpfs 3171840 0 3171840 0% /run/shm /dev/sda1 330148460 292982708 20372152 94% /opt/www
On a bien un nouveau point de montage dans le container.
Visualisation de la configuration du container
LXD introduit une nouvelle option pour gérer la configuration : lxc config.
Pour afficher la configuration, on utilise lxc config show CONTAINER. Par exemple :
lxc config show drupal8 name: drupal8 profiles: - default config: security.privileged: "true" volatile.convert_net0.name: eth0 volatile.last_state.idmap: '[]' devices: convert_mount0: path: /xchange source: /data/Xchange type: disk convert_mount1: optional: "true" path: /sys/fs/fuse/connections source: /sys/fs/fuse/connections type: disk convert_net0: hwaddr: 00:16:3e:8b:00:40 nictype: bridged parent: lxcbr0 type: nic eth0: type: none root: path: / type: disk sdb: path: /opt/www source: /data/www type: disk ephemeral: false
Troubleshooting
Par défaut maintenant les containers tournent en mode "unprivileged". Ceci renforce la sécurité, mais peut avoir des effets de bord.
J'ai eu un souci en installant un package httpd sur une image CentOS7, avec le message d'erreur suivant :
sudo rpm -ivh httpd-2.4.6-40.el7.centos.4.x86_64.rpm Preparing... ################################# [100%] Updating / installing... 1:httpd-2.4.6-40.el7.centos.4 ################################# [100%] error: unpacking of archive failed on file /usr/sbin/suexec: cpio: cap_set_file failed - Operation not permitted error: httpd-2.4.6-40.el7.centos.4.x86_64: install failed
Après avoir testé différents paramétrages, le problème a été résolu en modifiant le paramétrage du container :
$ lxc stop centos7 $ lxc config set centos7 security.privileged true $ lxc config get centos7 security.privileged true $ lxc start centos7
On peut alors tenter une installation :
lxc exec centos7 /bin/bash [root@centos7 ~]# [root@centos7 ~]# [root@centos7 ~]# rpm -ivh httpd-2.4.6-40.el7.centos.4.x86_64.rpm Preparing... ################################# [100%] Updating / installing... 1:httpd-2.4.6-40.el7.centos.4 ################################# [100%]