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 = trueen 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 queprivate_subnet_idsincluya subnets en al menos 2 AZs diferentes - Error: «Cannot create encrypted DB instance without KMS key»
Solución: Especificakms_key_ido 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.
