跳转到主要内容

第 0 章(可跳过)扬帆起航——准备实验环境

可跳过说明:本章只为尚未拥有实验环境的读者准备 Pigsty L1 沙箱,并完成首次 PostgreSQL 连通。已有符合版本契约、且确认没有生产数据和流量的 独立环境,可以直接进入 第 1 章

正文默认读者已经会 Linux、SSH 与 SQL;这里不补授操作系统、网络或 SQL 基础。本章 只建立后续实验共同需要的六项事实:

exact Pigsty/PostgreSQL/OS version
non-production environment authority
node and service identity
safe network boundary
working PostgreSQL connection
redacted baseline evidence

本书采用的复现基线是 Pigsty v4.5.0、PostgreSQL 18.6 与 Ubuntu 24.04 LTS reference environment。安装时固定 Pigsty release 与 PostgreSQL major,随后记录仓库 实际提供的 minor/build;不要为了伪造一致性降级已经修复安全问题的 minor release。

完成本章的标准

进入 ch01 前,读者应能:

  1. 明确目标是可销毁、无生产数据与流量的 L1;
  2. 记录 CPU、内存、磁盘、OS、架构、网络和成本边界;
  3. 从官方来源获取并固定 Pigsty v4.5.0
  4. 在执行前审查生成的 pigsty.yml,保护其中的凭据与 CA key;
  5. 完成单节点部署或验证一个等价的已有环境;
  6. 分开 PostgreSQL、PgBouncer、HAProxy service 与 Web UI 入口;
  7. 从 SQL 内部确认版本、数据库、角色、地址、端口与 recovery state;
  8. 保存不含密码、token、private key 的环境摘要;
  9. 知道安装失败时应保留日志、修复前置条件或重建 L1,而不是删除 PGDATA 猜测恢复。

本章目录

0.1 选择实验环境

0.2 安装单节点 Pigsty 沙箱

0.3 完成首次连通

安全边界

  • 单节点 L1 不提供生产高可用证明;
  • 云端不把 PostgreSQL、PgBouncer、Patroni、DCS、监控或管理入口裸露到公网;
  • pigsty.ymlfiles/pki/ca/ca.key 视为敏感材料;
  • 本章不要求关闭 firewall/SELinux、使用默认密码或以 root 长期运行;
  • 重装、清空数据和删除 cluster 都不是普通排错动作。

当前官方参考


返回全书导读 · 下一章:PostgreSQL 与 Pigsty 全局地图 · 查看全书目录 · 查看索引中心

0.1 选择实验环境

L1 的目标不是模拟生产,而是给 ch01~ch18 一个身份稳定、可以反复创建对象、能够 观察 PostgreSQL 与 Pigsty 的实验落点。选型优先保证隔离与可恢复,再追求便利。

0.1.1 本地虚拟机、开发服务器与已有 Pigsty 环境

三种可接受入口

入口 适合 优点 必须处理
本地 Linux VM 个人学习、可反复重建 隔离清楚、snapshot 方便 内存/磁盘、宿主休眠、端口转发
独立开发服务器 团队共享、长时间运行 资源稳定、远程可达 owner、并发实验、配额、清理
已有 Pigsty dev/test 已有标准环境 快速进入正文 版本、权限、数据/流量、作用域

macOS/Windows 宿主推荐在 Linux VM 中部署。Pigsty 管理 Linux 服务、package、filesystem 和 network;把它直接改写成容器教程会改变本书实验边界。WSL 可用于体验,但涉及 systemd、网络、存储与多节点演练时要重新验证。

环境接受表

environment_id: pg36-l1-...
owner: ...
purpose: book-labs
production_data: false
production_traffic: false
shared_users: [...]
rebuild_source: vm-image-or-inventory
snapshot_or_backup: ...
expires_at: ...
network_boundary: ...

已有 Pigsty 环境只有在以下问题都得到肯定回答后才可复用:

我能指认 exact node/cluster/database/role 吗?
它没有生产数据、生产流量和真实 secret 吗?
我有权创建和清理本书对象吗?
实验负载不会伤害其他用户吗?
失败后能恢复或重建吗?
版本差异已记录吗?

任一答案不明确,就新建 L1。能登录一台机器不等于获得数据库故障注入、服务重启或 数据清理授权。

命名与 snapshot

为 VM、hostname、SSH alias 和 evidence 使用 pg36-l1 前缀,避免与生产式名字混淆。 在全新 OS、Pigsty 安装完成、重要 extension 安装后分别保留 snapshot;记录 snapshot identity 和创建时间。snapshot 不是 backup 的替代,但适合恢复教学环境。

0.1.2 L1 沙箱的最低资源、网络与磁盘要求

