Yedekleme Stratejisi Olarak Reflink Kopyalama: Btrfs ve XFS’te Anlık Veri Klonlama

Yedekleme deyince aklımıza hep aynı şeyler gelir: rsync, tar arşivleri, belki bir snapshot aracı. Ama “anlık yedek al, disk dolmasın, üstelik işlem saniyeler içinde bitsin” dediğinizde, çoğu klasik yaklaşım yetersiz kalır. İşte burada reflink kopyalama devreye giriyor ve bence bu teknik hâlâ hak ettiği ilgiyi görmüyor.

Reflink, temelde bir “copy-on-write” (COW) mekanizmasıdır. Dosyayı fiziksel olarak kopyalamak yerine, aynı veri bloklarına işaret eden yeni bir metadata girişi oluşturursunuz. Kaynak dosya 50 GB olsun, reflink kopyası neredeyse anlık tamamlanır çünkü gerçek anlamda hiçbir veri taşınmaz. Değişiklik yapıldığında, yalnızca değişen bloklar yeni konuma yazılır. Bu yaklaşımı destekleyen iki ana dosya sistemi var: Btrfs ve XFS (XFS için çekirdek 4.16+ gerekir).

Reflink Neden Klasik Kopyadan Farklı?

Standart cp komutu çalıştırdığınızda ne olur? Çekirdek, kaynak dosyadaki her bloğu okur ve hedef konuma yazar. 100 GB veri için bu işlem dakikalar, bazen saatler alır. Disk I/O şişer, üretim sisteminizde bu süre zarfında performans düşer.

Reflink ile bu tablo tamamen değişir:

  • Kopyalama süresi: Dosya boyutundan bağımsız, genellikle milisaniyeler
  • Disk kullanımı: Başlangıçta sıfır ek alan (değişiklik olmadığı sürece)
  • I/O yükü: Minimal, sadece metadata işlemi
  • Anlık tutumluluk: İki kopya aynı bloğu paylaşır, biri değişirse yalnızca o blok çoğaltılır

Bunu production’da ilk gördüğümde inanmak güç geldi. 80 GB’lık bir PostgreSQL veri dizinini reflink ile kopyaladım, işlem 0,3 saniye sürdü. Aynı işlem rsync --inplace ile 12 dakika alıyordu.

Hangi Dosya Sistemi, Nasıl Hazırlanır?

Btrfs Üzerinde Kurulum

Btrfs, reflink’i varsayılan olarak destekler. Dosya sisteminizin Btrfs olup olmadığını kontrol edin:

df -T /veri
# veya
findmnt -T /veri

Eğer çıktıda btrfs görüyorsanız hazırsınız demektir. Btrfs üzerinde ek bir ayar gerekmez.

# Btrfs dosya sistemi oluşturma örneği (yeni disk için)
mkfs.btrfs -L veri-diski /dev/sdb1

# Mount ederken compress ve autodefrag seçenekleriyle
mount -o compress=zstd,autodefrag /dev/sdb1 /veri

XFS Üzerinde Reflink Desteği

XFS biraz daha dikkat gerektirir. Reflink desteği için dosya sisteminin bu özellikle formatlanmış olması şarttır. Mevcut bir XFS dosya sistemine sonradan reflink ekleyemezsiniz.

# XFS'i reflink destekli oluşturma
mkfs.xfs -m reflink=1 /dev/sdc1

# Mevcut XFS dosya sisteminde reflink aktif mi kontrol
xfs_info /veri | grep reflink
# Çıktı: "reflink=1" görünüyorsa destekleniyor

Önemli bir not: RHEL/CentOS 8 ve sonrası, yeni oluşturulan XFS dosya sistemlerinde reflink’i varsayılan olarak etkinleştirir. RHEL 7 ve eski sistemlerde manuel olarak belirtmeniz gerekir.

cp Komutuyla Reflink Kopyalama

