Terraform Import y Gestión de Estado
Terraform gestiona la infraestructura a través de su archivo de estado, que registra todos los recursos desplegados y su configuración actual. Dominar la gestión del estado es esencial para trabajar con infraestructura existente, migrar backends y mantener la consistencia entre el código y la realidad. Esta guía cubre las operaciones de estado más importantes que necesitarás en entornos de producción.
Requisitos Previos
- Terraform >= 1.0 instalado
- Acceso a una cuenta de proveedor cloud (AWS, GCP, Azure)
- Permisos suficientes para gestionar recursos
- Conocimientos básicos de HCL (HashiCorp Configuration Language)
Entender el Archivo de Estado
El estado de Terraform se almacena en terraform.tfstate (local) o en un backend remoto. Es un archivo JSON que mapea los recursos del código a los recursos reales en el proveedor.
# Ver el estado actual en formato legible
terraform show
# Listar todos los recursos en el estado
terraform state list
# Ver detalles de un recurso específico
terraform state show aws_instance.web
# Ver el archivo de estado en crudo (útil para depuración)
cat terraform.tfstate | python3 -m json.tool
El estado contiene información sensible como IPs, IDs de recursos y en algunos casos credenciales. Nunca lo commits a un repositorio público.
Importar Recursos Existentes
Cuando tienes infraestructura creada manualmente que quieres gestionar con Terraform, usa terraform import.
Importación básica
# Sintaxis: terraform import <tipo_recurso>.<nombre_local> <id_real_en_proveedor>
# Importar una instancia EC2 de AWS
terraform import aws_instance.web i-0abcd1234efgh5678
# Importar un grupo de seguridad
terraform import aws_security_group.main sg-0123456789abcdef0
# Importar un bucket S3
terraform import aws_s3_bucket.data my-existing-bucket-name
# Importar un registro de Route53
terraform import aws_route53_record.www Z1234567890ABC_example.com_A
Preparar el código antes de importar
Antes de importar, debes escribir el bloque de recurso correspondiente en tu código HCL:
# Definir el recurso antes de importar
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "servidor-web-produccion"
}
}
# Después de importar, ejecutar plan para ver diferencias
terraform plan
# Si hay diferencias menores, ajustar el código para que coincida
# Luego aplicar para sincronizar el estado
terraform apply
Import block (Terraform >= 1.5)
La versión 1.5 introdujo bloques de importación declarativos:
# importaciones.tf - Define las importaciones como código
import {
to = aws_instance.web
id = "i-0abcd1234efgh5678"
}
import {
to = aws_s3_bucket.data
id = "my-existing-bucket-name"
}
# Generar código automáticamente para los recursos importados
terraform plan -generate-config-out=generated.tf
# Revisar el código generado y ajustar según necesidad
cat generated.tf
Manipulación del Estado
Mover recursos en el estado
Cuando renombras un recurso en el código sin querer destruirlo:
# Mover un recurso a un nuevo nombre
terraform state mv aws_instance.web aws_instance.servidor_web
# Mover un recurso a un módulo
terraform state mv aws_instance.web module.compute.aws_instance.web
# Mover múltiples recursos (hacerlo uno a uno para mayor control)
terraform state mv aws_security_group.old module.network.aws_security_group.main
El bloque moved (Terraform >= 1.1) es la forma declarativa y preferida:
# En tu código .tf, declarar el movimiento
moved {
from = aws_instance.web
to = aws_instance.servidor_web
}
Eliminar recursos del estado
Útil cuando quieres que Terraform deje de gestionar un recurso sin destruirlo:
# Eliminar un recurso del estado (el recurso real NO se destruye)
terraform state rm aws_instance.temporal
# Eliminar todos los recursos de un módulo del estado
terraform state rm module.legacy
# Eliminar múltiples recursos con patrón
terraform state rm 'aws_instance.web[0]'
Extraer e importar estado
# Hacer backup del estado antes de cualquier operación destructiva
cp terraform.tfstate terraform.tfstate.backup.$(date +%Y%m%d)
# Extraer un recurso del estado a un archivo separado
terraform state pull > estado_completo.json
# Forzar push de un estado modificado (usar con extremo cuidado)
terraform state push estado_modificado.json
Migración de Backends
Configurar un backend remoto en S3
# backend.tf
terraform {
backend "s3" {
bucket = "mi-empresa-terraform-state"
key = "produccion/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-state-lock"
encrypt = true
}
}
# Migrar el estado local al backend remoto
terraform init -migrate-state
# Confirmar la migración cuando se solicite
# Terraform copiará el estado automáticamente
Migrar entre backends
# Paso 1: Hacer pull del estado actual
terraform state pull > backup_estado.json
# Paso 2: Actualizar la configuración del backend en main.tf
# Paso 3: Inicializar con migración
terraform init -migrate-state
# Paso 4: Verificar que el estado se migró correctamente
terraform state list
Bloqueo de Estado y Workspaces
Bloqueo de estado
El bloqueo previene modificaciones simultáneas que podrían corromper el estado:
# Forzar desbloqueo si un proceso quedó colgado (usar con cuidado)
terraform force-unlock LOCK_ID
# Ver el ID del lock en el mensaje de error de Terraform
# Error: Error acquiring the state lock
# Lock Info:
# ID: 12345678-abcd-1234-efgh-123456789012
Gestión de Workspaces
Los workspaces permiten múltiples estados para el mismo código:
# Listar workspaces disponibles
terraform workspace list
# Crear un nuevo workspace para staging
terraform workspace new staging
# Cambiar al workspace de producción
terraform workspace select produccion
# Ver el workspace actual
terraform workspace show
# Usar el workspace en el código
# En HCL: ${terraform.workspace}
# Usar el workspace para diferenciar entornos
resource "aws_instance" "web" {
instance_type = terraform.workspace == "produccion" ? "t3.medium" : "t3.micro"
tags = {
Entorno = terraform.workspace
}
}
Detección de Drift
El drift ocurre cuando la infraestructura real difiere del estado de Terraform (por cambios manuales):
# Refrescar el estado comparando con la infraestructura real
terraform refresh
# Plan que muestra el drift sin aplicar cambios
terraform plan -refresh-only
# Aplicar solo los cambios de refresh (actualizar estado sin modificar infraestructura)
terraform apply -refresh-only
# Deshabilitar refresh para operaciones más rápidas (en CI/CD con estado confiable)
terraform plan -refresh=false
# Detectar recursos que existen en el proveedor pero no en el estado
# Usando AWS como ejemplo
aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId,Tags[?Key==`Name`].Value]' --output table
# Comparar con lo que Terraform conoce
terraform state list | grep aws_instance
Solución de Problemas
Error: Estado bloqueado
# Ver información del lock
terraform plan
# Copiar el Lock ID del mensaje de error
# Desbloquear (solo si estás seguro de que no hay otra operación en curso)
terraform force-unlock <LOCK_ID>
Error: Recurso ya existe en el estado
# Si intentas importar un recurso que ya está en el estado
terraform state show aws_instance.web
# Decidir si moverlo o eliminarlo primero
terraform state rm aws_instance.web
terraform import aws_instance.web <nuevo_id>
Estado corrupto o inconsistente
# Restaurar desde backup
cp terraform.tfstate.backup terraform.tfstate
# O hacer pull desde el backend remoto
terraform state pull > terraform.tfstate.recovery
# Verificar integridad del estado
terraform validate
terraform plan
Recurso no encontrado en el proveedor
# El recurso existe en el estado pero fue eliminado manualmente
# Eliminarlo del estado para que Terraform no intente gestionarlo
terraform state rm aws_instance.eliminado_manualmente
# O usar terraform apply para recrearlo según el código
terraform apply -target=aws_instance.eliminado_manualmente
Conclusión
La gestión del estado es el aspecto más crítico de trabajar con Terraform en producción. Dominar terraform import, state mv, state rm y la migración de backends te permite mantener la infraestructura sincronizada con el código, refactorizar módulos sin interrupciones y recuperarte de situaciones de drift o estado corrupto. Siempre mantén backups del estado antes de realizar operaciones destructivas y usa backends remotos con bloqueo habilitado en entornos de equipo.


