Infraestructura como código con Terraform: de la gestión manual a la gestión automatizada de la nube

Administre la infraestructura de la nube con Terraform. Cubre la sintaxis de HCL, módulos, administración de estado, integración de CI/CD y estrategias de implementación en múltiples entornos.

E
ECOSIRE Research and Development Team
|16 de marzo de 20267 min de lectura1.6k Palabras|

Infraestructura como código con Terraform: de la gestión manual a la gestión automatizada de la nube

Las organizaciones que utilizan infraestructura como código (IaC) aprovisionan entornos un 90 % más rápido y experimentan un 60 % menos de interrupciones relacionadas con la configuración que aquellas que administran la infraestructura manualmente. Terraform se ha convertido en la herramienta IaC dominante, con más de 3000 proveedores que respaldan todas las principales plataformas de nube y servicios SaaS.

Esta guía cubre el uso práctico de Terraform para aplicaciones web, sistemas ERP y plataformas de comercio electrónico, desde la primera definición de recursos hasta implementaciones multientorno de nivel de producción.

Conclusiones clave

  • Terraform hace que los cambios de infraestructura sean revisables, comprobables y reversibles a través del control de versiones.
  • La gestión remota del estado evita conflictos cuando varios ingenieros modifican la infraestructura
  • Los módulos encapsulan patrones reutilizables, reduciendo la configuración de cientos de líneas a unos pocos parámetros.
  • La integración de Terraform Cloud o CI/CD impone la disciplina de planificar antes de aplicar para cambios seguros

¿Por qué Terraform para las PYMES?

El problema de la infraestructura manual

Sin IaC, su conocimiento de infraestructura reside en:

  • Rutas de clic de la consola de AWS que nadie documentó
  • Los comandos SSH se ejecutaron hace meses y nadie recuerda
  • Archivos de configuración editados directamente en los servidores.
  • El modelo mental de un ingeniero sobre "cómo funciona la red"

Con Terraform, su infraestructura vive en Git. Cada cambio es una solicitud de extracción. Cada implementación es reproducible. Cada ingeniero puede entender el panorama completo.

Conceptos básicos

ConceptoDescripción
ProveedorComplemento que interactúa con una plataforma en la nube (AWS, GCP, Azure, Cloudflare)
RecursoUn único componente de infraestructura (instancia EC2, base de datos RDS, depósito S3)
Fuente de datosReferencia de sólo lectura a la infraestructura existente
VariablesParámetro de entrada para configuración reutilizable
SalidaValor exportado desde una configuración de Terraform
EstadoRegistro de lo que gestiona Terraform y sus atributos actuales
MóduloGrupo reutilizable de recursos con una interfaz definida

Primera configuración de Terraform

AWS VPC y EC2 para una aplicación web

# providers.tf
terraform {
  required_version = ">= 1.7"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    bucket = "ecosire-terraform-state"
    key    = "production/terraform.tfstate"
    region = "us-east-1"
    encrypt = true
    dynamodb_table = "terraform-locks"
  }
}

provider "aws" {
  region = var.aws_region
}

# variables.tf
variable "aws_region" {
  type    = string
  default = "us-east-1"
}

variable "environment" {
  type    = string
  default = "production"
}

variable "instance_type" {
  type    = string
  default = "t3.large"
}

# main.tf
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name        = "${var.environment}-vpc"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

resource "aws_subnet" "public" {
  count             = 2
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.${count.index + 1}.0/24"
  availability_zone = data.aws_availability_zones.available.names[count.index]

  map_public_ip_on_launch = true

  tags = {
    Name = "${var.environment}-public-${count.index + 1}"
  }
}

resource "aws_instance" "app" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = var.instance_type
  subnet_id     = aws_subnet.public[0].id

  vpc_security_group_ids = [aws_security_group.app.id]
  key_name               = aws_key_pair.deploy.key_name

  root_block_device {
    volume_size = 50
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-app"
    Environment = var.environment
  }
}

resource "aws_db_instance" "postgres" {
  identifier     = "${var.environment}-db"
  engine         = "postgres"
  engine_version = "17"
  instance_class = "db.t3.medium"

  allocated_storage     = 50
  max_allocated_storage = 200
  storage_encrypted     = true

  db_name  = "ecosire"
  username = "app"
  password = var.db_password

  vpc_security_group_ids = [aws_security_group.db.id]
  db_subnet_group_name   = aws_db_subnet_group.main.name

  backup_retention_period = 7
  backup_window           = "03:00-04:00"
  maintenance_window      = "sun:04:00-sun:05:00"

  skip_final_snapshot = false
  final_snapshot_identifier = "${var.environment}-db-final"

  tags = {
    Environment = var.environment
  }
}

Módulos para infraestructura reutilizable

Creación de un módulo de aplicación web

# modules/web-app/main.tf
variable "name" {
  type = string
}

variable "environment" {
  type = string
}

variable "instance_type" {
  type    = string
  default = "t3.medium"
}

variable "vpc_id" {
  type = string
}

variable "subnet_ids" {
  type = list(string)
}

resource "aws_lb" "app" {
  name               = "${var.name}-${var.environment}-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = var.subnet_ids
}

resource "aws_lb_target_group" "app" {
  name     = "${var.name}-${var.environment}-tg"
  port     = 3000
  protocol = "HTTP"
  vpc_id   = var.vpc_id

  health_check {
    path                = "/health"
    healthy_threshold   = 2
    unhealthy_threshold = 3
    interval            = 30
  }
}

resource "aws_autoscaling_group" "app" {
  name                = "${var.name}-${var.environment}-asg"
  min_size            = 2
  max_size            = 10
  desired_capacity    = 2
  vpc_zone_identifier = var.subnet_ids
  target_group_arns   = [aws_lb_target_group.app.arn]

  launch_template {
    id      = aws_launch_template.app.id
    version = "$Latest"
  }

  tag {
    key                 = "Name"
    value               = "${var.name}-${var.environment}"
    propagate_at_launch = true
  }
}

output "alb_dns_name" {
  value = aws_lb.app.dns_name
}

Usando el módulo

# environments/production/main.tf
module "web" {
  source = "../../modules/web-app"

  name          = "ecosire-web"
  environment   = "production"
  instance_type = "t3.large"
  vpc_id        = module.network.vpc_id
  subnet_ids    = module.network.public_subnet_ids
}

module "api" {
  source = "../../modules/web-app"

  name          = "ecosire-api"
  environment   = "production"
  instance_type = "t3.large"
  vpc_id        = module.network.vpc_id
  subnet_ids    = module.network.public_subnet_ids
}

Gestión del Estado

Estado remoto con S3

# Bootstrap: create the state bucket and DynamoDB table manually or with a separate config
resource "aws_s3_bucket" "terraform_state" {
  bucket = "ecosire-terraform-state"

  lifecycle {
    prevent_destroy = true
  }
}

resource "aws_s3_bucket_versioning" "terraform_state" {
  bucket = aws_s3_bucket.terraform_state.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_dynamodb_table" "terraform_locks" {
  name         = "terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

El bloqueo de estado a través de DynamoDB evita que dos ingenieros ejecuten terraform apply simultáneamente, lo que podría dañar el estado.

Seguridad del archivo de estado

El archivo de estado de Terraform contiene información confidencial, incluidas contraseñas de bases de datos, claves API e ID de recursos. Protégelo:

  • Cifrar en reposo: control de versiones del depósito S3 + cifrado del lado del servidor
  • Cifrar en tránsito: HTTPS solo para acceso estatal
  • Restringir acceso: políticas de IAM que limitan quién puede leer/escribir el estado
  • Nunca comprometerse con Git: los archivos de estado nunca deben estar en control de versiones
  • Habilitar control de versiones: el control de versiones de S3 permite recuperarse de un estado corrupto

Integración CI/CD

Canalización Terraform de acciones de GitHub

name: Terraform
on:
  pull_request:
    paths: ['infrastructure/**']
  push:
    branches: [main]
    paths: ['infrastructure/**']

jobs:
  plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3

      - name: Terraform Init
        run: terraform init
        working-directory: infrastructure/environments/production

      - name: Terraform Plan
        run: terraform plan -out=tfplan
        working-directory: infrastructure/environments/production

      - name: Comment PR with plan
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const plan = require('fs').readFileSync('infrastructure/environments/production/tfplan.txt', 'utf8');
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## Terraform Plan\n\`\`\`\n${plan}\n\`\`\``
            });

  apply:
    needs: plan
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3

      - name: Terraform Apply
        run: terraform apply -auto-approve
        working-directory: infrastructure/environments/production

