Dans le cadre de notre projet homelab, Ansible va par exemple nous permettre de :

  • mettre à jour les paquets logiciels sur les différents conteneurs lancés
  • installer les éventuels paquets logiciels utiles à notre programme
  • installer Julia sur nos différents conteneurs

Pour se faire il est d’abord nécessaire de s’assurer que nous pouvons établir une connexion SSH avec nos conteneurs.

Sur la machine de déploiement, nous devons d’abord installer ansible.

$ sudo apt install ansible

Nous allons d’abord créer manuellement un fichier d’inventaire. Nous verrons par la suite que nous pouvons automatiser cela.

Sur la machine de déploiement, créez toujours dans le dossier de projet ~/homelab_julia_pve_tf_ansible le fichier inventory.ini suivant :

# Groupe des serveurs LXC
# Chaque serveur est identifié par un nom logique et son adresse IP
# Les commentaires indiquent le nom du conteneur et son ID dans Proxmox
[lxc_servers]
server1_lxc ansible_host=192.168.1.201  # ubuntu-lxc-1 (241201)
server2_lxc ansible_host=192.168.1.202  # ubuntu-lxc-2 (241202)
server3_lxc ansible_host=192.168.1.203  # ubuntu-lxc-3 (241203)
server4_lxc ansible_host=192.168.1.204  # ubuntu-lxc-4 (241204)
server5_lxc ansible_host=192.168.1.205  # ubuntu-lxc-5 (241205)

# Variables communes à tous les serveurs du groupe lxc_servers
[lxc_servers:vars]
ansible_user=root

# Groupe parent incluant tous les autres groupes
[all:children]
lxc_servers

# Variables globales pour tous les serveurs
[all:vars]
ansible_ssh_private_key_file=~/.ssh/id_ed25519

Nous pouvons vérifier que notre fichier d’inventaire Ansible est correctement formé.

Vérifier la syntaxe et lister tous les hôtes

deployer@ubuntu-deploy:~/homelab_julia_pve_tf_ansible$ ansible-inventory -i inventory.ini --list
{
    "_meta": {
        "hostvars": {
            "server1_lxc": {
                "ansible_host": "192.168.1.201",
                "ansible_ssh_private_key_file": "~/.ssh/id_ed25519",
                "ansible_user": "root"
            },
            "server2_lxc": {
                "ansible_host": "192.168.1.202",
                "ansible_ssh_private_key_file": "~/.ssh/id_ed25519",
                "ansible_user": "root"
            },
            "server3_lxc": {
                "ansible_host": "192.168.1.203",
                "ansible_ssh_private_key_file": "~/.ssh/id_ed25519",
                "ansible_user": "root"
            },
            "server4_lxc": {
                "ansible_host": "192.168.1.204",
                "ansible_ssh_private_key_file": "~/.ssh/id_ed25519",
                "ansible_user": "root"
            },
            "server5_lxc": {
                "ansible_host": "192.168.1.205",
                "ansible_ssh_private_key_file": "~/.ssh/id_ed25519",
                "ansible_user": "root"
            }
        }
    },
    "all": {
        "children": [
            "ungrouped",
            "lxc_servers"
        ]
    },
    "lxc_servers": {
        "hosts": [
            "server1_lxc",
            "server2_lxc",
            "server3_lxc",
            "server4_lxc",
            "server5_lxc"
        ]
    }
}

Lister les groupes de serveur sous forme de graph

deployer@ubuntu-deploy:~/homelab_julia_pve_tf_ansible$ ansible-inventory -i inventory.ini --graph
@all:
  |--@ungrouped:
  |--@lxc_servers:
  |  |--server1_lxc
  |  |--server2_lxc
  |  |--server3_lxc
  |  |--server4_lxc
  |  |--server5_lxc

Nous allons tester en vérifiant à l’aide la commande ping que chaque conteneur répond bien à l’écho ICMP. Nous passons temporairement la variable d’environnement ANSIBLE_HOST_KEY_CHECKING=False pour cette première connexion à nos conteneurs.

deployer@ubuntu-deploy:~/homelab_julia_pve_tf_ansible$ ANSIBLE_HOST_KEY_CHECKING=False ansible all -i inventory.ini -m ping  # juste la première fois !
server1_lxc | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
server3_lxc | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
server5_lxc | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
server2_lxc | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
server4_lxc | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

