Le bloc remote_state de root.hcl décrit le backend une seule fois, et
chaque unit qui inclut ce fichier en hérite avec sa propre clé de state.
Terragrunt écrit alors lui-même le fichier backend.tf grâce au sous-bloc
generate, au lieu que vous le recopiez dans chaque dossier. Cette leçon
construit le mécanisme sur un backend local, rejoué avec Terragrunt
1.1.6 et OpenTofu 1.13.1, puis montre la forme S3 qui s'en déduit.
Elle suppose le live repo structuré
et les backends
Terraform ou OpenTofu.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Lire le rôle de
remote_statedansroot.hcl - Donner à chaque unit sa clé de state avec
path_relative_to_include() - Savoir quand utiliser
generatepour factoriser une configuration répétée - Transposer le motif vers un backend S3 sans copier une forme dépréciée
Pourquoi centraliser le backend ?
Section intitulée « Pourquoi centraliser le backend ? »Sans centralisation, chaque unit redéfinit le stockage distant, la clé de state et les options propres au backend. Ce n'est pas seulement long à écrire, c'est fragile : une variation minime entre deux units produit des comportements difficiles à relire par la suite, par exemple deux units qui écrivent dans le même state. Centraliser donne un seul endroit où décider, et un seul endroit où corriger.
Quelle structure prépare-t-on ?
Section intitulée « Quelle structure prépare-t-on ? »Le scénario repart du module write-file des leçons précédentes. La différence
est que root.hcl porte maintenant un bloc remote_state, et que le unit
dev/app ne contient plus aucune configuration de backend.
Répertoirelab-d/
Répertoiremodules/
Répertoirewrite-file/
- main.tf
Répertoirelive/
- root.hcl
Répertoiredev/
Répertoireapp/
- terragrunt.hcl
Le module modules/write-file/main.tf est identique à celui du premier
projet :
reprenez-le tel quel.
Comment écrire remote_state avec un backend local ?
Section intitulée « Comment écrire remote_state avec un backend local ? »Le backend local permet de jouer le mécanisme sans aucun service. Le bloc
remote_state dit quel backend, avec quelle configuration, et le
sous-bloc generate dit où écrire le fichier de backend. Copiez dans
live/root.hcl :
remote_state { backend = "local" config = { path = "${get_parent_terragrunt_dir()}/.states/${path_relative_to_include()}/terraform.tfstate" } generate = { path = "backend.tf" if_exists = "overwrite_terragrunt" }}Deux fonctions font le travail. get_parent_terragrunt_dir() renvoie le
dossier du root.hcl inclus, donc live/. path_relative_to_include()
renvoie le chemin du unit relativement à ce dossier, donc dev/app. Leur
assemblage donne une clé propre à chaque unit : deux units ne peuvent plus
écraser le state l'un de l'autre.
Comment le unit réutilise-t-il cette configuration ?
Section intitulée « Comment le unit réutilise-t-il cette configuration ? »Le unit inclut la racine et n'écrit plus rien sur le backend. Copiez dans
live/dev/app/terragrunt.hcl :
include "root" { path = find_in_parent_folders("root.hcl")}
terraform { source = "../../../modules/write-file"}
inputs = { filename = "${get_terragrunt_dir()}/remote-state.txt" content = "hello with remote state"}Lancez ensuite, depuis live/dev/app :
terragrunt apply -auto-approveVérification : l'apply réussit, le fichier remote-state.txt existe à côté
du terragrunt.hcl, et le state se trouve dans live/.states/dev/app/terraform.tfstate.
Le fichier backend.tf est généré dans la copie de travail de Terragrunt, pas
dans votre source : vous n'avez rien à y versionner. Nettoyez avec
terragrunt destroy -auto-approve.
Ce state n'est plus dans le cache : vider .terragrunt-cache ne le supprime
plus. Il reste un fichier local sensible, car un state peut contenir des
secrets en clair. Ajoutez donc à votre .gitignore :
.terragrunt-cache/live/.states/Comment lire ce bloc ?
Section intitulée « Comment lire ce bloc ? »Chaque élément de remote_state répond à une question. Le tableau les résume
pour le backend local de cette leçon.
| Élément | Rôle | Pourquoi c'est utile |
|---|---|---|
backend = "local" | Choisit le type de backend | Aucun service nécessaire pour apprendre |
config.path | Chemin du fichier de state | Construit avec path_relative_to_include(), il est distinct par unit |
generate.path | Nom du fichier écrit dans la copie de travail | Évite de recopier un backend.tf à la main |
if_exists = "overwrite_terragrunt" | Écrase le fichier seulement s'il vient de Terragrunt, sinon erreur | Protège un fichier écrit à la main |
Et pour un backend S3 ou compatible S3 ?
Section intitulée « Et pour un backend S3 ou compatible S3 ? »Pour un stockage objet, seul le contenu de backend et config change ; la
logique (une clé par unit, un generate) reste la même. Le bloc suivant est une
forme à adapter, non rejouée pour cette leçon : le rejeu n'a pas disposé de
service S3 (l'init a échoué faute d'identifiants). Chaque option doit être
confrontée à la documentation de votre version du backend S3 d'OpenTofu ou de
Terraform.
remote_state { backend = "s3" config = { bucket = "mon-bucket-de-state" key = "${path_relative_to_include()}/tofu.tfstate" region = "eu-west-3" encrypt = true use_path_style = true use_lockfile = true } generate = { path = "backend.tf" if_exists = "overwrite_terragrunt" }}L'option use_lockfile = true active le verrouillage du state par un
fichier .tflock dans le bucket : sur S3, use_lockfile vaut false par
défaut, donc sans elle deux apply simultanés peuvent écraser le state (voir
la leçon sur les backends).
L'ancien verrou par dynamodb_table est déprécié.
Deux points d'attention viennent du rejeu. L'option force_path_style, que
l'on trouve dans d'anciens tutoriels, est dépréciée : OpenTofu 1.13.1 répond
Use use_path_style. Quant à l'adresse d'un service compatible S3 (MinIO, par
exemple), l'ancienne option endpoint est remplacée par endpoints.s3 dans la
documentation du backend S3 ; cette forme n'a pas été rejouée ici, donc vérifiez
la syntaxe exacte dans la documentation de votre version avant de la copier.
Et le provider dans tout cela ?
Section intitulée « Et le provider dans tout cela ? »Le mécanisme generate ne sert pas qu'au backend. Un bloc generate
placé à la racine de root.hcl, à côté de remote_state, écrit n'importe
quel fichier technique dans la copie de travail du unit avant que le moteur
ne s'exécute. Voici un provider.tf déclaré une seule fois pour tous les units,
à ajouter à la suite de remote_state dans live/root.hcl :
generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = <<-EOF provider "local" {} EOF}Vérification : après terragrunt apply -auto-approve dans live/dev/app,
provider.tf et backend.tf se trouvent tous deux dans la copie de travail
sous .terragrunt-cache, chacun avec l'en-tête # Generated by Terragrunt, et
rien n'apparaît dans votre source.
L'idée à retenir : remote_state centralise la stratégie de state,
generate écrit automatiquement une configuration répétée. Il faut l'utiliser
avec mesure : si toute la complexité finit dans un seul root.hcl, vous
remplacez de la duplication par un gros fichier difficile à relire.
Erreurs fréquentes
Section intitulée « Erreurs fréquentes »| Symptôme | Cause probable | Solution |
|---|---|---|
| Tous les units écrivent dans le même state | La clé est statique | Utiliser path_relative_to_include() |
Avertissement sur force_path_style | Option dépréciée | Utiliser use_path_style |
backend.tf n'est pas régénéré | Mauvaise config generate | Vérifier path et if_exists |
Erreur de provider déclaré deux fois (le moteur signale une « Duplicate provider configuration », libellé non rejoué ici) après generate "provider" | Le module déclare déjà un bloc provider du même nom, et le provider.tf généré le double | Garder un seul endroit : retirer le bloc du module, ou ne pas générer ce provider |
init échoue sur le backend S3 | Identifiants absents ou option incompatible | Fournir les identifiants et relire les options dans la documentation du backend |
À retenir
Section intitulée « À retenir »remote_statecentralise le backend dansroot.hcl, et chaque unit en hérite parinclude.path_relative_to_include()donne une clé de state distincte par unit.generateécritbackend.tfdans la copie de travail, rien à versionner.- Sur S3, ajoutez
use_lockfile = true(le verrou n'est pas actif par défaut) et utilisezuse_path_style, pasforce_path_style; l'adresse du service passe parendpoints.s3à vérifier dans la documentation. - La centralisation doit rester lisible, pas devenir un nouveau monolithe.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Six questions tirées sur huit : le rôle de remote_state, path_relative_to_include(), generate et les options S3 dépréciées.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Score par domaine
Un domaine regroupe plusieurs guides et reçoit plusieurs questions : son score est plus fiable qu'un score par thème, qui porte souvent sur une seule question.
Bilan
Points forts
Aucun sujet réussi à 80 % sur au moins deux questions pour l’instant.
Points faibles
Aucun sujet sous le seuil de réussite.
À faire ensuite
Des indices pour retenter votre chance ?
Continuer le cours : Terragrunt : dépendances et mock_outputs
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications