Bacula ile İlk Yedekleme Job’ı Nasıl Tanımlanır?

Bacula kurulumunu tamamladıktan sonra sıra geldi ilk yedekleme işini tanımlamaya. Bu adım çoğu sysadmin için biraz kafa karıştırıcı olabiliyor çünkü Bacula’nın konfigürasyon yapısı diğer yedekleme araçlarına göre oldukça farklı. Director, Storage Daemon, File Daemon ve Catalog gibi bileşenler arasındaki ilişkiyi kavramak başta zor gelse de bir kez oturduktan sonra Bacula’nın ne kadar güçlü bir araç olduğunu anlıyorsunuz. Bu yazıda sıfırdan bir yedekleme job’ı tanımlayacağız, gerçek dünya senaryoları üzerinden konfigürasyonları inceleyeceğiz ve işlerin neden çalışmadığını anlamak için hata ayıklama ipuçları paylaşacağız.

Bacula’nın Konfigürasyon Mantığını Anlamak

Bacula’da her şey birbirine referans veren konfigürasyon bloklarından oluşuyor. Bir Job tanımladığınızda, bu Job bir FileSet’e, bir Schedule’a, bir Pool’a ve bir Client’a referans veriyor. Bu bileşenlerin hepsinin önceden tanımlı olması gerekiyor yoksa Director başlarken hata fırlatıyor.

Ana konfigürasyon dosyası /etc/bacula/bacula-dir.conf dosyasıdır. Ancak büyük ortamlarda bu dosyayı parçalara bölmek çok daha yönetilebilir bir yapı sağlıyor. Ben genellikle şu yapıyı tercih ediyorum:

/etc/bacula/
├── bacula-dir.conf          # Ana Director konfigürasyonu
├── clients/
│   ├── webserver01.conf
│   └── dbserver01.conf
├── jobs/
│   ├── daily-backup.conf
│   └── weekly-backup.conf
└── pools/
    └── pools.conf

Bu yapıyı kullanmak için bacula-dir.conf dosyasına @ direktifiyle include eklemeliyiz:

# bacula-dir.conf içinde include kullanımı
@/etc/bacula/clients/webserver01.conf
@/etc/bacula/jobs/daily-backup.conf
@/etc/bacula/pools/pools.conf

İlk Job Tanımı: Temel Yapı

Basit bir Linux sunucusu yedekleme job’ı tanımlamakla başlayalım. Senaryo şu: Elimizde bir web sunucusu var, her gece /var/www ve /etc dizinlerini yedeklemek istiyoruz.

Önce bir FileSet tanımlıyoruz. FileSet, neyin yedekleneceğini ve nasıl yedekleneceğini belirliyor:

FileSet {
  Name = "WebServer-FileSet"
  Include {
    Options {
      signature = MD5
      compression = GZIP
      noatime = yes
    }
    File = /var/www
    File = /etc
    File = /home
  }
  Exclude {
    File = /var/www/cache
    File = /tmp
    File = /proc
    File = /sys
  }
}

Burada dikkat edilmesi gereken birkaç nokta var. signature = MD5 her dosya için MD5 hash hesaplıyor, bu da dosya bütünlüğünü doğrulamanıza olanak tanıyor. compression = GZIP ile depolama alanından tasarruf ediyorsunuz, ancak CPU kullanımı artıyor. Düşük CPU’lu sistemlerde bunu devre dışı bırakmak daha mantıklı olabilir. noatime = yes parametresi ise yedekleme sırasında dosyaların erişim zamanını güncellemesini engelliyor.

Schedule Tanımlama

Yedeklemenin ne zaman çalışacağını belirleyen Schedule bloğu:

Schedule {
  Name = "DailyBackupSchedule"
  Run = Full 1st sun at 23:00
  Run = Differential 2nd-5th sun at 23:00
  Run = Incremental mon-sat at 23:00
}

Bu konfigürasyonda klasik GFS (Grandfather-Father-Son) stratejisini uyguluyoruz. Her ayın ilk Pazar günü tam yedek alınıyor, diğer Pazar günleri differential yedek alınıyor, hafta içi ise sadece değişen dosyalar yedekleniyor. Bu strateji hem depolama alanından tasarruf sağlıyor hem de geri yükleme süreçlerini makul bir sürede tutuyoruz.

Pool Konfigürasyonu

Pool, yedekleme bantlarının veya disk birimlerinin nasıl yönetileceğini tanımlıyor. Disk tabanlı yedekleme için şu konfigürasyonu kullanıyoruz:

