Automatisation de la construction des images Incus
Mise à jour :
J’ai besoin d’industrialiser la construction d’images Incus pour garantir que mes images soient prêtes et cohérentes. Pour cela, j’utilise habituellement Packer, un outil puissant qui permet de créer des images machine de manière automatisée. Grâce à l’existence du builder Incus, je peux facilement créer des images de conteneurs incus optimisées pour mon environnement de développement de rôles Ansible. L’objectif est d’automatiser complètement ce processus pour éviter les erreurs humaines et améliorer l’efficacité des déploiements.
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.
Installation des prérequis
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 que Incus est correctement installé et configuré dans ton environnement. Le builder Packer pour Incus nécessite que Incus soit accessible pour générer les images de conteneurs. Plus d’infos ici/docs/conteneurs/moteurs-conteneurs/incus/
Création du fichier de configuration Packer
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 :
packer { required_plugins { incus = { version = ">= 1.0.0" source = "github.com/bketelsen/incus" } }}
source "incus" "noble" { image = "images:ubuntu/noble" output_image = "ubuntu-nobble-ansible" reuse = true}
build { sources = ["incus.noble"] provisioner "shell" { scripts = [ "scripts/ubuntu-noble/init.sh", ] }}
Dans cet exemple, le builder Incus utilise une image de base Ubuntu 24.04 pour créer une nouvelle image. Le bloc provisioner exécute des commandes pour configuer l’image pour être utilisé avec Ansible.
Le script bash :
apt updateapt install -y openssh-server python3 sudouseradd -m -s /bin/bash ansiblemkdir -p /home/ansible/.sshecho 'ssh-ed25519 xxxxxxxxxxxx' > /home/ansible/.ssh/authorized_keyschown -R ansible:ansible /home/ansible/.sshchmod 600 /home/ansible/.ssh/authorized_keysecho 'ansible ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/ansiblePASSWD=$(date | md5sum | cut -c1-8)echo "ansible:$PASSWD" | chpasswd
Exécution du build avec Packer
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 :
packer build ubuntu-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.
Vérification de l’image générée
Une fois l’image créée, tu peux la retrouver dans Incus en vérifiant la liste des images disponibles. Tu peux utiliser la commande suivante pour lister les images dans Incus :
incus image list
+-----------------------+--------------+--------+----------------------------------------+--------------+-----------+-----------+-----------------------+| ubuntu-nobble-ansible | c6602a03500c | no | Ubuntu noble amd64 (20241015_07:42) | x86_64 | CONTAINER | 203.71MiB | 2024/10/16 21:06 CEST |+-----------------------+--------------+--------+----------------------------------------+--------------+-----------+-----------+-----------------------+
Options supplémentaires du builder Incus
En plus des options vu ci-dessus, e builder Incusoffre plusieurs paramètres optionnels pour ajuster la création d’images.
reuse
: Permet de réutiliser un alias d’image existant.publish_remote_name
: Publie l’image sur un remote spécifique d’Incus.init_sleep
: Définit le délai (en secondes) entre le lancement et le provisionnement.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 ↗.
Je rencontre des difficultés à utiliser le provisioner Ansible de Packer en conjonction avec la connexion Incus. Bien que Packer semble bien créer et démarrer les conteneurs, le provisionnement avec Ansible ne fonctionne pas comme prévu. Il semble y avoir un problème de compatibilité entre le plugin Incus et la connexion Ansible attendue par Packer. Cela m’empêche d’automatiser correctement la configuration des images via Ansible, ce qui me pousse à vous proposer une solution alternative.
Création d’une image avec Ansible
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.
Avant, vous devez installer la collection community.general
:
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/12 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 :
-
Création d’une instance : Le code lance une instance Debian 12 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.
-
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.
-
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 :
ansible-playbook incus.yml -i debian-ansible,
Il faudrait juste encore trouver le code d’un inventaire dynamique.
Plus loin
Je suis en train de découvrir Incus et j’explore comment stocker les images créées localement dans une registry. Mon objectif est de trouver une manière simple et efficace de gérer ces images au sein de mon infrastructure. Une fois que j’aurai maîtrisé cette partie, je vais intégrer ce processus dans un pipeline CI/CD. Cela permettra d’automatiser complètement la création, le test et le déploiement des images, assurant ainsi un workflow de déploiement fluide et reproductible. Je vais aussi m’assurer que chaque nouvelle image est immédiatement disponible dans la registry pour les environnements de production.