Le cas typique du terraform import resource, sur une plateforme Azure déjà en production, consiste à rattacher une ressource existante à un state Terraform sans la recréer. La difficulté n’est pas la syntaxe brute de la commande, mais le trio qui l’entoure: un ID exact, une configuration qui colle à la réalité et un backend de state propre. Je vais aller droit au but: ce qui change dans l’état, comment préparer Azure, comment importer pas à pas, et quand le workflow moderne avec bloc import est plus sûr.
Ce qu’il faut garder en tête avant de reprendre une ressource Azure
- Terraform ne modifie pas votre infrastructure existante quand il l’importe: il la rattache à une adresse dans le state.
- La commande classique
terraform importfonctionne ressource par ressource; pour un usage durable, le blocimportest souvent plus robuste. - Sur Azure, l’ID à importer dépend du provider et du type de ressource; le nom visible dans le portail ne suffit pas toujours.
- Un import réussi peut quand même produire un plan de remplacement si la configuration ne reflète pas l’existant.
- Pour un nouveau backend Azure, je privilégie Microsoft Entra ID plutôt que les clés d’accès ou les SAS.
Ce que l’import change vraiment dans le state
Je vois souvent l’import comme une opération de mise en correspondance, pas comme une opération de création. Terraform garde en mémoire l’état réel de l’infrastructure, puis il compare cet état à votre configuration pour décider quoi faire ensuite. L’import sert simplement à dire: « cette ressource déjà présente dans Azure doit désormais être gérée à cette adresse Terraform ».
La conséquence est simple, mais on l’oublie facilement: l’import ne réécrit pas votre ressource. Il ne corrige ni les paramètres, ni les defaults, ni les écarts de configuration. C’est pour cela qu’un import peut être techniquement réussi et produire malgré tout un plan agressif au prochain terraform plan. Dans la pratique, je considère l’import comme réussi seulement si le plan suivant devient lisible, puis neutre ou presque.
La documentation HashiCorp insiste aussi sur un point que j’applique toujours: un objet distant ne doit pas être lié à plusieurs adresses Terraform. Si vous le rattachez deux fois, vous créez une ambiguïté dans le state et, tôt ou tard, un comportement imprévisible. Cette règle est encore plus importante dans les environnements Azure où beaucoup de ressources partagent des dépendances implicites.
Une fois cette logique comprise, le vrai sujet devient beaucoup plus concret: comment préparer Azure pour que l’import ne tourne pas au bricolage. C’est là que le backend et les droits d’accès comptent autant que la commande elle-même.
Préparer Azure avant de toucher à l’infrastructure
Sur Azure, je prépare toujours trois choses avant d’importer quoi que ce soit: le backend du state, les permissions et l’adresse exacte de la ressource. Si l’un des trois manque, on finit souvent avec un import partiel, un state dispersé ou un plan impossible à interpréter.
Pour un projet sérieux, je centralise le state dans un backend azurerm adossé à Azure Storage. Côté authentification, je privilégie Microsoft Entra ID pour les nouveaux workloads. Les clés d’accès et les SAS existent toujours, mais je les réserve aux cas hérités; ils sont plus difficiles à gouverner proprement dans la durée.
- Le state doit vivre dans un emplacement partagé et verrouillable.
- Le compte d’exécution doit avoir le rôle
Storage Blob Data Contributorsur le conteneur du state. - Le rôle
Readern’est utile que si le backend doit résoudre un endpoint de stockage spécifique. - La ressource à importer doit déjà exister dans Azure et son ID ARM complet doit être connu.
- Le bloc
resourcecorrespondant doit exister dans la configuration, même s’il est encore minimal.
J’ajoute souvent un dernier contrôle très pragmatique: l’adresse Terraform doit refléter la vraie structure du projet. Si vous savez déjà que la ressource appartient à un module, importez-la à sa destination finale, pas dans le root pour la déplacer ensuite. Cela évite un aller-retour inutile dans le state.
Une fois le terrain propre, on peut passer à l’exécution. Le point clé, ici, n’est pas de taper une commande vite, mais de l’exécuter avec la bonne adresse et le bon identifiant.

