ITSkillsCenter
Blog

Terraform et Ansible : infrastructure as code en pratique

12 دقائق للقراءة

Lecture : 11 minutes · Niveau : intermédiaire-avancé · Mise à jour : avril 2026

L’Infrastructure as Code transforme la manière dont une équipe gère ses serveurs. Au lieu de configurer manuellement chaque machine et de prier pour s’en souvenir, on décrit l’état désiré dans des fichiers versionnés et un outil applique cet état. Terraform et Ansible sont les deux références complémentaires : Terraform pour provisionner (créer les ressources), Ansible pour configurer (préparer ce qui tourne dessus).

Voir aussi → DevOps moderne pour PME : guide CI/CD et IaC.


Sommaire

  1. Terraform vs Ansible : différences claires
  2. Terraform : premier projet Hetzner
  3. State Terraform et bonnes pratiques
  4. Modules Terraform pour réutilisation
  5. Ansible : structure d’un projet propre
  6. Playbooks et rôles Ansible
  7. Vault Ansible pour les secrets
  8. Combiner Terraform et Ansible
  9. FAQ

1. Terraform vs Ansible : différences claires

Confondre les deux outils est l’erreur la plus courante.

Terraform (terraform.io) est un outil de provisioning déclaratif : on décrit ce qu’on veut (« je veux 2 serveurs Hetzner cx21 dans la région fsn1, avec une clé SSH admin »), Terraform calcule la différence entre l’état actuel et l’état désiré, et applique les changements. Il maintient un fichier state qui sait exactement ce qui existe. Il excelle pour cloud public, DNS, certificats, comptes, ressources managées.

Ansible (ansible.com) est un outil de configuration impérative : on décrit des étapes (« installer nginx, déposer cette config, redémarrer le service »), Ansible se connecte en SSH et les exécute. Il n’a pas de state, il converge à chaque exécution vers l’état décrit (idempotence). Il excelle pour configurer ce qui tourne sur les serveurs, déployer des applications, orchestrer des opérations.

Cas d’usage type : Terraform crée 3 serveurs vides, puis Ansible les configure (Docker, Nginx, certificats Let’s Encrypt). C’est la division de travail typique en IaC.


2. Terraform : premier projet Hetzner

Hetzner Cloud est un excellent choix PME : prix bas, datacenters européens, API stable. Le provider Terraform officiel est mature.

# main.tf
terraform {
  required_version = ">= 1.6"
  required_providers {
    hcloud = {
      source  = "hetznercloud/hcloud"
      version = "~> 1.45"
    }
  }
}

variable "hcloud_token" {
  type      = string
  sensitive = true
}

provider "hcloud" {
  token = var.hcloud_token
}

resource "hcloud_ssh_key" "admin" {
  name       = "admin"
  public_key = file("~/.ssh/id_ed25519.pub")
}

resource "hcloud_server" "web" {
  name        = "web-prod-1"
  server_type = "cx21"
  image       = "ubuntu-24.04"
  location    = "fsn1"
  ssh_keys    = [hcloud_ssh_key.admin.id]
  user_data   = file("cloud-init.yml")

  labels = {
    env  = "production"
    role = "web"
  }
}

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

Workflow standard :

# Initialiser (télécharge le provider)
terraform init

# Voir ce qui serait créé
terraform plan

# Créer
terraform apply

# Détruire (attention !)
terraform destroy

Le token Hetzner se passe en variable d’environnement (TF_VAR_hcloud_token) ou dans un fichier .tfvars qui n’est jamais commité dans Git.


3. State Terraform et bonnes pratiques

Terraform maintient un fichier terraform.tfstate qui décrit l’état actuel de l’infrastructure. Ce fichier est critique : sa perte ou sa corruption compromet la cohérence de l’outil avec la réalité.

Backend distant obligatoire en équipe

Stocker le state localement marche pour un seul utilisateur en exploration. Dès qu’une équipe travaille à plusieurs ou qu’un pipeline CI/CD applique du Terraform, il faut un backend distant avec verrouillage :

