ZFS Snapshot Oluşturma ve Yönetimi

Veri kaybı her sistem yöneticisinin kabusu. Bir şeyleri yanlışlıkla siliyorsunuz, bir güncelleme sistemi mahvedip bırakıyor, ya da bir uygulama veritabanını bozuyor. İşte tam bu noktada ZFS snapshot’ları devreye giriyor ve sizi kurtarıyor. ZFS’in snapshot mekanizması sadece bir yedekleme aracı değil, aynı zamanda üretim ortamlarında günlük operasyonların vazgeçilmez bir parçası haline gelmiş durumda. Bu yazıda ZFS snapshot’larını sıfırdan öğrenecek, gerçek dünya senaryolarında nasıl kullanacağınızı görecek ve otomatik snapshot yönetimini kuracaksınız.

ZFS Snapshot Nedir ve Nasıl Çalışır?

ZFS snapshot’ı, bir filesystem’in ya da volume’un belirli bir andaki salt okunur kopyasıdır. Ancak burada “kopya” kelimesi biraz yanıltıcı. ZFS, snapshot alındığı anda hiçbir veri kopyalamaz. Bunun yerine copy-on-write (COW) mekanizmasını kullanır.

Nasıl çalışır? ZFS her veri bloğunu değiştirdiğinde, orijinal bloğu yerinde değiştirmez. Bunun yerine yeni bir blok yazar ve metadata’yı günceller. Snapshot aldığınızda, ZFS o anki blok referanslarını saklar. Bir dosyayı değiştirdiğinizde, eski blok snapshot tarafından hâlâ referans alınmaktadır, bu yüzden silinmez. Sonuç olarak snapshot’lar başlangıçta neredeyse sıfır disk alanı kaplar ve sadece değişen bloklar için ek alan tüketir.

Bu yaklaşımın pratik faydaları şunlardır:

  • Anlık oluşturma: Terabaytlık bir filesystem’de bile snapshot saniyeler içinde tamamlanır
  • Düşük başlangıç maliyeti: İlk snapshot neredeyse hiç yer kaplamaz
  • Tutarlılık: Snapshot alındığı anda tüm filesystem tutarlı bir durumda dondurulur
  • Hızlı geri alma: Rollback işlemi de aynı şekilde anlık gerçekleşir

Temel ZFS Snapshot Komutları

Snapshot Oluşturma

Snapshot oluşturmak son derece basit. Sözdizimi şöyle: zfs snapshot pool/dataset@snapshot-adı

# Tek bir dataset için snapshot
zfs snapshot tank/data@2024-01-15

# Recursive snapshot (tüm alt dataset'leri dahil eder)
zfs snapshot -r tank@2024-01-15

# Tarih/saat damgalı snapshot
zfs snapshot tank/data@$(date +%Y-%m-%d_%H-%M-%S)

Recursive snapshot kullanırken dikkatli olun. -r parametresi ile tüm alt dataset’ler tek bir komutla snapshot’lanır ve bu snapshot’lar atomik olarak alınır, yani hepsi aynı anda tutarlı bir durumda dondurulur.

Mevcut Snapshot’ları Listeleme

# Tüm snapshot'ları listele
zfs list -t snapshot

# Belirli bir dataset'in snapshot'larını listele
zfs list -t snapshot tank/data

# Snapshot boyutlarıyla birlikte listele
zfs list -t snapshot -o name,creation,used,refer tank/data

# Sıralı çıktı için sort
zfs list -t snapshot -s creation tank/data

Burada dikkat edilmesi gereken iki önemli sütun var:

  • USED: Bu snapshot’ın tükettiği benzersiz disk alanı (başka hiçbir snapshot veya dataset tarafından paylaşılmayan)
  • REFER: Dataset’in bu snapshot’taki toplam veri boyutu

Snapshot’a Erişim

ZFS her dataset’in kök dizininde gizli bir .zfs/snapshot dizini oluşturur. Buradan eski dosyalarınıza doğrudan erişebilirsiniz:

# Snapshot içeriğini görüntüle
ls /data/.zfs/snapshot/

# Belirli bir snapshot'taki dosyaya eriş
ls /data/.zfs/snapshot/2024-01-15/

# Silinen bir dosyayı snapshot'tan kurtar
cp /data/.zfs/snapshot/2024-01-15/onemli_dosya.txt /data/onemli_dosya_restored.txt

Bu özellik inanılmaz derecede kullanışlı. Kullanıcılarınız yanlışlıkla bir dosyayı sildiğinde, IT destek çağrısı açmadan doğrudan .zfs/snapshot klasöründen kendi dosyalarını kurtarabilirler.

