PostgreSQL高可用方案-patroni+etcd+vipmanager(一)

1 前言

1.1概述

Patroni + etcd + vipmanager cybertec推出的postgresql 高可用方案。其中, Etcd 用于存放集群状态信息。Patroni 负责为PostgreSQL 集群提供故障转移和高可用服务。vipmanager 根据etcdConsul中保存的状态管理虚拟IP用于提供和管理虚拟ip,用于对外提供访问地址。

1.2 方案架构

 

1.3 软件介绍

1.3.1 etcd

etcdCoreOS团队于20136月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法,etcd基于Go语言实现。

etcd作为服务发现系统,有以下的特点:

  • 简单:安装配置简单,而且提供了HTTP API进行交互,使用也很简单
  • 安全:支持SSL证书验证
  • 快速:根据官方提供的benchmark数据,单实例支持每秒2k+读操作
  • 可靠:采用raft算法,实现分布式系统数据的可用性和一致性

1.3.2 Patroni 

PatroniCybertec公司开发的,可用于使用流复制来创建,管理,维护和监视高可用性PostgreSQL集群设置的工具。

Patroni 是根据MIT许可证发行的,可以通过PIP轻松安装。 对于UbuntuDebian,可以通过系统存储库获得;对于FedoraCentOSRHELCYBERTEC提供了RPM软件包。.

1.3.2 vip-manager

vip-managerCybertec公司开发的,根据etcdConsul中保存的状态管理虚拟IP的工具。如果 vip-manager 看到它在当前主数据库所在服务器上运行,它将获取虚拟IP

1.4 方案的功能

该方案实现PostgreSQL的高可用和在线恢复。主要的功能如下:

1. 在主数据库所在服务器上,创建接受访问的虚拟IP。若主数据库改变,虚拟ip也会漂移到新主数据库所在的节点。

2. 若主数据库停止,自动启动主数据库;

3. 若后备数据库停止,自动启动后备数据库;

4. 若主数据库无法启动,则将某一后备数据库提升为主数据库将旧的主数据库降级为后备数据库,之后它可通过一条命令重新初始化;

5. 若后备数据库无法启动可通过一条命令重新初始化;

6. 支持手动切换主数据库和后备数据库;

1.5 实验环境

本实验需要两台服务器。

硬件:

内存:32G

CPU:双核四线程CPU * 2

    

操作系统:

Centos 7.5

软件环境:

yum

Python 3.6.8

pip 9.0.3

etcd 3.3.11

patroni 2.0.2

PostgreSQL 12.4

vip-manager 1.0

 

主服务器(primary)的ip地址是10.19.134.134,主机名是node134PostgreSQL 的主节点和patroni 的主节点均在此部署。

后备服务器(standby)的ip地址是10.19.134.135,主机名是node135PostgreSQL 的备节点和patroni 的备节点均在此部署。

集群对外提供服务的虚拟ip 10.19.134.140。

2 安装和部署

2.1 安装和部署etcd

在两台服务器上分别部署etcd 3.3

安装和部署etcd的方法详见下面的文章:

 

在Linux上部署etcd集群

2.2 安装PostgreSQL

在两台服务器上分别安装PostgreSQL。本文中,我们通过源码安装 PostgreSQL 12.4

1. 关闭防火墙

[root@node134 ~]# systemctl  disable --now  firewalld

2. 关闭selinex

 [root@node134 ~]# sed   -e   '/^ {0,}SELINUX=/cSELINUX=disabled'  -i  /etc/selinux/config

     setenforce 0

3. 安装依赖

[root@node134 ~]# yum -y install readline-devel zlib-devel gcc

[root@node134 ~]# yum -y install perl perl-devel perl-ExtUtils-Embed

[root@node134 ~]# yum -y install python python-devel

4. 创建用户组postgres

[root@node134 ~]# groupadd postgres

5. 创建用户postgres,并且设置这个用户属于用户组postgres

[root@node134 ~]# useradd -d /var/lib/pgsql -g postgres postgres

6. 从官网下载PostgreSQL源码,这里我们下载 postgresql-12.4.tar.gz

7. 在数据库所在服务器上解压它

[root@node134 ~]# tar zxvf postgresql-12.4.tar.gz

 8. 进入解压后的目录,并编译和安装PostgreSQL。

 [root@node134 ~]# ./configure  --prefix=/opt/postgresql-12 --with-perl --with-python

[root@node134 ~]# make world

[root@node134 ~]# make install-world

