Sunucu Yedekleme Stratejisi: 3-2-1 Kuralı ve Betikler
Sunucu yedekleme stratejisi, verinin en az 3 kopyasını, 2 farklı ortamda ve 1 tanesini farklı bir lokasyonda tutmak (3-2-1 kuralı) ve bu kopyaların gerçekten geri yüklenebildiğini düzenli test etmektir. Snapshot tek başına yedek değildir; hızlı bir geri dönüş noktasıdır. Gerçek yedek ise sunucudan bağımsız bir yerde duran, sürümlenmiş ve test edilmiş kopyadır.
Bu rehberde kuralı sahada nasıl uygulayacağınızı, snapshot ile yedeğin farkını, çalışan MySQL ve dosya yedekleme betiklerini, uzak yedek kurulumunu ve geri dönüş testini sırayla ele alıyoruz.
3-2-1 Kuralı Pratikte Ne Demek?
- 3 kopya: Canlı veri + en az 2 yedek.
- 2 ortam: Aynı diskte değil; örneğin sunucunun yerel diski ve ayrı bir yedek sunucusu veya nesne depolama.
- 1 uzak kopya: Farklı bir veri merkezinde, mümkünse farklı bir ağda. Yangın, güç kesintisi, hatalı bir hypervisor işlemi veya hesabınızın ele geçirilmesi her iki kopyayı birden etkilememeli.
Fidye yazılımı çağında genişletilmiş hali de kullanılır: 3-2-1-1-0. Ek "1", değiştirilemez (immutable) veya yalnızca eklemeli (append-only) bir kopya; "0" ise geri yükleme testinde sıfır hata demektir.
Başlamadan önce iki rakamı belirleyin:
- RPO (Recovery Point Objective): En fazla ne kadar veri kaybını göze alabilirsiniz? (Örn. 24 saat, 1 saat)
- RTO (Recovery Time Objective): Sistem ne kadar sürede geri gelmeli?
Günlük yedek, RPO'su 1 saat olan bir e-ticaret veritabanı için yetersizdir. Bu iki değer sıklığı ve yöntemi belirler.
Snapshot ile Yedek Arasındaki Fark
VMware vSphere gibi sanallaştırma katmanlarında snapshot, VM'in o anki durumunu delta diskler ile işaretler. Çok hızlıdır, ama yedek değildir.
| Özellik | Snapshot | Yedek (backup) |
|---|---|---|
| Depolama yeri | Genellikle VM ile aynı datastore | Ayrı sunucu / ayrı lokasyon |
| Ana diske bağımlılık | Var (delta zinciri) | Yok, bağımsız geri yüklenir |
| Disk arızasında | Birlikte kaybolur | Korunur |
| Uzun süre tutma | Önerilmez, performansı düşürür | Amaç budur |
| En iyi kullanım | Güncelleme/değişiklik öncesi hızlı geri dönüş | Felaket kurtarma, silinen veriyi geri alma |
Pratik kural: Büyük bir güncelleme veya kernel/panel değişikliği öncesi snapshot alın, işlem doğrulanınca silin. Snapshot'ı günlerce tutmayın. Tutarlılık da önemlidir: çalışan bir veritabanının snapshot'ı "crash-consistent" olabilir; veritabanı için mutlaka mantıksal döküm (dump) veya uygulama farkındalıklı yedek alın.
Ne Yedeklenmeli?
Tüm diski yedeklemek yerine yeniden kuramayacağınız şeyleri yedekleyin:
- Veritabanları (MySQL/MariaDB, PostgreSQL)
- Web içeriği ve yüklemeler (
/var/www,/home) - Yapılandırma dosyaları (
/etc, nginx/Apache vhost'ları, cron, systemd unit'leri) - SSL anahtarları, SSH anahtarları,
.envdosyaları - Paket listesi (
dpkg --get-selectionsveyarpm -qa)
İşletim sistemi dosyalarını yedeklemek gerekmez; yeniden kurulum genelde daha hızlıdır. Tam sistem imajı ihtiyacınız varsa bunu ayrıca, düşük sıklıkla alın.
MySQL/MariaDB Yedekleme Betiği
Önce parolayı betiğe yazmamak için /root/.my.cnf oluşturun:
[client]
user=backup
password=GucluBirParola
chmod 600 /root/.my.cnf
Yedek kullanıcısına gereken asgari yetkileri verin:
CREATE USER 'backup'@'localhost' IDENTIFIED BY 'GucluBirParola';
GRANT SELECT, SHOW VIEW, TRIGGER, EVENT, LOCK TABLES, RELOAD, PROCESS ON *.* TO 'backup'@'localhost';
Betik (/usr/local/sbin/mysql-backup.sh):
#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR=/var/backups/mysql
KEEP_DAYS=7
STAMP=$(date +%Y%m%d-%H%M%S)
umask 077
mkdir -p "$BACKUP_DIR"
DBS=$(mysql -N -e "SHOW DATABASES" | grep -Ev '^(information_schema|performance_schema|sys)$')
for db in $DBS; do
OUT="$BACKUP_DIR/${db}-${STAMP}.sql.gz"
mysqldump --single-transaction --quick --routines --triggers --events "$db" \
| gzip -9 > "${OUT}.tmp"
gzip -t "${OUT}.tmp"
mv "${OUT}.tmp" "$OUT"
done
find "$BACKUP_DIR" -name '*.sql.gz' -mtime +"$KEEP_DAYS" -delete
Önemli noktalar:
--single-transaction, InnoDB tablolarını kilitlemeden tutarlı döküm alır. MyISAM tabloları varsa bu bayrak yeterli olmaz.set -o pipefail,mysqldumphata verirse betiğin başarısız olmasını sağlar; aksi halde boş bir gzip "başarılı" görünür..tmpdosyası,gzip -tkontrolünden sonra yeniden adlandırılır; yarım kalan yedek saklanmaz.- MariaDB'nin yeni sürümlerinde
mariadb-dumpkomutu da kullanılabilir, parametreler aynıdır.
Zamanlama için cron ve flock ile çakışmayı önleyin:
chmod 750 /usr/local/sbin/mysql-backup.sh
echo '15 3 * * * root flock -n /run/mysql-backup.lock /usr/local/sbin/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1' > /etc/cron.d/mysql-backup
RPO'nuz saatlik ise mysqldump yerine binary log (PITR) veya Percona XtraBackup/mariabackup gibi fiziksel yedek araçlarını değerlendirin.
Dosya Yedekleme: restic ile Şifreli, Sürümlü Yedek
rsync basit ve yeterli olabilir ama sürümleme, şifreleme ve tekilleştirme istiyorsanız restic pratik bir seçenektir. Debian/Ubuntu'da:
apt install restic
Yedek sunucusunda (örnek adres 192.0.2.10) bir kullanıcı açın, istemciden anahtar tabanlı SSH girişi tanımlayın ve depoyu başlatın:
echo 'DepoParolasiniBuraya' > /root/.restic-pass && chmod 600 /root/.restic-pass
export RESTIC_REPOSITORY="sftp:backup@192.0.2.10:/srv/restic/web01"
export RESTIC_PASSWORD_FILE=/root/.restic-pass
restic init
Yedek betiği (/usr/local/sbin/files-backup.sh):
#!/usr/bin/env bash
set -euo pipefail
export RESTIC_REPOSITORY="sftp:backup@192.0.2.10:/srv/restic/web01"
export RESTIC_PASSWORD_FILE=/root/.restic-pass
/usr/local/sbin/mysql-backup.sh
restic backup /etc /var/www /home /var/backups/mysql --exclude-caches
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6
Veritabanı dökümünü önce alıp aynı oturumda dosya yedeğine dahil etmek, uzak kopyanın da güncel olmasını sağlar. Not: Parola dosyasını da sunucudan bağımsız bir yerde (parola yöneticisi, çıktı) saklayın; depo parolası kaybolursa yedek açılamaz.
Uzak Yedek: Doğru Yapılandırma
Uzak yedeğin amacı, sunucu ele geçirilse bile yedeğin silinememesidir. Bunun için:
- Ayrı lokasyon ve ayrı kimlik bilgileri: Üretim sunucusunun root parolası yedek sunucusunda geçerli olmasın.
- Kısıtlı SSH anahtarı: Yedek kullanıcısının
authorized_keyssatırındarestrictseçeneğini kullanın ve mümkünse komutu sınırlayın. - Append-only mod: restic için
rest-server --append-onlygibi bir yapı, istemcinin eski snapshot'ları silmesini engeller. Eski sürümlerin temizliği (forget --prune) yedek sunucusu tarafında, kendi yetkinizle çalışır. - Şifreleme: Veri yedek sunucusuna gitmeden önce şifrelenmiş olmalı (restic bunu varsayılan yapar).
- Bant genişliği: Büyük ilk yedekten sonra artımlı yedekler küçüktür; yine de gerekirse
--limit-uploadkullanın.
Yedek hedefini farklı bir lokasyonda tutmak için ayrı bir fiziksel sunucu kiralama seçeneği veya üretim sunucunuzdan farklı bir ağda konumlanmış ikinci bir VDS kullanılabilir. Önemli olan, yedeğin üretimle aynı arıza alanında olmamasıdır.
Geri Dönüş Testi: Yedeğin Asıl Sınavı
Test edilmemiş yedek, yalnızca bir umuttur. Ayda bir (kritik sistemlerde haftada bir) şu adımları uygulayın:
1. Depo bütünlüğü:
restic snapshots
restic check --read-data-subset=10%
2. Dosya geri yükleme (üretimi ezmeden, geçici dizine):
restic restore latest --target /tmp/restore-test --include /etc/nginx
diff -r /etc/nginx /tmp/restore-test/etc/nginx
3. Veritabanı geri yükleme (ayrı test veritabanına):
mysql -e "CREATE DATABASE restore_test"
gunzip -c /tmp/restore-test/var/backups/mysql/ornekdb-20250101-031500.sql.gz | mysql restore_test
mysql -e "SELECT COUNT(*) FROM restore_test.siparisler"
Satır sayısını ve son kayıt tarihini canlı veriyle kıyaslayın.
4. Süreyi ölçün: Geri yüklemenin kaç dakika sürdüğünü yazın. Bu, gerçek RTO'nuzdur.
5. Yedek izleme: Betik başarısız olursa e-posta/monitoring uyarısı gelsin. Basit bir yöntem, başarılı bitişte bir "heartbeat" URL'sine istek atmak veya log dosyasının son değiştirilme zamanını izlemektir.
Sık Yapılan Hatalar ve Çözümleri
- Yedek aynı diskte: Disk arızasında hepsi gider. Çözüm: ikinci ortam ve uzak kopya.
- Parola betik içinde, dosya herkese açık:
chmod 600ve.my.cnfkullanın. mysqldumphata verdi ama betik "başarılı" dedi:set -euo pipefailvegzip -tekleyin.- Yalnızca snapshot'a güvenmek: Snapshot'ı yedek saymayın; datastore sorununda ikisi birlikte kaybolur.
- Geri yükleme hiç denenmedi: Takvime tekrarlayan bir test görevi ekleyin.
- Retention (saklama süresi) yok: Disk dolar, yedekler sessizce durur.
find -mtimeveyarestic forgetkullanın. - Şifreleme anahtarı/parolası sadece sunucuda: Sunucu giderse yedek de kullanılamaz. Parolayı ayrıca saklayın.
Özet Kontrol Listesi
- RPO ve RTO'yu belirleyin.
- Veritabanı için tutarlı döküm, dosyalar için sürümlü yedek alın.
- 3-2-1: üç kopya, iki ortam, bir uzak lokasyon.
- Uzak yedeği append-only veya kısıtlı yetkiyle koruyun.
- Başarısızlıkları izleyin.
- Geri yüklemeyi düzenli test edip süresini kaydedin.
Üretim iş yüklerinizi BGP destekli VDS sunucularda çalıştırıyorsanız, yedek planınızı da sunucuyla birlikte tasarlayın; ağ ve lokasyon seçimi yedeğin gerçekten bağımsız olup olmadığını belirler.
Sık sorulan sorular
Snapshot yedek yerine geçer mi?
Hayır. Snapshot genellikle VM ile aynı depolama üzerinde tutulur ve ana diske bağımlıdır. Depolama arızasında veya silinmede birlikte kaybolur. Snapshot'ı değişiklik öncesi hızlı geri dönüş için, yedeği ise felaket kurtarma için kullanın.
3-2-1 yedekleme kuralı nedir?
Verinin en az 3 kopyasını, 2 farklı depolama ortamında tutmak ve bunlardan 1'ini farklı bir lokasyonda saklamaktır. Böylece tek bir arıza, hata veya saldırı tüm kopyaları etkileyemez.
MySQL yedeği için mysqldump yeterli mi?
Küçük ve orta ölçekli, InnoDB ağırlıklı veritabanlarında --single-transaction ile mysqldump yeterlidir. Çok büyük veritabanlarında veya saatlik RPO gerektiğinde binary log ile noktaya geri dönüş ya da mariabackup/XtraBackup gibi fiziksel yedek araçları daha uygundur.
Geri dönüş testi ne sıklıkla yapılmalı?
Kritik sistemlerde haftalık, diğerlerinde en az aylık. Her testte yedeği üretimi ezmeden ayrı bir dizine veya test veritabanına geri yükleyin, verinin doğruluğunu kontrol edin ve geri yükleme süresini not edin.