Что такое Terragrunt?
Terragrunt — это тонкий wrapper для Terraform, который предоставляет дополнительные инструменты для поддержания DRY (Don't Repeat Yourself) принципа, управления remote state и упрощения работы с Terraform в больших проектах. Terragrunt помогает организовать код Terraform более эффективно и избежать дублирования конфигураций.
Основные возможности Terragrunt
- DRY principle — избежание дублирования кода через наследование
- Remote state management — автоматическая настройка backend
- Locking — автоматическая настройка state locking
- Multiple environments — удобное управление разными окружениями
- Dependencies — управление зависимостями между модулями
- Hooks — выполнение команд до и после Terraform операций
Установка Terragrunt
Установить Terragrunt можно несколькими способами:
1# macOS с Homebrew
2brew install terragrunt
3
4# Linux - скачивание бинарного файла
5wget https://github.com/gruntwork-io/terragrunt/releases/download/v0.54.8/terragrunt_linux_amd64
6chmod +x terragrunt_linux_amd64
7sudo mv terragrunt_linux_amd64 /usr/local/bin/terragrunt
8
9# Проверка установки
10terragrunt --version
11
12# Также потребуется Terraform
13terraform --version
Структура проекта с Terragrunt
1infrastructure/
2├── terragrunt.hcl # Корневая конфигурация
3├── modules/ # Terraform модули
4│ ├── vpc/
5│ │ ├── main.tf
6│ │ ├── variables.tf
7│ │ └── outputs.tf
8│ └── ec2/
9│ ├── main.tf
10│ ├── variables.tf
11│ └── outputs.tf
12└── environments/
13 ├── dev/
14 │ ├── terragrunt.hcl
15 │ ├── vpc/
16 │ │ └── terragrunt.hcl
17 │ └── ec2/
18 │ └── terragrunt.hcl
19 ├── staging/
20 │ ├── terragrunt.hcl
21 │ ├── vpc/
22 │ │ └── terragrunt.hcl
23 │ └── ec2/
24 │ └── terragrunt.hcl
25 └── prod/
26 ├── terragrunt.hcl
27 ├── vpc/
28 │ └── terragrunt.hcl
29 └── ec2/
30 └── terragrunt.hcl
Корневая конфигурация Terragrunt
1# infrastructure/terragrunt.hcl
2
3# Настройка remote state для всех модулей
4remote_state {
5 backend = "s3"
6 config = {
7 bucket = "my-terraform-state-bucket"
8 key = "${path_relative_to_include()}/terraform.tfstate"
9 region = "us-west-2"
10 encrypt = true
11 dynamodb_table = "terraform-state-lock"
12 }
13 generate = {
14 path = "backend.tf"
15 if_exists = "overwrite_terragrunt"
16 }
17}
18
19# Общий provider для всех модулей
20generate "provider" {
21 path = "provider.tf"
22 if_exists = "overwrite_terragrunt"
23 contents = <<EOF
24terraform {
25 required_providers {
26 aws = {
27 source = "hashicorp/aws"
28 version = "~> 5.0"
29 }
30 }
31}
32
33provider "aws" {
34 region = var.aws_region
35
36 default_tags {
37 tags = {
38 Environment = var.environment
39 Project = var.project_name
40 ManagedBy = "Terragrunt"
41 }
42 }
43}
44EOF
45}
46
47# Общие переменные
48inputs = {
49 project_name = "my-project"
50}
Конфигурация окружения
1# environments/dev/terragrunt.hcl
2
3# Наследование корневой конфигурации
4include "root" {
5 path = find_in_parent_folders()
6}
7
8# Переменные для dev окружения
9inputs = {
10 environment = "dev"
11 aws_region = "us-west-2"
12
13 # Настройки для dev
14 instance_type = "t3.micro"
15 min_size = 1
16 max_size = 2
17 desired_capacity = 1
18}
Конфигурация модуля
1# environments/dev/vpc/terragrunt.hcl
2
3# Наследование конфигурации окружения
4include "root" {
5 path = find_in_parent_folders()
6}
7
8include "env" {
9 path = find_in_parent_folders("terragrunt.hcl")
10}
11
12# Указание на Terraform модуль
13terraform {
14 source = "../../../modules/vpc"
15}
16
17# Переменные специфичные для VPC
18inputs = {
19 vpc_cidr = "10.0.0.0/16"
20 availability_zones = ["us-west-2a", "us-west-2b"]
21 public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
22 private_subnets = ["10.0.10.0/24", "10.0.20.0/24"]
23 enable_nat_gateway = true
24 single_nat_gateway = true # для dev экономим деньги
25}
Модуль с зависимостями
1# environments/dev/ec2/terragrunt.hcl
2
3include "root" {
4 path = find_in_parent_folders()
5}
6
7include "env" {
8 path = find_in_parent_folders("terragrunt.hcl")
9}
10
11terraform {
12 source = "../../../modules/ec2"
13}
14
15# Зависимость от VPC модуля
16dependency "vpc" {
17 config_path = "../vpc"
18
19 mock_outputs = {
20 vpc_id = "vpc-fake-id"
21 private_subnet_ids = ["subnet-fake-1", "subnet-fake-2"]
22 }
23}
24
25inputs = {
26 vpc_id = dependency.vpc.outputs.vpc_id
27 subnet_ids = dependency.vpc.outputs.private_subnet_ids
28 instance_type = "t3.micro"
29 key_name = "dev-key"
30
31 user_data = <<-EOF
32 #!/bin/bash
33 yum update -y
34 yum install -y httpd
35 systemctl start httpd
36 systemctl enable httpd
37 EOF
38}
Основные команды Terragrunt
1# Инициализация (аналог terraform init)
2terragrunt init
3
4# Планирование (аналог terraform plan)
5terragrunt plan
6
7# Применение (аналог terraform apply)
8terragrunt apply
9
10# Применение для всех модулей в директории
11terragrunt run-all apply
12
13# Планирование для всех модулей
14terragrunt run-all plan
15
16# Уничтожение ресурсов
17terragrunt destroy
18
19# Уничтожение всех ресурсов в директории
20terragrunt run-all destroy
21
22# Показать зависимости
23terragrunt graph-dependencies
24
25# Валидация конфигурации
26terragrunt validate
Hooks пример
1# terragrunt.hcl с hooks
2
3terraform {
4 source = "git::https://github.com/my-org/terraform-modules.git//vpc?ref=v1.0.0"
5
6 before_hook "before_init" {
7 commands = ["init"]
8 execute = ["echo", "Initializing Terraform..."]
9 }
10
11 after_hook "after_apply" {
12 commands = ["apply"]
13 execute = ["echo", "Terraform apply completed successfully!"]
14 run_on_error = false
15 }
16
17 after_hook "notify_slack" {
18 commands = ["apply"]
19 execute = [
20 "curl", "-X", "POST",
21 "-H", "Content-type: application/json",
22 "--data", "{\"text\":\"Terraform deployment completed for ${get_env(\"ENVIRONMENT\", \"unknown\")} environment\"}",
23 get_env("SLACK_WEBHOOK_URL", "")
24 ]
25 run_on_error = false
26 }
27}
Когда использовать Terragrunt
- Большие проекты с множественными окружениями
- Необходимость избежать дублирования Terraform кода
- Сложная структура зависимостей между модулями
- Стандартизация настроек backend и provider
- Автоматизация управления remote state
- Необходимость в hooks для дополнительных действий
Преимущества Terragrunt
- Соблюдение DRY принципа в Terraform коде
- Автоматическая настройка remote state
- Упрощенное управление множественными окружениями
- Удобное управление зависимостями
- Возможность выполнения команд для всех модулей сразу
- Поддержка hooks для автоматизации
Ограничения Terragrunt
- Дополнительный слой абстракции над Terraform
- Необходимость изучения специфичного HCL синтаксиса
- Может усложнить отладку проблем
- Зависимость от внешнего инструмента
- Менее популярен в некоторых командах
Рекомендации по использованию
Для эффективного использования Terragrunt рекомендуется:
- Начать с простой структуры и постепенно усложнять
- Создать четкую структуру директорий для окружений
- Использовать семантическое версионирование для модулей
- Документировать зависимости и структуру проекта
- Настроить CI/CD пайплайны с учетом Terragrunt команд
- Регулярно обновлять Terragrunt до новых версий
FAQ
Подходит ли Terragrunt для продакшена?
Да, Terragrunt активно используется в production средах крупных компаний для управления сложными Terraform проектами.
Можно ли использовать Terragrunt с существующим Terraform кодом?
Да, можно постепенно мигрировать существующий Terraform код на Terragrunt, начиная с настройки remote state и постепенно добавляя другие возможности.
Влияет ли Terragrunt на производительность?
Terragrunt добавляет минимальные накладные расходы, так как в основном генерирует Terraform файлы и передает управление самому Terraform.