Felaket Kurtarma Metrikleri: MTTR ve MTBF Analizi

Bir felaket kurtarma planı hazırladınızı düşünün. Belgeler tamam, prosedürler yazılı, ekip eğitildi. Peki bu planın gerçekten işe yarayıp yaramadığını nasıl ölçeceksiniz? İşte tam bu noktada MTTR ve MTBF metrikleri devreye giriyor. Bu iki metrik, soyut “sistemimiz güvenilir” iddiasını somut sayılara dönüştürmenin en etkili yolu. Sysadmin olarak yıllar içinde öğrendiğim en önemli ders şu oldu: ölçemediğiniz şeyi yönetemezsiniz, yönetemediğiniz şeyi de iyileştiremezsiniz.

MTTR ve MTBF Nedir?

MTTR (Mean Time To Recovery/Repair), bir sistemin arızalandıktan sonra tekrar çalışır hale gelmesi için geçen ortalama süredir. Yani bir şeyler patladığında, siz sorunu fark edip çözene kadar geçen toplam sürenin ortalaması.

MTBF (Mean Time Between Failures), iki ardışık arıza arasındaki ortalama süredir. Sistemin ne kadar süre sorunsuz çalıştığını gösterir. Bu metrik, sisteminizin genel güvenilirliğini ölçer.

Bu iki metrik birbirini tamamlar. MTBF yüksekse sisteminiz seyrek arızalanıyor demektir. MTTR düşükse arızaları hızlı çözüyorsunuz demektir. İdeal senaryo: yüksek MTBF + düşük MTTR.

Formüller

MTBF hesabı için:

# MTBF = Toplam Çalışma Süresi / Arıza Sayısı
# Örnek: 720 saatlik periyotta 3 arıza olduysa
# MTBF = 720 / 3 = 240 saat

# Uptime'ı sistem loglarından hesaplamak için
awk '/reboot/ {print $1, $2, $3}' /var/log/wtmp 2>/dev/null || last reboot | head -20

MTTR hesabı için:

# MTTR = Toplam Downtime Süresi / Arıza Sayısı
# Örnek: 3 arızada toplam 6 saat geçtiyse
# MTTR = 6 / 3 = 2 saat

# Son reboot zamanını kontrol et
uptime -s
# Sistem ne kadar süredir ayakta
uptime

Neden Bu Metrikler Önemli?

Bir e-ticaret şirketinde çalışırken yaşadığım bir olayı anlatayım. Yılbaşı gecesi üretim veritabanı çöktü. Ekip sorunu 4 saatte çözdü. “İyi iş çıkardık” dedik. Ama sonradan hesapladığımızda o 4 saatin şirkete maliyeti astronomikti. Eğer önceden MTTR analizimizi yapmış ve hedef belirlemiş olsaydık, o süreyi belki 1 saate indirebilirdik.

MTTR ve MTBF metrikleri size şunları sağlar:

  • SLA taahhütleri için gerçekçi hedefler koymanızı sağlar
  • Bütçe justifikasyonu yaparken somut veri sunar (neden yedekleme sistemine para harcıyoruz sorusuna cevap)
  • Ekip performansını nesnel olarak değerlendirmenizi sağlar
  • Zayıf noktaları tespit etmenizi kolaylaştırır
  • İyileştirme trendini takip etmenizi sağlar

Linux Sistemlerde Log Analizi ile MTTR Hesaplama

Gerçek dünyada MTTR’yi hesaplamak için sistem loglarını analiz etmek gerekir. Bunun için birkaç pratik script yazalım.

#!/bin/bash
# mttr_calculator.sh - Sistem downtime ve MTTR hesaplayıcı

LOG_FILE="/var/log/syslog"
OUTPUT_FILE="/tmp/mttr_report_$(date +%Y%m%d).txt"

echo "=== MTTR Analiz Raporu ===" > $OUTPUT_FILE
echo "Tarih: $(date)" >> $OUTPUT_FILE
echo "" >> $OUTPUT_FILE

# Kernel panic ve kritik hata sayısını bul
CRITICAL_ERRORS=$(grep -c "kernel panic|Out of memory|I/O error" $LOG_FILE 2>/dev/null || echo "0")
echo "Kritik Hata Sayısı: $CRITICAL_ERRORS" >> $OUTPUT_FILE

