9 de Abril de 2016 · 5 min de lectura
El Point In Time Recovery (PITR) o backup continuo es una funcionalidad cada día mas interesante, pues nos permite recuperar los datos de nuestra base de datos minutos antes de un desastre lógico.
WAL-E es una herramienta para conseguir backup continuo de postgresql con almacenamiento en el sistema de Amazon S3. Utiliza un paquete python con diversas utilidades de consola para operar con los backups y subir los ficheros necesarios al bucket.
Con WAL-E podemos hacer dos backups diferentes, el de los archivos WAL con todas la transacciones que se van realizando y el de pg_basebackups de postgresql.
Para los archivos WAL se debe cambiar la configuración de postgresql y en adelante utilice el comando wal-e necesario para ir subiendo los ficheros.
Para los basebackups, wal-e proporciona un comando que se encarga de la operación en postgresql y subir el fichero resultante. Este comando deberemos ejecutarlo periódicamente.
Con estos dos backups juntos podemos restaurar a cualquier punto en el tiempo, pues tenemos todo el registro de transacciones que ha ocurrido. La dependencia entre los dos backup es fuerte, es necesario siempre un basebackup como origen para poder restaurar las transacciones del WAL y no podremos restaurar transacciones que no se correspondan con su basebackup. La restauración de un basebackup sin tener los WAL es posible, pero no lo és la restauración de los WALs sin tener su basebackup correspondiente.
La instalación de wal-e es sencilla, está empaqueta en PyPI y es suficiente con hacer:
$ pip install wal-e
Aunque wal-e también permite almacenar en Swift o Azure, voy a explicar cómo lo hacemos subiendo a Amazon S3.
Para la conexión con Amazon S3 wal-e utiliza la librería de python boto, que es fácilmente configurable via variables de entorno con la credenciales que tengamos de acceso.
Para facilitar la configuración de estas variables de entorno accesibles por todos los procesos involucrados, wal-e propone la utilización de otra herramienta python llamada envdir, que recoge por parámetro la ruta a un directorio para establecer los ficheros que contenga como variables de entorno.
Así pues, configuramos la ruta /etc/wal-e.d/env/ con la acreditación necesaria para conectar a un bucket:
/etc/wal-e.d/env $ ls -tlr
-rwxr--r-- 1 root postgres 21 Mar 30 16:25 AWS_ACCESS_KEY_ID
-rwxr--r-- 1 root postgres 41 Mar 30 16:26 AWS_SECRET_ACCESS_KEY
-rwxr--r-- 1 root postgres 48 Mar 30 16:40 WALE_S3_PREFIX
-rwxr--r-- 1 root postgres 44 Mar 30 17:23 WALE_S3_ENDPOINT
/etc/wal-e.d/env $ cat WALE_S3_PREFIX
s3://nombre_del_bucket/directorio
/etc/wal-e.d/env $ cat WALE_S3_ENDPOINT
https+path://s3-eu-west-1.amazonaws.com:443
En el archivo de configuración de nuestro postgresql deberemos retocar estas variables:
wal_level = archive
archive_mode = on
archive_command = '/usr/bin/envdir /etc/wal-e.d/env /usr/local/bin/wal-e wal-push %p'
archive_timeout = 1800
Donde archive_command indica a postgres que utilice wal-e para archivar los ficheros WAL. Con archive_timeout escogemos cada cuando tiempo (en segundos) cerrar un fichero WAL y archivarlo, es decir, subirlo a S3. Este valor dependerá de cada caso, pero teniendo en cuenta un número excesivamente bajo afectará al rendimiento del postgresql.
Es necesario reiniciar el servicio postgresql tras los cambios, no es suficiente con un reload del servicio. En los logs de postgresql podremos ver como se suben los ficheros con el comando de wal-e push y ver si ha ocurrido algún error.
En el usuario postgres del servidor dejaremos configurado un cron de usuario para que se vayan subiendo los basebackups necesarios cada día. Este comando ya se encarga de conectar a postgresql y realizar las operaciones necesarias al empezar la copia y terminarla.
30 0 * * * /usr/bin/envdir /etc/wal-e.d/env /usr/local/bin/wal-e backup-push /var/lib/postgresql/9.5
También podemos configurar otro cron, con el comando wal-e delete para que vaya borrando los backups viejos y configurar la retención, en este ejemplo 30 días:
0 2 * * * /usr/bin/envdir /etc/wal-e.d/env /usr/local/bin/wal-e delete --confirm retain 30
Wal-e proporciona una manera de saber que backups hay disponibles con el comando backup-list.
postgres@host$ /usr/bin/envdir /etc/wal-e.d/env /usr/local/bin/wal-e backup-list
wal_e.main INFO MSG: starting WAL-E
DETAIL: The subcommand is "backup-list".
STRUCTURED: time=2016-04-05T13:04:18.412986-00 pid=25152
name last_modified expanded_size_bytes wal_segment_backup_start wal_segment_offset_backup_start wal_segment_backup_stop wal_segment_offset_backup_stop
base_000000010000000000000082_00000040 2016-03-30T15:24:40.000Z 000000010000000000000082 00000040
base_000000010000000000000084_00000040 2016-03-30T15:25:42.000Z 000000010000000000000084 00000040
base_0000000100000000000000DB_00000040 2016-03-30T22:30:13.000Z 0000000100000000000000DB 00000040
base_0000000100000001000000FC_00000040 2016-03-31T22:30:15.000Z 0000000100000001000000FC 00000040
base_00000001000000030000001D_00000040 2016-04-01T22:30:14.000Z 00000001000000030000001D 00000040
base_00000001000000040000003E_00000040 2016-04-02T22:30:12.000Z 00000001000000040000003E 00000040
base_00000001000000050000005F_00000040 2016-04-03T22:30:15.000Z 00000001000000050000005F 00000040
base_000000010000000600000080_00000040 2016-04-04T22:30:14.000Z 000000010000000600000080 00000040
mv /var/lib/postgresql/9.5/main /var/lib/postgresql/9.5/main_old
/usr/bin/envdir /etc/wal-e.d/env /usr/local/bin/wal-e backup-fetch /var/lib/postgresql base_000000010000000000000082_00000040
$ cat /etc/postgresql/9.5/main/recovery.conf
restore_command = '/usr/bin/envdir /etc/wal-e.d/env /usr/local/bin/wal-e wal-fetch "%f" "%p"'
#recovery_target_time = '2016-04-08 09:07:00'
#recovery_target_time = 'latest'
chown -R postgres:postgres /var/lib/postgresql/9.5/main
$ chmod 0700 /var/lib/postgresql/9.5/main
A veces, desarrollando una aplicación, poder utilizar una copia de datos de un punto en el tiempo otorga una ventaja importante a la hora de resolver o encontrar un problema complicado. Existen otras posibilidades de backup continuo en servidor como Barman, pero según nuestra experiencia, wal-e encaja mejor en muchos casos por su simpleza, pues al no necesitar servidor cuenta con otro punto de fallo menos.
Para terminar os dejo en la mesa otra idea que puede resultar interesante: la de utilizar un usuario de lectura del mismo bucket de backup, para que un entorno de desarrollo o pre-producción inicie con una copia lo más fresca posible de los datos de producción.