RDS Snapshot → S3: Diagnosticar y resolver un Export deshabilitado
Antes de entrar en el por qué y el cómo, esto es lo que entregamos:
⏱️ Diagnóstico claro en menos de un minuto (sin adivinar en la consola)
🫥 Camino no intrusivo: solo instancia temporal (no tocamos tu RDS actual)
🔐 Export que funciona, con la forma correcta de IAM/KMS
🧩 Comandos copy-paste para tu runbook o CI
Por qué el Export está deshabilitado 🔒
El bloqueo más frecuente es simple: el Snapshot fue tomado desde una instancia con almacenamiento magnético (standard) 🧲. Los Snapshots con ese linaje no son elegibles para Export. La consola es ambigua; el CLI te muestra exactamente qué pasa 🧪.Console vs CLI: lo que realmente ayuda ⚖️
| ❌ Solo consola | ✅ Runbook con CLI | |
|---|---|---|
| Feedback | Botón gris, sin motivo claro 😶🌫️ | Estado y campos explícitos (StorageType, errores) 🧾 |
| Acciones | Prueba y error 🎯 | Flujo determinístico (restore → Snapshot → export) ▶️ |
| Repeatability | Pasos manuales 🧱 | Scriptable & auditable 🤖 |
Diagnóstico rápido (CLI) 🕵️♂️
Revisar el tipo de almacenamiento del Snapshotaws rds describe-db-snapshots --db-snapshot-identifier <SNAPSHOT_ID> --query 'DBSnapshots[0].[DBSnapshotIdentifier,Engine,EngineVersion,StorageType,Encrypted,Status]' --output table
StorageType = standard, ese Snapshot no se va a exportar.Arquitectura a simple vista 🧭
El flujo es directo: restore del Snapshot → instancia gp3 temporal → nuevo Snapshot → Export a S3 con un IAM Role asumido por export.rds.amazonaws.com.

Esto muestra:
🔁 Dónde cambia el linaje de almacenamiento (magnético → gp3)
🔗 Cómo el servicio de export asume un IAM Role para escribir en un S3 Bucket
🧰 Las piezas mínimas (RDS, S3, IAM, KMS opcional)
Playbook (sin cambios sobre tu RDS existente) 📘
🧱 Restore del Snapshot en gp3 (instancia temporal)
# Vars
export REGION=<REGION>
export TEMP_DB_ID=<TEMP_DB_ID>
export SNAPSHOT_ID=<SNAPSHOT_ID>
export SUBNET_GROUP=<DB_SUBNET_GROUP>
export SG_ID=<SECURITY_GROUP_ID>
aws rds restore-db-instance-from-db-snapshot --region $REGION --db-instance-identifier $TEMP_DB_ID --db-snapshot-identifier $SNAPSHOT_ID --storage-type gp3 --no-publicly-accessible --db-subnet-group-name $SUBNET_GROUP --vpc-security-group-ids $SG_ID
📸 Crear un nuevo Snapshot (ahora SSD)
export NEW_SNAPSHOT_ID=${TEMP_DB_ID}-exportable-$(date +%Y%m%d)
aws rds create-db-snapshot --db-snapshot-identifier $NEW_SNAPSHOT_ID --db-instance-identifier $TEMP_DB_ID
# Sanity check
aws rds describe-db-snapshots --db-snapshot-identifier $NEW_SNAPSHOT_ID --query 'DBSnapshots[0].[DBSnapshotIdentifier,StorageType,Status]' --output table
🧷 Export a S3 (el wiring que importa)
✅ Requerimientos
🌍 S3 Bucket en la misma región que el Snapshot
🤝 IAM Role para Export con trust en
export.rds.amazonaws.com📝 El Role puede escribir en el S3 Bucket (PutObject, ListBucket, GetBucketLocation, etc.)
🔑 Si usás KMS, la KMS Key está Enabled y permite al servicio de export
🛑 Sin SCP de la Organization bloqueando
rds:StartExportTask
👇 Trust Policy (asumida por el servicio de export)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "export.rds.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
📜 Minimal Permissions Policy (S3 + KMS)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject*",
"s3:AbortMultipartUpload",
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:DeleteObject*"
],
"Resource": [
"arn:aws:s3:::<BUCKET>",
"arn:aws:s3:::<BUCKET>/*"
]
},
{
"Effect": "Allow",
"Action": [
"kms:CreateGrant",
"kms:DescribeKey",
"kms:Encrypt",
"kms:GenerateDataKey*"
],
"Resource": "<KMS_KEY_ARN>"
}
]
}
🧾 Bucket Policy (allow explícito para el Role)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowRDSExportWrite",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<ACCOUNT_ID>:role/<RDS_EXPORT_ROLE>"
},
"Action": [
"s3:PutObject",
"s3:AbortMultipartUpload",
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::<BUCKET>",
"arn:aws:s3:::<BUCKET>/*"
]
}
]
}
▶️ Iniciar el Export
aws rds start-export-task \
--export-task-identifier export-$NEW_SNAPSHOT_ID \
--source-arn arn:aws:rds:$REGION:<ACCOUNT_ID>:snapshot:$NEW_SNAPSHOT_ID \
--s3-bucket-name <BUCKET> \
--s3-prefix rds-exports/$NEW_SNAPSHOT_ID/ \
--iam-role-arn arn:aws:iam::<ACCOUNT_ID>:role/<RDS_EXPORT_ROLE> \
--kms-key-id <KMS_KEY_ARN>
👀 Observar la ejecución
aws rds describe-export-tasks \
--filters Name=export-task-identifier,Values=export-$NEW_SNAPSHOT_ID \
--query 'ExportTasks[0].[Status,ProgressPercentage,S3Bucket,S3Prefix,FailureCause]' \
--output table
Troubleshooting (triage rápido) 🧯
🔎 AccessDenied → revisá SCP de la Organization, permisos del caller y la Policy del IAM Role
🧱 KMSKeyNotAccessible → KMS Key deshabilitada o algún Deny afectando
export.rds.amazonaws.com🗺️ BucketRegionError → Snapshot y S3 Bucket deben estar en la misma región
🤝 Shared snapshot → alinear accesos/grants de KMS para cross-account
💡 Lecciones aprendidas
- No dependas de la consola para explicar el “por qué” — el CLI es tu fuente de verdad
- Prevenilo de entrada: estandarizá gp3 en tus módulos y bloqueá
standarden CI - Mantené un export Role preaprobado por cuenta/región para evitar IAM ad-hoc
🙋♂️ ¿Necesitás ayuda con esto?
¿Necesitás ayuda manteniendo tu RDS — Backups restaurables, governance de Snapshots, exports predecibles, etc. ?
Implementamos estos patrones en múltiples cuentas y regiones de AWS — repetibles, auditables y de bajo mantenimiento.
💬 Hablemos en LinkedIn — encantado de ayudar o intercambiar ideas.