Reflink kopyalamanın en basit yolu GNU cp komutuna --reflink parametresi eklemektir.

# Reflink kopyalama - tam anlamıyla anlık
cp --reflink=always kaynak.img hedef.img

# Eğer dosya sistemi desteklemiyorsa hata ver
cp --reflink=always /ext4-disk/dosya /ext4-disk/kopya
# hata: failed to clone '/ext4-disk/dosya' from '/ext4-disk/kopya': Operation not supported

# Güvenli mod: destekleniyorsa reflink, yoksa normal kopyalama
cp --reflink=auto kaynak.img hedef.img

--reflink=always ile --reflink=auto arasındaki fark kritik: always modunda dosya sistemi desteklemiyorsa komut hata verir ve durur. auto modunda sessizce normal kopyaya geçer. Otomasyon scriptlerinde hangisini kullanacağınız senaryoya göre değişir; genellikle kontrollü ortamlarda always tercih edilir ki “acaba reflink çalıştı mı?” sorusu kafanızı karıştırmasın.

Dizin kopyalamak için:

# Tüm dizini reflink ile kopyala
cp --reflink=always -r /veri/postgresql-15 /yedek/postgresql-15-$(date +%Y%m%d_%H%M)

Gerçek Dünya Senaryosu: Veritabanı Yedekleme

Diyelim ki PostgreSQL çalışıyor ve her gece mantıksal yedek almak yerine veri dizininin anlık klonunu istiyorsunuz. Bunu production’da uyguladığımda şöyle bir yapı kurdum:

#!/bin/bash
# postgres-reflink-backup.sh
# PostgreSQL veri dizininin günlük reflink klonunu alır

set -euo pipefail

PG_DATA="/var/lib/postgresql/15/main"
BACKUP_BASE="/yedek/pg-snapshots"
TARIH=$(date +%Y%m%d_%H%M%S)
HEDEF="${BACKUP_BASE}/pg-${TARIH}"

# PostgreSQL'e checkpoint yaptır (Btrfs/XFS snapshot'ı tutarlı kılmak için)
echo "Checkpoint başlatılıyor..."
sudo -u postgres psql -c "CHECKPOINT;" postgres

# Reflink kopyalama
echo "Reflink kopyası alınıyor: ${HEDEF}"
cp --reflink=always -r "${PG_DATA}" "${HEDEF}"

echo "Tamamlandı: $(du -sh ${HEDEF} | cut -f1) (referans boyut)"

# 7 günden eski yedekleri temizle
find "${BACKUP_BASE}" -maxdepth 1 -name "pg-*" -mtime +7 -exec rm -rf {} ;

echo "Eski yedekler temizlendi."

Bu script çalıştığında 100 GB’lık bir PostgreSQL veri dizini için kopyalama süresi 1-2 saniyeyi geçmez. Ve disk kullanımı? İlk kopya için neredeyse sıfır ek alan. Birden fazla kopyanın varlığında yalnızca değişen bloklar ek alan kullanır.

Btrfs Subvolume + Reflink: Kombine Yaklaşım

Btrfs kullanıcıları için reflink’in ötesinde bir güç daha var: subvolume snapshot’ları. Bu ikisini birlikte kullanmak inanılmaz esneklik sağlar.

# Btrfs subvolume olarak veri dizini oluşturma
btrfs subvolume create /veri/uygulama

# Anlık snapshot al (salt okunur)
btrfs subvolume snapshot -r /veri/uygulama /yedek/uygulama-snap-$(date +%Y%m%d)

# Yazılabilir snapshot (geliştirme/test amaçlı)
btrfs subvolume snapshot /veri/uygulama /test/uygulama-test

# Snapshot listesi
btrfs subvolume list /veri

Snapshot ile reflink arasındaki farka dikkat edin: Btrfs snapshot’ı tüm subvolume’ü kilitler ve izler, reflink ise dosya bazında çalışır. Büyük dizinleri yönetiyorsanız snapshot daha pratik, bireysel dosyalarla çalışıyorsanız reflink daha esnektir.

