Aller au contenu
Conteneurs & Orchestration medium

Automatisation de la construction des images Incus

10 min de lecture

logo incus

Construire des images Incus à la main ne passe pas à l'échelle. Ce guide industrialise cette construction par deux voies : Packer avec son builder Incus, et Ansible avec le connection plugin, pour produire des images reproductibles et publiables. On y voit un template Packer complet, le playbook Ansible équivalent, et la publication de l'image dans Incus. Les commandes sont valables sur Incus 7.0.

  • Construire une image avec un template Packer (builder Incus).
  • Faire la même chose avec un playbook Ansible.
  • Publier l'instance configurée en image réutilisable.
  • Choisir entre les deux approches selon le contexte.

Création d’une image personnalisée avec Packer

Section intitulée « Création d’une image personnalisée avec Packer »

Dans cette section, je vais vous guider à travers le processus de création d’une image personnalisée avec Packer en utilisant le builder Incus. Ce builder permet de construire des images de conteneurs compatibles avec l’environnement Incus tout en offrant les avantages d’automatisation et de reproductibilité que Packer fournit.

Avant de commencer, il est nécessaire d'installer Packer. Il est disponible sur le site officiel et peut être installé via des gestionnaires de paquets comme apt sur Linux, brew sur macOS, ou via un binaire sur Windows. Plus d'infos ici

Ensuite, assurez-vous qu'Incus est correctement installé et configuré dans votre environnement. Le builder Packer pour Incus a besoin qu'Incus soit accessible pour générer les images de conteneurs. Voir l'installation d'Incus au besoin.

La création d’une image avec Packer repose sur un template (modèle) au format JSON ou HCL qui définit comment l’image sera construite. Voici un exemple de fichier HCL simple pour une image Incus :

debian-incus.pkr.hcl
packer {
required_plugins {
incus = {
version = ">= 1.0.0"
source = "github.com/bketelsen/incus"
}
}
}
source "incus" "trixie" {
image = "images:debian/13"
output_image = "debian-ansible"
reuse = true
}
build {
sources = ["incus.trixie"]
provisioner "shell" {
scripts = [
"scripts/debian/init.sh",
]
}
}

Dans cet exemple, le builder Incus utilise une image de base Debian 13 pour créer une nouvelle image. Le bloc provisioner exécute des commandes qui configurent l'image pour l'usage avec Ansible.

Le script bash :

scripts/debian/init.sh
apt update
apt install -y openssh-server python3 sudo
useradd -m -s /bin/bash ansible
mkdir -p /home/ansible/.ssh
echo 'ssh-ed25519 xxxxxxxxxxxx' > /home/ansible/.ssh/authorized_keys
chown -R ansible:ansible /home/ansible/.ssh
chmod 600 /home/ansible/.ssh/authorized_keys
echo 'ansible ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/ansible
PASSWD=$(date | md5sum | cut -c1-8)
echo "ansible:$PASSWD" | chpasswd

Pour lancer la création de l’image, il suffit d’exécuter la commande suivante dans le terminal, à partir du répertoire où se trouve le fichier de configuration HCL :

Fenêtre de terminal
packer build debian-incus.pkr.hcl

Packer va alors lire le template, utiliser le builder incus pour télécharger l'image de base définie, exécuter le script de provisionnement pour configurer l’image, puis la rendre disponible localement.

Une fois l’image créée, vous la retrouvez dans Incus en vérifiant la liste des images disponibles :

Fenêtre de terminal
incus image list debian-ansible
+----------------+--------------+--------+--------------------------------------+--------------+-----------+-----------+----------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE |
+----------------+--------------+--------+--------------------------------------+--------------+-----------+-----------+----------------------+
| debian-ansible | 0fb77aa067dc | no | Debian trixie amd64 (20260630_05:24) | x86_64 | CONTAINER | 184.26MiB | 2026/07/01 07:59 UTC |
+----------------+--------------+--------+--------------------------------------+--------------+-----------+-----------+----------------------+

En plus des options vues ci-dessus, le builder Incus offre plusieurs paramètres optionnels pour ajuster la création d'images.

  1. reuse : Permet de réutiliser un alias d’image existant.
  2. publish_remote_name : Publie l’image sur un remote spécifique d'Incus.
  3. init_sleep : Définit le délai (en secondes) entre le lancement et le provisionnement.
  4. virtual_machine : Crée une image de machine virtuelle plutôt qu’une image de conteneur.

