En el artículo anterior expliqué cómo crear un bucket en Google Cloud Storage, y cómo subir archivos a la nube desde una aplicación Python, utilizando la API XML de GCS. Ahora voy a demostrar cómo montar un esquema de backup simple, que permita almacenar los backups del servidor en un bucket de Google Cloud Storage.

Anteriormente demostré cómo almacenar backups en Google Drive. Un esquema simple y útil para servidores privados virtuales, pero orientado a backups personales. Sin embargo, cuando se trata de servidores y datos de clientes, se debe optar por una solución más profesional. Google Cloud Storage ofrece almacenamiento para backups a ultra bajo costo. Un bucket clase "Nearline" cuesta tanto como 1 centavo de dólar por giga byte por mes. Para un volumen de datos pequeño es un costo despreciable.

Los pasos necesarios para crear un bucket en Google Cloud están explicados en el artículo Subir archivos a un bucket de Google Cloud Storage desde un script Python. Dicho artículo además, explica detalladamente la creación el script Python necesario para subir archivos a GCS. Sin embargo es mi intención proveer luego un script de instalación y publicar el esquema de backup completo en mi cuenta de GitHub. Por ahora comparto mi esquema, y los scripts necesarios para implementarlo.

Para no incurrir en grandes gastos de almacenamiento, la idea detrás de este esquema (tomada de la herramienta Backup-manager-gcs) consiste almacenar hasta un máximo de 31 copias de backup. Una copia de backup por día, tanto de las bases de datos MySQL como de los archivos en el servidor. Cada copia se identifica con el número de día del mes, desde el 1 al 31, y van rotando automáticamente, para no acumularse en el bucket.

Esquema de backup

El esquema de backup se divide en 4 scripts: un script Bash principal; un script bash para resguardar bases de datos MySQL; un script Bash para crear copias de seguridad de archivos y directorios; y un script Python para subir archivos a GCS.

Antes de comenzar, crear un directorio donde almacenar localmente las copias de seguridad:

# mkdir /backup

Luego crear los scripts Bash necesarios. La instalación del script upload2gcs.py está cubierta en el artículo Subir archivos a un bucket de Google Cloud Storage desde un script Python.

Script para backups de bases de datos MySQL, /root/scripts/backup-gcs/backup-databases.bash:

#!/bin/bash

MYUSER=backup
MYPASS=1234

ARGS="-u"$MYUSER" -p"$MYPASS" \
  --add-drop-database \
  --add-locks \
  --create-options \
  --complete-insert \
  --comments \
  --disable-keys \
  --dump-date \
  --extended-insert \
  --quick \
  --routines \
  --triggers \
  --ignore-table=mysql.event"

mysql -u$MYUSER -p$MYPASS -e 'show databases' | grep -Ev "(Database|information_schema|performance_schema)" > databases.list

while read DB
do
        DUMP="dump_"$DB".sql"
        echo -n $DUMP"... "
        mysqldump ${ARGS} $DB > $DUMP
        echo "OK."
done < databases.list

rm databases.list

tar czf databases.tar.gz dump_*.sql && rm dump_*.sql

Script para backups de directorios, /root/scripts/backup-gcs/backup-files.bash:

#!/bin/bash

# Get file/directory name to backup
if [ $# -lt 1 ]
then
  echo "uso: $0 DIR"
  exit -1
fi

# Remove slashes from name
DIR=$1
DIR_C=$(echo $DIR | sed 's/\///g')

# Get current date and time
DATE=$(date +%Y-%m-%d_%H%M%S)

# Save as gzipped tar
echo -n "files_${DIR_C}_$DATE.tar.gz... "
tar czf files_${DIR_C}_$DATE.tar.gz $DIR 2>/dev/null
echo "OK."

Script principal (el que será ejecutado por cron), /root/scripts/backup-gcs/backup.bash:

#!/bin/bash

BACKUPDIR=/backup

# Change to backup dir
cd $BACKUPDIR

# Get day of month
DOM=$(date +%d)

# List of directories to backup
FILES=(/var/www/ /var/log)

# Dump MySQL databases
/root/scripts/backup-gcs/backup-databases.bash
mv databases.tar.gz ${DOM}-databases.tar.gz

# tar files
for F in ${FILES[@]}; do
  /root/scripts/backup-gcs/backup-files.bash $F
done
tar -cf ${DOM}-files.tar files_* && rm files_*

# Upload to GCS
for F in $BACKUPDIR/${DOM}*; do
  /root/scripts/backup-gcs/upload2gcs.py $F
done

Este script principal (backup.bash) resguarda todas las bases de datos en el motor de bases de datos MySQL local, y posee una lista de directorios a resguardar (variable FILES).

A fin de poder crear copias de seguridad de todas las bases de datos MySQL, es necesario crear un usuario local con acceso de lectura a todas las bases de datos en el motor (*.*). Para ello, conectarse al motor de bases de datos como "root":

# mysql -u root -p

Luego crear el usuario "backup" (cambiar la contraseña "1234" por una más fuerte):

mysql> create user 'backup'@'localhost' identified by '1234';
mysql> grant lock tables, select on *.* to 'backup'@'localhost';
mysql> quit

La contraseña para el usuario "backup" se debe indicar luego en el script backup-databases.bash.

Otorgar permisos de ejecución a todos los scripts:

# chmod +x /root/scripts/backup-gcs/backup*

Finalmente, verificar el funcionamiento:

root@linuxito:~# /root/scripts/backup-gcs/backup.bash 
dump_webapp1.sql... OK.
dump_mysql.sql... OK.
files_varwww_2017-06-21_143407.tar.gz... OK.
files_varlog_2017-06-21_143408.tar.gz... OK.
Successfully created "backup//backup/21-databases.tar.gz"
Successfully created "backup//backup/21-files.tar"

Notar la doble barra (backup//) en la salida del script upload2gcs.py. Esto se debe a que la API XML de GCS permite subir archivos a un bucket utilizando rutas absolutas. De esta forma replica el nombre indicado localmente en el bucket. Si en cambio se indica el nombre del archivo local a través de una ruta relativa a la ubicación actual, se replica la ruta relativa dentro del bucket. Por esta razón, hay que tener cuidado al momento de especificar los nombres de los archivos locales que se van a subir al bucket.

Luego de ejecutar el script backup.bash, se crean los siguientes archivos en el sistema de archivos local:

root@linuxito:~# ll /backup/$(date +%d)*
-rw-r--r-- 1 root root  155489 Jun 21 14:34 /backup/21-databases.tar.gz
-rw-r--r-- 1 root root 3276800 Jun 21 14:34 /backup/21-files.tar

Los cuales fueron subidos con éxito al bucket en Google Cloud Storage:

Por último, crear un cronjob para que se ejecute una vez al día:

# nano /etc/cron.d/backup

Por ejemplo, para ejecutar todos los días a las 2:36 AM, pegar el siguiente contenido:

# /etc/cron.d/php5: crontab for backups
36 2 * * * root /root/scripts/backup-gcs/backup.bash

Al generar una salida, este trabajo enviará automáticamente un mail a root. Dependiendo de la configuración de correo para el usuario root, el mensaje con la salida del script de backup puede ser redirigido automáticamente a una casilla de correo electrónico de nuestra preferencia.

Referencias


Tal vez pueda interesarte


Compartí este artículo