# Servis restart olaylarını listele
echo "" >> $OUTPUT_FILE
echo "=== Servis Restart Olayları ===" >> $OUTPUT_FILE
grep "Started|Stopped|Failed" /var/log/syslog | grep -E "nginx|apache|mysql|postgresql" >> $OUTPUT_FILE

# Son 30 günün reboot geçmişi
echo "" >> $OUTPUT_FILE
echo "=== Reboot Geçmişi (Son 30 gün) ===" >> $OUTPUT_FILE
last reboot | head -10 >> $OUTPUT_FILE

cat $OUTPUT_FILE
echo "Rapor kaydedildi: $OUTPUT_FILE"

Bu script temel bir başlangıç noktası. Bunu cron ile haftalık çalıştırıp e-posta ile kendinize gönderebilirsiniz.

Servis Bazlı MTTR Takibi

Systemd kullanan sistemlerde servis bazlı downtime takibi çok daha kolay:

#!/bin/bash
# service_availability.sh - Belirli bir servisin uptime analizi

SERVICE=${1:-nginx}
JOURNAL_DAYS=${2:-30}

echo "=== $SERVICE Servis Analizi (Son $JOURNAL_DAYS gün) ==="

# Servis başlangıç ve bitiş zamanlarını çek
echo "Başlangıç olayları:"
journalctl -u $SERVICE --since "$JOURNAL_DAYS days ago" | grep "Started|start" | wc -l

echo "Hata olayları:"
journalctl -u $SERVICE --since "$JOURNAL_DAYS days ago" | grep -i "error|failed|critical" | wc -l

echo "Son 10 durum değişikliği:"
journalctl -u $SERVICE --since "$JOURNAL_DAYS days ago" | 
  grep -E "Started|Stopped|Failed|Reloading" | 
  tail -10

# Servisin şu anki durumu
echo ""
echo "Güncel durum:"
systemctl status $SERVICE --no-pager -l | head -20

MTBF Hesaplama Script’i

MTBF hesaplamak için arızalar arasındaki süreyi takip etmemiz gerekiyor. Bunun için bir monitoring veritabanı tutmak en sağlıklı yol:

#!/bin/bash
# mtbf_tracker.sh - Arıza kayıt ve MTBF hesaplama sistemi

DB_FILE="/var/log/failure_tracker.csv"
ACTION=${1:-"report"}
COMPONENT=${2:-"system"}
START_TIME=${3:-$(date +%s)}
END_TIME=${4:-$(date +%s)}

# CSV dosyası yoksa başlık satırı ekle
if [ ! -f "$DB_FILE" ]; then
    echo "timestamp,component,failure_start,failure_end,duration_minutes,description" > $DB_FILE
    echo "Arıza takip dosyası oluşturuldu: $DB_FILE"
fi

case $ACTION in
    "add")
        # Yeni arıza kaydı ekle
        DURATION=$(( ($END_TIME - $START_TIME) / 60 ))
        DESCRIPTION=${5:-"Manuel kayıt"}
        echo "$(date +%Y-%m-%d %H:%M:%S),$COMPONENT,$START_TIME,$END_TIME,$DURATION,$DESCRIPTION" >> $DB_FILE
        echo "Arıza kaydedildi. Süre: $DURATION dakika"
        ;;
    
    "report")
        # MTBF ve MTTR raporu oluştur
        echo "=== Arıza Analizi Raporu ==="
        echo "Bileşen: $COMPONENT"
        echo ""
        
        # Toplam arıza sayısı
        FAILURE_COUNT=$(grep "$COMPONENT" $DB_FILE | grep -v "^timestamp" | wc -l)
        echo "Toplam Arıza Sayısı: $FAILURE_COUNT"
        
        if [ $FAILURE_COUNT -gt 0 ]; then
            # Toplam downtime (dakika)
            TOTAL_DOWNTIME=$(grep "$COMPONENT" $DB_FILE | grep -v "^timestamp" | 
                awk -F',' '{sum += $5} END {print sum}')
            echo "Toplam Downtime: $TOTAL_DOWNTIME dakika"
            
            # MTTR hesapla
            MTTR=$(echo "scale=2; $TOTAL_DOWNTIME / $FAILURE_COUNT" | bc)
            echo "MTTR: $MTTR dakika"
        fi
        ;;
    
    "list")
        echo "=== Son Arızalar ==="
        cat $DB_FILE | column -t -s ','
        ;;
esac

Kullanım örneği:

# Yeni arıza kaydı ekle (başlangıç ve bitiş timestamp'i ile)
./mtbf_tracker.sh add "postgresql" 1699000000 1699003600 "Disk dolulugu nedeniyle cokme"

# Rapor al
./mtbf_tracker.sh report "postgresql"

# Tüm arızaları listele
./mtbf_tracker.sh list

Gerçek Dünya Senaryosu: E-Ticaret Platformu

Bir e-ticaret müşterim için yaptığım DR analizini paylaşayım. Platform şu bileşenlerden oluşuyordu:

  • Web sunucuları (Nginx + PHP-FPM)
  • Veritabanı kümeleri (PostgreSQL Master-Slave)
  • Redis cache
  • RabbitMQ mesaj kuyruğu
  • Elasticsearch

Her bileşen için ayrı MTBF/MTTR hedefleri belirledik. Ancak bu hedeflere ulaşıp ulaşmadığımızı test etmek için düzenli chaos engineering tatbikatları yaptık.

Otomatik Sağlık Kontrolü ve Alarm

#!/bin/bash
# health_check_with_metrics.sh - Kapsamlı sağlık kontrolü ve metrik kaydı

METRICS_FILE="/var/log/service_metrics.log"
ALERT_EMAIL="[email protected]"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# Kontrol edilecek servisler
SERVICES=("nginx" "php8.1-fpm" "postgresql" "redis-server" "rabbitmq-server")

check_service() {
    local service=$1
    local start_time=$(date +%s%3N)
    
    if systemctl is-active --quiet $service; then
        local end_time=$(date +%s%3N)
        local response_time=$(( $end_time - $start_time ))
        echo "$TIMESTAMP,OK,$service,$response_time ms" >> $METRICS_FILE
        return 0
    else
        echo "$TIMESTAMP,FAILED,$service,0" >> $METRICS_FILE
        
        # Hata başlangıç zamanını kaydet
        echo "FAILURE_START:$(date +%s):$service" >> /tmp/failure_tracking.log
        
        # Mail gönder
        echo "KRITIK: $service servisi DOWN! Zaman: $TIMESTAMP" | 
            mail -s "DR Alert: $service Failure" $ALERT_EMAIL 2>/dev/null
        
        return 1
    fi
}

# Tüm servisleri kontrol et
FAILED_SERVICES=0
for service in "${SERVICES[@]}"; do
    if ! check_service $service; then
        FAILED_SERVICES=$(( $FAILED_SERVICES + 1 ))
        echo "UYARI: $service DOWN!"
    fi
done

# Özet rapor
echo "$TIMESTAMP - Kontrol tamamlandı. Başarısız: $FAILED_SERVICES/${#SERVICES[@]}" >> $METRICS_FILE

# Eğer birden fazla servis downdaysa eskalasyon
if [ $FAILED_SERVICES -ge 2 ]; then
    echo "ESKALASYOn: Birden fazla kritik servis down! Acil müdahale gerekli." | 
        mail -s "KRITIK DR Alert - Çoklu Servis Arızası" $ALERT_EMAIL
fi

Prometheus ile Metrik Toplama

Modern altyapılarda MTTR ve MTBF metriklerini Prometheus ile takip etmek çok daha kolay ve görselleştirilebilir hale geliyor:

#!/bin/bash
# push_metrics_to_prometheus.sh
# Pushgateway üzerinden Prometheus'a metrik gönderir

PUSHGATEWAY_URL="http://prometheus-pushgateway:9091"
JOB_NAME="dr_metrics"
INSTANCE=$(hostname)

# Basit downtime metriği push'la
push_metric() {
    local metric_name=$1
    local metric_value=$2
    local component=$3
    
    cat <<EOF | curl --silent --data-binary @- "$PUSHGATEWAY_URL/metrics/job/$JOB_NAME/instance/$INSTANCE"
# HELP $metric_name DR metrik degeri
# TYPE $metric_name gauge
${metric_name}{component="$component"} $metric_value
EOF
}

# Uptime'ı saniye cinsinden hesapla
UPTIME_SECONDS=$(cat /proc/uptime | awk '{print int($1)}')
push_metric "system_uptime_seconds" "$UPTIME_SECONDS" "system"

# Disk kullanımı (kritik eşik takibi için)
DISK_USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
push_metric "disk_usage_percent" "$DISK_USAGE" "storage"

# Load average
LOAD_AVG=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | tr -d ',')
push_metric "system_load_average" "$LOAD_AVG" "cpu"

echo "Metrikler Prometheus Pushgateway'e gönderildi: $PUSHGATEWAY_URL"

