Terraform AWS RDS es la solución más eficiente para gestionar bases de datos relacionales en la nube mediante infraestructura como código. En esta guía completa, aprenderás a crear instancias RDS automatizadas de manera declarativa, configurar alta disponibilidad con Multi-AZ, y mantener backups automáticos de tus datos críticos usando Terraform.

¿Qué es Terraform AWS RDS?

Terraform AWS RDS permite provisionar y gestionar instancias de Amazon Relational Database Service mediante código declarativo. RDS es un servicio gestionado de AWS que soporta múltiples motores de bases de datos como MySQL, PostgreSQL, MariaDB, Oracle y SQL Server, eliminando tareas operativas como parches, backups y escalado.

Al combinar Terraform con RDS, obtienes los beneficios de infraestructura como código: versionado de configuración, despliegues reproducibles, y automatización completa del ciclo de vida de tus bases de datos. Esto es fundamental para equipos DevOps que buscan eliminar configuraciones manuales propensas a errores.

Ventajas de Usar Terraform AWS RDS

  • Automatización completa: Provisiona bases de datos en minutos sin acceso a la consola de AWS
  • Configuración declarativa: Define el estado deseado y Terraform se encarga del resto
  • Versionado: Mantén historial completo de cambios en tu repositorio Git
  • Multi-entorno: Replica configuraciones entre dev, staging y producción fácilmente
  • Gestión de secretos: Integración nativa con AWS Secrets Manager y Terraform variables sensibles
  • Alta disponibilidad: Configura Multi-AZ con una sola línea de código
  • Backups automáticos: Define políticas de retención y ventanas de backup mediante código

Si trabajas con contenedores y orquestación, te recomiendo revisar los tutoriales de Docker Compose para entender cómo conectar aplicaciones contenerizadas con bases de datos RDS provisionadas por Terraform.

Requisitos Previos para Terraform AWS RDS

Antes de comenzar, asegúrate de tener:

  • Terraform 1.0 o superior instalado en tu sistema
  • Cuenta AWS activa con permisos para crear recursos RDS, VPC y Security Groups
  • AWS CLI configurado con credenciales (aws configure)
  • Conocimientos básicos de SQL y administración de bases de datos
  • VPC existente con al menos dos subnets en diferentes zonas de disponibilidad (para Multi-AZ)

Verifica tu instalación de Terraform ejecutando:

terraform version
aws sts get-caller-identity

Configuración Inicial de Terraform AWS RDS

El primer paso para trabajar con Terraform AWS RDS es configurar el provider de AWS y definir las variables básicas. Crea un directorio para tu proyecto:

mkdir terraform-rds-project
cd terraform-rds-project

Crea el archivo provider.tf con la configuración del provider de AWS:

terraform {
  required_version = ">= 1.0"
  
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
  
  default_tags {
    tags = {
      Environment = var.environment
      ManagedBy   = "Terraform"
      Project     = "RDS-Infrastructure"
    }
  }
}

La configuración del provider de AWS establece la región y etiquetas por defecto que se aplicarán a todos los recursos creados.

Crear Instancia Terraform AWS RDS con MySQL

Vamos a crear una instancia RDS de MySQL completa con todas las mejores prácticas de seguridad y alta disponibilidad. Primero, define las variables en variables.tf:

variable "aws_region" {
  description = "Región de AWS donde se desplegará RDS"
  type        = string
  default     = "us-east-1"
}

variable "environment" {
  description = "Entorno de despliegue"
  type        = string
  default     = "production"
}

variable "db_name" {
  description = "Nombre de la base de datos inicial"
  type        = string
  default     = "myappdb"
}

variable "db_username" {
  description = "Usuario maestro de la base de datos"
  type        = string
  default     = "admin"
  sensitive   = true
}

variable "db_password" {
  description = "Contraseña del usuario maestro"
  type        = string
  sensitive   = true
}

variable "vpc_id" {
  description = "ID de la VPC donde se creará RDS"
  type        = string
}

variable "private_subnet_ids" {
  description = "IDs de subnets privadas para RDS (mínimo 2 AZs)"
  type        = list(string)
}

variable "instance_class" {
  description = "Clase de instancia RDS"
  type        = string
  default     = "db.t3.micro"
}

Ahora crea el archivo main.tf con la configuración completa de Terraform AWS RDS:

# Security Group para RDS
resource "aws_security_group" "rds" {
  name_description = "Security group for RDS MySQL instance"
  vpc_id      = var.vpc_id

  ingress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"] # Ajusta según tu VPC CIDR
    description = "MySQL access from VPC"
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
    description = "Allow all outbound traffic"
  }

  tags = {
    Name = "${var.environment}-rds-sg"
  }
}

