Introducción

En un mundo ideal, toda la infraestructura de una organización nació desde Terraform. En la realidad, la mayoría de los equipos encuentran infraestructura existente creada manualmente, mediante scripts, o con otras herramientas. Adoptar Terraform en estos contextos requiere importar esos recursos existentes al estado de Terraform sin destruirlos ni recrearlos.

En esta lección aprenderás todos los métodos disponibles para importar recursos: desde el comando clásico terraform import hasta los modernos bloques declarativos introducidos en Terraform 1.5 y 1.6.


  1. ¿Por Qué Importar Recursos Existentes?

Existen varios escenarios donde necesitas importar recursos:

  • Migración a Terraform: Tu organización adoptó Terraform y necesitas gestionar recursos creados manualmente antes de la migración.
  • Recursos creados fuera de Terraform: Un recurso fue creado con la consola web de AWS, CLI, o scripts de automatización.
  • Recuperación de estado perdido: El archivo terraform.tfstate se perdió o corrompió y necesitas reconstruirlo.
  • Colaboración entre equipos: Un equipo creó recursos que ahora otro equipo necesita gestionar con Terraform.
  • Módulos nuevos sobre infraestructura existente: Adoptas un módulo que recrea recursos que ya existen.

¿Qué NO hace la importación?

Es fundamental entender las limitaciones desde el principio:

  • La importación no escribe el código HCL automáticamente (excepto con generated_config en Terraform 1.6+).
  • La importación no migra la configuración de un recurso a otro.
  • La importación no crea el recurso en el proveedor; solo lo registra en el estado de Terraform.

  1. Flujo de Trabajo de Importación Clásica

El proceso de importación con terraform import sigue siempre estos pasos:

1. Identificar el recurso existente
        ↓
2. Escribir el bloque resource en HCL (vacío o básico)
        ↓
3. Ejecutar terraform import
        ↓
4. Inspeccionar el estado importado
        ↓
5. Ajustar el HCL para que coincida con el estado
        ↓
6. Ejecutar terraform plan y verificar que no hay cambios

Veamos cada paso en detalle.


  1. terraform import: Sintaxis y Uso

Sintaxis básica

terraform import [opciones] RESOURCE_ADDRESS RESOURCE_ID

Donde:

  • RESOURCE_ADDRESS: La dirección del recurso en tu configuración HCL. Por ejemplo: aws_instance.web o module.networking.aws_vpc.main
  • RESOURCE_ID: El identificador del recurso en el proveedor. Varía según el tipo de recurso.

Ejemplos de IDs por tipo de recurso AWS

Tipo de recurso Ejemplo de ID de importación
aws_instance i-1234567890abcdef0
aws_s3_bucket my-bucket-name
aws_vpc vpc-12345678
aws_subnet subnet-12345678
aws_security_group sg-12345678
aws_iam_role my-role-name
aws_iam_policy arn:aws:iam::123456789012:policy/my-policy
aws_rds_instance my-db-identifier
aws_route53_zone Z1234567890ABC
aws_cloudfront_distribution EDFDVBD6EXAMPLE
aws_eks_cluster my-cluster-name

Importante: Siempre consulta la documentación del recurso específico en el registro de Terraform (registry.terraform.io) para conocer el formato correcto del ID de importación. Cada recurso puede tener un formato diferente.


  1. Proceso Completo de Importación: Ejemplo con EC2

Paso 1: Identificar el recurso existente

# En la consola de AWS o mediante la CLI
aws ec2 describe-instances --query 'Reservations[].Instances[].{ID:InstanceId,Name:Tags[?Key==`Name`]|[0].Value,State:State.Name}' --output table

# Salida ejemplo:
# -----------------------------------------------
# |            DescribeInstances                |
# +-----------+-----------+---------------------+
# |    ID     |   Name    |        State        |
# +-----------+-----------+---------------------+
# | i-0abc123 | web-prod  | running             |
# +-----------+-----------+---------------------+

Paso 2: Escribir el bloque resource en HCL

Crea un bloque resource vacío o mínimo. No necesitas todos los atributos todavía:

# main.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

# Bloque mínimo para la importación
# El nombre del recurso debe coincidir con lo que usarás en terraform import
resource "aws_instance" "web_prod" {
  # Puedes dejar esto vacío o con valores mínimos
  # Terraform los rellenará desde el estado importado
  ami           = "ami-placeholder"  # Será sobreescrito por el import
  instance_type = "t3.micro"         # Será sobreescrito por el import
}

Paso 3: Ejecutar terraform import

# Sintaxis: terraform import RESOURCE_ADDRESS RESOURCE_ID
terraform import aws_instance.web_prod i-0abc123def456

# Salida esperada:
# aws_instance.web_prod: Importing from ID "i-0abc123def456"...
# aws_instance.web_prod: Import prepared!
#   Prepared aws_instance for import
# aws_instance.web_prod: Refreshing state... [id=i-0abc123def456]
#
# Import successful!
#
# The resources that were imported are shown above. These resources are now in
# your Terraform state and will henceforth be managed by Terraform.

Paso 4: Inspeccionar el estado importado

# Ver el estado completo del recurso importado
terraform show

# O enfocarse en el recurso específico
terraform state show aws_instance.web_prod

# Salida (ejemplo abreviado):
# resource "aws_instance" "web_prod" {
#     ami                          = "ami-0c55b159cbfafe1f0"
#     availability_zone            = "us-east-1a"
#     id                           = "i-0abc123def456"
#     instance_state               = "running"
#     instance_type                = "t3.micro"
#     key_name                     = "my-key-pair"
#     private_ip                   = "10.0.1.50"
#     public_ip                    = "54.123.45.67"
#     subnet_id                    = "subnet-12345"
#     vpc_security_group_ids       = ["sg-67890"]
#     tags = {
#         "Environment" = "production"
#         "Name"        = "web-prod"
#     }
#     # ... muchos más atributos
# }

Paso 5: Ajustar el HCL para que coincida con el estado

Actualiza tu archivo main.tf con los valores reales del recurso:

# main.tf (actualizado tras inspeccionar el estado)

resource "aws_instance" "web_prod" {
  ami           = "ami-0c55b159cbfafe1f0"
  # AMI real que está usando la instancia
  instance_type = "t3.micro"
  key_name      = "my-key-pair"
  subnet_id     = "subnet-12345"

  vpc_security_group_ids = ["sg-67890"]
  # El security group al que pertenece la instancia

  tags = {
    Name        = "web-prod"
    Environment = "production"
    # Copiamos exactamente las etiquetas que tiene en AWS
  }

  # Importante: NO incluyas atributos que Terraform gestiona automáticamente
  # como: id, private_ip, public_ip, availability_zone (salvo que quieras fijarlo)
  # Terraform los calculará automáticamente
}

Paso 6: Verificar con terraform plan

terraform plan

# El objetivo es ver:
# No changes. Your infrastructure matches the configuration.
#
# Si ves cambios, necesitas ajustar más tu HCL para que coincida exactamente
# con la configuración actual del recurso

  1. Ejemplo Completo: Importar un Bucket S3

Situación

Tienes un bucket S3 llamado company-assets-2024 creado manualmente, con versionado habilitado y acceso público bloqueado. Necesitas importarlo a Terraform.

# Paso 1: Verificar que el bucket existe
aws s3 ls | grep company-assets-2024
# 2024-01-10 10:30:45 company-assets-2024
# Paso 2: Escribir el bloque resource inicial
# s3.tf

resource "aws_s3_bucket" "assets" {
  bucket = "company-assets-2024"
  # El nombre del bucket es el mínimo necesario para el bloque resource
}