Pigsty 官方单节点 quick start 可以从 1 vCPU / 2 GiB 起步;这只表示能完成基础部署。 本书 L1 同时运行 PostgreSQL、监控栈并执行查询/扩展实验,采用更保守档位:

档位 CPU 内存 可用磁盘 用途
安装下限 1 vCPU 2 GiB 20 GiB 只验证 quick start,可能发生内存/等待压力
本书最低 2 vCPU 4 GiB 40 GiB ch01~ch14 的小规模 fixture
推荐 4 vCPU 8 GiB 80 GiB 搜索、时空、分析 PoC 与舒适监控

这些是教学资源档,不是生产 sizing。不同架构、磁盘、extension 和宿主 overcommit 会 改变表现;第 26 章 才讨论有证据的容量结论。

安装前采样

uname -a
cat /etc/os-release
getconf _NPROCESSORS_ONLN
awk '/MemTotal/ {print}' /proc/meminfo
df -hT /
ip -brief address
ip route
timedatectl status

不要只看虚拟磁盘标称容量;确认 filesystem 可用空间和 inode。扩展 package、监控 retention、WAL、backup、fixture 与 evidence 都会增长。L1 的磁盘满也可能让 PostgreSQL 无法安全写入。

网络合同

stable hostname and address inside the lab
SSH from the operator workstation
package/repository reachability or exact offline package
working DNS and time synchronization
no overlap with production/private routes
no public database exposure

NAT 模式通常足够;只有需要从宿主访问 Web UI/数据库时才配置明确端口转发或 host-only 网络。记录从哪个 source CIDR 允许访问,避免使用 0.0.0.0/0

0.1.3 云主机的防火墙、入口与费用边界

最小暴露

云 security group 默认 deny inbound,只从操作者固定 IP、VPN 或 bastion 允许 SSH。 Web UI 优先通过 VPN/SSH tunnel;确需 443 时限制来源并配置 TLS。PostgreSQL/服务端口 只对明确应用网络开放。

不要向公网开放:

5432 / 6432 / 5433 / 5434 / 5436 / 5438
Patroni API and DCS
Grafana/Victoria/Alertmanager/admin endpoints
node/exporter/backup metrics

端口表随配置变化,以本地 inventory/rendered config 为准。只关闭 OS firewall 而依赖 云 security group,或反过来,都会制造单层防护。

凭据与主机

  • 使用普通管理用户 + sudo,不以 root/postgres 作为日常 SSH 用户;
  • SSH 使用 key,限制 source,关闭不需要的密码登录;
  • ./configure -g 生成随机密码,保护 pigsty.yml
  • 保护 Pigsty CA private key,不复制进聊天、工单或 Git;
  • 教学数据保持合成,不上传客户 dump;
  • 设置资源 tag、owner、expiration 和预算告警。

费用清单

compute uptime
system/data/backup disk and snapshots
public IPv4
egress and cross-zone traffic
object storage/API requests
retained image and unattached volume

停止 VM 可能仍收磁盘、snapshot 与 IP 费用;删除 VM 可能同时删除唯一 evidence。实验 结束先导出所需的去敏小型 evidence,再按云平台的 exact resource ID 清点。不要在 本书中提供一条通用递归删除命令。

进入安装前的 stop line

以下情况先解决,不继续:

目标可能承载生产数据/流量
OS/architecture 不在当前支持矩阵
磁盘或内存低于接受档
时间/DNS/package source 异常
公网入口无法限制
没有恢复或重建路径
无法保护 inventory 与 CA key

返回本章目录 · 下一节:安装单节点 Pigsty 沙箱 · 查看全书目录 · 查看索引中心

0.2 安装单节点 Pigsty 沙箱

本节以全新、可销毁 Linux 节点为前提,冻结 Pigsty v4.5.0,使用默认单节点 meta 模板和 PostgreSQL 18。官方命令与模板会继续演进;复现本书时固定 release,不追随 main 或“latest”漂移。

0.2.1 获取与核对版本

前置身份

id
hostnamectl
cat /etc/os-release
uname -m
sudo -n true
ssh localhost sudo -n true

Pigsty 需要 Linux、SSH 和 sudo。sudo -n/localhost SSH 失败时先修管理前置,不要把 脚本改成长期 root 运行。对照当前支持矩阵确认 发行版 minor 与架构。

固定 release

官方 bootstrap 方式:

curl -fsSL https://repo.pigsty.io/get | bash -s v4.5.0
cd ~/pigsty

若组织禁止 pipe-to-shell,先下载、记录 SHA-256、人工/安全工具审查,再执行;或:

git clone https://github.com/pgsty/pigsty.git
cd pigsty
git checkout v4.5.0
git status --short
git rev-parse HEAD
./bootstrap