Snapshot Silme

# Tek snapshot sil
zfs destroy tank/data@2024-01-15

# Birden fazla snapshot'ı virgülle belirt
zfs destroy tank/data@2024-01-14,2024-01-15

# Belirli bir aralıktaki tüm snapshot'ları sil
zfs destroy tank/data@2024-01-01%2024-01-31

# Recursive snapshot sil
zfs destroy -r tank@2024-01-15

# Silmeden önce ne olacağını gör (dry run)
zfs destroy -n -v tank/data@2024-01-15

-n parametresi ile her zaman önce dry run yapın, özellikle range silme işlemlerinde. Yanlış bir komutla önemli snapshot’larınızı kaybedebilirsiniz.

Snapshot Rollback

Bir güncelleme sisteminizi mahvetti ya da bir test ortamını temizlemeniz gerekiyor. Rollback tam bu iş için:

# En son snapshot'a geri dön
zfs rollback tank/data@2024-01-15

# Aradaki snapshot'ları da silerek daha eski bir snapshot'a dön
zfs rollback -r tank/data@2024-01-10

Dikkat: rollback işlemi seçtiğiniz snapshot’tan daha yeni olan tüm snapshot’ları siler. Eğer hem eski bir snapshot’a dönmek hem de aradaki snapshot’ları korumak istiyorsanız, clone yöntemini kullanmalısınız.

Gerçek dünya senaryosu: Bir PostgreSQL veritabanı sunucusunu güncelliyorsunuz. Güncelleme öncesi snapshot alıyorsunuz:

# Güncelleme öncesi
zfs snapshot tank/postgresql@before-pg14-upgrade

# Güncelleme yap
apt upgrade postgresql-14

# Güncelleme başarısız olduysa geri dön
systemctl stop postgresql
zfs rollback tank/postgresql@before-pg14-upgrade
systemctl start postgresql

ZFS Send/Receive ile Snapshot Transferi

ZFS’in en güçlü özelliklerinden biri send/receive mekanizması. Snapshot’ları başka bir sunucuya ya da harici bir diske aktarabilirsiniz.

# Snapshot'ı dosyaya kaydet
zfs send tank/data@2024-01-15 > /backup/data_snapshot.zfs

# Snapshot'ı başka bir pool'a gönder
zfs send tank/data@2024-01-15 | zfs receive backup/data

# SSH üzerinden uzak sunucuya gönder
zfs send tank/data@2024-01-15 | ssh backup-server "zfs receive tank/data"

# Incremental gönderim (sadece değişenleri gönder)
zfs send -i tank/data@2024-01-14 tank/data@2024-01-15 | ssh backup-server "zfs receive tank/data"

-i parametresi incremental transfer için kullanılır. İki snapshot arasındaki farkı gönderir. Bu özellik bant genişliğini dramatik şekilde azaltır. 1 TB’lık bir dataset için ilk tam transfer 300 GB olabilirken, günlük incremental transferler sadece birkaç GB olabilir.

Sıkıştırma ile birlikte kullanmak:

# pv ile ilerlemeyi izle, gzip ile sıkıştır
zfs send tank/data@2024-01-15 | pv | gzip | ssh backup-server "gunzip | zfs receive tank/data"

# mbuffer ile ağ tamponlaması ekle
zfs send -R tank@2024-01-15 | mbuffer -s 128k -m 1G | ssh backup-server "mbuffer -s 128k -m 1G | zfs receive -F tank"

Clone Oluşturma

Clone, bir snapshot’ın yazılabilir kopyasıdır. Test ortamları oluşturmak, veri analizi yapmak ya da bir güncellemeyi test etmek için mükemmeldir:

# Snapshot'tan clone oluştur
zfs clone tank/data@2024-01-15 tank/data-test

# Clone'u mount et ve kullan
ls /tank/data-test

# Clone'u gerçek dataset ile değiştir (promote)
zfs promote tank/data-test

# İşimiz bittikten sonra clone'u sil
zfs destroy tank/data-test

Gerçek dünya senaryosu: Production veritabanının bir kopyasını geliştirme ortamına vermek istiyorsunuz. Eski yöntemle bu saatler sürebilir. ZFS clone ile saniyeler içinde:

# Production snapshot al
zfs snapshot tank/prod-db@dev-copy-$(date +%Y%m%d)

# Dev ortamı için clone oluştur
zfs clone tank/prod-db@dev-copy-20240115 tank/dev-db

# Dev veritabanını başlat (zaten veri var, kopyalamaya gerek yok)
pg_ctlcluster 14 dev start

Otomatik Snapshot Yönetimi

Manuel snapshot almak güzel ama production ortamlarında otomatik bir sistem kurmanız gerekiyor. Bunun için iki yaklaşım var: cron tabanlı basit script ya da sanoid gibi bir araç.

Cron ile Basit Otomatik Snapshot

#!/bin/bash
# /usr/local/bin/zfs-auto-snapshot.sh

POOL="tank"
DATASET="tank/data"
DATE=$(date +%Y-%m-%d_%H-%M)
KEEP_HOURLY=24
KEEP_DAILY=30
KEEP_WEEKLY=8

# Snapshot al
zfs snapshot ${DATASET}@auto-${DATE}

# Saatlik snapshot temizliği (24'ten fazlasını sil)
HOURLY_SNAPS=$(zfs list -t snapshot -o name -s creation ${DATASET} | grep "auto-" | head -n -${KEEP_HOURLY})
for snap in $HOURLY_SNAPS; do
    zfs destroy $snap
done

echo "Snapshot alindi: ${DATASET}@auto-${DATE}"

Crontab ayarı:

# Her saat başı snapshot al
0 * * * * /usr/local/bin/zfs-auto-snapshot.sh >> /var/log/zfs-snapshot.log 2>&1

# Her gece 02:00'de günlük snapshot
0 2 * * * zfs snapshot tank/data@daily-$(date +%Y-%m-%d)

# Her Pazar 03:00'da haftalık snapshot
0 3 * * 0 zfs snapshot -r tank@weekly-$(date +%Y-%m-%d)

Sanoid ile Profesyonel Snapshot Yönetimi

sanoid ZFS snapshot yönetimi için en popüler araç. Debian/Ubuntu’da kurulumu:

apt install sanoid

# veya kaynak koddan
git clone https://github.com/jimsalterjrs/sanoid.git
cp sanoid/sanoid /usr/local/sbin/
cp sanoid/sanoid.conf /etc/sanoid/

Sanoid konfigürasyonu /etc/sanoid/sanoid.conf:

[tank/data]
    use_template = production
    recursive = yes

[tank/home]
    use_template = home_users
    recursive = yes

[template_production]
    frequently = 0
    hourly = 36
    daily = 30
    monthly = 3
    yearly = 0
    autosnap = yes
    autoprune = yes

[template_home_users]
    frequently = 4
    hourly = 24
    daily = 14
    monthly = 3
    yearly = 0
    autosnap = yes
    autoprune = yes

Systemd timer ile çalıştırma:

# Sanoid'i her 15 dakikada çalıştır
systemctl enable --now sanoid.timer
systemctl status sanoid.timer

Sanoid’in güzel yanı retention policy’yi otomatik yönetmesi. Saatlik 36, günlük 30, aylık 3 snapshot tutacak şekilde ayarladığınızda, eski olanları otomatik temizler.

Snapshot Boyutlarını İzleme

Snapshot’lar zamanla ciddi disk alanı tüketebilir. Düzenli izleme şart:

# Toplam snapshot kullanımını görüntüle
zfs list -t snapshot -o name,used,refer -s used | head -20

# Her dataset'in snapshot'larının toplam boyutu
zfs list -ro space tank

# En büyük snapshot'ları bul
zfs list -t snapshot -o name,used -s used -r tank | tail -20

# Belirli bir eşiği aşan snapshot'ları bul
zfs list -t snapshot -o name,used -r tank | awk '$2 ~ /G/ && $2+0 > 5 {print}'

Monitoring için basit bir script:

#!/bin/bash
# /usr/local/bin/zfs-snapshot-monitor.sh

THRESHOLD_GB=100
POOL="tank"

echo "=== ZFS Snapshot Durum Raporu ==="
echo "Tarih: $(date)"
echo ""

# Pool genel durumu
echo "## Pool Kullanimi:"
zpool list $POOL
echo ""

# En büyük 10 snapshot
echo "## En Buyuk 10 Snapshot:"
zfs list -t snapshot -o name,used,refer -s used -r $POOL | grep -v "^NAME" | tail -10
echo ""

# Toplam snapshot sayısı
TOTAL=$(zfs list -t snapshot -r $POOL | grep -v "^NAME" | wc -l)
echo "## Toplam Snapshot Sayisi: $TOTAL"

Felaket Kurtarma Senaryosu: Tam Sistem Yedeği

Gerçek bir felaket kurtarma senaryosu uygulayalım. Production sunucunuzun tam yedeğini harici bir yedek sunucuya alıyorsunuz:

#!/bin/bash
# /usr/local/bin/zfs-backup.sh

SOURCE_HOST="production-server"
BACKUP_HOST="backup-server"
SOURCE_POOL="tank"
BACKUP_POOL="backup"
DATASETS="tank/data tank/postgresql tank/home"
DATE=$(date +%Y-%m-%d)
LOG="/var/log/zfs-backup.log"

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

for DATASET in $DATASETS; do
    BACKUP_DATASET="${BACKUP_POOL}/${DATASET#*/}"
    SNAP_NAME="${DATASET}@backup-${DATE}"

    log "Snapshot aliniyor: $SNAP_NAME"
    zfs snapshot $SNAP_NAME

    # İlk kez mi yoksa incremental mi?
    LAST_SNAP=$(ssh $BACKUP_HOST "zfs list -t snapshot -o name -s creation $BACKUP_DATASET 2>/dev/null | grep 'backup-' | tail -1")

    if [ -z "$LAST_SNAP" ]; then
        log "Ilk tam yedek baslatiliyor: $DATASET"
        zfs send $SNAP_NAME | ssh $BACKUP_HOST "zfs receive -F $BACKUP_DATASET"
    else
        log "Incremental yedek baslatiliyor: $LAST_SNAP -> $SNAP_NAME"
        # Backup sunucusundaki snapshot adını kaynak ile eşleştir
        LAST_LOCAL="${DATASET}@${LAST_SNAP##*@}"
        zfs send -i $LAST_LOCAL $SNAP_NAME | ssh $BACKUP_HOST "zfs receive -F $BACKUP_DATASET"
    fi

    if [ $? -eq 0 ]; then
        log "Basarili: $DATASET"
    else
        log "HATA: $DATASET yedeği başarisiz!"
        # E-posta bildirimi gönder
        echo "ZFS yedek hatasi: $DATASET" | mail -s "ZFS Backup FAIL" [email protected]
    fi
done

log "Yedekleme tamamlandi."

Snapshot ile İlgili Sık Yapılan Hatalar

Snapshot’ları asla silmek istememe: Snapshot’lar disk dolana kadar biriktirilirse ciddi sorunlara yol açar. Pool dolduğunda yazma işlemleri durur. Mutlaka bir retention policy belirleyin.

Snapshot varken veri silerseniz ne olur: Sildiğiniz dosyanın alanı, o dosyaya referans veren snapshot’lar silinene kadar geri kazanılmaz. Büyük bir dosyayı silip neden disk alanı kazanmadığınıza şaşırabilirsiniz.

Rollback öncesi dikkat: Rollback, seçtiğiniz snapshot’tan sonraki tüm snapshot’ları siler. Önce zfs list -t snapshot ile durumu kontrol edin.

Snapshot adlandırma standardı: Tutarsız isimlendirme yönetimi zorlaştırır. Şu formatı öneririm: @[tip]-[tarih]-[saat] örneğin @auto-2024-01-15-1400 ya da @manual-before-upgrade.

Sonuç

ZFS snapshot’ları, sistem yöneticisinin elindeki en değerli araçlardan biri. Anlık oluşturma, sıfır başlangıç maliyeti, hızlı geri alma ve güçlü transfer mekanizması ile hem küçük ofis sunucularında hem de büyük ölçekli production ortamlarında mükemmel çalışıyor.

Önerdiğim minimum kurulum şu şekilde olmalı: saatlik otomatik snapshot’lar (24 saat tutulacak), günlük snapshot’lar (30 gün tutulacak), haftalık snapshot’lar (8 hafta tutulacak) ve aylık snapshot’lar (12 ay tutulacak). Bu kombinasyon, hem son dakikadaki değişikliklere hızlı erişim hem de uzun vadeli felaket kurtarma kapasitesi sağlar.

Sanoid gibi bir araçla bu politikayı otomatize edin, syncoid ile uzak sunucuya replication kurun ve düzenli olarak restore testleri yapın. Yedekleme sisteminizin çalışıp çalışmadığını test etmediğiniz sürece yedek almıyor sayılırsınız. Her ay en az bir kez bir snapshot’tan veri restore etmeyi deneyin ve sürecin doğru çalıştığını doğrulayın.

ZFS öğrenme eğrisi ilk başta dik görünebilir ama snapshot mekanizmasını kavradıktan sonra, bu özelliği olmayan bir sistemde nasıl çalıştığınızı sorgular hale geliyorsunuz.

Bir yanıt yazın

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