
“PostgreSQL 到底该怎么管”这个问题我大概想了五年。数据库本身不复杂复杂的是它身边的那些配套设施备份要写脚本、高可用要搭 Patroni、监控要配 Prometheus、看板得自己画、告警要对接钉钉或邮箱每一环单独拿出来都不难但串在一起就是一座大山。后来我接触到 Pigsty发现这条路终于可以走得更顺一些。Pigsty 是一个面向 PostgreSQL 的一体化开源数据库发行版它把部署、高可用、监控、日志、备份这些原本分散的工作整合成一套基于 Ansible 和 YAML 配置的交付体系你写完一份集群描述文件剩下的由它自动完成。这篇文章不打算写成功能清单。我会从实际使用者的角度讲清楚 Pigsty 的定位、内部组件如何协作、如何用一台机器快速体验、如何部署真正可用的主从集群以及我在反复安装和切换过程中踩过的那些坑。无论你是刚接手 PostgreSQL 运维任务的新手还是已经在生产环境摸爬滚打多年的老手只要你想摆脱“装好 PG 之后还得独自伺候周边一大堆组件”的尴尬状态这篇文章都应该能帮你省下不少时间。1. 换个角度理解 Pigsty它不只是一个监控面板而是一个“库发行版”我第一次听说 Pigsty 时以为它只是给 PostgreSQL 配了一套好看的 Grafana 看板。后来完整用了一遍才发现这个理解太浅了。Pigsty 的定位接近于“Linux 发行版”里的 CentOS 或 Ubuntu——它不是帮你装一个单纯的操作系统而是把内核、常用软件、包管理、镜像源全部给你整理好开箱即用。放到数据库场景里Pigsty 是把 PostgreSQL 以及它周边的基础设施打成一套完整交付物。1.1 它解决的到底是什么问题单独安装 PostgreSQL 非常简单一条包管理命令就能搞定。但到了生产环境问题马上变多主库挂了谁来把从库提升为新主应用连接字符串写的是固定 IP故障切换后 IP 变了怎么办数据库指标看哪里连接数、慢 SQL、复制延迟、缓存命中率每个指标都要自己找口径组织。日志分布在各个节点出了问题要 SSH 到服务器上一台一台 tail。备份策略怎么做物理备份还是逻辑备份保留几天怎么验证可恢复性。这些问题的答案并不在 PostgreSQL 内核里而是散落在 Patroni、Etcd、HAProxy、Prometheus、Grafana、Loki、pg_probackup 等一堆开源工具中。Pigsty 所做的就是把这些工具以 PostgreSQL 为核心重新编排统一暴露给使用者并通过一套 YAML 配置描述出整个环境的状态。1.2 与“手动搭一套 PG 全家桶”的差异如果你自己手动搭建过 PostgreSQL 高可用一定体验过版本兼容性的痛苦。Patroni 需要特定版本的 psycopg2Consul 和 Etcd 选哪个HAProxy 的端口怎么规划Prometheus 的 postgres_exporter 采集哪些指标Grafana 有没有现成好用的仪表盘——这些都没有统一标准。每换一个环境就要重来一遍。Pigsty 把这些工具的默认版本、默认端口、默认权限关系全部固定下来。例如它规定每个节点上可能存在的角色etcd负责元数据与选举pgsql运行 PostgreSQL 实例haproxy对外提供接入入口monitor节点承载 Prometheus 和 Grafana。所有这一切可以在一个叫做pigsty.yml的文件中声明。你不用在多个服务器之间来回切换操作只需要维护这一份配置。1.3 开箱即用与离线交付的底气我对 Pigsty 印象最深的一点是它非常强调“本地源”这个设计。整个发行版把需要的 RPM 包或 DEB 包、常用的 Python 依赖、Grafana 插件模板全部整理成本地软件源。初始化时它会先构建一个基础设施节点再基于这个节点向其他数据库节点分发软件包。也就是说当你在离线内网环境部署时只要提前准备好一份完整的安装包后续的安装过程根本不依赖外网。这一点对那些有严格网络隔离要求的业务场景太重要了。我在实际交付中遇到过目标服务器无法访问外网的情况手动装一个 PostgreSQL 都得倒腾半天依赖而 Pigsty 因为内置了离线安装路径整个布署过程反而比在线环境更稳定。正是这种“库发行版”的思路让 Pigsty 不再是一堆零散脚本的堆积而是一个具备一致体验的完整产品。理解了这层定位后面所有操作才有坐标系。2. 架构拆解从 etcd、Patroni 到 HAProxyPigsty 把高可用安排的明明白白想要用好 Pigsty必须先理解它内部的那套协作逻辑。它不是简单地把几个开源工具装在一起而是给它们规定了明确的职责边界和交互方式。2.1 四类角色一张 YAML 描述清楚在 Pigsty 的模型里节点角色大致分为四种角色默认组件承担职责infraPrometheus、Grafana、Loki、Nginx、DNS提供监控、日志、软件源和统一入口etcdEtcd 集群保存 PostgreSQL 集群的分布式共识信息支撑 Patroni 的选主pgsqlPostgreSQL、Patroni、HAProxy承载数据库实例并提供服务接入redisRedis、Redis Sentinel可选缓存组件与 PostgreSQL 集群独立因为 infra 节点同时承担软件源的角色所以整个 Pigsty 环境通常需要至少一台机器专门作为“元节点”。其他节点通过 Ansible 从这个元节点获取安装包和配置模板。2.2 Patroni 加 Etcd选主这件事得有个大家服气的裁判PostgreSQL 高可用本质上是回答一个问题主库死了谁说了算Patroni 给出了分布式系统里很经典的解法借助外部分布式存储来做 leader 选举同时它自己持续探测每个 PostgreSQL 实例的健康状态。Pigsty 选择了 Etcd 作为 Patroni 的分布式一致性存储而不是 Consul 或 ZooKeeper。原因是 Etcd 在 Kubernetes 生态里久经考验部署和管理相对简洁而且 Pigsty 本身也支持用同一套 Etcd 集群承载其他状态的保存。每个 PostgreSQL 节点上的 Patroni 会把主库位置、候选优先级、领导者租约等信息写入 Etcd。某个节点故障后Patroni 会依据 Etcd 中的信息协商出新的主库。我在实际测试中做过一次强制切换把当前主库机器直接关机大约 20 到 40 秒后HAProxy 的流量就会切到新的主库。整个过程应用基本无感。这种效果并不是 PostgreSQL 数据库内核自己具备的能力而是 Patroni 和 Etcd 协作的产物。2.3 HAProxy给太多无法直连数据库的团队一条活路很多人会有疑问客户端为什么不直接连接 PostgreSQL 而要走一层 HAProxy直接连接看似简单但有一个致命问题主库切换后客户端手里握着的连接全都失效。如果客户端本身不感知拓扑变化就必须有人在前端把请求分流到当前的主库。HAProxy 在这里承担的就是数据库流量的“路由器”。Pigsty 默认会给每个数据库节点分配两条 HAProxy 接入路径一条指向当前主库名称类似primary另一条指向候选从库名称类似replica。读写分离架构里应用把只读流量打到replica端口把写流量打到primary端口。主库切换时Patroni 通过回调脚本触发 HAProxy 的配置变更将主库端口重新指向新主节点。在应用看来始终只需要连接同一个虚拟地址。这里有一个细节HAProxy 不参与 SQL 解析它只做四层转发。所以 PostgreSQL 的预处理语句、事务、池化机制都不会受影响。它的性能损耗也极低在我的测试环境中即使不加任何外部连接池纯 HAProxy 转发也能轻松扛住几千个并发连接。2.4 Prometheus 三件套怎么融入架构监控是 Pigsty 的另一个重头戏。每个 pgsql 节点上会部署 node_exporter 和 postgres_exporter由 infra 节点上的 Prometheus 统一拉取指标。Grafana 预置了一百多个仪表盘覆盖节点资源、数据库集群状态、表级膨胀、复制延迟、慢查询趋势等。Loki 负责收集各组件日志提供关键字检索。也就是说你通过一份pigsty.yml部署出来的环境不仅包含数据库本身还包括一条完整的数据可观测链路。后面我会专门讲监控的使用这里先让大家有个整体概念。3. 预备环境与安装流程YAML 配置写完之后一条命令能办多少事Pigsty 的安装过程完全围绕 Ansible 展开。你只要准备一台能够访问所有目标节点的控制主机以及若干台待部署的服务器然后写好一份 YAML 配置剩下的大规模安装由 Ansible 并发执行。3.1 环境准备阶段最容易忽略的三件事我自己部署过好几轮 Pigsty发现环境准备如果有一步不到位后面排错会非常痛苦。先把最容易踩的坑列出来。第一操作系统兼容性。Pigsty 对操作系统有明确支持范围我长期使用的是 CentOS 7.9、CentOS 9 Stream 和 Ubuntu 22.04。如果你用的是某个非常小众的 Linux 发行版或者内核被深度修改过的定制系统很可能在编译依赖阶段报错。第二主机名的规范化。Pigsty 会根据主机名生成大量标签主机名里不要出现下划线或中文。建议统一用pg-test-01、pg-test-02这种风格。如果你的业务系统已经用了一堆不规则的机器名称在部署前先把 hostname 改掉否则后面 Grafana 看板里会出现一堆难认的标签。第三SSH 免密登录。Pigsty 控制机需要免密登录所有目标节点而且至少需要 root 权限。有些人习惯用普通用户加 sudo但在 Pigsty 的默认路径里直接采用 root 登录是最省事的。先把每个节点的/root/.ssh/authorized_keys配置好并通过ssh 节点IP确认能免密进入。3.2 一份最简配置怎么改安装 Pigsty 时默认模板会生成一个pigsty.yml。下面是我在实验环境里经常使用的精简配置假设我有三台机器IP 分别为 10.10.10.10、10.10.10.11、10.10.10.12规划如下10.10.10.10infra etcd pgsql10.10.10.11etcd pgsql10.10.10.12etcd pgsql这里把三台机器组成一个三成员 Etcd 集群同时每台都跑 PostgreSQL形成一主两从的高可用结构。all: children: infra: hosts: 10.10.10.10: infra_seq: 1 etcd: hosts: 10.10.10.10: etcd_seq: 1 10.10.10.11: etcd_seq: 2 10.10.10.12: etcd_seq: 3 pgsql: hosts: 10.10.10.10: pgsql_seq: 1 pgsql_role: primary 10.10.10.11: pgsql_seq: 2 pgsql_role: replica 10.10.10.12: pgsql_seq: 3 pgsql_role: replica在pgsql_cluster部分建议给集群起个有业务含义的名字例如pg-meta并指定集群内的实例名。Pigsty 会基于这些标签生成服务发现、看板和告警规则。3.3 从./install.sh到bin/pigsty install的完整动作安装方式随版本演进而略有不同。在较新的版本里控制台上执行./install.sh会先检查依赖启动一个本地 Python 虚拟环境并准备好 Ansible。随后你执行./install.sh bin/pigsty config edit bin/pigsty install其中config edit会生成或修改pigsty.yml将上一步的节点拓扑和集群配置填进去。install会按顺序执行整套 Playbook初始化基础设施角色配置 Yum 源或 Apt 源安装 Python、Ansible。部署 infra 组件Prometheus、Grafana、Loki、Nginx、Alertmanager。部署 Etcd 集群。部署 PostgreSQL、Patroni、HAProxy。注册监控目标加载 Grafana 数据源和看板。整个过程如果网络畅通三台机器的环境大概在 20 到 40 分钟能跑完。如果使用离线软件源时间会更长但不会因为外网中断而失败。3.4 用检查命令确认一切正常安装完成后建议先跑几个命令验证。首先看服务是否存活bin/pigsty status这个命令返回各个节点的角色和健康状态。然后在控制机上直接连接数据库psql -h 10.10.10.10 -U postgres -p 5432Pigsty 默认创建了一个超级用户postgres密码通常在安装日志或配置中有记录但出于安全考虑生产环境里一定要第一时间改掉。再检查监控入口Grafana 默认端口是 3000浏览器里打开http://10.10.10.10:3000应该能看到预置的组织和团队配置。我见过不少人把安装过程卡在“软件源配置”这一步。实际上 Pigsty 会在 infra 节点上建立一个本地 HTTP 服务数据库节点从这台 infra 拉取 RPM 包。配置里的repo_url字段如果填错所有节点都会安装失败。建议安装前先确认 infra 节点上3000之外还有一个默认的 80 端口被 Nginx 占用这是用来提供软件源和静态文件服务的。如果这台机器上已经跑着别的 Web 服务需要提前改端口避免冲突。4. 实战建库用 Pigsty 拉起一个 PostgreSQL 主从集群并验证故障切换配置和安装做完只是拿到了一个“空舞台”。接下来你要真正创建业务数据库、测试高可用行为。这一节我记录一次完整的操作过程覆盖从创建集群到手动宕机的验证。4.1 新建一套业务集群而不是复用默认集群Pigsty 安装后默认会建立一个叫pg-meta的集群用于承载基础设施本身的元数据。生产环境最好再独立创建一套业务集群这样监控、备份和权限都可以隔离。创建集群的配置通常写在pigsty.yml里通过pgsql_cluster下的新条目声明。pgsql_cluster: pg-test: hosts: 10.10.10.11: { pgsql_seq: 1, pgsql_role: primary } 10.10.10.12: { pgsql_seq: 2, pgsql_role: replica } vars: pgsql_version: 16 pg_cluster: pg-test接下来执行bin/pigsty pg add pg-test这条命令只处理与pg-test集群相关的任务不会影响已有的pg-meta。它会在目标节点上初始化数据目录、启动 Patroni、配置 HAProxy 路由并把新集群自动注册到 Prometheus 监控里。这一步涉及的操作很多但 Ansible 会保证幂等性重复执行不会产生脏数据。4.2 连接入口变得非常清晰集群建立后可以通过 HAProxy 端口访问。默认规则如下主库接入端口 5432后端只指向当前 leader。只读接入端口 5433后端指向所有 replicaPigsty 会做简单的轮询负载均衡。直连节点端口 5432 也可以直连到具体节点的 PostgreSQL但建议优先走 HAProxy避免主库切换后应用主动断开重连。用psql测一下psql -h 10.10.10.11 -p 5432 -U postgres -d postgres psql -h 10.10.10.11 -p 5433 -U postgres -d postgres第二个连接如果落在从库上执行写操作会报只读错误这是正确行为。很多新手看到从库不让写入以为配错了实际上这正是读写分离设计写流量必须走 5432读流量走 5433语义清晰。4.3 把主库杀掉看 Patroni 和 HAProxy 如何接力高可用验证不能只看文档必须真实把主库“弄坏”。我常用的方法是直接停止主库所在节点的 PostgreSQL 进程或者干脆用poweroff模拟整机宕机。下面是在主库节点上执行的操作systemctl stop patroni这条命令会让 PostgreSQL 优雅关闭同时 Patroni 向 Etcd 释放租约。几秒后任意一个候选副本会竞选成为新主。在控制机上再次查询bin/pigsty pg check pg-test可以看到集群 leader 已经变为原来的副本节点。此时再访问 HAProxy 的 5432 端口写入依然成功。这就是 Patroni 与 HAProxy 协作的结果。需要注意的是Patroni 本身有一种“避免脑裂”机制如果发现原主库仍然存活它不会允许原主库作为新主库重新加入而是将其降级为副本然后跟随新主库重新同步数据。因此即使原主库没有完全断电只是网络抖动了一下也不会出现双主写入的混乱局面。4.4 副本扩容与缩容一个隐藏的难点如果你后面想给集群加新的从节点最快捷的方式是在pg-test.hosts下增加一台机器的 IP然后重新执行bin/pigsty pg add pg-test。Pigsty 会用新机器上空的实例启动一个基础备份再从当前主库流式复制到新节点。整个过程中无需手动 pg_basebackup也无需暂停写入。缩容则要多留一个心眼。我刚开始操作时直接从配置里删掉某个副本然后执行了pgsql.yml的移除任务结果发现清理不干净监控里还残留旧节点。正确做法是先执行bin/pigsty pg remove pg-test -i 目标IP或者手动调用移除任务把该节点上的 Patroni、HAProxy 配置、Prometheus 抓取目标一并删除再动配置文件。如果顺序反了后续想再重新加入这个节点很容易出现 Etcd 中历史 key 未清理导致的冲突。5. 监控不是附属品Grafana 看板、Prometheus 指标和告警如何一并用起来很多数据库部署方案把监控放在最后好像监控只是“锦上添花”。Pigsty 不这么认为它在安装数据库的同时就把监控体系完整搭建出来。你不需要额外安装任何采集器只需要知道怎么用好这些看板和告警。5.1 默认看板里最值得盯的三个页面Grafana 登录后你会看到大量预置看板。面对这么多仪表盘容易眼花缭乱。我个人的习惯是只盯三个集群总览、节点总览、慢查询分析。PGSQL Cluster看板是最重要的入口。它把一条线从远端压到本地生成很大的日志量分析时访问日志存储压力很高所以生产环境一般不会开启。另外一个常见问题是有人登录 Grafana 后看不到任何数据原因大多是 Prometheus 的抓取目标没有准备就绪。在 Prometheus 的 Target 页面检查一下把 down 状态的 exporter 找出来修复比在 Grafana 里到处点要有效得多。5.3 告警规则的隐藏技巧Pigsty 自带了一套告警规则默认通过 Alertmanager 发送。你可以在alertmanager.yml里配置接收端支持钉钉、企业微信、Slack 和邮件等。我最常用的是钉钉机器人因为配置简单只要填一个 Webhook 地址即可。重要的不是怎么接而是如何避免告警轰炸。Pigsty 默认的阈值有些偏敏感比如“集群抖动”类告警在滚动升级期间会大量出现。建议在接入生产环境前先仔细过一遍默认告警规则文件把与业务无关的规则禁用。否则凌晨 3 点被无关告警叫醒一次之后再也不想用这套系统了。我配置告警时做了三件事把 “PG 实例重启”类告警直接关闭因为计划内的升级和重启不需要打扰人把 “复制延迟”告警从阈值 10MB 调整为 200MB避免从库大量写入时瞬间超阈值给每个告警规则加上负责人标签方便转给对应值班人员。5.4 慢查询日志的快速接入日志组件 Loki 默认采集 PostgreSQL 日志包括错误日志、自动清理日志和慢查询日志。使用前需要确保 PostgreSQL 的log_min_duration_statement参数被设置成一个合理值。例如ALTER SYSTEM SET log_min_duration_statement 500; SELECT pg_reload_conf();这样执行超过 500 毫秒的 SQL 就会被记入日志并通过 Loki 进入 Grafana。然后你可以用 LogQL 查询{apppgsql} |~ duration |~ testdb把关键字替换成自己的业务库名就能快速定位慢 SQL 出现的时间段和文本。这一套流程配置完成之后你相当于同时拥有了数据库监控、主机监控和日志检索三件套不用再把时间浪费在跳板机上敲命令了。6. 经验沉淀我用 Pigsty 时踩过的坑以及我建议的初始化调优参数最后这部分是我最想分享的内容。工具文档写得再好也拍不到实际操作中的那些坑。我把自己在测试和生产准备阶段遇到过的问题以及最后固定下来的一套初始化参数整理在下面。6.1 安装阶段最常见的两个失败原因第一个失败原因是系统时钟不同步。Etcd 集群对时间偏差非常敏感如果三台机器的系统时间差得太大选主过程会异常甚至出现间歇性的健康检查失败。Pigsty 不会自动帮你校正系统时间所以部署前一定要确认各节点时间同步。我自己习惯在基础环境准备阶段就配置好chrony或ntpd并且指定与业务网络内的时间服务器同步。第二个失败原因是配置里填错了pg_version与整套软件源的对应关系。Pigsty 的软件源是按操作系统和数据库版本组织的比如你选择的 Ubuntu 系统却在软件源中只放了 CentOS 的包安装时当然会失败。这种问题不会在第一阶段报错而是到 PostgreSQL 初始化那一层才突然失败排查起来非常费劲。最好的办法是严格按官方模板生成配置只修改必要字段。6.2 参数调优从哪里开始Pigsty 默认的 PostgreSQL 参数相对保守毕竟要考虑通用性。但如果你清楚自己的服务器配置完全可以把参数调得更激进。下面是我对一台 16 核 CPU、64GB 内存、SSD 磁盘的常见机器的建议配置参数默认值参考建议初始值说明shared_buffers128MB16GBPostgreSQL 共享缓冲区建议不超过内存的 25%effective_cache_size4GB48GB给优化器一个“系统缓存有多大”的暗示work_mem4MB32MB排序和哈希操作可用内存注意并发连接数maintenance_work_mem64MB2GB维护操作如 CREATE INDEX、VACUUM 用max_connections100500结合实际连接数设定不宜过大checkpoint_timeout5min15min减少检查点频率降低 IO 抖动max_wal_size1GB16GB控制 WAL 文件轮换间接影响恢复时间这些参数可以通过 Pigsty 的配置项直接下发。在pgsql_cluster.vars下面设置vars: pg_params: shared_buffers: 16GB effective_cache_size: 48GB work_mem: 32MB maintenance_work_mem: 2GB max_connections: 500 checkpoint_timeout: 15min max_wal_size: 16GB修改后重新执行bin/pigsty pg reload或者直接重启实例就能让参数生效。需要注意max_connections是 Patroni 管理的关键参数修改时 Pigsty 会把它写入 PostgreSQL 配置。有一点必须反复强调不要照搬别人的参数一定要根据自己的业务负载做压测。我给的那个表只是起点不是终点。尤其是max_connections如果应用使用连接池500 完全够用如果几百个服务直连数据库那 500 可能远远不够。参数调优的本质是在内存、CPU、IO 三者之间找平衡而不是追求某个固定数值。6.3 备份恢复Pigsty 自带的脚本比想象中好用Pigsty 内置了pg-probackup相关的封装脚本可以按集群定期做全量或增量备份。它的思路是把备份集中放在某个目录并保留一定策略。我第一次用时没仔细看以为只支持手动执行后来发现它已经集成了 cron 调度。建议把备份目标路径指向一个独立的数据盘不要让备份文件和 WAL 日志争抢同一块磁盘。否则当业务写入高峰来临时备份进程会把 IO 占满反而影响正常数据库服务。再一个建议是定期做恢复演练而不是只在出故障时才发现备份坏了。我一般每两周从备份中恢复一个临时实例跑一下核心业务的查询确认备份数据可用。6.4 最后的提醒别把监控当摆设部署完 Pigsty 后我发现很多团队最喜欢做的是盯着 Grafana 的绿色状态喜悦一阵然后就再也不打开了。等真正出问题时看板里其实早就出现过征兆只是没人解读。例如复制延迟持续走高、事务 ID 回卷风险接近阈值、表格膨胀比例越来越大。Pigsty 把这些数据全部放在了默认看板中如果团队里暂时没有专职 DBA建议至少设置一个每日巡检的人批量查看集群总览和节点总览把异常截图发到值班群里。这种方法虽然原始但非常有效。我在一次模拟测试中就通过看板发现某个从库的复制延迟在每天早上都有一个规律性尖峰后来定位到是定时任务在同一时间大量写入造成的。如果没有 Pigsty 的复制延迟监控曲线这个问题很难肉眼发现。结尾也是一种经验先从小集群开始别急着上生产如果你正准备引入 Pigsty我的建议是先找三台虚拟机构建一个小型环境完整走过一遍安装、建库、故障切换、备份恢复的全流程。在这个过程中你一定要尝试把主库杀掉观察监控指标如何变化亲手把角色切回来。这个“亲手摧毁再重建”的循环做过几次之后你对高可用的理解会完全不一样。我个人在实际使用中的体会是Pigsty 的价值不在于某个单项功能有多惊艳而在于它把一堆数据库运维琐事收敛成了“配置 命令”的简单组合。它不可能替你解决所有业务问题但至少让你在凌晨三点被叫醒时能够更快地定位问题而不是对着十几个终端窗口发懵。希望这篇文章能让你少走一些我走过的弯路也欢迎你在实践后回来分享你自己的踩坑经历。