RTO ve RPO ile İlişki

MTTR ve MTBF’yi konuşurken RTO (Recovery Time Objective) ve RPO (Recovery Point Objective) kavramlarını da masaya yatırmak gerekiyor. Bunlar DR planının temel taşları:

RTO: Sistemin ne kadar sürede kurtarılması gerektiğinin hedef değeri. MTTR’nin hedef değeri olarak düşünebilirsiniz.

RPO: Kabul edilebilir maksimum veri kaybı süresi. Son yedekten bu yana geçen süre.

Eğer RTO’nuz 2 saat ama MTTR’niz 4 saatse, SLA’nızı ihlal ediyorsunuz demektir. Bu açık, bütçe talebinde somut bir argüman olarak kullanılabilir.

DR Tatbikat Senaryosu

Her DR planının düzenli test edilmesi şart. İşte basit bir tatbikat scripti:

#!/bin/bash
# dr_drill.sh - Felaket Kurtarma Tatbikat Scripti

DRILL_LOG="/var/log/dr_drill_$(date +%Y%m%d_%H%M%S).log"
START_TIME=$(date +%s)

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

log "=== DR TATBIKATI BAŞLADI ==="
log "Tarih: $(date)"
log "Sunucu: $(hostname)"
log "Yapılan tatbikat: PostgreSQL Failover Simülasyonu"
log ""

# Adım 1: Mevcut durumu kaydet
log "ADIM 1: Mevcut sistem durumu kaydediliyor..."
systemctl status postgresql --no-pager >> $DRILL_LOG 2>&1
STEP1_TIME=$(date +%s)
log "Adım 1 tamamlandı. Süre: $(( $STEP1_TIME - $START_TIME )) saniye"

# Adım 2: Yedek sunucu hazırlığını kontrol et
log ""
log "ADIM 2: Standby sunucu bağlantısı test ediliyor..."
STANDBY_HOST="db-standby.internal"
if ping -c 3 $STANDBY_HOST > /dev/null 2>&1; then
    log "Standby sunucu erişilebilir: $STANDBY_HOST"
else
    log "HATA: Standby sunucuya erişilemiyor! Tatbikat başarısız."
    exit 1
fi
STEP2_TIME=$(date +%s)
log "Adım 2 tamamlandı. Süre: $(( $STEP2_TIME - $STEP1_TIME )) saniye"

# Adım 3: Replikasyon durumu kontrolü
log ""
log "ADIM 3: Replikasyon lag değeri kontrol ediliyor..."
REPL_LAG=$(psql -U postgres -c "SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))::INT as lag_seconds;" 
    -h $STANDBY_HOST -t 2>/dev/null | tr -d ' ')

if [ -n "$REPL_LAG" ] && [ "$REPL_LAG" -lt 60 ]; then
    log "Replikasyon lag değeri kabul edilebilir: $REPL_LAG saniye"
else
    log "UYARI: Replikasyon lag değeri yüksek veya ölçülemedi: $REPL_LAG saniye"
fi

# Tatbikat özeti
END_TIME=$(date +%s)
TOTAL_DURATION=$(( $END_TIME - $START_TIME ))
log ""
log "=== TATBIKAT TAMAMLANDI ==="
log "Toplam süre: $TOTAL_DURATION saniye"
log "Hedef RTO: 300 saniye (5 dakika)"

if [ $TOTAL_DURATION -le 300 ]; then
    log "SONUÇ: BAŞARILI - RTO hedefi karşılandı"
else
    log "SONUÇ: BAŞARISIZ - RTO hedefi aşıldı ($(( $TOTAL_DURATION - 300 )) saniye gecikme)"
fi

log "Detaylı rapor: $DRILL_LOG"

Metrik İyileştirme Stratejileri

Ölçüm yaptınız, sonuçlar ortada. Peki MTTR’yi düşürmek ve MTBF’yi yükseltmek için ne yapabilirsiniz?

MTTR’yi Düşürmek İçin:

  • Runbook otomasyonu: Sık karşılaşılan arızalar için adım adım kurtarma scriptleri hazırlayın. Gece 3’te uykulu kafayla hata yapmak yerine scripti çalıştırın.
  • Alarmlara akıllı önceliklendirme: Her alarm eşit değil. P0, P1, P2 sınıflandırması yapın. Gürültülü alarmlar alarm yorgunluğuna yol açar.
  • Bant genişliği yedeklemesi: Kurtarma işleminin kendisi de yavaşlayabilir. Felaket anında ağ trafiğini kurtarma işlemine önceliklendirin.
  • Eğitim tatbikatları: Ekibin senaryoları “kağıt üstünde” değil gerçek test ortamında deneyimlemesi çok önemli.