这里  --prefix=/opt/postgresql-12 表示 PostgreSQL 的安装目录是 “/opt/postgresql-12”

9. 修改PostgreSQL 的安装目录的拥用者为 postgres,并设置用户权限

[root@node134 ~]# chown postgres:postgres /opt/postgresql-12/ -R

[root@node134 ~]# chmod 755 /opt/postgresql-12/ -R

10. 切换OS用户为postgres,之后的操作均通过此用户完成。

[root@node134 ~]# su postgres

11. 创建PostgreSQL的数据目录

[postgres@node134 ~]# /opt/postgresql-12/bin/initdb -U postgres -D /opt/postgresql-12/data -E utf8

12. 根据需要,修改 postgresql.conf 中的参数。

比如:

listen_addresses = '*'

logging_collector = on

log_directory = 'pg_log'

13. 启动数据库

[postgres@node134 ~]# cd /opt/postgresql-12/bin

[postgres@node134 ~]# ./pg_ctl start -D ../data

14. 登录数据库,修改postgres用户的密码

[postgres@node134 ~]# ./psql -h 127.0.0.1 -U postgres -p 5432

postgres=# alter user postgres password 'postgres123';

postgres=# q

15. 修改 /data/pg_hba.conf,将认证方式从默认的trust 改为 md5,设置允许访问的ip地址。本实验中,修改和新增的内容如下:

host    all             all             127.0.0.1/32            md5

host    all             all             10.19.134.0/24            md5

16. 重启数据库

[postgres@node134 ~]# cd /opt/postgresql-12/bin

[postgres@node134 ~]# ./pg_ctl restart -D ../data

完成PostgreSQL 的部署。

2.3 搭建 postgresql 主备集群

部署postgresql 主备集群的方法详见如下文档:

【转载】Linux下PostgreSQL主备环境搭建和切换

2.4 安装和部署Patroni

1. 在两台服务器上安装 epel ,gccpython 3

[root@node134 ~]# yum -y install epel-release

[root@node134 ~]# yum -y install gcc

[root@node134 ~]# yum -y install python3

[root@node134 ~]# yum -y install python3-devel

2. 使用pip安装 psycopg2 patroni

[root@node134 ~]# pip install psycopg2-binary -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host=mirrors.aliyun.com

[root@node134 ~]# pip install patroni[etcd,consul] -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host=mirrors.aliyun.com

 

3. 验证是否安装成功:

[root@node134 ~]# which patroni

 

4. 在主机node134 上创建patroni的配置文件:

[root@node134 ~]# mkdir -p /etc/patroni/

[root@node134 ~]# cd /etc/patroni/

[root@node134 ~]# vi /etc/patroni/patroni_postgresql.yml

内容如下:

scope: postgresql12
namespace: /postgresql/
name: node134

restapi:
 listen: 10.19.134.134:8008
 connect_address: 10.19.134.134:8008

etcd:
 host: 10.19.134.134:2379

bootstrap:
 # this section will be written into Etcd:/<namespace>/<scope>/config after initializing new cluster
 # and all other cluster members will use it as a `global configuration`
 dcs:
   ttl: 30
   loop_wait: 10
   retry_timeout: 10
   maximum_lag_on_failover: 1048576
   master_start_timeout: 300
   synchronous_mode: false
   postgresql:
     use_pg_rewind: true
     use_slots: true
     parameters:
       listen_addresses: "*"
       port: 5432
       wal_level: replica
       hot_standby: "on"
       wal_keep_segments: 10
       max_wal_senders: 10
       max_replication_slots: 10
       wal_log_hints: "on"


postgresql:
 listen: 10.19.134.0:5432
 connect_address: 10.19.134.134:5432
 data_dir: /opt/postgresql-12/data
 bin_dir: /opt/postgresql-12/bin
 config_dir: /opt/postgresql-12/data
 pgpass: /etc/patroni/.pgpass

 authentication:
   replication:
     username: repuser
     password: repuser123
   superuser:
     username: postgres
     password: postgres123
   rewind:
     username: postgres
     password: postgres123

tags:
   nofailover: false
   noloadbalance: false
   clonefrom: false
nosync: false

5. 修改它的属主为postgres,并设置只有属主才有读写权限其他用户无任何权限:

[root@node134 ~]# chown -R postgres.postgres /etc/patroni/

[root@node134 ~]# chmod 600 /etc/patroni/patroni_postgresql.yml

6. 在主机node135 上创建patroni的配置文件:

[root@node135 ~]# mkdir -p /etc/patroni/

