Rclone ile Çoklu Bulut Yedekleme Stratejisi

Yedekleme konusunda “bir yedek, yedek değildir” lafını mutlaka duymuşsunuzdur. Peki ya “tek bulut, yeterli değildir” dersek? Üretim ortamlarında AWS S3’ün bir bölgesinin saatler boyunca erişilemez kaldığına, Backblaze B2’nin planlanmamış bakım yaptığına veya Google Cloud Storage faturalarının beklenmedik şekilde şiştiğine tanıklık ettim. İşte tam bu noktada çoklu bulut yedekleme stratejisi hayat kurtarıcı oluyor. Bu yazıda Rclone kullanarak birden fazla bulut sağlayıcısına aynı anda yedekleme yapan, otomatik çalışan ve izlenebilir bir sistem kuracağız.

Rclone Neden Bu İş İçin Biçilmiş Kaftan?

Rclone, 70’ten fazla bulut depolama sağlayıcısını destekleyen açık kaynaklı bir komut satırı aracı. Sadece kopyalama yapmıyor; senkronizasyon, şifreleme, bant genişliği sınırlama, paralel transfer gibi ciddi özellikler sunuyor. Bir sysadmin olarak benim için en büyük avantajı tek bir araçla AWS S3, Backblaze B2, Google Drive, Wasabi ve hatta SFTP sunucularını aynı anda yönetebilmek.

Diğer araçlarla kıyaslandığında Rclone’un öne çıkan özellikleri:

  • Native şifreleme desteği: Veriler buluta gitmeden önce şifreleniyor, bulut sağlayıcısı bile okuyamıyor
  • Server-side copy: Destekleyen sağlayıcılarda veriyi önce indir sonra yükle döngüsünü atlıyor
  • Bant genişliği yönetimi: Mesai saatlerinde yavaş, gece hızlı çalışma gibi senaryolar mümkün
  • Mount desteği: Bulut depolamayı yerel dosya sistemi gibi bağlama imkanı
  • Zengin filtreleme: Glob pattern, regex, boyut ve tarih bazlı filtreleme

Kurulum ve Temel Konfigürasyon

Kurulum son derece basit. Rclone’un kendi install script’ini kullanmak en pratik yol:

# Linux için
curl https://rclone.org/install.sh | sudo bash

# macOS için
brew install rclone

# Windows için (PowerShell)
winget install Rclone.Rclone

# Kurulumu doğrula
rclone version

Kurulum sonrası interactive konfigürasyon sihirbazını çalıştırıyoruz. Ben genellikle bu sihirbazı yerine direkt config dosyasını tercih ederim çünkü sunucular arası kopyalamak çok daha kolay oluyor.

Config dosyası varsayılan olarak ~/.config/rclone/rclone.conf konumunda. Örnek bir çoklu sağlayıcı konfigürasyonu:

[aws-prod]
type = s3
provider = AWS
access_key_id = AKIAXXXXXXXXXXXXXXXX
secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
region = eu-central-1
storage_class = STANDARD_IA

[backblaze-backup]
type = b2
account = xxxxxxxxxxxxxxxxxxxxxxxxxx
key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

[wasabi-archive]
type = s3
provider = Wasabi
access_key_id = xxxxxxxxxxxxxxxxxxxxxxxxxx
secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
endpoint = s3.eu-central-2.wasabisys.com
region = eu-central-2

[aws-encrypted]
type = crypt
remote = aws-prod:my-encrypted-bucket
filename_encryption = standard
directory_name_encryption = true
password = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
password2 = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Bu yapıda dikkat çeken nokta aws-encrypted remote’u. Bu aslında aws-prod üzerine oturmuş bir şifreleme katmanı. Gerçek veriler AWS’ye gitmeden önce Rclone tarafından şifreleniyor.

Gerçek Dünya Senaryosu: E-ticaret Veritabanı Yedekleme

Bir e-ticaret müşterimizin PostgreSQL veritabanını hem AWS S3 hem Backblaze B2 hem de Wasabi’ye yedeklediğimiz senaryoyu inceleyelim. Veri boyutu yaklaşık 50 GB, günlük değişim ise 2-3 GB civarında.

İlk adımda yedek alma script’ini hazırlıyoruz:

#!/bin/bash
# /opt/scripts/backup-database.sh

set -euo pipefail

# Değişkenler
BACKUP_DIR="/var/backups/postgresql"
DB_NAME="ecommerce_prod"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${DATE}.sql.gz"
LOG_FILE="/var/log/rclone-backup.log"
RETENTION_DAYS=7

# Renk kodları
RED='33[0;31m'
GREEN='33[0;32m'
YELLOW='33[1;33m'
NC='33[0m'

log() {
    echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "${LOG_FILE}"
}

# Backup dizinini oluştur
mkdir -p "${BACKUP_DIR}"

log "${YELLOW}Veritabanı yedekleme başlıyor: ${DB_NAME}${NC}"

# PostgreSQL dump al
if pg_dump -U postgres -Fc "${DB_NAME}" | gzip > "${BACKUP_FILE}"; then
    BACKUP_SIZE=$(du -sh "${BACKUP_FILE}" | cut -f1)
    log "${GREEN}Dump başarılı. Boyut: ${BACKUP_SIZE}${NC}"
else
    log "${RED}HATA: pg_dump başarısız oldu!${NC}"
    exit 1
fi

# Checksumu kaydet
sha256sum "${BACKUP_FILE}" > "${BACKUP_FILE}.sha256"
log "Checksum oluşturuldu"

# Bulut yüklemelerini paralel çalıştır
upload_to_remote() {
    local remote=$1
    local bucket=$2
    
    log "Yükleniyor: ${remote}:${bucket}"
    
    if rclone copy 
        "${BACKUP_FILE}" 
        "${remote}:${bucket}/$(date +%Y/%m/%d)/" 
        --progress 
        --stats 30s 
        --transfers 4 
        --checkers 8 
        2>> "${LOG_FILE}"; then
        log "${GREEN}${remote} yükleme başarılı${NC}"
        return 0
    else
        log "${RED}HATA: ${remote} yükleme başarısız!${NC}"
        return 1
    fi
}

# Paralel yükleme
upload_to_remote "aws-encrypted" "db-backups" &
PID_AWS=$!

upload_to_remote "backblaze-backup" "db-backups-b2" &
PID_B2=$!

upload_to_remote "wasabi-archive" "db-backups-wasabi" &
PID_WASABI=$!

# Tüm yüklemelerin tamamlanmasını bekle
FAILED=0
wait $PID_AWS || { log "${RED}AWS yükleme başarısız${NC}"; FAILED=$((FAILED+1)); }
wait $PID_B2 || { log "${RED}Backblaze yükleme başarısız${NC}"; FAILED=$((FAILED+1)); }
wait $PID_WASABI || { log "${RED}Wasabi yükleme başarısız${NC}"; FAILED=$((FAILED+1)); }

if [ $FAILED -gt 1 ]; then
    log "${RED}KRİTİK: Birden fazla yükleme başarısız! Acil müdahale gerekli.${NC}"
    # Slack bildirimi gönder
    curl -s -X POST -H 'Content-type: application/json' 
        --data "{"text":"🔴 BACKUP FAILED: ${DB_NAME} - ${FAILED} remote başarısız!"}" 
        "${SLACK_WEBHOOK_URL}"
fi

# Eski yedekleri temizle
find "${BACKUP_DIR}" -name "*.sql.gz" -mtime +${RETENTION_DAYS} -delete
find "${BACKUP_DIR}" -name "*.sha256" -mtime +${RETENTION_DAYS} -delete
log "Yerel eski yedekler temizlendi"

log "Yedekleme tamamlandı. Başarısız: ${FAILED}/3"

Bulut Tarafında Retention Yönetimi

Yerel temizlik yaptık ama bulut tarafını da yönetmemiz gerekiyor. Her sağlayıcı için ayrı retention politikaları uygulayabiliriz:

#!/bin/bash
# /opt/scripts/cloud-retention.sh
# Bu script eski bulut yedeklerini siler

REMOTE_LIST=("aws-encrypted:db-backups" "backblaze-backup:db-backups-b2" "wasabi-archive:db-backups-wasabi")

# 30 günden eski dosyaları sil
for remote in "${REMOTE_LIST[@]}"; do
    echo "Retention uygulanıyor: ${remote}"
    
    rclone delete "${remote}" 
        --min-age 30d 
        --include "*.sql.gz" 
        --dry-run 
        2>&1 | head -20
    
    # Dry-run'ı kaldırıp gerçek silme için:
    # rclone delete "${remote}" --min-age 30d --include "*.sql.gz"
done

# Boş dizinleri de temizle
for remote in "${REMOTE_LIST[@]}"; do
    rclone rmdirs "${remote}" --leave-root
done

