Bacula: настройка

Bacula это довольно сложная система резервного копирования. Рассмотрим один из вариантов его настройки с двумя стратегиями на двух примерах.

НАСТРОЙКА СЕРВЕРА: DIRECTOR

Director это основной демон который контроллирует работу всего и вся. В ней мы определим настройки самого директора, настройки каталога, настройки логирования и стораджей, а также сделаем инклуд конфигов резервируемых серверов, чтобы не раздувать сильно конфиг и было удобнее читать.

Director {
        Name = BaculaDirector
        Password = "vpishite_parol_dostupa_k_directory"
        QueryFile = "/usr/local/share/bacula/query.sql"
        PidDirectory = "/var/run"
        WorkingDirectory = "/var/db/bacula"
        Messages = Daemon
        Maximum Concurrent Jobs = 4
}

Catalog {
        Name = BaculaCatalog
        dbname = bacula
        dbaddress = 127.0.0.1
        user = bacula
        password = ""
}

Messages {
        Name = Daemon
        append = "/var/log/bacula.log" = all, !skipped, !restored
        catalog = all, !skipped, !saved
}

Storage {
        Name = ethanStorage
        Address = 192.168.1.23
        Password = "parol_directora"
        Device = ethanDevice
        Media Type = MediaType
        Maximum Concurrent Jobs = 4
}

Storage {
        Name = tardisStorage
        Address = 192.168.1.23
        Password = "parol_directora"
        Device = tardisDevice
        Media Type = MediaType
        Maximum Concurrent Jobs = 4
}

@/usr/local/etc/bacula/ethan_client.conf
@/usr/local/etc/bacula/tardis_client.conf

В стораджах указан адрес 192.168.1.23, который является айпи адресом, где установлен бакула и в нем же крутится директор. Соответственно в Password вписываем тот же пароль что указан в блоке Director { ... }.

НАСТРОЙКА СЕРВЕРА: FILEDAEMON

Данная служба на сервере нужна просто как заглушка.

Director {
        Name = BaculaDirector
        Password = "parol_directora"
}

FileDaemon {
        Name = BaculaClient
        WorkingDirectory = "/var/db/bacula"
        PidDirectory = "/var/run"
        Maximum Concurrent Jobs = 4
}

Messages {
        Name = Standard
        Director = BaculaDirector = all, !skipped, !restored
}

НАСТРОЙКА СЕРВЕРА: STORAGEDAEMON

Настраиваем блочные устройства и определяем директории в которых будут храниться данные.

Director {
        Name = BaculaDirector
        Password = "parol_directora"
}

Messages {
        Name = Standard
        Director = BaculaDirector = all
}

Storage {
  Name = storage
  SDPort = 9103
  WorkingDirectory = "/var/db/bacula"
  Pid Directory = "/var/run"
  Plugin Directory = "/usr/local/lib"
  Maximum Concurrent Jobs = 4
}

Device {
        Name = ethanDevice
        Media Type = MediaType
        Archive Device = /backups/ethan/volume
        LabelMedia = yes
        Random Access = yes
        AutomaticMount = yes
        RemovableMedia = no
        AlwaysOpen = no
        Maximum Concurrent Jobs = 4
}

Device {
        Name = tardisDevice
        Media Type = MediaType
        Archive Device = /backups/tardis/volume
        LabelMedia = yes
        Random Access = yes
        AutomaticMount = yes
        RemovableMedia = no
        AlwaysOpen = no
        Maximum Concurrent Jobs = 4
}

НАСТРОЙКА СЕРВЕРА: КОНСОЛЬ

Ну тут все просто.

Director {
        Name = BaculaDirector
        Password = "parol_directora"
        Address = 127.0.0.1
}

НАСТРОЙКА СЕРВЕРА: БЕКАП POSTGRESQL

Бекап постргрес работает следующим образом. Бакула запускает пайтон скрипт, который дампит базы данных, затем bacula-fd передает их на сервер. Файлы копируются полностью каждый день с ротацией раз в месяц (если сторадж исчерпан). На сторадже выделяется 80 гигабайт на все про все. Количество томов может достигать 32-х (32 бекапа в месяц).
/usr/local/etc/bacula/ethan_client.conf:

# Client Settings #
Client {
        Name = ethan
        Password = "parol_directora"
        Address = 192.168.1.14
        Catalog = BaculaCatalog
        Maximum Concurrent Jobs = 4
}