MTBF’yi Yükseltmek İçin:

  • Proaktif kapasite planlaması: Disk dolmadan alarm üretin. CPU sürekli yüksekse kök neden analizi yapın.
  • Yama yönetimi: Yamalar can sıkıcıdır ama yamlanmamış sistemler çok daha can sıkıcı arızalar üretir.
  • Bileşen izolasyonu: Bir bileşenin arızası diğerlerini etkilemesin. Circuit breaker, bulkhead pattern kullanın.
  • Tek nokta arızalarını ortadan kaldırın: SPOF (Single Point of Failure) analizi yapın ve kritik bileşenleri çiftleyin.

Metrik Takip Dashboard’u için Temel Formüller

Bir spreadsheet veya Grafana dashboard’unda takip etmeniz gereken hesaplamalar:

#!/bin/bash
# availability_calculator.sh - Sistem erişilebilirlik yüzde hesabı

calculate_availability() {
    local total_minutes=${1:-43200}  # Varsayılan: 30 gün
    local downtime_minutes=${2:-0}
    
    local uptime_minutes=$(( $total_minutes - $downtime_minutes ))
    local availability=$(echo "scale=4; ($uptime_minutes / $total_minutes) * 100" | bc)
    
    echo "=== Erişilebilirlik Raporu ==="
    echo "Analiz periyodu: $total_minutes dakika ($(( $total_minutes / 1440 )) gün)"
    echo "Toplam downtime: $downtime_minutes dakika"
    echo "Uptime: $uptime_minutes dakika"
    echo "Erişilebilirlik: %$availability"
    
    # SLA kontrolü
    local sla_target="99.9"
    if (( $(echo "$availability >= $sla_target" | bc -l) )); then
        echo "SLA Durumu: KARŞILANDI (%$sla_target hedef)"
    else
        local deficit=$(echo "scale=4; $sla_target - $availability" | bc)
        echo "SLA Durumu: BAŞARISIZ (Hedefin %$deficit altında)"
    fi
}

# Örnek: 30 günde 45 dakika downtime
calculate_availability 43200 45

Ekip Süreçleri ve Blameless Post-Mortem

Teknik metrikler kadar önemli olan bir diğer konu: arıza sonrası yapılan post-mortem kültürü. Parmak işaret etmeden, olayı anlayıp öğrenmek üzerine kurulu bir kültür MTTR’yi dramatik şekilde iyileştirir.

Her ciddi arıza sonrası şu soruları cevaplamaya çalışın:

  • Arıza ne zaman başladı, ne zaman tespit edildi? (Bu fark detection lag’ini gösterir)
  • İlk müdahale ne zaman yapıldı?
  • Hangi adımlar işe yaradı, hangileri zaman kaybettirdi?
  • Benzer arızanın tekrarlanmasını önlemek için ne yapılabilir?
  • Monitöring sistemimiz bu arızayı önceden tahmin edebilir miydi?

Bu soruların cevapları hem MTBF hem MTTR metriklerinizi iyileştirecek aksiyon maddelerine dönüşür.

Sonuç

MTTR ve MTBF metrikleri, felaket kurtarma planınızın nabzını ölçer. Bu metrikleri düzenli olarak takip etmek ve trend analizini yapmak, “sanırım iyileşiyoruz” yerine “rakamlar gösteriyor ki iyileşiyoruz” demenizi sağlar.

Pratikte şu üç adımdan başlayabilirsiniz: Önce mevcut durumu ölçün, baseline değerlerinizi belirleyin. Sonra hedef değerler koyun ve bu hedeflere ulaşmak için öncelikli iyileştirme aksiyonlarını belirleyin. Son olarak otomatik metrik toplama ve raporlama altyapısını kurun ki insan faktörü olmadan sürekli ölçüm yapın.

Yıllar içinde gördüğüm en yaygın hata, DR planını kağıt üstünde mükemmel hazırlayıp hiç test etmemek. MTTR ve MTBF metrikleri sizi gerçekçi olmaya zorlar. Rakamlar yalan söylemez. Ve bu yüzden bu metrikler, her sysadmin’in araç kutusunda olması gereken temel unsurlar arasında yer alır.

Bir yanıt yazın

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