Bacula

Bacula est un système de sauvegarde libre extrêmement puissant. Le logiciel dispose d’un ensemble de fonctionnalités extrêmement intéressant, et d’une qualité professionnelle telle que certains logiciels propriétaires devraient suivre son exemple.

Le logiciel se découpe en 4 parties:

  • Une ou plusieurs bases de données qui servent de catalogue (tâches, liens vers les fichiers, évènements…)
  • Un ou plusieurs directeurs qui gèrent l’ensemble des stratégies de sauvegarde et référencent les clients
  • Un ou plusieurs services de stockage qui vont gérer un ensemble de volumes virtuels ou physiques
  • Des clients à sauvegarder

Un petit schéma permettra de mieux comprendre l’architecture:

Bacula InfraIl s’agit ici d’une infrastructure pour quelques centaines de serveurs. Vous pouvez vous contenter d’un simple serveur avec du stockage, qui fera office de storage, director et catalogue.

Installation et configuration de la base de données

Nous allons utiliser postgresql pour sa rapidité et sa capacité à gérer de grands volumes de données.

Sous debian (wheezy)

aptitude install postgresql-9.1

On va ensuite se connecter en superutilisateur et créer la base et l’utilisateur bacula

su - postgres
createuser -sdrP bacula
createdb -E SQL_ASCII -T template0 -O bacula bacula

Sur FreeBSD:

cd /usr/ports/databases/postgresql91-server
make install clean
service postgresql initdb
service postgresql start

On se connecte en super utilisateur:

su - pgsql
createuser -sdrP bacula
createdb -E SQL_ASCII -T template0 -O bacula bacula

Installation des services

On installe les différents services nécessaires pour faire fonctionner bacula

Sous Debian:

aptitude install bacula-director-pgsql bacula-console bacula-sd-pgsql

A la fin de l’installation bacula vous demandera les informations sur la base de données PostGreSQL. Indiquez pour chaque élément l’utilisateur et le mot de passe précédémment créé.

Sous FreeBSD:

cd /usr/ports/sysutils/bacula-server
make install clean

Choisissez les options de compilation suivantes:

Capture d'écran de 2013-05-02 18:39:34

Pour terminer on va installer la base:

su - pgsql
/usr/local/share/bacula/make_postgresql_tables

Configuration du service de stockage

En premier lieu nous allons configurer le serveur de stockage. Celui-ci permet d’interagir avec les différents supports de stockage pour la sauvegarde. Bacula supporte le stockage de cartouches virtuelles mais également les lecteurs de bandes (LTO3-4-5…).

Notre configuration utilisera ici des cartouches virtuelles.

On va tout d’abord copier le fichier sample avant de l’éditer.

Sous Debian:

cp /etc/bacula/bacula-sd.conf.sample /etc/bacula/bacula-sd.conf

Sous FreeBSD:

cp /usr/local/etc/bacula/bacula-sd.conf.sample /usr/local/etc/bacula-sd.conf

Nous allons créer un répertoire de stockage pour nos cartouches:

mkdir -p /backup/Volumes

Editons maintenant bacula-sd.conf

La section Storage définit le service de stockage lui même. Chaque Storage doit avoir un nom et un port d’écoute. C’est également à ce niveau qu’on va définir un nombre limite de tâches concurrentes, permettant d’éviter de saturer la capacité des lecteurs physiques/virtuels. L’écoute est configurée sur toutes les interfaces, permettant aux directeurs distants de sauvegarder

Storage {                             # definition of myself
  Name = MY_BACULA_STORAGE
  SDPort = 9103                  # Director's port
  WorkingDirectory = "/var/db/bacula"
  Pid Directory = "/var/run"
  Maximum Concurrent Jobs = 20
  SDAddress = 0.0.0.0
}

Note: les chemins pid et db sont les suivants sur Debian:

WorkingDirectory = "/var/lib/bacula"
Pid Directory = "/var/run/bacula"

La section Director permet de définir les serveurs directeurs pouvant se connecter à ce noeud de stockage afin de stocker leurs données. Chaque directeur possède un mot de passe par SD. Celui-ci doit être long et complexe.

Director {
  Name = MY_BACULA_DIRECTOR
  Password = "mycomplexpasswordover40chars"
}

