Skip to content
Snippets Groups Projects
Verified Commit 38b7bd30 authored by Quentin Duchemin's avatar Quentin Duchemin
Browse files

[BackupRotation] Single config file for all hosts !

Allows to switch a service from a machine to another without having to reconfigure backups. Very useful for migrations for example.
parent f6e03cbe
No related branches found
No related tags found
No related merge requests found
......@@ -2,6 +2,7 @@ FROM python:3-slim-buster
RUN apt-get update && \
apt-get install -y --no-install-recommends \
iputils-ping \
postgresql-client \
mysql-client \
mongodb-clients \
......
......@@ -4,7 +4,7 @@ Cet outil orchestre le backup des différents services de Picasoft.
Il est capable de gérer les bases de données `postgres`, `mysql` ou `mongo` pour le moment.
Il est flexible et se configure via des fichiers JSON.
Il est flexible et se configure via un fichier JSON.
<!-- TOC depthFrom:1 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 -->
......@@ -19,12 +19,12 @@ Il est flexible et se configure via des fichiers JSON.
## Configuration
Les fichiers dans [`.config`](./config) recensent les informations sur les différents services mis en place sur les machines et les informations nécessaires pour lancer les rotations sur ces services.
Le fichier dans [`config/backup_config.json`](./config/backup_config.json) recensent les informations sur les différentes bases de données qui doivent être backupées.
Ces fichiers **sont** les fichiers utilisés **en production**.
Ils ne doivent pas être modifiés sur les machines sans être synchronisés avec le dépôt Git.
Ce fichier **est** utilisé **en production**.
Il ne doit pas être modifié sur les machines sans être synchronisé avec le dépôt Git.
On veillera à ce que les noms d'hôte correspondent bien aux noms des conteneurs (gérés par d'autres Docker Compose), et que le dossier `/DATA/BACKUP` existe.
Ce service est destiné à être lancé sur l'ensemble des machines : de cette manière peu importe que Mattermost tourne sous pica01 ou pica02, elle aura des backups. Si une base de donnée n'est pas accessible, elle est simplement ignorée, ce qui permet d'utiliser le même fichier de configuration pour l'ensemble des machines.
### Structure
......@@ -40,7 +40,7 @@ On veillera à ce que les noms d'hôte correspondent bien aux noms des conteneur
### Gestion des secrets
Afin de pouvoir versionner les fichiers de configuration sans exposer les identifiants aux bases de données, on utilise le système suivant :
Afin de pouvoir versionner le fichier de configuration sans exposer les identifiants aux bases de données, on utilise le système suivant :
* Dans le JSON, on utilise un nom de variable d'environnement à la place de l'identifant, **sans le $**, *e.g.* `ETHERPAD_DB_USER`.
* Dans le fichier `db.secrets`, on renseigne la valeur de cette variable d'environnement.
......@@ -49,17 +49,21 @@ La substitution est effectué automatiquement par l'outil.
### Exemple
Cet exemple montre trois possibilités : le backup d'une base MySQL, Postgresql et MongoDB.
```json
{
"wekan":
"mattermost":
{
"Host": "wekan-db",
"Port": "27017",
"Database": "wekan",
"Type": "mongo",
"Folder": "wekan",
"Host": "mattermost-db",
"Port": "5432",
"User": "MATTERMOST_DB_USER",
"Password": "MATTERMOST_DB_PASSWORD",
"Database": "mattermost",
"Type": "postgres",
"Folder": "mattermost",
"Cron" : "0 * * * *",
"Init-Backup" : "0",
"Init-Backup" : "1",
},
"etherpad":
{
......@@ -70,22 +74,29 @@ La substitution est effectué automatiquement par l'outil.
"Database": "--all-databases",
"Type": "mysql",
"Folder": "etherpad",
"Cron" : "0 * * * *",
"Cron" : "0 */6 * * *",
"Options" : "--single-transaction",
"Init-Backup" : "0",
"Init-Backup" : "1",
},
"wekan":
{
"Host": "wekan-db",
"Port": "27017",
"Database": "wekan",
"Type": "mongo",
"Folder": "wekan",
"Cron" : "0 */12 * * *",
"Init-Backup" : "1",
}
}
```
## Lancement
On se synchronise simplement avec le dépôt et on lance le Docker Compose.
On copie `secrets/db.secrets.example` dans `secrets/db.secrets` :
* On assigne le nom de la VM à `HOSTNAME` (*e.g.* `pica02`),
* On renseigne les secrets (voir [plus bas]((#gestion-des-secrets)))
On se synchronise simplement avec le dépôt et on copie `secrets/db.secrets.example` dans `secrets/db.secrets` et on renseigne les secrets (voir [Gestion des secrets]((#gestion-des-secrets))).
L'outil sélectionne automatiquement le bon fichier de configuration en fonction du nom d'hôte de la machine virtuelle, il n'y a donc rien à modifier :
On lance ensuite le Docker Compose :
```
$ docker-compose up -d
......
......@@ -10,13 +10,6 @@
"Folder": "mattermost",
"Cron" : "0 * * * *",
"Init-Backup" : "1",
"Backup-Rota":
{
"Hour" : 24,
"Day" : 7,
"Week" : 4,
"Month" : 12
}
},
"etherpad":
{
......@@ -30,12 +23,15 @@
"Cron" : "0 */6 * * *",
"Options" : "--single-transaction",
"Init-Backup" : "1",
"Backup-Rota":
{
"Hour" : 24,
"Day" : 7,
"Week" : 4,
"Month" : 12
}
},
"wekan":
{
"Host": "wekan-db",
"Port": "27017",
"Database": "wekan",
"Type": "mongo",
"Folder": "wekan",
"Cron" : "0 */12 * * *",
"Init-Backup" : "1",
}
}
{
"wekan":
{
"Host": "wekan-db",
"Port": "27017",
"Database": "wekan",
"Type": "mongo",
"Folder": "wekan",
"Cron" : "0 */12 * * *",
"Init-Backup" : "1",
"Backup-Rota":
{
"Hour" : 24,
"Day" : 7,
"Week" : 4,
"Month" : 12
}
}
}
......@@ -8,6 +8,8 @@ BACKUP_FOLDER=${BACKUP_FOLDER:-"/backup/"}
[ -z "${MONGO_PORT}" ] && { echo "=> MONGO_PORT cannot be empty" && exit 1; }
[ -z "${MONGO_DB}" ] && { echo "=> MONGO_DB cannot be empty" && exit 1; }
ping -c 1 -W 1 "${MONGO_HOST}" || echo "${MONGO_HOST} not available, skipping backup..."; exit 1
if [[ -z "${MONGO_USER}" && -z "${MONGO_PASS}" ]]; then
BACKUP_CMD="mongodump --forceTableScan -d ${MONGO_DB} -h ${MONGO_HOST}:${MONGO_PORT} -o $BACKUP_FOLDER"'${BACKUP_NAME}'
RESTORE_CMD="mongorestore -d ${MONGO_DB} -h ${MONGO_HOST}:${MONGO_PORT} "
......
......@@ -18,6 +18,8 @@ MYSQL_PASS=${MYSQL_PASS:-${MYSQL_ENV_MYSQL_PASS}}
[ -z "${MYSQL_USER}" ] && { echo "=> MYSQL_USER cannot be empty" && exit 1; }
[ -z "${MYSQL_PASS}" ] && { echo "=> MYSQL_PASS cannot be empty" && exit 1; }
ping -c 1 -W 1 "${MYSQL_HOST}" || echo "${MYSQL_HOST} not available, skipping backup..."; exit 1
BACKUP_CMD="mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${EXTRA_OPTS} ${MYSQL_DB} > $BACKUP_FOLDER"'${BACKUP_NAME}'
##########################
......
......@@ -8,6 +8,8 @@ BACKUP_FOLDER=${BACKUP_FOLDER:-"/backup/"}
[ -z "${POSTGRES_PASS}" ] && { echo "=> POSTGRES_PASS cannot be empty" && exit 1; }
[ -z "${POSTGRES_DB}" ] && { echo "=> POSTGRES_DB cannot be empty" && exit 1; }
ping -c 1 -W 1 "${POSTGRES_HOST}" || echo "${POSTGRES_HOST} not available, skipping backup..."; exit 1
BACKUP_CMD="pg_dump -w -c > $BACKUP_FOLDER"'${BACKUP_NAME}'
##########################
......@@ -60,7 +62,7 @@ export PGUSER=$POSTGRES_USER
export PGPASSWORD=$POSTGRES_PASS
echo "=> ${POSTGRES_SERVICE_NAME}: Restore database from \$1"
tar -xzvf \$1
tar -xzvf \$1
output="\$(echo \$1 | awk -F'.tar.gz' '{print \$1".sql"}')"
if psql < \$output ;then
echo "${POSTGRES_SERVICE_NAME}: Restore succeeded"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment