跳至内容
24.6 实战:把 `pg36_shop` 纳入服务治理

24.6 实战:把 `pg36_shop` 纳入服务治理

本节把全章压成一条可重放的 L0 证明:

machine-check service card
  -> calculate SLO and control objectives
      -> bind observation sources and missing semantics
          -> accept actionable alerts
              -> reject actionless page
                  -> bind four SOPs to upstream drills
                      -> enforce high-risk authority
                          -> enforce evidence retention/redaction
                              -> rerun current ch19 deployment gate
                                  -> hash-bind ch20–ch23 summaries
                                      -> reject 20 adversarial mutations

实验不会:

  • 创建或修改 PostgreSQL 对象;
  • 改 PgBouncer/HAProxy;
  • 切换 leader;
  • 运行 restore;
  • 修改 role/credential/HBA/TLS;
  • 部署 VMAlert rule;
  • 发送真实 page;
  • 删除或重置数据。

all 在本章表示“采集只读 gate 并验证全部合同”,不是“执行所有被引用的 高风险演练”。

实验合同:

24.6.1 发布服务卡、SLO、责任人与升级路径

目标环境

service             pg36_shop
target              pg36-l2-vagrant/pg-test
environment         l2-sandbox
data                synthetic teaching data
production traffic  false
Pigsty              v4.4.0
PostgreSQL major    18
host count          4
PG member count     4 across pg-meta and pg-test

服务卡明确:

catalog_status       teaching-reference
production_tier      false
production_slo       false

因此 validator 会拒绝任何把它改成 production SLO 的 mutation。

文件布局

static/labs/ch24/
├── requirements.json
├── service-card.json
├── slo-policy.json
├── observation-contract.json
├── alert-candidates.json
├── sop-catalog.json
├── change-policy.json
├── evidence-retention.json
├── governance-adr.md
├── dependency-map.mmd
├── lab-contract.md
├── negative-cases.json
├── build_evidence.py
├── validate.py
├── review.py
├── task.sh
└── governance-run.json

核心合同八份,其他文件负责解释、验证和保存公开摘要。

服务卡

service-card.json 记录:

customer journeys   place-order, read-order
owner functions     service, data, platform, security/privacy
dependencies        6
health layers       6
escalation           SEV-1, SEV-2, ticket
known gaps          6

四个 owner:

functionrole idaccountable
serviceshop-service-ownerjourney、SLO、release、业务决定
datashop-data-owner语义、保留、质量、隐私分类
platformdatabase-platform-ownerPG/Pigsty、容量、恢复、执行
security/privacysecurity-privacy-dutyaccess、例外、披露、隐私

这些是 role contracts,没有写个人名字。route://... 也只是教学 route id, 不声称有真实 pager。

依赖图

user
  -> pg36_shop application boundary
      -> HAProxy / PgBouncer
          -> PostgreSQL pg-test
              -> Patroni / etcd
              -> pgBackRest / WAL repository

all observable through
  VictoriaMetrics / VictoriaLogs / VMAlert / Alertmanager / Grafana

Mermaid 源文件: dependency-map.mmd

每项依赖带 failure semantics。例如:

victoria-observability fails
  -> service state becomes unknown
  -> do not interpret missing telemetry as healthy

六层健康

process
endpoint
authentication
transaction
correctness
durability_and_recovery

所有层的 sufficient_for_service_health=false,服务卡另有:

"service_health_requires_all_layers_and_user_contract": true

validator 会把第一层改成 true,确认“process alive 即服务健康”被拒绝。

SLO policy

slo-policy.json 定义:

IDkindtarget
SLO-AVAILABILITYratio99.9% / rolling 28d
SLO-LATENCYratio99% under 250 ms / rolling 28d
SLO-FRESHNESSratio99% under 5 s / rolling 28d
CTRL-CORRECTNESScontrolzero unexplained mismatch
CTRL-RESTORE-READINESScontrolpassing isolated restore ≤ 90d

算术验证:

window seconds              2,419,200
availability target         0.999
sample eligible events      10,000,000
sample error budget events  10,000
equivalent time budget      2,419.2 s / 40.32 min

Python validator 使用容差重新计算,而不是信任 JSON 中的答案。

exclusion

三个默认排除:

  • admission 前的语法错误;
  • 正确拒绝的未授权身份;
  • admission 前客户端断开且没有 server outcome。

明确:

planned_maintenance_excluded  false
retroactive_exclusion_allowed false

一个新例外必须记录 id、时间、operation、independent approver、reason 和 before/after count。

error-budget state

healthy      > 50%
watch        > 25% and <= 50%
constrained  > 0%  and <= 25%
exhausted    <= 0%

每个状态都有 action。validator 把 exhausted actions 清空,确认“没有后果的 预算”被拒绝。

只做合同 lint

不连接任何 sandbox:

static/labs/ch24/task.sh lint

输出:

status=validation-ok
schema=pg36-ch24-validation-report-v1
production_ch24_gate=pending
status=validation-ok
schema=pg36-ch24-negative-report-v1
counterexamples=20-rejected
production_ch24_gate=pending
status=lint-ok
counterexamples=20-rejected
mutation=none
production_ch24_gate=pending

lint 使用私密临时目录保存报告,并在结束时删除;不产生 repository 文件。

24.6.2 为备份、切换、权限和发布建立 SOP

四份 SOP

sop-catalog.json

IDcapabilityriskowner / approver
SOP-BACKUP-RESTOREbackup and restoreL3platform / data
SOP-ROLE-CHANGEswitch/failoverL3platform / service
SOP-ACCESS-ROTATIONaccess/credentialL2security / platform
SOP-SCHEMA-RELEASEschema releaseL2service / platform

owner 与 approver 不同。每份包含:

  • trigger;
  • exact target;
  • blast radius;
  • prerequisites;
  • procedure phases;
  • stop conditions;
  • verification;
  • rollback/roll-forward;
  • evidence;
  • review interval。

恢复 SOP

输入:

source cluster
backup repository
recovery objective
target time/name
isolated destination
application invariants
space/WAL/authority

停止:

  • identity/target 模糊;
  • destination 可接 production traffic;
  • WAL/integrity 失败;
  • 验收未事先固定。

通过:

  • target marker 存在;
  • post-target marker 不存在;
  • database identity 正确;
  • recovered server 已停止;
  • timing 只称 sandbox observation。

validator 会把 verification 替换为:

backup command exited zero

并拒绝。

role change SOP

先区分:

planned switchover
unplanned failover

共同停止线:

  • 多写主可能;
  • DCS/fencing unknown;
  • candidate 不符合 durability policy;
  • unknown writes 不能核对。

验证:

one leader
timeline progression
acknowledged rows present
unknown classified
pool routes current leader

rollback 文案刻意写:

prefer safe roll-forward to one fenced leader;
a planned return is a new change

timeline 已推进后,不能把“切回”当撤销历史。

access rotation SOP

步骤:

new secret version out-of-band
  -> new authentication test
      -> bounded client/pool migration
          -> old new-session auth rejected
              -> revoke login/credential
                  -> explicit existing-session decision
                      -> verify final role and secret-free evidence

若 suspected disclosure,不能 rollback 到旧 secret,只能再次向前轮换。

schema release SOP

expand schema
  -> old/new app compatible
      -> bounded idempotent backfill
          -> constraint/reconciliation
              -> feature switch
                  -> contract old representation later

停止:

  • lock 超时;
  • WAL/lag/disk/budget 越界;
  • old app 提前不兼容;
  • backfill 不可恢复或不幂等。

上游实验绑定

三份 SOP 引用第 20、21、23 章;第 22 章作为入口/池证据也在本章 upstream manifest 中绑定。

run idSHA-256production
ch20475e9b47-bc35-4687-87da-012f1d5ea455602e932b...9d9a5dpending
ch21run_20260729T201040Z_961665aac0b3589d...a212capending
ch2287a63891-d6bf-46b3-bb65-d70a8d7bac3a444a6521...e6a2pending
ch2364b857a6-8d8f-46e2-9462-3f097a95a69fe1548658...cb59pending

完整 digest 见 governance-run.json

绑定证明:

this governance contract references these exact public summaries

不证明:

raw private evidence is embedded
the runs are fresh today
the actions were repeated in chapter 24
the sandbox results are production performance

变更政策

change-policy.json 固定 L0–L3。

L2/L3:

requester_may_approve                 false
approver_may_execute                  false
requester_approver_executor_distinct  true
shared_accounts_allowed               false
independent_approver_qualified        true
exact_target_and_blast_radius         true
machine_preconditions                 true
confirmation_binds target/action/time true

break-glass:

skip normal wait          allowed
skip target/evidence      forbidden
time-bounded identity     required
after-action review       required
credential rotation       required

正式 L0 运行

需要第 19 章 private mode-0600 inventory:

export PG36_CH19_INVENTORY=/absolute/private/baseline.yml
export PG36_EVIDENCE_DIR=/absolute/private/new-empty/ch24-run

static/labs/ch24/task.sh all

runner:

1 reject nonempty evidence directory
2 run ch19 task.sh all
3 build governance-evidence.json
4 hash current source files
5 bind ch20–ch23 summaries
6 positive validation
7 negative mutation validation
8 review permissions and secret patterns

没有 reset action。

当前第 19 章 gate

正式运行观测:

captured        2026-07-29T21:57:40Z
Pigsty          v4.4.0
PostgreSQL      major 18
hosts           4
PG members      4
sandbox L2      accepted-with-exceptions
exceptions      6
production      pending
mutation        none

六项例外:

  • shared hypervisor;
  • single etcd;
  • single backup target;
  • virtual storage;
  • sandbox inventory secret handling;
  • lab resource floor。

再次通过 gate 没有消除这些例外。

正式 evidence

run id       34909737-527a-460c-927c-d9d71c93aa13
captured     2026-07-29T21:57:40.539Z
mode         read-only-contract-and-live-baseline-binding
mutation     none

private evidence 保存:

  • ch19 current capture;
  • governance evidence;
  • positive report;
  • negative report;
  • review output。

公开仓库只保存 governance-run.json

24.6.3 输出观察契约,并拒绝没有动作的告警候选

观察契约

observation-contract.json 为五个目标绑定:

source
metric type
good/total selector
dimensions
recording rule
query template
missing semantics
fallback

Pigsty component labels:

cls / ins / ip

application labels:

service / operation_class / environment

禁止:

customer_id / tenant_id / order_id / raw_sql / error_message

component telemetry

四组:

IDsourcespurpose
PG-COMPONENT-ACTIVITYactivity/database/ioconcurrency/error/I/O diagnosis
PG-COMPONENT-REPLICATIONreplication/receiver/LSNreplay and WAL risk
PG-COMPONENT-ARCHIVEarchiver/pgBackRestrecovery-path risk
PIGSTY-CORRELATIONVictoria stackcorrelate PG/pool/LB/host/log

它们不替代 user SLI。

accepted alerts

alert-candidates.json

alertclassroute
PG36ShopAvailabilityFastBurnsymptompage SEV-1
PG36ShopAvailabilitySlowBurnsymptompage SEV-2
PG36ShopAvailabilityBudgetTicketsymptomticket
PG36ShopCorrectnessMismatchintegritypage SEV-1
PG36ShopFreshnessFastBurnsymptompage SEV-2
PG36ShopCapacityHorizoncapacityticket
PG36MonitoringPathBrokenmetamonitoringpage SEV-2

其中:

symptom/integrity pages  4
metamonitoring pages     1
tickets                  2

所有 accepted item 都有:

  • user impact;
  • owner function;
  • route;
  • runbook;
  • first safe action;
  • verification;
  • dashboard;
  • missing semantics;
  • silence policy;
  • test id;
  • review expiry。

rejected alert

PostgresInstanceDownWithoutAction

字段:

proposed_route     page
decision           rejected
user_impact        null
owner              null
runbook             null
first_safe_action  null

replacement:

correlate endpoint and user-event symptoms;
retain instance state on topology dashboard

这不是漏填;它是一个特意保留的反例。若有人将 decision 改为 accepted, validator 失败。

三个 diagnostic-only causes

PG36ReplicaReplayDistance
PG36PoolQueueDepth
PG36HostCpuHigh

