Postgres có tính sẵn sàng cao với Patroni/ Spilo (Phần 1)

1258
04-12-2023
Postgres có tính sẵn sàng cao với Patroni/ Spilo (Phần 1)

Bất kỳ hệ thống nào, cho dù là Ứng dụng, Trang web, Công nhân/Người tiêu dùng, Cơ sở dữ liệu, … khi được xem là quan trọng thì công việc cần đảm bảo tính sẵn sàng cao (Tính sẵn sàng cao) vẫn luôn là tiêu chuẩn được đưa ra mỗi khi khai triển. Ngày hôm nay, mình muốn nói về High Availability cho Postgres bởi vì:

  • Postgres chưa được hỗ trợ chính thức cho High Availability
  • Có rất nhiều công cụ hỗ trợ của bên thứ 3 để xây dựng hệ thống Tính sẵn sàng cao cho Postgres

Trong khoảng thời gian gần đây, cô ấy đã tìm thấy một bài toán liên quan đến Postgres và yêu cầu bài toán là xây dựng phương án, giải pháp cho công việc Postgres có thể lăn ra dừng hoạt động bất cứ lúc nào. Sau khi tham khảo ý kiến của anh em System/ Cloud Engineer hay Devops thì mình thấy công việc sử dụng Patroni (Spilo) là một giải pháp hoàn thiện để xây dựng hệ thống High Availability cho Postgres.

Vậy thì cách phát triển khai báo và kết nối ở đây như thế nào?

1. Patroni/ Spilo là gì?

Theo như tài liệu thì Patroni được mô tả như sau:

Patroni là mẫu dành cho các giải pháp PostgreSQL có tính sẵn sàng cao (HA) sử dụng Python. Patroni có nguồn gốc là một nhánh của Thống đốc , một dự án từ Compose. Nó bao gồm nhiều tính năng mới

và Spilo được mô tả như sau:

Để biết ví dụ về triển khai dựa trên Docker với Patroni, hãy xem Spilo , hiện đang được sử dụng tại Zalando.

Tóm tắt lại, Patroni được sử dụng để phát triển HA cho Postgres. Tuy nhiên, theo đánh giá của mình thì Spilo nên được lựa chọn là phương án phát triển mà chúng ta ưu tiên sử dụng.

2. Khai báo Mô hình phát triển

Dưới đây là mô hình mà mình sẽ thực hiện phát triển khai:

Postgres có tính sẵn sàng cao với Patroni/ Spilo (Phần 1) - Ảnh 1.

in which:

  • ETCD là thành phần khóa phân phối được sử dụng cho Patroni và được cấu hình kết nối với nhau như một cụm ETCD

Các thành phần Postgres, Patroni & ETCD được cài đặt cùng nhau trên một máy chủ nhắm mục tiêu cho việc phức hợp hóa mô hình hệ thống và tiết kiệm chi phí, giảm thiểu rủi ro phát hiện sinh học trong tương lai.

2. Cấu hình

