第9章 复制镜像和引导
Patroni允许自定义创建新副本。它还支持定义在引导新的空群集时发生的情况。两者之间的区别已明确定义:只有在集群的DCS中存在初始化键时,Patroni才会创建副本。如果没有初始化键-Patroni将在拥有初初始化键锁定的第一个节点上专门调用引导程序。
9.1 引导
PostgreSQL 提供了 initdb 命令来初始化一个新的集群,Patroni 默认调用它。 在某些情况下,特别是在创建新集群作为现有集群的副本时,有必要用自定义操作替换内置方法。 Patroni 支持执行用户定义的脚本来引导新集群,为它们提供一些必需的参数,即集群的名称和数据目录的路径。 bootstrap的配置是Patroni的配置中的一部分。 例如:
bootstrap:
  method: <custom_bootstrap_method_name>
    <custom_bootstrap_method_name>:
    command: <path_to_custom_bootstrap_script> [param1 [, ...]]
    keep_existing_recovery_conf: False
    no_params: False
    recovery_conf:
      recovery_target_action: promote
      recovery_target_timeline: latest
      restore_command: <method_specific_restore_command>

每个引导方法必须至少定义一个名字和命令。特殊的initdb方法可用于触发默认行为,在这种情况下,方法参数可以完全省略。可以使用绝对路径或相对于Patroni命令位置的路径指定命令。除了在配置文件中定义的固定参数之外,Patroni还提供了两个特定于群集的参数:
--scope 要引导的集群的名称
--datadir 要引导的集群实例的数据目录的路径
可以通过将特殊的 no_params 参数设置为 True 来禁用传递这两个额外的标志。
如果引导脚本返回0,则Patroni尝试配置并启动它生成的PostgreSQL实例。 如果任何中间步骤失败,或者脚本返回非零值,则Patroni会认为引导程序已失败,自行清除后释放初始化锁,使另一个节点有机会进行引导。
如果在与自定义引导程序方法相同的部分中定义了recovery_conf块,则Patroni将在启动新引导的实例之前生成recovery.conf。 通常,此类recovery.conf应包含至少一个recovery_target_*参数,设置为promote的recovery_target_timeline将一起使用。
如果定义了keep_existing_recovery_conf 并将其设置为True,则Patroni 不会删除现有的recovery.conf 文件(如果存在)。 这在使用 pgBackRest 等工具从备份引导时非常有用,这些工具为您生成适当的 recovery.conf。
注意:Bootstrap 方法既不链接,也不会在主方法失败时退回到默认方法
9.2 构建副本
Patroni使用久经考验的pg_basebackup来创建新副本。它的缺点之一是它需要一个正在运行的主节点。另一个是缺乏对备份数据的“即时”压缩,也没有对过时的备份文件进行内置清理。有些人喜欢其他备份解决方案,例如WAL-E, pgBackRest, Barman 等,或者只是滚动自己的脚本。为了适应所有这些用例,Patroni支持运行自定义脚本来克隆新副本。这些在postgresql 配置块中配置:
postgresql:
  create_replica_methods:
    - <method name>
  <method name>:
    command: <command name>
    keep_data: True
    no_params: True
    no_master: 1

示例:wal_e
postgresql:
  create_replica_methods:
    - wal_e
    - basebackup
  wal_e:
    command: patroni_wale_restore
    no_master: 1
    envdir: {{WALE_ENV_DIR}}
    use_iam: 1
  basebackup:
    max-rate: '100M'

示例:pgbackrest
postgresql:
  create_replica_methods:
    - pgbackrest
    - basebackup
  pgbackrest:
    command: /usr/bin/pgbackrest --stanza=<scope> --delta restore
    keep_data: True
    no_params: True
  basebackup:
    max-rate: '100M'

