RDS Instance - Banco de Dados Relacional
Crie e gerencie bancos de dados relacionais totalmente gerenciados e escaláveis na AWS com PostgreSQL, MySQL, MariaDB, SQL Server ou Oracle.
Pré-requisito: Configuração do AWSProvider
Antes de criar qualquer recurso AWS, você precisa configurar um AWSProvider que gerencia credenciais e autenticação com a AWS.
IRSA:
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: AWSProvider
metadata:
name: production-aws
namespace: default
spec:
region: us-east-1
roleARN: arn:aws:iam::123456789012:role/infra-operator-role
defaultTags:
managed-by: infra-operator
environment: production
Credenciais Estáticas:
apiVersion: v1
kind: Secret
metadata:
name: aws-credentials
namespace: default
type: Opaque
stringData:
access-key-id: test
secret-access-key: test
---
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: AWSProvider
metadata:
name: localstack
namespace: default
spec:
region: us-east-1
accessKeyIDRef:
name: aws-credentials
key: access-key-id
secretAccessKeyRef:
name: aws-credentials
key: secret-access-key
defaultTags:
managed-by: infra-operator
environment: test
Verificar Status:
kubectl get awsprovider
kubectl describe awsprovider production-aws
Para produção, sempre use IRSA (IAM Roles for Service Accounts) ao invés de credenciais estáticas.
Criar Role IAM para IRSA
Para usar IRSA em produção, você precisa criar uma Role IAM com as permissões necessárias:
Trust Policy (trust-policy.json):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:infra-operator-system:infra-operator-controller-manager",
"oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
}
}
}
]
}
IAM Policy - RDS (rds-policy.json):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"rds:CreateDBInstance",
"rds:DeleteDBInstance",
"rds:DescribeDBInstances",
"rds:ModifyDBInstance",
"rds:StartDBInstance",
"rds:StopDBInstance",
"rds:CreateDBSnapshot",
"rds:DeleteDBSnapshot",
"rds:AddTagsToResource",
"rds:RemoveTagsFromResource",
"rds:ListTagsForResource",
"rds:CreateDBParameterGroup",
"rds:ModifyDBParameterGroup"
],
"Resource": "*"
}
]
}
Criar Role com AWS CLI:
# 1. Obter OIDC Provider do cluster EKS
export CLUSTER_NAME=my-cluster
export AWS_REGION=us-east-1
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
OIDC_PROVIDER=$(aws eks describe-cluster \
--name $CLUSTER_NAME \
--region $AWS_REGION \
--query "cluster.identity.oidc.issuer" \
--output text | sed -e "s/^https:\/\///")
# 2. Atualizar trust-policy.json com valores corretos
cat > trust-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_PROVIDER}:sub": "system:serviceaccount:infra-operator-system:infra-operator-controller-manager",
"${OIDC_PROVIDER}:aud": "sts.amazonaws.com"
}
}
}
]
}
EOF
# 3. Criar IAM Role
aws iam create-role \
--role-name infra-operator-rds-role \
--assume-role-policy-document file://trust-policy.json \
--description "Role for Infra Operator RDS management"
# 4. Criar e anexar policy
aws iam put-role-policy \
--role-name infra-operator-rds-role \
--policy-name RDSManagement \
--policy-document file://rds-policy.json
# 5. Obter Role ARN
aws iam get-role \
--role-name infra-operator-rds-role \
--query 'Role.Arn' \
--output text
Anotar ServiceAccount do Operator:
# Adicionar annotation ao ServiceAccount do operator
kubectl annotate serviceaccount infra-operator-controller-manager \
-n infra-operator-system \
eks.amazonaws.com/role-arn=arn:aws:iam::123456789012:role/infra-operator-rds-role
Substitua 123456789012 pelo seu AWS Account ID e EXAMPLED539D4633E53DE1B71EXAMPLE pelo seu OIDC provider ID.
Visão Geral
Amazon RDS (Relational Database Service) é um serviço de banco de dados relacional totalmente gerenciado que oferece:
Recursos:
- Totalmente Gerenciado: A AWS gerencia backups, patches, replicação e failover
- Alta Disponibilidade: Multi-AZ automático com failover em minutos
- Múltiplos Engines: PostgreSQL, MySQL, MariaDB, SQL Server, Oracle
- Escalabilidade: Aumente ou diminua a capacidade conforme necessário
- Backups Automatizados: Retenção configurável (até 35 dias)
- Point-in-Time Recovery (PITR): Restaure para qualquer ponto nos últimos 35 dias
- Criptografia em Repouso: AES-256 com AWS KMS
- Criptografia em Trânsito: SSL/TLS automático
- Performance Insights: Monitore e otimize performance
- Enhanced Monitoring: Métricas detalhadas de OS, IO, CPU
- Read Replicas: Replicação de leitura entre regiões (síncrona ou assíncrona)
- Patching Automatizado: Janelas de manutenção configuráveis
- Parameter Groups: Configuração customizada do banco de dados
- Security Groups: Controle de acesso em nível de rede
Status: ⚠️ Requer LocalStack Pro ou AWS Real
Início Rápido
RDS PostgreSQL:
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: RDSInstance
metadata:
name: e2e-postgres-db
namespace: default
spec:
providerRef:
name: localstack
# Identificador único do banco de dados
dbInstanceIdentifier: e2e-test-postgres
# Database engine
engine: postgres
engineVersion: "14.7"
# Instance class
dbInstanceClass: db.t3.micro
# Storage
allocatedStorage: 20
# Credenciais do administrador
masterUsername: dbadmin
masterUserPassword: Test123456!
# Nome do banco de dados inicial
dbName: testdb
port: 5432
# Configuração
multiAZ: false
publiclyAccessible: true
storageEncrypted: true
# Backups
backupRetentionPeriod: 7
preferredBackupWindow: "03:00-04:00"
# Tags
tags:
Environment: test
ManagedBy: infra-operator
Database: postgres
deletionPolicy: Delete
RDS MySQL:
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: RDSInstance
metadata:
name: e2e-mysql-db
namespace: default
spec:
providerRef:
name: localstack
# Identificador único
dbInstanceIdentifier: e2e-test-mysql
# MySQL engine
engine: mysql
engineVersion: "8.0.33"
# Instance class
dbInstanceClass: db.t3.small
# Storage
allocatedStorage: 30
# Credenciais
masterUsername: admin
masterUserPassword: MyPassword123!
# Banco de dados inicial
dbName: mydb
port: 3306
# Multi-AZ habilitado
multiAZ: true
publiclyAccessible: false
storageEncrypted: true
# Backups
backupRetentionPeriod: 14
# Tags
tags:
Environment: test
ManagedBy: infra-operator
Database: mysql
deletionPolicy: Delete
RDS PostgreSQL Produção:
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: RDSInstance
metadata:
name: app-database
namespace: default
spec:
providerRef:
name: production-aws
# Identificador único do banco de dados (2-63 caracteres)
dbInstanceIdentifier: app-db-prod
# Database engine
engine: postgres
engineVersion: "15.4"
# Instance class (capacidade)
dbInstanceClass: db.t3.micro
# Storage
allocatedStorage: 20
storageType: gp3
iops: 3000
# Credenciais do administrador
masterUsername: postgres
masterUserPasswordSecretRef:
name: db-password
key: password
# Multi-AZ para alta disponibilidade
multiAZ: true
# VPC e segurança
dbSubnetGroupName: private-subnet-group
vpcSecurityGroupRefs:
- name: db-sg
# Backups
backupRetentionPeriod: 7
preferredBackupWindow: "03:00-04:00"
preferredMaintenanceWindow: "sun:04:00-sun:05:00"
# Proteção contra deleção
deletionProtection: true
# Tagging
tags:
Environment: production
Application: web-app
deletionPolicy: Retain
Aplicar:
kubectl apply -f rds.yaml
Verificar Status:
kubectl get rdsinstances
kubectl describe rdsinstance e2e-postgres-db
kubectl get rdsinstance e2e-postgres-db -o yaml
Referência de Configuração
Campos Obrigatórios
Referência ao recurso AWSProvider para autenticação
Nome do recurso AWSProvider
Identificador único para a instância RDS (2 a 63 caracteres)
Regras:
- Apenas caracteres alfanuméricos e hífens
- Não pode começar ou terminar com hífen
- Deve ser único por região
- Não pode ser modificado após criação
Exemplo:
dbInstanceIdentifier: myapp-db-prod
Database engine
Opções:
postgres- PostgreSQLmysql- MySQLmariadb- MariaDBsqlserver-ex- SQL Server Expresssqlserver-se- SQL Server Standardsqlserver-ee- SQL Server Enterpriseoracle-se2- Oracle Standard Edition 2oracle-ee- Oracle Enterprise Edition
Exemplo:
engine: postgres
Versão do database engine
Exemplos:
- PostgreSQL:
15.4,14.9,13.13 - MySQL:
8.0.35,8.0.34,5.7.44 - MariaDB:
10.6.14,10.5.21,10.4.32
Exemplo:
engineVersion: "15.4"
Nota: Sempre especifique versões com patch (ex: 15.4, não 15)
Instance class (CPU, RAM, performance)
Família db.t3 (Burstable - Dev/Test):
db.t3.micro- 1 vCPU, 1 GB RAM (~$0.017/hora)db.t3.small- 1 vCPU, 2 GB RAM (~$0.034/hora)db.t3.medium- 1 vCPU, 4 GB RAM (~$0.068/hora)
Família db.t4g (Graviton - mais barato):
db.t4g.micro- 1 vCPU, 1 GB RAMdb.t4g.small- 1 vCPU, 2 GB RAM
Família db.m5 (General Purpose):
db.m5.large- 2 vCPU, 8 GB RAM (~$0.175/hora)db.m5.xlarge- 4 vCPU, 16 GB RAM (~$0.350/hora)db.m5.2xlarge- 8 vCPU, 32 GB RAM (~$0.700/hora)
Família db.r5 (Memory Optimized - Cache/Analytics):
db.r5.large- 2 vCPU, 16 GB RAM (~$0.280/hora)db.r5.xlarge- 4 vCPU, 32 GB RAM (~$0.560/hora)
Exemplo:
dbInstanceClass: db.t3.micro
Espaço de armazenamento alocado em GB
Range: 20 - 65,536 GB (depende do engine)
Tipos de armazenamento:
- gp2 (General Purpose): 20-65,536 GB (padrão)
- gp3 (General Purpose v3): 20-65,536 GB (recomendado, melhor performance)
- io1 (Provisioned IOPS): 100-65,536 GB (alta performance)
- io2 (Provisioned IOPS v2): 100-65,536 GB (máxima performance)
Exemplo:
allocatedStorage: 20
storageType: gp3
Nota: Você pode aumentar o tamanho depois, mas não pode diminuir
Nome de usuário do administrador do banco de dados
Regras:
- 1 a 16 caracteres (depende do engine)
- Apenas alfanuméricos
- Não pode ser
admin,root,postgres(alguns engines) - Não pode começar com número
Exemplo:
masterUsername: dbadmin
Referência ao Secret do Kubernetes contendo a senha
Nome do Secret do Kubernetes
Chave dentro do Secret
Exemplo de Secret:
apiVersion: v1
kind: Secret
metadata:
name: db-password
namespace: default
type: Opaque
stringData:
password: SuperSecurePassword123!
Regras de Senha:
- Mínimo 8 caracteres
- Contém: letras, números, símbolos especiais
- Não pode conter
@,/,", ou\
Campos Opcionais - Storage
Tipo de armazenamento EBS
Opções:
gp2: General Purpose SSD (padrão, bom para a maioria)gp3: General Purpose SSD v3 (recomendado, melhor performance)io1: Provisioned IOPS SSD (performance previsível)io2: Provisioned IOPS SSD v2 (máxima performance)
Exemplo:
storageType: gp3
IOPS provisionados (apenas io1/io2)
Range: 1,000 - 64,000 IOPS
Nota: Para gp3, IOPS é configurado separadamente do tamanho:
storageType: io1
allocatedStorage: 100
iops: 5000
Throughput de armazenamento para gp3 (MB/s)
Range: 125 - 1,000 MB/s:
storageType: gp3
storageThroughput: 500
Campos Opcionais - Rede e Segurança
Nome do DB Subnet Group (subnets privadas)
Importante: DEVE existir previamente na AWS:
dbSubnetGroupName: private-subnet-group
Criar subnet group via AWS CLI:
aws rds create-db-subnet-group \
--db-subnet-group-name private-subnet-group \
--db-subnet-group-description "Private subnets for RDS" \
--subnet-ids subnet-xxx subnet-yyy
Referências aos Security Groups do Kubernetes para controle de acesso
Nome do recurso SecurityGroup no Kubernetes
Exemplo:
vpcSecurityGroupRefs:
- name: rds-security-group
Alternativa - usar IDs diretos:
vpcSecurityGroupIds:
- sg-0123456789abcdef0
- sg-0123456789abcdef1
Se o banco de dados é acessível via internet pública
⚠️ Segurança: Nunca habilite em produção!:
publiclyAccessible: false # Manter privado
Protege contra deleção acidental
Recomendado: true em produção:
deletionProtection: true
Campos Opcionais - Backups e Recuperação
Dias de retenção de backup automatizado
Range: 1 - 35 dias
Recomendações:
- Desenvolvimento: 1-7 dias
- Staging: 7-14 dias
- Produção: 14-35 dias
Exemplo:
backupRetentionPeriod: 30
Custo: Aumenta com a retenção
Janela diária de backup (UTC, formato HH:MM-HH:MM)
Padrão: Selecionado automaticamente:
preferredBackupWindow: "03:00-04:00" # 3AM-4AM UTC
Dica: Escolha horário de baixo uso
Janela semanal de manutenção para patches (formato: ddd:HH:MM-ddd:HH:MM)
Padrão: Selecionado automaticamente:
preferredMaintenanceWindow: "sun:04:00-sun:05:00"
# Domingo, 4AM-5AM UTC
Dias válidos: mon, tue, wed, thu, fri, sat, sun
Pular criação de snapshot final ao deletar banco de dados
Cuidado: true pode perder dados!:
skipFinalSnapshot: false # Sempre criar snapshot final
Identificador do snapshot final ao deletar
Exemplo:
finalDBSnapshotIdentifier: app-db-final-snapshot-2025-11-22
Campos Opcionais - Alta Disponibilidade e Replicação
Habilitar Multi-AZ (alta disponibilidade)
Benefícios:
- Failover automático em caso de falha (minutos)
- Replicação síncrona para integridade de dados
- ~50% de aumento de custo
Recomendado: true em produção:
multiAZ: true
Usar IAM para autenticação (ao invés de senha)
Exemplo:
enableIAMDatabaseAuthentication: true
Benefícios:
- Sem senha hardcoded
- Tokens temporários
- Auditoria automática
Campos Opcionais - Criptografia
Habilitar criptografia em repouso
Padrão: true (recomendado):
storageEncrypted: true
ARN da chave KMS da AWS para criptografia
Padrão: Chave gerenciada pela AWS (sem custo):
storageEncrypted: true
kmsKeyId: arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012
Campos Opcionais - Monitoramento e Otimização
Habilitar Performance Insights (análise detalhada)
Exemplo:
enablePerformanceInsights: true
Custo: ~$0.02/hora adicional
Habilitar Enhanced Monitoring (métricas do OS)
Exemplo:
enableEnhancedMonitoring: true
monitoringInterval: 60 # A cada 60 segundos
Custo: Baseado no intervalo
Intervalo do Enhanced Monitoring (segundos)
Opções: 0 (desabilitado), 1, 5, 10, 15, 30, 60:
monitoringInterval: 60
Campos Opcionais - Outros
Pares chave-valor para organização e billing
Exemplo:
tags:
Environment: production
Application: web-app
Team: backend
CostCenter: engineering
ManagedBy: infra-operator
O que acontece com a instância quando o CR é deletado
Opções:
Delete: Instância é deletada da AWSRetain: Instância permanece na AWS mas não gerenciadaOrphan: Remove apenas gerenciamento
Exemplo:
deletionPolicy: Retain # Para produção
Campos de Status
Após a instância ser criada, os seguintes campos de status são populados:
ARN completo da instância RDS
arn:aws:rds:us-east-1:123456789012:db:app-db-prod
Informações de conexão do banco de dados
Hostname do banco de dados para conexão
```
app-db-prod.c9akciq32.us-east-1.rds.amazonaws.com
```
Porta de conexão (padrão: 5432 PostgreSQL, 3306 MySQL)
Estado atual da instância
Valores possíveis:
creating- Criandoavailable- Disponível e prontodeleting- Sendo deletadomodifying- Configuração sendo alteradabacking-up- Backup em andamentomaintenance- Manutenção programadafailed- Erro na criação
Espaço alocado em GB
Versão do engine em execução
Se Multi-AZ está habilitado
true quando a instância está available e pronta
Timestamp da última sincronização com AWS
Exemplos
PostgreSQL RDS de Produção com Multi-AZ
Banco de dados para aplicação web com alta disponibilidade:
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: RDSInstance
metadata:
name: production-postgres
namespace: default
spec:
providerRef:
name: production-aws
# Identificação
dbInstanceIdentifier: myapp-db-prod
engine: postgres
engineVersion: "15.4"
# Classe e storage
dbInstanceClass: db.t3.small
allocatedStorage: 50
storageType: gp3
iops: 3000
storageThroughput: 250
# Credenciais
masterUsername: postgres
masterUserPasswordSecretRef:
name: db-password
key: password
# Rede
dbSubnetGroupName: private-subnet-group
vpcSecurityGroupRefs:
- name: rds-security-group
publiclyAccessible: false
# Alta Disponibilidade
multiAZ: true
deletionProtection: true
# Backups
backupRetentionPeriod: 30
preferredBackupWindow: "03:00-04:00"
preferredMaintenanceWindow: "sun:04:00-sun:05:00"
# Monitoramento
enablePerformanceInsights: true
# Segurança
storageEncrypted: true
# Tags
tags:
Environment: production
Application: myapp
Team: backend
CostCenter: engineering
deletionPolicy: Retain
RDS MySQL para Desenvolvimento
Banco de dados simples para desenvolvimento local:
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: RDSInstance
metadata:
name: dev-mysql
namespace: default
spec:
providerRef:
name: dev-aws
dbInstanceIdentifier: myapp-db-dev
engine: mysql
engineVersion: "8.0.35"
# Instância pequena para dev
dbInstanceClass: db.t3.micro
allocatedStorage: 20
storageType: gp3
masterUsername: admin
masterUserPasswordSecretRef:
name: dev-db-password
key: password
# Dev não precisa de Multi-AZ
multiAZ: false
deletionProtection: false
# Backups menos frequentes
backupRetentionPeriod: 7
tags:
Environment: development
Application: myapp
deletionPolicy: Delete
RDS com Read Replica
Banco de dados primário com replicação de leitura para analytics:
# Banco de dados primário
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: RDSInstance
metadata:
name: primary-db
namespace: default
spec:
providerRef:
name: production-aws
dbInstanceIdentifier: myapp-db-primary
engine: postgres
engineVersion: "15.4"
dbInstanceClass: db.m5.large
allocatedStorage: 100
storageType: gp3
masterUsername: postgres
masterUserPasswordSecretRef:
name: db-password
key: password
multiAZ: true
backupRetentionPeriod: 35
# Habilitar backups (necessário para réplicas)
backupRetentionPeriod: 7
tags:
Environment: production
Role: primary
deletionPolicy: Retain
---
# Read Replica (para analytics/reporting)
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: RDSInstance
metadata:
name: read-replica-db
namespace: default
spec:
providerRef:
name: production-aws
dbInstanceIdentifier: myapp-db-read-replica
# Criar a partir do banco de dados primário
replicateSourceDb: myapp-db-primary
# Mesmo engine, pode ser classe menor
dbInstanceClass: db.t3.small
# Não precisa configurar senha (herda do primário)
# Réplica em AZ diferente para HA
availabilityZone: us-east-1b
tags:
Environment: production
Role: read-replica
deletionPolicy: Delete
RDS com Criptografia e PITR Completo
Banco de dados crítico com máxima segurança e recuperação:
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: RDSInstance
metadata:
name: critical-database
namespace: default
spec:
providerRef:
name: production-aws
dbInstanceIdentifier: critical-db-prod
engine: postgres
engineVersion: "15.4"
dbInstanceClass: db.r5.xlarge # Memory optimized
allocatedStorage: 500
storageType: io2
iops: 20000
masterUsername: postgres
masterUserPasswordSecretRef:
name: critical-db-password
key: password
# VPC privada com segurança
dbSubnetGroupName: critical-subnet-group
vpcSecurityGroupRefs:
- name: critical-rds-sg
publiclyAccessible: false
# HA e proteção
multiAZ: true
deletionProtection: true
# Backups com PITR completo
backupRetentionPeriod: 35
preferredBackupWindow: "02:00-03:00"
skipFinalSnapshot: false
finalDBSnapshotIdentifier: critical-db-final-backup
# Criptografia com KMS
storageEncrypted: true
kmsKeyId: arn:aws:kms:us-east-1:123456789012:key/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
# Monitoramento completo
enablePerformanceInsights: true
enableEnhancedMonitoring: true
monitoringInterval: 1
# Autenticação IAM
enableIAMDatabaseAuthentication: true
# Manutenção
preferredMaintenanceWindow: "sun:03:00-sun:04:00"
tags:
Environment: production
CriticalData: "true"
BackupRequired: "true"
Compliance: "required"
deletionPolicy: Retain
RDS MariaDB para WordPress/CMS
Banco de dados para aplicação web tradicional:
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: RDSInstance
metadata:
name: wordpress-db
namespace: default
spec:
providerRef:
name: production-aws
dbInstanceIdentifier: wordpress-db
engine: mariadb
engineVersion: "10.6.14"
dbInstanceClass: db.t3.small
allocatedStorage: 50
storageType: gp3
masterUsername: wordpress
masterUserPasswordSecretRef:
name: wordpress-db-password
key: password
dbSubnetGroupName: web-subnet-group
vpcSecurityGroupRefs:
- name: wordpress-rds-sg
multiAZ: true
backupRetentionPeriod: 14
tags:
Environment: production
Application: wordpress
deletionPolicy: Retain
Verificação
Verificar Status via kubectl
Comando:
# Listar todas as instâncias RDS
kubectl get rdsinstances
# Obter informações detalhadas
kubectl get rdsinstance production-postgres -o yaml
# Monitorar criação em tempo real
kubectl get rdsinstance production-postgres -w
# Ver eventos e status
kubectl describe rdsinstance production-postgres
Verificar na AWS
AWS CLI:
# Listar instâncias RDS
aws rds describe-db-instances \
--query 'DBInstances[].{Identifier:DBInstanceIdentifier,Status:DBInstanceStatus,Engine:Engine,Class:DBInstanceClass}' \
--output table
# Obter detalhes completos
aws rds describe-db-instances \
--db-instance-identifier app-db-prod \
--output json | jq '.DBInstances[0]'
# Ver endpoint de conexão
aws rds describe-db-instances \
--db-instance-identifier app-db-prod \
--query 'DBInstances[0].Endpoint'
# Testar conexão (PostgreSQL)
psql -h app-db-prod.c9akciq32.us-east-1.rds.amazonaws.com \
-U postgres \
-d postgres
# Ver backups
aws rds describe-db-snapshots \
--db-instance-identifier app-db-prod
# Ver status multi-AZ
aws rds describe-db-instances \
--db-instance-identifier app-db-prod \
--query 'DBInstances[0].MultiAZ'
LocalStack:
# Para testes com LocalStack
export AWS_ENDPOINT_URL=http://localhost:4566
aws rds describe-db-instances
aws rds describe-db-instances \
--db-instance-identifier app-db-prod
psql (PostgreSQL):
# Conectar ao banco de dados
psql -h <endpoint> -U postgres -d postgres
# Ver usuários
\du
# Ver bancos de dados
\l
# Ver espaço usado
SELECT pg_database.datname,
pg_size_pretty(pg_database_size(pg_database.datname))
FROM pg_database;
# Desconectar
\q
mysql (MySQL/MariaDB):
# Conectar ao banco de dados
mysql -h <endpoint> -u admin -p
# Ver bancos de dados
SHOW DATABASES;
# Ver usuários
SELECT user, host FROM mysql.user;
# Ver espaço usado
SELECT table_schema,
ROUND(SUM(data_length+index_length)/1024/1024,2) AS size_mb
FROM information_schema.tables
GROUP BY table_schema;
# Sair
EXIT;
Output Esperado
Exemplo:
status:
dbInstanceArn: arn:aws:rds:us-east-1:123456789012:db:app-db-prod
dbInstanceStatus: available
endpoint:
address: app-db-prod.c9akciq32.us-east-1.rds.amazonaws.com
port: 5432
engine: postgres
engineVersion: "15.4"
dbInstanceClass: db.t3.small
allocatedStorage: 50
multiAZ: true
storageEncrypted: true
ready: true
lastSyncTime: "2025-11-22T20:45:22Z"
Solução de Problemas
RDS travado em creating por mais de 30 minutos
Sintomas: dbInstanceStatus: creating indefinidamente
Causas comuns:
- Subnet group não existe ou é inválido
- Security group não encontrado
- Cota de instâncias RDS atingida
- Problema de conectividade com AWS
Soluções:
# Verificar status detalhado
kubectl describe rdsinstance app-database
# Ver logs do operator
kubectl logs -n infra-operator-system \
deploy/infra-operator-controller-manager \
--tail=100 | grep -i rds
# Verificar se subnet group existe
aws rds describe-db-subnet-groups \
--db-subnet-group-name private-subnet-group
# Verificar se AWSProvider está ready
kubectl get awsprovider
kubectl describe awsprovider production-aws
# Forçar sincronização
kubectl annotate rdsinstance app-database \
force-sync="$(date +%s)" --overwrite
# Último recurso: deletar e recriar (com Retain)
kubectl patch rdsinstance app-database \
--type merge \
-p '{"spec":{"deletionPolicy":"Retain"}}'
Timeout de conexão ao conectar no banco de dados
Sintomas: psql: could not translate host name ou Connection refused
Causas comuns:
- Security group não permite conexão (porta bloqueada)
- Banco de dados não é publicamente acessível e está conectando de fora da VPC
- Hostname/endpoint incorreto
- Rede não roteada corretamente
Soluções:
# Obter endpoint correto
aws rds describe-db-instances \
--db-instance-identifier app-db-prod \
--query 'DBInstances[0].Endpoint'
# Verificar se security group permite ingress
aws ec2 describe-security-groups \
--group-ids sg-0123456789abcdef0 \
--query 'SecurityGroups[0].IpPermissions'
# DEVE ter regra como:
# IpProtocol: tcp, FromPort: 5432, ToPort: 5432
# CidrIp: 10.0.0.0/16 (sua VPC)
# Se conectando de fora da VPC:
# 1. Habilitar publiclyAccessible (não recomendado)
# 2. Ou usar bastion/jump host
# 3. Ou usar VPN
# Testar com telnet/nc
nc -zv app-db-prod.c9akciq32.us-east-1.rds.amazonaws.com 5432
# Testar com psql verbose
psql -h app-db-prod.c9akciq32.us-east-1.rds.amazonaws.com \
-U postgres \
-d postgres \
-v
# Se usando Multi-AZ, failover pode estar em andamento
# Tente novamente em 5 minutos
Espaço em disco esgotado (storage full)
Sintomas: Erro Disk full ao executar queries, aplicação lenta
Causas:
- Dados cresceram além do esperado
- Logs acumulados ou backups
- Falta de limpeza de dados antigos
Soluções:
# Ver espaço disponível
aws rds describe-db-instances \
--db-instance-identifier app-db-prod \
--query 'DBInstances[0].AllocatedStorage'
# Aumentar storage (pode levar minutos)
kubectl patch rdsinstance app-database \
--type merge \
-p '{"spec":{"allocatedStorage":100}}'
# Ver progresso
kubectl get rdsinstance app-database -w
# Se PostgreSQL, limpar espaço
# Conectar ao banco de dados:
psql -h <endpoint> -U postgres -d postgres
# Vacuum full (recuperar espaço)
VACUUM FULL;
VACUUM ANALYZE;
# Se MySQL, otimizar tabelas
mysql -h <endpoint> -u admin -p
OPTIMIZE TABLE table_name;
# Ver tamanho do banco de dados
SELECT pg_database.datname,
pg_size_pretty(pg_database_size(pg_database.datname))
FROM pg_database;
Custos altos de RDS
Sintomas: Conta AWS com cobranças inesperadas de RDS
Causas comuns:
- Classe de instância muito grande
- IOPS provisionados altos
- Muitos backups retidos
- Replicação cross-region
Soluções:
# Calcular custo atual
# Use AWS Pricing Calculator
# t3.small: ~$0.034/hora * 730 = ~$25/mês
# gp3 storage: ~$0.12/GB/mês
# Reduzir classe (se possível)
kubectl patch rdsinstance app-database \
--type merge \
-p '{"spec":{"dbInstanceClass":"db.t3.micro"}}'
# Reduzir retenção de backup
kubectl patch rdsinstance app-database \
--type merge \
-p '{"spec":{"backupRetentionPeriod":7}}'
# Deletar snapshots antigos desnecessários
aws rds delete-db-snapshot \
--db-snapshot-identifier app-db-snapshot-old
# Para dev, deletar após uso
kubectl delete rdsinstance dev-database
Backup falha ou demora muito
Sintomas: Status de backup travado em backing-up por horas
Causas:
- Banco de dados muito grande
- IO saturado durante backup
- Muitas transações durante backup
Soluções:
# Ver status de backup
aws rds describe-db-instances \
--db-instance-identifier app-db-prod \
--query 'DBInstances[0].LatestRestorableTime'
# Ver snapshots completos
aws rds describe-db-snapshots \
--db-instance-identifier app-db-prod
# Aumentar janela de backup
kubectl patch rdsinstance app-database \
--type merge \
-p '{"spec":{"preferredBackupWindow":"02:00-04:00"}}'
# Aumentar IOPS para performance de backup
kubectl patch rdsinstance app-database \
--type merge \
-p '{"spec":{"iops":5000}}'
# Criar snapshot manual
aws rds create-db-snapshot \
--db-instance-identifier app-db-prod \
--db-snapshot-identifier manual-backup-$(date +%Y%m%d-%H%M%S)
Failover Multi-AZ lento ou falha
Sintomas: Após falha, aplicação offline por 5+ minutos
Causa: Failover automático pode demorar, especialmente se Multi-AZ não configurado corretamente
Soluções:
# Verificar se Multi-AZ está habilitado
aws rds describe-db-instances \
--db-instance-identifier app-db-prod \
--query 'DBInstances[0].MultiAZ'
# Habilitar se não estiver
kubectl patch rdsinstance app-database \
--type merge \
-p '{"spec":{"multiAZ":true}}'
# Testar failover manualmente
# CUIDADO: Causa downtime!
aws rds reboot-db-instance \
--db-instance-identifier app-db-prod \
--force-failover
# Ver progresso de reboot
aws rds describe-db-instances \
--db-instance-identifier app-db-prod \
--query 'DBInstances[0].DBInstanceStatus'
# Implementar retry na aplicação
# Usar connection pooling
# Configurar failover no nível da aplicação
Read Replica não sincronizando ou com lag
Sintomas: Réplica mostra dados desatualizados, não consegue conectar
Causas:
- Lag de replicação (atraso de rede)
- Banco de dados primário sob pressão de IO
- Problemas de rede
Soluções:
# Ver lag de réplica
aws rds describe-db-instances \
--db-instance-identifier myapp-db-read-replica \
--query 'DBInstances[0].StatusInfos'
# Aumentar classe de réplica se estiver subprovisionada
kubectl patch rdsinstance read-replica-db \
--type merge \
-p '{"spec":{"dbInstanceClass":"db.t3.small"}}'
# Aumentar IOPS no primário
kubectl patch rdsinstance primary-db \
--type merge \
-p '{"spec":{"iops":5000}}'
Performance degradada (queries lentas)
Sintomas: Queries normais ficam lentas, CPU/IO alto
Causas:
- Falta de índices
- Plano de query subótimo
- Falta de memória/CPU
- Locks de transações
Soluções:
# Habilitar Performance Insights
kubectl patch rdsinstance app-database \
--type merge \
-p '{"spec":{"enablePerformanceInsights":true}}'
# Usar console AWS Performance Insights para análise
# Aumentar memória/CPU se necessário
kubectl patch rdsinstance app-database \
--type merge \
-p '{"spec":{"dbInstanceClass":"db.m5.large"}}'
# Conectar e analisar queries
psql -h <endpoint> -U postgres -d postgres
# Ver queries lentas (PostgreSQL)
SELECT query, calls, mean_exec_time, max_exec_time
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;
# Ver índices faltando
SELECT schemaname, tablename
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY schemaname, tablename;
# Criar índices apropriados
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_orders_date ON orders(created_at);
Erro ao deletar banco de dados (finalizer travado)
Sintomas: kubectl delete rdsinstance pendente indefinidamente
Causa: Finalizer não consegue deletar snapshot final ou banco de dados
Soluções:
# Ver detalhes
kubectl describe rdsinstance app-database
# Ver finalizers
kubectl get rdsinstance app-database -o yaml | grep finalizers
# Opção 1: Mudar deletionPolicy antes de deletar
kubectl patch rdsinstance app-database \
--type merge \
-p '{"spec":{"deletionPolicy":"Retain"}}'
# Então deletar
kubectl delete rdsinstance app-database
# Opção 2: Deletar snapshot final manualmente
aws rds delete-db-snapshot \
--db-snapshot-identifier app-db-final-backup
# Então forçar delete do CR
kubectl patch rdsinstance app-database \
-p '{"metadata":{"finalizers":[]}}' \
--type=merge
# Opção 3: Manter snapshot final, apenas remover CR
kubectl patch rdsinstance app-database \
--type merge \
-p '{"spec":{"skipFinalSnapshot":true}}'
kubectl delete rdsinstance app-database
Boas Práticas
- Habilite Multi-AZ para produção — Failover automático em minutos, ~50% de custo a mais mas essencial para dados críticos, teste failover regularmente
- Habilite criptografia em todos os lugares — Criptografia de storage (AES-256), AWS KMS para chaves customizadas, SSL/TLS para conexões, criptografia de backup para compliance
- Configure retenção de backup apropriada — 7-35 dias dependendo da criticidade, mínimo 14 dias para produção, PITR até 35 dias, teste restore regularmente
- Restrinja acesso de security group — Apenas IPs/SGs necessários, nunca 0.0.0.0/0, segregue dev/staging/prod, audite regras regularmente
- Use apenas subnets privadas — Nunca publicamente acessível em produção, use NAT gateway para outbound, bastion/jump host para acesso admin
- Habilite monitoramento e insights — Performance Insights para tuning, alertas CloudWatch para anomalias, monitore métricas de CPU/Storage/IOPS
- Ajuste parameter groups — Customize configurações por engine (shared_buffers, work_mem para PostgreSQL), documente razão das mudanças, teste em dev primeiro
- Tagueie todos os recursos — Environment (dev/staging/prod), application, cost center, owner/team, flag de backup required
- Dimensione instâncias corretamente — Comece pequeno e monitore crescimento, use t3/t4g para cargas variáveis, m5 para cargas de produção previsíveis
- Otimize custos — Delete dev/staging após uso, retenção de backup apropriada, reserved instances para produção
- Planeje disaster recovery — Read replicas para DR regional, snapshots em outra região, documente RTO/RPO, automatize failover
- Habilite audit e compliance — CloudTrail para chamadas API, CloudWatch Logs para queries, autenticação IAM de banco de dados
- Otimize queries — Performance Insights para bottlenecks, logs de slow query, estratégia de índice apropriada, connection pooling na app
Casos de Uso
1. Aplicação Web Transacional
E-commerce ou SaaS com muitas transações pequenas:
dbInstanceClass: db.t3.small
allocatedStorage: 100
multiAZ: true
backupRetentionPeriod: 30
# Índices em user_id, order_id, timestamps
2. E-commerce com Carrinhos e Pedidos
Dados de alto volume com transações críticas:
dbInstanceClass: db.m5.large
allocatedStorage: 500
storageType: io1
iops: 10000
multiAZ: true
backupRetentionPeriod: 35
# Read replica para analytics
3. CMS (WordPress, Drupal)
Aplicações web com conteúdo dinâmico:
engine: mysql # ou mariadb
dbInstanceClass: db.t3.small
allocatedStorage: 50
multiAZ: true
enableCloudwatchLogsExports: [slowquery, error]
4. ERP/CRM com Alta Concorrência
Múltiplos usuários acessando simultaneamente:
dbInstanceClass: db.m5.2xlarge
allocatedStorage: 1000
storageType: io2
iops: 64000
multiAZ: true
backupRetentionPeriod: 35
enableEnhancedMonitoring: true