Snapshot ile Yazılım Güncelleme Güvenliği

Yazılım güncellemesi yapacaksın, sistem kritik, geri dönüş planın yok. Bu senaryo her sysadmin’in kâbusu. Ama snapshot teknolojisini doğru kullanırsan, bu kâbus tamamen ortadan kalkıyor. Snapshot, güncelleme öncesi sistemin tam bir fotoğrafını çekmen ve bir şeyler ters gittiğinde saniyeler içinde geri dönebilmen anlamına geliyor. Bu yazıda snapshot ile yazılım güncelleme güvenliğini nasıl sağlayacağını, hangi araçları kullanacağını ve gerçek dünya senaryolarında nasıl hareket edeceğini anlatacağım.

Snapshot Nedir ve Neden Güncelleme Öncesi Şart?

Snapshot, bir sistemin belirli bir andaki durumunu kayıt altına alan mekanizmadır. Klasik yedekten farkı şu: Yedek almak saatler sürebilir, snapshot ise genellikle saniyeler içinde tamamlanır. LVM snapshot, ZFS snapshot, Btrfs snapshot veya hypervisor seviyesinde VMware/KVM snapshot gibi farklı katmanlarda çalışabilir.

Yazılım güncellemesi sırasında en sık karşılaşılan sorunlar şunlardır:

  • Bağımlılık çakışmaları: Bir paketin güncellenmesi başka bir paketi bozabilir
  • Kernel güncelleme sonrası açılış sorunu: Özellikle özel kernel modülleri olan sistemlerde ciddi risk
  • Konfigürasyon dosyası üzerine yazılması: Servis yapılandırmaları update sırasında sıfırlanabilir
  • Uygulama uyumsuzluğu: Yeni versiyon, mevcut uygulama kodunuzla çalışmayabilir
  • Veritabanı şema değişiklikleri: Bazı güncellemeler otomatik migration çalıştırır, geri almak çok zordur

Bu sorunların hepsinde snapshot yoksa saatler süren bir kurtarma operasyonuyla karşı karşıya kalabilirsin. Snapshot varsa birkaç komutla 5 dakika öncesine dönüyorsun.

LVM Snapshot ile Güncelleme Güvenliği

LVM (Logical Volume Manager) kullanan sistemlerde snapshot almak oldukça basit. Önce mevcut LVM yapını gör:

# Mevcut logical volume'leri listele
lvdisplay
vgdisplay
df -h

# Boş alan kontrolü - snapshot için alan gerekiyor
vgs --units g

Güncelleme öncesi snapshot alma işlemi:

# Root volume snapshot'ı al (10GB ayır)
lvcreate -L 10G -s -n root_before_update /dev/vg0/root

# Var/home gibi ayrı volume'ler varsa onları da al
lvcreate -L 5G -s -n var_before_update /dev/vg0/var

# Snapshot durumunu kontrol et
lvs -a

Snapshot aldıktan sonra güncellemeyi çalıştır:

# Debian/Ubuntu sistemlerde
apt update && apt upgrade -y

# RHEL/CentOS/Rocky Linux sistemlerde
dnf update -y

# Güncelleme logunu kaydet
apt upgrade -y 2>&1 | tee /var/log/update_$(date +%Y%m%d_%H%M%S).log

Eğer bir şeyler ters giderse snapshot’a geri dön:

# Sistemi kapat (live sistemde revert tehlikeli)
# Recovery mode'a gir veya başka bir sistemden mount et

# Snapshot'a geri dön
lvconvert --merge /dev/vg0/root_before_update

# Sistem yeniden başlatıldığında merge otomatik tamamlanır
reboot

Önemli not: LVM snapshot, orijinal volume üzerindeki değişiklikleri COW (Copy-on-Write) mekanizmasıyla takip eder. Bu yüzden snapshot’ı çok uzun süre aktif tutarsan performans düşüşü yaşanabilir. İşin bitince ya merge et ya da sil.

Btrfs Snapshot: Modern Yaklaşım

Btrfs kullanan sistemlerde (Fedora, openSUSE, modern Ubuntu kurulumları) snapshot işlemi çok daha entegre ve kullanışlıdır. Snapper aracı bu işlemi otomatikleştirir:

# Snapper kurulumu
dnf install snapper -y  # Fedora/RHEL
apt install snapper -y  # Debian/Ubuntu

# Root için snapper konfigürasyonu oluştur
snapper -c root create-config /

# Mevcut konfigürasyonları listele
snapper list-configs

Güncelleme öncesi manuel snapshot:

# Güncelleme öncesi snapshot
snapper -c root create --description "Before system update $(date +%Y%m%d)"

# Snapshot listesini görüntüle
snapper -c root list

# Güncellemeyi çalıştır
dnf update -y

# Güncelleme sonrası snapshot (opsiyonel, karşılaştırma için iyi)
snapper -c root create --description "After system update $(date +%Y%m%d)"

Snapper’ın en güzel özelliği iki snapshot arasındaki farkı göstermesi:

# İki snapshot arasındaki değişiklikleri görüntüle
# Snapshot numaralarını snapper list ile öğren
snapper -c root diff 1 2

# Sadece değişen dosyaların listesi
snapper -c root status 1 2

Geri dönüş senaryosu:

# Btrfs snapshot'a undochange ile geri dön
snapper -c root undochange 1..2

# Ya da snapper rollback ile
snapper rollback 1

# Sistem yeniden başlatıldığında rollback tamamlanır
reboot

openSUSE sistemlerde zypper (paket yöneticisi) otomatik olarak snapper ile entegre çalışır. Her zypper install veya zypper update komutu öncesinde otomatik snapshot alınır. Bu, production sistemler için ideal bir yaklaşım.

ZFS Snapshot: Kurumsal Güç

ZFS kullanan sistemler (FreeBSD, TrueNAS, bazı Linux kurulumları) için snapshot yönetimi son derece güçlüdür:

# Mevcut ZFS pool ve dataset'leri listele
zpool list
zfs list

# Güncelleme öncesi snapshot al
zfs snapshot rpool/ROOT/ubuntu@before_update_$(date +%Y%m%d)

# Tüm dataset'leri recursive olarak snapshotle
zfs snapshot -r rpool@before_update_$(date +%Y%m%d)

# Snapshot listesi
zfs list -t snapshot

ZFS rollback işlemi:

# Son snapshot'a geri dön
zfs rollback rpool/ROOT/ubuntu@before_update_20240115

# Eski bir snapshot'a geri dönmek için -r flag gerekebilir
# Bu aradaki tüm snapshot'ları siler, dikkatli kullan
zfs rollback -r rpool/ROOT/ubuntu@before_update_20240115

ZFS’in harika bir özelliği de snapshot’ları başka bir sisteme göndermek:

# Snapshot'ı başka bir sunucuya gönder (felaket kurtarma)
zfs send rpool/ROOT/ubuntu@before_update_20240115 | 
  ssh backup-server "zfs receive backup/server01"

VMware ve KVM Hypervisor Seviyesinde Snapshot

Sanal makine çalıştırıyorsan hypervisor seviyesinde snapshot almak çoğu zaman en pratik yaklaşım. Guest OS’da hiçbir şey yapman gerekmiyor.

VMware ESXi için:

# VMware PowerCLI ile snapshot al
Connect-VIServer -Server esxi01.company.com

# VM snapshot'ı
New-Snapshot -VM "WebServer01" -Name "Before_Update_$(Get-Date -Format 'yyyyMMdd')" 
  -Description "Pre-update snapshot" -Memory -Quiesce

# Snapshot listesi
Get-Snapshot -VM "WebServer01"

# Snapshot'a geri dön
Set-VM -VM "WebServer01" -Snapshot (Get-Snapshot -VM "WebServer01" -Name "Before_Update_20240115")

KVM/libvirt ile:

# KVM VM snapshot'ı (internal snapshot)
virsh snapshot-create-as --domain webserver01 
  --name "before_update_$(date +%Y%m%d)" 
  --description "Pre-update snapshot" 
  --atomic

# Snapshot listesi
virsh snapshot-list webserver01

# Snapshot bilgisi
virsh snapshot-info webserver01 before_update_20240115

# Snapshot'a geri dön
virsh snapshot-revert webserver01 before_update_20240115

# VM'yi başlat
virsh start webserver01