tag 提供版本选择,不自动证明供应链可信。高要求环境应按组织规则验证 release artifact、来源、签名/摘要、package repository 与代理。offline package 必须匹配 OS minor/architecture,并核对对应 release 页面摘要。

保存不含 secret 的 acquisition manifest

{
  date -Is
  git describe --tags --always --dirty 2>/dev/null || true
  git rev-parse HEAD 2>/dev/null || true
  uname -a
  cat /etc/os-release
} > pg36-acquisition.txt

不要把 shell environment、完整 inventory 或 credential 写入该文件。

0.2.2 配置、部署与幂等重跑

生成,再评审

在 Pigsty source directory:

./configure -g -v 18
chmod 0600 pigsty.yml

-g 生成随机密码;默认 meta 是单节点模板。执行前评审:

inventory host/IP is this L1
pg_cluster and instance identity are expected
PostgreSQL major is 18
package/repository source is accepted
data/config/log/backup paths fit the disk
listen/access rules do not expose public networks
generated passwords are not defaults
modules and apps are actually needed

pigsty.yml 含访问和密码信息,不提交本书仓库、不粘贴到公开 issue。files/pki/ca/ca.key 生成后同样限制权限并备份到受控位置。

执行部署

先确认 target:

./install.yml --list-hosts
./install.yml --list-tags

再在 L1 执行:

./install.yml

保留:

start/end time
Pigsty revision
redacted inventory digest
Ansible exit code
failed task and host
package versions

不要把“play recap 全 green”当数据库验收;下一目从 service、component 和 SQL 三侧 验证。

幂等的正确含义

修复临时网络/package 前置后,可以对同一 desired state 重跑部署;幂等意味着系统应 收敛到声明状态,不意味着:

每次没有任何 changed
任何删除 playbook 都安全
运行中手改不会被覆盖
失败后可以删除 PGDATA 再试

若重跑持续出现 unexpected changes,比较 inventory、rendered file 与 runtime, 定位 non-idempotent task 或 drift。不要为“全绿”关闭安全控制。

失败与复位

package/download failed -> 修 repo/DNS/TLS,保留失败输出后重跑
inventory/host wrong    -> 停止;不要在错误目标继续
disk/memory exhausted   -> 扩容或重建 L1,不清理未知 PG/WAL 文件
partial database state  -> 先取证和确认是否已有数据,再决定恢复/重建

对全新、确认无数据的 disposable VM,回到安装前 snapshot 往往比手工拆半套服务可靠。 已有数据的机器不属于本节重建授权。

0.2.3 检查 PostgreSQL、连接池与观察组件状态

四层健康

process
  service active / no crash loop

endpoint
  port accepts and route selects expected backend

protocol
  PostgreSQL authentication and SQL work

semantic
  exact cluster/database/role/version and expected read-write state

检查环境/package:

pig status
postgres --version
psql --version

检查本机 unit(模板禁用某组件时,inactive 不自动等于失败):

systemctl is-active patroni
systemctl is-active pgbouncer
systemctl is-active haproxy
systemctl --failed

检查 PostgreSQL readiness:

pg_isready -h 127.0.0.1 -p 5432

pg_isready 不验证业务角色、数据库、查询或正确 backend,只是 protocol-level availability。

分清端口

默认 Pigsty service 通常包括:

端口 入口 教学语义
5432 PostgreSQL instance 本实例直连
6432 PgBouncer 本实例 pool
5433 HAProxy primary service 读写,经 pool
5434 HAProxy replica service 只读目标,经 pool
5436 HAProxy default service primary 直连
5438 HAProxy offline service offline/分析直连

以本地 pigsty.yml 与 rendered HAProxy config 为准。单节点仍可暴露 replica/offline service 名称,但没有第二故障域,不应宣称 HA。

观察系统

从受限网络访问 Web UI,确认:

PostgreSQL target discovered
host target discovered
Patroni/etcd/PgBouncer/HAProxy as configured
metrics have recent timestamps
logs and alert evaluation available

dashboard 可见不证明采集语义正确;记录 target identity 和 timestamp。不要公开默认 UI 密码或将管理 UI 暴露到公网。


上一节:选择实验环境 · 返回本章目录 · 下一节:完成首次连通 · 查看全书目录 · 查看索引中心

0.3 完成首次连通

最后一步不是“能打开 psql”,而是从连接内部确认操作落点,并保存一份不泄露凭据的 baseline。第 1 章会在此基础上创建本书专用数据库、模式和角色。

0.3.1 找到服务端点、数据库与实验凭据

五元连接身份

host/service
port/route semantics
database
role
TLS/session parameters

默认单节点通常提供 pg-meta cluster、meta database 与管理/业务/只读角色;实际值 从你的 pigsty.yml 读取。该文件含 secret,只在受控终端查看,不把整行 URI 或密码 复制进 shell history、截图和文档。

