k8s的高可用Postgres 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

猜你喜欢

转载自blog.51cto.com/14034751/2647897