RabbitMQ Backup ve Restore: Kuyruk Yapılandırmalarını Yedekleme ve Kurtarma Rehberi
Production ortamında RabbitMQ çalıştıran herkes bir gün şu soruyla yüzleşir: “Sunucu çökerse ne olacak?” Bu soru aslında daha spesifik birkaç soruya ayrılıyor. Exchange’lerim kaybolursa ne olur? Queue binding’lerim silindi mi? Virtual host yapılandırmam yerli yerinde mi? İşte bu rehberde bu soruların hepsine pratik cevaplar vereceğiz.
RabbitMQ backup konusu çoğu zaman ihmal edilir çünkü sistemin kendisi oldukça kararlı çalışır. Ama kararlı çalışması, yedeklemeye gerek olmadığı anlamına gelmiyor. Yapılandırma kayıpları, yanlışlıkla silinen queue’lar veya versiyon yükseltmelerinde yaşanan sorunlar, iyi bir backup stratejisi olmadan saatlerce süren kesintilere dönüşebilir.
RabbitMQ’da Neyi Yedekliyoruz?
Önce kafamızı netleştirelim. RabbitMQ’da yedeklenmesi gereken iki temel şey var:
Yapılandırma Verileri (Definitions):
- Virtual host’lar
- Exchange’ler
- Queue’lar
- Binding’ler
- Kullanıcılar ve izinleri
- Politikalar (policies)
- Parametre ayarları
Mesaj Verileri (Messages):
- Durable queue’lardaki kalıcı mesajlar
- Mnesia veritabanı dosyaları
Çoğu senaryoda yapılandırma yedeklemesi öncelikli. Mesaj yedeklemesi ise iş gereksinimlerinize göre değişiyor. Bazı sistemlerde mesajların kaybolması kabul edilebilirken, finansal işlemler veya kritik bildirimler söz konusu olduğunda mesajların da korunması şart oluyor.
Definitions Export ile Yapılandırma Yedekleme
RabbitMQ’nun en sağlıklı yedekleme yöntemi, Management Plugin üzerinden definitions export etmektir. Bu yöntem tüm yapılandırmayı JSON formatında dışarı aktarır.
Management API ile Export
# Tüm definitions'ı export et
curl -u admin:password http://localhost:15672/api/definitions
-o /backup/rabbitmq/definitions_$(date +%Y%m%d_%H%M%S).json
# Belirli bir virtual host'un definitions'ını export et
curl -u admin:password
http://localhost:15672/api/definitions/%2F
-o /backup/rabbitmq/vhost_default_$(date +%Y%m%d_%H%M%S).json
# Uzak sunucudan export
curl -u admin:password
http://192.168.1.100:15672/api/definitions
-o /backup/rabbitmq/remote_definitions.json
Bu komuttaki %2F ifadesi URL-encoded / karakteridir ve default virtual host’u temsil eder. Farklı bir vhost için %2Fmyvhost gibi kullanabilirsiniz.
rabbitmqctl ile Export
Management Plugin’in aktif olmadığı durumlarda veya komut satırı tercih ettiğinizde rabbitmqctl kullanabilirsiniz:
# RabbitMQ 3.7.0 ve sonrası için
rabbitmqctl export_definitions /backup/rabbitmq/definitions.json
# JSON formatını okunabilir hale getirme
rabbitmqctl export_definitions /dev/stdout | python3 -m json.tool
> /backup/rabbitmq/definitions_pretty.json
# Belirli vhost için
rabbitmqctl export_definitions /backup/rabbitmq/definitions.json
--vhost="production"
Otomatik Yedekleme Script’i
Gerçek dünyada bu işlemi manuel yapmak yerine script haline getirip cron’a bağlamalısınız:
#!/bin/bash
# /usr/local/bin/rabbitmq-backup.sh
BACKUP_DIR="/var/backup/rabbitmq"
LOG_FILE="/var/log/rabbitmq-backup.log"
RETENTION_DAYS=30
RABBITMQ_USER="admin"
RABBITMQ_PASS="your_secure_password"
RABBITMQ_HOST="localhost"
RABBITMQ_PORT="15672"
DATE=$(date +%Y%m%d_%H%M%S)
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Backup dizini oluştur
mkdir -p "$BACKUP_DIR"
log "RabbitMQ backup başlatılıyor..."
# Definitions export
BACKUP_FILE="$BACKUP_DIR/definitions_${DATE}.json"
if curl -sf -u "${RABBITMQ_USER}:${RABBITMQ_PASS}"
"http://${RABBITMQ_HOST}:${RABBITMQ_PORT}/api/definitions"
-o "$BACKUP_FILE"; then
log "Definitions başarıyla export edildi: $BACKUP_FILE"
# Dosya boyutunu kontrol et
FILE_SIZE=$(stat -c%s "$BACKUP_FILE")
if [ "$FILE_SIZE" -lt 100 ]; then
log "UYARI: Backup dosyası çok küçük, kontrol edin!"
fi
else
log "HATA: Definitions export başarısız!"
exit 1
fi
# Sıkıştır
gzip "$BACKUP_FILE"
log "Backup sıkıştırıldı: ${BACKUP_FILE}.gz"
# Eski backup'ları temizle
find "$BACKUP_DIR" -name "definitions_*.json.gz"
-mtime +${RETENTION_DAYS} -delete
log "30 günden eski backup'lar temizlendi"
log "Backup tamamlandı"
Bu script’i cron’a eklemek için:
# Crontab'a ekle - her gece 02:00'de çalışsın
crontab -e
# Aşağıdaki satırı ekle
0 2 * * * /usr/local/bin/rabbitmq-backup.sh >> /var/log/rabbitmq-backup.log 2>&1
Mnesia Veritabanı Yedekleme
Mesajları ve tam sistem durumunu yedeklemek istiyorsanız Mnesia veritabanını da yedeklemeniz gerekir. Bu daha kapsamlı ama aynı zamanda daha riskli bir yöntemdir çünkü RabbitMQ çalışırken Mnesia’yı doğrudan kopyalamak veri tutarsızlığına yol açabilir.
# RabbitMQ'yu durdur
systemctl stop rabbitmq-server
# Mnesia dizinini belirle (genellikle bu yollarda bulunur)
# /var/lib/rabbitmq/mnesia/
# /opt/rabbitmq/var/lib/rabbitmq/mnesia/
MNESIA_DIR="/var/lib/rabbitmq/mnesia"
BACKUP_DIR="/var/backup/rabbitmq/mnesia"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"
# Mnesia dizinini yedekle
tar -czf "${BACKUP_DIR}/mnesia_${DATE}.tar.gz"
-C /var/lib/rabbitmq mnesia/
echo "Mnesia backup tamamlandı: ${BACKUP_DIR}/mnesia_${DATE}.tar.gz"
# RabbitMQ'yu yeniden başlat
systemctl start rabbitmq-server
Önemli Not: Production ortamında RabbitMQ’yu durdurmadan Mnesia yedeklemesi yapmak istiyorsanız, önce node’u cluster’dan çıkarmanız veya hot-standby bir setup kullanmanız gerekir.
Yapılandırma Geri Yükleme (Import)
Şimdi asıl kritik kısma geldik: yedekten geri yükleme. Panik anında hata yapmamak için bu adımları önceden test etmiş olmanız çok önemli.
Management API ile Import
# Definitions'ı import et
curl -X POST
-u admin:password
-H "Content-Type: application/json"
-d @/backup/rabbitmq/definitions_20240115_020000.json
http://localhost:15672/api/definitions
# Belirli bir virtual host'a import
curl -X POST
-u admin:password
-H "Content-Type: application/json"
-d @/backup/rabbitmq/vhost_definitions.json
http://localhost:15672/api/definitions/%2Fproduction
# Sıkıştırılmış backup'tan import
gunzip -c /backup/rabbitmq/definitions_20240115_020000.json.gz |
curl -X POST
-u admin:password
-H "Content-Type: application/json"
-d @-
http://localhost:15672/api/definitions
rabbitmqctl ile Import
# Definitions import
rabbitmqctl import_definitions /backup/rabbitmq/definitions.json
# Sıkıştırılmış dosyadan import
gunzip -c /backup/rabbitmq/definitions.json.gz |
rabbitmqctl import_definitions /dev/stdin
Tam Sistem Kurtarma Prosedürü
Sunucunun tamamen çöktüğü ve sıfırdan kurmanız gerektiği senaryo için adım adım kurtarma prosedürü:
#!/bin/bash
# Tam sistem kurtarma script'i
BACKUP_FILE="/backup/rabbitmq/definitions_latest.json"
RABBITMQ_USER="admin"
RABBITMQ_PASS="your_secure_password"
echo "=== RabbitMQ Kurtarma Başlatılıyor ==="
# 1. RabbitMQ servis durumunu kontrol et
if ! systemctl is-active --quiet rabbitmq-server; then
echo "RabbitMQ başlatılıyor..."
systemctl start rabbitmq-server
sleep 10
fi
# 2. Management plugin aktif mi kontrol et
rabbitmq-plugins list | grep -q "rabbitmq_management.*E"
if [ $? -ne 0 ]; then
echo "Management plugin aktifleştiriliyor..."
rabbitmq-plugins enable rabbitmq_management
sleep 5
fi
# 3. Admin kullanıcısı oluştur (eğer yoksa)
rabbitmqctl list_users | grep -q "^admin"
if [ $? -ne 0 ]; then
echo "Admin kullanıcısı oluşturuluyor..."
rabbitmqctl add_user admin "$RABBITMQ_PASS"
rabbitmqctl set_user_tags admin administrator
rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
fi
# 4. Definitions import
echo "Definitions import ediliyor: $BACKUP_FILE"
if [ -f "${BACKUP_FILE}.gz" ]; then
gunzip -c "${BACKUP_FILE}.gz" | rabbitmqctl import_definitions /dev/stdin
elif [ -f "$BACKUP_FILE" ]; then
rabbitmqctl import_definitions "$BACKUP_FILE"
else
echo "HATA: Backup dosyası bulunamadı!"
exit 1
fi
echo "=== Kurtarma Tamamlandı ==="
rabbitmqctl list_vhosts
rabbitmqctl list_queues
Cluster Ortamında Yedekleme
Cluster kullanıyorsanız yedekleme stratejiniz biraz farklılaşır. Cluster’da definitions tek bir node’dan export edilse de tüm cluster’ı kapsıyor. Asıl önemli olan Mnesia verilerini doğru şekilde yönetmek.
# Cluster durumunu kontrol et
rabbitmqctl cluster_status
# Aktif node'lardan definitions export
for node in rabbit@node1 rabbit@node2 rabbit@node3; do
NODE_HOST=$(echo $node | cut -d@ -f2)
curl -sf -u admin:password
"http://${NODE_HOST}:15672/api/definitions"
-o "/backup/rabbitmq/${NODE_HOST}_definitions_$(date +%Y%m%d).json"
if [ $? -eq 0 ]; then
echo "Node ${NODE_HOST} backup alındı"
else
echo "UYARI: Node ${NODE_HOST} erişilemedi!"
fi
done
# Queue mirror politikası tanımla (HA için)
rabbitmqctl set_policy ha-all "^"
'{"ha-mode":"all","ha-sync-mode":"automatic"}'
--priority 0 --apply-to queues
Uygulama Yapılandırmasını da Yedekleyin
RabbitMQ’nun kendi yapılandırma dosyasını da yedeklemeyi unutmayın:
#!/bin/bash
# RabbitMQ tam yedekleme - hem definitions hem config
BACKUP_DIR="/var/backup/rabbitmq/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
# Ana yapılandırma dosyaları
CONFIG_FILES=(
"/etc/rabbitmq/rabbitmq.conf"
"/etc/rabbitmq/advanced.config"
"/etc/rabbitmq/rabbitmq-env.conf"
"/etc/rabbitmq/enabled_plugins"
)
for config in "${CONFIG_FILES[@]}"; do
if [ -f "$config" ]; then
cp "$config" "$BACKUP_DIR/"
echo "Kopyalandı: $config"
fi
done
# SSL sertifikaları (varsa)
if [ -d "/etc/rabbitmq/ssl" ]; then
cp -r /etc/rabbitmq/ssl "$BACKUP_DIR/"
echo "SSL sertifikaları kopyalandı"
fi
# Definitions export
curl -sf -u admin:password
http://localhost:15672/api/definitions
-o "$BACKUP_DIR/definitions.json"
# Tüm backup'ı sıkıştır
cd /var/backup/rabbitmq
tar -czf "rabbitmq_full_backup_$(date +%Y%m%d).tar.gz"
"$(date +%Y%m%d)/"
# Dizini temizle
rm -rf "$(date +%Y%m%d)/"
echo "Tam backup tamamlandı: rabbitmq_full_backup_$(date +%Y%m%d).tar.gz"
Backup Doğrulama
Backup aldıktan sonra doğrulamayı ihmal etmeyin. Alınamayan veya bozuk bir backup, hiç yoktan farklı değil:
#!/bin/bash
# Backup doğrulama script'i
BACKUP_FILE="$1"
if [ -z "$BACKUP_FILE" ]; then
echo "Kullanım: $0 <backup_dosyasi>"
exit 1
fi
echo "=== Backup Doğrulama ==="
# Dosya varlığını kontrol et
if [ ! -f "$BACKUP_FILE" ]; then
echo "HATA: Dosya bulunamadı: $BACKUP_FILE"
exit 1
fi
# Sıkıştırma kontrolü
if [[ "$BACKUP_FILE" == *.gz ]]; then
if ! gunzip -t "$BACKUP_FILE" 2>/dev/null; then
echo "HATA: Sıkıştırılmış dosya bozuk!"
exit 1
fi
JSON_CONTENT=$(gunzip -c "$BACKUP_FILE")
else
JSON_CONTENT=$(cat "$BACKUP_FILE")
fi
# JSON geçerliliği kontrol et
if ! echo "$JSON_CONTENT" | python3 -m json.tool > /dev/null 2>&1; then
echo "HATA: Geçersiz JSON formatı!"
exit 1
fi
# İçerik kontrolü
VHOST_COUNT=$(echo "$JSON_CONTENT" | python3 -c "
import sys, json
data = json.load(sys.stdin)
print(len(data.get('vhosts', [])))
")
QUEUE_COUNT=$(echo "$JSON_CONTENT" | python3 -c "
import sys, json
data = json.load(sys.stdin)
print(len(data.get('queues', [])))
")
EXCHANGE_COUNT=$(echo "$JSON_CONTENT" | python3 -c "
import sys, json
data = json.load(sys.stdin)
print(len(data.get('exchanges', [])))
")
echo "Backup Ozeti:"
echo " Virtual Hosts: $VHOST_COUNT"
echo " Queues: $QUEUE_COUNT"
echo " Exchanges: $EXCHANGE_COUNT"
echo " Dosya Boyutu: $(du -sh "$BACKUP_FILE" | cut -f1)"
echo " Son Degisiklik: $(stat -c %y "$BACKUP_FILE")"
echo ""
echo "Backup geçerli ve kullanılabilir durumda."
Gerçek Dünya Senaryosu: Production Kurtarma
Geçen yıl bir e-ticaret platformunda yaşanan bir olayı paylaşmak istiyorum. Disk full nedeniyle RabbitMQ Mnesia bozulmuş ve tüm queue yapılandırmaları gitmişti. Sitedeki sipariş mesajları işlenemiyor, binlerce kullanıcı etkileniyordu.
Neyse ki nightly backup aktifti. Kurtarma süreci şöyle ilerledi:
- Yeni bir RabbitMQ instance kuruldu (15 dakika)
- Management plugin aktifleştirildi ve admin kullanıcısı oluşturuldu (3 dakika)
- Son gece alınan definitions backup’ı import edildi (2 dakika)
- Uygulama sunucuları yeni RabbitMQ’ya yönlendirildi (5 dakika)
Toplam kesinti süresi 25 dakikaydı. Backup olmadan bu süre saatler, hatta günler olabilirdi. Özellikle hangi exchange’in hangi queue’ya nasıl bağlı olduğunu elle yeniden oluşturmak düşünülemez bile.
Backup Stratejisi Önerileri
Sıklık seçimi için:
- Geliştirme ortamı: Günlük backup yeterli
- Test ortamı: Her değişiklik sonrası manual backup
- Production ortamı: Saatlik definitions backup, günlük tam backup
Saklama süresi için:
- Son 7 günlük backup’ı tam tut
- Son 4 haftanın haftalık backup’larını tut
- Son 12 ayın aylık backup’larını tut
Güvenlik için:
- Backup dosyalarına şifreleme uygulayın
- Backup’ları farklı bir sunucuya veya cloud storage’a kopyalayın
- Backup kullanıcısı için minimum yetki prensibini uygulayın
Test için:
- Ayda en az bir kez restore testi yapın
- Restore testini üretim ortamından izole bir test sunucusunda gerçekleştirin
- Her backup’tan sonra doğrulama script’ini çalıştırın
Sonuç
RabbitMQ backup ve restore konusu göründüğünden çok daha kritik. Sistemin kararlı çalışması sizi aldatmasın. Queue yapılandırmalarını yeniden oluşturmak, binding’leri hatırlamak, kullanıcı izinlerini tekrar tanımlamak, özellikle ekip üyelerinin değiştiği veya dokümantasyonun yetersiz olduğu ortamlarda son derece güç olabiliyor.
Bu rehberde anlattığım yöntemleri sırayla uygulayın: Önce definitions export’u otomasyona bağlayın, sonra doğrulama script’ini entegre edin, ardından bir disaster recovery planı oluşturun ve bunu düzenli aralıklarla test edin. Backup’ın var olması kadar, çalışıyor olması da önemli.
Son bir hatırlatma: Bu script’leri production’a almadan önce mutlaka test ortamında deneyin. Her RabbitMQ versiyonu ve kurulum farklılıkları nedeniyle küçük uyarlamalar gerekebilir. Ama temel mantık her yerde aynı: düzenli al, güvenli sakla, düzenli test et.