terraform {
  backend "s3" {
    bucket         = "ma-pme-terraform-state"
    key            = "production/terraform.tfstate"
    region         = "eu-central-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

Alternatives : Terraform Cloud (gratuit jusqu’à 5 utilisateurs), Scaleway Object Storage, Hetzner Object Storage, Azure Blob, GCP Cloud Storage. L’idée est la même : un stockage centralisé, chiffré, avec verrouillage pour éviter deux apply simultanés.

Ne jamais éditer le state à la main

Toute modification doit passer par les commandes Terraform : terraform import pour intégrer une ressource créée hors Terraform, terraform state mv pour renommer, terraform state rm pour retirer. Éditer directement le JSON casse facilement.

Workspaces ou répertoires séparés ?

Pour environnements multiples (dev, staging, prod), deux approches : workspaces Terraform (un même code, des states séparés), ou répertoires séparés avec leur propre backend. Pour une PME, les répertoires séparés sont souvent plus clairs : infrastructure/staging/ et infrastructure/production/ chacun avec son main.tf.


4. Modules Terraform pour réutilisation

Quand le même pattern se répète (un serveur web standard, un cluster de DB), encapsuler dans un module.

# modules/web-server/main.tf
variable "name" {}
variable "server_type" { default = "cx21" }
variable "ssh_keys" { type = list(string) }

resource "hcloud_server" "this" {
  name        = var.name
  server_type = var.server_type
  image       = "ubuntu-24.04"
  location    = "fsn1"
  ssh_keys    = var.ssh_keys
}

output "ipv4" {
  value = hcloud_server.this.ipv4_address
}

Usage :

module "web_1" {
  source      = "./modules/web-server"
  name        = "web-1"
  ssh_keys    = [hcloud_ssh_key.admin.id]
}

module "web_2" {
  source      = "./modules/web-server"
  name        = "web-2"
  server_type = "cx31"
  ssh_keys    = [hcloud_ssh_key.admin.id]
}

La Terraform Registry (registry.terraform.io) propose des milliers de modules publics. Pour une PME, écrire ses propres modules simples est souvent préférable à importer des modules complexes mal compris.


5. Ansible : structure d’un projet propre

Un projet Ansible bien organisé suit une convention standard :

ansible/
├── ansible.cfg
├── inventory/
│   ├── production.yml
│   └── staging.yml
├── group_vars/
│   ├── all.yml
│   └── web.yml
├── host_vars/
│   └── web-1.yml
├── roles/
│   ├── common/
│   ├── nginx/
│   └── docker/
└── playbooks/
    ├── site.yml
    └── deploy.yml

Inventaire YAML (inventory/production.yml) :

all:
  vars:
    ansible_user: deploy
    ansible_ssh_private_key_file: ~/.ssh/id_ed25519
  children:
    web:
      hosts:
        web-1:
          ansible_host: 5.75.xxx.xxx
        web-2:
          ansible_host: 5.75.yyy.yyy
    db:
      hosts:
        db-1:
          ansible_host: 5.75.zzz.zzz

ansible.cfg minimal :

[defaults]
inventory = ./inventory/production.yml
host_key_checking = True
retry_files_enabled = False
stdout_callback = yaml

6. Playbooks et rôles Ansible

Un playbook orchestre des rôles sur des groupes de machines.

playbooks/site.yml :

- name: Configuration commune
  hosts: all
  become: yes
  roles:
    - common

- name: Configuration des serveurs web
  hosts: web
  become: yes
  roles:
    - docker
    - nginx

Un rôle est un dossier structuré : roles/nginx/tasks/main.yml, roles/nginx/templates/nginx.conf.j2, roles/nginx/handlers/main.yml.

Exemple roles/nginx/tasks/main.yml :

- name: Installer Nginx
  apt:
    name: nginx
    state: present
    update_cache: yes

- name: Déployer la configuration site
  template:
    src: site.conf.j2
    dest: /etc/nginx/sites-available/site.conf
    owner: root
    group: root
    mode: '0644'
  notify: reload nginx

- name: Activer le site
  file:
    src: /etc/nginx/sites-available/site.conf
    dest: /etc/nginx/sites-enabled/site.conf
    state: link
  notify: reload nginx

- name: S'assurer que Nginx tourne
  systemd:
    name: nginx
    state: started
    enabled: yes

roles/nginx/handlers/main.yml :

- name: reload nginx
  systemd:
    name: nginx
    state: reloaded

Les handlers ne se déclenchent que si une tâche les a notifyés — utile pour ne recharger qu’une fois après plusieurs changements.

Exécution :

ansible-playbook playbooks/site.yml
ansible-playbook playbooks/site.yml --check        # dry-run
ansible-playbook playbooks/site.yml --tags nginx   # un sous-ensemble
ansible-playbook playbooks/site.yml --limit web-1  # une seule machine

7. Vault Ansible pour les secrets

Ansible Vault chiffre les fichiers de secrets pour les versionner sans risque.

# Chiffrer un fichier
ansible-vault encrypt group_vars/db/secrets.yml

# Éditer
ansible-vault edit group_vars/db/secrets.yml

# Lancer un playbook qui en a besoin
ansible-playbook site.yml --ask-vault-pass
# ou avec un fichier de mot de passe (mode CI)
ansible-playbook site.yml --vault-password-file ~/.ansible-vault-pass

Le mot de passe vault doit être stocké en sécurité (pas en clair dans Git) — typiquement dans un gestionnaire de secrets, ou en variable secrète GitHub pour le CI.

Pour des secrets plus sophistiqués, ansible-vault peut être complété par sops, HashiCorp Vault ou un secrets manager cloud.


8. Combiner Terraform et Ansible

Le workflow type : Terraform crée les serveurs, Ansible les configure. Pour faire le pont, deux approches.

Approche 1 : sortie Terraform → inventaire Ansible

Terraform génère l’inventaire dynamiquement :

output "ansible_inventory" {
  value = templatefile("${path.module}/inventory.tpl", {
    web_servers = hcloud_server.web[*].ipv4_address
  })
}

Puis :

terraform output -raw ansible_inventory > ../ansible/inventory/production.yml
ansible-playbook -i ../ansible/inventory/production.yml site.yml

Approche 2 : provisioner Terraform local-exec

Pour des cas simples, Terraform peut appeler Ansible directement après création :

resource "null_resource" "ansible_run" {
  depends_on = [hcloud_server.web]

  provisioner "local-exec" {
    command = "ansible-playbook -i '${hcloud_server.web.ipv4_address},' site.yml"
  }
}

Cette approche couple les deux outils, ce qui n’est pas toujours souhaitable. La séparation claire (Terraform → output → Ansible) reste plus saine pour les équipes.

Voir aussi → GitHub Actions : CI/CD pratique pour PME pour automatiser les exécutions Terraform et Ansible dans un pipeline.


9. FAQ

Pulumi ou Terraform : faut-il considérer Pulumi ?

Pulumi permet d’écrire l’IaC en TypeScript, Python, Go ou C# au lieu de HCL. Avantage : utiliser un vrai langage de programmation pour les abstractions complexes. Inconvénient : écosystème plus restreint, moins de modules communautaires. Pour une PME qui démarre, Terraform est le choix par défaut sauf préférence forte de l’équipe pour un autre langage.

Faut-il versionner le state Terraform dans Git ?

Non, jamais. Le state contient parfois des secrets en clair (mots de passe générés, clés). Le versionner dans Git est une fuite de données. Utiliser un backend distant chiffré.

Ansible vs Salt vs Puppet : que choisir ?

Pour une PME francophone qui démarre : Ansible. Le plus accessible, syntaxe lisible, communauté massive, sans agent à installer. Puppet et Chef ont leur place dans les très grandes infrastructures historiques. Salt est puissant mais plus marginal.

Combien de temps pour rendre une équipe productive sur Terraform ?

Avec un développeur ou sysadmin sérieux, quelques semaines suffisent pour les bases (provider, ressources, variables, modules simples). La maîtrise du state, des modules complexes, des stratégies multi-environnements demande quelques mois de pratique. La courbe d’apprentissage est rentable rapidement.

Faut-il appliquer Terraform depuis un poste dev ou un pipeline CI ?

Au début, depuis un poste dev avec backend distant suffit. Quand l’équipe grandit ou que l’infrastructure devient critique, faire passer Terraform par un pipeline (Atlantis, Terraform Cloud, GitHub Actions) ajoute traçabilité, revue, et empêche les apply non revus.

Idempotence Ansible : comment vérifier que mes playbooks la respectent ?

Lancer le playbook deux fois de suite. La seconde exécution doit afficher changed=0 partout. Si certaines tâches sont marquées changed à chaque run, elles sont mal écrites (souvent : utilisation de command ou shell au lieu d’un module Ansible idempotent comme apt, template, service).


Articles liés (cluster DevOps moderne)


Article mis à jour le 25 avril 2026. Pour signaler une erreur ou suggérer une amélioration, écrivez-nous.

Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 250.000 FCFA
Parlons de Votre Projet
Publicité