AWS RDS Multi-AZ ile Yüksek Erişilebilirlik Nasıl Sağlanır?
Prodüksiyonda bir veritabanı sunucusu çöktüğünde ne olur? Eğer yeterince hazırlıklı değilseniz, gecenin üçünde telefon çalar, ekip toplanır, saatler içinde veri kaybı ve gelir kaybı yaşanır. AWS RDS Multi-AZ tam olarak bu senaryoyu önlemek için tasarlanmış bir yapıdır. Ama “Multi-AZ açtım, oldu bitti” demek yeterli değil. Doğru yapılandırma, izleme ve failover testleri olmadan Multi-AZ size sadece yanlış bir güven hissi verir.
Bu yazıda RDS Multi-AZ’ı sadece teoride değil, gerçek prodüksiyon ortamlarında nasıl yapılandırıldığını, nasıl test edildiğini ve olası sorunların nasıl giderildiğini ele alacağız.
RDS Multi-AZ Nedir ve Nasıl Çalışır?
AWS RDS Multi-AZ, birincil (primary) veritabanı instance’ınızın farklı bir Availability Zone’da senkron olarak çoğaltılmış bir standby kopyasını tutar. Bu standby instance sadece failover için vardır, okuma trafiğini üstlenmez. Bu noktayı kafanıza kazıyın çünkü çok sık karıştırılıyor: Multi-AZ yüksek erişilebilirlik içindir, okuma ölçeklendirmesi için değildir.
MySQL, MariaDB, PostgreSQL ve Oracle için Multi-AZ, Amazon’un kendi replikasyon mekanizmasını kullanır. SQL Server ise Database Mirroring veya Always On Availability Groups kullanır. Replikasyon senkrondur, yani bir yazma işlemi hem primary’ye hem standby’a yazılmadan tamamlanmış sayılmaz. Bu sayede RPO (Recovery Point Objective) sıfıra yakındır.
Failover süreci otomatiktir. AWS, primary instance’ın erişilemez olduğunu tespit ettiğinde (genellikle 60-120 saniye içinde) DNS kaydını standby instance’ın endpoint’ine yönlendirir. Uygulamanız aynı endpoint’i kullandığı sürece yeniden bağlantı açtığında yeni instance’a ulaşır.
Temel Kavramlar: Endpoint Yönetimi
Burada kritik bir nokta var. RDS Multi-AZ yapısında uygulamanız her zaman cluster endpoint’ini veya instance endpoint’ini kullanmalıdır, IP adresini değil. Failover sonrası IP değişir, DNS değişmez.
Bir RDS instance oluşturalım ve endpoint bilgisini çekelim:
# RDS instance oluşturma (Multi-AZ aktif)
aws rds create-db-instance
--db-instance-identifier prod-mysql-primary
--db-instance-class db.r6g.large
--engine mysql
--engine-version 8.0.35
--master-username admin
--master-user-password "G3rcekSifre!2024"
--allocated-storage 100
--storage-type gp3
--multi-az
--vpc-security-group-ids sg-0abc123def456789
--db-subnet-group-name prod-db-subnet-group
--backup-retention-period 7
--deletion-protection
--region eu-west-1
Instance oluştuktan sonra endpoint bilgisini çekelim:
# Endpoint ve durum bilgisini al
aws rds describe-db-instances
--db-instance-identifier prod-mysql-primary
--query 'DBInstances[0].{Endpoint:Endpoint.Address,Port:Endpoint.Port,AZ:AvailabilityZone,SecondaryAZ:SecondaryAvailabilityZone,MultiAZ:MultiAZ,Status:DBInstanceStatus}'
--output json
Bu komutun çıktısında SecondaryAvailabilityZone alanı standby’ın hangi AZ’de olduğunu gösterir. Primary ve secondary’nin farklı AZ’lerde olduğunu doğrulamak, temel bir sağlık kontrolüdür.
Subnet Group ve Network Yapılandırması
Multi-AZ çalışabilmesi için en az iki farklı AZ’de subnet’iniz olması gerekir. Prodüksiyonda genellikle üç AZ kullanırız çünkü AWS bir AZ’yi bakım için geçici olarak devre dışı bırakabilir.
# DB Subnet Group oluşturma
aws rds create-db-subnet-group
--db-subnet-group-name prod-db-subnet-group
--db-subnet-group-description "Production DB Subnet Group - Multi-AZ"
--subnet-ids subnet-0111aaa eu-west-1a subnet-0222bbb eu-west-1b subnet-0333ccc eu-west-1c
# Subnet group detaylarını kontrol et
aws rds describe-db-subnet-groups
--db-subnet-group-name prod-db-subnet-group
--query 'DBSubnetGroups[0].Subnets[*].{SubnetID:SubnetIdentifier,AZ:SubnetAvailabilityZone.Name,Status:SubnetStatus}'
Security group tarafında da dikkatli olmanız gerekiyor. Uygulama sunucularınızın bulunduğu security group’tan database port’una erişim açık olmalı, ancak dışarıya kapalı tutulmalı. Bu basit görünüyor ama prodüksiyonda sıkça atlanan bir detay.
Parametre Grupları ve Optimizasyon
Varsayılan parametre grubu ile Multi-AZ çalışır ama prodüksiyon ortamı için özelleştirilmiş parametreler şart. Özellikle replikasyon gecikmesini etkileyen parametrelere dikkat etmek gerekiyor.
# Özel parametre grubu oluştur
aws rds create-db-parameter-group
--db-parameter-group-name prod-mysql8-params
--db-parameter-group-family mysql8.0
--description "Production MySQL 8.0 Parameters"
# Kritik parametreleri ayarla
aws rds modify-db-parameter-group
--db-parameter-group-name prod-mysql8-params
--parameters
"ParameterName=innodb_flush_log_at_trx_commit,ParameterValue=1,ApplyMethod=immediate"
"ParameterName=sync_binlog,ParameterValue=1,ApplyMethod=immediate"
"ParameterName=innodb_buffer_pool_size,ParameterValue={DBInstanceClassMemory*3/4},ApplyMethod=pending-reboot"
"ParameterName=max_connections,ParameterValue=500,ApplyMethod=pending-reboot"
"ParameterName=slow_query_log,ParameterValue=1,ApplyMethod=immediate"
"ParameterName=long_query_time,ParameterValue=2,ApplyMethod=immediate"
Burada innodb_flush_log_at_trx_commit=1 ve sync_binlog=1 ayarları kritik. Bu ikisi performansı biraz düşürür ama veri bütünlüğünü garanti altına alır. Multi-AZ’de bu değerleri 0 yaparsanız failover durumunda veri kaybı riski artar.
Failover Testi: “Fire Drill”
Prodüksiyonda failover testini hiç yapmadan “Multi-AZ çalışıyordur” demek tehlikeli. Ayda bir ya da en azından her büyük deployment öncesinde failover testi yapılmalı. Bunu otomatikleştirdiğimiz bir script:
#!/bin/bash
# failover-test.sh - RDS Multi-AZ Failover Test Script
DB_INSTANCE="prod-mysql-primary"
REGION="eu-west-1"
LOG_FILE="/var/log/rds-failover-test-$(date +%Y%m%d-%H%M%S).log"
echo "Failover testi başlıyor: $(date)" | tee -a $LOG_FILE
# Mevcut AZ bilgisini kaydet
CURRENT_AZ=$(aws rds describe-db-instances
--db-instance-identifier $DB_INSTANCE
--region $REGION
--query 'DBInstances[0].AvailabilityZone'
--output text)
echo "Primary AZ (önce): $CURRENT_AZ" | tee -a $LOG_FILE
# Failover başlat ve süreyi ölç
START_TIME=$(date +%s)
aws rds reboot-db-instance
--db-instance-identifier $DB_INSTANCE
--force-failover
--region $REGION
echo "Failover komutu gönderildi. Instance hazır olana kadar bekleniyor..." | tee -a $LOG_FILE
# Instance available durumuna gelene kadar bekle
aws rds wait db-instance-available
--db-instance-identifier $DB_INSTANCE
--region $REGION
END_TIME=$(date +%s)
FAILOVER_DURATION=$((END_TIME - START_TIME))
# Yeni AZ bilgisini al
NEW_AZ=$(aws rds describe-db-instances
--db-instance-identifier $DB_INSTANCE
--region $REGION
--query 'DBInstances[0].AvailabilityZone'
--output text)
echo "Primary AZ (sonra): $NEW_AZ" | tee -a $LOG_FILE
echo "Failover süresi: $FAILOVER_DURATION saniye" | tee -a $LOG_FILE
if [ "$CURRENT_AZ" != "$NEW_AZ" ]; then
echo "BAŞARILI: Failover tamamlandı, AZ değişti." | tee -a $LOG_FILE
else
echo "UYARI: AZ değişmedi, failover beklenen şekilde gerçekleşmemiş olabilir." | tee -a $LOG_FILE
fi
Bu testi yaparken uygulama tarafında bağlantı kesilmesini de izleyin. Failover süresi ne kadar oldu, kaç istek hata aldı, connection pool ne kadar sürede toparlandı bunları kayıt altına alın. Gerçek bir kriz anında bu veriler paha biçilmez.
CloudWatch ile İzleme
Multi-AZ izleme için CloudWatch’u doğru yapılandırmak şart. Sadece CPU ve disk değil, replikasyona özgü metriklere de alarm kurmanız gerekiyor.
# Replikasyon gecikmesi için alarm
aws cloudwatch put-metric-alarm
--alarm-name "RDS-MultiAZ-ReplicaLag-High"
--alarm-description "RDS Multi-AZ replikasyon gecikmesi çok yüksek"
--metric-name ReplicaLag
--namespace AWS/RDS
--dimensions Name=DBInstanceIdentifier,Value=prod-mysql-primary
--statistic Maximum
--period 60
--evaluation-periods 3
--threshold 30
--comparison-operator GreaterThanThreshold
--alarm-actions arn:aws:sns:eu-west-1:123456789:prod-alerts
--ok-actions arn:aws:sns:eu-west-1:123456789:prod-alerts
--region eu-west-1
# Burst balance düşüşü için alarm (gp2 storage kullananlar için kritik)
aws cloudwatch put-metric-alarm
--alarm-name "RDS-BurstBalance-Low"
--alarm-description "RDS storage burst balance kritik seviyede"
--metric-name BurstBalance
--namespace AWS/RDS
--dimensions Name=DBInstanceIdentifier,Value=prod-mysql-primary
--statistic Minimum
--period 300
--evaluation-periods 2
--threshold 20
--comparison-operator LessThanThreshold
--alarm-actions arn:aws:sns:eu-west-1:123456789:prod-alerts
--region eu-west-1
Gp3 storage kullanıyorsanız burst balance endişeniz yok, ama gp2’de bu alarm hayat kurtarıcı. Burst balance sıfırlanınca disk I/O yerle bir oluyor ve bu durum replikasyon gecikmesini tetikliyor.
İzlenmesi gereken temel metrikler şunlardır:
- DatabaseConnections: Bağlantı sayısı max_connections’a yaklaşıyor mu?
- FreeStorageSpace: Disk dolmadan önce aksiyon alın
- ReadIOPS / WriteIOPS: Beklenmedik I/O spike’ları replikasyonu etkiler
- CPUCreditBalance: T3/T4 instance kullanıyorsanız
- ReplicaLag: Senkron replikasyonda normalde 0 olmalı
Uygulama Tarafı: Connection Pool Yapılandırması
Failover sırasında en çok sorun yaşadığımız yer uygulama tarafındaki connection pool yapılandırması. DNS TTL değişse bile uygulamanız eski IP’yi önbellekte tutuyorsa failover’dan haberi olmaz.
Java Spring Boot uygulaması için örnek bir HikariCP yapılandırması:
# application.properties veya environment variable olarak
spring.datasource.url=jdbc:mysql://prod-mysql-primary.cluster-xyz.eu-west-1.rds.amazonaws.com:3306/mydb?useSSL=true&requireSSL=true&connectTimeout=3000&socketTimeout=30000
# Connection pool ayarları
spring.datasource.hikari.connection-timeout=3000
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.max-lifetime=900000
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
# Kritik: Failover sonrası eski bağlantıları tespit et
spring.datasource.hikari.keepalive-time=60000
spring.datasource.hikari.connection-test-query=SELECT 1
Python uygulamaları için de benzer bir dikkat gerekiyor. max_lifetime ve pool_pre_ping ayarlarını mutlaka açın:
# Python SQLAlchemy için environment variable
DATABASE_URL="mysql+pymysql://admin:[email protected]:3306/mydb"
DB_POOL_SIZE=10
DB_MAX_OVERFLOW=20
DB_POOL_TIMEOUT=30
DB_POOL_RECYCLE=300
DB_POOL_PRE_PING=true
pool_pre_ping=True veya HikariCP’de keepalive-time olmadan failover sonrası uygulamanız “dead” bağlantılara yazı yazar ve timeout bekler. Bu, failover sürenizi 60 saniyeden 5 dakikaya çıkarabilir.
Enhanced Monitoring ve Performance Insights
Standard CloudWatch metrikleri instance seviyesinde çalışır, işletim sistemi seviyesinde değil. Enhanced Monitoring ile OS metrikleri de izlenebilir. Bunu açmadan prodüksiyon kurmayın:
# Enhanced Monitoring ile instance güncelle
aws rds modify-db-instance
--db-instance-identifier prod-mysql-primary
--monitoring-interval 15
--monitoring-role-arn arn:aws:iam::123456789:role/rds-monitoring-role
--enable-performance-insights
--performance-insights-retention-period 7
--apply-immediately
# Performance Insights için IAM rolü oluştur (eğer yoksa)
aws iam create-role
--role-name rds-monitoring-role
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "monitoring.rds.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}'
aws iam attach-role-policy
--role-name rds-monitoring-role
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole
Performance Insights, özellikle failover sonrasında neden yavaşlama yaşandığını anlamak için çok değerli. “Top SQL” bölümünde failover anında yeniden bağlanan sorguların pile-up’ını net görebilirsiniz.
Gerçek Dünya Senaryosu: Plansız Failover Yönetimi
Geçen yıl bir müşteri projesinde eu-west-1a AZ’sinde beklenmedik bir hardware arızası yaşandı. RDS otomatik failover başlattı. İşte o anda olanlar ve nasıl tepki verdik:
İlk 0-30 saniye: CloudWatch “RDS Failover” eventi geldi. SNS bildirimi ekibi uyardı. Uygulamada connection error’ları başladı.
30-90 saniye arası: DNS yayıldı, connection pool’lar yeniden bağlantı denemeye başladı. Doğru yapılandırılmış servisler otomatik toparlandı.
90 saniye sonra: Yanlış yapılandırılmış bir legacy servis manuel restart gerektirdi. Bu servisin connection pool’unda pool_pre_ping yoktu ve max_lifetime çok uzun ayarlıydı.
Bu deneyimden sonra oluşturduğumuz acil durum checklist’i:
#!/bin/bash
# rds-failover-check.sh - Failover sonrası hızlı kontrol
DB_INSTANCE="prod-mysql-primary"
REGION="eu-west-1"
echo "=== RDS Failover Kontrol Listesi ==="
echo "Zaman: $(date)"
# 1. Instance durumu
echo -e "n[1] Instance Durumu:"
aws rds describe-db-instances
--db-instance-identifier $DB_INSTANCE
--region $REGION
--query 'DBInstances[0].{Status:DBInstanceStatus,AZ:AvailabilityZone,SecondaryAZ:SecondaryAvailabilityZone,MultiAZ:MultiAZ}'
# 2. Son event'leri göster
echo -e "n[2] Son RDS Events (Son 1 saat):"
aws rds describe-events
--source-identifier $DB_INSTANCE
--source-type db-instance
--duration 60
--region $REGION
--query 'Events[*].{Zaman:Date,Mesaj:Message}'
# 3. Endpoint değişti mi?
echo -e "n[3] Mevcut Endpoint:"
aws rds describe-db-instances
--db-instance-identifier $DB_INSTANCE
--region $REGION
--query 'DBInstances[0].Endpoint.{Address:Address,Port:Port}'
# 4. CloudWatch'tan son 5 dakika replikasyon lagı
echo -e "n[4] Replikasyon Durumu (son 5 dk):"
aws cloudwatch get-metric-statistics
--namespace AWS/RDS
--metric-name ReplicaLag
--dimensions Name=DBInstanceIdentifier,Value=$DB_INSTANCE
--start-time $(date -u -d '5 minutes ago' +%Y-%m-%dT%H:%M:%SZ)
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ)
--period 60
--statistics Maximum
--region $REGION
Backup ve Maintenance Window Stratejisi
Multi-AZ’de otomatik backup, standby instance üzerinden alınır. Bu sayede primary instance’da I/O artışı olmaz. Ama backup window’u yanlış ayarlarsanız peak saatlerinize denk gelebilir.
Maintenance window’u da dikkatli seçin. Patch uygulaması sırasında RDS bir failover yapar, bu beklenen bir durum. Ama bunu cuma akşamı saat 22:00’de değil, trafik en düşük olduğu perşembe sabahı 03:00-05:00 arasında yapın.
# Maintenance ve backup window güncelle
aws rds modify-db-instance
--db-instance-identifier prod-mysql-primary
--backup-window "02:00-03:00"
--maintenance-window "thu:03:00-thu:05:00"
--backup-retention-period 14
--apply-immediately false
--apply-immediately false kullanın, aksi takdirde değişiklik hemen uygulanabilir ve plansız bir restart yaşarsınız.
Multi-AZ vs Multi-AZ Cluster
AWS, 2022’de Multi-AZ Cluster özelliğini duyurdu. Klasik Multi-AZ’den farklı olarak bu yapıda iki readable standby instance var. MySQL 8.0.28+ ve PostgreSQL 13.4+ destekliyor.
Klasik Multi-AZ’den farkları:
- Yazma gecikmesi: Multi-AZ Cluster’da lokal SSD ve senkron replikasyon sayesinde yazma gecikmesi daha düşük
- Failover süresi: Cluster yapısında 35 saniyenin altına inebiliyor
- Readable standby: İki standby instance okuma trafiği alabilir, böylece hem HA hem de okuma ölçeklendirmesi sağlanır
- Maliyet: Klasik Multi-AZ’den daha pahalı
Eğer okuma ağırlıklı yüküz varsa ve failover süresini minimize etmek istiyorsanız Multi-AZ Cluster ciddi bir alternatif.
Maliyet Optimizasyonu
Multi-AZ aktif edilince maliyetiniz yaklaşık iki katına çıkar. Bu korkutucu ama prodüksiyon için kaçınılmaz. Maliyeti optimize etmenin birkaç yolu:
- Storage tipi: Gp2 yerine gp3 kullanın. Gp3 hem daha ucuz hem daha performanslı
- Reserved Instance: 1 veya 3 yıllık RI alarak %30-60 tasarruf edebilirsiniz
- Instance boyutu: Dev/test ortamlarında Multi-AZ’ye gerek yok, sadece prodüksiyon için açın
- Snapshot frekansı: 7 günlük retention yeterlidir, 35 güne çıkarmak gereksiz maliyet
# Mevcut instance storage tipini gp3'e çevir (downtime yok)
aws rds modify-db-instance
--db-instance-identifier prod-mysql-primary
--storage-type gp3
--iops 3000
--storage-throughput 125
--apply-immediately false
Gp3’e geçiş downtime gerektirmez, arka planda yapılır. Ama büyük instance’larda bu işlem saatler sürebilir. Apply-immediately false ile maintenance window’a bırakın.
Sonuç
RDS Multi-AZ, doğru yapılandırıldığında veritabanı katmanınızda çok güçlü bir koruma sağlar. Ama bu “kur ve unut” bir özellik değil. Düzenli failover testleri, uygulama tarafında doğru connection pool ayarları, CloudWatch alarmları ve maintenance window optimizasyonu olmadan Multi-AZ sadece size kağıt üzerinde güven verir.
Prodüksiyona aldığınız her RDS instance için şu üç soruyu kendinize sorun: Failover testi yaptım mı? Uygulama otomatik reconnect ediyor mu? Replikasyon durumunu izliyor muyum? Bu üç soruya “evet” diyebiliyorsanız, gece telefon çaldığında daha rahat uyuyabilirsiniz.
Multi-AZ bir başlangıç noktasıdır. Buna ek olarak okuma replikaları, Aurora Global Database veya cross-region replikasyon gibi ileri seviye yapılarla DR (Disaster Recovery) stratejinizi de güçlendirmeyi düşünün. Veritabanı, her sistemin kalbidir, ona göre muamele edin.
