跳至内容
19.6 用声明式清单交付两个服务单元

19.6 用声明式清单交付两个服务单元

声明式交付的核心不是“YAML 很先进”,而是让目标、作用域、版本、差异与 执行证据可以评审。inventory 是意图,不是已经发生的事实。

19.6.1 inventory、参数模板与主机分组

inventory 同时承载图和参数

Pigsty inventory 的结构大致是:

all:
  children:
    infra:
      hosts: ...
    etcd:
      hosts: ...
    pg-meta:
      hosts: ...
      vars:
        pg_cluster: pg-meta
    pg-test:
      hosts: ...
      vars:
        pg_cluster: pg-test
  vars:
    version: v4.4.0
    pg_version: 18

它表达两类信息:

membership graph
  哪些 host 属于哪些 module/cluster

desired parameters
  version, paths, packages, tuning, users, DBs, services, access

混在一个文件里不表示它们的生命周期相同。host identity 可能多年稳定, password 要轮换,service definition 会迭代,初始化参数只在新 cluster 生效。

identity 参数必须明确

Pigsty 的参数层次包含 global、group/cluster、host/instance 等作用域。对 PostgreSQL member,核心 identity 至少有:

pg_cluster: pg-test
pg_seq: 1
pg_role: primary

官方 Pigsty parameter modelpg_clusterpg_seqpg_role 等视为无默认值的 identity 参数。

没有 identity,不应让自动化猜:

  • 这是哪个 HA group;
  • member 名是什么;
  • bootstrap primary 是谁;
  • service/monitor/backup 如何命名。

参数优先级要可解释

同一参数可能来自:

role default
global vars
module/group vars
cluster vars
host vars
extra vars
generated template
runtime dynamic config

最终值要能回答:

value
source
scope
owner
change context
rendered destination
live observed value

“我在 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。

模板不能自动知道:

peak TPS and query mix
working set
connection fan-out
storage latency
WAL generation
RPO/RTO
maintenance workload
tenant contention

第 26、27 章才通过压力与瓶颈证据调参。

从 exact release 生成配置

本章没有直接运行当前 dirty checkout,而是:

git archive v4.4.0

解到私有临时目录,并记录 tag commit:

2d5a45f759274048de0c197829228a71d0182e5c

然后:

./configure -c ha/full -s -n -g -v 18 -r default

参数含义:

-c ha/full   使用四节点功能演示模板
-s           跳过 IP 探测/替换
-n           非交互
-g           生成随机密码
-v 18        PostgreSQL major 18
-r default   默认上游仓库区域

ha/full 官方定位主要是演示与测试,不是生产拓扑模板;它把 infra、单 etcd、 MinIO 和 pg-meta 放在第一节点,pg-test 放在后面三节点。这正是本章 将其标为 sandbox 的原因。

generator output 必须 review

wizard 给出初稿后,逐项 review:

source release
target addresses and SSH user
OS/architecture
module membership
PostgreSQL major/locale/checksum
storage paths
cluster/member identity
service/offline placement
repo/mirror/proxy
secrets
safeguards
backup target
monitoring retention
firewall/access

configure 成功只表示生成文件,不表示目标可部署。

live inventory 是 secret-bearing artifact

随机密码比模板默认密码安全,但文件仍含 secret。处理:

mode 0600
private temporary/secret-managed path
never paste full file into issue/chat/log
never commit
rotate if exposed
production uses secret authority and lifecycle

本次初始化过程中,首次生成的凭据曾出现在工具输出边界;因此立即重新生成, 正式 live inventory 使用另一组未打印的值。这个事件提醒我们:

redaction 不是最后一步;command output、debug、diff 和 CI log 都是泄露面。

只导出 allowlist projection

inventory_projection.py 读取 live inventory,只保留:

Pigsty/PostgreSQL/locale non-secret globals
host set and group membership
cluster/member role/offline flags
source mode and a withheld source-fingerprint marker
safe projection checksum in the capture manifest
redacted secret-field count
secret_values_exported=0

它不使用“把已知 password 字段替换为星号后整份输出”的 denylist 模式。 denylist 容易漏掉新字段;allowlist 默认拒绝未知内容。

执行:

export PG36_CH19_INVENTORY=/absolute/private/pg36.yml
export PG36_EVIDENCE_DIR=/absolute/evidence/ch19
static/labs/ch19/task.sh project

