Pular para o conteúdo

Banco de Dados Relacional Python

Este gerador cria um novo projeto de banco de dados relacional Python apoiado por Amazon Aurora (PostgreSQL ou MySQL), SQLModel para modelagem de dados e Alembic para migrações de esquema. Ele gera o código da aplicação e a infraestrutura necessária para provisionar e gerenciar um banco de dados usando AWS CDK ou Terraform, com definição de esquema declarativa, implantação automática de migração e um cliente de banco de dados.

Execute este gerador@aws/nx-plugin:py#rdb

pnpm nx g @aws/nx-plugin:py#rdb
Monte seu comando10

Obrigatório

Opções do gerador10 opções
nameObrigatóriostring

Nome do projeto de banco de dados a ser gerado

directorystringPadrão: packages

O diretório onde armazenar a aplicação.

infraenumPadrão: aurora

Serviço de banco de dados relacional a ser provisionado.

auroranone
engineenumPadrão: postgres

Motor de banco de dados a ser usado com o serviço selecionado.

postgresmysql
frameworkenumPadrão: sqlmodel

Framework ORM a ser usado para o projeto gerado.

sqlmodel
iacenumPadrão: inherit

O provedor IaC preferido. Por padrão, este é herdado da sua seleção inicial.

inheritcdkterraform
subDirectorystring

O subdiretório onde o projeto é colocado. Por padrão, este é o nome do projeto.

databaseUserstringPadrão: dbadmin

Nome de usuário do administrador do banco de dados. O padrão é 'dbadmin'.

databaseNamestring

Nome inicial do banco de dados. O padrão é o nome do projeto.

preferInstallDependenciesbooleanPadrão: true

Se deve preferir instalar dependências após a execução do gerador. Defina como false para adiar a instalação ao agrupar múltiplos geradores (uma instalação ainda é executada se necessário para que geradores subsequentes possam calcular o grafo de projeto Nx); instale uma vez no final.

O gerador cria a seguinte estrutura de projeto no diretório <directory>/<name>:

  • Directory<name>
    • __init__.py Package exports
    • connection.py Database engine and session factory with IAM authentication
    • utils.py Runtime config and local development helpers
    • migration_handler.py Lambda handler that runs Alembic migrations during deployment
    • create_db_user_handler.py Lambda handler that creates the application database user during deployment
    • Directorymodels
      • __init__.py Model exports, imported by Alembic to discover your tables
      • example.py Example SQLModel table definition
  • Directorymigrations
    • versions Alembic-generated migration scripts
    • env.py Alembic environment (connects to the database)
    • script.py.mako Alembic migration script template
  • Directorytests
    • __init__.py Module initialisation
    • conftest.py Test configuration
    • test_noop.py Placeholder test
  • alembic.ini Alembic configuration
  • config.json Local development connection details and runtime config key
  • Dockerfile.migration Container image for the migration handler
  • Dockerfile.create-db-user Container image for the create-db-user handler
  • project.json Project configuration and build targets
  • pyproject.toml Packaging configuration file used by UV
  • README.md Project README
  • .python-version Contains the project’s Python version
  • .gitignore Files excluded from version control

Scripts de desenvolvimento local são compartilhados entre todos os projetos de banco de dados e gerados em packages/common/scripts/:

  • Directorypackages/common/scripts/src/rdb
    • pull-image.ts Pulls the database container image
    • start-container.ts Starts a local database container
    • wait-for-postgres-db.ts Waits for the local database to be ready (PostgreSQL)
    • wait-for-mysql-db.ts Waits for the local database to be ready (MySQL)

Como este gerador fornece infraestrutura como código baseada no seu iac escolhido, ele criará um projeto em packages/common que inclui os constructs CDK relevantes ou módulos Terraform.

O projeto comum de infraestrutura como código é estruturado da seguinte forma:

  • Directorypackages/common/constructs
    • Directorysrc
      • Directoryapp/ Constructs for infrastructure specific to a project/generator
      • Directorycore/ Generic constructs which are reused by constructs in app
      • index.ts Entry point exporting constructs from app
    • project.json Project build targets and configuration
  • Directorypackages/common/constructs/src
    • Directoryapp
      • Directorydbs
        • <name>.ts Infraestrutura específica para seu banco de dados
    • Directorycore
      • Directoryrdb
        • aurora.ts Construto genérico de banco de dados Aurora

O banco de dados implantado possui a seguinte arquitetura. Por padrão, um Amazon RDS Proxy fica na frente do cluster Aurora para agrupar conexões e habilitar autenticação IAM — veja Desabilitar RDS Proxy para a alternativa. A arquitetura é a mesma independentemente de você selecionar o mecanismo PostgreSQL ou MySQL; apenas o tipo de mecanismo Aurora difere.

