Infraestructura como Código: Por qué Terraform se Volvió el Estándar

DUGLAS MORENODUGLAS MORENO 👁 2

Infraestructura como Código: Por qué Terraform se Volvió el Estándar

Introducción

Las organizaciones están desplegando cada vez más servicios en la nube, contenedores en múltiples nubes y clusterizados de forma dinámica. El enfoque tradicional, basado en la ejecución de comandos manualmente en la consola, se volvió inestable, propenso a errores y difícil de escalar. La solución surgió de la necesidad de versionar, compartir y automatizar estos cambios, dando lugar a una nueva disciplina: Infrastructure as Code (IaC).

Terraform de HashiCorp se posicionó como el estándar de facto. Cientos de miles de equipos lo adoptan hoy. En este artículo, exploraremos qué es IaC, cuáles son sus ventajas y por qué Terraform se destacó. También compararemos un enfoque sin IaC con una implementación basada en Terraform, mostrando ejemplos concretos, explicaciones detalladas y el flujo de trabajo habitual de Terraform.

Qué es Infrastructure as Code

Infrastructure as Code significa definir la infraestructura computacional (servidores, redes, bases de datos, servicios en la nube, contenedores, etc.) usando archivos de texto editables, generalmente almacenados en control de versiones, en lugar de configuraciones manuales de consola o scripts.

  • Declarativo vs. Imperativo: IaC suele ser declarativo: declarás qué querés, y Terraform deduce cómo lograrlo.
  • Versionado: Los cambios en el código de infraestructura se rastrean como cualquier otro código fuente, lo que permite audits históricos, rollbacks y colaboración.
  • Repetibilidad: El mismo código produce idéntica infraestructura en cualquier ambiente (desarrollo, pruebas, producción), eliminando el problema del "funciona en mi máquina".

Beneficios Clave

  • Escalabilidad: Agregar nodos o servicios es tan simple como editar un archivo o agregar un bloque en Terraform.
  • Colaboración: Los equipos pueden trabajar en módulos independientes sin interferir entre sí.
  • Seguridad y Gobernanza: Se pueden aplicar restricciones, etiquetas y políticas como código (por ejemplo, usando Terraform Cloud/Enterprise).
  • Velocidad: Los pipelines de CI/CD pueden aprovisionar recursos en segundos, en lugar de minutos u horas.

El Surgimiento de Terraform

Antes de Terraform, existían herramientas como Chef, Puppet y Ansible, enfocadas en la configuración de sistemas operativos y la ejecución de tareas. Si bien útiles, estaban diseñados para cambiar el estado de los sistemas existentes, no para crear nuevos recursos en la nube.

La llegada de la nube moderna (AWS EC2, Google Compute Engine, Azure Virtual Machines, servicios containers como Kubernetes) generó una necesidad de un modelo de lenguaje neutral frente al proveedor que abstraiga la creación de recursos. HashiCorp lanzó Terraform en 2014 con estos principios de diseño:

  • Backend de recursos específico por proveedor: Cada proveedor tiene su propio proveedor Terraform, escrito por el equipo del proveedor o la comunidad.
  • Estado declarativo: Terraform guarda un estado (.tfstate) que representa la infraestructura actual, permitiendo la detección de cambios.
  • Modularidad: Recursos reutilizables a través de módulos, permitting el compartir plantillas entre equipos.
  • Economía de escritura sobre lectura: Aprovecha el modelo de APIs de la nube (principalmente REST) que es más fácil de consumir por escrito que por lectura.

Con el tiempo, Terraform ganó soporte para más de 1000 proveedores, un ecosistema fuerte (módulos, proyectos comunitarios) y un modelo de negocio claro (open-source + Enterprise). Estas razones lo consolidaron como la herramienta IaC predominante.

Comparación: Despliegue Manual vs. Terraform

Sin IaC – Aprovisionamiento Manual

Imaginá que querés crear una máquina virtual simple en AWS y expone un servidor web en la puerta de enlace de internet. El enfoque tradicional podría verse así:

# 1️⃣ Iniciar sesión en AWS (requiere credenciales configuradas)
aws configure

# 2️⃣ Crear una clave SSH (si no tenés una)
aws ec2 create-key-pair --key-name my-keypair --query 'KeyMaterial' --output text > my-keypair.pem
chmod 400 my-keypair.pem