Estrategia multiambiente

Medio ambientePropósitoTamaños de instanciaObjetivo de costo
DesarrolloPruebas de funcionest3.micro / t3.pequeño<$100/mes
Puesta en escenaValidación de preproducciónProducción de espejos (más pequeños)~30% de la producción
ProducciónTráfico en vivoTamaño adecuado para cargaOptimizado

Utilice espacios de trabajo de Terraform o directorios separados por entorno:

infrastructure/
  modules/
    web-app/
    database/
    network/
  environments/
    development/
      main.tf
      terraform.tfvars
    staging/
      main.tf
      terraform.tfvars
    production/
      main.tf
      terraform.tfvars

Preguntas frecuentes

Terraform o Pulumi: ¿cuál deberíamos elegir?

Terraform si su equipo incluye ingenieros de operaciones que prefieren la configuración declarativa. Pulumi si su equipo tiene muchos desarrolladores y prefiere escribir infraestructura en TypeScript o Python. Terraform tiene un ecosistema más grande y más módulos comunitarios. Pulumi tiene una curva de aprendizaje inicial más pronunciada pero es más flexible para lógica compleja.

¿Cómo importamos la infraestructura existente a Terraform?

Utilice terraform import para poner los recursos existentes bajo la gestión de Terraform. Por ejemplo: CÓDIGO1. Después de importar, escriba la configuración correspondiente. Terraform 1.5+ admite bloques de importación en archivos de configuración para importaciones masivas.

¿Cómo manejamos los secretos en Terraform?

Nunca guarde secretos en archivos Terraform. Utilice terraform.tfvars (excluido de Git), variables de entorno (TF_VAR_db_password) o un administrador de secretos (AWS Secrets Manager, HashiCorp Vault). Marque las variables confidenciales con sensitive = true para evitar que aparezcan en la salida del plan.

¿Cuál es el costo de administrar Terraform?

Terraform en sí es gratuito y de código abierto. Terraform Cloud tiene un nivel gratuito para hasta 5 usuarios con estado remoto y planifica/solicita. El costo principal es la curva de aprendizaje (20 a 40 horas para un ingeniero experimentado) y el mantenimiento continuo (2 a 4 horas por mes). Esto se compensa con el tiempo ahorrado en la gestión manual de la infraestructura.


¿Qué viene después?

Terraform proporciona la base para la infraestructura automatizada. Combínelo con canalizaciones de CI/CD para implementación automatizada, monitoreo para visibilidad operativa y recuperación ante desastres para resiliencia.

Comuníquese con ECOSIRE para obtener consultoría sobre automatización de infraestructura, o explore nuestra Guía de DevOps para pequeñas empresas para obtener la hoja de ruta completa.


Publicado por ECOSIRE: ayuda a las empresas a automatizar la infraestructura de la nube.

E

Escrito por

ECOSIRE Research and Development Team

Construyendo productos digitales de nivel empresarial en ECOSIRE. Compartiendo perspectivas sobre integraciones Odoo, automatización de eCommerce y soluciones empresariales impulsadas por IA.

Chatea en whatsapp