Ces options apportent plus de flexibilité pour des scénarios avancés. Plus d'infos ici.

Point d'attention terrain : coupler le provisioner Ansible de Packer à la connexion Incus reste fragile. Packer crée et démarre bien le conteneur, mais le provisionnement Ansible via le plugin Incus ne s'enchaîne pas toujours correctement. Quand ce couplage pose problème, une approche 100 % Ansible est plus robuste et se passe entièrement de Packer.

On peut utiliser Ansible avec le plugin de connexion Incus pour automatiser la création et la configuration d’images directement sur des conteneurs, sans passer par Packer. Ce plugin permet à Ansible de traiter les conteneurs Incus comme des machines distantes, facilitant ainsi l’exécution des rôles et playbooks. Le fonctionnement du connection plugin est détaillé dans le guide Gérer Incus avec Ansible.

Avant, vous devez installer la collection community.general :

Fenêtre de terminal
ansible-galaxy collection install community.general

Voici le playbook faisant les mêmes opérations que celles avec Packer.

---
- name: Create instance
hosts: localhost
connection: local
tasks:
- name: Create instance
ansible.builtin.shell:
cmd: incus launch images:debian/13 debian-ansible
creates: debian-ansible.ok
- name: Create instance
ansible.builtin.shell:
cmd: incus start debian-ansible
- name: Create flag
ansible.builtin.file:
path: debian-ansible.ok
state: touch
- name: Run command in container
hosts: debian-ansible
connection: community.general.incus
gather_facts: false
vars:
pwd: "{{ lookup('password', '/dev/null length=15 chars=ascii_letters') }}"
tasks:
- name: Install packages
ansible.builtin.raw: apt install -y python3
args:
executable: /usr/bin/bash
- name: Create user
ansible.builtin.user:
name: ansible
shell: /usr/bin/bash
password: "{{ pwd }}"
state: present
create_home: true
home: /home/ansible
- name: Copy SSH Key
ansible.posix.authorized_key:
user: ansible
state: present
key: "{{ lookup('file', item) }}"
with_fileglob:
- ~/.ssh/id_ed25519.pub
- name: Add user to sudoers
community.general.sudoers:
user: ansible
name: ansible
nopassword: true
commands: ALL
state: present
- name: Create instance
hosts: localhost
connection: local
tasks:
- name: Stop instance
ansible.builtin.shell:
cmd: incus stop debian-ansible
removes: debian-ansible.ok
- name: Create Image
ansible.builtin.shell:
cmd: incus publish --alias debian_ansible debian-ansible --reuse
removes: debian-ansible.ok
- name: Delete flag
ansible.builtin.file:
path: debian-ansible.ok
state: absent

Ce code Ansible est divisé en plusieurs étapes :

  1. Création d'une instance : Le code lance une instance Debian 13 avec Incus et crée un fichier de flag pour marquer la création réussie de l'instance. L'instance est ensuite démarrée.

  2. Exécution de commandes dans le conteneur : Ansible se connecte à l'instance via Incus et exécute plusieurs tâches : installer Python3, créer un utilisateur ansible avec un mot de passe aléatoire, copier une clé SSH et ajouter l’utilisateur aux sudoers.

  3. Création de l’image : Une fois les configurations effectuées, l’instance est arrêtée et publiée en tant qu’image nommée debian_ansible dans Incus. Le fichier de flag est supprimé.

La commande reste habituelle car j'ai mis les paramètres dans le playbook :

Fenêtre de terminal
ansible-playbook incus.yml -i debian-ansible,

L'inventaire peut aussi être peuplé dynamiquement par le plugin d'inventaire community.general.incus, plutôt que passé en ligne de commande. Cette construction d'image s'intègre ensuite naturellement dans un pipeline CI/CD pour publier chaque nouvelle image automatiquement.

  • Deux voies pour industrialiser : le builder Packer Incus, ou un playbook Ansible de bout en bout.
  • Le couplage Packer + provisioner Ansible reste fragile ; l'approche tout-Ansible est plus robuste.
  • Le playbook lance une instance, la configure via le connection plugin, puis la publie en image.
  • incus publish --alias transforme une instance arrêtée en image réutilisable.
  • L'image publiée apparaît dans incus image list avec son fingerprint, sa taille et sa date.

FAQ : questions fréquentes sur l'automatisation des images Incus

Section intitulée « FAQ : questions fréquentes sur l'automatisation des images Incus »

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn