Biblioteca / Terraform / IaC

Terraform Starter Pack - AWS v2.0

14 modulos Terraform listos para produccion: VPC EC2 RDS S3 IAM CloudWatch y pipeline CI/CD.

TerraformAWSIaCVPCRDSAuto ScalingCloudWatchGitHub Actions
TF + README · 28 paginas + 14 modulosNivel: IntermedioActualizado mayo 2026Descargar PDF

Capitulo 1

Introduccion a IaC con Terraform en AWS

Infrastructure as Code convierte la infraestructura en software versionable revisable y reproducible. Terraform es hoy el estandar de facto para gestionar infraestructura cloud de forma declarativa.

ClickOps vs Terraform

AspectoConsola AWS ClickOpsTerraform IaC
ReproducibilidadImposible cada entorno es diferenteIdentico en dev staging y produccion
Revision de cambiosNo hay historialPull request con diff completo
ColaboracionUn solo usuario a la vezMultiples ingenieros con control de versiones
AprovisionamientoHoras o diasMinutos con terraform apply
Deteccion de driftManualAutomatica con terraform plan
RollbackImposible o muy lentoterraform apply a version anterior

Estructura de proyecto recomendada

bash - estructura de directorios
infra/
├── environments/
│   ├── dev/
│   │   ├── main.tf        # llamadas a modulos para dev
│   │   ├── variables.tf   # valores especificos de dev
│   │   └── backend.tf     # backend S3 para dev
│   ├── staging/
│   └── prod/
├── modules/
│   ├── vpc/
│   ├── ec2/
│   ├── rds/
│   ├── s3/
│   ├── iam/
│   └── cloudwatch/
└── README.md
Convencion clave

Usa el mismo modulo en todos los entornos cambiando solo las variables. Nunca copies y pegues bloques de HCL entre entornos.

Capitulo 2

Backend remoto y gestion de estado

El estado de Terraform es el mapa entre tu codigo y los recursos reales en AWS. Sin backend remoto compartido no puedes trabajar en equipo.

Bootstrap del backend S3 + DynamoDB

bash - crear backend manualmente una sola vez
# S3 bucket para estado
aws s3api create-bucket --bucket tf-state-CUENTA-REGION --region us-east-1
aws s3api put-bucket-versioning \
  --bucket tf-state-CUENTA-REGION \
  --versioning-configuration Status=Enabled
aws s3api put-bucket-encryption \
  --bucket tf-state-CUENTA-REGION \
  --server-side-encryption-configuration \
  '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'

# DynamoDB para locking
aws dynamodb create-table \
  --table-name tf-state-lock \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST

Configuracion del backend en cada entorno

terraform - backend.tf
terraform {
  backend "s3" {
    bucket         = "tf-state-123456789-us-east-1"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "tf-state-lock"
  }
  required_providers {
    aws = { source = "hashicorp/aws"; version = "~> 5.0" }
  }
  required_version = ">= 1.6.0"
}
provider "aws" {
  region = var.aws_region
  default_tags {
    tags = {
      Environment = var.environment
      ManagedBy   = "terraform"
    }
  }
}

Capitulo 3

Modulo VPC - red base

La VPC es la red privada virtual de tu infraestructura. Un modulo bien disenado se reutiliza en todos los entornos sin modificacion.

Modulo VPC con tres capas

terraform - modules/vpc/main.tf
resource "aws_vpc" "this" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true
}

resource "aws_subnet" "public" {
  count             = length(var.availability_zones)
  vpc_id            = aws_vpc.this.id
  cidr_block        = cidrsubnet(var.vpc_cidr, 4, count.index)
  availability_zone = var.availability_zones[count.index]
  map_public_ip_on_launch = false
}

resource "aws_subnet" "private" {
  count             = length(var.availability_zones)
  vpc_id            = aws_vpc.this.id
  cidr_block        = cidrsubnet(var.vpc_cidr, 4, count.index + 4)
  availability_zone = var.availability_zones[count.index]
}

resource "aws_subnet" "data" {
  count             = length(var.availability_zones)
  vpc_id            = aws_vpc.this.id
  cidr_block        = cidrsubnet(var.vpc_cidr, 4, count.index + 8)
  availability_zone = var.availability_zones[count.index]
}

resource "aws_internet_gateway" "this" { vpc_id = aws_vpc.this.id }

resource "aws_nat_gateway" "this" {
  count         = length(var.availability_zones)
  allocation_id = aws_eip.nat[count.index].id
  subnet_id     = aws_subnet.public[count.index].id
  depends_on    = [aws_internet_gateway.this]
}

resource "aws_flow_log" "this" {
  vpc_id               = aws_vpc.this.id
  traffic_type         = "ALL"
  log_destination      = aws_s3_bucket.flow_logs.arn
  log_destination_type = "s3"
}

Capitulo 4

Modulos de computo EC2 y Auto Scaling

El modulo de computo combina Launch Template Auto Scaling Group y ALB para crear un servicio escalable y tolerante a fallos.

Launch Template con ASG y politica de escalado

terraform - ec2 con autoscaling
resource "aws_launch_template" "app" {
  name_prefix   = "${var.app_name}-"
  image_id      = var.ami_id
  instance_type = var.instance_type
  vpc_security_group_ids = [aws_security_group.app.id]
  iam_instance_profile { name = aws_iam_instance_profile.app.name }
  metadata_options {
    http_endpoint               = "enabled"
    http_tokens                 = "required"
    http_put_response_hop_limit = 1
  }
  monitoring { enabled = true }
  lifecycle { create_before_destroy = true }
}

resource "aws_autoscaling_group" "app" {
  name                = "${var.app_name}-asg"
  vpc_zone_identifier = var.private_subnet_ids
  target_group_arns   = [aws_lb_target_group.app.arn]
  health_check_type   = "ELB"
  min_size            = var.asg_min
  max_size            = var.asg_max
  desired_capacity    = var.asg_desired
  launch_template { id = aws_launch_template.app.id; version = "$Latest" }
  instance_refresh {
    strategy = "Rolling"
    preferences { min_healthy_percentage = 75 }
  }
}

resource "aws_autoscaling_policy" "cpu" {
  name                   = "cpu-tracking"
  autoscaling_group_name = aws_autoscaling_group.app.name
  policy_type            = "TargetTrackingScaling"
  target_tracking_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ASGAverageCPUUtilization"
    }
    target_value = 70.0
  }
}

Capitulo 5

Modulos de datos RDS y S3

Los datos son el activo mas critico. El modulo implementa Multi-AZ cifrado obligatorio y backups automatizados desde el primer deploy.

RDS Multi-AZ PostgreSQL con todas las protecciones

terraform - rds postgresql produccion
resource "aws_db_instance" "postgres" {
  identifier        = "${var.app_name}-${var.environment}"
  engine            = "postgres"
  engine_version    = "16.2"
  instance_class    = var.db_instance_class
  allocated_storage = var.db_storage_gb
  storage_type      = "gp3"
  db_name           = var.db_name
  username          = var.db_username
  multi_az               = true
  db_subnet_group_name   = aws_db_subnet_group.this.name
  vpc_security_group_ids = [aws_security_group.db.id]
  backup_retention_period = 30
  backup_window           = "03:00-04:00"
  storage_encrypted       = true
  kms_key_id              = var.kms_key_arn
  monitoring_interval     = 60
  monitoring_role_arn     = aws_iam_role.rds_monitoring.arn
  performance_insights_enabled = true
  enabled_cloudwatch_logs_exports = ["postgresql", "upgrade"]
  deletion_protection    = true
  skip_final_snapshot    = false
  final_snapshot_identifier = "${var.app_name}-final"
}

Capitulo 6

IAM seguridad y cumplimiento como codigo

Implementar seguridad como codigo garantiza que los controles se aplican en cada deploy no solo cuando alguien lo recuerda.

AWS Config y CloudTrail automatizados

terraform - reglas de cumplimiento y auditoria
resource "aws_config_config_rule" "root_mfa" {
  name = "root-account-mfa-enabled"
  source {
    owner             = "AWS"
    source_identifier = "ROOT_ACCOUNT_MFA_ENABLED"
  }
}

resource "aws_config_config_rule" "s3_public" {
  name = "s3-bucket-public-read-prohibited"
  source {
    owner             = "AWS"
    source_identifier = "S3_BUCKET_PUBLIC_READ_PROHIBITED"
  }
}

resource "aws_cloudtrail" "this" {
  name                          = "cloudtrail-all-regions"
  s3_bucket_name                = aws_s3_bucket.cloudtrail.id
  include_global_service_events = true
  is_multi_region_trail         = true
  enable_log_file_validation    = true
  kms_key_id                    = var.kms_key_arn
}

Capitulo 7

Observabilidad CloudWatch y alertas

La observabilidad no es opcional en produccion. Sin metricas y alertas los problemas se descubren cuando los usuarios los reportan.

Modulo de alarmas criticas reutilizable

terraform - alarmas cloudwatch
locals {
  alarms = {
    cpu_high = {
      metric    = "CPUUtilization"
      namespace = "AWS/EC2"
      threshold = 80
      description = "CPU mayor 80% en produccion"
    }
    rds_connections = {
      metric    = "DatabaseConnections"
      namespace = "AWS/RDS"
      threshold = 80
      description = "Conexiones RDS mayor 80% del maximo"
    }
    alb_5xx = {
      metric    = "HTTPCode_Target_5XX_Count"
      namespace = "AWS/ApplicationELB"
      threshold = 10
      description = "Errores 5xx mayor 10 en 5 minutos"
    }
    alb_latency = {
      metric    = "TargetResponseTime"
      namespace = "AWS/ApplicationELB"
      threshold = 2
      description = "Latencia P99 mayor 2 segundos"
    }
  }
}

resource "aws_cloudwatch_metric_alarm" "this" {
  for_each            = local.alarms
  alarm_name          = "${var.app_name}-${each.key}"
  alarm_description   = each.value.description
  metric_name         = each.value.metric
  namespace           = each.value.namespace
  statistic           = "Average"
  period              = 300
  evaluation_periods  = 2
  threshold           = each.value.threshold
  comparison_operator = "GreaterThanThreshold"
  treat_missing_data  = "notBreaching"
  alarm_actions       = [aws_sns_topic.alerts.arn]
  ok_actions          = [aws_sns_topic.alerts.arn]
}

Capitulo 8

CI/CD para Terraform

Automatizar el ciclo de validacion y aplicacion de Terraform elimina errores humanos y garantiza que los cambios pasen por revision.

Pipeline GitHub Actions completo

yaml - .github/workflows/terraform.yml
name: Terraform CI/CD
on:
  pull_request:
    branches: [main]
    paths: ['infra/**']
  push:
    branches: [main]
    paths: ['infra/**']

env:
  TF_VERSION: '1.7.0'
  AWS_REGION: 'us-east-1'

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
        with: { terraform_version: '${{ env.TF_VERSION }}' }
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}
      - run: terraform init
        working-directory: infra/environments/prod
      - run: terraform validate
      - run: terraform fmt -check -recursive

  plan:
    needs: validate
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - run: terraform plan -out=tfplan

  apply:
    needs: plan
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - run: terraform apply -auto-approve tfplan
Siguiente paso

Con estos 14 modulos y el pipeline CI/CD tendras infraestructura reproducible revisada y auditada. El siguiente nivel es Terragrunt para gestionar multiples entornos de forma mas eficiente.