Dikkat edin, önce --dry-run ile ne silineceğini görüyoruz. Bu alışkanlığı edinmek, bir gün production yedeğini silmekten sizi kurtarır.

Rclone Bisect ile Veri Tutarlılığı Doğrulama

Yedek var ama doğru mu? Bu soruyu sormanız lazım. Rclone’un check komutu bu iş için var:

#!/bin/bash
# /opt/scripts/verify-backups.sh

VERIFICATION_LOG="/var/log/backup-verification.log"
DATE=$(date +%Y-%m-%d)

echo "=== Yedek Doğrulama: ${DATE} ===" >> "${VERIFICATION_LOG}"

# Kaynak ile AWS arasındaki tutarsızlıkları kontrol et
rclone check 
    /var/backups/postgresql/ 
    aws-encrypted:db-backups/ 
    --one-way 
    --checkers 16 
    2>> "${VERIFICATION_LOG}"

# AWS ile Backblaze arasındaki tutarlılığı kontrol et
rclone check 
    aws-encrypted:db-backups/ 
    backblaze-backup:db-backups-b2/ 
    --checkers 16 
    --size-only 
    2>> "${VERIFICATION_LOG}"

echo "Doğrulama tamamlandı" >> "${VERIFICATION_LOG}"

# Hata varsa uyar
if grep -q "ERROR" "${VERIFICATION_LOG}"; then
    echo "Yedek tutarsızlığı tespit edildi! Log dosyasını inceleyin." | 
        mail -s "UYARI: Yedek Doğrulama Hatası" [email protected]
fi

Bant Genişliği Optimizasyonu ve Zamanlama

Üretim sunucusunda yedekleme yapıyorsanız bant genişliği yönetimi kritik. Rclone bunu trafik kuralları ile yapıyor:

# Mesai saatlerinde sınırlı, gece serbest
rclone copy 
    /var/backups/ 
    aws-encrypted:db-backups/ 
    --bwlimit "08:00,10M 18:00,off 00:00,100M" 
    --transfers 4 
    --buffer-size 64M 
    --s3-upload-concurrency 8 
    --s3-chunk-size 64M 
    --fast-list 
    --progress

# Sadece değişen dosyaları gönder (incremental)
rclone sync 
    /var/backups/ 
    aws-encrypted:db-backups/ 
    --checksum 
    --update 
    --use-server-modtime 
    --transfers 8

Bazı önemli parametrelerin açıklaması:

  • –bwlimit: Saat bazlı bant genişliği limiti, format HH:MM,hız şeklinde
  • –transfers: Paralel dosya transfer sayısı, network gecikmesi yüksekse artırın
  • –buffer-size: Her transfer için ayrılan bellek buffer’ı
  • –s3-chunk-size: Multipart upload parça boyutu, büyük dosyalar için kritik
  • –fast-list: S3 list işlemlerini hızlandırır ama daha fazla bellek kullanır
  • –checksum: Boyut ve tarih yerine checksum karşılaştırması yapar

Systemd Entegrasyonu ile Profesyonel Zamanlama

Cron yerine systemd timer kullanmak birçok avantaj sağlıyor: başarısızlık durumunda otomatik yeniden deneme, detaylı loglama ve servis bağımlılıkları.

# /etc/systemd/system/rclone-backup.service
[Unit]
Description=Rclone Çoklu Bulut Yedekleme
After=network-online.target postgresql.service
Wants=network-online.target
OnFailure=backup-failure-notify@%n.service

[Service]
Type=oneshot
User=backup
Group=backup
ExecStart=/opt/scripts/backup-database.sh
StandardOutput=journal
StandardError=journal
TimeoutStartSec=3600
Nice=19
IOSchedulingClass=idle
CPUSchedulingPolicy=idle

# Güvenlik kısıtlamaları
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/var/backups /var/log
PrivateTmp=true
# /etc/systemd/system/rclone-backup.timer
[Unit]
Description=Rclone Yedekleme Timer
Requires=rclone-backup.service

[Timer]
OnCalendar=*-*-* 02:00:00
RandomizedDelaySec=300
Persistent=true
AccuracySec=1min

[Install]
WantedBy=timers.target

Timer’ı aktif etmek için:

sudo systemctl daemon-reload
sudo systemctl enable --now rclone-backup.timer

# Durumu kontrol et
sudo systemctl status rclone-backup.timer
sudo systemctl list-timers rclone-backup.timer

# Logları görüntüle
sudo journalctl -u rclone-backup.service -f

Mount ve Anlık Erişim Senaryosu

Bazen yedekten tek bir dosya almak gerekiyor. Tüm arşivi indirmek yerine Rclone mount kullanmak çok daha pratik:

# Geçici mount noktası oluştur
mkdir -p /mnt/backup-cloud

# AWS yedeklerini mount et (daemon modunda)
rclone mount aws-encrypted:db-backups /mnt/backup-cloud 
    --daemon 
    --allow-other 
    --read-only 
    --cache-dir /tmp/rclone-cache 
    --vfs-cache-mode full 
    --vfs-cache-max-size 10G 
    --buffer-size 64M 
    --dir-cache-time 5m

# Dosyalara normal Linux komutlarıyla eriş
ls -lh /mnt/backup-cloud/2024/01/15/
cp /mnt/backup-cloud/2024/01/15/ecommerce_prod_20240115_020000.sql.gz /tmp/

# İşin bitince unmount
fusermount -u /mnt/backup-cloud

Bu yöntemle 50 GB’lık arşive girmek için tek bir 2 GB’lık yedek dosyasını indirmek yeterli. Ciddi zaman ve bant genişliği tasarrufu.

Felaket Kurtarma Senaryosu: Her Şeyi Kaybettik

En kötü senaryo: sunucu yanmış, her şey gitti. Backblaze’deki yedeğe dönmek için:

#!/bin/bash
# /opt/scripts/disaster-recovery.sh
# Kullanım: ./disaster-recovery.sh 20240115 ecommerce_prod

TARGET_DATE=${1:-$(date +%Y%m%d)}
DB_NAME=${2:-"ecommerce_prod"}
RESTORE_DIR="/var/restore"
YEAR=${TARGET_DATE:0:4}
MONTH=${TARGET_DATE:4:2}
DAY=${TARGET_DATE:6:2}

mkdir -p "${RESTORE_DIR}"

echo "Felaket kurtarma başlıyor..."
echo "Tarih: ${YEAR}/${MONTH}/${DAY}"
echo "Veritabanı: ${DB_NAME}"

# Önce Backblaze'i dene (genellikle en ucuz ve hızlı)
if rclone ls "backblaze-backup:db-backups-b2/${YEAR}/${MONTH}/${DAY}/" 2>/dev/null | grep -q "${DB_NAME}"; then
    echo "Backblaze'de yedek bulundu, indiriliyor..."
    
    rclone copy 
        "backblaze-backup:db-backups-b2/${YEAR}/${MONTH}/${DAY}/" 
        "${RESTORE_DIR}/" 
        --include "${DB_NAME}*.sql.gz" 
        --progress 
        --transfers 4
        
elif rclone ls "aws-encrypted:db-backups/${YEAR}/${MONTH}/${DAY}/" 2>/dev/null | grep -q "${DB_NAME}"; then
    echo "AWS'de yedek bulundu, indiriliyor..."
    
    rclone copy 
        "aws-encrypted:db-backups/${YEAR}/${MONTH}/${DAY}/" 
        "${RESTORE_DIR}/" 
        --include "${DB_NAME}*.sql.gz" 
        --progress 
        --transfers 4
else
    echo "HATA: Hiçbir remote'da yedek bulunamadı!"
    exit 1
fi

# Checksum doğrula
BACKUP_FILE=$(ls "${RESTORE_DIR}/${DB_NAME}"*.sql.gz | head -1)
if [ -f "${BACKUP_FILE}.sha256" ]; then
    sha256sum -c "${BACKUP_FILE}.sha256" && echo "Checksum doğrulandı" || echo "UYARI: Checksum uyuşmuyor!"
fi

# PostgreSQL'e restore et
echo "Restore başlıyor: ${DB_NAME}"
createdb -U postgres "${DB_NAME}_restored"
gunzip -c "${BACKUP_FILE}" | pg_restore -U postgres -d "${DB_NAME}_restored" --verbose

echo "Restore tamamlandı: ${DB_NAME}_restored"

İzleme ve Raporlama

Yedeklemenin çalışıp çalışmadığını bilmek için pasif izleme yetmez. Aktif doğrulama gerekli. Ben Healthchecks.io ile entegrasyon kullanıyorum ama basit bir SMTP bildirimi de işe yarıyor:

#!/bin/bash
# Günlük yedek raporu

REPORT_DATE=$(date '+%Y-%m-%d')
REPORT=""