[root@node135 ~]# cd /etc/patroni/

[root@node135 ~]# vi /etc/patroni/patroni_postgresql.yml

内容如下:

scope: postgresql12
namespace: /postgresql/
name: node135

restapi:
  listen: 10.19.134.135:8008
  connect_address: 10.19.134.135:8008

etcd:
  host: 10.19.134.135:2379

bootstrap:
  # this section will be written into Etcd:/<namespace>/<scope>/config after initializing new cluster
  # and all other cluster members will use it as a `global configuration`
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    master_start_timeout: 300
    synchronous_mode: false
    postgresql:
      use_pg_rewind: true
      use_slots: true
      parameters:
        listen_addresses: "*"
        port: 5432
        wal_level: replica
        hot_standby: "on"
        wal_keep_segments: 10
        max_wal_senders: 10
        max_replication_slots: 10
        wal_log_hints: "on"

postgresql:
  listen: 10.19.134.0:5432
  connect_address: 10.19.134.135:5432
  data_dir: /opt/postgresql-12/data
  bin_dir: /opt/postgresql-12/bin
  config_dir: /opt/postgresql-12/data
  pgpass: /etc/patroni/.pgpass

  authentication:
    replication:
      username: repuser
      password: repuser123
    superuser:
      username: postgres
      password: postgres123
    rewind:
      username: postgres
      assword: postgres123

tags:
  nofailover: false
  noloadbalance: false
  clonefrom: false

nosync: false

7. 然后修改它的属主为postgres,并设置只有属主才有读写权限

[root@node135 ~]# chown -R postgres.postgres /etc/patroni/

[root@node135 ~]# chmod 600 /etc/patroni/patroni_postgresql.yml

8. 我们可以将 patroni 注册为服务创建文件 /usr/lib/systemd/system/patroni.service,内容如下:

[Unit]
Description=High availability PostgreSQL Cluster
After=syslog.target network.target

[Service]
Type=simple
User=postgres
Group=postgres
ExecStart=/usr/local/bin/patroni /etc/patroni/patroni_postgresql.yml
KillMode=process
TimeoutSec=30
Restart=no

[Install]
WantedBy=multi-user.target

9. 完成后,通过操作系统命令启动和关闭patroni服务:

[root@node134 ~]# systemctl start patroni

10. 在另一个窗口中查看 patroni 集群状态

[root@node134 ~]# patronictl -c /etc/patroni/patroni_postgresql.yml list

结果如下:

+ Cluster: postgresql12 (6914170278151575561) -----+----+-----------+

| Member  | Host               | Role    | State   | TL | Lag in MB |

+---------+--------------------+---------+---------+----+-----------+

| node134 | 10.19.134.134:5435 | Leader  | running | 25 |           |

| node135 | 10.19.134.135:5435 | Replica | running | 25 |         0 |

上述信息可知,位于 node134 上PostgreSQL 是主数据库,位于node135 的数据库。

2.5 安装 vip-manager

1. 安装golang

yum -y install golang

2. 设置环境变量GOPROXY,它表示代理服务,仅在中国大陆需要。

export GOPROXY=https://goproxy.io

3. 下载 vip-manager 源码。本文使用的版本是1.0.1

4. 解压vip-manager 的源码。

tar zxvf vip-manager-1.0.1.tar.gz

5. 进入解压后的目录vip-manager-1.0.1,编译vip-manager

cd vip-manager-1.0.1

make

6. 将生成的vip-manager二进制文件复制到/usr/bin/vip-manager

cp ./vip-manager /usr/bin/vip-manager

7. 将服务文件从 package/scripts/vip-manager.service 复制到 /usr/lib/systemd/system/

cp ./package/scripts/vip-manager.service  /usr/lib/systemd/system/

8. 将安装配置文件从vipconfig/vip-manager.yml 复制到 /etc/default/

cp ./vipconfig/vip-manager.yml  /etc/default/

8. 编辑配置文件 /etc/default/vip-manager.yml,修改下面这些参数的值:

ip  要管理的虚拟IP地址

netmask  与虚拟IP vip所属的子网相关联的子网掩码。

interface 运行vip-manager的机器上的本地网络接口。当使用hosting-type=basic(默认)时需要。该界面将添加和删除vip

trigger-key  将由vip经理监控的DCS中的密钥。必须匹配Patroni配置中的<namespace>/<scope>/leader。当DCS返回的值等于trigger-value时,vip-manager将确保虚拟IP已注册到这台机器。如果不匹配,vip-manager会确保虚拟IP没有注册到这台机器上。

