Test Ortamı Oluşturma: Snapshot ile Hızlı Kopyalama
Test ortamı kurmanın en sinir bozucu kısmı nedir biliyor musunuz? Production’a benzer bir ortam hazırlamak için saatler harcamak, paketleri tek tek kurmak, konfigürasyonları elle girmek ve sonunda “acaba bir şeyi atlladım mı?” diye endişelenmek. Snapshot teknolojisi tam da bu noktada hayat kurtarıyor. Bir sistemi belirli bir noktada dondurup, o noktadan istediğiniz kadar kopya üretebiliyorsunuz. Test edin, mahvedin, silin, tekrar başlayın.
Snapshot Nedir ve Neden Test Ortamı İçin Mükemmeldir
Snapshot, bir diskin veya volume’ün belirli bir andaki durumunun kopyasıdır. Ama burada önemli bir nüans var: çoğu snapshot implementasyonu copy-on-write (COW) mantığıyla çalışır. Yani snapshot alındığında tüm veri kopyalanmaz, sadece “bu an” işaretlenir. Sonraki yazma işlemleri gerçekleştikçe, orijinal bloklar snapshot alanına kopyalanır.
Bu mimarinin test ortamı açısından anlamı şu: 100 GB’lık bir sistemi 5 dakikada kopyalayabilirsiniz. Disk alanı da hemen 200 GB olmaz, çünkü değişen bloklar kadar yer kaplar.
Gerçek dünya senaryosu: Diyelim ki bir e-ticaret uygulamasının yeni versiyonunu production’a almadan önce test etmek istiyorsunuz. Veritabanı 80 GB, uygulama sunucusu konfigürasyonları karmaşık. Snapshot olmadan bu ortamı hazırlamak yarım gün sürer. Snapshot ile 10 dakika.
LVM Snapshot: Linux’ta Temel Yöntem
LVM (Logical Volume Manager) kullanan sistemlerde snapshot alma işlemi oldukça basittir. Önce mevcut LVM yapımıza bakalım:
# Mevcut volume group ve logical volume'leri listele
lvs -a -o +devices
vgs
pvs
Diyelim ki /dev/vg_production/lv_app adında bir logical volume’ünüz var ve bunun snapshot’ını almak istiyorsunuz:
# 10 GB snapshot alanı ayırarak snapshot oluştur
lvcreate -L 10G -s -n lv_app_test_snapshot /dev/vg_production/lv_app
# Snapshot'ı doğrula
lvs -a | grep snapshot
Snapshot oluştuktan sonra bunu bir test sunucusuna mount edebilirsiniz:
# Snapshot'ı mount et
mkdir -p /mnt/test_environment
mount -o ro /dev/vg_production/lv_app_test_snapshot /mnt/test_environment
# Ya da yazma iznuyle mount etmek istiyorsanız
mount /dev/vg_production/lv_app_test_snapshot /mnt/test_environment
Snapshot boyutunu izlemek önemli. COW nedeniyle dolmaya başlarsa otomatik devre dışı kalır:
# Snapshot doluluk oranını izle
watch -n 5 'lvs -a --units m | grep snapshot'
# Snapshot boyutunu genişlet (gerekirse)
lvextend -L +5G /dev/vg_production/lv_app_test_snapshot
LVM Snapshot ile Tam Test Ortamı Kurulumu
Şimdi daha gerçekçi bir senaryo: Production veritabanı sunucusunun snapshot’ını alıp test ortamında ayağa kaldırmak.
#!/bin/bash
# test_env_create.sh
PROD_VG="vg_production"
PROD_LV="lv_database"
SNAP_NAME="lv_db_test_$(date +%Y%m%d_%H%M)"
SNAP_SIZE="20G"
MOUNT_POINT="/mnt/test_db"
echo "[$(date)] Snapshot alınıyor..."
lvcreate -L ${SNAP_SIZE} -s -n ${SNAP_NAME} /dev/${PROD_VG}/${PROD_LV}
if [ $? -eq 0 ]; then
echo "[$(date)] Snapshot başarıyla oluşturuldu: ${SNAP_NAME}"
mkdir -p ${MOUNT_POINT}
mount /dev/${PROD_VG}/${SNAP_NAME} ${MOUNT_POINT}
echo "[$(date)] Test ortamı hazır: ${MOUNT_POINT}"
else
echo "[$(date)] HATA: Snapshot alınamadı!"
exit 1
fi
Btrfs ile Snapshot: Modern Yaklaşım
Btrfs dosya sistemi, snapshot’ı birinci sınıf bir özellik olarak sunar. Fedora, openSUSE ve bazı modern Ubuntu kurulumlarında Btrfs yaygınlaşıyor. Btrfs snapshot’larının avantajı: neredeyse anlık ve başlangıçta sıfır ek disk alanı kullanır.
# Btrfs subvolume oluştur (önce varsa mevcut yapıyı gör)
btrfs subvolume list /
# Production uygulama subvolume'ünün snapshot'ını al
btrfs subvolume snapshot /app_production /app_test_20240115
# Salt okunur snapshot (daha güvenli test için)
btrfs subvolume snapshot -r /app_production /app_test_readonly
Test bittikten sonra temizlik:
# Test snapshot'ını sil
btrfs subvolume delete /app_test_20240115
# Tüm snapshot'ları listele
btrfs subvolume list / | grep snapshot
Btrfs’in harika bir özelliği de send/receive ile snapshot’ı başka bir sunucuya taşıyabilmeniz:
# Snapshot'ı başka sunucuya gönder
btrfs send /app_test_readonly | ssh testserver "btrfs receive /mnt/test_volume"
# Artımlı gönderim (daha verimli)
btrfs send -p /app_baseline /app_test_readonly | ssh testserver "btrfs receive /mnt/test_volume"
ZFS Snapshot: Kurumsal Güç
ZFS kullananlar için snapshot yönetimi son derece güçlü. FreeBSD, TrueNAS veya Ubuntu ZFS kurulumlarında bu yöntemi kullanabilirsiniz:
# ZFS pool ve dataset yapısını gör
zpool list
zfs list
# Dataset snapshot'ı al
zfs snapshot tank/production/app@test_baseline_20240115
# Tüm snapshot'ları listele
zfs list -t snapshot
# Snapshot'tan yeni dataset oluştur (test ortamı için)
zfs clone tank/production/app@test_baseline_20240115 tank/test/app_clone
# Clone'u mount et
zfs set mountpoint=/mnt/test_app tank/test/app_clone
ZFS’in güçlü yanlarından biri recursive snapshot, yani bir parent dataset ile tüm child’larını tek seferde yakalayabilirsiniz:
# Tüm alt dataset'lerle birlikte snapshot al
zfs snapshot -r tank/production@full_test_snapshot
# Hangi snapshot'ların ne kadar yer kapladığını gör
zfs list -t snapshot -o name,used,refer,creation
Vagrant ve Virtualbox ile Snapshot Yönetimi
Geliştirici makinelerinde veya küçük test ortamlarında Vagrant + VirtualBox kombinasyonu çok yaygın. Vagrant’ın snapshot desteği oldukça kullanışlı:
# Vagrant makinesini başlat
vagrant up
# Temel kurulum tamamlandıktan sonra snapshot al
vagrant snapshot save baseline_clean
# Test et, boz, mahvet...
# ...
# Temiz hale geri dön
vagrant snapshot restore baseline_clean
# Tüm snapshot'ları listele
vagrant snapshot list
# Belirli bir snapshot'ı sil
vagrant snapshot delete baseline_clean
Gerçek dünya senaryosu: Bir Ansible playbook geliştiriyorsunuz. Her playbook çalıştırmasında temiz bir ortamdan başlamak istiyorsunuz. Vagrant snapshot olmadan her seferinde vagrant destroy && vagrant up yapmak 5-10 dakika alır. Snapshot restore ise 30 saniye.
#!/bin/bash
# ansible_test_loop.sh
SNAPSHOT_NAME="pre_ansible_test"
# Eğer snapshot yoksa oluştur
vagrant snapshot list | grep -q ${SNAPSHOT_NAME} || vagrant snapshot save ${SNAPSHOT_NAME}
for playbook in playbooks/*.yml; do
echo "Test ediliyor: ${playbook}"
# Temiz ortama dön
vagrant snapshot restore ${SNAPSHOT_NAME}
# Playbook'u test et
vagrant ssh -- "cd /vagrant && ansible-playbook ${playbook}"
echo "Sonuç: $?"
done
QEMU/KVM ile VM Snapshot
Production ortamlarında KVM sanallaştırma kullanıyorsanız, virsh ile snapshot yönetimi yapabilirsiniz:
# VM snapshot al (VM çalışırken - live snapshot)
virsh snapshot-create-as --domain prod_webserver
--name "pre_update_20240115"
--description "Güncelleme öncesi temiz snapshot"
--live
# Snapshot listesini gör
virsh snapshot-list prod_webserver
# Snapshot detaylarını incele
virsh snapshot-info prod_webserver pre_update_20240115
# Test ortamı için snapshot'tan yeni VM oluşturma
# Önce disk imajını kopyala
cp /var/lib/libvirt/images/prod_webserver.qcow2
/var/lib/libvirt/images/test_webserver.qcow2
# qcow2 backing file ile linked clone oluştur (daha verimli)
qemu-img create -f qcow2
-b /var/lib/libvirt/images/prod_webserver.qcow2
/var/lib/libvirt/images/test_webserver_linked.qcow2
QEMU’nun backing file özelliği özellikle ilgi çekici. Test VM’i, orijinal imajın değişmeyen bloklarını okurken sadece farkları kendi dosyasına yazar. 50 GB’lık bir imajdan 10 tane test VM oluşturabilirsiniz ve başlangıçta toplam disk kullanımı 50 GB civarında kalır.
# Backing file zincirini kontrol et
qemu-img info /var/lib/libvirt/images/test_webserver_linked.qcow2
# Snapshot bilgilerini listele
qemu-img snapshot -l /var/lib/libvirt/images/prod_webserver.qcow2
Docker ile Hızlı Test Ortamı
Container dünyasında snapshot kavramı biraz farklı ama özü aynı. Docker image layer sistemi aslında bir snapshot mekanizmasıdır:
# Çalışan container'dan image oluştur (snapshot gibi)
docker commit running_app_container myapp:test_baseline
# Bu image'dan istediğiniz kadar test container'ı başlatın
docker run -d --name test_env_1 myapp:test_baseline
docker run -d --name test_env_2 myapp:test_baseline
docker run -d --name test_env_3 myapp:test_baseline
# Her birini bağımsız test edin
docker exec -it test_env_1 /bin/bash
Veritabanı test ortamları için özellikle şu pattern çok işe yarıyor:
# Seed verisiyle dolu bir PostgreSQL image hazırla
docker run -d --name pg_seed postgres:15
docker exec pg_seed psql -U postgres -c "CREATE DATABASE testdb;"
# ... veri yükle ...
# Bu anı kaydet
docker commit pg_seed postgres_with_testdata:v1
# Her test için temiz bir veritabanıyla başla
docker run -d --name pg_test_run1 postgres_with_testdata:v1
docker run -d --name pg_test_run2 postgres_with_testdata:v1
Snapshot Yönetiminde Dikkat Edilmesi Gerekenler
Snapshot birikmesi: En sık yapılan hata, snapshot’ları silmeden bırakmak. LVM’de snapshot alanı dolduğunda snapshot otomatik invalide olur ve bu durum production sistemleri etkileyebilir.
# Eski LVM snapshot'ları temizle
for snap in $(lvs --noheadings -o lv_name,lv_attr | grep 'sw' | awk '{print $1}'); do
echo "Eski snapshot siliniyor: $snap"
lvremove -f /dev/vg_production/${snap}
done
Uygulama tutarlılığı: Dosya sistemi tutarlı olabilir ama uygulama tutarlı olmayabilir. Veritabanı gibi uygulamalar için snapshot öncesi flush yapın:
# MySQL/MariaDB için snapshot öncesi flush
mysql -u root -p -e "FLUSH TABLES WITH READ LOCK;"
# Snapshot al
lvcreate -L 10G -s -n db_snap /dev/vg_prod/lv_mysql
# Kilidi aç
mysql -u root -p -e "UNLOCK TABLES;"
Snapshot ile backup karıştırmayın: Snapshot, backup değildir. Snapshot, kaynak volume ile aynı fiziksel diskte yaşar. Disk arızasında ikisi de gider. Snapshot hızlı test ortamı ve kısa vadeli kurtarma içindir, uzun vadeli yedek için ayrı bir sistem gerekir.
Otomatik Test Ortamı Pipeline’ı
Tüm bu bilgileri bir araya getirip CI/CD pipeline’ına entegre edelim:
#!/bin/bash
# create_test_env.sh - Tam otomatik test ortamı kurulum scripti
set -e
PROD_VG="vg_production"
PROD_LV="lv_app"
DATE_TAG=$(date +%Y%m%d_%H%M%S)
SNAP_NAME="snap_test_${DATE_TAG}"
SNAP_SIZE="15G"
TEST_MOUNT="/mnt/test_${DATE_TAG}"
LOG_FILE="/var/log/test_env_${DATE_TAG}.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a ${LOG_FILE}
}
cleanup() {
log "Temizlik yapılıyor..."
umount ${TEST_MOUNT} 2>/dev/null || true
lvremove -f /dev/${PROD_VG}/${SNAP_NAME} 2>/dev/null || true
rm -rf ${TEST_MOUNT}
log "Temizlik tamamlandı."
}
# Script bitince otomatik temizlik
trap cleanup EXIT
log "Test ortamı oluşturuluyor: ${SNAP_NAME}"
# Uygulama servisini durdur (tutarlılık için)
systemctl stop myapp 2>/dev/null || true
# Snapshot al
lvcreate -L ${SNAP_SIZE} -s -n ${SNAP_NAME} /dev/${PROD_VG}/${PROD_LV}
log "Snapshot alındı."
# Uygulamayı yeniden başlat
systemctl start myapp 2>/dev/null || true
# Mount et
mkdir -p ${TEST_MOUNT}
mount /dev/${PROD_VG}/${SNAP_NAME} ${TEST_MOUNT}
log "Test ortamı mount edildi: ${TEST_MOUNT}"
# Testleri çalıştır
log "Testler başlatılıyor..."
cd ${TEST_MOUNT}
# Burada test komutlarınız gelir
# ./run_tests.sh
# pytest tests/
# npm test
log "Testler tamamlandı."
# cleanup trap tetiklenecek
Bu scripti crontab’a veya Jenkins/GitLab CI pipeline’ına ekleyebilirsiniz. Her test koşusunda temiz, production benzeri bir ortam elde edersiniz.
Sonuç
Snapshot teknolojisi, test ortamı yönetimini kökten değiştiriyor. LVM, Btrfs, ZFS veya sanallaştırma katmanında snapshot alın, test edin, silin, tekrar alın. Saatlik kurulum süreleri dakikalara iniyor, “test ortamı production’dan farklı davrandı” şikayetleri ortadan kalkıyor.
Hangi teknolojiyi seçeceğiniz altyapınıza göre değişir. Bare metal Linux sunucularınız varsa LVM veya Btrfs, KVM/QEMU ortamındaysanız virsh snapshot veya qcow2 backing file, geliştirici ortamında Vagrant, container dünyasındaysanız Docker commit ile başlayabilirsiniz.
En önemli nokta: snapshot’ları biriktirmeyin, boyutlarını izleyin ve backup yerine geçmediğini unutmayın. Bu üç kurala uyduğunuzda snapshot, sysadmin hayatınızın vazgeçilmez araçlarından biri haline gelir.