Pool {
  Name = "DailyPool"
  Pool Type = Backup
  Recycle = yes
  AutoPrune = yes
  Volume Retention = 30 days
  Maximum Volume Bytes = 50G
  Maximum Volumes = 100
  Label Format = "Daily-"
  Storage = FileStorage
}

Pool {
  Name = "WeeklyPool"
  Pool Type = Backup
  Recycle = yes
  AutoPrune = yes
  Volume Retention = 90 days
  Maximum Volume Bytes = 100G
  Maximum Volumes = 20
  Label Format = "Weekly-"
  Storage = FileStorage
}

Volume Retention parametresi, bir volume’ün ne kadar süre saklanacağını belirliyor. AutoPrune = yes ile süresi dolan volume’ler otomatik olarak temizleniyor. Label Format ise Bacula’nın otomatik olarak oluşturacağı volume isimlerinin prefix’ini belirliyor.

Storage Daemon Konfigürasyonu

Storage Daemon konfigürasyonunda yedeklerin fiziksel olarak nereye yazılacağını belirliyoruz:

# /etc/bacula/bacula-sd.conf

Storage {
  Name = bacula-sd
  SDPort = 9103
  WorkingDirectory = "/var/lib/bacula"
  Pid Directory = "/run/bacula"
  Maximum Concurrent Jobs = 10
}

Director {
  Name = bacula-dir
  Password = "guclu-bir-sifre-buraya"
}

Autochanger {
  Name = FileStorage
  Device = FileChanger
  Changer Command = ""
  Changer Device = /dev/null
}

Device {
  Name = FileChanger
  Media Type = File
  Archive Device = /backup/bacula
  LabelMedia = yes
  Random Access = yes
  AutomaticMount = yes
  RemovableMedia = no
  AlwaysOpen = no
  Maximum Concurrent Jobs = 5
}

/backup/bacula dizininin mevcut olduğundan ve Bacula kullanıcısının bu dizine yazma yetkisi olduğundan emin olun:

mkdir -p /backup/bacula
chown -R bacula:bacula /backup/bacula
chmod 750 /backup/bacula

Client Konfigürasyonu

Director tarafında client tanımı şu şekilde yapılıyor:

Client {
  Name = webserver01-fd
  Address = 192.168.1.10
  FDPort = 9102
  Catalog = MyCatalog
  Password = "client-sifre-buraya"
  File Retention = 60 days
  Job Retention = 6 months
  AutoPrune = yes
}

File Retention ve Job Retention parametreleri Catalog veritabanında ne kadar süre kayıt tutulacağını belirliyor. Bu değerleri gerçekçi tutmak önemli, çok uzun tutarsanız Catalog veritabanı şişiyor.

Client tarafında ise /etc/bacula/bacula-fd.conf dosyasını düzenliyoruz:

Director {
  Name = bacula-dir
  Password = "client-sifre-buraya"
}

FileDaemon {
  Name = webserver01-fd
  FDport = 9102
  WorkingDirectory = /var/lib/bacula
  Pid Directory = /run/bacula
  Maximum Concurrent Jobs = 5
}

Messages {
  Name = Standard
  director = bacula-dir = all, !skipped, !restored
}

Ana Job Tanımı

Artık tüm bileşenler hazır, asıl Job bloğunu yazabiliyoruz:

Job {
  Name = "WebServer-Daily-Backup"
  Type = Backup
  Level = Incremental
  Client = webserver01-fd
  FileSet = "WebServer-FileSet"
  Schedule = "DailyBackupSchedule"
  Storage = FileStorage
  Messages = Standard
  Pool = DailyPool
  Full Backup Pool = WeeklyPool
  Priority = 10
  Write Bootstrap = "/var/lib/bacula/webserver01-%j.bsr"
  Maximum Concurrent Jobs = 1
}

Write Bootstrap parametresi çok önemli. BSR (Bootstrap) dosyası, bir felakette Catalog olmadan bile yedekten geri dönmenizi sağlıyor. Bu dosyayı güvenli bir yerde saklayın, hatta yedekleyin.

Full Backup Pool ile tam yedekler farklı bir Pool’a yönlendiriyoruz. Bu sayede günlük incremental yedekler DailyPool‘a, haftalık full yedekler ise WeeklyPool‘a gidiyor.

Konfigürasyonu Doğrulama

Job tanımlarken en sık yapılan hata, konfigürasyonu test etmeden servisi yeniden başlatmak. Bacula Director’ı başlatmadan önce mutlaka syntax kontrolü yapın:

# Director konfigürasyonunu test et
bacula-dir -t -c /etc/bacula/bacula-dir.conf

# Storage Daemon konfigürasyonunu test et
bacula-sd -t -c /etc/bacula/bacula-sd.conf

# File Daemon konfigürasyonunu test et
bacula-fd -t -c /etc/bacula/bacula-fd.conf

Hata yoksa servisleri yeniden başlatın:

systemctl restart bacula-director
systemctl restart bacula-sd
systemctl restart bacula-fd

bconsole ile İlk Job’ı Çalıştırma

Konfigürasyonu doğruladıktan sonra bconsole üzerinden job’ı manuel olarak tetikleyip test edebilirsiniz:

# bconsole'a bağlan
bconsole

# Bağlantıyı test et
*status director

# Tanımlı job'ları listele
*show jobs

# Job'ı manuel çalıştır
*run job="WebServer-Daily-Backup" level=Full yes

# Job durumunu takip et
*status client=webserver01-fd

# Çalışan job'ları görüntüle
*status dir

# Job mesajlarını görüntüle
*messages

# Son job'ın detaylarını göster
*list jobs

İlk full backup’ı manuel olarak level=Full ile çalıştırmanızı tavsiye ederim. Bu sayede her şeyin doğru çalıştığını doğrulayabilirsiniz.

Volume Label Oluşturma

Disk tabanlı yedeklemelerde ilk çalıştırmadan önce volume label oluşturmanız gerekebilir. Bacula LabelMedia = yes ayarıyla bunu otomatik yapabiliyor ancak bazen manuel müdahale gerekiyor:

# bconsole içinde
*label storage=FileStorage pool=DailyPool

# Bacula size volume ismi soracak, Label Format'a uygun bir isim girin
Enter new Volume name: Daily-0001

# Veya otomatik label
*label storage=FileStorage pool=DailyPool barcodes

Gerçek Dünya Senaryosu: Veritabanı Sunucusu Yedekleme

Web sunucusu yedeklemesi nispeten basit. Asıl karmaşıklık veritabanı sunucularında başlıyor. PostgreSQL yedeklemek için önce bir pre-script ile dump almanız, sonra bu dump’ı yedeklemeniz gerekiyor. Şöyle yapıyoruz:

Job {
  Name = "DBServer-Daily-Backup"
  Type = Backup
  Level = Full
  Client = dbserver01-fd
  FileSet = "DBServer-FileSet"
  Schedule = "DailyBackupSchedule"
  Storage = FileStorage
  Messages = Standard
  Pool = DailyPool
  Priority = 20
  Write Bootstrap = "/var/lib/bacula/dbserver01-%j.bsr"
  
  # Yedekleme öncesi PostgreSQL dump al
  Client Run Before Job = "/usr/local/bin/pre-backup-db.sh"
  
  # Yedekleme sonrası dump dosyasını temizle
  Client Run After Job = "/usr/local/bin/post-backup-db.sh"
}

pre-backup-db.sh scripti:

#!/bin/bash
# /usr/local/bin/pre-backup-db.sh

DUMP_DIR="/var/backups/db-dumps"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/bacula-pre-backup.log"

mkdir -p $DUMP_DIR

echo "$(date): PostgreSQL dump basliyor" >> $LOG_FILE

# Tum veritabanlarini dump al
sudo -u postgres pg_dumpall -f "$DUMP_DIR/all_databases_$DATE.sql"

if [ $? -eq 0 ]; then
    echo "$(date): PostgreSQL dump basarili" >> $LOG_FILE
    # Eski dump dosyalarini temizle (7 gunden eski)
    find $DUMP_DIR -name "*.sql" -mtime +7 -delete
    exit 0
else
    echo "$(date): PostgreSQL dump BASARISIZ" >> $LOG_FILE
    exit 1
fi

Bu scriptin çalışabilmesi için bacula kullanıcısına gerekli izinleri vermeyi unutmayın. Script başarısız olursa (exit 1 döndürürse) Bacula job’ı durduruyor, bu tam istediğimiz davranış.

Hata Ayıklama: En Sık Karşılaşılan Sorunlar

Yedekleme job’ları bazen beklenmedik şekillerde başarısız oluyor. En sık karşılaştığım sorunlar ve çözümleri şunlar:

Bağlantı Sorunları: Director Client’a ulaşamıyorsa log dosyasına bakın:

