Cấu hình PostgreSQL cluster với pacemaker và DRBD

HA (high availability) là một cấu trúc hệ thống không thể thiếu trong vận hành một database system. Bài viết này sẽ giới thiệu cách cấu hình một PostgreSQL cluster sử dụng pacemaker và DRDB.

Pacemaker

Pacemaker là một phần mềm mã nguồn mở dùng để quản lý HA cluster được sử dụng rất phổ biến trong các hệ thống hạ tầng IT.

Đặc điểm của pacemaker

Pacemaker được cấu thành từ 2 bộ phận chính corosync và pacemaker. Corosync thực hiện giám sát, giao tiếp giữa các node trong cluster, trong khi pacemaker quản lý điều khiển các hoạt động của resource agents trong cluster. Resource agents là những agent được viết dưới dạng script (bash, perl, ..) xử lý giám sát các resource (như volume, VIP, filesystem,..) và được điều khiển bởi pacemaker.

Về tổng quan, pacemaker nổi bật với những tính năng bên dưới.

  • Giám sát hệ thống và tự động phục hồi service khi có lỗi
  • Hỗ trợ nhiều servers trong cùng một cluster
  • Tính sử dụng cao (nhờ có thể chỉnh sửa resource agent)

DRBD (Distributed Replicated Block Device)

DRBD là một phần mềm phát triển bởi linbit dùng để đồng bộ dữ liệu giữa 2 node ở mức độ block dữ liệu. drbd được sử dụng phổ biến trong những hệ thống đơn giản và dữ liệu đồng bộ không lớn lắm. Một số đặc điểm về drbd.

  • Thiết lập ban đầu đơn giản
  • Dễ dàng kết hợp với cluster như pacemaker
  • Không cần hiệu chỉnh nhiều trong lúc vận hành

Ngoài những ưu điểm trên, DRBD khó vận hành khi replicate nhiều nodes (ở phiên bản trước 9.0, DRBD chỉ cho phép replicate giữa 2 nodes)

  • drbd chỉ cho phép đồng bộ dữ liệu giữa 2 node.
  • đồng bộ toàn bộ (drbd volume) dữ liệu khi split brain xảy ra.

Ở một số phương pháp đồng bộ khác như rsync, chỉ cần đồng bộ những files có thay đổi. Như vậy sẽ giảm thiểu nhiều thời gian đồng bộ dữ liệu từ primary node. Thời gian phục hồi secondary node ảnh hưởng tới tính HA của hệ thống.

Cấu hình

Bên dưới mình trình bày một hướng dẫn cụ thể cấu hình một PostgreSQL cluster sử dụng pacemaker và DRBD.

Môi trường thực thi

# Resources phiên bản Ghi Chú
1 OS CentOS 8 Bao gồm 2 nodes, node1: 172.17.28.69 và node2: 172.17.28.71
2 PostgreSQL 13 beta 2 sử dụng bản build từ source
3 Pacemaker Sử dụng package từ CentOS yum repo Sử dụng rerource agents: drbd, Filesystem, pgsql, IP
4 DRBD 9.0 sử dụng giao thức (mức độ đồng bộ) B (đồng bộ trên memory hay tiền đồng bộ). Bài viết này mình cấu hình DRBD trên LVM (phần mềm quản lý volume logic được sử dụng rất phổ biến.

Các bước thực hiện

Cài đặt PostgreSQL 13 beta2 Thực hiện trên: 2 nodes

Đã có nhiều bài viết liên quan tới cài đặt nên ở đây mình sẽ giảm thiểu giải thích các bước cài đặt PostgreSQL

# cd /usr/local/src
# wget https://ftp.postgresql.org/pub/source/v13beta2/postgresql-13beta2.tar.gz > /dev/null
# tar xfz postgresql-13beta2.tar.gz
# cd postgresql-13beta2
# ./configure --prefix=/usr/local/pgsql/pg13 > /dev/null
# make -j16 install > /dev/null

Cấu hình LVM và DRBD

  1. Thực hiện trên: 2 nodes Download drbd packages
    Download DRBD packages từ đây
+ drbd90-utils-9.13.1-1.el8.elrepo.x86_64.rpm
+ drbd90-utils-sysvinit-9.13.1-1.el8.elrepo.x86_64.rpm
+ kmod-drbd90-9.0.23-1.el8_2.elrepo.x86_64.rpm
  1. Thực hiện trên: 2 nodes Cài đặt drbd packages
sudo yum localinstall *rpm
  1. Thực hiện trên: 2 nodes Kiểm tra xem firewalld đã tắt chưa
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)

Tắt Firewalld ở đây để thuận lợi khi giao tiếp giữa các nodes. Nếu firewalld chưa tắt, bạn có thể tắt và vô hiệu hóa bằng lệnh systemctl stop firewalld; systemctl disable firewalld.

  1. Thực hiện trên: 2 nodes Tạo ổ đĩa logic LVM

Thông tin thiết lập LVM

# Resources phiên bản
1 Tên ổ đĩa /dev/sdb
2 Tên physical volume /dev/sdb1
3 Tên volume group vg
4 Tên logical volume lv

Ở đây mình chuẩn bị một đĩa cứng với dung lượng 1GB (sdb) và chỉ sử dụng 512MB cho DRBD volume.

# fdisk /dev/sdb 
...snip...
Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): 

Using default response p.
Partition number (1-4, default 1): 
First sector (2048-2097151, default 2048): 
Last sector, +sectors or +size{K,M,G,T,P} (2048-2097151, default 2097151): 

Created a new partition 1 of type 'Linux' and of size 1023 MiB.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

# lsblk 
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda           8:0    0   15G  0 disk 
├─sda1        8:1    0    1G  0 part /boot
└─sda2        8:2    0   14G  0 part 
  ├─cl-root 253:0    0 12.5G  0 lvm  /
  └─cl-swap 253:1    0  1.5G  0 lvm  [SWAP]
sdb           8:16   0    1G  0 disk 
└─sdb1        8:17   0 1023M  0 part 
sr0          11:0    1  7.7G  0 rom  
# pvcreate /dev/sdb1
  Physical volume "/dev/sdb1" successfully created.
# vgcreate vg /dev/sdb1
  Volume group "vg" successfully created
# lvcreate --size 512MB --name lv vg
  Logical volume "lv" created.
#
# lsblk 
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda           8:0    0   15G  0 disk 
├─sda1        8:1    0    1G  0 part /boot
└─sda2        8:2    0   14G  0 part 
  ├─cl-root 253:0    0 12.5G  0 lvm  /
  └─cl-swap 253:1    0  1.5G  0 lvm  [SWAP]
sdb           8:16   0    1G  0 disk 
└─sdb1        8:17   0 1023M  0 part 
  └─vg-lv   253:2    0  512M  0 lvm  
sr0          11:0    1  7.7G  0 rom  
[root@node1 src]# 
  1. Tạo ổ đĩa DRBD trên LVM đã tạo

Thông tin thiết lập ổ DRBD

# Nội dung giải thích
1 Tên LVM sử dụng cho DRBD /dev/vg/lv
2 Node1 IP 172.17.28.69
3 Node2 IP 172.17.28.71
4 Port sử dụng cho replicate dữ liệu 7001
5 Protocol B (đồng bộ mức độ bộ nhớ)
  • Thực hiện trên: 2 nodes Tạo file drbd resource
# vi /etc/drbd.d/pgres.res
resource pgres {
    protocol B;
    device minor 1;
    meta-disk internal;
    disk /dev/mapper/vg-lv;
    on node1 {
        address 172.17.28.69:7001;
    }
    on node2 {
        address 172.17.28.71:7001;
    }
}

Bạn có thể thao khảo thêm ở manual của DRBD để có thêm nhiều tinh chỉnh.

  • Thực hiện trên: 2 nodes Tạo meta data cho ổ DRBD
# drbdadm create-md pgres
initializing activity log
initializing bitmap (16 KB) to all zero
Writing meta data...
New drbd meta data block successfully created.
# 
  • Thực hiện trên: 2 nodes Khởi động DRBD
# systemctl start drbd
# systemctl enable drbd
Synchronizing state of drbd.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable drbd
Created symlink /etc/systemd/system/multi-user.target.wants/drbd.service → /usr/lib/systemd/system/drbd.service.
# drbdadm status pgres
pgres role:Secondary
  disk:Inconsistent
  node2 role:Secondary
    peer-disk:Inconsistent
  • Thực hiện trên: Node1 Thiết lập node 1 là primary
[root@node1 ~]# drbdadm --force primary pgres
[root@node1 ~]# drbdadm status pgres
pgres role:Primary
  disk:UpToDate
  node2 role:Secondary
    peer-disk:UpToDate