# DB Subnet Group
resource "aws_db_subnet_group" "rds" {
  name       = "${var.environment}-rds-subnet-group"
  subnet_ids = var.private_subnet_ids

  tags = {
    Name = "${var.environment}-rds-subnet-group"
  }
}

# DB Parameter Group
resource "aws_db_parameter_group" "rds" {
  name   = "${var.environment}-mysql8-params"
  family = "mysql8.0"

  parameter {
    name  = "character_set_server"
    value = "utf8mb4"
  }

  parameter {
    name  = "collation_server"
    value = "utf8mb4_unicode_ci"
  }

  parameter {
    name  = "max_connections"
    value = "200"
  }

  tags = {
    Name = "${var.environment}-mysql-params"
  }
}

# RDS Instance
resource "aws_db_instance" "mysql" {
  identifier = "${var.environment}-mysql-rds"

  # Engine configuration
  engine         = "mysql"
  engine_version = "8.0.35"
  instance_class = var.instance_class

  # Database configuration
  db_name  = var.db_name
  username = var.db_username
  password = var.db_password

  # Storage configuration
  allocated_storage     = 20
  max_allocated_storage = 100
  storage_type          = "gp3"
  storage_encrypted     = true

  # High availability
  multi_az               = true
  db_subnet_group_name   = aws_db_subnet_group.rds.name
  vpc_security_group_ids = [aws_security_group.rds.id]

  # Backup configuration
  backup_retention_period = 7
  backup_window           = "03:00-04:00"
  maintenance_window      = "mon:04:00-mon:05:00"

  # Snapshot configuration
  skip_final_snapshot       = false
  final_snapshot_identifier = "${var.environment}-mysql-final-snapshot"

  # Monitoring
  enabled_cloudwatch_logs_exports = ["error", "general", "slowquery"]
  performance_insights_enabled    = true
  monitoring_interval             = 60

  # Security
  deletion_protection = true
  publicly_accessible = false

  # Parameter group
  parameter_group_name = aws_db_parameter_group.rds.name

  tags = {
    Name = "${var.environment}-mysql-rds"
  }
}

Esta configuración implementa todas las mejores prácticas recomendadas por HashiCorp Developer para entornos de producción.

Configuración de Outputs para Terraform AWS RDS

Los outputs permiten exportar información crítica de tu instancia RDS para usar en otros módulos o aplicaciones. Crea el archivo outputs.tf:

output "rds_endpoint" {
  description = "Endpoint de conexión de RDS"
  value       = aws_db_instance.mysql.endpoint
}

output "rds_arn" {
  description = "ARN de la instancia RDS"
  value       = aws_db_instance.mysql.arn
}

output "rds_id" {
  description = "ID de la instancia RDS"
  value       = aws_db_instance.mysql.id
}

output "rds_port" {
  description = "Puerto de la base de datos"
  value       = aws_db_instance.mysql.port
}

output "security_group_id" {
  description = "ID del security group de RDS"
  value       = aws_security_group.rds.id
}

Estos outputs son especialmente útiles cuando integras RDS con aplicaciones desplegadas mediante Docker Compose o Kubernetes, permitiendo inyectar dinámicamente las credenciales de conexión.

Desplegar Terraform AWS RDS Paso a Paso

Una vez creados todos los archivos de configuración, sigue estos pasos para desplegar tu instancia Terraform AWS RDS:

1. Inicializa el proyecto de Terraform:

terraform init

Este comando descarga el provider de AWS y prepara el entorno.

2. Crea un archivo terraform.tfvars con tus valores:

aws_region         = "us-east-1"
environment        = "production"
vpc_id             = "vpc-0123456789abcdef"
private_subnet_ids = ["subnet-abc123", "subnet-def456"]
db_password        = "TuPasswordSegura123!"
instance_class     = "db.t3.micro"

IMPORTANTE: Nunca commits el archivo terraform.tfvars a Git si contiene contraseñas. Usa variables de entorno o HashiCorp Vault para secretos en producción.

3. Valida la configuración:

terraform validate

4. Previsualiza los cambios:

terraform plan

Terraform te mostrará exactamente qué recursos se crearán antes de aplicar cambios.

5. Aplica la configuración:

terraform apply

Confirma con yes cuando se te solicite. El proceso toma aproximadamente 10-15 minutos para provisionar una instancia RDS con Multi-AZ.

6. Verifica los outputs:

terraform output

Obtendrás el endpoint de conexión que puedes usar en tus aplicaciones.

Crear Réplicas de Lectura con Terraform AWS RDS

Las réplicas de lectura mejoran el rendimiento distribuyendo las consultas SELECT. Para crear una réplica con Terraform AWS RDS, agrega este recurso:

resource "aws_db_instance" "mysql_replica" {
  identifier             = "${var.environment}-mysql-replica"
  replicate_source_db    = aws_db_instance.mysql.identifier
  instance_class         = var.instance_class
  publicly_accessible    = false
  skip_final_snapshot    = true
  
  # La réplica hereda configuración de la instancia principal
  auto_minor_version_upgrade = true
  
  tags = {
    Name = "${var.environment}-mysql-read-replica"
    Role = "read-replica"
  }
}

Las réplicas son especialmente útiles para aplicaciones con alta carga de lectura, como dashboards de monitoreo construidos con herramientas de la stack de Docker Compose.

Usar Módulo Terraform AWS RDS Oficial

En lugar de gestionar recursos individuales, puedes usar el módulo oficial terraform-aws-modules/rds que abstrae la complejidad:

module "db" {
  source  = "terraform-aws-modules/rds/aws"
  version = "~> 7.0"

  identifier = "${var.environment}-mysql"

  engine            = "mysql"
  engine_version    = "8.0"
  instance_class    = "db.t3.micro"
  allocated_storage = 20

  db_name  = var.db_name
  username = var.db_username
  password = var.db_password
  port     = 3306

  vpc_security_group_ids = [aws_security_group.rds.id]
  db_subnet_group_name   = aws_db_subnet_group.rds.name

  # Multi-AZ
  multi_az = true

  # Backups
  backup_retention_period = 7
  backup_window           = "03:00-04:00"
  maintenance_window      = "mon:04:00-mon:05:00"

  # Enhanced Monitoring
  enabled_cloudwatch_logs_exports = ["error", "general", "slowquery"]
  create_monitoring_role          = true
  monitoring_interval             = 60

  # Security
  deletion_protection = true
  storage_encrypted   = true

  family = "mysql8.0"

  parameters = [
    {
      name  = "character_set_server"
      value = "utf8mb4"
    },
    {
      name  = "max_connections"
      value = "200"
    }
  ]

  tags = {
    Environment = var.environment
  }
}

Este módulo actualizado en 2026 incluye soporte para blue-green deployments y configuraciones avanzadas de PostgreSQL, MySQL y Aurora según la documentación oficial en GitHub.

Best Practices de Seguridad para Terraform AWS RDS

Implementar seguridad robusta es crítico al trabajar con Terraform AWS RDS. Aquí están las mejores prácticas:

1. Cifrado en Reposo y Tránsito

resource "aws_db_instance" "mysql" {
  # ... otras configuraciones
  
  storage_encrypted = true
  kms_key_id        = aws_kms_key.rds.arn
  
  # Forzar SSL/TLS
  parameter_group_name = aws_db_parameter_group.ssl_required.name
}

resource "aws_db_parameter_group" "ssl_required" {
  name   = "mysql-ssl-required"
  family = "mysql8.0"

  parameter {
    name  = "require_secure_transport"
    value = "1"
  }
}

2. Gestión de Contraseñas con AWS Secrets Manager

resource "aws_secretsmanager_secret" "rds_password" {
  name = "${var.environment}/rds/master-password"
  
  recovery_window_in_days = 7
}

resource "aws_secretsmanager_secret_version" "rds_password" {
  secret_id     = aws_secretsmanager_secret.rds_password.id
  secret_string = var.db_password
}

resource "aws_db_instance" "mysql" {
  # ... otras configuraciones
  
  password = aws_secretsmanager_secret_version.rds_password.secret_string
}

3. Network Isolation

  • Nunca configures publicly_accessible = true en producción
  • Usa subnets privadas sin rutas a Internet Gateway
  • Limita Security Groups solo a IPs/rangos específicos
  • Implementa VPC endpoints para acceso desde servicios AWS

4. Deletion Protection y Backups

resource "aws_db_instance" "mysql" {
  # ... otras configuraciones
  
  deletion_protection     = true
  skip_final_snapshot     = false
  final_snapshot_identifier = "${var.environment}-final-${formatdate("YYYY-MM-DD-hhmm", timestamp())}"
  
  backup_retention_period = 35  # Máximo permitido
  copy_tags_to_snapshot   = true
}

Para más información sobre seguridad en infraestructura, revisa nuestros artículos sobre hardening de contenedores Docker.

Monitoreo y Troubleshooting de Terraform AWS RDS

El monitoreo proactivo previene problemas de rendimiento y disponibilidad. Configura CloudWatch Alarms para tu instancia Terraform AWS RDS:

resource "aws_cloudwatch_metric_alarm" "database_cpu" {
  alarm_name          = "${var.environment}-rds-cpu-utilization"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2
  metric_name         = "CPUUtilization"
  namespace           = "AWS/RDS"
  period              = 300
  statistic           = "Average"
  threshold           = 80
  alarm_description   = "RDS CPU utilization is too high"
  
  dimensions = {
    DBInstanceIdentifier = aws_db_instance.mysql.id
  }
}

