Base de Datos Relacional Python
Este generador crea un nuevo proyecto de base de datos relacional Python respaldado por Amazon Aurora (PostgreSQL o MySQL), SQLModel para el modelado de datos, y Alembic para las migraciones de esquema. Genera el código de aplicación y la infraestructura necesarios para aprovisionar y administrar una base de datos usando AWS CDK o Terraform, con definición de esquema declarativa, despliegue automático de migraciones y un cliente de base de datos.
Generar una Base de Datos Relacional
Sección titulada «Generar una Base de Datos Relacional»- Instale el Nx Console VSCode Plugin si aún no lo ha hecho
- Abra la consola Nx en VSCode
- Haga clic en
Generate (UI)en la sección "Common Nx Commands" - Busque
@aws/nx-plugin - py#rdb - Complete los parámetros requeridos
- Haga clic en
Generate
pnpm nx g @aws/nx-plugin:py#rdbyarn nx g @aws/nx-plugin:py#rdbnpx nx g @aws/nx-plugin:py#rdbbunx nx g @aws/nx-plugin:py#rdbTambién puede realizar una ejecución en seco para ver qué archivos se cambiarían
pnpm nx g @aws/nx-plugin:py#rdb --dry-runyarn nx g @aws/nx-plugin:py#rdb --dry-runnpx nx g @aws/nx-plugin:py#rdb --dry-runbunx nx g @aws/nx-plugin:py#rdb --dry-runOpciones
Sección titulada «Opciones»| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
| name Requerido | string | - | Nombre del proyecto de base de datos a generar |
| directory | string | packages | El directorio donde almacenar la aplicación. |
| subDirectory | string | - | El subdirectorio donde se coloca el proyecto. Por defecto es el nombre del proyecto. |
| infra | aurora | none | aurora | Servicio de base de datos relacional a aprovisionar. |
| engine | postgres | mysql | postgres | Motor de base de datos a utilizar con el servicio seleccionado. |
| databaseUser | string | dbadmin | Nombre de usuario administrador de la base de datos. Por defecto es 'dbadmin'. |
| databaseName | string | - | Nombre inicial de la base de datos. Por defecto es el nombre del proyecto. |
| framework | sqlmodel | sqlmodel | Framework ORM a utilizar para el proyecto generado. |
| iac | inherit | cdk | terraform | inherit | El proveedor IaC preferido. Por defecto se hereda de tu selección inicial. |
| preferInstallDependencies | boolean | true | Si se prefiere instalar las dependencias después de que se ejecute el generador. Establecer en false para diferir la instalación al agrupar múltiples generadores (la instalación aún se ejecuta si es necesaria para que los generadores subsiguientes puedan calcular el grafo del proyecto); instalar una vez al final. |
Salida del Generador
Sección titulada «Salida del Generador»El generador crea la siguiente estructura de proyecto en el directorio <directory>/<name>:
Directorio<name>
- __init__.py Exportaciones del paquete (
get_engine,session_context) - connection.py Motor de base de datos y fábrica de sesiones con autenticación IAM
- utils.py Configuración de tiempo de ejecución y ayudantes de desarrollo local
- migration_handler.py Manejador Lambda que ejecuta migraciones Alembic durante el despliegue
- create_db_user_handler.py Manejador Lambda que crea el usuario de base de datos de la aplicación durante el despliegue
Directoriomodels
- example.py Definición de tabla SQLModel de ejemplo
- __init__.py Exportaciones del paquete (
Directoriomigrations
- versions Scripts de migración generados por Alembic
- env.py Entorno Alembic (se conecta a la base de datos)
- script.py.mako Plantilla de script de migración Alembic
- alembic.ini Configuración de Alembic
- config.json Detalles de conexión de desarrollo local y clave de configuración de tiempo de ejecución
- Dockerfile.migration Imagen de contenedor para el manejador de migración
- Dockerfile.create-db-user Imagen de contenedor para el manejador create-db-user
- project.json Configuración del proyecto y objetivos de compilación
Los scripts de desarrollo local se comparten entre todos los proyectos de base de datos y se generan en packages/common/scripts/:
Directoriopackages/common/scripts/src/rdb
- pull-image.ts Descarga la imagen de contenedor de la base de datos
- start-container.ts Inicia un contenedor de base de datos local
- wait-for-postgres-db.ts Espera a que la base de datos local esté lista (PostgreSQL)
- wait-for-mysql-db.ts Espera a que la base de datos local esté lista (MySQL)
Infraestructura
Sección titulada «Infraestructura»Dado que este generador proporciona infraestructura como código basada en tu proveedor de iacProvider seleccionado, creará un proyecto en packages/common que incluye los constructos CDK o módulos de Terraform correspondientes.
El proyecto común de infraestructura como código tiene la siguiente estructura:
Directoriopackages/common/constructs
Directoriosrc
Directorioapp/ Constructos para infraestructura específica de un proyecto/generador
- …
Directoriocore/ Constructos genéricos reutilizados por los constructos en
app- …
- index.ts Punto de entrada que exporta los constructos de
app
- project.json Objetivos de compilación y configuración del proyecto
Directoriopackages/common/terraform
Directoriosrc
Directorioapp/ Módulos de Terraform para infraestructura específica de un proyecto/generador
- …
Directoriocore/ Módulos genéricos reutilizados por los módulos en
app- …
- project.json Objetivos de compilación y configuración del proyecto
Directoriopackages/common/constructs/src
Directorioapp
Directoriodbs
- <name>.ts Infraestructura específica para tu base de datos
Directoriocore
Directoriordb
- aurora.ts Construcción genérica de base de datos Aurora
Directoriopackages/common/terraform/src
Directorioapp
Directoriodbs
Directorio<name>
- <name>.tf Módulo específico para tu base de datos
Directoriocore
Directoriordb
Directorioaurora
- aurora.tf Módulo genérico de Aurora
Arquitectura
Sección titulada «Arquitectura»La base de datos desplegada tiene la siguiente arquitectura. Por defecto, un Amazon RDS Proxy se sitúa frente al clúster Aurora para agrupar conexiones y habilitar la autenticación IAM — consulte Deshabilitar RDS Proxy para la alternativa. La arquitectura es la misma ya sea que seleccione el motor PostgreSQL o MySQL; solo difiere el tipo de motor Aurora.
Desarrollo Local
Sección titulada «Desarrollo Local»Modelado de Datos
Sección titulada «Modelado de Datos»El proyecto generado usa SQLModel para definir el esquema de tu base de datos. El flujo de trabajo es model-first: agrega o actualiza clases de tabla SQLModel en el directorio <name>/models/ de tu proyecto de base de datos, luego genera una migración a partir de esos cambios de modelo.
Modelo de ejemplo:
from sqlalchemy import Column, Stringfrom sqlmodel import Field, SQLModel
class ExampleModel(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) name: str = Field(sa_column=Column(String(255), nullable=False)) description: str | None = Field(default=None, sa_column=Column(String(255), nullable=True))Importa tus modelos en <name>/models/__init__.py para que Alembic pueda descubrirlos durante la autogeneración.
Crear Migraciones
Sección titulada «Crear Migraciones»Después de agregar o actualizar modelos, usa Alembic para generar y aplicar scripts de migración. El objetivo alembic generado inicia automáticamente un contenedor de base de datos local antes de ejecutarse:
pnpm nx run <project>:alembic revision --autogenerate -m "describe your change"yarn nx run <project>:alembic revision --autogenerate -m "describe your change"npx nx run <project>:alembic revision --autogenerate -m "describe your change"bunx nx run <project>:alembic revision --autogenerate -m "describe your change"Esto genera un nuevo script de migración en migrations/versions/. Revisa el script generado antes de aplicarlo.
Aplica la migración a tu base de datos local:
pnpm nx run <project>:migrateyarn nx run <project>:migratenpx nx run <project>:migratebunx nx run <project>:migrateCuando despliegues el stack de AWS, la infraestructura generada aplica automáticamente las migraciones generadas a la base de datos desplegada.
Aplicar Migraciones Existentes
Sección titulada «Aplicar Migraciones Existentes»Cuando descargues archivos de migración creados por otros desarrolladores, aplícalos a tu base de datos local:
pnpm nx run <project>:migrateyarn nx run <project>:migratenpx nx run <project>:migratebunx nx run <project>:migrateEjecutar Comandos Alembic
Sección titulada «Ejecutar Comandos Alembic»El objetivo alembic generado expone la CLI de Alembic, por lo que puedes ejecutar cualquier comando Alembic contra la base de datos local. Consulta la referencia de comandos de Alembic para ver los comandos disponibles.
pnpm nx run <project>:alembic <alembic-command>yarn nx run <project>:alembic <alembic-command>npx nx run <project>:alembic <alembic-command>bunx nx run <project>:alembic <alembic-command>Detener la Base de Datos Local
Sección titulada «Detener la Base de Datos Local»Detener dev (por ejemplo, con Ctrl+C) elimina automáticamente el contenedor de base de datos local, pero conserva el volumen nombrado para que tus datos persistan entre reinicios.
Conectarse a la Base de Datos
Sección titulada «Conectarse a la Base de Datos»Importa session_context desde tu paquete de base de datos y úsalo como un administrador de contexto asíncrono para obtener una AsyncSession:
from sqlmodel import select
from my_scope.my_db import session_contextfrom my_scope.my_db.models.example import ExampleModel
async def example(): async with session_context() as session: results = (await session.execute(select(ExampleModel))).all()El cliente de base de datos automáticamente:
- Recupera la configuración de la base de datos desde AWS AppConfig usando la variable de entorno
RUNTIME_CONFIG_APP_ID - Genera tokens de autenticación temporales a través del
boto3RDS Signer para autenticación IAM - Establece conexiones TLS usando
ssl.create_default_context()
Desplegar tu Base de Datos
Sección titulada «Desplegar tu Base de Datos»El generador de base de datos relacional crea infraestructura CDK o Terraform basada en tu iacProvider seleccionado.
El constructo CDK se crea en common/constructs. Ejemplo de uso:
import { MyDatabase } from ':my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); ... const db = new MyDatabase(this, 'Db', { vpc, vpcSubnets: { subnetType: SubnetType.PRIVATE_ISOLATED, } }); }}Esto aprovisiona un clúster Aurora con RDS Proxy, credenciales de administrador, usuario de base de datos de aplicación, registro de configuración en tiempo de ejecución y manejador de migraciones.
La infraestructura generada crea dos usuarios de base de datos:
- Usuario administrador - Creado durante el aprovisionamiento del clúster con credenciales almacenadas en AWS Secrets Manager
- Usuario de aplicación - Creado a través de un recurso personalizado Lambda con autenticación IAM habilitada y privilegios DML (SELECT, INSERT, UPDATE, DELETE) en la base de datos de aplicación
El módulo Terraform se crea en common/terraform. Ejemplo de uso:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database"
vpc_id = module.vpc.vpc_id database_subnet_ids = module.vpc.private_isolated_subnet_ids lambda_subnet_ids = module.vpc.private_subnet_ids
tags = local.common_tags}Esto aprovisiona un clúster Aurora con RDS Proxy, credenciales de administrador, Lambda create-db-user, registro de configuración en tiempo de ejecución, Lambda de migración y recursos de registro de contenedores.
La infraestructura generada crea dos usuarios de base de datos:
- Usuario administrador - Creado durante el aprovisionamiento del clúster con credenciales almacenadas en AWS Secrets Manager
- Usuario de aplicación - Creado a través de una función Lambda con autenticación IAM habilitada y privilegios DML (SELECT, INSERT, UPDATE, DELETE) en la base de datos de aplicación
El usuario de aplicación se crea automáticamente con un nombre aleatorio y autenticación IAM. El cliente de base de datos generado ya está configurado para autenticarse como este usuario usando tokens RDS de corta duración, por lo que tu código de aplicación nunca maneja contraseñas de base de datos.
Tu VPC debe incluir subredes públicas, subredes privadas con salida y subredes privadas aisladas. La base de datos puede ejecutarse en subredes privadas aisladas, mientras que las funciones Lambda de aplicación deben ejecutarse en subredes privadas con salida para que puedan alcanzar servicios de AWS como AppConfig.
const vpc = new Vpc(this, 'Vpc', { subnetConfiguration: [ { name: 'public', subnetType: SubnetType.PUBLIC, }, { name: 'private_with_egress', subnetType: SubnetType.PRIVATE_WITH_EGRESS, }, { name: 'private_isolated', subnetType: SubnetType.PRIVATE_ISOLATED, }, ],});module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 6.0"
name = "app" ... public_subnet_names = ["public"] private_subnet_names = ["private_with_egress"] intra_subnet_names = ["private_isolated"]
enable_nat_gateway = true single_nat_gateway = true}Usa el generador connection para conectar un proyecto a esta base de datos — consulta la guía de conexión para el tipo de cómputo relevante (por ejemplo, FastAPI, servidor MCP, agente) para el cableado de infraestructura requerido para alcanzarla.
Configuración de RDS Proxy
Sección titulada «Configuración de RDS Proxy»La infraestructura generada incluye un RDS Proxy de forma predeterminada, que se sitúa entre tu aplicación y el clúster Aurora. RDS Proxy proporciona varios beneficios:
- Agrupación de conexiones - Mantiene un pool de conexiones de base de datos que pueden compartirse entre instancias de aplicación, reduciendo la sobrecarga de establecer nuevas conexiones
- Resiliencia de conexión - Maneja automáticamente las conmutaciones por error y reconexiones durante reemplazos de instancias Aurora o mantenimiento
- Autenticación IAM - Admite autenticación de base de datos basada en IAM, eliminando la necesidad de gestionar credenciales de base de datos en el código de tu aplicación
- Seguridad mejorada - Aplica cifrado TLS para todas las conexiones
Deshabilitar RDS Proxy
Sección titulada «Deshabilitar RDS Proxy»Puedes deshabilitar el proxy RDS de la siguiente manera:
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableRdsProxy: false,});Cuando RDS Proxy está deshabilitado, tu aplicación se conecta directamente al endpoint del clúster Aurora.
De forma predeterminada, RDS Proxy está habilitado. Puedes deshabilitarlo si es necesario:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_rds_proxy = false}Cuando RDS Proxy está deshabilitado, tu aplicación se conecta directamente al endpoint del clúster Aurora.
Requisitos SSL al Conectarse sin RDS Proxy
Sección titulada «Requisitos SSL al Conectarse sin RDS Proxy»El paquete CA de Amazon RDS debe estar en el almacén de confianza del sistema del tiempo de ejecución.
Tiempos de Ejecución de Contenedor
Sección titulada «Tiempos de Ejecución de Contenedor»ADD https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem /etc/pki/ca-trust/source/anchors/global-bundle.pemRUN update-ca-trustADD https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem /usr/local/share/ca-certificates/rds-global-bundle.crtRUN update-ca-certificatesFunciones Lambda Zip
Sección titulada «Funciones Lambda Zip»Para funciones Lambda desplegadas como zip (como una py#api FastAPI), el almacén de confianza CA integrado del entorno de ejecución Lambda de Amazon Linux 2023 incluye las CA raíz de Amazon utilizadas por RDS.
Cuando uses RDS Proxy, no necesitas configurar el paquete CA de RDS en el tiempo de ejecución que se conecta a la base de datos.
Instancias del Clúster
Sección titulada «Instancias del Clúster»Configure las instancias de escritura y lectura para su clúster Aurora.
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... writer: ClusterInstance.serverlessV2('writer'), readers: [ClusterInstance.serverlessV2('reader')],});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... instance_count = 2 # 1 writer + 1 reader}Capacidad Serverless
Sección titulada «Capacidad Serverless»Controla los límites de escalado de Aurora Serverless v2 para adaptarse a tu carga de trabajo.
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... serverlessV2MinCapacity: 0.5, serverlessV2MaxCapacity: 8,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... serverless_min_capacity = 0.5 serverless_max_capacity = 8}Versión del Motor
Sección titulada «Versión del Motor»Fija una versión específica del motor Aurora.
Por defecto, la imagen del contenedor de base de datos local generada coincide con la versión predeterminada del motor Aurora. Si cambias la versión del motor Aurora, se recomienda también usar una versión de imagen de contenedor local que coincida para máxima compatibilidad. Consulta las notas de lanzamiento de AWS para versiones de Aurora PostgreSQL y versiones de Aurora MySQL para identificar la versión correspondiente de la base de datos comunitaria.
La imagen de la base de datos local se configura en el campo localDev.image del archivo config.json generado en la raíz de tu proyecto de base de datos. Actualiza ese valor cuando cambies las versiones del motor.
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... engineVersion: AuroraPostgresEngineVersion.VER_17_7,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... engine_version = "17.7"}import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... engineVersion: AuroraMysqlEngineVersion.VER_3_12_0,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... engine_version = "8.0.mysql_aurora.3.12.0"}Protección contra Eliminación
Sección titulada «Protección contra Eliminación»La protección contra eliminación está habilitada por defecto (deletionProtection: true en CDK, deletion_protection = true en Terraform) para proteger el clúster de Aurora de eliminaciones accidentales.
Deshabilitar la Protección contra Eliminación
Sección titulada «Deshabilitar la Protección contra Eliminación»Puede deshabilitar la protección contra eliminación para entornos donde se espera la eliminación de la base de datos, como stacks de desarrollo o preview de corta duración.
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... deletionProtection: false,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false}Política de Eliminación
Sección titulada «Política de Eliminación»El constructo CDK retiene el clúster Aurora por defecto (removalPolicy: RemovalPolicy.RETAIN). Cambia esto cuando quieras que la eliminación del stack CDK haga una instantánea o destruya el clúster en su lugar.
Cuando uses RemovalPolicy.DESTROY, la protección contra eliminación también debe estar deshabilitada antes de que el clúster pueda ser eliminado.
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... removalPolicy: RemovalPolicy.SNAPSHOT,});Para un entorno efímero donde la base de datos debe ser eliminada con el stack:
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... deletionProtection: false, removalPolicy: RemovalPolicy.DESTROY,});Terraform no utiliza políticas de eliminación de CDK. Por defecto, el módulo crea una instantánea final al eliminar (skip_final_snapshot = false). Para omitir la instantánea final en un entorno efímero:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false skip_final_snapshot = true}Registro y Monitoreo
Sección titulada «Registro y Monitoreo»Performance Insights está habilitado en la instancia de escritura de Aurora de forma predeterminada (cifrado con la clave KMS del clúster). También puede exportar los registros del motor de Aurora a CloudWatch Logs (postgresql para Aurora PostgreSQL; audit, error, general y slowquery para Aurora MySQL). Habilite la exportación de registros por base de datos:
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableCloudwatchLogs: true, enablePerformanceInsights: false, // disable if not required});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_cloudwatch_logs = true enable_performance_insights = false # disable if not required}Rotación de Clave de Cifrado
Sección titulada «Rotación de Clave de Cifrado»La clave KMS utilizada para cifrar el clúster Aurora y su secreto de credenciales tiene la rotación automática de claves habilitada por defecto. Deshabilítela si su política de seguridad gestiona la rotación externamente.
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableKeyRotation: false,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_key_rotation = false}Conexiones
Sección titulada «Conexiones»Usa el generador connection para integrar este proyecto con otros en tu espacio de trabajo. Las siguientes conexiones involucran este proyecto: