SSD Nodes Learn 🎉 VPS dès $5.50/mois
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-08-07

Ansible ou Terraform : lequel choisir ?

Terraform crée le VPS, Ansible le configure. Comprenez la vraie séparation, les provisioners à éviter, les commandes de relais et les cas où Ansible suffit.

Ansible et Terraform en une phrase

Ansible et Terraform ne sont pas deux outils qui effectuent le même travail. Terraform déclare l’infrastructure qui existe : serveurs, disques, réseaux et enregistrements DNS. Ansible déclare l’état attendu à l’intérieur d’une machine qui existe déjà : paquets, utilisateurs, fichiers de configuration et services en cours d’exécution. Terraform crée le VPS. Ansible transforme ce VPS en serveur web.

Les deux outils sont déclaratifs et relèvent de l’infrastructure as code (IaC). La vraie différence concerne ce qu’ils mémorisent. Terraform écrit un fichier d’état qui associe chaque ressource de votre code à un objet réel créé via une API. Il peut ainsi comprendre que la suppression de cinq lignes implique la destruction d’un serveur. Ansible ne conserve aucun état entre deux exécutions. Il se connecte en SSH, inspecte la machine et ne modifie que ce qui ne correspond pas déjà au playbook.

Cette seule différence explique le reste de ce guide, notamment pourquoi mélanger ces deux rôles dans un même outil entraîne des problèmes.

Ce que Terraform fait réellement

Terraform communique avec une API par l’intermédiaire d’un plugin provider. La page du registre de votre provider définit les types de ressources que vous pouvez déclarer. Un serveur sur un hôte et un serveur sur un autre hôte portent donc des noms de ressources différents et acceptent des arguments différents.

resource "cloud_server" "web" {
  name  = "web1"
  image = "ubuntu-24.04"
  type  = "small"
}

output "web_ip" {
  value = cloud_server.web.ipv4_address
}

Remplacez cloud_server par le type de ressource documenté par votre provider. Le bloc output est la partie importante de ce guide, car c’est lui qui permet à l’adresse de quitter Terraform.

terraform init
terraform fmt -check
terraform validate
terraform plan -out=tfplan
terraform apply tfplan

terraform init télécharge le provider et écrit un fichier de verrouillage. terraform plan affiche la différence entre votre code et le fichier d’état, puis se termine par une ligne comme Plan: 1 to add, 0 to change, 0 to destroy.. Lisez cette ligne à chaque fois. Certains arguments ne peuvent pas être modifiés sur place. Le plan l’indique avec # forces replacement à côté de l’attribut, suivi de 1 to add, 0 to change, 1 to destroy. L’application de ce plan supprime le serveur et en crée un nouveau vide. C’est ainsi que des utilisateurs perdent des données qu’ils pensaient protégées.

Enregistrez le plan dans un fichier, puis appliquez ce fichier au lieu d’exécuter un terraform apply sans argument. Vous vous assurez ainsi que le plan que vous avez vérifié est bien celui qui sera appliqué. Entre les deux commandes, une autre personne peut avoir modifié l’infrastructure.

terraform.tfstate contient l’état. Si vous le perdez, Terraform ne sait plus que ces serveurs vous appartiennent. La prochaine application tente alors d’en créer des doublons. Stockez cet état dans un backend distant dès que plusieurs personnes exécutent les commandes, car deux applications simultanées produisent ceci :

Error: Error acquiring the state lock

OpenTofu est un fork de Terraform qui utilise les mêmes commandes et le même format de fichier. En juillet 2026, tout ce guide fonctionne si vous saisissez tofu au lieu de terraform.

Ce qu’Ansible fait réellement

Ansible n’a besoin ni d’agent ni d’API. Il ouvre une connexion SSH, copie un petit module Python sur la cible, l’exécute, puis le supprime. Tout ce que vous pouvez atteindre avec SSH et un mot de passe sudo, Ansible peut le configurer.

- name: Base web server
  hosts: web
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.apt:
        name: nginx
        state: present
        update_cache: true

    - name: Ensure nginx is running at boot
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true
ansible -i inventory.ini web -m ansible.builtin.ping
ansible-playbook -i inventory.ini site.yml --check --diff
ansible-playbook -i inventory.ini site.yml

Le module ping vérifie SSH, Python et sudo avant que vous commenciez à déboguer un playbook. Un résultat correct est web1 | SUCCESS => {"ping": "pong"}. L’exécution --check --diff est ce qui se rapproche le plus d’un plan dans Ansible : elle indique les changements qui seraient effectués sans les appliquer. Toutefois, les tâches qui dépendent de tâches précédentes peuvent produire un résultat incorrect en mode check, car le changement précédent n’a pas réellement été effectué.

Chaque exécution se termine par un récapitulatif tel que ok=6 changed=2 unreachable=0 failed=0. Exécutez le même playbook deux fois. La deuxième exécution doit indiquer changed=0. Une tâche qui signale un changement à chaque exécution n’est pas idempotente. Il s’agit généralement d’une tâche command ou shell qui aurait dû utiliser un véritable module. Si ce sujet est nouveau pour vous, commencez par un premier playbook Ansible sur un VPS unique, puis développez votre configuration à partir de là.

