SSD Nodes Learn Hosting plans →
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-08-22

Ansible ou Terraform : lequel choisir ?

Terraform crée le VPS, Ansible le configure. Comprenez la séparation des rôles, le passage de relais, les provisioners et les cas où Ansible seul suffit.

Ansible et Terraform en une phrase

Ansible et Terraform ne sont pas deux outils qui exécutent le même travail. Terraform déclare les éléments qui composent l’infrastructure : serveurs, disques, réseaux et enregistrements DNS. Ansible déclare l’état attendu 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 donc déterminer que la suppression de cinq lignes implique la destruction d’un serveur. Ansible ne conserve aucun état entre deux exécutions. Il se connecte via 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 seul 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. Ainsi, un serveur sur un hôte et un serveur sur un autre hôte correspondent à des noms de ressources différents, avec 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 détermine vers quelle adresse Terraform envoie la requête.

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, en terminant 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.

Enregistrer le plan dans un fichier, puis appliquer ce fichier, plutôt que d’exécuter un simple terraform apply, garantit que le plan vérifié est bien celui qui sera exécuté. Quelqu’un d’autre peut avoir modifié l’infrastructure entre les deux commandes.

terraform.tfstate contient l’état. Si vous le perdez, Terraform ne sait plus que ces serveurs vous appartiennent. Le prochain apply tente alors de créer des doublons. Conservez cet état dans un backend distant dès que plusieurs personnes exécutent les commandes. Deux exécutions 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 à la place 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 qui est accessible avec SSH et un mot de passe sudo peut être configuré par Ansible.

- 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 ce qui serait modifié sans rien modifier. Toutefois, les tâches qui dépendent de tâches précédentes peuvent produire un résultat incorrect en mode check, car la modification précédente n’a en réalité pas eu lieu.

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 indique changed à 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 vous découvrez ce sujet, commencez par un premier playbook Ansible sur un VPS unique, puis développez votre configuration à partir de là.

Là où les deux outils se recouvrent et se gênent

Terraform peut exécuter des commandes sur un nouveau serveur avec le provisioner remote-exec. La documentation de HashiCorp recommande elle-même de n’utiliser les provisioners qu’en 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 d’un provisioner n’apparaissent jamais dans terraform plan. Votre revue ne montre donc aucune trace de ces étapes. Si le script échoue, Terraform marque la ressource comme à recréer, puis le prochain apply détruit et reconstruit 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 revanche, 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é.

La transmission, correctement effectuée

La transmission est une limite, 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 ce qu’il faut dans une substitution de shell. Pour plusieurs serveurs, utilisez terraform output -json et construisez l’inventaire à partir de son résultat, 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 à accéder à la nouvelle machine.

Lecture de 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

Placez 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 d’hôtes à partir de vos ressources serveur : il lit les ressources ansible_host et ansible_group, que vous déclarez dans votre code Terraform à l’aide du 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 intéressant lorsque l’inventaire dépasse quelques machines et que les modifications manuelles commencent à produire des erreurs de saisie. C’est aussi à ce stade que gérer plusieurs serveurs Linux depuis une seule machine de contrôle devient un véritable workflow plutôt qu’une simple habitude.

Avez-vous vraiment besoin de Terraform ?

La plupart des personnes qui lisent 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 elles-mêmes des tâches répétées. Si vous avez commandé un seul VPS depuis un panneau de contrôle 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 l’environnement de 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 sont durables et 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 vierge 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 que vous administrez. Terraform devient utile lorsque vous reconstruisez votre troisième environnement.

Ce qui peut échouer lors du transfert

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 n’écoute. Attendez que le port soit disponible au lieu d’ajouter un délai fixe. Ansible fournit ansible.builtin.wait_for_connection pour cela précisément ; exécutez-le comme première tâche du play. Dès que le même playbook cible un groupe plutôt qu’un serveur fraîchement créé, déterminez à l’avance ce qui doit se passer lorsqu’un hôte reste inaccessible, car Ansible retire cet hôte du reste de l’exécution et la ligne de récapitulatif est le seul endroit où il vous l’indique.

La clé d’hôte a changé. Vous avez détruit et recréé le serveur, et le nouveau répond à 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 dès que Terraform reconstruit les serveurs. C’est une bonne raison de limiter les reconstructions sur les machines qui hébergent 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 destructeur que vous ne pouvez pas expliquer ligne par ligne.

Ansible signale un changement à 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 ces scripts 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 destruction et sa recréation lors du prochain apply. Terraform n’a 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 la main.

Ansible peut-il remplacer Terraform ?

Pour un petit nombre de serveurs conservés longtemps, oui. Ansible possède des modules cloud qui créent des serveurs. Si vous commandez deux instances VPS et les conservez, cela suffit. En revanche, vous perdez le fichier d’état et le graphe des dépendances : si vous retirez une tâche du playbook, la ressource continue de fonctionner et d’être facturée, car Ansible n’enregistre jamais qu’il l’a créée. Terraform aurait planifié sa destruction.

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 commandé manuellement. Terraform devient utile plus tard, lorsque vous recréez régulièrement des environnements ou gérez des ressources du provider autres que des 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 sorties en une seule fois lorsqu’il y a plusieurs hôtes. Écrivez cette valeur dans un fichier d’inventaire, 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 indique que le serveur est créé dès que son API le signale, 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 deviner une durée de sleep, car le temps de démarrage varie selon l’image et le plan.