Vous avez adopté Terraform pour vos nouveaux projets, mais que faire de toute cette infrastructure créée manuellement via la console AWS, Azure ou GCP ? Des dizaines, voire des centaines de ressources existent déjà en production — des VPC, des instances EC2, des bases de données RDS, des buckets S3 — le tout créé à la main, au fil des années, sans aucune trace de code.
C'est précisément le problème que résout terraform import. Cette fonctionnalité permet d'intégrer des ressources cloud existantes dans votre state Terraform, pour ensuite les gérer entièrement via l'Infrastructure as Code. Dans cet article, nous allons explorer en profondeur le processus d'import, des commandes de base jusqu'aux nouvelles fonctionnalités de Terraform 1.5+ avec les blocs import, en passant par les outils d'aide et les stratégies de migration à grande échelle.

Pourquoi Importer vos Ressources Existantes ?
Avant de plonger dans le comment, comprenons le pourquoi. L'import de ressources existantes dans Terraform répond à plusieurs besoins critiques.
Les motivations principales
- Traçabilité et audit : savoir exactement quelle infrastructure existe, qui l'a modifiée et quand, grâce à l'historique Git
- Reproductibilité : pouvoir recréer un environnement identique pour le staging, le DR ou une autre région
- Cohérence : éviter le "shadow IT" où des ressources non documentées existent dans le cloud
- Prévention des drifts : détecter quand quelqu'un modifie manuellement une ressource qui devrait être gérée par le code
- Collaboration : permettre à toute l'équipe de comprendre et modifier l'infrastructure via des Pull Requests
- Conformité : répondre aux exigences réglementaires qui imposent une gestion documentée de l'infrastructure
Le défi de l'import
Il faut comprendre une limitation fondamentale : terraform import n'importe que le state, pas le code. Autrement dit, la commande enregistre la ressource existante dans le fichier state de Terraform, mais vous devez écrire manuellement le code HCL correspondant. C'est un processus en plusieurs étapes qui demande de la rigueur.
La Commande terraform import : Les Bases
La commande terraform import est disponible depuis les premières versions de Terraform. Son fonctionnement est simple mais demande une préparation minutieuse.
Syntaxe de base
# Syntaxe générale
terraform import [options] ADRESSE_RESSOURCE ID_RESSOURCE
# Exemples concrets
terraform import aws_instance.web_server i-0abc123def456789
terraform import aws_vpc.main vpc-0abc123def456789
terraform import aws_s3_bucket.assets mon-bucket-assets
terraform import aws_db_instance.production mon-instance-rds
terraform import aws_security_group.web sg-0abc123def456789
L'adresse de la ressource correspond au bloc resource dans votre code Terraform (par exemple aws_instance.web_server). L'ID de la ressource est l'identifiant unique de la ressource dans le cloud (par exemple l'ID d'une instance EC2).
Trouver l'ID d'une ressource
Chaque type de ressource a son propre format d'ID pour l'import. La documentation du provider Terraform indique toujours l'ID attendu :
# AWS - Les IDs varient selon le type de ressource
# EC2 Instance : ID de l'instance
terraform import aws_instance.example i-0abc123def456789
# S3 Bucket : nom du bucket
terraform import aws_s3_bucket.example mon-bucket
# RDS Instance : identifiant de l'instance
terraform import aws_db_instance.example mon-instance-rds
# IAM Role : nom du rôle
terraform import aws_iam_role.example mon-role
# Security Group : ID du security group
terraform import aws_security_group.example sg-0abc123def456789
# Route 53 Record : zone_id_type_name (format composé)
terraform import aws_route53_record.example Z0123456789_example.com_A
# Ressources avec des IDs composés
terraform import aws_route_table_association.example subnet-0abc123/rtb-0def456
Le Processus d'Import Étape par Étape
L'import de ressources suit un processus rigoureux en plusieurs étapes. Prenons un exemple concret : importer une instance EC2 existante.
Étape 1 : Identifier la ressource à importer
Commencez par recenser les informations sur la ressource existante via la console AWS ou l'AWS CLI :
# Obtenir les détails de l'instance EC2
aws ec2 describe-instances --instance-ids i-0abc123def456789 --output json
# Résultat (simplifié)
{
"Reservations": [{
"Instances": [{
"InstanceId": "i-0abc123def456789",
"InstanceType": "t3.large",
"ImageId": "ami-0abcdef1234567890",
"SubnetId": "subnet-0abc123",
"VpcId": "vpc-0def456",
"SecurityGroups": [
{"GroupId": "sg-0abc123", "GroupName": "web-server-sg"}
],
"Tags": [
{"Key": "Name", "Value": "prod-web-server"},
{"Key": "Environment", "Value": "production"}
],
"KeyName": "prod-key",
"IamInstanceProfile": {
"Arn": "arn:aws:iam::123456789012:instance-profile/web-server-profile"
}
}]
}]
}
Étape 2 : Écrire le bloc resource minimal
Créez un bloc resource dans votre code Terraform. À ce stade, un bloc minimal suffit :
# imported_resources.tf
resource "aws_instance" "web_server" {
# Les attributs seront complétés après l'import
# Pour l'instant, un bloc vide ou minimal suffit
ami = "ami-0abcdef1234567890"
instance_type = "t3.large"
}
Étape 3 : Exécuter terraform import
# S'assurer que terraform init a été exécuté
terraform init
# Importer la ressource
terraform import aws_instance.web_server i-0abc123def456789
# Sortie attendue
# aws_instance.web_server: Importing from ID "i-0abc123def456789"...
# aws_instance.web_server: Import prepared!
# Prepared aws_instance for import
# aws_instance.web_server: Refreshing state... [id=i-0abc123def456789]
#
# Import successful!
#
# The resources that were imported are shown above.
Étape 4 : Exécuter terraform plan et ajuster le code
C'est l'étape la plus importante et la plus laborieuse. Après l'import, exécutez terraform plan pour voir les différences entre votre code et l'état réel de la ressource :
terraform plan
# Le plan va montrer des changements car votre code ne reflète pas
# encore tous les attributs de la ressource importée
Vous devez alors ajuster votre code pour qu'il corresponde exactement à l'état réel. L'objectif est d'obtenir un terraform plan sans aucun changement :
# imported_resources.tf - Version complète après ajustement
resource "aws_instance" "web_server" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.large"
subnet_id = "subnet-0abc123"
vpc_security_group_ids = [aws_security_group.web.id]
key_name = "prod-key"
iam_instance_profile = "web-server-profile"
root_block_device {
volume_type = "gp3"
volume_size = 50
encrypted = true
delete_on_termination = true
}
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 1
}
tags = {
Name = "prod-web-server"
Environment = "production"
}
lifecycle {
# Empêcher la destruction accidentelle d'une ressource importée
prevent_destroy = true
}
}
Étape 5 : Vérifier avec terraform plan
terraform plan
# Sortie souhaitée :
# No changes. Your infrastructure matches the configuration.
#
# Terraform has compared your real infrastructure against your
# configuration and found no differences, so no changes are needed.
Si le plan indique encore des changements, ajustez votre code ou utilisez ignore_changes pour les attributs qui ne doivent pas être gérés par Terraform :
resource "aws_instance" "web_server" {
# ... attributs ...
lifecycle {
prevent_destroy = true
ignore_changes = [
# Ignorer les changements faits en dehors de Terraform
user_data,
ami, # Si l'AMI est gérée par un autre processus
]
}
}
Import Block : La Révolution de Terraform 1.5+
Depuis Terraform 1.5 (sorti en juin 2023), une nouvelle approche d'import est disponible : les blocs import. Cette fonctionnalité transforme radicalement le workflow d'import en le rendant déclaratif et planifiable.
Syntaxe du bloc import
# imports.tf
import {
to = aws_instance.web_server
id = "i-0abc123def456789"
}
import {
to = aws_vpc.main
id = "vpc-0abc123def456789"
}
import {
to = aws_s3_bucket.assets
id = "mon-bucket-assets"
}
import {
to = aws_security_group.web
id = "sg-0abc123def456789"
}
Les avantages par rapport à terraform import
- Planifiable :
terraform planmontre l'import avant de l'exécuter - Déclaratif : les imports sont du code versionnable dans Git
- Batch : importer plusieurs ressources en un seul
terraform apply - Réversible : supprimer le bloc import pour annuler (avant le apply)
- Génération de code : avec
-generate-config-out, Terraform peut générer le code HCL
Génération automatique du code (Terraform 1.5+)
La fonctionnalité la plus excitante est la génération automatique de code. Terraform peut examiner la ressource importée et générer le bloc HCL correspondant :
# Écrire les blocs import sans écrire les blocs resource
# imports.tf
import {
to = aws_instance.web_server
id = "i-0abc123def456789"
}
# Générer le code automatiquement
terraform plan -generate-config-out=generated_resources.tf
# Terraform va :
# 1. Lire la ressource depuis AWS
# 2. Générer le fichier generated_resources.tf avec le code HCL
# 3. Afficher le plan d'import
Le fichier généré ressemble à ceci :
# generated_resources.tf (généré automatiquement)
resource "aws_instance" "web_server" {
ami = "ami-0abcdef1234567890"
associate_public_ip_address = false
availability_zone = "eu-west-1a"
cpu_core_count = 2
cpu_threads_per_core = 2
disable_api_stop = false
disable_api_termination = false
ebs_optimized = true
iam_instance_profile = "web-server-profile"
instance_type = "t3.large"
key_name = "prod-key"
monitoring = false
subnet_id = "subnet-0abc123"
vpc_security_group_ids = ["sg-0abc123"]
capacity_reservation_specification {
capacity_reservation_preference = "open"
}
metadata_options {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "required"
instance_metadata_tags = "disabled"
}
root_block_device {
delete_on_termination = true
encrypted = true
iops = 3000
throughput = 125
volume_size = 50
volume_type = "gp3"
}
tags = {
Environment = "production"
Name = "prod-web-server"
}
tags_all = {
Environment = "production"
Name = "prod-web-server"
}
}
Workflow complet avec les blocs import
# 1. Écrire les blocs import
cat > imports.tf <<'EOF'
import {
to = aws_instance.web_server
id = "i-0abc123def456789"
}
EOF
# 2. Générer le code (optionnel mais recommandé)
terraform plan -generate-config-out=generated.tf
# 3. Nettoyer et ajuster le code généré
# Remplacer les valeurs hardcodées par des variables
# Supprimer les attributs calculés inutiles
# Ajouter des lifecycle rules si nécessaire
# 4. Vérifier le plan
terraform plan
# Doit afficher : "1 to import, 0 to add, 0 to change, 0 to destroy"
# 5. Appliquer l'import
terraform apply
# 6. Supprimer les blocs import (ils ne sont plus nécessaires)
rm imports.tf
# 7. Vérifier que tout est clean
terraform plan
# Doit afficher : "No changes"
Limites de l'Import Terraform
L'import Terraform, bien qu'essentiel, a des limitations qu'il est important de connaître pour éviter les mauvaises surprises.
Limitations techniques
- Pas tous les attributs sont importés : certains attributs en écriture seule (comme les mots de passe) ne peuvent pas être lus depuis l'API du cloud et ne seront pas dans le state
- Pas de support pour toutes les ressources : certaines ressources de certains providers ne supportent pas encore l'import
- Relations complexes : les dépendances entre ressources ne sont pas automatiquement détectées ; vous devez les reconstruire manuellement dans le code
- Modules : importer dans un module nécessite d'utiliser le chemin complet comme
module.vpc.aws_subnet.public[0] - for_each et count : l'import dans des ressources avec
for_eachoucountnécessite une syntaxe spécifique
Import avec for_each et count
# Import avec count
terraform import 'aws_subnet.public[0]' subnet-0abc123
terraform import 'aws_subnet.public[1]' subnet-0def456
# Import avec for_each
terraform import 'aws_subnet.public["eu-west-1a"]' subnet-0abc123
terraform import 'aws_subnet.public["eu-west-1b"]' subnet-0def456
Avec les blocs import :
import {
to = aws_subnet.public["eu-west-1a"]
id = "subnet-0abc123"
}
import {
to = aws_subnet.public["eu-west-1b"]
id = "subnet-0def456"
}
Limitations de la génération de code
- Le code généré est souvent verbeux avec des attributs inutiles
- Les références entre ressources sont remplacées par des valeurs littérales
- Les variables et locals ne sont pas créés automatiquement
- Les modules ne sont pas générés ; tout est en ressources plates
Outils d'Aide à l'Import
Pour les migrations à grande échelle, la commande terraform import manuelle est fastidieuse. Heureusement, plusieurs outils communautaires automatisent le processus.
Terraformer (Google)
Terraformer est un outil open source développé par Google qui génère automatiquement le code Terraform et le state à partir d'une infrastructure existante :
# Installation
brew install terraformer
# Importer toutes les instances EC2
terraformer import aws --resources=ec2_instance --regions=eu-west-1
# Importer un ensemble de ressources
terraformer import aws \
--resources=vpc,subnet,security_group,ec2_instance,s3 \
--regions=eu-west-1 \
--profile=production
# Importer avec des filtres
terraformer import aws \
--resources=ec2_instance \
--filter="Name=tags.Environment;Value=production" \
--regions=eu-west-1
Terraformer génère une structure de répertoires avec le code HCL et les fichiers state :
generated/
└── aws/
├── ec2_instance/
│ ├── instance.tf
│ ├── outputs.tf
│ ├── provider.tf
│ └── terraform.tfstate
├── vpc/
│ ├── vpc.tf
│ ├── outputs.tf
│ ├── provider.tf
│ └── terraform.tfstate
└── s3/
├── s3_bucket.tf
├── outputs.tf
├── provider.tf
└── terraform.tfstate
aztfexport (Microsoft)
Pour Azure, Microsoft fournit aztfexport, un outil dédié à l'export des ressources Azure vers Terraform :
# Installation
brew install aztfexport
# Exporter un resource group entier
aztfexport resource-group mon-resource-group
# Exporter une ressource spécifique
aztfexport resource /subscriptions/.../resourceGroups/.../providers/Microsoft.Compute/virtualMachines/ma-vm
# Mode interactif
aztfexport resource-group mon-resource-group --non-interactive=false
gcloud terraform vet (Google Cloud)
Pour GCP, l'outil gcloud propose des fonctionnalités d'export :
# Exporter un projet GCP
gcloud beta resource-config bulk-export \
--resource-format=terraform \
--project=mon-projet-gcp
Stratégie de Migration Progressive
Migrer une infrastructure entière vers Terraform ne se fait pas en un jour. Voici une stratégie éprouvée pour une migration progressive et sûre.
Phase 1 : Inventaire et priorisation
# Lister toutes les ressources existantes
aws resourcegroupstaggingapi get-resources \
--region eu-west-1 \
--output json > inventory.json
# Compter par type de ressource
aws resourcegroupstaggingapi get-resources \
--region eu-west-1 \
--query 'ResourceTagMappingList[].ResourceARN' \
--output text | \
sed 's/.*://; s/\/.*//' | sort | uniq -c | sort -rn
Priorisez les ressources par criticité et dépendance :
- Réseau (VPC, subnets, security groups) : fondation de tout le reste
- IAM (rôles, politiques) : nécessaire pour les autres ressources
- Stockage (S3, EBS) : données persistantes
- Base de données (RDS, DynamoDB) : critique mais complexe à migrer
- Compute (EC2, ECS, Lambda) : souvent le plus volumineux
- DNS et certificats : Route 53, ACM
Phase 2 : Import par couches
Importez par couches en commençant par les fondations :
# Couche 1 : Réseau
# network/imports.tf
import {
to = aws_vpc.main
id = "vpc-0abc123"
}
import {
to = aws_subnet.public["eu-west-1a"]
id = "subnet-0abc123"
}
import {
to = aws_subnet.public["eu-west-1b"]
id = "subnet-0def456"
}
import {
to = aws_subnet.private["eu-west-1a"]
id = "subnet-0ghi789"
}
import {
to = aws_subnet.private["eu-west-1b"]
id = "subnet-0jkl012"
}
import {
to = aws_internet_gateway.main
id = "igw-0abc123"
}
import {
to = aws_nat_gateway.main
id = "nat-0abc123"
}
import {
to = aws_route_table.public
id = "rtb-0abc123"
}
import {
to = aws_route_table.private
id = "rtb-0def456"
}
# Générer le code pour la couche réseau
cd network/
terraform plan -generate-config-out=generated_network.tf
# Nettoyer, ajuster, tester
terraform plan # Vérifier : 0 changes
terraform apply # Importer
Phase 3 : Vérification et stabilisation
Après chaque lot d'imports :
# Vérifier qu'il n'y a aucun changement prévu
terraform plan
# Si des changements apparaissent :
# 1. Ajuster le code pour correspondre à l'état réel
# 2. OU utiliser ignore_changes si l'attribut est géré ailleurs
# 3. OU accepter le changement si c'est une normalisation souhaitée
# Vérifier le state
terraform state list
terraform state show aws_vpc.main
Phase 4 : Refactoring progressif
Une fois importé, le code est souvent brut. Refactorisez progressivement :
# Avant : valeurs hardcodées issues de l'import
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.large"
subnet_id = "subnet-0abc123"
}
# Après : variables et références
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
subnet_id = module.networking.private_subnet_ids[0]
tags = merge(local.common_tags, {
Name = "${var.project}-${var.environment}-web"
Role = "webserver"
})
}
Exemple Pratique Complet : Import d'une Infrastructure AWS
Voici un exemple complet et réaliste d'import d'une infrastructure AWS existante composée d'un VPC, d'un security group, d'une instance EC2 et d'un bucket S3.
Étape 1 : Recenser les ressources existantes
# Lister les VPCs
aws ec2 describe-vpcs --query 'Vpcs[*].[VpcId,CidrBlock,Tags[?Key==`Name`].Value|[0]]' --output table
# Résultat :
# | vpc-0abc123 | 10.0.0.0/16 | prod-vpc |
# Lister les Security Groups du VPC
aws ec2 describe-security-groups \
--filters "Name=vpc-id,Values=vpc-0abc123" \
--query 'SecurityGroups[*].[GroupId,GroupName]' \
--output table
# Lister les instances EC2
aws ec2 describe-instances \
--filters "Name=vpc-id,Values=vpc-0abc123" \
--query 'Reservations[*].Instances[*].[InstanceId,InstanceType,State.Name,Tags[?Key==`Name`].Value|[0]]' \
--output table
# Lister les buckets S3
aws s3 ls
Étape 2 : Créer la structure du projet
mkdir -p import-project
cd import-project
# Créer les fichiers de base
touch providers.tf imports.tf variables.tf
# providers.tf
terraform {
required_version = ">= 1.7.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.30"
}
}
backend "s3" {
bucket = "mon-entreprise-terraform-state"
key = "imported/prod/terraform.tfstate"
region = "eu-west-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
provider "aws" {
region = "eu-west-1"
}
Étape 3 : Écrire les blocs import
# imports.tf
import {
to = aws_vpc.prod
id = "vpc-0abc123"
}
import {
to = aws_security_group.web
id = "sg-0def456"
}
import {
to = aws_instance.web_server
id = "i-0ghi789"
}
import {
to = aws_s3_bucket.assets
id = "prod-company-assets"
}
Étape 4 : Générer et ajuster le code
# Initialiser Terraform
terraform init
# Générer le code
terraform plan -generate-config-out=generated.tf
# Examiner le code généré
cat generated.tf
Nettoyez ensuite le code généré pour le rendre maintenable :
# main.tf (version nettoyée du code généré)
locals {
environment = "prod"
project = "mon-projet"
common_tags = {
Environment = local.environment
Project = local.project
ManagedBy = "terraform"
}
}
resource "aws_vpc" "prod" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = merge(local.common_tags, {
Name = "${local.project}-${local.environment}-vpc"
})
lifecycle {
prevent_destroy = true
}
}
resource "aws_security_group" "web" {
name = "web-server-sg"
description = "Security group pour les serveurs web"
vpc_id = aws_vpc.prod.id
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "HTTPS"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "SSH depuis le VPN"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["10.10.0.0/16"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = merge(local.common_tags, {
Name = "${local.project}-${local.environment}-web-sg"
})
}
resource "aws_instance" "web_server" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.large"
subnet_id = "subnet-0abc123" # À remplacer par une référence après import du subnet
vpc_security_group_ids = [aws_security_group.web.id]
key_name = "prod-key"
root_block_device {
volume_type = "gp3"
volume_size = 50
encrypted = true
delete_on_termination = true
}
tags = merge(local.common_tags, {
Name = "${local.project}-${local.environment}-web"
Role = "webserver"
})
lifecycle {
prevent_destroy = true
ignore_changes = [ami] # L'AMI sera mise à jour par un autre processus
}
}
resource "aws_s3_bucket" "assets" {
bucket = "prod-company-assets"
tags = merge(local.common_tags, {
Name = "prod-company-assets"
})
lifecycle {
prevent_destroy = true
}
}
resource "aws_s3_bucket_versioning" "assets" {
bucket = aws_s3_bucket.assets.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "assets" {
bucket = aws_s3_bucket.assets.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
Étape 5 : Valider et appliquer
# Vérifier le plan
terraform plan
# Résultat attendu :
# Plan: 4 to import, 0 to add, 0 to change, 0 to destroy.
# Appliquer l'import
terraform apply
# Vérifier post-import
terraform plan
# Résultat : No changes. Your infrastructure matches the configuration.
# Supprimer les blocs import (plus nécessaires après l'apply)
rm imports.tf
# Vérification finale
terraform plan
# Résultat : No changes.
Import en Masse : Stratégies et Scripts
Pour les migrations à grande échelle avec des centaines de ressources, l'automatisation est indispensable.
Script d'import automatisé
#!/bin/bash
# import_resources.sh
# Script pour générer les blocs import à partir d'un inventaire AWS
set -euo pipefail
REGION="eu-west-1"
OUTPUT_FILE="imports.tf"
echo "# Blocs import générés automatiquement" > "$OUTPUT_FILE"
echo "# Date : $(date)" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
# Importer les VPCs
echo "=== Import des VPCs ==="
aws ec2 describe-vpcs --region "$REGION" \
--query 'Vpcs[*].[VpcId,Tags[?Key==`Name`].Value|[0]]' \
--output text | while read -r vpc_id vpc_name; do
resource_name=$(echo "$vpc_name" | tr '-' '_' | tr '[:upper:]' '[:lower:]')
cat >> "$OUTPUT_FILE" <> "$OUTPUT_FILE" <> "$OUTPUT_FILE" <Pipeline CI/CD pour l'import
# .gitlab-ci.yml pour la migration
stages:
- inventory
- generate
- review
- import
inventory:
stage: inventory
script:
- ./scripts/import_resources.sh
artifacts:
paths:
- imports.tf
generate:
stage: generate
script:
- terraform init
- terraform plan -generate-config-out=generated.tf
artifacts:
paths:
- generated.tf
- imports.tf
review:
stage: review
script:
- echo "Revue manuelle du code généré requise"
- cat generated.tf
when: manual
import:
stage: import
script:
- terraform init
- terraform apply -auto-approve
when: manual
dependencies:
- generate
Bonnes Pratiques pour l'Import
Checklist avant l'import
Avoir un remote backend configuré et fonctionnelFaire un snapshot ou backup de l'infrastructure existanteDocumenter toutes les ressources à importer avec leurs IDsPlanifier l'import par couches (réseau, puis IAM, puis compute, etc.)Tester d'abord sur un environnement non-productionInformer l'équipe que des imports sont en cours (pour éviter les modifications manuelles pendant l'import)
Checklist après l'import
Vérifier que terraform plan ne montre aucun changementNettoyer le code généré (remplacer les valeurs hardcodées par des variables)Ajouter prevent_destroy sur les ressources critiquesConfigurer ignore_changes pour les attributs gérés ailleursSupprimer les blocs import après le applyCommiter le code nettoyé et le fichier .terraform.lock.hclMettre en place une détection de drift régulière
Pièges à éviter
Ne jamais importer sans lire la documentation du provider : chaque ressource a un format d'ID spécifiqueNe pas importer et modifier en même temps : d'abord importer avec un plan clean, puis modifier dans des commits séparésAttention aux ressources avec des dépendances : importer dans le bon ordre pour que les références fonctionnentNe pas oublier les ressources associées : un bucket S3 a souvent des policies, du versioning, du chiffrement en ressources séparées dans TerraformTester avec terraform plan avant chaque apply : un plan qui montre des destructions après un import signifie que votre code ne correspond pas à la réalité
Conclusion
L'import de ressources existantes dans Terraform est une étape incontournable pour toute organisation qui adopte l'Infrastructure as Code progressivement. Que vous utilisiez la commande classique terraform import, les nouveaux blocs import de Terraform 1.5+, ou des outils comme Terraformer et aztfexport, le processus suit toujours le même schéma : identifier, importer, ajuster, valider.
Les points clés à retenir sont les suivants. Commencez par les couches fondamentales (réseau, IAM) avant les ressources applicatives. Utilisez les blocs import avec -generate-config-out pour accélérer le processus. Nettoyez toujours le code généré pour le rendre maintenable. Ajoutez prevent_destroy sur les ressources critiques. Validez chaque lot avec terraform plan avant de passer au suivant.
La migration vers l'IaC est un investissement qui porte ses fruits sur le long terme. Chaque ressource importée est une ressource de plus qui bénéficie de la traçabilité, de la reproductibilité et de la collaboration offertes par Terraform et le workflow GitOps.
Cet article conclut notre série approfondie sur Terraform. Vous disposez maintenant de toutes les connaissances nécessaires pour gérer votre infrastructure de manière professionnelle, des bonnes pratiques à l'intégration Kubernetes en passant par la migration de l'existant. Bonne infrastructure as code !