运维开发网

k8s的高可用Postgres Patroni实现原理测试报告

运维开发网 https://www.qedev.com 2021-03-06 12:35 出处:51CTO 作者:Super孙文波
背景:因项目需求,需要基于k8s部署高可用postgres数据库。采用方案:PatroniPatroni介绍patroni是一款运用dcs存储集群来存储信息、主备状态与配置,通过patroni来检测并且实现主备库自动切换的软件。使用一套模板化的配置文件来自动搭建初始化数据库流复制集群以及配置数据库。patroni高可用集群由postgresql,patroni,dcs存储组成patroni:通过参

背景:因项目需求,需要基于k8s部署高可用postgres数据库。

采用方案:Patroni

Patroni介绍

patroni 是一款运用 dcs 存储集群来存储信息、主备状态与配置,通过 patroni 来检测并且实 现主备库自动切换的软件。使用一套模板化的配置文件来自动搭建初始化数据库流复制集群 以及配置数据库。

patroni 高可用集群由 postgresql,patroni,dcs 存储组成

patroni:通过参数文件来配置自动初始化数据库搭建流复制(配置 pg 参数 文件、创建用户、可以配置预加脚本),指定 etcd 节点等。负责通过一个 api 接口连接到 dcs(分布式存储系统:etcd 集群),向其

插入键值记录 patroni 参数、数据库参数、主备信息以及连接信息。平常通过 etcd 对其 它节点做心跳检测。与数据库的主备切换或者做恢复时通过向 etcd 拿取键 值中储存的主备信息来判断各节点的状态进行切换。

etcd:最少需要三个节点且为奇数来进行 leader 选举(脑裂发生时会 etcd 集群会僵死等待恢复,不会发生都认为自己是主的情况)。在各个节点上同 步健康状态信息以及数据库节点的主备状态与连接、配置信息。平常会对

其余节点做心跳检测。

组件说明:

patroni:通过参数文件来配置自动初始化数据库搭建流复制(配置 pg 参数文件、创建用户、可以配置预加脚本),指定 etcd 节点等。负责通过一个 api 接口连接到 dcs(分布式存储系统集群),向其插入键值记录 patroni

参数、数据库参数、主备信息以及连接信息。平时通过对 etcd 中的信息进行更新、读取来判断集群的健康状态。在主备切换或者做恢复时通过向etcd 读取主备信息来判断各节点的状态进行切换。(此处用etcd举例,还可以选择zookeeper、consul)

etcd最少需要三个节点且为奇数来进行 leader 选举(脑裂发生时 etcd 集群会僵死等待恢复,不会发生都认为自己是主的情况)。存储 并在各个节点上同步键值信息。

patroni工作流程图:

k8s的高可用Postgres Patroni实现原理测试报告

流程文字描述:

  • Patroni 自动创建主备流复制集群通过 api 接口往 etcd 记录键值来储存主备信息与连接 信息以及配置信息

  • Etcd 进行心跳检测(etcd 之间的心态检测)与存储键值信息

  • patroni 通过连接 etcd 对其它节点做心跳检测,每 loop_wait 秒一次

  • patroni 通过连接到 etcd 集群,向其插入键值记录 patroni 参数、数据库参数、主备信 息以及连接信息。进行数据库的主备切换时通过向 etcd 拿取键值中储存的主备信息来
  • 判断各节点的状态来切换。各节点会在 data 目录下生成 recovery.done(与 recovery.conf 一样,里面的 primary_conninfo 记录是上一次主节点的连接信息),原主节点发生切换
  • 时自动改变后缀为 recovery.conf,原备节点会删除掉自身的 recovery.conf 文件,再通 过 pg_rewind 来快速恢复节点,不需要做基础备份。

  • 异步流复制时主从之间延时:主从之间 wal 日志延时超过 maximum_lag_on_failover(byte)的大小,主备有可能会重启但不会发生切换。 数据丢失量通过 maximum_lag_on_failover,ttl,loop_wait 三个参数控制。

  • 最坏的情况下的丢失量: maximum_lag_on_failover 字节+最后的 TTL 秒时间内写入的日志量(loop_wait /2 在平 均情况下)。

  • haproxy+keeplived 保持对外的访问 ip 端口不变

优势:

  • 自动检测主备状态进行切换、统一模板配置

  • 在上图最基本的架构中,任意 down 一个 etcd 节点或者任意一个 patroni 节点、数据节点,通过转换都能使集群继续运行下去。测试中有针对于三个 etcd 网络互不通做了脑 裂测试,故障发生后 etcd 集群会僵死等待恢复,

  • 不会发生都认为自己是主的情况。主 库会变成只读状态,恢复网络后,主、备继续用 etcd 的数据信息恢复到故障前的状态,etcd 也恢复正常。

  • 在线添加 etcd、patroni 节点以及数据节点

  • 支持同步异步流复制,级联流复制

  • 异步流复制可设置最小丢失数据量

  • 使用 pg_rewind 进行恢复,缩短恢复时间

  • haproxy+keeplived 可以保持在主备切换或者节点故障后,实现 ip 漂移。对外的 ip+端口不变。

限制:

  • patroni 对数据库操作需要普通用户

  • 需要至少三个以上且为奇数的 etcd 节点

  • 底层基于的是流复制

  • 大部分参数都需要通过更改 etcd 中键值来修改

  • 因故障发生的连接会回滚,但是需要客户端重新发起连接

使用过程中发现的疑点:

  • 使用patroni部署高可用postgres主库发生故障时,如何实现无感知恢复(迁移服务)

    答:使用官网helm chart patroni部署高可用集群,DCS组件默认使用etcd分布式键值(key-value)数据库,通过 etcd 对节点服务做心跳检测。与数据库的主备切换或者做恢复时通过向 etcd 拿取键值中储存的主备信息来判断各节点的状态进行切换。

    patroni values.yaml 内容如下

# Distribution Configuration stores
# Please note that only one of the following stores should be enabled.
# 请注意,应该只启用以下存储中的一个,这里因为我们是基于k8s部署所以选择kubernetes中的dcs。etcd也可以单独部署,将enable改为true同时将上面dcs改为false即可。
kubernetes:
  dcs:
    enable: true
  configmaps:
    enable: false
etcd:
  enable: false
  deployChart: false
  # If not deploying etcd chart, fill-in value for etcd service
  # <service>.<namespace>.svc.cluster.local
  host:
  # Leave blank to use vendored etcd chart
  discovery:

基于k8s部署的patroni,etcd是集成在DCS还是单独启动?为什么说是用etcd分布式键值库而不是Zookeeper或者是其他。

k8s的高可用Postgres Patroni实现原理测试报告

答:从官方的相关文档看,DCS可以是Etcd,也可以是Consul、Zookeeper、Exhibitor等等、使用不同的模块对应不同的分布式键值库。通过查看patroni的Dockerfile发现在build patroni镜像时将etcd相关安装包已经打在镜像中了,

并且进入pod查看有python的进程,所以判断DCS使用的etcd。

k8s的高可用Postgres Patroni实现原理测试报告

主库所在的pod发生故障时,该pod会被k8s杀死,那新建后这个pod的角色是什么?

答:经过多次测试,当主库pod发生故障,k8s将这个pod杀死,为了满足副本数,会新建一个pod,此时这个新建的pod不会参与竞选leader。具体竞选的策略使用etcd raft算法。相关配置在pod中postgres.yml中配置。

举例:现在有五个postgres的副本数,其中一个发生故障被杀死,在新建过程中,剩余的4个pod节点会开始竞选leader,竞选成功后为主库节点,其它pod为从库。且只有主库拥有所有权限,从库只有读权限。

DCS使用的是k8s集群的etcd。是自身的还是k8s集群的etcd?

答:经过测试调研验证DCS使用的etcd集群是k8s的etcd集群,官网解释如下:

k8s的高可用Postgres Patroni实现原理测试报告

测试过程:

pod正常情况下: etcd 数据如下,可以看到状态为running的

k8s的高可用Postgres Patroni实现原理测试报告

如果某个pod启动失败或者是服务有异常,etcd 数据如下,

k8s的高可用Postgres Patroni实现原理测试报告

基本流程:

Patroni 自动创建主备流复制集群通过 api 接口往 etcd 记录键值来储存主备信息与连接信息以及配置信息。

Etcd 进行心跳检测(etcd 之间的心态检测)与存储键值信息

patroni 通过连接 etcd 对其它节点做心跳检测,每 loop_wait 秒一次

patroni 通过连接到 etcd 集群,向其插入键值记录 patroni 参数、数据库参数、主备信 息以及连接信息。进行数据库的主备切换时通过向 etcd 拿取键值中储存的主备信息来 判断各节点的状态来切换。

各节点会在 data 目录下生成 recovery.done(与recovery.conf 一样,里面的 primary_conninfo 记录是上一次主节点的连接信息),原主节点发生切换 时自动改变后缀为 recovery.conf,原备节点会删除掉自身的 recovery.conf 文件,再通 过 pg_rewind 来快速恢复节点,不需要做基础备份。

etcdctl 工具使用方法:

#查看etcd根路径的key
etcdctl get / --prefix --keys-only=true | grep patroni

#查看某个key的value
etcdctl get /registry/events/default/test-patroni-0.165076b4d481f7d7 --prefix --keys-only=false -w=json | python -m json.tool

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号