1 puan yazan GN⁺ 3 시간 전 | Henüz yorum yok. | WhatsApp'ta paylaş
  • k8s tabanlı PostgreSQL kümesinde ağ arızası sırasında replikasyon gecikmesi (replication lag) birikerek güvenli failover’ı imkânsız hale getiren yapısal zayıflığın nasıl çözüldüğü
  • Mevcut yapı erişilebilirliği (availability), dayanıklılığın (durability) önüne koyuyordu; primary yazı almaya devam ederken replikalar geri kalıyor ve veri kaybı olmadan terfi ettirilebilecek aday kalmıyordu
  • Çözüm olarak failover adaylarına senkron replikasyon (synchronous replication) uygulandı ve koordinasyon için açık kaynak yüksek erişilebilirlik yöneticisi Patroni kullanıldı
  • Yalnızca leader pool standby’larının senkron replikasyona katıldığı, okuma replikalarının ise asenkron kaldığı hibrit replikasyon modeli ile dayanıklılık ve gecikme arasında denge sağlandı
  • remote_apply modu uygulandığında yazma gecikmesi %53 artsa da, 5 arıza senaryosunun doğrulanması ile güvenli otomatik failover sağlandı

Game day’de ortaya çıkan sorun

  • Datadog, sistem ve süreçlerdeki boşlukları proaktif biçimde bulmak için düzenli olarak game day gerçekleştiriyor; platforma kasıtlı yük bindirerek gerçek koşullardaki tepkileri öğreniyor
  • Bir game day sırasında staging ortamında bir availability zone (AZ) arızası simüle edilerek ağ gecikmesi oluşturuldu ve PostgreSQL mimarisindeki zayıflık açığa çıktı
    • Birden fazla Kubernetes tabanlı PostgreSQL kümesinin primary/writer düğümü etkilenen AZ üzerinde çalışıyordu
    • Ağ gecikmesi aniden artınca primary, replikalarla istikrarlı iletişim kuramadı; replikasyon gecikmesi arttı → yazmalar tıkandı → uygulama eski verileri sunmaya başladı
  • Yeterince güncel hiçbir replika olmadığından failover güvenli değildi ve küme fiilen durdu
  • Bu yapı normal koşullarda iyi çalışıyordu, ancak belirli ağ arızalarında erişilebilirliği dayanıklılığın önüne koyduğu için güvenli bir kurtarma yolu sunmuyordu
    • Primary, replikasyon gecikirken bile yazı kabul etmeye devam ediyor, replikasyon gecikmesi büyüdükçe replikalar daha da geride kalıyordu
    • Sonuç olarak veri kaybı riski olmadan hiçbir failover adayı terfi ettirilemiyordu; tek seçenek gecikmenin azalmasını ve replikaların yetişmesini beklemekti
  • Hedef, PostgreSQL’in performans özelliklerini gereğinden fazla bozmadan failover’ı hem otomatik hem de güvenli hale getirmekti

Temel mimari: Kubernetes üzerinde PostgreSQL

  • Kubernetes tabanlı PostgreSQL kümesi iki havuzdan oluşuyor: leader pool ve read replica pool; PostgreSQL tek yazarli (single-writer) bir sistemdir
    • Okuma/yazma ayrımı sayesinde leader üzerinde ek yük oluşturmadan okuma ölçeklenebilir, yazma gecikmesi ise öngörülebilir ve kararlı kalır
  • Leader pool, tüm yazmaları işleyen tek aktif writer düğümü ile 2 standby düğümden oluşur
    • Standby’lar uygulama trafiğini işlemez, ancak leader arızasında terfi ettirilebilir
  • Read replica pool, salt okunur trafiği işleyen çok sayıda düğümden oluşur; okuma ölçeklenebilirliği ve sorgu izolasyonu için optimize edilmiştir ve kasıtlı olarak failover hedefi dışında bırakılmıştır

Patroni ve ZooKeeper’ın rolü

  • Patroni, replikasyon, failover ve leader seçimini yönetir; dağıtık yapılandırma deposu (DCS) olarak ZooKeeper kullanılır
    • ZooKeeper mevcut leader anahtarını/kilidini, küme yapılandırmasını ve her üyenin replikasyon durumu meta verisini (en güncel LSN vb.) saklar
    • Patroni bu bilgilerle terfi ve geri düşürme kararlarını temkinli verir; agresif failover yerine veri tutarlılığını önceler
  • Yeni bir düğüm kümeye katıldığında önce ZooKeeper’da leader olup olmadığını kontrol eder
    • Leader yoksa geçici znode oluşturarak leader anahtarını almaya çalışır; ZooKeeper yalnızca tek bir düğümün bu anahtarı almasını garanti ederek birden fazla primary oluşmasını önler
    • Leader zaten varsa kendini replika olarak yapılandırır ve streaming replication başlatır
  • Ağ bölünmesi (network partition) durumunda leader veya ZooKeeper bağlantısını kaybeden replika, küme durumunu doğrulayamaz; Patroni bu düğümü geçici olarak duraklatır veya geri düşürür
  • Leader bağlantıyı kaybederse Patroni, ZooKeeper ile birlikte yalnızca uygun tek bir standby’ın leader lock almasını sağlar ve kısmi ağ arızalarında bile kontrollü failover garanti eder
    • Bağlantı geri geldiğinde eski leader, leader lock’ı yeniden alamazsa kendini standby’a düşürür; böylece split brain önlenir

Güvenli failover neden mümkün değildi

  • Tek yazar modelinde arıza olduğunda Patroni, sağlıklı standby’lar arasından yeni bir leader seçer
  • Veri kaybını önlemek için Patroni terfi öncesi güvenlik kontrolü yapar; bunun merkezinde replikasyon gecikmesinin maximum_lag_on_failover eşiği içinde olup olmadığı vardır
    • Standby leader’ın gerisindeyse terfi sırasında veri eksikliği veya tutarsızlık oluşabilir
  • Game day sırasında primary bağlantıyı kaybedince tüm standby’ların replikasyon gecikmesi eşik değeri aştı ve Patroni failover’ı doğru biçimde reddetti
    • Kümenin güvenli şekilde yazı kabul eden bir primary olmadan kalmasının nedeni Patroni değil, güvenli terfi adayı bulunmamasıydı

Streaming replication’ın iki modu

  • Streaming replication’da leader, tüm değişiklikleri içeren write-ahead log (WAL) verisini replikalara sürekli gönderir; replikalar WAL’ı yerelde uygulayarak senkron kalır
  • Asenkron replikasyon (varsayılan)

    • Leader, transaction commit etmeden önce replikalardan onay beklemez
    • Yazma gecikmesini en aza indirir, yüksek throughput sağlar
    • Ancak leader arızalanırsa primary’de commit edilmiş ama henüz replike edilmemiş transaction’lar terfi sırasında kaybolabilir
  • Senkron replikasyon

    • Leader, istemciye yanıt vermeden önce en az 1 replikanın onayını bekler
    • En az bir replikanın fazla geride kalma riskini büyük ölçüde azaltır; commit edilmiş transaction’ın başka bir düğümde de bulunduğunu doğruladıktan sonra yanıt verildiği için daha güçlü dayanıklılık sağlar
    • Failover adayının güncel olma olasılığı yüksektir; bu da veri ayrışması riski olmadan terfiye imkân tanır

Hibrit replikasyon yapılandırması

  • Dayanıklılık, gecikme ve throughput arasında denge kurmak için hibrit replikasyon modeli benimsendi
    • Leader pool’daki standby düğümler senkron replikasyona katılır; leader, belirlenmiş senkron standby’ın onayından sonra yazmayı commit eder
    • Read replica’lar asenkron replikasyonda kalır; yalnızca salt okunur trafiği işlerler ve failover hedefi olmadıkları için leader pool üzerindeki replikasyon yükü sınırlı tutulur
  • Böylece okuma replikalarına aynı gecikme maliyeti yüklenmeden, yalnızca failover adayları için sıkı dayanıklılık garantisi uygulanır

Güvenli failover için PostgreSQL ve Patroni ayarı

  • Senkron replikasyonu etkinleştirmek için hem PostgreSQL hem Patroni tarafında parametreler ayarlandı
  • Ayarlanan başlıca parametreler

    • synchronous_mode: Patroni senkron replikasyonunu etkinleştirir; true olduğunda synchronous_node_count değerine göre senkron standby onayı sonrası commit yapılır (varsayılan false → true, Patroni tarafından yönetilir, zorunlu)
    • synchronous_node_count: senkron standby düğüm sayısıdır; synchronous_standby_names listesini oluşturmak için kullanılır (varsayılan 1 → 1, Patroni tarafından yönetilir, isteğe bağlı)
    • synchronous_mode_strict: sıkı senkron modu zorlar; true iken kullanılabilir replika yoksa asenkrona dönmek yerine yazmaları engeller (varsayılan false → true, Patroni tarafından yönetilir, isteğe bağlı)
    • synchronous_commit: PostgreSQL commit dayanıklılığı ayarıdır (varsayılan on → remote_apply, PostgreSQL tarafından yönetilir, isteğe bağlı)
  • Uygulamadan sonra leader, ancak senkron standby veriyi alıp uyguladığını doğruladığında istemciye transaction yanıtı gönderir

Dayanıklılık ve gecikme arasındaki denge

  • Senkron replikasyon dayanıklılığı artırır, ancak leader senkron standby onayı beklediği için yazma gecikmesini yükseltir ve sürekli yük altında throughput’u etkileyebilir
  • Performans etkisi, senkron standby sayısına (synchronous_node_count) ve synchronous_commit ile seçilen dayanıklılık seviyesine bağlıdır
  • synchronous_commit dayanıklılık seviyelerine göre ödünleşimler

    • remote_apply: replikanın WAL’ı yazıp flush etmesini ve replay etmesini bekler; en güçlü tutarlılık, en yüksek gecikme
    • on (içeride remote_flush): replikanın WAL’ı diske flush etmesini bekler; güçlü dayanıklılık sağlar ancak standby üzerinde henüz okunabilir olmayabilir
    • remote_write: WAL’ın replikanın OS cache’ine (diske değil) ulaşmasını bekler; daha düşük gecikme sunar ama OS çökmesine karşı hassastır
    • local: standby beklemeden yerel disk flush sonrası commit eder; düğümler arası dayanıklılık garantisi yoktur
    • off: yerel WAL flush öncesi commit eder; en düşük gecikme, en yüksek veri kaybı riski

Senkron replikasyon performans kıyaslaması

  • Her commit en az bir standby onayı beklediğinden senkron replikasyon ek gecikme getirir; bunun etkisini ölçmek için PostgreSQL’in standart yük testi aracı pgbench ile benchmark yapıldı (Patroni sürüm 3.2.1)
  • Basit okuma/yazma karışımını simüle eden TPC-B transaction paketi kullanıldı ve iki metrik ölçüldü
    • Ortalama gecikme: transaction başına ortalama işlem süresi (ms)
    • Saniye başına transaction sayısı (tps): bağlantı kurulum süresi hariç tamamlanan transaction sayısı
  • Test parametreleri

    • Ölçek faktörü (veritabanı boyutu), istemci sayısı (eşzamanlı kullanıcı trafiği), thread sayısı (CPU ve paralellik), transaction sayısı (iş yükü yoğunluğu) değiştirilerek üretime benzer koşullar taklit edildi
    • Quorum commit modundaki senkron replikasyon bu benchmark kapsamında test edilmedi
  • Benchmark sonuçları

    • Yazma gecikmesi artış oranı: remote_apply %53, on %46, remote_write %38, local %32
    • Throughput (tps) düşüş oranı: remote_apply %34, on %31, remote_write %27, local %23
    • remote_apply, replikanın WAL replay ve apply aşamasını da beklediği için tutarlı biçimde en yüksek gecikmeyi ve en düşük throughput’u gösterdi; ancak en güçlü tutarlılığı sunduğundan güvenli failover için uygundu
  • Üretimde uygulama

    • Benchmark sonrasında yüksek yazma trafiğine sahip birden fazla kümede remote_apply devreye alındı; sürekli üretim yükü altında bile uygulama seviyesinde yazma gecikmesi ve throughput üzerinde anlamlı etki görülmedi
    • Performans riskini azaltmak için veri merkezi ve iş yükü katmanına göre kademeli rollout yapıldı; aşamalar arasında bake-in süresi ve sürekli izleme uygulandı
    • Örneğin yüksek throughput’lu kaynak işleme iş yükü, senkron replikasyon etkinleştirildikten sonra DB yazma gecikmesi artsa da işlem gecikmesi veya aşağı akış backlog oluşturmadan çalışmayı sürdürdü
    • synchronous_commit, kesinti olmadan patronictl edit-config ile anında ayarlanabilir; bu da ultra yüksek throughput’lu iş yüklerinde commit dayanıklılığını hızlıca düşürme esnekliği sağlar

Arıza senaryolarıyla failover doğrulaması

  • Senkron replikasyon ve sıkı failover kontrolünün veri bütünlüğünü koruduğu, split-brain’i önlediği ve otomatik kurtarmayı sağladığı doğrulandı
  • Senaryo 1: 1 senkron standby kaybı

    • Senkron standby kaybolduğunda Patroni, senkron replikasyonu sürdürmek için başka uygun bir standby atamaya çalışır
    • Leader düğümündeki Patroni, kopmuş, takılmış veya gecikmiş streaming bağlantılarını pg_stat_replication ile tespit eder ve ZooKeeper üzerinden replika üyeliğini izler
    • Sağlıklı ve uygun streaming replikaların listesini yeniden hesaplar, synchronous_node_count değerine göre synchronous_standby_names alanını günceller ve senkron replikasyonu aktif tutar
  • Senaryo 2: Tüm senkron standby’ların kaybı

    • Davranış synchronous_mode_strict değerine bağlıdır
    • Sıkı olmayan mod: yazma erişilebilirliği öncelikli

      • Patroni, synchronous_standby_names değerini boşaltarak senkron replikasyonu geçici olarak devre dışı bırakır; sağlıklı bir replika yeniden katılana kadar leader asenkrona geçer ve yazılara izin verir
    • Sıkı mod: güvenlik için yazmaları engelle

      • Patroni, synchronous_standby_names değerini * yapar; açıkça tanımlı senkron standby olmasa bile PostgreSQL yazma transaction’larını kabul edip yerelde commit eder, ancak bir replika WAL’ı onaylayana kadar istemci yanıtını engeller
      • Senkron replikasyona katılabilecek uygun bir replika yeniden bağlandığında Patroni ona senkron standby rolünü atar
  • Senaryo 3: Tüm standby ve replika düğümlerinin kullanılamaz olması

    • Tüm replikalar kullanılamaz durumdaysa ve synchronous_mode_strict = true ise PostgreSQL, en az bir uygun replika geri dönene kadar transaction onayını bekletir
    • Veri tutarlılığı korunur, ancak uygulama seviyesinde geçici yazma kesintisi yaşanır
  • Senaryo 4: Senkron commit sırasında leader arızası

    • Leader’ın senkron standby onayını beklerken, onay gelmeden durduğu uç durum
    • Yaygın nedenler: commit sırasında istemcinin transaction iptali, leader PostgreSQL sürecinin çökmesi veya sonlanması, commit aşamasında ağ bölünmesi
    • PostgreSQL WAL’ı yerelde flush etmiş ama standby’a replike edememişse, onay alınmadığı için transaction replika üzerinde görünmez
    • Leader, WAL’ı senkron standby’a replike etmeden çöker ve o standby terfi ettirilirse transaction kaybı yaşanabilir; eski leader ile yeni primary’nin geçmişi ayrışır
    • Eski leader, pg_rewind ile timeline ayrım noktasını belirler ve veri dizinini yeni primary timeline’ına uyacak şekilde geri sarar; replike edilmemiş yerel değişiklikleri atıp standby olarak yeniden katılır
    • Bu davranış Patroni’den değil, PostgreSQL’in senkron commit iç işleyişinden kaynaklanır; quorum ayarları ile onay mekanizmasının dikkatli ayarlanması ve izlenmesi gerektiğini gösterir
  • Senaryo 5: ZooKeeper kullanılamaz

    • ZooKeeper kullanılamaz olduğunda Patroni leader’lığı doğrulayamaz ve yeni seçim yapamaz; veri tutarsızlığını önlemek için muhafazakâr moda geçer
    • Failsafe modu devre dışıyken

      • ZooKeeper’a ulaşılamasa da leader erişilebilir durumdaysa ve tüm düğümler sağlıklıysa yazılar devam eder, ancak yalnızca leader lock TTL süresi dolana kadar
      • Leader key yenileme döngü süresi geçip kilit yenilenemezse Patroni leader’ı geri düşürür ve kümeyi salt okunura çevirir
    • Failsafe modu etkinse

      • Leader, ZooKeeper bağlantısını kaybettiğinde Patroni REST API üzerinden tüm küme üyelerine erişilip erişilemediğini sürekli doğrular
      • Yalnızca tüm üyelere erişilebiliyorsa yazılara devam edilir; aksi halde salt okunura düşürülür

Senkron replikasyon altında manuel failover ve switchover

  • Patroni, health check ve ZooKeeper koordinasyonuna dayalı otomatik failover ve switchover’a ek olarak patronictl komutuyla manuel işlemleri de destekler; ancak senkron replikasyon etkin olduğunda tüm standby’lar geçerli aday olmadığından veri bütünlüğünü koruyan guardrail’ler uygulanır
  • Asenkron standby’a failover

    • patronictl failover: seçilen düğüm asenkron ise başarısız olur
    • patronictl switchover: seçilen düğüm asenkron ise başarısız olur
    • Senkron replikasyon etkin durumdayken asenkron düğüme zorla failover yapılması, dayanıklılık garantisini baypas ederek veri kaybına yol açabilir
  • Hedef senkron standby ise

    • patronictl failover: başarılı olur, leader senkron standby’a geçer
    • patronictl switchover: başarılı olur, leader ile senkron standby arasında zarif bir handoff gerçekleşir
  • Farklı synchronous_commit modlarının davranışı ve Patroni guardrail’leri doğrulandıktan sonra, yüksek yazma, yüksek okuma ve karma iş yüklerine sahip üretim kümelerinde senkron replikasyon etkinleştirildi; gecikme ve throughput üzerinde ölçülebilir etki görülmedi
  • Sorun yaşanırsa synchronous_mode: false ayarıyla kesinti olmadan güvenli şekilde asenkron replikasyona geri dönülebilir

