跳至内容

36.6 将控制固化到平台

平台化不是把所有决定自动化,而是让安全默认、身份、证据、审批和复位在每次操作中 一致出现。自动化适合执行已解析的意图;当 target、authority 或 evidence 仍有歧义时, 平台应停下来,而不是更快执行。

36.6.1 配置模板、验证脚本与策略即代码

控制从机器可读合同开始

desired state
  inventory / parameter / role / service / backup policy

precondition
  exact identity / version / topology / authority / headroom

plan
  rendered change / affected objects / lock and restart / traffic impact

gate
  risk / approval / rollback / evidence completeness

execution
  bounded target / idempotency / audit

postcondition
  native state + platform state + business invariant

模板只消除重复,不应隐藏高风险选择。默认填入:

  • stable service/cluster naming 与 environment/data class;
  • least-privilege role 与明确 HBA 来源;
  • timeout、pool、backup、monitoring、安全和容量基线;
  • version pin 与 extension compatibility;
  • safeguard、exact target 和 destructive approval;
  • owner、SLO/RPO/RTO 与验证 revision。

把业务密码、private key 或 raw token 从 inventory Git 中分离;模板引用受控 secret source,并验证存在性/权限,不输出值。

Pigsty inventory 是 desired state,不是全部事实

Pigsty 以声明式配置表达 node、cluster、instance、service、database、user 与参数, playbook 将其物化。推荐流程:

inventory PR
  -> schema/policy lint
  -> render and semantic diff
  -> sandbox/canary
  -> exact -l scope
  -> staged rollout
  -> SQL + Patroni/DCS + proxy/pool + monitoring verification

--check --diff 可帮助预览部分 Ansible 变化,但不能模拟所有 handler、运行时决策、 数据库锁、外部 repository 或 failover。preview 是证据之一,不是执行结果。

删除、重建和 PITR 等流程必须额外读取当前 identity 与 authority。Pigsty 的 pg_safeguard 可阻止危险 PGSQL 删除路径,但不能替代 exact inventory、备份验证、 流量排空和审批。安全控制应多层、互相独立。

原生证据复核平台结论

平台声称回到原生/组件证据
primary/replica 正常Patroni/DCS role、PostgreSQL recovery/timeline/replication
service route 正确HAProxy backend + endpoint 实际连接 identity
pool 正常PgBouncer pool/client/server state + PostgreSQL sessions
backup 正常pgBackRest info/check + 隔离 restore/business manifest
参数生效pg_settings source/pending_restart + process/runtime
监控覆盖collector target、query result、rule test、notification

平台 UI 的绿色状态不能成为唯一证据;否则平台控制面故障时,团队失去验证路径。

策略即代码也要可解释

规则输出:

decision: deny
policy_revision: ...
target_identity: ...
failed_predicates:
  - required backup restore evidence expired
  - production destructive approval absent
evidence_links: [...]
exception_path: ...

不可解释的 deny 会诱使人绕过控制;不可审计的 allow 会隐藏风险。policy 变更本身需要 review、测试、版本和回退,并覆盖 allow/deny/unknown 三类 fixture。

36.6.2 备份、切换、容量和维护的周期演练

建 capability calendar

按风险与变更频率决定周期,而不是所有项目“一年一次”:

能力建议触发
backup check连续运行;失败立即路由
isolated restore固定周期 + backup/repository/version 大变更
planned switchover维护周期 + topology/Patroni 变更
unplanned failover tabletop/drill固定周期 + DCS/fencing 变更
capacity benchmarkworkload/hardware/major config 变化
vacuum/freeze review持续趋势 + 数据增长/事务模式变化
integrity check风险分层周期 + storage/ICU/major version 变化
security access review固定周期 + owner/role/network 变化
migration/upgrade rehearsal每次 candidate revision

周期只是上限;invalidation event 应提前触发。

调度演练而不调度事故

exercise:
  capability: ...
  environment: isolated
  source_snapshot_or_fixture: ...
  hidden_scenario_seed: ...
  allowed_mutations: [...]
  forbidden_targets: [...]
  guards: [...]
  expected_evidence: [...]
  cleanup_and_preservation: ...
  production_claims_forbidden: [...]

故障注入限定 disposable clone 或明确无数据、无流量 sandbox。production chaos 需要 另一套组织授权,不能由“周期演练”四个字自动许可。

