PostgreSQL HA Cluster Test Scripti: Kapsamlı Analiz ve Kullanım Kılavuzu

Giriş
PostgreSQL High Availability (HA) cluster’ları, kritik uygulamalar için kesintisiz veritabanı hizmeti sağlamak amacıyla tasarlanır. Bu tür sistemlerin doğru çalışıp çalışmadığını test etmek, sistem yöneticileri için hayati önem taşır. Bu makalede, PostgreSQL HA cluster’ını kapsamlı bir şekilde test eden profesyonel bir bash scripti analiz edilecek ve kullanım detayları açıklanacaktır.
Sistem Mimarisi
Test scripti, aşağıdaki bileşenlerden oluşan bir HA cluster’ı hedefler:
- 3 PostgreSQL Node: postgresql0, postgresql1, postgresql2
- Patroni: PostgreSQL cluster yönetimi için
- etcd: Cluster koordinasyonu için
- HAProxy: Load balancer ve connection pooling
Test Script Analizi
Script Başlığı ve Genel Yapı
#!/bin/bash
# PostgreSQL HA Cluster Test Script
# Bu script PostgreSQL HA cluster'ının düzgün çalışıp çalışmadığını test eder
set -e
# Renk kodları
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
NC='\033[0m' # No Color
Script, bash’in strict mode’unda çalışır (set -e
) ve herhangi bir komutun başarısız olması durumunda durur. Renkli output için ANSI renk kodları tanımlanmıştır.
Konfigürasyon Parametreleri
# Bağlantı bilgileri
HAPROXY_IP="192.168.99.52"
HAPROXY_PORT="5000"
POSTGRES_USER="postgres"
POSTGRES_PASSWORD="postgres123"
DATABASE="postgres"
# Node IP'leri
NODE1_IP="192.168.99.50"
NODE2_IP="192.168.99.51"
NODE3_IP="192.168.99.52"
Bu bölümde cluster’ın temel bağlantı bilgileri tanımlanır. HAProxy’nin 3. node üzerinde çalıştığı görülmektedir.
Yardımcı Fonksiyonlar
# Test sayacı
TEST_COUNT=0
PASS_COUNT=0
FAIL_COUNT=0
# Log fonksiyonları
log() {
echo -e "${GREEN}[$(date +'%H:%M:%S')] ✓ $1${NC}"
}
warn() {
echo -e "${YELLOW}[$(date +'%H:%M:%S')] ⚠ $1${NC}"
}
error() {
echo -e "${RED}[$(date +'%H:%M:%S')] ✗ $1${NC}"
}
info() {
echo -e "${BLUE}[$(date +'%H:%M:%S')] ℹ $1${NC}"
}
header() {
echo
echo -e "${PURPLE}================================================${NC}"
echo -e "${PURPLE} $1${NC}"
echo -e "${PURPLE}================================================${NC}"
}
Bu fonksiyonlar, test sonuçlarının renkli ve zaman damgalı olarak gösterilmesini sağlar. Test istatistikleri de bu bölümde takip edilir.
Ana Test Fonksiyonu
# Test fonksiyonu
run_test() {
local test_name="$1"
local test_command="$2"
TEST_COUNT=$((TEST_COUNT + 1))
info "Test $TEST_COUNT: $test_name"
if eval "$test_command" >/dev/null 2>&1; then
log "PASS: $test_name"
PASS_COUNT=$((PASS_COUNT + 1))
return 0
else
error "FAIL: $test_name"
FAIL_COUNT=$((FAIL_COUNT + 1))
return 1
fi
}
run_test
fonksiyonu, tüm testlerin standart bir şekilde çalıştırılmasını ve sonuçlarının kaydedilmesini sağlar.
Test Bölümleri
1. Cluster Durum Kontrolü
# Cluster durumu kontrol
check_cluster_status() {
header "1. CLUSTER DURUM KONTROLÜ"
info "Patroni cluster durumu kontrol ediliyor..."
echo
patronictl -c /etc/patroni.yml list
echo
# Her node'un patroni durumunu kontrol et
run_test "Node1 Patroni Servisi" "systemctl is-active patroni >/dev/null"
# etcd durumu (Node1'de)
run_test "etcd Servisi (Node1)" "systemctl is-active etcd >/dev/null"
# HAProxy durumu kontrol et
run_test "HAProxy Servisi" "curl -s http://$NODE3_IP:7000 >/dev/null"
}
Bu bölüm, cluster’ın temel bileşenlerinin çalışır durumda olup olmadığını kontrol eder:
- Patroni servislerinin durumu
- etcd cluster koordinatörünün durumu
- HAProxy’nin erişilebilirliği
2. Bağlantı Testleri
# PostgreSQL bağlantı testi
test_connection() {
local host="$1"
local port="$2"
local desc="$3"
PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$host" -p "$port" -U "$POSTGRES_USER" -d "$DATABASE" -c "SELECT 1;" >/dev/null 2>&1
}
# Bağlantı testleri
test_connections() {
header "2. BAĞLANTI TESTLERİ"
run_test "HAProxy üzerinden PostgreSQL bağlantısı" "test_connection $HAPROXY_IP $HAPROXY_PORT 'HAProxy'"
run_test "Node1 direkt PostgreSQL bağlantısı" "test_connection $NODE1_IP 5432 'Node1'"
run_test "Node2 direkt PostgreSQL bağlantısı" "test_connection $NODE2_IP 5432 'Node2'"
run_test "Node3 direkt PostgreSQL bağlantısı" "test_connection $NODE3_IP 5432 'Node3'"
}
Bağlantı testleri, hem HAProxy üzerinden hem de her node’a direkt olarak PostgreSQL bağlantısının kurulabilirliğini test eder.
3. Master Node Tespiti
# Master node tespiti
identify_master() {
header "3. MASTER NODE TESPİTİ"
info "Master node tespit ediliyor..."
# Patroni'den master'ı öğren
MASTER_NODE=$(patronictl -c /etc/patroni.yml list | grep "Leader" | awk '{print $2}')
if [[ -n "$MASTER_NODE" ]]; then
log "Master Node: $MASTER_NODE"
# Master IP'sini tespit et
case $MASTER_NODE in
"postgresql0") MASTER_IP="$NODE1_IP" ;;
"postgresql1") MASTER_IP="$NODE2_IP" ;;
"postgresql2") MASTER_IP="$NODE3_IP" ;;
esac
info "Master IP: $MASTER_IP"
echo
return 0
else
error "Master node tespit edilemedi!"
return 1
fi
}
Bu fonksiyon, Patroni’yi kullanarak cluster’da hangi node’un master rolünde olduğunu tespit eder.
4. Veri İşlemleri Testi
# Veri yazma/okuma testi
test_data_operations() {
header "4. VERİ YAZMA/OKUMA TESTLERİ"
local test_table="ha_test_$(date +%s)"
info "Test tablosu oluşturuluyor: $test_table"
# HAProxy üzerinden test tablosu oluştur
run_test "Test tablosu oluşturma" "
PGPASSWORD='$POSTGRES_PASSWORD' psql -h $HAPROXY_IP -p $HAPROXY_PORT -U $POSTGRES_USER -d $DATABASE -c \"
CREATE TABLE $test_table (
id SERIAL PRIMARY KEY,
test_data VARCHAR(100),
created_at TIMESTAMP DEFAULT NOW()
);\"
"
# Veri ekleme
run_test "Veri ekleme testi" "
PGPASSWORD='$POSTGRES_PASSWORD' psql -h $HAPROXY_IP -p $HAPROXY_PORT -U $POSTGRES_USER -d $DATABASE -c \"
INSERT INTO $test_table (test_data) VALUES
('Test data 1'),
('Test data 2'),
('Test data 3');\"
"
# Veri okuma
run_test "Veri okuma testi" "
PGPASSWORD='$POSTGRES_PASSWORD' psql -h $HAPROXY_IP -p $HAPROXY_PORT -U $POSTGRES_USER -d $DATABASE -c \"
SELECT COUNT(*) FROM $test_table;\" | grep -q '3'
"
# Replication kontrolü - Slave node'larda veriyi kontrol et
info "Replication kontrolü yapılıyor..."
sleep 2
# Her node'da veriyi kontrol et
for ip in $NODE1_IP $NODE2_IP $NODE3_IP; do
if PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$ip" -p 5432 -U "$POSTGRES_USER" -d "$DATABASE" -c "SELECT COUNT(*) FROM $test_table;" 2>/dev/null | grep -q '3'; then
log "Replication OK: $ip"
else
error "Replication FAIL: $ip"
fi
done
# Test tablosunu temizle
PGPASSWORD="$POSTGRES_PASSWORD" psql -h $HAPROXY_IP -p $HAPROXY_PORT -U $POSTGRES_USER -d $DATABASE -c "DROP TABLE IF EXISTS $test_table;" >/dev/null 2>&1
echo
}
Bu kritik test bölümü:
- Tablo oluşturma işlemini test eder
- Veri ekleme işlemini test eder
- Veri okuma işlemini test eder
- Replication kontrolü yapar – en önemli özellik
- Test verilerini temizler
5. Performans Testi
# Performans testi
test_performance() {
header "5. PERFORMANS TESTİ"
info "Basit performans testi yapılıyor..."
# 1000 insert testi
local start_time=$(date +%s.%N)
PGPASSWORD="$POSTGRES_PASSWORD" psql -h $HAPROXY_IP -p $HAPROXY_PORT -U $POSTGRES_USER -d $DATABASE -c "
CREATE TEMP TABLE perf_test AS
SELECT generate_series(1,1000) as id,
'test_data_' || generate_series(1,1000) as data;
" >/dev/null 2>&1
local end_time=$(date +%s.%N)
local duration=$(echo "$end_time - $start_time" | bc -l)
log "1000 kayıt işleme süresi: ${duration} saniye"
# Temizle
PGPASSWORD="$POSTGRES_PASSWORD" psql -h $HAPROXY_IP -p $HAPROXY_PORT -U $POSTGRES_USER -d $DATABASE -c "DROP TABLE IF EXISTS perf_test;" >/dev/null 2>&1
echo
}
Bu bölüm, 1000 kayıt oluşturarak basit bir performans ölçümü yapar.
6. Failover Testi
# Failover testi
test_failover() {
header "6. FAILOVER TESTİ"
warn "Bu test master node'u geçici olarak kapatacak!"
read -p "Devam etmek istiyor musunuz? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
warn "Failover testi atlandı."
return
fi
# Mevcut master'ı tespit et
identify_master
local original_master="$MASTER_NODE"
local original_master_ip="$MASTER_IP"
info "Original Master: $original_master ($original_master_ip)"
# Test verisi ekle
local test_value="failover_test_$(date +%s)"
PGPASSWORD="$POSTGRES_PASSWORD" psql -h $HAPROXY_IP -p $HAPROXY_PORT -U $POSTGRES_USER -d $DATABASE -c "
CREATE TABLE IF NOT EXISTS failover_test (id SERIAL, data TEXT);
INSERT INTO failover_test (data) VALUES ('$test_value');
" >/dev/null 2>&1
# Master node'u durdur (sadece bu sunucudaysak)
if [[ "$(hostname -I | awk '{print $1}')" == "$original_master_ip" ]]; then
warn "Master node ($original_master) durduruluyor..."
systemctl stop patroni
# Failover'ın gerçekleşmesini bekle
info "Failover bekleniyor (30 saniye)..."
sleep 30
# Yeni master'ı kontrol et
NEW_MASTER=$(ssh root@$NODE2_IP "patronictl -c /etc/patroni.yml list | grep 'Leader' | awk '{print \$2}'" 2>/dev/null ||
ssh root@$NODE3_IP "patronictl -c /etc/patroni.yml list | grep 'Leader' | awk '{print \$2}'" 2>/dev/null)
if [[ "$NEW_MASTER" != "$original_master" && -n "$NEW_MASTER" ]]; then
log "Failover başarılı! Yeni Master: $NEW_MASTER"
# Bağlantıyı test et
sleep 5
if test_connection $HAPROXY_IP $HAPROXY_PORT "HAProxy after failover"; then
log "HAProxy yeni master'a başarıyla yönlendiriyor"
# Test verisini kontrol et
if PGPASSWORD="$POSTGRES_PASSWORD" psql -h $HAPROXY_IP -p $HAPROXY_PORT -U $POSTGRES_USER -d $DATABASE -c "SELECT data FROM failover_test WHERE data='$test_value';" 2>/dev/null | grep -q "$test_value"; then
log "Veri kaybı yok - Failover başarılı!"
else
error "Veri kaybı tespit edildi!"
fi
else
error "HAProxy failover sonrası bağlantı kuramıyor"
fi
else
error "Failover başarısız! Master değişmedi."
fi
# Original master'ı tekrar başlat
warn "Original master ($original_master) tekrar başlatılıyor..."
systemctl start patroni
sleep 15
# Cluster'ın düzelmesini bekle
info "Cluster stabilizasyonu bekleniyor..."
sleep 10
else
warn "Bu sunucu master değil, failover testi başka sunucudan yapılmalı"
return
fi
# Temizle
PGPASSWORD="$POSTGRES_PASSWORD" psql -h $HAPROXY_IP -p $HAPROXY_PORT -U $POSTGRES_USER -d $DATABASE -c "DROP TABLE IF EXISTS failover_test;" >/dev/null 2>&1
echo
}
Bu en kritik test, HA cluster’ın asıl amacını test eder:
- Master node’u kasıtlı olarak durdurur
- Failover sürecini izler
- Yeni master’ın seçildiğini kontrol eder
- HAProxy’nin yeni master’a yönlendirme yaptığını test eder
- Veri kaybı olmadığını kontrol eder
- Eski master’ı geri çevrimiçi yapar
7. HAProxy Durum Kontrolü
# HAProxy durumu kontrolü
test_haproxy() {
header "7. HAPROXY DURUM KONTROLÜ"
info "HAProxy backend'leri kontrol ediliyor..."
# HAProxy stats sayfasını kontrol et
if curl -s "http://$NODE3_IP:7000" | grep -q "Statistics Report"; then
log "HAProxy dashboard erişilebilir"
info "Dashboard: http://$NODE3_IP:7000"
# Backend durumlarını göster
echo
info "Backend Durumları:"
curl -s "http://$NODE3_IP:7000/;csv" | grep "postgres" | while IFS=',' read -r line; do
server_name=$(echo "$line" | cut -d',' -f2)
status=$(echo "$line" | cut -d',' -f18)
echo " - $server_name: $status"
done
else
error "HAProxy dashboard erişilemiyor"
fi
echo
}
HAProxy’nin statistics sayfasından backend durumlarını kontrol eder.
8. Sistem Kaynak Kontrolü
# Sistem kaynak kullanımı
check_resources() {
header "8. SİSTEM KAYNAK KULLANIMI"
info "Sistem kaynakları kontrol ediliyor..."
echo "CPU Kullanımı:"
top -bn1 | grep "Cpu(s)" | awk '{print " " $0}'
echo
echo "Memory Kullanımı:"
free -h | grep -E "(Mem|Swap)" | awk '{print " " $0}'
echo
echo "Disk Kullanımı (/data/patroni):"
df -h /data/patroni | tail -1 | awk '{print " " $0}'
echo
echo "PostgreSQL Process'leri:"
ps aux | grep postgres | grep -v grep | wc -l | awk '{print " Toplam PostgreSQL process: " $0}'
echo
}
Sistem kaynaklarının kullanım durumunu raporlar.
Özet ve Rapor
# Özet rapor
show_summary() {
header "TEST SONUÇ ÖZETİ"
echo -e "${BLUE}Toplam Test: $TEST_COUNT${NC}"
echo -e "${GREEN}Başarılı: $PASS_COUNT${NC}"
echo -e "${RED}Başarısız: $FAIL_COUNT${NC}"
local success_rate=$((PASS_COUNT * 100 / TEST_COUNT))
echo -e "${PURPLE}Başarı Oranı: %$success_rate${NC}"
echo
if [[ $FAIL_COUNT -eq 0 ]]; then
log "TÜM TESTLER BAŞARILI! HA Cluster düzgün çalışıyor."
else
warn "Bazı testler başarısız oldu. Loglari kontrol edin."
fi
echo
info "Faydalı Komutlar:"
echo " - Cluster durumu: patronictl -c /etc/patroni.yml list"
echo " - HAProxy dashboard: http://$NODE3_IP:7000"
echo " - PostgreSQL bağlantı: psql -h $HAPROXY_IP -p $HAPROXY_PORT -U $POSTGRES_USER"
echo " - Patroni logları: journalctl -u patroni -f"
echo " - HAProxy logları: journalctl -u haproxy -f"
}
Test sonuçlarının özetini ve faydalı komutları listeler.
Ana Fonksiyon ve Script Başlatma
# Ana fonksiyon
main() {
header "PostgreSQL HA CLUSTER TEST BAŞLIYOR"
info "Test parametreleri:"
echo " - HAProxy Endpoint: $HAPROXY_IP:$HAPROXY_PORT"
echo " - PostgreSQL User: $POSTGRES_USER"
echo " - Node1: $NODE1_IP"
echo " - Node2: $NODE2_IP"
echo " - Node3: $NODE3_IP"
# Testleri çalıştır
check_cluster_status
test_connections
identify_master
test_data_operations
test_performance
test_haproxy
check_resources
# Kullanıcıya sor
echo
read -p "Failover testini de yapmak istiyor musunuz? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
test_failover
fi
show_summary
}
# Gerekli araçları kontrol et
if ! command -v patronictl &> /dev/null; then
error "patronictl komutu bulunamadı. Patroni kurulu değil?"
exit 1
fi
if ! command -v psql &> /dev/null; then
error "psql komutu bulunamadı. PostgreSQL client kurulu değil?"
exit 1
fi
# Testi başlat
main "$@"
Ana fonksiyon tüm testleri sırasıyla çalıştırır ve sonuçları raporlar.
Script’in Avantajları
1. Kapsamlı Test Kapsama
- Tüm HA bileşenlerini test eder
- Gerçek veri işlemlerini simüle eder
- Failover senaryosunu test eder
2. Kullanıcı Dostu Interface
- Renkli output ile sonuçlar net görülür
- Progress tracking ile test ilerlemesi takip edilir
- Detaylı logging ile debug imkanı
3. Güvenlik Önlemleri
- Failover testi için kullanıcı onayı alır
- Test verilerini otomatik temizler
- Hata durumunda script durur
4. Modüler Yapı
- Her test bölümü bağımsız çalışabilir
- Yeni testler kolayca eklenebilir
- Konfigürasyon merkezi bir yerden yönetilir
Kullanım Önerileri
1. Düzenli Test Çalıştırma
Bu scripti cron job olarak düzenli aralıklarla çalıştırarak cluster sağlığını izleyebilirsiniz:
# Günlük saat 02:00'de test çalıştır
0 2 * * * /path/to/ha_test.sh > /var/log/ha_test_$(date +\%Y\%m\%d).log 2>&1
2. Monitoring Entegrasyonu
Script çıktıları monitoring sistemlerine entegre edilebilir:
# Sadece başarısız testlerde alert gönder
if [[ $FAIL_COUNT -gt 0 ]]; then
echo "HA Cluster test failures: $FAIL_COUNT" | mail -s "HA Alert" admin@company.com
fi
3. CI/CD Pipeline’a Entegrasyon
HA cluster değişikliklerinden sonra otomatik test çalıştırabilirsiniz.
Özelleştirme İmkanları
1. Ek Test Bölümleri
- Backup/restore testleri
- Connection pooling testleri
- SSL/TLS bağlantı testleri
- Monitoring endpoint testleri
2. Multi-Environment Desteği
Farklı ortamlar için konfigürasyon dosyaları kullanabilirsiniz:
# config/production.conf
HAPROXY_IP="10.0.1.100"
NODE1_IP="10.0.1.101"
# ...
# Script başında
source "config/${ENVIRONMENT:-development}.conf"
3. JSON/XML Output
Test sonuçlarını strukturlu formatta çıkarabilirsiniz:
# JSON format için
echo '{"total_tests": '$TEST_COUNT', "passed": '$PASS_COUNT', "failed": '$FAIL_COUNT'}' > test_results.json
Sonuç
Bu PostgreSQL HA Cluster test scripti, production ortamlarında kritik önem taşıyan HA cluster’larının sağlık durumunu kapsamlı bir şekilde test etmek için tasarlanmış profesyonel bir araçtır. Script’in modüler yapısı, detaylı logging özelliği ve failover testleri ile gerçek dünya senaryolarını simüle etme kabiliyeti, onu sistem yöneticileri ve DevOps ekipleri için vazgeçilmez bir araç haline getirmektedir.
HA cluster’ların karmaşık doğası göz önüne alındığında, bu tür otomatize test araçları hem zaman tasarrufu sağlar hem de insan hatası riskini minimize eder. Düzenli olarak çalıştırıldığında, potansiyel sorunları production’da karşılaşmadan önce tespit etme imkanı sunar.
Bu script’i temel alarak, kendi ortamınızın özel ihtiyaçlarına göre özelleştirmeler yapabilir ve HA cluster’ınızın güvenilirliğini maksimum seviyede tutabilirsiniz.