for remote in "aws-encrypted:db-backups" "backblaze-backup:db-backups-b2" "wasabi-archive:db-backups-wasabi"; do
    REMOTE_NAME=$(echo $remote | cut -d: -f1)
    
    # Son 24 saatteki dosyaları listele
    RECENT_FILES=$(rclone ls "${remote}" --min-age 0s --max-age 24h 2>/dev/null | wc -l)
    TOTAL_SIZE=$(rclone size "${remote}" 2>/dev/null | grep "Total size" | awk '{print $3, $4}')
    
    REPORT+="Remote: ${REMOTE_NAME}n"
    REPORT+="  Son 24 saat dosya sayısı: ${RECENT_FILES}n"
    REPORT+="  Toplam boyut: ${TOTAL_SIZE}nn"
done

echo -e "Yedekleme Durumu Raporu - ${REPORT_DATE}nn${REPORT}" | 
    mail -s "[YEDEK RAPORU] ${REPORT_DATE}" [email protected]

Bu script’i de systemd timer’a ekleyip her sabah 08:00’de çalıştırabilirsiniz. Raporu okuma alışkanlığı edinin; yedek almaktan daha önemli olan yedeği doğrulamak.

Güvenlik Konuları: API Anahtarları ve Erişim Kontrolü

Rclone config dosyası API anahtarları içeriyor, dikkatli olunması şart:

# Config dosyasının izinlerini kısıtla
chmod 600 ~/.config/rclone/rclone.conf

# Backup kullanıcısı için ayrı config
sudo -u backup rclone config file
sudo chmod 600 /home/backup/.config/rclone/rclone.conf

# Environment variable ile hassas bilgileri dışarı al
export RCLONE_CONFIG_AWS_PROD_ACCESS_KEY_ID="${AWS_ACCESS_KEY}"
export RCLONE_CONFIG_AWS_PROD_SECRET_ACCESS_KEY="${AWS_SECRET_KEY}"

# AWS için minimal IAM politikası (sadece gerekli izinler)
# s3:PutObject, s3:GetObject, s3:DeleteObject, s3:ListBucket
# NOT: s3:GetBucketLocation da gerekli

AWS tarafında IAM politikasını mümkün olduğunca kısıtlayın. Yedekleme kullanıcısına sadece ilgili bucket’a ve sadece ihtiyaç duyulan işlemlere izin verin. Okuma ve yazma iznini ayırın; restore işlemi için ayrı bir read-only kullanıcı oluşturun.

Sonuç

Rclone ile çoklu bulut yedekleme stratejisi oluşturmak sandığınızdan çok daha az zaman alıyor ama sunduğu güvence son derece yüksek. Bu yazıda anlattığımız yaklaşımı özetlersek:

  • 3-2-1 kuralına uyum: 3 kopya, 2 farklı ortam, 1 offsite. Çoklu bulut bu kuralı doğal olarak karşılıyor.
  • Şifreleme her zaman açık: Bulut sağlayıcısı güvenlik ihlali yaşasa bile verileriniz korunuyor.
  • Paralel yükleme: Üç sağlayıcıya sırayla değil aynı anda yüklemek toplam süreyi dramatik şekilde kısaltıyor.
  • Checksum doğrulama: Yedek almak kadar doğrulamak da önemli, bu adımı atlamayın.
  • Aktif izleme: Yedeklemenin sessizce başarısız olması en tehlikeli senaryo. Rapor alın, raporları okuyun.
  • Felaket kurtarma tatbikatı: Ayda bir gerçek bir restore deneyin. Kağıt üzerinde çalışan prosedür yetmez.

Rclone ekosistemi sürekli gelişiyor. rclone bisync komutu ile iki yönlü senkronizasyon, rclone serve ile HTTP/FTP/S3 protokolü üzerinden servis etme gibi özellikler bu aracı sadece yedekleme değil genel depolama yönetimi için de güçlü kılıyor. Altyapınızın karmaşıklığı arttıkça Rclone + Restic kombinasyonunu da incelemenizi öneririm; Restic’in deduplikasyon ve anlık görüntü özelliklerini Rclone’un geniş sağlayıcı desteğiyle birleştirmek ciddi bir yedekleme platformu oluşturuyor.

Sistemi kurup çalıştırdıktan sonra yapmanız gereken en önemli şey: bir gün gelip yedeği gerçekten kullanmak zorunda kaldığınızda soğukkanlı kalabilmek. O soğukkanlılığı size ancak iyi test edilmiş ve doğrulanmış bir yedekleme sistemi verebilir.

Bir yanıt yazın

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