Desplegar bases de datos en la nube exige tener muy en cuenta la seguridad, la escalabilidad y la facilidad de gestión. Una mala configuración o un setup poco óptimo puede traducirse en grandes dolores de cabeza técnicos, deuda técnica y, en el peor de los casos, un impacto serio al negocio si se produce una caída o si la base de datos no rinde. Amazon Aurora MySQL ofrece un servicio de base de datos relacional altamente escalable y seguro.
En este blog vemos cómo automatizar el despliegue de un clúster de Amazon Aurora MySQL con Terraform, con foco en armar una configuración de alta disponibilidad con varias instancias de lectura para escalar las consultas.
Requisitos previos:
- Una cuenta de AWS
- Terraform instalado en tu máquina
- Conocimientos de los servicios de AWS y de Terraform
- Código de Terraform desde el repositorio de Github
Estructura del proyecto: nuestro proyecto en Terraform se organiza en módulos para mayor claridad y reutilización. Los módulos clave son:
- Módulo KMS: gestiona las claves de cifrado de la base de datos.
- Módulo del clúster Aurora: se encarga del despliegue y la configuración del clúster Aurora MySQL.
Resumen de la estructura modular de directorios
Esta estructura de directorios está pensada para organizar y gestionar el código de Terraform de forma eficiente al desplegar un clúster de Amazon Aurora MySQL con cifrado gestionado por AWS KMS.
Directorio raíz
Incluye main.tf, providers.tf, terraform.tfvars, variables.tf y outputs.tf.
main.tf: contiene la configuración principal donde se invocan los módulos.providers.tf: define la configuración del proveedor y los requisitos de versión.variables.tf: declara las variables que se usan en las distintas configuraciones.terraform.tfvars: establece valores que sobrescriben las variables definidas en otros archivos.outputs.tf: define las salidas de la configuración de Terraform.
Directorio de módulos
Contiene un subdirectorio por cada módulo del proyecto.
Módulo KMS: se encarga de crear y gestionar las claves de AWS KMS para cifrar los datos en reposo.
main.tf: contiene los recursos para crear las claves KMS.variables.tf: define las variables de entrada propias de KMS.outputs.tf: expone los atributos de salida de los recursos KMS.
Módulo del clúster Aurora: gestiona el despliegue del clúster Aurora MySQL.
main.tf: configura el clúster Aurora MySQL y los recursos asociados.variables.tf: lista las variables de entrada propias del clúster Aurora MySQL.outputs.tf: expone atributos como el endpoint de la base de datos.
Con esta estructura se logra un código limpio y ordenado, y se mejora la reutilización y el mantenimiento del código de Terraform, lo que facilita administrar los recursos en la nube de forma efectiva.
1\. Configuración del módulo KMS
El cifrado en reposo es clave para proteger los datos. El clúster Aurora MySQL usa AWS KMS para la gestión de claves; en concreto, AWS Customer Managed Key (CMK), donde tú creas, administras y eres dueño de la clave que cifra tu clúster Aurora. Gestionar tu propia clave KMS para el cifrado del clúster Aurora ofrece varias ventajas frente a usar una clave KMS gestionada por AWS: las CMK habilitan políticas de control de acceso granulares, e incluyen la posibilidad de definir quién puede usarlas y administrarlas; cada uso de una CMK queda registrado en CloudTrail con fines de auditoría —algo crucial para el cumplimiento normativo—, además del control geográfico, que te permite restringir el uso de la clave a regiones específicas de AWS. Los cargos por usar CMK —facturados por almacenamiento y uso de API— también son más predecibles y transparentes, lo que ayuda a presupuestar y gestionar costos en comparación con las claves gestionadas por AWS.
El módulo KMS se ocupa de crear y administrar estas claves; el archivo outputs.tf del módulo expone el nombre de la clave KMS que utilizará el módulo de Aurora.
# KMS Module - variables.tf
variable "rds" {
description = "Enable customer managed KMS key for RDS"
default = true
type = bool
}
# KMS Module - main.tf
resource "aws_kms_key" "rds" {
description = "KMS key for RDS"
enable_key_rotation = true
deletion_window_in_days = 30
}
Explicación:
- Rotación de claves: la rotación automática refuerza la seguridad al cambiar de forma periódica la clave de cifrado subyacente.
- Ventana de eliminación: indica el plazo previo a que una clave eliminada se destruya de forma irreversible, lo que permite recuperarla si fuera necesario.
2\. Configuración del módulo del clúster Aurora
El módulo del clúster Aurora es el corazón de nuestro despliegue. Configura la base de datos con parámetros de rendimiento y disponibilidad. Permite ajustar opciones que van desde el motor de base de datos a desplegar hasta la VPC y los Security Groups existentes con los que va a operar, e incluye opciones como evitar la eliminación accidental del clúster mediante Terraform —a menos que se quite explícitamente la cláusula prevent_destroy = true del bloque lifecycle del módulo:
# Aurora Cluster Module - variables.tf
variable "read_replica_count" {
description = "Number of Read Replicas in addition to Writer instance"
type = number
}
# Aurora MySQL Cluster config
resource "aws_rds_cluster" "aurora_mysql_cluster" {
cluster_identifier = var.name
engine = var.engine
engine_mode = var.engine_mode
engine_version = var.aurora_mysql_cluster_engine_version
database_name = var.database_name
master_username = var.aurora_mysql_cluster_master_username
# Create and store password in Secrets Manager
manage_master_user_password = true
final_snapshot_identifier = "${var.name}-snapshot"
skip_final_snapshot = var.skip_final_snapshot
deletion_protection = var.deletion_protection
backup_retention_period = var.backup_retention_period
preferred_backup_window = var.backup_window
preferred_maintenance_window = var.maintenance_window
port = var.port
db_subnet_group_name = aws_db_subnet_group.db_subnet_group.name
vpc_security_group_ids = concat(var.security_group_ids, [aws_security_group.aurora_mysql_sg.id])
apply_immediately = true
iam_database_authentication_enabled = false
copy_tags_to_snapshot = true
storage_encrypted = true
kms_key_id = var.kms_key_id
db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.cluster_param_group.name
enabled_cloudwatch_logs_exports = var.engine_mode == "serverless" ? [] : var.enabled_cloudwatch_logs_exports
tags = merge(var.tags, { "Name" = var.name })
lifecycle {
ignore_changes = [ engine_version, scaling_configuration, engine_mode ]
prevent_destroy = true
}
}
# Aurora MySQL Instances within Cluster - one Writer and "read_replica_count" Readers
resource "aws_rds_cluster_instance" "aurora_mysql_instance" {
count = var.engine_mode == "serverless" ? 0 : (1 + var.read_replica_count)
identifier = "${var.name}-${count.index}"
cluster_identifier = aws_rds_cluster.aurora_mysql_cluster.id
engine = var.engine
engine_version = var.aurora_mysql_cluster_engine_version
instance_class = var.instance_type
db_subnet_group_name = aws_db_subnet_group.db_subnet_group.name
db_parameter_group_name = aws_db_parameter_group.db_param_group.name
monitoring_role_arn = var.create_monitoring_role && var.monitoring_interval > 0 ? aws_iam_role.rds_enhanced_monitoring[0].arn : null
monitoring_interval = var.create_monitoring_role && var.monitoring_interval > 0 ? var.monitoring_interval : null
auto_minor_version_upgrade = true
performance_insights_enabled = true
tags = var.tags
lifecycle {
ignore_changes = [ engine_version ]
}
}
Parámetros de configuración importantes (defínelos en terraform.tfvars):
- Identificador del clúster: identificador único del clúster Aurora; clave para su gestión.
- Configuración del motor: define el motor de base de datos y la versión, garantizando compatibilidad y disponibilidad de funciones. Puede ser Aurora MySQL 5.7.x o MySQL 8.0.x, aunque hoy se recomienda usar 8.0.x, ya que AWS dejó de mantener la 5.7.x y solo ofrece soporte extendido (de pago).
- Cantidad de instancias: controla el número de instancias de lectura que se crean junto con la de escritura, lo que facilita el escalado de lectura.
- Seguridad y red: asocia el clúster a una configuración específica de VPC y Security Group, garantizando que opere dentro de un entorno de red seguro y aislado. Vas a usar los IDs de subred y demás valores asociados de una VPC existente donde quieras colocar tu nuevo clúster Aurora MySQL.
- Gestión de credenciales: se apoya en Secrets Manager para almacenar el usuario y la contraseña de la base de datos, siguiendo las mejores prácticas para el manejo de credenciales.
3\. Salidas y gestión
Las salidas son fundamentales para obtener los datos de conexión y administrar el clúster después del despliegue, así como para pasar valores en tiempo de ejecución entre módulos cuando haga falta.
# Outputs - outputs.tf
output "aurora_cluster_endpoint" {
description = "The endpoint at which the Aurora cluster is accessible"
value = aws_rds_cluster.aurora.endpoint
}
# Outputs - outputs.tf
output "aurora_cluster_reader_endpoint" {
description = "The reader endpoint for the Aurora cluster"
value = aws_rds_cluster.aurora.reader_endpoint
}
4\. Conclusión
Usar Terraform para desplegar clústeres de Amazon Aurora MySQL simplifica el proceso y asegura consistencia y repetibilidad entre entornos. Al apoyarte en módulos para las claves de cifrado de cliente de KMS y para la configuración fina del clúster Aurora, el setup se mantiene modular y fácil de ajustar. Esta solución aprovecha las nuevas capacidades integradas de AWS para crear y almacenar tu contraseña maestra de MySQL de forma nativa en Secrets Manager. Este enfoque se alinea con las mejores prácticas de arquitectura cloud, incluidas la seguridad, la escalabilidad y la recuperación ante desastres. Ya sea para escalar instancias de lectura ante más carga o para gestionar claves de cifrado de forma segura, Terraform ofrece una solución sólida para administrar configuraciones de clústeres Aurora MySQL en AWS, desde las más simples hasta las más complejas, y para todo tipo de casos de uso.
¿Te quedan dudas sobre cómo aplicar estas recomendaciones para desplegar un clúster Aurora MySQL ajustado a tu caso de uso en tu entorno de AWS con Terraform?
Contáctanos en DoiT International. Contamos exclusivamente con talento sénior de Engineering y nos especializamos en consultoría cloud avanzada para diseño de arquitectura, asesoría en debugging y servicios de consultoría.