# Pigsty 作为参考实现

LLMS 索引： [llms.txt](/llms.txt)

---

本书选择 Pigsty，不是为了把 PostgreSQL 原理隐藏在自动化后面，而是为了让
读者看到一套完整参考实现如何把原理变成可交付环境。

阅读方法始终是双向的：

```text
平台职责 -> Pigsty 参数/组件/动作
Pigsty 现象 -> PostgreSQL/catalog/log/backup/route 证据
```

## 18.5.1 把 PostgreSQL、HA、备份、接入和观察组合起来 {#item-18-5-1}

### 声明期望状态

Pigsty 4.5 的
[Architecture](https://pigsty.io/docs/concept/arch/)
说明，它用 config inventory 与参数描述部署环境，再由 Ansible playbook 实现。

最小 cluster 声明大致包含：

```yaml
pg-shop:
  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 }
    10.10.10.14: { pg_seq: 4, pg_role: offline }
  vars:
    pg_cluster: pg-shop
    pg_version: 18
```

声明有两个重要作用：

- 让拓扑、身份、版本与参数进入版本化评审；
- 让重复执行与漂移修复有一个共同期望。

它没有证明：

- 四个地址真的跨故障域；
- 存储与网络满足容量；
- package repository 完整；
- secret 已正确交付；
- RPO/RTO 已演练；
- 业务应用兼容。

inventory 是控制平面输入，不是验收报告。

### 模块与职责映射

Pigsty 官方架构列出多个模块。本书关注：

| 模块/组件 | 本书中的职责 |
|---|---|
| NODE | 主机基线、监控、日志、HAProxy 等节点能力 |
| ETCD | HA 的分布式配置与 leader 协调 |
| PGSQL | PostgreSQL、Patroni、PgBouncer、pgBackRest、exporter |
| INFRA | 软件仓库、DNS/NTP、指标/日志/告警/可视化 |
| MINIO（可选） | S3-compatible 对象/备份仓库候选 |
| REDIS（可选） | 缓存候选，但 authority 仍由合同决定 |

模块安装并不改变业务边界。例如部署 REDIS 不会自动让它成为商品权威；部署
MINIO 也不会自动完成 media 两阶段状态机。

### PostgreSQL 仍是数据面核心

自动化完成后，仍要从 PostgreSQL 验证：

```sql
SELECT current_setting('server_version');
SELECT pg_is_in_recovery();
TABLE pg_extension;
TABLE pg_roles;
SELECT * FROM pg_stat_replication;
SELECT * FROM pg_stat_wal_receiver;
```

以及：

```text
database/schema/object owner
ACL
business checksum
extension versions
replication position
archive status
backup restore result
```

Pigsty 提供实现路径，不改变这些原生事实的语义。

### Patroni 与 etcd 形成 HA 控制

Pigsty 的
[High Availability](https://doc.pigsty.io/docs/concept/ha/)
描述了参考链：

```text
PostgreSQL physical streaming replication
  -> Patroni manages member role/process
  -> etcd provides DCS/leader election
  -> Patroni health API exposes current role
  -> HAProxy routes by health/role
```

理解边界：

- PostgreSQL replication 决定数据复制位置；
- Patroni 决定/执行 promotion 与成员管理；
- etcd 参与 leader 共识，不存业务表；
- HAProxy 决定新连接去哪，不复制数据；
- client 必须处理切换期间连接/事务失败。

“自动切换”不是“请求无感成功”。切换中的连接会中断，未决事务需要应用依据
幂等身份判断和重试。

### 复制不是备份

HA 复制会忠实传播：

```text
DROP TABLE
wrong UPDATE
application bug
malicious committed change
logical corruption
```

Pigsty 官方 HA 文档也明确区分流复制故障覆盖与人为/软件错误恢复，后者需要
延迟副本或 PITR。

因此平台组合同时需要：

```text
HA: current service continuity
backup/WAL: historical recovery
PITR: select target time/LSN/transaction
forensics: preserve evidence before repair
```

第 20、21、32、35 章分别承担这些证据。

### pgBackRest 形成恢复链，但恢复仍需演练

参考实现可生成 pgBackRest 配置、执行 base/differential/incremental backup、
归档 WAL 并管理 repository。

验收不能止于：

```text
backup command exit 0
```

还要证明：

```text
repository manifest and retention
WAL continuity
encryption/key recovery
independent failure domain
empty isolated target restore
extension packages
business checksum
RTO under representative size
operator runbook
```

第 21 章会在隔离目标恢复；第 32 章选择随机 recovery target。

### HAProxy 把拓扑封装为服务

Pigsty 官方
[Service/Access](https://pigsty.io/docs/pgsql/service/)
说明 service 由访问端点与 selector 组成，并提供默认 `primary`、`replica`、
`default`、`offline` 等服务。

概念映射：

```text
primary endpoint  -> current writable primary
replica endpoint  -> eligible read-only members with fallback policy
offline endpoint  -> offline/analytical candidates
default endpoint  -> default PostgreSQL/PgBouncer path
```

要进一步验收：

- health check 与实际 role 是否一致；
- failover 后多久摘除旧 primary；
- fallback 是否会把只读流量压回 primary；
- client DNS/VIP/port 怎样接入；
- TLS 在哪终止；
- health endpoint 是否越权；
- 连接失败与重试风暴怎样受控。

### PgBouncer 把连接变成有限资源池

池化可减少 backend 数、平滑短连接，但会引入语义：

```text
session / transaction / statement pooling
prepared statements
temporary tables
session GUC
LISTEN/NOTIFY
advisory locks
server reset
cancel routing
authentication
```

应用是否兼容，取决于 pool mode 与使用的 session feature。第 22 章会用实际
请求验证，不能只看 PgBouncer 端口可连。

### offline replica 实现分析隔离候选

Pigsty 的
[Offline Instance](https://pigsty.io/docs/pgsql/config/cluster/)
把 `pg_role: offline` 用于慢查询、ETL、OLAP 与交互查询。

蓝图提出：

```text
primary + 2 replicas + 1 offline
```

offline 服务合同：

- read-only；
- 不保证 read-your-writes；
- 显示 replay lag；
- 分析连接池独立；
- 查询 timeout/temp 配额独立；
- 不默认承接 online replica 流量；
- 长查询与 WAL replay 冲突有明确处理。

节点存在不证明这些条件，仍需第 22、26、27 章。

### 观察栈连接组件信号

Pigsty 4.5
[Monitoring](https://pigsty.io/docs/pgsql/monitor/)
描述了 Grafana、VictoriaMetrics、VictoriaLogs 与 PostgreSQL/PgBouncer/
Patroni/HAProxy/Node 等 exporter/日志源。

平台至少需要关联：

```text
client/service probe
HAProxy backend
PgBouncer queue/pool
PostgreSQL session/query/wait
Patroni role/timeline
replication lag
WAL/archive/backup
host CPU/memory/I/O/network
extension-specific state
business freshness
```

仪表盘只是表现层。alert owner、阈值依据、抑制、升级与 runbook 仍由团队
定义。

## 18.5.2 哪些能力开箱可用，哪些仍需组织流程 {#item-18-5-2}

### 三层“可用”

讨论开箱能力时应分：

```text
L0 mechanism
  配置/组件/命令存在，能在受控环境执行

L1 environment validation
  目标环境完成身份、版本、行为和复位/恢复证据

L2 service acceptance
  目标、容量、安全、值班、变更、演练和业务签字成立
```

本章：

```text
direct PostgreSQL fixture L1 = passed for chapter-specific mechanisms
Pigsty mapping = documented
Pigsty L1 = not-run
production L2 = pending chapters 19-36
```

不要把不同对象的 L1 混在一起：本地 PostgreSQL 18.6 实验通过，不等于目标
Linux/Pigsty cluster 通过。

### 参考实现可直接提供的机制

按官方能力，Pigsty 可以自动化：

```text
host desired state
software repository/package deployment
PostgreSQL instance/cluster creation
Patroni/etcd HA wiring
HAProxy service definitions
PgBouncer deployment/configuration
pgBackRest configuration and scheduled backup
monitoring/log collection/dashboard/alerts baseline
roles/databases/extensions declarations
offline replica role
```

“提供机制”的准确含义：

- 有对应 module/parameter/playbook；
- 可以在支持环境中声明和部署；
- 有默认配置和可观察入口。

它不是针对 `pg36_shop` 的完成证明。

### 组织必须补齐的工作

| 工作 | 为什么不能由工具自动决定 |
|---|---|
| 数据 authority | 业务语义与冲突裁决 |
| SLO/error budget | 业务损失、成本与风险取舍 |
| RPO/RTO scope | 故障模型与恢复价值 |
| tenant trust | 法规、组织与威胁模型 |
| extension admission | 功能收益、生命周期、支持 |
| capacity headroom | 真实 workload 与增长 |
| on-call/RACI | 人与组织责任 |
| change approval | 风险、窗口与可逆性 |
| incident judgment | 不完整证据下的取舍 |
| postmortem actions | 系统性改进优先级 |

自动化可以检查字段非空，不能替业务 owner 承诺。

### 默认值是起点，不是证据

生产环境常见错误：

```text
default topology -> default failure guarantee
default HA timeout -> our RTO
default backup schedule -> our RPO
default dashboard -> complete observability
default password -> acceptable security
default pool size -> safe connection budget
default shared_buffers/work_mem -> tuned
```

正确流程：

```text
document default
  -> explain why it may fit
  -> measure target
  -> accept/override
  -> validate
  -> monitor drift
```

### secret 永远不属于示例 inventory

本章
[`pigsty-declaration.example.yml`](/labs/ch18/pigsty-declaration.example.yml)
只放不可用 sentinel：

```yaml
password: "REPLACE_VIA_APPROVED_SECRET_SOURCE"
```

正式环境要决定：

```text
secret authority
render/injection path
file permissions
rotation
revocation
backup/log redaction
break-glass
audit
```

示例中的明文不是“方便”，而是泄露路径。

### 配置成功后还要独立验收

部署命令成功后，验收从外到内：

```text
inventory identity
host/OS/time/storage/network
package/version
PostgreSQL role and settings
replication/timeline
service selectors and endpoints
pool behavior
backup archive + isolated restore
monitoring and alert path
business golden
failure drill
```

每项证据要保存 target、时间、版本和执行者。截图可以辅助，不应是唯一机器证据。

### 环境与组织漂移

技术漂移：

```text
manual ALTER SYSTEM
package patch mismatch
extension extversion mismatch
inventory not applied
certificate expiry
backup schedule disabled
alert rule changed
```

组织漂移：

```text
owner 离职
on-call 无人
runbook 过期
SLO 与业务不匹配
例外无到期
恢复密钥不可得
```

平台治理必须同时检测两类。第二类不会出现在 `pg_settings`。

### 何时可以说“生产就绪”

至少满足：

```text
offering approved
target L1 evidence retained
business acceptance golden passes
RPO/RTO drills pass
security threat model and tests pass
capacity has headroom
SLI/SLO/error budget approved
alerts reach accountable responder
change/rollback/upgrade tested
incident and recovery runbooks exercised
open exceptions bounded and expiring
```

因此本章不会使用“部署完成，所以生产就绪”的句式。

## 18.5.3 不把参考实现冒充唯一架构 {#item-18-5-3}

### 稳定的是合同，变化的是实现

应尽量稳定：

```text
service endpoint semantics
data authority
consistency/freshness
identity/privilege boundary
RPO/RTO definition
backup/recovery evidence
extension lifecycle
observability requirements
exit path
```

可以替换：

```text
automation engine
HA controller/DCS
proxy/pooler
backup tool/repository
metrics/log stack
cloud/on-prem substrate
```

替换实现时，合同成为验收基线。

### 不要绕过组件理解

Pigsty 把复杂组件组合起来，但值班者仍需知道故障落在哪一层：

| 症状 | 可能层 |
|---|---|
| endpoint 不通 | DNS/VIP/HAProxy/network |
| pool queue 高 | PgBouncer/connection budget |
| primary 不明确 | Patroni/etcd/network partition |
| replica lag | PostgreSQL/WAL/I/O/long query |
| backup missing | archive/pgBackRest/repository/secret |
| dashboard blank | exporter/collection/storage/query |
| SQL wrong result | schema/data/extension/business semantics |

“重跑 playbook”不是通用诊断，更可能覆盖证据或扩大变更。

### 不要把云托管与自托管简化成好坏

托管服务可能减少：

```text
hardware lifecycle
base engine patching
some HA/backup implementation
control-plane construction
```

但团队仍负责：

```text
data model
SQL/application behavior
roles/security configuration
SLO and capacity/cost
restore acceptance
extension compatibility
migration/exit
incident collaboration
```

自托管给予更多控制和透明度，也带来更多直接责任。选择应基于组织能力、法规、
故障模型、成本与退出，而非身份认同。

### 保持原生证据层

无论实现是什么，都尽量保留：

```text
SQL business golden
catalog inventory
configuration snapshot
backup manifest
restore checksum
service probe
fault timeline
versioned ADR
```

这些证据比某个 UI 路径更可迁移。

### 用接口封装平台差异

消费者看到：

```text
service name
endpoint class
database
runtime identity
TLS/auth method
pool/session contract
SLO/freshness
quota
support/escalation
```

不应依赖：

```text
当前 primary IP
Patroni member name
HAProxy 内部 selector
backup repository layout
Ansible role internals
monitoring storage schema
```

这样平台升级或替换时，业务应用变更最小。

### 参考实现也必须有退出路线

从 Pigsty 迁出并不是“一条 `pg_dump`”：

1. 冻结 PostgreSQL/extension/locale/role 依赖；
2. 选择 physical 或 logical 路径；
3. 重建 service endpoint 与 pooling 语义；
4. 重建 backup/PITR；
5. 重建 monitoring/alerts；
6. 验证 HA 与 failover；
7. 验证业务 golden；
8. 切换并保留回退；
9. 退役旧控制面与 secret。

反向迁入同样需要这些合同。

### 一个合格的参考映射

本章示例 YAML 明确注释：

```text
not Pigsty L1 validated
example IPs
no real secrets
backup policy pending
synchronous mode not selected
ports/selectors/pool pending chapter 22
extension lifecycle governed outside package list
```

有意保留 unknown，比填入未经证实的“最佳实践”更专业。

### 何时偏离 Pigsty 参考

可以偏离，只要有证据：

```text
existing organizational platform already satisfies contracts
managed service is required
unsupported OS/network/security boundary
different HA/recovery model
specialized kernel/distribution
team skills and support model
regulatory requirement
cost/capacity evidence
```

偏离应写 ADR，包含等价职责、差异、风险与退出，而不是静默拼装。

### 本书为什么仍然以 Pigsty 实战

因为读者要从 SQL 走到生产，必须面对：

```text
host
package
topology
service endpoint
pool
HA
backup
monitoring
change
incident
```

Pigsty 给出一个可以落地、查看、运行与破坏性演练的完整对象；PostgreSQL 原生
证据则防止读者只会操作一个封装。两条线并行，才能真正迁移知识。

### 这一章的最终边界

我们接受：

> Pigsty 4.5 是 `pg36_shop` 下卷的参考实现。

我们尚未接受：

> 示例 inventory 已经可以部署生产，或提案中的 SLO 已经实现。

后一项只有在下卷 evidence 完成后才可能成立。

---

[上一节：平台服务目录与多租户](../04/) · [返回本章目录](../) · [下一节：实战：设计 `pg36_shop` 生产蓝图](../06/) ·
[查看全书目录](/toc/) · [查看索引中心](/indexes/)
