Veri Yedekleme Stratejisi: 3-2-1 Kuralı Nedir ve Nasıl Uygulanır?

Yıllarca sistem yöneticiliği yaptıktan sonra şunu net olarak söyleyebilirim: yedek almayan sistem yöneticisi değil, henüz felaketi yaşamamış sistem yöneticisidir. Disk arızaları, yanlışlıkla silinen dosyalar, fidye yazılımı saldırıları, veri merkezi yangınları… Bunların hepsi gerçek. Ve hepsini “benim başıma gelmez” diye düşünen onlarca meslektaşımın sonradan nasıl panik yaptığını gördüm. İşte bu yüzden bugün 3-2-1 kuralından, bu kuralın nasıl uygulandığından ve gerçek dünyada nasıl test edildiğinden bahsedeceğiz.

3-2-1 Kuralı Nedir?

3-2-1 kuralı, fotoğrafçı Peter Krogh tarafından 2000’lerin başında ortaya atılmış, ancak BT dünyasında altın standart haline gelmiş bir yedekleme stratejisidir. Formül son derece basit:

  • 3 kopya veri tut (1 orijinal + 2 yedek)
  • 2 farklı depolama ortamı kullan
  • 1 kopya mutlaka farklı bir fiziksel lokasyonda olsun

Kulağa basit geliyor, değil mi? Ama uygulamada çoğu şirketin bu kuralın en az bir maddesini ihlal ettiğini görüyorum. “Zaten her gece yedek alıyoruz” diyen şirketler var ki, o yedekler aynı sunucunun ikinci diskinde duruyor. Sunucu gidince yedek de gidiyor. Bu senaryo maalesef hayal ürünü değil.

Neden 3-2-1 Kuralı Bu Kadar Önemli?

Farklı felaket senaryolarını düşünelim:

  • Disk arızası: Orijinal veri gider. 2 yedeğiniz varsa kurtarırsınız.
  • Fidye yazılımı: Şifreli verinin yanında ağa bağlı yedekler de şifrelenir. Offline veya immutable yedeğiniz yoksa mahvolursunuz.
  • Yangın veya su baskını: Fiziksel olarak aynı yerdeki tüm depolama ortamları gider. Offsite kopyanız sizi kurtarır.
  • Yanlışlıkla silme: “rm -rf /” şakası yapmak zorunda değilsiniz, basit bir rm production.sql yeterli. Yedeğiniz varsa 5 dakikada geri dönersiniz.
  • Yazılım hatası veya veri bozulması: Corrupt olan veriyi birkaç saat sonra fark edersiniz. Bu durumda yeterli sayıda ve zaman dağılımlı yedek şart.

Depolama Ortamları ve Seçenekleri

Yerel Depolama (Primary Backup)

İlk yedek genellikle aynı veri merkezinde, farklı bir depolama ortamında tutulur. Hız açısından en avantajlısı budur. Kurtarma süresi (RTO) çok kısadır.

#!/bin/bash
# Basit yerel yedekleme scripti
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
SOURCE="/var/www/html"
DEST="/mnt/backup_drive/web_backup"
LOG="/var/log/backup.log"

echo "[$BACKUP_DATE] Yedekleme basliyor..." >> $LOG

rsync -avz --delete 
  --exclude='*.tmp' 
  --exclude='cache/' 
  $SOURCE/ $DEST/$BACKUP_DATE/

if [ $? -eq 0 ]; then
    echo "[$BACKUP_DATE] Yedekleme basarili." >> $LOG
else
    echo "[$BACKUP_DATE] HATA: Yedekleme basarisiz!" >> $LOG
    # Mail gonder
    echo "Yedekleme basarisiz!" | mail -s "BACKUP ERROR" [email protected]
fi

NAS/SAN Depolama

İkinci kopya için NAS cihazları oldukça yaygın tercih. Burada dikkat etmeniz gereken nokta, NAS’ın üretim ağıyla aynı segmentte olmamasıdır. Fidye yazılımı saldırılarında ağ erişimi olan her şey hedef alınır.

# NFS mount ile NAS'a yedekleme
#!/bin/bash
NAS_MOUNT="/mnt/nas_backup"
BACKUP_SRC="/data/databases"
RETENTION_DAYS=30

# NAS mount kontrolu
if ! mountpoint -q $NAS_MOUNT; then
    mount -t nfs 192.168.10.50:/backups $NAS_MOUNT
    if [ $? -ne 0 ]; then
        echo "NAS mount basarisiz!" | mail -s "CRITICAL: Backup Failed" [email protected]
        exit 1
    fi
fi

# Yedekleme
BACKUP_DIR="$NAS_MOUNT/db_backups/$(date +%Y/%m/%d)"
mkdir -p $BACKUP_DIR

pg_dumpall -U postgres | gzip > $BACKUP_DIR/postgres_full_$(date +%H%M).sql.gz

# Eski yedekleri temizle
find $NAS_MOUNT/db_backups -mtime +$RETENTION_DAYS -name "*.gz" -delete

Bulut Depolama (Offsite Kopya)

3-2-1 kuralının “1 offsite” kısmı için bulut depolama günümüzde en pratik çözüm. AWS S3, Azure Blob Storage, Backblaze B2 veya Wasabi gibi seçenekler mevcut. Maliyet açısından Backblaze B2 ve Wasabi oldukça uygun fiyatlı.

# AWS S3'e yedekleme - aws cli kullanarak
#!/bin/bash
S3_BUCKET="s3://sirket-backup-2024"
LOCAL_BACKUP="/tmp/backup_$(date +%Y%m%d)"
ENCRYPTION_KEY="/etc/backup/encryption.key"

# Veriyi sıkıştır ve şifrele
tar -czf - /var/www/ /etc/ /home/ | 
  openssl enc -aes-256-cbc -pbkdf2 
  -pass file:$ENCRYPTION_KEY | 
  aws s3 cp - $S3_BUCKET/$(date +%Y/%m/%d)/full_backup_$(date +%H%M).tar.gz.enc

# S3 lifecycle policy ile otomatik silme ayarlanmali
# Burada sadece upload kontrol ediliyor
if [ $? -eq 0 ]; then
    echo "S3 yedekleme basarili: $(date)" >> /var/log/s3_backup.log
else
    echo "S3 HATA: $(date)" >> /var/log/s3_backup.log
    aws sns publish 
      --topic-arn arn:aws:sns:eu-west-1:123456789:backup-alerts 
      --message "S3 backup failed on $(hostname)"
fi

Veritabanı Yedekleme

Web server dosyalarını yedeklemek yetmez. Veritabanları için ayrı bir strateji gerekli. Özellikle sıcak yedekleme (hot backup) yapabilmek kritik.

#!/bin/bash
# MySQL/MariaDB için kapsamli yedekleme scripti
DB_USER="backup_user"
DB_PASS="guclu_sifre_buraya"
BACKUP_DIR="/mnt/backup/mysql"
RETENTION=7

mkdir -p $BACKUP_DIR

# Tum veritabanlarini listele ve tek tek yedekle
mysql -u$DB_USER -p$DB_PASS -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema|sys)" | while read DB; do
    DUMP_FILE="$BACKUP_DIR/${DB}_$(date +%Y%m%d_%H%M%S).sql.gz"
    
    mysqldump 
      -u$DB_USER 
      -p$DB_PASS 
      --single-transaction 
      --routines 
      --triggers 
      --events 
      $DB | gzip > $DUMP_FILE
    
    echo "Yedeklendi: $DB -> $DUMP_FILE"
done

# Eski yedekleri temizle
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION -delete
echo "$(date): MySQL yedekleme tamamlandi" >> /var/log/mysql_backup.log

Yedekleme Rotasyonu ve Retention Policy

“Ne kadar geriye gidebilmeliyim?” sorusu çok kritik. Fidye yazılımı bazen günlerce fark edilmeden çalışır. Sadece dünkü yedeğiniz varsa, şifreli verinin yedeğini almış olursunuz. Grandfather-Father-Son (GFS) rotasyon şeması burada çok işe yarar:

  • Günlük yedekler: Son 7 gün
  • Haftalık yedekler: Son 4 hafta
  • Aylık yedekler: Son 12 ay
  • Yıllık yedekler: Düzenleyici gereksinimler için 5-7 yıl
