WIUNIX ACADEMY
رپلیکیشن PostgreSQL با Patroni؛ quorum، جابهجایی و بازیابی امن
صفحهٔ 4 از 6؛ مراحل قبلی و پیشنیازها را پیش از ادامه مرور کن.
آموزش متناسب با محیط تو
کجا اجرا میکنی؟
سیستمعامل و نسخه را انتخاب کن تا مراحل، دستورها و راهحلها برای همان محیط نمایش داده شوند.
آموزش متناسب با مقادیر تو
تنظیمات این آموزش
مقادیر نمونه را برای محیط خودت تنظیم کن؛ متن و دستورهای مرتبط با هم تغییر میکنند. رمز، کلید خصوصی و توکن وارد نکن. مقادیر فقط در همین زبانه نگهداری میشوند و به سرور یا لینک اشتراکگذاری فرستاده نمیشوند. پیش از اجرا، DNS، گواهیها و سیاست شبکهٔ واقعی را بررسی کن.
آیپی، دامنه یا پورت مثالها با محیط تو فرق دارد؟ دکمهٔ زیر را باز کن، مقادیر را تغییر بده و «اعمال در آموزش» را بزن؛ سپس دستورهای بهروزشده را کپی کن.
تنظیم مقادیر برای محیط من11 مقدار قابلتغییر
قدم بعدی
برای PostgreSQL فقط یک مدیر پردازه تعیین کنید
unit بعدی را روی هر سه VM ذخیره کنید. Patroni شروع و توقف فرزند PostgreSQL را مدیریت میکند. KillMode برابر process فرصت خاموش کردن کنترلشدهٔ فرزند را به Patroni میدهد. سرویسهای PostgreSQL و Patroni بسته نباید همزمان اجرا شوند. پیش از bootstrap اول، پوشهٔ data باید هنوز وجود نداشته باشد؛ basebackup برای ساخت standby است و نباید مقصد دادهٔ مفید باشد.
ماشین آزمایشی پایگاه داده؛ Bash با دسترسی مدیر
sudo nano /etc/systemd/system/academy-pg-patroni.service
unit کامل بعدی با ریشهٔ درست ذخیره شود.
قدم بعدی
فایل: مدیریت دیتابیس با Patroni
این unit آزمایش است. watchdog خاموش است و restart خودکار اثبات fencing نیست. تولید به watchdog یا fencing بررسیشده، حالت required با شکست امن، محدودیت منابع و آزمون واقعی partition و توقف پردازه با کنسول بازیابی نیاز دارد.
ماشین آزمایشی پایگاه داده؛ Bash با دسترسی مدیر
[Unit]
Description=Academy PostgreSQL18 Patroni lab
After=network-online.target academy-pg-etcd.service
Wants=network-online.target
[Service]
Type=simple
User=postgres
Group=postgres
UMask=0077
ExecStart=/usr/bin/patroni /srv/academy-pg18/patroni.yml
KillMode=process
TimeoutStopSec=120
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
یک مدیر چرخهٔ پردازه داریم و unit دیتابیس بسته فعال نیست.
قدم بعدی
ابتدا pg1 و بعد pg2 و pg3 را راهاندازی کنید
ابتدا روی pg1 و بعد روی pg2 و pg3 اجرا کنید. وجود sentinel، مسیر data غیرمنتظره یا سرویس فعال بسته مانع ادامه است. مقداردهی pg1 و ساخت standby دادهٔ تازه ایجاد میکند و وارد کردن دیتابیس موجود نیست. حالت همگام سختگیرانه تا آماده شدن replica همگام عمداً نوشتن را متوقف میکند. هنوز سرویس را برای بوت فعال نکنید؛ اول نقشها و روش بازیابی را بررسی کنید.
ماشین آزمایشی پایگاه داده؛ Bash با دسترسی مدیر
set -eu
sudo -u postgres python3 - <<'PY'
import json, pathlib
p=pathlib.Path('/srv/academy-pg18')
config=json.loads((p/'patroni.yml').read_text())
assert 'REPLACE_' not in json.dumps(config), 'Edit secrets privately first'
assert not (p/'data').exists(), 'Do not overwrite existing data'
PY
if systemctl is-active --quiet postgresql.service || systemctl is-active --quiet patroni.service; then exit 1; fi
sudo -u postgres patroni --validate-config '/srv/academy-pg18/patroni.yml'
sudo systemctl daemon-reload
sudo systemctl start academy-pg-patroni.service
sudo journalctl -u academy-pg-patroni.service -n 40 --no-pager
pg1 مقداردهی میشود و pg2 و pg3 با basebackup در مسیر تازه replica میشوند.
قدم بعدی
نقش، اعتماد API و بازپخش WAL را بررسی کنید
روی pg1 اجرا کنید. patronictl فایل حفاظتشده را میخواند و از mTLS و احراز هویت API استفاده میکند؛ تنظیم را چاپ نکنید. SQL محلی از peer روی سوکت خصوصی استفاده میکند؛ رپلیکیشن شبکه با نقش اختصاصی SCRAM و TLS verify-full است. درخواست API بدون گواهی کلاینت باید رد شود؛ خطای گواهی را با گزینهٔ insecure دور نزنید.
خروجی زیر نمونهٔ سادهشده برای خواندن نقشهاست؛ شناسه، LSN، timeline و تأخیر واقعی خودتان را ثبت کنید.
ماشین آزمایشی پایگاه داده؛ Bash با دسترسی مدیر
sudo -u postgres patronictl -c '/srv/academy-pg18/patroni.yml' list
sudo -u postgres psql -h '/srv/academy-pg18/socket' -p 5432 -d postgres -X -v ON_ERROR_STOP=1 -c "SELECT application_name,state,sync_state,write_lsn,flush_lsn,replay_lsn FROM pg_stat_replication;"
sudo -u postgres psql -h '/srv/academy-pg18/socket' -p 5432 -d postgres -X -c "SELECT slot_name,active,wal_status,restart_lsn FROM pg_replication_slots;"
sudo -u postgres curl --fail --cacert '/srv/academy-pg18/tls/ca.crt' --cert '/srv/academy-pg18/tls/api.crt' --key '/srv/academy-pg18/tls/api.key' 'https://10.77.18.11:8008/cluster'
sudo -u postgres curl --cacert '/srv/academy-pg18/tls/ca.crt' 'https://10.77.18.11:8008/health'
pg1 Leader running
pg2 Sync Standby streaming
pg3 Replica streaming
یک leader، یک standby همگام و replica دیگر؛ WAL در حالت streaming و کلاینت بدون گواهی رد میشود.
قدم بعدی
نشان آزمایشی بنویسید و روی standby بخوانید
فقط روی leader فعلی دیتابیس تازهٔ مخصوص این آزمایش را بسازید؛ دیتابیس موجود را استفاده نکنید. پنل بعدی روی pg2 و پس از رسیدن WAL فقط خواندنی است. برابر بودن ردیفها رپلیکیشن همین نشان را ثابت میکند و تضمین همهٔ خرابیها نیست. اگر pg2 از قبل leader است، پنل خواندن را روی standby واقعی اجرا کنید.
ماشین آزمایشی پایگاه داده؛ Bash با دسترسی مدیر
sudo -u postgres createdb -h '/srv/academy-pg18/socket' -p 5432 academy_replication_probe
sudo -u postgres psql -h '/srv/academy-pg18/socket' -p 5432 -d academy_replication_probe -X -v ON_ERROR_STOP=1 <<'SQL'
SET statement_timeout = '15s';
CREATE TABLE probe(id integer PRIMARY KEY, marker text NOT NULL);
INSERT INTO probe VALUES (1, 'before-switchover');
SELECT pg_current_wal_lsn();
SQL
نشان commit شده و LSN رهبر ثبت شده است؛ timeout نیاز به بررسی دارد، نه ارتقای اجباری.
قدم بعدی
وضعیت recovery و همان نشان را بخوانید
روی standby یعنی pg2 اجرا کنید. recovery باید true باشد و همان ردیف برسد. در دیتابیس بیکار، فاصلهٔ زمانی آخرین replay تضمین مناسبی برای lag صفر نیست؛ LSN و نشان برنامه را هم بررسی کنید.
ماشین آزمایشی پایگاه داده؛ Bash با دسترسی مدیر
sudo -u postgres psql -h '/srv/academy-pg18/socket' -p 5432 -d academy_replication_probe -X -v ON_ERROR_STOP=1 <<'SQL'
SELECT pg_is_in_recovery(), pg_last_wal_replay_lsn();
TABLE probe;
SELECT status,sender_host,sender_port FROM pg_stat_wal_receiver;
SQL
recovery برابر true، نشان 1 موجود و WAL receiver از رهبر واقعی streaming است.