Quand une seule configuration d'infrastructure doit servir plusieurs environnements

Vous avez une configuration Terraform qui définit votre VPC, vos sous-réseaux et votre équilibreur de charge. Elle fonctionne parfaitement pour votre environnement de développement. Maintenant, vous avez besoin de la même configuration pour la préproduction et la production. L'approche naïve consiste à copier trois fois le dossier entier et à modifier quelques valeurs de variables. Cela fonctionne jusqu'à ce que vous deviez mettre à jour une règle de groupe de sécurité, et vous réalisez que vous devez faire la même modification à trois endroits, en espérant ne pas en oublier un.

Le problème n'est pas d'écrire du code d'infrastructure. Le problème est de gérer le même code sur plusieurs environnements sans tout dupliquer ni casser accidentellement la production pendant que vous travaillez sur le développement.

Deux approches courantes résolvent ce problème : les workspaces et les modules racines séparés. Elles traitent le même problème de manière fondamentalement différente, et le choix entre elles dépend du fonctionnement de votre équipe et du degré de séparation dont vos environnements ont besoin.

Workspaces : un seul code source, plusieurs états

Les workspaces sont une fonctionnalité intégrée à des outils comme Terraform qui vous permet d'utiliser le même code source avec différents fichiers d'état. Considérez cela comme un seul dossier de configuration qui peut produire trois environnements différents. Le code est identique. Ce qui change, c'est le fichier d'état qui suit ce qui a été déployé.

Le flux de travail est simple. Vous créez un workspace pour chaque environnement, puis vous basculez vers le workspace correct avant d'exécuter des modifications. L'outil achemine automatiquement les lectures et écritures d'état vers le bon emplacement backend en fonction du workspace actif. Si vous êtes dans le workspace de développement, vos modifications n'affectent que l'état de développement. L'état de production reste intact.

Voici à quoi ressemble ce flux de travail en pratique :

# Créer un workspace pour chaque environnement
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod

# Basculer vers le workspace de développement
export TF_WORKSPACE=dev
# Ou utiliser : terraform workspace select dev

# Planifier et appliquer les modifications pour le workspace actif
export TF_VAR_instance_type=t3.micro
terraform plan -out=dev.tfplan
terraform apply dev.tfplan

# Basculer vers la production quand c'est prêt
export TF_WORKSPACE=prod
export TF_VAR_instance_type=t3.large
terraform plan -out=prod.tfplan
terraform apply prod.tfplan
flowchart TD subgraph Workspaces A1["Un seul code source"] --> B1["Workspace : dev"] A1 --> C1["Workspace : staging"] A1 --> D1["Workspace : prod"] B1 --> E1["État : dev"] C1 --> F1["État : staging"] D1 --> G1["État : prod"] E1 --> H1["Un seul backend"] F1 --> H1 G1 --> H1 end subgraph Modules_racines I1["Module partagé"] --> J1["Config racine : dev"] I1 --> K1["Config racine : staging"] I1 --> L1["Config racine : prod"] J1 --> M1["Backend : dev"] K1 --> N1["Backend : staging"] L1 --> O1["Backend : prod"] end

Cela fonctionne bien lorsque vos environnements sont similaires et que les différences se limitent à des valeurs de variables. Peut-être que le développement utilise des instances plus petites, la préproduction des instances moyennes et la production les plus grandes. La structure est la même. Seuls les nombres changent.

Mais les workspaces ont un coût caché. Comme tous les environnements vivent dans le même code source, le risque d'opérer sur le mauvais workspace est réel. Un développeur travaillant dans le workspace de développement peut accidentellement exécuter un plan ou un apply contre la production s'il oublie de basculer. L'outil ne l'empêche pas. Il suit seulement quel workspace est actif. L'attention humaine devient la barrière de sécurité.

Il y a une autre limitation. Lorsque vous modifiez la structure de la configuration, tous les environnements reçoivent la modification en même temps. Vous ne pouvez pas mettre à jour la préproduction d'abord, vérifier que cela fonctionne, puis déployer la même modification en production un jour plus tard. Tous les environnements évoluent ensemble car ils partagent le même code. Si la modification casse quelque chose, elle casse tout simultanément.

Modules racines : dossiers séparés, logique partagée

L'alternative est de donner à chaque environnement son propre module racine. Au lieu d'un dossier avec trois workspaces, vous avez trois dossiers : dev, staging et prod. Chaque dossier contient son propre fichier de configuration principal et sa propre configuration de backend d'état. Ils sont complètement indépendants.

Mais vous ne réécrivez pas la logique d'infrastructure trois fois. Chaque module racine appelle les mêmes modules partagés depuis un répertoire modules. La définition du VPC, la logique des sous-réseaux, la configuration de l'équilibreur de charge vivent toutes dans des modules réutilisables. Les modules racines appellent simplement ces modules avec des variables spécifiques à l'environnement.

L'avantage est clair. Vous ne pouvez pas modifier accidentellement la production en travaillant sur le développement car vous devez explicitement changer de répertoire. La séparation est physique, pas seulement logique. Vous pouvez également mettre à jour les environnements indépendamment. La production peut rester sur une version stable d'un module pendant que le développement utilise la dernière version avec des modifications expérimentales. La préproduction peut être mise à jour en premier, testée, puis promue en production.

L'inconvénient est la duplication, mais c'est une duplication structurelle, pas logique. Vous répétez les appels de modules et les définitions de variables pour chaque environnement. Vous ne répétez pas la logique d'infrastructure réelle. Les modules contiennent la logique, et ils sont partagés. La duplication se trouve dans le câblage, pas dans l'implémentation.

Quand utiliser quoi

Les workspaces conviennent aux petites équipes avec peu d'environnements et des différences minimes entre eux. Si vous avez deux environnements presque identiques, les workspaces réduisent la surcharge. Vous écrivez le code une fois, et le workspace gère la séparation des états.

Les modules racines fonctionnent mieux pour les grandes équipes, les environnements qui nécessitent une séparation stricte, ou les situations où chaque environnement nécessite des flux d'approbation différents. Si les modifications de production nécessitent une revue de pull request, une approbation du responsable et une fenêtre de changement, tandis que les modifications de développement peuvent être appliquées directement, les modules racines rendent cette séparation naturelle. Chaque dossier d'environnement peut avoir son propre pipeline CI/CD avec des barrières différentes.

De nombreuses équipes commencent avec les workspaces car ils sont plus simples à configurer. Au fur et à mesure que l'équipe grandit et que le nombre d'environnements augmente, elles migrent vers les modules racines. La migration n'est pas douloureuse car les modules sont déjà séparés. Vous créez simplement de nouveaux dossiers racines qui appellent les mêmes modules.

Une liste de contrôle pratique

Avant de choisir votre approche, passez en revue ces questions :

  • Combien d'environnements gérez-vous ? Plus de trois pousse vers les modules racines.
  • Les environnements ont-ils besoin de processus d'approbation différents ? Oui signifie modules racines.
  • Une erreur dans un environnement peut-elle en affecter un autre ? Si oui, les modules racines réduisent ce risque.
  • Votre équipe compte-t-elle plus de cinq personnes ? Les grandes équipes bénéficient d'une séparation explicite par dossier.
  • Avez-vous besoin de mettre à jour les environnements à des moments différents ? Les modules racines permettent des déploiements progressifs.

Si vous avez répondu oui à trois de ces questions ou plus, commencez par les modules racines. Si vous avez répondu non à la plupart d'entre elles, les workspaces vous conviendront pour l'instant.

L'essentiel à retenir

Les workspaces et les modules racines résolvent le même problème avec des compromis différents. Les workspaces réduisent la duplication de code mais augmentent le risque opérationnel. Les modules racines ajoutent de la duplication structurelle mais offrent des limites claires entre les environnements. Choisissez en fonction du fonctionnement de votre équipe et du degré d'isolation dont vos environnements ont besoin. Commencez simplement, mais sachez quand changer. L'objectif n'est pas de choisir l'approche parfaite dès le premier jour. L'objectif est de reconnaître quand votre approche actuelle commence à causer plus de problèmes qu'elle n'en résout.