Felaket Kurtarma Testini Otomatikleştirme: Adım Adım Rehber

Bir felaket kurtarma planı hazırlamak güzel bir şey. Ama o planı hiç test etmemek, karanlıkta el yordamıyla yürümek gibi. Gerçek bir kriz anında “acaba çalışır mı?” sorusunu sormak istemezsiniz. İşte tam bu noktada DR testlerini otomatikleştirmek devreye giriyor. Bu yazıda, felaket kurtarma testlerini elle yapmaktan kurtulup nasıl güvenilir, tekrarlanabilir ve izlenebilir bir sisteme kavuşabileceğinizi anlatacağım.

Neden DR Testini Otomatikleştirmeliyiz?

Manuel DR testleri birkaç temel sorunla birlikte gelir. İlk olarak, insan hatası kaçınılmazdır. Saat 02:00’de panik içinde komut çalıştıran bir sysadmin, adımları atlayabilir veya yanlış sırayla uygulayabilir. İkincisi, manuel testler nadiren yapılır çünkü zaman alıcı ve yorucu. Ayda bir yapılması gereken test, altı ayda bir yapılır, sonra “meşguldük” bahanesiyle tamamen unutulur.

Otomatik DR testi ise şunları sağlar:

  • Tutarlılık: Her test aynı adımlarla, aynı sırayla çalışır
  • Sık test imkanı: Haftalık hatta günlük test mümkün hale gelir
  • Belgeleme: Her testin kayıtları otomatik tutulur
  • Erken uyarı: Sorunları production’da değil, test ortamında yakalar
  • RTO/RPO doğrulaması: Gerçek kurtarma sürelerini ölçersiniz

Temel Kavramlar ve Ön Hazırlık

Başlamadan önce bazı terimleri netleştirelim. RTO (Recovery Time Objective) sisteminizin ne kadar sürede ayağa kalkması gerektiğini tanımlar. RPO (Recovery Point Objective) ise ne kadar veri kaybını tolere edebileceğinizi. Otomatik testleriniz bu iki değeri sürekli ölçmeli ve raporlamalıdır.

Test ortamınızı izole tutmak kritik. Production yedeklerini test ederken canlı sistemi etkilemek istemezsiniz. Bunun için ayrı bir test ağı veya VLAN kullanın.

# Test ortamı için izole network namespace oluşturma
sudo ip netns add dr-test-env
sudo ip link add veth-dr type veth peer name veth-host
sudo ip link set veth-dr netns dr-test-env
sudo ip netns exec dr-test-env ip addr add 10.99.0.1/24 dev veth-dr
sudo ip netns exec dr-test-env ip link set veth-dr up
echo "DR test ortamı hazır: 10.99.0.0/24"

Ana Test Framework’ünü Kurmak

Ben bu işler için genellikle Bash tabanlı bir orchestration scripti yazıyorum, üstüne Ansible veya Python entegre ediyorum. İşte temel iskelet:

#!/bin/bash
# dr-test-framework.sh - Felaket Kurtarma Test Framework'ü

set -euo pipefail

# Konfigurasyon
DR_TEST_HOME="/opt/dr-test"
LOG_DIR="/var/log/dr-tests"
REPORT_DIR="/opt/dr-test/reports"
TEST_TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="${LOG_DIR}/dr_test_${TEST_TIMESTAMP}.log"
ALERT_EMAIL="[email protected]"
SLACK_WEBHOOK="${SLACK_WEBHOOK_URL:-}"

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

# Logging fonksiyonu
log() {
    local level=$1
    shift
    local message="$@"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo -e "${timestamp} [${level}] ${message}" | tee -a "${LOG_FILE}"
}

# Test sonucu kaydetme
record_test_result() {
    local test_name=$1
    local status=$2
    local duration=$3
    local details=$4
    
    echo "${TEST_TIMESTAMP},${test_name},${status},${duration},${details}" 
        >> "${REPORT_DIR}/results_${TEST_TIMESTAMP}.csv"
    
    if [[ "$status" == "FAIL" ]]; then
        log "ERROR" "TEST BAŞARISIZ: ${test_name} - ${details}"
        send_alert "${test_name}" "${details}"
    else
        log "INFO" "TEST BAŞARILI: ${test_name} (${duration}s)"
    fi
}

# Slack bildirimi
send_alert() {
    local test_name=$1
    local message=$2
    
    if [[ -n "$SLACK_WEBHOOK" ]]; then
        curl -s -X POST "$SLACK_WEBHOOK" 
            -H 'Content-type: application/json' 
            -d "{"text":"DR TEST BAŞARISIZ: ${test_name}nDetay: ${message}"}"
    fi
    
    echo -e "DR TEST BAŞARISIZ: ${test_name}n${message}" | 
        mail -s "[UYARI] DR Test Başarısız" "${ALERT_EMAIL}"
}

mkdir -p "${LOG_DIR}" "${REPORT_DIR}"
log "INFO" "DR Test Framework başlatıldı - ${TEST_TIMESTAMP}"

Veritabanı Kurtarma Testini Otomatikleştirme

En kritik bileşen genellikle veritabanıdır. PostgreSQL için otomatik yedek restore testi şöyle görünür:

#!/bin/bash
# test-postgres-recovery.sh

TEST_NAME="PostgreSQL Yedek Kurtarma Testi"
START_TIME=$(date +%s)
TEST_DB_NAME="dr_test_restore_$(date +%s)"
BACKUP_SOURCE="/backup/postgres/latest"
TEST_PG_PORT=15432

log "INFO" "PostgreSQL kurtarma testi başlıyor..."

# Test PostgreSQL instance'ı başlat
start_test_postgres() {
    local test_data_dir="/tmp/pg_dr_test_${TEST_TIMESTAMP}"
    mkdir -p "${test_data_dir}"
    
    # Yeni cluster başlat
    initdb -D "${test_data_dir}" --auth=trust -U postgres 
        > "${LOG_DIR}/initdb_${TEST_TIMESTAMP}.log" 2>&1
    
    # Farklı port ile başlat
    pg_ctl -D "${test_data_dir}" 
           -o "-p ${TEST_PG_PORT}" 
           -l "${LOG_DIR}/pg_test_${TEST_TIMESTAMP}.log" 
           start
    
    sleep 3
    
    if pg_isready -p "${TEST_PG_PORT}" -U postgres; then
        log "INFO" "Test PostgreSQL instance hazır (port: ${TEST_PG_PORT})"
        return 0
    else
        log "ERROR" "Test PostgreSQL instance başlatılamadı"
        return 1
    fi
}

