Backups en MongoDB con AWS Lambda y S3

Tener copias de seguridad de los datos es importante. Muy importante. Seguramente no caigamos en la cuenta de lo fundamental que es hasta que necesitamos echar mano de una de ellas para recuperación en caso de desastre.

Si bien es cierto que MongoDB ofrece mecanismos de seguridad, como utilizar ReplicaSet, para ofrecer una cierta tolerancia a fallos, el realizar backups periódicos permite tener una capa de protección adicional frente a estos desastres. Ni siquiera grandes empresas del sector están exentas de errores (como sucedió recientemente con GitLab), y tener un backup externo de los datos puede resultar de utilidad.

La solución que presentamos está basada en el software de Amazon Web Services. Utilizaremos AWS Lambda para configurar una función que extraiga los datos de MongoDB, los comprima en un archivo ZIP y los suba a un contenedor de S3.

Evidentemente, este mecanismo no es válido para todos los usos de MongoDB. Si el volumen de datos o la cantidad de operaciones que se realizan es muy alta, este mecanismo de backups sería inapropiado. En ese caso hay otros mecanismos de seguridad más avanzados, algunos ofrecidos por el equipo de MongoDB como, por ejemplo, dentro de un ReplicaSet, tener miembros ocultos o miembros con delay. Vamos a ver alguno de ellos.

El sistema tradicional: Utilizar una instancia de EC2

Lo primero que se me vino a la cabeza cuando pensé en hacer un backup periódico de una base de datos de MongoDB, fue utilizar una instancia de EC2 para generar el backup (a través de mongodump) y subirlo a un contenedor de S3.

Como se trata de una operación muy sencilla, y que apenas consume recursos, desde la consola de AWS, se contrata la instancia más pequeña y barata posible (una t2.nano es más que suficiente) y se programa, a través de un cronjob, el backup de tus base de datos. En este link encontrarás detalla una solución completa.

Muy interesantes, además, los primeros comentarios en los que se explica cómo descargarse los backups realizados y los cambios que hay que hacer para que funcione con una base de datos que requiera autenticación.

Aunque a priori esta solución es perfecta, enseguida vemos un problema. Hemos reservado una instancia entera de AWS y realmente va a estar trabajando un par de minutos al día como mucho.

Aquí es donde entra en escena el servicio de AWS Lambda que, como dicen los propios de Amazon, permite “run code, not servers”.

Pasándose a serverless con AWS Lambda

Desde AWS Lambda podemos programar una función con node.js que gestione la creación de backup sin necesidad de usar instancias de EC2. Para empezar, por supuesto, hay que dirigirse a la sección de Lambda y proceder a crear una nueva función.

Aparecerán los distintos lenguajes de programación a los que AWS da soporte, así como varias funciones predefinidas para ir empezando. En este caso, se trabajará con node.js 6.10, disponible desde finales de marzo de 2017.

Como necesitamos archivos binarios de MongoDB para poder realizar el backup, no podemos utilizar ninguna de las blueprint que AWS nos ofrece, así que elegiremos “Blank Function”.

Tras confirmar nuestra selección, aparece una vista para configurar “triggers”. En AWS Lambda se programan funciones, pero, ¿cuándo se invocan estas funciones? Cuando así lo indique el trigger que vamos a configurar a continuación. Para realizar backups periódicos de MongoDB, el más apropiado es “Cloud Watch Events – Schedule”.

Por sencillez seleccionaremos la opción de backups diarios ya definida en el selector, aunque sería posible indicar, a través de un cron, la frecuencia con la que queremos realizar los backups.

Finalmente llegamos al panel de configuración de la función, en el que podemos escribir la que nos interese programar y algunos ajustes adicionales. Aquí nos encontramos con un pequeño obstáculo: como la función que vamos a programar tiene dependencias externas, no podemos simplemente escribirla.

Es necesario subirla como un archivo ZIP al gestor de funciones. Es más, como el archivo ZIP que generamos es demasiado grande, tampoco se puede subir directamente a AWS Lambda, sino que hay que hacerlo a través de S3.

La función que vamos a subir está disponible en este repositorio.

En el README del repositorio se detallan los pasos a seguir para subirla correctamente a S3.

Una vez esté subida la función a S3, es necesario copiar la URL del archivo y ponerla en la configuración de AWS Lambda. También se deben configurar las variables de entorno definidas: MONGO_URL y S3_PATH para que sus valores sean, respectivamente, la base de datos de MongoDB de la que se va a hacer el backup, y el contenedor de S3 en el que se van a almacenar los backups.

Además de esto, tenemos que cambiar la configuración por defecto de AWS Lambda, en lo relativo a la llamada a la función, en concreto hay 3 aspectos que seguramente debamos adaptar a nuestro caso:

  • Timeout: Por defecto las funciones de AWS Lambda tienen un tiempo para completarse de 3 segundos. Es poco probable que sea tiempo suficiente para todo el proceso de backup de la base de datos, por lo que es recomendable ampliarlo a un periodo mayor. El valor exacto dependerá del volumen de datos de la base de datos.
  • Memoria: Por defecto AWS Lambda ejecuta las funciones con 128 MB de RAM. Según el volumen de la base de datos de la que queramos hacer el backup, puede que no sea memoria suficiente. Por suerte, se puede ampliar la memoria que utiliza desde la propia interfaz de AWS.
  • Permisos: La función que hemos programado hace una subida del archivo ZIP con el backup a S3 de forma automática, por lo que es importante que el proceso que lo ejecuta tenga permisos de escritura en el bucket de S3 en que se estén haciendo las copias. Para modificar los roles y permisos, es necesario acceder a la sección de IAM, y modificar los permisos del rol asociado a la función que acabamos de crear para que pueda escribir en S3.

Tras completar la configuración anterior, ya tendríamos todos los requisitos para que funcionara la función de AWS Lambda. El propio panel de configuración nos da la opción de probar la función directamente (sin tener que esperar a que se ejecute por los “triggers” que se hayan establecido), aunque se aplicarán las tarifas del servicio.

Sin embargo, como el primer millón de llamadas a las funciones cada mes es gratuito, podemos hacer unos cuantos tests sin llegar a pagar nada. Y, caso de que excedamos el millón de llamadas, el siguiente millón solo cuesta 0.20 $.

¿Debería cambiar a una arquitectura serverless?

Sin duda. Los grandes proveedores están integrando estos servicios en sus plataformas: Google está en fase Beta con las Google Cloud Functions y Microsoft ha sacado Azure Functions, que ofrecen unos servicios similares a los de AWS Lambda.

En nuestro caso, al utilizar AWS Lambda, rápidamente vemos un beneficio económico, la instancia más barata de EC2, la t2.nano, cuesta unos 5$ al mes, y a menos que se supere el millón de llamadas a AWS Lambda, este servicio sería gratuito.

Sin embargo, el beneficio fundamental de pasarse a serverless es la comodidad de tener que preocuparte sólo por el código y no por la infraestructura. Tras migrar a AWS Lambda, ya no hay que hacer SSH a la máquina para revisar la memoria, ni gestionar los logs, ni estar pendiente de un ataque DDoS, ni preocuparse por actualizar el sistema operativo, ni estar pendiente de la escalabilidad del sistema.

Todas estas cosas quedarían gestionadas por AWS, dejando que los desarrolladores nos dediquemos a… ¡desarrollar! ¿Necesitas algún motivo más?

Escribe un comentario