投影不是可用于部署的 inventory,故意不可逆。

sanitized example 只表示形状

inventory.example.yml 使用 sentinel secret,帮助理解结构。它不应原样部署。

审阅 example 时也要防止:

真实 address/owner accidentally copied
有效 token/password
private key
internal repository credential
production backup endpoint

inventory 是 code,但不等于把一切都放 Git

适合版本化:

schema and groups
non-secret desired parameters
service definitions
role/database declarations without secret values
policy IDs
change history

需要受控 secret store:

password
private key
recovery secret
API token
CA signing key
KMS credential

需要外部事实系统:

asset/failure-domain inventory
IPAM/DNS authority
owner/on-call
certificate issuance
package artifact promotion

声明式不是单文件崇拜,而是让 authority 可追踪。

19.6.2 生产服务与隔离验证服务

先澄清本节标题的边界

生产设计应该区分:

application service unit
platform/control/validation unit

本章用 pg-testpg-meta 演练这种分工,但两者都位于 disposable sandbox:

production_data_permitted=false
production_traffic_permitted=false

所以 pg-test 是 production-shaped teaching service,不是生产服务; pg-meta 也不是合格的生产 control plane。

服务单元一:pg-test

声明:

pg-test:
  hosts:
    10.10.10.11:
      pg_seq: 1
      pg_role: primary
    10.10.10.12:
      pg_seq: 2
      pg_role: replica
    10.10.10.13:
      pg_seq: 3
      pg_role: replica
      pg_offline_query: true
  vars:
    pg_cluster: pg-test

目的:

three-member topology
primary/replica service rehearsal
offline placement rehearsal
chapter 20 fault target
chapter 21 recovery target
chapter 22 endpoint target

当前 bootstrap role:

.11 primary
.12 replica
.13 replica/offline

future failover 后 runtime role 可能变化;inventory declaration 与 observed role 的解释要跟着 chapter 20 contract 更新。

服务单元二:pg-meta

声明:

pg-meta:
  hosts:
    10.10.10.10:
      pg_seq: 1
      pg_role: primary
  vars:
    pg_cluster: pg-meta

同一 node 还承载:

Pigsty infra
single etcd member
MinIO
monitoring/logging
admin source

它可用于控制与验证,但这个共置形成大 blast radius。不要把“组件齐全”解释为 “组件高可用”。

两个 service unit 必须有不同 system identifier

部署时如果错误 clone 同一 cluster,再改名字,表面可能出现两个 group。 因此验收要求:

system_id(pg-meta) != system_id(pg-test)

同时:

system_id(pg-test-1)
= system_id(pg-test-2)
= system_id(pg-test-3)

这是 declaration 和 physical lineage 的交叉检查。

control data 与 application data 不要无意混合

真实平台需要决定:

Pigsty metadata DB 是否与业务 cluster 分离
monitoring outage 是否影响 DB availability
backup repository failure 是否影响 primary
DCS failure 是否影响 existing traffic/new failover
control credentials 是否能访问 business data
control-plane maintenance blast radius

本沙箱共置是资源选择,不是推荐生产答案。

offline 服务不等于隔离环境

.13 是 replica + offline query 标记。它仍:

接收同一 WAL
占同一 laptop CPU/storage
依赖同一 DCS
可能被 direct access
可能因慢查询产生 recovery conflict

要实现更强隔离,可能需要:

dedicated host/failure domain
cgroup/resource limits
separate service/HBA/role
query timeout
replication/freshness SLO
dedicated cluster or analytical system

production topology 要替换六个例外

从本章沙箱走向生产,不是删除 sandbox 字样。至少解决:

independent failure domains
etcd quorum
backup target/DR independence
qualified storage
secret authority/rotation
measured resource capacity

并完成后续章节 gate。

service unit review 表

问题pg-metapg-test
authoritycontrol/validationteaching application service
members13
current primary.10.11
replicas0.12, .13
offline placementno.13
system IDownshared within three members
production SLOnonenone
later fault targetlimitedchapter 20

这张表应进入 design review,而不是从 Ansible recap 猜。

19.6.3 幂等部署、差异检查与失败重跑

幂等的正确含义

理想的 idempotent task:

run desired convergence once -> target state
run again without input/drift -> no material change

但整套部署包含:

