Veri Merkezi Felaket Senaryosu: Tam Sistem Kaybı

Sabah 03:47’de telefonun çalması hiçbir şeyin iyi habercisi değildir. “Sistemler tamamen çöktü, hiçbir şey açılmıyor” mesajını gördüğünde midenin nasıl bir his verdiğini bilen sysadminler için bu yazıyı yazdım. Tam sistem kaybı, yani veri merkezinin tüm altyapısının bir anda devre dışı kalması, kariyerin en zorlu sınavıdır. Bu senaryoyu yaşamadan önce planlamak, yaşadıktan sonra ağlamaktan çok daha akıllıcadır.

Tam Sistem Kaybı Ne Anlama Gelir?

Kısmi bir arıza ile tam sistem kaybını birbirine karıştırmamak gerekir. Bir sunucunun çökmesi arızadır, çözülür. Ama tam sistem kaybında karşına çıkan tablo şudur: birincil ve ikincil depolama sistemlerinin eş zamanlı çöküşü, ağ altyapısının tamamen devre dışı kalması, sanallaştırma katmanının bütünüyle yanması ya da fiziksel bir felaketin (yangın, sel, deprem) tüm rack’leri silip süpürmesi.

Bu senaryoda sadece bir servisi ayağa kaldırmıyorsun. Sıfırdan bir ortam inşa ediyorsun, üstelik zaman baskısı altında, muhtemelen yorgun ve stresli bir ekiple.

RTO (Recovery Time Objective) ve RPO (Recovery Point Objective) değerlerin bu noktada gerçekten ne kadar geçerli olduğunu öğreneceksin. Kağıt üzerinde “4 saatte toparlanırız” diyenler bu senaryoda genellikle 4 saatin nasıl 40 saate dönüştüğünü yakından izler.

Felaket Öncesi: Altyapı Envanteri ve Belgeleme

Felaket kurtarma planının temel taşı belgeleme olduğu halde, bu en sık ihmal edilen adımdır. Sistem tamamen çöktüğünde neyin nerede olduğunu bilmiyorsan, kurtarma değil keşif yapıyorsun demektir.

Her veri merkezinde güncel tutulması gereken belgeler şunlardır:

  • Ağ topoloji haritası: IP adresleri, VLAN yapılandırmaları, fiziksel bağlantılar
  • Sunucu envanteri: Her makine için işletim sistemi versiyonu, kurulu servisler, bağımlılıklar
  • Parola kasası: Tüm kritik sistem parolaları, şifreli ve offline kopyayla birlikte
  • Lisans bilgileri: İşletim sistemi, yazılım lisansları ve aktivasyon anahtarları
  • Vendor iletişim listesi: Donanım tedarikçileri, ISP, bulut sağlayıcı destek hatları
  • Recovery runbook: Adım adım kurtarma prosedürleri, hangi sistemi önce ayağa kaldıracağına dair öncelik sırası

Bu belgelerin bir kopyasının veri merkezinin dışında, tercihen şifreli bir bulut depolamada ve ofsite fiziksel bir medyada tutulması şarttır. Sunucular yanarsa belgeler de yanar mantığıyla hareket edersen, felakette körün taşı gibi elle yön bulursun.

Yedekleme Stratejisi: 3-2-1-1 Kuralı

Klasik 3-2-1 kuralını biliyorsun: 3 kopya, 2 farklı medya türü, 1 offsite. Ama tam sistem kaybı senaryosu için buna bir “1” daha ekliyoruz: 1 kopya air-gapped (internetten tamamen izole edilmiş) ortamda.

Ransomware saldırıları artık yedekleme sistemlerini de hedef alıyor. Yedeğin S3’te tutuluyorsa ve hesabın ele geçirildiyse, yedeğin de gitmiş demektir.

Yedekleme Doğrulama Script’i

Yedek almak yetmez, yedeğin gerçekten çalışıp çalışmadığını düzenli test etmek gerekir. Bu script, Restic yedeklerini kontrol eder ve son 24 saat içinde başarılı yedek alınmadıysa uyarı gönderir:

#!/bin/bash
# backup_verify.sh - Yedek bütünlük kontrolü

RESTIC_REPOSITORY="/mnt/backup/restic-repo"
RESTIC_PASSWORD_FILE="/etc/restic/password"
ALERT_EMAIL="[email protected]"
MAX_AGE_HOURS=24

export RESTIC_REPOSITORY
export RESTIC_PASSWORD_FILE

# Son snapshot zamanını kontrol et
LAST_SNAPSHOT=$(restic snapshots --json 2>/dev/null | 
    python3 -c "import json,sys; snaps=json.load(sys.stdin); 
    print(snaps[-1]['time'][:19] if snaps else 'NONE')")

if [ "$LAST_SNAPSHOT" = "NONE" ]; then
    echo "KRITIK: Hic snapshot bulunamadi!" | 
        mail -s "[ALARM] Yedek Bulunamadi" $ALERT_EMAIL
    exit 1
fi

# Snapshot yaşını hesapla
SNAP_EPOCH=$(date -d "$LAST_SNAPSHOT" +%s)
NOW_EPOCH=$(date +%s)
AGE_HOURS=$(( (NOW_EPOCH - SNAP_EPOCH) / 3600 ))

if [ $AGE_HOURS -gt $MAX_AGE_HOURS ]; then
    echo "KRITIK: Son yedek ${AGE_HOURS} saat once alindi!" | 
        mail -s "[ALARM] Yedek Eskidi" $ALERT_EMAIL
    exit 2
fi

# Bütünlük kontrolü
restic check --read-data-subset=10% 2>&1
if [ $? -ne 0 ]; then
    echo "KRITIK: Yedek butunluk kontrolu basarisiz!" | 
        mail -s "[ALARM] Yedek Bozuk" $ALERT_EMAIL
    exit 3
fi

echo "Yedek kontrolu basarili. Son yedek: $LAST_SNAPSHOT (${AGE_HOURS} saat once)"

Felaket Anı: İlk 15 Dakika

Alarm geldiğinde paniğe kapılmak en doğal tepkidir. Ama bu 15 dakikada yapacakların, sonraki saatleri şekillendirir.

İlk yapman gerekenler:

  • Durumu kayıt altına al: Tam olarak ne zaman, hangi sistemler, ne hata veriyor
  • Escalation zincirini tetikle: Tek başına kahraman olmaya çalışma, doğru kişileri anında haberdar et
  • Sorunu izole et: Hata yayılıyor mu? Ağı kesmen gerekiyor mu?
  • Felaket kurtarma planını aç: Kafadan yapmaya çalışma, dokümanı takip et

Panik anında gözden kaçan bir detay, kurtarmayı saatlerce uzatabilir. Bu nedenle fiziksel bir kontrol listesi, dijital dökümandan daha değerlidir çünkü ekranda bir şey göremiyorken kağıt hala okunabilir.

Altyapıyı Sıfırdan Ayağa Kaldırma

Öncelik Sıralaması

Her servisi aynı anda ayağa kaldırmaya çalışmak kaotik bir ortam yaratır. Kurtarma sırası şu şekilde belirlenmelidir:

  • Katman 1 – Temel Ağ: Core switch, firewall, DNS, DHCP
  • Katman 2 – Kimlik Yönetimi: Active Directory veya LDAP, RADIUS
  • Katman 3 – Depolama: SAN/NAS sistemleri, veritabanı sunucuları
  • Katman 4 – Kritik Uygulama Sunucuları: ERP, e-posta, web servisleri
  • Katman 5 – İzleme ve Loglama: Monitoring, SIEM sistemleri

Otomatik Kurtarma Altyapısı ile Ansible

Manuel adımları minimize etmek için Ansible playbook kullanmak, insan hatasını büyük ölçüde azaltır. İşte temel bir sunucu hazırlama playbook’u:

# disaster_recovery_base.yml
---
- name: Temel Sunucu Kurtarma Playbook
  hosts: recovery_targets
  become: yes
  vars:
    ntp_servers:
      - "0.tr.pool.ntp.org"
      - "1.tr.pool.ntp.org"
    dns_servers:
      - "10.0.0.53"
      - "10.0.0.54"

  tasks:
    - name: Kritik paketleri yukle
      apt:
        name:
          - rsync
          - nfs-common
          - open-iscsi
          - chrony
        state: present
        update_cache: yes

    - name: NTP yapilandir
      template:
        src: chrony.conf.j2
        dest: /etc/chrony/chrony.conf
      notify: Restart chrony

    - name: SSH hardening uygula
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: "{{ item.regexp }}"
        line: "{{ item.line }}"
      loop:
        - { regexp: '^PermitRootLogin', line: 'PermitRootLogin no' }
        - { regexp: '^PasswordAuthentication', line: 'PasswordAuthentication no' }
        - { regexp: '^X11Forwarding', line: 'X11Forwarding no' }
      notify: Restart sshd

  handlers:
    - name: Restart chrony
      service:
        name: chrony
        state: restarted

    - name: Restart sshd
      service:
        name: sshd
        state: restarted

Veritabanı Kurtarma

PostgreSQL tam veri kaybı senaryosunda WAL (Write-Ahead Log) arşivleri ve base backup kombinasyonuyla en son tutarlı noktaya dönülebilir. Aşağıdaki script, belirli bir zaman noktasına dönüş (Point-in-Time Recovery) yapar:

#!/bin/bash
# postgres_pitr.sh - PostgreSQL Point-in-Time Recovery

PG_VERSION="15"
PGDATA="/var/lib/postgresql/${PG_VERSION}/main"
BACKUP_BASE="/mnt/backup/postgres/base"
WAL_ARCHIVE="/mnt/backup/postgres/wal"
RECOVERY_TARGET="2024-03-15 03:45:00"

echo "PostgreSQL PITR basliyor..."
echo "Hedef zaman: $RECOVERY_TARGET"

# PostgreSQL durdur
systemctl stop postgresql

# Mevcut data dizinini yedekle (varsa)
if [ -d "$PGDATA" ]; then
    mv "$PGDATA" "${PGDATA}.old.$(date +%s)"
fi

# Base backup'i geri yukle
echo "Base backup yukleniyor..."
mkdir -p "$PGDATA"
tar -xzf "${BACKUP_BASE}/latest.tar.gz" -C "$PGDATA"
chown -R postgres:postgres "$PGDATA"
chmod 700 "$PGDATA"

# Recovery konfigürasyonu oluştur
cat > "${PGDATA}/recovery.signal" << 'EOF'
EOF

cat >> "${PGDATA}/postgresql.conf" << EOF
restore_command = 'cp ${WAL_ARCHIVE}/%f %p'
recovery_target_time = '${RECOVERY_TARGET}'
recovery_target_action = 'promote'
EOF

echo "PostgreSQL recovery modunda baslatiliyor..."
systemctl start postgresql

# Recovery tamamlanana kadar bekle
while systemctl is-active --quiet postgresql; do
    PG_STATUS=$(sudo -u postgres psql -t -c "SELECT pg_is_in_recovery();" 2>/dev/null | tr -d ' ')
    if [ "$PG_STATUS" = "f" ]; then
        echo "Recovery tamamlandi, sunucu normal moda gecti."
        break
    fi
    echo "Recovery devam ediyor..."
    sleep 10
done

LVM Snapshot ile Hızlı Disk Kurtarma

Fiziksel sunucularda LVM snapshot’lardan geri dönüş, sistemin dakikalar içinde eski haline getirilmesini sağlar:

#!/bin/bash
# lvm_restore.sh - LVM snapshot'tan geri yükleme

VG_NAME="vg_data"
LV_NAME="lv_app"
SNAPSHOT_NAME="lv_app_snap_20240315"

echo "LVM snapshot geri yukleme basliyor..."

# Uygulama servislerini durdur
echo "Servisler durduruluyor..."
systemctl stop nginx tomcat postgresql 2>/dev/null

# Volume'u unmount et
MOUNT_POINT=$(df -h /opt/app 2>/dev/null | tail -1 | awk '{print $NF}')
if mountpoint -q "${MOUNT_POINT}"; then
    umount "${MOUNT_POINT}"
    echo "Volume unmount edildi: ${MOUNT_POINT}"
fi

# Snapshot kontrolü
if ! lvs "${VG_NAME}/${SNAPSHOT_NAME}" &>/dev/null; then
    echo "HATA: Snapshot bulunamadi: ${SNAPSHOT_NAME}"
    exit 1
fi

# Snapshot'a geri don
echo "Snapshot'a geri donuluyor..."
lvconvert --merge "${VG_NAME}/${SNAPSHOT_NAME}"

if [ $? -eq 0 ]; then
    echo "Merge basarili, sistemi yeniden baslatma gerekiyor..."
    # Volume'u mount et
    mount "/dev/${VG_NAME}/${LV_NAME}" "${MOUNT_POINT}"
    # Servisleri baslat
    systemctl start postgresql nginx tomcat
    echo "Servisler baslatildi."
else
    echo "HATA: Merge basarisiz!"
    exit 1
fi

Ağ Altyapısını Yeniden Yapılandırma

Sunucular hazır ama ağ konfigürasyonu yoksa hiçbir işe yaramaz. Firewall kurallarının ve ağ yapılandırmasının yedeklerini almak için düzenli çalışacak bir script:

#!/bin/bash
# network_config_backup.sh - Ağ konfigürasyonlarını yedekle

BACKUP_DIR="/mnt/offsite-backup/network-configs/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"

# iptables kurallarını kaydet
iptables-save > "${BACKUP_DIR}/iptables_rules.v4"
ip6tables-save > "${BACKUP_DIR}/iptables_rules.v6"

# ip route tablosunu kaydet
ip route show table all > "${BACKUP_DIR}/routing_table.txt"

# Ağ arayüz konfigürasyonlarını kaydet
cp -r /etc/network/ "${BACKUP_DIR}/network_interfaces" 2>/dev/null
cp -r /etc/netplan/ "${BACKUP_DIR}/netplan" 2>/dev/null

# NetworkManager bağlantılarını kaydet
if command -v nmcli &>/dev/null; then
    nmcli connection show > "${BACKUP_DIR}/nm_connections.txt"
    cp -r /etc/NetworkManager/system-connections/ 
        "${BACKUP_DIR}/nm_system_connections" 2>/dev/null
fi

# VLAN konfigürasyonlarını kaydet
ip -d link show | grep vlan > "${BACKUP_DIR}/vlan_config.txt"

# DNS konfigürasyonunu kaydet
cp /etc/resolv.conf "${BACKUP_DIR}/"
cp /etc/hosts "${BACKUP_DIR}/"

# Sıkıştır ve imzala
tar -czf "${BACKUP_DIR}.tar.gz" -C "$(dirname $BACKUP_DIR)" "$(basename $BACKUP_DIR)"
sha256sum "${BACKUP_DIR}.tar.gz" > "${BACKUP_DIR}.tar.gz.sha256"
rm -rf "$BACKUP_DIR"

echo "Ag konfigurasyonlari yedeklendi: ${BACKUP_DIR}.tar.gz"

Felaket Kurtarma Testi: Gerçek mi, Tatbikat mı?

Birçok şirket felaket kurtarma planını sadece kağıt üzerinde tutar ve yılda bir “masa başı tatbikatı” yaparak geçiştirmeye çalışır. Bu yaklaşım tehlikelidir. Gerçek bir test olmadan planın çalışıp çalışmadığını bilemezsin.

Test türleri şu şekilde sıralanabilir:

  • Masa başı egzersizi: Ekip senaryoyu tartışır, adımları gözden geçirir. Düşük maliyetli ama yetersiz.
  • Modüler test: Tek bir sistem veya servis üzerinde kurtarma denenir. Daha gerçekçi.
  • Tam yük devri testi: Production trafiği DR ortamına yönlendirilir, asıl sistem kapatılır. En gerçekçi test.
  • Surprise drill: Ekibe haber vermeden test başlatılır. Hem insanları hem de prosedürleri gerçek stres altında sınar.

Test sonunda mutlaka yapılması gerekenler:

  • Gerçek RTO ve RPO değerlerini kayıt altına al
  • Hangi adımlarda beklenmedik sorunlar çıktı, belgele
  • Planı güncelle
  • Bir sonraki testin tarihini belirle

Kurtarma Sonrası: Post-Mortem ve Öğrenilen Dersler

Sistemler ayağa kalktıktan sonra iş bitmez. En değerli aşama aslında post-mortem analizidir. Suçlama aramadan, sadece sistemik sorunları anlamak amacıyla yapılan bu toplantı, gelecekte aynı felaketin yaşanmasını engeller.

Post-mortem belgesi şunları içermelidir:

  • Zaman çizelgesi: Olayın başlangıcından çözüme kadar dakika dakika neler oldu
  • Kök neden analizi: Gerçek sorun neydi, semptomları değil kökü bul
  • Katkıda bulunan faktörler: Neyin felaketi daha da kötüleştirdiği
  • Ne iyi gitti: Planın doğru çalışan kısımlarını da belgelemek önemli
  • Eylem maddeleri: Kim, ne yapacak, ne zamana kadar

Post-mortem’i bir suçlama seansına dönüştürmek, ekibin gelecekte sorunları gizlemesine yol açar. Kültürü “hatalar öğrenme fırsatıdır” yönünde şekillendirirsen, ekip bir dahaki felakette çok daha hazırlıklı olur.

Bulut Tabanlı DR: Hibrit Yaklaşım

Tüm altyapıyı ikinci bir fiziksel veri merkezinde tutmak çoğu şirket için bütçe açısından mümkün değildir. Bulut tabanlı DR, bu soruna pragmatik bir çözüm sunar.

AWS veya Azure üzerinde “sıcak standby” yerine “pilot light” yaklaşımıyla sadece kritik sistemlerin minimal konfigürasyonunu tutmak ve felaket anında tam kapasiteye ölçeklendirmek hem maliyetlidir hem de esnektir.

Terraform ile DR ortamını kod olarak yönetmek, tüm altyapıyı dakikalar içinde ayağa kaldırmayı mümkün kılar:

# dr_infrastructure.tf - Temel DR altyapısı

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

variable "dr_region" {
  default = "eu-west-1"
}

variable "environment" {
  default = "dr"
}

provider "aws" {
  region = var.dr_region
}

# DR VPC
resource "aws_vpc" "dr_vpc" {
  cidr_block           = "10.99.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name        = "dr-vpc"
    Environment = var.environment
  }
}