Chevauchement des deux outils et conflits possibles

Terraform peut exécuter des commandes sur un nouveau serveur avec le provisioner remote-exec. La documentation de HashiCorp présente elle-même les provisioners comme un dernier recours. Pour de bonnes raisons.

Un provisioner ne s’exécute que lors de la création de la ressource. Si vous modifiez le script, rien ne se passe sur le serveur existant, car, du point de vue de Terraform, la ressource correspond déjà au code. Les étapes du provisioner n’apparaissent jamais dans terraform plan ; votre review n’en montre donc aucune trace. Si le script échoue, Terraform marque la ressource comme tainted, puis le prochain apply détruit et recrée un serveur qui fonctionnait probablement correctement.

L’échec survient aussi au mauvais moment. Le provider signale que le serveur est créé dès que l’API le confirme, alors que le système d’exploitation est encore en cours de démarrage et que sshd n’est pas encore en écoute.

Error: remote-exec provisioner error
timeout - last error: dial tcp 203.0.113.10:22: connect: connection refused

Ansible présente la tentation inverse. Ses modules cloud peuvent créer des serveurs, et cette approche fonctionne pour quelques machines. En contrepartie, vous perdez le graphe de dépendances et le fichier d’état. Ansible crée volontiers une ressource, mais si vous supprimez la tâche de votre playbook, la ressource continue de fonctionner et reste facturée, car rien n’a enregistré qu’elle vous appartenait.

La règle qui en découle est la suivante : laissez Terraform gérer les objets qu’une API crée et détruit, et laissez Ansible gérer tout ce qui se trouve à l’intérieur d’un système d’exploitation démarré.

Le passage de relais, en pratique

Le passage de relais est une frontière, pas une intégration. Terraform termine son exécution, publie une adresse, puis s’arrête. Ansible démarre à partir de cette adresse.

terraform apply -auto-approve
terraform output -raw web_ip
printf '[web]\n%s ansible_user=root\n' "$(terraform output -raw web_ip)" > inventory.ini
ansible -i inventory.ini web -m ansible.builtin.ping
ansible-playbook -i inventory.ini site.yml

terraform output -raw affiche une valeur sans guillemets ni enveloppe JSON. C’est exactement ce qu’il faut dans une substitution de shell. Pour plusieurs serveurs, utilisez terraform output -json et construisez l’inventaire à partir de sa sortie, car -raw ne gère qu’une seule chaîne, un seul nombre ou une seule valeur booléenne.

L’étape ping entre les deux outils mérite d’être conservée. Elle permet de distinguer « Terraform m’a fourni la mauvaise adresse » de « mon playbook contient un bug ». Ces deux problèmes semblent identiques lorsque le playbook est le premier élément à se connecter à la nouvelle machine.

Lire l’état Terraform comme inventaire Ansible

Si vous préférez ne pas écrire de fichier d’inventaire, la collection cloud.terraform lit directement l’état.

ansible-galaxy collection install cloud.terraform

Créez terraform.yml à côté de votre playbook :

plugin: cloud.terraform.terraform_provider
project_path: /home/deploy/infra
ansible-inventory -i terraform.yml --graph
ansible-playbook -i terraform.yml site.yml

Deux points sont à connaître avant de vous appuyer dessus. Le plugin exécute terraform show sur project_path. Ce répertoire doit donc déjà être initialisé, sinon le plugin échoue. Il ne crée pas non plus automatiquement des hôtes à partir de vos ressources serveur. Il lit les ressources ansible_host et ansible_group, que vous déclarez dans votre code Terraform avec le provider Ansible. Rien n’apparaît dans ansible-inventory --graph tant que vous ne les avez pas ajoutées.

Un fichier d’inventaire généré classique est plus facile à déboguer et fonctionne avec n’importe quel provider. Le plugin devient utile lorsque l’inventaire dépasse quelques machines et que les modifications manuelles commencent à introduire des fautes de frappe. C’est également à ce stade que gérer plusieurs serveurs Linux depuis une même machine de contrôle devient un véritable workflow plutôt qu’une simple habitude.

Avez-vous réellement besoin de Terraform ?

La plupart des lecteurs de ce guide n’en ont pas besoin, du moins pas encore. Terraform devient rentable lorsque la création et la suppression de l’infrastructure sont des opérations récurrentes. Si vous avez commandé un seul VPS depuis un control panel et prévoyez de le conserver pendant deux ans, Terraform décrit une opération qui n’a lieu qu’une fois et ajoute un fichier d’état que vous ne devez pas perdre.

Utilisez Terraform lorsque vous reconstruisez souvent vos environnements, lorsque la staging doit correspondre exactement à la production, lorsque plusieurs personnes modifient l’infrastructure et que vous voulez examiner un plan avant toute suppression, ou lorsque ce que vous gérez dépasse les serveurs et inclut des enregistrements DNS, des load balancers et des règles de firewall exposés par l’API d’un provider.