[root@node1 ~]##
  • Thực hiện trên: Node1 Định dạng xfs cho ổ DRBD
[root@node1 src]# mkfs.xfs /dev/drbd1 -L PGDATA -f
meta-data=/dev/drbd1             isize=512    agcount=4, agsize=32765 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=131059, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=1368, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@node1 src]#

Tới đây mình có thể sử dụng ổ drbd, dữ liệu sẽ được đồng bộ từ node primary sang secondary. Bạn có thể chuyển chuyển vai trò các nodes lẫn nhau nhờ lệnh drbd secondary pgres để chuyển vai trò ổ drbd sang secondary (passive) drbd primary pgres để chuyển vai trò thành primary (active)

Cài đặt Pacemaker

Phần này mình sẽ hướng dẫn cài đặt pacemaker với cấu trúc như bên dưới.

+                       [ VIP: 172.17.28.111 ] (resources: drbd, Filesystem, pgsql, Ip)
+                                  |
++----------------------+          |          +----------------------+
+| [  Cluster Node1  ]  |          |          | [  Cluster Node2  ]  |
+|   IP: 172.17.28.69   +----------+----------+   172.17.28.71       |
+|                      |                     |                      |
++----------------------+                     +----------------------+

Các giá trị thiết lập cho pacemaker resources.

# Resource giá trị Chú thích
1 ocf:linbit:drbd drbd_resource=pgres Sử dụng pgres resource vừa tạo
2 ocf:heartbeat:Filesystem device="/dev/drbd1" directory=/pgdata fstype=xfs Mount ổ DRBD vào thư mục dữ liệu
3 ocf:heartbeat:pgsql

pgctl=/usr/local/pgsql/pg13/bin/pg_ctl

psql=/usr/local/pgsql/pg13/bin/psql 

pgdata=/pgdata/pg13data pgport=5432

PostgreSQL resource. Thực hiện các thao tác khởi động, monitoring, ... PostgreSQL.
4 ocf:heartbeat:IPaddr2 ip=172.17.28.111 VIP resource. Thực hiện các thao tác khởi động mornitoring, ... IP ảo cho cluster.

Các bước thực hiện với pacemaker

  • Thực hiện trên: 2 Nodes thực hiện enable HighAvailability yum repo (mặc định repo này không được enable trên CentOS 8), và cài đặt pacemaker packages.
# dnf config-manager --set-enabled HighAvailability
# yum install -y pacemaker pcs fence-agents-all psmisc > /dev/null
  • Thực hiện trên: 2 Nodes Thiết lập mật khẩu cho hacluster OS user (user này được tạo ra khi cài đặt pacemaker packages).
# echo "firstclt" | sudo passwd hacluster --stdin
Changing password for user hacluster.
passwd: all authentication tokens updated successfully.
  • Thực hiện trên: 2 Nodes Khởi động pcsd deamon (để có thể thực hiện các câu lệnh pcs).
# sudo systemctl start pcsd.service
# systemctl enable pcsd.service
Created symlink /etc/systemd/system/multi-user.target.wants/pcsd.service → /usr/lib/systemd/system/pcsd.service.
  • Thực hiện trên: 2 Nodes Thực hiện chứng thực giữa các nodes cho cluster
# sudo pcs host auth node1 node2 -u hacluster -p firstclt
node2: Authorized
node1: Authorized
  • Thực hiện trên: Node1 Khởi tạo cluster và khởi động
[root@node1 ~]# sudo pcs cluster setup firstcluster node1 node2 --force --start
...snip...
Sending 'corosync authkey', 'pacemaker authkey' to 'node1', 'node2'
node2: successful distribution of the file 'corosync authkey'
node2: successful distribution of the file 'pacemaker authkey'
node1: successful distribution of the file 'corosync authkey'
node1: successful distribution of the file 'pacemaker authkey'
Sending 'corosync.conf' to 'node1', 'node2'
node2: successful distribution of the file 'corosync.conf'
node1: successful distribution of the file 'corosync.conf'
Cluster has been successfully set up.
Starting cluster on hosts: 'node1', 'node2'...
[root@node1 ~]#
  • Xác nhận trạng thái cluster
# crm_mon -Arf1
Cluster Summary:
  * Stack: corosync
  * Current DC: node1 (version 2.0.3-5.el8_2.1-4b1f869f0f) - partition with quorum
  * Last updated: Wed Jul 15 03:29:57 2020
  * Last change:  Wed Jul 15 03:29:48 2020 by hacluster via crmd on node1
  * 2 nodes configured
  * 0 resource instances configured