Loading the diagram…

O projeto gerado usa SQLModel para definir seu esquema de banco de dados. O fluxo de trabalho é model-first: adicione ou atualize classes de tabela SQLModel no diretório <name>/models/ do seu projeto de banco de dados e, em seguida, gere uma migração a partir dessas alterações de modelo.

Exemplo de modelo:

packages/my_db/my_db/models/example.py
from sqlalchemy import Column, String
from 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))

Importe seus modelos em <name>/models/__init__.py para que o Alembic possa descobri-los durante a autogeração.

Após adicionar ou atualizar modelos, use o Alembic para gerar e aplicar scripts de migração. O target alembic gerado inicia automaticamente um contêiner de banco de dados local antes de executar:

Terminal window
pnpm nx run <project>:alembic revision --autogenerate -m "describe your change"

Isso gera um novo script de migração em migrations/versions/. Revise o script gerado antes de aplicá-lo.

Aplique a migração ao seu banco de dados local:

Terminal window
pnpm nx run <project>:migrate

Quando você implantar a stack AWS, a infraestrutura gerada aplica automaticamente as migrações geradas ao banco de dados implantado.

Quando você obtiver arquivos de migração criados por outros desenvolvedores, aplique-os ao seu banco de dados local:

Terminal window
pnpm nx run <project>:migrate

O target alembic gerado expõe a CLI do Alembic, para que você possa executar qualquer comando Alembic no banco de dados local. Consulte a referência de comandos do Alembic para comandos disponíveis.

Terminal window
pnpm nx run <project>:alembic <alembic-command>

Parar dev (por exemplo, com Ctrl+C) remove automaticamente o contêiner do banco de dados local, mas preserva o volume nomeado para que seus dados persistam entre reinicializações.

Importe session_context do seu pacote de banco de dados e use-o como um gerenciador de contexto assíncrono para obter uma AsyncSession:

from sqlmodel import select
from my_scope_my_db import session_context
from my_scope_my_db.models.example import ExampleModel
async def example():
async with session_context() as session:
results = (await session.execute(select(ExampleModel))).scalars().all()

O cliente de banco de dados automaticamente:

  • Recupera a configuração do banco de dados do AWS AppConfig em tempo de execução
  • Gera tokens de autenticação temporários via boto3 RDS Signer para autenticação IAM
  • Estabelece conexões TLS usando ssl.create_default_context()

O gerador de banco de dados relacional cria infraestrutura CDK ou Terraform com base no iac selecionado.

O construto CDK é criado em common/constructs. Exemplo de uso:

packages/infra/src/stacks/application-stack.ts
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,
}
});
}
}

Isso provisiona um cluster Aurora com RDS Proxy, credenciais de administrador, usuário de banco de dados da aplicação, registro de configuração de runtime e manipulador de migração.

A infraestrutura gerada cria dois usuários de banco de dados:

  • Usuário administrador - Criado durante o provisionamento do cluster com credenciais armazenadas no AWS Secrets Manager
  • Usuário da aplicação - Criado via um recurso personalizado Lambda com autenticação IAM habilitada e privilégios DML (SELECT, INSERT, UPDATE, DELETE) no banco de dados da aplicação

O usuário da aplicação é criado automaticamente com um nome aleatório e autenticação IAM. O cliente de banco de dados gerado já está configurado para autenticar como este usuário usando tokens RDS de curta duração, então o código da sua aplicação nunca manipula senhas de banco de dados.

Sua VPC deve incluir sub-redes públicas, sub-redes privadas com saída e sub-redes privadas isoladas. O banco de dados pode ser executado em sub-redes privadas isoladas, enquanto as funções Lambda da aplicação devem ser executadas em sub-redes privadas com saída para que possam alcançar serviços AWS como AppConfig.

Clique aqui para um exemplo de configuração de VPC.

Use o gerador connection para conectar um projeto a este banco de dados — consulte o guia de conexão para o tipo de computação relevante (por exemplo, FastAPI, servidor MCP, agente) para a configuração de infraestrutura necessária para alcançá-lo.

A imagem Docker construída para este projeto pode ser verificada em busca de vulnerabilidades usando Trivy, executando a partir da imagem Trivy hospedada no ECR.

Um target trivy é adicionado ao seu projeto que verifica a imagem construída e sai com código diferente de zero se alguma vulnerabilidade de severidade HIGH ou CRITICAL for encontrada. O Dockerfile gerado usa uma imagem base sem vulnerabilidades corrigíveis conhecidas dessas severidades no momento da geração, e atualiza as ferramentas incluídas (como npm) para mantê-lo assim.