都不 page。它们进入 dashboard,只有 correlated user/integrity/durability 合同触发后才帮助定位。

metamonitoring

要求:

  • application series freshness;
  • VMAlert evaluation failures;
  • Alertmanager notification canary;
  • VictoriaMetrics query/ingestion;
  • external blackbox probe。

missing_is_healthy=false

二十个反例

IDmutation被哪类不变量拒绝
N01宣称 production SLOscope
N02删除 platform ownerownership
N03process 即服务健康health chain
N04SLO target = 100%ratio target
N05排除 planned maintenanceexclusion
N06instance health = user SLImeasurement
N07missing = healthymissing semantics
N08exhausted 无 actionbudget policy
N09availability series 缺失算健康observation
N10允许 unbounded labelscardinality/privacy
N11page 无 first actionactionability
N12cause 直接 pagealert class
N13capacity 直接 pageroute
N14接受 actionless instance pagerejection
N15backup exit 0 即 restorerecovery evidence
N16一人申请批准执行authority
N17break-glass 跳过 target/evidenceemergency boundary
N18access evidence 允许 secretprivacy
N19伪造 ch21 run idupstream identity
N20沙箱切换称 production proofclaim boundary

正式结果:

case_count      20
rejected_count  20
failure_count   0

review 输出

status=review-ok
run_id=34909737-527a-460c-927c-d9d71c93aa13
service_card=complete
objectives=3-ratio+2-control
accepted_alerts=7
actionless_alerts=1-rejected
sops=4
counterexamples=20-rejected
ch19_live_gate=accepted-with-exceptions
upstream_runs=4-bound-by-hash
mutation=none
production_ch24_gate=pending
secret_material=absent

为什么 production 仍 pending

机器验证通过,不等于生产批准。仍缺:

  1. 真实 service/data/platform/security owner;
  2. 真实 on-call schedule 与 notification test;
  3. 真实用户 traffic 的 eligible/good classifier;
  4. 生产 failure domains;
  5. 生产容量和 workload;
  6. 多次切换/恢复的分布,而非一次观察;
  7. 真实 RTO/RPO 谈判;
  8. 法律/隐私 retention authority;
  9. production secret/audit 路径;
  10. 第 25 章真实 instrumentation/rules/dashboards;
  11. 生产等价环境中的重复演练;
  12. 正式 exception 与 expiry。

所以本章结论:

governance contract       pass
machine validation        pass
adversarial validation    pass
current sandbox baseline  accepted-with-exceptions
upstream identity binding pass
real alert delivery       not run
production SLO evidence   absent
production approval       pending

重验已有 evidence

export PG36_EVIDENCE_DIR=/absolute/private/existing/ch24-run
static/labs/ch24/task.sh verify
static/labs/ch24/task.sh review

修改任何受 hash 保护的 policy/script 后,旧 evidence 验证会失败。应:

retain old evidence with old source
create new empty evidence directory
run current contract again
compare decisions explicitly

不能覆盖旧 evidence 让历史“自动符合”新政策。

本章验收

  • service card 有 4 owner、6 dependencies、6 health layers;
  • 3 个 ratio SLO 和 2 个 control objective 可计算;
  • planned maintenance 未被隐藏;
  • missing telemetry 不算健康;
  • error budget 真实影响 change policy;
  • 四类 SOP 有停止线与验证;
  • L2/L3 权力分离;
  • break-glass 仍需 target/evidence;
  • 五个 observation source 有 query/missing/fallback;
  • 7 个 accepted alerts 可行动;
  • cause、capacity 与 symptom 分开;
  • actionless page 明确拒绝;
  • 六类 evidence 不允许 secret;
  • ch19 live gate 重新只读通过;
  • ch20–23 run 按 id/hash 绑定;
  • 20 个 adversarial mutations 全拒绝;
  • production gap 与 pending gate 保留。

第 25 章的任务不是重新发明这些语义,而是把它们实现为真实的应用 metric、 Pigsty recording/alert rules、dashboard、notification route 和 rule tests。


上一节:证据、审计与合规 · 返回本章目录 · 下一章:望闻问切:监控体系与可观测诊断 · 查看全书目录 · 查看索引中心

最后更新于