PG Resilience Lab
PostgreSQL klasterini 10 xil usulda buzib, RTO, RPO va ledger yaxlitligini o'lchagan HA/DR laboratoriyasi
Bu loyiha nimani isbotlaydi
- 10 nosozlik × 3 run: tasdiqlangan 91 700 o'tkazmadan 0 tasi yo'qoldi, 0 tasi ikki marta qo'llandi, ledger doim muvozanatda
- Sinxron replikatsiyani kutayotgan commit'ni cancel qilish "muvaffaqiyat" deb javob berib uni yo'qotishini o'lchadim (72 qator); fencing terminate'ga o'tkazildi, 0 yo'qotish
- 17 → 18 upgrade'ning ikki usuli: pg_upgrade --link 22.6 s, logical replication + HAProxy cutover 2.4 s yozish uzilishi
- Xato DROP TABLE'ni pg_waldump bilan topilgan xid'dan oldingacha PITR bilan tikladim, mediana 32 s
- Rol
- Yakka: klaster dizayni, nosozlik kiritish va o'lchovni avtomatlashtirish, tahlil, 6 ta ADR va koreyscha runbook
- Muddat
- 2026.10 – 2026.10
- Texnologiyalar
- PostgreSQL
- repmgr
- pgBackRest
- HAProxy
- Docker
- k6
- Bash
- Python
- NestJS
Asosiy raqamlar
| Ko'rsatkich | Qiymat | Turi | Dalil |
|---|---|---|---|
| Tasdiqdan keyin yo'qolgan o'tkazmalar (30 run) | 0 / 91,700 | O'lchangan | Dalilni ko'rish |
| RTO medianasi · primary kill -9 | 7,07 s | O'lchangan | Dalilni ko'rish |
| RTO medianasi · 45 s tarmoqdan uzilish | 27,91 s | O'lchangan | Dalilni ko'rish |
| RTO medianasi · split-brain | 28,2 s | O'lchangan | Dalilni ko'rish |
| RTO medianasi · DROP TABLE → PITR | 32,03 s | O'lchangan | Dalilni ko'rish |
| 17 → 18 logical replication cutover yozish uzilishi | 2,43 s | O'lchangan | Dalilni ko'rish |
| 17 → 18 pg_upgrade --link yozish uzilishi | 22,6 s | O'lchangan | Dalilni ko'rish |
| cancel bilan bo'shatilib, muvaffaqiyat deb javob berilgan va yo'qolgan commit'lar | 72 / 620 | O'lchangan | Dalilni ko'rish |
| Xavfsizlik tekshiruvlari o'tdi | 18 / 18 | O'lchangan | Dalilni ko'rish |
Hal qilinadigan muammo
Ko'p HA sozlamalari "sozlandi" bilan tugaydi: primary haqiqatan o'lganda yozish necha soniyada qaytishi va tasdiqlangan tranzaksiya yo'qolmasligi o'lchanmaydi. Bu laboratoriya LedgerCore'ga soniyasiga 20 ta o'tkazma yuborib turib 10 xil nosozlikni har birini 3 martadan kiritadi: primary to'xtashi, kill -9, server o'chishi va qayta yonishi, tarmoqdan uzilish, WAL diski to'lishi, data papkasining o'chirilishi, jadval faylining yo'qolishi, xato DROP TABLE va split-brain. Har run'da RTO, tasdiqdan keyin yo'qolgan o'tkazmalar (RPO), ikki marta qo'llanish va double-entry invarianti hisoblanadi.
Arxitektura
3 ta PostgreSQL 17 tugun (repmgr 5.5, 1 primary + 2 standby) va witness replikatsiya tarmog'ida, LedgerCore API va HAProxy ilova tarmog'ida turadi; faqat replikatsiya tarmog'ini uzish mijozlar eski primary'ga yetib boradigan split-brain'ni takrorlaydi. synchronous_standby_names = 'ANY 1 (pg1, pg2, pg3)'. Har tugundagi health agent (:8008) /primary'ga faqat tugun recovery'da bo'lmasa, fence qilinmagan bo'lsa va 3 soniya ichida javob bergan sinxron standby bo'lsa 200 qaytaradi; HAProxy buni har soniyada tekshiradi. Yakkalangan primary read-only bo'lib, sessiyalarni terminate qiladi. Backup TLS server rejimidagi alohida pgBackRest ombor xostida (asinxron WAL arxivlash, backup standby'dan), barcha ulanishlar lab CA'sidan verify-full TLS. runner konteyneri k6 yuki, nosozlik kiritish, tiklash va tahlilni avtomatik bajaradi.
Ma'lumotlar modeli
Asosiy cheklovlar va indekslar
- synchronous_standby_names = 'ANY 1 (pg1, pg2, pg3)': bitta standby yo'qolsa ham yozish davom etadi
- HAProxy :5000 faqat sinxron kvorumi tirik primary'ga yo'naltiradi
- Barcha ulanishlar hostssl, verify-full va scram-sha-256; tarmoqdan superuser kirishi rad etiladi; credcheck kamida 16 belgi
- ledger_app roli: statement_timeout 5 s · lock_timeout 2 s · idle_in_transaction_session_timeout 10 s
Asosiy loyihaviy qarorlar
ADR-0001 repmgr + witness
- Vaziyat
- 3 tugunda avtomatik failover kerak edi va kursdagi vositalar bilan mexanizmni bevosita boshqarmoqchi edim.
- Qaror
- repmgr 5.5 + witness, primary_visibility_consensus, standby_disconnect_on_failover, bolalar uzilsa primary fence
- Evaziga
- DCS lock yo'q, split-brain himoyasini kvorum yo'naltirish va fencing bilan to'ldirish kerak
ADR-0002 Sinxron kvorum ANY 1
- Vaziyat
- FIRST 1 (pg2) kabi bitta sinxron standby belgilansa, pg2 to'xtaganda barcha yozishlar to'xtaydi.
- Qaror
- synchronous_standby_names = 'ANY 1 (pg1, pg2, pg3)'
- Evaziga
- pg2 25 s to'xtaganda FIRST 1: 12 119 muvaffaqiyatsiz urinish va 213 ta voz kechilgan o'tkazma, ANY 1: 0. Ikkala standby ham uzilsa yozish baribir to'xtaydi
ADR-0003 Kvorumni tekshiradigan HAProxy health check
- Vaziyat
- Birinchi run'larda yakkalanib qaytgan primary o'zini fence qilgunicha taxminan 18 s HAProxy'ga primary sifatida ko'rindi.
- Qaror
- /primary faqat recovery'da emas, fence qilinmagan va 3 s ichida javob bergan sinxron standby bo'lsa 200
- Evaziga
- Barcha standby sekin bo'lsa, sog'lom primary ham yozishdan chiqadi; bu holatda sinxron replikatsiya commit'larni baribir to'sib turgan bo'ladi
ADR-0006 Sinxron kutishda cancel emas, terminate
- Vaziyat
- Bo'lingan primary'da sinxron standby'ni kutayotgan sessiyalarni tozalash kerak, statement_timeout esa bu kutishni uzmaydi.
- Qaror
- Fencing faqat pg_terminate_backend ishlatadi, runbook SyncRep kutishlarida cancel'ni taqiqlaydi
- Evaziga
- Mijoz ulanish xatosini oladi va qayta urinishi kerak; LedgerCore idempotency key bilan xavfsiz qayta yuboradi
Oldin va keyin
- Nima o'zgartirildi
- Bo'linish paytida sinxron replikatsiyani kutayotgan commit'larni pg_cancel_backend bilan bo'shatish PostgreSQL'ni ularni muvaffaqiyatli deb javob berishga majbur qiladi va failover'dan keyin qatorlar yo'qoladi. Fencing endi faqat pg_terminate_backend ishlatadi, runbook cancel'ni taqiqlaydi (ADR-0006).
Nosozlik tarixi
- Belgi
- ack-leak tajribasi paytida ikkala standby ham promote bo'lolmadi, logda recovery ended before configured recovery target was reached qoldi.
- Sabab
- 09-ssenariydagi PITR postgresql.auto.conf'da recovery_target_xid'ni qoldirgan, keyin klonlangan har bir standby uni ko'chirgan; shuning uchun har promote allaqachon o'tib ketgan recovery target'ni kutgan.
- Yechim
- PITR'dan so'ng darhol ALTER SYSTEM RESET recovery_target_* bajariladi, clone va rejoin ham recovery_target sozlamalarini ehtiyot uchun o'chiradi.
- Takrorlanmasligi uchun
- 09-ssenariyning tiklash bosqichi PITR'dan keyin yangi to'liq backup oladi; tuzatishdan keyingi 30 run'lik kampaniyada (3 ta PITR bilan) bu xato qaytmadi.
Test va sifat
- Testlar soni
- —
- Qamrov
- —
- CI
- —
- Test vositalari
- 장애 시나리오 10종 × 3회, 실험 8종, 보안 점검 18개(security/run.sh), bash -n, LedgerCore 단위 테스트 3개(연결 끊김 수정)
Deploy va ekspluatatsiya
- Deploy muhiti
- Bitta xostda Docker Compose. Windows'da .\lab.ps1 init tasodifiy parollar bilan .env yaratadi, .\lab.ps1 up esa image build, sertifikatlar, klaster bootstrap, birinchi to'liq backup va pg_cron vazifalarini bir buyruqda bajaradi.
- Backup
- Alohida pgBackRest ombor xosti (TLS server rejimi, zstd), asinxron WAL arxivlash, to'liq backup haftada, differential har kuni, incremental har 4 soatda, standby'dan. Har kuni oxirgi backup vaqtinchalik tiklanib, ledger yaxlitligi va checksum tekshiriladi (tiklash 1.8 s + recovery 1.4 s, buzilish 0). S3 repo2 (aes-256-cbc) sozlangan, lekin o'lchanmagan.
- Rollback
- pg_upgrade muvaffaqiyatsiz bo'lsa, eski 17 data papkasi avtomatik qaytariladi. .\lab.ps1 baseline buzilgan tugunlarni rejoin yoki qayta quradi va pg1'ni yana primary qiladi.
- Monitoring
- Har tugunda health agent (:8008), HAProxy stats (:8404), barcha tugunlardagi repmgr hodisalari nosozlik vaqtiga nisbatan timeline'ga yig'iladi. Sinxron kvorum, WAL arxivlash xatolari va jadval bloat'i PG Insight'da kuzatildi.
Skrinshotlar
Cheklovlar va xulosalar
Hozirgi cheklovlar
- Barcha konteynerlar bitta xostda: laboratoriya haqiqiy server nosozligini emas, HA mexanizmlarini (aniqlash, saylash, fencing, yo'naltirish, tiklash) tekshiradi; sinxron replikatsiya narxi ham haqiqatdagidan arzon ko'rinadi.
- Raqamlar 2 vCPU Linux sandbox'da xuddi shu paketlarning Ubuntu asosidagi o'rinbosar image'lari bilan o'lchandi; repodagi Dockerfile postgres:17-bookworm va PGDG paketlarini ishlatadi.
- repmgr'da DCS leader lock yo'q, shuning uchun split-brain himoyasi sinxron kvorum, kvorumga asoslangan yo'naltirish va soft fence birikmasi; Patroni + etcd kuchliroq kafolat beradi.
- S3 ombori (repo2) sozlangan, lekin o'lchovlarda ishlatilmagan; PgBouncer yo'q.
Qayta qursam
- Xuddi shu ssenariylarni Patroni + etcd'da ishlatib, RTO va split-brain xatti-harakatini repmgr bilan solishtiraman.
- Sinxron replikatsiyaning haqiqiy tarmoq narxini o'lchash uchun kamida ikki serverda ishlataman.
Asosiy kod
node/bin/pg-health-agent/primary'ga faqat kvorumli primary uchun 200
docker/haproxy/haproxy.cfg1 s tekshiruv, fall 2, o'chgan server sessiyalari yopiladi
node/bin/fence-selfRead-only + terminate (cancel taqiqlangan)
scenarios/09-accidental-drop-pitr.shpg_waldump bilan xid topish → PITR → standby'larni delta bilan qayta qurish
measure/analyze.pyRTO, RPO, dublikat va ledger yaxlitligini hisoblaydi
experiments/ack-leak.shcancel va terminate'dagi yo'qotishlarni o'lchaydi
upgrade/logical.sh17 → 18 logical replication, sequence sinxronlash, HAProxy cutover
docs/runbook.ko.mdHar bir nosozlik uchun javob tartibi (koreyscha)
Hozirgi holat va keyingi qadamlar
30 ta run'da muvaffaqiyatli javob olgan 91 700 ta o'tkazmaning birortasi yo'qolmadi, ikki marta qo'llanmadi va ledger muvozanati buzilmadi. RTO medianasi: jarayon nosozliklarida 6.7~7.5 s, server o'chishida 24.7 s, tarmoqdan uzilishda 27.9 s, split-brain'da 28.2 s, PITR'da 32.0 s, data papkasi o'chirilganda 35.9 s. Birinchi run'lar ma'lumotni xavf ostiga qo'ygan yoki klaster o'zini tiklay olmagan 12 ta muammoni ochdi va hammasi tuzatildi, jumladan DB ulanishi uzilganda LedgerCore API jarayoni butunlay qulaydigan bug. 17 → 18 upgrade'da pg_upgrade --link 22.6 s, logical replication + HAProxy cutover 2.4 s yozish uzilishi berdi, ikkalasida ham yo'qotish 0.