Lorsque cela fonctionne correctement les résultats apparaissent en vert. Lorsqu’il y a un soucis il apparaissent en rouge

Remarque

Lorsque ANSIBLE_HOST_KEY_CHECKING=False, Ansible désactive la vérification de l’authenticité des clés d’hôte SSH. Concrètement, cela signifie que :

  1. Le système ne vérifie pas si l’empreinte de la clé publique du serveur distant correspond à une entrée dans le fichier ~/.ssh/known_hosts

  2. Il n’y a pas de protection contre les attaques de type “Man-in-the-Middle” (MITM) où un attaquant pourrait :

    • Se faire passer pour le serveur légitime
    • Intercepter les communications
    • Rediriger le trafic vers une machine malveillante

En temps normal, lors d’une première connexion SSH, le système affiche ce message de sécurité :

The authenticity of host '192.168.1.201' can't be established.
ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

Avec ANSIBLE_HOST_KEY_CHECKING=False, cette vérification est ignorée, ce qui peut être :

  • Pratique pour des environnements de test ou de développement
  • Dangereux dans un environnement de production ou sur des réseaux non sécurisés

En outre il est possible, que vous n’arriviez pas lors de l’exécution de cette commande à avoir une réponse positive de tous les conteneurs. Cela est probablement dû à la passphrase qui est demandée pour chaque conteneur. Plusieurs solutions sont possibles :

  1. Utiliser ssh-agent pour gérer les clés :
# Démarrer l'agent SSH
$ eval $(ssh-agent)
Agent pid 6793
 
# Ajouter la clé à l'agent (demande la passphrase une seule fois)
$ ssh-add ~/.ssh/id_ed25519
Enter passphrase for /home/deployer/.ssh/id_ed25519:
Identity added: /home/deployer/.ssh/id_ed25519 (deployer@ubuntu-deploy)
 
# Vérifier les identités chargées par l'agent
$ ssh-add -L
ssh-ed25519 (...) deployer@ubuntu-deploy
  1. Dans le fichier ~/ansible.cfg, configurer l’utilisation de ssh-agent :
[defaults]
# Active l'utilisation de ssh-agent
use_ssh_agent = True
  1. Pour l’automatisation complète sur des environnements de test uniquement, vous pouvez :
  • Générer une paire de clés sans passphrase
  • Utiliser cette clé spécifique pour les déploiements automatisés
# Génération d'une clé sans passphrase pour l'automatisation
ssh-keygen -t ed25519 -f ~/.ssh/ansible_automation -N ""
  1. Utiliser un gestionnaire de secrets comme HashiCorp Vault ou AWS Secrets Manager pour une approche plus sécurisée dans un environnement de production.

Note importante : L’utilisation de clés sans passphrase doit être limitée aux environnements de test/développement et jamais en production.

Il est alors possible de faire simplement

$ ansible all -i inventory.ini -m ping

Cela permet de faire un écho ICMP sur toutes les machines définit dans le fichier d’inventaire.

$ ansible lxc_servers -i inventory.ini -m ping

Permet de ne pinguer qu’un groupe particulier de serveurs.

Remarque : le fichier d’inventaire peut aussi être sous la forme d’un fichier YAML comme inventory.yml ci-dessous :

---
# Groupe des serveurs LXC
# Chaque serveur est identifié par un nom logique et son adresse IP
# Les commentaires indiquent le nom du conteneur et son ID dans Proxmox
lxc_servers:
  hosts:
    server1_lxc:
      ansible_host: 192.168.1.201  # ubuntu-lxc-1 (241201)
    server2_lxc:
      ansible_host: 192.168.1.202  # ubuntu-lxc-2 (241202)
    server3_lxc:
      ansible_host: 192.168.1.203  # ubuntu-lxc-3 (241203)
    server4_lxc:
      ansible_host: 192.168.1.204  # ubuntu-lxc-4 (241204)
    server5_lxc:
      ansible_host: 192.168.1.205  # ubuntu-lxc-5 (241205)

  # Variables communes à tous les serveurs du groupe lxc_servers
  vars:
    ansible_user: root
    ansible_ssh_private_key_file: ~/.ssh/id_ed25519

ansible