19.6 用声明式清单交付两个服务单元
声明式交付的核心不是“YAML 很先进”,而是让目标、作用域、版本、差异与 执行证据可以评审。inventory 是意图,不是已经发生的事实。
19.6.1 inventory、参数模板与主机分组
inventory 同时承载图和参数
Pigsty inventory 的结构大致是:
它表达两类信息:
混在一个文件里不表示它们的生命周期相同。host identity 可能多年稳定, password 要轮换,service definition 会迭代,初始化参数只在新 cluster 生效。
identity 参数必须明确
Pigsty 的参数层次包含 global、group/cluster、host/instance 等作用域。对 PostgreSQL member,核心 identity 至少有:
官方
Pigsty parameter model
将 pg_cluster、pg_seq、pg_role 等视为无默认值的 identity 参数。
没有 identity,不应让自动化猜:
- 这是哪个 HA group;
- member 名是什么;
- bootstrap primary 是谁;
- service/monitor/backup 如何命名。
参数优先级要可解释
同一参数可能来自:
最终值要能回答:
“我在 YAML 里搜不到”不等于它使用 PostgreSQL 默认;可能来自 role default 或 template。
本章 live inventory 没有重复声明每一个 role default。验收从 SQL 读取 checksum、locale、timezone 等结果,避免把“省略”误作“不确定”或 “一定是 PostgreSQL 默认”。
参数模板是起点,不是服务等级
pg_conf: oltp.yml 可提供合理 OLTP 起点,node_tune: oltp 可收敛主机
baseline。它们不包含业务 workload evidence。
模板不能自动知道:
第 26、27 章才通过压力与瓶颈证据调参。
从 exact release 生成配置
本章没有直接运行当前 dirty checkout,而是:
解到私有临时目录,并记录 tag commit:
然后:
参数含义:
ha/full 官方定位主要是演示与测试,不是生产拓扑模板;它把 infra、单 etcd、
MinIO 和 pg-meta 放在第一节点,pg-test 放在后面三节点。这正是本章
将其标为 sandbox 的原因。
generator output 必须 review
wizard 给出初稿后,逐项 review:
configure 成功只表示生成文件,不表示目标可部署。
live inventory 是 secret-bearing artifact
随机密码比模板默认密码安全,但文件仍含 secret。处理:
本次初始化过程中,首次生成的凭据曾出现在工具输出边界;因此立即重新生成, 正式 live inventory 使用另一组未打印的值。这个事件提醒我们:
redaction 不是最后一步;command output、debug、diff 和 CI log 都是泄露面。
只导出 allowlist projection
inventory_projection.py 读取 live
inventory,只保留:
它不使用“把已知 password 字段替换为星号后整份输出”的 denylist 模式。 denylist 容易漏掉新字段;allowlist 默认拒绝未知内容。
执行:
投影不是可用于部署的 inventory,故意不可逆。
sanitized example 只表示形状
inventory.example.yml 使用 sentinel
secret,帮助理解结构。它不应原样部署。
审阅 example 时也要防止:
inventory 是 code,但不等于把一切都放 Git
适合版本化:
需要受控 secret store:
需要外部事实系统:
声明式不是单文件崇拜,而是让 authority 可追踪。
19.6.2 生产服务与隔离验证服务
先澄清本节标题的边界
生产设计应该区分:
本章用 pg-test 和 pg-meta 演练这种分工,但两者都位于 disposable
sandbox:
所以 pg-test 是 production-shaped teaching service,不是生产服务;
pg-meta 也不是合格的生产 control plane。
服务单元一:pg-test
声明:
目的:
当前 bootstrap role:
future failover 后 runtime role 可能变化;inventory declaration 与 observed role 的解释要跟着 chapter 20 contract 更新。
服务单元二:pg-meta
声明:
同一 node 还承载:
它可用于控制与验证,但这个共置形成大 blast radius。不要把“组件齐全”解释为 “组件高可用”。
两个 service unit 必须有不同 system identifier
部署时如果错误 clone 同一 cluster,再改名字,表面可能出现两个 group。 因此验收要求:
同时:
这是 declaration 和 physical lineage 的交叉检查。
control data 与 application data 不要无意混合
真实平台需要决定:
本沙箱共置是资源选择,不是推荐生产答案。
offline 服务不等于隔离环境
.13 是 replica + offline query 标记。它仍:
要实现更强隔离,可能需要:
production topology 要替换六个例外
从本章沙箱走向生产,不是删除 sandbox 字样。至少解决:
并完成后续章节 gate。
service unit review 表
| 问题 | pg-meta |
pg-test |
|---|---|---|
| authority | control/validation | teaching application service |
| members | 1 | 3 |
| current primary | .10 |
.11 |
| replicas | 0 | .12, .13 |
| offline placement | no | .13 |
| system ID | own | shared within three members |
| production SLO | none | none |
| later fault target | limited | chapter 20 |
这张表应进入 design review,而不是从 Ansible recap 猜。
19.6.3 幂等部署、差异检查与失败重跑
幂等的正确含义
理想的 idempotent task:
但整套部署包含:
所以不能用“Ansible 是幂等的”替代每个 action 的语义。
Pigsty 官方
Playbooks
说明大多数 playbook 可重复运行,同时指出清理参数和 *-rm.yml 等有重要
caveat。
一次完整部署的受控顺序
本章实际流程:
Pigsty deploy.yml 是 core chain 的 one-pass deployment。它完成很多工作,
不意味着每个业务 policy 自动满足。
recap 是执行证据,不是服务验收
本次安全 recap:
| target | ok | changed | unreachable | failed |
|---|---|---|---|---|
10.10.10.10 |
326 | 248 | 0 | 0 |
10.10.10.11 |
174 | 134 | 0 | 0 |
10.10.10.12 |
159 | 120 | 0 | 0 |
10.10.10.13 |
159 | 120 | 0 | 0 |
localhost |
6 | 4 | 0 | 0 |
它证明 playbook 没报告 failed/unreachable。它不证明:
这些另行验收。
changed=0 也不是唯一幂等标准
一些 task 合理地每次:
也有 task 误报 changed。应关注:
二次执行前先查 playbook/tag 的语义,不以追求漂亮 recap 为目标。
失败重跑前先分类
失败类型:
| 类型 | 例子 | 下一步 |
|---|---|---|
| transient | repo timeout、短暂 DNS | 保存证据后 bounded retry |
| declaration | wrong group/var | 修 inventory,review diff |
| prerequisite | sudo/clock/disk | 修前提并重新 preflight |
| partial init | primary created, replica failed | 查 cluster state,按 role runbook |
| incompatible | package/extension/OS | 停止,修矩阵 |
| destructive drift | wrong target/data exists | 停止并升级决策 |
| secret exposure | log printed credential | 先 rotate/contain |
不要在不知道已执行到哪里时直接:
失败现场是证据。
限制 scope
Pigsty playbook 支持 Ansible -l 与 tags。例:
使用前必须确认:
-l pg-test 是作用域控制,不是安全沙箱。
diff 不能泄密
安全 diff 分层:
不要把 live inventory git diff、Ansible -vvv、template variables 或
.pgpass 直接上传。
automatic reboot 被刻意拒绝
bootstrap 观察到 meta 节点已安装 kernel 与当前 running kernel 有差异。这 可能要求 reboot 才完成 host baseline,但本章没有自动重启:
- reboot 会改变运行状态;
- control/infra/DB 共置;
- 尚未建立第 20 章 HA 行为证据;
- maintenance authority 未授予;
- 本章 deployment 成功不要求偷偷消除 warning。
正确做法是登记 exception/change,计划可观察的 reboot,而不是为了让 preflight 变绿直接执行。
normal lab 没有 deploy action
task.sh 只提供:
其中 all 只读。没有 deploy 是有意设计:
source-controlled 验收脚本不应在读者以为“检查环境”时顺便收敛 package、 重启服务或重建数据库。
部署需要独立变更窗口和 runbook。
removal playbook 是 destructive action
Pigsty pgsql-rm.yml 用于移除 cluster/instance。官方文档说明 production
应显式启用 pg_safeguard,并对 override 格外谨慎。
本章只提供多重 guard 的
reset-cluster.sh,没有运行它。它要求:
这是演示 destructive contract,不是授权。
交付完成定义
声明式交付完成需同时满足:
本章环境满足 sandbox L2,带六个 exception;production gate 仍 pending。
上一节:拓扑、命名与故障域 · 返回本章目录 · 下一节:实战:L2 部署验收 · 查看全书目录 · 查看索引中心