#!/bin/bash
# GFS rotasyon mantigi
BACKUP_ROOT="/mnt/nas/backups"
SOURCE="/data"
TODAY=$(date +%A)  # Pazartesi, Sali...
DAY_OF_MONTH=$(date +%d)
MONTH=$(date +%m)

perform_backup() {
    local DEST=$1
    mkdir -p $DEST
    rsync -az --delete $SOURCE/ $DEST/
    echo "Backup: $DEST - $(date)" >> /var/log/gfs_backup.log
}

# Gunluk yedek her zaman
perform_backup "$BACKUP_ROOT/daily/$(date +%Y%m%d)"

# Pazar gunu haftalik yedek
if [ "$TODAY" = "Sunday" ]; then
    perform_backup "$BACKUP_ROOT/weekly/week_$(date +%V)"
fi

# Ayin 1'inde aylik yedek
if [ "$DAY_OF_MONTH" = "01" ]; then
    perform_backup "$BACKUP_ROOT/monthly/$(date +%Y%m)"
fi

# Ocak 1'inde yillik yedek
if [ "$DAY_OF_MONTH" = "01" ] && [ "$MONTH" = "01" ]; then
    perform_backup "$BACKUP_ROOT/yearly/$(date +%Y)"
fi

# Eski gunluk yedekleri temizle (7 gunden eski)
find $BACKUP_ROOT/daily -maxdepth 1 -type d -mtime +7 -exec rm -rf {} ;
# Eski haftalik yedekleri temizle (35 gunden eski)
find $BACKUP_ROOT/weekly -maxdepth 1 -type d -mtime +35 -exec rm -rf {} ;

Yedekleme Dogrulamasi ve Test Prosedurü

İşte burada pek çok sysadmin hata yapıyor. Yedek almak yetmez, yedeğin çalışıp çalışmadığını test etmek zorundasınız. “Yedek var” ile “yedekten geri dönebilirsin” aynı şey değil.

Altın kural: Test etmediğiniz yedek, yedek değildir.

Yedek testini otomatize etmek için basit bir yaklaşım:

#!/bin/bash
# Yedek dogrulama scripti
# Her hafta cron ile calistirin
BACKUP_FILE=$(ls -t /mnt/backup/mysql/*.sql.gz | head -1)
TEST_DB="backup_test_$(date +%Y%m%d)"
RESTORE_LOG="/var/log/backup_test.log"

echo "=== Yedek Test Basladi: $(date) ===" >> $RESTORE_LOG
echo "Test dosyasi: $BACKUP_FILE" >> $RESTORE_LOG

# Test veritabani olustur
mysql -u root -e "CREATE DATABASE $TEST_DB;"

# Yedegi geri yukle
zcat $BACKUP_FILE | mysql -u root $TEST_DB

if [ $? -eq 0 ]; then
    # Tablo sayisini kontrol et
    TABLE_COUNT=$(mysql -u root -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$TEST_DB';" | tail -1)
    echo "Geri yukleme BASARILI. Tablo sayisi: $TABLE_COUNT" >> $RESTORE_LOG
    
    # Test veritabanini sil
    mysql -u root -e "DROP DATABASE $TEST_DB;"
    
    # Basari bildirimi
    echo "Haftalik yedek testi BASARILI - Tablo: $TABLE_COUNT" | 
      mail -s "Backup Test OK: $(hostname)" [email protected]
else
    echo "KRITIK HATA: Yedek geri yukleme BASARISIZ!" >> $RESTORE_LOG
    echo "Acil: Yedek geri yukleme basarisiz!" | 
      mail -s "KRITIK: Backup Test FAILED on $(hostname)" [email protected]
fi

Immutable Backup ve Fidye Yazılımı Koruması

Modern fidye yazılımları artık yedekleri de hedef alıyor. Bu yüzden immutable backup (değiştirilemez yedek) konsepti çok önem kazandı. AWS S3 Object Lock, NetApp SnapLock veya Veeam’in immutable backup özelliği bu amaçla kullanılabilir.

Linux tarafında chattr komutuyla dosya sistemi seviyesinde koruma mümkün:

# Yedek dosyasini degistirilemez yap
# Dikkat: Bu islemi geri almak icin de root yetkisi gerekir
chattr +i /mnt/backup/critical/backup_20240115.tar.gz

# Dogrulama
lsattr /mnt/backup/critical/backup_20240115.tar.gz
# Cikti: ----i--------e-- backup_20240115.tar.gz

# Immutable ozelligini kaldirmak icin (sadece kurtarma sirasinda)
chattr -i /mnt/backup/critical/backup_20240115.tar.gz

# Bir dizindeki tum yedekleri immutable yap
find /mnt/backup/monthly -name "*.tar.gz" -exec chattr +i {} ;

S3 tarafında Object Lock kullanmak için:

# S3 bucket olusturma - Object Lock aktif
aws s3api create-bucket 
  --bucket sirket-immutable-backup 
  --region eu-west-1 
  --create-bucket-configuration LocationConstraint=eu-west-1 
  --object-lock-enabled-for-bucket

# Default retention ayarla (30 gun COMPLIANCE modu)
aws s3api put-object-lock-configuration 
  --bucket sirket-immutable-backup 
  --object-lock-configuration 
  '{"ObjectLockEnabled":"Enabled","Rule":{"DefaultRetention":{"Mode":"COMPLIANCE","Days":30}}}'

Felaket Kurtarma Planı ve Tatbikat

Yedekleme stratejisi kağıt üzerinde ne kadar iyi olursa olsun, gerçek bir felaket anında panik yapar ve adım atlarsınız. Bu yüzden yazılı bir DR (Disaster Recovery) planı şart. Ve bu plan düzenli olarak tatbikat yapılarak test edilmeli.

Ben şirketlerde yılda en az iki kez “sürpriz tatbikat” yapılmasını öneriyorum. Bir gün ekibe “üretim veritabanı gitti, 2 saat içinde geri getirin” diyorsunuz ve sadece izliyorsunuz. Bu tatbikatlar hem açıkları ortaya çıkarır hem de ekibi stres altında çalışmaya hazırlar.

DR planında bulunması gereken minimum bilgiler:

  • RTO (Recovery Time Objective): Ne kadar sürede geri dönmeliyiz? Örneğin 4 saat.
  • RPO (Recovery Point Objective): En fazla ne kadar veri kaybını kabul edebiliriz? Örneğin 1 saatlik veri.
  • Kurtarma adımları: Numara numaraya yazılmış prosedür. Yorgun ve panik halindeki birinin anlayabileceği kadar basit.
  • İletişim planı: Kim kimi arar? Yöneticilerin, müşterilerin telefon numaraları kağıt üzerinde de olsun. Sunucu gittiğinde dijital notlarınıza erişemeyebilirsiniz.
  • Yedeklerin konumu ve erişim bilgileri: Şifreler güvenli bir yerde (fiziksel kasa veya ayrı bir şifre yöneticisinde) saklanmalı.

Yaygın Hatalar ve Kaçınılması Gerekenler

Yıllar içinde gördüğüm en yaygın yedekleme hatalarını paylaşayım:

  • Sadece dosya yedeği, veri tabanı yedeği yok: Web server dosyaları tamam ama database dump yok. Uygulama çalışmaz.
  • Yedekleri test etmemek: Corrupt yedekler var, ama kimse fark etmemiş. Gerçek felaket anında anlaşılıyor.
  • Aynı fiziksel cihazda yedek tutmak: “Backup” klasörü üretim diskinde. Disk gidince her şey gidiyor.
  • Şifreleme yapmamak: Offsite yedekler şifresiz gönderiliyor. Fiziksel güvenlik ihlali olduğunda veri sızdırılmış olur.
  • Yedek bildirimlerini görmezden gelmek: Mail ile uyarı var ama kimse okumadığı için 3 aydır yedek alınmıyor.
  • Uygulama tutarlılığını sağlamamak: Çalışan bir veritabanı dosyalarını kopyalamak tutarlı bir yedek vermez. --single-transaction gibi seçenekler kullanılmalı.
  • Retention politikası olmamak: Disk dolana kadar yedek birikiyor, sonra en eski yedekler otomatik siliniyor ve önemli bir nokta kayboluyor.

Monitoring ve Alerting

Yedekleme sisteminiz sessizce hata veriyorsa, bunu ancak gerçekten ihtiyaç duyduğunuzda anlarsınız. Bu yüzden monitoring şart.

Basit bir Nagios/Icinga check scripti:

#!/bin/bash
# Nagios uyumlu yedek yaslilik kontrolu
# /usr/lib/nagios/plugins/check_backup_age.sh olarak kaydet

BACKUP_DIR=$1
MAX_AGE_HOURS=$2
BACKUP_PATTERN=$3

if [ -z "$BACKUP_DIR" ] || [ -z "$MAX_AGE_HOURS" ]; then
    echo "UNKNOWN: Kullanim: $0 <dizin> <maks_saat> [dosya_paterni]"
    exit 3
fi

PATTERN=${BACKUP_PATTERN:-"*.gz"}
LATEST=$(find $BACKUP_DIR -name "$PATTERN" -type f -printf '%T@ %pn' 2>/dev/null | sort -n | tail -1 | awk '{print $2}')

if [ -z "$LATEST" ]; then
    echo "CRITICAL: Hic yedek dosyasi bulunamadi: $BACKUP_DIR"
    exit 2
fi

FILE_AGE_HOURS=$(( ($(date +%s) - $(stat -c %Y "$LATEST")) / 3600 ))

if [ $FILE_AGE_HOURS -gt $MAX_AGE_HOURS ]; then
    echo "CRITICAL: En son yedek $FILE_AGE_HOURS saat once alindi (max: $MAX_AGE_HOURS) - $LATEST"
    exit 2
elif [ $FILE_AGE_HOURS -gt $(( MAX_AGE_HOURS / 2 )) ]; then
    echo "WARNING: En son yedek $FILE_AGE_HOURS saat once alindi - $LATEST"
    exit 1
else
    echo "OK: En son yedek $FILE_AGE_HOURS saat once alindi - $LATEST"
    exit 0
fi

Maliyet Optimizasyonu

Bulut yedekleme maliyetleri zamanla artabilir. Birkaç pratik ipucu:

  • Sıkıştırma kullanın: gzip veya zstd ile yüzde 60-80 oranında boyut azaltılabilir. zstd hızıyla öne çıkar.
  • Deduplication: Değişmeyen blokları tekrar yedeklemeyin. Restic, Borg Backup gibi araçlar bunu otomatik yapar.
  • Storage class kullanın: S3’te 90 günden eski yedekler için Glacier’a geçin. Maliyet dramatik düşer.
  • Lifecycle policy yazın: Manuel temizlik unutulur. Otomatik retention politikası kurun.
  • Ne yedekleyeceğinizi bilin: Her şeyi yedeklemeyin. OS’u yedeklemek yerine konfigürasyon dosyalarını ve veriyi yedekleyin. Sistem yeniden kurulabilir, veri kurulamaz.

Sonuç

3-2-1 kuralı kulağa basit geliyor, ama gerçek hayatta doğru uygulamak ciddi bir planlama ve disiplin istiyor. Özetlersek:

  • 3 kopya tutmak: Orijinal + 2 bağımsız yedek
  • 2 farklı ortam: Örneğin disk + bulut
  • 1 offsite kopya: Fiziksel olarak farklı lokasyon, tercihen farklı şehir

Bu kuralın ötesinde, modern tehditler için immutable backup ekleyin ve tüm sistemi düzenli testlerle doğrulayın. Yedek almak yolculuğun yarısı; geri dönebilmek asıl hedeftir.

En iyi yedekleme sistemi, felaket anında fark etmeyeceğiniz kadar iyi çalışan sistemdir. O gün geldiğinde, “her şeyi düşünmüştüm” demek istiyorsanız, bugün başlayın. Çünkü o gün, başlamak için en kötü zamandır.

Bir yanıt yazın

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