# Yedeği geri yükle
restore_backup() {
    local latest_backup=$(ls -t "${BACKUP_SOURCE}"/*.sql.gz 2>/dev/null | head -1)
    
    if [[ -z "$latest_backup" ]]; then
        log "ERROR" "Yedek dosyası bulunamadı: ${BACKUP_SOURCE}"
        return 1
    fi
    
    log "INFO" "Yedek geri yükleniyor: ${latest_backup}"
    
    # Veritabanı oluştur ve yedeği yükle
    createdb -p "${TEST_PG_PORT}" -U postgres "${TEST_DB_NAME}"
    
    gunzip -c "${latest_backup}" | 
        psql -p "${TEST_PG_PORT}" -U postgres -d "${TEST_DB_NAME}" 
        > "${LOG_DIR}/restore_${TEST_TIMESTAMP}.log" 2>&1
    
    return $?
}

# Veri bütünlüğünü doğrula
verify_data_integrity() {
    # Kritik tabloların varlığını kontrol et
    local tables=("users" "orders" "products" "transactions")
    
    for table in "${tables[@]}"; do
        local count=$(psql -p "${TEST_PG_PORT}" -U postgres -d "${TEST_DB_NAME}" 
            -t -c "SELECT COUNT(*) FROM ${table}" 2>/dev/null | tr -d ' ')
        
        if [[ -z "$count" || "$count" -eq 0 ]]; then
            log "ERROR" "Tablo boş veya mevcut değil: ${table}"
            return 1
        fi
        log "INFO" "Tablo doğrulandı: ${table} (${count} kayıt)"
    done
    
    # Checksum doğrulaması
    local checksum=$(psql -p "${TEST_PG_PORT}" -U postgres -d "${TEST_DB_NAME}" 
        -t -c "SELECT md5(string_agg(id::text, '' ORDER BY id)) FROM users LIMIT 1000")
    
    log "INFO" "Veri checksum: ${checksum}"
    return 0
}

# Temizlik
cleanup_test() {
    pg_ctl -D "/tmp/pg_dr_test_${TEST_TIMESTAMP}" stop -m fast 2>/dev/null || true
    rm -rf "/tmp/pg_dr_test_${TEST_TIMESTAMP}"
    log "INFO" "Test ortamı temizlendi"
}

# Ana test akışı
if start_test_postgres && restore_backup && verify_data_integrity; then
    END_TIME=$(date +%s)
    DURATION=$((END_TIME - START_TIME))
    record_test_result "${TEST_NAME}" "PASS" "${DURATION}" "Tüm tablolar doğrulandı"
else
    END_TIME=$(date +%s)
    DURATION=$((END_TIME - START_TIME))
    record_test_result "${TEST_NAME}" "FAIL" "${DURATION}" "Kurtarma veya doğrulama başarısız"
fi

cleanup_test

Uygulama Sunucusu Failover Testi

Veritabanından sonra uygulama katmanını test etmek gerekir. Bu senaryo, birincil uygulama sunucusunun çökmesini simüle eder:

#!/bin/bash
# test-app-failover.sh

TEST_NAME="Uygulama Sunucusu Failover Testi"
PRIMARY_HOST="app-primary.internal"
SECONDARY_HOST="app-secondary.internal"
HEALTH_CHECK_URL="http://${SECONDARY_HOST}:8080/health"
MAX_FAILOVER_TIME=120  # saniye cinsinden RTO

log "INFO" "Failover testi başlıyor. Primary: ${PRIMARY_HOST}"

# Primary'yi devre dışı bırak (simülasyon)
simulate_primary_failure() {
    log "INFO" "Primary sunucu arızası simüle ediliyor..."
    
    # HAProxy üzerinden primary'yi drain et
    echo "disable server app_pool/${PRIMARY_HOST}" | 
        socat stdio /var/run/haproxy/admin.sock
    
    # Firewall kuralıyla trafiği kes (test ortamında)
    iptables -I INPUT -s "${PRIMARY_HOST}" -j DROP
    iptables -I OUTPUT -d "${PRIMARY_HOST}" -j DROP
    
    log "INFO" "Primary sunucu izole edildi"
}

# Failover süresini ölç
measure_failover_time() {
    local start=$SECONDS
    local attempts=0
    local max_attempts=60
    
    while [[ $attempts -lt $max_attempts ]]; do
        if curl -sf --max-time 3 "${HEALTH_CHECK_URL}" > /dev/null 2>&1; then
            local elapsed=$((SECONDS - start))
            log "INFO" "Secondary sunucu devreye girdi. Süre: ${elapsed}s"
            
            if [[ $elapsed -le $MAX_FAILOVER_TIME ]]; then
                echo "$elapsed"
                return 0
            else
                log "ERROR" "Failover süresi RTO'yu aştı: ${elapsed}s > ${MAX_FAILOVER_TIME}s"
                echo "$elapsed"
                return 1
            fi
        fi
        
        sleep 2
        ((attempts++))
    done
    
    log "ERROR" "Failover gerçekleşmedi, timeout!"
    echo "TIMEOUT"
    return 1
}

# Primary'yi geri getir
restore_primary() {
    iptables -D INPUT -s "${PRIMARY_HOST}" -j DROP
    iptables -D OUTPUT -d "${PRIMARY_HOST}" -j DROP
    
    echo "enable server app_pool/${PRIMARY_HOST}" | 
        socat stdio /var/run/haproxy/admin.sock
    
    log "INFO" "Primary sunucu restore edildi"
}

START_TIME=$(date +%s)
simulate_primary_failure

FAILOVER_DURATION=$(measure_failover_time)
TEST_STATUS=$?

restore_primary

END_TIME=$(date +%s)
TOTAL_DURATION=$((END_TIME - START_TIME))

if [[ $TEST_STATUS -eq 0 ]]; then
    record_test_result "${TEST_NAME}" "PASS" "${FAILOVER_DURATION}" 
        "Failover ${FAILOVER_DURATION}s içinde tamamlandı (RTO: ${MAX_FAILOVER_TIME}s)"
else
    record_test_result "${TEST_NAME}" "FAIL" "${TOTAL_DURATION}" 
        "Failover süresi: ${FAILOVER_DURATION}s, RTO aşıldı veya failover gerçekleşmedi"
fi

Dosya Sistemi ve NFS Kurtarma Testi

Veri depolama katmanını da test etmek şart:

#!/bin/bash
# test-filesystem-recovery.sh

TEST_NAME="Dosya Sistemi ve NFS Kurtarma Testi"
BACKUP_DIR="/backup/fileserver"
TEST_RESTORE_DIR="/tmp/dr_fs_test_${TEST_TIMESTAMP}"
SAMPLE_FILES_COUNT=1000
CHECKSUM_FILE="${BACKUP_DIR}/checksums.md5"

log "INFO" "Dosya sistemi kurtarma testi başlıyor..."

verify_backup_integrity() {
    log "INFO" "Yedek bütünlüğü kontrol ediliyor..."
    
    # En son yedeği bul
    local latest_backup=$(ls -t "${BACKUP_DIR}"/backup_*.tar.gz 2>/dev/null | head -1)
    
    if [[ -z "$latest_backup" ]]; then
        log "ERROR" "Yedek bulunamadı"
        return 1
    fi
    
    # Tar archive bütünlüğünü kontrol et
    if ! tar -tzf "${latest_backup}" > /dev/null 2>&1; then
        log "ERROR" "Tar archive bozuk: ${latest_backup}"
        return 1
    fi
    
    local backup_age=$(( ($(date +%s) - $(stat -c %Y "${latest_backup}")) / 3600 ))
    log "INFO" "Yedek yaşı: ${backup_age} saat"
    
    # RPO kontrolü: 24 saatten eski yedek varsa uyar
    if [[ $backup_age -gt 24 ]]; then
        log "ERROR" "Yedek RPO'yu aşıyor: ${backup_age}h > 24h"
        return 1
    fi
    
    echo "$latest_backup"
    return 0
}

restore_and_verify() {
    local backup_file=$1
    mkdir -p "${TEST_RESTORE_DIR}"
    
    log "INFO" "Dosyalar geri yükleniyor: ${backup_file}"
    
    tar -xzf "${backup_file}" -C "${TEST_RESTORE_DIR}" 
        > "${LOG_DIR}/tar_restore_${TEST_TIMESTAMP}.log" 2>&1
    
    # Checksum doğrulaması
    if [[ -f "$CHECKSUM_FILE" ]]; then
        log "INFO" "Checksum doğrulanıyor..."
        pushd "${TEST_RESTORE_DIR}" > /dev/null
        
        if md5sum -c "${CHECKSUM_FILE}" --quiet 2>/dev/null; then
            log "INFO" "Tüm checksum'lar doğrulandı"
        else
            log "ERROR" "Checksum uyuşmazlığı tespit edildi!"
            popd > /dev/null
            return 1
        fi
        popd > /dev/null
    fi
    
    # Dosya sayısını doğrula
    local restored_count=$(find "${TEST_RESTORE_DIR}" -type f | wc -l)
    log "INFO" "Geri yüklenen dosya sayısı: ${restored_count}"
    
    if [[ $restored_count -lt $SAMPLE_FILES_COUNT ]]; then
        log "ERROR" "Beklenen dosya sayısından az: ${restored_count} < ${SAMPLE_FILES_COUNT}"
        return 1
    fi
    
    return 0
}

START_TIME=$(date +%s)
BACKUP_FILE=$(verify_backup_integrity)

if [[ $? -eq 0 ]] && restore_and_verify "${BACKUP_FILE}"; then
    END_TIME=$(date +%s)
    DURATION=$((END_TIME - START_TIME))
    record_test_result "${TEST_NAME}" "PASS" "${DURATION}" 
        "Dosya sistemi kurtarması başarılı"
else
    END_TIME=$(date +%s)
    DURATION=$((END_TIME - START_TIME))
    record_test_result "${TEST_NAME}" "FAIL" "${DURATION}" 
        "Dosya sistemi kurtarması başarısız"
fi

rm -rf "${TEST_RESTORE_DIR}"

Tüm Testleri Birleştiren Orchestrator

Tüm bu testleri yönetecek merkezi bir orchestrator scripti olmadan iş yarım kalır:

#!/bin/bash
# dr-orchestrator.sh - Ana DR Test Yöneticisi

source /opt/dr-test/dr-test-framework.sh

TESTS_PASSED=0
TESTS_FAILED=0
TESTS_SKIPPED=0

run_test() {
    local test_script=$1
    local test_description=$2
    local is_critical=${3:-false}
    
    log "INFO" "============================================"
    log "INFO" "Çalıştırılıyor: ${test_description}"
    log "INFO" "============================================"
    
    if [[ ! -x "$test_script" ]]; then
        log "WARN" "Test scripti bulunamadı veya çalıştırılamaz: ${test_script}"
        ((TESTS_SKIPPED++))
        return 0
    fi
    
    if timeout 600 bash "${test_script}"; then
        ((TESTS_PASSED++))
        log "INFO" "${test_description}: GEÇTI"
    else
        ((TESTS_FAILED++))
        log "ERROR" "${test_description}: KALDI"
        
        if [[ "$is_critical" == "true" ]]; then
            log "ERROR" "Kritik test başarısız, orchestrator durduruluyor!"
            generate_report
            exit 1
        fi
    fi
}

generate_report() {
    local report_file="${REPORT_DIR}/dr_report_${TEST_TIMESTAMP}.html"
    local total=$((TESTS_PASSED + TESTS_FAILED + TESTS_SKIPPED))
    
    cat > "${report_file}" << EOF
<!DOCTYPE html>
<html>
<head><title>DR Test Raporu - ${TEST_TIMESTAMP}</title>
<style>
  body { font-family: Arial, sans-serif; margin: 20px; }
  .pass { color: green; font-weight: bold; }
  .fail { color: red; font-weight: bold; }
  table { border-collapse: collapse; width: 100%; }
  th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
  th { background-color: #4CAF50; color: white; }
</style>
</head>
<body>
<h2>Felaket Kurtarma Test Raporu</h2>
<p>Tarih: $(date '+%d.%m.%Y %H:%M:%S')</p>
<p>Toplam: ${total} | 
   <span class="pass">Geçti: ${TESTS_PASSED}</span> | 
   <span class="fail">Kaldı: ${TESTS_FAILED}</span> | 
   Atlandı: ${TESTS_SKIPPED}</p>
<h3>Detay Sonuçlar</h3>
$(awk -F',' 'NR>0{print "<tr><td>"$2"</td><td class=""($3=="PASS"?"pass":"fail")"">"$3"</td><td>"$4"s</td><td>"$5"</td></tr>"}' 
    "${REPORT_DIR}/results_${TEST_TIMESTAMP}.csv")
</body>
</html>
EOF
    
    log "INFO" "Rapor oluşturuldu: ${report_file}"
    
    # Raporu e-posta ile gönder
    if command -v sendmail &>/dev/null; then
        (echo "Subject: DR Test Raporu - $(date '+%d.%m.%Y')"; 
         echo "Content-Type: text/html"; 
         echo ""; 
         cat "${report_file}") | sendmail "${ALERT_EMAIL}"
    fi
}

# Test sırası
log "INFO" "DR Test Suite başlatılıyor..."

run_test "/opt/dr-test/tests/test-postgres-recovery.sh" 
    "PostgreSQL Yedek Kurtarma" "true"

run_test "/opt/dr-test/tests/test-app-failover.sh" 
    "Uygulama Failover" "true"

run_test "/opt/dr-test/tests/test-filesystem-recovery.sh" 
    "Dosya Sistemi Kurtarma" "false"

run_test "/opt/dr-test/tests/test-dns-failover.sh" 
    "DNS Failover" "false"

run_test "/opt/dr-test/tests/test-vpn-recovery.sh" 
    "VPN Bağlantı Kurtarma" "false"

generate_report

log "INFO" "DR Test Suite tamamlandı: ${TESTS_PASSED} geçti, ${TESTS_FAILED} kaldı"

[[ $TESTS_FAILED -eq 0 ]] && exit 0 || exit 1

Cron ile Zamanlama ve Gitlab CI Entegrasyonu

Bu testleri düzenli çalıştırmak için iki yöntem öneriyorum. Basit ortamlar için cron yeterli:

# /etc/cron.d/dr-tests
# Her Cumartesi sabah 03:00'de haftalık tam DR testi
0 3 * * 6 root /opt/dr-test/dr-orchestrator.sh >> /var/log/dr-tests/cron.log 2>&1

# Her gece saat 02:00'de hafif yedek doğrulama testi
0 2 * * * root /opt/dr-test/tests/test-backup-integrity-only.sh >> /var/log/dr-tests/nightly.log 2>&1

# Test loglarını 90 gün tut
0 1 * * 0 root find /var/log/dr-tests -name "*.log" -mtime +90 -delete
0 1 * * 0 root find /opt/dr-test/reports -name "*.html" -mtime +180 -delete

GitLab CI ile entegrasyon için .gitlab-ci.yml:

# .gitlab-ci.yml - DR Test Pipeline
stages:
  - validate
  - dr-test
  - report

variables:
  DR_TEST_HOME: "/opt/dr-test"
  SLACK_WEBHOOK_URL: "${SLACK_WEBHOOK}"

validate-scripts:
  stage: validate
  script:
    - shellcheck /opt/dr-test/tests/*.sh
    - echo "Script doğrulama başarılı"
  only:
    - main
    - schedules

weekly-dr-test:
  stage: dr-test
  script:
    - /opt/dr-test/dr-orchestrator.sh
  artifacts:
    when: always
    paths:
      - /opt/dr-test/reports/
    expire_in: 30 days
  only:
    - schedules
  tags:
    - dr-test-runner
  timeout: 2 hours

notify-results:
  stage: report
  script:
    - |
      if [ "$CI_JOB_STATUS" == "failed" ]; then
        curl -X POST "${SLACK_WEBHOOK}" 
          -d "{"text":"DR Testi BAŞARISIZ oldu! Pipeline: ${CI_PIPELINE_URL}"}"
      fi
  when: always
  only:
    - schedules

Gerçek Dünya Senaryosu: Veri Merkezi Geçiş Testi

Geçen yıl müşterimde yaşanan bir senaryoyu paylaşayım. İki veri merkezi arası tam failover testini otomatikleştirmemiz gerekiyordu. Test haftalık çalıştırılacak, hiçbir insan müdahalesi olmayacaktı.

Kritik öğrendiklerimiz şunlar oldu: Test ortamını production’dan izole etmek tek başına yetmez, test verilerinin de güncel olması gerekir. Bunun için “shadow sync” mekanizması kurdu: Her gece production verilerinin anonymize edilmiş kopyası test ortamına aktarılıyor. Böylece hem güncel veriyle test yapıyoruz hem de KVKK uyumluluğunu koruyoruz.

Ayrıca testlerin idempotent olmasına dikkat edin. Yani bir test yarıda kesilip tekrar çalıştırıldığında sistemi tutarsız bırakmamalı. Her test başında mevcut durumu kontrol edip gerekirse önceki test kalıntılarını temizleyen bir “pre-flight check” eklemek bu sorunu çözer.

İzleme ve Metrik Toplama

DR testlerinin sonuçlarını Prometheus/Grafana stack’ine göndermek uzun vadede büyük kolaylık sağlar. Geçmiş testlerin trendini görmek, bozulma eğilimlerini erkenden yakalamak için şart:

# dr-metrics-exporter.sh - Prometheus metriklerini pushgateway'e gönder
PUSHGATEWAY_URL="http://pushgateway.internal:9091"
JOB_NAME="dr_test"

push_metric() {
    local metric_name=$1
    local value=$2
    local labels=$3
    
    cat << EOF | curl -s --data-binary @- "${PUSHGATEWAY_URL}/metrics/job/${JOB_NAME}"
# TYPE ${metric_name} gauge
${metric_name}{${labels}} ${value}
EOF
}

# Test sonuçlarını oku ve metrik olarak gönder
while IFS=',' read -r timestamp test_name status duration details; do
    local_success=0
    [[ "$status" == "PASS" ]] && local_success=1
    
    push_metric "dr_test_success" "$local_success" 
        "test_name="${test_name}",timestamp="${timestamp}""
    
    push_metric "dr_test_duration_seconds" "$duration" 
        "test_name="${test_name}",timestamp="${timestamp}""
        
done < "${REPORT_DIR}/results_${TEST_TIMESTAMP}.csv"

log "INFO" "Metrikler Prometheus pushgateway'e gönderildi"

Sık Yapılan Hatalar

DR testini otomatikleştirirken gözlemlediğim yaygın hataları paylaşmak istiyorum:

  • Test ortamının production’dan farklı olması: Küçük konfigürasyon farkları bile testlerin production’daki gerçeği yansıtmamasına yol açar. Terraform veya Ansible ile ortamları kod olarak yönetin.
  • Sadece “çalışıyor mu?” kontrolü yapmak: Sistem ayağa kalktı, ama doğru veriyle mi çalışıyor? Fonksiyonel doğrulama (birkaç kritik API çağrısı, veritabanı sorgusu) şart.
  • Temizlik adımlarını ihmal etmek: Her testin sonunda kaynakları temizlemek kritik. Biriken test kalıntıları disk dolmasına veya port çakışmalarına yol açar.
  • Alertleri tek kanala bağlamak: Eğer e-posta sunucunuz da o felaket senaryosunun bir parçasıysa, sadece e-posta bildirimi yeterli değil. Slack, PagerDuty, SMS gibi birden fazla kanal kullanın.
  • Başarısız testleri görmezden gelmek: “Bu hafta böyle çıktı, bakarız” demek. Otomasyon bu konuda acımasız olmalı: başarısız test anında eskalasyon.

Sonuç

Felaket kurtarma testini otomatikleştirmek, tek seferlik bir proje değil sürekli bir olgunluk yolculuğu. Başlangıçta basit tutun: önce en kritik sisteminizin (büyük ihtimalle veritabanı) yedek doğrulamasını otomatikleştirin. Ardından uygulama failover, dosya sistemi, ağ katmanı sırasıyla ekleyin.

En önemli çıktı test geçip geçmemek değil, her testte RTO ve RPO değerlerini gerçekçi şekilde ölçüp takip etmektir. Zamanla bu değerlerin nasıl değiştiğini gören bir ekip, hem teknik iyileştirmeleri nereden başlatacağını bilir hem de iş sürekliliği planlarını gerçek verilerle günceller.

Kod tabanınızı versiyon kontrolüne alın, testlerinizi CI/CD pipeline’ına entegre edin ve her hafta otomatik çalışmasına izin verin. Gerçek felaket geldiğinde, en büyük avantajınız “bunu zaten yüzlerce kez test ettik” diyebilmek olacak.

Bir yanıt yazın

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