Node List:
  * Online: [ node1 node2 ]

Full List of Resources:
  * No resources

Migration Summary:
  • Thực hiện trên: Node1 Thiết lập một số thông số mặc định
[root@node1 ~]# pcs cluster enable --all # thiết lập khởi động cluster cùng với OS
[root@node1 ~]# pcs property set stonith-enabled=false  # không thiết lập snonith vì không có device liên quan
[root@node1 ~]# pcs property set cluster-recheck-interval=10m # kiểm tra trạng thái mỗi 10 phút
[root@node1 ~]# pcs property set no-quorum-policy=ignore # thiết lập thao tác khi mất quorum 
  • Thực hiện trên: Node1 Tạo DRBD resource trên cluster
# pcs resource create drbd-fisrtcluster ocf:linbit:drbd drbd_resource=pgres op monitor \
interval=15s op start timeout=60 op stop timeout=60 op promote timeout=90
# pcs resource promotable drbd-fisrtcluster master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true
# pcs resource cleanup

Kiểm tra trạng thái cluster

# crm_mon -Arf1
...snip...
Full List of Resources:
  * Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
    * Masters: [ node1 ]
    * Slaves: [ node2 ]
...snip...
  • Thực hiện trên: Node1 Tạo Filesystem resource trên cluster
# sudo mkdir /pgdata # tạo data directory để mount filesystem
# sudo pcs resource create pgFS-firstcluster ocf:heartbeat:Filesystem device="/dev/drbd1" \
 directory=/pgdata fstype=xfs options=defaults,noatime,nodiratime,attr2 op start timeout=60 \
op stop timeout=60 --group masterg-firstcluster
  • Kiểm tra trạng thái cluster
# crm_mon -Arf1
...snip...
Full List of Resources:
  * Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
    * Masters: [ node1 ]
    * Slaves: [ node2 ]
  * Resource Group: masterg-firstcluster:
    * pgFS-firstcluster (ocf::heartbeat:Filesystem):    Started node1
...snip...
  • Thực hiện trên: Node1 Khởi tạo postgres DB cluster trên filesystem vừa tạo
[root@node1 ~]# chown postgres /pgdata/ -R
[root@node1 ~]# df -h /pgdata
Filesystem      Size  Used Avail Use% Mounted on
/dev/drbd1      507M   30M  478M   6% /pgdata
[root@node1 ~]# su - postgres
$ /usr/local/pgsql/pg13/bin/initdb -E utf8 --no-locale -D /pgdata/pg13data
  • Thực hiện trên: Node1 Tạo pgsql resource cho postgres
# sudo pcs resource create pgsql-firstcluster ocf:heartbeat:pgsql \
pgctl=/usr/local/pgsql/pg13/bin/pg_ctl psql=/usr/local/pgsql/pg13/bin/psql \
pgdata=/pgdata/pg13data pgport=5432 stop_escalate=1 op start timeout=60s \
interval=0s on-fail=restart op monitor timeout=60s interval=7s on-fail=restart \
op monitor timeout=60s interval=2s on-fail=restart role=Master op promote \
timeout=60s interval=0s on-fail=restart op demote timeout=60s interval=0s \
on-fail=stop op stop timeout=60s interval=0s on-fail=block op notify timeout=60s \
interval=0s --group masterg-firstcluster
  • Thiết lập failover postgres resource nếu số lượng lỗi (không thể kết nối) là một lần.
# pcs resource meta pgsql-firstcluster migration-threshold=1
  • Kiểm tra trạng thái cluster
# crm_mon -Arf1
...snip...
Full List of Resources:
  * Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
    * Masters: [ node1 ]
    * Slaves: [ node2 ]
  * Resource Group: masterg-firstcluster:
    * pgFS-firstcluster (ocf::heartbeat:Filesystem):    Started node1
    * pgsql-firstcluster        (ocf::heartbeat:pgsql): Started node1
...snip...
# ps -ef | grep postgres: | grep -v grep
postgres   11226   11217  0 03:47 ?        00:00:00 postgres: checkpointer
postgres   11227   11217  0 03:47 ?        00:00:00 postgres: background writer
postgres   11228   11217  0 03:47 ?        00:00:00 postgres: walwriter
postgres   11229   11217  0 03:47 ?        00:00:00 postgres: autovacuum launcher
postgres   11230   11217  0 03:47 ?        00:00:00 postgres: stats collector
postgres   11231   11217  0 03:47 ?        00:00:00 postgres: logical replication launcher
#
  • Thực hiện trên: Node1 Tạo VIP cho cluster
