
Un workspace Terraform donne à une même configuration plusieurs instances
d'état. Un seul jeu de fichiers .tf, plusieurs états logiques, et une
expression, terraform.workspace, pour adapter ce que la configuration produit.
Le workspace default existe dès le premier init, et les autres se créent
avec terraform workspace new.
Tout ce qui suit a été exécuté sur Terraform v1.15.4, messages et codes de
retour compris. Deux idées répandues n'y survivent pas, celle du workspace
default qu'on pourrait supprimer en basculant ailleurs, et celle du
delete qui détruirait ce que le workspace gérait.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Créer, lister et sélectionner un workspace
- Où Terraform range les états, et où il range la sélection courante
- Dériver le nommage et le dimensionnement de
terraform.workspace - Sélectionner un workspace sans interaction, pour une chaîne d'intégration
- Retirer un workspace sans laisser d'objet orphelin
- Reconnaître les cas où un workspace n'est pas la bonne réponse
Prérequis
Section intitulée « Prérequis »- Terraform 1.11 ou plus récent (installer Terraform). Les mesures viennent de la branche stable du moment, 1.15.x.
- Comprendre le state Terraform, puisqu'un workspace n'isole que cela.
Créer, lister, basculer
Section intitulée « Créer, lister, basculer »Trois commandes suffisent à tout le cycle courant.
-
Lister ce qui existe. L'astérisque marque le workspace courant :
Fenêtre de terminal terraform workspace list* default -
Créer un workspace, ce qui bascule dessus dans la foulée :
Fenêtre de terminal terraform workspace new devCreated and switched to workspace "dev"!You're now on a new, empty workspace. Workspaces isolate their state,so if you run "terraform plan" Terraform will not see any existing statefor this configuration. -
Basculer vers un workspace existant :
Fenêtre de terminal terraform workspace select defaultSwitched to workspace "default".Si le workspace n'existe pas, Terraform le dit et propose les deux issues :
Workspace "recette" doesn't exist.You can create this workspace with the "new" subcommandor include the "-or-create" flag with the "select" subcommand.
L'option -or-create évite justement de tester l'existence avant de
basculer, ce qui en fait le motif employé en intégration continue :
terraform workspace select -or-create recetteOù vivent les états, et où vit la sélection
Section intitulée « Où vivent les états, et où vit la sélection »Deux emplacements différents, et les confondre est une source d'erreurs. Sur
un backend local, default garde son état à la racine, et chaque autre
workspace reçoit le sien sous terraform.tfstate.d/ :
terraform.tfstate <- defaultterraform.tfstate.d/dev/terraform.tfstateterraform.tfstate.d/prod/terraform.tfstateLe workspace sélectionné, lui, ne fait partie d'aucun état : il est écrit
dans .terraform/environment, un fichier local, dans un répertoire
ignoré par git.
cat .terraform/environmentdevAdapter la configuration au workspace
Section intitulée « Adapter la configuration au workspace »C'est l'expression terraform.workspace qui rend une configuration unique
utilisable par plusieurs environnements, sans y écrire aucun nom en dur :
resource "local_file" "app" { count = terraform.workspace == "prod" ? 3 : 1
filename = "${path.root}/sorties/app-${terraform.workspace}-${count.index}.conf" content = "environnement ${terraform.workspace} instance ${count.index}\n"}Le même code produit un fichier dans dev et trois dans prod. Une
variable ne ferait pas ce travail : elle garde la même valeur d'un workspace
à l'autre tant qu'on ne la surcharge pas à chaque commande.
Sélectionner sans interaction : TF_WORKSPACE
Section intitulée « Sélectionner sans interaction : TF_WORKSPACE »En automatisation, on ne veut pas dépendre d'une sélection implicite laissée
par une commande précédente. La variable d'environnement TF_WORKSPACE
désigne le workspace pour la commande en cours, sans toucher à la sélection
locale :
TF_WORKSPACE=prod terraform outputworkspace_actif = "prod"Mesuré : après cette commande, .terraform/environment contient toujours sa
valeur précédente. C'est précisément ce qu'on attend d'une chaîne
d'intégration, qui ne doit rien laisser derrière elle.
Reprendre un état existant
Section intitulée « Reprendre un état existant »Quand on scinde un projet, on veut parfois qu'un nouveau workspace démarre avec un état déjà rempli plutôt que vide :
terraform workspace new -state=ancien.tfstate repriseRetirer un workspace proprement
Section intitulée « Retirer un workspace proprement »C'est l'opération qui demande le plus d'attention, parce que la commande porte un nom qui suggère plus qu'elle ne fait.
terraform workspace delete bac-a-sableError: Workspace is not empty
Workspace "bac-a-sable" is currently tracking the following resource instances: - local_file.app[0] - random_pet.temoin
Deleting this workspace would cause Terraform to lose track of any associatedremote objects, which would then require you to delete them manually outsideof Terraform. You should destroy these objects with Terraform before deletingthe workspace.Le garde-fou est clair, et l'ordre correct l'est tout autant : on détruit, puis on supprime.
TF_WORKSPACE=bac-a-sable terraform destroy -auto-approveterraform workspace delete bac-a-sableTrois conditions doivent donc être réunies pour qu'un delete aboutisse : le
workspace existe, il ne suit aucune ressource, et ce n'est pas le
workspace courant.
Les pièges mesurés
Section intitulée « Les pièges mesurés »Le mécanisme est en place. Voici ce qui casse en pratique, chaque cas ayant été rejoué.
-force supprime l'état, pas les ressources
Section intitulée « -force supprime l'état, pas les ressources »C'est le piège le plus coûteux, parce que la commande réussit :
terraform workspace delete -force prodDeleted workspace "prod"!
WARNING: "prod" was non-empty.The resources managed by the deleted workspace may still exist,but are no longer manageable by Terraform since the state has been deleted.Mesuré : les trois fichiers produits par prod sont toujours sur le disque
après cette commande, et plus aucun état ne les connaît. Ce sont des
orphelins, qu'il faudra retrouver et supprimer à la main.
Le workspace default ne se supprime jamais
Section intitulée « Le workspace default ne se supprime jamais »Beaucoup de guides expliquent qu'il suffit de basculer ailleurs avant de
supprimer. C'est vrai pour un workspace ordinaire, et faux pour
default. Depuis default lui-même :
Workspace "default" is your active workspace.
You cannot delete the currently active workspace. Please switchto another workspace and try again.Ce message invite bien à basculer. Mais une fois basculé, le contrôle suivant répond :
Cannot delete the default workspaceBasculer ne débloque donc rien : default n'est pas supprimable, et le
conseil habituel envoie le lecteur dans un mur.
TF_WORKSPACE crée un workspace fantôme
Section intitulée « TF_WORKSPACE crée un workspace fantôme »Voici le fait le plus contre-intuitif de cette page, vérifié sur un projet
neuf. Si TF_WORKSPACE désigne un workspace qui n'existe pas, la commande ne
proteste pas : elle le crée.
TF_WORKSPACE=prd terraform planAprès ce simple plan, terraform.tfstate.d/prd/ existe, et un apply qui
suivrait y écrirait son état. Une faute de frappe dans une variable
d'environnement suffit donc à fabriquer un environnement parallèle, sans le
moindre avertissement.
Deux commandes refusent de tourner tant que TF_WORKSPACE est posé
Section intitulée « Deux commandes refusent de tourner tant que TF_WORKSPACE est posé »L'effet de bord est documenté, et il déroute quand on l'oublie dans un shell interactif :
The selected workspace is currently overridden using the TF_WORKSPACEenvironment variable.
To select a new workspace, either update this environment variable or unsetit and then run this command again.workspace select et workspace new sortent en 1 dans ce cas. La
documentation déconseille formellement de poser cette variable dans un shell
interactif, précisément parce qu'on oublie qu'elle est là.
Tous les backends ne gèrent pas les workspaces
Section intitulée « Tous les backends ne gèrent pas les workspaces »Parler de « backend distant » en général induit en erreur. Dix backends seulement gèrent plusieurs workspaces nommés : AzureRM, Consul, COS, GCS, Kubernetes, Local, OSS, Postgres, Remote et S3. Les autres n'exposent qu'un seul état, et la question ne se pose donc pas.
Le nom d'un workspace n'accepte pas tout
Section intitulée « Le nom d'un workspace n'accepte pas tout »Le nom doit rester valide dans un segment d'URL, pour que tous les backends puissent le stocker sans échappement :
The workspace name "avec/slash" is not allowed. The name must contain only URLsafe characters, contain no path separators, and not be an empty string.Quand un workspace n'est pas la bonne réponse
Section intitulée « Quand un workspace n'est pas la bonne réponse »Le cas d'usage que la documentation met en avant est le court terme : un
workspace adossé à une branche de fonctionnalité, default portant la
production, le workspace temporaire étant détruit puis supprimé après la
fusion.
Pour des environnements durables, la réponse officielle est différente, et elle tient en une phrase : « Workspaces are not appropriate for system decomposition or deployments requiring separate credentials and access controls », parce que les workspaces d'un répertoire de travail utilisent le même backend. L'alternative recommandée est un module réutilisable appelé par une configuration racine par déploiement, chacune avec son propre backend, ce que détaille séparer dev, staging et prod.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Correction |
|---|---|---|
Workspace is not empty | le workspace suit encore des ressources | terraform destroy d'abord, puis delete |
Cannot delete the default workspace | tentative de supprimer default | il n'est pas supprimable, basculer ne change rien |
You cannot delete the currently active workspace | suppression depuis le workspace lui-même | basculer sur un autre workspace, puis supprimer |
Workspace "x" doesn't exist | sélection d'un workspace absent | terraform workspace new x, ou select -or-create x |
The selected workspace is currently overridden | TF_WORKSPACE est posé | la retirer de l'environnement, ou l'aligner sur la cible |
un environnement inconnu apparaît dans workspace list | TF_WORKSPACE mal orthographié : la commande l'a créé | supprimer le workspace fantôme, et fixer la variable |
| des ressources ne sont plus gérées par personne | delete -force sur un workspace non vide | les retrouver et les supprimer à la main : l'état est perdu |
| deux personnes appliquent au mauvais endroit | la sélection vit dans .terraform/, non partagée | poser TF_WORKSPACE explicitement dans les commandes |
Mettre en pratique
Section intitulée « Mettre en pratique »Le lab un seul répertoire, trois états livre une configuration troué et un
workspace hérité déjà appliqué, à retirer sans laisser d'orphelin. Les tests
n'ouvrent aucun .tf : ils interrogent chaque workspace par TF_WORKSPACE, sans
toucher à votre sélection, et lisent l'inventaire dans terraform.tfstate.d/.
Le contrôle décisif applique la configuration dans un workspace témoin que
vous n'avez jamais vu : une valeur en dur y produit le mauvais nom et tombe. Il
se joue hors ligne.
À retenir
Section intitulée « À retenir »- Un workspace isole un état, et rien d'autre : ni backend, ni credentials, ni répertoire.
- Sur backend local,
defaultreste à la racine, les autres vont sousterraform.tfstate.d/. - La sélection courante vit dans
.terraform/environment, fichier local jamais partagé. terraform.workspaceest ce qui adapte la configuration ; une variable ne suit pas le workspace.select -or-createévite le test d'existence, etnew -state=démarre un workspace depuis un état existant.deletene détruit rien : il refuse tant que le workspace suit des ressources.-forceréussit et laisse des orphelins : l'état disparaît, les objets restent.defaultn'est jamais supprimable, et basculer ailleurs n'y change rien.TF_WORKSPACEcrée le workspace s'il est absent, et bloqueselectcommenewtant qu'il est posé.- Pour des environnements durables à droits distincts, la réponse est une racine par déploiement, pas un workspace.
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les questions ci-dessous portent sur ce qui surprend en pratique : la
suppression qui ne détruit rien, le workspace default qui résiste, et la
variable d'environnement qui fabrique un environnement.
Le garde-fou
Error: Workspace is not empty
Workspace "bac-a-sable" is currently tracking the following resource instances:
- local_file.app[0]
- random_pet.temoin
Deleting this workspace would cause Terraform to lose track of any associated
remote objects, which would then require you to delete them manually outside
of Terraform.
L'ordre correct
TF_WORKSPACE=bac-a-sable terraform destroy -auto-approve
terraform workspace delete bac-a-sable
On détruit, puis on supprime. delete ne fait que retirer un fichier d'état : ce qu'il gérait continue d'exister.Deux messages, un seul verdict
Depuisdefault lui-même :Workspace "default" is your active workspace.
You cannot delete the currently active workspace. Please switch
to another workspace and try again.
Ce message invite à basculer. Une fois basculé sur un autre workspace :Cannot delete the default workspace
Pourquoi cela compte
Beaucoup de guides s'arrêtent au premier message et concluent qu'il suffit de basculer. Mesuré sur Terraform 1.15.4, cela ne débloque rien :default existe dès le premier init et ne peut pas être retiré.Si son état vous gêne, videz-le avec un terraform destroy, mais le workspace restera.L'usage prévu
TF_WORKSPACE=prod terraform output
workspace_actif = "prod"
Mesuré : après cette commande, .terraform/environment contient toujours sa valeur précédente. La commande n'a rien laissé derrière elle, ce qu'on attend d'un pipeline.Deux effets de bord
Tant que la variable est posée, deux commandes refusent de tourner, en code 1 :The selected workspace is currently overridden using the TF_WORKSPACE
environment variable.
C'est le cas de workspace select et de workspace new. La documentation déconseille donc formellement de poser cette variable dans un shell interactif : on oublie qu'elle est là.Mesuré sur un projet neuf
Avant :workspace list ne connaît que default, et terraform.tfstate.d n'existe pas.TF_WORKSPACE=faute-de-frappe terraform plan
Après ce plan seul :workspace list : ['* default', 'faute-de-frappe']
terraform.tfstate.d : ['faute-de-frappe']
Un apply qui suit y écrit son état et produit ses ressources.La conséquence
Une faute de frappe dans une variable d'environnement de CI ne fait pas échouer la commande : elle fabrique un environnement parallèle, vide au départ, et applique dedans. Rien ne le signale.Le garde-fou pratique consiste à lister les workspaces attendus avant d'appliquer, ou à comparerterraform.tfstate.d/ à une liste connue.Le fichier
cat .terraform/environment
dev
Il vit dans .terraform/, répertoire ignoré par git. La sélection ne fait donc partie ni de l'état, ni du dépôt.Ce qu'il faut en retenir
La sélection est une propriété de votre poste, pas du projet. Sur un poste partagé ou en CI, ne vous fiez jamais à la sélection courante : nommez le workspace explicitement, avecTF_WORKSPACE ou un workspace select en début de chaîne.À noter aussi : le fichier est absent tant qu'on n'a jamais quitté default.L'expression
resource "local_file" "app" {
count = terraform.workspace == "prod" ? 3 : 1
filename = "${path.root}/sorties/app-${terraform.workspace}-${count.index}.conf"
content = "environnement ${terraform.workspace} instance ${count.index}\n"
}
Le même code produit un fichier dans dev et trois dans prod.Pourquoi pas une variable
Une variable garde la même valeur d'un workspace à l'autre tant qu'on ne la surcharge pas à chaque commande. Elle ne suit donc pas la bascule, et c'est une source classique de ressources mal nommées.Le test qui tranche : appliquer dans un workspace dont le nom n'apparaît nulle part dans la configuration. Si le résultat porte ce nom, la dérivation est correcte.La liste
AzureRM, Consul, COS, GCS, Kubernetes, Local, OSS, Postgres, Remote et S3.Parler de « backend distant » en général induit en erreur : la prise en charge des workspaces est une propriété de chaque backend, pas du fait d'être distant.Le point qui compte davantage
Même sur un backend qui les gère, les workspaces d'un répertoire de travail partagent le même backend, donc les mêmes credentials et les mêmes droits.C'est la raison pour laquelle la documentation les écarte pour des déploiements exigeant des accès distincts, et recommande à la place une configuration racine par déploiement.La commande
terraform workspace new -state=ancien.tfstate reprise
Le message trompeur
Terraform répond exactement comme pour une création ordinaire :Created and switched to workspace "reprise"!
You're now on a new, empty workspace.
Or l'état n'est pas vide. Mesuré juste après :terraform state list
local_file.sortie[0]
local_file.sortie[1]
local_file.sortie[2]
random_pet.temoin
Fiez-vous à state list, pas au message affiché.Pour aller plus loin
Section intitulée « Pour aller plus loin »- Séparer dev, staging et prod : l'alternative officielle quand les environnements ont des droits distincts.
- Gérer les variables par environnement : faire varier les valeurs, une fois les états rangés.
- Quiz Organiser les environnements Terraform : un contrôle des acquis sur la section.
- Les workspaces d'état : la référence officielle : le périmètre exact, et les alternatives.
- La commande workspace : la référence officielle :
new,select,deleteet leurs options.