Test Senaryoları ile Felaket Kurtarma Simülasyonu

Felaket kurtarma planı yapmak bir şeydir, onu gerçekten test etmek bambaşka bir şeydir. Çoğu sistem yöneticisi “yedeklerimiz var, sorun olmaz” der ama gerçek bir kriz anında bu yedeklerin çalışıp çalışmadığını, ekibin nasıl tepki vereceğini ve sistemlerin ne kadar sürede ayağa kalkacağını bilmez. İşte bu yüzden felaket kurtarma simülasyonları, teorik planlardan çok daha değerlidir. Bu yazıda gerçek dünya senaryolarına dayanan, uygulanabilir DR test metodolojilerini ve kod örneklerini ele alacağız.

Felaket Kurtarma Testinin Temel Kavramları

Bir DR testine başlamadan önce iki temel metriği netleştirmeniz gerekiyor:

RTO (Recovery Time Objective): Sistemin felaketten sonra ne kadar sürede ayağa kalkması gerektiği. Örneğin e-ticaret siteniz için bu 4 saat olabilir.

RPO (Recovery Point Objective): Ne kadar veri kaybını tolere edebileceğiniz. Günde bir yedek alıyorsanız maksimum 24 saatlik veri kaybı kabul edilebilir demektir.

Bu iki değer, test senaryolarınızın başarı kriterlerini belirler. Testi geçmek için hem RTO’yu hem de RPO’yu karşılamanız gerekir.

DR testleri genel olarak üç kategoriye ayrılır:

  • Masa başı tatbikatı (Tabletop Exercise): Ekip toplanır, senaryo kağıt üzerinde tartışılır. En düşük riskli yöntemdir.
  • Kısmi test (Partial Test): Sistemlerin belirli bir bölümü gerçekten failover edilir.
  • Tam ölçekli test (Full-Scale Test): Tüm üretim sistemleri kapatılır, her şey DR ortamından çalıştırılır. En gerçekçi ama en riskli yöntemdir.

Test Ortamı Hazırlığı

Testlere başlamadan önce izole bir ortam oluşturmanız şarttır. Bunu yapmadan gerçek üretim sistemlerine zarar verebilirsiniz.

#!/bin/bash
# DR test ortamı ön hazırlık scripti
# Bu script test öncesi kontrol listesini çalıştırır

DR_LOG="/var/log/dr_test_$(date +%Y%m%d_%H%M%S).log"
TEST_ENV="staging"

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

check_prerequisites() {
    log "Ön koşul kontrolü başlıyor..."
    
    # Disk alanı kontrolü
    AVAILABLE=$(df /backup | awk 'NR==2{print $4}')
    if [ "$AVAILABLE" -lt 51200000 ]; then
        log "HATA: Yetersiz disk alanı. En az 50GB gerekli."
        exit 1
    fi
    
    # Network bağlantısı kontrolü
    if ! ping -c 3 "$DR_SERVER_IP" &>/dev/null; then
        log "HATA: DR sunucusuna erişilemiyor: $DR_SERVER_IP"
        exit 1
    fi
    
    # Son yedeğin yaşını kontrol et
    LAST_BACKUP=$(find /backup -name "*.tar.gz" -newer /backup/.last_success 2>/dev/null | head -1)
    if [ -z "$LAST_BACKUP" ]; then
        log "UYARI: Son 24 saat içinde alınmış yedek bulunamadı!"
    fi
    
    log "Ön koşul kontrolü tamamlandı."
}

check_prerequisites

Senaryo 1: Veritabanı Sunucusu Çöküşü

Bu senaryo, en sık karşılaşılan felaket türlerinden biridir. PostgreSQL veya MySQL sunucunuzun tamamen çöktüğünü ve yedeğe geri dönmeniz gerektiğini simüle ediyoruz.

Test ortamında önce mevcut veritabanını “çökmüş gibi” davranacak şekilde durduruyoruz, ardından kurtarma prosedürünü uyguluyoruz.