resource "aws_s3_bucket_versioning" "assets" {
  bucket = aws_s3_bucket.assets.id

  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_public_access_block" "assets" {
  bucket = aws_s3_bucket.assets.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
# Paso 3: Importar el bucket y sus recursos asociados

# Importar el bucket principal
terraform import aws_s3_bucket.assets company-assets-2024
# Salida: Import successful!

# Importar la configuración de versionado
# El formato del ID para versionado de S3 es: nombre-del-bucket
terraform import aws_s3_bucket_versioning.assets company-assets-2024
# Salida: Import successful!

# Importar el bloque de acceso público
terraform import aws_s3_bucket_public_access_block.assets company-assets-2024
# Salida: Import successful!
# Paso 4: Inspeccionar el estado
terraform state show aws_s3_bucket.assets

# Paso 5: Ajustar el HCL si hay diferencias

# Paso 6: Verificar que no hay cambios pendientes
terraform plan
# Resultado esperado: No changes. Your infrastructure matches the configuration.

  1. Limitaciones del terraform import Clásico

Limitación Descripción
No genera código HCL Debes escribir el código manualmente, lo cual es tedioso para recursos con muchos atributos
Un recurso a la vez No hay forma de importar múltiples recursos con un solo comando
Sin soporte en módulos complejos Importar recursos dentro de módulos anidados puede ser complicado
Sin validación previa No hay forma de previsualizar qué se importará antes de ejecutarlo
No es declarativo La importación es imperativa (comando puntual), no forma parte del código versionado
Riesgo de errores humanos Si el ID es incorrecto, el estado puede quedar inconsistente

  1. El Nuevo Bloque import (Terraform 1.5+)

A partir de Terraform 1.5, se introdujo una forma declarativa de importar recursos mediante bloques import en el código HCL. Esta es la forma recomendada actualmente.

Sintaxis del bloque import

import {
  to = RESOURCE_ADDRESS
  # La dirección del recurso en tu configuración HCL

  id = "RESOURCE_ID"
  # El ID del recurso en el proveedor cloud
}

Ventajas sobre terraform import clásico

  • Declarativo: Forma parte del código versionado en Git
  • Previsualizable: terraform plan muestra lo que se importará antes de hacerlo
  • Reproducible: El bloque puede compartirse con el equipo y ejecutarse en cualquier entorno
  • Sin estado intermedio inconsistente: La importación se realiza de forma atómica con el plan/apply

Ejemplo con bloque import

# imports.tf

# Importar el bucket S3 existente
import {
  to = aws_s3_bucket.assets
  id = "company-assets-2024"
}

# Importar la configuración de versionado
import {
  to = aws_s3_bucket_versioning.assets
  id = "company-assets-2024"
}

# Importar el bloque de acceso público
import {
  to = aws_s3_bucket_public_access_block.assets
  id = "company-assets-2024"
}

# Importar una instancia EC2
import {
  to = aws_instance.web_prod
  id = "i-0abc123def456"
}

# Importar un recurso dentro de un módulo
import {
  to = module.networking.aws_vpc.main
  id = "vpc-12345678"
}
# s3.tf (el recurso que coincide con el import)

resource "aws_s3_bucket" "assets" {
  bucket = "company-assets-2024"

  tags = {
    Name        = "Company Assets"
    Environment = "production"
    ManagedBy   = "Terraform"
  }
}

resource "aws_s3_bucket_versioning" "assets" {
  bucket = aws_s3_bucket.assets.id

  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_public_access_block" "assets" {
  bucket = aws_s3_bucket.assets.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
# Proceso con bloques import declarativos

# 1. Ver qué se importará (sin hacer cambios)
terraform plan
# Salida:
# Plan: 3 to import, 0 to add, 0 to change, 0 to destroy.
# Puedes ver exactamente qué recursos se importarán

# 2. Aplicar la importación
terraform apply
# Los bloques import se ejecutan automáticamente durante el apply

# 3. Después de la importación, los bloques import pueden (y deben) eliminarse
# Los recursos ya están en el estado, no necesitas importarlos de nuevo

  1. generated_config (Terraform 1.6+): Generación Automática de Configuración

Una de las limitaciones históricas de la importación era tener que escribir manualmente el HCL. Terraform 1.6 introdujo generated_config_out que genera automáticamente el código HCL a partir de los recursos importados.

# Primero defines el bloque import (solo el bloque, sin el resource)
# imports.tf
# import {
#   to = aws_instance.web_prod
#   id = "i-0abc123def456"
# }

# Luego ejecutas plan con la opción de generación automática
terraform plan -generate-config-out=generated.tf
# generated.tf (generado automáticamente por Terraform)
# ESTE ARCHIVO ES GENERADO - REVÍSALO Y ADÁPTALO ANTES DE USARLO

resource "aws_instance" "web_prod" {
  ami                         = "ami-0c55b159cbfafe1f0"
  associate_public_ip_address = true
  availability_zone           = "us-east-1a"
  cpu_core_count              = 1
  cpu_threads_per_core        = 1
  disable_api_stop            = false
  disable_api_termination     = false
  ebs_optimized               = false
  get_password_data           = false
  hibernation                 = false
  instance_initiated_shutdown_behavior = "stop"
  instance_type               = "t3.micro"
  ipv6_address_count          = 0
  key_name                    = "my-key-pair"
  monitoring                  = false
  placement_partition_number  = null
  private_ip                  = "10.0.1.50"
  secondary_private_ips       = []
  security_groups             = []
  source_dest_check           = true
  subnet_id                   = "subnet-12345"
  tenancy                     = "default"
  user_data_replace_on_change = false

  vpc_security_group_ids = ["sg-67890"]

  capacity_reservation_specification {
    capacity_reservation_preference = "open"
  }

  credit_specification {
    cpu_credits = "unlimited"
  }

  enclave_options {
    enabled = false
  }

  maintenance_options {
    auto_recovery = "default"
  }

  metadata_options {
    http_endpoint               = "enabled"
    http_put_response_hop_limit = 1
    http_tokens                 = "optional"
    instance_metadata_tags      = "disabled"
  }

  private_dns_name_options {
    enable_resource_name_dns_a_record    = false
    enable_resource_name_dns_aaaa_record = false
    hostname_type                        = "ip-name"
  }

  root_block_device {
    delete_on_termination = true
    encrypted             = false
    iops                  = 100
    tags                  = {}
    throughput            = 0
    volume_size           = 8
    volume_type           = "gp2"
  }

  tags = {
    Environment = "production"
    Name        = "web-prod"
  }
  tags_all = {
    Environment = "production"
    Name        = "web-prod"
  }
}

Qué hacer con el código generado

# 1. Revisar el archivo generado
# El código puede incluir atributos innecesarios o con valores
# que cambian en cada plan (como ip privadas, etc.)

# 2. Limpiar atributos redundantes o problemáticos
# Eliminar atributos que Terraform puede calcular automáticamente
# como: private_ip (si no quieres fijarlo), availability_zone, etc.

# 3. Mover el contenido útil a tus archivos .tf principales
# Por ejemplo, copiar a main.tf o ec2.tf y eliminar generated.tf

# 4. Verificar que el plan no muestra cambios
terraform plan
# Objetivo: No changes. Your infrastructure matches the configuration.

# 5. Eliminar los bloques import del código (ya no son necesarios)
# Los recursos ya están en el estado

  1. Importación Masiva vs Importación Individual

Importación individual (método clásico)

# Importación uno a uno - lenta para muchos recursos
terraform import aws_s3_bucket.bucket1 my-bucket-1
terraform import aws_s3_bucket.bucket2 my-bucket-2
terraform import aws_s3_bucket.bucket3 my-bucket-3

Importación masiva (método declarativo recomendado)

# imports.tf - Todos los imports declarativos en un solo archivo

# Importar múltiples buckets S3
import {
  to = aws_s3_bucket.bucket1
  id = "my-bucket-1"
}

import {
  to = aws_s3_bucket.bucket2
  id = "my-bucket-2"
}

import {
  to = aws_s3_bucket.bucket3
  id = "my-bucket-3"
}

# Importar recursos de red
import {
  to = aws_vpc.main
  id = "vpc-12345678"
}

import {
  to = aws_subnet.public_1
  id = "subnet-aaaabbbb"
}

import {
  to = aws_subnet.public_2
  id = "subnet-ccccdddd"
}

import {
  to = aws_internet_gateway.main
  id = "igw-12345678"
}
# Un solo terraform apply importa todos los recursos
terraform apply
# Plan: 7 to import, 0 to add, 0 to change, 0 to destroy.

Importación con for_each (Terraform 1.7+)

# Para recursos con for_each, puedes importar todos de una vez
variable "bucket_names" {
  default = ["bucket-dev", "bucket-staging", "bucket-prod"]
}

resource "aws_s3_bucket" "envs" {
  for_each = toset(var.bucket_names)
  bucket   = each.key
}

# Importar cada elemento del for_each
import {
  for_each = toset(var.bucket_names)
  to       = aws_s3_bucket.envs[each.key]
  id       = each.key
}

  1. Tabla: Diferencias entre terraform import Clásico y Bloque import

Característica terraform import (clásico) Bloque import (1.5+)
Disponibilidad Todas las versiones Terraform >= 1.5
Tipo Imperativo (comando) Declarativo (código)
Versionable en Git No (solo el comando en scripts) Si (forma parte del .tf)
Previsualización No (ejecuta directamente) Si (aparece en terraform plan)
Generación de HCL No Si (con -generate-config-out)
Importación masiva Solo con scripts de shell Si (múltiples bloques import)
For_each support No Si (desde Terraform 1.7)
Equipo colaborativo Difícil (cada dev ejecuta el comando) Fácil (está en el código compartido)
Reversibilidad El estado se modifica permanentemente Se puede ver el plan antes de confirmar
Recomendado para Casos puntuales, Terraform < 1.5 Proyectos nuevos, migraciones grandes

  1. Ejercicio Práctico: Importar un Recurso de Archivo Local

Objetivo

Practicar el flujo completo de importación usando el provider local (sin necesidad de credenciales de nube). Simularemos que tenemos un archivo existente que queremos gestionar con Terraform.

Instrucciones

  1. Crea manualmente un archivo de texto
  2. Define el recurso en HCL
  3. Importa el recurso usando el bloque import declarativo
  4. Verifica que Terraform reconoce el archivo sin cambios

Solución Detallada

# Paso 1: Creamos el "recurso existente" manualmente
# (Simulamos infraestructura previa a Terraform)
mkdir -p /tmp/terraform-import-lab
echo "Configuración de producción - NO MODIFICAR" > /tmp/terraform-import-lab/config.txt
echo "database_host=db.example.com" >> /tmp/terraform-import-lab/config.txt
echo "max_connections=100" >> /tmp/terraform-import-lab/config.txt

# Verificamos que existe
cat /tmp/terraform-import-lab/config.txt
# /tmp/import-lab/terraform.tf

terraform {
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.0"
    }
  }
}
# /tmp/import-lab/main.tf

# El recurso que queremos importar
resource "local_file" "config" {
  filename = "/tmp/terraform-import-lab/config.txt"
  content  = "Configuración de producción - NO MODIFICAR\ndatabase_host=db.example.com\nmax_connections=100\n"
  # Contenido que coincide exactamente con el archivo existente
}
# /tmp/import-lab/imports.tf

# Bloque declarativo de importación (Terraform 1.5+)
import {
  to = local_file.config
  id = "/tmp/terraform-import-lab/config.txt"
  # Para el provider local, el ID es la ruta absoluta del archivo
}
# Paso 2: Inicializar el proyecto
cd /tmp/import-lab
terraform init

# Paso 3: Ver el plan de importación
terraform plan
# Salida:
# Terraform will perform the following actions:
#
#   # local_file.config will be imported
#     resource "local_file" "config" {
#         content              = "Configuración de producción..."
#         filename             = "/tmp/terraform-import-lab/config.txt"
#         id                   = "..."
#     }
#
# Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.

# Paso 4: Aplicar la importación
terraform apply
# Terraform importa el archivo al estado

# Paso 5: Verificar que el archivo está bajo gestión de Terraform
terraform state list
# local_file.config

terraform state show local_file.config
# Muestra todos los atributos del archivo importado

# Paso 6: Verificar que no hay cambios pendientes
terraform plan
# Salida esperada: No changes. Your infrastructure matches the configuration.

# Paso 7: Eliminar el bloque import (ya no es necesario)
# Edita imports.tf y elimina el bloque import
# Los bloques import se ejecutan una sola vez y luego deben eliminarse

# Paso 8: Verificar que el plan sigue sin cambios
terraform plan
# Salida: No changes. Your infrastructure matches the configuration.

Variante: Usando terraform import clásico

# Si estás usando Terraform < 1.5, el proceso es:

# 1. Crear el recurso en HCL (sin bloque import)
# 2. Ejecutar terraform import
terraform import local_file.config /tmp/terraform-import-lab/config.txt

# 3. Verificar el estado
terraform state show local_file.config

# 4. Ajustar el HCL si es necesario
# 5. Verificar con terraform plan
terraform plan

  1. Errores Comunes al Importar

Error 1: ID de recurso incorrecto

terraform import aws_s3_bucket.assets mi-bucket-con-nombre-erroneo
# Error: error importing S3 Bucket:
# BucketNotFound: specified bucket does not exist

# Solución: Verificar el nombre exacto del bucket
aws s3 ls | grep "mi-bucket"
terraform import aws_s3_bucket.assets nombre-exacto-del-bucket

Error 2: El recurso HCL no existe cuando se ejecuta el import

# Si no existe el bloque resource "aws_s3_bucket" "assets" {} en el código
terraform import aws_s3_bucket.assets my-bucket
# Error: resource address "aws_s3_bucket.assets" does not exist in the configuration.

