Automatización con Terraform y Ansible para Infraestructura como Código
La convergencia de Terraform y Ansible ha redefinido la forma en que los administradores de sistemas y los equipos de DevOps gestionan la infraestructura como código (IaC) en entornos de hosting. Mientras que Terraform se encarga del aprovisionamiento declarativo de recursos (servidores, redes, balanceadores), Ansible orquesta la configuración interna, el despliegue de aplicaciones y el mantenimiento continuo. Esta sinergia permite que la automatización servidores deje de ser un lujo y se convierta en un pilar fundamental de cualquier infraestructura moderna.
En este artículo exploraremos en profundidad cómo combinar ambas herramientas para lograr un flujo de trabajo robusto, escalable y repetible. Analizaremos casos prácticos, estructuras de código y buenas prácticas que te permitirán implementar IaC hosting desde cero, optimizando costes y reduciendo errores humanos.
¿Por qué Terraform y Ansible juntos?
No se trata de elegir entre una herramienta u otra, sino de entender que cada una resuelve un problema diferente dentro del ciclo de vida de la infraestructura.
Terraform: El arquitecto de la nube
Terraform es una herramienta de aprovisionamiento declarativo. Define el estado deseado de la infraestructura en archivos de configuración (HCL) y se encarga de crearla, modificarla o destruirla. Su enfoque es idempotente: aplicar el mismo plan cien veces produce el mismo resultado.
Fortalezas clave:
- Gestión de recursos en múltiples proveedores (AWS, Azure, GCP, OpenStack, vSphere).
- Visibilidad completa del estado mediante archivos de estado (state files).
- Manejo de dependencias entre recursos (por ejemplo, crear una VPC antes que una instancia).
- Ideal para el aprovisionamiento de infraestructura base.
Ansible: El ingeniero de sistemas
Ansible es una herramienta de automatización sin agente que se conecta por SSH a los servidores para configurarlos. Su lenguaje YAML es fácil de leer y escribir, y su modelo push permite aplicar cambios de forma inmediata.
Fortalezas clave:
- Configuración de software (instalar paquetes, modificar archivos, reiniciar servicios).
- Despliegue de aplicaciones y actualizaciones.
- Gestión de usuarios, permisos y cron jobs.
- Orquestación de tareas complejas con roles y playbooks.
[INFO] Terraform no configura el interior de un servidor; Ansible no aprovisiona recursos de nube. Juntos cubren todo el espectro de la infraestructura como código.
Flujo de trabajo ideal: Provisionar con Terraform, configurar con Ansible
El patrón más común consiste en que Terraform cree la infraestructura y, al finalizar, ejecute Ansible para configurar cada servidor. Este flujo se puede automatizar completamente en pipelines CI/CD.
Paso 1: Definir la infraestructura con Terraform
Creamos un directorio terraform/ con los siguientes archivos:
# main.tf
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "web_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "web-prod-01"
}
# Pasamos la IP pública a Ansible mediante un inventario dinámico
provisioner "local-exec" {
command = "echo ${self.public_ip} > /tmp/inventory_hosts"
}
}
# outputs.tf
output "server_ip" {
value = aws_instance.web_server.public_ip
}
# variables.tf
variable "env" {
default = "production"
}
Paso 2: Configurar el servidor con Ansible
En el directorio ansible/ definimos un playbook que se ejecutará contra la IP generada por Terraform.
# playbook.yml
---
- hosts: webservers
become: yes
tasks:
- name: Instalar Nginx
apt:
name: nginx
state: present
update_cache: yes
- name: Copiar sitio web
copy:
src: index.html
dest: /var/www/html/index.html
owner: www-data
group: www-data
mode: '0644'
- name: Asegurar que Nginx esté corriendo
service:
name: nginx
state: started
enabled: yes
# inventory.ini (generado automáticamente por Terraform)
[webservers]
54.123.45.67 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa
Paso 3: Orquestar la ejecución
Podemos unir ambas herramientas con un script bash o dentro de un pipeline de Jenkins/GitLab CI.
#!/bin/bash
set -e
# 1. Aprovisionar infraestructura
cd terraform
terraform init
terraform apply -auto-approve
# 2. Obtener IP y generar inventario
SERVER_IP=$(terraform output -raw server_ip)
echo "[webservers]" > ../ansible/inventory.ini
echo "$SERVER_IP ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa" >> ../ansible/inventory.ini
# 3. Configurar servidor
cd ../ansible
ansible-playbook -i inventory.ini playbook.yml
echo "Infraestructura desplegada y configurada correctamente."
[TIP] Para entornos críticos, considera usar un inventario dinámico de Ansible que consulte el estado de Terraform directamente, evitando archivos temporales.
Buenas prácticas para IaC hosting con Terraform y Ansible
1. Separación de responsabilidades
Mantén los proyectos de Terraform y Ansible en directorios independientes dentro de un mismo repositorio. Cada uno debe tener su propio README.md y estructura de variables.
mi-proyecto-iac/
├── terraform/
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│ └── modules/
├── ansible/
│ ├── playbooks/
│ ├── roles/
│ ├── group_vars/
│ └── inventory/
└── scripts/
└── deploy.sh
2. Gestión de secretos
Nunca incluyas claves privadas, tokens de API o contraseñas en el código. Utiliza:
- Terraform: Variables de entorno o backends remotos como Vault.
- Ansible: Ansible Vault para cifrar variables sensibles.
# Cifrar un archivo de variables
ansible-vault encrypt group_vars/all/vault.yml
# Ejecutar playbook solicitando la contraseña
ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass
3. Uso de módulos y roles
Para evitar la repetición, crea módulos de Terraform reutilizables (por ejemplo, un módulo webserver que incluya VPC, subred, instancia y security group). En Ansible, utiliza roles para estandarizar configuraciones como nginx, postgresql o docker.
4. Control de versiones
Terraform tiene un archivo de estado (terraform.tfstate) que contiene información sensible. Nunca lo subas a Git. Configura un backend remoto (S3, Azure Storage, etc.) con bloqueo de estado.
# backend.tf
terraform {
backend "s3" {
bucket = "mi-empresa-terraform-state"
key = "production/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
}
}
5. Pruebas en entornos aislados
Antes de aplicar cambios en producción, utiliza workspaces de Terraform para crear entornos de staging o desarrollo.
terraform workspace new staging
terraform apply
Luego, desde Ansible, puedes usar variables de grupo para adaptar configuraciones (por ejemplo, número de workers de Nginx).
Caso práctico: Despliegue de un clúster web escalable
Imaginemos que necesitamos desplegar un sitio web con alta disponibilidad. El flujo combinado sería:
-
Terraform crea:
- Una VPC con subredes públicas y privadas.
- Un balanceador de carga (ALB) en la subred pública.
- Un Auto Scaling Group (ASG) con instancias EC2 en la subred privada.
- Una base de datos RDS en la subred privada.
- Un bucket S3 para assets estáticos.
-
Ansible se ejecuta en cada nueva instancia lanzada por el ASG mediante un user_data que llama a un playbook:
- Instala Nginx, PHP-FPM y Redis.
- Configura el virtual host.
- Despliega la aplicación desde un repositorio Git.
- Ajusta los parámetros de PHP según el tamaño de la instancia.
-
Mantenimiento continuo: Cuando haya que actualizar la configuración de Nginx, se ejecuta un playbook específico contra todo el clúster usando el inventario dinámico.
# ansible/playbooks/update-nginx.yml
---
- hosts: tag_webserver
become: yes
tasks:
- name: Actualizar configuración de Nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: reiniciar nginx
handlers:
- name: reiniciar nginx
service:
name: nginx
state: restarted
Errores comunes y cómo evitarlos
Mezclar responsabilidades
Error: Usar Terraform para instalar software (por ejemplo, con remote-exec o file provisioner).
Solución: Limitar Terraform al aprovisionamiento y delegar toda la configuración a Ansible. Los provisioners de Terraform deben ser el último recurso, solo para tareas mínimas como generar inventarios.
Ignorar el estado remoto
Error: Trabajar con el estado local en terraform.tfstate y perderlo al borrar el directorio.
Solución: Configurar un backend remoto desde el inicio. Esto permite trabajar en equipo y recuperar el estado ante desastres.
Playbooks demasiado largos
Error: Un único playbook de 500 líneas que hace de todo.
Solución: Dividir en roles. Por ejemplo, un rol nginx, otro php, otro firewall. Luego, un playbook principal que los invoca:
---
- hosts: webservers
roles:
- common
- nginx
- php
- monitoring
No probar la idempotencia
Error: Asumir que un playbook funciona solo porque se ejecuta una vez.
Solución: Ejecutar el playbook dos veces seguidas y verificar que no haya cambios en la segunda ejecución. Ansible muestra changed=0 si todo está correcto.
Conclusión
La combinación de Terraform y Ansible para infraestructura como código no solo acelera el despliegue de servidores, sino que garantiza consistencia, repetibilidad y control de versiones en entornos de hosting de cualquier escala. Mientras Terraform se encarga de la capa física y lógica de la nube, Ansible afina cada tornillo del sistema operativo y las aplicaciones.
Para un SysAdmin moderno, dominar ambas herramientas es tan esencial como saber usar la terminal. La automatización servidores ya no es opcional: es la base de cualquier operación de hosting que aspire a ser ágil, segura y rentable.
[WARNING] No subestimes la complejidad del estado de Terraform en equipos grandes. Establece políticas claras de bloqueo y revisión de cambios (pull requests) para evitar conflictos.
Empieza con un proyecto pequeño: un servidor web con Terraform y un playbook básico de Ansible. Una vez que veas el poder de pulsar un botón y tener toda la infraestructura lista, querrás automatizar todo lo que toques.