# sudo pcs resource create vip-firstcluster ocf:heartbeat:IPaddr2 ip=172.17.28.111 \
nic=ens33 cidr_netmask=28 op start timeout=60s interval=0s on-fail=restart \
op monitor timeout=120s interval=20s on-fail=restart op stop timeout=60s \
interval=0s on-fail=block --group masterg-firstcluster
  • Kiểm tra trạng thái cluster
# crm_mon -Arf1
...snip...
Full List of Resources:
  * Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
    * Masters: [ node1 ]
    * Slaves: [ node2 ]
  * Resource Group: masterg-firstcluster:
    * pgFS-firstcluster (ocf::heartbeat:Filesystem):    Started node1
    * pgsql-firstcluster        (ocf::heartbeat:pgsql): Started node1
    * vip-firstcluster  (ocf::heartbeat:IPaddr2):       Started node1
...snip...
# ip a | grep -w inet
    inet 127.0.0.1/8 scope host lo
    inet 172.17.28.69/28 brd 172.17.28.79 scope global noprefixroute ens33
    inet 172.17.28.111/28 scope global ens33
    inet 192.168.91.131/24 brd 192.168.91.255 scope global dynamic noprefixroute ens37
#
  • Thực hiện trên: Node1 Tạo constraint cho cluster
  • Khởi động group master với DRBD trên cùng một Node
# sudo pcs constraint colocation add started masterg-firstcluster with Master \
drbd-fisrtcluster-clone INFINITY 
  • Khởi động theo thứ tự DRBD xong rồi master group
# sudo pcs constraint order promote drbd-fisrtcluster-clone then start \
masterg-firstcluster symmetrical=false score=INFINITY 
  • Thực hiện trên: Node1 Test failover cluster
    • Kiểm tra trạng thái cluster
# crm_mon -Arf1
...snip...
Full List of Resources:
  * Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
    * Masters: [ node1 ]
    * Slaves: [ node2 ]
  * Resource Group: masterg-firstcluster:
    * pgFS-firstcluster (ocf::heartbeat:Filesystem):    Started node1
    * pgsql-firstcluster        (ocf::heartbeat:pgsql): Started node1
    * vip-firstcluster  (ocf::heartbeat:IPaddr2):       Started node1
...snip...
  • Failover master resource sang node2
# pcs resource move masterg-firstcluster
Warning: Creating location constraint 'cli-ban-masterg-firstcluster-on-node1' with a score of -INFINITY for resource masterg-firstcluster on node1.
        This will prevent masterg-firstcluster from running on node1 until the constraint is removed
        This will be the case even if node1 is the last node in the cluster
  • Kiểm tra trạng thái cluster
# crm_mon -Arf1
...snip...
Full List of Resources:
  * Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
    * Masters: [ node2 ]
    * Slaves: [ node1 ]
  * Resource Group: masterg-firstcluster:
    * pgFS-firstcluster (ocf::heartbeat:Filesystem):    Started node2
    * pgsql-firstcluster        (ocf::heartbeat:pgsql): Started node2
    * vip-firstcluster  (ocf::heartbeat:IPaddr2):       Started node2
...snip...
  • Xóa constraint tạo ra bởi lệnh move resource
# pcs resource clear masterg-firstcluster
Removing constraint: cli-ban-masterg-firstcluster-on-node1

Đến đây bạn đã có một PostgreSQL cluster tự động failover giữa các nodes nếu gặp lỗi.

Lời kết

Bao gồm pacemaker có rất nhiều cấu trúc cluster có thể áp dụng cho hệ thống của bạn. Bạn nên tham khảo vào mục đích sử dụng, yêu cầu từ hệ thống và business để lựa chọn cấu hình phù hợp với hệ thống của mình.

Viết bình luận

Filtered HTML

  • Các địa chỉ web và email sẽ tự động được chuyển sang dạng liên kết.
  • Các thẻ HTML được chấp nhận: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Tự động ngắt dòng và đoạn văn.

Plain text

  • Không được dùng mã HTML.
  • Các địa chỉ web và email sẽ tự động được chuyển sang dạng liên kết.
  • Tự động ngắt dòng và đoạn văn.

Facebook Comments Box