Restez avec Ansible seul lorsque les serveurs ont une longue durée de vie et sont peu nombreux, et lorsque la question quotidienne est « ce serveur est-il correctement configuré ? » plutôt que « ce serveur existe-t-il ? ». Un playbook unique qui sécurise un serveur fraîchement installé couvre le même périmètre que les dix premières minutes sur un nouveau VPS, avec l’avantage de s’exécuter de la même manière sur le serveur suivant.

L’ordre d’apprentissage en découle. Ansible devient utile dès le premier serveur dont vous avez la responsabilité. Terraform devient utile à partir du troisième environnement que vous reconstruisez.

Ce qui casse lors du passage de relais

Le serveur n’est pas prêt. Terraform se termine correctement, mais Ansible échoue immédiatement.

fatal: [web1]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 203.0.113.10 port 22: Connection refused", "unreachable": true}

L’API a renvoyé une adresse avant que sshd soit en écoute. Attendez l’ouverture du port au lieu d’ajouter une temporisation fixe. Ansible fournit ansible.builtin.wait_for_connection précisément pour cela ; exécutez-le comme première tâche du play.

La clé d’hôte a changé. Vous avez détruit et recréé le serveur, et le nouveau répond sur la même adresse avec une nouvelle clé.

Host key verification failed.

Supprimez l’entrée obsolète avec ssh-keygen -R 203.0.113.10. Cela se produit constamment lorsque Terraform reconstruit les ressources. C’est une bonne raison de limiter les reconstructions sur les machines qui contiennent des données.

Sudo échoue. fatal: [web1]: FAILED! => {"msg": "Missing sudo password"} signifie que become: true nécessite un mot de passe sur cet hôte. Configurez sudo sans mot de passe pour l’utilisateur de déploiement ou transmettez --ask-become-pass.

Terraform veut détruire une ressource que vous n’avez pas modifiée. Le plan affiche des changements que vous n’avez jamais écrits. Cela signifie que l’infrastructure réelle a divergé du code, généralement parce qu’une personne a modifié un paramètre dans le panneau web du provider. Exécutez terraform plan -refresh-only pour afficher uniquement cette différence, puis déterminez si le code ou la ressource réelle est incorrect. N’appliquez jamais un plan destructif que vous ne pouvez pas expliquer ligne par ligne.

Ansible indique changed à chaque exécution. Une tâche shell sans garde creates ou when s’exécute systématiquement. Ce n’est pas un simple problème d’affichage, car vous ne pouvez alors plus utiliser changed=0 pour vérifier qu’un serveur se trouve dans l’état demandé.

FAQ

Terraform peut-il remplacer Ansible ?

Pas pour la configuration à l’intérieur d’un serveur. Terraform peut exécuter des scripts avec le provisioner remote-exec, mais ceux-ci ne s’exécutent qu’à la création de la ressource, n’apparaissent jamais dans terraform plan et marquent la ressource comme défaillante lorsqu’ils échouent. Cela planifie sa suppression et sa recréation lors du prochain apply. Terraform ne possède pas d’équivalent à un module qui vérifie si nginx est déjà installé et ne fait rien dans ce cas. Utilisez Terraform pour créer la machine, puis passez le relais.

Ansible peut-il remplacer Terraform ?

Pour un petit nombre de serveurs persistants, oui. Ansible dispose de modules cloud qui créent des serveurs. Si vous commandez deux instances VPS et les conservez, cela suffit. En revanche, vous perdez le state file et le dependency graph : si vous supprimez une tâche du playbook, la ressource continue de fonctionner et d’être facturée, car Ansible n’a jamais enregistré sa création. Terraform aurait planifié sa suppression.

Lequel dois-je apprendre en premier ?

Ansible, si vous administrez déjà des serveurs. Il est utile dès la première machine, ne nécessite rien d’autre que SSH et ces compétences s’appliquent à un serveur que vous avez commandé manuellement. Terraform devient utile plus tard, lorsque vous reconstruisez régulièrement des environnements ou gérez des ressources du provider autres que les serveurs, comme des enregistrements DNS et des règles de firewall.

Comment transmettre à Ansible l’adresse IP du nouveau serveur depuis Terraform ?

Déclarez un output dans votre code Terraform, puis lisez-le après l’apply. terraform output -raw web_ip affiche la valeur brute pour une substitution shell, tandis que terraform output -json fournit toutes les outputs en une fois lorsqu’il y a plusieurs hôtes. Écrivez cette valeur dans un fichier d’inventory, ou installez la collection cloud.terraform et indiquez à ansible-inventory -i terraform.yml --graph le répertoire du projet.

Pourquoi mon playbook échoue-t-il juste après la fin de Terraform ?

Le provider signale que le serveur est créé dès que son API l’indique, alors que le système d’exploitation est encore en cours de démarrage. SSH est donc refusé pendant les premières secondes. L’erreur est UNREACHABLE! avec Connection refused. Faites de ansible.builtin.wait_for_connection la première tâche du play au lieu de choisir arbitrairement une durée d’attente, car le temps de démarrage varie selon l’image et le plan.