Conceptos Fundamentales del Motor de Plantillas en Terragrunt
Terragrunt, como herramienta de infraestructura como código (IaC) basada en Terraform, incluye un motor de plantillas que permite crear configuraciones de infraestructura dinámicas y reutilizables. Esta guía técnica describe cómo emplear las características de templating de Terragrunt para optimizar el despliegue de infraestructura en entornos múltiples.
Características Principales
- Reutilización de Configuraciones: Mediante el bloque
includepara heredar y extender configuraciones base. - Generación Automática: Uso del bloque
generatepara crear archivos de Terraform de forma dinámica. - Administración de Dependencias: El bloque
dependencypermite establecer relaciones entre módulos y resolver el orden de ejecución. - Segregación por Entornos: Combinación de
localsy variables de entrada para adaptar configuraciones a distintos ambientes.
Configuración Inicial y Estructura Básica
Para empezar, instala Terragrunt y crea una estructura de directorios base. Un archivo de configuración típico (terragrunt.hcl) se compone de varios bloques esenciales.
# Configuración del estado remoto en un bucket de almacenamiento
remote_state {
backend = "gcs"
config = {
bucket = "estado-infraestructura-empresa"
prefix = "${path_relative_to_include()}/terraform.tfstate"
region = "us-central1"
}
}
# Herencia de configuración desde un archivo raíz
include "global" {
path = find_in_parent_folders("global.hcl")
}
# Variables locales para valores específicos del entorno
locals {
ambiente = "staging"
rango_red = "172.16.0.0/20"
}
# Entradas que se pasan a los módulos de Terraform
inputs = {
ambiente = local.ambiente
rango_red = local.rango_red
}
Técnicas de Generación Dinámica de Archivos
Uso del Bloque generate para Creación Automatizada
El bloque generate facilita la creación de archivos de configuración de Terraform, como proveedores o backends, garantizando consistencia en todos los módulos.
generate "proveedor_cloud" {
path = "proveedor_cloud.tf"
if_exists = "overwrite"
contents = <<eof ambiente="${local.ambiente}" eof="" equipo="${local.equipo}" etiquetas="{" etiquetas_predeterminadas="" project="${local.proyecto}" proveedor="" region="${local.region}"></eof>
Este snippet genera automáticamente un archivo proveedor_cloud.tf con configuraciones uniformes para Google Cloud.
Herancia de Configuraciones con include
El bloque include permite compartir configuraciones comunes y sobrescribirlas según las necesidades del entorno.
# global.hcl - Configuración base compartida
remote_state {
backend = "s3"
config = {
bucket = "estado-central-terraform"
encrypt = true
dynamodb_table = "bloqueos-despliegue"
}
}
# staging/terragrunt.hcl - Herencia y personalización
include "global" {
path = find_in_parent_folders("global.hcl")
}
locals {
ambiente = "staging"
}
remote_state {
config = {
key = "staging/${path_relative_to_include()}/terraform.tfstate"
region = "us-west-2"
}
}
Gestión de Dependencias y Secuencia de Despliegue
Definición de Relaciones entre Módulos
Terragrunt resuelve automáticamente las dependencias, asegurando que los módulos se desplieguen en el orden correcto.
dependency "red_virtual" {
config_path = "../red_virtual"
# Valores simulados para entornos no desplegados
mock_outputs = {
id_red = "red-xyz789"
cidr_subredes = ["10.0.1.0/24", "10.0.2.0/24"]
}
}
inputs = {
id_red = dependency.red_virtual.outputs.id_red
cidr_subredes = dependency.red_virtual.outputs.cidr_subredes
}
Ejecución Paralela con Dependencias Explícitas
Utiliza el bloque dependencies para establecer el orden de despliegue de módulos interconectados.
dependencies {
paths = ["../red_virtual", "../reglas_firewall"]
}
Al ejecutar terragrunt run-all apply, Terragrunt desplegará primero las dependencias antes de aplicar el módulo actual.
Administración de Configuraciones Multi-Ambiente
La estructura de directorios organizada por entornos simplifica la gestión de configuraciones para desarrollo, preproducción y producción.
Estructura de Directorios Recomendada
infraestructura/
├── global.hcl # Configuración global
├── desarrollo/
│ ├── red_virtual/terragrunt.hcl
│ └── servicio_web/terragrunt.hcl
├── preproduccion/
│ ├── red_virtual/terragrunt.hcl
│ └── servicio_web/terragrunt.hcl
└── produccion/
├── red_virtual/terragrunt.hcl
└── servicio_web/terragrunt.hcl
Configuración Específica por Entorno
# desarrollo/servicio_web/terragrunt.hcl
include "global" {
path = find_in_parent_folders("global.hcl")
}
locals {
ambiente = "desarrollo"
replicas = 1
tamano_instancia = "e2-standard-2"
}
inputs = merge(
include.global.inputs,
{
ambiente = local.ambiente
replicas = local.replicas
tamano_instancia = local.tamano_instancia
}
)
Prácticas Avanzadas y Optimización
Uso de Locals para Lógica Condicional
locals {
# Obtención de secretos desde variables de entorno
credencial_acceso = get_env("GOOGLE_CREDENTIALS")
# Lógica basada en el entorno
tamano_instancia = local.ambiente == "produccion" ? "n2-highmem-4" : "e2-medium"
# Generación dinámica de etiquetas
etiquetas_comunes = merge(
{
Ambiente = local.ambiente
MantenidoPor = "terragrunt"
},
local.etiquetas_personalizadas
)
}
Funciones Integradas para Manipulación de Configuraciones
Terragrunt ofrece funciones para trabajar con archivos, rutas y comandos externos.
locals {
# Lectura de un archivo YAML
configuracion = yamldecode(file("${get_terragrunt_dir()}/settings.yaml"))
# Cálculo de rutas relativas
ruta_relativa = path_relative_to_include()
# Ejecución de comandos para obtener metadatos
revision_actual = run_cmd("git", "log", "--oneline", "-1")
}
Mecanismos de Reintentos y Manejo de Errores
errors {
retry "errores_temporales" {
retryable_errors = [".*timeout.*", ".*transient.*"]
max_attempts = 5
sleep_interval_sec = 20
}
ignore "avisos_no_criticos" {
ignorable_errors = [".*deprecation warning.*"]
message = "Ignorando avisos de deprecación no bloqueantes"
}
}