External disk snapshot’ı (daha güvenli, disk aktifken de çalışır):

# External snapshot oluştur
virsh snapshot-create-as --domain webserver01 
  --name "before_update_ext" 
  --diskspec vda,snapshot=external,file=/var/lib/libvirt/images/webserver01_snap.qcow2 
  --disk-only 
  --atomic

# Snapshot durumunu kontrol et
virsh domblklist webserver01

Pratik Güncelleme Workflow’u

Gerçek bir production ortamında güncelleme güvenliğini nasıl sağlarsın? İşte benim kullandığım pratik bir script:

#!/bin/bash
# pre_update_snapshot.sh - Güncelleme öncesi güvenlik scripti

set -euo pipefail

TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/update_snapshot_${TIMESTAMP}.log"
SNAPSHOT_NAME="pre_update_${TIMESTAMP}"

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

# Disk alanı kontrolü
check_disk_space() {
    local available=$(df / | awk 'NR==2 {print $4}')
    local minimum=5242880  # 5GB in KB
    
    if [ "$available" -lt "$minimum" ]; then
        log "HATA: Yetersiz disk alanı. Minimum 5GB gerekli."
        exit 1
    fi
    log "Disk alanı yeterli: $(df -h / | awk 'NR==2 {print $4}') boş"
}

# Snapshot türünü tespit et ve al
take_snapshot() {
    # LVM kontrolü
    if command -v lvdisplay &>/dev/null && lvdisplay /dev/vg0/root &>/dev/null; then
        log "LVM tespit edildi, snapshot alınıyor..."
        lvcreate -L 10G -s -n "${SNAPSHOT_NAME}" /dev/vg0/root
        log "LVM snapshot alındı: ${SNAPSHOT_NAME}"
        
    # Btrfs kontrolü
    elif df -T / | grep -q btrfs; then
        log "Btrfs tespit edildi, snapper ile snapshot alınıyor..."
        snapper -c root create --description "pre_update_${TIMESTAMP}"
        log "Btrfs snapshot alındı"
        
    # ZFS kontrolü
    elif command -v zfs &>/dev/null; then
        log "ZFS tespit edildi, snapshot alınıyor..."
        zfs snapshot -r "rpool@${SNAPSHOT_NAME}"
        log "ZFS snapshot alındı: ${SNAPSHOT_NAME}"
        
    else
        log "UYARI: Snapshot destekli dosya sistemi bulunamadı!"
        log "rsync ile yedek alınıyor..."
        rsync -aAX --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*"} 
          / "/backup/${SNAPSHOT_NAME}/"
    fi
}

# Sistem bilgilerini kaydet
save_system_info() {
    log "Sistem bilgileri kaydediliyor..."
    
    # Kurulu paket listesi
    if command -v dpkg &>/dev/null; then
        dpkg -l > "/var/log/packages_before_${TIMESTAMP}.txt"
    elif command -v rpm &>/dev/null; then
        rpm -qa --queryformat '%{NAME}-%{VERSION}-%{RELEASE}n' | sort > 
          "/var/log/packages_before_${TIMESTAMP}.txt"
    fi
    
    # Çalışan servisler
    systemctl list-units --state=running > "/var/log/services_before_${TIMESTAMP}.txt"
    
    log "Sistem bilgileri kaydedildi"
}

# Ana akış
log "=== Güncelleme Öncesi Hazırlık Başlıyor ==="
check_disk_space
save_system_info
take_snapshot
log "=== Hazırlık Tamamlandı. Güncellemeye devam edebilirsiniz ==="
log "Geri dönüş gerekirse snapshot adı: ${SNAPSHOT_NAME}"

Bu script’i çalıştır, sonra güvenle güncellemeye devam et:

chmod +x pre_update_snapshot.sh
sudo ./pre_update_snapshot.sh

# Güncellemeyi çalıştır
sudo apt upgrade -y  # veya dnf update -y

# Sistem sağlıklıysa snapshot'ı temizle
sudo lvremove /dev/vg0/pre_update_20240115_143022

Kernel Güncelleme Senaryosu: En Riskli Durum

