Linux

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.

Muhammed Kerim Koç

1996 yılında Giresun Şebinkarahisarda dünyaya geldim. İlk ve orta öğretimi Şebinkarahisarda tamamladım. Liseyi Şebinkarahisar Anadolu Teknik ve Endüstri Meslek Lisesinde bitirdim. Üniversite için de Şebinkarahisar Teknik Bilimler Meslek Yüksek Okulunda Bilgisayar programcılığını okudum. Üniversite stajı için gelmiş olduğum özel bir firmada işe başladım. 5,5 yıl bu firmadan çalıştıktan sonra farklı bir sektör olan inşaat sektöründe Bilgi teknolojileri Uzmanı olarak 8 ay çalıştım. Daha sonra özel bir şirkette Sistem Network Sorumlusu olarak 4 ay çalıştıktan sonra proje sonlandırılmasından dolayı işten ayrıldım. Tekrar dan 5.5 yıl çalışmış olduğum firmaya Sistem ve Network Yöneticisi olarak geri döndüm ve çalışmaya başladım. Kendimi geliştirmek için Bilge Adam Akademi den Sistem Uzmanlığı eğitimi aldım. Sanallaştırma ve Ağ tarafında kendimi sürekli olarak geliştiriyorum.

İlgili Makaleler

Başa dön tuşu