MET : Terraform, infrastructure as code (2/6)


Créer des serveurs manuellement appartient au passé. Avec Terraform, votre infrastructure devient du code : versionnée, reproductible et déployable en quelques secondes.
Dans le premier article de cette série, nous avons présenté notre vision d’une infrastructure cloud moderne. Aujourd’hui, nous nous penchons sur le premier outil de notre stack : Terraform.
Le problème : une infrastructure artisanale
Imaginez le scénario classique :
- Vous vous connectez à la console de votre hébergeur
- Vous cliquez sur « Créer un serveur »
- Vous choisissez des options (RAM, CPU, OS…)
- Vous notez l’IP quelque part (ou pas)
- Vous répétez pour chaque serveur
Six mois plus tard :
- « C’était quoi déjà la config de ce serveur ? »
- « Qui a créé ce réseau privé ? »
- « Peut-on recréer la même infra pour le client X ? »
La réponse est souvent : « Euh… il va falloir fouiller ».
La solution : l’Infrastructure as Code
Terraform est un outil open source créé par HashiCorp qui permet de définir votre infrastructure dans des fichiers de configuration. Au lieu de cliquer dans une interface, vous décrivez ce que vous voulez, et Terraform se charge de le créer.
« Décrivez l’état souhaité, Terraform se charge d’y parvenir. »
Les avantages sont nombreux :
- Versioning : votre infrastructure est dans Git, avec un historique complet
- Reproductibilité : recréez la même infra avec une seule commande
- Documentation vivante : le code EST la documentation
- Revue de code : les changements d’infrastructure passent par des merge requests
- Rollback : revenez à une version précédente si nécessaire
Notre infrastructure dans Terraform
Voici comment nous définissons nos serveurs. Tout commence par la configuration du provider (l’hébergeur) :
# Configuration Terraform
terraform {
required_version = ">= 1.6"
required_providers {
hcloud = {
source = "hetznercloud/hcloud"
version = "~> 1.45"
}
}
}
# Connexion à l’API de l’hébergeur
provider "hcloud" {
token = var.hcloud_token # Token stocké dans une variable d’environnement
}
Ce bloc indique à Terraform :
- Quelle version de Terraform utiliser
- Quel provider (ici Hetzner Cloud) et avec quelle version
- Comment s’authentifier (via un token API sécurisé)
Définition du serveur
Ensuite, nous déclarons nos serveurs. Voici la définition de notre serveur principal :
# Serveur principal - Kubernetes Control Plane
resource "hcloud_server" "control_plane" {
name = "k8s-master"
server_type = "cpxxx" # Notre modèle
image = "ubuntu-22.04"
location = "nbg1" # Datacenter de Nuremberg (Allemagne)
ssh_keys = data.hcloud_ssh_keys.all.ssh_keys[*].id
labels = {
role = "k8s-control-plane"
environment = "production"
managed_by = "terraform"
}
lifecycle {
prevent_destroy = true # Protection contre la suppression accidentelle
}
}
Décomposons ce code :
- resource : déclare une ressource à créer
- hcloud_server : type de ressource (serveur Hetzner)
- server_type : taille du serveur
- location : le datacenter (Nuremberg, Allemagne = RGPD ✓)
- labels : métadonnées pour l’organisation et le filtrage
- prevent_destroy : empêche la suppression accidentelle
Le réseau privé
Pour que nos serveurs communiquent de manière sécurisée, nous créons un réseau privé :
# Réseau privé pour la communication inter-nœuds
resource "hcloud_network" "k8s_network" {
name = "k8s-private-network"
ip_range = "10.0.0.0/16"
labels = {
environment = "production"
}
}
# Sous-réseau pour les serveurs
resource "hcloud_network_subnet" "k8s_subnet" {
network_id = hcloud_network.k8s_network.id
type = "cloud"
network_zone = "eu-central"
ip_range = "10.0.1.0/24"
}
# Rattacher le serveur au réseau privé
resource "hcloud_server_network" "control_plane_network" {
server_id = hcloud_server.control_plane.id
network_id = hcloud_network.k8s_network.id
ip = "10.0.1.10"
}
Ce réseau privé permet :
- Une communication sécurisée entre les nœuds Kubernetes
- L’isolation du trafic interne (non exposé à Internet)
- Des performances optimales (latence minimale)
Variables : flexibilité et sécurité
Les informations sensibles (tokens API, mots de passe) ne sont jamais codées en dur. Nous utilisons des variables :
# variables.tf
variable "hcloud_token" {
description = "Token API de l’hébergeur"
type = string
sensitive = true # Masqué dans les logs
}
variable "ssh_keys" {
description = "Clés SSH autorisées"
type = list(string)
default = []
}
Ces variables sont ensuite définies via :
- Des variables d’environnement (
TF_VAR_hcloud_token) .tfvarsUn fichier (non commité dans Git)- Un gestionnaire de secrets (Vault, etc.)
Le workflow Terraform en pratique
Utiliser Terraform au quotidien se résume à trois commandes :
1. Initialisation
# Télécharger les providers et initialiser le projet terraform init
2. Planification
# Afficher ce qui sera créé/modifié/supprimé terraform plan
Cette commande est cruciale : elle montre exactement ce que Terraform va faire, sans rien exécuter. Exemple de sortie :
Terraform effectuera les actions suivantes :
# hcloud_server.control_plane sera créé
+ resource "hcloud_server" "control_plane" {
+ name = "k8s-master"
+ server_type = "cpx52"
+ location = "nbg1"
...
}
Plan : 1 à ajouter, 0 à modifier, 0 à détruire.
3. Application
# Appliquer les changements (avec confirmation) terraform apply
Terraform crée ensuite les ressources et stocke leur état dans un fichier terraform.tfstate.
Nos bonnes pratiques
🔐 Sécurité
- Jamais de secrets dans le code : utilisez des variables et des gestionnaires de secrets
- État distant : stockez le tfstate dans un bucket S3 chiffré, pas en local
- Revue de code : tous les changements d’infrastructure passent par une merge request
🛡️ Protection
- prevent_destroy : sur les ressources critiques (serveurs, bases de données)
- ignore_changes : pour les attributs gérés manuellement
📁 Organisation
- main.tf : ressources principales
- variables.tf : déclarations de variables
- outputs.tf : valeurs exportées (IP, ID…)
- terraform.tfvars : valeurs des variables (non commitées)
Intégration à notre workflow
Pour simplifier l’usage, nous avons créé des commandes Make :
# Planifier les changements make terraform-plan # Appliquer les changements make terraform-apply # Importer des serveurs existants make terraform-import-servers ODIN_ID=12345 ATHENA_ID=67890
Cela permet à toute l’équipe d’utiliser Terraform sans connaître les commandes exactes.
Le résultat
Avec Terraform, notre infrastructure est désormais :
| 📝 | Documentée | Le code décrit exactement ce qui existe |
| 🔄 | Reproductible | Recréation complète en 10 minutes |
| 📊 | Versionnée | Historique complet des changements |
| 👥 | Collaborative | Revue de code avant chaque modification |
| 🛡️ | Sécurisée | Secrets externalisés, protection anti-suppression |
Et ensuite ?
Terraform crée les serveurs, mais ils sont « vides ». Dans le prochain article, nous verrons comment Ansible prend le relais pour :
- Configurer le système d’exploitation
- Installer Kubernetes (K3s)
- Déployer les services de base
Le tout de manière automatisée et idempotente.
🚀 Besoin d’aide pour adopter l’Infrastructure as Code ?
Nous accompagnons les entreprises dans la mise en place de Terraform, qu’il s’agisse de migrer une infrastructure existante ou de partir de zéro.