# 3️⃣ Obtener una AMI reciente de Amazon Linux
AMI=$(aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-*-x86_64-gp2" --query "Images | sort_by(@, &CreationDate) | [-1].ImageId" --output text)

# 4️⃣ Lanzar una instancia
INSTANCE_ID=$(aws ec2 run-instances \
    --image-id $AMI \
    --instance-type t2.micro \
    --key-name my-keypair \
    --security-group-ids sg-xxxxxxxxx \
    --subnet-id subnet-xxxxxxxxx \
    --query 'Instances[0].InstanceId' \
    --output text)

# 5️⃣ Esperar a que la IP pública esté asignada
aws ec2 wait instance-running --instance-ids $INSTANCE_ID
PUBLIC_IP=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID --query 'Reservations[0].Instances[0].PublicIpAddress' --output text)

# 6️⃣ Conectar y editar /etc/httpd.conf (simplificado)
ssh -i my-keypair.pem ec2-user@$PUBLIC_IP 'sudo yum install -y httpd && sudo systemctl start httpd && echo "Hola desde Terraform" > /var/www/html/index.html'

# 7️⃣ Verificar
 curl http://$PUBLIC_IP

Problemas con este enfoque:

  • Paso a paso: 7 comandos, cada uno con sus propias variables.
  • Propenso a errores: Perdés un parámetro y la VM no está expuesta.
  • No versionado: No hay forma de ver una versión previa de la configuración.
  • Difícil de colaborar: Cada ingeniero sigue un flujo de trabajo ligeramente diferente.
  • Escalabilidad limitada: Añadir 100 instancias manualmente es inviable.

Con IaC (Terraform)

El mismo objetivo se expresa en unos pocos archivos HCL (HashiCorp Configuration Language). Aquí tenés un main.tf mínimo:

# main.tf
provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "web" {
  ami                    = "ami-0c55b159cbfafe1f0"  # Amazon Linux 2 (ejemplo)
  instance_type          = "t2.micro"
  key_name               = "my-keypair"
  security_groups        = ["sg-xxxxxxxxx"]
  subnet_id              = "subnet-xxxxxxxxx"

  tags = {
    Name = "web-server"
  }

  user_data = <<-EOF
              #!/bin/bash
              sudo yum install -y httpd
              sudo systemctl start httpd
              echo "Hola desde Terraform" > /var/www/html/index.html
              EOF
}

Una vez que el archivo está listo, el flujo de trabajo de Terraform es:

# Inicializar el working directory (descarga el proveedor)
terraform init

# Ver el plan – preview de los cambios que harán
terraform plan

# Aplicar (crea la infraestructura)
terraform apply

Todo el proceso se escribe una vez, se puede versionar y se ejecuta en cualquier lado (local, CI, nube). Agregar más instancias es tan simple como duplicar el bloque aws_instance o iterar con for_each.

Script de ejemplo para "Sin IaC" (demo rápido)

Aquí tenés un script Bash autocontenido que imprime los pasos manuales (no ejecuta realmente llamadas a la nube, solo muestra lo que sucedería). Puedes correrlo en cualquier terminal:

#!/usr/bin/env bash

echo "=== Aprovisionamiento Manual de una VM AWS ==="
echo "1) Iniciar sesión: aws configure"
echo "2) Crear clave SSH: aws ec2 create-key-pair ..."
echo "3) Obtener AMI: aws ec2 describe-images ..."
echo "4) Lanzar instancia: aws ec2 run-instances ..."
echo "5) Esperar IP pública: aws ec2 wait instance-running"
echo "6) Conectar vía SSH y desplegar aplicación web"
echo "7) Verificar con curl"
echo ""
echo "Eso es todo… manual, propenso a errores y no versionado."

Script de ejemplo con Terraform (descripción, no ejecutable)

La siguiente es una vista previa del archivo variables.tf que podrías usar junto con main.tf:

variable "instance_count" {
  description = "Cantidad de instancias web a crear"
  type        = number
  default     = 1
}

resource "aws_instance" "web" {
  count = var.instance_count
  ami   = var.ami_id
  # ... otros argumentos
}

La ventaja de este enfoque es clara: puedes pasar instance_count=5 y la misma plantilla creará cinco servidores idénticos sin modificar el HCL.

Empezando Con Terraform

Instalación y Configuración Inicial

apt update && apt install -y terraform   # Debian/Ubuntu
# o
brew install hashicorp/tap/terraform   # macOS
# o
choco install terraform                # Windows

Configurás tus credenciales de AWS (o cualquier proveedor) usando variables de entorno (AWS_ACCESS_KEY_ID, etc.) o el perfil ~/.aws/credentials.