trigger-value  DCS的触发键应答将被匹配的值。必须匹配Patroni配置中的<name>。这通常设置为与这个vip-manager实例相关联的patroni集群成员的名称。默认为机器的主机名。

hosting-type  要么是basic要么是hetzner。介绍了虚拟IP的管理机制。默认为basic

dcs-type  vip-manager用于监控触发键的DCS类型。默认为etcd

dcs-endpoints 定义到达DCS地址的url。可以使用逗号分隔的列表将多个端点传递给这个参数或环境变量。在配置文件中,可以指定一个列表,示例请参见配置示例。dcs-type=etcd时,默认为http://127.0.0.1:2379 dcs-type=consul时,默认为http://127.0.0.1:8500

同时,用“#”注释掉 etcd-ca-fileetcd-cert-fileetcd-key-file。我们不使用SSL 认证.

9. 在主节点上,这些参数配置如下:

ip: 10.19.134.140

netmask: 24

interface: eth0

trigger-key: "/postgresql/postgresql12/leader"

trigger-value: "node134"

hosting-type: basic

dcs-type: etcd

dcs-endpoints:
  - http://127.0.0.1:2379
  - http://10.19.134.134:2379

在备节点上,这些参数配置如下:

ip: 10.19.134.140

netmask: 24

interface: eth0

trigger-key: "/postgresql/postgresql12/leader"

trigger-value: "node135"

hosting-type: basic

dcs-type: etcd

dcs-endpoints:
  - http://127.0.0.1:2379
  - http://10.19.134.135:2379

10. 分别在主节点和后备节点上启动vip-manager

systemctl start vip-manager

前言

1.1 etcd简介

etcd是CoreOS团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法,etcd基于Go语言实现。

etcd作为服务发现系统,有以下的特点:

  • 简单:安装配置简单,而且提供了HTTP API进行交互,使用也很简单
  • 安全:支持SSL证书验证
  • 快速:根据官方提供的benchmark数据,单实例支持每秒2k+读操作
  • 可靠:采用raft算法,实现分布式系统数据的可用性和一致性

1.2 安装环境

本实验需要两台服务器,如下表所示。

 

 

操作系统

内存

CPU

IP地址

主机名

服务器1

Centos 7.5

32G

双核四线程CPU * 2

10.40.239.234

node234

服务器2

Centos 7.5

32G

双核四线程CPU * 2

10.40.239.235

node235

2 操作流程

2.1 对服务器校时

这里我们使用国家授时中心NTP(Network Time Protocol)服务对两台服务器校时:

ntpdate ntp.ntsc.ac.cn

2.2 安装etcd

在两台服务器上执行下面的命令,安装etcd:

yum -y install etcd

 

执行下面的命令,查看etcd:

yum list installed |grep -i etcd

如果出现如下结果,表示安装成功:

etcd.x86_64                 3.3.11-2.el7.centos            @extras

 

2.3 配置etcd

2.3.1 node234 上的配置

    1. 备份原先的etcd配置文件。

cp /etc/etcd/etcd.conf /etc/etcd/etcd.conf.bak

 

2.编辑配置文件:

vi /etc/etcd/etcd.conf

配置如下内容:

ETCD_DATA_DIR="/var/lib/etcd/node234.etcd"

ETCD_LISTEN_PEER_URLS="http://10.40.239.234:2380"

ETCD_LISTEN_CLIENT_URLS="http://10.40.239.234:2379,http://localhost:2379"

ETCD_NAME="node234"

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.40.239.234:2380"

ETCD_ADVERTISE_CLIENT_URLS="http://10.40.239.234:2379"

ETCD_INITIAL_CLUSTER="node234=http://10.40.239.234:2380, node235=http://10.40.239.235:2380"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_INITIAL_CLUSTER_STATE="new"

 

这里解释一下这些参数的含义:

ETCD_DATA_DIR:数据存储目录。由etcd自动创建。

 

ETCD_LISTEN_PEER_URLS:监听在对等节点流量上的URL列表,该参数告诉etcd在指定的 “协议://IP:端口”组合上接收来自其对等方的传入请求。协议可以是http或者https。或者,使用unix://<file-path>或者unixs://<file-path>到unix sockets。如果将0.0.0.0作为IP,etcd将监听在所有的接口上的给定端口。如果给定了IP和端口,etcd将监听指定的接口和端口。可以使用多个URL指定要监听的地址和端口的数量。 etcd将响应来自任何列出的地址和端口的请求。

 

