12.6 部署与接入 `pg36_shop`
部署数据库应用不是把一条 URL 放进环境变量。完整交付关系是:
Pigsty 提供 role/database 声明、PgBouncer、HAProxy service 与监控;应用团队仍要声明自己使用哪个入口、依赖什么 pool mode、允许多少并发,以及如何证明业务合同成立。
12.6.1 角色、数据库、服务与凭据声明
Owner 与 runtime 分离
本书延续第 4、6 章角色:
应用绝不能用 owner 连接。否则:
- schema injection/DDL defect 的 blast radius 扩大;
- owner 可能绕过 RLS;
- migration 与业务 activity 无法区分;
- secret 泄露可修改所有 objects;
- readiness 的
current_user失去保护价值。
本章 setup 最终断言:
“最小权限”必须由 catalog 证明,不能只看 YAML。
Pigsty declaration
声明示例 中的关键部分:
这些数字是教学起点,不是容量答案。需要按:
重新计算。
Pigsty declaration 负责创建/管理 cluster-level identity;对象级:
仍应进入 versioned SQL 与 code review。不要把所有权限散落在临时 psql 历史里。
Credential 是输入,不是源码
样例只要求:
但不记录它。生产建议:
- secret store/inventory overlay 生成 runtime file;
- file owner 是 service account,mode 0600;
- 不进 Git、artifact、process args、日志;
- role credential 可轮换;
- 支持 overlap/dual credential 时有明确窗口;
- TLS verification 与 CA/hostname 按环境配置;
- PgBouncer auth 与 PostgreSQL role 同步路径已验证。
读取变量。示例 URL 故意没有密码;部署系统负责填充 secret。不要把:
写进 process list。
Connection string 也要版本化非秘密部分
应记录:
秘密值单独管理。发布 evidence 可以保存“参数名与非秘密身份”,不保存 expanded URL。
12.6.2 通过连接池和服务端点接入
Pigsty 默认服务语义
Pigsty v4.5 默认:
| service | port | target |
|---|---|---|
| primary | 5433 | read/write primary via PgBouncer 6432 |
| replica | 5434 | read-only replicas via PgBouncer 6432 |
| default | 5436 | direct primary PostgreSQL 5432 |
| offline | 5438 | direct offline/replica analytical path |
因此:
不是“应用永远只能用 5433”的宇宙规则:Pigsty 允许修改 service destination 或自定义 services。运行手册必须保存目标集群的实际配置,不能仅凭端口推断。
为什么 migration 用 direct path
DDL、session-level diagnostic、某些 bulk operation 或 pooler admin 不适合 transaction pool。direct service:
- session identity 稳定;
- prepared/session state 边界简单;
- DDL error 与 backend 更直接;
- 不与在线 client pool 混在同一入口。
这不等于 direct path 可绕过审核。它应只对 migration/admin role 开放,设置:
应用运行角色不需要 direct 管理权限。
应用侧仍然使用 pgxpool
PgBouncer 不是 Go 并发安全 connection handle 的替代。应用侧 pool:
- 复用 client connections;
- 限制每个 process 同时进入数据库路径的请求;
- 暴露 acquisition queue;
- 管理 connection lifetime/health;
- 将 request context 传播到 acquire。
但两层池不要无限叠加:
即使 PostgreSQL 只有 64 server connections,app、network、PgBouncer fd/memory 和排队仍可能过载。
晋级时使用不变的 service suite
本地验证连接:
manifest 明确:
Pigsty 晋级不能把字段手改成 run。task.sh 保留 admin
PGSERVICE 用于 setup/observer,并允许用独立的
PG36_APP_DATABASE_URL 指向实际 primary service:
不设置该变量时,本地教学路径从 named admin service 派生
user=pg36_app 的 direct connection。设置后,manifest 只会声明:
这表示完整行为矩阵确实经过该 endpoint,但 endpoint 自称是 5433 仍不能证明其内部 pool mode/config。promotion job 应显式接收两个独立目标:
并在证据中保存:
- resolved service/port;
- PgBouncer version;
- database/user pool_mode;
max_prepared_statements;- TLS/auth identity;
- query mode;
- primary writable identity;
- full HTTP/failure suite。
不要为了“复用脚本”让 admin DDL 也走 app pool,或让 app smoke 使用 owner。
Failover 不由连接串自动变安全
Pigsty service 可在 primary 变化后把新连接路由到新主库。但 in-flight transaction 可能:
- 连接断开;
- rollback;
- commit outcome unknown;
- 请求超时后在新 primary 重试。
应用仍需要:
- idempotency key;
- finite retry;
- writable readiness;
- no remote side effect in transaction callback;
- failover fault test;
- reconnect/backoff jitter;
- old primary fencing 由 HA layer 保证。
“HA service”解决目标发现与路由,不替应用解决命令重放语义。
12.6.3 用平台指标验证部署,而非只看进程存活
Deployment gate
部署后按层验证:
systemctl is-active 只覆盖第一层的一小部分。
Pigsty 观察面
发布窗口至少同时看:
- PostgreSQL overview/cluster/instance;
- active sessions 与 wait events;
- query statistics 与 error/latency;
- PgBouncer clients, servers, pools, wait;
- HAProxy/service health;
- WAL rate 与 replica lag;
- CPU、memory、disk、network;
- application R/E/D/S(rate/error/duration/saturation)。
具体 dashboard 名称随 Pigsty 版本调整,运行手册应链接目标环境实际页面,不在代码里硬编码一串脆弱 panel ID。
用关系做验收
不设跨环境绝对 golden:
应设合同关系和 SLO:
其中最后两项必须在目标环境实测。
发布后观察而非立即 contract
应用 100% 新版本不等于旧连接/worker 已退出。保留观察窗口:
满足后才让第 11 章 contract gate 进入审批。数据库 DDL 与应用 rollout 的 observability 要合并在同一个 UTC window 中。
失败时停止什么
| 信号 | 首要动作 |
|---|---|
| wrong DB/user/replica | readiness fail,立即停止流量 |
| schema marker missing | 停应用晋级,检查 migration state |
| PgBouncer mode/config unknown | 不发布 prepared/session-dependent path |
| pool wait 上升、DB 未饱和 | 降 app admission/查 pooler,不先加 index |
| DB lock/IO saturated | 停 rollout/回退流量,按第 8 章诊断 |
| idempotency duplicate | 停止写入晋级,保存 ledger/outbox |
| unknown commit during failover | 同 key 查询/重放,不换 key |
| logs 泄露 secret | 安全事件处置与 credential rotation |
本节检查表
- owner NOLOGIN,runtime 非 owner;
- Pigsty user/database declaration 无明文 secret;
- object grants 由 versioned SQL 管理;
- catalog 证明 app 无 CREATE/DELETE/BYPASSRLS;
- primary/default/offline service 职责明确;
- 实际 service destination/pool_mode 已验证;
- app pool 与 PgBouncer pool 联合预算;
- app path 与 admin path 使用不同 role/endpoint;
- deployment artifact 不记录 expanded URL;
- readiness 验证 writable primary;
- full business/failure suite 通过实际 pooler path;
- Pigsty、PgBouncer、PostgreSQL 与 app 同窗观察;
- failover unknown commit 通过 idempotency 处理;
- 旧 artifact/worker identity 清零后才 contract。
参考资料
- Pigsty:Service / Access
- Pigsty:PgBouncer Administration
- Pigsty:PostgreSQL User
- Pigsty:PostgreSQL Database
- Pigsty:PostgreSQL Dashboards
- PostgreSQL 18:libpq Connection Parameters
上一节:服务级可观测性 · 返回本章目录 · 下一节:实战:交付应用闭环与规约 v1.0 · 查看全书目录 · 查看索引中心