这是本节的多页打印视图。
点击此处打印 .
返回本页常规视图 .
概念 理解 Pigsty 的核心概念、架构设计与设计理念,掌握高可用、备份恢复、安全合规等关键能力。
Pigsty 是一个可移植、可扩展的开源 PostgreSQL 发行版,用于在本地环境中构建生产级数据库服务,方便进行声明式配置和自动化。它拥有庞大的生态系统,提供了一整套工具、脚本和最佳实践,让 PostgreSQL 真正达到企业级 RDS 的服务水准。
Pigsty 名字源自 P ostgreSQL I n G reat STY le,也可理解为 P ostgres, I nfras, G raphics, S ervice, T oolbox, it’s all Y ours —— 属于您的 PostgreSQL 图形化自建工具箱。您可以在 GitHub 上找到源代码,访问 官方文档 了解更多信息,或在 在线演示 中体验 Web 界面 。
为什么需要 Pigsty,它能做什么? PostgreSQL 是一个足够完美的数据库内核,但它需要更多工具与系统的配合才能成为一个足够好的数据库服务。在生产环境中,您需要管理数据库的方方面面:高可用、备份恢复、监控告警、访问控制、参数调优、扩展安装、连接池化、负载均衡……
如果这些复杂的运维工作都能自动化处理,是不是会更容易一些?这正是 Pigsty 诞生的原因。
Pigsty 为您提供:
开箱即用的 PostgreSQL 发行版
Pigsty 深度整合了 PostgreSQL 生态中的 440+ 扩展插件 ,为您提供开箱即用的分布式、时序、地理、空间、图、向量、搜索等多模态数据库能力。从内核到 RDS 发行版,在 EL/Debian/Ubuntu 下提供 13-18 版本的生产级数据库服务。
故障自愈的高可用架构
基于 Patroni、Etcd 和 HAProxy 打造的 高可用架构 ,让硬件故障自动切换,流量无缝衔接。主库故障恢复时间 RTO < 45s,数据恢复点 RPO ≈ 0。您可以在无需应用配合的情况下滚动维护升级整个集群。
完整的时间点恢复能力
基于 pgBackRest 与可选的 MinIO 集群,提供开箱即用的 PITR 时间点恢复 能力。让您拥有快速回到过去任意时间点的能力,为软件缺陷与人为删库兜底。
灵活的服务接入与流量管理
通过 HAProxy、Pgbouncer、VIP 提供灵活的 服务接入 模式,实现读写分离、连接池化、自动路由。交付稳定可靠、自动路由、事务池化的高性能数据库服务。
惊艳的可观测性
基于 Prometheus 与 Grafana 的现代可观测性技术栈,提供无与伦比的 监控最佳实践 。超过三千类监控指标描述系统的方方面面,从全局大盘到单个对象的增删改查都能一览无余。
声明式的配置管理
遵循 基础设施即代码 的理念,使用声明式配置描述整个环境。您只需告诉 Pigsty “想要什么样的数据库集群”,无需操心具体如何实现,系统会自动调整到期望状态。
模块化的架构设计
采用模块化 架构 设计,可自由组合以适应不同场景。除了核心的 PostgreSQL 模块外,还提供 Redis、MinIO、Etcd、FerretDB 等可选模块,以及对多种 PG 兼容内核的支持。
扎实的安全最佳实践
采用业界领先的安全最佳实践:自签名 CA 签发证书加密通信,AES 加密备份,scram-sha-256 加密密码,开箱即用的 ACL 模型,遵循最小权限原则的 HBA 规则集,确保数据安全。
简单易用的部署方案
所有依赖被预先打包,可在无互联网访问的环境中一键安装。本地沙箱环境可运行在 1核2G 的微型虚拟机中,提供与生产环境完全一致的功能模拟。提供基于 Vagrant 的本地沙箱与基于 Terraform 的云端部署方案。
Pigsty 不是什么 Pigsty 并不是传统的、包罗万象的 PaaS(平台即服务)系统。
Pigsty 不提供基础硬件资源 。它运行在您提供的节点之上,无论是裸金属、虚拟机还是云主机,但它本身不创建或管理这些资源(尽管提供了 Terraform 模板来简化云资源的准备)。
Pigsty 不是容器编排系统 。它直接运行在操作系统之上,不需要 Kubernetes 或 Docker 作为基础设施。当然,它可以与这些系统共存,并提供 Docker 模块来运行无状态应用。
Pigsty 不是通用的数据库管理工具 。它专注于 PostgreSQL 及其生态,虽然也支持 Redis、Etcd、MinIO 等周边组件,但核心始终是围绕 PostgreSQL 构建的。
Pigsty 不会锁定您 。它基于开源组件构建,不修改 PostgreSQL 内核,不引入专有协议。您随时可以脱离 Pigsty 继续使用管理好的 PostgreSQL 集群。
Pigsty 不限制您应该或不应该如何构建数据库服务。例如:
Pigsty 为您提供了良好的参数默认值和配置模板,但您可以覆盖任何参数。 Pigsty 提供了声明式 API,但您依然可以使用底层工具(Ansible、Patroni、pgBackRest 等)进行手动管理。 Pigsty 可以管理完整的生命周期,也可以只使用其中的监控系统来观测现有的数据库实例或 RDS。 Pigsty 提供的抽象层次不同于硬件层面,它工作在数据库服务层面,聚焦于如何让 PostgreSQL 以最佳状态交付价值,而不是重新发明轮子。
PostgreSQL 部署方式的演进 要理解 Pigsty 的价值,让我们回顾一下 PostgreSQL 部署方式的演进历程。
手工部署时代 在传统的部署方式中,DBA 需要手工安装配置 PostgreSQL,手工设置复制,手工配置监控,手工处理故障。这种方式的问题显而易见:
效率低下 :每个实例都需要重复大量手工操作,容易出错。缺乏标准化 :不同 DBA 配置的数据库可能千差万别,难以维护。可靠性差 :故障处理依赖人工介入,恢复时间长,容易出现人为失误。观测性弱 :缺乏统一的监控体系,问题发现和定位困难。托管数据库时代 为了解决这些问题,云厂商提供了托管数据库服务(RDS)。云 RDS 确实解决了部分运维问题,但也带来了新的挑战:
成本高昂 :托管服务通常收取硬件成本数倍到十几倍的"服务费"。供应商锁定 :迁移困难,受制于特定云平台。功能受限 :无法使用某些高级特性,扩展插件受限,参数调整受限。数据主权 :数据存储在云端,自主可控性降低。本地 RDS 时代 Pigsty 代表了第三种方式:在本地环境中构建媲美甚至超越云 RDS 的数据库服务。
Pigsty 结合了前两种方式的优点:
自动化程度高 :一键部署,自动配置,故障自愈,像云 RDS 一样便捷。完全自主可控 :运行在您自己的基础设施上,数据完全掌握在自己手中。成本极低 :以接近纯硬件的成本运行企业级数据库服务。功能完整 :无限制地使用 PostgreSQL 的全部能力和生态扩展。开放架构 :基于开源组件,无供应商锁定,可随时迁移。这种方式特别适合:
私有云与混合云 :需要在本地环境中运行数据库的企业。成本敏感型用户 :希望降低数据库 TCO 的组织。高安全要求场景 :需要完全自主可控的关键数据。PostgreSQL 深度用户 :需要使用高级特性和丰富扩展的场景。开发与测试 :需要在本地快速搭建与生产环境一致的数据库。接下来 现在您已经了解了 Pigsty 的基本概念,可以:
查看 系统架构 了解 Pigsty 的模块化设计 了解 集群模型 理解 Pigsty 如何组织数据库集群 学习 高可用 机制掌握故障自愈的原理 探索 时间点恢复 了解如何应对数据误删 研究 服务接入 理解如何稳定交付数据库服务 体验 基础设施即代码 感受声明式配置的魅力 或直接开始 快速上手 在几分钟内部署您的第一个 Pigsty 环境 1 - 积木式架构 Pigsty 的模块化架构介绍 —— 声明式组合,按需定制,自由部署。
Pigsty 使用 模块化架构 与 声明式接口 ,您可以像 搭积木一样自由按需组合模块 。
模块 Pigsty 采用模块化设计,有六个主要的默认模块:PGSQL 、INFRA 、NODE 、ETCD 、REDIS 和 MINIO 。
PGSQL :由 Patroni、Pgbouncer、HAproxy、PgBackrest 等驱动的自治高可用 Postgres 集群。INFRA :本地软件仓库、Nginx、Grafana、Victoria、AlertManager、Blackbox Exporter 可观测性全家桶。NODE :调整节点到所需状态、名称、时区、NTP、ssh、sudo、haproxy、docker、vector、keepalivedETCD :分布式键值存储,用作高可用 Postgres 集群的 DCS:共识选主/配置管理/服务发现。REDIS :Redis 服务器,支持独立主从、哨兵、集群模式,并带有完整的监控支持。MINIO :与 S3 兼容的简单对象存储服务器,可作为 PG数据库备份的可选目的地。你可以声明式地自由组合它们。如果你想要主机监控,在基础设施节点上安装 INFRA 模块,并在纳管节点上安装 NODE 模块就足够了。
ETCD 和 PGSQL 模块用于搭建高可用 PG 集群,将模块安装在多个节点上,可以自动形成一个高可用的数据库集群。
您可以复用 Pigsty 基础架构并开发您自己的模块,REDIS 和 MINIO 可以作为一个样例。后续还会有更多的模块加入,例如对 Mongo 与 MySQL 的初步支持已经提上了日程。
请注意,所有模块都强依赖 NODE 模块:在 Pigsty 中节点必须先安装 NODE 模块,被 Pigsty 纳管后方可部署其他模块。
当节点(默认)使用本地软件源进行安装时,NODE 模块对 INFRA 模块有弱依赖。因此安装 INFRA 模块的管理节点/基础设施节点会在 deploy.yml 剧本中完成 Bootstrap 过程,解决循环依赖。
单机安装 默认情况下,Pigsty 将在单个 节点 (物理机/虚拟机) 上安装。deploy.yml 剧本将在当前 节点上安装 INFRA 、ETCD 、PGSQL 和可选的 MINIO 模块,
这将为你提供一个功能完备的可观测性技术栈全家桶 (Prometheus、Grafana、Loki、AlertManager、PushGateway、BlackboxExporter 等) ,以及一个内置的 PostgreSQL 单机实例作为 CMDB,也可以开箱即用。 (集群名 pg-meta,库名为 meta)。
这个节点现在会有完整的自我监控系统、可视化工具集,以及一个自动配置有 PITR 的 Postgres 数据库(HA不可用,因为你只有一个节点)。你可以使用此节点作为开发箱、测试、运行演示以及进行数据可视化和分析。或者,还可以把这个节点当作管理节点,部署纳管更多的节点!
监控 安装的 单机元节点 可用作管理节点 和监控中心 ,以将更多节点和数据库服务器置于其监视和控制之下。
Pigsty 的监控系统可以独立使用,如果你想安装 Prometheus / Grafana 可观测性全家桶,Pigsty 为你提供了最佳实践!
它为 主机节点 和 PostgreSQL数据库 提供了丰富的仪表盘。
无论这些节点或 PostgreSQL 服务器是否由 Pigsty 管理,只需简单的配置,你就可以立即拥有生产级的监控和告警系统,并将现有的主机与PostgreSQL纳入监管。
高可用PG集群 Pigsty 帮助您在任何地方 拥有 您自己的生产级高可用 PostgreSQL RDS 服务。
要创建这样一个高可用 PostgreSQL 集群/RDS服务,你只需用简短的配置来描述它,并运行剧本来创建即可:
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 }
vars : { pg_cluster : pg-test }
$ bin/pgsql-add pg-test # 初始化集群 'pg-test'
不到10分钟,您将拥有一个服务接入,监控,备份PITR,高可用配置齐全的 PostgreSQL 数据库集群。
硬件故障由 patroni、etcd 和 haproxy 提供的自愈高可用架构来兜底,在主库故障的情况下,默认会在 45 秒内执行自动故障转移(Failover)。
客户端无需修改配置重启应用:Haproxy 利用 patroni 健康检查进行流量分发,读写请求会自动分发到新的集群主库中,并避免脑裂的问题。
这一过程十分丝滑,例如在从库故障,或主动切换(switchover)的情况下,客户端只有一瞬间的当前查询闪断,
软件故障、人为错误和 数据中心级灾难由 pgbackrest 和可选的 MinIO 集群来兜底。这为您提供了本地/云端的 PITR 能力,并在数据中心失效的情况下提供了跨地理区域复制,与异地容灾功能。
1.1 - 节点 节点(node)是对硬件资源/操作系统的抽象,可以是物理机,裸金属、虚拟机、或者容器与 pods。
节点(node) 是对硬件资源/操作系统的抽象,可以是物理机,裸金属、虚拟机、或者容器与 pods。
只要装着 Linux 操作系统 (以及 systemd 守护进程),能使用 CPU/内存/磁盘/网络 等标准资源,即可视作节点。
节点上可以安装 模块 ,Pigsty 中存在几种不同类型节点,主要区别就在于安装了不同的模块。
在 单机部署 Pigsty 时,多者合而为一,当前节点将同时作为普通节点,管理节点、基础设施节点、ETCD 节点,以及数据库节点。
普通节点 使用 Pigsty 管理节点,可在其上安装模块。node.yml 剧本将调整节点至所需状态。
普通节点上可能会运行以下服务:
组件 端口 描述 状态 node_exporter9100节点监控指标导出器 ✅ 默认启用 haproxy9101HAProxy 负载均衡器(管理端口) ✅ 默认启用 vector9598日志收集代理 ✅ 默认启用 docker9323启用容器支持 ⚠️ 按需启用 keepalivedn/a管理节点集群 L2 VIP ⚠️ 按需启用 keepalived_exporter9650监控 Keepalived 状态 ⚠️ 按需启用
这里,node_exporter 会向监控系统暴露主机上的各类监控指标,vector 会向日志收集系统发送日志,haproxy 则提供负载均衡功能,对外暴露服务。
这三项服务默认开启。而 Docker ,keepalived 及 keepalived_exporter 这三项服务作为可选项,可按需启用。
ADMIN节点 一套 Pigsty 部署中有且只有一个 管理节点 ,管理节点是执行 Ansible 剧本,发起控制/部署命令的节点。
该节点拥有对所有其他节点的 ssh/sudo 访问权限。管理节点的安全至关重要,请确保它的访问受到严格控制。
在 单机安装 的 配置过程 中,当前安装节点就是管理节点。
但也有其他的可能,例如,如果你的笔记本可以 ssh 访问所有被管理节点,并且安装了 Ansible,那么在这种情况下,
您的笔记本电脑就可以作为一个管理节点 —— 尽管这对于生产环境来说不太合适。
例如,您使用自己的笔记本电脑,管理一台云端上部署了 Pigsty 的虚拟机,这时候,您的笔记本电脑就是管理节点。
在严肃的生产环境中,管理节点通常是 1-2 台 DBA 专用的 管控机 。在资源受限的环境中,则通常会复用 INFRA节点 作为管理节点。
因为所有的 INFRA 节点上都默认安装了 Ansible,可以作为额外的备用的管理节点。
INFRA节点 一套 Pigsty 部署可能有 1 个或多个 INFRA 节点,大型生产环境可能有 2-3 个。
配置清单中的 infra 分组指定哪些节点是 INFRA节点,这些节点上会部署 INFRA 模块,包含下列组件:
组件 端口 描述 nginx80/443Web 图形界面,本地软件仓库 grafana3000可视化平台 victoriaMetrics8428时序数据库(收存监控指标) victoriaLogs9428日志收集服务器 victoriaTraces10428链路追踪收集服务器 vmalert8880告警与衍生指标计算规则 alertmanager9059告警聚合分发/屏蔽管理 blackbox_exporter9115黑盒探测,ping 节点 / vip dnsmasq53内部 DNS 域名解析 chronyd123NTP 时间服务器 ansible-执行剧本,发起管理
其中,Nginx 作为当前模块的入口,提供 Web 图形界面和本地软件仓库服务。
如果你部署多个 INFRA 节点,每个 Infra 节点上的服务是相互独立的。
但你确实可以从任意一个 Infra 节点上的 Grafana 访问所有的监控数据源。
请注意,INFRA 模块受到 Grafana 传染,使用 AGPLv3 许可证开源。
但作为例外,如果你只使用 Nginx / Victoria 全家桶等组件,而不使用 Grafana,实际上使用的是 Apache-2.0 许可证。
ETCD节点 ETCD 模块为 PostgreSQL 高可用提供分布式共识服务(DCS)。
配置清单 中的 etcd 分组指定哪些节点是 ETCD 节点,ETCD 节点上运行着 etcd 服务器,监听以下两个端口:
组件 端口 描述 etcd2379ETCD 分布式键值存储(客户端端口) etcd2380ETCD 集群 Peer 通信端口
MINIO节点 MINIOn 模块为 PostgreSQL 提供了一个可选的 备份存储仓库 。
配置清单中的 minio 分组指定哪些节点是 MinIO 节点,这些节点上会运行 MinIO 服务器,监听以下端口:
组件 端口 描述 minio9000MinIO S3 API 服务端口 minio9001MinIO 管理控制台端口
PGSQL节点 安装了 PGSQL 模块的节点被称为 PGSQL 节点。节点与 PostgreSQL 实例为 1:1 部署,也就是每个节点上只运行一个 PG 实例。
PGSQL 节点可从相应 PostgreSQL 实例借用 身份 —— 由 node_id_from_pg 控制,默认为 true,即节点名会被设置为 PG 实例名。
PGSQL节点在 普通节点 的基础上,还会额外运行以下组件:
组件 端口 描述 状态 postgres5432PostgreSQL 数据库服务器 ✅ 默认启用 pgbouncer6432Pgbouncer 连接池 ✅ 默认启用 patroni8008Patroni 高可用管理组件 ✅ 默认启用 pg_exporter9630Postgres 监控指标导出器 ✅ 默认启用 pgbouncer_exporter9631PGBouncer 监控指标导出器 ✅ 默认启用 pgbackrest_exporter9854Pgbackrest 监控指标导出器 ✅ 默认启用 vip-managern/a将 L2 VIP 绑定在集群主库节点上 ⚠️ 按需启用 {{ pg_cluster }}-primary5433通过 haproxy 对外暴露数据库服务:主连接池:读/写服务 ✅ 默认启用 {{ pg_cluster }}-replica5434通过 haproxy 对外暴露数据库服务:副本连接池:只读服务 ✅ 默认启用 {{ pg_cluster }}-default5436通过 haproxy 对外暴露数据库服务:主直连服务 ✅ 默认启用 {{ pg_cluster }}-offline5438通过 haproxy 对外暴露数据库服务:离线直连:离线读服务 ✅ 默认启用 {{ pg_cluster }}-<service>543x通过 haproxy 对外暴露数据库服务:PostgreSQL 定制服务 ⚠️按需定制
其中,vip-manager 只有当用户配置了 PG VIP 时才会启用。
在 pg_services 中可以定义更多的 自定义服务 ,这些服务会被 haproxy 对外暴露,并使用更多的服务端口。
1.2 - INFRA 架构 Pigsty 中基础设施模块的架构,组件与功能详解。
运行生产级别高可用 PostgreSQL 集群,通常需要一套完善的基础设施服务(底座)来支撑,例如监控告警、日志收集、时间同步、DNS 解析,本地软件仓库等。
Pigsty 提供了 INFRA 模块 来解决这个问题 —— 这是一个 可选模块 ,但我们强烈推荐启用它。
概览 下图是 单机部署 时的架构示意图,图中右半部分即为 INFRA 模块 所包含的组件,其中包括:
Nginx Nginx 是 Pigsty 所有 WebUI 类服务的访问入口,默认使用 80 / 443 端口对外提供 HTTP / HTTPS 服务。在线演示
带有 WebUI 的基础设施组件可以通过 Nginx 统一对外暴露服务,例如 Grafana 、VictoriaMetrics (VMUI)、AlertManager ,
以及 HAProxy 控制台,此外,本地软件仓库 等静态文件资源也通过 Nginx 对内外提供服务。
Nginx 会根据 infra_portal 中的定义,配置本地 Web 服务器或反向代理服务器。
infra_portal :
home : { domain : i.pigsty }
默认情况下将对外暴露 Pigsty 的管理首页:i.pigsty,上面不同的端点挂载代理了不同的组件:
Pigsty 允许对 Nginx 进行丰富的定制,将其作为本地文件服务器,或者反向代理服务器,配置自签名或者真正的 HTTPS 证书。
更多信息,请参阅:教程:Nginx:向外代理暴露Web服务 与 教程:Certbot:申请与更新HTTPS证书
Repo Pigsty 会在安装时,默认在 Infra 节点上创建一个 本地软件仓库 ,以加速后续软件安装。在线演示
该软件仓库默认位于 /www/pigsty 目录,
由 Nginx 对外提供服务,挂载在 /pigsty 路径上:
Pigsty 支持 离线安装 ,实质上是将做好的本地软件仓库提前复制到目标环境中。
当 Pigsty 执行生产部署,需要创建本地软件仓库时,如果发现本地已经存在 /www/pigsty/repo_complete 标记文件,则会跳过从上游下载软件包的步骤,直接使用已有的软件包,避免联网下载。
更多信息,请参阅:配置:INFRA - REPO
Grafana Grafana 是 Pigsty 监控系统的核心组件,用于可视化展示监控指标、日志与各种信息。在线演示
Grafana 默认监听 3000 端口,挂载于 Nginx /ui 路径点上代理访问:
Pigsty 预置了基于 VictoriaMetrics / Logs / Traces 的大量监控面板,并通过 URL 跳转实现一键下钻上卷,帮助快速定位故障。
Grafana 亦可作为低代码可视化平台使用,因此默认安装 ECharts 、victoriametrics-datasource、victorialogs-datasource 等插件,
同时将 Vector / Victoria 数据源统一注册为 vmetrics-*、vlogs-*、vtraces-*,方便扩展自定义仪表板。
更多信息请参阅:配置:INFRA - GRAFANA 。
VictoriaMetrics VictoriaMetrics 是 Pigsty 的时序数据库,负责拉取并存储所有监控指标。在线演示
默认监听 8428 端口,挂载于 Nginx /vmetrics 路径上,亦可通过 p.pigsty 域名直接访问:
VictoriaMetrics 完全兼容 Prometheus API,支持 PromQL 查询、远程读写协议以及 Alertmanager API。
内置的 VMUI 提供即席查询界面,可直接探索指标数据,也可作为 Grafana 的数据源使用。
更多信息请参阅:配置:INFRA - VMETRICS
VictoriaLogs VictoriaLogs 是 Pigsty 的日志平台,集中存储来自所有节点的结构化日志。在线演示
默认监听 9428 端口,挂载于 Nginx /vlogs 路径上:
所有纳管节点默认运行 Vector Agent,负责收集系统日志、PostgreSQL 日志、Patroni 日志、Pgbouncer 日志等,结构化处理后推送至 VictoriaLogs 。
内置 Web UI 支持日志检索与过滤,也可配合 Grafana 的 victorialogs-datasource 插件进行可视化分析。
更多信息请参阅:配置:INFRA - VLOGS
VictoriaTraces VictoriaTraces 用于收集链路追踪数据与慢 SQL 记录。在线演示
默认监听 10428 端口,挂载于 Nginx /vtraces 路径上:
VictoriaTraces 提供 Jaeger 兼容接口,可用于分析服务调用链路与数据库慢查询。
结合 Grafana 面板,能够快速定位性能瓶颈,追溯问题根因。
更多信息请参阅:配置:INFRA - VTRACES
VMAlert VMAlert 是告警规则计算引擎,负责评估告警规则并将触发的事件推送至 Alertmanager 。在线演示
默认监听 8880 端口,挂载于 Nginx /vmalert 路径上:
VMAlert 从 VictoriaMetrics 读取指标数据,周期性执行告警规则评估。
Pigsty 预置了 PGSQL、NODE、REDIS 等模块的告警规则,覆盖常见故障场景,开箱即用。
更多信息请参阅:配置:INFRA - VMALERT
AlertManager AlertManager 负责告警事件的聚合、去重、分组与分发。在线演示
默认监听 9059 端口,挂载于 Nginx /alertmgr 路径上,亦可通过 a.pigsty 域名直接访问:
AlertManager 支持多种通知渠道:邮件、Webhook、Slack、PagerDuty、企业微信等。
通过配置告警路由规则,可实现按严重程度、模块类型进行差异化分发,支持静默、抑制等高级功能。
更多信息请参阅:配置:INFRA - AlertManager
BlackboxExporter Blackbox Exporter 用于主动探测目标的可达性,实现黑盒监控。
默认监听 9115 端口,挂载于 Nginx /blackbox 路径上:
支持 ICMP Ping、TCP 端口、HTTP/HTTPS 端点等多种探测方式。
可用于监控 VIP 可达性、服务端口存活、外部依赖健康状态等场景,是判断故障影响范围的重要手段。
更多信息请参阅:配置:INFRA - BLACKBOX
Ansible Ansible 是 Pigsty 的核心编排工具,所有部署、配置、管理操作均通过 Ansible Playbook 完成。
Pigsty 在安装时会自动在管理节点(Infra 节点)上安装 Ansible 。
它采用声明式配置风格与幂等剧本设计:同一剧本可重复执行,系统会自动收敛至期望状态,无需担心副作用。
Ansible 的核心优势:
无 Agent :通过 SSH 远程执行,无需在目标节点安装额外软件。声明式 :描述期望状态,而非执行步骤,配置即文档。幂等性 :多次执行结果一致,支持部分失败后重试。更多信息请参阅:剧本:Pigsty Playbook
DNSMASQ DNSMASQ 在 INFRA节点 上提供环境内的 DNS 解析服务,将域名解析到对应 IP 地址。
DNSMASQ 默认监听 53 端口(UDP/TCP),为环境内所有节点提供 DNS 解析服务,解析记录位于 的 /infra/hosts 目录中。
其他模块在部署时会自动将域名注册到 INFRA 节点的 DNSMASQ 服务中,您可以按需使用。
DNS 是完全可选的模块,Pigsty 本身不依赖它即可正常运行 。
客户端节点可将 INFRA 节点配置为 DNS 服务器,即可通过域名访问各服务,无需记忆 IP 地址。
更多信息请参阅:配置:INFRA - DNS 与 教程:DNS:配置域名解析
Chronyd Chronyd 提供 NTP 时间同步服务,确保环境内所有节点时钟一致。默认监听 123 端口(UDP),作为环境内的时间源。
时间同步对分布式系统至关重要:日志排查需要时间戳对齐,证书校验依赖时钟准确,PostgreSQL 流复制也对时钟偏移敏感。
在隔离网络环境中,INFRA 节点可作为内部 NTP 服务器,其他节点同步至此。
在 Pigsty 中,默认所有节点都会启动 chonyd 服务用于时间同步。默认使用 pool.ntp.org 公共 NTP 服务器作为上游时间源。
Chronyd 本质上归属 Node 模块 管理,但在网络隔离的环境中,你使用 admin_ip 指向 INFRA 节点上的 Chronyd 服务作为内部时间源。
此时 INFRA节点 上的 Chronyd 服务将充当内部时间同步基础设施的角色。
更多信息请参阅:配置:NODE - TIME
INFRA节点与普通节点 在 Pigsty 中,节点与基础设施的关系是 弱循环依赖 :node_monitor → infra → node
NODE模块 本身不依赖 INFRA模块 ,但节点模块中的监控功能(node_monitor)需要依赖基础设施模块提供的监控平台与服务。
因此,在 infra.yml 和 deploy 剧本中,
采用了一种 “交织部署” 的技术:
如果您不追求 “一次性” 部署所有节点,也可以采用 分阶段部署 的方式,先初始化 INFRA 节点,然后再初始化其他普通节点即可。
节点与基础设施是如何耦合的? 普通节点会通过 admin_ip 参数来引用某个 INFRA节点 作为它们的基础设施提供者。
例如,当你配置了全局的 admin_ip = 10.10.10.10,那么通常意味着所有节点都会使用这个 IP 上的基础设施服务。
这样的设计允许你快速,批量的切换节点的基础设施提供者 —— 以下是 可能 引用 ${admin_ip} 的配置参数列表:
例如,当节点安装软件的时候,local 仓库指向的就是 admin_ip:80/pigsty 上的 Nginx 本地软件仓库。DNS 服务器指向的也是 admin_ip:53 上的 DNSMASQ 。
但这并不是强制要求的,例如,节点完全可以忽略并不使用 local 仓库,直接从互联网上游源安装(大部分单机配置模板);DNS 服务器也完全可以不配置与不使用,Pigsty 本身并无对 DNS 服务器的依赖。
INFRA节点与ADMIN节点 通常发起管理的 ADMIN节点 会与基础设施节点(INFRA节点 )重合。
在 单机部署 就是这样的。在多节点部署中,如果有多个 INFRA 节点,管理节点通常是 infra 分组中的第一个,其余作为备用。
不过,也有例外存在。您可能会出于各种原因,将两者分离开来:
例如在 大规模生产环境部署 中,一种经典模式是使用 1-2 台归属于 DBA 组的专用管理主机(微型虚拟机即可),
作为整个环境的控制中枢,并使用 2-3 台高配置的物理机(或者更多!),作为整个环境的监控基础设施。这时候管理节点就与基础设施节点分离开来了。
这时候,你在配置文件中填入的 admin_ip 应该指向某个 INFRA 节点的 IP 地址,而不是当前 ADMIN 节点的 IP 地址。
这是因为历史遗留原因:Pigsty 设计之初,ADMIN 节点 与 INFRA 节点 是强绑定的概念,后来才逐渐演化出分离的能力,因此参数名称未做修改。
另一种常见的情况是 本地管理云节点 ,例如,您可以在自己的笔记本上安装 Ansible,然后填入你的云节点作为 “被管理对象”。
在这种情况下,您的笔记本充当 ADMIN 节点,而云服务器充当 INFRA 节点。
all :
children :
infra : { hosts : { 10.10.10.10 : { infra_seq: 1 , ansible_host : your_ssh_alias } } } # <--- 利用 ansible_host 指向云节点(填入 ssh 别名)
etcd : { hosts : { 10.10.10.10 : { etcd_seq: 1 } }, vars : { etcd_cluster : etcd } } # ssh 连接会使用 ssh your_ssh_alias
pg-meta : { hosts : { 10.10.10.10 : { pg_seq: 1, pg_role: primary } }, vars : { pg_cluster : pg-meta } }
vars :
version : v4.0.0
admin_ip : 10.10.10.10
region : default
多个 INFRA 节点 默认情况下,Pigsty 只需要一个 INFRA 节点即可满足大部分需求。INFRA 模块挂了,也不会影响其他节点上的数据库服务。
但是,在一些对监控与告警要求极高的生产环境中,您可能希望部署多个 INFRA 节点,来提升基础设施的可用性。
一种常见的部署是使用两个 Infra 节点,提供一份冗余副本,并互相监控对方…
或者使用更多,部署分布式的 Victoria 集群实现无限水平扩展。
每个 Infra 节点都是 独立 的,Nginx 指向的都是本机上的服务。
VictoriaMetrics 也是独立抓取环境中所有服务的监控指标,
日志会默认推送到所有 VictoriaLogs 日志采集端点上。
唯一的例外是 Grafana,每一个 Grafana 中都会注册所有的 VictoriaMetrics / Logs / Traces / PostgreSQL 实例作为数据源。
因此每一个 Grafana 实例都能看到完整的监控数据。
如果您对 Grafana 进行修改,例如添加新的仪表板,或者修改数据源配置,这些变更只会影响当前节点上的 Grafana 实例。
如果您希望所有节点上的 Grafana 保持一致,可以使用一个 PostgreSQL 数据库作为共享存储,详情参考 教程:配置 Grafana 高可用 。
1.3 - PGSQL 架构 PostgreSQL 模块的组件交互与数据流。
PGSQL 模块在生产环境中以 集群 的形式组织,这些 集群 是由一组通过 主-备 关联的数据库 实例 组成的 逻辑实体 。
概览 PGSQL 模块 包含下列组件,协同提供生产级 PostgreSQL 高可用集群服务:
其中 vip-manager 为按需启用的组件。此外,PGSQL 还会使用到其他模块中的组件:
如果用类比来形容,PostgreSQL 数据库内核就是 CPU,而整个 PGSQL 模块将其封装为一台完整的计算机。
Patroni 与 Etcd 组成 高可用子系统 ,pgBackRest 与 MinIO 组成 备份恢复子系统 。
HAProxy 与 Pgbouncer 、vip-manager 组成 接入子系统 。
各种 Exporter 与 Vector 构成 可观测性子系统 ;
最后还可以替换不同的 内核 CPU 与 扩展卡 。
组件交互
高可用子系统 高可用 子系统由 Patroni 与 etcd 组成,负责 PostgreSQL 集群的故障检测、自动切换与配置管理。
工作原理 :Patroni 在每个节点上运行,托管本地 PostgreSQL 进程,并将集群状态(领导者、成员、配置)写入 etcd 。
当主库故障时,Patroni 通过 etcd 协调选举,选出最健康的从库提升为新主库,整个过程自动完成,RTO 通常在 45 秒内。
关键交互 :
更多信息请参阅:高可用 与 配置:PGSQL - PG_BOOTSTRAP
服务接入子系统 接入子系统由 HAProxy 、Pgbouncer 与 vip-manager 组成,负责对外暴露服务、路由流量与连接池化。
有多种不同的接入方法,一种典型的流量路径是:客户端 → DNS/VIP → HAProxy (543x) → Pgbouncer (6432) → PostgreSQL (5432)
服务端口 :
5433 primary:读写服务,路由至主库 Pgbouncer 5434 replica:只读服务,路由至从库 Pgbouncer 5436 default:默认服务,直连主库(绕过连接池)5438 offline:离线服务,直连离线从库(ETL/分析)关键特性 :
更多信息请参阅:服务接入 与 配置:PGSQL - PG_ACCESS
备份恢复子系统 备份恢复子系统由 pgBackRest 组成(可选配 MinIO 作为远程仓库),负责数据备份与时间点恢复(PITR )。
备份类型 :
全量备份 :完整的数据库副本增量/差异备份 :仅备份变更的数据块WAL 归档 :持续归档事务日志,支持任意时间点恢复存储后端 :
local(默认):本地磁盘,备份存储在 pg_fs_bkup 挂载点minio:S3 兼容对象存储,支持集中化备份管理与异地容灾关键交互 :
更多信息请参阅:PITR 、备份恢复 与 配置:PGSQL - PG_BACKUP
可观测性子系统 可观测性子系统由三个 Exporter 与 Vector 组成,负责指标采集与日志收集。
数据流向 :
指标 :Exporter → VictoriaMetrics(INFRA)→ Grafana 仪表盘日志 :Vector → VictoriaLogs(INFRA)→ Grafana 日志查询pg_exporter / pgbouncer_exporter 通过本地 Unix Socket 连接目标服务,与 HA 拓扑解耦。在 精简安装 模式下,可禁用这些组件。
更多信息请参阅:配置:PGSQL - PG_MONITOR
PostgreSQL PostgreSQL 是 PGSQL 模块的核心,默认监听 5432 端口提供关系型数据库服务,采用与 节点 1:1 对应的部署模型。
Pigsty 目前支持 PostgreSQL 14 - 18(生命周期内的大版本),使用 PGDG 官方仓库 提供的二进制包安装。
Pigsty 还允许您使用其他的 PG 内核分支 替换默认的 PostgreSQL 内核,
并在 PG 内核上加装多达 440 个扩展插件。
PostgreSQL 进程默认由 高可用 Agent —— Patroni 托管拉起。
当一个集群中只有一个节点时,该实例即为主库;当集群包含多个节点时,其余实例会自动作为从库加入:
通过物理复制,实时从主库同步数据变更。从库可以承载只读请求,并在主库故障时自动接管。
您可以直接访问 PostgreSQL,或者通过 HAProxy 与 Pgbouncer 连接池来访问。
更多信息请参阅:配置:PGSQL - PG_BOOTSTRAP
Patroni Patroni 是 PostgreSQL 高可用控制组件,默认监听 8008 端口。
Patroni 接管 PostgreSQL 的启动、停止、配置与健康状态,将领导者、成员信息写入 etcd 。
它负责自动故障转移、保持复制因子、协调参数变更,并提供 REST API 供 HAProxy 、监控与管理员查询。
HAProxy 通过 Patroni 健康检查端点判断实例角色,将流量路由至正确的主库或从库。
vip-manager 监视 etcd 中的领导者键,在主库切换时自动漂移 VIP。
更多信息请参阅:配置:PGSQL - PG_BOOTSTRAP
Pgbouncer Pgbouncer 是轻量级连接池中间件,默认监听 6432 端口,与 PostgreSQL 数据库与节点保持 1:1 部署。
Pgbouncer 以无状态方式运行在每个实例上,通过本地 Unix Socket 连接 PostgreSQL ,默认通过 Transaction Pooling 的方式
对 PG 连接进行池化管理,能够吸收大量客户端的瞬时连接请求,稳定数据库会话,降低锁征用,显著提升高并发状态下的性能表现。
Pigsty 默认让生产流量(读写服务 5433 / 只读服务 5434)经由 Pgbouncer ,
仅默认服务(5436)与离线服务(5438)绕过连接池直连 PostgreSQL 。
连接池模式由 pgbouncer_poolmode 控制,默认为 transaction(事务级复用),可通过 pgbouncer_enabled 关闭连接池。
更多信息请参阅:配置:PGSQL - PG_ACCESS
pgBackRest pgBackRest 是专业的 PostgreSQL 备份恢复工具,也是 PG 生态的最强备份工具之一,支持全量/增量/差异备份与 WAL 归档。
Pigsty 使用 pgBackRest 实现 PostgreSQL 的 PITR 能力,
您可以在备份保留的时间窗口内,将集群回滚到任意时间点。
pgBackRest 与 PostgreSQL 配合,在主库上创建备份仓库,执行备份与归档任务。
默认使用本地备份仓库(pgbackrest_method = local),也可配置为 MinIO 等对象存储,实现集中化备份管理。
初始化完成后可通过 pgbackrest_init_backup 自动发起首次全量备份。
恢复过程与 Patroni 集成,支持将副本引导为新的主库或备库。
更多信息请参阅:备份恢复 与 配置:PGSQL - PG_BACKUP
HAProxy HAProxy 是服务入口与负载均衡器,对外暴露多个数据库服务端口。
端口 服务名 目标 说明 9101管理接口 - HAProxy 统计与管理页面 5433primary 主库 Pgbouncer 读写服务,路由至主库连接池 5434replica 从库 Pgbouncer 只读服务,路由至从库连接池 5436default 主库 Postgres 默认服务,直连主库(绕过连接池) 5438offline 离线库 Postgres 离线服务,直连离线从库(ETL/分析)
HAProxy 通过 Patroni REST API 提供的健康检查信息判断实例角色,将流量路由至对应的主库或从库。
服务定义由 pg_default_services 与 pg_services 组合而成。
可通过 pg_service_provider 指定专用的 HAProxy 节点组承载更高流量,
默认使用本地节点上的 HAProxy 对外发布服务。
更多信息请参阅:服务接入 与 配置:PGSQL - PG_ACCESS
vip-manager vip-manager 负责将 L2 VIP 绑定到当前主库节点,这是一个可选的组件,如果您的网络支持 L2 VIP,可以考虑启用。
vip-manager 在每个 PG 节点上运行,监视 etcd 中由 Patroni 写入的领导者键,
将 pg_vip_address 绑定到当前主库节点的网卡上。
当集群发生故障转移时,vip-manager 会立即释放旧主机上的 VIP,并在新主机上重新绑定,从而将流量切换到新的主库。
该组件可选,通过 pg_vip_enabled 启用。
启用后需确保所有节点处于同一 VLAN,否则 VIP 无法正确漂移。
通常公有云网络环境不支持 L2 VIP,建议仅在本地自建环境与私有云环境中启用。
更多信息请参阅:教程:VIP 配置 与 配置:PGSQL - PG_ACCESS
pg_exporter pg_exporter 导出 PostgreSQL 监控指标,默认监听 9630 端口。
pg_exporter 运行在每个 PG 节点上,通过本地 Unix Socket 连接 PostgreSQL ,
导出覆盖会话、缓冲命中、复制延迟、事务率等丰富指标,供 INFRA 节点上的 VictoriaMetrics 抓取。
采集配置由 pg_exporter_config 指定,
支持自动数据库发现(pg_exporter_auto_discovery ),
并可通过 pg_exporter_cache_ttls 配置阶梯式缓存策略。
您可以通过参数禁用这个组件,在 精简安装 中,这个组件不会被启用。
更多信息请参阅:配置:PGSQL - PG_MONITOR
pgbouncer_exporter pgbouncer_exporter 导出 Pgbouncer 连接池指标,默认监听 9631 端口。
pgbouncer_exporter 使用的同样是 pg_exporter 的二进制程序,但是使用专用的指标配置文件,支持 pgbouncer 1.8 - 1.25+ 。
pgbouncer_exporter 读取 Pgbouncer 的统计视图,提供连接池利用率、等待队列与命中率指标。
若禁用 Pgbouncer ,本组件也同时关闭。在 精简安装 中,这个组件也不会被启用。
更多信息请参阅:配置:PGSQL - PG_MONITOR
pgbackrest_exporter pgbackrest_exporter 导出备份状态指标,默认监听 9854 端口。
pgbackrest_exporter 解析 pgBackRest 状态,生成最近备份时间、大小、类型等指标。结合告警策略可快速发现备份过期或失败,保障数据安全。
请注意,当备份很多,或者使用大型网络存储库时,采集过程开销较大,因此 pgbackrest_exporter 默认设置了 2分钟的采集间隔。
最慢情况下,您可能要在一个备份完成后的 2 分钟后,才能在监控系统中看到最新的备份状态。
更多信息请参阅:配置:PGSQL - PG_MONITOR
etcd etcd 是分布式一致性存储(DCS),为 Patroni 提供集群元数据存储与领导者选举能力。
etcd 由独立的 ETCD 模块 部署管理,不属于 PGSQL 模块本身,但对 PostgreSQL 高可用至关重要。
Patroni 将集群状态、领导者信息、配置参数写入 etcd,所有节点通过 etcd 达成共识。
vip-manager 也从 etcd 读取领导者键,实现 VIP 的自动漂移。
更多信息请参阅:ETCD 模块
vector Vector 是高性能日志采集组件,由 NODE 模块 部署,负责收集 PostgreSQL 相关日志。
Vector 常驻在节点上,跟踪 PostgreSQL 、Pgbouncer 、Patroni 与 pgBackRest 的日志目录,
将结构化日志发送至 INFRA 节点上的 VictoriaLogs 进行集中存储与查询。
更多信息请参阅:NODE 模块
2 - 集群模型图 Pigsty 是如何将不同种类的功能抽象成为模块的,以及这些模块的逻辑模型,实体关系图。
在 Pigsty 中最大的实体概念叫做 部署(Deployment) ,一套部署中的主要实体与关系(E-R 图)如下所示:
一套部署也可以理解为一个 环境(Environment) 。例如,生产环境(Prod),用户测试环境(UTA),预发环境(Staging),测试环境(Testing),开发环境(Devbox),等等。
每个环境中,都对应着一份 Pigsty 配置清单 ,描述了环境中的所有实体与属性。
通常来说,一套环境中也会带有一套共用的基础设施(INFRA ),广义的基础设施还包括 ETCD (高可用 DCS)以及 MINIO (集中式备份仓库),
同时供环境中的多套 PostgreSQL 数据库集群(以及其他数据库模块组件)使用。(例外:也有 不带基础设施的部署 )
在 Pigsty 中,几乎所有数据库模块都是以 “集群 "(Cluster)的方式组织起来的。每一个集群都是一个 Ansible 分组,包含有若干节点资源。
例如 PostgreSQL 高可用数据库集群,Redis,Etcd / MinIO 这些数据库都是以集群的形式存在。一套环境中可以包含多个集群。
2.1 - PGSQL 集群模型 介绍 Pigsty 中 PostgreSQL 集群的实体-关系模型,E-R 关系图,实体释义与命名规范。
PGSQL模块在生产环境中以集群 的形式组织,这些集群 是由一组由主-备 关联的数据库实例 组成的逻辑实体 。
每个集群都是一个自治 的业务单元,由至少一个 主库实例 组成,并通过服务向外暴露能力。
在 Pigsty 的PGSQL模块中有四种核心实体:
集群 (Cluster):自治的 PostgreSQL 业务单元,用作其他实体的顶级命名空间。服务 (Service):对外暴露能力的命名抽象,路由流量,并使用节点端口暴露服务。实例 (Instance):由在单个节点上的运行进程和数据库文件组成的单一 PostgreSQL 服务器。节点 (Node):运行 Linux + Systemd 环境的硬件资源抽象,可以是裸机、VM、容器或 Pod。辅以“数据库”“角色”两个业务实体,共同组成完整的逻辑视图。如下图所示:
具体样例 让我们来看两个具体的例子,以四节点的 Pigsty 沙箱环境 为例,在这个环境中,有一套三节点的 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 }
vars : { pg_cluster : pg-test }
上面的配置片段定义了一个如下所示的 高可用 PostgreSQL 集群,该集群中的相关实体包括:
集群 Cluster pg-testPostgreSQL 3 节点高可用集群 实例 Instance pg-test-11 号 PostgreSQL 实例,默认为主库 pg-test-22 号 PostgreSQL 实例,初始为从库 pg-test-33 号 PostgreSQL 实例,初始为从库 服务 Service pg-test-primary读写服务(路由到主库 pgbouncer) pg-test-replica只读服务(路由到从库 pgbouncer) pg-test-default直连读写服务(路由到主库 postgres) pg-test-offline离线读取服务(路由到专用 postgres) 节点 Nodes node-110.10.10.11 1 号节点,对应 pg-test-1 PG 实例node-210.10.10.12 2 号节点,对应 pg-test-2 PG 实例node-310.10.10.13 3 号节点,对应 pg-test-3 PG 实例
身份参数 Pigsty 使用 PG_ID 参数组为 PGSQL 模块的每个实体赋予确定的身份。以下三项为必选参数:
参数 类型 级别 说明 形式 pg_clusterstring集群 PG 集群名称,必选身份参数 有效的 DNS 名称,满足正则表达式 [a-zA-Z0-9-]+ pg_seqint实例 PG 实例编号,必选身份参数 自然数,可从 0 或 1 开始分配,集群内不重复 pg_roleenum实例 PG 实例角色,必选身份参数 枚举值,可为 primary,replica,offline
只要在集群层面定义了集群名称,实例层面分配了实例编号与角色,Pigsty 就能自动根据规则为每个实体生成唯一标识符。
实体 生成规则 示例 实例 {{ pg_cluster }}-{{ pg_seq }}pg-test-1,pg-test-2,pg-test-3服务 {{ pg_cluster }}-{{ pg_role }}pg-test-primary,pg-test-replica,pg-test-offline节点 显示指定覆盖,或自动从 PG 实例借用 pg-test-1,pg-test-2,pg-test-3
因为 Pigsty 采用节点与 PG 实例 1:1 的独占部署模型,因此默认情况下,主机节点的标识符会直接借用 PG 实例的标识符(node_id_from_pg )。
当然您也可以显式指定 nodename 进行覆盖,或者关闭 nodename_overwrite ,直接使用当前默认值。
分片身份参数 当你使用多套 PostgreSQL (分片 / Sharding)集群服务同一业务时,还会使用到另外两个身份参数:pg_shard 与 pg_group 。
在这种情况下,这一组 PostgreSQL 集群将拥有相同的 pg_shard 名称,以及各自的 pg_group 编号,例如下面的 Citus 集群 :
在这种情况下,pg_cluster 集群名通常由:{{ pg_shard }}{{ pg_group }} 组合而成,例如 pg-citus0、pg-citus1 等。
all :
children :
pg-citus0 : # citus 0号分片
hosts : { 10.10.10.10 : { pg_seq: 1, pg_role : primary } }
vars : { pg_cluster: pg-citus0 , pg_group : 0 }
pg-citus1 : # citus 1号分片
hosts : { 10.10.10.11 : { pg_seq: 1, pg_role : primary } }
vars : { pg_cluster: pg-citus1 , pg_group : 1 }
pg-citus2 : # citus 2号分片
hosts : { 10.10.10.12 : { pg_seq: 1, pg_role : primary } }
vars : { pg_cluster: pg-citus2 , pg_group : 2 }
pg-citus3 : # citus 3号分片
hosts : { 10.10.10.13 : { pg_seq: 1, pg_role : primary } }
vars : { pg_cluster: pg-citus3 , pg_group : 3 }
Pigsty 专门为水平分片集群提供专门的监控面板,便于对比各分片的性能与负载情况,但这需要您使用上述实体命名规则。
还有一些其他的身份参数,可能在特殊场景会使用到,例如,指定备份集群/级联复制上游的 pg_upstream ,指定 Greenplum 集群身份的 gp_role ,
指定外部监控实例的 pg_exporters ,指定实例为离线查询库的 pg_offline_query 等,请参考 PG_ID 参数文档 。
监控标签体系 Pigsty 提供了一套开箱即用的监控系统,在这个系统中使用上面的 身份参数 来标识各个 PostgreSQL 实体对象。
pg_up{cls="pg-test", ins="pg-test-1", ip="10.10.10.11", job="pgsql"}
pg_up{cls="pg-test", ins="pg-test-2", ip="10.10.10.12", job="pgsql"}
pg_up{cls="pg-test", ins="pg-test-3", ip="10.10.10.13", job="pgsql"}
例如,上面的 cls,ins,ip 三个标签,分别对应集群名、实例名与节点 IP,这三个核心实体的标识符。
它们与 job 标签,在 所有 VictoriaMetrics 采集的原生监控指标,以及 VictoriaLogs 日志流中都会出现并可用。
采集 PostgreSQL 指标的 job 名固定为 pgsql;
用于监控远程 PG 实例的 job 名固定为 pgrds。
采集 PostgreSQL CSV 日志的 job 名固定为 postgres;
采集 pgbackrest 日志的 job 名固定为 pgbackrest,其余 PG 组件通过 job: syslog 采集日志。
此外,还有一些普通实体身份标签,会在实体相关的特定监控指标中出现,例如:
datname: 数据库名,如果一个监控指标属于某个具体的数据库,则会带上这个标签。relname: 表名,如果一个监控指标属于某个具体的表,则会带上这个标签。idxname: 索引名,如果一个监控指标属于某个具体的索引,则会带上这个标签。funcname: 函数名,如果一个监控指标属于某个具体的函数,则会带上这个标签。seqname: 序列名,如果一个监控指标属于某个具体的序列,则会带上这个标签。query: 查询指纹,如果一个监控指标属于某个具体的查询,则会带上这个标签。2.2 - ETCD 集群模型 介绍 Pigsty 中 ETCD 集群的实体-关系模型,E-R 关系图,实体释义与命名规范。
ETCD 模块在生产环境中以集群 的形式组织,这些集群 是由一组通过 Raft 共识协议关联的 ETCD 实例 组成的逻辑实体 。
每个集群都是一个自治 的分布式键值存储单元,由至少一个 ETCD 实例 组成,通过客户端端口向外暴露服务能力。
在 Pigsty 的 ETCD 模块中有三种核心实体:
集群 (Cluster):自治的 ETCD 服务单元,用作其他实体的顶级命名空间。实例 (Instance):单个 ETCD 服务器进程,在节点上运行,参与 Raft 共识。节点 (Node):运行 Linux + Systemd 环境的硬件资源抽象,隐含式声明。相比于 PostgreSQL 集群,ETCD 集群模型更为简单,没有服务(Service)和复杂的角色(Role)区分。
所有 ETCD 实例在功能上是对等的,通过 Raft 协议选举出 Leader,其余为 Follower。
在扩容的中间状态,还允许不参与投票的 Learner 实例成员存在。
具体样例 让我们来看一个具体的例子,以三节点的 ETCD 集群为例:
etcd :
hosts :
10.10.10.10 : { etcd_seq : 1 }
10.10.10.11 : { etcd_seq : 2 }
10.10.10.12 : { etcd_seq : 3 }
vars :
etcd_cluster : etcd
上面的配置片段定义了一个如下所示的三节点 ETCD 集群,该集群中的相关实体包括:
集群 Cluster etcdETCD 三节点高可用集群 实例 Instance etcd-11 号 ETCD 实例 etcd-22 号 ETCD 实例 etcd-33 号 ETCD 实例 节点 Nodes 10.10.10.101 号节点,对应 etcd-1 实例 10.10.10.112 号节点,对应 etcd-2 实例 10.10.10.123 号节点,对应 etcd-3 实例
身份参数 Pigsty 使用 ETCD 参数组为 ETCD 模块的每个实体赋予确定的身份。以下两项为必选参数:
参数 类型 级别 说明 形式 etcd_clusterstring集群 ETCD 集群名称,必选身份参数 有效的 DNS 名称,默认为固定值 etcd etcd_seqint实例 ETCD 实例编号,必选身份参数 自然数,从 1 开始分配,集群内不重复
只要在集群层面定义了集群名称,实例层面分配了实例编号,Pigsty 就能自动根据规则为每个实体生成唯一标识符。
实体 生成规则 示例 实例 {{ etcd_cluster }}-{{ etcd_seq }}etcd-1,etcd-2,etcd-3
ETCD 模块不会为主机节点赋予额外的身份标识,节点使用其原有的主机名或 IP 地址进行标识。
端口协议 每个 ETCD 实例会监听以下两个端口:
ETCD 集群默认启用 TLS 加密通信,并使用 RBAC 认证机制。客户端需要使用正确的证书和密码才能访问 ETCD 服务。
集群规模 ETCD 作为分布式协调服务,集群规模直接影响其可用性,需要有超过半数(仲裁数)的节点存活才能维持服务。
集群规模 仲裁数 容忍故障数 适用场景 1 节点 1 0 开发、测试、演示 3 节点 2 1 中小规模生产环境 5 节点 3 2 大规模生产环境
因此,偶数节点的 ETCD 集群没有意义,超过五节点的 ETCD 集群并不常见,因此通常使用的规格就是单节点、三节点、五节点。
监控标签体系 Pigsty 提供了一套开箱即用的监控系统,在这个系统中使用上面的 身份参数 来标识各个 ETCD 实体对象。
etcd_up{cls="etcd", ins="etcd-1", ip="10.10.10.10", job="etcd"}
etcd_up{cls="etcd", ins="etcd-2", ip="10.10.10.11", job="etcd"}
etcd_up{cls="etcd", ins="etcd-3", ip="10.10.10.12", job="etcd"}
例如,上面的 cls,ins,ip 三个标签,分别对应集群名、实例名与节点 IP,这三个核心实体的标识符。
它们与 job 标签,在 所有 VictoriaMetrics 采集的 ETCD 监控指标中都会出现并可用。
采集 ETCD 指标的 job 名固定为 etcd。
2.3 - MINIO 集群模型 介绍 Pigsty 中 MinIO 集群的实体-关系模型,E-R 关系图,实体释义与命名规范。
MinIO 模块在生产环境中以集群 的形式组织,这些集群 是由一组分布式 MinIO 实例 组成的逻辑实体 ,共同提供高可用的对象存储服务。
每个集群都是一个自治 的 S3 兼容对象存储单元,由至少一个 MinIO 实例 组成,通过 S3 API 端口向外暴露服务能力。
在 Pigsty 的 MinIO 模块中有三种核心实体:
集群 (Cluster):自治的 MinIO 服务单元,用作其他实体的顶级命名空间。实例 (Instance):单个 MinIO 服务器进程,在节点上运行,管理本地磁盘存储。节点 (Node):运行 Linux + Systemd 环境的硬件资源抽象,隐含式声明。此外,MinIO 还有 存储池 (Pool)的概念,用于集群平滑扩容。
一个集群可以包含多个存储池,每个存储池由一组节点和磁盘组成。
部署模式 MinIO 支持三种主要部署模式,适用于不同的场景:
模式 代号 说明 适用场景 单机单盘 SNSD 单节点,单个数据目录,或单块磁盘 开发、测试、演示 单机多盘 SNMD 单节点,使用多块磁盘,通常至少 4 块盘 资源受限的小规模部署 多机多盘 MNMD 多节点,每节点多块磁盘 生产环境推荐
单机单盘模式可以使用任意目录作为存储,适合快速体验;单机多盘和多机多盘模式需要使用真实的磁盘挂载点,否则会拒绝启动。
具体样例 让我们来看一个多机多盘模式的具体例子,以四节点的 MinIO 集群为例:
minio :
hosts :
10.10.10.10 : { minio_seq : 1 }
10.10.10.11 : { minio_seq : 2 }
10.10.10.12 : { minio_seq : 3 }
10.10.10.13 : { minio_seq : 4 }
vars :
minio_cluster : minio
minio_data : '/data{1...4}'
minio_node : '${minio_cluster}-${minio_seq}.pigsty'
上面的配置片段定义了一个四节点的 MinIO 集群,每个节点使用四块磁盘,该集群中的相关实体包括:
集群 Cluster minioMinIO 四节点高可用集群 实例 Instance minio-11 号 MinIO 实例,管理 4 块磁盘 minio-22 号 MinIO 实例,管理 4 块磁盘 minio-33 号 MinIO 实例,管理 4 块磁盘 minio-44 号 MinIO 实例,管理 4 块磁盘 节点 Nodes 10.10.10.101 号节点,对应 minio-1 实例 10.10.10.112 号节点,对应 minio-2 实例 10.10.10.123 号节点,对应 minio-3 实例 10.10.10.134 号节点,对应 minio-4 实例
身份参数 Pigsty 使用 MINIO 参数组为 MinIO 模块的每个实体赋予确定的身份。以下两项为必选参数:
参数 类型 级别 说明 形式 minio_clusterstring集群 MinIO 集群名称,必选身份参数 有效的 DNS 名称,默认为 minio minio_seqint实例 MinIO 实例编号,必选身份参数 自然数,从 1 开始分配,集群内不重复
只要在集群层面定义了集群名称,实例层面分配了实例编号,Pigsty 就能自动根据规则为每个实体生成唯一标识符。
实体 生成规则 示例 实例 {{ minio_cluster }}-{{ minio_seq }}minio-1,minio-2,minio-3,minio-4
MinIO 模块不会为主机节点赋予额外的身份标识,节点使用其原有的主机名或 IP 地址进行标识。
minio_node 参数用于生成 MinIO 集群内部的节点名称(写入 /etc/hosts 供集群发现使用),而非主机节点的身份。
核心配置参数 除身份参数外,以下参数对 MinIO 集群配置至关重要:
这些参数共同决定了 MinIO 的核心配置 MINIO_VOLUMES:
单机单盘 :直接使用 minio_data 的值,如 /data/minio单机多盘 :使用 minio_data 展开的多个目录,如 /data{1...4}多机多盘 :组合 minio_node 与 minio_data,如 https://minio-{1...4}.pigsty:9000/data{1...4}端口与服务 每个 MinIO 实例会监听以下端口:
MinIO 默认启用 HTTPS 加密通信(由 minio_https 控制)。这对于 pgBackREST 等备份工具访问 MinIO 是必需的。
多节点 MinIO 集群可以通过访问 任意一个节点 来访问其服务。最佳实践是使用负载均衡器(如 HAProxy + VIP)统一接入点。
资源置备 MinIO 集群部署后,Pigsty 会自动创建以下资源(由 minio_provision 控制):
默认存储桶 (由 minio_buckets 定义):
存储桶 用途 pgsqlPostgreSQL pgBackREST 备份存储 meta元数据存储,启用版本控制 data通用数据存储
默认用户 (由 minio_users 定义):
用户 默认密码 策略 用途 pgbackrestS3User.BackuppgsqlPostgreSQL 备份专用用户 s3user_metaS3User.Metameta访问 meta 存储桶 s3user_dataS3User.Datadata访问 data 存储桶
pgbackrest 是 PostgreSQL 集群备份时使用的用户,s3user_meta 和 s3user_data 是未实际使用的保留用户。
监控标签体系 Pigsty 提供了一套开箱即用的监控系统,在这个系统中使用上面的 身份参数 来标识各个 MinIO 实体对象。
minio_up{cls="minio", ins="minio-1", ip="10.10.10.10", job="minio"}
minio_up{cls="minio", ins="minio-2", ip="10.10.10.11", job="minio"}
minio_up{cls="minio", ins="minio-3", ip="10.10.10.12", job="minio"}
minio_up{cls="minio", ins="minio-4", ip="10.10.10.13", job="minio"}
例如,上面的 cls,ins,ip 三个标签,分别对应集群名、实例名与节点 IP,这三个核心实体的标识符。
它们与 job 标签,在 所有 VictoriaMetrics 采集的 MinIO 监控指标中都会出现并可用。
采集 MinIO 指标的 job 名固定为 minio。
2.4 - REDIS 集群模型 介绍 Pigsty 中 Redis 集群的实体-关系模型,E-R 关系图,实体释义与命名规范。
Redis 模块在生产环境中以集群 的形式组织,这些集群 是由一组 Redis 实例 组成的逻辑实体 ,部署在一个或多个节点 上。
每个集群都是一个自治 的高性能缓存/存储单元,由至少一个 Redis 实例 组成,通过端口向外暴露服务能力。
在 Pigsty 的 Redis 模块中有三种核心实体:
集群 (Cluster):自治的 Redis 服务单元,用作其他实体的顶级命名空间。实例 (Instance):单个 Redis 服务器进程,在节点上的特定端口运行。节点 (Node):运行 Linux + Systemd 环境的硬件资源抽象,可以承载多个 Redis 实例,隐含式声明。与 PostgreSQL 不同,Redis 采用 单机多实例 的部署模型:一个物理/虚拟机节点上通常会部署 多个 Redis 实例,
以充分利用多核 CPU。因此,节点与实例是 1:N 的关系。此外,生产中通常不建议设置单个内存规模大于 12GB 的 Redis 实例。
工作模式 Redis 有三种不同的工作模式,由 redis_mode 参数指定:
模式 代号 说明 高可用机制 主从模式 standalone经典主从复制,默认模式 需配合 Sentinel 实现 哨兵模式 sentinel为主从模式提供高可用监控与自动故障转移 本身的多节点仲裁 原生集群模式 clusterRedis 原生分布式集群,无需哨兵即可高可用 内置自动故障转移
主从模式 :默认模式,通过 replica_of 参数设置主从复制关系。需要额外的 Sentinel 集群提供高可用。哨兵模式 :不存储业务数据,专门用于监控主从模式的 Redis 集群,实现自动故障转移,本身多节点即可高可用。原生集群模式 :数据自动分片到多个主节点,每个主节点可以有多个从节点,内置高可用能力,无需哨兵支持。具体样例 让我们来看三种模式的具体例子:
主从集群 一个节点上部署一主一从的经典主从集群:
redis-ms :
hosts :
10.10.10.10 :
redis_node : 1
redis_instances :
6379 : { }
6380 : { replica_of : '10.10.10.10 6379' }
vars :
redis_cluster : redis-ms
redis_password : 'redis.ms'
redis_max_memory : 64MB
集群 Cluster redis-msRedis 主从集群 节点 Nodes redis-ms-110.10.10.10 1 号节点,承载 2 个实例实例 Instance redis-ms-1-6379主库实例,监听 6379 端口 redis-ms-1-6380从库实例,监听 6380 端口,复制自 6379
哨兵集群 一个节点上部署三个哨兵实例,用于监控主从集群。哨兵集群通过 redis_sentinel_monitor 参数指定要监控的主从集群列表:
redis-sentinel :
hosts :
10.10.10.11 :
redis_node : 1
redis_instances : { 26379 : {}, 26380 : {}, 26381 : {} }
vars :
redis_cluster : redis-sentinel
redis_password : 'redis.sentinel'
redis_mode : sentinel
redis_max_memory : 16MB
redis_sentinel_monitor :
- { name: redis-ms, host: 10.10.10.10, port: 6379, password: redis.ms, quorum : 2 }
原生集群 下面的配置片段定义了由两个节点,六个实例组成的 Redis 原生分布式集群(最小规格,3主3从):
redis-test :
hosts :
10.10.10.12 : { redis_node: 1, redis_instances : { 6379 : {}, 6380 : {}, 6381 : {} } }
10.10.10.13 : { redis_node: 2, redis_instances : { 6379 : {}, 6380 : {}, 6381 : {} } }
vars :
redis_cluster : redis-test
redis_password : 'redis.test'
redis_mode : cluster
redis_max_memory : 32MB
该配置将创建一个 3 主 3 从 的原生 Redis 集群。
集群 Cluster redis-testRedis 原生集群(3 主 3 从) 实例 Instance redis-test-1-6379节点 1 上的实例,监听 6379 端口 redis-test-1-6380节点 1 上的实例,监听 6380 端口 redis-test-1-6381节点 1 上的实例,监听 6381 端口 redis-test-2-6379节点 2 上的实例,监听 6379 端口 redis-test-2-6380节点 2 上的实例,监听 6380 端口 redis-test-2-6381节点 2 上的实例,监听 6381 端口 节点 Nodes redis-test-110.10.10.12 1 号节点,承载 3 个实例redis-test-210.10.10.13 2 号节点,承载 3 个实例
身份参数 Pigsty 使用 REDIS 参数组为 Redis 模块的每个实体赋予确定的身份。以下三项为必选参数:
参数 类型 级别 说明 形式 redis_clusterstring集群 Redis 集群名称,必选身份参数 有效的 DNS 名称,满足 [a-z][a-z0-9-]* redis_nodeint节点 Redis 节点编号,必选身份参数 自然数,从 1 开始分配,集群内不重复 redis_instancesdict节点 Redis 实例定义,必选身份参数 JSON 对象,Key 为端口号,Value 为实例配置
只要在集群层面定义了集群名称,节点层面分配了节点编号与实例定义,Pigsty 就能自动根据规则为每个实体生成唯一标识符。
实体 生成规则 示例 实例 {{ redis_cluster }}-{{ redis_node }}-{{ port }}redis-ms-1-6379,redis-ms-1-6380
Redis 模块不会为主机节点赋予额外的身份标识,节点使用其原有的主机名或 IP 地址进行标识。
redis_node 参数用于实例命名,而非主机节点的身份。
实例定义 redis_instances 是一个 JSON 对象,Key 为 端口号 ,Value 为该实例的 配置项 :
redis_instances :
6379 : { } # 主库实例,无需额外配置
6380 : { replica_of : '10.10.10.10 6379' } # 从库实例,指定上游主库
6381 : { replica_of : '10.10.10.10 6379' } # 从库实例,指定上游主库
每个 Redis 实例会监听一个唯一的端口,端口在节点上唯一不重复,您可以任意选择端口号,
但请不要使用系统保留端口(小于 1024),或者与 Pigsty 使用的端口 冲突。
实例配置中的 replica_of 参数用于在主从模式下设置复制关系,格式为 '<ip> <port>',用于指定一个 Redis 从库的上游主库地址与端口。
此外,每个 Redis 节点上会运行一个 Redis Exporter,用于汇总采集当前节点上 所有本地实例 的监控指标:
Redis 模块的单机多实例部署模型带有一些一些局限性:
节点独占 :一个节点只能属于一个 Redis 集群,不能同时分配给不同的 Redis 集群。端口唯一 :同一节点上的 Redis 实例必须使用不同的端口号,避免端口冲突。密码共享 :同一节点上的多个 Redis 实例无法设置不同的密码(受 redis_exporter 限制)。手动高可用 :主从模式的 Redis 集群需要额外配置 Sentinel 才能实现自动故障转移。监控标签体系 Pigsty 提供了一套开箱即用的监控系统,在这个系统中使用上面的 身份参数 来标识各个 Redis 实体对象。
redis_up{cls="redis-ms", ins="redis-ms-1-6379", ip="10.10.10.10", job="redis"}
redis_up{cls="redis-ms", ins="redis-ms-1-6380", ip="10.10.10.10", job="redis"}
例如,上面的 cls,ins,ip 三个标签,分别对应集群名、实例名与节点 IP,这三个核心实体的标识符。
它们与 job 标签,在 所有 VictoriaMetrics 采集的 Redis 监控指标中都会出现并可用。
采集 Redis 指标的 job 名固定为 redis。
2.5 - INFRA 集群模型 介绍 Pigsty 中 INFRA 基础设施节点的实体-关系模型,组件构成与命名规范。
INFRA 模块在 Pigsty 中承担着特殊的角色:它不是传统意义上的"集群",而是由一组 基础设施节点 构成的管理中枢,为整个 Pigsty 部署提供核心服务。
每个 INFRA 节点都是一个自治 的基础设施服务单元,运行着 Nginx、Grafana、VictoriaMetrics 等核心组件,共同为纳管的数据库集群提供可观测性与管理能力。
在 Pigsty 的 INFRA 模块中有两种核心实体:
节点 (Node):运行基础设施组件的服务器,可以是裸机、VM、容器或 Pod。组件 (Component):在节点上运行的各类基础设施服务,如 Nginx、Grafana、VictoriaMetrics 等。INFRA 节点通常承担管理节点(Admin Node)的角色,是 Pigsty 的控制平面所在。
组件构成 每个 INFRA 节点上运行着以下核心组件:
这些组件共同构成了 Pigsty 的可观测性基础设施。
具体样例 让我们来看一个具体的例子,以双节点的 INFRA 部署为例:
infra :
hosts :
10.10.10.10 : { infra_seq : 1 }
10.10.10.11 : { infra_seq : 2 }
上面的配置片段定义了一个双节点的 INFRA 部署:
分组 Group infraINFRA 基础设施节点分组 节点 Nodes infra-110.10.10.10 1 号 INFRA 节点infra-210.10.10.11 2 号 INFRA 节点
在生产环境中,建议部署至少两个 INFRA 节点,以实现基础设施组件的冗余。
身份参数 Pigsty 使用 INFRA_ID 参数组为 INFRA 模块的每个实体赋予确定的身份。以下一项为必选参数:
参数 类型 级别 说明 形式 infra_seqint节点 INFRA 节点序号,必选身份参数 自然数,从 1 开始分配,分组内不重复
只要在节点层面分配了节点序号,Pigsty 就能自动根据规则为每个实体生成唯一标识符。
实体 生成规则 示例 节点 infra-{{ infra_seq }}infra-1,infra-2
INFRA 模块会为节点赋予 infra-N 形式的标识,用于监控系统中区分多个基础设施节点。
但这并不改变节点本身的主机名或系统身份,节点仍然使用其原有的主机名或 IP 地址进行标识。
服务门户 INFRA 节点通过 Nginx 提供统一的 Web 服务入口。infra_portal 参数定义了通过 Nginx 暴露的服务列表。
默认配置只定义了首页服务器:
infra_portal :
home : { domain : i.pigsty }
Pigsty 会自动为启用的组件(如 Grafana、VictoriaMetrics、AlertManager 等)配置反向代理端点。如果需要通过独立域名访问这些服务,可以显式添加配置:
infra_portal :
home : { domain : i.pigsty }
grafana : { domain: g.pigsty, endpoint : "${admin_ip}:3000" , websocket : true }
prometheus : { domain: p.pigsty, endpoint : "${admin_ip}:8428" } # VMUI
alertmanager : { domain: a.pigsty, endpoint : "${admin_ip}:9059" }
域名 服务 说明 i.pigstyHome Pigsty 首页 g.pigstyGrafana 监控可视化平台 p.pigstyVictoriaMetrics 时序数据库 Web UI a.pigstyAlertmanager 告警管理界面
建议通过域名访问 Pigsty 服务,而不是直接使用 IP + 端口的方式。
部署规模 INFRA 节点的数量取决于部署规模和高可用需求:
部署规模 INFRA 节点数 说明 开发测试 1 单节点部署,所有组件在同一节点 小规模生产 1-2 单节点或双节点,可与其他服务共用节点 中规模生产 2-3 独立的 INFRA 节点,组件冗余部署 大规模生产 3+ 多 INFRA 节点,可根据组件分离部署
单机部署 时,INFRA 组件与 PGSQL、ETCD 等模块共用同一个节点。
通常在小规模部署中,INFRA 节点通常还承担着 “管理节点 ” / “备用管理节点”,以及本地软件仓库(/www/pigsty)的角色。
在更大规模的部署中,这些职责可以剥离至专用节点。
监控标签体系 Pigsty 的监控系统会采集 INFRA 组件自身的指标。与数据库模块不同,INFRA 模块的每个组件 都被视为独立的监控对象,通过 cls(类)标签区分不同组件类型。
标签 说明 示例 cls组件类型,每种组件各自构成一个"类" nginxins实例名,格式为 {组件类型}-{infra_seq} nginx-1ip运行该组件的 INFRA 节点 IP 地址 10.10.10.10jobVictoriaMetrics 采集任务名,固定为 infra infra
以双节点 INFRA 部署(infra_seq: 1 和 infra_seq: 2)为例,各组件的监控标签如下:
组件 clsins 示例端口 Nginx nginxnginx-1,nginx-29113Grafana grafanagrafana-1,grafana-23000VictoriaMetrics vmetricsvmetrics-1,vmetrics-28428VictoriaLogs vlogsvlogs-1,vlogs-29428VictoriaTraces vtracesvtraces-1,vtraces-210428VMAlert vmalertvmalert-1,vmalert-28880Alertmanager alertmanageralertmanager-1,alertmanager-29059Blackbox blackboxblackbox-1,blackbox-29115
所有 INFRA 组件的监控指标都使用统一的 job="infra" 标签,通过 cls 标签区分组件类型:
nginx_up{cls="nginx", ins="nginx-1", ip="10.10.10.10", job="infra"}
grafana_info{cls="grafana", ins="grafana-1", ip="10.10.10.10", job="infra"}
vm_app_version{cls="vmetrics", ins="vmetrics-1", ip="10.10.10.10", job="infra"}
vlogs_rows_ingested_total{cls="vlogs", ins="vlogs-1", ip="10.10.10.10", job="infra"}
alertmanager_alerts{cls="alertmanager", ins="alertmanager-1", ip="10.10.10.10", job="infra"}
3 - 声明式配置 —— 基础设施即代码(IaC) Pigsty 使用基础设施即代码(IaC)的理念管理所有组件,针对大规模集群提供声明式管理能力。
Pigsty 遵循 IaC 与 GitOPS 的理念:使用声明式的 配置清单 描述整个环境,并通过 幂等剧本 来实现。
用户用声明的方式通过 参数 来描述自己期望的状态,而剧本则以幂等的方式调整目标节点以达到这个状态。
这类似于 Kubernetes 的 CRD & Operator,然而 Pigsty 在裸机和虚拟机上,通过 Ansible 实现了这样的功能。
Pigsty 诞生之初是为了解决超大规模 PostgreSQL 集群的运维管理问题,背后的想法很简单 —— 我们需要有在十分钟内在就绪的服务器上复刻整套基础设施(100+数据库集群 + PG/Redis + 可观测性)的能力。
任何 GUI + ClickOps 都无法在如此短的时间内完成如此复杂的任务,这让 CLI + IaC 成为唯一的选择 —— 它提供了精确,高效的控制能力。
配置清单 pigsty.yml 文件描述了整个部署的状态,无论是 生产环境(prod),预发环境(staging), 测试环境(test),还是 开发环境(devbox),
基础设施的区别仅在于配置清单的不同,而部署交付的逻辑则是完全相同的。
您可以使用 git 对这份部署的 “种子/基因” 进行版本控制与审计,而且,Pigsty 甚至支持将配置清单以数据库表的形式存储在 PostgreSQL CMDB 中,
更进一步从 Infra as Code 升级为 Infra as Data,无缝与您现有的工作流程集成与对接。
IaC 面向专业用户与企业场景而设计,但也针对个人开发者,SMB 进行了深度优化。
即使您并非专业 DBA,也无需了解这几百个调节开关与旋钮,所有参数都带有表现良好的默认值,
您完全可以在 零配置 的情况下,获得一个开箱即用的单机数据库节点;
简单地再添加两行 IP 地址,就能获得一套企业级的高可用的 PostgreSQL 集群。
声明模块 以下面的默认配置片段为例,这段配置描述了一个节点 10.10.10.10,其上安装了 INFRA 、NODE 、ETCD 和 PGSQL 模块。
# 监控、告警、DNS、NTP 等基础设施集群...
infra : { hosts : { 10.10.10.10 : { infra_seq : 1 } } }
# minio 集群,兼容 s3 的对象存储
minio : { hosts : { 10.10.10.10 : { minio_seq: 1 } }, vars : { minio_cluster : minio } }
# etcd 集群,用作 PostgreSQL 高可用所需的 DCS
etcd : { hosts : { 10.10.10.10 : { etcd_seq: 1 } }, vars : { etcd_cluster : etcd } }
# PGSQL 示例集群: pg-meta
pg-meta : { hosts : { 10.10.10.10 : { pg_seq: 1, pg_role: primary }, vars : { pg_cluster : pg-meta } }
要真正安装这些模块,执行以下剧本:
./infra.yml -l 10.10.10.10 # 在节点 10.10.10.10 上初始化 infra 模块
./etcd.yml -l 10.10.10.10 # 在节点 10.10.10.10 上初始化 etcd 模块
./minio.yml -l 10.10.10.10 # 在节点 10.10.10.10 上初始化 minio 模块
./pgsql.yml -l 10.10.10.10 # 在节点 10.10.10.10 上初始化 pgsql 模块
声明集群 您可以声明 PostgreSQL 数据库集群,在多个节点上安装 PGSQL 模块,并使其成为一个服务单元:
例如,要在以下三个已被 Pigsty 纳管的节点上,部署一个使用流复制组建的三节点高可用 PostgreSQL 集群,
您可以在配置文件 pigsty.yml 的 all.children 中添加以下定义:
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 : offline }
vars : { pg_cluster : pg-test }
定义完后,可以使用 剧本 将集群创建:
bin/pgsql-add pg-test # 创建 pg-test 集群
你可以使用不同的实例角色,例如 主库 (primary),从库 (replica),离线从库 (offline),延迟从库 (delayed),同步备库 (sync standby);
以及不同的集群:例如 备份集群 (Standby Cluster),Citus 集群 ,甚至是 Redis / MinIO / Etcd 集群
定制集群内容 您不仅可以使用声明式的方式定义集群,还可以定义集群中的数据库、用户、服务、HBA 规则等内容,例如,下面的配置文件对默认的 pg-meta 单节点数据库集群的内容进行了深度定制:
包括:声明了六个业务数据库与七个业务用户,添加了一个额外的 standby 服务(同步备库,提供无复制延迟的读取能力),定义了一些额外的 pg_hba 规则,一个指向集群主库的 L2 VIP 地址,与自定义的备份策略。
pg-meta :
hosts : { 10.10.10.10 : { pg_seq: 1, pg_role: primary , pg_offline_query : true } }
vars :
pg_cluster : pg-meta
pg_databases : # define business databases on this cluster, array of database definition
- name : meta # REQUIRED, `name` is the only mandatory field of a database definition
baseline : cmdb.sql # optional, database sql baseline path, (relative path among ansible search path, e.g files/)
pgbouncer : true # optional, add this database to pgbouncer database list? true by default
schemas : [ pigsty] # optional, additional schemas to be created, array of schema names
extensions: # optional, additional extensions to be installed : array of `{name[,schema]}`
- { name: postgis , schema : public }
- { name : timescaledb }
comment : pigsty meta database # optional, comment string for this database
owner : postgres # optional, database owner, postgres by default
template : template1 # optional, which template to use, template1 by default
encoding : UTF8 # optional, database encoding, UTF8 by default. (MUST same as template database)
locale : C # optional, database locale, C by default. (MUST same as template database)
lc_collate : C # optional, database collate, C by default. (MUST same as template database)
lc_ctype : C # optional, database ctype, C by default. (MUST same as template database)
tablespace : pg_default # optional, default tablespace, 'pg_default' by default.
allowconn : true # optional, allow connection, true by default. false will disable connect at all
revokeconn : false # optional, revoke public connection privilege. false by default. (leave connect with grant option to owner)
register_datasource : true # optional, register this database to grafana datasources? true by default
connlimit : -1 # optional, database connection limit, default -1 disable limit
pool_auth_user : dbuser_meta # optional, all connection to this pgbouncer database will be authenticated by this user
pool_mode : transaction # optional, pgbouncer pool mode at database level, default transaction
pool_size : 64 # optional, pgbouncer pool size at database level, default 64
pool_size_reserve : 32 # optional, pgbouncer pool size reserve at database level, default 32
pool_size_min : 0 # optional, pgbouncer pool size min at database level, default 0
pool_max_db_conn : 100 # optional, max database connections at database level, default 100
- { name: grafana ,owner: dbuser_grafana ,revokeconn: true ,comment : grafana primary database }
- { name: bytebase ,owner: dbuser_bytebase ,revokeconn: true ,comment : bytebase primary database }
- { name: kong ,owner: dbuser_kong ,revokeconn: true ,comment : kong the api gateway database }
- { name: gitea ,owner: dbuser_gitea ,revokeconn: true ,comment : gitea meta database }
- { name: wiki ,owner: dbuser_wiki ,revokeconn: true ,comment : wiki meta database }
pg_users : # define business users/roles on this cluster, array of user definition
- name : dbuser_meta # REQUIRED, `name` is the only mandatory field of a user definition
password : DBUser.Meta # optional, password, can be a scram-sha-256 hash string or plain text
login : true # optional, can log in, true by default (new biz ROLE should be false)
superuser : false # optional, is superuser? false by default
createdb : false # optional, can create database? false by default
createrole : false # optional, can create role? false by default
inherit : true # optional, can this role use inherited privileges? true by default
replication : false # optional, can this role do replication? false by default
bypassrls : false # optional, can this role bypass row level security? false by default
pgbouncer : true # optional, add this user to pgbouncer user-list? false by default (production user should be true explicitly)
connlimit : -1 # optional, user connection limit, default -1 disable limit
expire_in : 3650 # optional, now + n days when this role is expired (OVERWRITE expire_at)
expire_at : '2030-12-31' # optional, YYYY-MM-DD 'timestamp' when this role is expired (OVERWRITTEN by expire_in)
comment : pigsty admin user # optional, comment string for this user/role
roles: [dbrole_admin] # optional, belonged roles. default roles are : dbrole_{admin,readonly,readwrite,offline}
parameters : {} # optional, role level parameters with `ALTER ROLE SET`
pool_mode : transaction # optional, pgbouncer pool mode at user level, transaction by default
pool_connlimit : -1 # optional, max database connections at user level, default -1 disable limit
- {name: dbuser_view ,password: DBUser.Viewer ,pgbouncer: true ,roles: [dbrole_readonly], comment : read-only viewer for meta database}
- {name: dbuser_grafana ,password: DBUser.Grafana ,pgbouncer: true ,roles: [dbrole_admin] ,comment : admin user for grafana database }
- {name: dbuser_bytebase ,password: DBUser.Bytebase ,pgbouncer: true ,roles: [dbrole_admin] ,comment : admin user for bytebase database }
- {name: dbuser_kong ,password: DBUser.Kong ,pgbouncer: true ,roles: [dbrole_admin] ,comment : admin user for kong api gateway }
- {name: dbuser_gitea ,password: DBUser.Gitea ,pgbouncer: true ,roles: [dbrole_admin] ,comment : admin user for gitea service }
- {name: dbuser_wiki ,password: DBUser.Wiki ,pgbouncer: true ,roles: [dbrole_admin] ,comment : admin user for wiki.js service }
pg_services : # extra services in addition to pg_default_services, array of service definition
# standby service will route {ip|name}:5435 to sync replica's pgbouncer (5435->6432 standby)
- name: standby # required, service name, the actual svc name will be prefixed with `pg_cluster`, e.g : pg-meta-standby
port : 5435 # required, service exposed port (work as kubernetes service node port mode)
ip : "*" # optional, service bind ip address, `*` for all ip by default
selector : "[]" # required, service member selector, use JMESPath to filter inventory
dest : default # optional, destination port, default|postgres|pgbouncer|<port_number>, 'default' by default
check : /sync # optional, health check url path, / by default
backup : "[? pg_role == `primary`]" # backup server selector
maxconn : 3000 # optional, max allowed front-end connection
balance: roundrobin # optional, haproxy load balance algorithm (roundrobin by default, other : leastconn)
options : 'inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100'
pg_hba_rules :
- {user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title : 'allow grafana dashboard access cmdb from infra nodes' }
pg_vip_enabled : true
pg_vip_address : 10.10.10.2 /24
pg_vip_interface : eth1
node_crontab : # make a full backup 1 am everyday
- '00 01 * * * postgres /pg/bin/pg-backup full'
声明访问控制 您还可以通过声明式的配置,深度定制 Pigsty 的访问控制能力。例如下面的配置文件对 pg-meta 集群进行了深度安全定制:
使用三节点核心集群模板:crit.yml,确保数据一致性有限,故障切换数据零丢失。
启用了 L2 VIP,并将数据库与连接池的监听地址限制在了本地环回 IP + 内网 IP + VIP 三个特定地址。
模板强制启用了 Patroni 的 SSL API,与 Pgbouncer 的 SSL,并在 HBA 规则中强制要求使用 SSL 访问数据库集群。
同时还在 pg_libs 中启用了 $libdir/passwordcheck 扩展,来强制执行密码强度安全策略。
最后,还单独声明了一个 pg-meta-delay 集群,作为 pg-meta 在一个小时前的延迟镜像从库,用于紧急数据误删恢复。
pg-meta : # 3 instance postgres cluster `pg-meta`
hosts :
10.10.10.10 : { pg_seq: 1, pg_role : primary }
10.10.10.11 : { pg_seq: 2, pg_role : replica }
10.10.10.12 : { pg_seq: 3, pg_role: replica , pg_offline_query : true }
vars :
pg_cluster : pg-meta
pg_conf : crit.yml
pg_users :
- { name: dbuser_meta , password: DBUser.Meta , pgbouncer: true , roles: [ dbrole_admin ] , comment : pigsty admin user }
- { name: dbuser_view , password: DBUser.Viewer , pgbouncer: true , roles: [ dbrole_readonly ] , comment : read-only viewer for meta database }
pg_databases :
- {name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions : [ {name: postgis, schema : public}, {name: timescaledb}]}
pg_default_service_dest : postgres
pg_services :
- { name: standby ,src_ip : "*" ,port: 5435 , dest: default ,selector : "[]" , backup : "[? pg_role == `primary`]" }
pg_vip_enabled : true
pg_vip_address : 10.10.10.2 /24
pg_vip_interface : eth1
pg_listen : '${ip},${vip},${lo}'
patroni_ssl_enabled : true
pgbouncer_sslmode : require
pgbackrest_method : minio
pg_libs : 'timescaledb, $libdir/passwordcheck, pg_stat_statements, auto_explain' # add passwordcheck extension to enforce strong password
pg_default_roles : # default roles and users in postgres cluster
- { name: dbrole_readonly ,login: false ,comment : role for global read-only access }
- { name: dbrole_offline ,login: false ,comment : role for restricted read-only access }
- { name: dbrole_readwrite ,login: false ,roles: [dbrole_readonly] ,comment : role for global read-write access }
- { name: dbrole_admin ,login: false ,roles: [pg_monitor, dbrole_readwrite] ,comment : role for object creation }
- { name: postgres ,superuser: true ,expire_in: 7300 ,comment : system superuser }
- { name: replicator ,replication: true ,expire_in: 7300 ,roles: [pg_monitor, dbrole_readonly] ,comment : system replicator }
- { name: dbuser_dba ,superuser: true ,expire_in: 7300 ,roles: [dbrole_admin] ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 , comment : pgsql admin user }
- { name: dbuser_monitor ,roles: [pg_monitor] ,expire_in: 7300 ,pgbouncer: true ,parameters : {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment : pgsql monitor user }
pg_default_hba_rules : # postgres host-based auth rules by default
- {user : '${dbsu}' ,db: all ,addr: local ,auth: ident ,title : 'dbsu access via local os user ident' }
- {user : '${dbsu}' ,db: replication ,addr: local ,auth: ident ,title : 'dbsu replication from local os ident' }
- {user : '${repl}' ,db: replication ,addr: localhost ,auth: ssl ,title : 'replicator replication from localhost' }
- {user : '${repl}' ,db: replication ,addr: intra ,auth: ssl ,title : 'replicator replication from intranet' }
- {user : '${repl}' ,db: postgres ,addr: intra ,auth: ssl ,title : 'replicator postgres db from intranet' }
- {user : '${monitor}' ,db: all ,addr: localhost ,auth: pwd ,title : 'monitor from localhost with password' }
- {user : '${monitor}' ,db: all ,addr: infra ,auth: ssl ,title : 'monitor from infra host with password' }
- {user : '${admin}' ,db: all ,addr: infra ,auth: ssl ,title : 'admin @ infra nodes with pwd & ssl' }
- {user : '${admin}' ,db: all ,addr: world ,auth: cert ,title : 'admin @ everywhere with ssl & cert' }
- {user: '+dbrole_readonly',db: all ,addr: localhost ,auth: ssl ,title : 'pgbouncer read/write via local socket' }
- {user: '+dbrole_readonly',db: all ,addr: intra ,auth: ssl ,title : 'read/write biz user via password' }
- {user: '+dbrole_offline' ,db: all ,addr: intra ,auth: ssl ,title : 'allow etl offline tasks from intranet' }
pgb_default_hba_rules : # pgbouncer host-based authentication rules
- {user : '${dbsu}' ,db: pgbouncer ,addr: local ,auth: peer ,title : 'dbsu local admin access with os ident' }
- {user: 'all' ,db: all ,addr: localhost ,auth: pwd ,title : 'allow all user local access with pwd' }
- {user : '${monitor}' ,db: pgbouncer ,addr: intra ,auth: ssl ,title : 'monitor access via intranet with pwd' }
- {user : '${monitor}' ,db: all ,addr: world ,auth: deny ,title : 'reject all other monitor access addr' }
- {user : '${admin}' ,db: all ,addr: intra ,auth: ssl ,title : 'admin access via intranet with pwd' }
- {user : '${admin}' ,db: all ,addr: world ,auth: deny ,title : 'reject all other admin access addr' }
- {user: 'all' ,db: all ,addr: intra ,auth: ssl ,title : 'allow all user intra access with pwd' }
# OPTIONAL delayed cluster for pg-meta
pg-meta-delay : # delayed instance for pg-meta (1 hour ago)
hosts : { 10.10.10.13 : { pg_seq: 1, pg_role: primary, pg_upstream: 10.10.10.10, pg_delay : 1h } }
vars : { pg_cluster : pg-meta-delay }
Citus 分布式集群 下面是一个四节点的 Citus 分布式集群的声明式配置:
all :
children :
pg-citus0 : # citus coordinator, pg_group = 0
hosts : { 10.10.10.10 : { pg_seq: 1, pg_role : primary } }
vars : { pg_cluster: pg-citus0 , pg_group : 0 }
pg-citus1 : # citus data node 1
hosts : { 10.10.10.11 : { pg_seq: 1, pg_role : primary } }
vars : { pg_cluster: pg-citus1 , pg_group : 1 }
pg-citus2 : # citus data node 2
hosts : { 10.10.10.12 : { pg_seq: 1, pg_role : primary } }
vars : { pg_cluster: pg-citus2 , pg_group : 2 }
pg-citus3 : # citus data node 3, with an extra replica
hosts :
10.10.10.13 : { pg_seq: 1, pg_role : primary }
10.10.10.14 : { pg_seq: 2, pg_role : replica }
vars : { pg_cluster: pg-citus3 , pg_group : 3 }
vars : # global parameters for all citus clusters
pg_mode: citus # pgsql cluster mode : citus
pg_shard: pg-citus # citus shard name : pg-citus
patroni_citus_db : meta # citus distributed database name
pg_dbsu_password : DBUser.Postgres # all dbsu password access for citus cluster
pg_users : [ { name: dbuser_meta ,password: DBUser.Meta ,pgbouncer: true ,roles : [ dbrole_admin ] } ]
pg_databases : [ { name: meta ,extensions : [ { name : citus }, { name: postgis }, { name: timescaledb } ] } ]
pg_hba_rules :
- { user: 'all' ,db: all ,addr: 127.0.0.1/32 ,auth: ssl ,title : 'all user ssl access from localhost' }
- { user: 'all' ,db: all ,addr: intra ,auth: ssl ,title : 'all user ssl access from intranet' }
Redis 集群 下面给出了 Redis 主从集群、哨兵集群、以及 Redis Cluster 的声明配置样例
redis-ms : # redis classic primary & replica
hosts : { 10.10.10.10 : { redis_node: 1 , redis_instances : { 6379 : { }, 6380 : { replica_of : '10.10.10.10 6379' } } } }
vars : { redis_cluster: redis-ms ,redis_password: 'redis.ms' ,redis_max_memory : 64MB }
redis-meta : # redis sentinel x 3
hosts : { 10.10.10.11 : { redis_node: 1 , redis_instances : { 26379 : { } ,26380 : { } ,26381 : { } } } }
vars :
redis_cluster : redis-meta
redis_password : 'redis.meta'
redis_mode : sentinel
redis_max_memory : 16MB
redis_sentinel_monitor : # primary list for redis sentinel, use cls as name, primary ip:port
- { name: redis-ms, host: 10.10.10.10, port: 6379 ,password: redis.ms, quorum : 2 }
redis-test: # redis native cluster : 3m x 3s
hosts :
10.10.10.12 : { redis_node: 1 ,redis_instances : { 6379 : { } ,6380 : { } ,6381 : { } } }
10.10.10.13 : { redis_node: 2 ,redis_instances : { 6379 : { } ,6380 : { } ,6381 : { } } }
vars : { redis_cluster: redis-test ,redis_password: 'redis.test' ,redis_mode: cluster, redis_max_memory : 32MB }
ETCD 集群 下面给出了一个三节点的 Etcd 集群声明式配置样例:
etcd : # dcs service for postgres/patroni ha consensus
hosts : # 1 node for testing, 3 or 5 for production
10.10.10.10 : { etcd_seq : 1 } # etcd_seq required
10.10.10.11 : { etcd_seq : 2 } # assign from 1 ~ n
10.10.10.12 : { etcd_seq : 3 } # odd number please
vars : # cluster level parameter override roles/etcd
etcd_cluster : etcd # mark etcd cluster name etcd
etcd_safeguard : false # safeguard against purging
etcd_clean : true # purge etcd during init process
MinIO 集群 下面给出了一个三节点的 MinIO 集群声明式配置样例:
minio :
hosts :
10.10.10.10 : { minio_seq : 1 }
10.10.10.11 : { minio_seq : 2 }
10.10.10.12 : { minio_seq : 3 }
vars :
minio_cluster : minio
minio_data : '/data{1...2}' # 每个节点使用两块磁盘
minio_node : '${minio_cluster}-${minio_seq}.pigsty' # 节点名称的模式
haproxy_services :
- name : minio # [必选] 服务名称,需要唯一
port : 9002 # [必选] 服务端口,需要唯一
options :
- option httpchk
- option http-keep-alive
- http-check send meth OPTIONS uri /minio/health/live
- http-check expect status 200
servers :
- { name: minio-1 ,ip: 10.10.10.10 , port: 9000 , options : 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
- { name: minio-2 ,ip: 10.10.10.11 , port: 9000 , options : 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
- { name: minio-3 ,ip: 10.10.10.12 , port: 9000 , options : 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
3.1 - 配置清单 使用声明式的配置文件描述你需要的基础设施与集群
每一套 Pigsty 部署都对应着一份 配置清单 (Inventory),描述了基础设施与数据库集群的关键属性。
配置文件 Pigsty 默认使用 Ansible YAML 配置格式 ,
使用一个单一 YAML 配置文件 pigsty.yml 作为配置清单。
~/pigsty
^---- pigsty.yml # <---- 默认配置文件
您可以直接修改该配置文件来定制您的部署,或者使用 Pigsty 提供的 配置向导 configure 脚本自动生成合适的配置文件。
配置结构 配置清单使用标准的 Ansible YAML 配置格式 ,由两部分组成:全局参数 (all.vars)和多个 组 (all.children)。
您可以在 all.children 中定义新集群,并使用全局变量描述基础设施:all.vars,它看起来像这样:
all : # 顶级对象:all
vars : {...} # 全局参数
children : # 组定义
infra : # 组定义:'infra'
hosts : {...} # 组成员:'infra'
vars : {...} # 组参数:'infra'
etcd : {...} # 组定义:'etcd'
pg-meta : {...} # 组定义:'pg-meta'
pg-test : {...} # 组定义:'pg-test'
redis-test : {...} # 组定义:'redis-test'
# ...
集群定义 每个 Ansible 组可能代表一个集群,可以是节点集群、PostgreSQL 集群、Redis 集群、Etcd 集群或 MinIO 集群等…
集群定义由两部分组成:集群成员 (hosts )与 集群参数 (vars )。
您可以在 <cls>.hosts 中定义集群成员,并在 <cls>.vars 中使用 配置参数 描述集群。
下面是一个 3 节点高可用 PostgreSQL 集群的定义示例:
all :
children : # ansible 组列表
pg-test : # ansible 组名
hosts : # ansible 组内实例(集群成员)
10.10.10.11 : { pg_seq: 1, pg_role : primary } # 主机 1
10.10.10.12 : { pg_seq: 2, pg_role : replica } # 主机 2
10.10.10.13 : { pg_seq: 3, pg_role : offline } # 主机 3
vars : # ansible 组变量(集群参数)
pg_cluster : pg-test
集群级别的 vars (集群参数)将覆盖全局参数,实例级别的 vars 将覆盖集群参数和全局参数。
拆分配置 如果您的部署规模较大,或者希望更好地组织配置文件,
可以将配置清单 拆分为多个文件 ,便于管理与维护。
inventory/
├── hosts.yml # 主机和集群定义
├── group_vars/
│ ├── all.yml # 全局默认变量 (对应 all.vars)
│ ├── infra.yml # infra 组变量
│ ├── etcd.yml # etcd 组变量
│ └── pg-meta.yml # pg-meta 集群变量
└── host_vars/
├── 10.10.10.10.yml # 特定主机变量
└── 10.10.10.11.yml
您可以将集群成员定义放在 hosts.yml 文件中,将集群层面的 配置参数 放在 group_vars 目录下的对应文件中。
切换配置 您可以在执行剧本的时候,通过 -i 参数,临时指定另外的配置清单文件。
./pgsql.yml -i another_config.yml
./infra.yml -i nginx_config.yml
此外,Ansible 支持多种配置方式,您可以使用本地 yaml|ini 配置文件,或者是 CMDB 与任意的动态配置脚本作为配置源。
在 Pigsty 中,我们通过 Pigsty 主目录中的 ansible.cfg
指定同目录下的 pigsty.yml 作为默认的 配置清单 ,您可按需修改。
[defaults]
inventory = pigsty.yml
此外,Pigsty 还支持使用 CMDB 元数据库 来存储配置清单,便于与现有系统对接整合。
3.2 - 配置向导 使用 configure 脚本根据当前环境自动生成推荐的配置文件。
Pigsty 提供了一个 configure 脚本作为 配置向导 ,它能根据当前环境,自动生成合适的 pigsty.yml 配置文件。
这是一个 可选 的脚本:如果您已经了解了如何配置 Pigsty,大可以直接编辑 pigsty.yml 配置文件,跳过向导。
快速开始 进入 pigsty 源码家目录中,执行 ./configure 即可自动运行配置向导。不带任何参数时,默认使用 meta 单节点配置模板:
cd ~/pigsty
./configure # 交互式配置向导,自动检测环境并生成配置
该命令会以选定的模板为基础,检测当前节点的 IP 地址与区域,并生成适合当前环境的 pigsty.yml 配置文件。
功能说明 configure 脚本会根据环境与输入执行以下调整,并在当前目录下生成 pigsty.yml 配置文件。
检测当前节点 IP 地址,如果有多个 IP,则要求用户输入一个 首要的 IP 地址 作为当前节点的身份标识 使用 IP 地址替换配置模板中的占位符 10.10.10.10 ,并将其配置为 admin_ip 参数的值。 检测当前区域,将 region 设置为 default (全球默认仓库)或 china (使用中国镜像仓库) 针对小微实例(vCPU < 4),为 node_tune 和 pg_conf 参数使用 tiny 参数模板,优化资源使用。 如果指定了 -v PG 大版本,将 pg_version 以及所有 PG 别名参数设置为对应大版本。 如果指定了 -g 参数,将所有默认密码替换为随机生成的强密码,提升安全性。(强烈推荐 ) 当 PG 大版本 ≥ 17 时优先使用内置的 C.UTF-8 Locale,次选由操作系统支持的 C.UTF-8 。 检测当前环境中,用于执行部署的核心依赖 ansible 是否可用 同时检测部署目标节点是否 ssh 可达,并可以使用 sudo 执行命令。(-s 跳过) 使用示例 # 基本用法
./configure # 交互式配置向导
./configure -i 10.10.10.10 # 指定主 IP 地址
# 指定配置模板
./configure -c meta # 使用默认单节点模板(默认)
./configure -c rich # 使用功能丰富的单节点模板
./configure -c slim # 使用精简模板(仅 PGSQL + ETCD)
./configure -c ha/full # 使用 4 节点高可用沙箱模板
./configure -c ha/trio # 使用 3 节点高可用模板
./configure -c app/supa # 使用 Supabase 自托管模板
# 指定 PostgreSQL 版本
./configure -v 17 # 使用 PostgreSQL 17
./configure -v 16 # 使用 PostgreSQL 16
./configure -c rich -v 16 # rich 模板 + PG 16
# 区域与代理
./configure -r china # 使用中国镜像源
./configure -r europe # 使用欧洲镜像源
./configure -x # 导入当前代理环境变量
# 跳过与自动化
./configure -s # 跳过 IP 探测,保留占位符
./configure -n -i 10.10.10.10 # 非交互模式,指定 IP
./configure -c ha/full -s # 4 节点模板,跳过 IP 替换
# 安全增强
./configure -g # 生成随机密码
./configure -c meta -g -i 10.10.10.10 # 完整生产配置
# 指定输出与 SSH 端口
./configure -o prod.yml # 输出到 prod.yml
./configure -p 2222 # 使用 SSH 端口 2222
命令参数 ./configure
[ -c| --conf <template>] # 配置模板名称(meta|rich|slim|ha/full|...)
[ -i| --ip <ipaddr>] # 指定主 IP 地址
[ -v| --version <pgver>] # PostgreSQL 大版本号(13|14|15|16|17|18)
[ -r| --region <region>] # 上游软件仓库区域(default|china|europe)
[ -o| --output <file>] # 输出配置文件路径(默认:pigsty.yml)
[ -s| --skip] # 跳过 IP 地址探测与替换
[ -x| --proxy] # 从环境变量导入代理设置
[ -n| --non-interactive] # 非交互模式(不询问任何问题)
[ -p| --port <port>] # 指定 SSH 端口
[ -g| --generate] # 生成随机密码
[ -h| --help] # 显示帮助信息
参数详解 参数 说明 -c, --conf从 conf/<template>.yml 生成配置文件,支持子目录如 ha/full -i, --ip用指定 IP 替换配置模板中的占位符 10.10.10.10 -v, --version指定 PostgreSQL 大版本号(13-18),不指定时保持模板默认值 -r, --region设置软件仓库镜像区域:default(默认)、china(中国镜像)、europe(欧洲镜像) -o, --output指定输出文件路径,默认为 pigsty.yml -s, --skip跳过 IP 地址探测与替换,保留模板中的 10.10.10.10 占位符 -x, --proxy将当前环境的代理变量(HTTP_PROXY、HTTPS_PROXY、ALL_PROXY、NO_PROXY)写入配置 -n, --non-interactive非交互模式,不询问任何问题(需配合 -i 指定 IP) -p, --port指定 SSH 端口(非默认 22 端口时使用) -g, --generate为配置文件中的密码生成随机值,提高安全性(强烈推荐)
执行流程 configure 脚本按照以下顺序执行检测与配置:
┌─────────────────────────────────────────────────────────────┐
│ configure 执行流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. check_region 检测网络区域(GFW 检测) │
│ ↓ │
│ 2. check_version 验证 PostgreSQL 版本号 │
│ ↓ │
│ 3. check_kernel 检测操作系统内核(Linux/Darwin) │
│ ↓ │
│ 4. check_machine 检测 CPU 架构(x86_64/aarch64) │
│ ↓ │
│ 5. check_package_manager 检测包管理器(dnf/yum/apt) │
│ ↓ │
│ 6. check_vendor_version 检测 OS 发行版与版本 │
│ ↓ │
│ 7. check_sudo 检测免密 sudo 权限 │
│ ↓ │
│ 8. check_ssh 检测免密 SSH 到本机 │
│ ↓ │
│ 9. check_proxy 处理代理环境变量 │
│ ↓ │
│ 10. check_ipaddr 探测/输入主 IP 地址 │
│ ↓ │
│ 11. check_admin 验证管理员 SSH + Sudo 权限 │
│ ↓ │
│ 12. check_conf 选择配置模板 │
│ ↓ │
│ 13. check_config 生成配置文件 │
│ ↓ │
│ 14. check_utils 检测 Ansible 等工具是否安装 │
│ ↓ │
│ ✓ 配置完成,输出 pigsty.yml │
│ │
└─────────────────────────────────────────────────────────────┘
自动化行为 区域检测 脚本会自动检测网络环境,判断是否在中国大陆(GFW 内):
# 通过访问 Google 判断网络环境
curl -I -s --connect-timeout 1 www.google.com
如果无法访问 Google,自动设置 region: china 使用国内镜像 如果可以访问,使用 region: default 默认镜像 可通过 -r 参数手动指定区域 IP 地址处理 脚本按以下优先级确定主 IP 地址:
命令行参数 :如果通过 -i 指定了 IP,直接使用单 IP 探测 :如果当前节点只有一个 IP,自动使用演示 IP 检测 :如果检测到 10.10.10.10,自动选择(用于沙箱环境)交互式输入 :多个 IP 时,提示用户选择或输入[ WARN] Multiple IP address candidates found:
( 1) 192.168.1.100 inet 192.168.1.100/24 scope global eth0
( 2) 10.10.10.10 inet 10.10.10.10/24 scope global eth1
[ IN ] INPUT primary_ip address ( of current meta node, e.g 10.10.10.10) :
= > 10.10.10.10
低端硬件优化 当检测到 CPU 核心数 ≤ 4 时,脚本会自动调整配置:
[ WARN] replace oltp template with tiny due to cpu < 4
这样可以确保在低配虚拟机上也能顺利运行。
Locale 设置 脚本会在以下情况自动启用 C.UTF-8 作为默认 Locale:
PostgreSQL 版本 ≥ 17(内置 Locale Provider 支持) 或者 当前系统支持 C.UTF-8 / C.utf8 Localepg_locale : C.UTF-8
pg_lc_collate : C.UTF-8
pg_lc_ctype : C.UTF-8
中国区特殊处理 当区域设置为 china 时,脚本会自动:
启用 docker_registry_mirrors Docker 镜像加速 启用 PIP_MIRROR_URL Python 镜像加速 密码生成 使用 -g 参数时,脚本会为以下密码生成 24 位随机字符串:
密码参数 说明 grafana_admin_passwordGrafana 管理员密码 pg_admin_passwordPostgreSQL 管理员密码 pg_monitor_passwordPostgreSQL 监控用户密码 pg_replication_passwordPostgreSQL 复制用户密码 patroni_passwordPatroni API 密码 haproxy_admin_passwordHAProxy 管理密码 minio_secret_keyMinIO Secret Key etcd_root_passwordETCD Root 密码
同时还会替换以下占位符密码:
DBUser.Meta → 随机密码DBUser.Viewer → 随机密码S3User.Backup → 随机密码S3User.Meta → 随机密码S3User.Data → 随机密码$ ./configure -g
[ INFO] generating random passwords...
grafana_admin_password : xK9mL2nP4qR7sT1vW3yZ5bD8
pg_admin_password : aB3cD5eF7gH9iJ1kL2mN4oP6
...
[ INFO] random passwords generated, check and save them
配置模板 脚本从 conf/ 目录读取配置模板,支持以下模板:
核心模板 模板 说明 meta默认模板 :单节点安装,包含 INFRA + NODE + ETCD + PGSQLrich功能丰富版:包含几乎所有扩展、MinIO、本地仓库 slim精简版:仅 PostgreSQL + ETCD,无监控基础设施 fat完整版:rich 基础上安装更多扩展 pgsql纯 PostgreSQL 模板 infra纯基础设施模板
高可用模板 (ha/) 模板 说明 ha/dual2 节点高可用集群 ha/trio3 节点高可用集群 ha/full4 节点完整沙箱环境 ha/safe安全加固版高可用配置 ha/simu42 节点大规模仿真环境
应用模板 (app/) 模板 说明 supabaseSupabase 自托管配置 app/difyDify AI 平台配置 app/odooOdoo ERP 配置 app/teableTeable 表格数据库配置 app/registryDocker Registry 配置
特殊内核模板 模板 说明 ivoryIvorySQL:Oracle 兼容 PostgreSQL mssqlBabelfish:SQL Server 兼容 PostgreSQL polarPolarDB:阿里云开源分布式 PostgreSQL citusCitus:分布式 PostgreSQL orioleOrioleDB:新一代存储引擎
演示模板 (demo/) 模板 说明 demo/demo演示环境配置 demo/redisRedis 集群演示 demo/minioMinIO 集群演示
输出示例 $ ./configure
configure pigsty v4.0.0 begin
[ OK ] region = china
[ OK ] kernel = Linux
[ OK ] machine = x86_64
[ OK ] package = rpm,dnf
[ OK ] vendor = rocky ( Rocky Linux)
[ OK ] version = 9 ( 9.5)
[ OK ] sudo = vagrant ok
[ OK ] ssh = vagrant@127.0.0.1 ok
[ WARN] Multiple IP address candidates found:
( 1) 192.168.121.193 inet 192.168.121.193/24 brd 192.168.121.255 scope global dynamic noprefixroute eth0
( 2) 10.10.10.10 inet 10.10.10.10/24 brd 10.10.10.255 scope global noprefixroute eth1
[ OK ] primary_ip = 10.10.10.10 ( from demo)
[ OK ] admin = vagrant@10.10.10.10 ok
[ OK ] mode = meta ( el9)
[ OK ] locale = C.UTF-8
[ OK ] ansible = ready
[ OK ] pigsty configured
[ WARN] don' t forget to check it and change passwords!
proceed with ./deploy.yml
环境变量 脚本支持以下环境变量:
环境变量 说明 默认值 PIGSTY_HOMEPigsty 安装目录 ~/pigstyMETADB_URL元数据库连接 URL service=metaHTTP_PROXYHTTP 代理 - HTTPS_PROXYHTTPS 代理 - ALL_PROXY通用代理 - NO_PROXY代理白名单 内置默认值
注意事项 免密访问 :运行 configure 前,确保当前用户具有免密 sudo 权限和免密 SSH 到本机的能力。可以通过 bootstrap 脚本自动配置。
IP 地址选择 :请选择内网 IP 作为主 IP 地址,不要使用公网 IP 或 127.0.0.1。
密码安全 :生产环境务必 修改配置文件中的默认密码,或使用 -g 参数生成随机密码。
配置检查 :脚本执行完成后,建议检查生成的 pigsty.yml 文件,确认配置符合预期。
多次执行 :可以多次运行 configure 重新生成配置,每次会覆盖现有的 pigsty.yml。
macOS 限制 :在 macOS 上运行时,脚本会跳过部分 Linux 特有的检测,并使用占位符 IP 10.10.10.10。macOS 只能作为管理节点使用。
常见问题 如何使用自定义配置模板? 将您的配置文件放到 conf/ 目录下,然后使用 -c 参数指定:
cp my-config.yml ~/pigsty/conf/myconf.yml
./configure -c myconf
如何为多集群生成不同配置? 使用 -o 参数指定不同的输出文件:
./configure -c ha/full -o cluster-a.yml
./configure -c ha/trio -o cluster-b.yml
然后在执行剧本时指定配置文件:
./deploy.yml -i cluster-a.yml
非交互模式下如何处理多 IP? 必须使用 -i 参数明确指定 IP 地址:
./configure -n -i 10.10.10.10
如何保留模板中的占位符 IP? 使用 -s 参数跳过 IP 替换:
./configure -c ha/full -s # 保留 10.10.10.10 占位符
相关文档 配置清单 :了解 Ansible 配置清单的结构配置参数 :了解 Pigsty 参数的层级与优先级配置模板 :查看所有可用的配置模板安装部署 :了解完整的安装流程元数据库 :使用 PostgreSQL 作为动态配置源3.3 - 配置参数 使用配置参数对 Pigsty 进行精细化定制
在 配置清单 中,您可以使用各种参数对 Pigsty 进行精细化定制。这些参数涵盖了从基础设施设置到数据库配置的各个方面。
参数列表 Pigsty 提供了约 380+ 个配置参数,分布在 8 个默认模块中,用于精细控制系统的各个方面,完整列表见 参考-参数列表 。
模块 参数组 参数数 说明 PGSQL 9 123 PostgreSQL 数据库集群的核心配置 INFRA 10 82 基础设施组件:软件源、Nginx、DNS、监控、Grafana 等 NODE 11 83 主机节点调优:身份、DNS、包、调优、安全、管理员、时间、VIP等 ETCD 2 13 分布式配置存储与服务发现 REDIS 1 21 Redis 缓存与数据结构服务器 MINIO 2 21 S3 兼容对象存储服务 FERRET 1 9 MongoDB 兼容数据库 FerretDB DOCKER 1 8 Docker 容器引擎
参数形式 参数 是用于描述实体的 键值对 。键 (Key)是字符串,值 (Value)可以是五种类型之一:布尔值、字符串、数字、数组或对象。
all : # <------- 顶级对象:all
vars :
admin_ip : 10.10.10.10 # <------- 全局配置参数
children :
pg-meta : # <------- pg-meta 分组
vars :
pg_cluster : pg-meta # <------- 集群级别参数
hosts :
10.10.10.10 : # <------- 主机节点 IP
pg_seq : 1
pg_role : primary # <------- 实例级别参数
参数优先级 参数可以在不同级别设置,具有以下优先级:
级别 位置 描述 优先级 命令行 -e 命令行参数通过命令行传入 最高 (5) 主机/实例 <group>.hosts.<host>特定于单个主机的参数 较高 (4) 分组/集群 <group>.vars组/集群中主机共享的参数 中等 (3) 全局 all.vars所有主机共享的参数 较低 (2) 默认 <roles>/default/main.yml角色实现默认值 最低 (1)
以下是关于参数优先级的一些示例:
执行剧本时,使用命令行参数 -e grafana_clean=true 来抹除 Grafana 数据 使用主机变量上的实例级别参数 pg_role 覆盖 pg 实例角色 使用组变量上的集群级别参数 pg_cluster 覆盖 pg 集群名称。 使用全局变量上的全局参数 node_ntp_servers 指定全局 NTP 服务器 如果没有设置 pg_version ,Pigsty 将使用 pgsql 角色实现的默认值(默认为 18) 除了身份参数 外,每个参数都有适当的默认值,因此无需显式设置。
身份参数 身份参数是特殊的参数,它们会作为实体的 ID 标识符,因此 没有默认值 ,必须 显式设置 。
模块 身份参数 PGSQLpg_cluster, pg_seq, pg_role, …NODEnodename, node_clusterETCDetcd_cluster, etcd_seqMINIOminio_cluster, minio_seqREDISredis_cluster, redis_node, redis_instancesINFRAinfra_seq
例外是,etcd_cluster 与 minio_cluster 有默认值。
它假设每套部署只有一套 etcd 集群用于 DCS,和一套可选 MinIO 集群用于集中备份存储,因此为其分配了默认的集群名称 etcd 与 minio。
但您依然可以使用其他名称部署多套 etcd 或 MinIO 集群。
3.4 - 配置模板 使用预制的配置模板,快速生成适配当前环境的配置文件
在 Pigsty 中,部署的蓝图细节由 配置清单 所定义,也就是 pigsty.yml 配置文件,您可以通过声明式配置进行定制。
然而,直接编写配置文件可能会让新用户望而生畏。为此,我们提供了一些开箱即用的配置模板,涵盖了常见的使用场景。
每一个模板都是一个预定义的 pigsty.yml 配置文件,包含了适用于特定场景的合理默认值。
您可以根据自己的需要,选择一个模板作为定制起点,然后根据需要进行修改,以满足您的具体需求。
使用模板 Pigsty 提供了 configure 脚本作为可选的配置向导,它将根据您的环境和输入,生成具有良好默认值的 配置清单 。
使用 ./configure -c <conf> 指定配置模板,其中 <conf> 是相对于 conf 目录的路径(可省略 .yml 后缀)。
./configure # 默认使用 meta.yml 配置模板
./configure -c meta # 显式指定使用 meta.yml 单节点模板
./configure -c rich # 使用包含全部扩展与 MinIO 的富功能模板
./configure -c slim # 使用最小化的单节点模板
# 使用不同的数据库内核
./configure -c pgsql # 原生 PostgreSQL 内核,基础功能 (13~18)
./configure -c citus # Citus 分布式高可用 PostgreSQL (14~17)
./configure -c mssql # Babelfish 内核,兼容 SQL Server 协议 (15)
./configure -c polar # PolarDB PG 内核,Aurora/RAC 风格 (15)
./configure -c ivory # IvorySQL 内核,兼容 Oracle 语法 (18)
./configure -c mysql # OpenHalo 内核,兼容 MySQL (14)
./configure -c pgtde # Percona PostgreSQL Server 透明加密 (18)
./configure -c oriole # OrioleDB 内核,OLTP 增强 (17)
./configure -c supabase # Supabase 自托管配置 (15~18)
# 使用多节点高可用模板
./configure -c ha/dual # 使用 2 节点高可用模板
./configure -c ha/trio # 使用 3 节点高可用模板
./configure -c ha/full # 使用 4 节点高可用模板
如果不指定模板,Pigsty 默认使用 meta.yml 单节点配置模板。
模板列表 主要模板 以下是单节点配置模板,可用于在单台服务器上安装 Pigsty:
数据库内核模板 适用于各类数据库管理系统与内核的模板:
您可以后续添加更多节点,或使用 高可用模板 在一开始就规划好集群。
高可用模板 您可以配置 Pigsty 在多节点上运行,组成高可用(HA)集群:
应用模板 您可以使用以下模板运行 Docker 应用/软件:
演示模板 除主要模板外,Pigsty 还提供了一组面向不同场景的演示模板:
构建模板 以下配置模板用于开发和测试目的:
模板 说明 build.ymlEL 9/10、Debian 12/13、Ubuntu 22.04/24.04 开源构建配置
3.5 - 元数据库 使用 PostgreSQL 作为 CMDB 元数据库,存储 Ansible 配置清单。
Pigsty 允许您使用 PostgreSQL 元数据库 作为动态配置源,取代静态的 YAML 配置文件,实现更强大的配置管理能力。
概览 CMDB (Configuration Management Database,配置管理数据库)是一种将配置信息存储在数据库中进行管理的方式。
在 Pigsty 中,默认的配置源是一个静态 YAML 文件 pigsty.yml,
它作为 Ansible 的 配置清单 使用。
这种方式简单直接,但当基础设施规模扩大、需要复杂精细的管理与外部集成时,单一的静态文件难以满足需求。
特性 静态 YAML 文件 CMDB 元数据库 查询能力 手工搜索/grep SQL 任意条件查询,聚合分析 版本控制 依赖 Git 或手工备份 数据库事务,审计日志,时间旅行快照 权限控制 文件系统权限,粗粒度 PostgreSQL 数据库精细访问控制 并发编辑 需要锁文件或合并冲突 数据库事务天然支持并发 外部集成 需要解析 YAML 标准 SQL 接口,任意语言轻松对接 规模扩展 文件过大时难以维护 管理规模伸缩至物理极限 动态生成 静态文件,修改后需手动应用 即时生效,实时反映配置变更
Pigsty 在样板数据库 pg-meta.meta 的模式基线定义中,提供了 Pigsty CMDB 的数据库模式。
工作原理 CMDB 的核心思想是用一个 动态脚本 替换静态配置文件。
Ansible 支持使用可执行脚本作为配置清单,只要脚本输出符合 JSON 格式的清单数据即可。
当您启用 CMDB 后,Pigsty 会创建一个名为 inventory.sh 的动态清单脚本:
#!/bin/bash
psql ${ METADB_URL } -AXtwc 'SELECT text FROM pigsty.inventory;'
这个脚本的作用很简单:每次 Ansible 需要读取配置清单时,它会从 PostgreSQL 数据库的 pigsty.inventory 视图中查询配置数据,并以 JSON 格式返回。
整体架构如下:
flowchart LR
conf["bin/inventory_conf"]
tocmdb["bin/inventory_cmdb"]
load["bin/inventory_load"]
ansible["🚀 Ansible"]
subgraph static["📄 静态配置模式"]
yml[("pigsty.yml")]
end
subgraph dynamic["🗄️ CMDB 动态模式"]
sh["inventory.sh"]
cmdb[("PostgreSQL CMDB")]
end
conf -->|"切换"| yml
yml -->|"加载配置"| load
load -->|"写入"| cmdb
tocmdb -->|"切换"| sh
sh --> cmdb
yml --> ansible
cmdb --> ansible 数据模型 CMDB 的数据库模式定义在 files/cmdb.sql 文件中,所有对象都位于 pigsty 模式下。
核心数据表 表名 说明 主键 pigsty.group集群/分组定义,对应 Ansible 的 group clspigsty.host主机定义,属于某个分组 (cls, ip)pigsty.global_var全局变量,对应 all.vars keypigsty.group_var分组变量,对应 all.children.<cls>.vars (cls, key)pigsty.host_var主机变量,对应主机级别的变量 (cls, ip, key)pigsty.default_var默认变量定义,存储参数的元信息 keypigsty.job作业记录表,记录执行的任务 id
表结构详解 集群表 pigsty.group
CREATE TABLE pigsty . group (
cls TEXT PRIMARY KEY , -- 集群名称,主键
ctime TIMESTAMPTZ DEFAULT now (), -- 创建时间
mtime TIMESTAMPTZ DEFAULT now () -- 修改时间
);
主机表 pigsty.host
CREATE TABLE pigsty . host (
cls TEXT NOT NULL REFERENCES pigsty . group ( cls ), -- 所属集群
ip INET NOT NULL , -- 主机 IP 地址
ctime TIMESTAMPTZ DEFAULT now (),
mtime TIMESTAMPTZ DEFAULT now (),
PRIMARY KEY ( cls , ip )
);
全局变量表 pigsty.global_var
CREATE TABLE pigsty . global_var (
key TEXT PRIMARY KEY , -- 变量名
value JSONB NULL , -- 变量值(JSON 格式)
mtime TIMESTAMPTZ DEFAULT now () -- 修改时间
);
分组变量表 pigsty.group_var
CREATE TABLE pigsty . group_var (
cls TEXT NOT NULL REFERENCES pigsty . group ( cls ),
key TEXT NOT NULL ,
value JSONB NULL ,
mtime TIMESTAMPTZ DEFAULT now (),
PRIMARY KEY ( cls , key )
);
主机变量表 pigsty.host_var
CREATE TABLE pigsty . host_var (
cls TEXT NOT NULL ,
ip INET NOT NULL ,
key TEXT NOT NULL ,
value JSONB NULL ,
mtime TIMESTAMPTZ DEFAULT now (),
PRIMARY KEY ( cls , ip , key ),
FOREIGN KEY ( cls , ip ) REFERENCES pigsty . host ( cls , ip )
);
核心视图 CMDB 提供了一系列视图,用于查询和展示配置数据:
视图名 说明 pigsty.inventory核心视图 :生成 Ansible 动态清单 JSONpigsty.raw_config原始配置的 JSON 格式展示 pigsty.global_config全局配置视图,合并默认值和全局变量 pigsty.group_config分组配置视图,包含主机列表和分组变量 pigsty.host_config主机配置视图,合并分组和主机级别变量 pigsty.pg_clusterPostgreSQL 集群视图 pigsty.pg_instancePostgreSQL 实例视图 pigsty.pg_databasePostgreSQL 数据库定义视图 pigsty.pg_usersPostgreSQL 用户定义视图 pigsty.pg_servicePostgreSQL 服务定义视图 pigsty.pg_hbaPostgreSQL HBA 规则视图 pigsty.pg_remote远程 PostgreSQL 实例视图
pigsty.inventory 是最核心的视图,它将数据库中的配置数据转换为 Ansible 所需的 JSON 格式:
SELECT text FROM pigsty . inventory ;
工具脚本 Pigsty 提供了三个便利脚本来管理 CMDB:
inventory_load 将 YAML 配置文件解析并导入到 CMDB 中:
bin/inventory_load # 加载默认的 pigsty.yml 到默认 CMDB
bin/inventory_load -p /path/to/conf.yml # 指定配置文件路径
bin/inventory_load -d "postgres://..." # 指定数据库连接 URL
bin/inventory_load -n myconfig # 指定配置名称
脚本会执行以下操作:
清空 pigsty 模式中的现有数据 解析 YAML 配置文件 将全局变量写入 global_var 表 将集群定义写入 group 表 将集群变量写入 group_var 表 将主机定义写入 host 表 将主机变量写入 host_var 表 环境变量
PIGSTY_HOME:Pigsty 安装目录,默认为 ~/pigstyMETADB_URL:数据库连接 URL,默认为 service=metainventory_cmdb 切换 Ansible 使用 CMDB 作为配置源:
脚本会执行以下操作:
创建动态清单脚本 ${PIGSTY_HOME}/inventory.sh 修改 ansible.cfg 将 inventory 设置为 inventory.sh 生成的 inventory.sh 内容如下:
#!/bin/bash
psql ${ METADB_URL } -AXtwc 'SELECT text FROM pigsty.inventory;'
inventory_conf 切换回使用静态 YAML 配置文件:
脚本会修改 ansible.cfg 将 inventory 设置回 pigsty.yml。
使用流程 首次启用 CMDB 初始化 CMDB 模式 (通常在安装 Pigsty 时已自动完成):psql -f ~/pigsty/files/cmdb.sql
加载配置到数据库 :切换到 CMDB 模式 :验证配置 :ansible all --list-hosts # 列出所有主机
ansible-inventory --list # 查看完整清单
查询配置 启用 CMDB 后,您可以使用 SQL 灵活查询配置:
-- 查看所有集群
SELECT cls FROM pigsty . group ;
-- 查看某集群的所有主机
SELECT ip FROM pigsty . host WHERE cls = 'pg-meta' ;
-- 查看全局变量
SELECT key , value FROM pigsty . global_var ;
-- 查看某集群的变量
SELECT key , value FROM pigsty . group_var WHERE cls = 'pg-meta' ;
-- 查看所有 PostgreSQL 集群
SELECT cls , name , pg_databases , pg_users FROM pigsty . pg_cluster ;
-- 查看所有 PostgreSQL 实例
SELECT cls , ins , ip , seq , role FROM pigsty . pg_instance ;
-- 查看所有数据库定义
SELECT cls , datname , owner , encoding FROM pigsty . pg_database ;
-- 查看所有用户定义
SELECT cls , name , login , superuser FROM pigsty . pg_users ;
修改配置 您可以直接通过 SQL 修改配置:
-- 添加新集群
INSERT INTO pigsty . group ( cls ) VALUES ( 'pg-new' );
-- 添加集群变量
INSERT INTO pigsty . group_var ( cls , key , value )
VALUES ( 'pg-new' , 'pg_cluster' , '"pg-new"' );
-- 添加主机
INSERT INTO pigsty . host ( cls , ip ) VALUES ( 'pg-new' , '10.10.10.20' );
-- 添加主机变量
INSERT INTO pigsty . host_var ( cls , ip , key , value )
VALUES ( 'pg-new' , '10.10.10.20' , 'pg_seq' , '1' ),
( 'pg-new' , '10.10.10.20' , 'pg_role' , '"primary"' );
-- 修改全局变量
UPDATE pigsty . global_var SET value = '"new-value"' WHERE key = 'some_param' ;
-- 删除集群(级联删除主机和变量)
DELETE FROM pigsty . group WHERE cls = 'pg-old' ;
修改后立即生效,无需重新加载或重启任何服务。
切换回静态配置 如需切换回静态配置文件模式:
高级用法 配置导出 将 CMDB 中的配置导出为 YAML 格式:
psql service = meta -AXtwc "SELECT jsonb_pretty(jsonb_build_object('all', jsonb_build_object('children', children, 'vars', vars))) FROM pigsty.raw_config;"
或者使用 ansible-inventory 命令:
ansible-inventory --list --yaml > exported_config.yml
配置审计 利用 mtime 字段追踪配置变更:
-- 查看最近修改的全局变量
SELECT key , value , mtime FROM pigsty . global_var
ORDER BY mtime DESC LIMIT 10 ;
-- 查看某时间点之后的变更
SELECT * FROM pigsty . group_var
WHERE mtime > '2024-01-01' :: timestamptz ;
与外部系统集成 CMDB 使用标准 PostgreSQL,可以轻松与其他系统集成:
Web 管理界面 :通过 REST API(如 PostgREST)暴露配置数据CI/CD 流水线 :在部署脚本中直接读写数据库监控告警 :基于配置数据生成监控规则ITSM 系统 :与企业 CMDB 系统同步注意事项 数据一致性 :修改配置后,需要重新执行相应的 Ansible 剧本才能将变更应用到实际环境
备份 :CMDB 中的配置数据非常重要,请确保定期备份
权限 :建议为 CMDB 配置适当的数据库访问权限,避免误操作
事务 :批量修改配置时,建议在事务中进行,以便出错时回滚
连接池 :inventory.sh 脚本每次执行都会建立新连接,如果 Ansible 执行频繁,建议考虑使用连接池
小结 CMDB 是 Pigsty 配置管理的高级方案,适用于需要管理大量集群、复杂查询、外部集成或精细权限控制的场景。通过将配置数据存储在 PostgreSQL 中,您可以充分利用数据库的强大能力来管理基础设施配置。
功能 说明 数据存储 PostgreSQL pigsty 模式 动态清单 inventory.sh 脚本配置加载 bin/inventory_load切换到 CMDB bin/inventory_cmdb切换到 YAML bin/inventory_conf核心视图 pigsty.inventory
4 - PG 高可用 Pigsty 使用 Patroni 实现了 PostgreSQL 的高可用,确保主库不可用时自动进行故障转移,由从库接管。
概览 Pigsty 的 PostgreSQL 集群带有开箱即用的高可用方案,由 Patroni 、Etcd 和 HAProxy 强力驱动。
当您的 PostgreSQL 集群含有两个或更多实例时,您无需任何配置即拥有了硬件故障自愈的数据库高可用能力 —— 只要集群中有任意实例存活,集群就可以对外提供完整的服务,而客户端只要连接至集群中的任意节点,即可获得完整的服务,而无需关心主从拓扑变化。
在默认配置下,主库故障恢复时间目标 RTO ≈ 45s,数据恢复点目标 RPO < 1MB;从库故障 RPO = 0,RTO ≈ 0 (闪断);在一致性优先模式下,可确保故障切换数据零损失:
RPO = 0。以上指标均可通过参数,根据您的实际硬件条件与可靠性要求 按需配置 。
Pigsty 内置了 HAProxy 负载均衡器用于自动流量切换,提供 DNS/VIP/LVS 等多种接入方式供客户端选用。故障切换与主动切换对业务侧除零星闪断外几乎无感知,应用不需要修改连接串重启。
极小的维护窗口需求带来了极大的灵活便利:您完全可以在无需应用配合的情况下滚动维护升级整个集群。硬件故障可以等到第二天再抽空善后处置的特性,让研发,运维与 DBA 都能在故障时安心睡个好觉。
许多大型组织与核心机构已经在生产环境中长时间使用 Pigsty ,最大的部署有 25K CPU 核心与 220+ PostgreSQL 超大规格实例(64c / 512g / 3TB NVMe SSD);在这一部署案例中,五年内经历了数十次硬件故障与各类事故,但依然可以保持高于 99.999% 的总体可用性战绩。
高可用(High-Availability)解决什么问题?
将数据安全C/IA中的可用性提高到一个新高度:RPO ≈ 0, RTO < 45s。 获得无缝滚动维护的能力,最小化维护窗口需求,带来极大便利。 硬件故障可以立即自愈,无需人工介入,运维DBA可以睡个好觉。 从库可以用于承载只读请求,分担主库负载,让资源得以充分利用。 高可用有什么代价?
基础设施依赖:高可用需要依赖 DCS (etcd/zk/consul) 提供共识。 起步门槛增加:一个有意义的高可用部署环境至少需要 三个节点 。 额外的资源消耗:一个新从库就要消耗一份额外资源,不算大问题。 复杂度代价显著升高:备份成本显著加大,需要使用工具压制复杂度。 高可用的局限性
因为复制实时进⾏,所有变更被⽴即应⽤⾄从库。因此基于流复制的高可用方案⽆法应对⼈为错误与软件缺陷导致的数据误删误改。(例如:DROP TABLE,或 DELETE 数据)
此类故障需要使用 延迟集群 ,或使用先前的基础备份与 WAL 归档进行 时间点恢复 。
配置策略 RTO RPO 单机 + 什么也不做 数据永久丢失,无法恢复 数据全部丢失 单机 + 基础备份 取决于备份大小与带宽(几小时) 丢失上一次备份后的数据(几个小时到几天)单机 + 基础备份 + WAL归档 取决于备份大小与带宽(几小时) 丢失最后尚未归档的数据(几十MB)主从 + 手工故障切换 十分钟 丢失复制延迟中的数据(约百KB)主从 + 自动故障切换 一分钟内 丢失复制延迟中的数据(约百KB)主从 + 自动故障切换 + 同步提交 一分钟内 无数据丢失
原理 在 Pigsty 中,高可用架构的实现原理如下:
PostgreSQL 使⽤标准流复制搭建物理从库,主库故障时由从库接管。 Patroni 负责管理 PostgreSQL 服务器进程,处理高可用相关事宜。 Etcd 提供分布式配置存储(DCS)能力,并用于故障后的领导者选举 Patroni 依赖 Etcd 达成集群领导者共识,并对外提供健康检查接口。 HAProxy 对外暴露集群服务,并利⽤ Patroni 健康检查接口,自动分发流量至健康节点。 vip-manager 提供一个可选的二层 VIP,从 Etcd 中获取领导者信息,并将 VIP 绑定在集群主库所在节点上。 当主库故障时,将触发新一轮领导者竞选,集群中最为健康的从库将胜出(LSN位点最高,数据损失最小者),并被提升为新的主库。 胜选从库提升后,读写流量将立即路由至新的主库。
主库故障影响是 写服务短暂不可用 :从主库故障到新主库提升期间,写入请求将被阻塞或直接失败,不可用时长通常在 15秒 ~ 30秒,通常不会超过 1 分钟。
当从库故障时,只读流量将路由至其他从库,如果所有从库都故障,只读流量才会最终由主库承载。
从库故障的影响是 部分只读查询闪断 :当前从库上正在运行查询将由于连接重置而中止,并立即由其他可用从库接管。
故障检测由 Patroni 和 Etcd 共同完成,集群领导者将持有一个租约,
如果集群领导者因为故障而没有及时续租(10s),租约将会被释放,并触发 故障切换 (Failover) 与新一轮集群选举。
即使没有出现任何故障,您依然可以主动通过 主动切换 (Switchover)变更集群的主库。
在这种情况下,主库上的写入查询将会闪断,并立即路由至新主库执行。这一操作通常可用于滚动维护/升级数据库服务器。
4.1 - RPO 利弊权衡 针对 RPO (Recovery Point Objective)进行利弊权衡,在可用性与数据损失之间找到最佳平衡点。
RPO (Recovery Point Objective,恢复点目标)定义了在主库发生故障时,允许丢失的最大数据量 。
对于金融交易这类数据完整性至关重要的场景,通常要求 RPO = 0,即不允许任何数据丢失;
然而更为严格的 RPO 指标是有代价的,它会引入更高的写入延迟,降低系统吞吐量,并且存在从库故障导致主库不可用的风险。
因此对于常规场景,通常可以接受一定量的数据丢失(例如允许丢失不超过 1MB 的数据),以换取更高的可用性与性能。
利弊权衡 通常在异步复制场景下,从库和主库之间会存在一定的复制延迟(取决于网络和吞吐量,正常在 10KB-100KB / 100µs-10ms 的数量级),
这意味着当主库发生故障时,从库可能还没有完全同步主库的最新数据。这时候如果出现故障切换,新的主库可能会丢失一些尚未复制的数据。
潜在数据丢失量的上限由 pg_rpo 参数控制,默认为 1048576 (1MB),这意味着在故障转移期间最多可以容忍 1MiB 的数据丢失。
当集群主库宕机时,如果有任何一个从库的复制延迟在这个值以内,Pigsty 将自动提升该从库为新的主库。
然而当所有从库副本的复制延迟都超出这个阈值时,Pigsty 将拒绝进行 [自动故障切换 ] 以避免数据丢失。
此时需要人工介入进行决策 —— 等待主库恢复(可能永远也不会恢复),还是接受数据损失并强制提升一个从库为新的主库。
您需要根据业务的需求偏好配置这个值,在 可用性 和 一致性 之间进行 利弊权衡 。
增大这个值可以提高自动故障切换的成功率,但也会增加潜在的数据丢失量上限。
当您指定 pg_rpo = 0 时,Pigsty 将启用 同步复制 ,确保主库在确认至少一个从库持久化数据后才返回写入成功。
这种配置能确保没有复制延迟,但会带来显著的写入延迟,并降低整体的吞吐量。
flowchart LR
A([主库故障]) --> B{同步复制?}
B -->|否| C{延迟 < RPO?}
B -->|是| D{同步从库<br/>可用?}
C -->|是| E[有损自动故障切换<br/>RPO < 1MB]
C -->|否| F[拒绝自动切换<br/>等待主库恢复<br/>或人工介入决策]
D -->|是| G[无损自动故障切换<br/>RPO = 0]
D -->|否| H{严格模式?}
H -->|否| C
H -->|是| F
style A fill:#dc3545,stroke:#b02a37,color:#fff
style E fill:#F0AD4E,stroke:#146c43,color:#fff
style G fill:#198754,stroke:#146c43,color:#fff
style F fill:#BE002F,stroke:#565e64,color:#fff 保护模式 Pigsty 提供三种保护模式,以帮助用户在不同的 RPO 要求下进行利弊权衡,类似于 Oracle Data Guard 的数据保护模式。
最大性能(Maximum Performance)
默认模式 ,异步复制,事务提交仅需本地 WAL 持久化,无需等待从库,从库故障对主库完全透明,不影响服务主库故障时可能丢失尚未发送/接收的 WAL(通常 < 1MB,正常网络条件通常在 10ms/100ms,10KB/100KB 量级) 针对性能优化,适用于常规业务场景,容许在故障时损失少量数据。 最大可用性(Maximum Availability)
配置有 pg_rpo = 0 ,启用 Patroni 同步提交模式: synchronous_mode: true 正常情况下等待至少一个从库确认,实现零数据丢失。当 所有 同步从库故障时,自动降级为异步模式继续服务 兼顾数据安全与服务可用性,是生产环境 核心业务 的推荐配置 最大保护(Maximum Protection)
使用 crit.yml 模板,启用 Patroni 严格同步模式:synchronous_mode: true / synchronous_mode_strict: true 当所有同步从库故障时,主库将拒绝写入 以防止数据丢失,事务必须在至少一个从库持久化后才返回成功。 适用于金融交易、医疗记录等对数据完整性要求极高的场景 名称 最大性能 Performance最大可用 Availability最大保护 Protection复制方式 异步复制 同步复制 严格同步复制 数据丢失 可能丢失 (复制延迟量)正常零丢失,降级少量丢失 零丢失 主库写延迟 最低 中等 (+1 次网络往返)中等 (+1 次网络往返)吞吐量 最高 降低 降低 从库故障影响 无影响 自动降级,继续服务 主库停写 RPO < 1MB = 0(正常)/ < 1MB(降级) = 0 适用场景 常规业务、性能优先 重要业务、安全优先 金融核心、安全合规第一 配置方法 默认配置 pg_rpo = 0pg_conf : crit.yml
实现原理 三种保护模式的区别在于 Patroni 的两个核心参数:synchronous_mode 与 synchronous_mode_strict 如何配置:
synchronous_mode :Patroni 是否启用同步复制,如果启用,再看 synchronous_mode_strict 是否启用严格同步模式。synchronous_mode_strict = false ,默认配置,允许当从库故障时降级为异步模式,主库继续服务 (最大可用性)synchronous_mode_strict = true ,禁止降级,主库停止写入 直到同步从库恢复(最大保护)模式 synchronous_modesynchronous_mode_strict复制模式 从库故障行为 最大性能 false- 异步复制 无影响 最大可用 truefalse同步复制 自动降级为异步 最大保护 truetrue严格同步复制 主库拒绝写入
通常情况下,您只需要将 pg_rpo 参数设置为 0,即可打开 synchronous_mode 开关,启用 最大可用性模式 。
如果您使用 pg_conf = crit.yml 模板,则会同时额外打开 synchronous_mode_strict 严格模式开关,启用 最大保护模式 。
当然,您可以直接按需 配置 这些 Patroni 参数,您还可以参阅 Patroni 与 PostgreSQL 文档,通过配置实现更强的数据保护,例如:
可以指定指定 同步从库列表 ,配置更多同步从库以提高容灾能力,使用法定人数同步,甚至要求所有从库都执行同步提交。 您可以 配置 synchronous_commit : 'remote_apply',严格确保主从读写一致性。(Oracle 最大保护模式相当于 remote_write) 配置建议 最大性能模式 (异步复制)是 Pigsty 默认使用的模式,对于绝大多数业务来说已经足够使用。
容许故障时丢失少量数据(正常在 几KB - 几百KB 的数量级),换来更大的性能吞吐量与服务可用性水平,是常规业务场景的推荐配置。
在这种情况下,您可以通过 pg_rpo 参数调整允许的最大数据丢失量,以适应不同的业务需求。
最大可用性模式 (同步复制)适用于对据完整性要求高的场景,不允许数据丢失。
在这种模式下,最少需要一主一从的两节点 PostgreSQL 集群才有意义。
将 pg_rpo 设置为 0 即可启用该模式。
最大保护模式 (严格同步复制) 适用于金融交易、医疗记录等对数据完整性要求极高的场景,我们建议至少使用一主二从的三节点集群,
因为两节点的情况下,只要从库故障,主库就会停止写入,导致业务不可用,这会降低系统的整体可靠性。而三节点的规格下,如果只有一个从库故障,主库仍然可以继续服务。
4.2 - RTO 利弊权衡 针对 RTO (Recovery Time Objective)进行利弊权衡,在故障恢复速度与误切风险之间找到最佳平衡点。
RTO (Recovery Time Objective,恢复时间目标)定义了在主库发生故障时,系统恢复写入能力所需的最长时间 。
对于核心交易系统这类可用性至关重要的场景,通常要求 RTO 尽可能短,例如一分钟内。
然而更短的 RTO 指标是有代价的,它会增加误切风险:网络抖动可能被误判为故障,导致不必要的故障切换。
因此对于跨机房/跨地域部署的场景,通常需要放宽 RTO 要求(例如 1-2 分钟),以降低误切风险。
利弊权衡 故障切换时的不可用时长上限由 pg_rto 参数控制。Pigsty 提供了四种预设的 RTO 模式:
fast、norm、safe、wide,分别针对不同的网络条件与部署场景进行了优化,默认使用 norm 模式(约 45 秒)。
您也可以使用秒数直接指定 RTO 上限,系统会自动映射到最接近的模式。
当主库发生故障时,整个恢复流程涉及多个阶段:Patroni 检测故障、DCS 锁过期、新主选举、执行 promote、HAProxy 感知新主。
减小 RTO 意味着缩短各阶段的超时时间,这会使集群对网络抖动更加敏感,从而增加误切风险。
您需要根据实际网络条件选择合适的模式,在 恢复速度 与 误切风险 之间取得平衡。
网络质量越差,越应该选择保守的模式;网络质量越好,越可以选择激进的模式。
flowchart LR
A([主库故障]) --> B{Patroni<br/>检测到?}
B -->|PG崩溃| C[尝试本地重启]
B -->|节点宕机| D[等待 TTL 过期]
C -->|成功| E([本地恢复])
C -->|失败/超时| F[释放 Leader 锁]
D --> F
F --> G[从库竞选]
G --> H[执行 Promote]
H --> I[HAProxy 感知]
I --> J([服务恢复])
style A fill:#dc3545,stroke:#b02a37,color:#fff
style E fill:#198754,stroke:#146c43,color:#fff
style J fill:#198754,stroke:#146c43,color:#fff 四种模式 Pigsty 提供四种 RTO 模式,以帮助用户在不同的网络条件下进行利弊权衡。
名称 fast norm safe wide 适用场景 同机柜 同机房内(默认) 同省跨机房 跨地域/跨洲 网络条件 < 1ms,极稳定 1-5ms,正常 10-50ms,跨机房 100-200ms,公网 目标 RTO 30s 45s 90s 150s 误切风险 较高 中等 较低 极低 配置方法 pg_rto: fastpg_rto: normpg_rto: safepg_rto: wide
fast:同机柜/同交换机
适用于网络延迟极低(< 1ms)且非常稳定的场景,例如同机柜或同交换机部署 平均 RTO: 14s ,最坏情况: 29s ,TTL 仅 20s,检测间隔 5s 对网络质量要求最高,任何抖动都可能触发切换,误切风险较高 norm:同机房(默认)
默认模式 ,适用于同机房部署,网络延迟 1-5ms,质量正常,丢包率合理平均 RTO: 21s ,最坏情况: 43s ,TTL 为 30s,提供合理的容错窗口 平衡了恢复速度与稳定性,适合绝大多数生产环境 safe:同省跨机房
适用于同省/同区域跨机房部署,网络延迟 10-50ms,可能存在偶发抖动 平均 RTO: 43s ,最坏情况: 91s ,TTL 为 60s,更长的容错窗口 主库重启等待时间较长(60s),给予更多本地恢复机会,误切风险较低 wide:跨地域/跨洲
适用于跨地域甚至跨大洲部署,网络延迟 100-200ms,可能有公网级别的丢包率 平均 RTO: 92s ,最坏情况: 207s ,TTL 为 120s,极宽的容错窗口 牺牲恢复速度换取极低的误切率,适合异地容灾场景 RTO时序图 Patroni / PG HA 有两条关键故障路径,详细的 RTO 时序分析请参阅:主动故障检测 与 被动租约过期 。
实现原理 四种 RTO 模式的区别在于以下 10 个 Patroni 与 HAProxy HA 相关参数如何配置。
组件 参数 fast norm safe wide 说明 patronittl20 30 60 120 Leader 锁生存时间(秒) loop_wait5 5 10 20 HA 循环检查间隔(秒) retry_timeout5 10 20 30 DCS 操作重试超时(秒) primary_start_timeout15 25 45 95 主库重启等待时间(秒) safety_margin5 5 10 15 Watchdog 安全边际(秒) haproxyinter1s 2s 3s 4s 正常状态检查间隔 fastinter0.5s 1s 1.5s 2s 状态变化期检查间隔 downinter1s 2s 3s 4s DOWN 状态检查间隔 rise3 3 3 3 标记 UP 所需连续成功次数 fall3 3 3 3 标记 DOWN 所需连续失败次数
Patroni 参数 ttl :Leader 锁生存时间,主库须在此时间内续租,否则锁过期触发选举,直接决定被动故障的检测延迟。loop_wait :Patroni 主循环间隔,每个循环执行一次健康检查与状态同步,影响故障发现的及时性。retry_timeout :DCS 操作重试超时,网络分区时 Patroni 在此期间持续重试,超时后主库主动降级防止脑裂。primary_start_timeout :PG 崩溃后 Patroni 尝试本地重启的等待时间,超时后释放 Leader 锁触发切换。safety_margin :Watchdog 安全边际,确保故障时有足够时间触发系统重启,避免脑裂。HAProxy 参数 inter :正常状态下的健康检查间隔,服务状态稳定时使用。fastinter :状态变化期的检查间隔,检测到状态变化时使用更短间隔加速确认。downinter :DOWN 状态下的检查间隔,服务标记为 DOWN 后使用此间隔探测恢复。rise :标记 UP 所需连续成功次数,新主上线后需连续通过 rise 次检查才能接收流量。fall :标记 DOWN 所需连续失败次数,服务需连续失败 fall 次才会被标记为 DOWN。关键约束 Patroni 核心约束 :确保主库能在 TTL 过期前完成降级,防止脑裂。
l o o p _ w a i t + 2 × r e t r y _ t i m e o u t ≤ t t l loop\_wait + 2 \times retry\_timeout \leq ttl l oo p _ w ai t + 2 × re t ry _ t im eo u t ≤ ttl 配置建议 fast 模式 适用于对 RTO 要求极高的场景,但需要确保网络质量足够好(延迟 < 1ms,极低丢包率)。
建议仅在同机柜或同交换机部署时使用,并在生产环境充分测试后再启用。
norm 模式 (默认 )是 Pigsty 默认使用的配置,对于绝大多数同机房部署的业务来说已经足够使用。
平均 21 秒的恢复时间在可接受范围内,同时提供了合理的容错窗口,避免网络抖动导致的误切。
safe 模式 适用于同城跨机房部署,网络延迟较高或存在偶发抖动的场景。
更长的容错窗口可以有效避免网络抖动导致的误切,是跨机房容灾的推荐配置。
wide 模式 适用于跨地域甚至跨大洲部署,网络延迟高且可能存在公网级别的丢包率。
这种场景下,稳定性比恢复速度更重要,因此使用极宽的容错窗口来确保极低的误切率。
场景 推荐模式 理由 开发/测试环境 fast 快速反馈,误切影响小 同机房生产环境 norm 默认选择,平衡性好 同城双活/跨机房容灾 safe 容忍网络抖动,降低误切 异地容灾/跨国部署 wide 适应高延迟公网,极低误切率 网络质量不确定 safe 保守选择,避免误切
通常只需将 pg_rto 设为模式名称,Pigsty 会自动配置 Patroni 与 HAProxy 参数。
为了保持向后兼容性,Pigsty 仍然支持直接使用秒数配置 RTO,但效果相当于指定 norm 模式。
配置模式实际上是从 pg_rto_plan 中加载对应参数集,您可以修改或覆盖此配置以实现自定义 RTO 策略。
pg_rto_plan : # [ttl, loop, retry, start, margin, inter, fastinter, downinter, rise, fall]
fast : [ 20 , 5 , 5 , 15 , 5 , '1s' , '0.5s' , '1s' , 3 , 3 ] # rto < 30s
norm : [ 30 , 5 , 10 , 25 , 5 , '2s' , '1s' , '2s' , 3 , 3 ] # rto < 45s
safe : [ 60 , 10 , 20 , 45 , 10 , '3s' , '1.5s' , '3s' , 3 , 3 ] # rto < 90s
wide : [ 120 , 20 , 30 , 95 , 15 , '4s' , '2s' , '4s' , 3 , 3 ] # rto < 150s
4.3 - 故障切换模型 详细分析三种经典故障检测/恢复路径下,最差,最优,平均 RTO 的计算逻辑与结果
Patroni 故障按故障对象分类可以分为以下 10 类,按照检测路径不同,可以进一步归纳为五类,在本节内详细展开。
# 故障场景 描述 最终走哪条路径 1 PG 进程崩溃 crash、OOM killed 主动检测 2 PG 拒绝连接 max_connections 主动检测 3 PG 假活 进程在但无响应 主动检测 (检测超时)4 Patroni 进程崩溃 kill -9、OOM 被动检测 5 Patroni 假活 进程在但卡住 Watchdog 6 节点宕机 断电、硬件故障 被动检测 7 节点假活 IO hang、CPU 饥饿 Watchdog 8 主库 ↔ DCS 网络中断 防火墙、交换机故障 网络分区 9 存储故障 磁盘坏、磁盘满、挂载失败 主动检测 或 Watchdog 10 手动切换 Switchover/Failover 手动触发
但是在 RTO 计算上,最终所有故障都会收敛到两条路径上,本节深入探讨了这两种情况下的 RTO 上下限与均值。
flowchart LR
A([主库故障]) --> B{Patroni<br/>检测到?}
B -->|PG崩溃| C[尝试本地重启]
B -->|节点宕机| D[等待 TTL 过期]
C -->|成功| E([本地恢复])
C -->|失败/超时| F[释放 Leader 锁]
D --> F
F --> G[从库竞选]
G --> H[执行 Promote]
H --> I[HAProxy 感知]
I --> J([服务恢复])
style A fill:#dc3545,stroke:#b02a37,color:#fff
style E fill:#198754,stroke:#146c43,color:#fff
style J fill:#198754,stroke:#146c43,color:#fff 4.3.1 - 被动故障切换 节点宕机,导致领导者租约过期触发集群领导竞选的故障路径
RTO 时序图
故障模型 项目 最好 最坏 平均 说明 租约过期 ttl - loopttlttl - loop/2最好:即将刷新时宕机 最坏:刚刷新完就宕机 从库检测 0looploop / 2最好:恰好在检测点 最坏:刚错过检测点 抢锁提拔 021最好:直接抢锁提升 最坏:API超时+Promote 健康检查 (rise-1) × fastinter(rise-1) × fastinter + inter(rise-1) × fastinter + inter/2最好:检查前状态变化 最坏:检查后瞬间状态变化
被动故障与主动故障的核心区别 :
场景 Patroni 状态 租约处理 主要等待时间 主动故障 (PG崩溃)存活,健康 主动尝试重启 PG,超时后释放租约 primary_start_timeout被动故障 (节点宕机)随节点一起死亡 无法主动释放,只能等待 TTL 过期 ttl
在被动故障场景中,Patroni 随节点一起宕机,无法主动释放 Leader Key 。
DCS 中的租约只能等待 TTL 自然过期后触发集群选举。
时序分析 阶段 1:租约过期 Patroni 主库会在每个 loop_wait 周期刷新 Leader Key,将 TTL 重置为配置值。
时间线:
t-loop t t+ttl-loop t+ttl
| | | |
上次刷新 故障发生 最好情况 最坏情况
|←── loop ──→| | |
|←──────────── ttl ─────────────────────→|
最好情况 :故障发生在即将刷新租约之前(距上次刷新已过 loop),剩余 TTL = ttl - loop最坏情况 :故障发生在刚刷新租约之后,需等待完整 ttl平均情况 :ttl - loop/2T e x p i r e = { t t l − l o o p 最好 t t l − l o o p / 2 平均 t t l 最坏 T_{expire} = \begin{cases}
ttl - loop & \text{最好} \\
ttl - loop/2 & \text{平均} \\
ttl & \text{最坏}
\end{cases} T e x p i re = ⎩ ⎨ ⎧ ttl − l oo p ttl − l oo p /2 ttl 最好 平均 最坏 阶段 2:从库检测 从库在 loop_wait 周期醒来后检查 DCS 中的 Leader Key 状态。
时间线:
租约过期 从库醒来
| |
|←── 0~loop ─→|
最好情况 :租约过期时从库恰好醒来,等待 0最坏情况 :租约过期后从库刚进入睡眠,等待 loop平均情况 :loop/2T d e t e c t = { 0 最好 l o o p / 2 平均 l o o p 最坏 T_{detect} = \begin{cases}
0 & \text{最好} \\
loop/2 & \text{平均} \\
loop & \text{最坏}
\end{cases} T d e t ec t = ⎩ ⎨ ⎧ 0 l oo p /2 l oo p 最好 平均 最坏 阶段 3:抢锁提拔 从库发现 Leader Key 过期后,开始竞选过程,获得 Leader Key 的从库执行 pg_ctl promote,将自己提升为新主库。
通过 Rest API,并行发起查询,查询各从库的复制位置,通常 10ms,硬编码 2 秒超时。 比较 WAL 位置,确定最优候选,各从库尝试创建 Leader Key(CAS 原子操作) 执行 pg_ctl promote 提升自己为主库(很快,通常忽略不计) 选举流程:
从库A ──→ 查询复制位置 ──→ 比较 ──→ 尝试抢锁 ──→ 成功
从库B ──→ 查询复制位置 ──→ 比较 ──→ 尝试抢锁 ──→ 失败
最好情况 :单从库或直接抢到锁并提升,常数开销 0.1s最坏情况 :DCS API 调用超时:2s平均情况 :1s 常数开销T e l e c t = { 0.1 最好 1 平均 2 最坏 T_{elect} = \begin{cases}
0.1 & \text{最好} \\
1 & \text{平均} \\
2 & \text{最坏}
\end{cases} T e l ec t = ⎩ ⎨ ⎧ 0.1 1 2 最好 平均 最坏 阶段 4:健康检查 HAProxy 检测新主库上线,需要连续 rise 次健康检查成功。
检测时序:
新主提升 首次检查 第二次检查 第三次检查(UP)
| | | |
|←─ 0~inter ─→|←─ fast ─→|←─ fast ─→|
最好情况 :新主提升时恰好赶上检查,(rise-1) × fastinter最坏情况 :新主提升后刚错过检查,(rise-1) × fastinter + inter平均情况 :(rise-1) × fastinter + inter/2T h a p r o x y = { ( r i s e − 1 ) × f a s t i n t e r 最好 ( r i s e − 1 ) × f a s t i n t e r + i n t e r / 2 平均 ( r i s e − 1 ) × f a s t i n t e r + i n t e r 最坏 T_{haproxy} = \begin{cases}
(rise-1) \times fastinter & \text{最好} \\
(rise-1) \times fastinter + inter/2 & \text{平均} \\
(rise-1) \times fastinter + inter & \text{最坏}
\end{cases} T ha p ro x y = ⎩ ⎨ ⎧ ( r i se − 1 ) × f a s t in t er ( r i se − 1 ) × f a s t in t er + in t er /2 ( r i se − 1 ) × f a s t in t er + in t er 最好 平均 最坏 RTO 公式 将各阶段时间相加,得到总 RTO:
最好情况
R T O m i n = t t l − l o o p + 0.1 + ( r i s e − 1 ) × f a s t i n t e r RTO_{min} = ttl - loop + 0.1 + (rise-1) \times fastinter RT O min = ttl − l oo p + 0.1 + ( r i se − 1 ) × f a s t in t er 平均情况
R T O a v g = t t l + 1 + i n t e r / 2 + ( r i s e − 1 ) × f a s t i n t e r RTO_{avg} = ttl + 1 + inter/2 + (rise-1) \times fastinter RT O a vg = ttl + 1 + in t er /2 + ( r i se − 1 ) × f a s t in t er 最坏情况
R T O m a x = t t l + l o o p + 2 + i n t e r + ( r i s e − 1 ) × f a s t i n t e r RTO_{max} = ttl + loop + 2 + inter + (rise-1) \times fastinter RT O ma x = ttl + l oo p + 2 + in t er + ( r i se − 1 ) × f a s t in t er 模型计算 将四种 RTO 模型的参数带入上面的公式:
pg_rto_plan : # [ttl, loop, retry, start, margin, inter, fastinter, downinter, rise, fall]
fast : [ 20 , 5 , 5 , 15 , 5 , '1s' , '0.5s' , '1s' , 3 , 3 ] # rto < 30s
norm : [ 30 , 5 , 10 , 25 , 5 , '2s' , '1s' , '2s' , 3 , 3 ] # rto < 45s
safe : [ 60 , 10 , 20 , 45 , 10 , '3s' , '1.5s' , '3s' , 3 , 3 ] # rto < 90s
wide : [ 120 , 20 , 30 , 95 , 15 , '4s' , '2s' , '4s' , 3 , 3 ] # rto < 150s
四种模式计算结果 (单位:秒,格式:min / avg / max)
阶段 fast norm safe wide 租约过期 15 / 17 / 2025 / 27 / 3050 / 55 / 60100 / 110 / 120从库检测 0 / 3 / 50 / 3 / 50 / 5 / 100 / 10 / 20抢锁提拔 0 / 1 / 20 / 1 / 20 / 1 / 20 / 1 / 2健康检查 1 / 2 / 22 / 3 / 43 / 5 / 64 / 6 / 8总计 16 / 23 / 2927 / 34 / 4153 / 66 / 78104 / 127 / 150
4.3.2 - 主动故障检测 PostgreSQL 主库进程崩溃,Patroni 存活并尝试重启,超时后触发故障切换的路径
RTO 时序图
故障模型 项目 最好 最坏 平均 说明 故障检测 0looploop/2最好:PG 恰好在检测前崩溃 最坏:PG 刚检测完就崩溃 重启超时 0startstart最好:PG 瞬间自愈 最坏:等满 start 超时才释放租约 从库检测 0looploop/2最好:恰好在检测点 最坏:刚错过检测点 抢锁提拔 021最好:直接抢锁提升 最坏:API 超时 + Promote 健康检查 (rise-1) × fastinter(rise-1) × fastinter + inter(rise-1) × fastinter + inter/2最好:检查前状态变化 最坏:检查后瞬间状态变化
主动故障与被动故障的核心区别 :
场景 Patroni 状态 租约处理 主要等待时间 主动故障 (PG 崩溃)存活,健康 主动尝试重启 PG,超时后释放租约 primary_start_timeout被动故障 (节点宕机)随节点一起死亡 无法主动释放,只能等待 TTL 过期 ttl
在主动故障场景中,Patroni 仍然存活,能够主动检测到 PG 崩溃并尝试重启 。
如果重启成功,服务自愈;如果超时仍未恢复,Patroni 会主动释放 Leader Key ,触发集群选举。
时序分析 阶段 1:故障检测 Patroni 在每个 loop_wait 周期检查 PostgreSQL 状态(通过 pg_isready 或检查进程)。
时间线:
上次检测 PG崩溃 下次检测
| | |
|←── 0~loop ─→| |
最好情况 :PG 恰好在 Patroni 检测前崩溃,立即被发现,等待 0最坏情况 :PG 刚检测完就崩溃,需等待下一个周期,等待 loop平均情况 :loop/2T d e t e c t = { 0 最好 l o o p / 2 平均 l o o p 最坏 T_{detect} = \begin{cases}
0 & \text{最好} \\
loop/2 & \text{平均} \\
loop & \text{最坏}
\end{cases} T d e t ec t = ⎩ ⎨ ⎧ 0 l oo p /2 l oo p 最好 平均 最坏 阶段 2:重启超时 Patroni 检测到 PG 崩溃后,会尝试重启 PostgreSQL。此阶段有两种可能的结果:
时间线:
检测到崩溃 尝试重启 重启成功/超时
| | |
|←──── 0 ~ start ────────→|
路径 A:自愈成功 (最好情况)
PG 成功重启,服务恢复 不触发故障切换,RTO 极短 等待时间:0(相对于 Failover 路径) 路径 B:需要 Failover (平均/最坏情况)
等待 primary_start_timeout 超时后 PG 仍未恢复 Patroni 主动释放 Leader Key 等待时间:start T r e s t a r t = { 0 最好(自愈成功) s t a r t 平均(需要 Failover) s t a r t 最坏 T_{restart} = \begin{cases}
0 & \text{最好(自愈成功)} \\
start & \text{平均(需要 Failover)} \\
start & \text{最坏}
\end{cases} T res t a r t = ⎩ ⎨ ⎧ 0 s t a r t s t a r t 最好(自愈成功) 平均(需要 Failover ) 最坏 注意 :平均情况假设需要进行故障切换。如果 PG 能够快速自愈,则整体 RTO 会大幅降低。
阶段 3:从库检测 从库在 loop_wait 周期醒来后检查 DCS 中的 Leader Key 状态。当主库 Patroni 释放 Leader Key 后,从库发现后开始竞选。
时间线:
租约释放 从库醒来
| |
|←── 0~loop ─→|
最好情况 :租约释放时从库恰好醒来,等待 0最坏情况 :租约释放后从库刚进入睡眠,等待 loop平均情况 :loop/2T s t a n d b y = { 0 最好 l o o p / 2 平均 l o o p 最坏 T_{standby} = \begin{cases}
0 & \text{最好} \\
loop/2 & \text{平均} \\
loop & \text{最坏}
\end{cases} T s t an d b y = ⎩ ⎨ ⎧ 0 l oo p /2 l oo p 最好 平均 最坏 阶段 4:抢锁提拔 从库发现 Leader Key 空缺后,开始竞选过程,获得 Leader Key 的从库执行 pg_ctl promote,将自己提升为新主库。
通过 Rest API,并行发起查询,查询各从库的复制位置,通常 10ms,硬编码 2 秒超时。 比较 WAL 位置,确定最优候选,各从库尝试创建 Leader Key(CAS 原子操作) 执行 pg_ctl promote 提升自己为主库(很快,通常忽略不计) 选举流程:
从库A ──→ 查询复制位置 ──→ 比较 ──→ 尝试抢锁 ──→ 成功
从库B ──→ 查询复制位置 ──→ 比较 ──→ 尝试抢锁 ──→ 失败
最好情况 :单从库或直接抢到锁并提升,常数开销 0.1s最坏情况 :DCS API 调用超时:2s平均情况 :1s 常数开销T e l e c t = { 0.1 最好 1 平均 2 最坏 T_{elect} = \begin{cases}
0.1 & \text{最好} \\
1 & \text{平均} \\
2 & \text{最坏}
\end{cases} T e l ec t = ⎩ ⎨ ⎧ 0.1 1 2 最好 平均 最坏 阶段 5:健康检查 HAProxy 检测新主库上线,需要连续 rise 次健康检查成功。
检测时序:
新主提升 首次检查 第二次检查 第三次检查(UP)
| | | |
|←─ 0~inter ─→|←─ fast ─→|←─ fast ─→|
最好情况 :新主提升时恰好赶上检查,(rise-1) × fastinter最坏情况 :新主提升后刚错过检查,(rise-1) × fastinter + inter平均情况 :(rise-1) × fastinter + inter/2T h a p r o x y = { ( r i s e − 1 ) × f a s t i n t e r 最好 ( r i s e − 1 ) × f a s t i n t e r + i n t e r / 2 平均 ( r i s e − 1 ) × f a s t i n t e r + i n t e r 最坏 T_{haproxy} = \begin{cases}
(rise-1) \times fastinter & \text{最好} \\
(rise-1) \times fastinter + inter/2 & \text{平均} \\
(rise-1) \times fastinter + inter & \text{最坏}
\end{cases} T ha p ro x y = ⎩ ⎨ ⎧ ( r i se − 1 ) × f a s t in t er ( r i se − 1 ) × f a s t in t er + in t er /2 ( r i se − 1 ) × f a s t in t er + in t er 最好 平均 最坏 RTO 公式 将各阶段时间相加,得到总 RTO:
最好情况 (PG 瞬间自愈)
R T O m i n = 0 + 0 + 0 + 0.1 + ( r i s e − 1 ) × f a s t i n t e r ≈ ( r i s e − 1 ) × f a s t i n t e r RTO_{min} = 0 + 0 + 0 + 0.1 + (rise-1) \times fastinter \approx (rise-1) \times fastinter RT O min = 0 + 0 + 0 + 0.1 + ( r i se − 1 ) × f a s t in t er ≈ ( r i se − 1 ) × f a s t in t er 平均情况 (需要 Failover)
R T O a v g = l o o p + s t a r t + 1 + i n t e r / 2 + ( r i s e − 1 ) × f a s t i n t e r RTO_{avg} = loop + start + 1 + inter/2 + (rise-1) \times fastinter RT O a vg = l oo p + s t a r t + 1 + in t er /2 + ( r i se − 1 ) × f a s t in t er 最坏情况
R T O m a x = l o o p × 2 + s t a r t + 2 + i n t e r + ( r i s e − 1 ) × f a s t i n t e r RTO_{max} = loop \times 2 + start + 2 + inter + (rise-1) \times fastinter RT O ma x = l oo p × 2 + s t a r t + 2 + in t er + ( r i se − 1 ) × f a s t in t er 模型计算 将四种 RTO 模型的参数带入上面的公式:
pg_rto_plan : # [ttl, loop, retry, start, margin, inter, fastinter, downinter, rise, fall]
fast : [ 20 , 5 , 5 , 15 , 5 , '1s' , '0.5s' , '1s' , 3 , 3 ] # rto < 30s
norm : [ 30 , 5 , 10 , 25 , 5 , '2s' , '1s' , '2s' , 3 , 3 ] # rto < 45s
safe : [ 60 , 10 , 20 , 45 , 10 , '3s' , '1.5s' , '3s' , 3 , 3 ] # rto < 90s
wide : [ 120 , 20 , 30 , 95 , 15 , '4s' , '2s' , '4s' , 3 , 3 ] # rto < 150s
四种模式计算结果 (单位:秒,格式:min / avg / max)
阶段 fast norm safe wide 故障检测 0 / 3 / 50 / 3 / 50 / 5 / 100 / 10 / 20重启超时 0 / 15 / 150 / 25 / 250 / 45 / 450 / 95 / 95从库检测 0 / 3 / 50 / 3 / 50 / 5 / 100 / 10 / 20抢锁提拔 0 / 1 / 20 / 1 / 20 / 1 / 20 / 1 / 2健康检查 1 / 2 / 22 / 3 / 43 / 5 / 64 / 6 / 8总计 1 / 24 / 292 / 35 / 413 / 61 / 734 / 122 / 145
与被动故障对比 阶段 主动故障(PG 崩溃) 被动故障(节点宕机) 说明 检测机制 Patroni 主动检测 TTL 被动过期 主动检测更快发现故障 核心等待 startttlstart 通常小于 ttl,但需要额外的故障检测时间 租约处理 主动释放 被动过期 主动释放更及时 自愈可能 ✅ 有 ❌ 无 主动检测可尝试本地恢复
RTO 对比 (平均情况):
模式 主动故障(PG 崩溃) 被动故障(节点宕机) 差异 fast 24s 23s +1s norm 35s 34s +1s safe 61s 66s -5s wide 122s 127s -5s
分析 :在 fast 和 norm 模式下,主动故障的 RTO 略高于被动故障,因为需要等待 primary_start_timeout(start);
但在 safe 和 wide 模式下,由于 start < ttl - loop,主动故障反而更快。
不过主动故障有自愈的可能性,最好情况下 RTO 可以极短。
4.4 - 服务接入 Pigsty 使用 HAProxy 提供服务接入,并提供可选的 pgBouncer 池化连接,以及可选的 L2 VIP 与 DNS 接入。
分离读写操作,正确路由流量,稳定可靠地交付 PostgreSQL 集群提供的能力。
服务 是一种抽象:它是数据库集群对外提供能力的形式,并封装了底层集群的细节。
服务对于生产环境中的 稳定接入 至关重要,在 高可用 集群自动故障时方显其价值,单机用户 通常不需要操心这个概念。
单机用户 “服务” 的概念是给生产环境用的,个人用户/单机集群可以不折腾,直接拿实例名/IP地址访问数据库。
例如,Pigsty 默认的单节点 pg-meta.meta 数据库,就可以直接用下面三个不同的用户连接上去。
psql postgres://dbuser_dba:DBUser.DBA@10.10.10.10/meta # 直接用 DBA 超级用户连上去
psql postgres://dbuser_meta:DBUser.Meta@10.10.10.10/meta # 用默认的业务管理员用户连上去
psql postgres://dbuser_view:DBUser.View@pg-meta/meta # 用默认的只读用户走实例域名连上去
服务概述 在真实世界生产环境中,我们会使用基于复制的主从数据库集群。集群中有且仅有一个实例作为领导者(主库 )可以接受写入。
而其他实例(从库 )则会从持续从集群领导者获取变更日志,与领导者保持一致。同时,从库还可以承载只读请求,在读多写少的场景下可以显著分担主库的负担,
因此对集群的写入请求与只读请求进行区分,是一种十分常见的实践。
此外对于高频短连接的生产环境,我们还会通过连接池中间件(Pgbouncer)对请求进行池化,减少连接与后端进程的创建开销。但对于ETL与变更执行等场景,我们又需要绕过连接池,直接访问数据库。
同时,高可用集群在故障时会出现故障切换(Failover),故障切换会导致集群的领导者出现变更。因此高可用的数据库方案要求写入流量可以自动适配集群的领导者变化。
这些不同的访问需求(读写分离,池化与直连,故障切换自动适配)最终抽象出 服务 (Service)的概念。
通常来说,数据库集群都必须提供这种最基础的服务:
对于生产数据库集群,至少应当提供这两种服务:
读写服务(primary) :写入数据:只能由主库所承载。只读服务(replica) :读取数据:可以由从库承载,没有从库时也可由主库承载此外,根据具体的业务场景,可能还会有其他的服务,例如:
默认直连服务(default) :允许(管理)用户,绕过连接池直接访问数据库的服务离线从库服务(offline) :不承接线上只读流量的专用从库,用于ETL与分析查询同步从库服务(standby) :没有复制延迟的只读服务,由 同步备库 /主库处理只读查询延迟从库服务(delayed) :访问同一个集群在一段时间之前的旧数据,由 延迟从库 来处理接入服务 Pigsty的服务交付边界止步于集群的HAProxy,用户可以用各种手段访问这些负载均衡器。
典型的做法是使用 DNS 或 VIP 接入,将其绑定在集群所有或任意数量的负载均衡器上。
你可以使用不同的 主机 & 端口 组合,它们以不同的方式提供 PostgreSQL 服务。
主机
类型 样例 描述 集群域名 pg-test通过集群域名访问(由 dnsmasq @ infra 节点解析) 集群 VIP 地址 10.10.10.3通过由 vip-manager 管理的 L2 VIP 地址访问,绑定到主节点 实例主机名 pg-test-1通过任何实例主机名访问(由 dnsmasq @ infra 节点解析) 实例 IP 地址 10.10.10.11访问任何实例的 IP 地址
端口
Pigsty 使用不同的 端口 来区分 pg services
端口 服务 类型 描述 5432 postgres 数据库 直接访问 postgres 服务器 6432 pgbouncer 中间件 访问 postgres 前先通过连接池中间件 5433 primary 服务 访问主 pgbouncer (或 postgres) 5434 replica 服务 访问备份 pgbouncer (或 postgres) 5436 default 服务 访问主 postgres 5438 offline 服务 访问离线 postgres
组合
# 通过集群域名访问
postgres://test@pg-test:5432/test # DNS -> L2 VIP -> 主直接连接
postgres://test@pg-test:6432/test # DNS -> L2 VIP -> 主连接池 -> 主
postgres://test@pg-test:5433/test # DNS -> L2 VIP -> HAProxy -> 主连接池 -> 主
postgres://test@pg-test:5434/test # DNS -> L2 VIP -> HAProxy -> 备份连接池 -> 备份
postgres://dbuser_dba@pg-test:5436/test # DNS -> L2 VIP -> HAProxy -> 主直接连接 (用于管理员)
postgres://dbuser_stats@pg-test:5438/test # DNS -> L2 VIP -> HAProxy -> 离线直接连接 (用于 ETL/个人查询)
# 通过集群 VIP 直接访问
postgres://test@10.10.10.3:5432/test # L2 VIP -> 主直接访问
postgres://test@10.10.10.3:6432/test # L2 VIP -> 主连接池 -> 主
postgres://test@10.10.10.3:5433/test # L2 VIP -> HAProxy -> 主连接池 -> 主
postgres://test@10.10.10.3:5434/test # L2 VIP -> HAProxy -> 备份连接池 -> 备份
postgres://dbuser_dba@10.10.10.3:5436/test # L2 VIP -> HAProxy -> 主直接连接 (用于管理员)
postgres://dbuser_stats@10.10.10.3::5438/test # L2 VIP -> HAProxy -> 离线直接连接 (用于 ETL/个人查询)
# 直接指定任何集群实例名
postgres://test@pg-test-1:5432/test # DNS -> 数据库实例直接连接 (单例访问)
postgres://test@pg-test-1:6432/test # DNS -> 连接池 -> 数据库
postgres://test@pg-test-1:5433/test # DNS -> HAProxy -> 连接池 -> 数据库读/写
postgres://test@pg-test-1:5434/test # DNS -> HAProxy -> 连接池 -> 数据库只读
postgres://dbuser_dba@pg-test-1:5436/test # DNS -> HAProxy -> 数据库直接连接
postgres://dbuser_stats@pg-test-1:5438/test # DNS -> HAProxy -> 数据库离线读/写
# 直接指定任何集群实例 IP 访问
postgres://test@10.10.10.11:5432/test # 数据库实例直接连接 (直接指定实例, 没有自动流量分配)
postgres://test@10.10.10.11:6432/test # 连接池 -> 数据库
postgres://test@10.10.10.11:5433/test # HAProxy -> 连接池 -> 数据库读/写
postgres://test@10.10.10.11:5434/test # HAProxy -> 连接池 -> 数据库只读
postgres://dbuser_dba@10.10.10.11:5436/test # HAProxy -> 数据库直接连接
postgres://dbuser_stats@10.10.10.11:5438/test # HAProxy -> 数据库离线读-写
# 智能客户端:通过URL读写分离
postgres://test@10.10.10.11:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs= primary
postgres://test@10.10.10.11:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs= prefer-standby
5 - 时间点恢复 Pigsty 使用 pgBackRest 实现了 PostgreSQL 时间点恢复,允许用户回滚至备份策略容许范围内的任意时间点。
您可以将集群恢复回滚至过去任意时刻,避免软件缺陷与人为失误导致的数据损失。
Pigsty 的 PostgreSQL 集群带有自动配置的时间点恢复(PITR)方案,基于备份组件 pgBackRest 与可选的对象存储仓库 MinIO 提供。
高可用方案 可以解决硬件故障,但却对软件缺陷与人为失误导致的数据删除/覆盖写入/删库等问题却无能为力。
对于这种情况,Pigsty 提供了开箱即用的 时间点恢复 (Point in Time Recovery, PITR)能力,无需额外配置即默认启用。
Pigsty 为您提供了基础备份与 WAL 归档的默认配置,您可以使用本地目录与磁盘,亦或专用的 MinIO 集群或 S3 对象存储服务来存储备份并实现异地容灾。
当您使用本地磁盘时,默认保留恢复至过去一天内的任意时间点的能力。当您使用 MinIO 或 S3 时,默认保留恢复至过去一周内的任意时间点的能力。
只要存储空间管够,您尽可保留任意长地可恢复时间段,丰俭由人。
时间点恢复(PITR)解决什么问题?
容灾能⼒增强:RPO 从 ∞ 降⾄ ⼗⼏MB, RTO 从 ∞ 降⾄ ⼏⼩时/⼏刻钟。 确保数据安全:C/I/A 中的 数据完整性 :避免误删导致的数据⼀致性问题。 确保数据安全:C/I/A 中的 数据可⽤性 :提供对“永久不可⽤”这种灾难情况的兜底 单实例配置策略 事件 RTO RPO 什么也不做宕机 永久丢失 全部丢失 基础备份宕机 取决于备份大小与带宽(几小时) 丢失上一次备份后的数据(几个小时到几天) 基础备份 + WAL归档宕机 取决于备份大小与带宽(几小时) 丢失最后尚未归档的数据(几十MB)
时间点恢复有什么代价?
降低数据安全中的 C:机密性 ,产生额外泄漏点,需要额外对备份进⾏保护。 额外的资源消耗:本地存储或⽹络流量 / 带宽开销,通常并不是⼀个问题。 复杂度代价升⾼:⽤户需要付出备份管理成本。 时间点恢复的局限性
如果只有 PITR 用于故障恢复,则 RTO 与 RPO 指标相比 高可用方案 更为逊色,通常应两者组合使用。
RTO :如果只有单机 + PITR,恢复时长取决于备份大小与网络/磁盘带宽,从十几分钟到几小时,几天不等。RPO :如果只有单机 + PITR,宕机时可能丢失少量数据,一个或几个 WAL 日志段文件可能尚未归档,损失 16 MB 到⼏⼗ MB 不等的数据。除了 PITR 之外,您还可以在 Pigsty 中使用 延迟集群 来解决人为失误或软件缺陷导致的数据误删误改问题。
原理 时间点恢复允许您将集群恢复回滚至过去的“任意时刻”,避免软件缺陷与人为失误导致的数据损失。要做到这一点,首先需要做好两样准备工作:基础备份 与 WAL归档 。
拥有 基础备份 ,允许用户将数据库恢复至备份时的状态,而同时拥有从某个基础备份开始的 WAL归档 ,允许用户将数据库恢复至基础备份时刻之后的任意时间点。
详细原理,请参阅:基础备份与时间点恢复 ;具体操作,请参考 PGSQL管理:备份恢复 。
基础备份 Pigsty 使用 pgbackrest 管理 PostgreSQL 备份。pgBackRest 将在所有集群实例上初始化空仓库,但只会在集群主库上实际使用仓库。
pgBackRest 支持三种备份模式:全量备份 ,增量备份 ,差异备份,其中前两者最为常用。
全量备份将对数据库集群取一个当前时刻的全量物理快照,增量备份会记录当前数据库集群与上一次全量备份之间的差异。
Pigsty 为备份提供了封装命令:/pg/bin/pg-backup [full|incr]。您可以通过 Crontab 或任何其他任务调度系统,按需定期制作基础备份。
WAL归档 Pigsty 默认在集群主库上启⽤了 WAL 归档,并使⽤ pgbackrest 命令行工具持续推送 WAL 段⽂件至备份仓库。
pgBackRest 会⾃动管理所需的 WAL ⽂件,并根据备份的保留策略及时清理过期的备份,与其对应的 WAL 归档⽂件。
如果您不需要 PITR 功能,可以通过 配置集群 : archive_mode: off 来关闭 WAL 归档,移除 node_crontab 来停止定期备份任务。
实现 默认情况下,Pigsty提供了两种预置 备份策略 :默认使用本地文件系统备份仓库,在这种情况下每天进行一次全量备份,确保用户任何时候都能回滚至一天内的任意时间点。备选策略使用专用的 MinIO 集群或S3存储备份,每周一全备,每天一增备,默认保留两周的备份与WAL归档。
Pigsty 使用 pgBackRest 管理备份,接收 WAL 归档,执行 PITR。备份仓库可以进行灵活配置(pgbackrest_repo ):默认使用主库本地文件系统(local),但也可以使用其他磁盘路径,或使用自带的可选 MinIO 服务(minio)与云上 S3 服务。
pgbackrest_enabled : true # 在 pgsql 主机上启用 pgBackRest 吗?
pgbackrest_clean : true # 初始化时删除 pg 备份数据?
pgbackrest_log_dir : /pg/log/pgbackrest # pgbackrest 日志目录,默认为 `/pg/log/pgbackrest`
pgbackrest_method : local # pgbackrest 仓库方法:local, minio, [用户定义...]
pgbackrest_repo : # pgbackrest 仓库:https://pgbackrest.org/configuration.html#section-repository
local : # 默认使用本地 posix 文件系统的 pgbackrest 仓库
path : /pg/backup # 本地备份目录,默认为 `/pg/backup`
retention_full_type : count # 按计数保留完整备份
retention_full : 2 # 使用本地文件系统仓库时,最多保留 3 个完整备份,至少保留 2 个
minio : # pgbackrest 的可选 minio 仓库
type : s3 # minio 是与 s3 兼容的,所以使用 s3
s3_endpoint : sss.pigsty # minio 端点域名,默认为 `sss.pigsty`
s3_region : us-east-1 # minio 区域,默认为 us-east-1,对 minio 无效
s3_bucket : pgsql # minio 桶名称,默认为 `pgsql`
s3_key : pgbackrest # pgbackrest 的 minio 用户访问密钥
s3_key_secret : S3User.Backup # pgbackrest 的 minio 用户秘密密钥
s3_uri_style : path # 对 minio 使用路径风格的 uri,而不是主机风格
path : /pgbackrest # minio 备份路径,默认为 `/pgbackrest`
storage_port : 9000 # minio 端口,默认为 9000
storage_ca_file : /etc/pki/ca.crt # minio ca 文件路径,默认为 `/etc/pki/ca.crt`
bundle : y # 将小文件打包成一个文件
cipher_type : aes-256-cbc # 为远程备份仓库启用 AES 加密
cipher_pass : pgBackRest # AES 加密密码,默认为 'pgBackRest'
retention_full_type : time # 在 minio 仓库上按时间保留完整备份
retention_full : 14 # 保留过去 14 天的完整备份
# 您还可以添加其他的可选备份仓库,例如 S3,用于异地容灾
Pigsty 参数 pgbackrest_repo 中的目标仓库会被转换为 /etc/pgbackrest/pgbackrest.conf 配置文件中的仓库定义。
例如,如果您定义了一个美西区的 S3 仓库用于存储冷备份,可以使用下面的参考配置。
s3 : # ------> /etc/pgbackrest/pgbackrest.conf
repo1-type : s3 # ----> repo1-type=s3
repo1-s3-region : us-west-1 # ----> repo1-s3-region=us-west-1
repo1-s3-endpoint : s3-us-west-1.amazonaws.com # ----> repo1-s3-endpoint=s3-us-west-1.amazonaws.com
repo1-s3-key : '<your_access_key>' # ----> repo1-s3-key=<your_access_key>
repo1-s3-key-secret : '<your_secret_key>' # ----> repo1-s3-key-secret=<your_secret_key>
repo1-s3-bucket : pgsql # ----> repo1-s3-bucket=pgsql
repo1-s3-uri-style : host # ----> repo1-s3-uri-style=host
repo1-path : /pgbackrest # ----> repo1-path=/pgbackrest
repo1-bundle : y # ----> repo1-bundle=y
repo1-cipher-type : aes-256-cbc # ----> repo1-cipher-type=aes-256-cbc
repo1-cipher-pass : pgBackRest # ----> repo1-cipher-pass=pgBackRest
repo1-retention-full-type : time # ----> repo1-retention-full-type=time
repo1-retention-full : 90 # ----> repo1-retention-full=90
恢复 您可以直接使用以下封装命令可以用于 PostgreSQL 数据库集群的 时间点恢复 。
Pigsty 默认使用增量差分并行恢复,允许您以最快速度恢复到指定时间点。
pg-pitr # 恢复到WAL存档流的结束位置(例如在整个数据中心故障的情况下使用)
pg-pitr -i # 恢复到最近备份完成的时间(不常用)
pg-pitr --time= "2022-12-30 14:44:44+08" # 恢复到指定的时间点(在删除数据库或表的情况下使用)
pg-pitr --name= "my-restore-point" # 恢复到使用 pg_create_restore_point 创建的命名恢复点
pg-pitr --lsn= "0/7C82CB8" -X # 在LSN之前立即恢复
pg-pitr --xid= "1234567" -X -P # 在指定的事务ID之前立即恢复,然后将集群直接提升为主库
pg-pitr --backup= latest # 恢复到最新的备份集
pg-pitr --backup= 20221108-105325 # 恢复到特定备份集,备份集可以使用 pgbackrest info 列出
pg-pitr # pgbackrest --stanza=pg-meta restore
pg-pitr -i # pgbackrest --stanza=pg-meta --type=immediate restore
pg-pitr -t "2022-12-30 14:44:44+08" # pgbackrest --stanza=pg-meta --type=time --target="2022-12-30 14:44:44+08" restore
pg-pitr -n "my-restore-point" # pgbackrest --stanza=pg-meta --type=name --target=my-restore-point restore
pg-pitr -b 20221108-105325F # pgbackrest --stanza=pg-meta --type=name --set=20221230-120101F restore
pg-pitr -l "0/7C82CB8" -X # pgbackrest --stanza=pg-meta --type=lsn --target="0/7C82CB8" --target-exclusive restore
pg-pitr -x 1234567 -X -P # pgbackrest --stanza=pg-meta --type=xid --target="0/7C82CB8" --target-exclusive --target-action=promote restore
在执行 PITR 时,您可以使用 Pigsty 监控系统观察集群 LSN 位点状态,判断是否成功恢复到指定的时间点,事务点,LSN位点,或其他点位。
6 - 监控系统 Pigsty 的监控系统是如何架构与实现的,被监控的目标对象又是如何被自动纳入管理的。
7 - 安全合规 身份认证、访问控制、加密通信、审计日志,满足等保三级与 SOC2 合规要求。
Pigsty 的安全理念
默认安全 :开箱即用的安全配置,无需额外设置即可获得基本保护。
渐进配置 :企业级用户可根据需求,通过配置逐步增强安全措施。
纵深防御 :多层安全机制,即使某一层被突破,仍有其他层保护。
最小权限 :只授予用户完成任务所需的最低权限,降低风险。
概览 加密备份一应俱全,只要硬件与密钥安全,您无需操心数据库的安全性。
Pigsty 针对高标准,严要求的企业级场景设计 ,采用业界领先的 安全最佳实践 保护您的数据安全(机密性/完整性/可用性),默认配置下的安全性便足以满足绝大多数场景下的合规要求。
Pigsty 会创建自签名的 CA (或使用您提供的 CA)签发证书,加密网络通信。需要保护的敏感管理页面与API端点都受到密码保护。
数据库备份使用 AES 算法加密,数据库密码使用 scram-sha-256 算法加密,并提供插件强制执行密码强度策略。
Pigsty 提供了一套开箱即用,简单易用,便于扩展的 ACL 模型,提供读/写/管理/ETL 的权限区分,并带有遵循最小权限原则的 HBA 规则集,通过多重防护确保系统机密性。
Pigsty 默认启用数据库校验和避免静默数据腐坏,通过从库副本提供坏块兜底。提供 CRIT 数据零丢失配置模板,使用 watchdog 确保为高可用 Fencing 兜底。
您可以通过 audit 插件审计数据库操作,系统与数据库日志全部收集备查,以满足合规要求。
Pigsty 正确配置 SELinux 与防火墙配置,并遵循最小权限原则设计操作系统用户组与文件权限,确保系统安全基线符合合规要求。
而且在 Etcd,MinIO 等附属可选组件上的安全上也毫不妥协,etcd 与 minio 均使用 RBAC 模型与 TLS 加密通信,确保系统整体安全性。
只要您遵循安全性最佳实践,内网部署并合理配置安全组与防火墙,合理配置的系统通过各种合规检查毫无问题。
默认安全配置 Pigsty 默认启用以下安全特性:
特性 默认配置 说明 密码加密 scram-sha-256PostgreSQL 最安全的密码哈希算法 SSL 支持 启用 客户端可选择使用 SSL 加密连接 本地 CA 自动生成 自签名 CA 签发服务器证书 HBA 分层 按来源控制 不同来源使用不同认证强度 角色系统 四层权限 只读/读写/管理员/离线 数据校验 启用 检测存储层数据损坏 审计日志 启用 记录连接和慢查询
可增强配置 通过额外配置可启用更高安全级别:
特性 配置方式 安全等级 密码强度检查 启用 passwordcheck 扩展 等保三级 强制 SSL HBA 使用 hostssl 等保三级 客户端证书 HBA 使用 cert 认证 金融级 备份加密 配置 cipher_type 合规要求 防火墙 配置 node_firewall_mode 基础设施
如果您只有一分钟,请记住这张图:
flowchart TB
subgraph L1["🌐 第 1 层:网络安全"]
L1A["防火墙 + SSL/TLS 加密 + HAProxy 代理"]
L1B["谁能连进来?连接是否加密?"]
end
subgraph L2["🔑 第 2 层:身份认证"]
L2A["HBA 规则 + SCRAM-SHA-256 密码 + 证书认证"]
L2B["你是谁?怎么证明?"]
end
subgraph L3["👤 第 3 层:访问控制"]
L3A["角色系统 + 对象权限 + 数据库隔离"]
L3B["你能做什么?能访问哪些数据?"]
end
subgraph L4["🔒 第 4 层:数据安全"]
L4A["数据校验 + 备份加密 + 审计日志"]
L4B["数据完整吗?操作有记录吗?"]
end
L1 --> L2 --> L3 --> L4 核心价值 :开箱即用的企业级安全配置,默认启用最佳实践,额外配置可达等保三级与 SOC 2 合规要求。
本章内容 章节 说明 核心问题 安全概述 安全能力总览与检查清单 整体安全架构是怎样的? 身份认证 HBA 规则、密码策略、证书认证 如何验证用户身份? 访问控制 角色系统、权限模型、数据库隔离 如何控制用户权限? 加密通信 SSL/TLS、本地 CA、证书管理 如何保护数据传输? 合规清单 等保三级与 SOC2 详细对照 如何满足合规要求?
为什么安全很重要? 数据泄露的代价 flowchart LR
Breach["💥 数据泄露"]
subgraph Direct["💰 直接损失"]
D1["监管罚款<br/>GDPR 可达全球营收 4%"]
D2["法律诉讼费用"]
D3["客户赔偿"]
end
subgraph Indirect["📉 间接损失"]
I1["品牌声誉受损"]
I2["客户信任丧失"]
I3["业务中断"]
end
subgraph Compliance["⚠️ 合规风险"]
C1["等保三级:责任追究"]
C2["SOC 2:认证撤销"]
C3["行业准入:被禁止经营"]
end
Breach --> Direct
Breach --> Indirect
Breach --> Compliance 默认用户与密码 Pigsty 默认创建以下系统用户:
用户 用途 默认密码 部署后操作 postgres系统超级用户 无密码(仅本地) 保持无密码 dbuser_dba管理员用户 DBUser.DBA必须修改 dbuser_monitor监控用户 DBUser.Monitor必须修改 replicator复制用户 DBUser.Replicator必须修改
# pigsty.yml - 修改默认密码
pg_admin_password : 'YourSecurePassword123!'
pg_monitor_password : 'AnotherSecurePass456!'
pg_replication_password : 'ReplicationPass789!'
⚠️ 重要 :生产环境部署后,请立即 修改这些默认密码!
角色与权限系统 Pigsty 提供开箱即用的四层角色系统:
flowchart TB
subgraph Admin["🔴 dbrole_admin(管理员)"]
A1["继承 dbrole_readwrite"]
A2["可以创建/删除/修改对象 DDL"]
A3["适用于:业务管理员、需要建表的应用"]
end
subgraph RW["🟡 dbrole_readwrite(读写)"]
RW1["继承 dbrole_readonly"]
RW2["可以 INSERT/UPDATE/DELETE"]
RW3["适用于:生产业务账号"]
end
subgraph RO["🟢 dbrole_readonly(只读)"]
RO1["可以 SELECT 所有表"]
RO2["适用于:报表查询、数据分析"]
end
subgraph Offline["🔵 dbrole_offline(离线)"]
OFF1["只能访问离线实例"]
OFF2["适用于:ETL、个人分析、慢查询"]
end
Admin --> |继承| RW
RW --> |继承| RO 创建业务用户 pg_users :
# 只读用户 - 用于报表查询
- name : dbuser_report
password : ReportUser123
roles : [ dbrole_readonly]
pgbouncer : true
# 读写用户 - 用于生产业务
- name : dbuser_app
password : AppUser456
roles : [ dbrole_readwrite]
pgbouncer : true
# 管理员用户 - 用于 DDL 操作
- name : dbuser_admin
password : AdminUser789
roles : [ dbrole_admin]
pgbouncer : true
HBA 访问控制 HBA(Host-Based Authentication)控制"谁可以从哪里连接":
flowchart LR
subgraph Sources["连接来源"]
S1["🏠 本地 Socket"]
S2["💻 localhost"]
S3["🏢 内网 CIDR"]
S4["🛡️ 管理节点"]
S5["🌐 外网"]
end
subgraph Auth["认证方式"]
A1["ident/peer<br/>OS 用户映射,最安全"]
A2["scram-sha-256<br/>密码认证"]
A3["scram-sha-256 + SSL<br/>强制 SSL"]
end
S1 --> A1
S2 --> A2
S3 --> A2
S4 --> A3
S5 --> A3
Note["📋 规则按顺序匹配<br/>第一条匹配的规则生效"] 自定义 HBA 规则 pg_hba_rules :
# 允许应用服务器从内网连接
- {user: dbuser_app, db: mydb, addr: '10.10.10.0/24', auth : scram-sha-256}
# 强制某些用户使用 SSL
- {user: admin, db: all, addr: world, auth : ssl}
# 要求证书认证(最高安全级别)
- {user: secure_user, db: all, addr: world, auth : cert}
加密通信 SSL/TLS 架构 sequenceDiagram
participant Client as 🖥️ 客户端
participant Server as 🐘 PostgreSQL
Client->>Server: 1. ClientHello
Server->>Client: 2. ServerHello
Server->>Client: 3. 服务器证书
Client->>Server: 4. 客户端密钥
Client->>Server: 5. 加密通道建立
Server->>Client: 5. 加密通道建立
rect rgb(200, 255, 200)
Note over Client,Server: 🔒 加密数据传输
Client->>Server: 6. 应用数据(加密)
Server->>Client: 6. 应用数据(加密)
end
Note over Client,Server: ✅ 防止窃听 ✅ 防止篡改 ✅ 验证服务器身份 本地 CA Pigsty 自动生成本地 CA 并签发证书:
/etc/pki/
├── ca.crt # CA 证书(公开)
├── ca.key # CA 私钥(保密!)
└── server.crt/key # 服务器证书/私钥
⚠️ 重要 :请安全备份 ca.key,丢失后需要重新签发所有证书!
合规对照 等保三级(GB/T 22239-2019) 安全要求 Pigsty 默认 可配置达到 说明 身份鉴别唯一性 ✅ ✅ 每个用户唯一标识 口令复杂度 ⚠️ ✅ 启用 passwordcheck 口令定期更换 ⚠️ ✅ 需要运维流程 双因素认证 ⚠️ ✅ 证书 + 密码 访问控制 ✅ ✅ HBA + 角色系统 最小权限原则 ✅ ✅ 四层角色模型 通信加密 ✅ ✅ SSL/TLS 审计日志 ✅ ✅ 连接日志 + 慢查询 数据完整性 ✅ ✅ 数据校验和 备份恢复 ✅ ✅ pgBackRest
SOC 2 Type II 控制点 Pigsty 支持 说明 CC6.1 逻辑访问控制 ✅ HBA + 角色系统 CC6.6 传输加密 ✅ SSL/TLS CC7.2 系统监控 ✅ Prometheus + Grafana CC9.1 业务连续性 ✅ 高可用 + PITR A1.2 数据恢复 ✅ pgBackRest 备份
图例 :✅ 默认满足 · ⚠️ 需要额外配置
安全检查清单 部署前 部署后(必做) 定期维护 快速配置示例 生产环境安全配置 # pigsty.yml - 生产环境安全配置示例
all :
vars :
# 修改默认密码(必须!)
pg_admin_password : 'SecureDBAPassword2024!'
pg_monitor_password : 'SecureMonitorPass2024!'
pg_replication_password : 'SecureReplPass2024!'
# 启用密码强度检查
pg_libs : 'passwordcheck, pg_stat_statements, auto_explain'
# 自定义 HBA 规则
pg_hba_rules :
# 应用服务器
- {user: app, db: appdb, addr: '10.10.10.0/24', auth : scram-sha-256}
# 管理员强制 SSL
- {user: dbuser_dba, db: all, addr: world, auth : ssl}
金融级安全配置 # 金融级配置 - 启用证书认证
pg_hba_rules :
# 交易系统使用证书认证
- {user: trade_user, db: trade, addr: world, auth : cert}
# 其他系统使用 SSL + 密码
- {user: all, db: all, addr: world, auth : ssl}
# 启用备份加密
pgbackrest_repo :
minio :
cipher_type : aes-256-cbc
cipher_pass : 'YourBackupEncryptionKey'
接下来 深入了解安全配置的细节:
👁️ 安全概述 :整体安全架构与检查清单 🔑 身份认证 :HBA 规则与密码策略 👤 访问控制 :角色系统与权限模型 🔐 加密通信 :SSL/TLS 与证书管理 ✅ 合规清单 :等保三级与 SOC2 详细对照 相关话题:
7.1 - 本地 CA Pigsty 带有一套自签名的 CA 公私钥基础设施,用于签发 SSL 证书,加密网络通信流量。
Pigsty 部署默认启用了一些安全最佳实践:使用 SSL 加密网络流量,使用 HTTPS 加密 Web 界面。
为了实现这一功能,Pigsty 内置了本地自签名的 CA ,用于签发 SSL 证书,加密网络通信流量。
在默认情况下,SSL 与 HTTPS 是启用,但不强制使用的。对于有着较高安全要求的环境,您可以强制使用 SSL 与 HTTPS。
本地CA Pigsty 默认会在初始化时,在 ADMIN节点 本机 Pigsty 源码目录(~/pigsty)中生成一个自签名的 CA。
当您需要使用 SSL,HTTPS,数字签名,签发数据库客户端证书,高级安全特性时,可以使用此 CA。
每一套 Pigsty 部署使用的 CA 都是唯一的,不同的 Pigsty 部署之间的 CA 是不相互信任的。
本地 CA 由两个文件组成,默认放置于 files/pki/ca 目录中:
ca.crt :自签名的 CA 根证书,应当分发安装至到所有纳管节点,用于证书验证。ca.key :CA 私钥,用于签发证书,验证 CA 身份,应当妥善保管,避免泄漏!请保护好CA私钥文件
请妥善保管 CA 私钥文件,不要遗失,不要泄漏。我们建议您在完成 Pigsty 安装后及时备份此文件。
使用现有CA 如果您本身已经有 CA 公私钥基础设施,Pigsty 也可以配置为使用现有 CA 。
在执行部署前,将您的 CA 公钥与私钥文件放置于 files/pki/ca 目录中即可,并使用以下名称。
files/pki/ca/ca.key # 核心的 CA 私钥文件,必须存在,如果不存在,默认会重新随机生成一个
files/pki/ca/ca.crt # 如果没有证书文件,Pigsty会自动重新从 CA 私钥生成新的根证书文件
当 Pigsty 执行 deploy.yml 与 infra.yml 剧本进行安装时,如果发现 files/pki/ca 目录中的 ca.key 私钥文件存在,则会使用已有的 CA 。ca.crt 文件可以从 ca.key 私钥文件生成,所以如果没有证书文件,Pigsty 会自动重新从 CA 私钥生成新的根证书文件。
使用现有CA时请注意
您可以将 ca_method 参数配置为 copy,确保 Pigsty 找不到本地 CA 时报错中止,而不是自行重新生成新的自签名 CA。
信任CA 在 Pigsty 安装过程中,ca.crt 会在 node.yml 剧本的 node_ca 任务中,被分发至所有节点上的 /etc/pki/ca.crt 路径下。
EL系操作系统与 Debian系操作系统默认信任的 CA 根证书路径不同,因此分发的路径与更新的方式也不同。
信任CA证书
EL
Debian / Ubuntu rm -rf /etc/pki/ca-trust/source/anchors/ca.crt
ln -s /etc/pki/ca.crt /etc/pki/ca-trust/source/anchors/ca.crt
/bin/update-ca-trust rm -rf /usr/local/share/ca-certificates/ca.crt
ln -s /etc/pki/ca.crt /usr/local/share/ca-certificates/ca.crt
/usr/sbin/update-ca-certificates Pigsty 默认会为基础设施节点上的 Web 系统使用的域名签发 HTTPS 证书,您可以 HTTPS 访问 Pigsty 的 Web 系统。
如果您希望在客户端电脑上浏览器访问时不要弹出“不受信任的 CA 证书”信息,可以将 ca.crt 分发至客户端电脑的信任证书目录中。
您可以双击 ca.crt 文件将其加入系统钥匙串,例如在 MacOS 系统中,需要打开“钥匙串访问” 搜索 pigsty-ca 然后“信任”此根证书
查看证书内容 使用以下命令,可以查阅 Pigsty CA 证书的内容
openssl x509 -text -in /etc/pki/ca.crt
本地 CA 根证书内容样例 Certificate:
Data:
Version: 3 (0x2)
Serial Number:
50:29:e3:60:96:93:f4:85:14:fe:44:81:73:b5:e1:09:2a:a8:5c:0a
Signature Algorithm: sha256WithRSAEncryption
Issuer: O=pigsty, OU=ca, CN=pigsty-ca
Validity
Not Before: Feb 7 00:56:27 2023 GMT
Not After : Jan 14 00:56:27 2123 GMT
Subject: O=pigsty, OU=ca, CN=pigsty-ca
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:c1:41:74:4f:28:c3:3c:2b:13:a2:37:05:87:31:
....
e6:bd:69:a5:5b:e3:b4:c0:65:09:6e:84:14:e9:eb:
90:f7:61
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:pigsty-ca
X509v3 Key Usage:
Digital Signature, Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:1
X509v3 Subject Key Identifier:
C5:F6:23:CE:BA:F3:96:F6:4B:48:A5:B1:CD:D4:FA:2B:BD:6F:A6:9C
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
89:9d:21:35:59:6b:2c:9b:c7:6d:26:5b:a9:49:80:93:81:18:
....
9e:dd:87:88:0d:c4:29:9e
-----BEGIN CERTIFICATE-----
...
cXyWAYcvfPae3YeIDcQpng==
-----END CERTIFICATE-----
签发证书 如果您希望通过客户端证书认证,那么可以使用本地 CA 与 cert.yml 剧本手工签发PostgreSQL 客户端证书。
将证书的 CN 字段设置为数据库用户名即可:
./cert.yml -e cn = dbuser_dba
./cert.yml -e cn = dbuser_monitor
签发的证书会默认生成在 files/pki/misc/<cn>.{key,crt} 路径下。
7.2 - 七层安全模型 Pigsty 如何在七个安全层次上提供纵深防御,从物理安全到用户安全。
安全不是一道墙,而是一座城。Pigsty 采用 纵深防御 策略,在七个层次上构建多重保护,即使某一层被突破,仍有其他层提供保护。
概览
物理安全 物理访问失守,则其他层形同虚设。
物理安全是最基础的一层,涉及机房门禁、监控、环境控制、设备防盗、电力保障等。Pigsty 作为软件解决方案,在物理层面提供以下保护机制:
数据校验和 启用数据校验和可以检测存储层的静默数据损坏(如磁盘坏块、内存错误、固件 Bug):
pg_checksum : true # v3.5+ 默认启用
原理 :PostgreSQL 在每个数据页写入时计算校验和,读取时验证。发现损坏时报错而非返回错误数据。
兜底机制 :从库副本提供坏块兜底,主库数据页损坏时可从从库恢复。
透明数据加密 对于有合规要求的场景,可使用 PGTDE (PostgreSQL Transparent Data Encryption)扩展:
pg_extensions :
- pg_tde # 透明数据加密扩展
效果 :数据在磁盘上以加密形式存储,即使物理介质被盗也无法读取数据。
网络安全 控制数据包层面的访问和过滤。
防火墙 Pigsty 支持节点级防火墙配置,控制哪些端口对外开放:
node_firewall_mode : zone # off | none | zone
node_firewall_intranet : # 内网 CIDR(信任区域)
- 10.0.0.0 /8
- 172.16.0.0 /12
- 192.168.0.0 /16
node_firewall_public_port : # 公网开放端口
- 22 # SSH
- 80 # HTTP
- 443 # HTTPS
三种模式 :
模式 说明 适用场景 off不配置防火墙(默认) 开发环境、已有安全组 none禁用 firewalld 使用外部防火墙 zone区域模式:内网信任,公网受限 生产环境推荐
SSL/TLS 加密 Pigsty 在多个层次提供 SSL/TLS 加密:
组件 参数 默认值 说明 PostgreSQL HBA auth pwd支持 ssl(强制)、cert(证书) Pgbouncer pgbouncer_sslmodedisable可选 require / verify-full Patroni patroni_ssl_enabledfalseREST API 加密 Nginx nginx_sslmodeenable可选 enforce(强制 HTTPS) MinIO 默认启用 启用 使用本地 CA 证书 etcd 默认启用 启用 TLS 加密通信
安全加固配置 :
patroni_ssl_enabled : true # 启用 Patroni SSL
pgbouncer_sslmode : require # 强制 Pgbouncer SSL
nginx_sslmode : enforce # 强制 HTTPS
本地 CA 证书基础设施 Pigsty 自动生成本地 CA 并签发证书,无需购买商业证书:
files/pki/ca/
├── ca.crt # CA 证书(公开,分发到所有节点)
└── ca.key # CA 私钥(⚠️ 保密!安全备份!)
/etc/pki/ # 节点上的证书目录
├── ca.crt # CA 证书
├── server.crt # 服务器证书
└── server.key # 服务器私钥
⚠️ 重要 :请安全备份 ca.key,丢失后需要重新签发所有证书!
边界安全 处理内外网交界处的安全策略。
HAProxy 安全 HAProxy 作为数据库流量的统一入口,提供以下安全功能:
haproxy_admin_password : 'StrongPassword123' # 管理界面密码
安全特性 :
健康检查与流量控制,避免脑裂 连接限制与速率限制 管理界面密码保护 Nginx 安全 Nginx 作为 Web 服务的统一网关,提供:
nginx_sslmode : enforce # 强制 HTTPS
infra_portal : # 配置各组件域名
grafana : { domain : g.pigsty.cc }
alertmanager : { domain : a.pigsty.cc }
安全特性 :
统一的 HTTPS 入口,便于审计 反向代理保护后端服务 可集成外部认证(OAuth、LDAP) 主机安全 操作系统加固、补丁管理、最小化安装。
SELinux 配置 Pigsty 正确配置 SELinux 策略,确保 PostgreSQL 等服务正常运行:
node_selinux_mode : permissive # disabled | permissive | enforcing
模式 说明 适用场景 disabled完全禁用 开发环境 permissive宽容模式(记录但不阻止) 生产环境推荐 enforcing强制模式 高安全要求环境
操作系统加固 Pigsty 遵循最小权限原则设计:
文件权限 :敏感文件(如 CA 私钥)权限严格控制用户组 :PostgreSQL、etcd 等服务使用专用用户运行管理员配置 :node_admin_username : dba # 管理员用户名
node_admin_sudo : nopasswd # sudo 策略
系统更新 保持关键安全组件更新:
openssh:SSH 服务ca-certificates:系统根证书openssl:加密库应用安全 数据库配置、认证授权、输入验证。
密码策略 密码加密算法 pg_pwd_enc : scram-sha-256 # 最安全的密码哈希算法
算法 安全性 兼容性 说明 scram-sha-256⭐⭐⭐ PostgreSQL 10+ 推荐,默认值 md5⭐ 所有版本 仅用于老旧客户端
密码强度检查 启用 passwordcheck 扩展强制密码复杂度:
pg_libs : '$libdir/passwordcheck, pg_stat_statements, auto_explain'
pg_extensions :
- passwordcheck # 强制密码复杂度
- credcheck # 额外的密码检查
密码过期 pg_users :
- { name: dbuser_app, password: 'SecurePass123', expire_in : 365 } # 1年后过期
HBA 规则 HBA(Host-Based Authentication)控制"谁可以从哪里连接,使用什么方式认证":
pg_default_hba_rules :
- {user : '${dbsu}' ,db: all ,addr: local ,auth: ident ,title : 'dbsu local via ident' }
- {user : '${dbsu}' ,db: replication ,addr: local ,auth: ident ,title : 'dbsu repl via ident' }
- {user : '${repl}' ,db: replication ,addr: localhost ,auth: pwd ,title : 'repl via localhost' }
- {user : '${repl}' ,db: replication ,addr: intra ,auth: pwd ,title : 'repl from intranet' }
- {user : '${repl}' ,db: postgres ,addr: intra ,auth: pwd ,title : 'repl from intranet' }
- {user : '${monitor}' ,db: all ,addr: localhost ,auth: pwd ,title : 'monitor via localhost' }
- {user : '${monitor}' ,db: all ,addr: infra ,auth: pwd ,title : 'monitor from infra' }
- {user : '${admin}' ,db: all ,addr: infra ,auth: ssl ,title : 'admin from infra' }
- {user : '${admin}' ,db: all ,addr: world ,auth: ssl ,title : 'admin from world' }
- {user: '+dbrole_readonly',db: all ,addr: localhost ,auth: pwd ,title : 'read from localhost' }
- {user: '+dbrole_readonly',db: all ,addr: intra ,auth: pwd ,title : 'read from intranet' }
- {user: '+dbrole_offline' ,db: all ,addr: intra ,auth: pwd ,title : 'offline from intranet' }
认证方式 :
别名 说明 安全等级 ident/peerOS 用户映射 ⭐⭐⭐ 仅本地 pwd密码认证(scram-sha-256) ⭐⭐ ssl强制 SSL + 密码 ⭐⭐⭐ cert客户端证书认证 ⭐⭐⭐⭐ 最高 deny拒绝访问 -
监听地址 限制 PostgreSQL 监听的网络接口:
pg_listen : '${ip},${vip},${lo}' # 仅监听特定 IP,而非 0.0.0.0
数据安全 加密、备份、审计、完整性保护。
备份加密 pgBackRest 支持 AES-256 加密备份:
pgbackrest_repo :
minio :
cipher_type : aes-256-cbc # AES-256-CBC 加密
cipher_pass : 'pgBR.${pg_cluster}' # 使用集群名作为密码一部分
效果 :备份文件在存储中以加密形式保存,即使存储被入侵也无法读取数据。
审计日志 PostgreSQL 审计扩展 pg_extensions :
- pgaudit # SQL 审计日志
- pgauditlogtofile # 审计日志写入文件
- pg_auth_mon # 认证监控
- pg_auditor # 审计辅助
连接日志 # 在 pg_parameters 中配置
log_connections : on # 记录连接建立
log_disconnections : on # 记录连接断开
慢查询日志 log_min_duration_statement : 1000 # 记录 >1s 的查询
时间点恢复(PITR) Pigsty 默认配置 pgBackRest 支持时间点恢复:
pgbackrest_enabled : true
pgbackrest_repo :
local : # 本地备份
path : /pg/backup
retention_full : 2
minio : # 远程备份
path : /pgbackrest
retention_full_type : time
retention_full : 14 # 保留 14 天
用户安全 身份认证、权限管理、行为审计。
四角色模型 Pigsty 提供开箱即用的四层权限角色:
flowchart TB
subgraph Admin["🔴 dbrole_admin(管理员)"]
A1["继承 dbrole_readwrite"]
A2["可以 CREATE/DROP/ALTER(DDL)"]
A3["适用于:业务管理员、建表应用"]
end
subgraph RW["🟡 dbrole_readwrite(读写)"]
RW1["继承 dbrole_readonly"]
RW2["可以 INSERT/UPDATE/DELETE"]
RW3["适用于:生产业务账号"]
end
subgraph RO["🟢 dbrole_readonly(只读)"]
RO1["可以 SELECT 所有表"]
RO2["适用于:报表查询、数据分析"]
end
subgraph Offline["🔵 dbrole_offline(离线)"]
OFF1["只能访问离线实例"]
OFF2["适用于:ETL、慢查询、个人分析"]
end
Admin --> |继承| RW
RW --> |继承| RO 创建业务用户 :
pg_users :
- { name: dbuser_report, password: 'ReportPass123', roles : [ dbrole_readonly] }
- { name: dbuser_app, password: 'AppPass456', roles : [ dbrole_readwrite] }
- { name: dbuser_admin, password: 'AdminPass789', roles : [ dbrole_admin] }
默认用户与密码 用户 默认密码 用途 部署后操作 postgres无密码(仅本地) 系统超级用户 保持无密码 dbuser_dbaDBUser.DBA管理员用户 必须修改 dbuser_monitorDBUser.Monitor监控用户 必须修改 replicatorDBUser.Replicator复制用户 必须修改
自动生成强密码 :
./configure -g # 自动生成随机强密码
证书认证 最高安全级别,要求客户端提供有效证书:
pg_hba_rules :
- {user: admin, db: all, addr: world, auth : cert} # 管理员使用证书认证
ETCD 与 MinIO 安全 附属组件同样采用 RBAC 模型与 TLS 加密:
# ETCD
etcd_root_password : 'Etcd.Root.Strong' # 必须修改
# MinIO
minio_access_key : minioadmin
minio_secret_key : 'S3User.MinIO.Strong' # 必须修改
minio_users :
- { access_key: pgbackrest, secret_key: 'Min10.bAckup', policy : readwrite }
- { access_key: dba, secret_key: 'S3User.DBA.Strong', policy : consoleAdmin }
Watchdog 防护 防止脑裂,确保故障切换时主库强制关机:
patroni_watchdog_mode : required # off | automatic | required
效果 :当 Patroni 进程异常时,watchdog 强制重启节点,避免双主脑裂。
合规对照 等保三级(GB/T 22239-2019) 安全要求 Pigsty 默认 可配置达到 实现方式 身份鉴别唯一性 ✅ ✅ 用户名唯一标识 口令复杂度 ⚠️ ✅ passwordcheck 扩展口令定期更换 ⚠️ ✅ expire_in 属性双因素认证 ⚠️ ✅ 证书 + 密码 (auth: cert) 访问控制 ✅ ✅ HBA + 四层角色模型 最小权限原则 ✅ ✅ dbrole_readonly/readwrite/admin通信加密 ✅ ✅ SSL/TLS 审计日志 ✅ ✅ pgaudit + 连接日志数据完整性 ✅ ✅ pg_checksum: true备份恢复 ✅ ✅ pgBackRest + PITR
SOC 2 Type II 控制点 Pigsty 支持 实现方式 CC6.1 逻辑访问控制 ✅ HBA + RBAC CC6.6 传输加密 ✅ SSL/TLS(可强制) CC7.2 系统监控 ✅ Prometheus + Grafana CC9.1 业务连续性 ✅ 高可用 + PITR A1.2 数据恢复 ✅ pgBackRest 备份
图例 :✅ 默认满足 · ⚠️ 需要额外配置
安全检查清单 部署前 部署后(必做) 增强安全(可选) 接下来 深入了解安全配置的细节:
相关话题:
7.3 - 访问控制 Pigsty 提供了标准的安全实践:密码与证书认证,开箱即用的权限模型,SSL加密网络流量,加密远程冷备份等。
Pigsty 提供了一套开箱即用的,基于 角色系统 和 权限系统 的访问控制模型。
权限控制很重要,但很多用户做不好。因此 Pigsty 提供了一套开箱即用的精简访问控制模型,为您的集群安全性提供一个兜底。
角色系统 Pigsty 默认的角色系统包含四个 默认角色 和四个 默认用户 :
角色名称 属性 所属 描述 dbrole_readonlyNOLOGIN角色:全局只读访问 dbrole_readwriteNOLOGINdbrole_readonly 角色:全局读写访问 dbrole_adminNOLOGINpg_monitor,dbrole_readwrite 角色:管理员/对象创建 dbrole_offlineNOLOGIN角色:受限的只读访问 postgresSUPERUSER系统超级用户 replicatorREPLICATIONpg_monitor,dbrole_readonly 系统复制用户 dbuser_dbaSUPERUSERdbrole_admin pgsql 管理用户 dbuser_monitorpg_monitor pgsql 监控用户
这些 角色与用户 的详细定义如下所示:
pg_default_roles : # 全局默认的角色与系统用户
- { name: dbrole_readonly ,login: false ,comment : role for global read-only access }
- { name: dbrole_offline ,login: false ,comment : role for restricted read-only access }
- { name: dbrole_readwrite ,login: false ,roles: [dbrole_readonly] ,comment : role for global read-write access }
- { name: dbrole_admin ,login: false ,roles: [pg_monitor, dbrole_readwrite] ,comment : role for object creation }
- { name: postgres ,superuser: true ,comment : system superuser }
- { name: replicator ,replication: true ,roles: [pg_monitor, dbrole_readonly] ,comment : system replicator }
- { name: dbuser_dba ,superuser: true ,roles: [dbrole_admin] ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 ,comment : pgsql admin user }
- { name: dbuser_monitor ,roles: [pg_monitor] ,pgbouncer: true ,parameters : {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment : pgsql monitor user }
默认角色 Pigsty 中有四个默认角色:
业务只读 (dbrole_readonly): 用于全局只读访问的角色。如果别的业务想要此库只读访问权限,可以使用此角色。 业务读写 (dbrole_readwrite): 用于全局读写访问的角色,主属业务使用的生产账号应当具有数据库读写权限 业务管理员 (dbrole_admin): 拥有DDL权限的角色,通常用于业务管理员,或者需要在应用中建表的场景(比如各种业务软件) 离线只读访问 (dbrole_offline): 受限的只读访问角色(只能访问 offline 实例,通常是个人用户,ETL工具账号) 默认角色在 pg_default_roles 中定义,除非您确实知道自己在干什么,建议不要更改默认角色的名称。
- { name: dbrole_readonly , login: false , comment : role for global read-only access } # 生产环境的只读角色
- { name: dbrole_offline , login: false , comment : role for restricted read-only access (offline instance) } # 受限的只读角色
- { name: dbrole_readwrite , login: false , roles: [dbrole_readonly], comment : role for global read-write access } # 生产环境的读写角色
- { name: dbrole_admin , login: false , roles: [pg_monitor, dbrole_readwrite] , comment : role for object creation } # 生产环境的 DDL 更改角色
默认用户 Pigsty 也有四个默认用户(系统用户):
超级用户 (postgres),集群的所有者和创建者,与操作系统 dbsu 名称相同。 复制用户 (replicator),用于主-从复制的系统用户。 监控用户 (dbuser_monitor),用于监控数据库和连接池指标的用户。 管理用户 (dbuser_dba),执行日常操作和数据库更改的管理员用户。 这4个默认用户的用户名/密码通过4对专用参数进行定义,并在很多地方引用:
在生产部署中记得更改这些密码,不要使用默认值!
pg_dbsu : postgres # 数据库超级用户名,这个用户名建议不要修改。
pg_dbsu_password : '' # 数据库超级用户密码,这个密码建议留空!禁止dbsu密码登陆。
pg_replication_username : replicator # 系统复制用户名
pg_replication_password : DBUser.Replicator # 系统复制密码,请务必修改此密码!
pg_monitor_username : dbuser_monitor # 系统监控用户名
pg_monitor_password : DBUser.Monitor # 系统监控密码,请务必修改此密码!
pg_admin_username : dbuser_dba # 系统管理用户名
pg_admin_password : DBUser.DBA # 系统管理密码,请务必修改此密码!
如果您修改默认用户的参数,在 pg_default_roles 中修改相应的角色 定义 即可:
- { name: postgres ,superuser: true ,comment : system superuser }
- { name: replicator ,replication: true ,roles: [pg_monitor, dbrole_readonly] ,comment : system replicator }
- { name: dbuser_dba ,superuser: true ,roles: [dbrole_admin] ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 , comment : pgsql admin user }
- { name: dbuser_monitor ,roles: [pg_monitor, dbrole_readonly] ,pgbouncer: true ,parameters : {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment : pgsql monitor user }
权限系统 Pigsty 拥有一套开箱即用的权限模型,该模型与 默认角色 一起配合工作。
所有用户都可以访问所有模式。 只读用户(dbrole_readonly)可以从所有表中读取数据。(SELECT,EXECUTE) 读写用户(dbrole_readwrite)可以向所有表中写入数据并运行 DML。(INSERT,UPDATE,DELETE)。 管理员用户(dbrole_admin)可以创建对象并运行 DDL(CREATE,USAGE,TRUNCATE,REFERENCES,TRIGGER)。 离线用户(dbrole_offline)类似只读用户,但访问受到限制,只允许访问 离线实例 (pg_role = 'offline' 或 pg_offline_query = true) 由管理员用户创建的对象将具有正确的权限。 所有数据库上都配置了默认权限,包括模板数据库。 数据库连接权限由数据库 定义 管理。 默认撤销PUBLIC在数据库和public模式下的CREATE权限。 对象权限 数据库中新建对象的默认权限由参数 pg_default_privileges 所控制:
- GRANT USAGE ON SCHEMAS TO dbrole_readonly
- GRANT SELECT ON TABLES TO dbrole_readonly
- GRANT SELECT ON SEQUENCES TO dbrole_readonly
- GRANT EXECUTE ON FUNCTIONS TO dbrole_readonly
- GRANT USAGE ON SCHEMAS TO dbrole_offline
- GRANT SELECT ON TABLES TO dbrole_offline
- GRANT SELECT ON SEQUENCES TO dbrole_offline
- GRANT EXECUTE ON FUNCTIONS TO dbrole_offline
- GRANT INSERT ON TABLES TO dbrole_readwrite
- GRANT UPDATE ON TABLES TO dbrole_readwrite
- GRANT DELETE ON TABLES TO dbrole_readwrite
- GRANT USAGE ON SEQUENCES TO dbrole_readwrite
- GRANT UPDATE ON SEQUENCES TO dbrole_readwrite
- GRANT TRUNCATE ON TABLES TO dbrole_admin
- GRANT REFERENCES ON TABLES TO dbrole_admin
- GRANT TRIGGER ON TABLES TO dbrole_admin
- GRANT CREATE ON SCHEMAS TO dbrole_admin
由管理员新创建 的对象,默认将会上述权限。使用 \ddp+ 可以查看这些默认权限:
类型 访问权限 函数 =X dbrole_readonly=X dbrole_offline=X dbrole_admin=X 模式 dbrole_readonly=U dbrole_offline=U dbrole_admin=UC 序列号 dbrole_readonly=r dbrole_offline=r dbrole_readwrite=wU dbrole_admin=rwU 表 dbrole_readonly=r dbrole_offline=r dbrole_readwrite=awd dbrole_admin=arwdDxt
默认权限 SQL 语句 ALTER DEFAULT PRIVILEGES 允许您设置将来创建的对象的权限。 它不会影响已经存在对象的权限,也不会影响非管理员用户创建的对象。
在 Pigsty 中,默认权限针对三个角色进行定义:
{ % for priv in pg_default_privileges % }
ALTER DEFAULT PRIVILEGES FOR ROLE {{ pg_dbsu }} {{ priv }} ;
{ % endfor % }
{ % for priv in pg_default_privileges % }
ALTER DEFAULT PRIVILEGES FOR ROLE {{ pg_admin_username }} {{ priv }} ;
{ % endfor % }
-- 对于其他业务管理员而言,它们应当在执行 DDL 前执行 SET ROLE dbrole_admin,从而使用对应的默认权限配置。
{ % for priv in pg_default_privileges % }
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" {{ priv }} ;
{ % endfor % }
这些内容将会被 PG集群初始化模板 pg-init-template.sql 所使用,在集群初始化的过程中渲染并输出至 /pg/tmp/pg-init-template.sql。
该命令会在 template1 与 postgres 数据库中执行,新创建的数据库会通过模板 template1 继承这些默认权限配置。
也就是说,为了维持正确的对象权限,您必须用管理员用户 来执行 DDL,它们可以是:
{{ pg_dbsu }} ,默认为 postgres{{ pg_admin_username }} ,默认为 dbuser_dba授予了 dbrole_admin 角色的业务管理员用户(通过 SET ROLE 切换为 dbrole_admin 身份)。 使用 postgres 作为全局对象所有者是明智的。如果您希望以业务管理员用户身份创建对象,创建之前必须使用 SET ROLE dbrole_admin 来维护正确的权限。
当然,您也可以在数据库中通过 ALTER DEFAULT PRIVILEGE FOR ROLE <some_biz_admin> XXX 来显式对业务管理员授予默认权限。
数据库权限 在 Pigsty 中,数据库(Database)层面的权限在 数据库定义 中被涵盖。
数据库有三个级别的权限:CONNECT、CREATE、TEMP,以及一个特殊的’权限’:OWNERSHIP。
- name : meta # 必选,`name` 是数据库定义中唯一的必选字段
owner : postgres # 可选,数据库所有者,默认为 postgres
allowconn : true # 可选,是否允许连接,默认为 true。显式设置 false 将完全禁止连接到此数据库
revokeconn : false # 可选,撤销公共连接权限。默认为 false,设置为 true 时,属主和管理员之外用户的 CONNECT 权限会被回收
如果 owner 参数存在,它作为数据库属主,替代默认的 {{ pg_dbsu }} (通常也就是postgres) 如果 revokeconn 为 false,所有用户都有数据库的 CONNECT 权限,这是默认的行为。 如果显式设置了 revokeconn 为 true:数据库的 CONNECT 权限将从 PUBLIC 中撤销:普通用户无法连接上此数据库 CONNECT 权限将被显式授予 {{ pg_replication_username }}、{{ pg_monitor_username }} 和 {{ pg_admin_username }}CONNECT 权限将 GRANT OPTION 被授予数据库属主,数据库属主用户可以自行授权其他用户连接权限。 revokeconn 选项可用于在同一个集群间隔离跨数据库访问,您可以为每个数据库创建不同的业务用户作为属主,并为它们设置 revokeconn 选项。示例:数据库隔离 pg-infra :
hosts :
10.10.10.40 : { pg_seq: 1, pg_role : primary }
10.10.10.41 : { pg_seq: 2, pg_role: replica , pg_offline_query : true }
vars :
pg_cluster : pg-infra
pg_users :
- { name: dbuser_confluence, password: mc2iohos , pgbouncer: true, roles : [ dbrole_admin ] }
- { name: dbuser_gitlab, password: sdf23g22sfdd , pgbouncer: true, roles : [ dbrole_readwrite ] }
- { name: dbuser_jira, password: sdpijfsfdsfdfs , pgbouncer: true, roles : [ dbrole_admin ] }
pg_databases :
- { name: confluence , revokeconn: true, owner: dbuser_confluence , connlimit : 100 }
- { name: gitlab , revokeconn: true, owner: dbuser_gitlab, connlimit : 100 }
- { name: jira , revokeconn: true, owner: dbuser_jira , connlimit : 100 }
CREATE权限 出于安全考虑,Pigsty 默认从 PUBLIC 撤销数据库上的 CREATE 权限,从 PostgreSQL 15 开始这也是默认行为。
数据库属主总是可以根据实际需要,来自行调整 CREATE 权限。