# Solución: Crear primero el bloque resource (puede estar vacío inicialmente)
# resource "aws_s3_bucket" "assets" {}
# Luego ejecutar el import

Error 3: El recurso ya está en el estado

terraform import aws_s3_bucket.assets my-bucket
# Error: resource "aws_s3_bucket" "assets" already exists in the state

# Solución: Primero eliminarlo del estado si quieres reimportarlo
terraform state rm aws_s3_bucket.assets
# Luego volver a importar
terraform import aws_s3_bucket.assets my-bucket

Error 4: El plan muestra cambios después de importar

terraform plan
# Salida:
# ~ resource "aws_s3_bucket" "assets" {
#     ~ tags = {
#       + "ManagedBy" = "Terraform"
#     }
# }
# Plan: 0 to add, 1 to change, 0 to destroy.

# Esto significa que tu HCL define algo diferente al recurso real
# Opciones:
# A) Actualizar el HCL para que coincida con el recurso existente (omitir la tag)
# B) Aplicar el cambio (Terraform añadirá la tag "ManagedBy")
# C) Ignorar el cambio con lifecycle { ignore_changes = [tags["ManagedBy"]] }

Error 5: Importar el bloque incorrecto de un módulo

# Si el recurso está dentro de un módulo, debes usar la dirección completa
terraform import aws_vpc.main vpc-12345678
# Error: resource address "aws_vpc.main" not found
# (porque está dentro de un módulo)

# Solución: Usar la dirección completa con el módulo
terraform import module.networking.aws_vpc.main vpc-12345678

Error 6: Confundir terraform state rm con destruir el recurso

# INCORRECTO: Esto solo elimina el recurso del ESTADO, no lo destruye en AWS
terraform state rm aws_instance.web
# El recurso sigue existiendo en AWS pero Terraform ya no lo gestiona

# Si quieres destruir el recurso real, usa:
terraform destroy -target=aws_instance.web

  1. Resumen del Módulo 6

En esta última lección del módulo hemos completado el estudio de terraform import y las técnicas avanzadas de Terraform. Recapitulemos lo aprendido en todo el módulo:

Lo aprendido en esta lección

  • La importación permite incorporar recursos existentes al estado de Terraform sin destruirlos ni recrearlos.
  • El flujo clásico implica: escribir HCL → importar → inspeccionar estado → ajustar HCL → verificar plan sin cambios.
  • El bloque import declarativo (Terraform 1.5+) es la forma moderna y recomendada: es versionable, previsualizable y reproducible.
  • generated_config_out (Terraform 1.6+) genera automáticamente el HCL desde los recursos importados, eliminando el trabajo manual.
  • Después de importar, siempre verifica que terraform plan no muestra cambios; si los muestra, debes ajustar tu HCL.

Resumen del Módulo 6 completo

Lección Concepto Cuándo usar
06-01 Workspaces Múltiples entornos con configuración similar desde un mismo código
06-02 Funciones Transformar, calcular y manipular datos en configuraciones HCL
06-03 Bloques dinámicos Generar bloques de configuración repetitivos desde variables
06-04 Terraform import Incorporar infraestructura existente al control de Terraform

Con estas herramientas avanzadas, estás preparado para gestionar infraestructuras complejas, reales y evolutivas con Terraform de forma profesional.

En el siguiente módulo estudiaremos las mejores prácticas de organización del código Terraform, incluyendo estructura de proyectos, naming conventions, y estrategias para equipos de trabajo.

© Copyright 2026. Todos los derechos reservados