A verificação usa o mesmo mecanismo de contêiner que sua construção de imagem (docker ou finch), portanto nenhuma ferramenta adicional é necessária. A verificação não é armazenada em cache, pois a imagem que ela lê reside no mecanismo de contêiner em vez de no disco — então ela sempre verifica a imagem real e falha de forma explícita em vez de relatar uma aprovação em cache para uma imagem que não está mais lá. Cada execução, portanto, leva dezenas de segundos por imagem e atualiza o banco de dados de vulnerabilidades do Trivy, então ela precisa de acesso à rede. O script raiz trivy fornecido verifica todas as imagens no workspace:

Terminal window
pnpm trivy

Pode haver casos em que você deseja suprimir uma vulnerabilidade específica, por exemplo, quando nenhuma correção está disponível ainda e você avaliou o risco como aceitável.

Adicione o ID da vulnerabilidade (um por linha) ao arquivo .trivyignore na raiz do seu projeto (ou seja, ao lado do seu project.json):

.trivyignore
# node-tar arbitrary file write - not exploitable in our usage
CVE-2024-XXXXX

Para mais detalhes sobre filtragem de descobertas, consulte a documentação de filtragem do Trivy.

A infraestrutura gerada inclui um RDS Proxy por padrão, que fica entre sua aplicação e o cluster Aurora. O RDS Proxy oferece vários benefícios:

  • Pooling de conexões - Mantém um pool de conexões de banco de dados que podem ser compartilhadas entre instâncias da aplicação, reduzindo a sobrecarga de estabelecer novas conexões
  • Resiliência de conexão - Lida automaticamente com failovers e reconexões durante substituições de instâncias Aurora ou manutenção
  • Autenticação IAM - Suporta autenticação de banco de dados baseada em IAM, eliminando a necessidade de gerenciar credenciais de banco de dados no código da sua aplicação
  • Segurança aprimorada - Impõe criptografia TLS para todas as conexões

Você pode desabilitar o proxy RDS da seguinte forma:

packages/infra/src/stacks/application-stack.ts
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', {
...
enableRdsProxy: false,
});

Quando o RDS Proxy está desabilitado, sua aplicação se conecta diretamente ao endpoint do cluster Aurora.

O pacote CA do Amazon RDS deve estar no armazenamento de confiança do sistema do runtime.

ADD https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem /etc/pki/ca-trust/source/anchors/global-bundle.pem
RUN update-ca-trust

Para funções Lambda implantadas em zip (como uma py#api FastAPI), o armazenamento de confiança CA integrado do ambiente de execução Lambda do Amazon Linux 2023 inclui as CAs raiz da Amazon usadas pelo RDS.

Ao usar o RDS Proxy, você não precisa configurar o pacote CA do RDS no runtime que se conecta ao banco de dados.

Configure as instâncias de escritor e leitor para o seu cluster Aurora.

packages/infra/src/stacks/application-stack.ts
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', {
...
writer: ClusterInstance.serverlessV2('writer'),
readers: [ClusterInstance.serverlessV2('reader')],
});

Controle os limites de escalabilidade do Aurora Serverless v2 para corresponder à sua carga de trabalho. Ambos os provedores usam como padrão um mínimo de 0,5 ACUs e um máximo de 4.

packages/infra/src/stacks/application-stack.ts
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', {
...
serverlessV2MinCapacity: 0.5,
serverlessV2MaxCapacity: 8,
});

Fixe uma versão específica do motor Aurora.

Por padrão, a imagem do contêiner do banco de dados local gerada corresponde à versão padrão do motor Aurora. Se você alterar a versão do motor Aurora, é recomendável também usar uma versão de imagem de contêiner local correspondente para máxima compatibilidade. Consulte as notas de versão da AWS para versões do Aurora PostgreSQL e versões do Aurora MySQL para identificar a versão correspondente do banco de dados da comunidade.

A imagem do banco de dados local é configurada no campo localDev.image do arquivo config.json gerado na raiz do seu projeto de banco de dados. Atualize esse valor quando você alterar as versões do motor.

engine = postgres
packages/infra/src/stacks/application-stack.ts
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', {
...
engineVersion: AuroraPostgresEngineVersion.VER_17_7,
});
engine = mysql
packages/infra/src/stacks/application-stack.ts
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', {
...
engineVersion: AuroraMysqlEngineVersion.VER_3_12_0,
});

O cluster Aurora é protegido por duas proteções independentes, de modo que desativar apenas uma delas não pode excluir seus dados:

  • deletionProtection, aplicado pelo RDS.
  • RemovalPolicy.RETAIN, aplicado pelo CloudFormation, que deixa o cluster no lugar quando ele é removido da stack.

Você pode desabilitar a proteção para ambientes onde a exclusão do banco de dados é esperada, como stacks de desenvolvimento ou preview de curta duração.