resource "aws_cloudwatch_metric_alarm" "database_storage" {
  alarm_name          = "${var.environment}-rds-free-storage"
  comparison_operator = "LessThanThreshold"
  evaluation_periods  = 1
  metric_name         = "FreeStorageSpace"
  namespace           = "AWS/RDS"
  period              = 300
  statistic           = "Average"
  threshold           = 5000000000  # 5GB en bytes
  alarm_description   = "RDS free storage is low"
  
  dimensions = {
    DBInstanceIdentifier = aws_db_instance.mysql.id
  }
}

Errores comunes y soluciones:

  • Error: «DB Subnet Group doesn’t meet availability zone coverage requirement»
    Solución: Asegúrate de que private_subnet_ids incluya subnets en al menos 2 AZs diferentes
  • Error: «Cannot create encrypted DB instance without KMS key»
    Solución: Especifica kms_key_id o usa la clave AWS-managed por defecto
  • Performance Insights no se activa
    Solución: Verifica que la instancia clase soporte Performance Insights (db.t3.micro o superior)

Habilita logs detallados para troubleshooting:

export TF_LOG=DEBUG
terraform apply

Migrar Bases de Datos Existentes a Terraform AWS RDS

Si ya tienes instancias RDS creadas manualmente, puedes importarlas a Terraform usando el comando terraform import:

# 1. Crea el recurso vacío en tu configuración
resource "aws_db_instance" "mysql" {
  # Configuración completa aquí
}

# 2. Importa la instancia existente
terraform import aws_db_instance.mysql mi-instancia-rds-existente

# 3. Sincroniza el estado
terraform plan

Terraform mostrará las diferencias entre tu código y la configuración actual. Ajusta el código hasta que terraform plan no muestre cambios.

Conclusión

Terraform AWS RDS transforma la gestión de bases de datos en la nube de un proceso manual propenso a errores a un flujo de trabajo automatizado, versionado y reproducible. Hemos cubierto desde la configuración básica hasta técnicas avanzadas como réplicas de lectura, cifrado, y monitoreo con CloudWatch.

Los beneficios clave son claros: despliegues consistentes entre entornos, reducción de errores humanos, y trazabilidad completa de cambios mediante Git. Al implementar las mejores prácticas de seguridad y alta disponibilidad que discutimos, tendrás bases de datos RDS listas para producción que cumplen con estándares empresariales.

Como próximos pasos, considera explorar Aurora Serverless con Terraform para workloads variables, o implementar estrategias de blue-green deployment para actualizaciones sin downtime. También te recomiendo integrar RDS con pipelines CI/CD usando Terraform Cloud para automatización completa.

Preguntas Frecuentes sobre Terraform AWS RDS

¿Cuánto cuesta usar Terraform AWS RDS?

Terraform es gratuito y open-source. Solo pagas por los recursos AWS que creas. Una instancia db.t3.micro con Multi-AZ cuesta aproximadamente $30-40/mes en us-east-1. El almacenamiento gp3 cuesta $0.115/GB-mes. Usa la calculadora de AWS para estimaciones precisas según tu configuración.

¿Puedo migrar de CloudFormation a Terraform AWS RDS?

Sí, usando terraform import puedes importar recursos RDS existentes creados con CloudFormation, Ansible o manualmente. El proceso implica definir el recurso en Terraform, importar el estado actual, y ajustar la configuración hasta que coincida con la infraestructura existente. No hay downtime durante la migración.

¿Cómo gestiono actualizaciones de versiones del motor con Terraform AWS RDS?

Modifica el parámetro engine_version en tu configuración y ejecuta terraform apply. Por defecto, AWS aplica la actualización durante la ventana de mantenimiento (maintenance_window). Para aplicar inmediatamente, usa apply_immediately = true, aunque esto causará reinicio de la instancia y breve downtime.

¿Es seguro almacenar contraseñas en archivos Terraform?

No, nunca almacenes contraseñas en archivos .tf o terraform.tfvars versionados. Usa variables de entorno (TF_VAR_db_password), AWS Secrets Manager, HashiCorp Vault, o la integración nativa de Terraform con proveedores de secretos. Marca variables como sensitive = true para evitar que aparezcan en logs.

¿Puedo usar Terraform AWS RDS con PostgreSQL o Aurora?

Absolutamente. Terraform soporta todos los motores RDS: MySQL, PostgreSQL, MariaDB, Oracle, SQL Server y Aurora (MySQL/PostgreSQL compatible). Para Aurora, usa el recurso aws_rds_cluster en lugar de aws_db_instance. El módulo oficial terraform-aws-modules/rds incluye ejemplos completos para cada motor.

Avatar

Por Mid

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x