Aller au contenu
English
Compte : non connecté, synchronisation possible Mon apprentissage
Selectionner le thème
English

Centraliser backend et provider avec Terragrunt

Par mis à jour le

Améliorer cette page

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.

  • Lire le rôle de remote_state dans root.hcl
  • Donner à chaque unit sa clé de state avec path_relative_to_include()
  • Savoir quand utiliser generate pour factoriser une configuration répétée
  • Transposer le motif vers un backend S3 sans copier une forme dépréciée

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.

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 :

Fenêtre de terminal
terragrunt apply -auto-approve

Vé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/

Chaque élément de remote_state répond à une question. Le tableau les résume pour le backend local de cette leçon.

ÉlémentRôlePourquoi c'est utile
backend = "local"Choisit le type de backendAucun service nécessaire pour apprendre
config.pathChemin du fichier de stateConstruit avec path_relative_to_include(), il est distinct par unit
generate.pathNom 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 erreurProtège un fichier écrit à la main

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.

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.

SymptômeCause probableSolution
Tous les units écrivent dans le même stateLa clé est statiqueUtiliser path_relative_to_include()
Avertissement sur force_path_styleOption dépréciéeUtiliser use_path_style
backend.tf n'est pas régénéréMauvaise config generateVé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 doubleGarder un seul endroit : retirer le bloc du module, ou ne pas générer ce provider
init échoue sur le backend S3Identifiants absents ou option incompatibleFournir les identifiants et relire les options dans la documentation du backend
  • remote_state centralise le backend dans root.hcl, et chaque unit en hérite par include.
  • path_relative_to_include() donne une clé de state distincte par unit.
  • generate écrit backend.tf dans la copie de travail, rien à versionner.
  • Sur S3, ajoutez use_lockfile = true (le verrou n'est pas actif par défaut) et utilisez use_path_style, pas force_path_style ; l'adresse du service passe par endpoints.s3 à vérifier dans la documentation.
  • La centralisation doit rester lisible, pas devenir un nouveau monolithe.

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

6 questions
6 min.
70% requis

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

Ce projet vous est utile ?

Les guides, formations, quiz et labs restent gratuits. Si vous les utilisez régulièrement, vous pouvez contribuer à leur maintenance et à leur développement.

Devenir membre de soutien (nouvel onglet) Soutenir une fois (nouvel onglet) En savoir plus

Suivez aussi le projet sur LinkedIn