├── HA-Postgres-Cluster ├── HA-Postgres-Cluster-Deployment-View.png └── Step-by-Step-Guide-to-Deploy-a-Highly-Available-Postgres-Cluster.md └── README.md /HA-Postgres-Cluster/HA-Postgres-Cluster-Deployment-View.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libremomo/devops-notes/01092c8a04f9d84ad35a1f316bd646bbd79db918/HA-Postgres-Cluster/HA-Postgres-Cluster-Deployment-View.png -------------------------------------------------------------------------------- /HA-Postgres-Cluster/Step-by-Step-Guide-to-Deploy-a-Highly-Available-Postgres-Cluster.md: -------------------------------------------------------------------------------- 1 |
2 | Highly Available Postgres Cluster - Deployment View 3 |
4 | 5 | # راهنمای گام به گام استقرار کلاستر پستگرس با معماری HA 6 | در راهنمای حاضر، شیوهٔ راه‌اندازی یک کلاستر پستگرس با معماری Highly Available را توضیح می‌دهیم. برای این کار لازم است چند نمونهٔ پستگرس مستقر کنیم و مدیریت مکانیزم همتاسازی (replication) پستگرس را به پاترونی (Patroni) بسپریم. برای آنکه پاترونی بتواند وضعیت کلاستر را در هر لحظه ثبت و پایش کند، نیاز داریم یک کلاستر etcd راه‌اندازی کنیم و آن را در اختیار پاترونی قرار دهیم. در نهایت ترافیک ورودی را از طریق HAProxy بین نودهای پستگرس توزیع می‌کنیم. 7 | 8 | ## ۶- ۱. پیش‌نیازها 9 | برای راه‌اندازی این کلاستر دست‌کم به ۵ نود احتیاج داریم. این ۵ نود می‌توانند ماشین‌های لینوکسی فیزیکی یا مجازی باشند. ما در این راهنما از ماشین‌های مجازی استفاده می‌کنیم. حداقل نیازمندی‌های سخت‌افزاری و نرم‌افزاری این ماشین‌ها در زیر آمده است: 10 | 11 | | No. | Hostname | Role | CPU (Cores) | RAM (GB) | Disk (GB) | NIC | IP | OS | 12 | | :-: | :-------: | :------------------: | :---------: | :------: | :-------: | :-: | :-------------: | :--------------: | 13 | | 1 | psql-db-1 | psql, patroni, etcd | 16 | 16 | 100 | 1 | 192.168.228.141 | Ubuntu 22.04 LTS | 14 | | 2 | psql-db-2 | psql, patroni, etcd | 16 | 16 | 100 | 1 | 192.168.228.142 | Ubuntu 22.04 LTS | 15 | | 3 | psql-db-3 | psql, patroni, etcd | 16 | 16 | 100 | 1 | 192.168.228.143 | Ubuntu 22.04 LTS | 16 | | 4 | psql-lb-1 | HAProxy, Keepalived | 4 | 8 | 25 | 1 | 192.168.228.144 | Ubuntu 22.04 LTS | 17 | | 5 | psql-lb-2 | HAProxy, Keepalived | 4 | 8 | 25 | 1 | 192.168.228.145 | Ubuntu 22.04 LTS | 18 | 19 | - این ماشین‌ها باید بتوانند از حیث شبکه‌‌ای همدیگر را ببینند. بهترین حالت آن است که همگی در یک سابنت قرار داشته باشند تا میزان تأخیر ارتباطات آنها به حداقل برسد و در عملیات replication اختلالی رخ ندهد. 20 | - لازم است یک آی‌پی دیگر نیز در همین سابنت برای استفاده به عنوان Floating IP کنار بگذاریم. (مثلاً: 192.168.228.140) 21 | - کلاستر پستگرس نیازمند آن است که تاریخ و ساعت در همهٔ نودها به درستی و دقت تنظیم شده باشد. پیش از شروع فرایند نصب، از هماهنگ شدن ساعت هر نود با زمان اینترنتی مطمئن شوید. 22 | 23 | ## ۶- ۲. نصب پستگرس روی نودها 24 | 25 | **تذکر:** 26 | آنچه در این قسمت مطرح می‌کنیم عیناً باید روی هر سه نود پستگرس (psql-db-1~3) اجرا شود. 27 | 28 | --- 29 | پستگرس نسخهٔ ۱۴ به صورت پیش‌فرض روی مخازن اوبونتو وجود دارد، اما ما از نسخهٔ ۱۷ استفاده می‌کنیم. برای نصب این نسخه بایستی نخست مخزن APT خود پستگرس را به ماشین‌ها اضافه کنیم. [طبق مستندات پستگرس](https://www.postgresql.org/download/linux/ubuntu/) از مسیر زیر اقدام ‌می‌کنیم: 30 | 31 | ```bash 32 | # Import the repository signing key: 33 | sudo apt install curl ca-certificates 34 | sudo install -d /usr/share/postgresql-common/pgdg 35 | sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc 36 | 37 | # Create the repository configuration file: 38 | sudo sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' 39 | ``` 40 | پس از ایجاد `pdgd.list` یک بار کش APT را به‌روزرسانی می‌کنیم: 41 | ```bash 42 | sudo apt update 43 | ``` 44 | در نهایت با فرمان زیر، پستگرس را نصب می‌کنیم: 45 | ``` 46 | sudo apt -y install postgresql-17 postgresql-server-dev-17 47 | ``` 48 | 49 | پس از اتمام عملیات، باید از صحت نصب مطمئن شویم. نخست محل باینری‌های پستگرس را بررسی می‌کنیم: 50 | ```bash 51 | which psql 52 | ``` 53 | خروجی فرمان بالا باید چنین باشد: 54 | ```bash 55 | /usr/sbin/psql 56 | ``` 57 | سپس، با فرمان زیر وضعیت سرویس پستگرس را بررسی می‌کنیم: 58 | ```bash 59 | sudo systemctl status postgresql 60 | ``` 61 | از آنجا که باید کنترل پستگرس را به پاترونی بسپریم، سرویس فعلی را که به صورت خودکار اجرا شده، متوقف می‌کنیم: 62 | ```bash 63 | sudo systemctl stop postgresql 64 | ``` 65 | پاترونی از برخی از ابزارهایی که همراه با پستگرس نصب می‌شوند استفاده می‌کند، در نتیجه لازم است یک پیوند نمادین (symlink) از باینری‌های آن در مسیر `/usr/sbin/` قرار دهیم تا مطمئن شویم پاترونی به آنها دسترسی خواهد داشت: 66 | ```bash 67 | ln -s /usr/lib/postgresql/17/bin/* /usr/sbin/ 68 | ``` 69 | 70 | ## ۶- ۳. نصب پاترونی روی نودها 71 | 72 | **تذکر:** 73 | آنچه در این قسمت مطرح می‌کنیم باید عیناً روی هر سه نود پستگرس (psql-db-1~3) اجرا شود. 74 | 75 | --- 76 | پاترونی یک بستهٔ متن‌باز پایتونی است که پیکربندی پستگرس را مدیریت می‌کند. پاترونی را می‌توان برای انجام وظایفی مانند همتاسازی، پشتیبان‌گیری، و بازیابی پایگاه‌های داده تنظیم کرد. در این راهنما از پاترونی برای موارد زیر استفاده می‌کنیم: 77 | - پیکربندی نمونهٔ پستگرسی که روی همان سرور اجرا می‌شود 78 | - پیکربندی همتاسازی داده‌ها از روی نود پستگرس اصلی (primary) به نودهای آماده‌به‌کار (standby) 79 | - انتخاب نود اصلی جدید به صورت خودکار (automatic failover) در صورت افتادن نود اصلی فعلی 80 | 81 | برای نصب پاترونی از دستور زیر استفاده می‌کنیم: 82 | ```bash 83 | sudo apt install patroni 84 | ``` 85 | پس از آن، پکیج `python3-psycopg2` را هم نصب می‌کنیم.`Psycopg` آداپتور پستگرس برای پایتون است و برنامه‌های پایتونی و پایگاه‌های دادهٔ پستگرس را به هم متصل می‌کند: 86 | ```bash 87 | sudo apt install python3-psycopg2 88 | ``` 89 | پس از اتمام نصب، مسیر باینری‌ها و نسخهٔ پاترونی را با دستورهای زیر را بررسی می‌کنیم: 90 | ```bash 91 | which patroni 92 | 93 | patroni --version 94 | ``` 95 | ## ۶- ۴. نصب etcd روی نودها 96 | پیش از آنکه نودهای پاترونی را پیکربندی کنیم، لازم است زیرساخت لازم برای ثبت و نگهداری وضعیت کلاستر پستگرس راه‌اندازی کنیم. برای این منظور از etcd که یک پایگاه دادهٔ کلید-مقداری است، به منزلهٔ مخزن توزیع‌شده پیکربندی (DCS) استفاده می‌کنیم. برای اینکه این مخزن در برابر بروز خطا تاب‌آوری داشته باشد و بتواند در صورت از کار افتادن یک نود به کار خود ادامه دهد، لازم است که روی هر سه نود یک نمونه etcd راه‌اندازی کنیم و هر سه را با هم تبدیل به یک کلاستر کنیم. توجه کنید که در کلاستر etcd از الگوریتم Raft برای اجماع و انتخاب رهبر استفاده می‌شود، در نتیجه لازم است حتماً تعداد نودها **فرد** باشد. 97 | 98 | برای نصب etcd و پکیج‌های مورد نیاز دیگر از دستور زیر استفاده می‌کنیم: 99 | ```bash 100 | sudo apt install etcd-server etcd-client python3-etcd 101 | ``` 102 | - پکیج `etcd-server` حاوی باینری‌های دیمن etcd است. 103 | - پکیج `etcd-client` حاوی باینری‌های کلاینت etcd است. 104 | - پکیج `python3-etcd` یک کلاینت پایتونی برای تعامل با etcd است که به برنامه های پایتونی اجازه می‌دهد تا با خوشه های etcd ارتباط برقرار کرده و مدیریت کنند. 105 | 106 | --- 107 | **تذکر:** 108 | عملیات بالا را باید عیناً روی هر سه نود پستگرس (psql-db-1~3) اجرا کرد. 109 | 110 | --- 111 | ## ۶- ۵. پیکربندی نودهای etcd 112 | برای پیکربندی هر نود etcd، لازم است نخست فایل‌هایی که در شاخهٔ `/var/lib/etcd/` قرار دارد را پاک می‌کنیم. وجود فایل‌های پیش‌فرض در این مسیر باعث می‌شود نودهای etcd همگی با یک UUID یکسان ایجاد شوند و به همین خاطر نتوانند یکدیگر را به عنوان اعضای یک کلاستر شناسایی کنند: 113 | ```bash 114 | sudo rm -rf /var/lib/etcd/* 115 | ``` 116 | سپس فایلی را که در مسیر `etc/default/etcd/` قرار دارد در ویرایشگر باز می‌کنیم و خطوط زیر را به آن می‌افزاییم. تنها لازم است مقدار `etcd-node-name` و `etcd-node-ip` را برای هر نود مطابق جدول زیر در آن جایگذاری کنیم. 117 | 118 | | etcd-node-name | etcd-node-ip | 119 | | ---------------| -------------| 120 | |etcd-1 | 192.168.228.141 | 121 | |etcd-2 | 192.168.228.142 | 122 | |etcd-3 | 192.168.228.143 | 123 | 124 | 125 | ``` 126 | ETCD_NAME="" 127 | ETCD_LISTEN_PEER_URLS="http://:2380" 128 | ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://:2379" 129 | ETCD_INITIAL_ADVERTISE_PEER_URLS="http://:2380" 130 | ETCD_INITIAL_CLUSTER="etcd-1=http://192.168.228.141:2380,etcd-2=http://192.168.228.142:2380,etcd-3=http://192.168.228.143:2380" 131 | ETCD_ADVERTISE_CLIENT_URLS="http://:2379" 132 | ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" 133 | ETCD_INITIAL_CLUSTER_STATE="new" 134 | ``` 135 | پس از اتمام ویرایش فایل پیکربندی، سرویس etcd را بازنشانی می‌کنیم: 136 | ```bash 137 | sudo systemctl restart etcd 138 | ``` 139 | پس از بازنشانی، وضعیت سرویس را از طریق فرمان‌های زیر چک می‌کنیم: 140 | ```bash 141 | sudo systemctl is-enabled etcd 142 | sudo systemctl status etcd 143 | ``` 144 | خروجی فرمان اول باید `enabled` و خروجی فرمان دوم باید `active (running)` باشد. اکنون می‌توانیم با فرمان زیر بررسی کنیم که آ‌یا کلاستر به درستی شکل گرفته است یا نه: 145 | ```bash 146 | etcdctl member list 147 | ``` 148 | خروجی این فرمان مشابه این خواهد بود: 149 | ```bash 150 | 38c2f5960a646674: name=etcd-3 peerURLs=http://192.168.228.143:2380 clientURLs=http://192.168.228.143:2379 isLeader=true 151 | 152 | 659f84d35a13cf2f: name=etcd-1 peerURLs=http://192.168.228.141:2380 clientURLs=http://192.168.228.141:2379 isLeader=false 153 | 154 | 731fb9c8c2f57b00: name=etcd-2 peerURLs=http://192.168.228.142:2380 clientURLs=http://192.168.228.142:2379 isLeader=false 155 | ``` 156 | **نکته:** اگر پکیج `etcd-client` را نصب نکرده باشید نیز می‌توانید از فرمان زیر استفاده کنید: 157 | ```bash 158 | curl http://:2380/members 159 | ``` 160 | همان‌طور مشخص است کلاستر etcd به درستی شکل گرفته است و نودها همدیگر را شناخته‌اند و یک نود را به عنوان رهبر انتخاب کرده‌اند. اکنون می‌توانیم پیکربندی پاترونی را آغاز کنیم. 161 | 162 | ## ۶- ۶. پیکربندی نودهای پاترونی 163 | پیکربندی پاترونی مهم‌ترین بخش راه‌اندازی یک کلاستر Highly Available پستگرس است. بنابر این، بخش‌های مختلف آن را گام به گام اضافه می‌کنیم و پارامتر هر بلاک را جداگانه توضیح می‌دهیم. 164 | 165 | --- 166 | **تذکر:** 167 | - پیکربندی پاترونی باید روی هر نود پستگرس به صورت جداگانه صورت پذیرد. 168 | - نمونهٔ کاملی از فایل پیکربندی پاترونی را می‌توان در مخزن [گیتهاب پاترونی](https://github.com/patroni/patroni/blob/master/postgres0.yml) پیدا کرد. 169 | 170 | --- 171 | نخست، فایل `etc/patroni/config.yml/` را در ویرایشگر دلخواهمان باز می‌کنیم و پیکربندی زیر را به آن می‌افزاییم. در قسمت `name` باید `hostname` هر نود پستگرس را بنویسیم. مثلاً برای نود ۱، `dc1-psql-db-1` را قرار می‌دهیم و برای ۲ نود دیگر نیز به همین ترتیب عمل می‌کنیم: 172 | ```yml 173 | scope: postgres 174 | namespace: /db/ 175 | name: 176 | ``` 177 | آدرس API پاترونی را تکمیل می‌کنیم. به جای `` آی‌‌پی هر نود را وارد می‌کنیم: 178 | ```yml 179 | restapi: 180 | listen: :8008 181 | connect_address: :8008 182 | ``` 183 | آدرس آی‌پی و پورت نودهای کلاستر etcd را به پاترونی می‌دهیم: 184 | ```yml 185 | etcd: 186 | hosts: 192.168.228.141:2379,192.168.228.142:2379,192.168.228.143:2379 187 | ``` 188 | سپس پیکربندی‌های زیر را به بخش `bootstrap` می‌افزاییم. در این بخش تعریف می‌کنیم که نود پستگرس باید در هنگام راه‌اندازی اولیه از چه مقادیر و تنظیمات پیش‌فرضی استفاده کند. همچنین نحوهٔ تعامل پاترونی با مخزن توزیع‌شده پیکربندی (DCS) یا همان etcd را در اینجا تنظیم می‌کنیم: 189 | ```yml 190 | bootstrap: 191 | dcs: 192 | # Time-to-live for the leader lock, in seconds. 193 | ttl: 30 194 | # Number of seconds to wait between checks on the cluster state. 195 | loop_wait: 10 196 | # Timeout for DCS and PostgreSQL operations, in seconds. 197 | retry_timeout: 10 198 | # Maximum allowed lag in bytes for a follower to be considered as a candidate for promotion. 199 | maximum_lag_on_failover: 1048576 200 | postgresql: 201 | # Enables the use of pg_rewind for faster failover recovery. 202 | use_pg_rewind: true 203 | # Uses replication slots, which ensures that the primary does not remove WAL segments needed by replicas. 204 | use_slots: true 205 | parameters: 206 | # Enables hot standby mode and ensures that enough info is written to the WAL to support a robust HA setup. 207 | wal_level: hot_standby 208 | # Allows read-only queries on standby servers. 209 | hot_standby: "on" 210 | # Maximum number of concurrent connections. 211 | max_connections: 100 212 | # Maximum number of background worker processes. 213 | max_worker_processes: 8 214 | # Minimum number of past log file segments to keep for standby servers. 215 | wal_keep_segments: 8 216 | # Maximum number of concurrent connections for streaming replication. 217 | max_wal_senders: 10 218 | # Maximum number of replication slots. 219 | max_replication_slots: 10 220 | # Maximum number of prepared transactions (0 disables the feature). 221 | max_prepared_transactions: 0 222 | # Maximum number of locks per transaction. 223 | max_locks_per_transaction: 64 224 | # Logs additional information in the WAL to support pg_rewind. 225 | wal_log_hints: "on" 226 | # Disables tracking of commit timestamps. 227 | track_commit_timestamp: "off" 228 | # Enables WAL archiving. 229 | archive_mode: "on" 230 | # Forces a switch to a new WAL file if a new file hasn't been started within 1800 seconds. 231 | archive_timeout: 1800s 232 | # Command to archive WAL files. This command creates a directory named 'wal_archive', checks if the file doesn't already exist, and then copies it 233 | archive_command: mkdir -p ../wal_archive && test ! -f ../wal_archive/%f && cp %p ../wal_archive/%f 234 | recovery_conf: 235 | # Command used to retrieve archived WAL files during recovery. It copies files from the 'wal_archive' directory. 236 | restore_command: cp ../wal_archive/%f %p 237 | initdb: 238 | # Sets the default authentication method 239 | - auth: scram-sha-256 240 | # Sets the default character encoding for the database to UTF-8, which supports a wide range of characters. 241 | - encoding: UTF8 242 | # Enables data checksums on this cluster, which helps detect corruption caused by hardware or I/O subsystem faults. 243 | - data-checksums 244 | ``` 245 | 246 | در ادامه نحوهٔ احراز هویت کلاینت‌های کلاستر را تعیین می‌کنیم (`pg_hba.conf`) و به کاربر ‍`replicator` که برای همتاسازی بین نودهای کلاستر از آن استفاده می‌شود، اجازه می‌دهیم که با مکانیزم `scram-sha-256` که امن‌ترین شیوه احراز هویت از طریق رمز عبور است، به نودهای کلاستر پستگرس دسترسی پیدا کند. رمز عبور کاربر `admin` را نیز در ادامهٔ همین قسمت تعیین کرده و آن را جایگزین `` می‌کنیم: 247 | ```yml 248 | # This section configures the pg_hba.conf file, which controls client authentication for PostgreSQL. 249 | pg_hba: 250 | - host replication replicator 127.0.0.1/32 scram-sha-256 251 | - host replication replicator 192.168.228.141/0 scram-sha-256 252 | - host replication replicator 192.168.228.142/0 scram-sha-256 253 | - host replication replicator 192.168.228.143/0 scram-sha-256 254 | - host all all 0.0.0.0/0 scram-sha-256 255 | 256 | # This section defines database users and their properties. 257 | users: 258 | admin: 259 | password: 260 | options: 261 | - createrole 262 | - createdb 263 | ``` 264 | 265 | سپس، باقی‌ماندهٔ تنظیمات پستگرس و پاترونی، مانند آدرس پستگرس در هر نود، رمز عبور کاربر `replicator` و `postgres`، و ... را وارد کرده و تغییرات را ذخیره می‌کنیم. 266 | ```yml 267 | postgresql: 268 | # Specifies the IP address and port on which PostgreSQL should listen for connections. 269 | listen: :5432 270 | # The address and port other nodes should use to connect to this instance. 271 | connect_address: :5432 272 | # The directory where PostgreSQL will store its data files. 273 | data_dir: /var/lib/patroni/ 274 | # The location of the .pgpass file, which stores passwords for non-interactive connections. 275 | pgpass: /tmp/pgpass 276 | 277 | # This defines authentication details for different types of connections. 278 | authentication: 279 | replication: 280 | username: replicator 281 | password: 282 | superuser: 283 | username: postgres 284 | password: 285 | 286 | parameters: 287 | # Sets the current directory as the location for Unix-domain sockets. 288 | unix_socket_directories: '.' 289 | password_encryption: 'scram-sha-256' 290 | 291 | # These are Patroni-specific tags that control various behaviors 292 | tags: 293 | # Allows this node to be considered for failover. 294 | nofailover: false 295 | # Allows this node to be considered for load balancing. 296 | noloadbalance: false 297 | # This node will not be used as a preferred source when adding new nodes. 298 | clonefrom: false 299 | # Allows this node to be considered for synchronous replication. 300 | nosync: false 301 | ``` 302 | 303 | پس از اتمام ویرایش فایل `config.yml` لازم است مالکیت شاخه‌ای را که برای ذخیره‌سازی داده‌های پاترونی در نظر گرفتیم (`/var/lib/patroni/`) به کاربر`postgres` انتقال بدهیم و دسترسی خواندن و نوشتن را فقط به مالک شاخه محدود کنیم: 304 | ```bash 305 | mkdir -p /var/lib/patroni 306 | 307 | chown -R postgres:postgres /var/lib/patroni 308 | 309 | chmod 700 /var/lib/patroni 310 | ``` 311 | 312 | اکنون می‌توانیم سرویس پاترونی را روی هر سه نود راه‌اندازی کنیم. با این کار، نود اول به عنوان رهبر انتخاب شده و دو نود دیگر از طریق API پاترونی به آن می‌پیوندند. 313 | ```bash 314 | systemctl start patroni 315 | systemctl status patroni 316 | ``` 317 | --- 318 | **تذکر:** 319 | چنانچه پس از راه‌اندازی اولیه لازم شد در پارامترهای قسمت `bootstrap.dcs` تغییری ایجاد کنیم، باید از دستور ‍`patronictl edit-config` استفاده کنیم. 320 | 321 | --- 322 | 323 | برای بررسی نهایی نودهای پستگرسی که پاترونی مدیریت می‌کند، فرمان زیر را روی یکی از نودها اجرا کنید: 324 | ```bash 325 | patronictl -c /etc/patroni/config.yml list 326 | ``` 327 | 328 | خروجی آن باید چنین چیزی باشد: 329 | ``` 330 | + Cluster: postgres (7422247765142374405) --+-----------+----+-----------+ 331 | | Member | Host | Role | State | TL | Lag in MB | 332 | +---------------+-----------------+---------+-----------+----+-----------+ 333 | | dc1-psql-db-1 | 192.168.228.141 | Leader | running | 1 | | 334 | | dc1-psql-db-2 | 192.168.228.142 | Replica | streaming | 1 | 0 | 335 | | dc1-psql-db-3 | 192.168.228.143 | Replica | streaming | 1 | 0 | 336 | +---------------+-----------------+---------+-----------+----+-----------+ 337 | ``` 338 | 339 | در نهایت اجرای اتوماتیک سرویس پستگرس را پس از بوت شدن مجدد سیستم غیرفعال می‌کنیم تا کنترل کلاستر پستگرس در دست پاترونی باقی بماند. اگر اجرای این فرمان موفقیت‌آمیز باشد، خروجی خاصی نخواهد داشت: 340 | ```bash 341 | sudo systemctl disable --now postgresql 342 | ``` 343 | ## ۶- ۷. نصب و پیکربندی HAProxy 344 | پس از استقرار موفقیت‌آمیز کلاستر پستگرس باید ترافیک کلاینت‌ها را بین نودها توزیع کنیم. برای این منظور لازم است از لودبالانسرهای لایهٔ ۴ مانند HAProxy بالای سر کلاستر استفاده کنیم. در محیط‌های تست و توسعه می‌شود HAProxy را مستقیماً بر روی نودهای پستگرس نصب کرد. اما در محیط پروداکشن به دلایل زیر لازم است نودهای مجزایی برای آن در نظر بگیریم: 345 | - **عملکرد**: پستگرس، به‌ویژه زمانی که تحت فشار زیادی باشد، منابع زیادی مصرف می‌کند. از این‌رو، اختصاص دادن ماشین‌های مجزا به لودبالانسر به ما اطمینان می‌دهد که عملکرد دیتابیس بابت عملیات توزیع بار تحت تأثیر قرار نمی‌گیرد. 346 | - **قابلیت نگهداری**: در نظر گرفتن ماشین‌های مجزا برای لودبالانسر به ما امکان می‌دهد که تعمیر، به‌روزرسانی و عیب‌یابی در لایهٔ توزیع بار را بدون درگیر کردن نودهای پستگرس انجام بدهیم. 347 | - **مقیاس‌پذیری**: به اقتضای مقیاس‌پذیری ممکن است لازم باشد لایهٔ توزیع بار را به نحو متفاوتی نسبت به لایهٔ دیتابیس گسترش بدهیم. داشتن ماشین‌های مجزا این انعطاف‌پذیری را به ما می‌دهد. 348 | - **امنیت**: با استفاده از نودهای مجزا برای توزیع بار می‌توانیم در صورت لزوم معماری شبکهٔ ایمن‌تری را اجرا کنیم و از یک سو، نودهای دیتابیس را در یک شبکهٔ خصوصی بگذاریم و از سوی دیگر، نودهای HAProxy را در دسترسی لایه‌ٔ اپلیکیشن قرار بدهیم. 349 | --- 350 | **تذکر:** 351 | نصب و پیکربندی HAProxy باید عیناً روی هر کدام از نودهای توزیع بار صورت پذیرد. 352 | 353 | --- 354 | برای نصب HAProxy از فرمان زیر استفاده می‌کنیم: 355 | ```bash 356 | sudo apt update 357 | sudo apt install haproxy 358 | ``` 359 | پس از اتمام نصب، در ابتدا از فایل پیکربندی پیش فرض HAProxy یک پشتیبان درست می‌کنیم: 360 | ```bash 361 | mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.orig 362 | ``` 363 | سپس فایل جدیدی به نام `etc/haproxy/haproxy.cfg/` ایجاد می‌کنیم و خطوط زیر را به آن اضافه می‌کنیم: 364 | ``` 365 | # Global configuration settings 366 | global 367 | # Maximum connections globally 368 | maxconn 100 369 | # Logging settings 370 | log 127.0.0.1 local2 371 | 372 | # Default settings 373 | defaults 374 | # Global log configuration 375 | log global 376 | # Set mode to TCP 377 | mode tcp 378 | # Number of retries 379 | retries 2 380 | # Client timeout 381 | timeout client 30m 382 | # Connect timeout 383 | timeout connect 4s 384 | # Server timeout 385 | timeout server 30m 386 | # Check timeout 387 | timeout check 5s 388 | 389 | # Stats configuration 390 | listen stats 391 | # Set mode to HTTP 392 | mode http 393 | # Bind to port 8080 394 | bind *:8080 395 | # Enable stats 396 | stats enable 397 | # Stats URI 398 | stats uri / 399 | 400 | # PostgreSQL configuration 401 | listen production 402 | # Bind to port 5000 403 | bind *:5000 404 | # Enable HTTP check 405 | option httpchk OPTIONS/master 406 | # Expect status 200 407 | http-check expect status 200 408 | # Server settings 409 | default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions 410 | # Define PostgreSQL servers 411 | server dc1-psql-db-1 192.168.228.141:5432 maxconn 100 check port 8008 412 | server dc1-psql-db-2 192.168.228.142:5432 maxconn 100 check port 8008 413 | server dc1-psql-db-3 192.168.228.143:5432 maxconn 100 check port 8008 414 | listen standby 415 | bind *:5001 416 | option httpchk OPTIONS/replica 417 | http-check expect status 200 418 | default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions 419 | server dc1-psql-db-1 192.168.228.141:5432 maxconn 100 check port 8008 420 | server dc1-psql-db-2 192.168.228.142:5432 maxconn 100 check port 8008 421 | server dc1-psql-db-3 192.168.228.143:5432 maxconn 100 check port 8008 422 | ``` 423 | 424 | بر اساس پیکربندی فوق هر نود HAProxy روی پورت `5000` منتظر دریافت کانکشن‌ها به نود Primary و روی پورت `5001` منتظر دریافت کانکشن‌ها به نودهای replica است. بنابر این اکنون می‌توان درخواست‌های write را به نود اصلی فرستاد اما درخواست‌های read را به صورت roundrobin میان سه سروری که در انتهای پیکربندی به عنوان بک‌اند تعریف شده‌اند، توزیع کرد. 425 | علاوه بر این، طبق تنظیمات بلاک `listen stats`، داشبورد وضعیت HAProxy روی پورت `8080` قابل دسترس خواهد بود. در تنظیمات هر دو بلاک `listen production` و `listen standby`، در بخش `default-server` نیز پارامترهایی معین شده که رفتار HAProxy را در قبال سرورهای بک‌اند تعیین می‌کند: 426 | - فاصلهٔ زمانی بین چک‌های سلامتی ۳ ثانیه است (`inter 3s`). 427 | - اگر چک سلامتی ۳ بار پیاپی ناموفق باشد، آن نود به عنوان نود افتاده در نظر گرفته می‌شود (`fall 3`). 428 | - اگر چک سلامتی ۲ بار پیاپی موفق باشد، آن نود مجدداً برقرار در نظر گرفته می‌شود (`rise 2`). 429 | - اگر یک سرور به عنوان افتاده در نظر گرفته شود، HAProxy بلافاصله تمامی سشن‌های آن سرور را می‌بندد. این امر کمک می‌کند که سرورهای معیوب به سرعت کنار بروند و ترافیک به سروهای سالم هدایت شود (‍‍`on-marked-down shutdown-sessions`). 430 | 431 | اکنون می‌توان سرویس HAProxy را به کار انداخت و صحت آن را بررسی کرد: 432 | ```bash 433 | sudo systemctl restart haproxy 434 | sudo systemctl status haproxy 435 | ``` 436 | چنانچه راه‌اندازی سرویس ناموفق بود، با دستور زیر خطاهای فایل پیکربندی را بررسی کنید: 437 | ```bash 438 | /usr/sbin/haproxy -c -V -f /etc/haproxy/haproxy.cfg 439 | ``` 440 | ## ۶- ۸. نصب و پیکربندی Keepalived 441 | برای آنکه نودهای توزیع بار بتوانند در یک حالت Highly Available کار کنند و در صورت بروز عیب در یکی از آنها، نود دیگر بتواند به کار ادامه دهد لازم است یک آی‌پی شناور بین آنها وجود داشته باشد که در هر لحظه فقط روی یکی از آن دو نود فعال باشد و ترافیک پروداکشن به سمت آن هدایت شود. برای این منظور از Keepalived می‌کنیم. 442 | برای نصب Keepalived روی نودهای توزیع بار از فرمان زیر استفاده می‌کنیم: 443 | ```bash 444 | sudo apt install keepalived 445 | ``` 446 | پس از نصب، هر کدام از نودها را جداگانه پیکربندی می‌کنیم. پیکربندی نود اول (`192.168.228.144`) را در مسیر `etc/keepalived/keepalived.conf/` به این صورت انجام می‌دهیم: 447 | ``` 448 | global_defs { 449 | } 450 | vrrp_script chk_haproxy { 451 | script "/usr/bin/killall -0 haproxy" 452 | interval 2 453 | weight 2 454 | } 455 | vrrp_instance VI_1 { 456 | interface ens33 457 | state MASTER 458 | priority 101 # 101 on master, 100 on backup 459 | virtual_router_id 51 460 | advert_int 1 461 | authentication { 462 | auth_type PASS 463 | auth_pass 464 | } 465 | virtual_ipaddress { 466 | 192.168.228.140 467 | } 468 | unicast_src_ip 192.168.228.144 # This haproxy node 469 | unicast_peer { 470 | 192.168.228.145 # Other haproxy nodes 471 | } 472 | track_script { 473 | chk_haproxy 474 | } 475 | } 476 | ``` 477 | به طریق مشابه پیکربندی نود دوم (`192.168.228.145`) را در همان مسیر `etc/keepalived/keepalived.conf/` به این صورت انجام می‌دهیم: 478 | ``` 479 | global_defs { 480 | } 481 | vrrp_script chk_haproxy { 482 | script "/usr/bin/killall -0 haproxy" 483 | interval 2 484 | weight 2 485 | } 486 | vrrp_instance VI_1 { 487 | interface ens33 488 | state BACKUP 489 | priority 100 490 | virtual_router_id 51 491 | advert_int 1 492 | authentication { 493 | auth_type PASS 494 | auth_pass 495 | } 496 | virtual_ipaddress { 497 | 192.168.228.140 498 | } 499 | unicast_src_ip 192.168.228.145 # This haproxy node 500 | unicast_peer { 501 | 192.168.228.144 # Other haproxy nodes 502 | } 503 | track_script { 504 | chk_haproxy 505 | } 506 | } 507 | ``` 508 | در هر دو پیکربندی بالا باید این نکات توجه کرد: 509 | - در قسمت `interface` نام کارت شبکهٔ هر ماشین را بنویسید. 510 | - مقدار `virtual_router_id` یک عدد انتخابی است اما بین همهٔ نودهای Keepalived باید یکسان باشد. 511 | - رمزی که برای ارتباط دو نود Keepalived به جای `` قرار داده می‌شود باید در هر دو نود یکسان باشد. 512 | - آی‌پی شناور (`virtual_ipaddress`) در هر دو پیکربندی یکسان و برابر با `192.168.228.140` است. 513 | - در هر نود، `unicast_src_ip` معادل با آی‌پی همان نود و `unicast_peer` فهرستی از نودهای دیگر Keepalived است. هر کدام از آیپی‌های دیگر را باید در یک خط نوشت. 514 | 515 | پس ذخیره کردن پیکربندی Keepalived در هر دو نود می‌توانیم سرویس آن را فعال کنیم: 516 | ```bash 517 | sudo systemctl start keepalived 518 | sudo systemctl enable keepalived 519 | ``` 520 | درستی عملکرد Keepalived را نخست با بررسی وضعیت سرویس از طریق فرمان زیر: 521 | ```bash 522 | sudo systemctl status keepalived 523 | ``` 524 | و سپس از طریق بررسی آی‌پی‌های کارت شبکه با فرمان `ip a` متوجه می‌شویم. چنانچه نود ۱ علاوه بر آی‌پی خودش، آی‌پی شناور را نیز دریافت کرده باشد یعنی راه‌اندازی Keepalived به درستی انجام شده و مراحل راه‌اندازی کلاستر Highly Available پستگرس با ۳ نود دیتابیس و ۲ نود توزیع‌کنندهٔ بار به موفقیت به پایان رسیده است. هم اکنون می‌توانیم از آدرس `192.168.228.140:5000` برای درخواست‌های read/write و از `192.168.228.140:5001` برای درخواست‌های read-only استفاده کنیم. 525 | 526 | ## ۶- ۹. تست عملکرد 527 | برای تست عملیات failover، داشبورد HAProxy را که روی آدرس `192.168.228.140:8080` در دسترس است، باز می‌کنیم. دقت کنید که پورت 8080 را قبلاً خودمان در پیکربندی HAProxy تعیین کرده‌ایم و آی‌پی شناور نیز به همیشه ما را به آن نود HAProxy که ترافیک پروداکشن روی آن جریان دارد هدایت می‌کند. ذیل جدول `postgres` فهرست نودهای بک‌اند را مشاهده می‌کنید. نود اول که اکنون به عنوان primary عمل می‌کند سبز رنگ و `up` است و دو نود دیگر که در حالت streaming قرار دارند قرمز و `down` نشان داده می‌شوند. 528 | اکنون با دستور زیر نود ۱ را از مدار خارج می‌کنیم: 529 | ```bash 530 | sudo systemctl stop patroni 531 | ``` 532 | سپس وضعیت پاترونی را با دستور زیر چک می‌کنیم: 533 | ```bash 534 | patronictl -c /etc/patroni/config.yml list 535 | ``` 536 | خروجی باید چنین چیزی باشد: 537 | ``` 538 | + Cluster: postgres (7422247765142374405) --+-----------+----+-----------+ 539 | | Member | Host | Role | State | TL | Lag in MB | 540 | +---------------+-----------------+---------+-----------+----+-----------+ 541 | | dc1-psql-db-1 | 192.168.228.141 | Replica | stopped | | unknown | 542 | | dc1-psql-db-2 | 192.168.228.142 | Replica | running | 1 | 0 | 543 | | dc1-psql-db-3 | 192.168.228.143 | Leader | running | 2 | | 544 | +---------------+-----------------+---------+-----------+----+-----------+ 545 | ``` 546 | 547 | اکنون اگر به داشبود HAProxy بازگردید، خواهید دید که نود اول `DOWN` شده و به جای آن یکی از دو نود دوم و سوم `UP` شده است. در نهایت، زمانی که نود ۱ را دوباره به کلاستر برگردانید، به عنوان standby با نود primary همگام‌سازی خواهد شد. 548 | 549 | ## ۶- ۱۰. پیوندها 550 | - [Streaming Replication Protocol - PostgreSQL Documentation](https://www.postgresql.org/docs/current/protocol-replication.html) 551 | - [Patroni GitHub Repo](https://github.com/patroni/patroni/tree/master) 552 | ## ۶- ۱۱. منابع 553 | - [High Availability PostgreSQL with Patroni and HAProxy - ATA Learning ](https://adamtheautomator.com/patroni/) 554 | - [PostgreSQL HA Architecture - Mahmut Can Uçanefe](https://medium.com/@c.ucanefe/patroni-ha-proxy-feed1292d23f) 555 | - [Create a Highly Available PostgreSQL Cluster Using Patroni and HAProxy - Linode Docs](https://www.linode.com/docs/guides/create-a-highly-available-postgresql-cluster-using-patroni-and-haproxy/) 556 | - [Highly Available PostgreSQL Cluster using Patroni and HAProxy - JFrog Community](https://jfrog.com/community/devops/highly-available-postgresql-cluster-using-patroni-and-haproxy/) 557 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # devops-notes 2 | A repository for technical documentation, deployment guides, and system architecture references. 3 | --------------------------------------------------------------------------------