首次连接可让 psql 单独提示密码:

psql -h 127.0.0.1 -p 5432 -U dbuser_dba -d meta -W

不要把密码写在命令行 URI。需要非交互任务时使用 mode 0600.pgpass、service file 或组织 secret injection,并确保日志不打印环境。

先直连,后比较 service

先用 5432 直连确认 PostgreSQL,再按本地配置比较 6432/5433/5436。对每个 endpoint 执行同一 identity query,记录它是否经过 pool、route 到哪个 backend、支持什么会话 状态。不要把“端口可连”推断成“读写语义正确”。

常见失败

症状 首查 不要先做
connection refused host/port/listener/unit 放开全部 firewall
timeout route/security group/监听地址 重启所有组件
password failed exact role、HBA、secret source 把密码打印到日志
database missing database identity/inventory 连默认库后误以为成功
read-only endpoint 与 pg_is_in_recovery() 强行改 transaction_read_only

0.3.2 执行 SELECT version() 与只读状态查询

psql

\set ON_ERROR_STOP on
\pset pager off

SELECT
    current_setting('server_version') AS server_version,
    current_setting('server_version_num') AS server_version_num,
    current_database() AS database,
    current_user AS role,
    session_user,
    inet_server_addr() AS server_addr,
    inet_server_port() AS server_port,
    pg_is_in_recovery() AS in_recovery;

SELECT
    current_setting('transaction_read_only') AS transaction_read_only,
    current_setting('default_transaction_read_only')
        AS default_transaction_read_only;

Unix socket 连接时 inet_server_addr()/inet_server_port() 可以是 NULL,这是 transport 语义,不是 PostgreSQL 缺地址。service endpoint 可能返回 backend instance 地址, 不等于客户端连接的 HAProxy 地址。

再检查 search path 与身份:

SHOW search_path;
SELECT current_schemas(true);
SELECT
    pg_catalog.pg_has_role(current_user, 'USAGE') AS current_role_usable;

version() 包含 build 信息,适合证据;程序判断用 server_version_num,不要解析展示 字符串。

保存去敏基线

psql -X -v ON_ERROR_STOP=1 \
  -h 127.0.0.1 -p 5432 -U dbuser_dba -d meta \
  -A -F $'\\t' -t \
  -c \"SELECT current_setting('server_version_num'),
             current_database(), current_user,
             coalesce(inet_server_addr()::text, 'unix-socket'),
             coalesce(inet_server_port()::text, 'unix-socket'),
             pg_is_in_recovery();\" \
  > pg36-l1-identity.tsv

该输出不含 password;仍按内部环境资料保护 host/role。检查退出码与文件非空,不要因 redirect 创建空文件就认为成功。

0.3.3 确认编码、时区和扩展清单后进入 ch01

locale/time/encoding

SELECT
    datname,
    pg_encoding_to_char(encoding) AS encoding,
    datlocprovider,
    datcollate,
    datctype
FROM pg_catalog.pg_database
WHERE datname = current_database();

SHOW TimeZone;
SHOW DateStyle;

SELECT
    now() AS transaction_time,
    statement_timestamp() AS statement_time,
    clock_timestamp() AS wall_time;

后续时间、collation、索引和升级实验依赖这些事实。不要为了“统一”直接修改 cluster; 先记录差异,在对应章节决定是否需要重建或迁移。

installed 与 available extension 分开

当前数据库已安装:

SELECT
    extname,
    extversion,
    extnamespace::pg_catalog.regnamespace AS schema
FROM pg_catalog.pg_extension
ORDER BY extname;

操作系统/仓库可提供但未安装的扩展是另一集合,不能用 pg_available_extensions 冒充 installed。扩展是 database-local object;同一 instance 的另一 database 不会自动继承。

最终 baseline

book_baseline:
  environment: pg36-l1
  production_data: false
  production_traffic: false
  pigsty_release: v4.5.0
  pig_cli: ...
  postgresql_server: ...
  os_kernel_arch: ...
  cluster_database_role: ...
  connection_endpoint: ...
  encoding_locale_timezone: ...
  installed_extensions: [...]
  monitoring_observed_at: ...
  secret_values_recorded: false

进入 ch01 的 gate:

identity query succeeds
server major = 18, exact minor recorded
database and role are expected
L1 is writable and not in recovery
encoding/timezone/collation recorded
installed extension list recorded
monitoring has current target data
no production data/traffic or exposed management endpoint

不满足时留在第 0 章修环境。满足后进入 第 1 章:PostgreSQL 与 Pigsty 全局地图,在那里创建 pg36_shop,不要把默认 meta database 当作全书业务模型。


上一节:安装单节点 Pigsty 沙箱 · 返回本章目录 · 进入第 1 章 · 查看全书目录 · 查看索引中心