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 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.
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.
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.
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)
Ở 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.
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.
# | 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. |
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
Thực hiện trên: 2 nodes
Download drbd packages+ 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
Thực hiện trên: 2 nodes
Cài đặt drbd packagessudo yum localinstall *rpm
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
.
Thực hiện trên: 2 nodes
Tạo ổ đĩa logic 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]#
# | 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)
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. |
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 ~]#
# 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
# 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
# pcs resource meta pgsql-firstcluster migration-threshold=1
# 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
# 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# sudo pcs constraint colocation add started masterg-firstcluster with Master \ drbd-fisrtcluster-clone INFINITY
# 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
# 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...
# 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
# 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...
# 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.
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