#!/bin/bash
# PostgreSQL DR test scripti
# Senaryo: Ana DB sunucusu erişilemez, standby'a geçiş

PRIMARY_DB="db-primary.internal"
STANDBY_DB="db-standby.internal"
DB_USER="postgres"
TEST_DB="testdb"
START_TIME=$(date +%s)

log "=== PostgreSQL Failover Testi Başladı ==="
log "Başlangıç zamanı: $(date)"

# Adım 1: Standby'ın replikasyon durumunu kontrol et
log "Standby replikasyon lag kontrolü..."
REPL_LAG=$(psql -h "$STANDBY_DB" -U "$DB_USER" -t -c "
    SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))::INT
    AS replication_lag_seconds;
")

if [ "$REPL_LAG" -gt 60 ]; then
    log "UYARI: Replikasyon gecikmesi $REPL_LAG saniye. Veri kaybı riski var!"
fi

# Adım 2: Standby'ı promote et
log "Standby sunucu promote ediliyor..."
pg_ctl promote -D /var/lib/postgresql/data -w

# Adım 3: Uygulama bağlantılarını yönlendir
log "Uygulama konfigürasyonu güncelleniyor..."
sed -i "s/$PRIMARY_DB/$STANDBY_DB/g" /etc/app/database.conf

# Adım 4: Bağlantıyı doğrula
if psql -h "$STANDBY_DB" -U "$DB_USER" -c "SELECT 1;" &>/dev/null; then
    END_TIME=$(date +%s)
    ELAPSED=$((END_TIME - START_TIME))
    log "BAŞARILI: Failover $ELAPSED saniyede tamamlandı."
    log "RTO hedefi: 900 saniye | Gerçekleşen: $ELAPSED saniye"
else
    log "HATA: Yeni primary'e bağlanılamıyor!"
    exit 1
fi

Bu testi çalıştırdıktan sonra sonuçları belgelemeniz kritik önem taşır. Kaç saniyede tamamlandı? RTO hedefinizi karşıladınız mı? Veri kaybı yaşandı mı?

Senaryo 2: Dosya Sistemi Yedekten Geri Yükleme

Bir sunucuda kritik uygulama dosyaları silinmiş ya da bozulmuş olabilir. Bu senaryoda rsnapshot veya Bacula ile alınan yedeklerden geri yükleme simüle ediyoruz.

#!/bin/bash
# Dosya sistemi geri yükleme testi
# rsnapshot yedeklerinden seçici geri yükleme

BACKUP_ROOT="/backup/rsnapshot"
RESTORE_TARGET="/tmp/dr_restore_test"
TEST_DIR="/var/www/html"
SNAPSHOT_LEVEL="daily.0"

log "Dosya sistemi geri yükleme testi başlıyor..."

# Test için restore dizini oluştur
mkdir -p "$RESTORE_TARGET"

# Yedekten geri yükle
rsync -avz --progress 
    "$BACKUP_ROOT/$SNAPSHOT_LEVEL/localhost$TEST_DIR/" 
    "$RESTORE_TARGET/" 
    2>&1 | tee -a "$DR_LOG"

# Dosya bütünlüğünü kontrol et
ORIGINAL_COUNT=$(find "$TEST_DIR" -type f | wc -l)
RESTORED_COUNT=$(find "$RESTORE_TARGET" -type f | wc -l)

log "Orijinal dosya sayısı: $ORIGINAL_COUNT"
log "Geri yüklenen dosya sayısı: $RESTORED_COUNT"

if [ "$ORIGINAL_COUNT" -eq "$RESTORED_COUNT" ]; then
    log "BAŞARILI: Tüm dosyalar geri yüklendi."
else
    MISSING=$((ORIGINAL_COUNT - RESTORED_COUNT))
    log "UYARI: $MISSING dosya eksik!"
fi

# MD5 checksum doğrulaması
log "Checksum doğrulaması yapılıyor..."
find "$TEST_DIR" -type f -exec md5sum {} ; > /tmp/original_checksums.txt
find "$RESTORE_TARGET" -type f -exec md5sum {} ; > /tmp/restored_checksums.txt

diff /tmp/original_checksums.txt /tmp/restored_checksums.txt > /tmp/checksum_diff.txt
if [ -s /tmp/checksum_diff.txt ]; then
    log "UYARI: Checksum farklılıkları tespit edildi. Detaylar: /tmp/checksum_diff.txt"
else
    log "BAŞARILI: Tüm checksum'lar eşleşiyor."
fi

Senaryo 3: Tam Sunucu Kurtarma (Bare Metal Recovery)

Bu en kapsamlı senaryodur. Fiziksel veya sanal sunucu tamamen yok olmuş gibi davranıp, sistemi sıfırdan ayağa kaldırıyoruz. Modern ortamlarda bu genellikle snapshot’tan yeni bir VM oluşturmak anlamına gelir.

#!/bin/bash
# VMware / KVM snapshot'tan VM kurtarma testi
# Proxmox VE ortamı için örnek

VM_ID="105"
SNAPSHOT_NAME="pre_update_snapshot"
NEW_VM_ID="999"  # Test için geçici VM ID
DR_NODE="pve-dr-node"

log "Bare metal kurtarma testi başlıyor..."
log "Kaynak VM: $VM_ID, Snapshot: $SNAPSHOT_NAME"

# Snapshot'ı listele ve doğrula
SNAP_EXISTS=$(pvesh get /nodes/localhost/qemu/$VM_ID/snapshot | grep "$SNAPSHOT_NAME")
if [ -z "$SNAP_EXISTS" ]; then
    log "HATA: Snapshot bulunamadı: $SNAPSHOT_NAME"
    exit 1
fi

# DR node'unda yeni VM oluştur (snapshot'tan klonlama)
log "DR node'unda klonlama işlemi başlıyor..."
qm clone "$VM_ID" "$NEW_VM_ID" 
    --name "dr-test-$(date +%Y%m%d)" 
    --target "$DR_NODE" 
    --snapname "$SNAPSHOT_NAME" 
    --full 1

CLONE_STATUS=$?
if [ $CLONE_STATUS -ne 0 ]; then
    log "HATA: Klonlama başarısız! Exit code: $CLONE_STATUS"
    exit 1
fi

# Test VM'i farklı bir network segmentinde başlat
log "Test VM ağ ayarları yapılandırılıyor (izole VLAN)..."
qm set "$NEW_VM_ID" --net0 virtio,bridge=vmbr1,tag=999

# VM'i başlat
qm start "$NEW_VM_ID"
sleep 60  # Bootlanması için bekle

# VM'e SSH ile bağlan ve temel kontrolleri yap
VM_IP=$(qm agent "$NEW_VM_ID" network-get-interfaces | grep -A2 "eth0" | grep "ip-address" | head -1 | awk '{print $2}')
log "Test VM IP adresi: $VM_IP"

# Servis kontrolleri
SERVICES=("nginx" "postgresql" "redis")
for service in "${SERVICES[@]}"; do
    if ssh -o StrictHostKeyChecking=no "admin@$VM_IP" "systemctl is-active $service" 2>/dev/null | grep -q "active"; then
        log "OK: $service servisi çalışıyor"
    else
        log "HATA: $service servisi çalışmıyor!"
    fi
done

log "Test tamamlandı. Test VM temizleniyor..."
qm stop "$NEW_VM_ID" && qm destroy "$NEW_VM_ID"

Senaryo 4: Ağ Altyapısı Arızası Simülasyonu

Sadece sunucu değil, ağ altyapısı da çökebilir. Bu senaryoda kritik ağ bağlantılarının kesilmesini simüle edip uygulamanın nasıl davrandığını test ediyoruz.