XFS ile reflink: ocopy_file_range Altında Ne Oluyor?

XFS’te reflink, çekirdek düzeyinde FICLONE ve FICLONERANGE ioctl çağrılarını kullanır. cp --reflink bu çağrıları otomatik yapar ama bazen daha düşük seviyede ne olduğunu anlamak sorun gidermeyi kolaylaştırır.

# strace ile reflink çağrısını izleme
strace -e trace=ioctl cp --reflink=always buyuk-dosya.img kopya.img 2>&1 | grep FICLONE

# Çıktıda şunu görmelisiniz:
# ioctl(4, FICLONE, 3) = 0

Eğer FICLONE çağrısı görünmüyorsa veya hata alıyorsanız, dosya sisteminin reflink destekleyip desteklemediğini tekrar kontrol edin.

# XFS dosya sistemi özelliklerini detaylı inceleme
xfs_info /dev/sdc1

# Çıktının ilgili satırı:
# naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
# ...
# reflink=1

Disk Kullanımını İzleme: Gerçek Alan vs Referans Alan

Reflink’in kullandığınız disk alanını anlamak, alışılageldik du çıktısıyla çelişebilir. Şunu test edin:

# 1 GB'lık test dosyası oluştur
dd if=/dev/zero of=/veri/test.img bs=1M count=1024

# Reflink kopyası al
cp --reflink=always /veri/test.img /veri/test-kopya.img

# du ile bak
du -sh /veri/test.img /veri/test-kopya.img
# Her ikisi de "1.0G" gösterir - ama gerçekte toplam kullanım 1 GB!

# Gerçek disk kullanımını görmek için
du --apparent-size -sh /veri/test.img /veri/test-kopya.img
# vs
df -h /veri  # Toplam kullanılan alan 1 GB civarında kalır

Bu davranış log toplama veya monitoring sistemlerinde yanıltıcı olabilir. Özellikle du -sh /yedek/ ile yedek dizininin ne kadar yer kapladığını ölçerken, reflink’li kopyalar “her biri ayrı ayrı yer kaplıyor” gibi görünür ama disk dolmaz. Farkında olmadan alarm sistemleri yanlış threshold’lara ayarlanabilir.

Gerçek kullanımı ölçmek için Btrfs’te:

# Btrfs'te paylaşılan blokları da hesaba katan kullanım bilgisi
btrfs filesystem du /yedek/

# veya
compsize /veri/test.img /veri/test-kopya.img
# compsize aracı, paylaşılan blokları ve gerçek disk kullanımını gösterir
# apt install btrfs-compsize veya dnf install btrfs-compsize

Uygulama: CI/CD Pipeline’da Hızlı Ortam Klonlama

Bir başka kullanım alanı, development ve staging ortamları için hızlı disk imajı klonlama. KVM/QEMU kullanıyorsanız ve sanal makine imajlarınız Btrfs veya XFS üzerindeyse:

#!/bin/bash
# vm-clone-fast.sh
# Bir VM imajını reflink ile anlık klonlar

KAYNAK_IMAJ="/vm-pool/ubuntu-22.04-base.qcow2"
YENİ_VM="dev-instance-$(date +%s)"
HEDEF_IMAJ="/vm-pool/${YENİ_VM}.qcow2"

echo "VM imajı klonlanıyor: ${YENİ_VM}"
BASLANGIC=$(date +%s%N)

cp --reflink=always "${KAYNAK_IMAJ}" "${HEDEF_IMAJ}"

BITIS=$(date +%s%N)
SURE=$(( (BITIS - BASLANGIC) / 1000000 ))

echo "Klonlama tamamlandı: ${SURE}ms"
echo "İmaj: ${HEDEF_IMAJ}"

# VM'i başlat
# virt-install --import --disk path="${HEDEF_IMAJ}" ...