packages/infra/src/stacks/application-stack.ts
import { RemovalPolicy } from 'aws-cdk-lib';
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', {
...
deletionProtection: false,
removalPolicy: RemovalPolicy.DESTROY,
});

O construto CDK retém o cluster Aurora por padrão (removalPolicy: RemovalPolicy.RETAIN). Altere isso quando você quiser que a exclusão da stack CDK faça um snapshot ou destrua o cluster.

Ao usar RemovalPolicy.DESTROY, a proteção contra exclusão também deve ser desabilitada antes que o cluster possa ser excluído.

packages/infra/src/stacks/application-stack.ts
import { RemovalPolicy } from 'aws-cdk-lib';
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', {
...
removalPolicy: RemovalPolicy.SNAPSHOT,
});

Para um ambiente efêmero onde o banco de dados deve ser excluído com a stack:

packages/infra/src/stacks/application-stack.ts
import { RemovalPolicy } from 'aws-cdk-lib';
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', {
...
deletionProtection: false,
removalPolicy: RemovalPolicy.DESTROY,
});
engine = postgres

O log postgresql é exportado para Aurora PostgreSQL, com registro limitado apenas a instruções DDL (log_statement=ddl), de modo que os valores dos parâmetros das instruções nunca são registrados — desde que cada instrução seja enviada individualmente. log_statement=ddl registra todo o texto bruto de um lote de múltiplas instruções (por exemplo, uma única chamada psql -c "a;b;c") literalmente se qualquer instrução nele for DDL, incluindo quaisquer valores DML nesse mesmo lote.

engine = mysql

Os logs audit e error são exportados para Aurora MySQLgeneral e slowquery são deliberadamente excluídos, pois registram o texto completo das instruções, incluindo valores DML. Advanced Auditing tem escopo limitado a conexões e DDL (server_audit_events=CONNECT,QUERY_DDL), portanto, os valores dos parâmetros das instruções nunca são registrados.

O Performance Insights está habilitado na instância de gravação do Aurora por padrão (criptografado com a chave KMS do cluster). Os logs do mecanismo Aurora também são exportados para o CloudWatch Logs por padrão, configurados para exibir atividade no nível de esquema sem vazar dados de linha.

O volume de logs exportados — e, portanto, o custo de ingestão do CloudWatch Logs — escala com mudanças de esquema e conexões, em vez de tráfego de consultas, já que os tipos de log que carregam texto completo de instruções são excluídos. No Aurora MySQL, o evento de auditoria CONNECT é emitido por conexão, então cargas de trabalho que abrem uma conexão por solicitação produzem mais do que aquelas que usam pool.

Desabilite a exportação de logs por banco de dados se não for necessário:

packages/infra/src/stacks/application-stack.ts
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', {
...
enableCloudwatchLogs: false,
enablePerformanceInsights: false,
});

A chave KMS usada para criptografar o cluster Aurora e seu segredo de credenciais tem a rotação automática de chave habilitada por padrão. Desabilite-a se sua política de segurança gerenciar a rotação externamente.

packages/infra/src/stacks/application-stack.ts
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', {
...
enableKeyRotation: false,
});

A senha do usuário administrador (master) do Aurora é gerada e rotacionada pelo próprio Aurora no AWS Secrets Manager, usando senhas de usuário master gerenciadas pelo RDS. Seu código de infraestrutura nunca recebe a senha, então ela não pode vazar para um template do CloudFormation ou arquivo de estado do Terraform. O Aurora rotaciona o segredo a cada 7 dias sem nenhuma função de rotação para implantar ou manter.

O segredo é criptografado com a mesma chave KMS gerenciada pelo cliente que o cluster.

Sua aplicação nunca usa essas credenciais. Ela se conecta como um usuário de banco de dados com privilégios mínimos usando autenticação IAM — apenas os manipuladores de migração e create-db-user leem o segredo de administrador, e cada um recebe acesso apenas a esse segredo e sua chave KMS.

O segredo de administrador é exposto como secret.secretArn no cluster subjacente, e grantSecretRead concede a um consumidor acesso de leitura a ele:

packages/infra/src/stacks/application-stack.ts
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... });
db.grantSecretRead(myFunction);

Use o gerador connection para integrar este projeto com outros em seu workspace. As seguintes conexões envolvem este projeto:

Strands AgentsPythonAmazon AuroraPython
Python Agent to Relational DatabaseConnect a Python Agent to an Aurora relational database
FastAPIAmazon AuroraPython
FastAPI to Relational DatabaseConnect a FastAPI to an Aurora relational database
Model Context ProtocolPythonAmazon AuroraPython
Python MCP Server to Relational DatabaseConnect a Python MCP Server to an Aurora relational database