package repositories
generated secrets/certificates
database initialization
backup creation
monitoring registration
external APIs
service restarts
time-dependent facts

所以不能用“Ansible 是幂等的”替代每个 action 的语义。

Pigsty 官方 Playbooks 说明大多数 playbook 可重复运行,同时指出清理参数和 *-rm.yml 等有重要 caveat。

一次完整部署的受控顺序

本章实际流程:

1. resolve/extract exact release
2. generate and review private inventory
3. direct SSH ping four identities
4. copy exact release + private inventory to admin node
5. bootstrap admin prerequisites
6. run ./deploy.yml -i pg36.yml
7. retain private log and return code
8. capture only safe recap
9. read-only L2 evidence capture
10. positive + negative validation and review

Pigsty deploy.yml 是 core chain 的 one-pass deployment。它完成很多工作, 不意味着每个业务 policy 自动满足。

recap 是执行证据,不是服务验收

本次安全 recap:

targetokchangedunreachablefailed
10.10.10.1032624800
10.10.10.1117413400
10.10.10.1215912000
10.10.10.1315912000
localhost6400

它证明 playbook 没报告 failed/unreachable。它不证明:

correct target identity
correct locale/checksum
one leader
replication healthy
service routing
production capacity
backup restore
HA behavior

这些另行验收。

changed=0 也不是唯一幂等标准

一些 task 合理地每次:

refresh facts
check service
render timestamped artifact
probe endpoint
rotate ephemeral state

也有 task 误报 changed。应关注:

unplanned service restart
config checksum drift
package version change
database reinitialization
role/permission mutation
secret rotation
endpoint outage

二次执行前先查 playbook/tag 的语义,不以追求漂亮 recap 为目标。

失败重跑前先分类

失败类型:

类型例子下一步
transientrepo timeout、短暂 DNS保存证据后 bounded retry
declarationwrong group/var修 inventory,review diff
prerequisitesudo/clock/disk修前提并重新 preflight
partial initprimary created, replica failed查 cluster state,按 role runbook
incompatiblepackage/extension/OS停止,修矩阵
destructive driftwrong target/data exists停止并升级决策
secret exposurelog printed credential先 rotate/contain

不要在不知道已执行到哪里时直接:

rm -rf PGDATA
pgsql-rm
wipe/reconfigure all

失败现场是证据。

限制 scope

Pigsty playbook支持 Ansible -l 与 tags。例:

./pgsql.yml -i private.yml -l pg-test
./pgsql.yml -i private.yml -l 10.10.10.13
./pgsql.yml -i private.yml -l pg-test -t pg_service

使用前必须确认:

inventory exact path
limit resolves to expected hosts
tag dependencies
check/diff support and limitations
serial/batch behavior
current member role
change authority

-l pg-test 是作用域控制,不是安全沙箱。

diff 不能泄密

安全 diff 分层:

secret-free projected inventory diff
rendered config hash/semantic diff
live pg_settings diff excluding secrets
package/version diff
service membership diff
policy exception 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 只提供:

project
capture
verify
review
all
reset:cluster

其中 all 只读。没有 deploy 是有意设计:

source-controlled 验收脚本不应在读者以为“检查环境”时顺便收敛 package、 重启服务或重建数据库。

部署需要独立变更窗口和 runbook。

removal playbook 是 destructive action

Pigsty pgsql-rm.yml 用于移除 cluster/instance。官方文档说明 production 应显式启用 pg_safeguard,并对 override 格外谨慎。

本章只提供多重 guard 的 reset-cluster.sh,没有运行它。它要求:

exact sandbox target
exact reset token
no production data assertion
clients drained assertion
exact release/inventory
prior machine-ID allowlist
fresh passing evidence
interactive second ACK

这是演示 destructive contract,不是授权。

交付完成定义

声明式交付完成需同时满足:

source pinned
inventory reviewed and secret-safe
target identity proven
playbook rc/recap retained
live host facts pass
PostgreSQL init contract pass
Patroni/SQL/inventory topology agree
endpoint identity observable
exceptions accepted by owners
rollback/reset boundary explicit
later gates remain named

本章环境满足 sandbox L2,带六个 exception;production gate 仍 pending。


上一节:拓扑、命名与故障域 · 返回本章目录 · 下一节:实战:L2 部署验收 · 查看全书目录 · 查看索引中心

最后更新于