Rock64 : la conteneurisation via LXD

Rédigé par Alexandre le 2020-08-13

#auto-hébergement #debian #loisir

Avant de louer mon premier serveur dédié, je me suis posé la question du cloisonnement des différents services que je souhaitais héberger. N'ayant pas les moyens de louer un serveur performant pour faire de la virtualisation, je me suis intéressé à la conteneurisation. A l'époque, j'ai fait la découverte de Proxmox VE qui m'a permis d'apprendre, de façon simple, la conteneurisation via OpenVZ, puis LXC.

Quelques mois après avoir acquis un mini-ordinateur Rock64, je me suis naturellement tourné vers Proxmox VE. Malheureusement, le projet ne supporte pas (encore ?) l'architecture arm64 ou armhf. Je me suis alors tourné vers une autre solution, LXD. D'abord testé sur mon Rock64, j'ai finalement décidé de louer un serveur dédié encore moins onéreux et performant pour y déployer LXD.

Cet article documente l'installation et la configuration de LXD sur un serveur Kimsifu KS-3.

Installation

LXD n'est pas disponible dans les paquets Debian et comme je n'ai pas franchement envie de passer sur Ubuntu, je choisis l'installation via le paquet snap.

La version de snapd fournie dans Buster ne supporte pas les dernières versions du paquet lxd, pour contourner le problème, j'ajoute le dépôt testing :

sudo tee /etc/apt/sources.list.d/testing.list <<EOF
deb http://ftp.fr.debian.org/debian/ testing main
EOF

Configurer le système pour ne pas prendre automatiquement les paquets depuis testing :

sudo tee /etc/apt/preferences.d/testing.pref <<EOF
Package: *
Pin: release a=testing
Pin-Priority: 10
EOF

Appliquer la configuration :

sudo apt update

Installer le gestionnaire de paquets :

sudo apt install -t testing snapd

Installer LXD :

sudo snap install lxd

Permettre à l'utilisateur courant d'utiliser LXD :

sudo adduser $(whoami) lxd

Redémarrer :

sudo reboot

Configuration

Installer le paquet permettant de créer une interface de type pont :

sudo apt -y install bridge-utils

On va devoir modifier la configuration de notre serveur pour créer deux interfaces de type pont. La première permettra aux conteneurs d'utiliser l'IPv6, la seconde d'utiliser l'hôte comme passerelle IPv4.

Le fichier final devrait ressembler à ceci (adapter les IP !) :

# 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
auto eth0
iface eth0 inet manual

# Bridge interface for LXD (WAN)
auto lxdbr0
iface lxdbr0 inet static
  address 192.168.1.5/24
  gateway 192.168.1.254
  dns-nameservers 80.67.169.12 80.67.169.40
  bridge_ports eth0
  bridge_stp off
  bridge_fd 0

Redémarrer le réseau :

sudo systemctl restart networking

Activer l'ipforwarding :

sudo tee /etc/sysctl.d/100-ipforwarding.conf <<EOF
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
EOF

Activer les options :

sudo sysctl -p /etc/sysctl.d/100-ipforwarding.conf

NB : les ports utilisés en entrée par les conteneurs doivent également être ouverts sur le pare-feu de l'hôte

Stockage

Ayant choisi une petite eMMC, j'ai ajouté un disque dur externe qu'il faut préparer à recevoir nos conteneurs.

Effacer le disque dur externe :

sudo wipefs -a /dev/sda

Créer une partition :

sudo cfdisk /dev/sda

Effectuer les actions suivantes :

  • Select label type: gpt
  • Valider New
  • Conserver la taille définie
  • Appliquer avec Write
  • Répondre yes
  • Terminer avec Quit

Formater la partition au format BTRFS :

sudo mkfs.btrfs --force /dev/sda1

Monter la partition au démarrage :

UUID=$(sudo blkid --match-tag UUID /dev/sda1 | awk '{print $2}')
sudo tee --append /etc/fstab <<EOF

# EXT
$UUID  /mnt/lxd  btrfs  defaults,autodefrag  0  0
EOF

Monter la partition :

sudo mount /mnt/lxd

Initialisation

Avant de créer un premier conteneur, il est nécessaire d'initialiser LXD :

lxd init

Voici comment j'ai répondu aux questions :

Would you like to use LXD clustering? (yes/no) [default=no]: yes
What name should be used to identify this node in the cluster? [default=timon]: 
What IP address or DNS name should be used to reach this node? [default=192.168.1.5]: 
Are you joining an existing cluster? (yes/no) [default=no]: 
Setup password authentication on the cluster? (yes/no) [default=yes]: 
Trust password for new clients: 
Again: 
Do you want to configure a new local storage pool? (yes/no) [default=yes]: 
Name of the storage backend to use (lvm, btrfs, dir) [default=btrfs]: 
Create a new BTRFS pool? (yes/no) [default=yes]: no
Name of the existing BTRFS pool or dataset: /mnt/lxd
Do you want to configure a new remote storage pool? (yes/no) [default=no]: 
Would you like to connect to a MAAS server? (yes/no) [default=no]: 
Would you like to configure LXD to use an existing bridge or host interface? (yes/no) [default=no]: yes
Name of the existing bridge or host interface: lxdbr0
Would you like stale cached images to be updated automatically? (yes/no) [default=yes] 
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:

Configuration par défaut

Afin de s'économiser du travail lors de la création d'un nouveau conteneur, j'édite le profil par défaut :

  • désactiver le démarrage automatique
  • définir l'ordre de démarrage à 25
  • un seul vCPU
  • 512 Mo de RAM
  • disque dur de 1Go

Cela se traduit par cette ligne de commande :

lxc profile set default boot.autostart=false boot.autostart.priority=25 limits.cpu=1 limits.memory=512MB && lxc profile device set default root size=1GB

NB : La valeur de boot.autostart.priority est totalement arbitraire, mais j'ai choisi de me mettre sur une échelle de 100 afin de faciliter la lecture. Une valeur haute (100) sera prioritaire sur une valeur basse (99).

Optimisation

Si toutefois on peut parler d'optimisation puisqu'il s'agit ici d'appliquer ce qui me semble logique lors de l'utilisation de virtualisation ou conteneurisation.

Utiliser plus souvent la mémoire vive que l'espace d'échange (SWAP) :

sudo tee /etc/sysctl.d/100-swappiness.conf <<EOF
vm.swappiness=10
vm.vfs_cache_pressure=50
EOF

Activer les options :

sudo sysctl -p /etc/sysctl.d/100-swappiness.conf

Sauvegarde

Changer les droits du sous-volume créé plus haut :

sudo chown -R $(whoami) /mnt/backup

Mettre en place le dépôt :

git clone http://gitea.ykn.fr/pulsar/backup.git /mnt/backup/

Planifier la sauvegarde en éditant la crontab du super-utilisateur :

sudo crontab -e

Ajouter la ligne qui suit à la fin du fichier :

@daily /mnt/pumbaa/backup/fullBackup.bash

Épilogue

Exécuter la commande suivante...

lxc list

...qui liste les conteneurs :

+------+-------+------+------+------+-----------+----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | LOCATION |
+------+-------+------+------+------+-----------+----------+

Il est maintenant temps de créer un conteneur servant de modèle.