Kernel güncellemesi özel dikkat gerektirir. DKMS modülleri olan sistemlerde (NVIDIA driver, VirtualBox, WireGuard vs.) kernel güncellemesi sonrası sistem açılmayabilir.

# Güncelleme öncesi mevcut kernel ve modülleri kaydet
uname -r > /var/log/kernel_before_update.txt
lsmod >> /var/log/kernel_before_update.txt

# DKMS modüllerini kontrol et
dkms status

# Snapshot al (yukarıdaki yöntemlerden birini kullan)

# Sadece kernel güncellemesi yap
apt-get install --only-upgrade linux-image-generic linux-headers-generic

# Ya da belirli bir kernel versiyon
apt-get install linux-image-6.5.0-15-generic

# Güncelleme sonrası GRUB yapılandırmasını kontrol et
grep -A5 "menuentry" /boot/grub/grub.cfg | head -20

Kernel güncellemesi sonrası açılış sorunu yaşarsan:

# GRUB menüsünden eski kernel'ı seç
# Veya GRUB komut satırından:
# linux /boot/vmlinuz-<eski_versiyon> root=/dev/sda1
# initrd /boot/initrd.img-<eski_versiyon>
# boot

# Eski kernel'a boot ettikten sonra snapshot'a dön
# LVM için:
lvconvert --merge /dev/vg0/pre_update_snapshot

# Sonra yeni kernel'ı blacklist'e al (geçici)
echo "blacklist <problematic_module>" >> /etc/modprobe.d/blacklist.conf

Otomatik Snapshot Politikası Oluşturma

Production ortamda her güncelleme öncesi manuel snapshot almak unutulabilir. Bunu otomatik hale getirmen lazım:

# /etc/apt/apt.conf.d/80pre-update-snapshot dosyası oluştur
# APT hook ile her apt upgrade öncesi snapshot al

cat > /etc/apt/apt.conf.d/80pre-update-snapshot << 'EOF'
DPkg::Pre-Invoke {"/usr/local/bin/apt_pre_snapshot.sh";};
EOF

# Basit hook scripti
cat > /usr/local/bin/apt_pre_snapshot.sh << 'EOF'
#!/bin/bash
# Sadece upgrade/install işlemlerinde çalış
if [ "$1" = "upgrade" ] || [ "$1" = "install" ]; then
    SNAP_NAME="apt_pre_$(date +%Y%m%d_%H%M%S)"
    
    # Btrfs sistemlerde
    if df -T / | grep -q btrfs; then
        snapper -c root create --description "$SNAP_NAME" 2>/dev/null
    fi
    
    # LVM sistemlerde (eğer yeterli yer varsa)
    if lvdisplay /dev/vg0/root &>/dev/null; then
        FREE=$(vgs --units g --noheadings -o vg_free vg0 | tr -d ' g')
        if [ $(echo "$FREE > 5" | bc) -eq 1 ]; then
            lvcreate -L 5G -s -n "$SNAP_NAME" /dev/vg0/root 2>/dev/null
        fi
    fi
fi
EOF

chmod +x /usr/local/bin/apt_pre_snapshot.sh

Eski snapshot’ları otomatik temizle:

# Snapper için retention policy
cat >> /etc/snapper/configs/root << 'EOF'
TIMELINE_MIN_AGE="1800"
TIMELINE_LIMIT_HOURLY="5"
TIMELINE_LIMIT_DAILY="7"
TIMELINE_LIMIT_MONTHLY="2"
TIMELINE_LIMIT_YEARLY="0"
EOF

# LVM snapshot'ları için cron ile temizlik
cat > /etc/cron.daily/cleanup-lvm-snapshots << 'EOF'
#!/bin/bash
# 7 günden eski LVM snapshot'ları sil
# Snapshot ismine göre filtrele
lvs --noheadings -o lv_name,lv_time | while read name time; do
    if [[ "$name" == *"_before_update_"* ]]; then
        # Tarih karşılaştırması yap ve 7 günden eskiyse sil
        echo "Kontrol ediliyor: $name"
    fi
done
EOF
chmod +x /etc/cron.daily/cleanup-lvm-snapshots

Snapshot Sonrası Doğrulama

Güncelleme tamamlandıktan sonra snapshot’a ihtiyaç duyup duymadığını anlamak için hızlı doğrulama:

#!/bin/bash
# post_update_verify.sh

echo "=== Güncelleme Sonrası Doğrulama ==="

# Kritik servislerin durumu
CRITICAL_SERVICES=("nginx" "mysql" "postgresql" "redis" "docker")

for service in "${CRITICAL_SERVICES[@]}"; do
    if systemctl is-active --quiet "$service" 2>/dev/null; then
        echo "OK: $service çalışıyor"
    elif systemctl is-enabled --quiet "$service" 2>/dev/null; then
        echo "UYARI: $service aktif ama çalışmıyor!"
        systemctl status "$service" --no-pager -l
    fi
done

# Hatalı paket var mı?
if command -v dpkg &>/dev/null; then
    broken=$(dpkg -l | grep -c "^.F" || true)
    if [ "$broken" -gt 0 ]; then
        echo "HATA: $broken kırık paket tespit edildi"
        dpkg -l | grep "^.F"
    else
        echo "OK: Kırık paket yok"
    fi
fi

# Yeniden başlatma gerekiyor mu?
if [ -f /var/run/reboot-required ]; then
    echo "BİLGİ: Sistem yeniden başlatma bekliyor"
    cat /var/run/reboot-required.pkgs 2>/dev/null
fi

# Disk doluluk kontrolü
echo ""
echo "=== Disk Kullanımı ==="
df -h | grep -v tmpfs

Gerçek Dünya Senaryosu: PostgreSQL Sunucusunda Güncelleme

Diyelim ki PostgreSQL çalıştıran bir production sunucusunda major versiyon güncellemesi yapıyorsun. Bu en riskli senaryolardan biri:

  • Major versiyon geçişi (örn. PG 14 to 15) otomatik değil
  • pg_upgrade çalıştırmak gerekiyor
  • Veri formatı değişebilir, geri almak zor
# 1. Snapshot al
lvcreate -L 20G -s -n pgserver_before_pg15 /dev/vg0/root
lvcreate -L 50G -s -n pgdata_before_pg15 /dev/vg0/pgdata

# 2. PostgreSQL'i durdur ve pg_dumpall ile de yedek al (çift güvence)
systemctl stop postgresql
sudo -u postgres pg_dumpall > /backup/pgdump_before_update_$(date +%Y%m%d).sql

# 3. Güncellemeyi yap
apt install postgresql-15

# 4. pg_upgrade çalıştır
sudo -u postgres /usr/lib/postgresql/15/bin/pg_upgrade 
  -b /usr/lib/postgresql/14/bin 
  -B /usr/lib/postgresql/15/bin 
  -d /var/lib/postgresql/14/main 
  -D /var/lib/postgresql/15/main

# 5. Test et
systemctl start postgresql@15-main
sudo -u postgres psql -c "SELECT version();"

# 6. Her şey yolundaysa snapshot'ları temizle
lvremove -f /dev/vg0/pgserver_before_pg15
lvremove -f /dev/vg0/pgdata_before_pg15

Sonuç

Snapshot olmadan güncelleme yapmak, emniyet kemeri takmadan araba kullanmak gibi. Belki yüzlerce kez sorunsuz geçersin, ama bir kere kötü gittiğinde keşke snapshot alsaydım dersin.

Uygulamada dikkat etmen gereken birkaç kritik nokta var. Snapshot, yedek değildir. Disk arızasına karşı koruma sağlamaz, sadece yazılım güncellemesi gibi logic hatalardan kurtarır. Gerçek yedek ayrıca olmalı. Snapshot almak için yeterli boş alan olduğundan emin ol; LVM COW mekanizması değişiklikler büyüdükçe yer kaplar. Snapshot’ları sonsuza kadar bırakma; bittikten sonra temizle, yoksa performans etkisi yaratır. Kritik sistemlerde güncelleme öncesi snapshot alma işlemini otomatize et ve bunu standart operasyon prosedürüne yaz.

Hangi teknolojiyi kullanırsan kullan, LVM, Btrfs, ZFS veya hypervisor snapshot, önemli olan bu adımı routine haline getirmek. Bir süre sonra güncelleme öncesi snapshot almak sana diş fırçalamak kadar doğal gelecek.

Bir yanıt yazın

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