40 GB’lık bir QCOW2 imajı bu yöntemle 200-400ms içinde klonlanır. QEMU’nun kendi “backing file” mekanizması yerine bu yaklaşımı tercih etmemizin nedeni: reflink kopyalar birbirinden tamamen bağımsız, backing file zincirleri zamanla karmaşıklaşır ve yönetimi zorlaşır.

Sınırlamalar ve Dikkat Edilmesi Gerekenler

Reflink her derde deva değil, bilmeden kullanınca sürprizlerle karşılaşabilirsiniz:

  • Dosya sistemi sınırı: Reflink yalnızca aynı dosya sistemi içinde çalışır. /veri üzerindeki bir dosyayı /yedek üzerine reflink ile kopyalamak istiyorsanız ikisi de aynı mount point veya aynı Btrfs dosya sistemi içinde olmalı.
  • Fragmantasyon riski: Zamanla çok sayıda reflink kopyası oluşturulup değiştirilirse dosya sistemi fragmentasyonu artabilir. Btrfs için btrfs filesystem defragment, XFS için xfs_fsr düzenli çalıştırılabilir.
  • Yedekleme araçlarıyla uyumluluk: rsync, --reflink seçeneğini desteklemez. Borg Backup ve Bupstash gibi modern araçlar COW dosya sistemlerini daha iyi anlar ama reflink kopyaları oluştururken dikkatli olunmalı.
  • ext4 desteklemez: Türkiye’deki pek çok sunucuda hâlâ ext4 yaygın. Reflink için dosya sistemi geçişi gerekebilir, bu da planlama ister.
  • Çekirdek ve araç versiyonları: cp --reflink için GNU coreutils 7.5+ gerekir. Eski CentOS 7 sistemlerinde bu seçenek olmayabilir.
# cp'nin --reflink destekleyip desteklemediğini kontrol
cp --help | grep reflink
# Çıktı yoksa eski bir coreutils sürümü demektir

Defragmantasyon ve Bakım

Reflink yoğun kullanımından sonra periyodik bakım önerilir:

# Btrfs defragmantasyon (dikkat: reflink'leri kırar, paylaşılan bloklar ayrışır)
# Bu komutu yalnızca gerektiğinde çalıştırın
btrfs filesystem defragment -r /veri/uygulama

# XFS defragmantasyon
xfs_fsr /dev/sdc1

# Btrfs'te veri bütünlüğü kontrolü
btrfs scrub start /veri
btrfs scrub status /veri

Önemli uyarı: btrfs filesystem defragment komutu, reflink ile paylaşılan blokları fiziksel olarak çoğaltır. Yani defragmantasyon sonrasında disk kullanımı artabilir. Bunu yalnızca gerçekten fragmentasyon sorunu yaşandığında çalıştırın.

Sonuç

Reflink kopyalama, özellikle Btrfs veya XFS kullanan sistemlerde yedekleme ve klonlama stratejilerini kökten değiştirebilecek bir tekniktir. Klasik “her gece tam yedek al, 8 saat bekle” yaklaşımı yerine; saatlik, hatta dakikalık anlık klonlar almak artık pratik bir seçenek haline gelir.

Benim önerdiğim yaklaşım şu: Eğer yedek alacağınız veri Btrfs veya XFS üzerindeyse ve yedek de aynı dosya sistemi içinde tutulacaksa, cp --reflink=always ile başlayın. Basit, anlaşılır ve inanılmaz etkili. Daha ileri gitmek isteyenler için Btrfs subvolume snapshot’ları güçlü bir katman ekler.

Production ortamında uygulamadan önce test edin, disk kullanım metriklerinizi gözden geçirin ve özellikle du ile df arasındaki farkı anlayın. Bu detayları kavradıktan sonra reflink, araç kutunuzun vazgeçilmez bir parçası haline gelir.

Bir yanıt yazın

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