Autor: Yerry Maycol Tarqui Collatupa

Trabajo: NoSQL Backup Strategy

En este artículo se documentan el diseño, la automatización y la validación de una estrategia de respaldo y recuperación para una aplicación con Azure Cosmos DB, una base de datos NoSQL, con respaldos cifrados en Azure Blob Storage y flujos de GitHub Actions.

Introducción

Contar con una base de datos en la nube no elimina el riesgo de perder información: un borrado accidental, un error de la aplicación o una operación equivocada pueden destruir datos que ningún servicio recupera por sí solo. Por eso una estrategia de respaldo no se limita a generar copias; también debe definir dónde se guardan, cómo se protegen, cuánto tiempo se conservan y, sobre todo, cómo se comprueba que pueden restaurarse.

A partir de ese problema se desarrolló NoSQL Backup Strategy, un proyecto práctico que construye una aplicación de productos con ASP.NET Core y Azure Cosmos DB, y una herramienta propia, BackupTool, que genera respaldos cifrados de la base y los restaura con verificación. El proyecto integra Terraform para describir la infraestructura como código, GitHub Actions para automatizar el despliegue, el respaldo diario y la recuperación, Azure Blob Storage para conservar las copias y Azure App Service para publicar la aplicación en una nube pública.

La implementación se realizó de forma progresiva. Primero se construyeron la aplicación y la herramienta de respaldo; después se definió la infraestructura y se automatizó su creación y el despliegue. Con la aplicación publicada se generó un respaldo, se simuló un desastre que eliminó todos los datos y se restauraron desde la copia cifrada. Esta publicación documenta las evidencias principales del trabajo.

Estrategia de respaldo

La estrategia combina tres capas complementarias. La primera es el respaldo nativo de Cosmos DB, con política Periodic cada 240 minutos y retención de 48 horas, definida en Terraform. La segunda es un respaldo lógico propio: BackupTool lee todos los documentos, los empaqueta en un archivo JSON con un manifiesto (fecha, base, contenedor y cantidad), calcula el SHA-256 de los datos, los comprime con GZip y los cifra con AES-256-GCM, con una clave derivada con PBKDF2. El archivo resultante se guarda en un contenedor privado de Blob Storage. La tercera es la retención automática: una política de ciclo de vida elimina los respaldos con más de 30 días.

La recuperación sigue el camino inverso: descarga el respaldo, lo descifra, restaura los documentos en el contenedor indicado y verifica que la cantidad restaurada coincida con la del manifiesto. Si no coincide, el proceso termina con error.

Arquitectura de la solución

La aplicación es una página web con una API REST alojada en Azure App Service, que usa Azure Cosmos DB en modo serverless con la API NoSQL. Los respaldos no dependen de la aplicación: los flujos de GitHub Actions ejecutan BackupTool, que lee la base, cifra los datos y los sube a Blob Storage, y que también los restaura cuando se necesita.

Arquitectura de respaldo y recuperación de una base NoSQL en AzureFigura 1. Arquitectura de la solución: aplicación en App Service, Cosmos DB, BackupTool ejecutado por GitHub Actions y respaldos cifrados en Blob Storage.

Creación de los proyectos

La solución tiene dos proyectos .NET dentro del mismo repositorio. El primero, ProductosApi, es la aplicación web creada con la plantilla web mínima de ASP.NET Core.

Creación del proyecto ProductosApi con dotnet new webFigura 2. Creación del proyecto ProductosApi con la plantilla web mínima de ASP.NET Core.

El segundo, BackupTool, es una aplicación de consola. A este proyecto se agregaron los paquetes Microsoft.Azure.Cosmos y Newtonsoft.Json, necesarios para leer Cosmos DB, y Azure.Storage.Blobs, para escribir en Blob Storage.

Paquetes del proyecto BackupToolFigura 3. Paquetes instalados en el proyecto BackupTool.

Código de la solución

En Program.cs de la API se configuró el cliente de Cosmos DB con la configuración de la aplicación, se creó la base y el contenedor si no existen y se definieron los endpoints: /health para comprobar el estado y /api/productos para listar, consultar, crear, actualizar y eliminar productos, además de un endpoint que carga productos de ejemplo. La llave de acceso no se escribe en el código, sino que se entrega como configuración.

Archivo Program.cs de la API de productosFigura 4. Endpoints de la API definidos en Program.cs.

El acceso a los datos se encapsuló en la clase ProductosRepo, que concentra las consultas SQL de Cosmos DB y las operaciones de lectura, creación, reemplazo, eliminación y conteo de documentos.

Clase ProductosRepo con el acceso a Cosmos DBFigura 5. Clase ProductosRepo para el acceso al contenedor de Cosmos DB.

BackupTool implementa los comandos backup, restore, listar y destruir. El respaldo consulta todos los documentos, arma el manifiesto, calcula el SHA-256, comprime, cifra con AES-GCM y sube el archivo al contenedor backups con su cantidad y su huella como metadatos.

Código de respaldo y cifrado de BackupToolFigura 6. Generación del respaldo cifrado en BackupTool.

La restauración descarga el respaldo indicado o el más reciente, lo descifra, lo escribe en el contenedor de destino y verifica la cantidad de documentos. El comando listar muestra los respaldos almacenados, y destruir, que exige el parámetro de confirmación, permite simular un desastre.

Código de restauración, listado y destrucción de BackupToolFigura 7. Restauración con verificación, listado de respaldos y comando de destrucción.

Infraestructura como código

La infraestructura se describió con Terraform en el archivo main.tf: la cuenta de Cosmos DB serverless con la política de respaldo Periodic, la base productosdb y el contenedor productos, la cuenta de Storage con el contenedor privado backups y su política de retención de 30 días, el plan de App Service gratuito (F1) y la aplicación web con .NET 10. El estado de Terraform se guarda en una cuenta de Azure Storage.

Archivo main.tf con los recursos de TerraformFigura 8. Recursos de Azure definidos con Terraform en main.tf.

Automatización con GitHub Actions

El flujo backup.yml genera el respaldo. Inicia sesión en Azure, obtiene las conexiones de Cosmos DB y de Storage y enmascara los secretos en los registros, compila BackupTool, genera el respaldo cifrado y lista los respaldos almacenados. La frase de cifrado es un secreto del repositorio.

Workflow backup.yml de GitHub ActionsFigura 9. Flujo backup.yml que genera el respaldo cifrado.

Este flujo se ejecuta de forma automática todos los días. En el bloque schedule se define la expresión cron 17 10 * * *, que lo programa a las 10:17 UTC (5:17 a. m. en Perú), sin intervención manual; además se mantiene workflow_dispatch para poder lanzarlo a demanda y realizar pruebas.

Programación diaria del respaldo en backup.ymlFigura 10. Bloque schedule con la expresión cron y el disparador workflow_dispatch en backup.yml.

Para la recuperación se creó restore.yml, que recibe el nombre del respaldo (o el último) y el contenedor de destino, restaura los datos y verifica el resultado. Como complemento, desastre.yml elimina todos los productos solo si se escribe la confirmación BORRAR, y sirve para demostrar la recuperación.

Workflow restore.yml de GitHub ActionsFigura 11. Flujo restore.yml que restaura y verifica los datos.

Creación de la infraestructura y despliegue

La infraestructura se creó ejecutando el flujo infra.yml desde la CLI de GitHub, y Terraform creó los recursos de Azure.

Flujo infra.yml en ejecuciónFigura 12. Ejecución del flujo infra.yml que crea la infraestructura.

Con la infraestructura lista se ejecutó deploy.yml, que compila y publica la aplicación, la despliega en App Service y comprueba el endpoint /health.

Flujo deploy.yml en ejecuciónFigura 13. Ejecución del flujo deploy.yml que publica la aplicación.

Aplicación publicada

La aplicación quedó disponible en una URL pública de Azure App Service. Al ingresar se comprobó que se conectaba a Cosmos DB y que aún no tenía productos.

Aplicación de productos publicada en Azure App ServiceFigura 14. Aplicación publicada en Azure, sin productos.

El botón de ejemplos cargó cinco productos, que se guardaron como documentos en Cosmos DB.

Productos de ejemplo guardados en Cosmos DBFigura 15. Productos de ejemplo cargados desde la aplicación publicada.

Se agregó un producto más desde el formulario, con lo que la base quedó con seis documentos.

Producto nuevo agregado desde el formularioFigura 16. Seis productos guardados en Cosmos DB.

Respaldo

Para comprobar el flujo sin esperar a la ejecución programada de las 10:17 UTC, se lanzó backup.yml de forma manual. El flujo terminó con estado exitoso en menos de un minuto.

Ejecución exitosa del flujo backup.ymlFigura 17. Flujo backup.yml finalizado correctamente.

El registro del paso que genera el respaldo muestra los seis documentos respaldados, el nombre del archivo cifrado, su tamaño, el SHA-256 de los datos y el mensaje BACKUP OK.

Registro del paso que genera el respaldo cifradoFigura 18. Seis documentos respaldados y archivo cifrado generado.

En el portal de Azure se comprobó que el archivo cifrado está en el contenedor privado backups de la cuenta de almacenamiento.

Archivo cifrado en el contenedor backups de Azure StorageFigura 19. Respaldo cifrado almacenado en el contenedor privado de Blob Storage.

Simulación de desastre

Para demostrar la recuperación se lanzó desastre.yml con la confirmación BORRAR, que eliminó todos los productos de la base de datos.

Ejecución exitosa del flujo desastre.ymlFigura 20. Flujo desastre.yml que elimina los productos.

Al actualizar la aplicación publicada se comprobó que ya no tenía productos: el pie de página indica cero productos guardados.

Aplicación sin productos después del desastreFigura 21. Aplicación sin datos tras la simulación de desastre.

Recuperación

Se lanzó restore.yml con el último respaldo y como destino el contenedor productos, el que usa la aplicación. El flujo terminó con estado exitoso en 45 segundos.

Ejecución exitosa del flujo restore.ymlFigura 22. Flujo restore.yml finalizado correctamente.

El registro muestra el respaldo utilizado, su fecha, el mismo SHA-256 del respaldo original, los seis documentos restaurados y el mensaje VERIFICACION OK.

Registro del paso que restaura y verificaFigura 23. Restauración verificada: seis documentos recuperados.

Al actualizar la aplicación, los seis productos volvieron a aparecer, con lo que se comprobó que la estrategia permite recuperar los datos después de un desastre.

Aplicación con los seis productos recuperadosFigura 24. Productos recuperados desde el respaldo cifrado.

Repositorio público

Todo el trabajo está en un repositorio público de GitHub que contiene el código de la aplicación y de BackupTool, la infraestructura de Terraform, los flujos de GitHub Actions y las capturas del proceso. Las llaves de acceso y la frase de cifrado no forman parte del repositorio.

Repositorio público del proyecto en GitHubFigura 25. Repositorio público con el flujo de integración en verde.

Flujos ejecutados en GitHub ActionsFigura 26. Ejecuciones de los flujos de infraestructura, despliegue, respaldo, desastre y restauración.

Resultados

La implementación permitió comprobar un ciclo completo de protección y recuperación de datos: se respaldaron seis documentos, se eliminaron todos los productos y se restauraron desde el último respaldo cifrado, con verificación de la cantidad y del SHA-256 de los datos. Toda la solución se crea y se opera desde el repositorio: la infraestructura con Terraform, la aplicación con un flujo de despliegue y los procedimientos de respaldo y recuperación con flujos que pueden ejecutarse en cualquier momento.

Componente Validación Resultado
Aplicación ASP.NET Core Publicada en App Service y conectada a Cosmos DB Seis productos guardados
Respaldo cifrado backup.yml y BackupTool Seis documentos respaldados
Blob Storage Contenedor privado backups Archivo cifrado almacenado
Programación cron 17 10 * * * (diario, 10:17 UTC) Configurada
Desastre desastre.yml con confirmación BORRAR Cero productos
Restauración restore.yml con el último respaldo VERIFICACION OK
Aplicación recuperada Consulta de la aplicación publicada Seis productos
Repositorio público Código, infraestructura y flujos Publicado

Conclusiones

Un respaldo es útil solo si se puede restaurar: por eso cada recuperación verifica la cantidad de documentos y el SHA-256 de los datos.

Cifrar el respaldo antes de subirlo protege los datos aunque alguien acceda al contenedor de Blob Storage, y la política de ciclo de vida evita acumular archivos antiguos.

Combinar el respaldo nativo de Cosmos DB con un respaldo lógico propio da dos vías de recuperación: una administrada por la plataforma y otra bajo control del equipo, que además puede restaurarse en otro contenedor.

GitHub Actions automatizó el respaldo diario, el despliegue y los procedimientos de recuperación, lo que reduce los pasos manuales y los errores.

La combinación de Cosmos DB serverless, el plan F1 de App Service y un almacenamiento pequeño permitió publicar la solución en una nube pública con un costo mínimo.

Enlaces del proyecto

Repositorio público: tg2-nosql-backup-yerrytc en GitHub

Aplicación publicada: Abrir la aplicación en Azure

Nota: La aplicación está desplegada en el plan gratuito F1 de Azure App Service, por lo que puede tardar hasta un minuto en responder después de un periodo de inactividad. Una vez iniciada, funciona con normalidad.

Video de demostración: Ver en YouTube (4 min 32 s)