跳至内容

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 并再次确认。

验证回写完成

“文档更新”需要:

  1. alert fixture 能进入对应 runbook;
  2. 新参与者在 blind tabletop 中请求到正确证据;
  3. 错误/缺失 evidence 进入 stop line;
  4. 文档链接、query 和权限在当前环境有效;
  5. 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 不可实现,有三个诚实选择:

  1. 投资能力达到业务目标;
  2. 调整产品/降级设计,缩小承诺范围;
  3. 与业务共同接受并批准新目标和 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 和旧配置都被清点,版本演进才真正关闭; 否则值班时仍可能按过时入口执行。


上一节:把行动项变成控制 · 返回本章目录 · 下一节:将控制固化到平台 · 查看全书目录 · 查看索引中心

最后更新于