La section Device permet de définir un périphérique de stockage pour les volumes. Le Media Type définit le type de périphérique, ici des fichiers. On spécifie ensuite un répertoire, Archive Device, où seront stockés les volumes. Enfin on demande à bacula de nommer les volumes, d’écrire aléatoirement sur les volumes (sécurité), de monter automatiquement les volumes et de les laisser ouverts.

Device {
  Name = MY_BACULA_STORAGE_DEVICE
  Media Type = File
  Archive Device = /backup/Volumes/
  LabelMedia = yes;
  Random Access = Yes;
  AutomaticMount = yes;
  RemovableMedia = no;
  AlwaysOpen = yes;
}

Enfin la section Messages permet de définir un ou plusieurs directeurs à qui remonter les informations (logs), et de filtrer le type de logs qu’on envoie à chaque directeur.

Messages {
  Name = Standard
  director = MY_BACULA_DIRECTOR = all

Une fois que vous avez terminé, vous pouvez démarrer le service de stockage.

service bacula-sd start

Configuration du directeur

Premiers pas

Le directeur est celui qui orchestre toute la sauvegarde. Il sait ce qu’on sauvegarde, comment, à quelle période et où.

Dans un premier temps on va copier le fichier de configuration d’example du directeur (et créer un répertoire pour les fichiers de bacula sous FreeBSD

Sous Debian:

cp /etc/bacula/bacula-dir.conf.sample /etc/bacula/bacula-dir.conf

Sous FreeBSD:

cp /usr/local/etc/bacula-dir.conf.sample /usr/local/etc/bacula-dir.confmkdir /usr/local/etc/bacula/

On ouvre maintenant le fichier de configuration.

Director {                            # define myself
  Name = MY_BACULA_DIRECTOR
  DIRport = 9101                # where we listen for UA connections
  QueryFile = "/usr/local/share/bacula/query.sql"
  WorkingDirectory = "/var/db/bacula"
  PidDirectory = "/var/run"
  Maximum Concurrent Jobs = 10
  Password = "mycomplexpasswordover40chars"
  Messages = MailDaemon
  DirAddress = 0.0.0.0
}

On configure ici le nom du directeur et son mot de passe (utilisés sur les storage daemon), les interfaces et le port d’écoute, et les différents répertoires et fichiers de requête. Vous pouvez également spécifier le nombre de tâches que peut faire le service en parallèle.

La directive Messages définit la commande à exécuter et ses paramètres lors de notifications

Note: le QueryFile, le WorkingDirectory et le PidDirectory sont différents sur Debian:

QueryFile = "/etc/bacula/scripts/query.sql"
WorkingDirectory = "/var/lib/bacula"
PidDirectory = "/var/run/bacula"

La configuration de bacula pouvant devenir volumineuse, nous allons découper le fichier de configuration en plusieurs fichiers en ajoutant les lignes suivantes:

@/usr/local/etc/bacula/bacula-dir-storage.conf
@/usr/local/etc/bacula/bacula-dir-pools.conf
@/usr/local/etc/bacula/bacula-dir-catalogs.conf
@/usr/local/etc/bacula/bacula-dir-schedules.conf
@/usr/local/etc/bacula/bacula-dir-jobdefs.conf
@/usr/local/etc/bacula/bacula-dir-jobs.conf
@/usr/local/etc/bacula/bacula-dir-filesets.conf
@/usr/local/etc/bacula/bacula-dir-clients.conf

Note: le chemin est /etc/bacula sur Debian

Enfin on termine par la définition de l’envoi de messages MailDaemon:

Messages {
  Name = MailDaemon
  mailcommand = "/usr/sbin/bsmtp -h localhost -f \"\(Bacula\) \<bacula@mydomain.com\>\" -s \"Bacula daemon message\" mymailbox@mydomain.com"
  mail = root = all, !skipped            
  console = all, !skipped, !saved
  append = "/var/log/bacula/bacula.log" = all, !skipped
}

Console {
  Name = bacula-mon
  Password = "monmotdepassemonitorcomplexe"
  CommandACL = status, .status
}

Définition des noeuds de stockage

La première chose à faire est de donner au directeur des noeuds de stockages sur lesquels stocker ses données (bacula-dir-storage.conf).

Storage {
  Name = MY_BACULA_STORAGE
  Address = storage1.mydomain.com
  SDPort = 9103
  Password = "mycomplexpasswordover40chars"
  Device = MY_BACULA_STORAGE_DEVICE
  Media Type = File
}

Dans l’exemple ci-dessus, on précise le nom du noeud de stockage, son adresse IP et port, mais également le mot de passe à utiliser (identique à celui de la section director renseignée sur le SD), le périphérique et son nom.

Attention: l’adresse ne peut pas être localhost, uniquement une adresse IP routable ou un nom DNS

Définition des pools de cartouches

On va maintenant configurer des pools de cartouches pour la sauvegarde (bacula-dir-pools.conf). Ceux-ci définissent les propriétés des différentes cartouches

Pool {
  Name = MY_BACULA_POOL
  Pool Type = Backup
  Recycle = yes
  AutoPrune = yes
  Volume Retention = 365 days
  Volume Use Duration = 7 days
  Maximum Volume Bytes = 50G
  Maximum Volumes = 100
  LabelFormat = "POOL1_VOL_"
}

Chaque pool dispose d’un identifiant et un type (généralement Backup). On peut définir des propriétés:

  • Recycle: recycler les volumes, s’il n’y a plus d’espace, ou que les cartouches sont trop anciennes
  • AutoPrune: recycle automatiquement les cartouches s’il n’y a plus d’espace disponible
  • Volume Use Duration: la période pendant laquelle le volume peut être utilisé. C’est utile si vous utilisez des cartouches de sauvegarde complète et des cartouches de sauvegarde incrémentale, afin de supprimer les sauvegardes incrémentales à chaque fois que la sauvegarde totale est faite.
  • Volume Retention: la période de rétention des données sur les cartouches
  • Max Volume Bytes: la taille maximale d’une cartouche. Une valeur entre 50 et 300G est raisonnable
  • Maximum Volumes: le nombre maximal de cartouches. Attention à ne pas dépasser l’espace disque total (somme des Max Volume Bytes * Maximum Volumes de chaque pool)
  • LabelFormat: le préfixe de nomage des cartouches

Définition des catalogues

Les catalogue contient l’ensemble des liens entre fichiers, versions et volumes de données. Il s’agit d’un élément extrêmement sensible.

Catalog {
  Name = MyBaculaCatalog
  dbname = "bacula"; DB Address = "192.168.1.1"; dbuser = "bacula"; dbpassword = "bacula"
}

Spécifiez les données correspondant à votre serveur PostGreSQL.

Planification des sauvegardes

L’important dans une sauvegarde est de correctement planifier vos sauvegardes, afin d’éviter de charger le réseau lorsqu’il est utilisé, ou de pouvoir sauvegarder les données dans une période de temps donnée. Si on possède un seul directeur et périphérique de sauvegarde il est important de vérifier qu’il est possible de tout sauvegarder le même soir/jour, autrement il faudra répartir les sauvegardes dans le temps.

De même il est possible de définir des stratégies de sauvegardes avec plusieurs directeurs, par exemple directeur1 sauvegarde les serveurs A,B,C le lundi,mercredi,vendredi,dimanche et directeur 2 les sauvegarde les autres jours.

La configuration des planifications se fait dans bacula-dir-schedule.conf

Schedule {
  Name = "Cycle Hebdo"
  Run = Full sun at 05:00
  Run = Differential 2nd-5th sun at 23:05
  Run = Incremental mon-sat at 23:30
  Run = Incremental wed at 5:30 pool=WED_BACKUP_POOL
  FullPool = POOL_BACKUP_FULL
  IncrementalPool = POOL_BACKUP_INCR
  Pool = MY_BACULA_POOL
  Storage = MY_BACULA_STORAGE
}

Nous avons ici une configuration verbeuse, afin de définir la flexibilité de l’ensemble des paramètres:

  • Run: définit le moment déclenchant la tâche
    • Full: une sauvegarde complète
    • Differential: uniquement les changements depuis la dernière sauvegarde complète
    • Incrémentale: uniquement les changements depuis la dernière sauvegarde réussie
    • Jour et heure: on peut définir tout et n’importe quoi, ici le dimanche à 5h, comme du 2ème au 5ème dimanche du mois, ou encore le premier janvier… et spécifier un pool pour cette tâche spécifique
  • FullPool: si la directive n’est pas outrepassée, le pool de cartouches sur lesquelles faire les sauvegardes totales
  • IncremantalPool: si la directive n’est pas outrepassée le pool de cartouches sur lesquelles faire la sauvegarde incrémentale
  • Pool: le pool par défaut pour tous les types de sauvegarde
  • Storage: le noeud de stockage où sauvegarder

Définir des ensembles de fichiers

Les ensembles de fichiers sont des listes de fichiers à sauvegarder (avec possibilité d’exclusion)

FileSet {
   Name = "WEB_FILESET"
   Include {
     Options {
       signature = MD5
       Compression = GZIP
       wildfile = "*.zip"
       Exclude = yes
     }
     File = /usr/local/www
   }
  Exclude {
    File = /usr/local/www/tmp
 File = /usr/local/www/.git
  }
 }

Pour chaque inclusion de fichiers il est possible de spécifier un ou plusieurs chemins (répertoires/fichiers) ainsi que des options:

  • compression: par défaut désactivée, il est possible de choisir GZIP ou LZO (pour les serveurs chargés en CPU). Elle est recommandée pour les cartouches virtuelles mais pas physiques
  • signature: permet de garder une trace md5 ou sha1 de chaque fichier, garantissant leur intégrité.

On peut exclure des répertoires avec la directive exclude, ou bien encore des fichiers par patern (ici des zip).

Spécifier des définitions de tâches

Les définitions de tâches sont des tâches non appliquées. Elles permettent de créer une arborescence de tâches héritées et ainsi de déployer très rapidement des stratégies de sauvegarde sur un panel de clients très large.

Tâches de sauvegarde

JobDefs {
  Name = "Web_Backup_JD"
  Type = Backup
  Level = Incremental
  Client = WEB1_FD
  FileSet = "WEB_FILESET"
  Schedule = "Cycle Hebdo"
  Storage = MY_BACULA_STORAGE
  Messages = MailDaemon
  Pool = MY_BACULA_POOL
  Priority = 10
  Max Start Delay = 1h
  Max Run Time = 6h
}

Cette définition permet de configurer une tâche de sauvegarde et de l’associer à un client (unique) et à une planification précise. Les directives Storage et Pool sont écrasées par celles définies dans la planification, si elles sont présentes.

Les autres directives définissent

  • FileSet: l’ensemble de fichiers associé à cette tâche
  • Priority: le niveau de priorité de cette tâche. Si d’autres tâches sont à effectuer avec une priorité plus faible elles seront retardées pour effectuer celle-ci
  • Max Start Delay: définit la limite après laquelle la tâche ne sera pas effectuée si elle n’a pas été commencée (à cause d’autres tâches en cours par exemple). Dans notre cas, si on sauvegarde à 23h et qu’à minuit la tâche n’a pas commencé, elle est annulée (optionnel)
  • Max Run Time: après 6h on annule la tâche (par défaut 6 jours)

Il est également possible de lancer des commandes avant et après la tâche sur le système de sauvegarde mais également sur le client, voire des commandes en cas d’échec. Je vous invite à lire la documentation sur les jobs.

Tâches de restauration

Pour pouvoir restaurer des fichiers vous aurez besoin de définir une tâche de restauration. Bacula permet de restaurer dans le répertoire d’origine mais également dans des répertoires différents. Il est même possible de planifier des tâches de restauration, afin de s’assurer qu’une donnée n’est pas altérée sur un serveur. Voici un exemple de tâche:

JobDefs {
  Name = "Web_Restore_JD"
  Type = Restore
  Client = WEB1_FD
  FileSet = "WEB_FILESET"
  Storage = MY_BACULA_STORAGE
  Messages = Standard
  Pool = MY_BACULA_POOL
  Where = "/"
  Add Suffix = .restore
}

La directive Where définit le répertoire dans lequel restaurer le fichier. Ici on définit le répertoire / car bacula restaure en conservant l’arborescence de fichiers.

La directive Add Suffix (optionnelle) permet de rajouter un suffixe aux fichiers restaurés, afin d’éviter de les écraser. D’autres options existent et sont présentes dans la documentation des Jobs.

Définition des tâches

Les tâches se définissent de la même manière que les définitions de tâches (JobDefs).

Afin d’inclure un ensemble de définition, utilisez simplement la directive JobDefs:

Job {
  Name = "Backup_WebServer"
  JobDefs = "Web_Backup_JD"
}

Job {
  Name = "Restore_WebServer"
  JobDefs = "Web_Restore_JD"
}

Vous pouvez ajouter/écraser des attributs ou ne pas utiliser de JobDefs si besoin est. Dans un environnement avec plus d’une dizaine de machines il peut être utile de définir des JobDefs afin de pouvoir créer une tâche avec héritage pour chaque client.

Déclaration des clients

Bacule se connecte lui-même sur les clients. Chaque client dispose d’un service en attente de tâches de sauvegarde. Voici la définition d’un client côté directeur:

Client {
  Name = WEB1_FD
  Address = myclient.domain.com
  FDPort = 9102
  Catalog = MyCatalog
  Password = "motdepasseduclienttrèslong"
  File Retention = 30 days
  Job Retention = 6 months
  AutoPrune = yes
  Maximum Concurrent Jobs = 3
  Maximum Bandwidth Per Job = 10 Mb/s
}

Décrivons les attributs intéressants:

  • Catalog: le catalogue local à utiliser pour ce client
  • Password: le mot de passe commun au directeur et au client
  • File Retention: durée pendant laquelle garder les fichiers pour ce client. Il faut spécifier une valeur inférieure à celle des cartouches et des tâches auquel cas la rétention appliquée sur les 3 sera la plus faible
  • Job Retention: durée pendant laquelle garder les tâches pour ce client. Il faut spécifier une valeur inférieure à celle des cartouches, auquel cas la rétention appliquée sur les 2 sera la plus faible.
  • AutoPrune: supprime les entrées du catalogue une fois la période de rétention expirée. Mettre cette valeur à no implique un catalogue grossissant plus qu’il ne devrait
  • Maximum Concurrent Jobs: si vous effectuez plusieurs tâches de sauvegarde sur des répertoires différents il peut être judicieux de paralléliser la sauvegarde (à éviter si vous sauvegardez les mêmes données)
  • Maximum Bandwith Per Job: permet de limiter la bande passante utilisée, utile dans le cas d’une sauvegarde en journée ou s’il y a beaucoup de tâches en parallèle sur l’ensemble du serveur.

Aller encore plus loin

Bacula dispose d’énormément d’options extrêmement poussées, il est donc possible de faire beaucoup de choses avec cet outil et un simple article ne peut pas tout détailler. Je vous invite à regarder cette page afin de connaître toutes les options de configuration

Sauvegarde incrémentale (logs)

Lors de cette veille, le serveur de test sur lequel je travaillais a effectué une sauvegarde incrémentale. Bacula étant verbeux, il a rédigé un rapport de sauvegarde dans les logs. Vous pourrez voir qu’il gère le décallage horaire de serveurs (le serveur de sauvegarde de test ayant 2h de décallage):

02-mai 23:05 PALA_DIRECTOR JobId 7: Start Backup JobId 7, Job=Backup_AllWebClusters.2013-05-02_23.05.00_02
02-mai 23:05 PALA_DIRECTOR JobId 7: Using Device "PALA_STORAGE_DEV"
02-mai 21:16 WEBCLUSTER1_FD JobId 7: Warning: DIR and FD clocks differ by -6522 seconds, FD automatically compensating.
02-mai 23:05 PALA_STORAGE JobId 7: Volume "PALA_VOL_0001" previously written, moving to end of data.
02-mai 23:05 PALA_STORAGE JobId 7: Ready to append to end of Volume "PALA_VOL_0001" size=12015358632
02-mai 23:06 PALA_STORAGE JobId 7: Job write elapsed time = 00:01:07, Transfer rate = 6.378 M Bytes/second
02-mai 23:06 PALA_DIRECTOR JobId 7: Bacula PALA_DIRECTOR 5.2.6 (21Feb12):
  Build OS:               x86_64-pc-linux-gnu debian 7.0
  JobId:                  7
  Job:                    Backup_AllWebClusters.2013-05-02_23.05.00_02
  Backup Level:           Incremental, since=2013-05-02 17:40:46
  Client:                 "WEBCLUSTER1_FD" 5.2.12 (12Sep12) amd64-portbld-freebsd9.1,freebsd,9.1-RELEASE
  FileSet:                "WebCluster_FILESET" 2013-05-02 17:35:20
  Pool:                   "PALA_POOL" (From Job resource)
  Catalog:                "PalaCatalog" (From Client resource)
  Storage:                "PALA_STORAGE" (From Job resource)
  Scheduled time:         02-mai-2013 23:05:00
  Start time:             02-mai-2013 23:05:03
  End time:               02-mai-2013 23:06:10
  Elapsed time:           1 min 7 secs
  Priority:               10
  FD Files Written:       138
  SD Files Written:       138
  FD Bytes Written:       427,368,697 (427.3 MB)
  SD Bytes Written:       427,389,095 (427.3 MB)
  Rate:                   6378.6 KB/s
  Software Compression:   None
  VSS:                    no
  Encryption:             no
  Accurate:               no
  Volume name(s):         PALA_VOL_0001
  Volume Session Id:      6
  Volume Session Time:    1367509217
  Last Volume Bytes:      12,443,069,451 (12.44 GB)
  Non-fatal FD errors:    0
  SD Errors:              0
  FD termination status:  OK
  SD termination status:  OK
  Termination:            Backup OK

02-mai 23:06 PALA_DIRECTOR JobId 7: Begin pruning Jobs older than 6 months .
02-mai 23:06 PALA_DIRECTOR JobId 7: No Jobs found to prune.
02-mai 23:06 PALA_DIRECTOR JobId 7: Begin pruning Files.
02-mai 23:06 PALA_DIRECTOR JobId 7: No Files found to prune.
02-mai 23:06 PALA_DIRECTOR JobId 7: End auto prune.

Installation du File Daemon

Le File Daemon est l’agent de sauvegarde de bacula.

Pour l’installer sur Debian:

aptitude install bacula-fd

Sur FreeBSD il s’agit du même paquet que pour le serveur, désactivez simplement le support SQL

cd /usr/ports/sysutils/bacula-server
make install clean

Renommez ensuite les fichiers de configuration bacula-fd.conf.sample en bacula-fd.conf et éditez le

FileDaemon {
  Name = WEB1_FD
  DIRport = 9102
  Working Directory = "/var/db/bacula"
  Pid Directory = "/var/run"
  Maximum Concurrent Jobs = 20
}
Director {
  Name = MY_BACULA_DIRECTOR
  Password = "mycomplexpasswordover40chars"
}
Messages {
  Name = Standard
  director = MY_BACULA_DIRECTOR = all, !skipped
}

La section FileDaemon définit l’agent lui-même.

Note: les répertoires sont respectivement /var/lib/bacula et /var/run/bacula sous Debian

La directive Director permet de définir 1 ou plusieurs Directeurs pouvant effectuer la sauvegarde, enfin la directive messages permet de définir les remontées de logs.

Conclusion

Je m’arrête sur cette partie dédiée à la sauvegarde, mais il faudrait bien entendu parler de la restauration et de la gestion quotidienne. Celles-ci sont possibles via le client Bacula (disponible sur Linux, Mac OSX et Windows) et/ou une interface web que vous pouvez installer

Bacula est un système de sauvegarde extrêmement complet, qui reste dans une logique UNIX, en offrant une sauvegarde complète mais ne s’occupant pas du système de fichiers. Il convient d’offrir un bon support de données (ext3/ext4/ufs2) pour votre catalogue et vos cartouches virtuelles. Afin de garantir la sécurité des données sauvegardées, il faut absolument utiliser 2 supports de données, dans l’idéal 2 directeurs avec 2 StorageDaemon, qui font chacun un backup à chaud de leurs catalogues, de manière régulière. Il peut être également intéressant d’utiliser des pools de sauvegarde dédiés à chaque journée, et un pool de sauvegarde pour la sauvegarde hebdomadaire.

Pour finir, Bacula est donc un système de sauvegarde de qualité profesionnelle sous licence libre, qui saura satisfaire tous les besoins (le tout étant de correctement architecturer son infrastructure).