--- title: "将独立实例转换为 Patroni 集群" linkTitle: "转换现有集群" weight: 140 icon: fa-solid fa-truck-moving description: "将现有 PostgreSQL 数据迁移并转换为 Patroni 集群的操作步骤。" module: [PATRONI] categories: [任务] aliases: [/patroni/existing_data/] upstream_link: "https://patroni.readthedocs.io/en/latest/existing_data.html" --- 本节介绍将独立 PostgreSQL 实例转换为 Patroni 集群的操作流程。 如需从零开始部署 Patroni 集群(不使用已有 PostgreSQL 实例),请参阅 [**运行与配置**](/zh/docs/patroni/readme#running_configuring)。 -------- ## 操作步骤 以下是将现有 PostgreSQL 集群转换为 Patroni 托管集群的步骤概览。本步骤假设现有集群的所有节点当前均在运行,并且您 **不打算** 在迁移过程中修改 PostgreSQL 配置。具体步骤如下: 1. 按照 Patroni 配置中 [**认证**](/zh/docs/patroni/config/yaml#postgresql_settings) 章节的说明创建 PostgreSQL 用户。下方代码块中提供了创建用户的示例 SQL 命令,请根据您的实际环境替换用户名和密码。如果相关用户已存在,可跳过此步骤。 ``` sql -- Patroni 超级用户 -- 请将 PATRONI_SUPERUSER_USERNAME 和 PATRONI_SUPERUSER_PASSWORD 替换为实际值 CREATE USER PATRONI_SUPERUSER_USERNAME WITH SUPERUSER ENCRYPTED PASSWORD 'PATRONI_SUPERUSER_PASSWORD'; -- Patroni 复制用户 -- 请将 PATRONI_REPLICATION_USERNAME 和 PATRONI_REPLICATION_PASSWORD 替换为实际值 CREATE USER PATRONI_REPLICATION_USERNAME WITH REPLICATION ENCRYPTED PASSWORD 'PATRONI_REPLICATION_PASSWORD'; -- Patroni rewind 用户(若您打算在 Patroni 配置中启用 use_pg_rewind) -- 请将 PATRONI_REWIND_USERNAME 和 PATRONI_REWIND_PASSWORD 替换为实际值 CREATE USER PATRONI_REWIND_USERNAME WITH ENCRYPTED PASSWORD 'PATRONI_REWIND_PASSWORD'; GRANT EXECUTE ON function pg_catalog.pg_ls_dir(text, boolean, boolean) TO PATRONI_REWIND_USERNAME; GRANT EXECUTE ON function pg_catalog.pg_stat_file(text, boolean) TO PATRONI_REWIND_USERNAME; GRANT EXECUTE ON function pg_catalog.pg_read_binary_file(text) TO PATRONI_REWIND_USERNAME; GRANT EXECUTE ON function pg_catalog.pg_read_binary_file(text, bigint, bigint, boolean) TO PATRONI_REWIND_USERNAME; ``` 2. 在所有 PostgreSQL 节点上依次执行以下操作。请逐节点完成所有步骤后再处理下一个节点,先从主库开始,然后依次处理各从库节点: 1. 如果 PostgreSQL 通过 systemd 管理,请先禁用 PostgreSQL 的 systemd 服务单元——因为 PostgreSQL 的启停将改由 Patroni 负责管理。 2. 为 Patroni 创建 YAML 配置文件。可使用 [**Patroni 配置生成与校验工具**](/zh/docs/patroni/config#validate_generate_config) 完成此操作。 - **注意(仅适用于主库):** 如果现有集群成员之间使用复制槽进行复制,建议启用 **`use_slots`** 并通过 **`slots`** 配置项将现有复制槽设为永久槽。请注意,当 **`use_slots`** 启用时,Patroni 会自动为成员间复制创建复制槽,并删除它无法识别的复制槽。此处使用永久槽的目的是在迁移至 Patroni 的过程中保留现有复制槽。详情请参阅 [**动态配置项**](/zh/docs/patroni/config/dynamic#dynamic)。 3. 通过 **`patroni`** systemd 服务单元启动 Patroni。Patroni 将自动检测到 PostgreSQL 已在运行,并开始监控该实例。 3. 将 PostgreSQL 的"启动控制权"移交给 Patroni。为此,需要通过 [`patronictl restart cluster-name member-name`](/zh/docs/patroni/patronictl#patronictl_restart_parameters) 命令重启各集群成员。为最大限度减少停机时间,建议将此步骤拆分为: 1. 立即重启从库节点。 2. 在维护窗口内计划性地重启主库。 4. 如果您在第 2.2 步中配置了永久槽,应在 Patroni 创建的复制槽的 **`restart_lsn`** 追上对应成员原始槽的 **`restart_lsn`** 之后,通过 [`patronictl edit-config cluster-name`](/zh/docs/patroni/patronictl#patronictl_edit_config_parameters) 命令将其从 **`slots`** 配置中移除。移除后,Patroni 将在这些原始槽不再被需要时自动将其删除。以下是用于比较两个槽 **`restart_lsn`** 的示例查询: ``` sql -- 假设 original_slot_for_member_x 是原集群中用于向成员 X 复制变更的槽名称, -- slot_for_member_x 是 Patroni 为同一目的创建的槽名称。 -- 需要确认 slot_for_member_x 的 restart_lsn >= original_slot_for_member_x 的 restart_lsn SELECT slot_name, restart_lsn FROM pg_replication_slots WHERE slot_name IN ( 'original_slot_for_member_x', 'slot_for_member_x' ) ``` ## PostgreSQL 大版本升级 目前,进行大版本升级的唯一可行方式是: 1. 停止 Patroni。 2. 升级 PostgreSQL 二进制文件,并在主库上执行 [pg_upgrade](https://www.postgresql.org/docs/current/pgupgrade.html)。 3. 更新 **`patroni.yml`**。 4. 从 DCS 中删除 **`initialize`** 键,或清除 DCS 中的完整集群状态。后者可通过执行 [`patronictl remove cluster-name`](/zh/docs/patroni/patronictl#patronictl_remove_parameters) 命令完成。这是必要的,因为 **`pg_upgrade`** 会运行 **`initdb`**,从而创建一个具有新 PostgreSQL 系统标识符的新数据库。 5. 如果您在上一步中清除了集群状态,建议将旧数据目录中的 **`patroni.dynamic.json`** 复制到新数据目录,以保留之前设置的 PostgreSQL 参数。 6. 在主库上启动 Patroni。 7. 在从库节点上升级 PostgreSQL 二进制文件,更新 **`patroni.yml`**,并清空 **`data_dir`**。 8. 在从库节点上启动 Patroni,等待复制完成。 PostgreSQL 不支持在从库节点上运行 **`pg_upgrade`**。如果您清楚自己在做什么,也可以尝试 中描述的 rsync 方式,以替代清空从库节点 **`data_dir`** 的操作。但最安全的方式仍然是让 Patroni 为您完成数据复制。 -------- ## 常见问题 - **Patroni 启动时报错,提示无法绑定到 PostgreSQL 端口。** 请核查 **`postgresql.conf`** 中的 **`listen_addresses`** 和 **`port`** 配置,以及 **`patroni.yml`** 中的 **`postgresql.listen`** 配置。同时不要忘记确认 **`pg_hba.conf`** 中允许相应的访问。 - **请求 Patroni 重启节点后,PostgreSQL 报错:`could not open configuration file "/etc/postgresql/10/main/pg_hba.conf": No such file or directory`** 这个问题可能由多种原因引起,具体取决于您管理 PostgreSQL 配置的方式。如果您指定了 **`postgresql.config_dir`**,Patroni 只会在引导新集群时,根据 [**bootstrap**](/zh/docs/patroni/config/yaml#bootstrap_settings) 章节中的配置生成 **`pg_hba.conf`**。在当前场景中,由于 **`PGDATA`** 非空,引导过程并未发生,因此该文件必须事先存在。