Importer une ressource Azure pas à pas
Pour un premier import, je recommande une ressource simple et peu risquée, par exemple un groupe de ressources ou une ressource réseau périphérique. L’idée est de valider le flux complet avant de toucher à des composants plus sensibles comme Key Vault, les réseaux privés ou l’identité.
- Déclarez la ressource dans votre configuration avec les champs essentiels seulement.
- Récupérez l’ID ARM exact de la ressource dans Azure.
- Exécutez
terraform importavec l’adresse Terraform et l’ID de la ressource. - Vérifiez le résultat avec
terraform state showpuisterraform plan. - Ajustez la configuration jusqu’à obtenir un plan propre.
Exemple minimal:
resource "azurerm_resource_group" "rg_prod" {
name = "rg-prod"
location = "westeurope"
}terraform import azurerm_resource_group.rg_prod /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-prod
terraform state show azurerm_resource_group.rg_prod
terraform planLe détail important, ici, c’est l’adresse du state: azurerm_resource_group.rg_prod doit correspondre exactement à votre bloc resource. Pour une ressource placée dans un module, l’adresse devient par exemple module.network.azurerm_subnet.app. Je préfère toujours vérifier cette correspondance avant l’import, parce qu’une erreur d’adresse est plus coûteuse à corriger qu’une erreur de commande.
Si le plan affiche une destruction ou une recréation, je n’applique pas immédiatement. Je considère ce résultat comme un signal: soit la configuration est incomplète, soit l’ID n’est pas le bon, soit la ressource a des propriétés obligatoires que je n’ai pas encore modélisées. C’est précisément pour réduire ce genre de friction que le workflow moderne a pris de l’importance.
Pourquoi le bloc d’import est souvent plus robuste que la commande classique
Depuis Terraform 1.5, le workflow fondé sur un bloc import est devenu mon option par défaut dans les équipes qui veulent quelque chose de traçable et de révisable. La raison est simple: on ne se contente pas d’exécuter une action locale, on versionne l’intention dans la configuration elle-même. Résultat: le processus s’intègre mieux aux revues de code, à Azure DevOps et aux pipelines CI/CD.
Le bloc import dit explicitement à Terraform quelle ressource distante doit être liée à quelle adresse. La configuration reste lisible, et le plan permet de voir ce qui va se passer avant de modifier le state. Si besoin, Terraform peut aussi générer une base de configuration à partir de la ressource importée, ce qui évite de repartir de zéro quand l’existant est mal documenté.
import {
to = azurerm_resource_group.rg_prod
id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-prod"
}Je résume souvent les options de cette façon:
| Méthode | Ce qu’elle apporte | Limite principale | Mon usage |
|---|---|---|---|
terraform import en CLI |
Rapide et direct | Une ressource à la fois, peu de visibilité avant exécution | Correction ponctuelle ou petit périmètre |
Bloc import
|
Versionnable, prévisible, compatible CI/CD | Nécessite une configuration minimale | Choix par défaut pour Azure |
-generate-config-out |
Génère une base de HCL à partir de l’existant | Le résultat est souvent trop verbeux et doit être nettoyé | Quand l’existant est mal documenté |
| Import en lot | Adapté à de gros parcs | Montage plus lourd | Grandes organisations avec beaucoup de ressources Azure |
La documentation HashiCorp va dans le même sens: le bloc import doit s’accompagner d’un resource correspondant, et la génération de configuration sert surtout de point de départ, pas de vérité finale. Je partage cette approche, parce qu’elle réduit nettement les surprises au moment de l’apply. La vraie discipline consiste ensuite à nettoyer la configuration générée pour ne conserver que ce qui compte.
Une fois cette logique en place, la question suivante devient naturellement celle de l’échelle: comment faire quand les ressources sont dans des modules ou quand l’infrastructure Azure est vaste. C’est là que la structure du code commence à peser autant que l’import lui-même.
Importer dans les modules et à grande échelle
Dans un projet Azure mature, les ressources sont rarement au niveau racine. Elles vivent dans des modules, parfois profondément imbriqués, et l’adresse d’import doit suivre cette structure. Si la ressource appartient au module réseau, l’adresse peut ressembler à module.network.azurerm_virtual_network.vnet; si elle est dans un sous-module, l’adresse s’allonge encore. Je préfère le rappeler parce qu’un import au mauvais endroit donne l’impression d’un problème Terraform alors qu’il s’agit souvent juste d’un mauvais chemin.
Pour éviter de casser la logique du projet, j’importe directement à l’adresse cible. Cela évite de créer une ressource au root puis de la déplacer dans un second temps. Sur le papier, ce détour paraît anodin; en pratique, il ajoute une source de divergence entre la configuration, le state et l’organisation du module.
- Ressource isolée si vous devez corriger un objet unique ou un petit lot homogène.
-
Bloc
importou génération de configuration si vous voulez tracer l’opération et la faire passer par une revue. - Import en lot seulement si les conventions de nommage, les providers et le backend sont déjà bien stabilisés.
- AzAPI ou AzureRM selon la couverture réelle du service Azure concerné, surtout pour les ressources les plus récentes.
Quand le volume devient important, il faut penser processus avant de penser vitesse. Sur une grande plateforme Microsoft, ce n’est pas la commande qui manque le plus, c’est la capacité à maintenir un état cohérent à long terme. C’est aussi pour cela que je traite les imports comme une étape d’onboarding de l’existant, pas comme un simple geste d’administration.
Avant de parler d’erreurs, il reste un point utile: les importations échouent rarement pour une raison mystérieuse. Elles échouent le plus souvent pour cinq causes très banales, mais évitables.
Les erreurs qui font échouer un import propre
Le premier piège, c’est l’ID incomplet ou incorrect. Sur Azure, je m’attends à un identifiant ARM complet qui commence souvent par /subscriptions/.... Si vous ne fournissez qu’un nom court, Terraform peut ne pas trouver la ressource attendue ou, pire, viser le mauvais scope.
Le deuxième piège, c’est l’adresse Terraform mal alignée. La ressource existe peut-être bien dans Azure, mais elle n’est pas déclarée à la bonne adresse dans le code. Dans ce cas, l’import semble fonctionner, puis le plan suivant révèle que Terraform ne parle pas de la même chose que vous.
- La configuration ne correspond pas à l’existant quand un attribut obligatoire manque ou qu’une valeur par défaut a été oubliée.
- Le même objet est importé deux fois quand l’équipe teste plusieurs chemins sans nettoyer le state.
- Le backend est mal préparé quand le state n’est pas centralisé ou que les permissions sont insuffisantes.
- Le plan de vérification est ignoré alors qu’il révèle immédiatement un remplacement involontaire.
- Le provider n’est pas le bon quand un service Azure récent demande une prise en charge différente.
Je regarde aussi les ressources qui impliquent des dépendances plus sensibles que les autres. Réseaux, identité, Key Vault, points de terminaison privés: ce sont souvent elles qui affichent les diffs les plus trompeurs. Quand un plan annonce une recréation alors que vous vouliez seulement reprendre le contrôle, je ralentis immédiatement et je corrige la configuration avant toute exécution supplémentaire.
À ce stade, la logique est claire: l’import n’est pas un raccourci, c’est une phase de remise en ordre. La dernière étape consiste donc à garder quelques repères simples pour que l’opération reste propre au fil des ressources ajoutées.
Les repères que je garde pour un import Azure sans casse
- Je commence par une ressource peu critique pour valider le flux complet de bout en bout.
- Je documente l’ID ARM, l’adresse Terraform et le backend dans la même demande de changement.
- Je ne valide jamais un import tant que le
terraform plansuivant n’est pas compréhensible. - Je traite les ressources en module à leur adresse finale, pas dans un emplacement temporaire.
- Je passe au bulk import seulement quand les conventions de nommage et les providers sont déjà stables.
Si je devais réduire toute la méthode à une règle pratique, ce serait celle-ci: importe d’abord, aligne ensuite, automatise seulement quand le plan est propre. C’est la différence entre une reprise d’existant maîtrisée et une migration qui laisse le state plus fragile qu’avant.
