18.4 平台服务目录与多租户
如果消费者只能申请“一台 PostgreSQL”,平台交付的是资源,不是服务。
一个可用目录应该让消费者在申请前就知道:
18.4.1 服务等级、规格、版本与扩展套餐
offering 是完整合同,不是机器型号
本章的
service-catalog.json
为每个 offering 保存:
机器 CPU/内存/磁盘规格当然重要,但它只是实现 offering 的一种资源配置。
同一 pg-ha-standard 可以在不同硬件代际上实现;只要服务合同和经过验证的
容量仍然成立,消费者不应绑定某台主机。
pg-dev
定位:
它允许较广的试验 extension bundle,包括 federation-lab。这不意味着开发
环境可以无治理:
- 必须有 consumer owner;
- 连接、存储、temp、statement time 要声明;
- 必须有到期日;
- 敏感生产数据不能因为“只是 dev”就复制进去;
- 实验凭据不能进入 Git;
- 删除仍需精确目标和恢复需求确认。
开发 offering 的目标是加快安全实验,不是变成永不下线的影子生产。
pg-ha-standard
这是 pg36_shop 的默认生产候选:
目录中:
这些是要进入第 20、21、24 章验证的目标。它们不能由“三节点”直接推出。
允许的 bundle:
vector-pilot 只能走 exception;federation-lab 不允许。
pg-ha-critical
critical 不是把 standard 的数字改得更漂亮。它意味着:
目录提出:
“RPO 0”必须带范围。同步副本若与 primary 共享电源/机房,不能自动覆盖整个 区域故障;若为可用性临时降级同步策略,也可能改变承诺。
pg-analytics-offline
它不是第二个 source of truth:
Pigsty 官方
Cluster / Instance
把 pg_role: offline 定位为慢查询、ETL、OLAP 与交互分析专用 read-only
replica。隔离的目的不是“让慢查询没人管”,而是不让它默认争用在线 replica。
规格要由容量曲线产生
不要先定义:
再假设业务会自然匹配。更可靠的顺序:
- 定义 workload class;
- 固定数据量、并发和增长;
- 测量容量曲线和饱和点;
- 选定安全 headroom;
- 映射到可采购/可部署资源;
- 定义升降配条件。
硬件 SKU 可以变化,基准 workload 与目标不应随意变化。
版本是一组矩阵
平台版本不只一个 postgresql=18:
兼容矩阵至少回答:
- 哪组是当前支持;
- 哪组是下一升级候选;
- 哪组已弃用;
- package repository 能否重建;
- backup/restore/replica/upgrade 是否覆盖;
- 安全补丁时限;
- 谁批准例外。
extension bundle 是服务的一部分
bundle 不只是安装清单:
offering 只引用已审阅 bundle,避免每个用户自行拼装无法升级的组合。
服务目标要分平台与消费者责任
平台可负责:
消费者仍负责:
责任边界要写 RACI,不能在事故时才争论“数据库没问题还是应用没问题”。
目录本身也需要版本与状态
本章目录:
当下卷 evidence 完成后,应产生新 release,而不是原地把历史 proposal 改成 “一直就是通过”。目录是决策记录的一部分。
18.4.2 数据库、模式、实例和集群隔离
四层隔离解决不同问题
| 层级 | 隔离了什么 | 没隔离什么 |
|---|---|---|
| schema | 名称、对象组织、部分权限 | database GUC/连接、WAL、资源、故障 |
| database | catalog、连接入口、部分设置 | instance CPU/I/O/WAL、superuser、升级 |
| instance | postmaster、内存、端口、WAL、配置 | host/kernel/storage/network |
| cluster/service | HA/恢复/生命周期边界 | 若共主机/控制平面仍可能相关 |
“tenant 一个 schema”与“tenant 一个 cluster”不只是成本不同,安全与爆炸半径 完全不同。
schema 隔离
适合:
风险:
安全做法:
- 不给不可信运行时角色在公共解析路径中的
CREATE; - 对安全定义函数固定安全
search_path; - 使用显式 schema qualification;
- 分离 NOLOGIN owner 与 LOGIN runtime;
- 定期审计 ACL 与 dependencies。
database 隔离
适合:
优点是 namespace 和连接边界更清楚;代价是:
- PostgreSQL 原生跨 database 查询不透明;
- connection pool/监控/迁移对象增多;
- extension 每 database 管理;
- 仍共享 WAL、CPU、I/O、backup 与 major upgrade;
- instance superuser 仍可越界。
database 不是强资源隔离。
instance 隔离
适合:
同一 host 上多个 instance 仍共享:
必须配 OS/cgroup/volume/port/backup 与监控隔离,否则只是多个 postmaster 抢 同一资源。
cluster 隔离
适合:
代价是节点、备份、监控、升级、值班和容量碎片化。不是所有小数据库都值得 一个三节点 cluster。
选择顺序从信任与故障开始
推荐问:
- tenant 是否互信?
- 数据分类是否允许共实例/共主机?
- 是否允许同一个 superuser/平台团队访问?
- workload 能否互相制造事故?
- 是否需要不同 PostgreSQL/extension/preload?
- 是否需要独立 failover/restore/upgrade?
- 跨 tenant 查询/事务是否必要?
- 成本和运营能力是否承受更高隔离?
安全硬边界优先于便利与成本。
多租户至少有三种模型
也可以混合:
但迁移路径要提前设计:如何从 shared 提升到 dedicated,identity、sequence、 外键、事件与投影如何移动。
RLS 是纵深防御,不是唯一边界
Row-Level Security 可以根据角色/会话上下文限制行,但需要审计:
第 23 章会用正负 tenant 测试验证。不能因为 CREATE POLICY 成功,就宣布
隔离完成。
隔离与可观测性必须同粒度
若配额按 tenant,指标却只能看整个 cluster,就无法:
- 识别 noisy neighbor;
- 归属成本;
- 证明公平性;
- 按 tenant 降级;
- 预测迁移。
需要在不暴露敏感 SQL/数据的前提下,保留 service/database/role/workload class/tenant 等必要维度,并控制 cardinality。
18.4.3 成本归属、配额和生命周期
没有成本归属,平台会奖励浪费
共享数据库中,使用者容易只看到:
平台承担的真实成本:
成本模型不一定要精确计费,但必须让 owner 看见边际影响。
用服务单位表达成本
可以按组织成熟度从简单到复杂:
避免只按主表大小计费:索引、TOAST、replica、backup 与 WAL 可能远大于主表。
配额是正确性保护,不只是节省
重要配额:
| 配额 | 保护 |
|---|---|
| connection | 防止 backend/内存/调度耗尽 |
| active query | 防止过度并发 |
| statement timeout | 限制无界执行 |
| lock timeout | 限制排队与级联 |
| idle transaction | 防止长快照/持锁 |
work_mem class |
限制乘法内存 |
temp_file_limit |
防止 spill 填盘 |
| storage/WAL growth | 保护恢复链与容量 |
| logical slot retention | 防止 WAL 无限保留 |
| maintenance window | 保证 vacuum/index/backup |
配额超限行为要确定:
静默超卖不是服务。
连接预算从端到端计算
不要让每个应用实例都配置:
预算应满足:
还要考虑:
- 每个应用副本数;
- failover 后流量汇聚;
- pool retry storm;
- transaction vs session pooling;
- offline/replica 独立预算;
- emergency admin 保留。
第 22、34 章会做饱和与过载演练。
生命周期从申请前开始
完整状态机:
若没有 expiry/decommission,临时数据库会永久占用备份、监控和升级路径。
变更要分普通与例外
普通变更:
例外:
例外必须有:
“临时允许”但没有到期日,通常等于永久。
删除与退役是高风险动作
本书实验里的 reset 有精确 token、target、marker 和 active-session guard; 生产退役还要更多:
- 确认 owner 与法律/业务 retention;
- 停止新连接和写入;
- 记录最后 backup/manifest;
- 导出需要保留的数据;
- drain 外部消费者和投影;
- 验证 DNS/service/secret/monitoring 依赖;
- 双人审批 destructive target;
- 擦除或进入保留;
- 保存完成证据。
“在 inventory 中删掉一段 YAML”不等于数据已经安全退役。
复审由事件与周期共同触发
周期复审:
事件复审:
平台目录最终要可验证
本章 validator 会检查:
- offering ID 唯一;
- production offering 有非空
service_objectives; - allowed bundle 全部存在;
- blueprint 引用的 offering 全部存在;
- bundle 与 lower-volume gate 引用闭合;
- lab-only FDW 不得生产准入。
反例把 pg-ha-standard.service_objectives 置空时,必须得到:
机器验证不能判断 99.9% 是否合理,但能阻止“生产服务连目标字段都没有”的 结构退化。
上一节:明确替代边界 · 返回本章目录 · 下一节:Pigsty 作为参考实现 · 查看全书目录 · 查看索引中心