#!/bin/bash
# Network partition testi - iptables ile bağlantı kesme simülasyonu
# DİKKAT: Bu scripti sadece test ortamında çalıştırın!

TARGET_SUBNET="10.10.20.0/24"  # Simüle edilecek ağ
TEST_DURATION=300  # 5 dakika bağlantı kesme
MONITOR_INTERVAL=10

log "Ağ kesinti simülasyonu başlıyor..."
log "Hedef subnet: $TARGET_SUBNET"
log "Süre: $TEST_DURATION saniye"

# Bağlantıyı kes
iptables -A INPUT -s "$TARGET_SUBNET" -j DROP
iptables -A OUTPUT -d "$TARGET_SUBNET" -j DROP

log "Bağlantı kesildi. Uygulama izleniyor..."

# Test süresi boyunca uygulama davranışını izle
END_TIME=$(($(date +%s) + TEST_DURATION))
ALERT_COUNT=0

while [ $(date +%s) -lt $END_TIME ]; do
    # Uygulama health check
    HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 http://app.internal/health)
    
    if [ "$HTTP_STATUS" != "200" ]; then
        ALERT_COUNT=$((ALERT_COUNT + 1))
        log "ALERT #$ALERT_COUNT: Uygulama yanıt vermiyor (HTTP: $HTTP_STATUS)"
    else
        log "OK: Uygulama yanıt veriyor (HTTP: $HTTP_STATUS) - Graceful degradation çalışıyor"
    fi
    
    sleep "$MONITOR_INTERVAL"
done

# Bağlantıyı geri yükle
log "Test süresi doldu. Bağlantı restore ediliyor..."
iptables -D INPUT -s "$TARGET_SUBNET" -j DROP
iptables -D OUTPUT -d "$TARGET_SUBNET" -j DROP

log "Toplam alert sayısı: $ALERT_COUNT"
log "Ağ geri yükleme sonrası recovery süresi ölçülüyor..."

# Recovery süresini ölç
RECOVERY_START=$(date +%s)
until curl -s --max-time 5 http://app.internal/health | grep -q "ok"; do
    sleep 2
done
RECOVERY_TIME=$(($(date +%s) - RECOVERY_START))
log "Recovery süresi: $RECOVERY_TIME saniye"

Otomatik DR Test Raporlama

Manuel test sonuçlarını takip etmek zorlaşabilir. Özellikle düzenli testler yapıyorsanız otomatik raporlama şart.

#!/bin/bash
# DR test sonuç raporu oluşturucu

REPORT_FILE="/var/reports/dr_test_$(date +%Y%m%d).html"
LOG_FILE="$DR_LOG"

generate_html_report() {
    cat > "$REPORT_FILE" << EOF
<!DOCTYPE html>
<html>
<head><title>DR Test Raporu - $(date +%Y-%m-%d)</title></head>
<body>
<h2>Felaket Kurtarma Test Raporu</h2>
<p>Test Tarihi: $(date '+%d/%m/%Y %H:%M')</p>
<p>Test Ortamı: $TEST_ENV</p>
<hr>
<h3>Test Sonuçlari</h3>
<pre>
$(cat "$LOG_FILE" | grep -E "BAŞARILI|HATA|UYARI|OK" | head -50)
</pre>
<h3>Metrikler</h3>
EOF

    # RTO hesapla
    RTO_ACTUAL=$(grep "tamamlandı" "$LOG_FILE" | grep -oP 'd+ saniye' | tail -1)
    echo "<p>Gerçekleşen RTO: $RTO_ACTUAL</p>" >> "$REPORT_FILE"
    
    # Başarı oranı
    SUCCESS=$(grep -c "BAŞARILI" "$LOG_FILE")
    FAILURE=$(grep -c "HATA" "$LOG_FILE")
    TOTAL=$((SUCCESS + FAILURE))
    
    if [ "$TOTAL" -gt 0 ]; then
        RATE=$((SUCCESS * 100 / TOTAL))
        echo "<p>Başarı Oranı: %$RATE ($SUCCESS/$TOTAL)</p>" >> "$REPORT_FILE"
    fi
    
    echo "</body></html>" >> "$REPORT_FILE"
    log "Rapor oluşturuldu: $REPORT_FILE"
    
    # Raporu e-posta ile gönder
    mail -s "DR Test Raporu - $(date +%Y-%m-%d)" 
        -a "Content-Type: text/html" 
        [email protected] < "$REPORT_FILE"
}