# Backup Job #
Job {
        Name = "ethan_postgresql"
        Client = ethan
        Type = "Backup"
        Fileset = "ethan_FileSet"
        Storage = ethanStorage
        Schedule = ethan_Schedule
        ClientRunBeforeJob = "/etc/bacula/custom/bacula-postgres.py start"
        Messages = Daemon
        Pool = ethan_Full
        Full Backup Pool = ethan_Full
        ClientRunAfterJob = "/etc/bacula/custom/bacula-postgres.py clean"
}

# Restore Job #
Job {
        Name = "ethan_RestoreData"
        Type = Restore
        Client = ethan
        FileSet = ethan_FileSet
        Storage = ethanStorage
        Schedule = ethan_Schedule
        Messages = Daemon
        Pool = ethan_Full
        Where = /opt/bacula-restore
        Enabled = no
}

# What to Backup and What to Exclude #
FileSet {
        Name = "ethan_FileSet"
        Include {
                Options {
                        signature=MD5
                }
                File = /opt/postgres-backup
                File = /opt/1C
                File = /opt/1cbase
        }
        Exclude {
                File = *~
        }
}

# Where and How to Backup #
Pool {
        Name                    = ethan_Full
        Pool Type               = Backup
        Recycle                 = yes
        AutoPrune               = yes
        Volume Retention        = 1 month
        Storage                 = ethanStorage
        Maximum Volume Bytes    = 80G
        Maximum Volumes         = 32
        LabelFormat             = "ethan_FullAuto-"
}

# When to Backup #
Schedule {
        Name = ethan_Schedule
        Run = Level=Full mon-sun at 3:15
}

Как видно по секции FileSet { ... } данные будут копироваться с директорий /opt/postgres-backup, /opt/1C и /opt/1cbase. База 1С у нас на постгрес, потому вместе с ним забираем еще и файлы сервера на всякий кейс и списки баз данных, которые расшариваем по самбе.
Обратите внимание на Restore job. Там указан на каком клиенте и в какой директории восстанавливать данные при восстановлении т.е. восстановление происходит не на сервере, а сразу на клиенте. Директива Enabled=no задан, чтобы задача восстановления не запускалась по планировщику задач, но чтобы можно было ее вручную выполнить с bconsole.

НАСТРОЙКА КЛИЕНТА: БЕКАП POSTGRESQL

Вот такие настройки bacula-fd.conf на стороне клиента.

Director {
        Name = BaculaDirector
        Password = "parol_directora"
}

FileDaemon {
        Name = ethan
        FDport = 9102
        WorkingDirectory = /var/lib/bacula
        Pid Directory = /var/run
        Maximum Concurrent Jobs = 20
        FDAddress = 192.168.1.14
}

Messages {
        Name = Daemon
        director = BaculaDirector = all, !skipped, !restored
}

А вот такой скрипт дампит базы данных постгрес.

#!/usr/bin/env python3

import os
import sys
import subprocess
from time import *
import datetime
import shutil
from termcolor import colored

def tmp_exists(tmp_dir):
        print('[*] Check temp directory...')
        if not os.path.isdir(tmp_dir):
                print(' - '+tmp_dir+' not found. Creating directory...')
                os.makedirs(tmp_dir)
                call('chown bacula:bacula '+tmp_dir);
        else:
                print(' - '+tmp_dir+' found. Continue...')
        return True

def psql_dump(psql_user,tmp_dir):
        print('[*] PostgreSQL dump...')
        code,result,err = call("psql -U "+psql_user+" -c 'select datname from pg_database where datistemplate = false;'|grep -Ev 'datname|-|rows|postgres'|sed '/^\s*$/d'|awk '{print $1}'")
        dblist = result.split("\n")
        dblist = filter(None,dblist)
        current_date = strftime("%d-%m-%Y")
        for n,val in enumerate(dblist):
                print(' - '+val)
                call('pg_dump -U '+psql_user+' --clean --if-exists '+val+' > '+tmp_dir+'/'+val+'-'+current_date+'.psql')
                call('gzip -q -f '+tmp_dir+'/'+val+'-'+current_date+'.psql')
                call('chown bacula:bacula '+tmp_dir+'/'+val+'-'+current_date+'.psql.gz')

def remove_dump(tmp_dir):
        print('Removing '+tmp_dir)
        shutil.rmtree(tmp_dir)


def call(command):
        process = subprocess.Popen(command,stdout = subprocess.PIPE,stderr = subprocess.PIPE,shell = True,universal_newlines=True)
        std_out,std_err = process.communicate()
        return process.returncode,std_out,std_err

def main():
        psql_user = 'postgres'
        tmp_dir = '/opt/postgres-backup'

        if sys.argv[1] == 'start':
                print('[!] Starting a backup job...')
                if tmp_exists(tmp_dir):
                        psql_dump(psql_user,tmp_dir)

        if sys.argv[1] == 'clean':
                print('[!] Cleaning backups...')
                if tmp_exists(tmp_dir):
                        remove_dump(tmp_dir)

main()

НАСТРОЙКА СЕРВЕРА: БЕКАП SAMBA

Раз в год делается полная резеврная копия файловой помойки. Далее уже каждый день делается дифференциальный бекап для экономии места (бекапятся только новые и измененные файлы).
/usr/local/etc/bacula/tardis_client.conf:

# Client Settings #
Client {
        Name = tardis
        Password = "parl_directora"
        Address = 192.168.1.6
        Catalog = BaculaCatalog
        Maximum Concurrent Jobs = 4
}

# Backup Job #
Job {
        Name = "tardis_files"
        Client = tardis
        Type = "Backup"
        Fileset = "tardis_FileSet"
        Storage = tardisStorage
        Schedule = tardis_Schedule
        Messages = Daemon
        Pool = tardis_Full
        Full Backup Pool = tardis_Full
        Differential Backup Pool = tardis_Diff
        Spool Data = no
        Spool Attributes = yes
}

# Restore Job #
Job {
        Name = "tardis_RestoreData"
        Type = Restore
        Client = tardis
        FileSet = tardis_FileSet
        Storage = tardisStorage
        Schedule = tardis_Schedule
        Messages = Daemon
        Pool = tardis_Full
        Where = /opt/bacula-restores
        Enabled = no
}

# What to Backup and What to Exclude #
FileSet {
        Name = "tardis_FileSet"
        Include {
                Options {
                        signature=MD5
                        compression=LZO
                }
                File = /opt/atlassian
                File = /opt/share
                File = /opt/wwwservices
        }
        Exclude {
                File = *~
                File = *.log
                File = *.gz
                File = *.zip
                File = *.7z
                File = *.rar
                File = *.tar
                File = *.mp3
                File = *.iso
                File = *.img
                File = *.exe
        }
}

# Where and How to Backup #
Pool {
        Name                    = tardis_Full
        Pool Type               = Backup
        Recycle                 = yes
        Purge Oldest Volume     = yes
        AutoPrune               = yes
        Volume Retention        = 1 year
        Storage                 = tardisStorage
        Maximum Volume Bytes    = 9T
        Maximum Volumes         = 1
        LabelFormat             = "tardis_FullAuto-"
}

Pool {
        Name                    = tardis_Diff
        Pool Type               = Backup
        Recycle                 = yes
        Purge Oldest Volume     = yes
        AutoPrune               = yes
        Volume Retention        = 1 weeks
        Storage                 = tardisStorage
        Maximum Volume Bytes    = 600G
        Maximum Volumes         = 14
        LabelFormat             = "tardis_DiffAuto-"
}

# When to Backup #
Schedule {
        Name = tardis_Schedule
        Run = Level=Full jan 1st sat at 1:00
        Run = Level=Differential on 2-31 at 1:00
}

Думаю объяснять тут особо нечего кроме volumes. Max volumes bytes это объем, которое может достигать один том, а томов максимум может быть 14. Если последний том вышел за пределы 600 гигабайт, то создается и заполняется новый. Если места нет, то предыдущие вычищаяются при этом операция очищения может проводиться только раз в неделю.

НАСТРОЙКА КЛИЕНТА: БЕКАП SAMBA

Ну тут стандартный конфиг без изысков.
/etc/bacula/bacula-fd.conf:

Director {
        Name = BaculaDirector
        Password = "parol_directora"
}

FileDaemon {
        Name = tardis
        FDport = 9102
        WorkingDirectory = /var/lib/bacula
        Pid Directory = /var/run
        Maximum Concurrent Jobs = 20
        FDAddress = 192.168.1.6
}

Messages {
        Name = Daemon
        director = BaculaDirector = all, !skipped, !restored
}

P.S. О установке bacula web interface читайте тут.