# 管理 PostgreSQL 数据库集群

> 创建/销毁 PostgreSQL 集群，以及对现有集群进行扩容，缩容，克隆集群。

---

LLMS index: [llms.txt](/llms.txt)

---

## 速查手册

| 操作                  | 快捷命令                          | 说明                 |
|:--------------------|:------------------------------|:-------------------|
| [**创建集群**](#创建集群)   | `bin/pgsql-add <cls>`         | 创建新的 PostgreSQL 集群 |
| [**扩容集群**](#扩容集群)   | `bin/pgsql-add <cls> <ip...>` | 为现有集群添加从库副本        |
| [**缩容集群**](#缩容集群)   | `bin/pgsql-rm <cls> <ip...>`  | 从集群中移除指定实例         |
| [**销毁集群**](#销毁集群)   | `bin/pgsql-rm <cls>`          | 销毁整个 PostgreSQL 集群 |
| [**刷新服务**](#刷新服务)   | `bin/pgsql-svc <cls> [ip...]` | 重载集群的负载均衡配置        |
| [**刷新HBA**](#刷新hba) | `bin/pgsql-hba <cls> [ip...]` | 重载集群的 HBA 访问规则     |
| [**克隆集群**](#克隆集群)   | -                             | 通过备份集群或 PITR 克隆    |
{.full-width}

其他管理任务，请参考：[**高可用管理**](/docs/pgsql/admin/patroni)，[**管理用户**](/docs/pgsql/admin/user/)，[**管理数据库**](/docs/pgsql/admin/db/)。


----------------

## 创建集群

要创建一个新的 PostgreSQL 集群，请首先在 [**配置清单**](/docs/concept/iac/inventory) 中 [**定义集群**](/docs/pgsql/config/cluster)，然后 [**纳管节点**](/docs/node/admin#添加节点) 并进行初始化：

**脚本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-0-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-0-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/node-add  &lt;cls&gt;     <span class="c1"># 添加分组 &lt;cls&gt; 下的节点</span></span></span></code></pre></div></div>
</div>

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-0-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-0-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./node.yml  -l &lt;cls&gt;    <span class="c1"># 直接使用 Ansible 剧本添加分组 &lt;cls&gt; 下的节点</span></span></span></code></pre></div></div>
</div>

**示例**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-0-tab-2" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-0-tab-2-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/node-add pg-test    <span class="c1"># 例子，添加 pg-test 分组下的节点，实际执行 ./node.yml -l pg-test</span></span></span></code></pre></div></div>
</div>

在被纳管的节点上，可以使用以下命令创建集群：（针对 **`<cls>`** 分组执行 [**`pgsql.yml`**](/docs/pgsql/playbook#pgsqlyml) 剧本）

**脚本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-1-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-1-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-add &lt;cls&gt;     <span class="c1"># 创建 PostgreSQL 集群 &lt;cls&gt;</span></span></span></code></pre></div></div>
</div>

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-1-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-1-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./pgsql.yml -l &lt;cls&gt;    <span class="c1"># 直接使用 Ansible 剧本创建 PostgreSQL 集群 &lt;cls&gt;</span></span></span></code></pre></div></div>
</div>

**示例**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-1-tab-2" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-1-tab-2-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-add pg-test   <span class="c1"># 例子，创建 pg-test 集群</span></span></span></code></pre></div></div>
</div>


**示例：创建三节点 PG 集群 `pg-test`**

<div id="td-asciinema-bbaec645058227f42673d57f065de673-2" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"markers":[4,"执行"],"preload":false,"speed":1.3,"startAt":0},"src":"/demo/pgsql.cast","theme":"auto"}</script>
</div>


<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading" aria-level="4">针对已经存在的集群重新执行创建存在风险</div>


如果您在已经存在的集群上重新执行创建操作，Pigsty 不会移除已有的数据文件，但现有服务配置会被覆盖，集群会发生 **重启**！
此外，如果你在 [**数据库定义**](/docs/pgsql/config/db#baseline) 中指定了 `baseline` SQL，它也会重新执行，如果里面包含删除/覆盖逻辑，可能会导致 **数据丢失**。
</div>








----------------

## 扩容集群

若要将新从库添加到 **现有的 PostgreSQL 集群** 中，您需要将 [**实例定义**](/docs/pgsql/config/cluster) 添加到 [**配置清单**](/docs/concept/iac/inventory)：`all.children.<cls>.hosts` 中。

```yaml
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary } # 已存在的成员
    10.10.10.12: { pg_seq: 2, pg_role: replica } # 已存在的成员
    10.10.10.13: { pg_seq: 3, pg_role: replica } # <--- 新成员
  vars: { pg_cluster: pg-test }
```

扩容集群的操作与 [**创建集群**](#创建集群) 非常类似，首先需要将扩容的节点纳入 Pigsty 管理：[**添加节点**](/docs/node/admin#添加节点)：

**脚本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-4-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-4-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/node-add &lt;ip&gt;       <span class="c1"># 添加 IP 地址为 &lt;ip&gt; 的节点</span></span></span></code></pre></div></div>
</div>

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-4-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-4-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./node.yml -l &lt;ip&gt;      <span class="c1"># 直接使用 Ansible 剧本添加 &lt;ip&gt; 对应的节点</span></span></span></code></pre></div></div>
</div>

**示例**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-4-tab-2" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-4-tab-2-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/node-add 10.10.10.13    <span class="c1"># 例子，添加 IP 为 10.10.10.13 的节点，实际执行 ./node.yml -l 10.10.10.13</span></span></span></code></pre></div></div>
</div>

然后在新节点上运行以下命令以扩容集群（针对新节点安装 [**PGSQL 模块**](/docs/pgsql)，使用与现有集群相同的 [**`pg_cluster`**](/docs/pgsql/param#pg_cluster)）

**脚本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-5-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-5-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-add &lt;cls&gt; &lt;ip&gt;  <span class="c1"># 添加 IP 地址为 &lt;ip&gt; 的节点</span></span></span></code></pre></div></div>
</div>

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-5-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-5-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./pgsql.yml -l &lt;ip&gt;       <span class="c1"># 核心逻辑：使用 Ansible 剧本在 &lt;ip&gt; 节点上安装 PGSQL 模块</span></span></span></code></pre></div></div>
</div>

**示例**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-5-tab-2" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-5-tab-2-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-add pg-test 10.10.10.13   <span class="c1"># 示例，为 pg-test 集群扩容 IP 为 10.10.10.13 的节点</span></span></span></code></pre></div></div>
</div>

扩容完成后，您应当 [**刷新服务**](/docs/pgsql/admin/cluster#刷新服务) 以将新成员添加至负载均衡器中以实际承载流量。

**示例：为两节点集群 `pg-test` 扩容一个新从库 `10.10.10.13`**

<div id="td-asciinema-bbaec645058227f42673d57f065de673-6" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql-append.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"preload":false,"speed":1.2,"startAt":0},"src":"/demo/pgsql-append.cast","theme":"auto"}</script>
</div>







----------------

## 缩容集群

若要从 **现有的 PostgreSQL 集群** 中移除副本，您需要从 [**配置清单**](/docs/concept/iac/inventory) 的 `all.children.<cls>.hosts` 中移除对应的 [**实例定义**](/docs/pgsql/config/cluster)。

缩容会停止实例并默认删除其数据目录。操作前先执行 `pig pg list <cls>` 与 `pig pb info`，确认目标不是主库、存在近期可恢复备份，
并让操作者输入精确的 `<ip>`，确认后方可实际执行。

缩容集群首先需要卸载目标节点上的 PGSQL 模块（针对 **`<ip>`** 执行 [**`pgsql-rm.yml`**](/docs/pgsql/playbook#pgsql-rmyml) 剧本）：

**脚本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-7-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-7-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-rm &lt;cls&gt; &lt;ip&gt;   <span class="c1"># 从集群 &lt;cls&gt; 中移除 &lt;ip&gt; 节点上的 PostgreSQL 实例</span></span></span></code></pre></div></div>
</div>

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-7-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-7-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./pgsql-rm.yml -l &lt;ip&gt;    <span class="c1"># 直接使用 Ansible 剧本移除 &lt;ip&gt; 节点上的 PostgreSQL 实例</span></span></span></code></pre></div></div>
</div>

**示例**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-7-tab-2" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-7-tab-2-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-rm pg-test 10.10.10.13  <span class="c1"># 例子，从 pg-test 集群移除 10.10.10.13 节点</span></span></span></code></pre></div></div>
</div>

移除 PGSQL 模块后，您可以选择将节点从 Pigsty 管理中移除：[**移除节点**](/docs/node/admin#移除节点)（可选）：

**脚本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-8-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-8-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/node-rm &lt;ip&gt;          <span class="c1"># 从 Pigsty 管理中移除 &lt;ip&gt; 节点</span></span></span></code></pre></div></div>
</div>

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-8-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-8-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./node-rm.yml -l &lt;ip&gt;     <span class="c1"># 直接使用 Ansible 剧本从 Pigsty 管理中移除 &lt;ip&gt; 节点</span></span></span></code></pre></div></div>
</div>

**示例**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-8-tab-2" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-8-tab-2-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/node-rm 10.10.10.13   <span class="c1"># 例子，从 Pigsty 管理中移除 10.10.10.13 节点</span></span></span></code></pre></div></div>
</div>

缩容完成后，您应当从 [**配置清单**](/docs/concept/iac/inventory) 中移除该实例的定义，然后 [**刷新服务**](/docs/pgsql/admin/cluster#刷新服务) 以将它从负载均衡器中踢除。

```yaml
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
    10.10.10.13: { pg_seq: 3, pg_role: replica } # <--- 执行后移除此行
  vars: { pg_cluster: pg-test }
```

**示例：从三节点集群 `pg-test` 中缩容一个从库 `10.10.10.13`**

<div id="td-asciinema-bbaec645058227f42673d57f065de673-9" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql-shrink.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"preload":false,"speed":1.2,"startAt":0},"src":"/demo/pgsql-shrink.cast","theme":"auto"}</script>
</div>








----------------

## 销毁集群

销毁集群需要在集群的所有节点上卸载 PGSQL 模块（针对 **`<cls>`** 执行 [**`pgsql-rm.yml`**](/docs/pgsql/playbook#pgsql-rmyml) 剧本）：

这是不可逆的数据删除：先用 `pig pg list <cls>` 与 `pig pb info` 核对状态和近期备份，决定是否保留独立备份副本，
并要求操作者输入精确集群名。下面命令会直接执行相应的销毁操作。

**脚本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-10-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-10-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-rm &lt;cls&gt;        <span class="c1"># 销毁整个 PostgreSQL 集群 &lt;cls&gt;</span></span></span></code></pre></div></div>
</div>

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-10-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-10-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./pgsql-rm.yml -l &lt;cls&gt;   <span class="c1"># 直接使用 Ansible 剧本销毁整个 PostgreSQL 集群 &lt;cls&gt;</span></span></span></code></pre></div></div>
</div>

**示例**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-10-tab-2" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-10-tab-2-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-rm pg-test      <span class="c1"># 例子，销毁 pg-test 集群</span></span></span></code></pre></div></div>
</div>

销毁 PGSQL 模块后，您可以选择将节点一并从 Pigsty 管理中移除：[**移除节点**](/docs/node/admin#移除节点)（可选，如果还有其他服务可以保留）：

**脚本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-11-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-11-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/node-rm &lt;cls&gt;         <span class="c1"># 从 Pigsty 管理中移除 &lt;cls&gt; 分组下的所有节点</span></span></span></code></pre></div></div>
</div>

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-11-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-11-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./node-rm.yml -l &lt;cls&gt;    <span class="c1"># 直接使用 Ansible 剧本从 Pigsty 管理中移除 &lt;cls&gt; 分组下的所有节点</span></span></span></code></pre></div></div>
</div>

**示例**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-11-tab-2" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-11-tab-2-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/node-rm pg-test       <span class="c1"># 例子，从 Pigsty 管理中移除 pg-test 分组下的所有节点</span></span></span></code></pre></div></div>
</div>

销毁结束后，建议及时从 [**配置清单**](/docs/concept/iac/inventory) 中移除整个 [**集群定义**](/docs/pgsql/config/cluster)。

```yaml
pg-test: # 清理这个集群定义分组
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
    10.10.10.13: { pg_seq: 3, pg_role: replica }
  vars: { pg_cluster: pg-test }
```


**示例：销毁三节点 PG 集群 `pg-test`**

<div id="td-asciinema-bbaec645058227f42673d57f065de673-12" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql-rm.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"preload":false,"speed":1.2,"startAt":0},"src":"/demo/pgsql-rm.cast","theme":"auto"}</script>
</div>


注意：如果为这个集群配置了 [**`pg_safeguard`**](/docs/pgsql/param#pg_safeguard)（或全局设置为 `true`），`pgsql-rm.yml` 将中止执行，以避免意外销毁集群。
您可以使用剧本命令行参数明确地覆盖它，以强制执行销毁。
此外默认情况下，集群的备份仓库将同集群一并删除。如果你希望保留备份（例如在使用集中式备份仓库时），可以设置 [**`pg_rm_backup=false`**](/docs/pgsql/param#pg_rm_backup) 参数：


```bash
./pgsql-rm.yml -l pg-meta -e pg_safeguard=false    # 强制销毁受保护的 pg 集群 pg-meta
./pgsql-rm.yml -l pg-meta -e pg_rm_backup=false    # 在销毁集群过程中保留其备份仓库
```








----------------

## 刷新服务

PostgreSQL 集群通过主机节点上的 [**HAProxy**](/docs/concept/arch/pgsql#haproxy) 对外提供 [**服务**](/docs/pgsql/service/)。
当服务定义变化、实例权重变化，或者集群成员发生变化时（例如集群 [**扩容**](#扩容集群) / [**缩容**](#缩容集群)），您需要刷新服务以更新负载均衡器的静态成员配置。默认 Primary/Replica 服务通过 Patroni REST API 健康检查识别当前角色，正常的主从切换或故障转移会自动改道，不要求重新生成 HAProxy 配置。

要在整个集群或特定实例上刷新服务配置（针对 **`<cls>`** 或 **`<ip>`** 执行 [**`pgsql.yml`**](/docs/pgsql/playbook#pgsqlyml) 的 `pg_service` 子任务）：

**脚本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-13-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="2"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-13-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-svc &lt;cls&gt;           <span class="c1"># 刷新整个集群 &lt;cls&gt; 的服务配置</span>
</span></span><span class="line"><span class="cl">bin/pgsql-svc &lt;cls&gt; &lt;ip...&gt;   <span class="c1"># 刷新集群 &lt;cls&gt; 中指定实例的服务配置</span></span></span></code></pre></div></div>
</div>

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-13-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="2"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-13-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./pgsql.yml -l &lt;cls&gt; -t pg_service -e <span class="nv">pg_reload</span><span class="o">=</span><span class="nb">true</span>        <span class="c1"># 刷新整个集群的服务配置</span>
</span></span><span class="line"><span class="cl">./pgsql.yml -l &lt;ip&gt;  -t pg_service -e <span class="nv">pg_reload</span><span class="o">=</span><span class="nb">true</span>        <span class="c1"># 刷新指定实例的服务配置</span></span></span></code></pre></div></div>
</div>

**示例**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-13-tab-2" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="2"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-13-tab-2-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-svc pg-test                 <span class="c1"># 例子，刷新 pg-test 集群的服务配置</span>
</span></span><span class="line"><span class="cl">bin/pgsql-svc pg-test 10.10.10.13     <span class="c1"># 例子，刷新 pg-test 集群中 10.10.10.13 实例的服务配置</span></span></span></code></pre></div></div>
</div>

> 备注：如果您使用集中式的专用负载均衡集群（[**`pg_service_provider`**](/docs/pgsql/param#pg_service_provider)），那么只有刷新集群主库时才会更新负载均衡配置。


**示例：刷新集群 `pg-test` 的服务配置**

<div id="td-asciinema-bbaec645058227f42673d57f065de673-14" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql-svc.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"preload":false,"speed":1.2,"startAt":0},"src":"/demo/pgsql-svc.cast","theme":"auto"}</script>
</div>


<details><summary>示例：重载 PG 服务以踢除一个实例</summary>

[![asciicast](https://asciinema.org/a/568815.svg)](https://asciinema.org/a/568815)

</details>




----------------

## 刷新HBA

当您修改了 HBA 相关配置后，需要刷新 HBA 规则以应用更改。（[**`pg_hba_rules`**](/docs/pgsql/param#pg_hba_rules) / [**`pgb_hba_rules`**](/docs/pgsql/param#pgb_hba_rules)）
如果您有任何特定于清单角色的 HBA 规则，或者在 IP 地址段中引用了集群成员的别名，那么修改 `pg_role` 标签或集群扩缩容后也可能需要刷新 HBA。这里的角色筛选使用静态清单变量，不会随 Patroni 主从切换自动改变。

要在整个集群或特定实例上刷新 PG 和 Pgbouncer 的 HBA 规则（针对 **`<cls>`** 或 **`<ip>`** 执行 [**`pgsql.yml`**](/docs/pgsql/playbook#pgsqlyml) 的 HBA 相关子任务）：

**脚本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-15-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="2"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-15-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-hba &lt;cls&gt;           <span class="c1"># 刷新整个集群 &lt;cls&gt; 的 HBA 规则</span>
</span></span><span class="line"><span class="cl">bin/pgsql-hba &lt;cls&gt; &lt;ip...&gt;   <span class="c1"># 刷新集群 &lt;cls&gt; 中指定实例的 HBA 规则</span></span></span></code></pre></div></div>
</div>

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-15-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="2"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-15-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./pgsql.yml -l &lt;cls&gt; -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload -e <span class="nv">pg_reload</span><span class="o">=</span><span class="nb">true</span>   <span class="c1"># 刷新整个集群</span>
</span></span><span class="line"><span class="cl">./pgsql.yml -l &lt;ip&gt;  -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload -e <span class="nv">pg_reload</span><span class="o">=</span><span class="nb">true</span>   <span class="c1"># 刷新指定实例</span></span></span></code></pre></div></div>
</div>

**示例**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-15-tab-2" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="2"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-15-tab-2-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-hba pg-test                 <span class="c1"># 例子，刷新 pg-test 集群的 HBA 规则</span>
</span></span><span class="line"><span class="cl">bin/pgsql-hba pg-test 10.10.10.13     <span class="c1"># 例子，刷新 pg-test 集群中 10.10.10.13 实例的 HBA 规则</span></span></span></code></pre></div></div>
</div>


**示例：刷新集群 `pg-test` 的 HBA 规则**

<div id="td-asciinema-bbaec645058227f42673d57f065de673-16" class="td-asciinema td-max-width-on-larger-screens" data-td-asciinema
  data-timer-label="播放时间">
  <div class="td-asciinema__chrome">
    <span class="td-asciinema__lights" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="td-asciinema__title" dir="auto">demo/pgsql-hba.cast</span>
  </div>
  <div data-td-asciinema-player></div>
  <script type="application/json" data-td-asciinema-config>{"options":{"autoPlay":true,"fit":"width","loop":true,"preload":false,"speed":1.2,"startAt":0},"src":"/demo/pgsql-hba.cast","theme":"auto"}</script>
</div>



----------------

## 配置集群

PostgreSQL 的配置参数由 Patroni 管理，初始参数由 [**Patroni 配置模板**](/docs/pgsql/template/) 指定。
集群初始化之后，配置存储在 Etcd 中，并由 Patroni 进行动态管理，并在集群中同步与共享。
Patroni 本身的 [**配置参数**](/docs/pgsql/admin/patroni#修改配置) 大部分可以通过 `patronictl` 命令行工具修改。
其余参数（例如，etcd DCS 配置，日志/RestAPI 等配置）则可以通过下面的子任务进行更新。例如，当 [**etcd**](/docs/etcd) 集群成员发生变动时，你可以刷新 Patroni 配置：

```bash
./pgsql.yml -l pg-test -t pg_conf                   # 更新 Patroni 配置文件
ansible pg-test -b -a 'systemctl reload patroni'    # 重载 Patroni 服务
```

您可以在不同层次上覆盖 Patroni 集中管理的默认，例如单独 [**为实例指定配置参数**](/docs/pgsql/param#pg_parameters)；
单独为 [**为用户指定配置参数**](/docs/pgsql/admin/user)，或者 [**为数据库指定配置参数**](/docs/pgsql/admin/db)。



----------------

## 克隆集群

有两种克隆集群的方式：使用 [**备份集群**](/docs/pgsql/config/cluster#备份集群) 功能，或者使用 [**时间点恢复**](/docs/pgsql/backup/restore#快速上手) 功能。
前者配置简单，无需备份仓库，但需要可达的复制上游，只能克隆指定集群的最新状态；后者依赖集中式的 [**备份仓库**](/docs/pgsql/backup/repository)（例如 Silo），可以克隆到恢复窗口内的任意时间点。

| 方式   | 优点          | 缺点              | 适用场景       |
|:-----|:------------|:----------------|:-----------|
| 备份集群 | 无需备份仓库      | 需要可达上游，只能克隆最新状态 | 灾备，读写分离，迁移 |
| PITR | 可恢复到窗口内任意时点 | 依赖集中式备份仓库       | 误操作恢复，数据审计 |


### 使用备份集群克隆

备份集群（Standby Cluster）通过流复制从上游集群持续同步数据，是克隆集群最简单的方式。
只需在新集群主库上指定 [**`pg_upstream`**](/docs/pgsql/param#pg_upstream) 参数，即可自动从上游集群拉取数据。

```yaml
# pg-test 是原始集群
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars: { pg_cluster: pg-test }

# pg-test2 是 pg-test 的备份集群（克隆）
pg-test2:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary, pg_upstream: 10.10.10.11 }  # 指定上游
    10.10.10.13: { pg_seq: 2, pg_role: replica }
  vars: { pg_cluster: pg-test2 }
```

使用以下命令创建备份集群：

**脚本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-17-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-17-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bin/pgsql-add pg-test2    <span class="c1"># 创建备份集群，自动从上游 pg-test 克隆数据</span></span></span></code></pre></div></div>
</div>

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-17-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-17-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./pgsql.yml -l pg-test2   <span class="c1"># 直接使用 Ansible 剧本创建备份集群</span></span></span></code></pre></div></div>
</div>

备份集群会持续追随上游集群，保持数据同步。您可以随时将其 **提升** 为独立集群：

<details><summary>示例：提升备份集群为独立集群</summary>

通过 [**配置集群**](#配置集群) 擦除 `standby_cluster` 配置段，即可将备份集群提升为独立集群：

```bash
$ pg edit-config pg-test2
-standby_cluster:
-  create_replica_methods:
-  - basebackup
-  host: 10.10.10.11
-  port: 5432

Apply these changes? [y/N]: y
```

提升后，`pg-test2` 将成为可以独立承载写入请求的独立集群，与原集群 `pg-test` 分叉。

</details>

<details><summary>示例：更改复制上游</summary>

如果上游集群发生主从切换，您可以通过 [**配置集群**](#配置集群) 更改备份集群的复制上游：

```bash
$ pg edit-config pg-test2

 standby_cluster:
   create_replica_methods:
   - basebackup
-  host: 10.10.10.11     # <--- 旧的上游
+  host: 10.10.10.14     # <--- 新的上游
   port: 5432

Apply these changes? [y/N]: y
```

</details>


### 使用 PITR 克隆

[**时间点恢复**](/docs/pgsql/backup/restore)（PITR）允许您将集群恢复到恢复窗口内的任意时间点。
此方式依赖集中式的 [**备份仓库**](/docs/pgsql/backup/repository)（如 Silo/S3），但功能更加强大。

要使用 PITR 克隆集群，在配置中添加 [**`pg_pitr`**](/docs/pgsql/backup/restore#pitr-参数定义) 参数指定恢复目标：

```yaml
# 从 pg-meta 集群的备份克隆一个新集群 pg-meta2
pg-meta2:
  hosts: { 10.10.10.12: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta2
    pg_pitr:
      cluster: pg-meta                    # 从 pg-meta 的备份恢复
      time: '2025-01-10 10:00:00+00'      # 恢复到指定时间点
      archive: false                       # 独立恢复阶段禁用归档
      action: promote                      # 完成重放后提升并启动集群
```

使用 `pgsql-pitr.yml` 剧本执行克隆：

**剧本**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-18-tab-0" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="1"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-18-tab-0-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./pgsql-pitr.yml -l pg-meta2    <span class="c1"># 使用上面显式声明的 action: promote</span></span></span></code></pre></div></div>
</div>

**命令行**

<div class="td-code td-code--untitled" id="td-code-bbaec645-fence-0-tabpane-18-tab-1" data-td-code data-td-code-auto-id
     data-language="bash" data-line-count="2"><div class="td-code__utilities td-code__utilities--compact">
  <span class="td-code__language">BASH</span>
</div>
  <div class="td-code__viewport" id="td-code-bbaec645-fence-0-tabpane-18-tab-1-viewport" data-td-code-viewport><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 也可以通过命令行参数指定 PITR 选项</span>
</span></span><span class="line"><span class="cl">./pgsql-pitr.yml -l pg-meta2 -e <span class="s1">&#39;{&#34;pg_pitr&#34;: {&#34;cluster&#34;: &#34;pg-meta&#34;, &#34;time&#34;: &#34;2025-01-10 10:00:00+00&#34;, &#34;archive&#34;: false, &#34;action&#34;: &#34;promote&#34;}}&#39;</span></span></span></code></pre></div></div>
</div>

PITR 支持多种恢复目标类型：

| 目标类型  | 参数示例                             | 说明           |
|:------|:---------------------------------|:-------------|
| 时间点   | `time: "2025-01-10 10:00:00+00"` | 恢复到指定时间戳     |
| 事务 ID | `xid: "250000"`                  | 恢复到指定事务之前/之后 |
| 恢复点   | `name: "before_migration"`       | 恢复到命名恢复点     |
| LSN   | `lsn: "0/4001C80"`               | 恢复到指定 WAL 位置 |
| 最新    | `pg_pitr: {}`                    | 恢复到 WAL 归档末尾 |

<div class="alert alert-info" role="alert"><div class="h4 alert-heading" role="heading" aria-level="4">PITR 恢复后处理</div>


跨集群恢复完成后，按 [**克隆善后**](/docs/pgsql/backup/cluster/#克隆善后) 处理归档与 stanza。
</div>


更多 PITR 的详细用法，请参考 [**恢复操作**](/docs/pgsql/backup/restore)；跨集群恢复后的归档与 stanza 处理见 [**克隆数据库集群**](/docs/pgsql/backup/cluster/)。