generate_html_report

Senaryo 5: Ransomware Saldırısı Simülasyonu

Günümüzde en yaygın felakette türlerinden biri artık fidye yazılımı saldırılarıdır. Bu senaryoda kritik dizinler “şifrelenmiş” gibi davranıp, temiz yedekten kurtarma yapıyoruz.

#!/bin/bash
# Ransomware kurtarma simülasyonu
# Temiz bir snapshot noktasına geri dönüş testi

INFECTED_DIRS=("/var/www/html" "/opt/app/data")
CLEAN_BACKUP_DATE="2024-01-15"  # Bilinen temiz yedek tarihi
BACKUP_SOURCE="/backup/daily/$CLEAN_BACKUP_DATE"

log "=== Ransomware Kurtarma Simülasyonu ==="
log "Temiz yedek tarihi: $CLEAN_BACKUP_DATE"

# Adım 1: Sistemi ağdan izole et (simülasyon için sadece loglama)
log "ADIM 1: Etkilenen sistemler ağdan izole ediliyor..."
log "Firewall kuralları uygulandı. Lateral movement engellendi."

# Adım 2: Etkilenme kapsamını belirle
log "ADIM 2: Etkilenme kapsamı analizi..."
for dir in "${INFECTED_DIRS[@]}"; do
    FILE_COUNT=$(find "$dir" -type f 2>/dev/null | wc -l)
    ENCRYPTED=$(find "$dir" -name "*.encrypted" -o -name "*.locked" 2>/dev/null | wc -l)
    log "Dizin: $dir | Toplam: $FILE_COUNT | Etkilenen: $ENCRYPTED"
done

# Adım 3: Yedek bütünlüğünü doğrula
log "ADIM 3: Yedek bütünlüğü kontrol ediliyor..."
if [ -f "$BACKUP_SOURCE/manifest.sha256" ]; then
    cd "$BACKUP_SOURCE"
    if sha256sum -c manifest.sha256 --quiet 2>/dev/null; then
        log "BAŞARILI: Yedek bütünlüğü doğrulandı."
    else
        log "HATA: Yedek bütünlüğü bozuk! Alternatif yedek aranıyor..."
        # Bir önceki yedeği dene
        BACKUP_SOURCE="/backup/daily/$(date -d "$CLEAN_BACKUP_DATE - 1 day" +%Y-%m-%d)"
    fi
fi

# Adım 4: Kurtarma işlemi
log "ADIM 4: Kurtarma işlemi başlıyor..."
RESTORE_START=$(date +%s)

for dir in "${INFECTED_DIRS[@]}"; do
    log "Geri yükleniyor: $dir"
    rsync -avz --delete 
        "$BACKUP_SOURCE/$(basename $dir)/" 
        "$dir/" >> "$DR_LOG" 2>&1
done

RESTORE_END=$(date +%s)
RESTORE_DURATION=$((RESTORE_END - RESTORE_START))
log "Geri yükleme süresi: $RESTORE_DURATION saniye"

# Adım 5: Uygulama doğrulama
log "ADIM 5: Uygulama fonksiyonellik testi..."
sleep 10
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/health)
if [ "$HTTP_CODE" = "200" ]; then
    log "BAŞARILI: Uygulama normal çalışıyor."
