Aller au contenu principal
TerraformInfrastructure as CodeFormation

Init, Plan, Apply : le workflow Terraform

30 min de lecture Terraform — Chapitre 2

Maîtrise le workflow Terraform complet : init, plan, apply, destroy. Puis découvre les resources, data sources, le state et la structure de projet.

Tu sais ce qu’est Terraform et tu as vu la syntaxe HCL. Maintenant, on rentre dans le vif : le workflow que tu vas répéter des centaines de fois — init, plan, apply, destroy. C’est le cœur de Terraform, et le maîtriser fait la différence entre un débutant et quelqu’un d’opérationnel.

Le workflow en 4 commandes

Chaque interaction avec Terraform suit le même cycle, que tu déploies un serveur ou une infrastructure complète de 200 ressources.

terraform init — préparer le terrain

terraform init

C’est toujours la première commande. Elle fait trois choses :

  • Télécharge les providers déclarés dans required_providers (dans .terraform/)
  • Initialise le backend de stockage du state (local par défaut)
  • Génère le fichier .terraform.lock.hcl qui verrouille les versions des providers

Tu dois relancer init quand tu ajoutes un nouveau provider, changes de backend, ou clones un projet existant. En dehors de ces cas, une seule fois suffit.

💡 Astuce : terraform init -upgrade force la mise à jour des providers vers la dernière version compatible avec tes contraintes de version.

terraform plan — le filet de sécurité

terraform plan

Le plan compare l’état souhaité (tes fichiers .tf) avec l’état actuel (le state) et affiche les changements prévus sans rien exécuter.