Conceptos Básicos

  • Dirección de recursos: provider, resource_type, resource_name
  • Argumentos: opciones para un recurso.
  • Argumentos de desplazamiento: sobrescribir en el momento del apply (por ejemplo, terraform apply -var='instance_type=t2.nano').
  • Variables: mantenelas en variables.tf; valores predeterminados en terraform.tfvars.
  • Salida: output para exponer valores útiles después del apply (por ejemplo, la IP pública).

Flujo de trabajo Típico

  1. Escribir los archivos .tf.
  2. terraform init – descarga el proveedor y configura el backend (estado remoto en S3/Consul, por ejemplo).
  3. terraform plan – muestra lo que cambiará; idempotente (ejecutar plan varias veces produce el mismo diff).
  4. terraform apply – crea o modifica la infraestructura; puedes usar terraform destroy para eliminarla.

Estado Remoto vs. Estado Local

Para equipos, el estado debe ser remotizado. Un patrón típico usa un bucket S3 con cifrado SSE-KMS y un bloqueo DynamoDB para prevenir actualizaciones conflictivas:

terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-lock-table"
  }
}

Módulos y Compartir

Un módulo encapsula un patrón reutilizable (por ejemplo, un grupo de autoscaling). Ejemplo de modules/example-instance/main.tf:

resource "aws_instance" "vm" {
  ami           = var.ami_id
  instance_type = var.instance_type
}

Luego referencialo:

module "apps" {
  source  = "hashicorp/example-instance/aws"
  version = "1.2.0"
  instance_type = "t2.micro"
}

Buenas Prácticas y Errores Comunes

  • Nunca comits vacíos: Un terraform plan sin cambios (terraform plan -out=tfplan && terraform apply tfplan) asegura que no haya drifts silenciosos.
  • Usa backends remotos: El estado local no se escala y pierde la colaboración.
  • Aplica el principio de "Una responsabilidad por módulo": Un módulo debe representar un recurso de nube lógico (por ejemplo, balanceador de carga, no toda la VPC).
  • Aplica etiquetas: Las etiquetas consistentes ayudan con la gobernanza y la facturación.
  • Evita depends_on cuando sea posible: El grafo de dependencias del proveedor es robusto; agregar dependencias artificiales puede ocultar problemas subyacentes.

Errores Comunes

Error Por qué es problemático Cómo evitarlo
Estado fuera de sincronización Modificar el estado manualmente (terraform state edit) puede causar deploys conflictivos. Siempre usa IaC para los cambios; usa terraform refresh para sincronizar.
Exponer secrets en código fuente Las claves, tokens y certificados aparecen en Git. Usa terraform workspace con variables de entorno o el bloque secrets de Terraform Cloud.
Sobreaprovisionar recursos Las instancias "solo por si acaso" aumentan drásticamente los costos. Inicia con planes mínimos, luego escala basado en métricas (AutoScaling Groups, Spot Instances).
Ignorar la idempotencia Ejecutar apply varias veces produce recursos duplicados. Revisa count o for_each; asegúrate de que el diff sea vacío después del primer apply.

Conclusión

Infrastructure as Code revolucionó la forma en que creamos y administramos recursos en la nube. Elimina el caos del aprovisionamiento manual, da a los equipos un modelo de desarrollo basado en código y facilita la colaboración, auditoría y escalabilidad.

Terraform se convirtió en el estándar porque abstrae las complejidades específicas de cada proveedor, provee un estado claro y cuenta con un ecosistema sólido. Al entender los beneficios de IaC, la historia de Terraform y comparar un flujo de trabajo manual con un enfoque basado en Terraform, podés empezar a adoptar mejores prácticas que reduzcan errores, mejoren la velocidad y mantengan la infraestructura como un artefacto primero.

Próximos pasos:

  • Instala Terraform y crea una cuenta gratuita en Terraform Cloud (o usa un backend S3 local).
  • Escribe un simple main.tf que cree un recurso de prueba (por ejemplo, un bucket de S3).
  • Versiona el código, ejecuta terraform plan y observa el diff; luego aplica y explora los valores de salida.

Con este fundamento, ya estás listo para escalar hacia la creación de redes complejas, clusters Kubernetes y pipelines multi-cloud, todo gestionados como código.


Si tenés preguntas sobre módulos específicos, backends remotos o optimización de costos con Terraform, dejame un comentario o contactame directamente.

Comentarios (0)

Sé el primero en comentar.

Dejá tu comentario