create_replica_methods 定义了可用的副本创建方法及其执行顺序。
Patroni 将在第一个返回 0 的方法上停止。每个方法都应该在配置文件中定义一个单独的部分,列出要执行的命令以及应该传递给该命令的任何自定义参数。 所有参数将以 --name=value 格式传递。 除了用户定义的参数外,Patroni 还提供了几个特定于集群的参数:
--scope 这个副本属于哪个集群
--datadir 副本的数据目录
--role 复制用户的名字,总是‘replica’
--connstring 连接字符串以连接到要克隆的集群成员(主或其他副本)。 连接字符串中的用户可以执行 SQL 和复制协议命令。
如果定义了特殊的no_master参数,即使没有运行中的主服务器或副本,Patroni也可以调用副本创建方法。在这种情况下,将在连接字符串中传递一个空字符串。这对于从二进制备份还原以前运行的集群很有用
如果定义了特殊的keep_data参数,它将指示Patroni在调用restore之前不清除PGDATA文件夹。
如果定义了特殊的no_params参数,则将传递参数限制为自定义命令。basebackup 方法是一种特殊情况:如果create_replica_methods为空,将使用它,尽管可以在create_replica_methods方法中明确列出它。此方法使用pg_basebackup初始化一个新副本,除非有带有clonefrom标签的副本,否则基本备份将从主获取,在这种情况下,此类副本之一将用作pg_basebackup的来源。
它无需任何配置即可工作。但也可能指定basebackup配置节。适用与其他方法配置相同的规则,即,仅应在此处指定长选项(带有–)。
并非所有参数都有意义,如果您覆盖了连接字符串或提供了创建已压缩或压缩的基本备份的选项,则patroni将无法从中创建副本。传递给basebackup部分的参数的名称或值不执行验证
另请注意,如果符号链接用于 WAL 文件夹,则由用户指定正确的 --waldir 路径作为选项,以便在副本构建或重新初始化后符号链接将持续存在。但是,只有pg v10之后才支持此选项。
您可以将 basebackup 参数指定为映射(键值对)或元素列表,其中每个元素可以是键值对或单个键(对于不接收任何值的选项,例如 ,--verbose)。 考虑这两个例子:
postgresql:
  basebackup:
    max-rate: '100M'
    checkpoint: 'fast'


postgresql:
  basebackup:
    - verbose
    - max-rate: '100M'
    - waldir: /pg-wal-mount/external-waldir

如果所有副本创建方法都失败,Patroni 将在下一个事件循环周期内按顺序重试所有方法。
9.3 备用集群
另一个可用选项是运行“备用集群”,其中仅包含从某个远程主节点复制的备用节点。 这种类型的集群具有:
• “standby leader”,其行为与常规集群领导者非常相似,只是它从远程主服务器复制。
• cascade replicas,从备用leader复制。
Standby leader持有并更新 DCS 中的leader锁。 如果leader锁到期,cascade replicas将执行选举以从备用replica中选择另一个leader。
为了灵活性,您可以通过在standby_cluster 部分提供create_replica_methods 键来指定在集群处于“备用模式”时创建副本和恢复WAL 记录的方法。 与创建副本不同,当集群分离并作为普通集群运行时,由 postgresql 部分中的 create_replica_methods 控制。 postgresql 部分中的“standby”和“normal” create_replica_methods 引用键。
bootstrap:
  dcs:
    standby_cluster:
      host: 1.2.3.4
      port: 5432
      primary_slot_name: patroni
      create_replica_methods:
      - basebackup

要配置这样的集群,您需要在Patroni配置中指定standby_cluster 部分:
请注意,这些选项在集群引导期间只会应用一次,之后更改它们的唯一方法是通过 DCS。
如果在备集群上使用复制槽,还必须在主集群上创建对应的复制槽。 备用集群实施不会自动完成。 您可以在主集群上使用 Patroni 的永久复制槽功能来维护与 primary_slot_name 同名的复制槽,或者如果未提供 primary_slot_name 则为默认值。