ETCD_LISTEN_CLIENT_URLS:监听在客户端流量上的URL列表,该参数告诉etcd在指定的“协议://IP:端口”组合上接受来自客户端的传入请求。协议可以是http或者https。或者,使用unix://<file-path>或者unixs://<file-path>到unix sockets。如果将0.0.0.0作为IP,etcd将监听在所有的接口上的给定端口。如果给定了Ip和端口,etcd将监听指定的接口和端口。可以使用多个URL指定要监听的地址和端口的数量。 etcd将响应来自任何列出的地址和端口的请求。

 

ETCD_NAME:此成员的名字。

 

ETCD_INITIAL_ADVERTISE_PEER_URLS:此成员对等URL的列表,用来通知到集群的其余部分。 这些地址用于在集群周围传送etcd数据。 所有集群成员必须至少有一个路由。 这些URL可以包含域名。

 

ETCD_ADVERTISE_CLIENT_URLS:此成员的客户端URL的列表,这些URL广播给集群的其余部分。 这些URL可以包含域名。

 

ETCD_INITIAL_CLUSTER:启动集群的初始化配置。配置集群的成员。

 

ETCD_INITIAL_CLUSTER_TOKEN:引导期间etcd群集的初始集群令牌。

 

ETCD_INITIAL_CLUSTER_STATE:初始群集状态(“新”或“现有”)。 对于在初始静态或DNS引导过程中存在的所有成员,将其设置为new。 如果此选项设置为existing,则etcd将尝试加入现存集群。 如果设置了错误的值,etcd将尝试启动,但会安全地失败。

 

更多信息,可以参照etcd官方文档

 

2.3.1 node235 上的配置

1. 备份原先的etcd配置文件。

cp /etc/etcd/etcd.conf /etc/etcd/etcd.conf.bak

 

2.编辑配置文件:

 

ETCD_DATA_DIR="/var/lib/etcd/node235.etcd"

ETCD_LISTEN_PEER_URLS="http://10.40.239.235:2380"

ETCD_LISTEN_CLIENT_URLS="http://10.40.239.235:2379,http://localhost:2379"

ETCD_NAME="node235"

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.40.239.235:2380"

ETCD_ADVERTISE_CLIENT_URLS="http://10.40.239.235:2379"

ETCD_INITIAL_CLUSTER="node234=http://10.40.239.234:2380,node235=http://10.40.239.235:2380"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_INITIAL_CLUSTER_STATE="new"

 

2.4 修改etcd.service

在两台服务器上,分别修改服务启动文件 /usr/lib/systemd/system/etcd.service,内容设置如下:

[Service]

Type=notify

WorkingDirectory=/var/lib/etcd/

EnvironmentFile=-/etc/etcd/etcd.conf

User=etcd

# set GOMAXPROCS to number of processors

ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd 

--name="${ETCD_NAME}" 

--data-dir="${ETCD_DATA_DIR}" 

--listen-peer-urls="${ETCD_LISTEN_PEER_URLS}" 

--listen-client-urls="${ETCD_LISTEN_CLIENT_URLS}" 

--initial-advertise-peer-urls="${ETCD_INITIAL_ADVERTISE_PEER_URLS}" 

--advertise-client-urls="${ETCD_ADVERTISE_CLIENT_URLS}" 

--initial-cluster="${ETCD_INITIAL_CLUSTER}"  

--initial-cluster-token="${ETCD_INITIAL_CLUSTER_TOKEN}" 

--initial-cluster-state="${ETCD_INITIAL_CLUSTER_STATE}""

Restart=on-failure

LimitNOFILE=65536

 

2.5 启动 etcd

依次启动 node234和node235节点的 etcd

systemctl start etcd.service

设置允许开机启动:

systemctl enable etcd.service

2.6 查看etcd的状态

执行下列命令,验证etcd的状态:

etcdctl cluster-health

结果:

member 5a4542289ef36c64 is healthy: got healthy result from http://10.40.239.234:2379

member f792ada069403352 is healthy: got healthy result from http://10.40.239.235:2379

 

查看etfd 结点列表:

etcdctl member list

结果:

5a4542289ef36c64: name=node234 peerURLs=http://10.40.239.234:2380 clientURLs=http://10.40.239.234:2379 isLeader=true

f792ada069403352: name=node236 peerURLs=http://10.40.239.235:2380 clientURLs=http://10.40.239.236:2379 isLeader=false

 
原文地址:https://www.cnblogs.com/xianghuaqiang/p/14792001.html