else
    log "HATA: Uygulama health check başarısız! HTTP: $HTTP_CODE"
fi

DR Test Takvimi ve Sıklığı

Testlerin ne zaman yapılacağı da en az nasıl yapılacağı kadar önemlidir. Önerilen frekanslar şunlardır:

  • Haftalık: Otomatik yedek doğrulama ve checksum kontrolü
  • Aylık: Kısmi geri yükleme testi (tek bir veritabanı veya uygulama bileşeni)
  • Üç ayda bir: Tam failover testi, standby ortamının aktivasyonu
  • Altı ayda bir: Tam ölçekli DR tatbikatı, ekibin tüm iletişim prosedürlerini dahil et
  • Yılda bir: Üst yönetimin katıldığı masa başı tatbikatı ve plan güncellemesi

Bu takvimleri crontab ile otomatize edebilirsiniz:

# Otomatik DR test takvimi
# /etc/cron.d/dr-tests dosyasına eklenecek

# Her gece 02:00'de yedek doğrulama
0 2 * * * root /opt/dr-scripts/verify_backups.sh >> /var/log/dr_backup_verify.log 2>&1

# Her Pazar sabahı 04:00'te aylık geri yükleme testi
0 4 * * 0 root /opt/dr-scripts/monthly_restore_test.sh >> /var/log/dr_monthly_test.log 2>&1

# Her çeyreğin ilk günü saat 06:00'da failover testi
0 6 1 1,4,7,10 * root /opt/dr-scripts/quarterly_failover_test.sh >> /var/log/dr_quarterly.log 2>&1

# Test raporunu her Pazartesi sabahı e-posta ile gönder
0 8 * * 1 root /opt/dr-scripts/generate_weekly_report.sh

Sık Yapılan Hatalar ve Kaçınma Yolları

DR testlerinde en çok karşılaştığım hatalar şunlardır:

  • Yedekleri hiç test etmemek: En klasik hata. Yedek almak yeterli değil, yedeği geri yükleyebiliyor musunuz, bunu bilmeniz gerekiyor.
  • Üretim ortamında test yapmak: Her zaman izole bir test ortamı kullanın. Aksi halde “simülasyon” gerçek felakete dönüşebilir.
  • Ekibi teste dahil etmemek: DR planı sadece siz biliyorsanız tatil veya hasta olduğunuzda plan işe yaramaz. Tüm ekip tatbikata katılmalı.
  • Belgeleme yapmamak: Her testi detaylı belgeleyin. Bir sonraki testte neyin değiştiğini görmek için önceki sonuçlara ihtiyacınız olacak.
  • Başarısız testleri önemsememek: Bir test başarısız olduğunda kutlayın, sorun var anlamına gelir, gerçek krizden önce buldunuz.
  • Planı güncellemeden testi tekrar etmek: Test sonuçlarına göre planı mutlaka güncelleyin, sonra tekrar test edin.

Sonuç

Felaket kurtarma simülasyonu, organizasyonunuzun en değerli sigorta poliçesidir. Yazıda ele aldığımız senaryolar, veritabanı çöküşünden fidye yazılımı saldırısına kadar gerçek hayatta karşılaşabileceğiniz durumları kapsıyor. Ancak en önemli nokta şu: mükemmel bir plan bile test edilmemişse kağıt üzerinde kalır.

İlk adım olarak basit başlayın. Bu hafta yedeklerinizden bir dosyayı geri yükleyin ve ne kadar sürdüğünü not edin. Gelecek ay bir veritabanı failover’ı simüle edin. Her testten öğrenin, planı güncelleyin ve tekrar test edin. Bir felaket anında “umarım çalışır” değil “test ettim, çalışıyor” diyebilmek için harcadığınız her dakika kesinlikle değer.

Gerçek bir kriz geldiğinde en iyi arkadaşınız, üç ay önce yaptığınız tatbikatta aldığınız notlar olacak.

Bir yanıt yazın

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