Terraform will perform the following actions:

  # hcloud_server.web will be created
  + resource "hcloud_server" "web" {
      + id          = (known after apply)
      + image       = "ubuntu-24.04"
      + location    = "fsn1"
      + name        = "web-1"
      + server_type = "cx22"
      + status      = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Les symboles à connaître :

  • + création d’une ressource
  • ~ modification in-place (la ressource survit)
  • -/+ destruction puis recréation (la ressource est remplacée)
  • - suppression

🔥 Règle non négociable : lis toujours le plan avant d’appliquer. Un -/+ sur ta base de données prod = perte de données. Le plan, c’est ton dernier rempart.

terraform apply — exécuter les changements

terraform apply

Apply affiche le plan, demande confirmation (yes), puis exécute les changements via les APIs du provider. Terraform crée les ressources dans l’ordre imposé par le graphe de dépendances et parallélise ce qui peut l’être.

Pour les pipelines CI/CD, sauvegarde le plan et applique-le sans confirmation : terraform plan -out=tfplan puis terraform apply tfplan. Cette approche garantit que ce qui est appliqué est exactement ce qui a été reviewé.

terraform destroy — tout supprimer

terraform destroy                              # Tout supprimer (confirmation requise)
terraform destroy -target=hcloud_server.web    # Cibler une ressource spécifique

⚠️ En production, destroy sans -target est une arme nucléaire. Préfère supprimer les blocs de code et laisser plan/apply gérer la suppression de manière contrôlée.

Resources et Data Sources en détail

Resources : ce que Terraform gère

Une resource représente un objet d’infrastructure que Terraform crée, met à jour et supprime (cycle CRUD). Chaque resource a des arguments (ce que tu configures) et des attributs (ce que Terraform récupère après création).

resource "hcloud_server" "web" {
  # Arguments — tu les définis
  name        = "web-1"
  server_type = "cx22"
  image       = "ubuntu-24.04"
  location    = "fsn1"

  # Attributs disponibles après apply :
  # hcloud_server.web.id
  # hcloud_server.web.ipv4_address
  # hcloud_server.web.status
}

Les attributs sont accessibles via la syntaxe type.nom.attribut. Tu les utilises pour câbler les ressources entre elles — c’est comme ça que Terraform construit le graphe de dépendances.

Data sources : lire sans modifier

Un data source interroge une API pour récupérer des informations en lecture seule. Terraform ne crée, modifie ou supprime rien.

data "hcloud_ssh_key" "deploy" {
  name = "deploy-key"
}

resource "hcloud_server" "web" {
  name        = "web-1"
  server_type = "cx22"
  image       = "ubuntu-24.04"
  ssh_keys    = [data.hcloud_ssh_key.deploy.id]
}

Le préfixe data. distingue un data source d’une resource dans les références. Cas d’usage typiques : récupérer une clé SSH existante, lire les infos d’une image, obtenir l’ID d’un VPC partagé.

Dépendances implicites et explicites

Terraform détecte automatiquement les dépendances via les références. Quand tu écris ssh_keys = [hcloud_ssh_key.default.id], Terraform sait qu’il doit créer la clé SSH avant le serveur.

Pour les cas où la dépendance n’est pas visible dans les arguments, utilise depends_on = [hcloud_network_subnet.internal] dans le bloc resource.

💡 Préfère toujours les dépendances implicites. depends_on est un dernier recours — il empêche Terraform d’optimiser l’ordre d’exécution.

Le State : la mémoire de Terraform

Le fichier terraform.tfstate est un JSON qui mappe chaque resource de ton code à un objet réel dans le cloud. Sans state, Terraform ne peut pas savoir ce qui existe déjà ni calculer les différences.

Ce que le state contient

  • Le mapping resource "hcloud_server" "web" → ID Hetzner 58712345
  • Tous les attributs de chaque ressource (IPs, status, metadata…)
  • Les dépendances entre ressources
  • La version du format et des providers

Commandes d’inspection et règles

terraform state list                    # Lister les ressources
terraform state show hcloud_server.web  # Détail d'une ressource

Trois règles non négociables :

  1. Ne modifie jamais le state à la main — utilise terraform state mv, rm, import
  2. Ne commite jamais le state dans Git — il contient des données sensibles (ajoute *.tfstate, .terraform/ au .gitignore)
  3. En équipe, utilise un backend distant (S3+DynamoDB, GCS, Terraform Cloud) pour le partage et le locking

Cas entreprise : pipeline CI/CD Terraform

Une équipe DevOps de 5 personnes gère 150 ressources cloud avec Terraform. Sans workflow structuré, c’est le chaos : qui a appliqué quoi ? Est-ce que le state est à jour ? Quelqu’un a-t-il modifié l’infra à la main ?

Leur pipeline GitLab CI :

  1. Merge Requestterraform plan automatique, résultat posté en commentaire
  2. Review → Un collègue relit le plan (comme une code review)
  3. Mergeterraform apply automatique avec le plan sauvegardé
  4. State distant sur S3 avec locking DynamoDB — impossible d’appliquer en parallèle

🎯 Résultat : chaque changement d’infra passe par une MR. L’historique est dans Git. Le plan est relu avant exécution. Zéro surprise, zéro “qui a touché au firewall vendredi soir ?”.

Les pièges du workflow

⚠️ State lock oublié — Si un apply plante en plein milieu, le state peut rester verrouillé. terraform force-unlock <LOCK_ID> le déverrouille, mais assure-toi d’abord que personne d’autre n’est en train d’appliquer.

⚠️ Drift non détecté — Si quelqu’un modifie une ressource dans la console web, Terraform ne le saura qu’au prochain plan. Lance terraform plan régulièrement (ou en cron) pour détecter les drifts avant qu’ils ne posent problème.

⚠️ Apply sans plan sauvegardé en CI — Entre le moment où plan tourne et celui où apply s’exécute, l’infra peut avoir changé. Sauvegarde toujours le plan (-out=tfplan) et applique ce fichier.

⚠️ Oublier -target en prod — Un terraform destroy sans -target supprime tout. En prod, cible toujours la ressource spécifique.

Résumé

Le workflow Terraform est simple et se répète à chaque changement d’infrastructure :

  • init → prépare le projet (providers, backend, lock)
  • plan → affiche les changements sans les exécuter — ton filet de sécurité
  • apply → exécute les changements après confirmation
  • destroy → supprime les ressources (avec prudence en prod)

Les concepts clés associés :

  • Resources = objets gérés par Terraform (CRUD complet)
  • Data sources = lecture seule de données existantes
  • State = fichier JSON qui mappe le code à l’infra réelle — ne jamais le perdre ni le commiter
  • Dépendances = automatiques via les références, depends_on en dernier recours

Dans le prochain chapitre, on attaque les variables et expressions HCL — pour rendre ton code dynamique, réutilisable et paramétrable.

🖥️ Pratique sur ton propre serveur

Pour suivre Terraform en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.

Obtenir 200$

Articles liés