Failover güvenli olmadığında: Kubernetes tabanlı yüksek erişilebilir PostgreSQL kurmak
(datadoghq.com)- 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_applymodu 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_failovereş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;trueolduğundasynchronous_node_countdeğ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_nameslistesini 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;trueiken 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) vesynchronous_commitile seçilen dayanıklılık seviyesine bağlıdır -
synchronous_commitdayanıklılık seviyelerine göre ödünleşimlerremote_apply: replikanın WAL’ı yazıp flush etmesini ve replay etmesini bekler; en güçlü tutarlılık, en yüksek gecikmeon(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 olmayabilirremote_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ırlocal: standby beklemeden yerel disk flush sonrası commit eder; düğümler arası dayanıklılık garantisi yokturoff: 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
- Yazma gecikmesi artış oranı:
-
Üretimde uygulama
- Benchmark sonrasında yüksek yazma trafiğine sahip birden fazla kümede
remote_applydevreye 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 olmadanpatronictl edit-configile 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
- Benchmark sonrasında yüksek yazma trafiğine sahip birden fazla kümede
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_replicationile tespit eder ve ZooKeeper üzerinden replika üyeliğini izler - Sağlıklı ve uygun streaming replikaların listesini yeniden hesaplar,
synchronous_node_countdeğerine göresynchronous_standby_namesalanını günceller ve senkron replikasyonu aktif tutar
-
Senaryo 2: Tüm senkron standby’ların kaybı
- Davranış
synchronous_mode_strictdeğerine bağlıdır -
Sıkı olmayan mod: yazma erişilebilirliği öncelikli
- Patroni,
synchronous_standby_namesdeğ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
- Patroni,
-
Sıkı mod: güvenlik için yazmaları engelle
- Patroni,
synchronous_standby_namesdeğ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
- Patroni,
- Davranış
-
Senaryo 3: Tüm standby ve replika düğümlerinin kullanılamaz olması
- Tüm replikalar kullanılamaz durumdaysa ve
synchronous_mode_strict = trueise 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
- Tüm replikalar kullanılamaz durumdaysa ve
-
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
patronictlkomutuyla 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 olurpatronictl 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çerpatronictl switchover: başarılı olur, leader ile senkron standby arasında zarif bir handoff gerçekleşir
- Farklı
synchronous_commitmodları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: falseayarı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:
SyncRepveWalSenderWaitForReplybekleme olaylarının süresi ve sıklığı;wait_event:SyncRepetiketiyle filtrelenmişpostgresql.activity.waitsDatadog metriğinden toplanır (arka plandapg_stat_activitytablosu 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_standbyuzun 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.