36.5 回写 SLO、SOP 与架构 ADR
事故揭示的新事实如果只留在 postmortem,日常开发、发布和值班仍会按旧假设运行。 复盘的下游消费者是 SLO、runbook、service catalog、inventory、ADR、测试与版本路线; 每个消费者都需要明确 revision 和 owner。
36.5.1 更新观察契约、告警规则与 runbook
observation contract 是接口
应用、PostgreSQL、Pigsty 组件和 incident process 对同一 identity 达成约定:
service: pg36_shop
revision: obs-v...
identity:
service: ...
environment: ...
pg_cluster: ...
system_identifier_projection: ...
instance: ...
database: ...
role: ...
application_name: ...
user_slis:
availability: ...
latency: ...
correctness: ...
diagnostic_sources:
postgresql_views: [...]
logs: [...]
patroni_dcs: [...]
proxy_pool: [...]
host_storage: [...]
missing_semantics: ...
retention_and_access: ...
owners: ...新增 label 不是免费:高基数会增加监控成本,敏感 identity 会扩大数据暴露。每个维度 回答“哪项决策需要它”,没有消费者的 telemetry 不应无限保留。
从 SLI 到诊断,不从组件告警猜影响
推荐两层告警:
page
user SLI / error-budget burn / imminent data or recovery risk
ticket or context
component symptom, capacity trend, maintenance debt例如 replica lag 可能威胁 RPO 或 read-only 用户路径,也可能只是一个无业务 route 的 重建节点。告警需要 topology、route 和 objective 才能分级。Pigsty 的 PostgreSQL、 Patroni、PgBouncer、HAProxy、host、backup 指标可作为诊断层,业务 good-event 仍要由 应用定义。
规则发布前测试:
normal
threshold boundary
fast burn
slow burn
missing series
one instance vs whole service
maintenance and failover
notification routing每条 page 链接一个能在当前版本执行的 runbook,而不是 dashboard 首页。
runbook 写判断,不堆命令
symptom_or_page: ...
objective: ...
required_identity: ...
first_evidence:
- source: ...
why: ...
routes:
- predicate: ...
action: ...
expected: ...
stop: ...
rollback: ...
unknown_route:
action: STOP_AND_ESCALATE
authority: ...
version_scope: ...
last_exercised_at: ...
evidence_example: ...命令输出随 PostgreSQL/Pigsty 版本漂移;runbook 应说明指标和 SQL 的语义,并记录版本 适用范围。危险操作不要留一个通用变量空槽让值班者临时填目标,应从已验证 identity 生成 exact plan 并再次确认。
验证回写完成
“文档更新”需要:
- alert fixture 能进入对应 runbook;
- 新参与者在 blind tabletop 中请求到正确证据;
- 错误/缺失 evidence 进入 stop line;
- 文档链接、query 和权限在当前环境有效;
- postmortem action 反向链接 observation/runbook revision。
文档过期检测也可自动化:版本、owner、链接、最近演练时间和依赖对象进入 lint。
36.5.2 修正 RPO/RTO、容量和安全假设
objective、capability 与 observation 分栏
objective
业务愿意承诺什么
designed capability
架构和控制预计支持什么
observed result
某次真实事件或受控演练测到什么一次 sandbox failover 的 6,211.692334 ms acknowledgement gap 是 observation,不是
生产 RTO;一次 fixture PITR 的恢复时间也不包含审批、下载、容量申请、DNS、外部对账
和用户切换。反过来,一个写在文档里的 15 分钟 RTO 若从未演练,也不是 capability。
RPO 不是一个数据库数字
按结果类型拆分:
database transaction durability
replica / WAL archive lag
backup recovery point
business event and outbox state
external side effect
audit/reconciliation source异步复制、archive 与 backup 各有不同 loss window。PITR 到正确 target 仍可能丢弃 target 后的合法写;数据库恢复也不会自动撤销已发出的支付、邮件或消息。因此 RPO 合同写数据类别、cutoff、source、对账方法和 exception。
RTO 分解而不是报一个 stopwatch
$$ \mathrm{RTO} = T_{\mathrm{detect}} + T_{\mathrm{decide}} + T_{\mathrm{provision}} + T_{\mathrm{restore}} + T_{\mathrm{validate}} + T_{\mathrm{route}} + T_{\mathrm{observe}} $$
不同路线各自分布:
- automatic/controlled failover;
- PITR candidate + reconciliation;
- replica rebuild;
- backup restore;
- data extraction/forensic recovery;
- host/region rebuild。
记录 p50/p95 并不代表数据足够;小样本保留 raw runs 和条件。把最慢、最不确定且可改变 的阶段转成行动,而不是只优化 PostgreSQL copy speed。
容量与安全假设也要版本化
事故后检查 ADR 中的隐含假设:
peak and retry multiplier
pool/session/work_mem concurrency
WAL/archive/slot growth rate
vacuum/freeze window
backup repository and restore bandwidth
DCS/failure-domain independence
credential and network trust boundary
break-glass availability and audit
monitoring dependency during control-plane failure每项写 evidence、margin、owner、invalidation event。将“单节点也够用”“replica 一定 最新”“内网可信”“备份每天成功”这种自然语言替换为可测谓词。
不因事故随意降低目标
若观测证明 objective 不可实现,有三个诚实选择:
- 投资能力达到业务目标;
- 调整产品/降级设计,缩小承诺范围;
- 与业务共同接受并批准新目标和 residual risk。
不能为了让报表变绿而单方面降低 SLO/RPO/RTO,也不能保留不可能实现的目标让值班者 承担结构性失败。
36.5.3 将必要变更纳入服务目录与版本路线
service catalog 是事故路由表
数据库服务条目至少包含:
service_and_tier:
business_owner:
technical_owner:
oncall_and_escalation:
data_classification:
postgresql:
cluster:
major_and_extensions:
databases:
writer_and_reader_services:
pigsty:
inventory_revision:
release:
dependencies:
dcs:
backup_repository:
object_storage:
identity_and_secrets:
objectives:
sli_slo:
rpo_rto:
controls:
backup_restore:
ha_fencing:
capacity:
integrity:
security:
last_verified:
exceptions:这不是手工 CMDB 展示页。inventory 和 runtime 能自动投影的字段不重复录入;业务 owner、data class、objective、外部 dependency 与例外仍需显式治理。
用 ADR 记录为什么
配置告诉系统“是什么”,ADR 解释“为什么这样、在什么条件下仍正确”:
# ADR-...: ...
Status / Date / Owners
Context and incident evidence
Decision
Alternatives considered
Assumptions and version scope
Consequences and new failure modes
Migration / rollback
Verification and observability
Invalidation / review trigger
Related controls and postmortems例如把 DCS 从单故障域扩为多成员,不能只写节点数;ADR 要讨论 failure domain、quorum、 latency、failsafe/watchdog、maintenance、network partition 和运营复杂度。
版本路线按风险依赖排序
行动可能需要:
- PostgreSQL minor/major fix;
- Pigsty/Patroni/pgBackRest/PgBouncer/HAProxy 版本更新;
- extension compatibility 与
shared_preload_libraries; - OS、kernel、filesystem、ICU/libc 或 hardware firmware;
- dashboard/alert/runbook schema;
- 应用 driver、retry、transaction 和 idempotency contract。
建立 compatibility matrix:
current -> candidate
known incident relevance
support/security window
configuration semantic diff
extension and backup compatibility
rollback boundary
staged evidence
production approval不要把多个必要升级捆成一次无法归因的大爆炸。先解决阻塞链和可观测性,再 canary/ batch;每阶段都有 before/after、stop 和 rollback。
Pigsty 映射
Pigsty 的声明式 inventory 与幂等 playbook 适合承载 desired state;监控栈适合承载 control telemetry;pgBackRest、Patroni、PgBouncer 和 HAProxy 分别承载恢复、权威、 连接与路由机制。但平台不会替业务定义:
good user event
transaction and idempotency boundary
acceptable data loss
business invariant
external side-effect reconciliation这些应用合同必须回写 service catalog,并与 Pigsty/PostgreSQL 证据在同一次演练中 共同验收。
路线变更也需要退出条件
每个 roadmap item 记录:
why now
dependency and owner
target version/revision
evidence before rollout
success and stop criteria
rollback support window
when old path is retired只有当旧例外、旧 runbook、旧 dashboard 和旧配置都被清点,版本演进才真正关闭; 否则值班时仍可能按过时入口执行。
上一节:把行动项变成控制 · 返回本章目录 · 下一节:将控制固化到平台 · 查看全书目录 · 查看索引中心