#+TITLE: Incus pour gérer vos VM et CT #+DATE: 2025-11-14T00:00:00Z #+DRAFT: false #+AUTHOR: Evrard Van Espen #+DESCRIPTION: Présentation d'Incus, une alternative à Proxmox pour gérer les VMs et les CTs #+SLUG: incus #+TAGS: système #+HERO: ./incus.png * /Incus/, c'est quoi ? /Incus/ est une solution moderne de virtualisation et de gestion de conteneurs, conçue comme un /fork/ communautaire de /LXD/ après le changement de licence de /Canonical/. */Open source/* et axé sur la simplicité, /Incus/ permet de créer et gérer des *conteneurs* et des *machines virtuelles*, le tout avec une intégration fluide sur /Linux/. Il se distingue par sa *légèreté*, sa *sécurité renforcée* et sa *compatibilité* avec les technologies /cloud/, tout en offrant une *interface en ligne de commande* intuitive et une /API REST/. Idéal pour les développeurs et les administrateurs système, /Incus/ facilite le déploiement d’environnements isolés, que ce soit pour le développement, les tests ou la production, tout en restant performant et facile à prendre en main. Son approche modulaire et sa communauté active en font un outil de choix pour ceux qui recherchent une alternative flexible et transparente aux solutions propriétaires. * Installation #+BEGIN_INFO /Incus/ est compatible et disponible sur la majorité des distributions /Linux/. #+END_INFO Dans mon cas, j'ai installé /Incus/ sur une machine /Fedora 43/. Ma machine hôte est dotée de 2 cartes réseau, une qui sera utilisée pour la connexion à la machine et une autre qui sera utilisée comme pont pour les machines invitées. ** Installer le paquet /incus/ sur la machine #+BEGIN_SRC dnf install -y incus #+END_SRC ** Activer et démarrer le service /Incus/ #+BEGIN_SRC systemctl enable --now incus systemctl start incus #+END_SRC ** Configuration du /kernel/ Ces modifications sont nécessaires pour permettre au /kernel linux/ de lancer les machines virtuelles et les conteneurs. Pour aller plus loin, vous pouvez consulter [[https://docs.rockylinux.org/10/books/incus_server/01-install/#environment-set-up][cette page]]. Mettre le contenu suivant dans =/etc/sysctl.d/90-incus-override.conf= #+BEGIN_SRC ## The following changes have been made for LXD ## # fs.inotify.max_queued_events specifies an upper limit on the number of events that can be queued to the corresponding inotify instance - (default is 16384) fs.inotify.max_queued_events = 1048576 # fs.inotify.max_user_instances This specifies an upper limit on the number of inotify instances that can be created per real user ID - (default value is 128) fs.inotify.max_user_instances = 1048576 # fs.inotify.max_user_watches specifies an upper limit on the number of watches that can be created per real user ID - (default is 8192) fs.inotify.max_user_watches = 1048576 # vm.max_map_count contains the maximum number of memory map areas a process may have. Memory map areas are used as a side-effect of calling malloc, directly by mmap and mprotect, and also when loading shared libraries - (default is 65530) vm.max_map_count = 262144 # kernel.dmesg_restrict denies container access to the messages in the kernel ring buffer. Please note that this also will deny access to non-root users on the host system - (default is 0) kernel.dmesg_restrict = 1 # This is the maximum number of entries in ARP table (IPv4). You should increase this if you create over 1024 containers. net.ipv4.neigh.default.gc_thresh3 = 8192 # This is the maximum number of entries in ARP table (IPv6). You should increase this if you plan to create over 1024 containers.Not needed if not using IPv6, but... net.ipv6.neigh.default.gc_thresh3 = 8192 # This is a limit on the size of eBPF JIT allocations which is usually set to PAGE_SIZE * 40000. Set this to 1000000000 if you are running Rocky Linux 9.x net.core.bpf_jit_limit = 1000000000 # This is the maximum number of keys a non-root user can use, should be higher than the number of containers kernel.keys.maxkeys = 2000 # This is the maximum size of the keyring non-root users can use kernel.keys.maxbytes = 2000000 # This is the maximum number of concurrent async I/O operations. You might need to increase it further if you have a lot of workloads that use the AIO subsystem (e.g. MySQL) fs.aio-max-nr = 524288 #+END_SRC #+BEGIN_WARNING *Redémarrer la machine* #+END_WARNING Une fois que la machine a redémarré, lancer #+BEGIN_SRC sysctl net.core.bpf_jit_limit #+END_SRC Et vérifier que le retour est bien #+BEGIN_SRC net.core.bpf_jit_limit = 1000000000 #+END_SRC ** Initialisation d'/Incus/ Lancer la commande =incus admin init=. Le processus permet de choisir la configuration qui sera appliquée. #+BEGIN_SRC Would you like to use clustering? (yes/no) [default=no]: #+END_SRC Ce choix permet d'activer ou non le mode /cluster/, je laisse le choix par défaut (/no/) car je n'ai qu'une seule machine pour le moment. #+BEGIN_SRC Do you want to configure a new storage pool? (yes/no) [default=yes]: #+END_SRC Ici, laisser le choix par défaut (/yes/) pour configurer le stockage d'/Incus/. #+BEGIN_SRC Name of the new storage pool [default=default]: #+END_SRC Ici, il est possible de choisir le nom pour le stockage, je laisse la valeur par défaut. #+BEGIN_SRC Name of the storage backend to use (btrfs, dir, lvm, zfs, ceph) [default=zfs]: #+END_SRC Ici, il est possible de choisir le système de stockage qui sera utilisé. Dans mon cas, j'ai choisi =dir=. #+BEGIN_INFO =dir= n'est pas recommandé pour la production, mais permet d'accéder facilement aux fichiers présents dans les conteneurs sans passer par /Incus/. #+END_INFO #+BEGIN_SRC Would you like to create a new local network bridge? (yes/no) [default=yes]: What should the new bridge be called? [default=incusbr0]: What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: none #+END_SRC Laisser ces choix à leurs valeurs par défaut, il s'agit ici de configurer le réseau qui sera utilisé par nos invités. #+BEGIN_SRC Would you like the Incus server to be available over the network? (yes/no) [default=no]: yes #+END_SRC Ici, il est possible de permettre (ou non) d'accéder au serveur depuis le réseau. Je choisi /yes/ car je veux pouvoir gérer /Incus/ depuis ma machine de travail. #+BEGIN_SRC Address to bind Incus to (not including port) [default=all]: Port to bind Incus to [default=8443]: #+END_SRC Laisser ces choix à leurs valeurs par défaut aussi, il s'agit de configurer le port et l'interface sur laquelle l'/API/ d'/Incus/ se mettra en écoute. #+BEGIN_SRC Would you like stale cached images to be updated automatically? (yes/no) [default=yes]: #+END_SRC Ici, il est possible d'activer (ou non) la mise à jour automatique des images de VM ou CT. Laisser le choix par défaut (/yes/). #+BEGIN_SRC Would you like a YAML "incus admin init" preseed to be printed? (yes/no) [default=no]: #+END_SRC Laisser le choix par défaut (/no/). ** Configurer l'utilisateur d'administration Il est possible et recommandé de créer un utilisateur spécifique pour l'administration du serveur /Incus/. Dans mon cas, cet utilisateur sera =balin=. Ajouter l'utilisateur aux groupes /Incus/ : #+BEGIN_SRC usermod -aG incus-admin balin usermod -aG incus balin #+END_SRC Configurer les =subuid= et =subgid= pour l'utilisateur =root= : Dans les fichiers =/etc/subuid= et =/etc/subgid=, ajoutez la ligne suivante : #+BEGIN_SRC root:1000000:1000000000 #+END_SRC #+BEGIN_WARNING *Redémarrer la machine* #+END_WARNING ** Configuration du pare-feu / réseau #+BEGIN_INFO Les commandes données utiliseront =firewalld= car c'est le programme par défaut de /Fedora/. #+END_INFO Ajouter une zone pour le pont réseau #+BEGIN_SRC firewall-cmd --new-zone=bridge --permanent firewall-cmd --reload #+END_SRC Ajouter le pont réseau à la nouvelle zone #+BEGIN_SRC firewall-cmd --zone=bridge --add-interface=incusbr0 --permanent firewall-cmd --zone=bridge --set-target=ACCEPT --permanent firewall-cmd --reload #+END_SRC Lancer =firewall-cmd --zone=bridge --list-all= et vérifier le résultat #+BEGIN_SRC bridge (active) target: ACCEPT icmp-block-inversion: no interfaces: incusbr0 sources: services: ports: protocols: forward: no masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: #+END_SRC Créer une zone pour le réseau local #+BEGIN_SRC firewall-cmd --new-zone=local --permanent firewall-cmd --reload #+END_SRC Accepter le trafic local dans la nouvelle zone #+BEGIN_SRC firewall-cmd --zone=local --add-source=127.0.0.1/8 --permanent firewall-cmd --zone=local --set-target=ACCEPT --permanent firewall-cmd --reload #+END_SRC Vérifier la configuration de la nouvelle zone =firewall-cmd --zone=local --list all= #+BEGIN_SRC local (active) target: ACCEPT icmp-block-inversion: no interfaces: sources: 127.0.0.1/8 services: ports: protocols: forward: no masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: #+END_SRC Ajouter le réseau local dans la zone =trusted= ainsi que le service =ssh= (si pas déjà fait) #+BEGIN_SRC firewall-cmd --zone=trusted --add-source=192.168.1.0/24 firewall-cmd --zone=trusted --add-service=ssh firewall-cmd --runtime-to-permanent firewall-cmd --reload #+END_SRC *** Configuration d'un pont physique J'ai choisi d'utiliser la deuxième interface réseau de ma machine (=enp5s0f1=) pour permettre aux VMs et CTs d'accéder en direct à mon réseau local. #+BEGIN_SRC incus network create localnet --type=physical parent=enp5s0f1 #+END_SRC Pour que cela fonctionne, il est aussi nécessaire d'installer et démarrer =openvswitch= #+BEGIN_SRC dnf install -y openvswitch systemctl enable --now openvswitch systemctl start openvswitch #+END_SRC * Commandes utiles - =incus list= :: Lister toutes les instances (conteneurs et machines virtuelles). - =incus launch images:ubuntu/22.04 = :: Créer et démarrer un conteneur à partir d’une image Ubuntu 22.04. - =incus start = :: Démarrer une instance existante. - =incus stop = :: Arrêter une instance en cours d’exécution. - =incus restart = :: Redémarrer une instance. - =incus delete = :: Supprimer définitivement une instance. - =incus exec -- bash= :: Ouvrir un shell interactif dans un conteneur. - =incus file pull /chemin/vers/fichier ./= :: Copier un fichier depuis un conteneur vers la machine hôte. - =incus file push ./fichier /chemin/= :: Copier un fichier de la machine hôte vers un conteneur. - =incus config show = :: Afficher la configuration d’une instance. - =incus image list= :: Lister les images disponibles localement. - =incus profile list= :: Lister les profils de configuration disponibles. - =incus network list= :: Lister les réseaux configurés. * Lancer des conteneurs et tester Nous allons maintenant lancer deux conteneurs pour vérifier que tout fonctionne et qu'ils peuvent communiquer entre eux. Lancer les conteneurs #+BEGIN_SRC incus launch images:fedora/43 foo incus launch images:fedora/43 bar #+END_SRC Dans un premier terminal, lancer #+BEGIN_SRC incus exec foo -- bash #+END_SRC Et dans un second #+BEGIN_SRC incus exec bar -- bash #+END_SRC Normalement le =ping= entre les deux devrait fonctionner. Les deux conteneurs devraient avoir des adresses /IP/ similaires à =10.123.111.40/24=, donc des adresses /IP/ qui ne sont pas dans le réseau local mais dans le réseau d'/Incus/. * Lancer un conteneur dans le réseau local Précédemment, un pont "physique" a été créé pour permettre de connecter des VMs et CTs directement au réseau local. Créer un conteneur sans interface réseau #+BEGIN_SRC incus init images:fedora/43 testlocal #+END_SRC Lui ajouter une interface réseau #+BEGIN_SRC incus config device add testlocal eth0 nic nictype=macvlan parent=enp5s0f1 name=eth0 #+END_SRC Puis le démarrer #+BEGIN_SRC incus start testlocal #+END_SRC Finalement, ouvrir un /shell/ dans le conteneur #+BEGIN_SRC incus exec testlocal -- bash #+END_SRC Et vérifier son adresse /IP/. Il devrait avoir une interface =eth0= avec une adresse /IP/ dans le réseau local et attribuée par le routeur. * Sources - [[https://linuxcontainers.org/incus/docs/main/tutorial/first_steps/][Documentation officielle]] - [[https://docs.rockylinux.org/10/books/incus_server/00-toc/][Documentation sur /RockyLinux/]]