🎨 Sysprovider Code
Sysprovider LogoWiki
🇪🇸Hosting español para ecommerce

Despliegue de Servidores con Infraestructura como Código (IaC) usando Terraform y Ansible

Actualizado el 12 de octubre de 2025

La automatización de servidores ha pasado de ser una ventaja competitiva a un requisito indispensable en cualquier infraestructura moderna. Gestionar decenas o cientos de servidores de forma manual no solo es ineficiente, sino que introduce un alto riesgo de error humano y deriva en el temido configuration drift. Aquí es donde la Infraestructura como Código (IaC) se convierte en tu mejor aliada.

En este artículo, exploraremos en profundidad el despliegue de servidores utilizando dos de las herramientas más potentes del ecosistema DevOps: Terraform para la orquestación y aprovisionamiento de la infraestructura, y Ansible para la configuración y gestión del estado interno de los sistemas. Verás cómo combinarlas te permite construir un pipeline de despliegue robusto, reproducible y escalable.

¿Por qué Terraform y Ansible? El Yin y el Yang del IaC

A menudo surge la pregunta: ¿por qué usar dos herramientas cuando una sola podría hacer "casi todo"? La respuesta está en la especialización. Aunque Ansible puede aprovisionar recursos en la nube y Terraform puede ejecutar scripts de configuración, cada uno brilla en su dominio específico.

Terraform: El Arquitecto de la Infraestructura

Terraform es una herramienta de orquestación declarativa. Su lenguaje, HCL (HashiCorp Configuration Language), te permite describir el estado deseado de tu infraestructura: redes, subredes, firewalls, instancias de servidores, balanceadores de carga, etc.

  • Enfoque Declarativo: Dices qué quieres (una VM con 4GB de RAM y una IP pública), no cómo crearla.
  • Gestión de Estado: Terraform mantiene un archivo de estado (terraform.tfstate) que mapea los recursos reales con tu configuración. Esto permite detectar cambios y aplicar solo las diferencias.
  • Proveedores: Soporta cientos de proveedores (AWS, Azure, GCP, VMware, OpenStack, etc.) a través de un ecosistema de plugins.

Ansible: El Manitas de la Configuración

Ansible es una herramienta de gestión de configuración imperativa (aunque con sabor declarativo). Se conecta a los servidores ya creados (generalmente por SSH) y se asegura de que el software esté instalado, los servicios estén corriendo y los archivos de configuración tengan el contenido correcto.

  • Sin Agente: No requiere instalar nada en el servidor de destino. Solo necesita Python y SSH.
  • Idempotencia: Ejecutar un playbook una o cien veces produce el mismo resultado final. Si el servidor ya está configurado, no hace nada.
  • Módulos: Ofrece miles de módulos para gestionar paquetes (apt, yum), servicios (systemd), archivos (template, copy), usuarios, etc.

[INFO] La combinación Terraform + Ansible es el estándar de facto en la industria. Terraform se encarga del "hardware lógico" (la nube) y Ansible del "software" (el sistema operativo y las aplicaciones).

Flujo de Trabajo Ideal: Aprovisionar y Configurar

El flujo de trabajo típico para desplegar un servidor web con esta pila es el siguiente:

  1. Terraform crea la red, la subred, el grupo de seguridad y una instancia de servidor (por ejemplo, un EC2 en AWS o un droplet en DigitalOcean).
  2. Terraform llama a un playbook de Ansible (usando el provisioner remote-exec o, mejor, el local-exec para ejecutar Ansible desde tu máquina local o un runner de CI/CD).
  3. Ansible se conecta a la IP pública del nuevo servidor, instala Nginx, configura el firewall (ufw), despliega un sitio web de prueba y se asegura de que el servicio esté habilitado en el arranque.

Manos a la Obra: Ejemplo Práctico de Despliegue

Vamos a construir un ejemplo sencillo pero funcional. Desplegaremos un servidor web Nginx en DigitalOcean usando Terraform y luego lo configuraremos con Ansible.

1. Estructura de Directorios

infraestructura/
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars
└── ansible/
    ├── inventory.yml
    ├── playbook.yml
    └── roles/
        └── nginx/
            ├── tasks/
            │   └── main.yml
            └── templates/
                └── index.html.j2

2. Terraform: main.tf

Este archivo define el proveedor (DigitalOcean), la clave SSH, el droplet (servidor) y un output para obtener la IP.

# main.tf
terraform {
  required_providers {
    digitalocean = {
      source = "digitalocean/digitalocean"
      version = "~> 2.0"
    }
  }
}

provider "digitalocean" {
  token = var.do_token
}

resource "digitalocean_ssh_key" "default" {
  name       = "Mi Clave SSH"
  public_key = file(var.public_key_path)
}

resource "digitalocean_droplet" "web" {
  image     = "ubuntu-22-04-x64"
  name      = "servidor-web-01"
  region    = "nyc3"
  size      = "s-1vcpu-1gb"
  ssh_keys  = [digitalocean_ssh_key.default.fingerprint]
}

# Output para obtener la IP
output "server_ip" {
  value = digitalocean_droplet.web.ipv4_address
}

3. Terraform: variables.tf y terraform.tfvars

# variables.tf
variable "do_token" {
  description = "Token de API de DigitalOcean"
  type        = string
  sensitive   = true
}

variable "public_key_path" {
  description = "Ruta a la clave pública SSH"
  type        = string
  default     = "~/.ssh/id_rsa.pub"
}
# terraform.tfvars
do_token = "dop_v1_your_super_secret_token_here"

4. El Trigger: Provisioner de Terraform para llamar a Ansible

Para que Terraform ejecute Ansible automáticamente después de crear el droplet, añadimos un provisioner local.

# Dentro de main.tf, dentro del recurso droplet
resource "digitalocean_droplet" "web" {
  # ... configuración anterior ...

  provisioner "local-exec" {
    command = "ansible-playbook -i ansible/inventory.yml ansible/playbook.yml -e 'server_ip=${self.ipv4_address}'"
  }
}

[WARNING] Usar local-exec para ejecutar Ansible desde tu máquina local es práctico para desarrollo. En producción, deberías mover esto a un pipeline de CI/CD (GitLab CI, GitHub Actions, Jenkins) que ejecute Terraform y Ansible de forma aislada.

5. Ansible: Inventario Dinámico y Playbook

Creamos un inventario estático simple que recibe la IP como variable.

# ansible/inventory.yml
[webservers]
server-ansible ansible_host={{ server_ip }} ansible_user=root

Ahora, el playbook:

# ansible/playbook.yml
---
- name: Configurar servidor web Nginx
  hosts: webservers
  gather_facts: yes
  become: yes

  tasks:
    - name: Actualizar cache de apt
      apt:
        update_cache: yes
        cache_valid_time: 3600

    - name: Instalar Nginx
      apt:
        name: nginx
        state: present

    - name: Asegurar que Nginx está corriendo y habilitado
      systemd:
        name: nginx
        state: started
        enabled: yes

    - name: Copiar un index.html personalizado
      template:
        src: roles/nginx/templates/index.html.j2
        dest: /var/www/html/index.html
      notify: restart nginx

  handlers:
    - name: restart nginx
      systemd:
        name: nginx
        state: restarted

Y la plantilla HTML:

<!-- ansible/roles/nginx/templates/index.html.j2 -->
<!DOCTYPE html>
<html>
<head>
<title>Servidor Desplegado con IaC</title>
</head>
<body>
<h1>¡Hola desde Terraform y Ansible!</h1>
<p>Servidor: {{ ansible_hostname }}</p>
<p>IP: {{ ansible_default_ipv4.address }}</p>
</body>
</html>

6. Ejecución

# Inicializar Terraform
cd infraestructura/
terraform init

# Ver el plan de ejecución
terraform plan