2.1 Khởi tạo ban đầu

  • Sau khi chúng tôi cài đặt cụm ETCD và Postgres thành công. Chúng ta có thể cài đặt bảo trợ như sau:
    apt -y install python3 python3-pip python3-dev libpq-dev  pip3 install setuptools psycopg2>=3.0.0 patroni[etcd3,raft] 
  • Tạo dịch vụ tập tin /lib/systemd/system/patroni.servicecho người bảo trợ
    [Unit] Description=Runners to orchestrate a high-availability PostgreSQL After=network.target ConditionPathExists=/etc/patroni/config.yml  [Service] Type=simple  User=postgres Group=postgres  # Read in configuration file if it exists, otherwise proceed EnvironmentFile=-/etc/patroni_env.conf  WorkingDirectory=~  # Pre-commands to start watchdog device # Uncomment if watchdog is part of your patroni setup #ExecStartPre=-/usr/bin/sudo /sbin/modprobe softdog #ExecStartPre=-/usr/bin/sudo /bin/chown postgres /dev/watchdog  # Start the patroni process ExecStart=/usr/bin/patroni /etc/patroni/config.yml  # Send HUP to reload from patroni.yml ExecReload=/bin/kill -s HUP $MAINPID  # only kill the patroni process, not it's children, so it will gracefully stop postgres KillMode=process  # Give a reasonable amount of time for the server to start up/shut down TimeoutSec=30  # Do not restart the service if it crashes, we want to manually inspect database on failure Restart=no  [Install] WantedBy=multi-user.target 
  • Tạo file config /etc/patroni/config.ymlcho người bảo trợ như sau

    bootstrap:   dcs:     failsafe_mode: true     loop_wait: 15     maximum_lag_on_failover: 33554432     postgresql:       parameters:         archive_command: test ! -f /var/lib/postgresql/data/wal_archive/%f && cp %p           /var/lib/postgresql/data/wal_archive/%f         archive_mode: 'on'         archive_timeout: 1800s         datestyle: iso, mdy         default_text_search_config: pg_catalog.english         effective_cache_size: 512MB         hot_standby: 'on'         lc_messages: en_US.UTF-8         lc_monetary: en_US.UTF-8         lc_numeric: en_US.UTF-8         lc_time: en_US.UTF-8         log_destination: stderr         log_directory: /var/log/postgresql         log_file_mode: 384         log_filename: postgresql.log         log_line_prefix: '%t [%p]: [%l-1] %c %x %d %u %a %h '         log_rotation_age: 1d         log_rotation_size: 100MB         log_timezone: Etc/UTC         log_truncate_on_rotation: 'on'         logging_collector: 'on'         max_connections: 200         max_wal_size: 1GB         min_wal_size: 80MB         timezone: Etc/UTC         update_process_title: 'off'         wal_keep_size: 1600MB         wal_log_hints: 'on'       use_pg_rewind: true       use_slots: true     retry_timeout: 15     ttl: 45   initdb:   - encoding: UTF8   - locale: en_US.UTF-8   - data-checksums etcd3:   hosts:   - ETCD_IPAddress1:2379   - ETCD_IPAddress2:2379   - ETCD_IPAddress3:2379 log:   dir: /var/log/postgresql postgresql:   authentication:     replication:       password: <password>       username: replicator     rewind:       password: <password>       username: replicator     superuser:       password: <password>       username: superuser   connect_address: <IPAddress>:5432   bin_dir: /usr/lib/postgresql/15/bin   config_dir: /etc/postgresql/15/main   data_dir: /var/lib/postgresql/15/main   listen: '*:5432'   name: <node_name>   parameters:     listen_addresses: '*'     log_autovacuum_min_duration: 0     log_checkpoints: false     log_connections: false     log_disconnections: false     max_stack_depth: 7MB     port: 5432     shared_buffers: 102MB     unix_socket_directories: /var/run/postgresql     wal_buffers: -1     wal_sync_method: fsync   pg_hba:   - local  all  postgres  trust   - local  replication  postgres  trust   - local  all  all  trust   - local  replication  replicator  trust   - host  all  all  ::1/128  md5   - host  all  postgres  127.0.0.1/32  trust   - host  all  postgres  ::1/128  trust   - host  all  postgres  all  reject   - host  replication  replicator  0.0.0.0/0  md5   - hostnossl  all  postgres  all  reject   - hostssl  all  +cloud  127.0.0.1/32  pam   - hostssl  all  +cloud  ::1/128  pam   - hostssl  all  +cloud  all  pam   - hostssl  all  all  all  md5   - hostssl  replication  replicator  0.0.0.0/0  md5   pgpass: /run/postgresql/pgpass   use_unix_socket: true   use_unix_socket_repl: true restapi:   authentication:     password: <pasword>     username: postgres   connect_address: <IPAddress>:8008   listen: :8008 scope: postgres-patroni 

    Lưu ý :

    • bạn cần phải tạo các người dùng/vai trò tương ứng trong cơ sở dữ liệu với thông báo khai báo thông tin ở: postgresql.authentication. Chi tiết về các tùy chọn cấu hình có thể tìm thấy ở đây . Thông tin về người dùng/ vai trò trên các nút phải giống nhau
    • cần phải khai báo giá trị đúng của postgresql.bin_dirpostgresql.data_dirpostgresql.config_dirđang có trên máy chủ thực thi
    • Cần thay đổi địa chỉ IP tương ứng của các nútIPAddress
  • Thực hiện bắt đầu bảo trợ
    systemctl daemon-reload systemctl start patroni systemctl enable patroni 
  • Lúc này, họ đã khởi động được một nhóm trưởng
    patronictl --config-file /etc/patroni/config.yml list    + Cluster: postgres-patroni ------------------+---------+---------+----+-----------+ | Member                      | Host          | Role    | State   | TL | Lag in MB | +-----------------------------+---------------+---------+---------+----+-----------+ | postgres-patroni-cb5o3izc   | 10.20.161.208 | Leader  | running |  1 |           | +-----------------------------+---------------+---------+---------+----+-----------+ 

2.2 Khởi tạo Postgres Cluster

Trên các nút vẫn thực hiện tương tự như bước 2.1 ở trên nhưng lưu ý, chúng ta cần phải cấu hình giống nhau về postgresql.authenticationvà scope. Tuy nhiên, để có thể khởi tạo cụm và kết nối các nút với nhau, chúng ta cần phải đảm bảo các thư mục data_dirgiống nhau. Chúng tôi có thể thực hiện xóa thư mục này hoặc sao chép từ nút trưởng sang. Ví dụ:

rm -rf /var/lib/postgresql/15/main 

Khi khởi động máy chủ, máy chủ sẽ thực hiện sao lưu và đồng bộ hóa thư mục này với lệnh thông qua nút lãnh đạo pg_basebackup.

Để kiểm tra xem cài đặt thành công hay không, chúng tôi có thể sử dụng lệnh sau:

patronictl --config-file /etc/patroni/config.yml list  + Cluster: postgres-patroni ------------------+---------+---------+----+-----------+ | Member                      | Host          | Role    | State   | TL | Lag in MB | +-----------------------------+---------------+---------+---------+----+-----------+ | postgres-patroni-cb5o3izc   | 10.20.161.208 | Leader  | running |  1 |           | | postgres-patroni-jubx88ye-1 | 10.20.161.253 | Replica | running |  1 |         0 | | postgres-patroni-jubx88ye-2 | 10.20.161.174 | Replica | running |  1 |         0 | +-----------------------------+---------------+---------+---------+----+-----------+ 

Như vậy, cơ bản, chúng tôi đã cấu hình xong High Availability cho Postgres.

2.3 Kiểm tra chuyển đổi dự phòng

Khi chúng tôi dừng một máy chủ cơ sở dữ liệu bất kỳ đang làm lãnh đạo, ngay lập tức sẽ có một nút cơ sở dữ liệu khác được tự động thúc đẩy làm mới lãnh đạo. Lúc này, chúng ta cần phải cập nhật lại cấu hình của ứng dụng để thay đổi cấu hình địa chỉ cho DB.

Như vậy, chúng tôi đã có được Tính sẵn sàng cao cho Cơ sở dữ liệu nhưng chưa được sử dụng cho ứng dụng. Làm cách nào để có thể thực hiện được điều này? Chúng ta sẽ theo dõi phần tiếp theo Postgres có tính sẵn sàng cao với Patroni/ Spilo (Phần 2)

SHARE