# Director log dosyasını takip et
tail -f /var/log/bacula/bacula.log

# Daha detaylı debug icin
bacula-dir -d 200 -c /etc/bacula/bacula-dir.conf

# Firewall kurallarini kontrol et
firewall-cmd --list-all
# veya
iptables -L -n | grep 9102

Yetki Sorunları: Bacula çoğu zaman dosyalara erişemiyor çünkü yedeklenecek dosyalar root’a ait. File Daemon’ın root olarak çalıştığından emin olun:

# File Daemon'in hangi kullaniciyla calistigini kontrol et
ps aux | grep bacula-fd

# Servis dosyasini kontrol et
systemctl cat bacula-fd | grep User

Catalog Sorunları: MySQL/PostgreSQL tabanlı Catalog bozulursa yedekleme işleri görünmez hale geliyor:

# Catalog veritabanini kontrol et
bconsole
*list pools
*list clients
*list jobs

# Catalog'u onar
/etc/bacula/scripts/make_bacula_tables mysql

Başarılı Yedeklemeyi Doğrulama

Yedekleme aldıktan sonra gerçekten çalışıp çalışmadığını doğrulamak kritik. “Yedek aldım” ile “geri yükleyebileceğim bir yedek aldım” arasında büyük fark var:

# bconsole ile son job'i dogrula
*list joblog jobid=1

# Yedeklenen dosyalari goruntule
*list files jobid=1

# Volume icerigini kontrol et
*list volumes

# Test amacli dosya geri yukle
*restore client=webserver01-fd where=/tmp/bacula-restore

# Restore sonrasi dosyalari karsilastir
diff -r /var/www/html /tmp/bacula-restore/var/www/html

Ayda en az bir kez restore testi yapmanızı şiddetle tavsiye ediyorum. Restore hiç test edilmemiş bir yedekleme sistemi, olmayan bir yedekleme sistemiyle aynı şeydir.

E-posta Bildirimleri Ayarlama

Job tamamlandığında e-posta almak için Messages bloğunu konfigüre edin:

Messages {
  Name = Standard
  mailcommand = "/usr/sbin/bsmtp -h localhost -f "(Bacula) <[email protected]>" -s "Bacula: %t %e of %c %l" %r"
  mail = [email protected] = all, !skipped
  operator = [email protected] = mount
  console = all, !skipped, !saved
  append = "/var/log/bacula/bacula.log" = all, !skipped
  catalog = all
}

Bu konfigürasyonla başarılı yedeklemeler de dahil tüm durumlar için mail alıyorsunuz. Çok fazla mail gelmesini istemiyorsanız mail = ... = error, !skipped şeklinde sadece hatalarda bildirim alacak şekilde ayarlayabilirsiniz.

Performans Optimizasyonu İpuçları

Büyük dosya sistemlerini yedeklerken Bacula bazen yavaş kalabiliyor. Birkaç pratik optimizasyon:

  • Maximum Concurrent Jobs değerini artırarak paralel yedekleme yapabilirsiniz ancak I/O darboğazı oluşturabilir.
  • Sparse File desteğini aktif edin, özellikle sanal makine disk imajlarını yedekliyorsanız: Options { sparse = yes }
  • Ağ üzerinden yedeklemelerde bant genişliği limitlemesi için Maximum Bandwidth Per Job = 50 mb/s kullanabilirsiniz.
  • Incremental yedeklemelerin hızını artırmak için Accurate = yes yerine default davranışı kullanın. Accurate mod dosya sistemi üzerinde ek yük oluşturuyor.

Sonuç

Bacula’da ilk job tanımlamak başta karmaşık görünse de bileşenler arasındaki ilişkiyi kavradıktan sonra son derece esnek ve güçlü bir sistem kurabiliyorsunuz. FileSet, Schedule, Pool ve Client tanımlarını doğru yapılandırdığınızda günlerce sorunsuz çalışan bir yedekleme altyapısı elde ediyorsunuz.

En kritik nokta şu: Yedekleme aldığınızı sanmak ile gerçekten geri yükleyebileceğiniz bir yedek almak farklı şeyler. Her kurulumdan sonra ve düzenli aralıklarla restore testi yapın. BSR dosyalarınızı güvenli bir yerde saklayın. Log dosyalarını düzenli olarak gözden geçirin.

Bir sonraki yazıda Bacula’da restore işlemlerini detaylıca ele alacağız: Tek dosya geri yüklemeden tam sistem kurtarmaya kadar tüm senaryoları inceleyeceğiz.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir