Terragrunt для DRY-модулей Terraform
IaC · Terraform
Проблема
На три окружения (dev, staging, prod) Terraform плодит три директории, в каждой — copy-paste main.tf, backend.tf, providers.tf. Изменение провайдера требует трёх почти идентичных PR. Бэкенд-конфиг разъезжается, terraform init случайно пишет state в чужое окружение. Всё пахнет, но пока работает.
Решение
Terragrunt — тонкая обёртка над Terraform, которая делает две вещи:
- DRY-конфигурация. Бэкенд, провайдеры, общие переменные описываются один раз в корневом
terragrunt.hcl. Дочерниеterragrunt.hclих наследуют черезinclude. - Автоматическое определение бэкенда. Путь в S3/Azure Blob генерируется из пути в репозитории — перепутать окружения физически нельзя.
Пример
Структура:
infra/
├── terragrunt.hcl # корневой: remote state, провайдеры
├── modules/
│ └── vpc/
│ ├── main.tf
│ └── variables.tf
└── environments/
├── dev/
│ └── vpc/terragrunt.hcl
├── staging/
│ └── vpc/terragrunt.hcl
└── prod/
└── vpc/terragrunt.hcl
terragrunt.hcl в корне — определяется один раз:
remote_state {
backend = "s3"
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
config = {
bucket = "acme-tfstate"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "eu-central-1"
encrypt = true
dynamodb_table = "acme-tfstate-lock"
}
}
generate "providers" {
path = "providers.tf"
if_exists = "overwrite_terragrunt"
contents = file("${get_terragrunt_dir()}/../../_shared/providers.tf")
}
environments/prod/vpc/terragrunt.hcl — весь окружение-специфичный код:
include "root" {
path = find_in_parent_folders()
}
terraform {
source = "../../../modules/vpc"
}
inputs = {
cidr_block = "10.10.0.0/16"
env = "prod"
}
Запуск — как обычный Terraform, только через terragrunt:
cd environments/prod/vpc
terragrunt plan
terragrunt apply
# Прогнать все окружения разом
cd environments
terragrunt run-all plan
Когда применять
- Окружений больше одного, конфиги уже дрейфуют.
- Несколько команд делят одно IaC-репо.
- Хочется запретить «прод случайно писал state в dev-бакет» на уровне инструмента, а не ревью.
Источник
- gruntwork-io/terragrunt
- bregman-arie/devops-resources — раздел Terraform
Как применить у себя
- Выделить общий код из существующих окружений в
modules/и_shared/. - Создать корневой
terragrunt.hclсremote_stateиgenerate. - Переписать каждое окружение на мини-
terragrunt.hclсinclude+inputs. - Удалить руками дублирующиеся
backend.tf/providers.tfиз окружений. - Прогон
terragrunt run-all planбез изменений ресурсов = миграция прошла чисто → статус Изучено.