Neden DRBD seçilmedi

  • Yüksek erişilebilirlik değerlendirmesinde blok seviyesinde replikasyon sistemi DRBD (Distributed Replicated Block Device) da incelendi; bu yaklaşım PostgreSQL veri dizini ve WAL dosyaları dahil tüm volume’ü sunucular arasında aynalayarak neredeyse gerçek zamanlı standby replikası oluşturur
  • DRBD, PostgreSQL’in yerleşik streaming replication’ına göre daha düşük gecikme sunabilir; ancak yeni altyapı, izleme ve operasyon playbook’ları dahil önemli bir mimari dönüşüm gerektirir
  • Olgun Kubernetes tabanlı kurulum ve PostgreSQL senkron replikasyonunun ayrıntılı denetimi göz önüne alındığında, görünürlük, esneklik ve operasyonel güven açısından daha iyi olan veritabanı düzeyindeki replikasyon tercih edildi

Senkron replikasyon izleme

  • Senkron replikasyon etkinleştirildikten sonra replikasyon durumu ve failover hazırlığı yakından izlendi; özellikle iki sinyal büyük ölçekte kararlılığın korunmasına katkı sağladı
  • SyncRep bekleme olayı

    • Primary, commit’i tamamlayıp durumu döndürmeden önce senkron standby onayı beklediğinde oluşur; bir miktarı normaldir ancak uzun veya sık beklemeler replika performans sorunu ya da düğümler arası ağ gecikmesine işaret eder
    • Neden önemli: uzun beklemeler yazma gecikmesini artırır ve throughput’u düşürür
    • İzlenenler: SyncRep ve WalSenderWaitForReply bekleme olaylarının süresi ve sıklığı; wait_event:SyncRep etiketiyle filtrelenmiş postgresql.activity.waits Datadog metriğinden toplanır (arka planda pg_stat_activity tablosu sorgulanır)
  • Senkron standby tespit edilememesi

    • Patroni uzun süre sağlıklı bir senkron standby tespit edemezse küme güvenli failover yeteneğini kaybeder
    • Neden önemli: senkron standby yoksa failover sırasında veri kaybına açıklık oluşur
    • Uyarı ölçütü: patroni_sync_standby uzun süre boş kalırsa yüksek erişilebilirlik (HA) sağlık uyarısı üretilir; bu veri OpenMetrics’ten toplanır, yerel Datadog entegrasyonu yoktur
  • Senkron replikasyon dayanıklılığı artırır, ancak replika sağlıksız veya erişilemez olduğunda erişilebilirlik ve performans düşebilir; bu yüzden bekleme süreleri ile standby erişilebilirliğinin izlenmesi, yük altında erişilebilirlik ve performansı korumak için kritiktir

Güvenli failover tasarım aşamasından başlamalı

  • Simüle edilen AZ arızası, PostgreSQL mimarisindeki kritik zayıflığı ortaya çıkardı: replikalar leader’ın gerisinde kalıyor, bu da ya ağ arızasının bitmesini beklemeyi ya da veri ayrışmasını göze almayı zorunlu kılıyordu; bu ödünleşim üretimde kabul edilemezdi
  • Patroni tabanlı senkron replikasyonun benimsenmesi ve dayanıklılık/gecikme ayarları sayesinde, zayıflamış ağ koşullarında bile failover hem mümkün hem güvenli hale getirildi; benchmark ve tekrarlanan arıza simülasyonlarıyla, büyük ölçekli performans bozulması olmadan öngörülebilir kurtarma doğrulandı
  • Senkron replikasyon, arıza sırasında yazmaları engelleyerek başarısızlığı üst akış servislerine açıkça gösterir; asenkron replikasyondaki gibi yazmalar sessizce kaybolmaz, bunun yerine retry ve queueing gibi yöntemlerle karşılanabilir; böylece arıza modu daha görünür ve daha kurtarılabilir olur
  • Sonraki adım olarak quorum tabanlı commit modu ve replikasyon durumu için daha derin gözlemlenebilirlik araştırılıyor

Henüz yorum yok.

Henüz yorum yok.