# DR Subnet
resource "aws_subnet" "dr_private" {
  vpc_id            = aws_vpc.dr_vpc.id
  cidr_block        = "10.99.1.0/24"
  availability_zone = "${var.dr_region}a"

  tags = {
    Name = "dr-private-subnet"
  }
}

# DR Launch Template - kritik sunucular için
resource "aws_launch_template" "dr_app_server" {
  name_prefix   = "dr-app-server-"
  image_id      = data.aws_ami.ubuntu_22.id
  instance_type = "t3.xlarge"

  user_data = base64encode(<<-EOF
    #!/bin/bash
    # DR sunucu başlangıç script'i
    apt-get update -y
    apt-get install -y ansible git

    # DR playbook'u çek ve çalıştır
    git clone https://git.sirket.com/infra/dr-playbooks.git /opt/dr
    cd /opt/dr && ansible-playbook site.yml
    EOF
  )

  tag_specifications {
    resource_type = "instance"
    tags = {
      Name        = "dr-app-server"
      Environment = var.environment
    }
  }
}

data "aws_ami" "ubuntu_22" {
  most_recent = true
  owners      = ["099720109477"]

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }
}

Sonuç

Tam sistem kaybı senaryosu, sysadmin kariyerinin en ağır sınavıdır ve kimse bu sınavın “kolay” olduğunu söyleyemez. Ama hazırlıklı olmak ile hazırlıksız yakalanmak arasındaki fark, saatler ile günler, hatta bazı durumlarda şirketin yaşaması ile kapanması arasındaki fark olabilir.

Bugün yapman gereken en önemli şeyler şunlardır: Belgelerini güncelle ve kopyalarını veri merkezinin dışına çıkar. Yedeklerinin gerçekten çalıştığını doğrula, sadece alındığını değil. Bir sonraki çeyrek için gerçek bir DR testi planla. Ve ekibinle felaket kurtarma prosedürlerini gözden geçir, bir kriz anında ilk kez okumak zorunda kalmasınlar.

03:47’de telefon çaldığında, en iyi hissi veren şey “hazırlıklıyız” demektir. O hazırlık bugün yapılan çalışmalardan gelir.

Bir yanıt yazın

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