# Aplicar (crea el droplet y ejecuta Ansible)
terraform apply -auto-approve

# Destruir cuando ya no sea necesario
terraform destroy -auto-approve

Buenas Prácticas para un IaC Robusto

Implementar IaC no es solo escribir archivos .tf y .yml. Requiere disciplina y buenas prácticas.

Gestión del Estado de Terraform

El archivo terraform.tfstate es crítico. Si lo pierdes, Terraform no sabrá qué recursos gestiona. Nunca lo subas a Git (añádelo a .gitignore). En su lugar, usa un backend remoto:

# backend.tf
terraform {
  backend "s3" {
    bucket = "mi-bucket-terraform-state"
    key    = "produccion/servidores-web.tfstate"
    region = "us-east-1"
  }
}

También puedes usar Terraform Cloud, Azure Storage, o consul.

Control de Versiones y Entornos

  • Git: Todo el código de infraestructura debe estar versionado en Git.
  • Ramas: Usa ramas como main (producción), staging y develop.
  • Módulos: Crea módulos de Terraform reutilizables para componentes comunes (VPC, balanceador, base de datos).

Seguridad

  • Secretos: Nunca hardcodees tokens o contraseñas. Usa variables de entorno, un vault (como HashiCorp Vault) o el sistema de secretos de tu proveedor de nube.
  • Ansible Vault: Para cifrar playbooks que contengan contraseñas, usa ansible-vault encrypt playbook.yml.

[TIP] Combina Terraform con un remote state y bloqueo de estado para evitar que dos personas o pipelines modifiquen la misma infraestructura simultáneamente.

Casos de Uso Avanzados: Más Allá del Servidor Simple

La combinación Terraform + Ansible escala a escenarios mucho más complejos.

Clústeres de Alta Disponibilidad

Terraform puede crear un Auto Scaling Group (ASG) en AWS y un Load Balancer. Luego, Ansible puede configurar cada nueva instancia que se lance automáticamente (usando un golden image o un user-data script que llame a un playbook de Ansible Pull).

Despliegues Multi-Nube

Puedes tener un mismo playbook de Ansible configurando servidores en AWS, Azure y un datacenter on-premise, mientras que Terraform gestiona los recursos específicos de cada nube.

Integración con CI/CD

En un pipeline de GitLab CI/CD, podrías tener un job que ejecute terraform plan, otro que aplique los cambios después de aprobación manual, y un tercero que ejecute ansible-playbook contra los nuevos servidores.

# .gitlab-ci.yml (fragmento)
stages:
  - plan
  - apply
  - configure

terraform-plan:
  stage: plan
  script:
    - terraform init
    - terraform plan -out=tfplan
  artifacts:
    paths: [tfplan]

terraform-apply:
  stage: apply
  script:
    - terraform apply tfplan
  only:
    - main

ansible-configure:
  stage: configure
  script:
    - ansible-playbook -i ansible/inventory.yml ansible/playbook.yml
  needs: ["terraform-apply"]

Conclusión

Adoptar Infraestructura como Código con Terraform y Ansible transforma la gestión de servidores. Pasas de un arte manual y propenso a errores a una ingeniería de software disciplinada.

Terraform te da el poder de crear y destruir infraestructura compleja con un solo comando, mientras que Ansible te asegura que el software se configure exactamente como necesitas, sin desviaciones. Juntos, forman la base de cualquier estrategia moderna de automatización de servidores.

No importa si gestionas 5 servidores o 5000; el tiempo invertido en aprender estas herramientas se amortiza exponencialmente. Empieza con un pequeño proyecto de prueba, versiona tu código, y verás cómo la repetitividad y los errores desaparecen, dejando paso a una infraestructura predecible, auditable y escalable.

¿Necesitas ayuda?Son dos de nuestros técnicos, Agustín y Mikel, y están disponibles para resolver cualquier problema.

Hablar con ellos ahora
Agustín y Mikel