Pigsty 能承载的周期任务

  • 通过监控栈持续观察 PostgreSQL、host、Patroni、PgBouncer、HAProxy、backup;
  • 用 pgBackRest policy 与 exporter 观察 backup/archive,再在隔离目标实际 restore;
  • 用 Patroni/Pigsty 服务模型演练计划切换和受控故障切换;
  • 从 version-controlled inventory 重建 node/cluster,并验证 drift;
  • 用 playbook tag/limit 管理作用域;
  • 把 exporter query、alert rule、dashboard 与 runbook revision 共同发布。

具体 playbook、参数和输出会随 Pigsty 版本变化。运行前以已固定 release 的官方文档和 本地 source 为准;破坏性 playbook 不从书中复制到生产。

统一 evidence envelope

不同演练使用同一外壳:

contract + source hashes
environment identity
before / during / after
decision log
raw restricted evidence + redacted projection
business manifest
cleanup / retained artifacts
negative cases
review and production-claim boundary

统一 envelope 让平台能跨演练统计:哪些 control 过期、哪些 action 没有 evidence、 哪些版本从未恢复、哪些团队只跑 happy path。

演练失败不是坏成绩

演练在不伤害生产的前提下暴露:

backup不可读
权限不足
runbook过期
candidate选错
业务不变量缺失
cleanup不完整
值班升级路径断裂

这正是它的产出。禁止为了完成率修改 pass condition 或隐藏失败;修复后从同一合同 重新验证,并保留前次失败证据。

36.6.3 从单个补丁升级为默认护栏

从 incident-specific 修复抽象不变量

单点补丁:

给 pg-prod-7 的某个脚本加一行 if

默认护栏:

任何 destructive workflow:
  必须解析 environment + cluster + system identity
  必须有 current backup/recovery evidence
  必须声明 data/traffic/authority
  必须有 exact scope、preview、rollback、approval
  缺失或冲突 -> deny/stop

抽象层次以共同机制为准,不是越通用越好。一个巨大“万能安全框架”若无法描述 PostgreSQL timeline、replication slot、PITR target 或 collation dependency,反而 会隐藏领域事实。

safer default 的五个性质

  1. 自动采用:新 service 默认获得,不靠记忆 opt-in;
  2. 显式例外:绕过需要 owner、理由、补偿控制和到期;
  3. 可观察:知道 guard 是否执行、何时失效;
  4. 可版本化:配置、policy、runbook、dashboard 共同 revision;
  5. 可验证/可退出:有反例、回退和 retirement path。

例如:

new PostgreSQL service
  default backup/archive policy
  default service endpoints and pool limits
  default SLI + PostgreSQL/host dashboards
  default safeguard and least privilege
  default restore/failover exercise registration

业务仍要填 owner、data class、RPO/RTO、good event 与不变量;模板不能替它猜。

推广前做 blast-radius 管理

平台默认变更影响面大,按:

fixture -> sandbox -> one canary service -> cohort -> default for new
-> migrate existing -> retire exception

每阶段比较 compatibility、false positive/negative、延迟与资源成本、operator burden 和 rollback。guard 误拒绝所有紧急恢复也会制造可用性风险;保留受控 break-glass,并 监控使用频率。

建 control registry

control_id: ...
objective: ...
implementation_revision: ...
default_scope: ...
exceptions: [...]
telemetry: ...
owner_role: ...
last_verified:
  at: ...
  environment: ...
  evidence: ...
valid_until: ...
related_incidents: [...]
replacement: ...

跨 postmortem 查询重复 theme,而不是逐篇人工回忆。平台 backlog 优先合并能覆盖多个 incident/service 的控制,仍保留每个 incident 的特有 action。

平台完成的定义

一个控制成为默认护栏后,仍要证明:

new service receives it
existing intended scope converged
exception inventory complete
runtime telemetry healthy
negative fixture is blocked
positive fixture is not blocked
break-glass is audited and expires
revalidation is scheduled

“已经写进 Pigsty 模板”只完成第一步。最终效果必须在 PostgreSQL、组件、用户路径和 业务不变量上共同可见。


上一节:回写 SLO、SOP 与架构 ADR · 返回本章目录 · 下一节:实战:复盘四类事故并完成全书结业 · 查看全书目录 · 查看索引中心

最后更新于