Passer au contenu principal

Expertise (Terraform)

Terragrunt

Terragrunt est un wrapper Terraform open-source créé par Gruntwork. Il résout les problèmes de répétition (DRY) dans les projets multi-environnements et multi-régions, sans modifier le code HCL Terraform. C'est l'outil de référence dès qu'un projet dépasse 3 environnements.

Le problème que résout Terragrunt

Sans Terragrunt, une infrastructure avec 3 environnements (dev, staging, prod) dans 2 régions nécessite 6 copies du même bloc backend, 6 copies de la configuration provider, 6 ensembles de fichiers quasi-identiques. Toute modification doit être répercutée 6 fois.

Terragrunt centralise ces configurations répétées dans un fichier terragrunt.hcl racine et les hérite dans chaque environnement.

Structure d'un projet Terragrunt

infrastructure/
├── terragrunt.hcl              # config racine partagée
├── modules/
│   ├── vpc/
│   └── ec2/
└── live/
    ├── eu-west-1/
    │   ├── prod/
    │   │   ├── vpc/
    │   │   │   └── terragrunt.hcl
    │   │   └── ec2/
    │   │       └── terragrunt.hcl
    │   └── staging/
    │       └── vpc/
    │           └── terragrunt.hcl
    └── us-east-1/
        └── prod/
            └── vpc/
                └── terragrunt.hcl

terragrunt.hcl racine

# infrastructure/terragrunt.hcl
locals {
  region      = basename(dirname(path_relative_to_include()))
  environment = basename(dirname(path_relative_to_include()))
  account_id  = get_aws_account_id()
}

remote_state {
  backend = "s3"
  generate = {
    path      = "backend.tf"
    if_exists = "overwrite_terragrunt"
  }
  config = {
    bucket         = "tfstate-${local.account_id}-${local.region}"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = local.region
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <

terragrunt.hcl par module

# live/eu-west-1/prod/vpc/terragrunt.hcl
include "root" {
  path = find_in_parent_folders()
}

terraform {
  source = "../../../../modules/vpc"
}

inputs = {
  name        = "prod-vpc"
  cidr_block  = "10.0.0.0/16"
  environment = "prod"
}

Dépendances entre modules

# live/eu-west-1/prod/ec2/terragrunt.hcl
include "root" {
  path = find_in_parent_folders()
}

dependency "vpc" {
  config_path = "../vpc"

  mock_outputs = {
    vpc_id            = "vpc-00000000"
    public_subnet_ids = ["subnet-00000000"]
  }
}

terraform {
  source = "../../../../modules/ec2"
}

inputs = {
  vpc_id    = dependency.vpc.outputs.vpc_id
  subnet_id = dependency.vpc.outputs.public_subnet_ids[0]
}

Commandes Terragrunt

# Équivalents des commandes Terraform
terragrunt init
terragrunt plan
terragrunt apply

# Appliquer tous les modules d'un environnement en respectant les dépendances
terragrunt run-all apply --terragrunt-working-dir live/eu-west-1/prod/

# Plan de tout l'environnement
terragrunt run-all plan --terragrunt-working-dir live/eu-west-1/prod/

# Afficher le graphe de dépendances
terragrunt graph-dependencies