跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

Pigsty v5.0 文档

从核心概念和快速上手,到生产部署、模块参考与日常运维。

Pigsty v5.0 文档聚焦 Pigsty 自身:架构、安装、部署、配置、运维,以及每个正式模块的完整手册。

v5.0 文档预览 OINK 0.6.0 本地优先

K(macOS)或 CtrlK 可随时打开离线搜索与命令面板。

开始使用

核心模块

PGSQL核心

高可用 PostgreSQL 集群、服务、备份、监控、安全与日常管理。

INFRA核心

VictoriaMetrics、VictoriaLogs、Grafana、Nginx 与基础设施服务。

NODE核心

主机纳管、软件基线、日志采集、VIP 与 HAProxy 负载均衡。

ETCD核心

为 PostgreSQL 高可用提供可靠的分布式配置存储。

可选模块

S3 兼容对象存储与 PostgreSQL 备份仓库。

JUICE文件系统

以 PostgreSQL 和对象存储为后端的 JuiceFS。

KAFKA消息

动态 KRaft、TLS、ACL 与完整可观测性。

MYSQL数据库

MySQL 8.4 LTS 与 InnoDB Cluster。

DOCKER运行时

受管 Docker 服务与容器运行环境。

VIBE开发

Code-Server、Jupyter 与 AI 编程沙箱。

内容边界

本站不复制 Pig、Patroni、pg_exporter、pgBackRest、PgBouncer、软件仓库、应用模板和试点项目的独立手册。正文确需引用这些组件时,会链接到原有文档站;Pigsty 自身的集成、配置与运维说明仍保留在对应模块内。

1 - 上手

在你的笔记本/云服务器上部署 Pigsty 单机版本,访问数据库以及 Web 用户界面

Pigsty 采用可伸缩的架构设计,既可用于 超大规模生产环境,也可用于 单机开发演示环境,本文关注后者。

如果您打算学习了解 Pigsty,可以从 快速上手 单机部署开始。一台 1C/2G 的 Linux 虚拟机即可运行 Pigsty。

您可以利用一台 Linux MiniPC,云厂商提供的免费/优惠虚拟机,Windows 的 WSL,或者在自己的笔记本上创建虚拟机用于 Pigsty 部署。 Pigsty 提供了开箱即用的 Vagrant 模板与 Terraform 模版,可以帮助您一键在本地或云端置备 Linux 虚拟机。

pigsty-arch

单机版本的 Pigsty 包含了所有核心功能,575PG 扩展,自包含的 Grafana / Victoria 监控,IaC 置备能力。 以及本地 PITR 时间点恢复。如果您配备了外部的对象存储(用于 PostgreSQL PITR 备份),那么对于 Demo,个人网站,小型服务等场景, 即使是单机环境,也可以提供一定程度的 数据持久性 保证。 不过,单机无法实现 高可用 —— 故障自动切换至少需要 3 个节点。

如果您想要在没有互联网连接的环境中安装 Pigsty,请参考 离线安装 模式。 如果您只需要 PostgreSQL 数据库本身,请参考 精简安装 模式。 如果您准备开始进行严肃的多节点生产部署,请参考 部署指南


快速开始

准备 一台具有 SSH 权限节点, 安装 兼容的 Linux 系统,使用具有免密 sshsudo 权限的 管理用户 执行:

curl -fsSL https://repo.pigsty.cc/get | bash  # 安装 Pigsty 与依赖
cd ~/pigsty; ./configure -g                   # 生成配置(使用默认单机配置模板,-g 参数会生成随机密码)
./deploy.yml                                  # 执行部署剧本,完成部署

是的,就是这么简单。您完全可以在不了解任何细节的情况下,使用 预制配置模板 一键拉起 Pigsty。

接下来,您可以探索 图形用户界面,访问 PostgreSQL 数据库服务;或者进行 配置定制执行剧本 部署更多集群。

1.1 - 快速上手 Pigsty 单机部署

快速上手 Pigsty,从一台全新的 Linux 主机开始,完成单机安装部署!

本文是 Pigsty 单节点安装指南 单节点,生产环境的多节点高可用部署请参考 部署 文档。

Pigsty 单机安装分为三步走:安装配置部署


摘要

准备 一台具有 SSH 权限节点, 安装 兼容的 Linux 系统,使用具有免密 sshsudo 权限的 管理用户 执行:

选择 Pigsty 下载镜像:

pigsty.cc(中国)
curl -fsSL https://repo.pigsty.cc/get | bash
pigsty.io(全球)
curl -fsSL https://repo.pigsty.io/get | bash

该命令会执行 安装 脚本,下载并提取 Pigsty 源码至家目录并安装依赖,接下来依次完成 配置部署 即可完成交付。

进入源码目录

Terminal
cd ~/pigsty

生成配置清单

Terminal
./configure -g

如果你已经准备好 pigsty.yml,可以跳过这一步。

执行部署剧本

Terminal
./deploy.yml

安装完成后,您可以通过 IP / 域名 + 80/443 端口访问 Web 用户界面, 并通过 5432 端口访问 PostgreSQL 服务

完整流程根据服务器规格/网络条件需 3~10 分钟,离线安装 时能够显著加速;无需监控时可使用 精简安装 进一步加速。

视频样例:在线单机安装(Debian 13, x86_64)

demo/install-hero.cast

准备

安装 Pigsty 涉及一些 准备工作,以下是简略检查清单,单机部署时,许多限制可以放宽。

项目 要求 项目 要求
节点 单节点,至少 1C2G,上不封顶 磁盘 /data 作为默认主挂载点,建议使用 xfs
系统 Linux x86_64 / aarch64,EL / Debian / Ubuntu 网络 静态 IPv4 内网地址
SSH 通过公钥 nopass SSH 登陆纳管节点 SUDO sudo 权限,最好带有 nopass 免密选项

通常您只需要关注本机 IP 地址 —— 作为特例,单机部署时,如果没有静态 IP 地址,可使用 127.0.0.1 作为逃生窗口。


安装

您可以使用以下命令自动安装 Pigsty 源码包至 ~/pigsty 目录(推荐),部署所需依赖(Ansible)会自动安装。

选择 Pigsty 下载镜像:

pigsty.cc(中国)
curl -fsSL https://repo.pigsty.cc/get | bash            # 安装当前默认版本
curl -fsSL https://repo.pigsty.cc/get | bash -s v4.5.0  # 显式安装当前公开稳定版
pigsty.io(全球)
curl -fsSL https://repo.pigsty.io/get | bash            # 安装当前默认版本
curl -fsSL https://repo.pigsty.io/get | bash -s v4.5.0  # 显式安装当前公开稳定版

如果您不希望执行远程脚本,可以手动 下载 或克隆源码。使用 git 克隆安装时,请务必检出特定版本后再使用。

Terminal
git clone https://github.com/pgsty/pigsty; cd pigsty;
git checkout v4.5.0;  # 使用 git 安装时,请务必检出已发布的 tag

手工下载克隆安装时,请额外执行 bootstrap 脚本以手动安装 Ansible 等部署依赖,您也可以 自行安装

Terminal
./bootstrap           # 安装 ansible,用于执行后续部署

配置

在 Pigsty 中,部署的蓝图细节由 配置清单 所定义,也就是 pigsty.yml 配置文件,您可以通过声明式配置进行定制。

Pigsty 提供了 configure 脚本作为可选的 配置向导, 它将根据您的环境和输入,生成具有良好默认值的 配置清单

Terminal
./configure -g                # 使用配置向导生成配置文件,并且生成随机密码

配置过程生成的配置文件默认位于:~/pigsty/pigsty.yml,您可以在安装前进行检查,按需修改与定制。

有许多 配置模板 供您参考与使用,但您也完全可以跳过配置向导,直接编辑 pigsty.yml 配置文件进行定制。

Terminal
./configure                  # 使用默认模板,安装默认的 PG 18,带有必要扩展
./configure -v 17            # 使用 PG 17 的版本,而非默认的 PG18
./configure -c rich          # 创建本地软件仓库,下载所有扩展,安装主要扩展
./configure -c slim          # 最小安装模板,与 ./slim.yml 剧本一起使用
./configure -c app/supa      # 使用 app/supa 自托管 supabase 配置模板
./configure -c ivory         # 使用 ivorysql 内核而非原生 PG
./configure -i 10.11.12.13   # 显式指定主 IP 地址
./configure -r china         # 使用中国镜像而非默认仓库
./configure -c ha/full -s    # 使用 4 节点沙箱配置模板,不进行 IP 替换和探测

下面展示的是当前 main 分支(v5.0.0-preview)的输出;若安装其他版本,首行会显示对应版本号。

当前 main 分支的 configure 样例输出
示例 1 当前 main 分支的 configure 样例输出
configure output
vagrant@meta:~/pigsty$ ./configure
configure pigsty v4.5.0 begin
[ OK ] region = china
[ OK ] kernel  = Linux
[ OK ] machine = x86_64
[ OK ] package = deb,apt
[ OK ] vendor  = ubuntu (Ubuntu)
[ OK ] version = 22 (22.04)
[ OK ] sudo = vagrant ok
[ OK ] ssh = [email protected] ok
[WARN] Multiple IP address candidates found:
    (1) 192.168.121.38	    inet 192.168.121.38/24 metric 100 brd 192.168.121.255 scope global dynamic eth0
    (2) 10.10.10.10	    inet 10.10.10.10/24 brd 10.10.10.255 scope global eth1
[ OK ] primary_ip = 10.10.10.10 (from demo)
[ OK ] admin = [email protected] ok
[ OK ] mode = meta (ubuntu22.04)
[ 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

配置脚本常用参数

-i | --ip , IPv4

当前主机的首要内网 IP 地址,用于替换配置文件中的 IP 地址占位符 10.10.10.10

-c | --conf , string

指定 配置模板,填写相对于 conf/ 目录且不带 .yml 后缀的名称。

-v | --version , integer

指定 PostgreSQL 大版本 1419;PG19 当前为 Beta,建议使用专用 pg19 模板。

-r | --region , enum , defaultdefault

指定上游软件源区域以加速下载:defaultchinaeurope

-n | --non-interactive , boolean , defaultfalse

直接使用命令行参数提供首要 IP 地址,跳过交互式向导。

-x | --proxy , boolean , defaultfalse

使用当前环境变量配置 proxy_env 变量。

如果您的机器网卡绑定了多个 IP 地址,那么需要使用 -i|--ip <ipaddr> 显式指定一个当前节点的首要 IP 地址,或在交互式问询中提供。 该脚本将把 IP 占位符 10.10.10.10 替换为当前节点的主 IPv4 地址。选用的地址应为静态 IP 地址,请勿使用公网 IP 地址。

修改默认密码!

我们强烈建议您在安装前,事先修改配置文件中使用的默认密码与凭据,详情参考 安全建议


部署

Pigsty 的 deploy.yml 剧本 会将 配置 中生成的蓝图应用至目标节点。

Terminal
./deploy.yml     # 一次性部署核心链路中已定义的模块
部署过程的样例输出
deploy output
......

TASK [pgsql : pgsql init done] *************************************************
ok: [10.10.10.11] => {
    "msg": "postgres://10.10.10.11/postgres | meta  | dbuser_meta dbuser_view "
}
......

TASK [pg_monitor : load grafana datasource meta] *******************************
changed: [10.10.10.11]

PLAY RECAP *********************************************************************
10.10.10.11                : ok=302  changed=232  unreachable=0    failed=0    skipped=65   rescued=0    ignored=1
localhost                  : ok=6    changed=3    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

当您看到输出尾部如果带有 pgsql init donePLAY RECAP 等字样,说明安装已经完成!

上游软件仓库变更可能导致在线安装失败!

Pigsty 使用的上游软件仓库(如 Linux / PGDG 仓库)可能会因为不恰当的更新,进入崩溃状态并导致部署失败(有过多次先例)! 您可以选择等待上游仓库修复后安装,或者使用预制的 离线软件包 解决这个问题。

避免重复执行部署剧本!

警告: 在已经完成部署的环境中再次完整运行 deploy.yml 可能会重启相关服务并覆盖配置,请务必注意!


界面

Pigsty 单机安装完成后,您在当前节点上通常会安装有四个功能模块: PGSQLINFRANODEETCD

ID NODE PGSQL INFRA ETCD
1 10.10.10.10 pg-meta-1 infra-1 etcd-1

INFRA 模块通过浏览器提供了一个 图形化管理界面,您可以直接通过这台节点上的 Nginx 的 80/443 端口访问。

PGSQL 模块提供了一个 PostgreSQL 数据库服务器,监听 5432 端口,也可通过 Pgbouncer / HAProxy 代理访问

Pigsty 在线演示首页


更多

您可以以当前节点作为基础,部署和监控 更多集群:向 配置清单 添加数据库集群的定义并运行:

bin/node-add   pg-test      # 将集群 pg-test 的 3 个节点纳入 Pigsty 管理
bin/pgsql-add  pg-test      # 初始化一个 3 节点的 pg-test 高可用 PG 集群
bin/redis-add  redis-ms     # 初始化 Redis 集群: redis-ms

大多数模块都需要先安装 NODE 模块。查看可用的 模块 了解详情:

PGSQLINFRANODEETCDMINIOREDISDOCKER……

1.2 - Docker 部署

在 Docker 容器中快速拉起 Pigsty 单机环境,适合 macOS/Windows 用户体验学习

Pigsty 旨在运行于原生 Linux 系统上,但也可以在带有 systemd 的 Linux 容器环境中运行。 如果您没有原生 Linux 环境(例如 macOSWindows 用户),可以使用 Docker 快速拉起一个本地单机 Pigsty 环境进行测试与体验。


快速开始

进入 Pigsty 源码包的 docker/ 目录,使用以下一键命令启动 Pigsty:

cd ~/pigsty/docker
make launch          # 启动容器 + 生成配置 + 执行部署

部署完成后,您可以通过以下方式访问服务:

服务 地址 凭据
SSH ssh root@localhost -p 2222 密码:pigsty
Web 界面 http://localhost:8080 -
Grafana http://localhost:8080/ui admin / grafana_admin_password
PostgreSQL psql 'postgres://dbuser_dba:<pg_admin_password>@localhost:5432/postgres' pg_admin_password

make launch 内部会执行 ./configure -g 生成随机密码,可通过以下命令查看:

cd ~/pigsty/docker
make pass | grep -E 'grafana_admin_password|pg_admin_password'
Web 界面与 PostgreSQL 服务

Web 界面与 PostgreSQL 服务仅在完成 部署./deploy.yml)后才可用。


准备

使用 Docker 部署 Pigsty 需要满足以下条件:

项目 要求 项目 要求
Docker Docker 20.10+(Docker Desktop 或 CE) CPU 至少 1 核
内存 至少 2GB 磁盘 至少 20GB 可用空间

请确保默认宿主机端口(2222/8080/8443/5432)可用,否则请先修改 .env 文件。

Docker 部署适用场景
  • 在 macOS / Windows 等非 Linux 环境下快速体验 Pigsty
  • 学习和测试 Pigsty 的功能特性,进行开发调试
  • 快速构建一个本地开发用的 PostgreSQL 环境
Docker 部署不适用场景
  • 生产环境部署:容器环境性能和稳定性不如原生 Linux
  • 高可用集群:Docker 单机模式无法实现多节点高可用
  • 大规模部署:建议使用原生 Linux 虚拟机或物理机

镜像

Pigsty 提供开箱即用的 Docker 镜像,发布在 Docker Hub

镜像 拉取大小 解压大小 内容
pgsty/pigsty ~500MB 1.3GB Debian 13 + systemd + SSH + pig + Ansible
  • 同时支持 amd64(x86_64)和 arm64(Apple Silicon、AWS Graviton)架构
  • 镜像标签按 Pigsty 版本命名。当前 main 分支的 Docker 配置默认值与站点口径均为 v5.0.0-preview;拉取或部署前仍应独立确认远端已有同名镜像
  • 镜像内已预生成 docker 配置模板,可直接执行 ./deploy.yml 部署

镜像基于 Debian 13 (Trixie) 构建,预装了 pig CLI 工具和 Ansible,并已初始化好 Pigsty 源码。


启动

Pigsty 提供了开箱即用的 Docker 支持,位于源码的 docker/ 目录中。

最简单的方式是使用 make launch 一键启动,它会自动完成启动容器、生成配置、执行部署三个步骤:

cd ~/pigsty/docker
make launch          # 一键启动:up + config + deploy

或者分步执行,可以在每一步进行检查和调整:

cd ~/pigsty/docker
make up              # 启动容器
make exec            # 进入容器
./configure -c docker -g --ip 127.0.0.1  # 生成配置(可选,镜像已预配置)
./deploy.yml         # 执行部署

如果您想要使用本地构建的镜像而非从 Docker Hub 拉取,可以先执行构建:

cd ~/pigsty/docker
make build           # 本地构建镜像
make launch          # 启动容器 + 生成配置 + 执行部署

配置

您可以通过修改 .env 文件来自定义镜像版本和端口映射:

PIGSTY_VERSION=v4.5.0         # 当前 main 的源码默认值;拉取前核验远端标签
PIGSTY_SSH_PORT=2222          # SSH 端口
PIGSTY_HTTP_PORT=8080         # Nginx HTTP 端口
PIGSTY_HTTPS_PORT=8443        # Nginx HTTPS 端口
PIGSTY_PG_PORT=5432           # PostgreSQL 端口

端口映射说明

环境变量 默认值 容器端口 说明
PIGSTY_VERSION v4.5.0 - 当前 main 的源码默认值;远端标签需另行核验
PIGSTY_SSH_PORT 2222 22 SSH 访问端口
PIGSTY_HTTP_PORT 8080 80 Nginx HTTP 端口
PIGSTY_HTTPS_PORT 8443 443 Nginx HTTPS 端口
PIGSTY_PG_PORT 5432 5432 PostgreSQL 端口

如果默认端口已被占用,可以通过环境变量临时覆盖:

PIGSTY_HTTP_PORT=8888 docker compose up -d

命令

Pigsty Docker 提供了丰富的 Makefile 命令,方便您管理容器和镜像。

Docker Compose 命令

推荐使用 Docker Compose 方式运行,以下是常用命令:

make up           # 启动容器
make down         # 停止并删除容器
make start        # 启动已停止的容器
make stop         # 停止容器
make restart      # 重启容器
make pull         # 拉取最新镜像
make config       # 在容器内执行 ./configure
make deploy       # 在容器内执行 ./deploy.yml
make launch       # 一键启动:up + config + deploy

容器访问命令

make exec         # 进入容器 bash
make ssh          # 通过 SSH 进入容器
make log          # 查看容器日志
make status       # 查看 systemd 状态
make ps           # 查看进程列表
make conf         # 查看配置文件
make pass         # 查看配置中的密码

镜像构建命令

make build        # 本地构建镜像
make buildnc      # 不使用缓存构建镜像
make push         # 构建并推送多架构镜像

镜像管理命令

make save         # 导出镜像到 pigsty-<version>-<arch>.tgz
make load         # 从 tgz 文件导入镜像
make rmi          # 删除当前版本的 pigsty 镜像

容器清理命令

make clean        # 停止并删除容器
make purge        # 停止并删除容器,然后直接删除当前目录的 ./data
谨慎执行 make purge

当前 Makefile 不再提供倒计时确认;make purge 会在移除容器后直接执行 rm -rf -- ./data。请先确认当前目录与待删除数据,必要时先备份。


手动运行

如果您不想使用 Docker Compose,也可以直接使用 docker run 命令:

mkdir -p ./data
docker run -d --privileged --name pigsty \
  -p 2222:22 -p 8080:80 -p 5432:5432 \
  -v ./data:/data \
  pgsty/pigsty:<version>

docker exec -it pigsty ./configure -c docker -g --ip 127.0.0.1
docker exec -it pigsty ./deploy.yml

或者使用 Makefile 提供的 make run 命令:

make run          # 使用 docker run 启动
make exec         # 进入容器
make clean        # 停止并删除容器
make purge        # 删除容器并直接删除当前目录的 ./data

原理

Pigsty Docker 镜像基于 Debian 13 (Trixie),启用了 systemd 作为 init 系统。 这使得容器内的服务管理方式与原生 Linux 系统保持一致,可以使用 systemctl 管理服务。

镜像的关键特性:

  • systemd 支持:容器内运行完整的 systemd,可以正常使用服务管理
  • SSH 访问:预配置了 SSH 服务,root 密码为 pigsty
  • 特权模式:需要 --privileged 参数以支持 systemd
  • 数据持久化:通过 /data 卷挂载实现数据持久化
  • 预装软件:预装 pig CLI 和 Ansible,已完成 Pigsty 源码初始化

镜像构建时会执行以下初始化步骤:

# 安装 pig CLI
RUN echo "deb [trusted=yes] https://repo.pigsty.cc/apt/infra/ generic main" \
    > /etc/apt/sources.list.d/pigsty.list \
    && apt-get update && apt-get install -y pig

# 初始化 Pigsty 源码并安装 Ansible
RUN pig sty init -v ${PIGSTY_VERSION} \
    && pig sty boot \
    && pig sty conf -c docker --ip 127.0.0.1

在容器内执行 ./configure 时,使用 -c docker 参数会应用专门针对 Docker 环境优化的 配置模板

  • 使用 127.0.0.1 作为默认 IP 地址
  • 针对容器环境进行了优化调整

常见问题

容器无法启动

确保 Docker 已正确安装且有足够的资源分配。在 Docker Desktop 中,建议分配至少 2GB 内存。 检查是否有端口冲突,特别是 2222、8080、8443、5432 端口。

服务访问失败

Web 界面和 PostgreSQL 服务仅在部署完成后才可用。请确保 ./deploy.yml 已成功执行完成。 可以通过 make status 检查容器内服务状态。

端口冲突

如果默认端口已被占用,可以通过修改 .env 文件或使用环境变量指定其他端口:

PIGSTY_HTTP_PORT=8888 PIGSTY_PG_PORT=5433 docker compose up -d

数据持久化

容器数据默认挂载到 ./data 目录。如果需要清空数据重新开始:

make purge        # 删除容器并直接删除当前目录的 ./data(无倒计时确认)

macOS 上的性能

在 macOS 上使用 Docker Desktop 时,由于虚拟化层的开销,性能会比原生 Linux 环境差。 这是正常现象,Docker 部署主要用于开发测试,生产环境请使用 原生 Linux 安装


更多

1.3 - 从浏览器访问图形用户界面

探索 Pigsty 提供的 Web 图形管理界面,Grafana 大盘,以及如何通过域名和 HTTPS 访问它们。

Pigsty 单机安装 完成后,您在当前节点上将安装有 INFRA 模块,它带有一套开箱即用的 Nginx Web 服务器。

其中的默认服务器配置提供了一个 WebUI 图形界面,用于展示监控仪表盘,并统一代理访问其他组件的 Web 界面。


访问

您可以通过在浏览器中键入部署节点 IP 地址来访问这个图形界面。在默认配置下,Nginx 将通过 80/443 标准端口对外提供服务。

IP 直接访问 域名(HTTP) 域名(HTTPS) Demo
http://10.10.10.10 http://i.pigsty https://i.pigsty https://demo.pigsty.cc

Pigsty 在线演示首页


监控

要访问 Pigsty 的监控系统大盘(Grafana),您可以访问服务器的 /ui 端点。

IP 直接访问 域名(HTTP) 域名(HTTPS) Demo
http://10.10.10.10/ui http://i.pigsty/ui https://i.pigsty/ui https://demo.pigsty.cc/ui

如果您的服务对互联网与办公网开放,我们建议您通过 域名 访问,并启用 HTTPS 加密,只需要少量配置工作即可实现。


端点

在默认配置下,Nginx 会在 80/443 端口的默认服务器上,通过不同的路径暴露以下端点:

端点 组件 原生端口 备注 公开演示
/ Nginx 80/443 首页、本地仓库、文件服务 demo.pigsty.cc
/ui/ Grafana 3000 Grafana 仪表盘入口 demo.pigsty.cc/ui/
/vmetrics/ VictoriaMetrics 8428 时序数据库 Web UI demo.pigsty.cc/vmetrics/
/vlogs/ VictoriaLogs 9428 日志数据库 Web UI demo.pigsty.cc/vlogs/
/vtraces/ VictoriaTraces 10428 链路追踪 Web UI demo.pigsty.cc/vtraces/
/vmalert/ VMAlert 8880 告警规则管理 demo.pigsty.cc/vmalert/
/alertmgr/ AlertManager 9059 告警管理 Web UI demo.pigsty.cc/alertmgr/
/blackbox/ Blackbox 9115 黑盒探测器
/haproxy/* HAProxy 9101 负载均衡管理 Web UI
/pev PEV2 80 PostgreSQL 执行计划可视化 demo.pigsty.cc/pev
/nginx Nginx 80 Nginx 状态页(指标采集用)

域名访问

如果您有自己的域名,可以将其解析到 Pigsty 服务器的 IP 地址,从而通过域名访问 Pigsty 提供的各项服务。

如果您希望启用 HTTPS,则应当修改 infra_portal 参数中 home 服务器的配置:

all:
  vars:
    infra_portal:
      home : { domain: i.pigsty } # 将 i.pigsty 替换为你的域名
all:
  vars:
    infra_portal:  # domain 指定域名  # certbot 参数指定证书名称
      home : { domain: demo.pigsty.cc ,certbot: mycert }

您可以在部署完成后,执行 make cert 命令为该域名申请免费的 Let’s Encrypt 证书。 如果您没有定义 certbot 字段,Pigsty 会默认使用本地 CA 签发自签名的 HTTPS 证书, 在这种情况下,您必须首先信任 Pigsty 的自签名 CA 才可以在浏览器中正常访问。

您还可以将本地目录与其他上游服务挂载到 Nginx 上,更多管理预案,请参考 INFRA 管理 - Nginx

1.4 - 快速上手 PostgreSQL

快速上手 PostgreSQL,使用命令行与图形客户端连接上 PostgreSQL 并开始使用。

PostgreSQL(简称 PG)是世界上最先进、最流行的开源关系型数据库,你可以用它来存储和检索多模态数据。

本指南面向有基础 Linux 基本命令行操作经验、但对 PostgreSQL 不太熟悉的开发者,带你快速上手 Pigsty 中的 PG。

我们假设您是个人用户,使用默认单机模式进行部署。关于生产环境多节点高可用集群的使用,请参考 生产服务接入


基本知识

默认 单机安装 模板下,您将在当前节点上创建一个名为 pg-meta 的 PostgreSQL 数据库集群,只有一个主库实例。

PostgreSQL 监听在 5432 端口,集群中带有一个预置的数据库 meta 可供使用。

您可以在安装完毕后退出当前管理用户 ssh 会话,并重新登陆刷新环境变量后, 通过简单地敲一个 pp 回车,通过命令行工具 psql 访问该数据库集群:

vagrant@pg-meta-1:~$ pp
psql (18.6 (Ubuntu 18.6-1.pgdg24.04+1))
Type "help" for help.

postgres=#

您也可以切换为操作系统的 postgres 用户,直接执行 psql 命令,即可连接到默认的 postgres 管理数据库上。


连接数据库

想要访问 PostgreSQL 数据库,您需要使用 命令行工具 或者 图形化客户端 工具,填入 PostgreSQL 的 连接字符串

postgres://username:password@host:port/dbname

一些驱动和工具也可能会要求你分别填写这些参数,通常以下五项为必选项:

参数 说明 示例值 备注
host 数据库服务器地址 10.10.10.10 换为你的节点 IP 地址或域名,本机可以省略
port 端口号 5432 PG 默认端口,可以省略
username 用户名 dbuser_dba Pigsty 默认的数据库管理员
password 密码 DBUser.DBA Pigsty 默认的管理员密码,(请修改密码
dbname 数据库名 meta 默认模板的数据库名称

个人使用时可以直接使用 Pigsty 默认的数据库超级用户 dbuser_dba 进行连接和管理,数据库管理用户 dbuser_dba 拥有数据库的全部权限。 默认情况下,如果您在配置 Pigsty 时指定了 configure -g 参数,密码会随机生成,并保存在 ~/pigsty/pigsty.yml 文件中,可以通过以下命令查看:

cat ~/pigsty/pigsty.yml | grep pg_admin_password

默认账号密码

Pigsty 的默认 单机模板 默认配置预置了以下数据库用户,可以开箱即用:

用户名 密码 角色 用途
dbuser_dba DBUser.DBA 超级用户 数据库管理(请修改密码
dbuser_meta DBUser.Meta 业务管理员 应用读写(请修改密码
dbuser_view DBUser.Viewer 只读用户 数据查阅(请修改密码

例如,你可以通过三个不同的连接串,使用三个不同的用户连接到 pg-meta 集群的 meta 数据库:

postgres://dbuser_dba:[email protected]:5432/meta
postgres://dbuser_meta:[email protected]:5432/meta
postgres://dbuser_view:[email protected]:5432/meta

请注意,这些默认密码会在 configure -g 时自动被替换为随机强密码,请注意将 IP 地址和密码替换为实际值。


使用命令行工具

psql 是 PostgreSQL 官方命令行客户端工具,功能强大,是 DBA 和开发者的首选工具。

在部署了 Pigsty 的服务器上,你可以直接使用 psql 连接本地数据库:

# 最简单的方式:使用 postgres 系统用户本地连接(无需密码)
sudo -u postgres psql

# 使用连接字符串(推荐,通用性最好)
psql 'postgres://dbuser_dba:[email protected]:5432/meta'

# 使用参数形式
psql -h 10.10.10.10 -p 5432 -U dbuser_dba -d meta

# 使用环境变量避免密码出现在命令行
export PGPASSWORD='DBUser.DBA'
psql -h 10.10.10.10 -p 5432 -U dbuser_dba -d meta

成功连接后,你会看到类似这样的提示符:

psql (18.6)
Type "help" for help.

meta=#

常用 psql 命令

进入 psql 后,可以执行 SQL 语句,也可以使用以 \ 开头的元命令:

命令 说明 命令 说明
Ctrl+C 中断查询 Ctrl+D 退出 psql
\? 显示所有元命令帮助 \h 显示 SQL 命令帮助
\l 列出所有数据库 \c dbname 切换到指定数据库
\d table 查看表结构 \d+ table 查看表的详细信息
\du 列出所有用户/角色 \dx 列出已安装的扩展
\dn 列出所有的模式 \dt 列出所有表

执行 SQL

psql 中直接输入 SQL 语句,以分号 ; 结尾:

-- 查看 PostgreSQL 版本
SELECT version();

-- 查看当前时间
SELECT now();

-- 创建一张测试表
CREATE TABLE test (id SERIAL PRIMARY KEY, name TEXT, created_at TIMESTAMPTZ DEFAULT now());

-- 插入数据
INSERT INTO test (name) VALUES ('hello'), ('world');

-- 查询数据
SELECT * FROM test;

-- 删除测试表
DROP TABLE test;

使用图形客户端

如果你更喜欢图形界面,以下是几款流行的 PostgreSQL 客户端:

Grafana

Pigsty INFRA 模块中自带了 Grafana,并预先配置好了 PostgreSQL 数据源(Meta)。 您可以直接通过 浏览器图形界面,从 Grafana Explore 面板中使用 SQL 查询数据库,无需额外安装客户端工具。

Grafana 默认的用户名是 admin,密码可以在 配置清单 中的 grafana_admin_password 字段找到(默认 pigsty)。

DataGrip

DataGrip 是 JetBrains 出品的专业数据库 IDE,功能强大。 Intellij IDEA 自带的 Database Console 也可以使用类似的方式连接 PostgreSQL。

DBeaver

DBeaver 是免费开源的通用数据库工具,支持几乎所有主流数据库。这是一个多平台可用的桌面客户端。

pgAdmin

pgAdmin 是 PGDG 官方提供的 PostgreSQL 专用 GUI 工具,可以通过浏览器使用,也有桌面客户端版本。

Pigsty 在 软件模板:pgAdmin 中提供了使用 Docker 一键部署 pgAdmin 服务的配置模板。


查阅监控大盘

Pigsty 提供了许多 PostgreSQL 监控面板,覆盖从集群总览到单表分析的各个层面:

推荐先从 PGSQL Overview 开始浏览,面板中的许多元素都可以点击,您可以逐层深入,查阅每个集群、实例、数据库甚至是表,索引,函数等数据库内对象的详情信息。


尝试扩展插件

PostgreSQL 最强大的特性之一是其 扩展生态系统。扩展可以为数据库添加新的数据类型、函数、索引方法等能力。

Pigsty 提供 575 个扩展,涵盖时序、地理、向量、全文检索等 16 大类别,一键安装即可使用。 你可以先从三个常用功能扩展开始,然后按需 加装 timescaledb 等更多扩展。

  • postgis:地理信息系统,处理地图、位置数据(默认安装)
  • pgvector:向量数据库,支持 AI 嵌入向量相似度搜索(默认安装)
  • timescaledb:时序数据库,高效存储和查询时间序列数据(可选安装)
\dx                            -- psql 元命令,列出已经安装的扩展
TABLE pg_available_extensions; -- 查询已经安装,可以启用的扩展
CREATE EXTENSION postgis;      --  启用 postgis 扩展

下一步

恭喜你完成了 PostgreSQL 的基础上手!下一步,你可以开始对你的数据库进行一些 配置与定制

1.5 - 通过配置清单定制 Pigsty 部署

使用声明式的配置文件,表达你需要的基础设施与集群。

除了使用 配置向导 自动生成配置,您也可以从零开始手工编写 Pigsty 配置文件。 本教程将指导您从头开始,逐步构建一个复杂的 配置清单

如果您事先在 配置清单 中定义好 NODE、INFRA、ETCD、MINIO 与 PGSQL,那么 deploy.yml 可以一次性完成这条核心链路的部署,但它隐藏了所有细节。Docker、Redis、Kafka、原生 MySQL、JUICE 与 VIBE 等可选模块需要另行执行各自的剧本。

所以本文档会把所有模块与剧本拆解开来,介绍如何从一个简单的配置,通过增量添加的方式,形成一套复杂完备的部署。


最小配置

最简单的有效配置文件可能如下所示,唯一的内容是定义 admin_ip 变量,这是当前安装 Pigsty 节点的 IP 地址(管理节点

最简配置
all: { vars: { admin_ip: 10.10.10.10 } }
中国特色
# 天朝自有国情在此,额外配置 region: china 以使用国内的镜像源加速下载
all: { vars: { admin_ip: 10.10.10.10, region: china } }

这个配置不会部署任何东西,但是执行 ./deploy.yml 剧本时,会在 files/pki/ca 生成一套自签名的 CA,用于签发证书。

为了方便起见,我们还可以额外设置 region 参数,指定使用哪个区域的软件镜像源(defaultchinaeurope)。


加入节点

Pigsty 的 NODE 模块负责管理集群中的节点。配置清单里存在的 IP 地址,都会被 Pigsty 纳入管理,安装 NODE 模块。

最简配置
all:  # 不要忘了将 10.10.10.10 替换为您的实际 IP 地址
  children: { nodes: { hosts: { 10.10.10.10: {} } } } 
  vars: 
    admin_ip: 10.10.10.10                   # 当前节点 IP 地址
    region: default                         # 全球默认软件仓库
    node_repo_modules: node,pgsql,infra     # 添加 node, pgsql, infra 软件仓库
中国特色
all:  # 不要忘了将 10.10.10.10 替换为您的实际 IP 地址                        
  children: { nodes: { hosts: { 10.10.10.10: {} } } } 
  vars:
    admin_ip: 10.10.10.10                 # 当前节点 IP 地址
    region: china                         # 使用中国镜像
    node_repo_modules: node,pgsql,infra   # 添加 node, pgsql, infra 软件仓库

为了让这个配置更有用,我们添加了两个 全局参数: 指定该节点要添加的软件源 node_repo_modules; 以及使用哪个区域的镜像的 region

上面的两个参数能够让节点使用正确的软件仓库,安装默认指定的必须包。 在 NODE 模块中有许多可用的 定制项:您可以定制节点的名称,DNS,软件仓库,要安装的软件包,DNS,NTP,内核参数,调优模板,监控,日志采集等各种细节。 但即使您什么都不改,默认配置也足够了。

接下来,执行 deploy.yml 剧本,或者更精确地执行 node.yml 剧本,将会把这里定义节点 “纳入 Pigsty 管理”,调整至默认配置描述的状态。

ID NODE INFRA ETCD PGSQL 说明
1 10.10.10.10 - - - 添加节点

加入基础设施

一套功能完备的 RDS 云数据库服务需要基础设施的支持,例如,监控系统(指标/日志采集,告警,可视化),NTP,DNS 等各种基础性服务。

现在,我们通过定义一个特殊的分组 infra,来部署 INFRA 模块。为 Pigsty 添加基础设施支持。

最简配置
all:  # 只是简单的改了个分组名 nodes -> infra,并添加新的实例变量 infra_seq
  children: { infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } } } 
  vars: 
    admin_ip: 10.10.10.10
    region: default
    node_repo_modules: node,pgsql,infra
中国特色
all:  # 只是简单的改了个分组名 nodes -> infra,并添加新的实例变量 infra_seq
  children: { infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } } } 
  vars:
    admin_ip: 10.10.10.10
    region: china
    node_repo_modules: node,pgsql,infra

同时,我们还分配了一个 身份参数infra_seq,这是为了在多节点部署高可用 INFRA 模块时将不同的节点区分开来。

执行 infra.yml 剧本,将在 10.10.10.10 上安装 INFRANODE 模块。

./infra.yml   # 在 infra 分组上安装 INFRA 模块(连带安装 NODE 模块)
demo/infra.cast

只要 IP 地址存在,NODE 模块会隐含定义。NODE 模块也是幂等的,即使重复执行一次,也没有什么副作用。

安装完成后,您将拥有一套完整的可观测性基础设施,以及节点监控功能,但 PostgreSQL 数据库服务尚未部署。

如果您的目的就是设置这一套监控系统(Grafana + Victoria),那么到此为止就大功告成了!infra 模板就是为此设计的。 Pigsty 中的一切都是 模块化 的:您可以只部署监控基础设施,而不部署数据库服务; 或者反过来 —— 在没有基础设施的情况下,运行高可用 PostgreSQL 集群 —— 精简安装

ID NODE INFRA ETCD PGSQL 说明
1 10.10.10.10 infra-1 - - 添加基础设施模块

部署数据库集群

要提供 PostgreSQL 服务,您还需要额外安装 PGSQL 模块和它所依赖的 ETCD 模块,这并不复杂,两行配置而已:

最简配置
all:
  children:
    infra:   { hosts: { 10.10.10.10: { infra_seq: 1 } } }
    etcd:    { hosts: { 10.10.10.10: { etcd_seq:  1 } } } # 新增 etcd 集群
    pg-meta: { hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }, vars: { pg_cluster: pg-meta } } # 新增 pg 集群
  vars: { admin_ip: 10.10.10.10, region: default, node_repo_modules: node,pgsql,infra }
中国特色
all:
  children:
    infra:   { hosts: { 10.10.10.10: { infra_seq: 1 } } }
    etcd:    { hosts: { 10.10.10.10: { etcd_seq:  1 } } } # 新增 etcd 集群
    pg-meta: { hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }, vars: { pg_cluster: pg-meta } } # 新增 pg 集群
  vars: { admin_ip: 10.10.10.10, region: china, node_repo_modules: node,pgsql,infra }

我们在这里添加了两个新的分组:etcdpg-meta,分别定义了一个单节点的 etcd 集群和一个单节点的 PostgreSQL 集群。

您可以使用 ./deploy.yml 重新收敛核心链路中已定义的模块,也可以使用以下命令进行增量部署:

./etcd.yml  -l etcd      # 在 etcd 组上安装 ETCD 模块
./pgsql.yml -l pg-meta   # 在 pg-meta 组上安装 PGSQL 模块

PGSQL 模块依赖 ETCD 进行高可用共识,因此请确保先安装 ETCD 模块。 执行完毕后,您就拥有一个可用的 PostgreSQL 服务了!

ID NODE INFRA ETCD PGSQL 说明
1 10.10.10.10 infra-1 etcd-1 pg-meta-1 添加 etcd 与 PostgreSQL 集群

至此,我们用 node.yml, infra.yml, etcd.ymlpgsql.yml 四个 剧本, 在单机上部署了完整的四个核心功能模块。


定义数据库与用户

您不仅可以定制在哪些节点上安装哪些模块,还可以定制 PostgreSQL 集群的内部细节,例如 数据库用户

all:
  children:
    # 隐藏其他分组与变量以简化展示
    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-meta
        pg_users:       # 定义数据库用户
          - { name: dbuser_meta ,password: DBUser.Meta ,pgbouncer: true ,roles: [dbrole_admin] ,comment: admin user  }
        pg_databases:   # 定义业务数据库
          - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database }
  • pg_users:这里定义一个名为 dbuser_meta 的新用户,密码为 DBUser.Meta
  • pg_databases:定义一个名为 meta 的新数据库,包含 Pigsty CMDB 模式(完全可选)。

Pigsty 提供了非常丰富的定制参数,覆盖了数据库与用户的方方面面。 如果您事先定义好了上面两个参数描述所需的数据库与用户,那么它们会在 ./pgsql.yml 剧本执行时被自动创建。 如果集群已经创建,您也可以进行增量变更,在现有集群上创建或修改 用户数据库

bin/pgsql-user pg-meta dbuser_meta      # 确保 pg-meta 集群中有用户 dbuser_meta
bin/pgsql-db   pg-meta meta             # 确保 pg-meta 集群中有数据库 meta

配置 PG 版本与扩展

您可以安装 不同大版本 的 PostgreSQL,以及多达 575扩展插件。让我们卸载当前默认的 PG 18,并安装 PG 16:

./pgsql-rm.yml -l pg-meta   # 移除旧的 pg-meta 集群(因为它是 PG 18)

我们可以通过定制参数,让集群默认安装并启用一些常用的扩展:timescaledbpostgispgvector

all:
  children:
    infra:   { hosts: { 10.10.10.10: { infra_seq: 1 } } }
    etcd:    { hosts: { 10.10.10.10: { etcd_seq:  1 } } } # 新增 etcd 集群
    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-meta
        pg_version: 16   # 指定 PG 版本为 16
        pg_extensions: [ timescaledb, postgis, pgvector ]      # 安装这些扩展
        pg_libs: 'timescaledb, pg_stat_statements, auto_explain'  # 预加载这些扩展动态库
        pg_databases:
          - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [vector, postgis, timescaledb ] }
        pg_users:
          - { name: dbuser_meta ,password: DBUser.Meta ,pgbouncer: true ,roles: [dbrole_admin] ,comment: admin user }
        
  vars:
    admin_ip: 10.10.10.10
    region: default
    node_repo_modules: node,pgsql,infra
./pgsql.yml -l pg-meta   # 安装 PG16 和扩展重新创建 pg-meta 集群

添加更多节点

我们可以向部署中添加更多节点,将其纳入 Pigsty 的管理之中,部署监控,配置仓库,安装软件 ……

一次添加整个集群,或者逐个添加节点
bin/node-add pg-test

bin/node-add 10.10.10.11
bin/node-add 10.10.10.12
bin/node-add 10.10.10.13
demo/node.cast

部署高可用PG集群

现在假设我们要在刚添加的三个新节点上,部署一套新的数据库集群 pg-test,采用三节点高可用架构,只需要:

all:
  children:
    infra:   { hosts: { 10.10.10.10: { infra_seq: 1 } } }
    etcd:    { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }
    pg-meta: { hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }, vars: { pg_cluster: pg-meta } }
    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 }
demo/pgsql.cast

部署 Redis 集群

Pigsty 提供了可选的 Redis 支持,可作为 PostgreSQL 前端的缓存服务。

bin/redis-add redis-ms
bin/redis-add redis-meta
bin/redis-add redis-test

Redis 高可用设置需要使用集群模式或哨兵模式,详情请参阅 Redis 配置


部署 Silo 对象存储集群

Pigsty 的 MINIO 模块 当前部署 Silo S3 兼容对象存储,可作为 PostgreSQL 的 备份存储仓库。模块、清单分组与剧本继续沿用 minio 兼容名称。

./minio.yml -l minio

严肃的生产环境 Silo 部署通常需要至少 4 个节点,每个节点配备 4 块硬盘(4N/16D)。


部署 Docker 模块

如果您想要使用容器运行一些 管理 PG 的工具 或者 使用 PostgreSQL 的软件,可以安装 DOCKER 模块。

./docker.yml -l infra

你可以使用预制的应用配置模板,一键拉起一些常见的软件工具,例如用于 PG 管理的 GUI 工具: Pgadmin

./app.yml    -l infra -e app=pgadmin

甚至,您还可以用 Pigsty 自建 企业级质量的 Supabase,使用外面的高可用 PostgreSQL 集群作为底座,将无状态的部分运行在容器之中。

1.6 - 使用 Ansible 剧本完成部署

使用 Ansible 剧本部署与管理 Pigsty 集群

Pigsty 使用 Ansible 对集群进行管理,这是在 SRE 群体中非常流行的大规模/批量化/自动化运维工具。

Ansible 可以使用 声明式 的方式对服务器进行配置管理,所有模块的部署都是通过一系列幂等的 Ansible 剧本 实现的。

例如,在单机部署时,您会用到 deploy.yml 剧本。Pigsty 还有更多 内置剧本,您可以根据需要选择使用。

了解 Ansible 基础知识有助于更好的使用 Pigsty,但这 并非必须,特别是在单机部署时。


部署剧本

Pigsty 提供了一个 “一条龙” 部署剧本 deploy.yml,用于一次性部署核心链路:CA/软件仓库、NODE、INFRA、ETCD、PGSQL,以及配置中启用的 MINIO。Redis、Kafka、原生 MySQL 等可选模块即使已在清单中定义,也需要分别执行其模块剧本。

Playbook 命令 分组 infra [nodes] etcd minio [pgsql]
infra.yml ./infra.yml -l infra
node.yml ./node.yml
etcd.yml ./etcd.yml -l etcd
minio.yml ./minio.yml -l minio
pgsql.yml ./pgsql.yml

这是最简单的部署方式,您也可以参考 定制指南 里的说明,一步来增量式地完成所有模块与节点的部署。


安装 Ansible

使用 Pigsty 安装脚本,或离线安装的 bootstrap 阶段,Pigsty 会自动为您安装 ansible 及其依赖。

如果您想手动安装 Ansible,可以参考以下说明,支持的 Ansible 最低版本为 2.9

Debian / Ubuntu
sudo apt install -y ansible python3-jmespath
EL
sudo dnf install -y ansible python3.12-jmespath python3-cryptography  # EL 8
sudo dnf install -y ansible python3-jmespath                           # EL 9
sudo dnf install -y ansible                                            # EL 10
MacOS
brew install ansible
pip3 install jmespath
修改默认密码!

请注意,目前 EL10 EPEL 仓库尚未提供完整的 Ansible 包,Pigsty PGSQL EL10 仓库中补充了这个包。

Ansible 在 macOS 上也可用。您可以使用 Homebrew 在 Mac 上安装 Ansible, 并将其用作管理节点来管理远程云服务器。如果您在云 VPS 上部署单节点 Pigsty 这很方便,但不建议在生产环境中使用。


执行剧本

Ansible 剧本(Playbook)是包含要执行的一系列任务定义的可执行 YAML 文件。 执行剧本需要您的环境变量 PATH 中有 ansible-playbook 可执行文件。 运行 ./node.yml 剧本本质上是执行 ansible-playbook node.yml 命令。

您可以使用一些参数来精细控制剧本的执行,其中以下 4 个参数 需要您了解,以便有效使用 Ansible:

目的 参数 描述
对象 -l|--limit <pattern> 限制在特定 分组 / 主机 / 模式 上执行
任务 -t|--tags <tags> 只运行具有特定标签的任务
参数 -e|--extra-vars <vars> 额外的命令行参数
配置 -i|--inventory <path> 使用特定的清单文件
./node.yml                         # 在所有主机上运行 node 剧本
./pgsql.yml -l pg-test             # 在 pg-test 集群上运行 pgsql 剧本
./infra.yml -t repo_build          # 运行 infra.yml 的子任务 repo_build
./pgsql-rm.yml -e pg_rm_pkg=false  # 删除 pgsql,但保留软件包(不卸载软件)
./infra.yml -i conf/mynginx.yml    # 使用另外一个位置的配置文件

限制主机

剧本的 执行目标 可以通过 -l|--limit <selector> 限制。 当尝试在特定主机/节点或组/集群上运行剧本时,这很方便。 以下是主机限制的一些示例:

./pgsql.yml                              # 在所有主机上运行(危险!)
./pgsql.yml -l pg-test                   # 在 pg-test 集群上运行
./pgsql.yml -l 10.10.10.10               # 在单个主机 10.10.10.10 上运行
./pgsql.yml -l pg-*                      # 在匹配 glob 模式 `pg-*` 的主机/组上运行
./pgsql.yml -l '10.10.10.11,&pg-test'    # 在 pg-test 组的 10.10.10.11 上运行
./pgsql-rm.yml -l 'pg-test,!10.10.10.11' # 在 pg-test 上运行,除了 10.10.10.11

查看 Ansible 文档中的所有详细信息:Patterns: targeting hosts and groups

谨慎运行没有主机限制的剧本!

在大多数时候,缺少这个值可能会有危险,因为大多数剧本将在 all 主机上执行。请谨慎使用


限制任务

执行任务 可以通过 -t|--tags <tags> 控制。 如果指定,将只执行具有给定标签的任务,而不是整个剧本。

./infra.yml -t repo          # 创建仓库
./node.yml  -t node_pkg      # 安装节点包
./pgsql.yml -t pg_install    # 安装 PG 包和扩展
./etcd.yml  -t etcd_config   # 重新渲染 ETCD 配置
./minio.yml -t minio_alias   # 写入 mcli 客户端别名

要运行多个任务,指定多个标签并用逗号分隔 -t tag1,tag2

./node.yml  -t node_repo,node_pkg   # 添加仓库,然后安装包
./pgsql.yml -t pg_hba,pg_reload     # 配置,然后重新加载 pg hba 规则

额外变量

您可以使用 CLI 参数在运行时覆盖配置参数,它具有 最高优先级

额外的命令行参数可以通过 -e|--extra-vars KEY=VALUE 传递,可以多次使用:

# 使用另一个管理员用户创建管理员
./node.yml -e ansible_user=admin -k -K -t node_admin

# 初始化一个特定的 Redis 实例:10.10.10.11:6379
./redis.yml -l 10.10.10.10 -e redis_port=6379 -t redis

# 删除 PostgreSQL,但保留软件包和数据
./pgsql-rm.yml -e pg_rm_pkg=false -e pg_rm_data=false

对于复杂参数,可以使用 JSON 字符串,一次传递多个复杂参数。

# 添加仓库并安装包
./node.yml -t node_install -e '{"node_repo_modules":"infra","node_packages":["duckdb"]}'

指定清单

默认配置文件是 Pigsty 主目录中的 pigsty.yml。 您可以使用 -i <path> 参数指定不同的 配置清单 文件路径。

./pgsql.yml -i conf/rich.yml            # 根据 rich 配置初始化一个下载了所有扩展的单节点
./pgsql.yml -i conf/ha/full.yml         # 根据 full 配置初始化一个 4 节点集群
./pgsql.yml -i conf/app/supa.yml        # 根据 supa.yml 配置初始化一个 1 节点 Supabase 部署
更改默认清单文件

要永久更改 默认 配置文件,请修改 ansible.cfg 中的 inventory 参数。


便捷脚本

Pigsty 提供了一系列便捷脚本来简化常见操作,这些脚本位于 bin/ 目录下:

bin/node-add   <cls>            # 将节点纳入 Pigsty 管理:./node.yml -l <cls>
bin/node-rm    <cls>            # 从 Pigsty 移除节点:./node-rm.yml -l <cls>
bin/pgsql-add  <cls>            # 初始化 PG 集群:./pgsql.yml -l <cls>
bin/pgsql-rm   <cls>            # 移除 PG 集群:./pgsql-rm.yml -l <cls>
bin/pgsql-user <cls> <username> # 添加业务用户:./pgsql-user.yml -l <cls> -e username=<user>
bin/pgsql-db   <cls> <dbname>   # 添加业务数据库:./pgsql-db.yml -l <cls> -e dbname=<db>
bin/redis-add  <cls>            # 初始化 Redis 集群:./redis.yml -l <cls>
bin/redis-rm   <cls>            # 移除 Redis 集群:./redis-rm.yml -l <cls>

这些脚本是对 Ansible 剧本的简单封装,让您可以更方便地执行常见操作。


剧本列表

以下是 Pigsty 中的 内置剧本,您也轻松添加自己的剧本,或者按需定制修改剧本的实现逻辑。

模块 Playbook 功能
INFRA deploy.yml 在当前节点上一键部署 Pigsty
INFRA infra.yml 在基础设施节点上初始化 Pigsty 基础设施
INFRA infra-rm.yml 从基础设施节点移除基础设施组件
INFRA cache.yml 从目标节点制作离线安装包
INFRA cert.yml 使用 Pigsty 自签名 CA 颁发证书
NODE node.yml 初始化节点,将节点调整到所需状态
NODE node-rm.yml 从 Pigsty 移除节点
PGSQL pgsql.yml 初始化 HA PostgreSQL 集群,或添加新副本
PGSQL pgsql-rm.yml 移除 PostgreSQL 集群,或移除副本
PGSQL pgsql-db.yml 向现有 PostgreSQL 集群添加新业务数据库
PGSQL pgsql-user.yml 向现有 PostgreSQL 集群添加新业务用户
PGSQL pgsql-pitr.yml 在现有 PostgreSQL 集群上执行时间点恢复
PGSQL pgsql-monitor.yml 使用本地导出器监控远程 PostgreSQL 实例
PGSQL pgsql-migration.yml 为现有 PostgreSQL 生成迁移手册和脚本
PGSQL slim.yml 安装最小组件的 Pigsty
REDIS redis.yml 初始化 Redis 集群/节点/实例
REDIS redis-rm.yml 移除 Redis 集群/节点/实例
ETCD etcd.yml 初始化 ETCD 集群,或扩容新成员
ETCD etcd-rm.yml 移除 ETCD 集群与数据,或移除现有成员缩容
MINIO minio.yml 初始化 Silo 对象存储集群
MINIO minio-rm.yml 移除 Silo、配置与可选数据
DOCKER docker.yml 在节点上安装 Docker
DOCKER app.yml 使用 Docker Compose 安装应用程序
JUICE juice.yml 安装与配置 JuiceFS
VIBE vibe.yml 安装 Vibe 编码环境
KAFKA kafka.yml 创建或收敛 Kafka dynamic KRaft 集群
KAFKA kafka-rm.yml 移除 Kafka 集群或成员
MYSQL(试点) mysql.yml 部署原生 MySQL 8.4 单节点或三节点集群
MYSQL(试点) mysql-rm.yml 停止并退役原生 MySQL,保留本地状态

1.7 - 离线安装

在没有互联网访问的环境中,使用离线安装包安装 Pigsty

Pigsty 默认从互联网上游 安装 所需软件包,但有些环境与互联网隔离。 为了解决这个问题,Pigsty 支持使用 离线软件包 进行离线安装。 您可以将其视作 Linux- 原生版本的 Docker 镜像。


概览

离线软件包 打包了所有需要的 RPM/DEB 软件包及其依赖;它是常规 安装 后的本地 APT / YUM 仓库的快照。

严肃的生产环境部署 中,我们 强烈推荐 您使用离线安装包进行安装。 它可以确保后续所有新节点的软件版本与现有环境保持一致, 并且可以避免上游变动导致的在线安装失败(相当常见!) 确保您能独立自主运行它至地老天荒。

使用离线软件包的优点
  • 可以简单方便的在互联网隔离的环境中交付实施。
  • 一次性预下载所有软件包,可以有效加速安装过程。
  • 无需担心上游依赖项的变动导致依赖错漏/安装失败。
  • 如果有多个节点,那么所有软件包只需要下载一次,节省带宽资源。
  • 可以通过本地仓库确保所有节点的软件版本一致,实行统一版本管理
使用离线软件包的缺点
  • 离线安装包针对 特定的操作系统小版本制作,通常不能跨版本使用
  • 仅为制作时刻的快照,可能不包含最新的更新和操作系统安全补丁。
  • 离线安装包通常约 1GB 左右,而在线安装则是按需下载,更节省空间。

离线软件包

下表记录 v4.4.0 历史离线制品及其制作时使用的操作系统小版本;这些版本不代表 当前推荐操作系统

Linux 发行版 系统代码 小版本 软件包
RockyLinux 9 x86_64 el9.x86_64 9.7 pigsty-pkg-v4.4.0.el9.x86_64.tgz
RockyLinux 9 aarch64 el9.aarch64 9.7 pigsty-pkg-v4.4.0.el9.aarch64.tgz
RockyLinux 10 x86_64 el10.x86_64 10.1 pigsty-pkg-v4.4.0.el10.x86_64.tgz
RockyLinux 10 aarch64 el10.aarch64 10.1 pigsty-pkg-v4.4.0.el10.aarch64.tgz
Debian 12 x86_64 d12.x86_64 12.14 pigsty-pkg-v4.4.0.d12.x86_64.tgz
Debian 12 aarch64 d12.aarch64 12.14 pigsty-pkg-v4.4.0.d12.aarch64.tgz
Debian 13 x86_64 d13.x86_64 13.6 pigsty-pkg-v4.4.0.d13.x86_64.tgz
Debian 13 aarch64 d13.aarch64 13.6 pigsty-pkg-v4.4.0.d13.aarch64.tgz
Ubuntu 26.04 x86_64 u26.x86_64 26.04.0 pigsty-pkg-v4.4.0.u26.x86_64.tgz
Ubuntu 26.04 aarch64 u26.aarch64 26.04.0 pigsty-pkg-v4.4.0.u26.aarch64.tgz
Ubuntu 24.04 x86_64 u24.x86_64 24.04.4 pigsty-pkg-v4.4.0.u24.x86_64.tgz
Ubuntu 24.04 aarch64 u24.aarch64 24.04.4 pigsty-pkg-v4.4.0.u24.aarch64.tgz
Ubuntu 22.04 x86_64 u22.x86_64 22.04.5 pigsty-pkg-v4.4.0.u22.x86_64.tgz
Ubuntu 22.04 aarch64 u22.aarch64 22.04.5 pigsty-pkg-v4.4.0.u22.aarch64.tgz

如果您使用的是上述历史制品精确匹配的操作系统小版本,可以使用对应的 v4.4.0 离线软件包。 v4.4.0 社区版在 GitHub 公开提供 Debian 13、EL 10、Ubuntu 24.04 三个平台的双架构离线包,共 6 个制品。 Debian 12、EL 9、Ubuntu 22.04、Ubuntu 26.04 的制品名称与校验和保留在此,离线包通过商业版提供。

社区版制品可以从 GitHub 发布页面 下载。v4.4.0 全部离线包的 MD5 校验和如下:

7de8b932412f1863fd9c033a7be355d7  pigsty-pkg-v4.4.0.d12.aarch64.tgz
2e5006a8d35eb1c087dc0ed11cf14d14  pigsty-pkg-v4.4.0.d12.x86_64.tgz
955308c00d3890f6e82a6a83bc624760  pigsty-pkg-v4.4.0.d13.aarch64.tgz
350f31c66de0aafff3bd91c2c9d740a0  pigsty-pkg-v4.4.0.d13.x86_64.tgz
0b4817a8edbab0bdf37ecee730fb0412  pigsty-pkg-v4.4.0.el10.aarch64.tgz
4584a61e4456749e68d86e4817cfe526  pigsty-pkg-v4.4.0.el10.x86_64.tgz
21621daf510a532829c36464d48f9198  pigsty-pkg-v4.4.0.el9.aarch64.tgz
504afd5030e2738a25e1b4c570d0e654  pigsty-pkg-v4.4.0.el9.x86_64.tgz
461c999424dee587ca33fe1a63df40d7  pigsty-pkg-v4.4.0.u22.aarch64.tgz
20ccc5ab8f9f4648b05bcd304f9fb5fc  pigsty-pkg-v4.4.0.u22.x86_64.tgz
d092c48ee55116ed5e2c99a3d909ccdd  pigsty-pkg-v4.4.0.u24.aarch64.tgz
24fa5399d8421305961fcaf91325b382  pigsty-pkg-v4.4.0.u24.x86_64.tgz
36f69b699d8b3041d35384970e157631  pigsty-pkg-v4.4.0.u26.aarch64.tgz
330047d117b20f04317dce506edd5d9a  pigsty-pkg-v4.4.0.u26.x86_64.tgz
离线软件包是为特定的 Linux 操作系统小版本制作的

当操作系统小版本不匹配时,有概率能用,也有概率失败,我们建议你不要冒险尝试。

请务必注意,上表 v4.4.0 历史制品中的 EL9/EL10 安装包基于 9.7 / 10.1 制作,Debian 安装包基于 12.14 / 13.6 制作,Ubuntu 安装包基于 22.04.5 / 24.04.4 / 26.04.0 制作。 跨操作系统小版本可能因 OpenSSL 或系统库版本变化导致安装失败。您需要在安装相同操作系统的环境中执行在线安装后制作离线安装包,或联系我们定制离线软件包。


使用离线软件包

离线安装的步骤

  1. 下载 Pigsty 离线软件包,将其放到 /tmp/pkg.tgz
  2. 下载 Pigsty 源码包,解压并进入目录(假设解压到家目录:cd ~/pigsty
  3. ./bootstrap,它将解压软件包并配置使用本地仓库(并从中离线安装 ansible
  4. ./configure -g -c rich,您可以直接使用配置好离线安装的模板 rich,或者自行配置
  5. 照常运行 ./deploy.yml,从本地仓库安装核心链路所需软件;其他可选模块仍需执行各自的剧本
demo/install-offline.cast
警告

如果你在离线安装时遇到 “No package nginx available” 之类的错误,通常说明之前有过失败的安装尝试。删除 /www/pigsty 目录后重新执行部署即可。

如果您想要在自己的配置中,使用已经解包配置好的离线软件包,请修改并确保以下配置项:

  • repo_enabled:将此参数打开,设置为 true,则会构建本地软件源(在大部份配置中被显式关闭)
  • node_repo_modules:将此参数设置为 local,则环境中所有节点都从本地软件仓库安装
    • 在大部份模板中,此参数被显式配置为:node,infra,pgsql,即直接从这些上游软件仓库安装。
    • 将其设置为 local,则会使用本地软件仓库安装所有软件包,速度最快,没有其他仓库的变数干扰。
    • 如果你想同时使用本地软件仓库和上游软件仓库,可以将其设置为 local,node,infra,pgsql

第一个参数如果打开,Pigsty 会创建 本地软件仓库,第二个参数如果包含 local,则环境中的所有节点会使用这个本地软件仓库。 如果只包含 local,那么它会成为所有节点的唯一软件源,如果你还想要从其他上游软件仓库继续安装其他软件包,可以将其他仓库模块名称也添加进去,例如 local,node,infra,pgsql

混合安装模式

如果您的环境有互联网访问,那么有一种混合方法可以融合离线安装与在线安装的优点。 您可以使用离线软件包作为基础,并在线补足不匹配的增量软件包。

v4.4.0 历史制品为例,假设您使用的是 RockyLinux 9.6,但该离线软件包是为 RockyLinux 9.7 制作的。 您可以使用 el9 离线软件包(虽然是针对 9.7 制作的),然后在执行正式安装前,执行 make repo-build 重新下载 9.6 对应的缺失软件包, Pigsty 将从上游仓库重新下载所需的 增量


制作离线软件包

如果您选择的操作系统不在默认列表中,您可以使用内置的 cache.yml 剧本制作自己的离线软件包:

  1. 找到一台运行完全相同操作系统版本,且可以访问互联网的节点
  2. 使用 rich 配置模板执行 在线安装./configure -c rich),并确认目标 Infra 节点的 /www/pigsty 本地仓库已经生成;若尚未生成,可先对该节点执行 ./infra.yml -t repo
  3. cd ~/pigsty; ./cache.yml -l <infra-host>:明确选择一个已经具备本地仓库的 Infra 节点,制作并取回离线软件包
  4. 默认制品位于 ~/pigsty/dist/${version}/pigsty-pkg-${version}.${os}.${arch}.tgz;将它复制到离线环境(ftp、scp、usb 等),再通过 bootstrap 解包使用

cache.yml 的当前默认值如下,可使用额外变量覆盖:

cache_pkg_name , defaultpigsty-pkg-${version}.${os}.${arch}.tgz
离线包文件名模板
cache_pkg_dir , defaultdist/${version}
管理节点上的输出目录
cache_repo , defaultpigsty
从目标节点打包的本地仓库;多个仓库用逗号分隔

我们提供 付费服务,提供经过测试的预制 Linux 主版本。次版本制作离线软件包(¥200)。


Bootstrap

Pigsty 依赖 ansible 执行剧本,这个脚本负责用各种方式来确保 ansible 正确安装。

./bootstrap       # 确保 ansible 正确安装(如果有离线包,优先使用离线安装并解包使用)

通常在两种情况下,你需要运行这个脚本:

  • 你不是通过 安装脚本 来安装 Pigsty 的,而是通过下载,git clone 源码包的方式安装的,因此没有安装 ansible。
  • 你准备通过离线软件包来安装 Pigsty,需要使用这个脚本来从离线软件包中安装 ansible。

bootstrap 脚本将自动检测离线软件包是否存在(-p 指定,默认为 /tmp/pkg.tgz)。 如果存在则解压使用它,然后从里面安装 ansible。 如果离线包不存在,它会尝试从互联网安装 ansible。如果还是不行,那你就要自己想办法了!

我的 yum/apt 仓库文件跑到哪里去了?

引导程序默认会 移走 现有软件源配置,以确保只有所需的仓库被启用。 您可以在 /etc/yum.repos.d/backup (EL) 或 /etc/apt/backup (Debian / Ubuntu) 中找回它们。

如果您想在 bootstrap 过程中保留现有软件源配置,请使用 -k|--keep 参数。

./bootstrap -k # 或 --keep

1.8 - 精简安装

只安装高可用 PostgreSQL 集群及其最小依赖的精简安装模式

如果您只想要高可用 PostgreSQL 数据库集群本身,而不需要监控、基础设施等功能,请考虑 精简安装

精简安装没有 INFRA 模块,没有监控,没有 本地仓库,只有 ETCDPGSQL 以及部分 NODE 功能。

精简安装适合以下场景
  • 只需要 PostgreSQL 数据库本身,不需要可观测性基础设施。
  • 资源极度受限的环境,不愿意承担基础设施开销(单机约 0.2 vCPU / 500MB 开销)
  • 已有外部监控系统,希望统一使用自己的监控管理体系。
  • 不需要 Grafana 可视化看板组件。
精简安装的局限性
  • 没有 基础设施模块,无法使用 WebUI 和本地软件仓库功能。
  • 离线安装 仅限单机模式使用,多节点精简安装只能在线安装。

概览

使用精简安装,您需要:

  1. 使用 slim.yml 精简安装配置模板(configure -c slim
  2. 执行 slim.yml 剧本进行部署,而不是默认的 deploy.yml
curl https://repo.pigsty.cc/get | bash
./configure -g -c slim
./slim.yml
demo/install-slim.cast

说明

精简安装只安装/配置以下组件:

组件 必要性 描述
patroni ⚠️ 必需 引导高可用 PostgreSQL 集群
etcd ⚠️ 必需 Patroni 的元数据库依赖(DCS)
pgbouncer ✔️ 可选 PostgreSQL 连接池
vip-manager ✔️ 可选 L2 VIP 绑定到 PostgreSQL 集群主节点
haproxy ✔️ 可选 根据 Patroni 健康检查,自动路由 服务
chronyd ✔️ 可选 与 NTP 服务器的时间同步
tuned ✔️ 可选 节点调优模板和内核参数管理

你可以通过进一步的配置,关闭所有可选组件,只保留必需组件 patronietcd

因为缺少 Infra 模块的 Nginx 提供本地仓库服务,只有单机安装的时候可以进行 离线安装


配置

精简安装的配置文件示例:conf/slim.yml

ID NODE PGSQL INFRA ETCD
1 10.10.10.10 pg-meta-1 不安装基础设施模块 etcd-1
---
#==============================================================#
# File      :   slim.yml
# Desc      :   Pigsty slim installation config template
# Ctime     :   2020-05-22
# Mtime     :   2025-12-28
# Docs      :   https://pigsty.io/docs/conf/slim
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for slim / minimal installation
# No monitoring & infra will be installed, just raw postgresql
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c slim
#   ./slim.yml

all:
  children:

    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 }  # three-member cluster keeps an odd voter count
      vars: # cluster level parameter override roles/etcd
        etcd_cluster: etcd  # mark etcd cluster name etcd

    #----------------------------------------------#
    # PostgreSQL Cluster
    #----------------------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
        #10.10.10.11: { pg_seq: 2, pg_role: replica } # you can add more!
        #10.10.10.12: { pg_seq: 3, pg_role: replica, pg_offline_query: true }
      vars:
        pg_cluster: pg-meta
        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  }
        pg_databases:
          - { name: meta, baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [ vector ]}
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

  vars:
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    nodename_overwrite: false           # do not overwrite node hostname on single node mode
    node_repo_modules: node,infra,pgsql # add these repos directly to the singleton node
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    pg_version: 18                      # Default PostgreSQL Major Version is 18
    pg_packages: [ pgsql-main, pgsql-common ]   # pg kernel and common utils
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

部署

精简安装需要使用 slim.yml 剧本而不是 deploy.yml 剧本进行部署:

./slim.yml

高可用集群

精简安装模式也可以部署高可用集群,在 etcdpg-meta 分组中添加更多节点即可,一个三节点的部署样例:

ID NODE PGSQL INFRA ETCD
1 10.10.10.10 pg-meta-1 不安装基础设施模块 etcd-1
2 10.10.10.11 pg-meta-2 不安装基础设施模块 etcd-2
3 10.10.10.12 pg-meta-3 不安装基础设施模块 etcd-3
all:
  children:
    etcd:
      hosts:
        10.10.10.10: { etcd_seq: 1 }
        10.10.10.11: { etcd_seq: 2 }  # <-- 新增
        10.10.10.12: { etcd_seq: 3 }  # <-- 新增

    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 } # <-- 新增
      vars:
        pg_cluster: pg-meta
        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  }
        pg_databases:
          - { name: meta, baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [ vector ]}
        pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ] # 每天凌晨 1 点执行全量备份
  vars:
    # 省略 ……

1.9 - 安全建议

快速上手和单机部署的基本安全检查。

默认配置适用于本地演示和受信内网中的开发测试。只要部署可能被其他主机访问,就应至少完成凭据、网络和关键文件三项检查。

生产环境还应参考 安全模型合规实践安全考量


密码

Pigsty 的默认凭据公开记录在源码和文档中,不能直接用于生产。

配置向导可以随机化其识别的内置参数和示例凭据:

./configure -g

configure -g 不会替换以下内容:

  • pgBackRest 的 cipher_pass
  • ha/safe 中的 Silo 用户和部分示例口令;
  • 用户自行添加的数据库、对象存储或应用凭据。

生成完成后,应检查 pigsty.yml,逐项替换未覆盖的凭据。配置向导会在终端输出生成的密码,因此终端记录和自动化日志也应按敏感信息保护。

完整范围见 默认凭据


防火墙

node_firewall_mode 默认为 zone,信任 node_firewall_intranet 定义的内网,并限制公网放行端口。

端口 服务 默认公网状态
22 SSH 放行
80 Nginx HTTP 放行
443 Nginx HTTPS 放行
5432 PostgreSQL 基础默认值不放行;演示配置 pigsty.yml 额外放行

生产部署通常应从演示配置中移除 5432。如果业务需要直接连接数据库,应在云安全组、防火墙和 HBA 中同时限制来源地址。

还应检查内网定义是否符合实际信任边界。默认 RFC 1918 地址段可能覆盖范围过大,办公网、容器网段和其他租户网络不应自动视为可信。


文件

以下文件和目录包含高敏感信息:

  • pigsty.yml:系统与业务凭据、节点和服务配置;
  • files/pki/ca/ca.key:本地 CA 私钥;
  • 管理用户 SSH 私钥:用于访问纳管节点;
  • files/pki/misc/*.key:客户端证书私钥;
  • /pg/tmp/pg-user-*.sql:用户创建过程中生成的明文口令 SQL。

应限制管理节点和配置仓库访问,避免将完整配置或私钥提交到公开仓库,并为 CA 私钥和必要配置建立受控备份。


相关文档

2 - 部署

在生产环境中进行多节点、高可用的 Pigsty 规划、准备与部署工作。

快速上手 不同,企业生产环境 Pigsty 部署需要更多 架构规划准备工作

本章将帮助您理解 Pigsty 的完整部署流程,并提供生产环境部署的最佳实践建议。


我们建议您在真实的生产环境部署之前,使用 Pigsty 提供的 沙箱环境 进行测试与演练,确保对部署流程有充分的了解。 您可以使用 Vagrant 在本地快速创建一个四节点的 Pigsty 沙箱环境用于测试,或者利用 Terraform 在云端置备一个更大规模的仿真环境。

pigsty-sandbox

对于生产环境部署,您通常需要准备至少三个 节点 以实现高可用。您需要进一步了解 Pigsty 的 相关概念 以及常见操作的管理 SOP。 包括如何通过 参数配置 进行定制,如何执行 Ansible 剧本 进行部署。以及如何加固部署的 安全性 以满足企业合规要求。

2.1 - 生产部署

如何在 Linux 主机上安装 Pigsty?

本文是 Pigsty 生产环境多节点部署指南,部署单机版本 Demo/Dev 环境可以参考 快速上手 文档。


摘要

准备 几台 具有 SSH 权限节点, 安装 兼容的 Linux 系统,使用具有免密 sshsudo 权限的 管理用户 执行:

pigsty.cc(中国)
curl -fsSL https://repo.pigsty.cc/get | bash;
pigsty.io(全球)
curl -fsSL https://repo.pigsty.io/get | bash;

该命令会执行 安装 脚本,下载并提取 Pigsty 源码至家目录并安装依赖,接下来依次完成 配置部署 即可完成交付。

在执行 deploy.yml 进行部署前,您可能需要进一步审视与编辑 配置清单pigsty.yml 文件,确认部署细节。

cd ~/pigsty      # 进入 Pigsty 目录
./configure -g   # 生成配置文件(可选,如果知道如何配置可以跳过)
./deploy.yml     # 执行部署剧本,根据生成的配置文件开始安装

安装完成后,您可以通过 IP / 域名 + 80/443 端口访问 Web 用户界面, 并通过 5432 端口访问 PostgreSQL 服务

完整流程根据服务器规格/网络条件需 3~10 分钟,离线安装 时能够显著加速;无需监控时可使用 精简安装 进一步加速。

视频样例:20 节点生产仿真环境(Ubuntu 24.04 x86_64)

demo/install-simu.cast

准备

在生产环境中部署安装 Pigsty 涉及一些 准备工作,以下为完整检查清单,供您参考。

项目 要求 项目 要求
节点 至少 1C2G,上不封顶 规格 多个同质节点,2 / 3 / 4 / 或更多
磁盘 /data 作为默认主挂载点 FS 推荐使用 xfs,按需使用 ext4 / zfs
VIP L2 VIP,可选 (云环境不可用) 网络 静态 IPv4 地址,单节点无固定 IP 可使用 127.0.0.1
CA 可以使用自签名 CA 或指定已有证书 域名 本地 / 公网域名,可选,默认 i.pigsty 自签名域名
内核 Linux x86_64 / aarch64 Linux el8, el9, el10, d12, d13, u22, u24, u26
Locale C.UTF-8C 防火墙 端口:80 / 443 / 22 / 5432 (可选)
用户 避免使用 rootpostgres Sudo sudo 权限,最好带有 nopass 免密选项
SSH 通过公钥 nopass SSH 登陆纳管节点 可达性 ssh <ip|alias> sudo ls 无错误

安装

您可以使用以下命令自动安装 Pigsty 源码包~/pigsty 目录(推荐),部署所需依赖(Ansible)会自动安装。

pigsty.cc(中国)
curl -fsSL https://repo.pigsty.cc/get | bash            # 安装当前默认版本
curl -fsSL https://repo.pigsty.cc/get | bash -s v4.5.0  # 显式安装当前公开稳定版
pigsty.io(全球)
curl -fsSL https://repo.pigsty.io/get | bash            # 安装当前默认版本
curl -fsSL https://repo.pigsty.io/get | bash -s v4.5.0  # 显式安装当前公开稳定版

如果您不希望执行远程脚本,可以手动 下载 或克隆源码。使用 git 克隆安装时,请务必检出特定版本后再使用。

git clone https://github.com/pgsty/pigsty; cd pigsty;
git checkout v4.5.0;  # 使用 git 安装时,请务必检出已发布的 tag

手工下载克隆安装时,请额外执行 bootstrap 脚本以手动安装 Ansible 等部署依赖,您也可以 自行安装

./bootstrap           # 安装 ansible,用于执行后续部署

配置

在 Pigsty 中,部署的蓝图细节由 配置清单 所定义,也就是 pigsty.yml 配置文件,您可以通过声明式配置进行定制。

Pigsty 提供了 configure 脚本作为可选的 配置向导, 它将根据您的环境和输入,生成具有良好默认值的 配置清单

./configure -g                # 使用配置向导生成配置文件,并且生成随机密码

配置过程生成的配置文件默认位于:~/pigsty/pigsty.yml,您可以在安装前进行检查,按需修改与定制。

有许多 配置模板 供您参考与使用,但您也完全可以跳过配置向导,直接编辑 pigsty.yml 配置文件进行定制。

./configure -c ha/full -g       # 使用四节点沙箱环境模板
./configure -c ha/trio -g       # 使用三节点最小 HA 模板
./configure -c ha/dual -g -v 18 # 使用两节点半高可用模板,使用 PG 18
./configure -c ha/simu -s       # 使用二十节点生产仿真模板,不检查 IP,不生成随机强密码
配置 / configure 过程的样例输出
vagrant@meta:~/pigsty$ ./configure
configure pigsty v4.5.0 begin
[ OK ] region = china
[ OK ] kernel  = Linux
[ OK ] machine = x86_64
[ OK ] package = deb,apt
[ OK ] vendor  = ubuntu (Ubuntu)
[ OK ] version = 22 (22.04)
[ OK ] sudo = vagrant ok
[ OK ] ssh = [email protected] ok
[WARN] Multiple IP address candidates found:
    (1) 192.168.121.38	    inet 192.168.121.38/24 metric 100 brd 192.168.121.255 scope global dynamic eth0
    (2) 10.10.10.10	    inet 10.10.10.10/24 brd 10.10.10.255 scope global eth1
[ OK ] primary_ip = 10.10.10.10 (from demo)
[ OK ] admin = [email protected] ok
[ OK ] mode = meta (ubuntu22.04)
[ 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

配置向导只会为您替换 当前节点 的 IP(如果您不想要替换,使用 -s 参数),所以对于一个多节点的部署,您需要自己替换其他节点的 IP 地址。 同时,你还需要按需对配置文件进行进一步的定制,例如修改默认密码、添加更多节点等。

配置脚本常用参数

参数 说明
-c|--conf 用于指定使用的 配置模板,相对于 conf/ 目录,不带 .yml 后缀的配置名称
-v|--version 指定 PostgreSQL 大版本 1419;PG19 当前为 Beta
-r|--region 用于指定上游软件源的区域,加速下载: (default|china|europe)
-n|--non-interactive 直接使用命令行参数提供首要 IP 地址,跳过交互式向导
-x|--proxy 使用当前环境变量配置 proxy_env 变量

如果您的机器网卡绑定了多个 IP 地址,那么需要使用 -i|--ip <ipaddr> 显式指定一个当前节点的首要 IP 地址,或在交互式问询中提供。 该脚本将把 IP 占位符 10.10.10.10 替换为当前节点的主 IPv4 地址。选用的地址应为静态 IP 地址,请勿使用公网 IP 地址。

配置过程生成的配置文件默认位于:~/pigsty/pigsty.yml,您可以在安装前进行检查与修改定制。

修改默认密码!

安装前应修改配置文件中的默认密码与凭据,详见 安全建议


部署

Pigsty 的 deploy.yml 剧本 会将 配置 中生成的蓝图应用至 所有的目标节点

./deploy.yml     # 一次性在所有目标节点上部署核心模块
部署过程的样例输出
......

TASK [pgsql : pgsql init done] *************************************************
ok: [10.10.10.11] => {
    "msg": "postgres://10.10.10.11/postgres | meta  | dbuser_meta dbuser_view "
}
......

TASK [pg_monitor : load grafana datasource meta] *******************************
changed: [10.10.10.11]

PLAY RECAP *********************************************************************
10.10.10.11                : ok=302  changed=232  unreachable=0    failed=0    skipped=65   rescued=0    ignored=1
localhost                  : ok=6    changed=3    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

当您看到输出尾部如果带有 pgsql init donePLAY RECAP 等字样,说明安装已经完成!

上游软件仓库变更可能导致在线安装失败!

Pigsty 使用的上游软件仓库(如 Linux / PGDG 仓库)可能会因为不恰当的更新,进入崩溃状态并导致部署失败(相当常见)! 对于严肃的生产环境部署,我们强烈建议使用经过验证的 离线软件包 进行 离线安装

避免重复执行部署剧本!

警告: 在已经完成部署的环境中再次完整运行 deploy.yml 可能会重启相关服务并覆盖配置,请务必注意!


界面

假设您使用 四节点 部署模版,那么 Pigsty 部署完成后,您的环境应该具有类似下面的部署结构:

ID NODE PGSQL INFRA ETCD
1 10.10.10.10 pg-meta-1 infra-1 etcd-1
2 10.10.10.11 pg-test-1 - -
3 10.10.10.12 pg-test-2 - -
4 10.10.10.13 pg-test-3 - -

INFRA 模块通过浏览器提供了一个 图形化管理界面,您可以直接通过这台节点上的 Nginx 的 80/443 端口访问。

PGSQL 模块提供了一个 PostgreSQL 数据库服务器,监听 5432 端口,也可通过 Pgbouncer / HAProxy 代理访问

对于生产环境的多节点高可用 PostgreSQL 集群来说,您需要通过 服务接入 来使用数据库服务,实现流量自动路由。

Pigsty 在线演示首页


更多

安装完成后,您可以探索 用户界面,并通过 5432 端口访问 PostgreSQL 服务

您还可以使用 Pigsty 部署和监控 更多集群:向 配置清单 添加定义并运行:

bin/node-add   pg-test      # 将集群 pg-test 的 3 个节点纳入 Pigsty 管理
bin/pgsql-add  pg-test      # 初始化一个 3 节点的 pg-test 高可用 PG 集群
bin/redis-add  redis-ms     # 初始化 Redis 集群: redis-ms

大多数模块都需要先安装 NODE 模块。查看可用的 模块 了解详情:

PGSQLINFRANODEETCDMINIOREDISDOCKER……

2.2 - 资源准备

生产部署的准备工作,包括硬件,节点、磁盘、网络、VIP、域名、软件、文件系统等……

Pigsty 运行在节点(物理机或虚拟机)之上,本文档介绍硬件相关的规划与准备。


节点

Pigsty 目前运行在 Linux 内核和 x86_64 / aarch64 架构的节点上。 "节点" 指的是 SSH 可访问 且提供裸 Linux 操作系统环境的资源。 它可以是物理机、虚拟机或配备 systemdsudosshd 的类似操作系统的容器。

部署 Pigsty 至少需要 1 个节点,您可以准备更多,并在 执行部署剧本 中一次性部署所有节点,或稍后添加并单独部署。 最小节点规格要求是 1C1G,建议至少使用 1C2G。越高越好,没有上限。系统参数将根据可用资源自动调优

所需节点的数量,取决于您的需求,更多详情请参考 架构规划。 尽管带有 外部备份单机部署 也提供一定程度上的兜底, 但我们建议在生产部署中使用复数个节点,起作用的 高可用配置 至少需要 3 个节点才能工作,2 个节点则提供 半高可用


磁盘

Pigsty 将使用 /data 作为默认数据目录,如果您有专用的主数据磁盘,建议将其挂载到那里,并为额外的磁盘驱动器使用 /data1/data2/dataN。 如果你想使用其他的数据目录,可以通过以下参数进行配置:

名称 描述 默认值
node_data 节点主数据目录 /data
pg_fs_main PG 主数据目录 /data/postgres
pg_fs_backup PG 备份数据目录 /data/backups
etcd_data ETCD 数据目录 /data/etcd
infra_data Infra 数据目录 /data/infra
nginx_data Nginx 数据目录 /data/nginx
minio_data Silo 数据目录 /data/minio
redis_fs_main Redis 数据目录 /data/redis
kafka_data Kafka 数据目录 /data/kafka

原生 MySQL 8.4 试点模块当前不提供数据目录参数,固定使用 /var/lib/mysql


文件系统

您可以使用任何支持的 Linux 文件系统来格式化数据磁盘,但对于生产环境部署,我们建议使用 xfs

xfs 是 Linux 的标配之一,提供了最佳的性能与便利的 CoW 机制,允许你瞬间克隆大型数据库集群。使用 Silo 多盘部署时,必须使用 xfs 文件系统。 ext4 是另一个可用的选择,但缺乏 CoW 功能,但有着更为丰富的数据恢复工具生态。zfs 可以提供 RAID,快照功能,但性能折损较大且需要单独安装。 我们推荐您在这三种文件系统中按需权衡,择一使用。

如果有特殊需求,您也可以使用其他文件系统,但我们强烈不建议使用 NFS 网络文件系统来运行数据库服务。

Pigsty 的工作假设是 /data 目录属于 root:root,权限为 755。 管理员可以分配一级目录的所有权和权限。每个应用在其子目录中运行时将使用专用用户。 Pigsty 使用的目录结构说明,请参考 FHS 文档说明。


网络

Pigsty 默认使用在线安装模式,需要出站互联网访问。 使用 离线安装 模式则不再需要互联网访问。

在内网中,Pigsty 需要 静态网络 才能工作,您应该为每个节点明确分配一个 固定的 IPv4 地址。

IP 地址将用作节点的 唯一标识符,它应该是绑定到用于 内部 网络通信的主网络接口的主 IP 地址。

作为特例,单机部署 时如果没有固定 IP 地址,可以使用本地环回地址 127.0.0.1 作为变通。

永远不要使用公网 IP 作为标识符

使用公网 IP 地址作为节点标识符可能导致安全和连接问题,请务必使用内网 IP 地址作为标识。


VIP

Pigsty 支持 NODE 集群(keepalived)和 PGSQL 集群(vip-manager)的可选 L2 VIP。

要使用 L2 VIP 功能,您必须为节点集群/数据库集群明确分配指定一个 L2 VIP 地址。 在您自己的硬件上运行时这不是大问题,但在公有云环境中工作时可能成为问题。

L2 VIP 需要 L2 网络

要使用可选的节点 VIP 和 PG VIP 功能,请确保所有节点位于同一 L2 网络内。


CA

Pigsty 默认为每一套部署生成一套自签名的 CA 基础设施,用于签发环境中所有的加密证书。

如果您已经有了正规的企业 CA,或者已经有了自签名的 CA,您也可以选择使用已有的 CA 来签发 Pigsty 所需的证书。


域名

Pigsty 默认使用一个本地静态域名 i.pigsty 来访问 WebUI,这是可选的,你也可以直接使用 IP 地址访问。

对于生产环境部署来说,建议您使用域名来访问服务,只有使用域名,才能启用 HTTPS 支持,加密您的数据传输。 同时,域名访问允许您在同一个端口上运行多种不同的服务,并通过不同的域名进行区分。

如果您的部署提供 互联网访问,那么可以使用公共 DNS 供应商(如 Cloudflare、阿里云 DNS、AWS Route53 等)来管理您的域名解析。 将您的域名指向 Pigsty 节点的 公网 IP 地址 即可。 如果您的部署针对 局域网/办公网 开放,那么可以使用内部 DNS 服务器来管理域名解析。 将您的域名指向 Pigsty 节点的 办公网 IP 地址 即可。

如果您的访问仅限于本机,或特定的几台机器,那么可以使用本地静态解析来管理域名解析。 将以下记录添加到(用于访问 Pigsty WebUI 的机器) /etc/hosts 文件(本地静态解析)中,即可从浏览器中访问。

10.10.10.10 i.pigsty    # 替换为您计划使用的域名,与 Pigsty 节点的 IP 地址

Linux

Pigsty 运行在 Linux 操作系统上,支持 8 个发行版大版本在双架构上的 16 个当前平台目标:兼容操作系统列表

我们推荐使用 Rocky Linux 9.8 / 10.2Debian 12.15 / 13.6,或 Ubuntu 22.04.5 / 24.04.4 / 26.04.0 作为默认操作系统选项。

在 MacOS 和 Windows 上,您可以用各种虚拟机软件或者 Docker systemd 镜像来安装 Pigsty。

我们 强烈建议 使用全新安装的操作系统环境,如果您的服务器已经运行了 Nginx / PostgreSQL 等服务,请考虑使用新的节点进行部署。

在所有节点上使用相同的操作系统版本

多节点部署时,请确保所有节点使用相同的 Linux 发行版,架构与版本。异构节点部署虽然可能可以工作,但不受支持且可能导致不可预见的问题。


Locale

我们建议您将 en_US 设置为操作系统的主要语言,至少确保该 Locale 可用,从而确保 PG 日志打印英文。

一些发行版可能默认没有提供 en_US 区域设置,例如 Debian。使用以下命令启用 en_US 区域设置:

localedef -i en_US -f UTF-8 en_US.UTF-8
localectl set-locale LANG=en_US.UTF-8

对于 PostgreSQL 来说,我们强烈建议您默认使用 PG 17+ 内置的 C.UTF-8 作为默认排序规则。

配置向导 中如果检测到 PG 版本满足或者操作系统支持,就默认配置 C.UTF-8 作为排序规则。


Ansible

Pigsty 使用 Ansible 从管理节点发起对所有被管理节点的控制, 安装 Ansible 会介绍更多细节。

Pigsty 默认会在 Infra 节点上安装 Ansible,所以 Infra 节点是可以作为管理节点(或备用管理节点)使用。 在 单机部署 的时候,您当前执行安装的节点,既是运行 ansible 管理命令的 管理节点,也是部署基础设施的 INFRA节点


Pigsty

您可以使用以下方式 安装 最新稳定版本的 Pigsty 源代码:

pigsty.cc(中国)
curl -fsSL https://repo.pigsty.cc/get | bash;
pigsty.io(全球)
curl -fsSL https://repo.pigsty.io/get | bash;

安装 最新特定版本的 Pigsty,可以使用 -s <version> 参数:

pigsty.cc(中国)
curl -fsSL https://repo.pigsty.cc/get | bash -s <version>  # 安装特定版本(当前稳定版:v4.5.0)
pigsty.io(全球)
curl -fsSL https://repo.pigsty.io/get | bash -s <version>  # 安装特定版本(当前稳定版:v4.5.0)

安装 最新 Beta 版本的 Pigsty 源代码,可以使用 beta 脚本:

pigsty.cc(中国)
curl -fsSL https://repo.pigsty.cc/beta | bash;
pigsty.io(全球)
curl -fsSL https://repo.pigsty.io/beta | bash;

如果你是开发者,或者想要获取最新的开发版本,可以直接 git 克隆 Pigsty 代码仓库:

git clone https://github.com/pgsty/pigsty.git;
cd pigsty; git checkout <tag>  # 使用已发布版本(当前稳定 tag:v4.5.0)

如果您的环境没有互联网访问,也可以直接从 GitHub Release 页面,或者 Pigsty 仓库下载源码包:

wget https://repo.pigsty.cc/src/pigsty-v<version>.tgz
wget https://repo.pigsty.io/src/pigsty-v<version>.tgz

2.3 - 架构规划

使用多少个节点?为哪些模块配置高可用?如何根据可用的资源与业务需求进行规划?

Pigsty 采用 模块化架构,您可以像搭积木一样组合出自己想要的部署方案,并用简单的 声明式配置 表达您的意图。

常见方案

这里有一些常见的组合模式供您参考,您可以根据自己的需求进行进一步的定制与调整:

方案 INFRA ETCD PGSQL MINIO 说明
单机部署(meta 1 1 1 单机部署 默认配置,经典方案
单机部署(slim 1 1 不要监控设施,只要数据库
基础设施(infra 1 只要监控基础设施
单机部署(rich 1 1 1 1 单机 + 对象存储 + 本地仓库/扩展
多节点方案 INFRA ETCD PGSQL MINIO 说明
双节点(dual 1 1 2 2节点半 HA,可容忍坏特定一个
三节点(trio 3 3 3 标准3节点 HA,可容忍坏一个
四节点(full 1 1 1+3 演示专用,1 INFRA/ETCD
生产部署(simu 2 3 n n 2个 INFRA,3个 ETCD
大规模生产(自定义) 3 5 n n 3个 INFRA,5个 ETCD

使用什么样的架构规划方案,取决于您对数据库可靠性的要求,以及手头可用的资源。 通常来说,严肃的生产环境部署至少需要 3 个节点以实现 高可用配置。 如果您只有 2 个节点,则可以使用 半高可用配置

专家咨询服务:架构规划

我们提供 架构咨询服务(¥2,000)为您筹划合适的 Pigsty 配置方案。


利弊权衡

  • 若要使用 Pigsty 的监控系统,则至少需要 1 个 INFRA 节点,生产部署通常使用 2 个,大规模部署 3 个。
  • 若要启用 PG 高可用,则至少需要 1 个 ETCD 节点;生产部署通常使用 3 个,大规模环境中使用 5 个。偶数成员也能运行,但不会比少一个成员的奇数集群提高故障容忍数,因此应优先采用奇数规模。
  • 若要启用 MINIO 模块的 Silo 对象存储,则至少需要 1MINIO 节点,严肃使用时通常使用 4+ 节点部署 MNMD 集群。
  • PG 生产集群通常至少为两节点主从配置;严肃场景通常使用 3 节点;高只读负载可以有更多从库(几十个)
  • 此外对于 PostgreSQL 来说,您还可以按需使用 离线实例,同步实例,备份集群,延迟集群等等高级配置。

单节点配置

最简单的配置,所有内容都在单个节点上运行,默认安装四个基本模块,通常用于 Demo,Devbox,或测试环境。

ID NODE PGSQL INFRA ETCD
1 node-1 pg-meta-1 infra-1 etcd-1

如果为备份/PITR 配置了外部 S3 / MinIO 备份仓库 提供兜底的 RTO/RPO,此配置亦可用于普通标准的生产环境。

单节点配置有多种变体:


双节点配置

双节点配置 将启用数据库复制和 半高可用 能力,提供更好的数据冗余,以及有限的故障转移支持:

ID NODE PGSQL INFRA ETCD
1 node-1 pg-meta-1 (replica) infra-1 etcd-1
2 node-2 pg-meta-2 (primary)

双节点配置的高可用自动切换机制有限制,这种"半 HA"设置只能从特定节点故障中自动恢复:

  • 如果 node-1 故障,无自动故障转移:需要手动提升 node-2
  • 如果 node-2 故障,自动故障转移有效:node-1 自动提升

三节点配置

三节点模板 提供真正的基础高可用配置,可以容忍任意一个节点的故障,并从中自动恢复。

ID NODE PGSQL INFRA ETCD
1 node-1 pg-meta-1 infra-1 etcd-1
2 node-2 pg-meta-2 infra-2 etcd-2
3 node-3 pg-meta-3 infra-3 etcd-3

四节点配置

Pigsty 沙箱环境 使用的 标准四节点配置

ID NODE PGSQL INFRA ETCD
1 node-1 pg-meta-1 infra-1 etcd-1
2 node-2 pg-test-1
3 node-3 pg-test-2
4 node-4 pg-test-3

在这里我们出于演示目的,不配置 INFRA / ETCD 模块的高可用,您也可以对其进行进一步的调整

ID NODE PGSQL INFRA ETCD MINIO
1 node-1 pg-meta-1 infra-1 etcd-1 minio-1
2 node-2 pg-test-1 infra-2 etcd-2
3 node-3 pg-test-2 etcd-3
4 node-4 pg-test-3

更多节点

如果您有着完善的虚拟化设施或充足的资源,完全可以 使用更多的节点,让每个模块都采用 独占式部署,从而获得最佳的可靠性,可观测性与性能表现。

ID NODE INFRA ETCD MINIO PGSQL
1 10.10.10.10 infra-1 pg-meta-1
2 10.10.10.11 infra-2 pg-meta-2
3 10.10.10.21 etcd-1
4 10.10.10.22 etcd-2
5 10.10.10.23 etcd-3
6 10.10.10.31 minio-1
7 10.10.10.32 minio-2
8 10.10.10.33 minio-3
9 10.10.10.34 minio-4
10 10.10.10.40 pg-src-1
11 10.10.10.41 pg-src-2
12 10.10.10.42 pg-src-3
13 10.10.10.50 pg-test-1
14 10.10.10.51 pg-test-2
15 10.10.10.52 pg-test-3
16 ……

2.4 - 管理机制

关于管理用户、管理节点,Sudo、SSH、可达性验证,以及防火墙的配置与准备

Pigsty 需要一个在所有被管理节点上具有免密 SSHSudo 权限的操作系统 管理用户

这个用户需要能够通过 ssh 访问到所有被管理节点,并且能够在这些节点上执行 sudo 命令。

要想将节点纳入 Pigsty 中管理,


用户

通常我们会选择 dbaadmin 这样的用户名称,并避免使用 rootpostgres

  • 使用 root 进行部署是可行的,但不符合生产最佳实践。
  • 使用 postgrespg_dbsu)作为管理员用户是严格禁止的。

免密码

如果您可以接受为每个 sshsudo 命令输入密码,则免密码要求是可选的。

您可以在 执行剧本 时使用 -k|--ask-pass 来提示输入 SSH 密码, 以及 -K|--ask-become-pass 来提示输入 sudo 密码。

./deploy.yml -k -K

一些企业的安全策略可能不允许免密 sshsudo,在这种情况下,您可以使用上述选项。

或者考虑配置一个 sudo 密码缓存时间较长的 sudoers 规则,以减少密码提示的频率。


创建管理员用户

通常,您的服务器/虚拟机供应商会为您创建一个初始管理员用户。

如果你对这个用户不满意,Pigsty 的部署剧本可以为你创建一个 新的管理员用户

假设您在节点上有 root 权限,或有一个现有的管理员用户,您可以使用 Pigsty 本身创建管理员用户:

./node.yml -k -K -t node_admin \
  -e ansible_user=[当前可登录的管理员名称] \
  -e node_admin_username=[你准备创建的管理员名称]

它将利用现有的管理员创建新的管理员,创建由以下参数描述的专用 dba(uid=88)用户,并正确配置 sudo / ssh。

名称 描述 默认值
node_admin_enabled 启用节点管理员用户 true
node_admin_uid 节点管理员用户的 UID 88
node_admin_username 节点管理员用户名 dba

Sudo

所有 管理员用户 都应该在所有被管理节点上具有 sudo 权限【最好带有免密码执行权限】。

如果您想从头开始配置具有免密 sudo 权限的管理员用户,可以编辑/创建 suoder 文件(假设用户名为 vagrant):

echo '%vagrant ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/vagrant

假设您的管理员用户名选择是 dba,那么 /etc/sudoers.d/dba 内容应该是:

%dba ALL=(ALL) NOPASSWD: ALL

如果您的安全策略不允许免密码 sudo,请将 NOPASSWD: 部分删除:

%dba ALL=(ALL) ALL

Ansible 依赖 sudo 在被管理节点上以 root 权限执行命令。 在 sudo 不可用的环境中(比如 Docker 容器内)需要先安装 sudo 才能正确部署。


SSH

您的当前用户应该能够以相应的管理员用户身份免密 SSH 访问所有被管理节点。

您的当前用户可以是管理员用户本身,但不是必需的,只要您能以管理员用户身份 SSH。

SSH 配置是 Linux 101,但我们会在此处介绍基础知识,以防您不熟悉:

生成 SSH 密钥

如果您没有 SSH 密钥对,请生成一个:

ssh-keygen -t rsa -b 2048 -N '' -f ~/.ssh/id_rsa -q

如果您没有密钥对,Pigsty 会在 bootstrap 阶段为您完成此操作。

复制 SSH 密钥

您需要将生成的公钥分发到远程(和本地)服务器,并将其放入所有节点上管理员用户的 ~/.ssh/authorized_keys 文件中。 可以使用 ssh-copy-id 工具。

ssh-copy-id <ip>                        # 交互式密码输入
sshpass -p <password> ssh-copy-id <ip>  # 非交互式(谨慎使用)

使用别名

当无法直接 SSH 访问时(由于跳板机、其他端口、凭据等),考虑在 ~/.ssh/config 中配置 SSH 别名:

Host meta
    HostName 10.10.10.10
    User dba                      # 远程上不同的用户
    IdentityFile /etc/dba/id_rsa  # 不是普通密钥
    Port 24                       # 不是众所周知的端口

并在清单中引用别名,使用 ansible_host 指定真实的 SSH 别名:

nodes:
  hosts:          # 如果节点 `10.10.10.10` 需要 SSH 别名 `meta`
    10.10.10.10: { ansible_host: meta }  # 通过 `ssh meta` 访问

SSH 参数可以直接在 Ansible 中使用,详情请查看 Ansible Inventory Guide。 通过这种技术,您可以使用跳板机访问私有网络中的节点,或者使用不同的端口和凭据访问节点。 或者是利用本地笔记本作为管理节点。


验证可达性

您应该能够从管理节点通过当前用户免密 ssh 访问所有被管理节点。 远程用户(管理员用户)应该有权限运行免密 sudo 命令。 要验证免密 ssh sudo 是否工作,在管理节点上对所有被管理节点运行此命令:

ssh <ip|alias> 'sudo ls'

如果没有密码提示或错误,免密 ssh/sudo 按预期工作。


防火墙

在生产环境部署时,通常需要设置防火墙,以阻止未经授权的端口访问。

默认情况下,你可以阻断办公网/互联网对节点的入站访问,只开放下列端口:

  • 要通过 ssh 访问节点,您必须允许 SSH 端口 22 入站访问。
  • 要访问 WebUI 服务,您必须允许 HTTP(80)/ HTTPS(443)入站访问。
  • 要访问 PostgreSQL 数据库服务,您必须允许 PostgreSQL 的 5432 入站访问。

如果您通过其他端口访问 PostgreSQL 服务,请相应地允许它们。 Pigsty 组件使用的端口列表,请参考:使用的端口

  • 5432:PostgreSQL 数据库
  • 6432:Pgbouncer 连接池
  • 5433:PG 主要服务
  • 5434:PG 副本服务
  • 5436:PG 默认服务
  • 5438:PG 离线服务

2.5 - 沙箱环境

用于学习、测试与演示的 Pigsty 标准四节点沙箱环境

Pigsty 提供了一个标准的四节点 沙箱环境,用于学习、测试与功能演示。

沙箱使用固定的 IP 地址和预定义的身份标识符,便于复现各种演示用例。


环境描述

默认的沙箱环境由 4 个节点组成,默认使用配置文件 ha/full.yml

ID IP 地址 节点名 PostgreSQL INFRA ETCD MINIO
1 10.10.10.10 meta pg-meta-1 infra-1 etcd-1 minio-1
2 10.10.10.11 node-1 pg-test-1
3 10.10.10.12 node-2 pg-test-2
4 10.10.10.13 node-3 pg-test-3

沙箱的配置可以概括表示为以下配置文件:

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }
    etcd:  { hosts: { 10.10.10.10: { etcd_seq:  1 } }, vars: { etcd_cluster: etcd } }
    minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio } }

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

    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 }

  vars:
    version: v4.5.0
    admin_ip: 10.10.10.10
    region: default
    pg_version: 18
pigsty-sandbox

PostgreSQL 集群

沙箱带有一个位于 meta 节点上的单实例 PostgreSQL 集群 pg-meta

10.10.10.10 meta pg-meta-1
10.10.10.2  pg-meta          # 可选的 L2 VIP

沙箱中还有一个由三个实例组成的 PostgreSQL 高可用集群 pg-test,部署在另外三个节点上:

10.10.10.11 node-1 pg-test-1
10.10.10.12 node-2 pg-test-2
10.10.10.13 node-3 pg-test-3
10.10.10.3  pg-test          # 可选的 L2 VIP

两个可选的 L2 VIP 分别绑定在 pg-metapg-test 集群的主实例上。

基础设施

meta 节点上还部署有:

  • ETCD 集群:单节点 etcd 集群,为 PostgreSQL HA 提供 DCS 服务
  • Silo 集群:由 MINIO 模块管理的单节点 minio 集群,提供 S3 兼容对象存储服务
10.10.10.10 etcd-1
10.10.10.10 minio-1

ha/full.yml 还声明了三种 Redis 示例拓扑,并在 Infra 节点启用了 Docker 安装开关;标准 deploy.yml 不会部署这两个可选模块,需要按需另行执行 ./redis.yml./docker.yml


创建沙箱

Pigsty 提供了开箱即用的模板,您可以使用 Vagrant 在本地创建沙箱,或使用 Terraform 在云上创建沙箱。

当然,您也可以自己手工准备并置备这些节点。

本地沙箱(Vagrant)

本地沙箱使用 VirtualBox/libvirt 创建本地虚拟机,可以在您的 Mac / PC 上免费运行。

运行完整的 4 节点沙箱,您的机器应至少拥有 4 核 CPU8GB 内存

cd ~/pigsty/vagrant
make full       # 使用默认 Ubuntu 24.04 镜像创建 4 节点沙箱
make full9      # 使用 RockyLinux 9 创建 4 节点沙箱
make full12     # 使用 Debian 12 创建 4 节点沙箱
make full24     # 使用 Ubuntu 24.04 创建 4 节点沙箱
make full26     # 使用 Ubuntu 26.04 创建 4 节点沙箱

当前 Vagrant 配置统一使用 Vagrant Cloud 上的 cloud-image/* Box。可用镜像、源码固定的版本以及架构说明以 Vagrant 文档 为准;未在源码中固定版本的 Box 会由 Vagrant 解析其当前可用版本。

云沙箱(Terraform)

云沙箱使用公有云 API 创建虚拟机,可以轻松创建和销毁,按需付费,非常适合快速测试。

使用 spec/aliyun-full.tf 模板在阿里云上创建 4 节点沙箱:

cd ~/pigsty/terraform
cp spec/aliyun-full.tf terraform.tf
terraform init
terraform apply

更多详情请参考 Terraform 文档。


其他规格

除了标准的 4 节点沙箱,Pigsty 还提供了其他规格的环境:

以下 Makefile 快捷目标均在 ~/pigsty/vagrant 目录中执行:

cd ~/pigsty/vagrant

单节点开发箱(meta)

最简单的 1 节点环境,用于快速上手、开发和测试:

make meta       # 创建单节点开发箱

双节点环境(dual)

2 节点环境,用于测试主从复制:

make dual       # 创建 2 节点环境

三节点环境(trio)

3 节点环境,用于测试基本高可用:

make trio       # 创建 3 节点环境

生产仿真环境(simu)

20 节点的大型仿真环境,用于模拟生产环境进行完整测试:

make simu       # 创建 20 节点生产仿真环境

该环境包含:

  • 3 个基础设施节点(meta1, meta2, meta3
  • 2 个 HAProxy 代理节点
  • 4 个 MINIO(Silo)节点
  • 5 个 ETCD 节点
  • 6 个 PostgreSQL 节点(2 个集群,每个 3 节点)

2.6 - Vagrant

使用 Vagrant 在本地创建虚拟机环境

Vagrant 是一个流行的本地虚拟化工具,可以按照声明式的方式创建本地虚拟机。

Pigsty 需要 Linux 环境运行,您可以使用 Vagrant 轻松在本地创建 Linux 虚拟机进行测试。

当前推荐并验证的基线为 Rocky Linux 9.8 / 10.2、Debian 12.15 / 13.6,以及 Ubuntu 22.04.5 / 24.04.4 / 26.04.0;Vagrant 的大版本别名会映射到对应的固定 Box 版本。


安装依赖

首先,确保您的系统中已经安装了 Vagrant 和虚拟机软件(VirtualBoxlibvirt,Hyper-V,Parallel,……)。

在 MacOS 上,您可以使用 Homebrew 一键安装 vagrant 与 virtualbox; 在 Linux 上,您可以使用 VirtualBox 或 vagrant-libvirt 作为虚拟机管理软件; 在 Windows 专业版上,可以使用 VirtualBox 与 Hyper-V 作为提供商。

macOS
brew install vagrant virtualbox ansible
# 安装 VirtualBox 后需要重启系统,并在系统偏好设置中允许其内核扩展。
安装 Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

创建虚拟机

使用 Pigsty 提供的 make 快捷方式创建虚拟机:

cd ~/pigsty/vagrant

make meta       # 1 节点开发箱,用于快速上手、开发和测试
make full       # 4 节点沙箱,用于高可用测试和功能演示
make simu       # 20 节点仿真环境,用于生产环境模拟

# 其他不常用的规格
make dual       # 2 节点环境
make trio       # 3 节点环境
make deci       # 10 节点环境

您可以使用变体别名指定不同的操作系统镜像:

make meta9      # 使用 Rocky Linux 9.8 创建单节点
make full12     # 使用 Debian 12.15 创建 4 节点沙箱
make simu24     # 使用 Ubuntu 24.04.4 创建 20 节点仿真环境
make full26     # 使用 Ubuntu 26.04.0 创建 4 节点沙箱

可用的操作系统后缀:8(EL8)、9(EL9)、10(EL10)、12(Debian 12.15)、13(Debian 13.6)、22(Ubuntu 22.04.5)、24(Ubuntu 24.04.4)、26(Ubuntu 26.04.0)

构建环境

您还可以使用以下别名创建 Pigsty 构建环境,这些模板不会替换基础镜像:

make oss        # 7 节点 OSS 构建环境
make pro        # 7 节点 PRO 构建环境
make rpm        # 2 节点 EL9/10 构建环境
make deb        # 5 节点 Debian12/13 Ubuntu22/24/26 构建环境
make all        # 7 节点全量构建环境

规格配置

Pigsty 在 vagrant/spec/ 目录下提供了多种预定义的虚拟机规格:

模板 节点数 规格 说明 别名
meta.rb 1 节点 2c4g x 1 单节点开发箱 Devbox
dual.rb 2 节点 1c2g x 2 双节点环境
trio.rb 3 节点 1c2g x 3 三节点环境
full.rb 4 节点 2c4g + 1c2g x 3 4 节点完整沙箱 Sandbox
deci.rb 10 节点 混合 10 节点环境
simu.rb 20 节点 混合 20 节点生产仿真环境 Simubox
minio.rb 4 节点 1c2g x 4 + 磁盘 MINIO(Silo)测试环境
citus.rb 13 节点 混合 Citus 协调节点与 6 组双副本 Worker
oss.rb 7 节点 2c2g x 7 7 平台 OSS 构建环境
pro.rb 7 节点 2c2g x 7 7 平台 PRO 构建环境
rpm.rb 2 节点 1c2g x 2 2 节点 EL 构建环境
deb.rb 5 节点 1c2g x 5 5 节点 Deb 构建环境
all.rb 7 节点 1c2g x 7 7 节点全量构建环境

每个规格文件包含一个描述虚拟机节点的 Specs 变量。例如,full.rb 包含 4 节点沙箱的定义:

当前 Vagrant 模板会为每台虚拟机显式置备 32 GB 主系统盘。普通节点另外创建一个数据盘,容量由规格中的 disk 指定、未指定时为 128 GB; 名称以 minio 开头的对象存储节点则创建四块 32 GB 数据盘并挂载到 /data1/data4。 这些磁盘依赖 Vagrant 的实验性 disks 功能:使用仓库 Makefile 时已自动导出 VAGRANT_EXPERIMENTAL=disks,直接运行 vagrant 时需自行设置。

# full: pigsty full-featured 4-node sandbox for HA-testing & tutorial & practices

Specs = [
  { "name" => "meta"   , "ip" => "10.10.10.10" ,  "cpu" => "2" ,  "mem" => "4096" ,  "image" => "cloud-image/ubuntu-24.04" },
  { "name" => "node-1" , "ip" => "10.10.10.11" ,  "cpu" => "1" ,  "mem" => "2048" ,  "image" => "cloud-image/ubuntu-24.04" },
  { "name" => "node-2" , "ip" => "10.10.10.12" ,  "cpu" => "1" ,  "mem" => "2048" ,  "image" => "cloud-image/ubuntu-24.04" },
  { "name" => "node-3" , "ip" => "10.10.10.13" ,  "cpu" => "1" ,  "mem" => "2048" ,  "image" => "cloud-image/ubuntu-24.04" },
]

simu 规格详情

simu.rb 提供了一个 20 节点的生产环境仿真配置:

  • 3 x infra 节点(meta1-3):4c16g
  • 2 x haproxy 节点(proxy1-2):1c2g
  • 4 x minio 节点(minio1-4):1c2g
  • 5 x etcd 节点(etcd1-5):1c2g
  • 6 x pgsql 节点(pg-src-1-3pg-dst-1-3):2c4g

配置脚本

使用 vagrant/config 脚本可以根据规格和选项生成最终的 Vagrantfile

cd ~/pigsty
vagrant/config [spec] [image] [scale] [provider]

# 示例
vagrant/config meta u24            # 使用 1 节点规格,Ubuntu 24.04.4 镜像
vagrant/config dual el9            # 使用 2 节点规格,Rocky Linux 9.8 镜像
vagrant/config trio d12 2          # 使用 3 节点规格,Debian 12.15 镜像,双倍资源
vagrant/config full u22 4          # 使用 4 节点规格,Ubuntu 22.04.5 镜像,4 倍资源
vagrant/config simu u26 1 libvirt  # 使用 20 节点规格,Ubuntu 26.04.0 镜像,libvirt 提供商

镜像别名

config 脚本支持多种镜像别名:

发行版 别名 Vagrant Box
Rocky 8 el8, rocky8, r8 cloud-image/rocky-8
Rocky 9 el9, rocky9, el, r9 cloud-image/rocky-9
Rocky 10 el10, rocky10, r10 cloud-image/rocky-10
Debian 12 d12, debian12, deb12 cloud-image/debian-12
Debian 13 d13, debian13, deb13 cloud-image/debian-13
Ubuntu 22.04.5 u22, ubuntu22, ubuntu2204 cloud-image/ubuntu-22.04
Ubuntu 24.04.4 u24, ubuntu24, ubuntu2404, ubuntu cloud-image/ubuntu-24.04
Ubuntu 26.04.0 u26, ubuntu26, ubuntu2604 cloud-image/ubuntu-26.04
AlmaLinux 8 alma8 cloud-image/almalinux-8
AlmaLinux 9 alma9 cloud-image/almalinux-9
AlmaLinux 10 alma10 cloud-image/almalinux-10
RHEL 8 / 9 rhel8, rhel9 generic/rhel8, generic/rhel9
Oracle Linux 8 / 9 oracle8, oracle9 generic/oracle8, generic/oracle9

历史别名 d11/debian11/deb11u20/ubuntu20/ubuntu2004 仍可在脚本映射表中看到,但当前会被显式拒绝,不属于支持镜像。

资源缩放

您可以使用环境变量 VM_SCALE 来调整资源倍数,默认值为 1

VM_SCALE=2 vagrant/config meta     # 将 meta 规格的 CPU/内存资源翻倍

例如,使用 VM_SCALE=4 配置 meta 规格,会将默认的 2c4g 调整为 8c16g:

Specs = [
  { "name" => "meta" , "ip" => "10.10.10.10", "cpu" => "8" , "mem" => "16384" , "image" => "cloud-image/ubuntu-24.04" },
]
simu 与 deci 规格不支持缩放

simudeci 规格不支持资源缩放,scale 参数会被自动重置为 1,因为其资源配置已经针对仿真场景优化。


虚拟机管理

vagrant/Makefile 提供了一系列快捷方式来管理虚拟机;以下命令在该目录中执行:

cd ~/pigsty/vagrant
make           # 等于 make start
make new       # 销毁现有虚拟机,创建新的虚拟机
make ssh       # 将虚拟机 SSH 配置写入 ~/.ssh/(创建后必须执行)
make dns       # 将虚拟机 DNS 记录写入 /etc/hosts(可选)
make start     # 启动虚拟机并配置 SSH(up + ssh)
make up        # 使用 vagrant up 启动虚拟机
make halt      # 关闭虚拟机(别名:down, dw)
make clean     # 销毁虚拟机(别名:del, destroy)
make status    # 显示虚拟机状态(别名:st)
make pause     # 暂停虚拟机(别名:suspend)
make resume    # 恢复虚拟机
make nuke      # 使用 virsh 销毁所有虚拟机和卷(仅 libvirt)
make info      # 显示 libvirt 信息(虚拟机、网络、存储卷)

SSH 密钥

Pigsty Vagrant 模板默认使用您的 ~/.ssh/id_rsa[.pub] 作为虚拟机的 SSH 密钥。

在开始之前,请确保您有一个有效的 SSH 密钥对。如果没有,可以使用以下命令生成:

ssh-keygen -t rsa -b 2048 -N '' -f ~/.ssh/id_rsa -q

支持的镜像

标准 EL、Debian、Ubuntu、AlmaLinux 镜像矩阵使用 Vagrant Cloud 上的 cloud-image/* Box;显式的 RHEL / Oracle Linux 直连别名使用 generic/* Box。当前配置脚本对 VirtualBox、libvirt 以及 amd64arm64 使用同一套 cloud-image/* 名称映射;具体 Box 载荷是否可用仍由 Vagrant Cloud 在运行时解析。

VirtualBox 与 libvirt 使用同一套映射。vagrant/config 会为所有受支持的 cloud-image/* 镜像写入下表中的已验证版本,以保证 amd64 与 arm64 环境可复现:

系统 Vagrant Box 源码版本策略
Rocky 8 cloud-image/rocky-8 8.10.20240528.0
Rocky 9 cloud-image/rocky-9 9.8.20260525.0
Rocky 10 cloud-image/rocky-10 10.2.20260525.0
Debian 12 cloud-image/debian-12 20260806.2562.0
Debian 13 cloud-image/debian-13 20260810.2566.0
Ubuntu 22.04 cloud-image/ubuntu-22.04 20260810.0.0
Ubuntu 24.04 cloud-image/ubuntu-24.04 20260801.0.0
Ubuntu 26.04 cloud-image/ubuntu-26.04 20260731.0.0
AlmaLinux 8 cloud-image/almalinux-8 8.10.20260803
AlmaLinux 9 cloud-image/almalinux-9 9.8.20260810
AlmaLinux 10 cloud-image/almalinux-10 10.2.20260526.0

已停止支持但仍保留显式别名的 Debian 11 与 Ubuntu 20.04 也分别固定为 20260618.2513.020250624.0.0generic/* 的 RHEL、Oracle Linux 与 CentOS 7 兼容实验镜像固定为其最后发布的 4.3.12。这些旧镜像不属于当前支持矩阵。


环境变量

您可以使用以下环境变量来控制 Vagrant 行为:

export VM_SPEC='meta'              # 规格名称
export VM_IMAGE='cloud-image/rocky-9' # 镜像名称
export VM_SCALE='1'                # 资源缩放倍数
export VM_PROVIDER='virtualbox'    # 虚拟化提供商
export VAGRANT_EXPERIMENTAL=disks  # 直接运行 vagrant 时启用磁盘功能;Makefile 已自动设置

注意事项

VirtualBox 网络配置

使用较旧版本的 VirtualBox 作为 Vagrant 提供商时,需要额外配置才能使用 10.x.x.x CIDR 作为 Host-Only 网络:

echo "* 10.0.0.0/8" | sudo tee -a /etc/vbox/networks.conf
第一次下载镜像较慢

第一次使用 Vagrant 启动特定操作系统时,会下载相应的 Box 镜像文件(通常 1-2 GB)。下载完成后,镜像会被缓存,后续创建虚拟机时会直接复用。

libvirt 提供商

如果您使用 libvirt 作为提供商,可以使用 make info 查看虚拟机、网络和存储卷,使用 make nuke 强制销毁所有相关资源。

2.7 - Terraform

使用 Terraform 在公有云上创建虚拟机环境

Terraform 是一个流行的"基础设施即代码"工具,您可以使用它在公有云上一键创建虚拟机。

Pigsty 当前提供阿里云、AWS(全球与中国区)、Azure、GCP、腾讯云、Hetzner、Vultr、DigitalOcean 与 Linode 的 Terraform 示例模板;其中 aliyun-s3.tf 还会为 S3/pgBackRest 场景创建私有 OSS Bucket 与专用 RAM 读写凭据。


快速开始

安装 Terraform

在 macOS 上,您可以使用 Homebrew 安装 Terraform:

brew install terraform

其他平台请参考 Terraform 官方安装指南

初始化与应用

进入 Terraform 目录,选择模板,初始化提供商插件,然后应用配置:

cd ~/pigsty/terraform
cp spec/aliyun.tf terraform.tf         # 选择模板
terraform init                         # 安装云提供商插件(首次使用时)
terraform apply                        # 生成执行计划并创建资源

运行 apply 命令后,按提示输入 yes 确认,Terraform 将为您创建虚拟机及相关云资源。

获取 IP 地址

创建完成后,打印管理节点的公网 IP 地址:

terraform output -raw meta_ip

配置 SSH 访问

全球云模板通常同时提供可直接执行的 ssh_command 输出:

terraform output -raw ssh_command

仓库中的 ./ssh 是面向旧式“全部输出都是 IP、root 密码为 PigstyDemo4”模板的兼容脚本:它会遍历 每一个 Terraform 输出,将其当作 IP 写入 ~/.ssh/pigsty_config,再用 sshpass 分发密钥。因此它适用于 aliyun.tfaliyun-full.tfaliyun-oss.tfaliyun-pro.tf 这类兼容模板;不要对包含 ssh_command、私网 IP 或访问密钥输出的现代模板运行它。

使用兼容脚本时:

./ssh       # 写入 SSH 配置并分发密钥
ssh meta    # 使用主机名而非 IP 登录
使用 SSH 配置文件

如果您希望使用 ~/.ssh/pigsty_config 中的配置,请确保在 ~/.ssh/config 中包含以下内容:

Include ~/.ssh/pigsty_config

销毁资源

测试完成后,可以一键销毁所有创建的云资源:

terraform destroy

模板规格

Pigsty 在 terraform/spec/ 目录下提供了多种预定义的云资源模板:

模板文件 云厂商 说明
aliyun.tf 阿里云 单节点元节点模板,支持所有发行版和 AMD/ARM(默认)
aliyun-s3.tf 阿里云 单节点 + 私有 OSS Bucket 与 RAM 读写凭据,供 S3/pgBackRest 使用
aliyun-full.tf 阿里云 4 节点沙箱模板,支持所有发行版和 AMD/ARM
aliyun-oss.tf 阿里云 6 节点构建模板,支持所有发行版和 AMD/ARM
aliyun-pro.tf 阿里云 7 节点多发行版测试模板,用于跨操作系统测试
aws.tf AWS AWS 全球区域单节点,Debian 12/13,AMD/ARM
aws-cn.tf AWS AWS 中国区旧式单节点环境
azure.tf Azure Azure 单节点,Debian 12/13,AMD/ARM
gcp.tf GCP GCP 单节点,Debian 12/13,AMD/ARM
qcloud.tf 腾讯云 腾讯云单节点环境
hetzner.tf Hetzner 单节点,Debian 12/13,AMD/ARM
vultr.tf Vultr 单节点,Debian 12/13,当前仅 AMD
digitalocean.tf DigitalOcean 单节点,Debian 12/13,当前仅 AMD
linode.tf Linode 单节点,Debian 12/13,当前仅 AMD

使用模板时,将模板文件复制为 terraform.tf

cd ~/pigsty/terraform
cp spec/aliyun-full.tf terraform.tf   # 使用阿里云 4 节点沙箱模板
terraform init && terraform apply

变量配置

各模板的变量并不完全相同。阿里云模板支持完整的多发行版矩阵,默认 u26;AWS 全球、Azure、GCP、腾讯云与 Hetzner 支持 Debian 12/13 并可选 AMD/ARM,默认 d12/amd64;Vultr、DigitalOcean 与 Linode 当前只提供 AMD 实例选择。

架构与发行版

variable "architecture" {
  description = "架构类型 (amd64 或 arm64)"
  type        = string
  default     = "amd64"    # 注释此行以使用 arm64
  #default     = "arm64"   # 取消注释以使用 arm64
}

variable "distro" {
  description = "发行版代码(具体集合由模板决定)"
  type        = string
  default     = "d12"       # 全球云模板通常默认 Debian 12;阿里云模板默认 u26
}

资源配置

阿里云模板可在 locals 块中配置以下资源参数;其他云模板使用各自提供商的实例、磁盘与网络变量或本地值,请以所选 .tf 文件为准:

locals {
  bandwidth        = 100                    # 公网带宽 (Mbps)
  disk_size        = 40                     # 系统盘大小 (GB)
  spot_policy      = "SpotWithPriceLimit"   # 竞价策略:NoSpot, SpotWithPriceLimit, SpotAsPriceGo
  spot_price_limit = 5                      # 最高竞价价格 (仅在 SpotWithPriceLimit 时有效)
}

阿里云配置

凭证设置

将您的阿里云凭证添加到环境变量中,例如在 ~/.bash_profile~/.zshrc 中:

export ALICLOUD_ACCESS_KEY="<your_access_key>"
export ALICLOUD_SECRET_KEY="<your_secret_key>"
export ALICLOUD_REGION="cn-shanghai"

支持的镜像

以下是阿里云中常用的 ECS 公共操作系统镜像 前缀:

当前推荐并验证的基线为 Rocky Linux 9.8 / 10.2、Debian 12.15 / 13.6,以及 Ubuntu 22.04.5 / 24.04.4 / 26.04.0。

发行版 代码 x86_64 镜像前缀 aarch64 镜像前缀
CentOS 7.9 el7 centos_7_9_x64 -
Rocky 8.10 el8 rockylinux_8_10_x64 rockylinux_8_10_arm64
Rocky 9.8 el9 rockylinux_9_8_x64 rockylinux_9_8_arm64
Rocky 10.2 el10 rockylinux_10_2_x64 rockylinux_10_2_arm64
Debian 11.11 d11 debian_11_11_x64 -
Debian 12.15 d12 debian_12_15_x64 debian_12_15_arm64
Debian 13.6 d13 debian_13_6_x64 debian_13_6_arm64
Ubuntu 22.04.5 LTS u22 ubuntu_22_04_x64_20G ubuntu_22_04_arm64_20G
Ubuntu 24.04.4 LTS u24 ubuntu_24_04_x64_20G ubuntu_24_04_arm64_20G
Ubuntu 26.04.0 LTS u26 ubuntu_26_04_x64_20G ubuntu_26_04_arm64_20G
Anolis 8.10 an8 anolisos_8_10_x64 anolisos_8_10_arm64
Alibaba Cloud Linux 3 al3 aliyun_3_x64_20G_alibase_[0-9]+ aliyun_3_arm64_20G_alibase_[0-9]+

OSS 存储配置

aliyun-s3.tf 模板会额外创建 OSS 存储桶及相关权限,用于 PostgreSQL 的 PITR 备份:

  • OSS Bucket:创建名为 pigsty-oss 的私有存储桶
  • RAM 用户:创建专用的 pigsty-oss-user 用户
  • 访问密钥:生成 AccessKey 并保存到 ~/pigsty.sk
  • RAM 策略:面向读写场景,为该用户授予存储桶及桶内对象的 oss:* 权限

AWS 配置

凭证设置

全球与中国区模板都可以读取标准 AWS 环境变量或凭证文件:

export AWS_ACCESS_KEY_ID="<your_access_key>"
export AWS_SECRET_ACCESS_KEY="<your_secret_key>"
export AWS_REGION="us-west-2"

# ~/.aws/config
[default]
region = us-west-2

# ~/.aws/credentials
[default]
aws_access_key_id = <YOUR_AWS_ACCESS_KEY>
aws_secret_access_key = <AWS_ACCESS_SECRET>

aws.tf 默认读取 ~/.ssh/id_rsa.pub;旧式中国区 aws-cn.tf 则读取以下专用公钥:

~/.aws/pigsty-key.pub
AWS 模板需要调整

aws.tf 使用 Debian 官方 AMI 的滚动查询;aws-cn.tf 使用中国区硬编码 AMI 与 ~/.aws/pigsty-key.pub,部署前应核对目标区域、AMI 与密钥。


腾讯云配置

凭证设置

将腾讯云凭证添加到环境变量中:

export TENCENTCLOUD_SECRET_ID="<your_secret_id>"
export TENCENTCLOUD_SECRET_KEY="<your_secret_key>"
export TENCENTCLOUD_REGION="ap-beijing"
腾讯云模板需要调整

腾讯云模板是社区贡献的示例,可能需要根据您的具体需求进行调整。

其他云凭证

# Azure:推荐先 az login;服务主体方式使用以下四项
export ARM_CLIENT_ID="<client_id>"
export ARM_CLIENT_SECRET="<client_secret>"
export ARM_SUBSCRIPTION_ID="<subscription_id>"
export ARM_TENANT_ID="<tenant_id>"

# GCP:也可使用 gcloud auth application-default login
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"

# Hetzner / Vultr / DigitalOcean / Linode
export HCLOUD_TOKEN="<api_token>"
export VULTR_API_KEY="<api_key>"
export DIGITALOCEAN_TOKEN="<api_token>"
export LINODE_TOKEN="<api_token>"

GCP 模板还要求提供 project 变量,例如 terraform apply -var="project=my-project"。除 AWS 中国区外,使用密钥认证的当前模板默认读取 ~/.ssh/id_rsa.pub;如需其他公钥路径,请直接修改所选模板。


快捷命令

Pigsty 提供了一些 Makefile 快捷命令用于 Terraform 操作:

cd ~/pigsty/terraform

make u          # terraform apply -auto-approve + 运行旧式 ./ssh(仅兼容模板)
make d          # terraform destroy -auto-approve
make apply      # terraform apply(交互式确认)
make destroy    # terraform destroy(交互式确认)
make out        # terraform output
make ssh        # 运行 ssh 脚本配置 SSH 访问
make r          # 重置 terraform.tf 到版本库状态

对于带有 ssh_command、私网 IP 或其他非 IP 输出的现代模板,请直接运行 terraform apply,不要使用会随后调用旧式 ./sshmake u


注意事项

云资源费用

使用 Terraform 创建的云资源会产生费用。测试完成后,请及时使用 terraform destroy 销毁资源,避免不必要的开支。

建议使用按量付费的实例类型进行测试。模板默认使用竞价实例(Spot Instance)以降低成本。

默认密码

阿里云模板与腾讯云模板默认设置 root 密码 PigstyDemo4;Linode 因密码复杂度要求使用 PigstyDemo4!。 AWS、Azure、GCP、Hetzner、Vultr 与 DigitalOcean 的当前模板主要使用 SSH 公钥认证,并没有统一的默认 root 密码。示例密码只能用于临时测试,生产环境必须更换或禁用密码登录。

安全组配置

这些模板面向演示/开发,当前安全组或云防火墙会从 0.0.0.0/0(部分同时含 ::/0)开放全部或近乎全部入站流量,而不只是 Pigsty 必需端口。 部署前应先限制来源网段与端口;不要原样用于生产环境。

SSH 访问

创建完成后,使用以下命令 SSH 登录到管理节点:

ssh root@<public_ip>

兼容旧式输出与密码约定的阿里云模板还可以使用 ./sshmake ssh 写入 SSH 别名;其他模板请使用其 ssh_command 输出。

2.8 - 安全考量

Pigsty 生产部署中的凭据、网络、认证、加密、数据保护与审计检查。

Pigsty 默认配置面向受信内网中的开发、测试和演示。生产部署需要根据实际威胁模型完成凭据、网络、认证、证书、备份和审计配置。

安全机制及其边界见 安全与合规,可执行检查项见 合规实践ha/safe 是加固配置示例,不替代逐项审查。


机密性

重要文件

重点保护以下资产:

  • pigsty.yml 与其他 inventory:通常包含系统和业务凭据;
  • files/pki/ca/ca.key:可以签发受部署信任的证书;
  • 管理用户 SSH 私钥:默认可以在纳管节点上执行 sudo;
  • 客户端证书私钥与备份加密密钥;
  • 自动化过程中生成的 /pg/tmp/pg-user-*.sql

应限制管理节点和配置仓库访问,避免把完整配置或私钥提交到公开仓库。CA 私钥和恢复所需配置应进行受控备份。

密码

生产部署必须替换所有公开默认凭据。建议先使用:

./configure -g

该选项不会替换 pgBackRest cipher_passha/safe 中的全部 Silo 示例凭据,也不会处理用户自定义值。应按照 默认凭据 复核生成结果。

PostgreSQL 默认使用 SCRAM-SHA-256 保存新设置或更新的口令。需要强制复杂度时,在 pg_libs 中预加载 passwordcheck,或配置 credcheck。账号有效期可以通过 expire_inexpire_at 声明。

凭据轮换还需要同步更新数据库用户、PgBouncer 用户列表、组件配置和使用方连接信息。执行前应准备回退方案。


网络边界

IP地址

PostgreSQL 默认监听 0.0.0.0。需要收敛监听地址时,可设置:

pg_listen: '${ip},${vip},${lo}'

监听地址不是唯一边界。生产环境应同时检查:

演示配置 pigsty.yml 会额外向公网放行 5432,生产环境通常应移除。需要直接连接数据库时,应限制到明确的业务网段。

网络流量

  • PostgreSQL 服务端默认启用 TLS,但内网 HBA 默认不强制 TLS;
  • PgBouncer TLS 默认关闭,由 pgbouncer_sslmode 控制;
  • Patroni REST API HTTPS 默认关闭,由 patroni_ssl_enabled 控制;
  • Nginx 与 MINIO 模块所选对象存储后端默认启用 HTTPS;etcd 客户端和对等通信使用 TLS。

HBA 的 auth: ssl 只要求加密连接。客户端还应使用 sslmode=verify-full 和可信 CA 验证数据库服务端,详见 加密通信

Grafana、VictoriaMetrics 等组件可能监听节点端口,默认防火墙不会将其直接开放到公网。对外访问应优先通过 Nginx,并限制管理页面的来源地址和身份。


身份认证与访问控制

  • 使用 HBA 明确用户、数据库、来源地址和认证方式,避免宽泛的 world 规则;
  • 为高权限远程用户使用 auth: cert,并建立客户端证书交付与吊销流程;
  • 通过 内置角色 分配业务权限,不向普通业务账号授予超级用户;
  • 为多业务共享集群设置 revokeconn: true,并检查实际数据库 ACL;
  • 使用声明的数据库属主或受控管理角色创建对象,确保默认权限生效;
  • 需要隔离离线查询时,显式为 dbrole_offline 的 HBA 规则设置 role: offline

变更 HBA、用户或角色后,应同时核对配置清单和数据库中的实际状态。


完整性

Pigsty 默认启用页级数据校验和,用于发现写入后发生的页面损坏。校验和不能检测所有内存错误、逻辑错误和应用写入错误。

CRIT 模板 启用 Patroni 严格同步模式和更详细的连接日志。同步模式以不丢失已确认事务为目标,但依赖 synchronous_commit、同步副本状态和故障切换条件;没有同步副本时会阻塞写入。

watchdog 在 CRIT 中配置为 automatic,只有系统存在可用 watchdog 设备时才会启用。是否需要 required 模式应结合硬件和可用性要求评估。


可用性

  • 关键集群通常应至少部署三个实例,并把实例分散到独立故障域;
  • 使用 HAProxy、VIP 或 DNS 服务名接入,避免客户端绑定固定主库地址;
  • etcd 应使用奇数节点,并分散到独立故障域;
  • INFRA、DNS、监控和软件仓库也应根据可用性要求消除单点;
  • 使用 pg_rpopg_rto 时,应理解其配置含义并通过演练验证目标。

副本只解决部分节点故障,不能替代备份。


备份与恢复

  • 本地 pgBackRest 仓库默认不加密,并与数据库主机共享故障域;
  • pgbackrest_method: minio 对象存储仓库默认启用 AES-256-CBC,但 cipher_pass: pgBackRest 是公开值,必须替换;
  • ha/safe 中的 pgBR.${pg_cluster} 也是示例值,不应作为最终密钥;
  • 重要备份应保存到独立故障域,并评估对象锁、版本控制或离线副本;
  • 定期执行全量恢复和 PITR 演练,验证 WAL、密钥、恢复时间和应用一致性。

具体机制见 数据安全时间点恢复;配置与操作见 PGSQL 备份恢复


审计与响应

默认 OLTP 模板记录 DDL、慢查询和 PostgreSQL 18 的连接授权事件;CRIT 模板进一步记录连接和断开事件。

pgaudit 需要安装、预加载并配置审计策略,单纯安装软件包不会产生 SQL 审计日志。启用 Vector 和 VictoriaLogs 后,还应根据要求调整日志保留周期、访问权限与归档方式。

指标、日志和告警只提供事件输入。生产环境还需建立告警分级、值班、事件判定、响应、取证和复盘流程。


主机与软件供应链

  • 根据兼容性验证结果将 SELinux 从默认 permissive 调整为 enforcing
  • 禁用不需要的 SSH 口令和 root 远程登录,并考虑堡垒机或多因素认证;
  • 审查管理用户和数据库系统用户的 sudo 范围;
  • 及时升级受支持的 Pigsty 和上游组件版本;
  • 核对软件仓库 GPG 公钥指纹,并按需要启用逐包签名验证。

供应链与漏洞响应说明见 合规实践

3 - 概念

理解 Pigsty 的核心概念、架构设计与设计理念,掌握高可用、备份恢复、安全合规等关键能力。

Pigsty 是一个可移植、可扩展的开源 PostgreSQL 发行版,用于在本地环境中构建生产级数据库服务,方便进行声明式配置和自动化。它拥有庞大的生态系统,提供了一整套工具、脚本和最佳实践,让 PostgreSQL 真正达到企业级 RDS 的服务水准。

Pigsty 名字源自 PostgreSQL In Great STYle,也可理解为 Postgres,Infras,Graphics,Service,Toolbox,it’s all Yours —— 属于您的 PostgreSQL 图形化自建工具箱。您可以在 GitHub 上找到源代码,访问 官方文档 了解更多信息,或在 在线演示 中体验 Web 界面

pigsty-banner


为什么需要 Pigsty,它能做什么?

PostgreSQL 是一个足够完美的数据库内核,但它需要更多工具与系统的配合才能成为一个足够好的数据库服务。在生产环境中,您需要管理数据库的方方面面:高可用、备份恢复、监控告警、访问控制、参数调优、扩展安装、连接池化、负载均衡……

如果这些复杂的运维工作都能自动化处理,是不是会更容易一些?这正是 Pigsty 诞生的原因。

Pigsty 为您提供:

  • 开箱即用的 PostgreSQL 发行版

    Pigsty 整合了 PostgreSQL 生态中的 575 个扩展插件,提供开箱即用的分布式、时序、地理、空间、图、向量、搜索等多模态数据库能力。从内核到 RDS 发行版,在 EL/Debian/Ubuntu 下提供 14 - 18 版本的生产级数据库服务。

  • 故障自愈的高可用架构

    基于 Patroni、Etcd 和 HAProxy 打造的 高可用架构,让硬件故障自动切换,流量无缝衔接。主库故障恢复时间 RTO < 45s,数据恢复点 RPO ≈ 0。您可以在无需应用配合的情况下滚动维护升级整个集群。

  • 完整的时间点恢复能力

    基于 pgBackRest 与可选的 Silo 对象存储集群,提供开箱即用的 PITR 时间点恢复 能力。让您可以回到恢复窗口内的任意时间点,为软件缺陷与人为删库兜底。

  • 灵活的服务接入与流量管理

    通过 HAProxy、Pgbouncer、VIP 提供灵活的 服务接入 模式,实现读写分离、连接池化、自动路由。交付稳定可靠、自动路由、事务池化的高性能数据库服务。

  • 惊艳的可观测性

    基于 Victoria 与 Grafana 的可观测性技术栈,提供无与伦比的 监控最佳实践。超过三千类监控指标描述系统的方方面面,从全局大盘到单个对象的增删改查都能一览无余。

  • 声明式的配置管理

    遵循 基础设施即代码 的理念,使用声明式配置描述整个环境。您只需告诉 Pigsty “想要什么样的数据库集群”,无需操心具体如何实现,系统会自动调整到期望状态。

  • 模块化的架构设计

    采用模块化 架构 设计,可自由组合以适应不同场景。除了核心的 PostgreSQL 模块外,还提供 Redis、MINIO(Silo)、Etcd 等可选模块,以及对多种 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、Silo 等周边组件,但核心始终是围绕 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 的基本概念,可以:

3.1 - 积木式架构

Pigsty 的模块化架构介绍 —— 声明式组合,按需定制,自由部署。

Pigsty 使用 模块化架构声明式接口,您可以像 搭积木一样自由按需组合模块


模块

Pigsty 采用模块化设计,有六个主要的默认模块:PGSQLINFRANODEETCDREDISMINIO

  • PGSQL:由 Patroni、Pgbouncer、HAproxy、PgBackrest 等驱动的自治高可用 Postgres 集群。
  • INFRA:本地软件仓库、Nginx、Grafana、Victoria、AlertManager、Blackbox Exporter 可观测性全家桶。
  • NODE:调整节点到所需状态、名称、时区、NTP、ssh、sudo、haproxy、docker、vector、keepalived
  • ETCD:分布式键值存储,用作高可用 Postgres 集群的 DCS:共识选主/配置管理/服务发现。
  • REDIS:Redis 服务器,支持独立主从、哨兵、集群模式,并带有完整的监控支持。
  • MINIO:与 S3 兼容的简单对象存储服务器,可作为 PG 数据库备份的可选目的地。

你可以声明式地自由组合它们。如果你想要主机监控,在基础设施节点上安装 INFRA 模块,并在纳管节点上安装 NODE 模块就足够了。 ETCDPGSQL 模块用于搭建高可用 PG 集群,将模块安装在多个节点上,可以自动形成一个高可用的数据库集群。 您可以复用 Pigsty 基础架构并开发自己的模块,REDISMINIO 可作为样例。像 PostgreSQL Mongo 模式 这样的协议兼容层,则通过标准 PGSQL 与 Docker APP 工作流组合实现。

请注意,所有模块都强依赖 NODE 模块:在 Pigsty 中节点必须先安装 NODE 模块,被 Pigsty 纳管后方可部署其他模块。 当节点(默认)使用本地软件源进行安装时,NODE 模块对 INFRA 模块有弱依赖。因此安装 INFRA 模块的管理节点/基础设施节点会在 deploy.yml 剧本中完成 Bootstrap 过程,解决循环依赖。

pigsty-sandbox


单机安装

默认情况下,Pigsty 将在单个 节点 (物理机/虚拟机) 上安装。deploy.yml 剧本将在 当前 节点上安装 INFRAETCDPGSQL 和可选的 MINIO 模块, 这将为你提供一个功能完备的可观测性技术栈全家桶(VictoriaMetrics、VictoriaLogs、VictoriaTraces、Grafana、Alertmanager、Blackbox Exporter 等),以及一个内置的 PostgreSQL 单机实例作为 CMDB,也可以开箱即用。(集群名 pg-meta,库名为 meta

这个节点现在会有完整的自我监控系统、可视化工具集,以及一个自动配置有 PITR 的 Postgres 数据库(HA 不可用,因为你只有一个节点)。你可以使用此节点作为开发箱、测试、运行演示以及进行数据可视化和分析。或者,还可以把这个节点当作管理节点,部署纳管更多的节点!

pigsty-arch


监控

安装的 单机元节点 可用作 管理节点监控中心,以将更多节点和数据库服务器置于其监视和控制之下。

Pigsty 的监控系统可以独立使用,如果你想安装 VictoriaMetrics / Grafana 可观测性全家桶,Pigsty 为你提供了最佳实践! 它为 主机节点PostgreSQL数据库 提供了丰富的仪表盘。 无论这些节点或 PostgreSQL 服务器是否由 Pigsty 管理,只需简单的配置,你就可以立即拥有生产级的监控和告警系统,并将现有的主机与 PostgreSQL 纳入监管。

pigsty-dashboard.jpg


高可用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 数据库集群。

pigsty-ha.png

硬件故障由 patroni、etcd 和 haproxy 提供的自愈高可用架构来兜底,在主库故障的情况下,默认会在 45 秒内执行自动故障转移(Failover)。 客户端无需修改配置重启应用:Haproxy 利用 patroni 健康检查进行流量分发,读写请求会自动分发到新的集群主库中,并避免脑裂的问题。 这一过程十分丝滑,例如在从库故障,或主动切换(switchover)的情况下,客户端只有一瞬间的当前查询闪断,

软件故障、人为错误和数据中心级灾难由 pgBackRest 和可选的 Silo 集群来兜底。这为您提供了本地/云端的 PITR 能力,并在数据中心失效的情况下提供跨地理区域复制与异地容灾功能。

3.1.1 - 节点

节点(node)是对硬件资源/操作系统的抽象,可以是物理机,裸金属、虚拟机、或者容器与 pods。

节点(node) 是对硬件资源/操作系统的抽象,可以是物理机,裸金属、虚拟机、或者容器与 pods。

只要装着 Linux 操作系统(以及 systemd 守护进程),能使用 CPU/内存/磁盘/网络 等标准资源,即可视作节点。

节点上可以安装 模块,Pigsty 中存在几种不同类型节点,主要区别就在于安装了不同的模块。

类型 说明
普通节点 被 Pigsty 管理的节点
ADMIN 节点 使用 Ansible 发出管理指令的节点
INFRA 节点 安装 INFRA 模块的基础设施节点
ETCD 节点 安装 ETCD 模块的分布式共识节点
MINIO 节点 安装 MINIO 模块的对象存储节点
PGSQL 节点 安装 PGSQL 模块的数据库节点
…… 安装了其他各类模块的节点……

单机部署 Pigsty 时,多者合而为一,当前节点将同时作为普通节点,管理节点、基础设施节点、ETCD 节点,以及数据库节点。


普通节点

使用 Pigsty 管理节点,可在其上安装模块。node.yml 剧本将调整节点至所需状态。 普通节点上可能会运行以下服务:

组件 端口 描述 状态
node_exporter 9100 节点监控指标导出器 ✅ 默认启用
haproxy 9101 HAProxy 负载均衡器(管理端口) ✅ 默认启用
vector 9598 日志收集代理 ✅ 默认启用
docker 9323 启用容器支持 ⚠️ 按需启用
keepalived n/a 管理节点集群 L2 VIP ⚠️ 按需启用
keepalived_exporter 9650 监控 Keepalived 状态 ⚠️ 按需启用

这里,node_exporter 会向监控系统暴露主机上的各类监控指标,vector 会向日志收集系统发送日志,haproxy 则提供负载均衡功能,对外暴露服务。 这三项服务默认开启。而 Dockerkeepalivedkeepalived_exporter 这三项服务作为可选项,可按需启用。


ADMIN节点

一套 Pigsty 部署中有且只有一个 管理节点,管理节点是执行 Ansible 剧本,发起控制/部署命令的节点。

该节点拥有对所有其他节点的 ssh/sudo 访问权限。管理节点的安全至关重要,应严格控制访问;其信任范围与关键资产参见 安全模型:信任边界

单机安装配置过程 中,当前安装节点就是管理节点。 但也有其他的可能,例如,如果你的笔记本可以 ssh 访问所有被管理节点,并且安装了 Ansible,那么在这种情况下, 您的笔记本电脑就可以作为一个管理节点 —— 尽管这对于生产环境来说不太合适。

例如,您使用自己的笔记本电脑,管理一台云端上部署了 Pigsty 的虚拟机,这时候,您的笔记本电脑就是管理节点。

在严肃的生产环境中,管理节点通常是 1-2 台 DBA 专用的 管控机。在资源受限的环境中,则通常会复用 INFRA节点 作为管理节点。 因为所有的 INFRA 节点上都默认安装了 Ansible,可以作为额外的备用的管理节点。


INFRA节点

一套 Pigsty 部署可能有 1 个或多个 INFRA 节点,大型生产环境可能有 2-3 个。

配置清单中的 infra 分组指定哪些节点是 INFRA 节点,这些节点上会部署 INFRA 模块,包含下列组件:

组件 端口 描述
nginx 80/443 Web 图形界面,本地软件仓库
grafana 3000 可视化平台
victoriaMetrics 8428 时序数据库(收存监控指标)
victoriaLogs 9428 日志收集服务器
victoriaTraces 10428 链路追踪收集服务器
vmalert 8880 告警与衍生指标计算规则
alertmanager 9059 告警聚合分发/屏蔽管理
blackbox_exporter 9115 黑盒探测,ping 节点 / vip
dnsmasq 53 内部 DNS 域名解析
chronyd 123 NTP 时间服务器
ansible - 执行剧本,发起管理

其中,Nginx 作为当前模块的入口,提供 Web 图形界面和本地软件仓库服务。 如果你部署多个 INFRA 节点,每个 Infra 节点上的服务是相互独立的。 但你确实可以从任意一个 Infra 节点上的 Grafana 访问所有的监控数据源。

Pigsty 使用 Apache-2.0 许可证开源,但请注意其中的 Grafana 组件使用 AGPLv3 许可证。


ETCD节点

ETCD 模块为 PostgreSQL 高可用提供分布式共识服务(DCS)。

配置清单 中的 etcd 分组指定哪些节点是 ETCD 节点,ETCD 节点上运行着 etcd 服务器,监听以下两个端口:

组件 端口 描述
etcd 2379 ETCD 分布式键值存储(客户端端口)
etcd 2380 ETCD 集群 Peer 通信端口

MINIO 节点

MINIO 模块为 PostgreSQL 提供可选的 Silo 备份存储仓库

配置清单中的 minio 分组指定哪些节点是 MINIO 模块节点;v4.5.0 会在这些节点上运行 Silo 服务器,监听以下端口:

组件 端口 描述
silo 9000 S3 API 服务端口
silo 9001 Silo 管理控制台端口

PGSQL节点

安装了 PGSQL 模块的节点被称为 PGSQL 节点。节点与 PostgreSQL 实例为 1:1 部署,也就是每个节点上只运行一个 PG 实例。

PGSQL 节点可从相应 PostgreSQL 实例借用 身份 —— 由 node_id_from_pg 控制,默认为 true,即节点名会被设置为 PG 实例名。

PGSQL 节点在 普通节点 的基础上,还会额外运行以下组件:

组件 端口 描述 状态
postgres 5432 PostgreSQL 数据库服务器 ✅ 默认启用
pgbouncer 6432 Pgbouncer 连接池 ✅ 默认启用
patroni 8008 Patroni 高可用管理组件 ✅ 默认启用
pg_exporter 9630 Postgres 监控指标导出器 ✅ 默认启用
pgbouncer_exporter 9631 PGBouncer 监控指标导出器 ✅ 默认启用
pgbackrest_exporter 9854 Pgbackrest 监控指标导出器 ✅ 默认启用
vip-manager n/a 将 L2 VIP 绑定在集群主库节点上 ⚠️ 按需启用
{{ pg_cluster }}-primary 5433 通过 haproxy 对外暴露数据库服务:主连接池:读/写服务 ✅ 默认启用
{{ pg_cluster }}-replica 5434 通过 haproxy 对外暴露数据库服务:副本连接池:只读服务 ✅ 默认启用
{{ pg_cluster }}-default 5436 通过 haproxy 对外暴露数据库服务:主直连服务 ✅ 默认启用
{{ pg_cluster }}-offline 5438 通过 haproxy 对外暴露数据库服务:离线直连:离线读服务 ✅ 默认启用
{{ pg_cluster }}-<service> 543x 通过 haproxy 对外暴露数据库服务:PostgreSQL 定制服务 ⚠️按需定制

其中,vip-manager 只有当用户配置了 PG VIP 时才会启用。 在 pg_services 中可以定义更多的 自定义服务,这些服务会被 haproxy 对外暴露,并使用更多的服务端口。

3.1.2 - INFRA 架构

Pigsty 中基础设施模块的架构,组件与功能详解。

运行生产级别高可用 PostgreSQL 集群,通常需要一套完善的基础设施服务(底座)来支撑,例如监控告警、日志收集、时间同步、DNS 解析,本地软件仓库等。 Pigsty 提供了 INFRA 模块 来解决这个问题 —— 这是一个 可选模块,但我们强烈推荐启用它。


概览

下图是 单机部署 时的架构示意图,图中右半部分即为 INFRA 模块 所包含的组件,其中包括:

组件 种类 描述
Nginx Web 服务器 Web 界面 的统一入口,本地软件仓库,内部服务的反向代理
Repo 软件仓库 APT / DNF 仓库,下载有所有部署需要的 RPM/DEB 包及其依赖
Grafana 可视化平台 呈现监控指标、日志与链路追踪,承载监控大屏、巡检报表以及自定义数据应用。
VictoriaMetrics 时序数据库 拉取全部监控指标,兼容 Prometheus API,并通过 VMUI 提供查询界面。
VictoriaLogs 日志平台 集中收集存储日志,所有节点默认运行 Vector,将系统日志与数据库日志推送到此。
VictoriaTraces 链路追踪 收集慢 SQL、服务链路等追踪数据。
VMAlert 告警计算 评估告警规则,将事件推送至 Alertmanager。
AlertManager 告警管理 聚合告警事件,分发告警通知,支持邮件、Webhook 等渠道。
BlackboxExporter 黑盒探测 探测各个 IP/VIP/URL 的可达性。
DNSMASQ DNS 解析 提供 DNS 解析服务,解析 Pigsty 内部使用到的域名。【可选】
Chronyd 时间同步 提供 NTP 时间同步服务,确保所有节点时间一致。 【可选】
CA 证书签发 签发环境内的加密证书
Ansible 发起管理 批量,声明式,无 Agent 管理大量服务器的工具

pigsty-arch


Nginx

Nginx 是 Pigsty 所有 WebUI 类服务的访问入口,默认使用 80 / 443 端口对外提供 HTTP / HTTPS 服务。在线演示

IP 访问(替换) 域名(HTTP) 域名(HTTPS) 公开演示
http://10.10.10.10 http://i.pigsty https://i.pigsty https://demo.pigsty.cc

带有 WebUI 的基础设施组件可以通过 Nginx 统一对外暴露服务,例如 GrafanaVictoriaMetrics(VMUI)、AlertManager, 以及 HAProxy 控制台,此外,本地软件仓库 等静态文件资源也通过 Nginx 对内外提供服务。

Nginx 会根据 infra_portal 中的定义,配置本地 Web 服务器或反向代理服务器。

infra_portal:
  home : { domain: i.pigsty }

默认情况下将对外暴露 Pigsty 的管理首页:i.pigsty,上面不同的端点挂载代理了不同的组件:

端点 组件 原生端口 备注 公开演示
/ Nginx 80/443 首页、本地仓库、文件服务 demo.pigsty.cc/zh/
/ui/ Grafana 3000 Grafana 仪表盘入口 demo.pigsty.cc/ui/
/vmetrics/ VictoriaMetrics 8428 时序数据库 Web UI demo.pigsty.cc/vmetrics/
/vlogs/ VictoriaLogs 9428 日志数据库 Web UI demo.pigsty.cc/vlogs/
/vtraces/ VictoriaTraces 10428 链路追踪 Web UI demo.pigsty.cc/vtraces/
/vmalert/ VMAlert 8880 告警规则管理 demo.pigsty.cc/vmalert/
/alertmgr/ AlertManager 9059 告警管理 Web UI demo.pigsty.cc/alertmgr/
/blackbox/ Blackbox 9115 黑盒探测器

Pigsty 在线演示首页

Pigsty 允许对 Nginx 进行丰富的定制,将其作为本地文件服务器,或者反向代理服务器,配置自签名或者真正的 HTTPS 证书。

更多信息,请参阅:教程:Nginx:向外代理暴露Web服务教程:Certbot:申请与更新HTTPS证书


Repo

Pigsty 会在安装时,默认在 Infra 节点上创建一个 本地软件仓库,以加速后续软件安装。在线演示

该软件仓库默认位于 /www/pigsty 目录, 由 Nginx 对外提供服务,挂载在 /pigsty 路径上:

IP 访问(替换) 域名(HTTP) 域名(HTTPS) 公开演示
http://10.10.10.10/pigsty http://i.pigsty/pigsty https://i.pigsty/pigsty https://demo.pigsty.cc/pigsty

Pigsty 支持 离线安装,实质上是将做好的本地软件仓库提前复制到目标环境中。 当 Pigsty 执行部署并发现 /www/pigsty/repo_complete 时,会跳过上游下载并直接使用已有仓库。 当前源码由 sow 生成该文件,它既是完成标记也是仓库内容的 SHA-256 清单;需要强制重建时使用 ./infra.yml -t repo_build -e repo_build=true

repo

更多信息,请参阅:配置:INFRA - REPO


Grafana

Grafana 是 Pigsty 监控系统的核心组件,用于可视化展示监控指标、日志与各种信息。在线演示

Grafana 默认监听 3000 端口,挂载于 Nginx /ui 路径点上代理访问:

IP 访问(替换) 域名(HTTP) 域名(HTTPS) 公开演示
http://10.10.10.10/ui http://i.pigsty/ui https://i.pigsty/ui https://demo.pigsty.cc/ui

Pigsty 预置了基于 VictoriaMetrics / Logs / Traces 的大量监控面板,并通过 URL 跳转实现一键下钻上卷,帮助快速定位故障。

Grafana 亦可作为低代码可视化平台使用,因此默认安装 ECharts、victoriametrics-datasource、victorialogs-datasource 等插件, 同时将 Vector / Victoria 数据源统一注册为 vmetrics-*vlogs-*vtraces-*,方便扩展自定义仪表板。

dashboard

更多信息请参阅:配置:INFRA - GRAFANA


VictoriaMetrics

VictoriaMetrics 是 Pigsty 的时序数据库,负责拉取并存储所有监控指标。在线演示

默认监听 8428 端口,挂载于 Nginx /vmetrics 路径上,亦可通过 p.pigsty 域名直接访问:

IP 访问(替换) 域名(HTTP) 域名(HTTPS) 公开演示
http://10.10.10.10/vmetrics http://p.pigsty https://i.pigsty/vmetrics https://demo.pigsty.cc/vmetrics

VictoriaMetrics 完全兼容 Prometheus API,支持 PromQL 查询、远程读写协议以及 Alertmanager API。 内置的 VMUI 提供即席查询界面,可直接探索指标数据,也可作为 Grafana 的数据源使用。

vmetrics

更多信息请参阅:配置:INFRA - VMETRICS


VictoriaLogs

VictoriaLogs 是 Pigsty 的日志平台,集中存储来自所有节点的结构化日志。在线演示

默认监听 9428 端口,挂载于 Nginx /vlogs 路径上:

IP 访问(替换) 域名(HTTP) 域名(HTTPS) 公开演示
http://10.10.10.10/vlogs http://i.pigsty/vlogs https://i.pigsty/vlogs https://demo.pigsty.cc/vlogs

所有纳管节点默认运行 Vector Agent,负责收集系统日志、PostgreSQL 日志、Patroni 日志、Pgbouncer 日志等,结构化处理后推送至 VictoriaLogs。 内置 Web UI 支持日志检索与过滤,也可配合 Grafana 的 victorialogs-datasource 插件进行可视化分析。

vlogs

更多信息请参阅:配置:INFRA - VLOGS


VictoriaTraces

VictoriaTraces 用于收集链路追踪数据与慢 SQL 记录。在线演示

默认监听 10428 端口,挂载于 Nginx /vtraces 路径上:

IP 访问(替换) 域名(HTTP) 域名(HTTPS) 公开演示
http://10.10.10.10/vtraces http://i.pigsty/vtraces https://i.pigsty/vtraces https://demo.pigsty.cc/vtraces

VictoriaTraces 提供 Jaeger 兼容接口,可用于分析服务调用链路与数据库慢查询。 结合 Grafana 面板,能够快速定位性能瓶颈,追溯问题根因。

更多信息请参阅:配置:INFRA - VTRACES


VMAlert

VMAlert 是告警规则计算引擎,负责评估告警规则并将触发的事件推送至 Alertmanager在线演示

默认监听 8880 端口,挂载于 Nginx /vmalert 路径上:

IP 访问(替换) 域名(HTTP) 域名(HTTPS) 公开演示
http://10.10.10.10/vmalert http://i.pigsty/vmalert https://i.pigsty/vmalert https://demo.pigsty.cc/vmalert

VMAlertVictoriaMetrics 读取指标数据,周期性执行告警规则评估。 Pigsty 预置了 PGSQL、NODE、REDIS 等模块的告警规则,覆盖常见故障场景,开箱即用。

vmalert

更多信息请参阅:配置:INFRA - VMALERT


AlertManager

AlertManager 负责告警事件的聚合、去重、分组与分发。在线演示

默认监听 9059 端口,挂载于 Nginx /alertmgr 路径上,亦可通过 a.pigsty 域名直接访问:

IP 访问(替换) 域名(HTTP) 域名(HTTPS) 公开演示
http://10.10.10.10/alertmgr http://a.pigsty https://i.pigsty/alertmgr https://demo.pigsty.cc/alertmgr

AlertManager 支持多种通知渠道:邮件、Webhook、Slack、PagerDuty、企业微信等。 通过配置告警路由规则,可实现按严重程度、模块类型进行差异化分发,支持静默、抑制等高级功能。

alertmanager

更多信息请参阅:配置:INFRA - AlertManager


BlackboxExporter

Blackbox Exporter 用于主动探测目标的可达性,实现黑盒监控。

默认监听 9115 端口,挂载于 Nginx /blackbox 路径上:

IP 访问(替换) 域名(HTTP) 域名(HTTPS) 公开演示
http://10.10.10.10/blackbox http://i.pigsty/blackbox https://i.pigsty/blackbox https://demo.pigsty.cc/blackbox

支持 ICMP Ping、TCP 端口、HTTP/HTTPS 端点等多种探测方式。 可用于监控 VIP 可达性、服务端口存活、外部依赖健康状态等场景,是判断故障影响范围的重要手段。

blackbox

更多信息请参阅:配置:INFRA - BLACKBOX


Ansible

Ansible 是 Pigsty 的核心编排工具,所有部署、配置、管理操作均通过 Ansible Playbook 完成。

Pigsty 在安装时会自动在管理节点(Infra 节点)上安装 Ansible。 它采用声明式配置风格与幂等剧本设计:同一剧本可重复执行,系统会自动收敛至期望状态,无需担心副作用。

Ansible 的核心优势:

  • 无 Agent:通过 SSH 远程执行,无需在目标节点安装额外软件。
  • 声明式:描述期望状态,而非执行步骤,配置即文档。
  • 幂等性:多次执行结果一致,支持部分失败后重试。

更多信息请参阅:剧本:Pigsty Playbook


DNSMASQ

DNSMASQINFRA节点 上提供环境内的 DNS 解析服务,将域名解析到对应 IP 地址。

DNSMASQ 默认监听 53 端口(UDP/TCP),为环境内所有节点提供 DNS 解析服务,解析记录位于 /etc/dnsmasq.d/pigsty 目录中。

其他模块在部署时会自动将域名注册到 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.ymldeploy 剧本中, 采用了一种 “交织部署” 的技术:

  • 首先初始化所有 普通节点 上的 NODE模块,但是不配置监控,因为基础设施服务尚未部署完成。
  • 然后初始化 INFRA节点 上的 INFRA模块,此时监控已经可用
  • 然后回过头来,重新配置所有 普通节点 上的监控功能,连接到已经部署完成的监控平台

如果您不追求 “一次性” 部署所有节点,也可以采用 分阶段部署 的方式,先初始化 INFRA 节点,然后再初始化其他普通节点即可。

节点与基础设施是如何耦合的?

普通节点会通过 admin_ip 参数来引用某个 INFRA节点 作为它们的基础设施提供者。

例如,当你配置了全局的 admin_ip = 10.10.10.10,那么通常意味着所有节点都会使用这个 IP 上的基础设施服务。

这样的设计允许你快速,批量的切换节点的基础设施提供者 —— 以下是 可能 引用 ${admin_ip} 的配置参数列表:

参数 模块 默认值 说明
repo_endpoint INFRA http://${admin_ip}:80 软件仓库访问地址
repo_upstream.baseurl INFRA http://${admin_ip}/pigsty 本地软件源 baseurl
infra_portal.endpoint INFRA ${admin_ip}:<port> Nginx 反向代理后端地址
dns_records INFRA ["${admin_ip} i.pigsty", ...] DNS 解析记录
node_default_etc_hosts NODE ["${admin_ip} i.pigsty"] 默认静态 DNS 记录
node_etc_hosts NODE [] 自定义静态 DNS 记录
node_dns_servers NODE ["${admin_ip}"] 动态 DNS 服务器地址
node_ntp_servers NODE ["pool pool.ntp.org iburst"] NTP 时间服务器(可选)

例如,当节点安装软件的时候,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.5.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 高可用

INFRA Overview 仪表盘

3.1.3 - PGSQL 架构

PostgreSQL 模块的组件交互与数据流。

PGSQL 模块在生产环境中以 集群 的形式组织,这些 集群 是由一组通过 主-备 关联的数据库 实例 组成的 逻辑实体


概览

PGSQL 模块 包含下列组件,协同提供生产级 PostgreSQL 高可用集群服务:

组件 简介 描述
postgres 数据库 世界上最先进的开源关系型数据库,PGSQL 模块的核心。
patroni 高可用 托管 PostgreSQL 进程,协调故障转移、选主、配置变更。
pgbouncer 连接池 轻量级连接池中间件,复用连接、降低开销、提供额外灵活性。
pgbackrest 备份恢复 全量/增量备份与 WAL 归档,支持本地与对象存储。
pg_exporter 指标导出 导出 PostgreSQL 监控指标,以 Prometheus 兼容格式提供。
pgbouncer_exporter 指标导出 导出 Pgbouncer 连接池指标。
pgbackrest_exporter 指标导出 导出 pgBackrest 备份状态指标。
vip-manager VIP 管理 将 L2 VIP 绑定到当前主库节点,实现透明漂移。【可选】

其中 vip-manager 为按需启用的组件。此外,PGSQL 还会使用到其他模块中的组件:

组件 模块 简介 描述
haproxy NODE 负载均衡 对外暴露服务端口,根据角色分发流量至主库或从库。
vector NODE 日志采集 收集 PostgreSQL、PatroniPgbouncer 等日志推送至中心。
etcd ETCD DCS 分布式一致性存储,用于保存集群元数据与领导者信息。

如果用类比来形容,PostgreSQL 数据库内核就是 CPU,而整个 PGSQL 模块将其封装为一台完整的计算机。 PatroniEtcd 组成 高可用子系统pgBackRest 与可选的 Silo 组成 备份恢复子系统HAProxyPgbouncervip-manager 组成 接入子系统。 各种 Exporter 与 Vector 构成 可观测性子系统; 最后还可以替换不同的 内核 CPU扩展卡

Pigsty PostgreSQL 集群架构
子系统 组件 功能
高可用子系统 Patroni + etcd 故障检测、自动切换、配置管理
接入子系统 HAProxy + Pgbouncer + vip-manager 服务暴露、负载均衡、连接池、VIP
备份恢复子系统 pgBackRest(+ Silo) 全量/增量备份、WAL 归档、PITR
可观测性子系统 pg_exporter / pgbouncer_exporter / pgbackrest_exporter + Vector 指标采集、日志收集

组件交互

pigsty-arch

  • 集群 DNS 由 infra 节点上的 DNSMASQ 负责解析
  • 集群 VIP 由 vip-manager 组件管理,它负责将 pg_vip_address 绑定到集群主库节点上。
  • 集群服务由节点上的 HAProxy 对外暴露,不同服务通过节点的不同端口(543x)区分。
  • Pgbouncer 是连接池中间件,默认监听 6432 端口,可以缓冲连接、暴露额外的指标,并提供额外的灵活性。
  • PostgreSQL 监听 5432 端口,提供关系型数据库服务
    • 在多个节点上安装 PGSQL 模块,并使用同一集群名,将自动基于流式复制组成高可用集群
    • PostgreSQL 进程默认由 patroni 管理。
  • Patroni 默认监听端口 8008,监管着 PostgreSQL 服务器进程
    • PatroniPostgres 服务器作为子进程启动
    • Patroni 使用 etcd 作为 DCS:存储配置、故障检测和领导者选举。
    • Patroni 通过健康检查提供 Postgres 信息(比如主/从),HAProxy 通过健康检查使用该信息分发服务流量
  • pg_exporter 在 9630 端口对外暴露 postgres 监控指标
  • pgbouncer_exporter 在端口 9631 暴露 pgbouncer 指标
  • pgBackRest 默认使用本地备份仓库 (pgbackrest_method = local
    • 如果使用 local(默认)作为备份仓库,pgBackRest 将在主库节点的 pg_fs_backup 下创建本地仓库
    • 如果使用 minio 作为备份仓库,pgBackRest 将在专用的 Silo 或外部 S3 服务上创建备份仓库
  • Vector 负责收集 Postgres 相关日志(postgres, pgbouncer, patroni, pgbackrest)
    • vector 监听 9598 端口,也对 infra 节点上的 VictoriaMetrics 暴露自身的监控指标
    • vector 将日志发送至 infra 节点上的 VictoriaLogs

高可用子系统

高可用 子系统由 Patronietcd 组成,负责 PostgreSQL 集群的故障检测、自动切换与配置管理。

工作原理Patroni 在每个节点上运行,托管本地 PostgreSQL 进程,并将集群状态(领导者、成员、配置)写入 etcd。 当主库故障时,Patroni 通过 etcd 协调选举,选出最健康的从库提升为新主库,整个过程自动完成,RTO 通常在 45 秒内。

关键交互

  • PostgreSQL:作为父进程启动、停止、重载 PG,控制其生命周期
  • etcd:外部依赖,写入/监视领导者键,实现分布式共识与故障检测
  • HAProxy:通过 REST API(:8008)提供健康检查,告知实例角色
  • vip-manager:监视 etcd 中的领导者键,自动漂移 VIP

更多信息请参阅:高可用配置:PGSQL - PG_BOOTSTRAP


服务接入子系统

接入子系统由 HAProxyPgbouncervip-manager 组成,负责对外暴露服务、路由流量与连接池化。

有多种不同的接入方法,一种典型的流量路径是:客户端 → DNS/VIP → HAProxy (543x) → Pgbouncer (6432) → PostgreSQL (5432)

层级 组件 端口 职责
L2 VIP vip-manager - 将 L2 VIP 绑定到主库节点(可选)
L4 负载均衡 HAProxy 543x 服务暴露、负载均衡、健康检查
L7 连接池 Pgbouncer 6432 连接复用、会话管理、事务池化

服务端口

  • 5433 primary:读写服务,路由至主库 Pgbouncer
  • 5434 replica:只读服务,路由至从库 Pgbouncer
  • 5436 default:默认服务,直连主库(绕过连接池)
  • 5438 offline:离线服务,直连离线从库(ETL/分析)

关键特性

  • HAProxy 通过 Patroni REST API 判断实例角色,自动路由流量
  • Pgbouncer 采用事务级池化,吸收连接峰值,降低 PG 连接开销
  • vip-manager 监视 etcd 领导者键,故障切换时自动漂移 VIP

更多信息请参阅:服务接入配置:PGSQL - PG_ACCESS


备份恢复子系统

备份恢复子系统由 pgBackRest 组成(可选配 Silo 或外部 S3 作为远程仓库),负责数据备份与时间点恢复(PITR)。

备份类型

  • 全量备份:完整的数据库副本
  • 增量/差异备份:仅备份变更的数据块
  • WAL 归档:持续归档事务日志,支持恢复到恢复窗口内的任意时间点

存储后端

  • local(默认):本地磁盘,备份存储在 pg_fs_backup 挂载点
  • minio:S3 兼容对象存储,支持集中化备份管理与异地容灾

关键交互

更多信息请参阅:PITR备份恢复配置:PGSQL - PG_BACKUP


可观测性子系统

可观测性子系统由三个 ExporterVector 组成,负责指标采集与日志收集。

组件 端口 采集对象 关键指标
pg_exporter 9630 PostgreSQL 会话、事务、复制延迟、缓冲命中
pgbouncer_exporter 9631 Pgbouncer 连接池利用率、等待队列、命中率
pgbackrest_exporter 9854 pgBackRest 最近备份时间、大小、类型
vector 9598 postgres/patroni/pgbouncer 日志 结构化日志流

数据流向

  • 指标: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 内核上加装多达 575 个扩展插件。

PostgreSQL 进程默认由 高可用 Agent —— Patroni 托管拉起。 当一个集群中只有一个节点时,该实例即为主库;当集群包含多个节点时,其余实例会自动作为从库加入: 通过物理复制,实时从主库同步数据变更。从库可以承载只读请求,并在主库故障时自动接管。

pigsty-ha.png

您可以直接访问 PostgreSQL,或者通过 HAProxyPgbouncer 连接池来访问。

更多信息请参阅:配置:PGSQL - PG_BOOTSTRAP


Patroni

Patroni 是 PostgreSQL 高可用控制组件,默认监听 8008 端口。

Patroni 接管 PostgreSQL 的启动、停止、配置与健康状态,将领导者、成员信息写入 etcd。 它负责自动故障转移、保持复制因子、协调参数变更,并提供 REST API 供 HAProxy、监控与管理员查询。

HAProxy 通过 Patroni 健康检查端点判断实例角色,将流量路由至正确的主库或从库。 vip-manager 监视 etcd 中的领导者键,在主库切换时自动漂移 VIP。

patroni

更多信息请参阅:配置: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 关闭连接池。

pgbouncer.png

更多信息请参阅:配置:PGSQL - PG_ACCESS


pgBackRest

pgBackRest 是专业的 PostgreSQL 备份恢复工具,也是 PG 生态的最强备份工具之一,支持全量/增量/差异备份与 WAL 归档。

Pigsty 使用 pgBackRest 实现 PostgreSQL 的 PITR 能力, 您可以在备份保留的时间窗口内,将集群回滚到任意时间点。

pgBackRestPostgreSQL 配合,在主库上创建备份仓库,执行备份与归档任务。 默认使用本地备份仓库(pgbackrest_method = local),也可配置为 Silo 或外部 S3 对象存储,实现集中化备份管理。

初始化完成后可通过 pgbackrest_init_backup 自动发起首次全量备份。 恢复过程与 Patroni 集成,支持将副本引导为新的主库或备库。

pgbackrest

更多信息请参阅:备份恢复配置:PGSQL - PG_BACKUP


HAProxy

HAProxy 是服务入口与负载均衡器,对外暴露多个数据库服务端口。

端口 服务名 目标 说明
9101 管理接口 - HAProxy 统计与管理页面
5433 primary 主库 Pgbouncer 读写服务,路由至主库连接池
5434 replica 从库 Pgbouncer 只读服务,路由至从库连接池
5436 default 主库 Postgres 默认服务,直连主库(绕过连接池)
5438 offline 离线库 Postgres 离线服务,直连离线从库(ETL/分析)

HAProxy 通过 Patroni REST API 提供的健康检查信息判断实例角色,将流量路由至对应的主库或从库。 服务定义由 pg_default_servicespg_services 组合而成。

可通过 pg_service_provider 指定专用的 HAProxy 节点组承载更高流量, 默认使用本地节点上的 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,建议仅在本地自建环境与私有云环境中启用。

node-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 配置阶梯式缓存策略。

您可以通过参数禁用这个组件,在 精简安装 中,这个组件不会被启用。

pg-exporter

更多信息请参阅:配置: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 常驻在节点上,跟踪 PostgreSQLPgbouncerPatronipgBackRest 的日志目录, 将结构化日志发送至 INFRA 节点上的 VictoriaLogs 进行集中存储与查询。

更多信息请参阅:NODE 模块

3.2 - 集群模型图

Pigsty 是如何将不同种类的功能抽象成为模块的,以及这些模块的逻辑模型,实体关系图。

在 Pigsty 中最大的实体概念叫做 部署(Deployment),一套部署中的主要实体与关系(E-R 图)如下所示:

Pigsty 数据模型 ER 图

一套部署也可以理解为一个 环境(Environment)。例如,生产环境(Prod),用户测试环境(UTA),预发环境(Staging),测试环境(Testing),开发环境(Devbox),等等。 每个环境中,都对应着一份 Pigsty 配置清单,描述了环境中的所有实体与属性。

通常来说,一套环境中也会带有一套共用的基础设施(INFRA),广义的基础设施还包括 ETCD(高可用 DCS)以及 MINIO(集中式备份仓库), 同时供环境中的多套 PostgreSQL 数据库集群(以及其他数据库模块组件)使用。(例外:也有 不带基础设施的部署

在 Pigsty 中,几乎所有数据库模块都是以 “集群"(Cluster)的方式组织起来的。每一个集群都是一个 Ansible 分组,包含有若干节点资源。 例如 PostgreSQL 高可用数据库集群、Redis、Etcd 与 Silo 都以集群形式存在。一套环境中可以包含多个集群。

3.2.1 - PGSQL 集群模型

介绍 Pigsty 中 PostgreSQL 集群的实体-关系模型,E-R 关系图,实体释义与命名规范。

PGSQL 模块在生产环境中以 集群 的形式组织,这些 集群 是由一组由 主-备 关联的数据库 实例 组成的 逻辑实体

每个集群都是一个 自治 的业务单元,由至少一个 主库实例 组成,并通过服务向外暴露能力。

在 Pigsty 的 PGSQL 模块中有四种核心实体:

  • 集群(Cluster):自治的 PostgreSQL 业务单元,用作其他实体的顶级命名空间。
  • 服务(Service):对外暴露能力的命名抽象,路由流量,并使用节点端口暴露服务。
  • 实例(Instance):由在单个节点上的运行进程和数据库文件组成的单一 PostgreSQL 服务器。
  • 节点(Node):运行 Linux + Systemd 环境的硬件资源抽象,可以是裸机、VM、容器或 Pod。

辅以“数据库”“角色”两个业务实体,共同组成完整的逻辑视图。如下图所示:

er-pgsql

具体样例

让我们来看两个具体的例子,以四节点的 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-test PostgreSQL 3 节点高可用集群
实例 Instance
pg-test-1 1 号 PostgreSQL 实例,默认为主库
pg-test-2 2 号 PostgreSQL 实例,初始为从库
pg-test-3 3 号 PostgreSQL 实例,初始为从库
服务 Service
pg-test-primary 读写服务(路由到主库 pgbouncer)
pg-test-replica 只读服务(路由到从库 pgbouncer)
pg-test-default 直连读写服务(路由到主库 postgres)
pg-test-offline 离线读取服务(路由到专用 postgres)
节点 Nodes
node-1 10.10.10.11 1 号节点,对应 pg-test-1 PG 实例
node-2 10.10.10.12 2 号节点,对应 pg-test-2 PG 实例
node-3 10.10.10.13 3 号节点,对应 pg-test-3 PG 实例
ha

身份参数

Pigsty 使用 PG_ID 参数组为 PGSQL 模块的每个实体赋予确定的身份。以下三项为必选参数:

参数 类型 级别 说明 形式
pg_cluster string 集群 PG 集群名称,必选身份参数 有效的 DNS 名称,满足正则表达式 [a-zA-Z0-9-]+
pg_seq int 实例 PG 实例编号,必选身份参数 自然数,可从 0 或 1 开始分配,集群内不重复
pg_role enum 实例 PG 实例角色,必选身份参数 枚举值,可为 primaryreplicaoffline

只要在集群层面定义了集群名称,实例层面分配了实例编号与角色,Pigsty 就能自动根据规则为每个实体生成唯一标识符。

实体 生成规则 示例
实例 {{ pg_cluster }}-{{ pg_seq }} pg-test-1pg-test-2pg-test-3
服务 {{ pg_cluster }}-{{ pg_role }} pg-test-primarypg-test-replicapg-test-offline
节点 显示指定覆盖,或自动从 PG 实例借用 pg-test-1pg-test-2pg-test-3

因为 Pigsty 采用节点与 PG 实例 1:1 的独占部署模型,因此默认情况下,主机节点的标识符会直接借用 PG 实例的标识符(node_id_from_pg)。 当然您也可以显式指定 nodename 进行覆盖,或者关闭 nodename_overwrite,直接使用当前默认值。


分片身份参数

当你使用多套 PostgreSQL (分片 / Sharding)集群服务同一业务时,还会使用到另外两个身份参数:pg_shardpg_group

在这种情况下,这一组 PostgreSQL 集群将拥有相同的 pg_shard 名称,以及各自的 pg_group 编号,例如下面的 Citus 集群

在这种情况下,pg_cluster 集群名通常由:{{ pg_shard }}{{ pg_group }} 组合而成,例如 pg-citus0pg-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"}

例如,上面的 clsinsip 三个标签,分别对应集群名、实例名与节点 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: 查询指纹,如果一个监控指标属于某个具体的查询,则会带上这个标签。

3.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
etcd ETCD 三节点高可用集群
实例 Instance
etcd-1 1 号 ETCD 实例
etcd-2 2 号 ETCD 实例
etcd-3 3 号 ETCD 实例
节点 Nodes
10.10.10.10 1 号节点,对应 etcd-1 实例
10.10.10.11 2 号节点,对应 etcd-2 实例
10.10.10.12 3 号节点,对应 etcd-3 实例

身份参数

Pigsty 使用 ETCD 参数组为 ETCD 模块的每个实体赋予确定的身份。以下两项为必选参数:

参数 类型 级别 说明 形式
etcd_cluster string 集群 ETCD 集群名称,必选身份参数 有效的 DNS 名称,默认为固定值 etcd
etcd_seq int 实例 ETCD 实例编号,必选身份参数 自然数,从 1 开始分配,集群内不重复

只要在集群层面定义了集群名称,实例层面分配了实例编号,Pigsty 就能自动根据规则为每个实体生成唯一标识符。

实体 生成规则 示例
实例 {{ etcd_cluster }}-{{ etcd_seq }} etcd-1etcd-2etcd-3

ETCD 模块不会为主机节点赋予额外的身份标识,节点使用其原有的主机名或 IP 地址进行标识。


端口协议

每个 ETCD 实例会监听以下两个端口:

端口 参数 用途
2379 etcd_port 客户端端口,供 Patroni、vip-manager 等客户端访问
2380 etcd_peer_port 节点间通信端口,用于 Raft 共识协议

ETCD 集群默认启用 TLS 加密通信,并使用 RBAC 认证机制。客户端需要使用正确的证书和密码才能访问 ETCD 服务。


集群规模

ETCD 作为分布式协调服务,集群规模直接影响其可用性,需要有超过半数(仲裁数)的节点存活才能维持服务。

集群规模 仲裁数 容忍故障数 适用场景
1 节点 1 0 开发、测试、演示
3 节点 2 1 中小规模生产环境
5 节点 3 2 大规模生产环境

偶数成员的 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"}

例如,上面的 clsinsip 三个标签,分别对应集群名、实例名与节点 IP,这三个核心实体的标识符。 它们与 job 标签,在 所有 VictoriaMetrics 采集的 ETCD 监控指标中都会出现并可用。 采集 ETCD 指标的 job 名固定为 etcd

3.2.3 - MINIO 集群模型

介绍 Pigsty MINIO 模块部署 Silo 时使用的集群、实例与节点身份模型。

MINIO 是 Pigsty 的对象存储兼容模块名。v4.5.0 当前源码通过 minio_type: silo 部署 Silo,并以 集群 组织一组对象存储 实例

每个集群都是一个 自治 的 S3 兼容对象存储单元,由至少一个实例组成,通过 S3 API 端口对外提供服务。

MINIO 模块中有三种核心实体:

  • 集群(Cluster):自治的对象存储服务单元,用作其他实体的顶级命名空间。
  • 实例(Instance):单个 Silo 服务器进程,在节点上运行并管理本地磁盘。
  • 节点(Node):运行 Linux + Systemd 环境的硬件资源抽象,隐含式声明。

此外,Silo 保留 存储池(Pool)概念,用于扩容。


部署模式

Silo 支持 Pigsty 的三类清单部署模式:

模式 代号 说明 适用场景
单机单盘 SNSD 单节点,单个数据目录,或单块磁盘 开发、测试、演示
单机多盘 SNMD 单节点,使用多块磁盘,通常至少 4 块盘 资源受限的小规模部署
多机多盘 MNMD 多节点,每节点多块磁盘 生产环境推荐

单机单盘模式可以使用普通目录快速体验。Silo 多盘模式应使用真实磁盘挂载点,否则服务会拒绝启动。


具体样例

以下示例显式选择当前默认的 Silo 后端,并定义四节点多盘集群:

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_type: silo
    minio_cluster: minio
    minio_data: '/data{1...4}'
    minio_node: '${minio_cluster}-${minio_seq}.pigsty'

上面的配置片段定义了一个四节点的 Silo 集群,每个节点使用四块磁盘;实例标识仍沿用 MINIO 模块的兼容命名:

集群 Cluster
minio Silo 四节点高可用集群
实例 Instance
minio-1 1 号对象存储实例,管理 4 块磁盘
minio-2 2 号对象存储实例,管理 4 块磁盘
minio-3 3 号对象存储实例,管理 4 块磁盘
minio-4 4 号对象存储实例,管理 4 块磁盘
节点 Nodes
10.10.10.10 1 号节点,对应 minio-1 实例
10.10.10.11 2 号节点,对应 minio-2 实例
10.10.10.12 3 号节点,对应 minio-3 实例
10.10.10.13 4 号节点,对应 minio-4 实例

身份参数

Pigsty 使用 MINIO 参数组为对象存储实体赋予确定身份。以下两项为必选参数:

参数 类型 级别 说明 形式
minio_cluster string 集群 对象存储集群名称,必选身份参数 有效且非空的名称,无默认值
minio_seq int 实例 对象存储实例编号,必选身份参数 非负整数,建议从 1 开始,集群内不重复

只要在集群层面定义了集群名称,实例层面分配了实例编号,Pigsty 就能自动根据规则为每个实体生成唯一标识符。

实体 生成规则 示例
实例 {{ minio_cluster }}-{{ minio_seq }} minio-1minio-2minio-3minio-4

MINIO 模块不会为主机节点赋予额外的身份标识,节点使用其原有的主机名或 IP 地址进行标识。 minio_node 用于生成 Silo 集群内部的节点名称(写入 /etc/hosts 供集群发现使用),而非主机节点身份。

角色在整个清单中按 minio_cluster 查找实际成员,Ansible Group 名称不必与集群名称一致。minio_type 是保留的后端选择器,当前必须为 silo


核心配置参数

除身份参数外,以下参数对 Silo 集群配置至关重要:

参数 类型 说明
minio_type enum 保留选择器,当前只接受 silo
minio_data path 数据目录,使用 {x...y} 指定多盘
minio_node string 节点名模式,用于多节点部署
minio_domain string 服务域名,默认为 sss.pigsty

这些参数共同决定 minio_volumes,再由角色写入 Silo 的 MINIO_VOLUMES

  • 单机单盘:直接使用 minio_data 的值,如 /data/minio
  • 单机多盘:使用 minio_data 展开的多个目录,如 /data{1...4}
  • 多机多盘:组合 minio_nodeminio_data,如 https://minio-{1...4}.pigsty:9000/data{1...4}

端口与服务

每个对象存储实例会监听以下端口:

端口 参数 用途
9000 minio_port S3 API 服务端口
9001 minio_admin_port Web 管理控制台端口

MINIO 模块默认启用 HTTPS 加密通信(由 minio_https 控制)。按默认 pgBackRest S3 仓库配置使用时应保持 HTTPS,并正确安装 Pigsty CA。

多节点 Silo 集群可以通过访问 任意一个节点 来访问其服务。最佳实践是使用负载均衡器(如 HAProxy + VIP)提供统一接入点。


资源置备

Silo 集群部署后,Pigsty 会自动创建以下资源(由 minio_provision 控制):

默认存储桶(由 minio_buckets 定义):

存储桶 用途
pgsql PostgreSQL pgBackREST 备份存储
meta 元数据存储,启用版本控制
data 通用数据存储

默认用户(由 minio_users 定义):

用户 默认密码 策略 用途
pgbackrest S3User.Backup pgsql PostgreSQL 备份专用用户
s3user_meta S3User.Meta meta 访问 meta 存储桶
s3user_data S3User.Data data 访问 data 存储桶

这些密码属于文档公开的 默认凭据,仅供演示与本地开发使用,生产部署前必须替换。

pgbackrest 是 PostgreSQL 集群备份时使用的用户,s3user_metas3user_data 是未实际使用的保留用户。


监控标签体系

Pigsty 使用上面的 身份参数 标识对象存储实体。Silo 可用性序列示例如下:

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"}

其中 clsinsip 分别对应集群名、实例名与节点 IP。兼容监控命名保持 job=minio,当前后端标签为 flavor=silo。详细接口见 指标列表

3.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 为主从模式提供高可用监控与自动故障转移 本身的多节点仲裁
原生集群模式 cluster Redis 原生分布式集群,无需哨兵即可高可用 内置自动故障转移
  • 主从模式:默认模式,通过 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-ms Redis 主从集群
节点 Nodes
redis-ms-1 10.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-test Redis 原生集群(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-1 10.10.10.12 1 号节点,承载 3 个实例
redis-test-2 10.10.10.13 2 号节点,承载 3 个实例

身份参数

Pigsty 使用 REDIS 参数组为 Redis 模块的每个实体赋予确定的身份。以下三项为必选参数:

参数 类型 级别 说明 形式
redis_cluster string 集群 Redis 集群名称,必选身份参数 有效的 DNS 名称,满足 [a-z][a-z0-9-]*
redis_node int 节点 Redis 节点编号,必选身份参数 自然数,从 1 开始分配,集群内不重复
redis_instances dict 节点 Redis 实例定义,必选身份参数 JSON 对象,Key 为端口号,Value 为实例配置

只要在集群层面定义了集群名称,节点层面分配了节点编号与实例定义,Pigsty 就能自动根据规则为每个实体生成唯一标识符。

实体 生成规则 示例
实例 {{ redis_cluster }}-{{ redis_node }}-{{ port }} redis-ms-1-6379redis-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,用于汇总采集当前节点上 所有本地实例 的监控指标:

端口 参数 用途
9121 redis_exporter_port 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"}

例如,上面的 clsinsip 三个标签,分别对应集群名、实例名与节点 IP,这三个核心实体的标识符。 它们与 job 标签,在 所有 VictoriaMetrics 采集的 Redis 监控指标中都会出现并可用。 采集 Redis 指标的 job 名固定为 redis

3.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 节点上运行着以下核心组件:

组件 端口 说明
Nginx 80/443 Web 服务门户,本地软件仓库,统一反向代理入口
Grafana 3000 可视化平台,监控大屏,巡检与数据应用
VictoriaMetrics 8428 时序数据库,兼容 Prometheus API
VictoriaLogs 9428 日志数据库,接收 Vector 推送的结构化日志
VictoriaTraces 10428 链路追踪存储,用于慢 SQL / 请求追踪
VMAlert 8880 告警规则评估器,基于 VictoriaMetrics 触发告警
Alertmanager 9059 告警聚合与分发
Blackbox Exporter 9115 ICMP/TCP/HTTP 黑盒探测
DNSMASQ 53 DNS 服务器,提供内部域名解析
Chronyd 123 NTP 时间服务器

这些组件共同构成了 Pigsty 的可观测性基础设施。


具体样例

让我们来看一个具体的例子,以双节点的 INFRA 部署为例:

infra:
  hosts:
    10.10.10.10: { infra_seq: 1 }
    10.10.10.11: { infra_seq: 2 }

上面的配置片段定义了一个双节点的 INFRA 部署:

分组 Group
infra INFRA 基础设施节点分组
节点 Nodes
infra-1 10.10.10.10 1 号 INFRA 节点
infra-2 10.10.10.11 2 号 INFRA 节点

在生产环境中,建议部署至少两个 INFRA 节点,以实现基础设施组件的冗余。


身份参数

Pigsty 使用 INFRA_ID 参数组为 INFRA 模块的每个实体赋予确定的身份。以下一项为必选参数:

参数 类型 级别 说明 形式
infra_seq int 节点 INFRA 节点序号,必选身份参数 自然数,从 1 开始分配,分组内不重复

只要在节点层面分配了节点序号,Pigsty 就能自动根据规则为每个实体生成唯一标识符。

实体 生成规则 示例
节点 infra-{{ infra_seq }} infra-1infra-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.pigsty Home Pigsty 首页
g.pigsty Grafana 监控可视化平台
p.pigsty VictoriaMetrics 时序数据库 Web UI
a.pigsty Alertmanager 告警管理界面

建议通过域名访问 Pigsty 服务,而不是直接使用 IP + 端口的方式。


部署规模

INFRA 节点的数量取决于部署规模和高可用需求:

部署规模 INFRA 节点数 说明
开发测试 1 单节点部署,所有组件在同一节点
小规模生产 1-2 单节点或双节点,可与其他服务共用节点
中规模生产 2-3 独立的 INFRA 节点,组件冗余部署
大规模生产 3+ 多 INFRA 节点,可根据组件分离部署

单机部署 时,INFRA 组件与 PGSQL、ETCD 等模块共用同一个节点。 通常在小规模部署中,INFRA 节点通常还承担着 “管理节点” / “备用管理节点”,以及本地软件仓库(/www/pigsty)的角色。 在更大规模的部署中,这些职责可以剥离至专用节点。


监控标签体系

Pigsty 的监控系统会采集 INFRA 组件自身的指标。与数据库模块不同,INFRA 模块的每个 组件 都被视为独立的监控对象,通过 cls(类)标签区分不同组件类型。

标签 说明 示例
cls 组件类型,每种组件各自构成一个"类" nginx
ins 实例名,格式为 {组件类型}-{infra_seq} nginx-1
ip 运行该组件的 INFRA 节点 IP 地址 10.10.10.10
job VictoriaMetrics 采集任务名,固定为 infra infra

以双节点 INFRA 部署(infra_seq: 1infra_seq: 2)为例,各组件的监控标签如下:

组件 cls ins 示例 端口
Nginx nginx nginx-1nginx-2 9113
Grafana grafana grafana-1grafana-2 3000
VictoriaMetrics vmetrics vmetrics-1vmetrics-2 8428
VictoriaLogs vlogs vlogs-1vlogs-2 9428
VictoriaTraces vtraces vtraces-1vtraces-2 10428
VMAlert vmalert vmalert-1vmalert-2 8880
Alertmanager alertmanager alertmanager-1alertmanager-2 9059
Blackbox blackbox blackbox-1blackbox-2 9115

所有 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.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,其上安装了 INFRANODEETCDPGSQL 模块。

# 监控、告警、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.ymlall.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 集群 
pigsty-iac.jpg

你可以使用不同的实例角色,例如 主库(primary),从库(replica),离线从库(offline),延迟从库(delayed),同步备库(sync standby); 以及不同的集群:例如 备份集群(Standby Cluster),Citus 集群,甚至是 Redis / MINIO(Silo) / 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_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_connlimit: 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
    pg_crontab:  # 每天凌晨 1 点执行全量备份(写入 postgres 用户 crontab)
      - '00 01 * * * /pg/bin/pg-backup full'

声明访问控制

您还可以通过声明式的配置,深度定制 Pigsty 的 访问控制 能力。例如下面的配置文件对 pg-meta 集群进行了深度安全定制:

使用三节点核心集群模板:crit.yml,确保数据一致性有限,故障切换数据零丢失。 启用了 L2 VIP,并将数据库与连接池的监听地址限制在了本地环回 IP + 内网 IP + VIP 三个特定地址。 模板强制启用了 Patroni 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 }  # three-member cluster keeps an odd voter count
  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(Silo)集群

下面给出了一个三节点 Silo 集群的声明式配置样例。清单分组与参数继续沿用 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_type: silo
    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.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 集群或 Silo 集群等…

集群定义由两部分组成:集群成员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.3.2 - 配置向导

使用 configure 脚本根据当前环境自动生成推荐的配置文件。

Pigsty 提供了一个 configure 脚本作为 配置向导,它能根据当前环境,自动生成合适的 pigsty.yml 配置文件。

这是一个 可选 的脚本:如果您已经了解了如何配置 Pigsty,大可以直接编辑 pigsty.yml 配置文件,跳过向导。


快速开始

进入 pigsty 源码家目录中,执行 ./configure 即可自动运行配置向导。不带任何参数时,默认使用 meta 单节点配置模板:

cd ~/pigsty
./configure          # 交互式配置向导,自动检测环境并生成配置

该命令会以选定的模板为基础,检测当前节点的 IP 地址与区域,并生成适合当前环境的 pigsty.yml 配置文件。

demo/configure.cast

功能说明

configure 脚本会根据环境与输入执行以下调整,并默认在 Pigsty 目录下生成 pigsty.yml 配置文件。

  • 检测当前节点 IP 地址,如果有多个 IP,则要求用户输入一个 首要的 IP 地址 作为当前节点的身份标识
  • 使用 IP 地址替换配置模板中的占位符 10.10.10.10,并将其配置为 admin_ip 参数的值。
  • 检测当前区域,将 region 设置为 default (全球默认仓库)或 china (使用中国镜像仓库)
  • 针对小微实例(vCPU < 4),为 node_tunepg_conf 参数使用 tiny 参数模板,优化资源使用。
  • 如果指定了 -v PG 大版本,将 pg_version 与模板中的 pg18-* 包组别名切换到对应大版本;mssqlpolarpg19 是固定内核模板,不执行该替换。
  • 如果指定了 -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 supabase           # 使用 Supabase 自托管模板
./configure -c app/immich         # 使用 Immich 相册模板

# 指定 PostgreSQL 版本
./configure -v 18                 # 使用 PostgreSQL 18(默认)
./configure -v 16                 # 使用 PostgreSQL 16
./configure -c rich -v 15         # rich 模板 + PG 15
./configure -c pg19               # 使用专用 PostgreSQL 19 Beta 模板

# 区域与代理
./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 大版本号(14|15|16|17|18|19)
    [-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 大版本号(14-19);PG19 为 Beta,建议直接使用 pg19 模板
-r, --region 设置软件仓库镜像区域:default(默认)、china(中国镜像)、europe(欧洲镜像)
-o, --output 指定输出文件路径,默认为 pigsty.yml;相对路径基于 Pigsty 目录,绝对路径原样使用
-s, --skip 跳过 IP 探测、目标节点 SSH/Sudo 检查与实质 IP 替换,保留 10.10.10.10 占位符
-x, --proxy 将当前环境的代理变量(HTTP_PROXYHTTPS_PROXYALL_PROXYNO_PROXY)写入配置
-n, --non-interactive 非交互模式;单 IP 或演示 IP 可自动选择,多 IP 歧义时需配合 -i
-p, --port 指定环境检查所用 SSH 端口;不会自动把 ansible_port 写入输出配置
-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_env       处理代理环境变量                      │
│         ↓                                                   │
│ 10. check_ipaddr          探测/输入主 IP 地址                   │
│         ↓                                                   │
│ 11. check_admin           验证管理员 SSH + Sudo 权限            │
│         ↓                                                   │
│ 12. check_conf            选择配置模板                         │
│         ↓                                                   │
│ 13. check_config          生成配置文件                         │
│         ↓                                                   │
│ 14. check_utils           检测 Ansible 等工具是否安装           │
│         ↓                                                   │
│     ✓ 配置完成,输出 pigsty.yml                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

自动化行为

区域检测

脚本会自动检测网络环境,判断是否在中国大陆(GFW 内):

# 实际检测使用 HTTPS 与 2 秒总超时
curl -I -s --max-time 2 https://www.google.com
  • 如果可以访问 Google,使用 region: default 默认镜像
  • 如果 Google 不可达但 https://pigsty.cc 可达,设置 region: china 使用国内镜像
  • 如果两者都不可达,回退到 region: default 并给出网络不可达警告
  • 可通过 -r 参数手动指定区域

IP 地址处理

脚本按以下优先级确定主 IP 地址:

  1. 命令行参数:如果通过 -i 指定了 IP,直接使用
  2. 单 IP 探测:如果当前节点只有一个 IP,自动使用
  3. 演示 IP 检测:如果检测到 10.10.10.10,自动选择(用于沙箱环境)
  4. 交互式输入:多个 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(即 1~3 核)时,脚本会自动调整配置:

[WARN] replace oltp template with tiny due to cpu < 4

这样可以确保在低配虚拟机上也能顺利运行。

Locale 设置

脚本会在以下情况自动启用 C.UTF-8 作为默认 Locale:

  • PostgreSQL 版本 ≥ 17(内置 Locale Provider 支持)
  • 或者 当前系统支持 C.UTF-8 / C.utf8 Locale
pg_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_password Grafana 管理员密码
pg_admin_password PostgreSQL 管理员密码
pg_monitor_password PostgreSQL 监控用户密码
pg_replication_password PostgreSQL 复制用户密码
patroni_password Patroni API 密码
haproxy_admin_password HAProxy 管理密码
minio_secret_key Silo Root Secret
etcd_root_password ETCD Root 密码

同时还会替换以下占位符密码:

  • DBUser.Meta → 随机密码
  • DBUser.Viewer → 随机密码
  • S3User.Backup → 随机密码
  • S3User.Meta → 随机密码
  • S3User.Data → 随机密码
  • DBUser.Supa → 随机密码
  • Vibe.Coding → 随机密码
$ ./configure -g
[INFO] generating random passwords...
    grafana_admin_password   : xK9mL2nP4qR7sT1vW3yZ5bD8
    pg_admin_password        : aB3cD5eF7gH9iJ1kL2mN4oP6
    ...
[INFO] random passwords generated, check and save them

配置模板

脚本从 conf/ 目录读取配置模板。-c 的值是相对于 conf/、不带 .yml 后缀的路径,例如 ha/fullapp/immich

核心模板

模板 说明
meta 默认模板:单节点安装,包含 INFRA + NODE + ETCD + PGSQL
rich 功能丰富版:包含几乎所有扩展、Silo、本地仓库
slim 精简版:仅 PostgreSQL + ETCD,无监控基础设施
fat 完整版:rich 基础上安装更多扩展
pgsql 纯 PostgreSQL 模板
pg19 PostgreSQL 19 Beta 单节点试用模板
infra 纯基础设施模板

高可用模板 (ha/)

模板 说明
ha/dual 2 节点高可用集群
ha/trio 3 节点高可用集群
ha/full 4 节点完整沙箱环境
ha/safe 安全加固版高可用配置
ha/octo 8 节点紧凑高可用仿真
ha/simu 20 节点生产仿真环境
ha/citus 13 节点 Citus 分布式集群

应用模板

模板 说明
supabase Supabase 自托管配置
app/dify Dify AI 平台配置
app/odoo Odoo ERP 配置
app/electric Electric 同步引擎配置
app/insforge Insforge 后端平台配置
app/hindsight Hindsight 应用配置
app/teable Teable 表格数据库配置
app/mattermost Mattermost 协作平台配置
app/maybe Maybe 财务应用配置
app/registry Docker Registry 配置
app/immich Immich 相册与视频管理配置
app/jumpserver JumpServer 堡垒机配置

特殊内核模板/模式

模板 说明
ivory IvorySQL:Oracle 兼容 PostgreSQL
mssql Babelfish:SQL Server 兼容 PostgreSQL
polar PolarDB:阿里云开源分布式 PostgreSQL
ha/citus Citus:分布式 PostgreSQL 高可用集群
mysql OpenHalo:MySQL 协议兼容 PostgreSQL
pgtde Percona PostgreSQL Server:透明加密
oriole OrioleDB:新一代存储引擎
agens AgensGraph:图数据库内核
pgedge pgEdge:分布式 PostgreSQL 内核
mongo MongoDB 兼容栈模板

演示与构建模板

模板 说明
vibe Vibe Coding 开发环境模板
docker Docker 容器内运行模板
demo/bare 最小可读单节点配置示例
demo/el EL 系发行版完整参数示例
demo/debian Debian/Ubuntu 完整参数示例
demo/demo 多模块演示环境配置
demo/kernel 十节点数据库内核矩阵
demo/redis Redis 主从、哨兵与原生集群演示
demo/minio Silo(源码默认)多节点多盘集群演示
demo/kafka Kafka KRaft 开发与安全集群演示
demo/mysql 原生 MySQL 8.4 试点演示
demo/remote 远程 PostgreSQL/RDS 监控示例
demo/saas 传统单节点 SaaS 组件组合示例
demo/wool 中国区低配云主机示例
build/oss 跨发行版开源软件包构建环境
build/dev 三节点开发与构建环境

输出示例

$ ./configure
configure pigsty v4.5.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 = [email protected] 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 = [email protected] 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_HOME Pigsty 安装目录 ~/pigsty
METADB_URL 元数据库连接 URL service=meta
HTTP_PROXY HTTP 代理 -
HTTPS_PROXY HTTPS 代理 -
ALL_PROXY 通用代理 -
NO_PROXY 代理白名单 内置默认值

注意事项

  1. 免密访问:运行 configure 前,确保当前用户具有免密 sudo 权限和免密 SSH 到本机的能力。可以通过 bootstrap 脚本自动配置。

  2. IP 地址选择:请选择 内网 IP 作为主 IP 地址,不要使用公网 IP 或 127.0.0.1

  3. 密码安全:生产环境 务必 修改配置文件中的默认密码。可以使用 -g 参数随机化向导识别的凭据,并按 默认凭证清单 检查其余值。

  4. 配置检查:脚本执行完成后,建议检查生成的 pigsty.yml 文件,确认配置符合预期。

  5. 多次执行:可以多次运行 configure 重新生成配置,每次会覆盖现有的 pigsty.yml

  6. 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 占位符

相关文档

3.3.3 - 配置参数

使用配置参数对 Pigsty 进行精细化定制

配置清单 中,您可以使用各种参数对 Pigsty 进行精细化定制。这些参数涵盖了从基础设施设置到数据库配置的各个方面。


参数列表

按照当前源码与参数参考页对账,Pigsty 的 10 个正式模块共有 373 个公开参数,用于精细控制系统的各个方面;完整列表见 参考-参数列表。原生 MySQL 8.4 试点模块的 13 个公开参数单列,不计入该合计。

模块 参数组 参数数 说明
PGSQL 9 124 PostgreSQL 高可用集群配置
INFRA 10 73 软件仓库与 Victoria 可观测基础设施
NODE 11 73 节点初始化、系统调优与运维基线
ETCD 2 13 ETCD 集群与移除保护参数
MINIO 2 22 Silo 部署、观测与移除参数
REDIS 2 22 Redis/Valkey 部署与移除参数
DOCKER 1 8 Docker 引擎参数
JUICE 1 2 JuiceFS 实例与缓存参数
VIBE 1 18 Code/Jupyter/Node.js/Claude/Codex 配置
KAFKA 2 18 Kafka 部署参数与移除保护参数

参数形式

参数 是用于描述实体的 键值对(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 标识符,因此 没有默认值,必须 显式设置

模块 身份参数
PGSQL pg_cluster, pg_seq, pg_role, …
NODE nodename, node_cluster
ETCD etcd_cluster, etcd_seq
MINIO minio_cluster, minio_seq
REDIS redis_cluster, redis_node, redis_instances
INFRA infra_seq

例外是 etcd_cluster 仍有默认值 etcd。 对象存储的 minio_cluster 已不再提供默认值,必须在每个对象存储集群的变量中显式定义; 不要放在 all.vars 中,否则会把所有主机标记为 MINIO 模块成员。

3.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             # 使用包含全部扩展与 Silo 的富功能模板
./configure -c slim             # 使用最小化的单节点模板

# 使用不同的数据库内核
./configure -c pgsql            # 原生 PostgreSQL 内核,基础功能 (14~18)
./configure -c pg19             # PostgreSQL 19 Beta 专用试用模板
./configure -c mssql            # Babelfish 内核,兼容 SQL Server 协议 (17/18)
./configure -c polar            # PolarDB PG 内核,Aurora/RAC 风格 (17)
./configure -c ivory            # IvorySQL 内核,兼容 Oracle 语法 (18)
./configure -c mysql            # OpenHalo 内核,兼容 MySQL (14)
./configure -c pgtde            # Percona PostgreSQL Server 透明加密 (18)
./configure -c oriole           # OrioleDB 内核,OLTP 增强 (16~18)
./configure -c agens            # AgensGraph 图数据库内核 (17)
./configure -c pgedge           # pgEdge 分布式数据库内核 (15~18,默认 18)
./configure -c ha/citus         # Citus 分布式高可用 PostgreSQL (14~18)
./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:

模板 说明
meta.yml 默认模板,单节点 PostgreSQL 在线安装
rich.yml 富功能模板,包含本地软件源、Silo 及更多示例
slim.yml 精简模板,仅安装 PostgreSQL,不含监控与基础设施

数据库内核模板

适用于各类数据库管理系统与内核的模板:

模板 说明
pgsql.yml 原生 PostgreSQL 内核,基础功能 (14~18)
pg19.yml PostgreSQL 19 Beta 专用试用模板
mssql.yml Babelfish 内核,兼容 SQL Server 协议 (17/18)
polar.yml PolarDB PG 内核,Aurora/RAC 风格 (17)
ivory.yml IvorySQL 内核,兼容 Oracle 语法 (18)
mysql.yml OpenHalo 内核,兼容 MySQL (14)
pgtde.yml Percona PostgreSQL Server 透明加密 (18)
oriole.yml OrioleDB 内核,OLTP 增强 (16~18)
agens.yml AgensGraph 图数据库内核 (17)
pgedge.yml pgEdge 分布式数据库内核 (15~18,默认 18)
supabase.yml Supabase 自托管配置 (15~18)

您可以后续添加更多节点,或使用 高可用模板 在一开始就规划好集群。


高可用模板

您可以配置 Pigsty 在多节点上运行,组成高可用(HA)集群:

模板 说明
dual.yml 2 节点半高可用部署
trio.yml 3 节点标准高可用部署
full.yml 4 节点标准部署
safe.yml 4 节点安全增强部署,含延迟从库
octo.yml 8 节点紧凑高可用仿真
simu.yml 20 节点生产环境模拟
ha/citus.yml Citus 分布式高可用 PostgreSQL (14~18)

应用模板

您可以使用以下模板运行 Docker 应用/软件:

模板 说明
supabase.yml 启动单节点 Supabase
odoo.yml 启动 Odoo ERP 系统
dify.yml 启动 Dify AI 工作流系统
electric.yml 启动 Electric 同步引擎
insforge.yml 启动 Insforge 后端平台
hindsight.yml 启动 Hindsight 应用
mattermost.yml 启动 Mattermost 协作平台
teable.yml 启动 Teable 表格数据库
maybe.yml 启动 Maybe 财务应用
registry.yml 启动 Docker Registry

演示模板

除主要模板外,Pigsty 还提供了一组面向不同场景的演示模板:

模板 说明
el.yml EL 8/9 系统的全参数配置文件
debian.yml Debian/Ubuntu 系统的全参数配置文件
remote.yml 监控远程 PostgreSQL 集群或 RDS 的示例配置
redis.yml Redis 集群示例配置
minio.yml 4 节点 Silo(源码默认)多盘集群示例
kafka.yml 单节点开发集群 + 三节点安全集群的 Kafka dynamic KRaft 示例
mysql.yml 原生 MySQL 8.4 单节点/三节点试点示例;不同于 OpenHalo conf/mysql.yml
demo.yml Pigsty 公开演示站 的配置文件
fat.yml 含本地软件源与完整功能的单节点配置文件
infra.yml 仅部署基础设施模块
vibe.yml Vibe Coding / AI 应用开发模板
mongo.yml FerretDB / MongoDB 兼容示例
docker.yml Docker 应用宿主模板

构建模板

以下配置模板用于开发和测试目的:

模板 说明
build/oss.yml EL 9/10、Debian 12/13、Ubuntu 22.04/24.04/26.04 开源构建配置
build/dev.yml 开发测试构建配置

3.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 cls
pigsty.host 主机定义,属于某个分组 (cls, ip)
pigsty.global_var 全局变量,对应 all.vars key
pigsty.group_var 分组变量,对应 all.children.<cls>.vars (cls, key)
pigsty.host_var 主机变量,对应主机级别的变量 (cls, ip, key)
pigsty.default_var 默认变量定义,存储参数的元信息 key
pigsty.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 动态清单 JSON
pigsty.raw_config 原始配置的 JSON 格式展示
pigsty.global_config 全局配置视图,合并默认值和全局变量
pigsty.group_config 分组配置视图,包含主机列表和分组变量
pigsty.host_config 主机配置视图,合并分组和主机级别变量
pigsty.pg_cluster PostgreSQL 集群视图
pigsty.pg_instance PostgreSQL 实例视图
pigsty.pg_database PostgreSQL 数据库定义视图
pigsty.pg_users PostgreSQL 用户定义视图
pigsty.pg_service PostgreSQL 服务定义视图
pigsty.pg_hba PostgreSQL HBA 规则视图
pigsty.pg_remote 远程 PostgreSQL 实例视图

pigsty.inventory 是最核心的视图,它将数据库中的配置数据转换为 Ansible 所需的 JSON 格式:

SELECT text FROM pigsty.inventory;

工具脚本

Pigsty 提供了三个便利脚本来管理 CMDB:

脚本 功能
bin/inventory_load 将 YAML 配置文件加载到 PostgreSQL 数据库中
bin/inventory_cmdb 切换配置源为 CMDB(动态清单脚本)
bin/inventory_conf 切换配置源为静态配置文件 pigsty.yml

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           # 指定配置名称

脚本会执行以下操作:

  1. 清空 pigsty 模式中的现有数据
  2. 解析 YAML 配置文件
  3. 将全局变量写入 global_var
  4. 将集群定义写入 group
  5. 将集群变量写入 group_var
  6. 将主机定义写入 host
  7. 将主机变量写入 host_var

环境变量

  • PIGSTY_HOME:Pigsty 安装目录,默认为 ~/pigsty
  • METADB_URL:数据库连接 URL,默认为 service=meta

inventory_cmdb

切换 Ansible 使用 CMDB 作为配置源:

bin/inventory_cmdb

脚本会执行以下操作:

  1. 创建动态清单脚本 ${PIGSTY_HOME}/inventory.sh
  2. 修改 ansible.cfginventory 设置为 inventory.sh

生成的 inventory.sh 内容如下:

#!/bin/bash
psql ${METADB_URL} -AXtwc 'SELECT text FROM pigsty.inventory;'

inventory_conf

切换回使用静态 YAML 配置文件:

bin/inventory_conf

脚本会修改 ansible.cfginventory 设置回 pigsty.yml


使用流程

首次启用 CMDB

  1. 初始化 CMDB 模式(通常在安装 Pigsty 时已自动完成):
psql -f ~/pigsty/files/cmdb.sql
  1. 加载配置到数据库
bin/inventory_load
  1. 切换到 CMDB 模式
bin/inventory_cmdb
  1. 验证配置
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';

修改后立即生效,无需重新加载或重启任何服务。

切换回静态配置

如需切换回静态配置文件模式:

bin/inventory_conf

高级用法

配置导出

将 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 系统同步

注意事项

  1. 数据一致性:修改配置后,需要重新执行相应的 Ansible 剧本才能将变更应用到实际环境

  2. 备份:CMDB 中的配置数据非常重要,请确保定期备份

  3. 权限:建议为 CMDB 配置适当的数据库访问权限,避免误操作

  4. 事务:批量修改配置时,建议在事务中进行,以便出错时回滚

  5. 连接池inventory.sh 脚本每次执行都会建立新连接,如果 Ansible 执行频繁,建议考虑使用连接池


小结

CMDB 是 Pigsty 配置管理的高级方案,适用于需要管理大量集群、复杂查询、外部集成或精细权限控制的场景。通过将配置数据存储在 PostgreSQL 中,您可以充分利用数据库的强大能力来管理基础设施配置。

功能 说明
数据存储 PostgreSQL pigsty 模式
动态清单 inventory.sh 脚本
配置加载 bin/inventory_load
切换到 CMDB bin/inventory_cmdb
切换到 YAML bin/inventory_conf
核心视图 pigsty.inventory

3.4 - PG 高可用

Pigsty 使用 Patroni 实现了 PostgreSQL 的高可用,确保主库不可用时自动进行故障转移,由从库接管。

概览

Pigsty 的 PostgreSQL 集群带有开箱即用的高可用方案,由 PatroniEtcdHAProxy 提供核心能力。

当您的 PostgreSQL 集群含有两个或更多实例时,您无需任何配置即拥有了硬件故障自愈的数据库高可用能力 —— 只要集群中有任意实例存活,集群就可以对外提供完整的服务,而客户端只要连接至集群中的任意节点,即可获得完整的服务,而无需关心主从拓扑变化。

默认 norm 模式的目标 RTO 为 45 秒内;异步复制的 pg_rpo=1MiB 是 Patroni 的候选从库采样落后阈值,并非实际丢失量硬上限。使用 crit.yml 的严格同步模式可让已确认事务在故障切换时保持 RPO = 0。以上行为可通过参数按实际硬件与可靠性要求 配置

Pigsty 内置了 HAProxy 负载均衡器用于自动流量切换,提供 DNS/VIP/LVS 等多种接入方式供客户端选用。故障切换与主动切换对业务侧除零星闪断外几乎无感知,应用不需要修改连接串重启。 极小的维护窗口需求带来了极大的灵活便利:您完全可以在无需应用配合的情况下滚动维护升级整个集群。硬件故障可以等到第二天再抽空善后处置的特性,让研发,运维与 DBA 都能在故障时安心睡个好觉。

pigsty-ha

许多大型组织与核心机构已经在生产环境中长时间使用 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 共同完成,集群领导者将持有一个租约, 如果集群领导者未能在租约 TTL 内续租(默认 norm 模式为 30 秒),租约会过期并触发 故障切换(Failover)与新一轮选举。

即使没有出现任何故障,您依然可以主动通过 主动切换(Switchover)变更集群的主库。 在这种情况下,主库上的写入查询将会闪断,并立即路由至新主库执行。这一操作通常可用于滚动维护/升级数据库服务器。

3.4.1 - RPO 利弊权衡

针对 RPO (Recovery Point Objective)进行利弊权衡,在可用性与数据损失之间找到最佳平衡点。

RPO(Recovery Point Objective,恢复点目标)定义了在主库发生故障时,允许丢失的最大数据量

对于金融交易这类数据完整性至关重要的场景,通常要求 RPO = 0,即不允许任何数据丢失;

然而更为严格的 RPO 指标是有代价的,它会引入更高的写入延迟,降低系统吞吐量,并且存在从库故障导致主库不可用的风险。 因此对于常规场景,通常可以接受一定量的数据丢失,以换取更高的可用性与性能。


利弊权衡

通常在异步复制场景下,从库和主库之间会存在一定的复制延迟(取决于网络和吞吐量,正常在 10KB-100KB / 100µs-10ms 的数量级), 这意味着当主库发生故障时,从库可能还没有完全同步主库的最新数据。这时候如果出现故障切换,新的主库可能会丢失一些尚未复制的数据。

pg_rpo 会被写入 Patroni 的 maximum_lag_on_failover,默认值为 1048576(1MiB)。它是 候选从库参与竞选时允许的采样落后阈值,不是实际数据丢失量的硬上限。

当集群主库宕机时,如果有任何一个从库的复制延迟在这个值以内,Pigsty 将自动提升该从库为新的主库。 然而当所有从库副本的复制延迟都超出这个阈值时,Pigsty 将拒绝进行 [自动故障切换] 以避免数据丢失。 此时需要人工介入进行决策 —— 等待主库恢复(可能永远也不会恢复),还是接受数据损失并强制提升一个从库为新的主库。

由于主库 WAL 位置并非实时采样,异步复制最坏情况下的实际丢失量还可能包含最近一个 ttl 窗口内产生的 WAL(平均约再加 loop_wait/2 时间内的 WAL)。您需要结合业务写入速率配置该阈值;增大它会提高自动故障切换的成功率,但也会放宽候选资格。

当您指定 pg_rpo = 0 时,Pigsty 将启用 同步复制,确保主库在确认至少一个从库持久化数据后才返回写入成功。 这种配置能确保没有复制延迟,但会带来显著的写入延迟,并降低整体的吞吐量。

flowchart LR
    A([主库故障]) --> B{同步复制?}

    B -->|否| C{延迟 < RPO?}
    B -->|是| D{同步从库<br/>可用?}

    C -->|是| E[有损自动故障切换<br/>候选采样落后在阈值内]
    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;默认候选采样落后阈值为 1MiB,但它不是实际丢失量的硬上限
  • 针对性能优化,适用于常规业务场景,容许在故障时损失少量数据。
最大可用性(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 可能丢失;默认候选阈值 1MiB 正常 = 0 / 降级后可能丢失 = 0
适用场景 常规业务、性能优先 重要业务、安全优先 金融核心、安全合规第一
配置方法 默认配置 pg_rpo = 0 pg_conf: crit.yml

实现原理

三种保护模式的区别在于 Patroni 的两个核心参数:synchronous_modesynchronous_mode_strict 如何配置:

  • synchronous_mode:Patroni 是否启用同步复制,如果启用,再看 synchronous_mode_strict 是否启用严格同步模式。
  • synchronous_mode_strict = false,默认配置,允许当从库故障时降级为异步模式,主库继续服务(最大可用性)
  • synchronous_mode_strict = true,禁止降级,主库停止写入 直到同步从库恢复(最大保护)
模式 synchronous_mode synchronous_mode_strict 复制模式 从库故障行为
最大性能 false - 异步复制 无影响
最大可用 true false 同步复制 自动降级为异步
最大保护 true true 严格同步复制 主库拒绝写入

通常情况下,您只需要将 pg_rpo 参数设置为 0,即可打开 synchronous_mode 开关,启用 最大可用性模式。 如果您使用 pg_conf = crit.yml 模板,则会同时额外打开 synchronous_mode_strict 严格模式开关,启用 最大保护模式。 此外,您可以启用 watchdog,在节点/Patroni 假死场景下直接 Fencing 主库而不是降级,实现与 Oracle 最大保护模式相同的行为表现

当然,您可以直接按需 配置 这些 Patroni 参数,您还可以参阅 Patroni 与 PostgreSQL 文档,通过配置实现更强的数据保护,例如:

  • 可以指定 同步从库列表,配置更多同步从库以提高容灾能力,使用法定人数同步,甚至要求所有从库都执行同步提交。
  • 您可以 配置 synchronous_commit: 'remote_apply',严格确保主从读写一致性。(Oracle 最大保护模式相当于 remote_write

配置建议

最大性能模式(异步复制)是 Pigsty 默认使用的模式,对于绝大多数业务来说已经足够使用。 容许故障时丢失少量数据,换来更大的性能吞吐量与服务可用性水平。 在这种情况下,可以通过 pg_rpo 调整候选从库的采样落后阈值; 实际最坏数据损失还取决于写入速率、ttl 与采样时机。

最大可用性模式(同步复制)适用于数据完整性要求高的场景;同步从库正常时可做到已确认事务零丢失(同步副本全部不可用后会降级) 在这种模式下,最少需要一主一从的两节点 PostgreSQL 集群才有意义。 将 pg_rpo 设置为 0 即可启用该模式。

最大保护模式 (严格同步复制) 适用于金融交易、医疗记录等对数据完整性要求极高的场景,我们建议至少使用一主二从的三节点集群, 因为两节点的情况下,只要从库故障,主库就会停止写入,导致业务不可用,这会降低系统的整体可靠性。而三节点的规格下,如果只有一个从库故障,主库仍然可以继续服务。

3.4.2 - RTO 利弊权衡

针对 RTO (Recovery Time Objective)进行利弊权衡,在故障恢复速度与误切风险之间找到最佳平衡点。

RTO(Recovery Time Objective,恢复时间目标)定义了在主库发生故障时,系统恢复写入能力所需的最长时间

对于核心交易系统这类可用性至关重要的场景,通常要求 RTO 尽可能短,例如一分钟内。

然而更短的 RTO 指标是有代价的,它会增加误切风险:网络抖动可能被误判为故障,导致不必要的故障切换。 因此对于跨机房/跨地域部署的场景,通常需要放宽 RTO 要求(例如 1-2 分钟),以降低误切风险。


利弊权衡

故障切换时的不可用时长上限由 pg_rto 参数控制。Pigsty 提供了四种预设的 RTO 模式: fastnormsafewide,分别针对不同的网络条件与部署场景进行了优化,默认使用 norm 模式(约 45 秒)。

当主库发生故障时,整个恢复流程涉及多个阶段: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: fast pg_rto: norm pg_rto: safe pg_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 有两条关键故障路径:主动故障检测(PG 崩溃后 Patroni 检测到并尝试重启)与 被动租约过期(节点宕机后等待 TTL 过期触发选举)。

tooltip: { trigger: axis, axisPointer: { type: shadow }, formatter: $fn:fmt }
legend: { top: 0, itemGap: 10, data: [租约过期, 故障检测, 重启超时, 从库检测, 抢锁提拔, 健康检查] }
grid: { left: 110, right: 24, bottom: 32, top: 40 }
xAxis: { type: value, name: 秒, nameLocation: end, max: 160, axisLine: { show: true }, axisTick: { show: true }, splitLine: { show: true, lineStyle: { type: dashed, opacity: 0.5 } }, minorTick: { show: true, splitNumber: 5 }, minorSplitLine: { show: true, lineStyle: { type: dotted, opacity: 0.2 } } }
yAxis: { type: category, axisLine: { show: true }, axisTick: { show: true }, splitLine: { show: false }, axisLabel: { fontSize: 9, fontFamily: monospace }, data: [wide-passive-max, wide-passive-avg, wide-passive-min, wide-active-max, wide-active-avg, wide-active-min, "", safe-passive-max, safe-passive-avg, safe-passive-min, safe-active-max, safe-active-avg, safe-active-min, "", norm-passive-max, norm-passive-avg, norm-passive-min, norm-active-max, norm-active-avg, norm-active-min, "", fast-passive-max, fast-passive-avg, fast-passive-min, fast-active-max, fast-active-avg, fast-active-min] }
series:
  - { name: 租约过期, type: bar, stack: main, barWidth: 16, z: 2, emphasis: { focus: series }, itemStyle: { color: "#e15759" }, data: [120, 110, 100, "-", "-", "-", "-", 60, 55, 50, "-", "-", "-", "-", 30, 27, 25, "-", "-", "-", "-", 20, 17, 15, "-", "-", "-"] }
  - { name: 故障检测, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#b07aa1" }, data: ["-", "-", "-", 20, 10, 0, "-", "-", "-", "-", 10, 5, 0, "-", "-", "-", "-", 5, 3, 0, "-", "-", "-", "-", 5, 3, 0] }
  - { name: 重启超时, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#f28e2c" }, data: ["-", "-", "-", 95, 95, 0, "-", "-", "-", "-", 45, 45, 0, "-", "-", "-", "-", 25, 25, 0, "-", "-", "-", "-", 15, 15, 0] }
  - { name: 从库检测, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#edc949" }, data: [20, 10, 0, 20, 10, 0, "-", 10, 5, 0, 10, 5, 0, "-", 5, 3, 0, 5, 3, 0, "-", 5, 3, 0, 5, 3, 0] }
  - { name: 抢锁提拔, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#59a14f" }, data: [2, 1, 0, 2, 1, 0, "-", 2, 1, 0, 2, 1, 0, "-", 2, 1, 0, 2, 1, 0, "-", 2, 1, 0, 2, 1, 0] }
  - { name: 健康检查, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#4e79a7" }, data: [8, 6, 4, 8, 6, 4, "-", 6, 5, 3, 6, 5, 3, "-", 4, 3, 2, 4, 3, 2, "-", 2, 2, 1, 2, 2, 1] }
  - { name: RTO总计, type: bar, barGap: "-100%", barWidth: 16, z: 1, itemStyle: { color: "#888", opacity: 0 }, emphasis: { itemStyle: { opacity: 0 } }, data: [150, 127, 104, 145, 122, 4, "-", 78, 66, 53, 73, 61, 3, "-", 41, 34, 27, 41, 35, 2, "-", 29, 23, 16, 29, 24, 1] }
  - { name: RTO预算, type: bar, barGap: "-100%", barWidth: 16, z: 0, itemStyle: { color: "rgba(0,0,0,0.08)" }, emphasis: { itemStyle: { color: "rgba(0,0,0,0.12)" } }, data: [150, 150, 150, 150, 150, 150, "-", 90, 90, 90, 90, 90, 90, "-", 45, 45, 45, 45, 45, 45, "-", 30, 30, 30, 30, 30, 30] }

实现原理

四种 RTO 模式的区别在于以下 10 个 PatroniHAProxy HA 相关参数如何配置。

组件 参数 fast norm safe wide 说明
patroni ttl 20 30 60 120 Leader 锁生存时间(秒)
loop_wait 5 5 10 20 HA 循环检查间隔(秒)
retry_timeout 5 10 20 30 DCS 操作重试超时(秒)
primary_start_timeout 15 25 45 95 主库重启等待时间(秒)
safety_margin 5 5 10 15 Watchdog 安全边际(秒)
haproxy inter 1s 2s 3s 4s 正常状态检查间隔
fastinter 0.5s 1s 1.5s 2s 状态变化期检查间隔
downinter 1s 2s 3s 4s DOWN 状态检查间隔
rise 3 3 3 3 标记 UP 所需连续成功次数
fall 3 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 过期前完成降级,防止脑裂。

loop_wait+2×retry_timeoutttlloop\_wait + 2 \times retry\_timeout \leq ttl

数据汇总


配置建议

fast 模式 适用于对 RTO 要求极高的场景,但需要确保网络质量足够好(延迟 < 1ms,极低丢包率)。 建议仅在同机柜或同交换机部署时使用,并在生产环境充分测试后再启用。

norm 模式默认)是 Pigsty 默认使用的配置,对于绝大多数同机房部署的业务来说已经足够使用。 按本文模型,被动/主动路径平均约 34/35 秒,同时提供了合理的容错窗口,避免网络抖动导致的误切。

safe 模式 适用于同城跨机房部署,网络延迟较高或存在偶发抖动的场景。 更长的容错窗口可以有效避免网络抖动导致的误切,是跨机房容灾的推荐配置。

wide 模式 适用于跨地域甚至跨大洲部署,网络延迟高且可能存在公网级别的丢包率。 这种场景下,稳定性比恢复速度更重要,因此使用极宽的容错窗口来确保极低的误切率。

模式 目标 RTO 被动检测 RTO 主动检测 RTO 场景
fast 30 16 / 23 / 29 1 / 24 / 29 同交换机,高质量网络
norm 45 27 / 34 / 41 2 / 35 / 41 默认,同机房,标准网络
safe 90 53 / 66 / 78 3 / 61 / 73 同城双活 / 跨机房容灾
wide 150 104 / 127 / 150 4 / 122 / 145 异地容灾 / 跨国部署
default 326 22 / 34 / 46 2 / 314 / 326 Patroni 默认参数

通常只需将 pg_rto 设为模式名称,Pigsty 会自动配置 Patroni 与 HAProxy 参数。 当前模板通过 pg_rto in pg_rto_plan 查找模式;数字或未知键会直接回退到 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

3.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

3.4.3.1 - 被动故障切换

节点宕机,导致领导者租约过期触发集群领导竞选的故障路径
infographic list-row-simple-horizontal-arrow
data
  title 租约过期故障切换流程
  desc 当整个节点宕机,Patroni 无法主动释放租约,只能等待 TTL 过期
  items
    - label 租约过期
      desc Patroni 失联,被动等待主库租约 TTL 过期
      icon mingcute/close-circle-fill
    - label 从库检测
      desc 从库从循环中醒来后发现租约过期,开始竞选
      icon mingcute/key-2-fill
    - label 抢锁提拔
      desc 从库相互比较并抢锁,胜利者提升自己的PG
      icon mingcute/radar-fill
    - label 健康检查
      desc HAPROXY 健康检查发现新主上线,分配流量
      icon mingcute/arrow-up-circle-fill
theme light
  palette antv

RTO 时序图

tooltip: { trigger: axis, axisPointer: { type: shadow }, formatter: $fn:fmt }
legend: { top: 0, itemGap: 12, data: [租约过期, 从库检测, 抢锁提拔, 健康检查] }
grid: { left: 64, right: 24, bottom: 32, top: 40 }
xAxis: { type: value, name: 秒, nameLocation: end, max: 160, axisLine: { show: true }, axisTick: { show: true }, splitLine: { show: true, lineStyle: { type: dashed, opacity: 0.5 } }, minorTick: { show: true, splitNumber: 5 }, minorSplitLine: { show: true, lineStyle: { type: dotted, opacity: 0.2 } } }
yAxis: { type: category, axisLine: { show: true }, axisTick: { show: true }, splitLine: { show: false }, axisLabel: { fontSize: 10, fontFamily: monospace }, data: [wide-max, wide-avg, wide-min, "", safe-max, safe-avg, safe-min, "", norm-max, norm-avg, norm-min, "", fast-max, fast-avg, fast-min] }
series:
  - { name: 租约过期, type: bar, stack: main, barWidth: 20, z: 2, emphasis: { focus: series }, itemStyle: { color: "#e15759" }, data: [120, 110, 100, "-", 60, 55, 50, "-", 30, 27, 25, "-", 20, 17, 15] }
  - { name: 从库检测, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#edc949" }, data: [20, 10, 0, "-", 10, 5, 0, "-", 5, 3, 0, "-", 5, 3, 0] }
  - { name: 抢锁提拔, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#59a14f" }, data: [2, 1, 0, "-", 2, 1, 0, "-", 2, 1, 0, "-", 2, 1, 0] }
  - { name: 健康检查, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#4e79a7" }, data: [8, 6, 4, "-", 6, 5, 3, "-", 4, 3, 2, "-", 2, 2, 1] }
  - { name: RTO总计, type: bar, barGap: "-100%", barWidth: 20, z: 1, itemStyle: { color: "#888", opacity: 0 }, emphasis: { itemStyle: { opacity: 0 } }, data: [150, 127, 104, "-", 78, 66, 53, "-", 41, 34, 27, "-", 29, 23, 16] }
  - { name: RTO预算, type: bar, barGap: "-100%", barWidth: 20, z: 0, itemStyle: { color: "rgba(0,0,0,0.08)" }, emphasis: { itemStyle: { color: "rgba(0,0,0,0.12)" } }, data: [150, 150, 150, "-", 90, 90, 90, "-", 45, 45, 45, "-", 30, 30, 30] }

故障模型

项目 最好 最坏 平均 说明
租约过期 ttl - loop ttl ttl - loop/2 最好:即将刷新时宕机
最坏:刚刷新完就宕机
从库检测 0 loop loop / 2 最好:恰好在检测点
最坏:刚错过检测点
抢锁提拔 0 2 1 最好:直接抢锁提升
最坏: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/2
Texpire={ttlloop最好ttlloop/2平均ttl最坏T_{expire} = \begin{cases} ttl - loop & \text{最好} \\ ttl - loop/2 & \text{平均} \\ ttl & \text{最坏} \end{cases}

阶段 2:从库检测

从库在 loop_wait 周期醒来后检查 DCS 中的 Leader Key 状态。

时间线:
    租约过期      从库醒来
       |            |
       |←── 0~loop ─→|
  • 最好情况:租约过期时从库恰好醒来,等待 0
  • 最坏情况:租约过期后从库刚进入睡眠,等待 loop
  • 平均情况loop/2
Tdetect={0最好loop/2平均loop最坏T_{detect} = \begin{cases} 0 & \text{最好} \\ loop/2 & \text{平均} \\ loop & \text{最坏} \end{cases}

阶段 3:抢锁提拔

从库发现 Leader Key 过期后,开始竞选过程,获得 Leader Key 的从库执行 pg_ctl promote,将自己提升为新主库。

  1. 通过 Rest API,并行发起查询,查询各从库的复制位置,通常 10ms,硬编码 2 秒超时。
  2. 比较 WAL 位置,确定最优候选,各从库尝试创建 Leader Key(CAS 原子操作)
  3. 执行 pg_ctl promote 提升自己为主库(很快,通常忽略不计)
选举流程:
  从库A ──→ 查询复制位置 ──→ 比较 ──→ 尝试抢锁 ──→ 成功
  从库B ──→ 查询复制位置 ──→ 比较 ──→ 尝试抢锁 ──→ 失败
  • 最好情况:单从库或直接抢到锁并提升,常数开销 0.1s
  • 最坏情况:DCS API 调用超时:2s
  • 平均情况1s 常数开销
Telect={0.1最好1平均2最坏T_{elect} = \begin{cases} 0.1 & \text{最好} \\ 1 & \text{平均} \\ 2 & \text{最坏} \end{cases}

阶段 4:健康检查

HAProxy 检测新主库上线,需要连续 rise 次健康检查成功。

检测时序:
  新主提升    首次检查    第二次检查   第三次检查(UP)
     |          |           |           |
     |←─ 0~inter ─→|←─ fast ─→|←─ fast ─→|
  • 最好情况:新主提升时恰好赶上检查,(rise-1) × fastinter
  • 最坏情况:新主提升后刚错过检查,(rise-1) × fastinter + inter
  • 平均情况(rise-1) × fastinter + inter/2
Thaproxy={(rise1)×fastinter最好(rise1)×fastinter+inter/2平均(rise1)×fastinter+inter最坏T_{haproxy} = \begin{cases} (rise-1) \times fastinter & \text{最好} \\ (rise-1) \times fastinter + inter/2 & \text{平均} \\ (rise-1) \times fastinter + inter & \text{最坏} \end{cases}

RTO 公式

将各阶段时间相加,得到总 RTO:

最好情况

RTOmin=ttlloop+0.1+(rise1)×fastinterRTO_{min} = ttl - loop + 0.1 + (rise-1) \times fastinter

平均情况

RTOavg=ttl+1+inter/2+(rise1)×fastinterRTO_{avg} = ttl + 1 + inter/2 + (rise-1) \times fastinter

最坏情况

RTOmax=ttl+loop+2+inter+(rise1)×fastinterRTO_{max} = ttl + loop + 2 + inter + (rise-1) \times fastinter

模型计算

将四种 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 / 20 25 / 27 / 30 50 / 55 / 60 100 / 110 / 120
从库检测 0 / 3 / 5 0 / 3 / 5 0 / 5 / 10 0 / 10 / 20
抢锁提拔 0 / 1 / 2 0 / 1 / 2 0 / 1 / 2 0 / 1 / 2
健康检查 1 / 2 / 2 2 / 3 / 4 3 / 5 / 6 4 / 6 / 8
总计 16 / 23 / 29 27 / 34 / 41 53 / 66 / 78 104 / 127 / 150

3.4.3.2 - 主动故障检测

PostgreSQL 主库进程崩溃,Patroni 存活并尝试重启,超时后触发故障切换的路径
infographic list-row-simple-horizontal-arrow
data
  title 崩溃故障切换流程
  desc 当 Patroni 健康,但 PostgreSQL 因故崩溃时的故障切换流程
  items
    - label 故障检测
      desc Patroni 在循环中检测到 PG 崩溃
      icon mingcute/close-circle-fill
    - label 重启超时
      desc Patroni 尝试重启 PG,超时后释放租约
      icon mingcute/refresh-2-fill
    - label 从库检测
      desc 从库从循环中醒来发现租约释放,开始竞选
      icon mingcute/key-2-fill
    - label 抢锁提拔
      desc 从库相互比较并抢锁,胜利者提升自己的 PG
      icon mingcute/radar-fill
    - label 健康检查
      desc HAProxy 健康检查发现新主上线,分配流量
      icon mingcute/arrow-up-circle-fill
theme light
  palette antv

RTO 时序图

tooltip: { trigger: axis, axisPointer: { type: shadow }, formatter: $fn:fmt }
legend: { top: 0, itemGap: 12, data: [故障检测, 重启超时, 从库检测, 抢锁提拔, 健康检查] }
grid: { left: 64, right: 24, bottom: 32, top: 40 }
xAxis: { type: value, name: 秒, nameLocation: end, max: 160, axisLine: { show: true }, axisTick: { show: true }, splitLine: { show: true, lineStyle: { type: dashed, opacity: 0.5 } }, minorTick: { show: true, splitNumber: 5 }, minorSplitLine: { show: true, lineStyle: { type: dotted, opacity: 0.2 } } }
yAxis: { type: category, axisLine: { show: true }, axisTick: { show: true }, splitLine: { show: false }, axisLabel: { fontSize: 10, fontFamily: monospace }, data: [wide-max, wide-avg, wide-min, "", safe-max, safe-avg, safe-min, "", norm-max, norm-avg, norm-min, "", fast-max, fast-avg, fast-min] }
series:
  - { name: 故障检测, type: bar, stack: main, barWidth: 20, z: 2, emphasis: { focus: series }, itemStyle: { color: "#b07aa1" }, data: [20, 10, 0, "-", 10, 5, 0, "-", 5, 3, 0, "-", 5, 3, 0] }
  - { name: 重启超时, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#f28e2c" }, data: [95, 95, 0, "-", 45, 45, 0, "-", 25, 25, 0, "-", 15, 15, 0] }
  - { name: 从库检测, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#edc949" }, data: [20, 10, 0, "-", 10, 5, 0, "-", 5, 3, 0, "-", 5, 3, 0] }
  - { name: 抢锁提拔, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#59a14f" }, data: [2, 1, 0, "-", 2, 1, 0, "-", 2, 1, 0, "-", 2, 1, 0] }
  - { name: 健康检查, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#4e79a7" }, data: [8, 6, 4, "-", 6, 5, 3, "-", 4, 3, 2, "-", 2, 2, 1] }
  - { name: RTO总计, type: bar, barGap: "-100%", barWidth: 20, z: 1, itemStyle: { color: "#888", opacity: 0 }, emphasis: { itemStyle: { opacity: 0 } }, data: [145, 122, 4, "-", 73, 61, 3, "-", 41, 35, 2, "-", 29, 24, 1] }
  - { name: RTO预算, type: bar, barGap: "-100%", barWidth: 20, z: 0, itemStyle: { color: "rgba(0,0,0,0.08)" }, emphasis: { itemStyle: { color: "rgba(0,0,0,0.12)" } }, data: [150, 150, 150, "-", 90, 90, 90, "-", 45, 45, 45, "-", 30, 30, 30] }

故障模型

项目 最好 最坏 平均 说明
故障检测 0 loop loop/2 最好:PG 恰好在检测前崩溃
最坏:PG 刚检测完就崩溃
重启超时 0 start start 最好:PG 瞬间自愈
最坏:等满 start 超时才释放租约
从库检测 0 loop loop/2 最好:恰好在检测点
最坏:刚错过检测点
抢锁提拔 0 2 1 最好:直接抢锁提升
最坏: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/2
Tdetect={0最好loop/2平均loop最坏T_{detect} = \begin{cases} 0 & \text{最好} \\ loop/2 & \text{平均} \\ loop & \text{最坏} \end{cases}

阶段 2:重启超时

Patroni 检测到 PG 崩溃后,会尝试重启 PostgreSQL。此阶段有两种可能的结果:

时间线:
  检测到崩溃     尝试重启     重启成功/超时
      |           |             |
      |←──── 0 ~ start ────────→|

路径 A:自愈成功(最好情况)

  • PG 成功重启,服务恢复
  • 不触发故障切换,RTO 极短
  • 等待时间:0(相对于 Failover 路径)

路径 B:需要 Failover(平均/最坏情况)

  • 等待 primary_start_timeout 超时后 PG 仍未恢复
  • Patroni 主动释放 Leader Key
  • 等待时间:start
Trestart={0最好(自愈成功)start平均(需要 Failover)start最坏T_{restart} = \begin{cases} 0 & \text{最好(自愈成功)} \\ start & \text{平均(需要 Failover)} \\ start & \text{最坏} \end{cases}

注意:平均情况假设需要进行故障切换。如果 PG 能够快速自愈,则整体 RTO 会大幅降低。

阶段 3:从库检测

从库在 loop_wait 周期醒来后检查 DCS 中的 Leader Key 状态。当主库 Patroni 释放 Leader Key 后,从库发现后开始竞选。

时间线:
    租约释放      从库醒来
       |            |
       |←── 0~loop ─→|
  • 最好情况:租约释放时从库恰好醒来,等待 0
  • 最坏情况:租约释放后从库刚进入睡眠,等待 loop
  • 平均情况loop/2
Tstandby={0最好loop/2平均loop最坏T_{standby} = \begin{cases} 0 & \text{最好} \\ loop/2 & \text{平均} \\ loop & \text{最坏} \end{cases}

阶段 4:抢锁提拔

从库发现 Leader Key 空缺后,开始竞选过程,获得 Leader Key 的从库执行 pg_ctl promote,将自己提升为新主库。

  1. 通过 Rest API,并行发起查询,查询各从库的复制位置,通常 10ms,硬编码 2 秒超时。
  2. 比较 WAL 位置,确定最优候选,各从库尝试创建 Leader Key(CAS 原子操作)
  3. 执行 pg_ctl promote 提升自己为主库(很快,通常忽略不计)
选举流程:
  从库A ──→ 查询复制位置 ──→ 比较 ──→ 尝试抢锁 ──→ 成功
  从库B ──→ 查询复制位置 ──→ 比较 ──→ 尝试抢锁 ──→ 失败
  • 最好情况:单从库或直接抢到锁并提升,常数开销 0.1s
  • 最坏情况:DCS API 调用超时:2s
  • 平均情况1s 常数开销
Telect={0.1最好1平均2最坏T_{elect} = \begin{cases} 0.1 & \text{最好} \\ 1 & \text{平均} \\ 2 & \text{最坏} \end{cases}

阶段 5:健康检查

HAProxy 检测新主库上线,需要连续 rise 次健康检查成功。

检测时序:
  新主提升    首次检查    第二次检查   第三次检查(UP)
     |          |           |           |
     |←─ 0~inter ─→|←─ fast ─→|←─ fast ─→|
  • 最好情况:新主提升时恰好赶上检查,(rise-1) × fastinter
  • 最坏情况:新主提升后刚错过检查,(rise-1) × fastinter + inter
  • 平均情况(rise-1) × fastinter + inter/2
Thaproxy={(rise1)×fastinter最好(rise1)×fastinter+inter/2平均(rise1)×fastinter+inter最坏T_{haproxy} = \begin{cases} (rise-1) \times fastinter & \text{最好} \\ (rise-1) \times fastinter + inter/2 & \text{平均} \\ (rise-1) \times fastinter + inter & \text{最坏} \end{cases}

RTO 公式

将各阶段时间相加,得到总 RTO:

最好情况(PG 瞬间自愈)

RTOmin=0+0+0+0.1+(rise1)×fastinter(rise1)×fastinterRTO_{min} = 0 + 0 + 0 + 0.1 + (rise-1) \times fastinter \approx (rise-1) \times fastinter

平均情况(需要 Failover)

RTOavg=loop+start+1+inter/2+(rise1)×fastinterRTO_{avg} = loop + start + 1 + inter/2 + (rise-1) \times fastinter

最坏情况

RTOmax=loop×2+start+2+inter+(rise1)×fastinterRTO_{max} = loop \times 2 + start + 2 + inter + (rise-1) \times fastinter

模型计算

将四种 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 / 5 0 / 3 / 5 0 / 5 / 10 0 / 10 / 20
重启超时 0 / 15 / 15 0 / 25 / 25 0 / 45 / 45 0 / 95 / 95
从库检测 0 / 3 / 5 0 / 3 / 5 0 / 5 / 10 0 / 10 / 20
抢锁提拔 0 / 1 / 2 0 / 1 / 2 0 / 1 / 2 0 / 1 / 2
健康检查 1 / 2 / 2 2 / 3 / 4 3 / 5 / 6 4 / 6 / 8
总计 1 / 24 / 29 2 / 35 / 41 3 / 61 / 73 4 / 122 / 145

与被动故障对比

阶段 主动故障(PG 崩溃) 被动故障(节点宕机) 说明
检测机制 Patroni 主动检测 TTL 被动过期 主动检测更快发现故障
核心等待 start ttl start 通常小于 ttl,但需要额外的故障检测时间
租约处理 主动释放 被动过期 主动释放更及时
自愈可能 ✅ 有 ❌ 无 主动检测可尝试本地恢复

RTO 对比(平均情况):

模式 主动故障(PG 崩溃) 被动故障(节点宕机) 差异
fast 24s 23s +1s
norm 35s 34s +1s
safe 61s 66s -5s
wide 122s 127s -5s

分析:在 fastnorm 模式下,主动故障的 RTO 略高于被动故障,因为需要等待 primary_start_timeoutstart); 但在 safewide 模式下,由于 start < ttl - loop,主动故障反而更快。 不过主动故障有自愈的可能性,最好情况下 RTO 可以极短。

3.4.3.3 - 网络分区

主库与 DCS 网络分区,导致租约过期并触发脑裂防护与故障切换的路径
infographic list-row-simple-horizontal-arrow
data
  title 网络分区故障切换流程
  desc 主库与 DCS 网络分区,Patroni 主动降级防止脑裂,等待 TTL 过期后切换
  items
    - label 主库降级
      desc Patroni 重试超时后主动降级 PG
      icon mingcute/shield-fill
    - label 租约过期
      desc Leader Key TTL 过期
      icon mingcute/close-circle-fill
    - label 从库检测
      desc 从库发现租约过期,开始竞选
      icon mingcute/key-2-fill
    - label 抢锁提拔
      desc 从库抢锁并提升为新主库
      icon mingcute/radar-fill
    - label 健康检查
      desc HAProxy 检测新主上线
      icon mingcute/arrow-up-circle-fill
theme light
  palette antv

RTO 时序图

tooltip: { trigger: axis, axisPointer: { type: shadow }, formatter: $fn:fmt }
legend: { top: 0, itemGap: 12, data: [主库降级, 租约过期, 从库检测, 抢锁提拔, 健康检查] }
grid: { left: 64, right: 24, bottom: 32, top: 40 }
xAxis: { type: value, name: 秒, nameLocation: end, max: 160, axisLine: { show: true }, axisTick: { show: true }, splitLine: { show: true, lineStyle: { type: dashed, opacity: 0.5 } }, minorTick: { show: true, splitNumber: 5 }, minorSplitLine: { show: true, lineStyle: { type: dotted, opacity: 0.2 } } }
yAxis: { type: category, axisLine: { show: true }, axisTick: { show: true }, splitLine: { show: false }, axisLabel: { fontSize: 10, fontFamily: monospace }, data: [wide-max, wide-avg, wide-min, "", safe-max, safe-avg, safe-min, "", norm-max, norm-avg, norm-min, "", fast-max, fast-avg, fast-min] }
series:
  - { name: 主库降级, type: bar, stack: main, barWidth: 20, z: 2, emphasis: { focus: series }, itemStyle: { color: "#76b7b2" }, data: [50, 40, 30, "-", 30, 25, 20, "-", 15, 13, 10, "-", 10, 8, 5] }
  - { name: 租约过期, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#e15759" }, data: [70, 70, 70, "-", 30, 30, 30, "-", 15, 15, 15, "-", 10, 10, 10] }
  - { name: 从库检测, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#edc949" }, data: [20, 10, 0, "-", 10, 5, 0, "-", 5, 3, 0, "-", 5, 3, 0] }
  - { name: 抢锁提拔, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#59a14f" }, data: [2, 1, 0, "-", 2, 1, 0, "-", 2, 1, 0, "-", 2, 1, 0] }
  - { name: 健康检查, type: bar, stack: main, z: 2, emphasis: { focus: series }, itemStyle: { color: "#4e79a7" }, data: [8, 6, 4, "-", 6, 5, 3, "-", 4, 3, 2, "-", 2, 2, 1] }
  - { name: RTO总计, type: bar, barGap: "-100%", barWidth: 20, z: 1, itemStyle: { color: "#888", opacity: 0 }, emphasis: { itemStyle: { opacity: 0 } }, data: [150, 127, 104, "-", 78, 66, 53, "-", 41, 34, 27, "-", 29, 23, 16] }
  - { name: RTO预算, type: bar, barGap: "-100%", barWidth: 20, z: 0, itemStyle: { color: "rgba(0,0,0,0.08)" }, emphasis: { itemStyle: { color: "rgba(0,0,0,0.12)" } }, data: [150, 150, 150, "-", 90, 90, 90, "-", 45, 45, 45, "-", 30, 30, 30] }

故障模型

项目 最好 最坏 平均 说明
主库降级 retry loop + retry loop/2 + retry Patroni 检测分区后重试,超时后主动降级
租约过期 ttl - loop - retry ttl - loop - retry ttl - loop - retry 降级后剩余的 TTL 时间(近似常数)
从库检测 0 loop loop/2 最好:恰好在检测点
最坏:刚错过检测点
抢锁提拔 0 2 1 最好:直接抢锁提升
最坏:API 超时+Promote
健康检查 (rise-1) × fastinter (rise-1) × fastinter + inter (rise-1) × fastinter + inter/2 最好:检查前状态变化
最坏:检查后瞬间状态变化

网络分区与节点宕机的核心区别

场景 Patroni 状态 PostgreSQL 状态 租约处理 脑裂风险
节点宕机(过期故障) 随节点死亡 完全不可用 被动等待 TTL 过期
网络分区(本文场景) 存活但无法访问 DCS 可能仍在运行(需要主动降级) 被动等待 TTL 过期 有,需防护

在网络分区场景中,主库 PostgreSQL 可能仍在运行并接受写入,这会导致 脑裂 问题。 Patroni 通过 主动降级 机制解决:当无法刷新 Leader Key 时,主动将 PostgreSQL 降级为只读或关闭。


时序分析

阶段 1:主库降级

当主库 Patroni 与 DCS 网络分区后,无法刷新 Leader Key,开始重试。

时间线:
  分区发生      检测分区      重试超时      主库降级
     |           |            |            |
     |←── loop ──→|←── retry ──→|
  • 检测延迟:分区发生后,需要等待下一个 loop_wait 周期才能检测到
  • 重试阶段:Patroni 会在 retry_timeout 期间持续重试 DCS 操作
  • 主动降级:重试超时后,Patroni 主动降级 PostgreSQL(防止脑裂)
Tdemote={retry最好(分区恰好在检测前)loop/2+retry平均loop+retry最坏(分区刚好在刷新后)T_{demote} = \begin{cases} retry & \text{最好(分区恰好在检测前)} \\ loop/2 + retry & \text{平均} \\ loop + retry & \text{最坏(分区刚好在刷新后)} \end{cases}

关键设计:Patroni 要求参数满足约束 loop_wait + 2 × retry_timeout ≤ ttl,确保主库在 TTL 过期之前完成降级。

阶段 2:租约过期

主库降级后,Leader Key 仍然存在于 DCS 中,需要等待 TTL 自然过期。

时间线:
  主库降级                   TTL 过期
     |                         |
     |←── ttl - (loop + retry) ──→|

由于主库已经降级,此阶段的等待时间是 TTL 剩余时间。由于分区检测和 TTL 剩余时间是负相关的(分区发生得越早,检测越慢,但 TTL 剩余越长),两者相加是常数:

Texpire=ttlloopretry(近似常数)T_{expire} = ttl - loop - retry \quad \text{(近似常数)}

注意:主库降级 + 租约过期的总时间仍然约等于 ttl,与过期故障相同。

阶段 3:从库检测

从库在 loop_wait 周期醒来后检查 DCS 中的 Leader Key 状态。

时间线:
    租约过期      从库醒来
       |            |
       |←── 0~loop ─→|
  • 最好情况:租约过期时从库恰好醒来,等待 0
  • 最坏情况:租约过期后从库刚进入睡眠,等待 loop
  • 平均情况loop/2
Tdetect={0最好loop/2平均loop最坏T_{detect} = \begin{cases} 0 & \text{最好} \\ loop/2 & \text{平均} \\ loop & \text{最坏} \end{cases}

阶段 4:抢锁提拔

从库发现 Leader Key 过期后,开始竞选过程。

选举流程:
  从库A ──→ 查询复制位置 ──→ 比较 ──→ 尝试抢锁 ──→ 成功
  从库B ──→ 查询复制位置 ──→ 比较 ──→ 尝试抢锁 ──→ 失败
  • 最好情况:单从库或直接抢到锁并提升,≈ 0
  • 最坏情况:DCS API 调用超时,2s
  • 平均情况1s
Telect={0最好1平均2最坏T_{elect} = \begin{cases} 0 & \text{最好} \\ 1 & \text{平均} \\ 2 & \text{最坏} \end{cases}

阶段 5:健康检查

HAProxy 检测新主库上线,需要连续 rise 次健康检查成功。

检测时序:
  新主提升    首次检查    第二次检查   第三次检查(UP)
     |          |           |           |
     |←─ 0~inter ─→|←─ fast ─→|←─ fast ─→|
  • 最好情况(rise-1) × fastinter
  • 最坏情况(rise-1) × fastinter + inter
  • 平均情况(rise-1) × fastinter + inter/2
Thaproxy={(rise1)×fastinter最好(rise1)×fastinter+inter/2平均(rise1)×fastinter+inter最坏T_{haproxy} = \begin{cases} (rise-1) \times fastinter & \text{最好} \\ (rise-1) \times fastinter + inter/2 & \text{平均} \\ (rise-1) \times fastinter + inter & \text{最坏} \end{cases}

RTO 公式

将各阶段时间相加,得到总 RTO。

由于主库降级 + 租约过期 ≈ ttl,网络分区的 RTO 公式与过期故障相同:

最好情况

RTOmin=ttlloop+0.1+(rise1)×fastinterRTO_{min} = ttl - loop + 0.1 + (rise-1) \times fastinterRTOminttlloop+(rise1)×fastinterRTO_{min} \approx ttl - loop + (rise-1) \times fastinter

平均情况

RTOavg=ttl+1+inter/2+(rise1)×fastinterRTO_{avg} = ttl + 1 + inter/2 + (rise-1) \times fastinterRTOavg=ttl+1+inter/2+(rise1)×fastinterRTO_{avg} = ttl + 1 + inter/2 + (rise-1) \times fastinter

最坏情况

RTOmax=ttl+loop+2+inter+(rise1)×fastinterRTO_{max} = ttl + loop + 2 + inter + (rise-1) \times fastinterRTOmax=ttl+loop+2+inter+(rise1)×fastinterRTO_{max} = ttl + loop + 2 + inter + (rise-1) \times fastinter

模型计算

将四种 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

Patroni 约束验证loop + 2×retry ≤ ttl):

模式 loop retry TTL loop + 2×retry 满足约束?
fast 5 5 20s 15s ✓ 安全
norm 5 10 30s 25s ✓ 安全
safe 10 20 60s 50s ✓ 安全
wide 20 30 120s 80s ✓ 安全

四种模式计算结果(单位:秒,格式:min / avg / max)

阶段 fast norm safe wide
主库降级 5 / 8 / 10 10 / 13 / 15 20 / 25 / 30 30 / 40 / 50
租约过期 10 15 30 70
从库检测 0 / 3 / 5 0 / 3 / 5 0 / 5 / 10 0 / 10 / 20
抢锁提拔 0 / 1 / 2 0 / 1 / 2 0 / 1 / 2 0 / 1 / 2
健康检查 1 / 2 / 2 2 / 3 / 4 3 / 5 / 6 4 / 6 / 8
总计 16 / 23 / 29 27 / 34 / 41 53 / 66 / 78 104 / 127 / 150

结论:网络分区的 RTO 与过期故障(节点宕机)相同,因为瓶颈都是 TTL 过期时间。


脑裂防护

网络分区的最大风险是 脑裂:老主库可能仍在运行并接受写入。Patroni 提供多重防护机制:

1. 主库自我降级

Patroni 的核心防护机制:当无法刷新 Leader Key 时,主动降级 PostgreSQL。

# Patroni 伪代码逻辑
if not can_refresh_leader_key():
    retry_until(retry_timeout)
    if still_cannot_refresh():
        demote_postgresql()  # 降级为只读或关闭

2. Linux Watchdog

如果 Patroni 进程卡住无法执行降级,Linux watchdog 会强制重启系统。

# patroni.yml 配置
watchdog:
  mode: required  # 要求 watchdog 可用
  device: /dev/watchdog
  safety_margin: 5

3. Fencing 机制

可以配置 fencing 脚本来强制隔离老主库(如关闭网络接口、停止服务等)。


特殊场景

场景 A:主库与 DCS 分区,从库正常

这是最常见的网络分区场景,本文主要分析此场景。

┌─────────┐         ╳         ┌─────────┐
│  主库   │ ←── 分区 ──→ │   DCS   │
│ Patroni │                   │  etcd   │
└─────────┘                   └─────────┘
                              正常连接
                              ┌─────────┐
                              │  从库   │
                              │ Patroni │
                              └─────────┘
  • 主库 Patroni 无法刷新 Leader Key → 主动降级
  • 从库正常检测到 TTL 过期 → 竞选成为新主库
  • RTO ≈ 过期故障 RTO

场景 B:主库正常,从库与 DCS 分区

┌─────────┐                   ┌─────────┐
│  主库   │ ←── 正常 ──→ │   DCS   │
│ Patroni │                   │  etcd   │
└─────────┘                   └─────────┘
                              分区
                              ┌─────────┐
                              │  从库   │
                              │ Patroni │
                              └─────────┘
  • 主库正常刷新 Leader Key
  • 从库无法参与竞选(但复制仍可继续)
  • 不会触发故障切换,服务继续正常运行

场景 C:所有节点与 DCS 分区

┌─────────┐         ╳         ┌─────────┐
│  主库   │ ←── 分区 ──→ │   DCS   │
│ Patroni │                   │  etcd   │
└─────────┘                   └─────────┘
┌─────────┐         ╳             │
│  从库   │ ←── 分区 ──────────────┘
│ Patroni │
└─────────┘
  • 主库降级,从库无法竞选
  • 集群完全不可用
  • 需要人工干预恢复 DCS 连接

与其他故障对比

故障类型 主库状态 租约处理 RTO 脑裂风险
过期故障 节点宕机 被动等待 TTL 过期 16s ~ 150s
崩溃故障 PG 崩溃,Patroni 存活 重启超时后主动释放 1s ~ 111s
网络分区 存活但与 DCS 隔离 被动等待 TTL 过期 16s ~ 150s 有,需防护
人工切换 正常或故障 直接释放/获取 1s ~ 11s

关键洞察:网络分区的 RTO 与过期故障相同,但需要额外的脑裂防护机制。 确保满足 loop_wait + 2 × retry_timeout ≤ ttl 约束是防止脑裂的关键设计。

3.4.4 - 服务接入

Pigsty 使用 HAProxy 提供服务接入,并提供可选的 pgBouncer 池化连接,以及可选的 L2 VIP 与 DNS 接入。

分离读写操作,正确路由流量,稳定可靠地交付 PostgreSQL 集群提供的能力。

服务 是一种抽象:它是数据库集群对外提供能力的形式,并封装了底层集群的细节。

服务对于生产环境中的 稳定接入 至关重要,在 高可用 集群自动故障时方显其价值,单机用户 通常不需要操心这个概念。


单机用户

“服务” 的概念是给生产环境用的,个人用户/单机集群可以不折腾,直接拿实例名/IP 地址访问数据库。

例如,Pigsty 默认的单节点 pg-meta.meta 数据库,就可以直接用下面三个不同的用户连接上去。

psql postgres://dbuser_dba:[email protected]/meta     # 直接用 DBA 超级用户连上去
psql postgres://dbuser_meta:[email protected]/meta   # 用默认的业务管理员用户连上去
psql postgres://dbuser_view:DBUser.Viewer@pg-meta/meta     # 用默认的只读用户走实例域名连上去

服务概述

在真实世界生产环境中,我们会使用基于复制的主从数据库集群。集群中有且仅有一个实例作为领导者(主库)可以接受写入。 而其他实例(从库)则会从持续从集群领导者获取变更日志,与领导者保持一致。同时,从库还可以承载只读请求,在读多写少的场景下可以显著分担主库的负担, 因此对集群的写入请求与只读请求进行区分,是一种十分常见的实践。

此外对于高频短连接的生产环境,我们还会通过连接池中间件(Pgbouncer)对请求进行池化,减少连接与后端进程的创建开销。但对于 ETL 与变更执行等场景,我们又需要绕过连接池,直接访问数据库。 同时,高可用集群在故障时会出现故障切换(Failover),故障切换会导致集群的领导者出现变更。因此高可用的数据库方案要求写入流量可以自动适配集群的领导者变化。 这些不同的访问需求(读写分离,池化与直连,故障切换自动适配)最终抽象出 服务 (Service)的概念。

通常来说,数据库集群都必须提供这种最基础的服务:

  • 读写服务(primary):可以读写数据库

对于生产数据库集群,至少应当提供这两种服务:

  • 读写服务(primary):写入数据:只能由主库所承载。
  • 只读服务(replica):读取数据:可以由从库承载,没有从库时也可由主库承载

此外,根据具体的业务场景,可能还会有其他的服务,例如:

  • 默认直连服务(default):允许(管理)用户,绕过连接池直接访问数据库的服务
  • 离线从库服务(offline):不承接线上只读流量的专用从库,用于 ETL 与分析查询
  • 同步从库服务(standby):没有复制延迟的只读服务,由 同步备库 /主库处理只读查询
  • 延迟从库服务(delayed):访问同一个集群在一段时间之前的旧数据,由 延迟从库 来处理

接入服务

Pigsty 的服务交付边界止步于集群的 HAProxy,用户可以用各种手段访问这些负载均衡器。

典型的做法是使用 DNS 或 VIP 接入,将其绑定在集群所有或任意数量的负载均衡器上。

pigsty-access.jpg

你可以使用不同的 主机 & 端口 组合,它们以不同的方式提供 PostgreSQL 服务。

主机

类型 样例 描述
集群域名 pg-test 由 infra 节点上的 dnsmasq 解析;pg_dns_target: auto 时,有 VIP 则指向 VIP,否则指向主库 IP
集群 VIP 地址 10.10.10.3 启用 pg_vip_enabled 后,由 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

组合

# 通过集群域名访问(下例假定已启用集群 VIP;未启用时默认直接解析到主库 IP)
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://[email protected]:5432/test # L2 VIP -> 主直接访问
postgres://[email protected]:6432/test # L2 VIP -> 主连接池 -> 主
postgres://[email protected]:5433/test # L2 VIP -> HAProxy -> 主连接池 -> 主
postgres://[email protected]:5434/test # L2 VIP -> HAProxy -> 备份连接池 -> 备份
postgres://[email protected]:5436/test # L2 VIP -> HAProxy -> 主直接连接 (用于管理员)
postgres://[email protected]: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://[email protected]:5432/test # 数据库实例直接连接 (直接指定实例, 没有自动流量分配)
postgres://[email protected]:6432/test # 连接池 -> 数据库
postgres://[email protected]:5433/test # HAProxy -> 连接池 -> 数据库读/写
postgres://[email protected]:5434/test # HAProxy -> 连接池 -> 数据库只读
postgres://[email protected]:5436/test # HAProxy -> 数据库直接连接
postgres://[email protected]:5438/test # HAProxy -> 数据库离线读-写

# 智能客户端:通过URL读写分离
postgres://[email protected]:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=primary
postgres://[email protected]:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=prefer-standby

3.5 - 时间点恢复 —— 数据库的时间机器(PITR)

高可用解决"机器坏了",时间点恢复解决"数据错了"。Pigsty 基于 pgBackRest 提供开箱即用的 PITR 能力,让您可以将集群回滚至恢复窗口内的任意时刻,为人为失误与软件缺陷兜底。

当您不小心删除了数据、表、甚至整个数据库时,时间点恢复(Point-in-Time Recovery,PITR)让您可以回到过去。

—— 这个曾经只有资深 DBA 才能施展的『魔法』,在 Pigsty 的标准配置中零配置开箱即用。


复制不是备份

高可用 可以在硬件故障时自动切换主库,让服务免于中断。但它有一个天然的盲区:复制不是备份

流复制会以毫秒级的延迟,把主库上发生的一切忠实地同步到所有从库 —— 包括那条忘了加 WHEREDELETE, 和那句敲错了目标库的 DROP TABLE。故障切换应对的是"机器坏了";而当"数据错了"的时候,每一个副本上的数据都错得整整齐齐。

数据库的灾难大体可以分为这两类。前者靠冗余解决:多个副本、自动切换,这是高可用的职责范围。 后者的唯一解药是 历史:基础备份与 WAL 归档让数据库回到错误发生之前。这正是时间点恢复所做的事情。

威胁 高可用 延迟集群 时间点恢复
硬件故障,实例宕机 ✔ 自动切换 ✔ 但 RTO 较长
误删数据 / 误删表 / 误删库 ✘ 错误被复制 ✔ 延迟窗口内 ✔ 恢复窗口内任意时刻
软件缺陷批量污染数据 ✘ 错误被复制 ✔ 延迟窗口内 ✔ 可反复尝试不同时间点
整个集群 / 机房级灾难 ✔ 需使用远程备份仓库

三者并非互相替代,而是互相补位:高可用负责秒级止血,延迟集群提供快速反悔窗口,而 PITR 是所有防线失守之后的最终兜底。


时间机器的原理

PITR 并不神秘。数据库本质上是一台状态机:基础备份 是某个时刻状态的完整快照, WAL(预写式日志)则是此后每一次状态变更的完整历史。拥有一份快照,再加上从快照开始的完整历史, 就可以把数据库重放到这段历史所覆盖的 任意时刻 —— 快照决定了您能回到多早,归档的进度决定了您能回到多近。

基础备份 + WAL 归档 = 时间点恢复

这两样原料的生产在 Pigsty 中都是自动编排的:集群初始化时默认尝试执行首次全量备份,主库持续将 WAL 段文件推送至备份仓库归档; 关于快照、历史、恢复目标与时间线的完整模型,请参阅 工作原理


开箱即用

在 Pigsty 的标准配置中,PITR 默认启用:每套 PostgreSQL 集群都带有备份仓库、WAL 归档与恢复工具, 由 pgBackRest 驱动。您也可以用几行声明式配置对备份策略进行深度定制:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pgbackrest_method: minio       # 备份写入 Silo / S3 兼容对象存储(默认为 local 本地仓库)
    pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ]  # 每天凌晨一点执行全量备份

默认使用主库本地磁盘作为备份仓库(/pg/backup),保留最近两个全量备份;每日全备时,恢复窗口约为 24~48 小时。 切换到专用 Silo 集群或外部 S3 对象存储后,备份获得独立于数据库主机的故障域与 AES-256 加密; 按时间保留十四天并每周全备时,恢复窗口约为 14~21 天。只要存储管够,恢复窗口丰俭由人。

恢复同样是声明式的:指定恢复目标,剧本完成停库、还原、重放与重建高可用,业务数据由人验证。

./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": { "time": "2026-07-11 10:00:00+08", "action": "promote" }}'

这个设计与 声明式配置 的理念一脉相承:备份策略是集群定义的一部分, 而"回到过去"也不过是一个 参数


收益与代价

PITR 为数据安全提供的是 完整性可用性 的跃升:

  • RPO(最大数据损失):通常降至分钟级,只丢失最后尚未归档的 WAL。
  • RTO(恢复耗时):从 ∞(永久丢失)降至几十分钟到几小时,取决于备份大小与磁盘/网络带宽。
单实例配置策略 事件 RTO RPO
什么也不做 主机与本地数据同时丢失 永久丢失 全部丢失
基础备份 主机与本地数据同时丢失 取决于备份大小与带宽(几小时) 丢失上次备份后的数据(几小时到几天)
基础备份 + WAL 归档 主机与本地数据同时丢失 取决于备份大小与带宽(几小时) 丢失最后尚未归档的数据

而它的代价,则主要落在另外三处:

  • 机密性:备份本身是额外的数据泄露面,需要加密与访问控制的保护(Pigsty 的远程仓库预设启用 AES-256 加密)。
  • 资源:备份占用存储空间,归档占用网络带宽。zstd 压缩与块级增量可以降低成本,但不能替代容量规划与实测。
  • 复杂度:备份需要管理、监控,以及最容易被忽略的一环 —— 恢复演练。

也要清醒地认识 PITR 的局限:单靠"单机 + PITR",故障时的 RTO 与 RPO 都显著逊色于高可用集群。 所以在严肃的生产环境中,两者应当组合使用 —— 高可用应对硬件故障,PITR 应对删库跑路。


接下来

  • 工作原理:快照与历史、恢复窗口、恢复目标与时间线 —— 建立 PITR 的心智模型
  • 实现架构:pgBackRest 引擎、仓库抽象、归档链路,以及"备份跟随主库"的工程细节
  • 策略权衡:故障域、空间与窗口、备份频率 —— 如何为您的场景设计备份策略
  • 声明式恢复pg_pitr 参数、pgsql-pitr.yml 剧本与 pig pitr 命令行工具
  • 典型场景:误删数据、发布事故、机房灾难 —— 事故发生时如何决策

具体操作手册请参阅任务层文档 PGSQL 备份恢复

3.5.1 - 时间点恢复的工作原理

快照与历史、恢复窗口、恢复目标与时间线:理解 PITR 的四个核心概念,建立正确的心智模型。

如果把数据库看作一台状态机,那么 WAL(Write-Ahead Log,预写式日志)就是它的完整变更历史 —— PostgreSQL 的每一次写入,都会先以日志记录的形式落盘,然后才应用到数据文件上。 这个为崩溃恢复而生的机制带来了一个副产品:只要把某个时刻的数据文件快照保存下来, 再持续保留此后产生的 WAL,就可以把数据库 重放 到这段历史所覆盖的任意时间点。

这就是时间点恢复的全部原理。它不是魔法,而是三个朴素概念的组合:快照(基础备份)、历史(WAL 归档)、目标(恢复到哪一刻)。


快照:基础备份

基础备份(Base Backup)是数据库集群在某一时刻的物理快照,它决定了恢复的 起点。 Pigsty 使用 pgBackRest 制作与管理基础备份,支持三种备份类型:

类型 内容 特点
全量备份(full) 复制整个数据库集群 独立可用,恢复最快,占用空间最大
差异备份(diff) 相对最近一次 全量备份 的变化 恢复需要:全量 + 差异
增量备份(incr) 相对最近一次 任意备份 的变化 空间最省,恢复需要完整备份链

备份通过封装脚本 pg-backup [full|diff|incr] 触发,不带参数时默认执行增量备份, 若仓库中尚无全量备份则自动升级为全量。备份任务由 pg_crontab 参数声明, 写入 postgres 用户的 crontab 定时执行。

基础备份的频率决定了恢复的速度:备份越新,恢复时需要重放的 WAL 就越少。 这是 策略权衡 中的关键变量之一。


历史:WAL 归档

快照只能让您回到备份的那一刻,而 WAL 归档 补全了此后的每一步。 Pigsty 默认在集群上开启归档,由 PostgreSQL 在每个 WAL 段文件(16 MB)写满后触发归档命令,交给 pgBackRest 推送至备份仓库:

archive_mode: 'on'                                            # 开启 WAL 归档
archive_command: 'pgbackrest --stanza=pg-meta archive-push %p' # 交由 pgBackRest 推送
archive_timeout: 300                                          # 低写入时最多五分钟触发切段归档

两个细节值得注意:

  • archive_timeout: 300 给恢复窗口的右边界上了一道保险:只要期间产生过 WAL,即使段文件迟迟写不满, 五分钟后也会触发切段归档,通常把归档延迟控制在分钟级。
  • 异步归档archive-async=y):pgBackRest 使用本地假脱机目录(/pg/spool)异步批量推送 WAL, 避免归档吞吐成为主库写入的瓶颈。Pigsty 将归档队列上限设为 4 GiB —— 队列指主库上尚未归档的 WAL 积压; 仓库长期不可用导致积压超限时,pgBackRest 会丢弃这些 WAL 以保护主库磁盘,代价是归档断链 —— 需要执行新的全量备份才能重新建立 PITR 能力。

归档的清理是自动的:pgBackRest 在过期备份被清除时,一并清理不再被任何备份需要的 WAL 归档。


恢复窗口

快照与历史合在一起,构成了 恢复窗口(Recovery Window)—— 您能够回到的时间范围:

  • 左边界:仓库中最早的那个基础备份的完成时刻 —— 再往前的历史已被保留策略清除。
  • 右边界:最新已归档的 WAL 位置 —— 通常距当前时刻不超过几分钟。

恢复窗口是滑动的:新备份不断产生,旧备份按保留策略过期,窗口随时间整体前移。 在 Pigsty 的仓库预设中,本地仓库保留最近两个全量备份(每日全备时窗口约一至两天), 远程 minio / S3 仓库按时间至少保留十四天。每周全备时,稳态窗口约为十四至二十一天。 窗口的长短本质上是空间与需求的权衡,详见 策略权衡


目标:恢复到哪一刻

恢复窗口内的定位方式不止"时间"一种。PostgreSQL 提供了六类恢复目标,Pigsty 通过 pg_pitr 参数统一封装:

目标类型 说明 典型场景
default 重放全部 WAL,恢复到归档流末尾 整库丢失后的灾难恢复
time 恢复到指定时间戳 误删数据 —— 最常用
xid 恢复到指定事务 ID 精确回退某个错误事务
lsn 恢复到指定 WAL 位点 按日志位置精确定位
name 恢复到命名还原点 事先用 pg_create_restore_point() 打点
immediate 到达一致状态即停止 最快可用,验证备份

set 字段只选择 pgBackRest 从哪个备份集开始还原,并不是 WAL 重放的停止目标。

边界语义

恢复目标默认是 包含(inclusive)的:目标点上的那个事务会被保留。 若要停在目标 之前(例如 xid 正是那个误删事务),使用 exclusive: true, 对应 PostgreSQL 的 recovery_target_inclusive = false

事务是恢复的原子单位:重放停止后,目标点前已提交的事务全部保留,未提交的事务全部回滚 —— 数据库最终呈现的一定是某个一致的瞬间,而不会出现"半个事务"。


时间线

恢复到过去并继续写入,历史就产生了 分叉。PostgreSQL 用 时间线(Timeline)来区分这些平行历史: 每次 PITR 恢复完成并提升后,都会创建一条新时间线,此后产生的 WAL 归属于新时间线,不会覆盖旧历史。

gitGraph
    commit id: "全量备份"
    commit id: "正常写入"
    commit id: "误删数据 ✗"
    commit id: "继续写入"
    branch Timeline-2
    checkout Timeline-2
    commit id: "PITR 恢复至误删前"
    commit id: "新的写入"

时间线的意义在于 可以反悔:旧时间线的 WAL 仍在仓库中,如果发现恢复的时间点选早了, 可以再次恢复到旧时间线上更晚的位置 —— 甚至"回到未来"。除 PITR 外,从库提升(Promote)与故障切换(Failover)同样会产生新时间线。

恢复时可以用 timeline 参数指定目标时间线,Pigsty 默认使用 latest


想知道这套机制在 Pigsty 中如何落地为具体的组件与配置?请继续阅读 实现架构

3.5.2 - 时间点恢复的实现架构

Pigsty 以 pgBackRest 为引擎实现 PITR:仓库抽象、归档链路、调度机制,以及"备份跟随主库"的工程设计。

原理 一页就能讲完,工程却没有那么简单: 归档不能拖垮主库的写入性能,备份放到对象存储上要加密,主从切换之后备份不能中断, 多套集群共用一个仓库时要相互隔离,海量小文件会拖垮备份吞吐……

Pigsty 选择 pgBackRest 作为备份引擎,并把这些工程问题的答案预置在了出厂配置中。 本文说明这套架构的组成:引擎、仓库、链路、调度,以及一个关键设计 —— 备份跟随主库。


备份引擎:pgBackRest

pgBackRest 是 PostgreSQL 生态中事实上的标准备份工具,Pigsty 用它承担三项职责: 执行基础备份(backup)、接收 WAL 归档(archive-push)、执行恢复(restore / archive-get)。 选择它的理由,恰好对应上面那些工程问题:

  • 并行:备份、归档、恢复都支持多进程并行,吞吐可以随核数扩展。
  • 增量:支持差异/增量备份与 块级增量(block incremental),只传输文件内部变化的块。
  • 压缩与加密:内置 zstd 压缩与 AES-256-CBC 加密,密文落盘,仓库泄露不等于数据泄露。
  • 多种仓库:本地磁盘、S3 兼容对象存储(Silo、MinIO、云厂商 OSS)、Azure、GCS、SFTP 皆可作为后端。
  • 打包bundle 特性将海量小文件合并为大对象存储,避免对象存储的小文件惩罚。

在仓库内部,pgBackRest 使用 stanza(节)隔离不同集群的备份。Pigsty 将 stanza 直接映射为集群名 pg_cluster,因此多套集群可以安全地共享同一个备份仓库:

备份仓库
├── backup/
│   ├── pg-meta/          # pg-meta 集群的基础备份
│   └── pg-test/          # pg-test 集群的基础备份
└── archive/
    ├── pg-meta/          # pg-meta 集群的 WAL 归档
    └── pg-test/          # pg-test 集群的 WAL 归档

仓库抽象

备份放在哪里,是备份策略中最重要的决定。Pigsty 把这个决定抽象为两个参数: pgbackrest_method 选择使用哪个仓库, pgbackrest_repo 定义所有候选仓库。默认提供两个开箱即用的选项:

pgbackrest_method: local          # 使用哪个仓库:local,minio,或自定义仓库名
pgbackrest_repo:                  # 仓库定义:https://pgbackrest.org/configuration.html#section-repository
  local:                          # 默认仓库:主库本地文件系统
    path: /pg/backup              # 备份目录,默认挂在主数据盘上
    retention_full_type: count    # 按份数保留全量备份
    retention_full: 2             # 保留最近 2 个全量备份(清理前最多 3 个)
  minio:                          # 可选仓库:Silo / S3 兼容对象存储
    type: s3                      # 使用 S3 兼容协议
    s3_endpoint: sss.pigsty       # 对象存储服务端点(负载均衡域名)
    s3_bucket: pgsql              # 桶名称
    s3_key: pgbackrest            # 访问密钥
    s3_key_secret: S3User.Backup  # 对象存储用户密钥
    storage_ca_file: /etc/pki/ca.crt  # 使用 Pigsty 自签名 CA 验证 HTTPS
    block: y                      # 启用块级增量备份
    bundle: y                     # 小文件打包存储
    cipher_type: aes-256-cbc      # 仓库加密:AES-256-CBC
    cipher_pass: pgBackRest       # 仓库加密密码
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 按时间保留 14 天

v4.5.0 的模板只把 pgbackrest_repo[pgbackrest_method] 选中的那一个字典项渲染为 pgBackRest 的 repo1; 同时列出 localminio 只是定义候选项,并不等于双仓同时备份。

注意两套预置仓库的策略差异:本地仓库 追求简单直接 —— 不加密、不打包、按份数保留; minio 对象存储仓库预设 面向生产 —— 加密、打包、块级增量、按时间保留两周。 这不是随意的默认值,而是对两种使用场景的判断:本地仓库与数据同生共死,重点是快; 对象存储只有部署在数据库主机或站点的故障域之外时才承担容灾职责;此时重点是安全与可追溯。

仓库定义到 pgBackRest 配置的转换是机械的:键名中的下划线替换为连字符,加上 repo1- 前缀, 渲染进 /etc/pgbackrest/pgbackrest.conf。所以 pgBackRest 支持的任何仓库选项都可以直接写进 pgbackrest_repo —— 例如添加一个云上 S3 仓库用于异地冷备:

s3:    # 自定义仓库 ------> /etc/pgbackrest/pgbackrest.conf
  type: s3                        # ----> repo1-type=s3
  s3_endpoint: oss-cn-beijing-internal.aliyuncs.com
  s3_region: oss-cn-beijing       # ----> repo1-s3-region=oss-cn-beijing
  s3_bucket: <your_bucket>        # ----> repo1-s3-bucket=<your_bucket>
  s3_key: <your_access_key>       # ----> repo1-s3-key=<your_access_key>
  s3_key_secret: <your_secret>    # ----> repo1-s3-key-secret=<your_secret>
  s3_uri_style: host              # ----> repo1-s3-uri-style=host
  path: /pgbackrest               # ----> repo1-path=/pgbackrest
  cipher_type: aes-256-cbc        # ----> repo1-cipher-type=aes-256-cbc
  cipher_pass: <your_password>    # ----> repo1-cipher-pass=<your_password>
  retention_full_type: time       # ----> repo1-retention-full-type=time
  retention_full: 90              # ----> repo1-retention-full=90

各类仓库的完整配置方法(Silo、外部 MinIO、阿里云 OSS、AWS S3、版本控制与对象锁定)请参阅 备份仓库


归档与调度

WAL 归档链路在集群初始化时自动接通:只要 pgbackrest_enabled 为真(默认),Patroni 配置模板就会为集群设置 archive_mode: onarchive_command: pgbackrest --stanza=<集群名> archive-push %p,WAL 段从此源源不断地流入备份仓库。

基础备份的生产则有两个入口:

  • 初始备份:集群初始化完成后,Pigsty 默认在主库上尝试执行一次全量备份(留下 /etc/pgbackrest/initial.done 标记,避免重复)。 可通过 pgbackrest_init_backup 关闭。
  • 定时备份pg_crontab 参数声明备份计划,写入 postgres 用户的 crontab。 Pigsty 随附的标准集群配置声明每天凌晨一点的全量备份;角色参数本身的默认值为空列表:
pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ]

pg-backup 是 pgBackRest 的薄封装:自动解析 stanza,执行 pgbackrest backup,并做一件重要的事 —— 角色检查


备份跟随主库

pgBackRest 安装在集群的 所有 节点上,但任何时刻只有 当前主库 实际执行备份与归档: pg-backup 在运行前检查节点角色,从库上直接退出。这个看似简单的设计带来一个重要性质 —— 备份链路与高可用拓扑解耦

  • 所有节点的备份配置完全相同,crontab 也完全相同;
  • 故障切换 后,新主库自动接续后续备份与 WAL 归档,无需人工干预;
  • 备份仓库只有一份由当前主库写入的权威数据流,不存在双写冲突。

仓库在另一个方向上也参与高可用:当使用远程仓库时,Pigsty 将 pgBackRest 注册为 Patroni 的备用副本创建方式 (create_replica_methods)。默认仍先尝试 basebackup,失败后才使用 pgbackrest --delta restore 从仓库拉取数据; 走到这一后备路径时,造从库的流量压力会从主库转移到备份仓库。


性能取舍

出厂配置中还有几处针对性能的预置判断,体现同一个原则:备份为生产让路,恢复全力以赴

配置 默认值 考量
压缩算法 zstd 高压缩比与高吞吐的平衡点,备份体积通常远小于原库
备份/归档并行度 约 1/4 核数(2~4 进程) 备份不与生产负载争抢 CPU
恢复并行度 核数(至多 8 进程) 恢复时争分夺秒,资源全开
异步归档 archive-async=y /pg/spool 假脱机批量推送,归档不阻塞写入
归档队列上限 4 GiB 未归档 WAL 积压超限时丢弃归档,保护主库磁盘不被写满
快速启动 start-fast=y 备份开始时立即执行检查点,不等常规检查点周期
增量恢复 delta=y 恢复时复用数据目录中未变化的文件,大幅缩短 RTO

归档队列上限的具体故障行为见 工作原理


可观测性

备份不被观测,就等于没有备份。每个 PostgreSQL 节点默认运行 pgbackrest_exporter(端口 9854), 将仓库中的备份状态导出为监控指标:最近一次备份的时刻、类型、大小、持续时间、错误状态 —— Grafana 监控面板与告警规则开箱即用。此外还有几个便捷入口:

入口 说明
pb info pgbackrest info 的别名封装,查看仓库中的备份列表
/pg/log/pgbackrest/ 备份、归档、恢复的详细日志
pg-backup 手动触发备份:full / diff / incr

关于备份的日常管理命令,请参阅 管理命令; 理解了架构之后,下一个问题是如何为您的场景选择策略 —— 请继续阅读 策略权衡

3.5.3 - 时间点恢复的策略权衡

备份是一份保险:备在哪里决定容灾等级,保留多久决定恢复窗口,多久备一次决定恢复速度 —— 三个问题定义一份备份策略。

备份本质上是一份保险:保费 是存储空间、网络带宽与管理成本,保额 是灾难来临时能挽回多少数据、多快恢复服务。 和所有保险一样,这里没有免费的午餐 —— 更长的恢复窗口意味着更多的空间,更快的恢复意味着更频繁的备份。

设计备份策略,就是回答三个问题:备在哪里?保留多久?多久备一次?


备在哪里:故障域决定容灾等级

备份仓库的位置是第一个、也是最重要的决定,因为它直接划定了备份能扛住哪个级别的灾难。

本地仓库pgbackrest_method: local)把备份放在主库本地磁盘上。它简单、快速、没有外部依赖, 恢复时走本地 I/O 速度最快 —— 但备份与数据共享同一个故障域:磁盘损毁、主机报废、机器被勒索加密时, 备份大概率与数据一同陪葬。它能对抗的是 逻辑错误(误删、缺陷),而不是 物理灾难

远程仓库pgbackrest_method: minio 或云上 S3)把备份放进独立的故障域。 数据库主机全灭,备份依然健在;配合 AES-256 加密与 Silo 多节点纠删码, 还能对抗仓库侧的磁盘故障,并降低备份介质泄露造成的明文暴露风险。 代价是恢复速度受网络带宽制约,以及多维护一个组件。

场景 推荐仓库 理由
开发、测试、演示 local 零依赖,坏了重建,无须容灾
生产环境 minio(专用 Silo 集群) 独立故障域,加密,多节点纠删码
云上部署 S3 / OSS 等对象存储 免维护,天然异地,成本低廉
高合规要求 S3 版本控制 + 已配置保留期的对象锁定 防篡改、防勒索:锁定版本在保留期内不可被永久删除

一个经常被忽略的角度:备份仓库同时是 安全资产。防勒索的关键不是"有备份", 而是"攻击者拿到数据库主机的最高权限后,依然无法销毁备份" —— 这正是对象存储的版本控制与对象锁定(WORM)的价值所在,详见 备份仓库


保留多久:空间与窗口

恢复窗口的长度由保留策略决定,而保留策略的成本是刚性的:窗口越长,空间越大,没有配置技巧可以绕开。

以一个 100 GB、每日变更 10 GB 的数据库为例(未计压缩):

  • 每日全量,保留两份(本地仓库默认思路):约 200 GB 备份 + 两天 WAL 归档 ≈ 2~3 倍 数据库大小, 换来一至两天的恢复窗口。
  • 每周全量 + 每日增量,按时间保留十四天(远程 minio 仓库预设):稳态低点约三份全量 + 十二份增量 + 十四天 WAL,下一次全量前增至十八份增量与二十一天 WAL;恢复窗口约 十四至二十一天

实际占用通常显著低于这个粗估:zstd 压缩往往能将备份压缩数倍,块级增量(block: y) 使增量备份只存储文件内部真正变化的数据块。但数量级的规律不变 —— 为备份仓库规划 数倍于数据库 的空间是基本前提。

窗口应该多长?一个实用的标尺是:窗口必须覆盖"错误从发生到被发现"的延迟。 误删表通常几分钟内就会被发现,一天的窗口绰绰有余;而缓慢污染数据的软件缺陷、 要到月底对账才暴露的错误,则需要以周计的窗口。“本地一两天、远程至少两周"正是对这两类需求的回应。


多久备一次:频率与恢复速度

恢复耗时(RTO)由两段组成:还原基础备份 的时间加上 重放 WAL 的时间。 备份大小决定前者,备份 频率 决定后者 —— 距离恢复目标最近的那个基础备份越新,需要重放的 WAL 就越少。

WAL 重放是单进程的,而且重放高峰期写入的 WAL 可能比还原备份本身还慢。 对写入繁忙的库,如果恢复目标恰好落在下一次备份之前,“每周全量"可能需要重放接近一周的 WAL —— 这正是增量备份的价值: 以极小的空间代价(块级增量下通常只有全量的百分之几),把"需要重放的历史"每天清零一次。

经验法则:备份窗口允许的前提下,宁可提高备份频率,不要拉长重放距离


两种预设策略

Pigsty 把上述权衡沉淀为两套开箱即用的预设,多数场景可以直接采用或微调:

两套配置是 候选仓库pgbackrest_method 每次选择其中一个,v4.5.0 模板只把被选项渲染为 repo1。 同时保留 localminio 两个字典项不等于双仓备份;真正的 pgBackRest 多仓方案需要额外的显式配置与独立验证。

标准策略:本地仓库 + 每日全量。配置简单,恢复走本地磁盘速度最快,适合开发测试与容灾要求有限的场景:

pgbackrest_method: local               # 备份到主库本地 /pg/backup(默认值,可省略)
pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ]   # 每日凌晨一点全量备份
# 保留最近两个全量备份,恢复窗口约一至两天

生产策略:Silo / S3 远程仓库 + 周全量日增量。独立故障域,AES-256 加密,十四至二十一天窗口,适合严肃生产环境:

pgbackrest_method: minio               # 备份到专用 Silo 集群(或外部 S3)
pg_crontab:                            # 周一全量,其余每日增量
  - '00 01 * * 1 /pg/bin/pg-backup full'
  - '00 01 * * 2,3,4,5,6,7 /pg/bin/pg-backup'
# 按时间至少保留 14 天;周全备时恢复窗口约 14~21 天

空间估算与保留策略的可视化推演,请参阅任务层文档 备份策略


没有演练过的备份,不算备份

最后一个权衡维度不在配置里,而在流程里。备份系统最危险的状态,是"看起来一直在正常运行”: 监控绿灯长明,仓库稳步增长,而没有人知道这些备份 能不能恢复、恢复要多久

把恢复演练纳入例行运维:定期用 克隆恢复 把备份还原成一套新集群 —— 这既是对备份完整性的端到端验证,也是对 RTO 的实测校准,而且不触碰生产集群;演练目标集群仍会被覆盖。 恢复的具体机制与工具,请继续阅读 声明式恢复

3.5.4 - 声明式恢复

恢复不该是深夜里的十几步手工操作:用 pg_pitr 参数声明想回到的时刻,由 pgsql-pitr.yml 剧本或 pig 命令行工具编排执行。

备份系统的全部价值,都在恢复的那一刻兑现。而恢复几乎总是发生在最糟糕的时刻 —— 生产事故、深夜告警、每一分钟都在损失。传统的 PITR 手工流程在这种时刻是残酷的: 停 HA、停库、写恢复配置、执行还原、盯日志、验证位点、重建元数据、拉起集群……十几个步骤环环相扣,任何一步出错都可能雪上加霜。

Pigsty 的答案与 声明式配置 一脉相承:恢复也是声明式的。 您描述想回到的时刻,编排工具负责停库、还原、重放与重新接管。


声明恢复目标

恢复目标用 pg_pitr 参数描述,交给 pgsql-pitr.yml 剧本执行。 最常用的形式只有一行 —— 把集群恢复到指定时间点:

./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": { "time": "2026-07-11 10:00:00+08", "action": "promote" }}'

六类恢复目标 与恢复行为的方方面面,都是这个参数的字段:

pg_pitr:                      # 恢复目标定义(按需声明,字段均可省略)
  cluster: pg-meta            # 从哪个集群的备份恢复(源 stanza),默认为本集群
  type: time                  # 目标类型:default | time | xid | lsn | name | immediate
  time: '2026-07-11 10:00:00+08'  # 恢复到的时间点(与 xid / lsn / name 互斥)
  exclusive: false            # 停在目标之前(排除目标点),默认包含
  action: promote             # 显式提升;指定目标时未声明 action,实际默认为 pause
  timeline: latest            # 目标时间线,默认 latest
  set: latest                 # 从哪个备份集开始还原,默认自动选择
  repo: { ... }               # 临时指定备份仓库(不使用本机配置时)
  backup: false               # 恢复前是否把原数据目录搬到 /pg/data-backup 留作后悔药
  archive: true               # 保留原有归档配置;探索性恢复可设为 false
  db_include: [ ... ]         # 只恢复指定数据库(选择性恢复)
  data: /pg/data              # 恢复到哪个数据目录

完整的字段说明与用法示例请参阅 恢复操作


剧本如何执行

pgsql-pitr.yml 把手工恢复的十几个步骤编排为六个阶段,并支持用 tags 分段执行:

阶段 动作
print 汇总恢复计划:源集群、目标类型、还原命令;只打印,不会暂停等待确认
pause patronictl pause:让 Patroni 进入维护模式,暂停高可用自动干预
stop 依次停止从库与主库的 Patroni 及 PostgreSQL 进程
pitr 渲染恢复配置,执行 pgbackrest restore(增量还原),启动进程重放 WAL,等待进入一致状态并打印控制信息
etcd 清除 etcd 中的旧集群元数据,避免新旧时间线的状态混淆
start 重新拉起 Patroni,恢复高可用自动驾驶,从库重新克隆

几处设计值得注意:

  • 增量还原:还原使用 pgBackRest 的 delta 模式,只重写数据目录中与备份不一致的文件。 对大库而言,这往往把"还原全库"缩短为"还原变化的部分",显著压缩 RTO。
  • 验证而非假设:剧本用 pg_controldata 打印检查点 LSN、时间线与 NextXID;最终仍由人检查业务数据是否正确。
  • 后悔药:声明 backup: true 时,恢复前会把原数据目录完整搬到 /pg/data-backup—— 如果恢复目标选错了,原现场还在。再次以 backup: true 运行会先删除已有的 /pg/data-backup,不要把它当成可反复覆盖的快照。
  • 分阶段执行:谨慎起见,可以用 tags 把恢复拆为三步走:-t down(停集群)、-t pitr(执行还原)、-t up(拉起集群), 每步之间人工检查。pitr 阶段返回只表示数据库已进入一致恢复状态;指定了时间、XID、LSN 或恢复点时,还要确认 WAL 已重放到目标。

恢复到达目标后的行为由 action 决定:promote(提升并开启新时间线)、 pause(暂停在目标点,可检查数据后再决定;指定目标时的实际默认值)、shutdown(停机待命)。 若要保留 pause / shutdown 的人工门,应分阶段执行并在确认后再运行 up;一步式执行应显式选择 promote。 剧本不会替您做"数据对不对"的判断 —— 这是工程师保留的最终决定权。


命令行工具:pig

除了 Ansible 剧本,pig 命令行工具提供了单实例粒度的 PITR 编排 —— 适合在数据库节点上直接操作,无需管理节点与剧本环境:

pig pitr -t "2026-07-11 10:00:00+08"    # 恢复到指定时间点
pig pitr --xid 250000 -X                # 恢复到事务 250000 之前(排除该事务)
pig pitr -d                             # 重放到 WAL 归档末尾(灾难恢复)
pig pitr -I --no-restart                # 只还原并准备 immediate 恢复,PostgreSQL 保持停止

pig pitr 执行单节点恢复编排:预检(校验目标、stanza、备份存在性)、 停止 Patroni 与 PostgreSQL、执行还原、按参数决定是否启动 PostgreSQL、给出恢复后指引。对于 Patroni 托管的数据目录, 恢复后 Patroni 会保持停止,验证数据后再用 pig pt start 恢复 HA 管理;它不会清理 etcd、重建副本或自动重入集群。 默认拒绝任何破坏性的强制停库动作,除非显式指定 --force-stop

更底层的 pig pb 系列命令封装了 pgBackRest 本身:pb info 查看备份、 pb backup 触发备份、pb restore 执行裸还原。这里有一道有意设置的硬边界: 当实例仍由 Patroni 托管时,pig pb restore 会直接拒绝执行 —— 因为 Patroni 会立刻把恢复到一半的库重新拉起,酿成事故。托管实例的恢复,请始终使用 pig pitrpgsql-pitr.yml


原地恢复与克隆恢复

同一套恢复机制,有两种截然不同的用法:

维度 原地恢复 克隆恢复
做法 把生产集群整体回滚到过去 用备份把 另一套集群 恢复到过去
停机 需要(恢复期间服务不可用) 不需要(生产集群不受影响)
影响 目标点之后的 所有 写入都被抹去 不影响源集群;目标集群会被覆盖,可反复尝试不同时间点
适用 整库损毁、灾难恢复、可接受回滚 误删找回、审计取证、恢复演练

克隆恢复的关键是 pg_pitrcluster 字段 —— 它指定 从谁的备份 恢复。 下面的命令把 pg-meta 的历史状态恢复到 pg-test 集群上,生产库全程无感:

./pgsql-pitr.yml -l pg-test -e '{"pg_pitr": { "cluster": "pg-meta", "time": "2026-07-11 10:00:00+08", "archive": false, "action": "promote" }}'

从克隆集群中把误删的表 pg_dump 出来、导回生产,是处理误删除的标准姿势 —— 全库回滚是最后手段,而不是第一反应。克隆恢复的完整流程与善后事项,请参阅 克隆数据库集群


恢复之后

恢复完成不等于事情结束。有三件事应当纳入收尾清单:

  1. 新时间线,新备份:提升后集群运行在新时间线上。尽快执行一次全量备份(pg-backup full), 让恢复窗口在新时间线上重新建立。
  2. 归档状态:探索性恢复后,按 恢复后处理 恢复归档。
  3. 克隆善后:克隆出的新集群与源集群的备份身份(stanza)不一致,需要重建 stanza 后再启用自身的备份, 详见 克隆数据库集群

工具完成机械步骤,剩下的是判断:恢复到哪一刻、用原地还是克隆、数据对不对。 这些决策的框架,请继续阅读 典型场景

3.5.5 - 时间点恢复的典型场景

误删数据、发布事故、审计取证、机房灾难 —— 事故发生时如何选择恢复目标与恢复方式,以及为什么要把事故排练成例行演练。

事故发生时,最贵的不是恢复本身,而是 决策时间。 恢复的机械步骤已经被 工具编排 好了,真正需要人来回答的只有三个问题: 恢复到哪一刻?原地恢复还是克隆恢复?如何验证数据是对的?

本文为最常见的几类事故给出决策框架 —— 最好在事故发生之前读完它。


判断框架

场景 典型问题 推荐方式 恢复目标
误删 / 误更新数据(DML) DELETE / UPDATE 忘加 WHERE 克隆恢复,导回数据 time / xid
误删表 / 库 / Schema(DDL) DROP TABLE / 错误迁移脚本 克隆恢复,导回对象 time / name
发布事故 / 批量污染 缺陷代码批量写坏数据 克隆恢复,比对后决策 time / xid
审计 / 取证 / 复盘 需要查看历史某刻的数据 克隆恢复(只读) time / lsn
整库损毁 / 机房灾难 硬件全灭、勒索加密 原地恢复或异地重建 default / time

贯穿所有场景的两条原则:

  • 先止损,再恢复。第一动作永远是阻止错误继续扩散:暂停问题应用、吊销问题账号的写权限。 恢复窗口在流逝,但慌乱中启动错误的恢复造成的二次伤害更大。
  • 克隆恢复是默认选项。它不触碰生产集群、可以反复尝试不同时间点、可以先验证再动手;代价是目标集群会被覆盖。 只有当集群已经整体不可用 —— 也就是"没有什么可失去"的时候,原地恢复才是首选。
flowchart TD
    A["发现数据错误"] --> B["止损:暂停错误来源"]
    B --> C{"生产集群还能服务吗?"}
    C -->|能| D["克隆恢复:另起集群回到错误前<br/>验证后导回数据"]
    C -->|不能| E["原地恢复:整体回滚<br/>或在新硬件上异地重建"]
    D --> F["善后:重建备份,复盘"]
    E --> F

误删数据(DML)

没加 WHEREDELETE、写错条件的 UPDATE、逻辑出错的批处理脚本 —— 这是 PITR 最高频的用武之地。

关键动作是 定位错误时刻:从应用日志、PostgreSQL 日志或监控曲线中找到错误发生的时间 (若启用了 审计日志,定位会更加精确)。 如果能定位到确切的事务号,xid 目标配合 exclusive 可以精确地停在错误事务 之前,一条数据都不多丢:

# 已知误删发生在 10:15 左右:克隆恢复到 10:14
./pgsql-pitr.yml -l pg-test -e '{"pg_pitr": { "cluster": "pg-meta", "time": "2026-07-11 10:14:00+08", "archive": false, "action": "promote" }}'

# 已知误删事务号为 250000:精确停在该事务之前
./pgsql-pitr.yml -l pg-test -e '{"pg_pitr": { "cluster": "pg-meta", "xid": "250000", "exclusive": true, "archive": false, "action": "promote" }}'

数据在克隆集群中验证无误后,用 pg_dump / COPY 把受影响的行导回生产库。

如果集群配置了 延迟集群,且误删仍在延迟窗口之内, 直接从延迟从库读取数据更快 —— 这是 PITR 之外的第二条时间通道。


误删对象(DDL)

DROP TABLEDROP DATABASE、跑错环境的迁移脚本。与 DML 场景同理,但有一个更强的约束: DDL 误删几乎不应该原地恢复 —— 为了找回一张表就把整个库回滚到过去,等于把误删之后所有正常业务写入一并抹掉。

标准流程是克隆恢复:另起集群恢复到误删之前,校验对象完整性,pg_dump 导出误删的表 / 库,导回生产。 如果变更前用 pg_create_restore_point() 打过还原点,name 目标可以让"恢复到变更之前"变得毫无歧义 —— 在高危变更前打点,是成本几乎为零的好习惯。


发布事故与批量污染

某次发布带着缺陷上线,几个小时里持续写入错误数据 —— 这类场景的难点不是恢复,而是 影响范围不清楚

克隆恢复在这里的价值是提供一个 干净的对照组:把克隆集群恢复到发布之前,与生产库做数据比对, 量化污染范围,再决定是修复数据(把正确值从克隆库导回)还是整体回滚(切换到克隆集群)。 因为克隆恢复可以反复执行,您可以多次尝试不同时间点,逐步逼近"最后一个干净时刻"。


审计与取证

“上个月月底这个账户的余额是多少?"—— 有些问题只有历史数据能回答。 克隆恢复到指定时刻、显式限制为只读查询、用后即焚,是回答这类问题的标准做法: 不影响生产、不修改历史、可审计可复现。指定时间、LSN、XID 或命名恢复点并配合 action: pause, 数据库可以停在目标点上供检查,而不推进到新时间线;但 pause 本身不会创建克隆集群,也不会配置只读权限, 目标由 inventory limit 与 cluster 源字段共同决定,只读约束需要另行实施。immediate 只表示尽快恢复到首个一致点,不用于选择历史时刻。


机房级灾难

主从全灭、磁盘阵列损毁、勒索软件加密了所有主机 —— 高可用在这类灾难面前无能为力,PITR 是最后一道防线。 其中最关键的前提是:备份仓库在灾难的故障域之外。使用 远程备份仓库 时, 数据库主机全部丢失也不影响恢复;使用本地仓库时,这道防线并不存在。

恢复流程是在新硬件上重建:准备新节点,恢复配置清单(它本身应在 git 中,见 声明式配置), 将集群指向远程仓库,恢复到归档流末尾:

./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": {"action": "promote"}}'  # 未指定恢复目标:重放到归档流末尾并显式提升

配置清单与远程备份仓库是重建的两块核心拼图,但不是全部:还需要 Pigsty 安装介质或软件仓库、 备份访问凭据与加密口令、PKI/CA、自定义文件,以及 DNS 和其他外部依赖。配置清单可以纳入私有版本控制, 秘密与私钥则应加密保存并与备份分离 —— 这才是独立故障域真正的意义。


把事故排练成肌肉记忆

以上每个场景的第一次实战,都不应该发生在生产事故中。

克隆恢复给了您一个不触碰生产的演练场:可以把可访问的集群备份恢复成一套新集群,验证、计时、销毁;目标集群会被覆盖。 建议把恢复演练作为例行运维的一部分 —— 每季度(或每次重大架构变更后)完整走一遍克隆恢复流程,回答三个问题:

  1. 备份可用吗? 端到端还原成功,数据完整。
  2. RTO 是多少? 实测还原耗时,而不是估算 —— 数据库在增长,去年的答案今年未必成立。
  3. 人熟练吗? 值班工程师能否不翻文档完成恢复。

没有演练过的备份只是一种心理安慰。演练过的备份,才是真正的时间机器。

具体操作步骤请参阅 恢复操作克隆数据库集群

3.6 - 监控系统

Pigsty 的监控系统是如何架构与实现的,被监控的目标对象又是如何被自动纳入管理的。

Pigsty 监控系统由指标、日志与告警三部分组成,默认随部署开箱可用;其中日志与告警也是 审计与追溯 的重要输入。 它既可以监控由 Pigsty 托管的数据库集群,也可以监控已有 PostgreSQL 集群与外部 RDS 服务。


监控目标

Pigsty 监控覆盖的核心对象包括:

  • PostgreSQL 集群与实例(SQL 性能、连接、复制、事务、检查点、WAL)
  • 基础设施组件(Grafana、VictoriaMetrics、Alertmanager、Nginx 等)
  • 宿主机节点(CPU、内存、磁盘、网络、内核)
  • 关键中间件(ETCD、MINIO、REDIS、JUICE、VIBE 等)

技术栈

组件 作用
Grafana 可视化监控面板、统一入口、告警视图
VictoriaMetrics 时序指标采集、存储与查询
VictoriaLogs 结构化日志采集、索引与检索
VMAlert + Alertmanager 告警规则执行与消息通知
Exporter / Agent 业务与系统指标暴露、日志转发

纳管方式

Pigsty 支持三种监控纳管方式:

模式 适用场景 入口
FULL 数据库由 Pigsty 直接部署与托管 PGSQL 监控系统
MANAGED 现有 PostgreSQL 集群,节点可 SSH 管理 监控现有集群
RDS 仅能通过连接串访问的云数据库 监控 RDS

继续阅读

3.7 - 安全合规

Pigsty 以安全即代码的方式管理认证、授权、加密、审计与备份恢复,并提供从默认配置到生产加固的清晰路径。

数据库通常是信息系统中最敏感的组件:它保存着最有价值的数据,也因此是攻击与故障后果最严重的地方。 数据库安全并不是某个可以一键开启的功能,而是一系列问题的答案之和:谁能连进来?连进来能做什么?流量会不会被窃听?操作有没有留痕?数据坏了、丢了、被删了,还能不能恢复?

Pigsty 把这些问题的答案沉淀为一套 开箱即用的安全基线,并用 声明式配置 的方式加以管理: HBA 规则角色与权限、证书与加密、备份与审计策略,全部以 参数 的形式在 配置清单 中声明,由幂等剧本渲染落地。

这种 安全即代码(Security as Code)的做法本身就是一项重要的安全实践:安全策略可以被版本控制、评审与回溯,配置清单为多实例环境提供统一基线。 当审计者问“谁能访问这个数据库”时,可以先从一份可读的 YAML 声明出发,再用实际生成的 HBA 与数据库授权验证它是否已经生效。


安全即代码

在传统运维中,安全配置散落在各个角落:某台服务器上的 pg_hba.conf,某位 DBA 手工执行过的 GRANT 语句,某次应急时临时放开的防火墙规则。 时间一长,文档与实际状态容易出现偏差,也很难快速确认各实例正在使用哪一版规则。

Pigsty 的做法不同:安全策略是集群定义的一部分,与集群的其他属性写在一起。

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_users:                     # 谁可以登录:账号、角色与过期时间
      - { name: dbuser_app ,password: '<独立随机口令>' ,roles: [dbrole_readwrite] ,expire_in: 365 }
    pg_databases:                 # 数据库及其隔离策略
      - { name: app ,owner: dbuser_app ,revokeconn: true }
    pg_hba_rules:                 # 谁能从哪里、以何种方式连接
      - { user: dbuser_app ,db: app ,addr: 10.1.0.0/16 ,auth: ssl ,order: 50 ,title: 'app access via ssl' }

用户、权限、HBA 规则以声明的方式描述,剧本负责把它们幂等地应用到集群的每个实例上: 新加入的实例可以沿用同一套策略,git 提交历史也可以记录安全配置的变更。手工执行的 GRANT、运行时参数修改和节点文件变更仍可能造成漂移,因此生产环境还需要定期核对实际状态。


默认安全基线

合理的默认值可以减少遗漏。以下能力在 Pigsty 默认配置下即处于启用状态:

能力 默认行为 相关参数
密码哈希 新设置或更新的 PostgreSQL 口令使用 SCRAM-SHA-256 pg_pwd_enc
数据校验和 集群初始化时启用页级校验和,捕获静默数据损坏 pg_checksum
服务端 TLS PostgreSQL 服务器证书就位并启用 ssl,可以接受 TLS 连接 -
本地 CA 自动创建自签名 CA,为受管组件签发证书 ca_create
etcd 加密认证 客户端与对等通信 TLS,RBAC 密码认证 etcd_root_password
MINIO 对象存储 HTTPS Silo 备份流量默认走 HTTPS minio_https
Nginx HTTPS Web 入口默认同时监听 80、443 nginx_sslmode
HBA 规则集 分层放行:本地 ident,内网口令,公网管理员强制 SSL pg_default_hba_rules
角色与权限 四层角色模型与默认权限模板,提供最小权限基线 pg_default_roles
备份恢复 pgBackRest 默认启用,本地仓库保留两份全量备份 pgbackrest_enabled
防火墙 zone 模式:信任内网网段,公网仅放行必要端口 node_firewall_mode
受限 sudo 数据库系统用户的 sudo 被限制在必要命令集内 pg_dbsu_sudo

有所取舍的加固项

默认配置面向运行在受信内网中的部署,一部分安全能力需要显式启用 —— 它们或有性能与兼容性代价,或需要用户提供额外的决策:

  • 默认配置与示例模板包含 文档公开的默认密码,方便快速上手与本地测试。生产部署应先用 ./configure -g 随机化其支持的凭据,再检查 pgBackRest 加密口令、ha/safe 中的 Silo 用户和自定义值。
  • Patroni REST APIPgBouncer 的 TLS 默认未启用(patroni_ssl_enabledpgbouncer_sslmode),可以使用已经签发的证书显式开启。
  • 密码强度检查passwordcheck)与 审计扩展pgaudit)默认未启用;使用前应确认软件包可用,再完成预加载与策略配置。
  • SELinux 默认处于 permissive 模式;演示配置的防火墙额外放行了 5432 端口,生产环境应当移除。
  • 本地备份仓库默认 不加密;远程 minio 仓库预设默认启用 AES-256 加密,但需要修改默认加密口令。

安全加固模板 ha/safe 将 TLS、证书认证、密码检查和备份加密等配置组合在一起, 并配合面向一致性优先业务的 CRIT 参数模板 给出一份可直接修改的示例。模板中的公开凭据、审计扩展与故障模型仍需逐项确认。 完整的升级路径见 安全模型


本章内容

章节 回答的问题
安全模型 信任的根在哪里?防线有几道?如何从默认基线逐步加固?
身份认证 谁能连进来?如何证明身份?HBA 规则如何声明与生效?
访问控制 连进来之后能做什么?最小权限如何成为默认行为?
加密通信 流量如何加密?证书由谁签发、如何分发与轮换?
数据安全 数据如何保证完整、可恢复、保密、可追溯?
合规实践 如何把安全能力映射到等保与 SOC 2 的控制要求?

相关话题

概念层之外,以下页面提供操作层面的安全内容:

3.7.1 - 安全模型

Pigsty 的信任边界与纵深防御体系:管理节点作为高信任控制面,从默认基线逐步完成生产加固。

在讨论具体的安全特性之前,值得先回答两个更基本的问题:信任的根在哪里,以及 防线有几道。 前者决定了你应该重点保护什么,后者决定了当某一道防线失守时,你还剩下什么。


信任边界

Pigsty 是一套基于 Ansible 的声明式部署系统,它的信任模型与其他控制平面系统类似:管理节点 就是控制平面,也是整个部署中最需要保护的节点。

角色 掌握的资产与权限
管理节点(Admin Node) 配置清单 pigsty.yml(通常包含系统与业务凭据)、CA 私钥、对所有节点的 SSH 管理权限
INFRA 节点 监控告警、DNS、Nginx 入口、软件仓库
数据库节点 数据库实例、本地 dbsu、受限 sudo
客户端 数据库凭据或客户端证书,经服务端口、HBA 与认证进入

这些角色掌握的能力不同,并不是简单的线性等级。其中三份资产尤其关键:

  1. 配置清单 pigsty.yml:包含所有组件的密码与凭证。应当严格控制管理节点与配置仓库(如果使用 git 管理)的访问权限。
  2. CA 私钥 files/pki/ca/ca.key:整个部署的信任锚点,持有它就可以签发任意受信证书。文件权限为 0600,存放于 0700 的目录中,建议离线备份。
  3. 管理用户的 SSH 私钥:管理节点通过 SSH 免密 sudo 管理所有纳管节点,这份私钥等价于所有节点的 root 权限。

Pigsty 的 安全策略 对此有明确表述:需要管理节点访问权限、或已持有 pigsty.yml 与 CA 私钥才能实施的攻击,不被视作安全漏洞 —— 这些是设计上的高信任控制面,必须以相应的等级加以保护。


七道防线

纵深防御不依赖某一项机制独立解决所有问题,而是让不同控制相互补充。 Pigsty 的安全能力可以归纳为七道防线:

# 防线 机制 详见
1 网络边界 防火墙分区、监听地址收敛、统一入口 本页下文
2 传输加密 本地 CA、组件间 TLS 加密通信
3 身份认证 HBA 规则集、SCRAM 密码、客户端证书 身份认证
4 访问控制 角色体系、默认权限、数据库隔离 访问控制
5 主机安全 SELinux、受限 sudo、专用系统用户 本页下文
6 数据安全 校验和、备份与加密、PITR、防误删 数据安全
7 审计追溯 DDL 与连接日志、审计扩展、集中日志 数据安全

其中第 2、3、4、6、7 道防线各有专门章节展开,这里补充说明网络与主机两道防线。

网络边界

Pigsty 在节点置备时默认启用防火墙(node_firewall_mode 默认为 zone 模式),按操作系统使用 firewalldufw 实现: 内网网段(10.0.0.0/8172.16.0.0/12192.168.0.0/16,由 node_firewall_intranet 定义)加入信任区, 公网侧仅放行 node_firewall_public_port 声明的端口,默认为 22(SSH)、80443(Web)。

默认演示配置 pigsty.yml 中额外放行了 5432 端口以便本地体验,生产部署通常应当移除。确需直接接入数据库时,应通过安全组、防火墙与 HBA 将来源限制到明确网段。

数据库默认监听所有地址(pg_listen0.0.0.0),实际访问范围由监听地址、防火墙与 HBA 共同决定。对于要求更严格的场景,可以将监听收敛到特定地址:

pg_listen: '${ip},${vip},${lo}'   # 仅监听主机 IP、集群 VIP 与本地环回地址

默认防火墙不会直接向公网开放 Grafana、VictoriaMetrics 等 Web 基础设施,外部访问通常经由 Nginx 门户 反向代理接入; 数据库流量则通过 HAProxy 提供的 服务 端口接入。入口越少,越容易加固,也越容易审计。

主机安全

主机层的核心原则:每个系统用户只拥有完成本职工作所需的最小权限

  • 数据库超级用户 postgrespg_dbsu)默认 不设密码,只能通过本地 ident 认证登录数据库,无法远程以超级用户身份进入。 它的 sudo 权限由 pg_dbsu_sudo 控制,默认为 limit 模式:仅允许免密执行数据库相关服务的 systemctl 操作与日志查看,而不是完整的 root 权限。
  • 管理用户(node_admin_username,默认 dba)供运维人员与剧本使用,默认拥有免密 sudo(nopass); 安全敏感的环境可通过 node_admin_sudo 改为 all(sudo 需输入密码)或 limit(限制命令集)。
  • SELinux 由 node_selinux_mode 控制,默认为 permissive 模式:记录违规行为但不阻断,为切换到 enforcing 强制模式积累基线。

Pigsty 不接管 SSH 服务端配置:禁用口令登录、限制 root 远程登录等操作系统级加固不在剧本管理范围内,应当纳入您自己的主机安全基线。


加固梯度

安全水位的提升不必一步到位。Pigsty 提供了一条清晰的升级路径,每一档都建立在前一档之上:

第一档:默认基线。开箱即用的安全能力包括 SCRAM 密码、数据校验和、本地 CA 与组件证书、分层 HBA、四层角色模型、默认备份和防火墙分区。 它适合受信内网中的开发、测试与验证环境;生产部署还需要继续检查凭据、网络边界和客户端验证。

第二档:随机凭证。默认密码是公开写在文档里的,任何暴露于网络的部署都必须更换。在生成配置时加上 -g 选项,可以随机化配置向导识别的内置参数和示例凭据:

./configure -g    # --generate:随机化向导识别的默认凭据

该选项不会替换 pgBackRest 的 cipher_passha/safe 中的全部 Silo 示例凭据,也不会处理用户自定义值。完整范围见 默认凭证清单

第三档:策略加固(ha/safe 模板)。配置模板 conf/ha/safe.yml 将多项安全配置组合为一份可以继续定制的参考:

  • TLS 与证书认证:主要 TCP HBA 规则使用 ssl,公网管理员使用客户端证书;PgBouncer 启用 require,Patroni API 启用 HTTPS。本地 ident 与部分 localhost 口令规则仍然保留。
  • 密码策略:显式预加载 passwordcheck,并为内置用户声明 expire_in;模板中的示例口令仍需在部署前检查和替换。
  • 攻击面收敛:监听地址收敛至 ${ip},${vip},${lo},监控与管理账号从公网访问连接池被显式拒绝。
  • 备份加密:pgBackRest 使用远程 minio 仓库预设并启用 AES-256-CBC;pgBR.${pg_cluster} 是可预测的示例值,必须替换。
  • 安全扩展:安装 passwordcheckcredcheckpgauditpgsodiumanonymizer 等安全相关扩展;安装不等于预加载、创建或配置。

第四档:内核加固(crit.yml 参数模板)。safe 模板默认为集群指定了面向核心业务的 CRIT 参数模板,它相对通用的 oltp 模板:

  • 强制启用数据校验和,不受 pg_checksum 参数影响;
  • 启用严格同步复制(synchronous_mode_strict),没有可用同步副本时阻塞需要同步确认的写入;
  • 记录连接与断开事件;PostgreSQL 18 还会区分连接接收、认证与授权阶段;
  • watchdog 配置为 automatic,仅在系统存在可用设备时启用。

严格同步模式以不丢失已确认事务为目标,但仍依赖 synchronous_commit、同步副本状态和故障切换条件;RPO 需要通过目标拓扑上的故障演练验证。

也可以不使用完整模板,只挑选需要的加固项,声明在集群或全局参数中:

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 }
  vars:
    pg_cluster: pg-meta
    pg_conf: crit.yml                    # 使用 crit 内核参数模板
    patroni_ssl_enabled: true            # Patroni API 启用 HTTPS
    pgbouncer_sslmode: require           # Pgbouncer 强制 TLS
    pg_listen: '${ip},${vip},${lo}'      # 监听地址收敛
    pg_libs: '$libdir/passwordcheck, pg_stat_statements, auto_explain'  # 密码强度检查

接下来

3.7.2 - 身份认证

Pigsty 以声明式方式管理 PostgreSQL 与 PgBouncer 的 HBA 规则,配合 SCRAM 密码与客户端证书,回答“谁能连进来、如何证明身份”。

PostgreSQL 使用 pg_hba.conf 进行 基于主机的认证(Host-Based Authentication):谁(用户)、从哪里(来源地址)、访问什么(数据库)、需要以何种方式证明身份(认证方法)。

这套机制足够强大,但在集群环境中手工维护的成本很高:主库与从库可能需要不同规则,配置文件又分布在每个实例的数据目录中。 如果缺少统一声明和刷新流程,各实例的规则很容易发生漂移。

Pigsty 的答案与 声明式配置 一脉相承:HBA 规则是配置清单的一部分,由剧本统一渲染与下发。


HBA 即代码

集群的 HBA 规则由两组参数拼接而成:全局默认规则 pg_default_hba_rules 与集群自定义规则 pg_hba_rulesPgBouncer 连接池 另有独立的两组对应参数(pgb_default_hba_rulespgb_hba_rules)。

每条规则可以用两种形式书写。别名形式 是推荐的方式,一条规则一行,语义一目了然:

pg_hba_rules:
  - { user: dbuser_app ,db: app ,addr: 10.1.0.0/16 ,auth: ssl ,order: 50 ,title: 'app user access via ssl' }

原始形式 则直接给出 pg_hba.conf 的原文,用于表达别名覆盖不了的特殊规则。

除了四要素之外,规则还有两个控制字段:

  • order:渲染顺序。HBA 按“先匹配先生效”的原则工作,顺序即优先级。约定 0-99 保留给用户的高优先级规则,100-999 是默认规则集,未指定 order 的规则排在最后。
  • role:实例角色过滤。commondefault 规则对所有实例生效;primaryreplicaofflinestandbydelayed 规则仅在对应角色的实例上启用; role: offline 的规则还会额外下发给标记了 pg_offline_query 的实例。同一份声明渲染到不同实例,得到的是各自角色对应的规则 —— 主从差异不再需要手工维护。

修改声明后,使用封装好的脚本应用变更,规则会被重新渲染并重载生效:

bin/pgsql-hba pg-meta          # 重新渲染并应用 pg-meta 集群的 HBA 规则

pg_hba_rules 用于追加规则,不会自动收窄范围更宽的默认规则。需要建立更严格的边界时,应同时审查 pg_default_hba_rules,并在变更后检查各实例实际生成的 pg_hba.conf


地址与认证别名

别名形式的价值在于把常见场景抽象为语义化的词汇。addr 字段的别名展开为具体的地址块:

别名 展开为 含义
local Unix Socket 仅本地套接字
localhost Unix Socket、127.0.0.1/32::1/128 本机
admin <admin_ip>/32 管理节点
infra 各 INFRA 节点的 /32 地址 基础设施节点
cluster 集群各成员的 /32 地址 集群内部
intra 10.0.0.0/8172.16.0.0/12192.168.0.0/16 内网网段,可通过 node_firewall_intranet 定制
world 0.0.0.0/0::/0 任意地址
CIDR 地址 原样保留 自定义网段

auth 字段的别名决定认证方法,以及是否强制 TLS 连接:

别名 认证方法 说明
deny reject 显式拒绝
trust trust 无条件放行,慎用
pwd scram-sha-256md5 pg_pwd_enc 而定,默认 SCRAM
sha scram-sha-256 强制 SCRAM
md5 md5 兼容旧客户端
ssl hostssl 与密码认证 密码认证,且必须走 TLS
ssl-sha hostsslscram-sha-256 TLS 与强制 SCRAM
cert hostsslcert 客户端证书认证
identos ident(PgBouncer 中为 peer 操作系统用户映射
peer peer 本地操作系统用户

用户字段支持四个占位符,渲染时替换为实际用户名:${dbsu}(超级用户)、${repl}(复制用户)、${monitor}(监控用户)、${admin}(管理用户); +role 前缀表示匹配该角色的所有成员。

这里还要区分两件事:auth: ssl 只要求连接使用 TLS,并不要求客户端验证服务端身份。安全敏感的客户端还应使用 sslmode=verify-full 和可信 CA,详见 加密通信


默认规则解读

Pigsty 的默认 HBA 规则集体现了一个简单的原则:来源越远,要求越严。以下是 PostgreSQL 侧的默认规则(源码原文):

pg_default_hba_rules:             # postgres default host-based authentication rules, order by `order`
  - {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  ,order: 100}
  - {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' ,order: 150}
  - {user: '${repl}'    ,db: replication ,addr: localhost ,auth: pwd   ,title: 'replicator replication from localhost',order: 200}
  - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: pwd   ,title: 'replicator replication from intranet' ,order: 250}
  - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: pwd   ,title: 'replicator postgres db from intranet' ,order: 300}
  - {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' ,order: 350}
  - {user: '${monitor}' ,db: all         ,addr: infra     ,auth: pwd   ,title: 'monitor from infra host with password',order: 400}
  - {user: '${admin}'   ,db: all         ,addr: infra     ,auth: ssl   ,title: 'admin @ infra nodes with pwd & ssl'   ,order: 450}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: ssl   ,title: 'admin @ everywhere with ssl & pwd'    ,order: 500}
  - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: pwd   ,title: 'pgbouncer read/write via local socket',order: 550}
  - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: pwd   ,title: 'read/write biz user via password'     ,order: 600}
  - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: pwd   ,title: 'allow etl offline tasks from intranet',order: 650}

逐层来看:

  • 本地最受信任:超级用户 postgres 只能通过本地 Unix Socket 以 ident 方式进入 —— 不需要密码,但也无法在远程使用。这就是为什么 dbsu 默认不设密码:不存在可以被窃取的口令。
  • 内网次之:复制与业务账号在内网使用 SCRAM 口令认证;监控和管理用户的远程访问主要面向 INFRA 节点。
  • 公网最严:默认只有管理员可以从任意地址访问,且必须同时提供口令与 TLS 连接。

PgBouncer 侧的默认规则更保守一层:监控与管理账号从公网访问连接池会被显式 deny,业务用户则限定在本机与内网。

需要特别说明,默认 +dbrole_offline 规则没有设置 role,因此会应用到所有实例。要把离线用户限制到 pg_role: offline 或设置了 pg_offline_query: true 的实例,必须在对应 HBA 规则上显式增加 role: offline

这份默认规则集是“可用性优先”的取舍:业务账号在内网使用口令认证即可接入。 ha/safe 模板将主要 TCP 规则改为 ssl,管理员从非内网位置访问必须持有客户端证书(cert);本地 ident 与部分 localhost 口令规则仍然保留。


密码策略

Pigsty 默认使用 PostgreSQL 官方推荐的 scram-sha-256 算法存储密码(pg_pwd_enc),仅在需要兼容老旧客户端时才应降级为 md5

密码处理链路会在执行 ALTER USER ... PASSWORD 前临时关闭语句日志(SET log_statement TO 'none'),避免口令进入 PostgreSQL 日志。 但明文口令仍会出现在配置清单中,渲染后的用户 SQL 也会以 0640 权限写入 /pg/tmp/pg-user-<name>.sql;相关任务没有完整使用 Ansible no_log。因此应限制管理节点、配置仓库和自动化输出的访问,并避免对含凭据任务使用 --diff

密码强度默认不做强制,需要时可以预加载 passwordcheck 扩展,或使用规则更丰富的 credcheck 扩展:

pg_libs: '$libdir/passwordcheck, pg_stat_statements, auto_explain'   # 拒绝弱密码

ha/safe 模板显式设置了上述 pg_libs;单独选择 CRIT 参数模板不会自动加载 passwordcheck

账号有效期通过用户定义中的 expire_in(自创建起天数)或 expire_at(截止日期)声明,配合组织的密码轮换制度使用:

pg_users:
  - { name: dbuser_app ,password: '<独立随机口令>' ,roles: [dbrole_readwrite] ,expire_in: 365 }

证书认证

口令终究可能被钓鱼、复用或撞库。对管理员这样的高权限账号,可以在 HBA 中使用 auth: cert 要求 客户端证书认证: 客户端必须持有由本地 CA 签发、CN 与数据库用户名一致的证书才能建立连接。在 HBA 仅接受 cert 的前提下,单独泄露口令不足以通过认证。

使用内置的 cert.yml 剧本签发客户端证书:

./cert.yml -e cn=dbuser_dba            # 为 dbuser_dba 签发客户端证书,默认有效期 20 年
./cert.yml -e cn=dbuser_dba -e expire=365d   # 或指定较短的有效期

签发的证书位于 files/pki/misc/<cn>.keyfiles/pki/misc/<cn>.crt。客户端私钥应通过受控渠道交付;客户端仍需使用 verify-full 验证数据库服务端,证书体系详见 加密通信


连接池与组件 API

数据库本体之外,还有两类入口需要认证:

PgBouncer 连接池 使用独立的 HBA 规则集与用户列表。默认关闭 pgbouncer_auth_query,此时只有声明了 pgbouncer: true 的用户才会进入 userlist.txt 并通过连接池认证;启用动态认证查询后,应重新评估可登录用户范围。

Patroni REST API 承载高可用控制指令(重启、切换、重载配置),写操作要求 HTTP Basic 认证(patroni_usernamepatroni_password), 且来源受地址白名单限制;启用 patroni_ssl_enabled 后 API 全程走 HTTPS。

Grafana、HAProxy 管理界面、MINIO 模块对象存储后端、etcd 等组件的凭证同样在配置清单中声明,完整清单与修改方式见 合规实践


接下来

3.7.3 - 访问控制

Pigsty 内置四层角色模型与默认权限模板,将最小权限原则落实为可声明、可复用的集群配置。

认证 回答“你是谁”,授权回答“你能做什么”。

权限失控很少是因为缺少机制 —— PostgreSQL 的 GRANTREVOKE 足够精细。问题在于缺少一套被默认执行的约定: 业务上线时直接把账号设为属主;临时排障授予超级用户后没有及时回收;新表创建后遗漏授权,最终在生产环境触发权限错误。

Pigsty 提供了一套开箱即用的基础访问控制模型作为起点:四层角色、默认权限与数据库隔离。 它减少了逐库手工授权,但仍需要部署方按业务边界分配角色,并定期核对实际权限。

pigsty-acl.jpg


角色体系

Pigsty 默认创建四个 业务角色 —— 它们不可登录,作为权限组使用:

角色 属性 继承 用途
dbrole_readonly NOLOGIN - 全局只读访问
dbrole_readwrite NOLOGIN dbrole_readonly 全局读写(DML),业务账号的默认选择
dbrole_admin NOLOGIN dbrole_readwritepg_monitor 对象创建(DDL),管理与发布流程使用
dbrole_offline NOLOGIN - 独立只读角色,可配合 HBA 限制到离线实例

以及四个 系统用户,各自只承担一种职责:

用户 属性 用途
postgres SUPERUSER 数据库超级用户:不设密码,仅限本地 ident 登录
replicator REPLICATION 流复制与备份,附带 pg_monitor 与只读权限
dbuser_dba SUPERUSER 日常管理用户,继承 dbrole_admin
dbuser_monitor - 监控用户,仅持有 pg_monitor 与只读权限

业务账号通过 roles 字段挂载到角色组上,权限随继承而来:

pg_users:
  - { name: dbuser_app    ,password: '...' ,roles: [dbrole_readwrite] }  # 常规业务账号
  - { name: dbuser_report ,password: '...' ,roles: [dbrole_readonly]  }  # 报表只读账号
  - { name: dbuser_etl    ,password: '...' ,roles: [dbrole_offline]   }  # 离线 ETL 账号

角色体系本身也是声明的一部分(pg_default_roles),可以定制。 该参数是一份完整列表;调整时应保留所需的系统用户与默认角色,并同步检查 HBA、默认权限和脚本中的角色引用。


默认权限

角色解决了“权限授予谁”,还剩下另一半问题:新创建的对象如何自动获得正确的权限?

PostgreSQL 的原生答案是 ALTER DEFAULT PRIVILEGES。Pigsty 通过 pg_default_privileges 将其声明化:

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

只读角色获得查询与执行权限,读写角色叠加 DML,管理角色再增加对象管理所需的 DDL 辅助权限。

所有权约定

默认权限机制有一个经常被忽略的前提:它只对配置了默认权限的对象创建者生效。Pigsty 会为以下身份配置默认权限:

  • 数据库系统用户 pg_dbsu,默认为 postgres
  • 管理用户 pg_admin_username,默认为 dbuser_dba
  • dbrole_admin
  • 每个在 pg_databases 中声明的数据库属主。

应用 DDL 通常应使用声明的数据库属主;平台级管理与发布操作可以使用 dbuser_dba,或先 SET ROLE dbrole_admin。由其他用户直接创建的对象不会自动进入这套默认权限体系,除非另行为该用户配置 ALTER DEFAULT PRIVILEGES

这不是 Pigsty 的限制,而是 PostgreSQL 默认权限机制本身的工作方式:默认权限跟随对象创建者,而不是数据库或会话中的登录用户名自动传播。


数据库隔离

默认情况下,PostgreSQL 向 PUBLIC 授予数据库 CONNECT 权限。只要 HBA 同时允许连接,可登录用户就可能进入并不属于自己的数据库;多业务共享集群时尤其需要收敛这一默认值。

在数据库定义中声明 revokeconn,即可回收公共连接权限:

pg_databases:
  - { name: app_a ,owner: dbuser_a ,revokeconn: true }
  - { name: app_b ,owner: dbuser_b ,revokeconn: true }

启用后,该数据库上 PUBLICCONNECT 权限被撤销,只显式授予复制、监控、管理用户与数据库属主 —— 属主获得带 GRANT OPTION 的连接权限,可以自行决定向谁开放访问。在没有其他角色继承或额外授权的前提下,app_a 的账号将无法连接 app_b

与之配套,集群初始化时还会回收数据库与 public 模式上 PUBLICCREATE 权限:

REVOKE CREATE ON DATABASE app FROM PUBLIC;
REVOKE CREATE ON SCHEMA public FROM PUBLIC;

普通用户不再能在公共数据库或模式中随意创建对象,从而降低不安全 search_path 与对象覆盖带来的风险。 PostgreSQL 15 起已经收紧 public 模式的默认 CREATE 权限;Pigsty 将这项边界统一应用到所有受支持的大版本上。


离线角色与实例隔离

dbrole_offline 的设计用途,是为 ETL、报表和个人查询提供一组独立的只读权限。但角色本身只控制对象权限,并不会自动限制用户连接到哪类实例。

当前默认 HBA 中,+dbrole_offline 的内网规则没有设置 role,因此会应用到所有实例。要把它限制到 pg_role: offline 的专用实例,或标记了 pg_offline_query: true 的普通从库,需要在完整的 pg_default_hba_rules 列表中修改这一条规则:

pg_default_hba_rules:
  # 复制并保留其他默认规则,仅修改离线角色这一条
  - { user: '+dbrole_offline', db: all, addr: intra, auth: pwd, role: offline, order: 650,
      title: 'allow offline users on offline instances' }

定义 pg_default_hba_rules 会替换整组默认值,不能只保留示例中的一条。只有当 HBA 已按实例角色过滤,且用户没有同时继承其他可登录角色时,这类高消耗查询才会被限制到离线实例。资源隔离还应配合 独立服务入口、连接数和查询资源控制。


数据库之外

最小权限原则同样贯彻到主机层面:

  • 超级用户 postgres 不设密码,只能本地 ident 登录;其 sudo 权限默认限制在数据库相关服务的启停与日志查看(pg_dbsu_sudolimit)。
  • 监控用户 dbuser_monitor 默认持有 pg_monitor、只读角色与专用 monitor 模式权限,不具备业务表写权限。
  • 复制用户 replicator 被显式授予备份恢复所需的目录函数执行权限,而不是笼统的超级用户。

接下来

3.7.4 - 加密通信

Pigsty 内置自签名 CA,为受管组件签发证书并分发信任,提供统一的 TLS 基础设施。

TLS 可以提供三类保护:传输加密服务端身份验证客户端身份验证。这三项能力需要分别配置:启用服务端 TLS 并不等于客户端已经验证了服务端身份,也不等于服务端要求客户端证书。

TLS 的主要运维成本不在加密算法本身,而在证书的签发、分发、信任与轮换。缺少统一管理时,内网服务往往只启用加密,却跳过证书验证,或者干脆继续使用明文连接。

Pigsty 的做法是把 PKI 也纳入声明式管理:部署时自动创建本地自签名 CA,为受管组件签发证书并分发信任,让 TLS 在部署完成后即可使用。


本地 CA

首次执行部署时,Pigsty 会在 管理节点 上检查并按需创建 CA:

文件 说明 权限
files/pki/ca/ca.key CA 私钥:整个部署的信任根,务必妥善保管 0600(目录 0700
files/pki/ca/ca.crt CA 根证书:可以自由分发 0644
  • CA 的行为由 ca_create 控制:已有私钥与证书会原样复用;证书缺失但私钥存在时,会用该私钥重新签发证书。 ca_create: false 只禁止创建缺失的 CA 私钥;找不到 ca.key 时部署会直接中止,防止意外生成新的信任根。请始终成对备份和恢复 ca.keyca.crt
  • CA 证书的 CN 由 ca_cn 指定,默认 pigsty-ca;密钥为 RSA 4096 位。
  • 有效期:CA 根证书 100 年,组件证书默认 20 年(cert_validity7300d)。 面向浏览器的 Nginx 证书是例外,当前默认有效期为 397 天。

较长的默认有效期用于降低私有基础设施的初始维护成本,并不意味着生产环境无需轮换。组织已有证书策略时,应缩短有效期,并建立到期监控和换证流程。


信任分发

签发证书只是一半,另一半是让每个 节点 信任这些证书。节点纳入管理时,Pigsty 将 CA 证书分发到所有节点的 /etc/pki/ca.crt,并链接进操作系统信任链:

  • EL 系(RHEL、Rocky、Alma):链接至 /etc/pki/ca-trust/source/anchors/ 并执行 update-ca-trust
  • Debian、Ubuntu:链接至 /usr/local/share/ca-certificates/ 并执行 update-ca-certificates

此后,使用操作系统信任库的客户端(例如 curl)可以验证 Pigsty CA 签发的证书。 CA 证书还会发布到 Nginx 门户 的站点根目录(ca.crt),供浏览器与外部客户端下载安装。

PostgreSQL 的 libpq 客户端需要单独说明:它默认使用 ~/.postgresql/root.crt,默认 sslmodeprefer,不会直接使用操作系统信任库验证服务端身份。


客户端验证服务端

安全敏感的 PostgreSQL 客户端应使用 sslmode=verify-full,并指定 Pigsty CA:

psql "host=pg-meta dbname=postgres user=dbuser_dba sslmode=verify-full sslrootcert=/etc/pki/ca.crt"

verify-full 会同时验证证书链与连接主机名,因此客户端使用的 DNS 名称或 IP 地址必须出现在服务端证书的 SAN 中。外部客户端需要先安装 ca.crt,或通过 sslrootcert 指定 CA 文件。


证书矩阵

本地 CA 为下列组件签发证书,构成统一的信任链:

组件 证书身份(CN) 部署路径 加密状态
PostgreSQL <集群>-<序号> /pg/cert/server.{crt,key} 服务端 SSL 默认启用;是否强制由 HBA 决定
PgBouncer 复用 PostgreSQL 证书 /pg/cert/ TLS 默认关闭(pgbouncer_sslmode
Patroni 复用 PostgreSQL 证书 /pg/cert/ API HTTPS 默认关闭(patroni_ssl_enabled
Etcd <实例名> /etc/etcd/server.{crt,key} 客户端与对等通信使用 TLS
Silo <节点名> ~minio/.minio/certs/ Silo HTTPS 默认开启(minio_https
Kafka <集群>-<序号> /etc/kafka/pki/kafka.pem kafka_security: scram 时启用 SASL_SSL/SSL;默认 plaintext
MySQL <实例名> /etc/mysql/pki/server.{crt,key} 强制安全传输;客户端与组复制校验证书链
Nginx pigsty(SAN 含门户域名) /etc/nginx/conf.d/cert/ HTTPS 默认开启(nginx_sslmode
INFRA 节点 <节点名> /etc/pki/infra.{crt,key} 供基础设施组件使用

表中的“加密状态”一列如实反映了默认配置的取舍:

  • 部署时启用:PostgreSQL 服务端可以接受 SSL 连接,etcd 的客户端与对等通信使用 TLS。
  • 默认加密:MINIO 模块的对象存储备份流量与 Nginx Web 流量默认启用 HTTPS。
  • 默认关闭,按需启用:Patroni REST API 与 PgBouncer 的 TLS 默认关闭,证书已经就位,可以通过相应参数开启;ha/safe 模板中两者均默认开启。

还有一层需要分清的区别:服务端支持 SSL 不等于强制客户端使用 SSL,更不等于客户端验证了服务端身份。 是否强制加密由 HBA 规则 决定(auth: sslcert);是否验证服务端则由客户端的 sslmode 与信任配置决定。默认规则仅对任意来源的管理员连接强制 TLS,safe 模板将主要 TCP 规则改为 sslcert,但仍保留本地 ident 与部分 localhost 口令规则。


客户端证书

内置剧本 cert.yml 用于签发客户端证书。证书的 CN 对应数据库用户名,供 HBA 的 cert 认证方式使用:

./cert.yml -e cn=dbuser_dba                  # 为 dbuser_dba 签发客户端证书,默认有效期 20 年
./cert.yml -e cn=dbuser_dba -e expire=365d   # 或指定更短的有效期

签发结果位于 files/pki/misc/<cn>.keyfiles/pki/misc/<cn>.crt。客户端私钥应通过受控渠道交付,并设置为仅对应用户可读。客户端证书解决服务端对客户端身份的验证,客户端仍需使用 verify-full 验证数据库服务端。


使用企业 CA

如果组织已有 PKI 体系,可以让 Pigsty 改用您的 CA(或由企业根 CA 签出的中间 CA)签发证书:把证书与私钥放到指定位置即可,剧本检测到已有 CA 后不会重新生成:

files/pki/ca/ca.key    # 您的 CA 私钥(或中间 CA 私钥)
files/pki/ca/ca.crt    # 对应的 CA 证书

同时建议设置 ca_create: false:这样当私钥缺失时部署会显式失败,避免意外创建新的信任根。该开关不会阻止角色在私钥存在、证书缺失时重新签发 CA 证书,因此仍应成对检查并恢复这两个文件。


密钥保护与轮换

  • CA 私钥只存在于管理节点上。它与 pigsty.yml 一起构成部署中信任等级最高的资产(参见 信任边界),建议离线备份。
  • CA 私钥一旦泄露,需要建立新的信任根并重新签发全部组件与客户端证书。执行前应规划新旧 CA 的信任过渡,避免一次性中断所有连接。
  • 组件证书的签发源保存在管理节点的 files/pki/<component>/,节点上的证书只是部署副本。仅删除节点上的证书会重新复制原证书,不会触发重新签发。轮换时应更新或删除管理节点上的对应证书源,再执行相关剧本,并按组件要求重载或滚动重启。

接下来

3.7.5 - 数据安全

使用校验和、备份与 PITR、加密和审计日志保护 PostgreSQL 数据的完整性、可恢复性、保密性与可追溯性。

网络边界身份认证权限控制 用于降低事件发生的概率;当硬件损坏、口令泄露或误操作已经发生时,还需要依靠数据层机制控制影响并完成恢复。

数据安全要回答四个问题:数据是 完整 的吗?丢了能 恢复 吗?被拿走了会 泄密 吗?发生了什么能 查清 吗?


完整性

磁盘坏块、内存位翻转、存储固件缺陷,都可能造成 静默数据损坏:数据坏了,但没有任何报错。 Pigsty 默认启用页级数据校验和(pg_checksumtrue), 集群初始化时以 data-checksums 建库,PostgreSQL 会在页面写入时计算校验和,并在读取时检查页面损坏。

页校验和主要发现存储介质、I/O 路径或写入后发生的页面损坏,不能检测所有内存错误、逻辑错误或应用写入的错误数据,也不能替代备份。

CRIT 参数模板 更进一步:校验和强制启用,不受参数影响; 同时启用 严格同步复制synchronous_mode_strict),在没有可用同步副本时阻塞需要同步确认的写入。 该模式以不丢失已确认事务为目标,但仍依赖客户端没有降低 synchronous_commit、同步副本正常参与提交,以及故障切换只选择包含所需 WAL 的节点。RPO 需要通过目标拓扑上的故障演练验证。


可恢复性

副本主要处理节点故障,备份则处理误删除、逻辑错误、集群损坏和更大范围的灾难。 高可用 可以缩短主库故障造成的中断,但如果有人误删了数据,复制也会把误操作同步到其他副本。备份因此无可替代。

Pigsty 默认启用 pgBackRestpgbackrest_enabled): 基础备份加上持续归档的 WAL,构成 时间点恢复(PITR)能力,可以将集群恢复到备份与 WAL 保留窗口内的目标时刻。

备份仓库由 pgbackrest_method 选择:

仓库 位置 默认保留策略 加密
local(默认) 本地 /pg/backup 目录 最近 2 份全量备份
minio Silo 或外部 S3 对象存储 14 天 AES-256-CBC

对于防误删场景,还有两项辅助机制:

  • 延迟从库:为关键集群声明一个 pg_delay: 1h 的延迟副本。在错误操作尚未回放前,可以暂停复制并提取数据。延迟副本最终仍会追上主库,不能代替备份。
  • 移除保护pg_safeguardetcd_safeguard 开启后,对应的移除剧本会拒绝执行,降低误删集群的风险。

备份的存在不等于恢复的能力。恢复演练应当成为例行工作:原理与决策见 时间点恢复,配置与操作见 PGSQL 备份恢复


保密性

静态数据的保密性分三层展开:

备份加密pgbackrest_method: minio 表示 S3 兼容对象存储仓库,可由 MINIO 模块部署的 Silo,或独立管理的 MinIO、RustFS 与外部 S3 服务提供;该预设默认启用 AES-256-CBC 加密。默认加密口令 pgBackRest 是公开值,生产环境必须修改。 ha/safe 模板按集群名称区分加密口令:

pgbackrest_repo:
  minio:
    cipher_type: aes-256-cbc
    cipher_pass: 'pgBR.${pg_cluster}'   # 示例值,部署前必须替换

pgBR.${pg_cluster} 是可预测的示例值,configure -g 也不会替换它。生产环境应使用独立随机口令,并与备份分开保存;口令丢失会导致备份无法恢复。

本地备份仓库默认不加密。加密可以降低备份文件被单独复制或介质被盗时的泄露风险,但如果密钥与备份位于同一主机,保护效果仍会受到限制。

传输加密。备份上传 Silo 或外部 S3 服务时走 HTTPS,PostgreSQL 客户端与流复制可以通过 HBA 强制 SSL。客户端还应验证服务端证书,详见 加密通信

静态加密。PostgreSQL 上游内核目前没有通用的内置透明数据加密(TDE),Pigsty 提供两条现实路径: 使用 Percona PostgreSQL 内核的 pg_tde 扩展实现表级透明加密(参见 pgtde 配置模板); 或使用 pgsodiumpgcryptoanonymizer安全扩展 在列级实现加密与脱敏 —— safe 模板已预装这一类扩展。 此外,全盘加密(LUKS、dm-crypt)在操作系统层解决介质被盗问题,与数据库层方案互补。


审计与追溯

出了问题,要能回答“谁在什么时候做了什么”。Pigsty 的日志审计分层递进:

默认基线:所有 DDL 语句被记录(log_statement: ddl),执行超过 100ms 的查询被记录(log_min_duration_statement: 100), PostgreSQL 18 及以上版本还会记录连接授权事件。

CRIT 模板:记录连接与断开事件(log_connectionslog_disconnections);PostgreSQL 18 还会区分连接接收、认证与授权阶段。

pgaudit 扩展:需要语句级的细粒度审计(对象级读写、按角色审计)时,安装 pgaudit 并加入 pg_libs 预加载。 safe 模板已预装该扩展,加载与审计策略需按需求显式声明。

启用 INFRA 日志组件并完成 Vector 配置后,PostgreSQL 日志会汇入 VictoriaLogs 集中存储(默认保留 15 天,可按合规要求调整)。 日志和指标为安全事件的检索、告警与回溯提供输入,但事件判定、响应和证据保全仍需要配套流程。


接下来

3.7.6 - 合规实践

合规是配置、流程与证据的组合:上线加固清单、等保与 SOC 2 控制点映射、供应链完整性与漏洞响应机制。

合规不是一个可以购买的产品,而是一种需要持续证明的状态。它由三部分组成:

  • 配置:安全能力是否启用 —— 这部分由 Pigsty 直接提供;
  • 流程:权限审批、变更管理、恢复演练等制度 —— 需要组织自行建立;
  • 证据:能证明前两者持续有效的记录 —— Pigsty 的 配置清单、运行日志和 监控系统 可以提供其中一部分。

本页从上线前的加固清单开始,给出 Pigsty 安全能力与常见合规框架的映射关系。 这些映射用于方案设计和差距分析,不构成等保测评结论、SOC 2 审计意见或法律建议。


默认凭证清单

Pigsty 的默认凭证公开写在文档与源码中,仅供演示与本地开发使用。任何生产部署或暴露于网络的部署,上线前必须修改所有适用的默认值

范围 默认值示例 configure -g
Grafana 管理员与只读用户 pigstyDBUser.Viewer
HAProxy 管理界面 pigsty
PostgreSQL 管理、监控、复制用户 DBUser.DBADBUser.MonitorDBUser.Replicator
Patroni REST API Patroni.API
etcd root Etcd.Root
MINIO 模块对象存储 root S3User.MinIO
对象存储备份与示例业务用户 S3User.BackupS3User.MetaS3User.Data
示例数据库用户 DBUser.MetaDBUser.SupaVibe.Coding
pgBackRest 加密口令 cipher_pass: pgBackRest
ha/safe 中的 Silo 用户与 pgBR.${pg_cluster} 模板示例值
用户自行添加的凭据 自定义值

生成配置时可以使用 -g,随机化配置向导识别的内置参数和示例字符串:

./configure -g     # 生成配置清单,并随机化向导识别的默认凭据

配置向导会把生成的密码输出到终端,因此终端记录和自动化日志也应按敏感信息保护。生成完成后还要检查配置文件,单独替换 pgBackRest cipher_passha/safe 中未覆盖的 MINIO 模块示例值和自定义凭据。


上线加固清单

部署前

  • 明确 网络边界:数据库端口不暴露公网,移除演示配置中防火墙放行的 5432
  • 确定证书策略:使用内置 CA,或接入企业 PKI(参见 使用企业 CA
  • 规划 客户端验证:为数据库客户端配置 sslmode=verify-full 与可信 CA
  • 规划账号体系:业务账号按 四层角色 分级,声明 expire_in 过期时间
  • 规划 备份仓库、保留周期、加密口令和异地副本
  • 评估是否采用 ha/safe 加固模板与 CRIT 参数模板

部署后

  • 确认 configure -g 覆盖的凭据与未覆盖的备份、对象存储、自定义凭据均已修改
  • 审查实际生效的 HBA 规则/pg/data/pg_hba.conf)是否与声明及预期一致
  • 查询实际用户、角色、默认权限 和数据库 CONNECT 授权,并与配置清单比较
  • 执行一次全量备份与 恢复演练,验证备份链路可用
  • 确认日志采集、监控告警与通知通道可用

周期性

  • 权限审计:核对 pg_users 声明与实际授权,清理过期与离职账号
  • 凭证与证书轮换
  • 恢复演练与故障切换演练
  • 跟进 Pigsty 与上游组件的安全更新

合规证据

声明式配置为合规审计提供了稳定的证据入口,但还需要保留运行时状态,证明配置已经应用并持续有效。

证据 来源
安全配置基线及其变更历史 pigsty.yml 配置清单与 Git 提交记录
访问控制矩阵 pg_default_rolespg_userspg_hba_rules 声明
实际生效的认证规则 各实例渲染出的 pg_hba.conf,用于与声明比较并发现漂移
实际用户与权限 PostgreSQL 系统目录、数据库 ACL、\du+\ddp+
操作与连接日志 PostgreSQL 日志(DDL、慢查询、连接),VictoriaLogs 集中留存
备份记录 pgBackRest 备份信息与监控面板
安全事件与告警记录 监控系统告警历史
证书清单 files/pki/ 目录与各组件部署证书

等保三级映射

《GB/T 22239-2019》三级要求中“安全计算环境”部分与 Pigsty 能力的对应关系:

控制要求 Pigsty 能力 需要补充
身份鉴别唯一性 独立账号体系,SCRAM-SHA-256 密码存储 账号实名管理制度
口令复杂度与定期更换 passwordcheckcredcheck 扩展,expire_in 账号过期 启用扩展;轮换制度
登录失败处理 可借助 credcheck 等扩展实现 按需启用与配置
访问控制与最小权限 四层角色模型、默认权限与数据库隔离 权限审批流程
安全审计 DDL、连接、慢查询日志,pgaudit,集中日志留存 CRIT 模板或手工启用连接日志;留存周期按要求调整
通信保密性 本地 CA 与 TLS,HBA 强制 sslcert 强制 TLS、客户端 verify-full 与证书轮换
数据完整性 页级校验和(默认启用),严格同步复制(CRIT) 存储保护、故障模型与演练
数据保密性 备份 AES 加密,TDE 与列级加密路径 按需启用
数据备份恢复 pgBackRest、PITR 与远端 S3 兼容仓库 恢复演练制度
剩余信息保护 - 介质销毁与擦除流程

等保还包括安全物理环境、安全通信网络、安全管理制度等部分,超出数据库发行版的能力范畴: Pigsty 可以支持“安全计算环境”中与数据库相关的部分技术控制,机房、网络设备与管理制度仍需在整体方案中补足。


SOC 2 映射

SOC 2 信任服务准则(TSC)中与数据库直接相关的部分控制点:

控制点 Pigsty 能力 需要补充
CC6.1 逻辑访问安全 HBA、RBAC、默认权限与数据库隔离 权限设计、审批与定期复核
CC6.2 用户注册与授权 声明式用户、角色和有效期 入职、变更、离职和身份核验流程
CC6.3 访问变更与撤销 pg_users、角色调整、REVOKE 与到期时间 工单、授权批准和及时回收证据
CC6.6 外部边界威胁 防火墙、监听地址、HBA 与管理入口限制 网络架构、边界设备和持续验证
CC6.7 信息传输与移动 TLS、客户端验证与备份加密 数据导出、介质和第三方传输策略
CC7.2 系统监控 Victoria 可观测性栈,数千项指标与告警 告警响应流程
CC7.3 事件追溯 集中日志,审计扩展 日志审查流程
A1.2 可用性与恢复 高可用PITR 演练记录与 RTO、RPO 目标

供应链与漏洞响应

合规审查越来越关注软件供应链,Pigsty 在分发与响应侧提供以下保障:

包完整性:Pigsty 软件仓库(repo.pigsty.iorepo.pigsty.cc)中的 RPM、DEB 包经 GPG 签名, 公钥指纹为 9592 A7BC 7A68 2E73 3337 6E09 E793 5D8D B9BD 8B20B9BD8B20),可在信任前核验。但部署时写入的仓库定义以及 INFRA 节点 上的本地仓库,默认不强制逐包签名验证;生产环境应检查包管理器的仓库信任与验签设置。

漏洞响应:安全问题通过 GitHub 私有漏洞报告或邮件渠道私下披露(参见 SECURITY.md), 项目目标是在 3 个工作日内确认、7 天内给出初步评估。

版本支持:安全修复随最新稳定版发布,保持升级是获得安全修复的方式;需要长期锁定版本的用户,可通过 订阅服务 获得延长支持。


接下来

4 - 关于

了解 Pigsty 项目本身的方方面面:功能特性、历史发展,开源协议,隐私政策,社区活动与新闻。

4.1 - 亮点特性

Pigsty 的价值主张与亮点功能特性。

PostgreSQL In Great STYle”: Postgres, Infras, Graphics, Service, Toolbox, it’s all Yours.

—— 开箱即用、本地优先的 PostgreSQL 发行版,开源 RDS 替代


价值主张

Pigsty 功能概览

总览

Pigsty 是一个更好的本地开源 RDS for PostgreSQL 替代:

  • 开箱即用的RDS:从内核到 RDS 发行版,在 EL/Debian/Ubuntu 下提供 14-18 版本的生产级 PG 数据库服务。
  • 丰富的扩展插件:提供无可比拟的 575 扩展,提供开箱即用的分布式的时序地理空间图文向量多模态数据库能力。
  • 灵活的模块架构:组合 Redis、Etcd、Silo 对象存储模块与 Mongo 等 PostgreSQL 模式;可独立监控现有 RDS、主机和数据库。
  • 惊艳的观测能力:基于 Victoria 与 Grafana 的现代可观测性技术栈,使用 Prometheus 兼容指标与生态工具。
  • 验证过的可靠性:故障自愈的高可用架构:硬件故障自动切换,流量无缝衔接。并提供自动配置的 PITR 兜底删库!
  • 简单易用可维护:声明式 API,GitOps 就位,傻瓜式操作,Database/Infra-as-Code 以及管理 SOP 封装管理复杂度!
  • 扎实的安全实践:提供 HBA、ACL、TLS、备份、日志与主机防火墙等基础能力,并说明默认边界与生产加固要求。
  • 广泛的应用场景:低代码数据应用开发,或使用预置的 Docker Compose 模板,一键拉起使用 PostgreSQL 的海量软件!
  • 开源的自由软件:以云数据库1/10不到的成本拥有与更好的数据库服务!帮您真正“拥有”自己的数据,实现自主可控!

PostgreSQL 整合了生态中的工具与最佳实践:

  • 开箱即用的 PostgreSQL 发行版,整合地理、时序、分布式、图、向量、搜索、AI 等 575 个 扩展插件
  • 运行于裸操作系统之上,无需容器支持,支持主流操作系统: EL 8/9/10, Ubuntu 22.04/24.04/26.04 以及 Debian 12/13。
  • 基于 patroni, haproxy, 与 etcd,打造故障自愈的高可用架构:硬件故障自动切换,流量无缝衔接。
  • 基于 pgBackRest 与可选的 Silo 对象存储 提供开箱即用的 PITR 时间点恢复,为软件缺陷与人为删库兜底。
  • 基于 Ansible 提供声明式的 API 对复杂度进行抽象,以 Database-as-Code 的方式极大简化了日常运维管理操作。
  • Pigsty 用途广泛,可用作完整应用运行时,开发演示数据/可视化应用,大量使用 PG 的软件可用 Docker 模板一键拉起。
  • 提供基于 Vagrant 的本地开发测试沙箱环境,与基于 Terraform 的云端自动部署方案,开发测试生产保持环境一致。
  • 使用 DocumentDB 与 FerretDB Docker APP 运行 PostgreSQL Mongo 兼容模式

开箱即用的RDS

让您立刻在本地拥有生产级的 PostgreSQL 数据库服务!

PostgreSQL 是一个足够完美的数据库内核,但它需要更多工具与系统的配合才能成为一个足够好的数据库服务(RDS),Pigsty 帮助 PostgreSQL 完成这一步飞跃。 Pigsty 为您解决使用 PostgreSQL 中会遇到的各种难题:内核扩展安装,连接池,负载均衡,服务接入,高可用 / 自动故障切换,日志收集,指标监控,告警,备份恢复,PITR,访问控制,参数调优,安全加密,证书签发,NTP,DNS,参数调优,配置管理,CMDB,管理预案… 您无需再为这些细节烦心劳神!

Pigsty 对 PostgreSQL 14 - 18 主干内核与其他兼容分支提供稳定支持,并在当前 main 中提供 PostgreSQL 19 Beta 试用模板;可运行于 EL / Debian / Ubuntu 以及 兼容操作系统发行版 上,在 x86_64 与 ARM64 芯片架构上可用,且无需容器支持。 除了数据库内核与大量开箱即用的扩展插件以外,Pigsty 还提供了数据库服务所需的完整基础设施与运行时,以及本地沙箱 / 生产环境 / 云 IaaS 自动部署方案。

Pigsty 可以一键从裸机开始拉起整套环境,触达软件交付的最后一公里。普通研发运维均可快速上手并兼职进行数据库管理,无需数据库专家即可自建企业级 RDS 服务!

pigsty-arch


丰富的扩展插件

超融合多模态,一切皆用 PostgreSQL,一个 PG 替换所有数据库!

PostgreSQL 的灵魂在于其丰富的 扩展生态,而 Pigsty 独一无二地深度整合了 PostgreSQL 生态中的 575 扩展,为您提供开箱即用的超融合多模态数据库!

插件间可以产生 协同效应,产生 1+1 远大于 2 的效果。 您可以使用 PostGIS 处理地理空间数据,使用 TimescaleDB 分析时序/事件流数据,并使用 Citus 将其原地升级为分布式地理时空数据库; 您可以用 PGVector 存储并搜索 AI 嵌入,用 ParadeDB 实现 ES 级全文检索,并同时使用精准的 SQL,全文检索,与模糊向量进行混合检索。 您还可以通过 pg_duckdbpg_mooncake 等分析扩展,实现专用 OLAP 数据库/数据湖仓的分析表现。

使用 PostgreSQL 单一组件替代 MySQL,Kafka,ElasticSearch,MongoDB,以及大数据分析技术栈已经成为一种最佳实践 —— 单一数据库选型能够显著降低系统复杂度,极大提高研发效能与敏捷性,实现程度惊人的软硬件,研发/运维人力降本增效。

pigsty-ecosystem.jpg


灵活的模块架构

灵活组合,自由扩展,多数据库支持,监控现有 RDS/主机/数据库

Pigsty 中的组件被抽象可独立部署的 模块,并可自由组合以应对多变的需求场景。INFRA 模块带有完整的现代监控技术栈,而 NODE 模块则将节点调谐至指定状态并纳管。 在多个节点上安装 PGSQL 模块会自动组建出基于主从复制的高可用数据库集群,而同样的 ETCD 模块则为数据库高可用提供共识与元数据存储。

除了上述四个 核心模块 之外,Pigsty 还提供一系列选装功能模块:MINIO 模块可以部署 Silo,提供本地对象存储能力并作为集中式数据库备份仓库。 REDIS 模块能以独立主从,哨兵,原生集群的方式为数据库提供辅助。DOCKER 模块可用于拉起无状态的应用软件。

此外,Pigsty 还提供 PG 兼容 / 衍生内核的支持,您可以使用 Babelfish 提供 MS SQL Server 兼容性,使用 IvorySQL 提供 Oracle 兼容性, 使用 OpenHaloDB 提供 MySQL 兼容性,使用 OrioleDB 提供极致的 OLTP 性能。

不仅如此,你还可以使用 PostgreSQL Mongo 模式 提供 MongoDB 兼容性,使用 Supabase 提供 Firebase 兼容,并使用 PolarDB 满足国产化合规要求。 消息队列可以使用 KAFKA 模块部署 Kafka 4.x dynamic KRaft 集群。更多专业版/试点模块将不断引入 Pigsty,如 GPSQLDUCKDBVICTORIATIGERBEETLEKUBERNETESCONSULJUPYTERGREENPLUMCLOUDBERRYMYSQL, …

pigsty-sandbox


惊艳的观测能力

使用现代开源可观测性技术栈,提供无与伦比的监控最佳实践!

Pigsty 提供了基于开源 Grafana 与 Victoria Stack 的现代可观测性技术栈做 监控:Grafana 负责可视化呈现,VictoriaMetrics 通过 Prometheus 兼容接口收集监控指标,VictoriaLogs 用于日志收集与查询,Alertmanager 用于告警通知,Blackbox Exporter 负责检查服务可用性。这些组件由 INFRA 模块部署。

Pigsty 所管理的任何组件都会被自动纳入监控之中,包括主机节点,负载均衡 HAProxy,数据库 Postgres,连接池 Pgbouncer,元数据库 ETCD,KV 缓存 Redis,对象存储 Silo,……,以及整套监控基础设施本身。大量的 Grafana 监控面板与预置告警规则会让你的系统观测能力有质的提升,当然,这套系统也可以被复用于您的应用监控基础设施,或者监控已有的数据库实例或 RDS。

无论是故障分析还是慢查询优化、无论是水位评估还是资源规划,Pigsty 为您提供全面的数据支撑,真正做到数据驱动。在 Pigsty 中,超过三千类监控指标被用于描述整个系统的方方面面,并被进一步加工、聚合、处理、分析、提炼并以符合直觉的可视化模式呈现在您的面前。从全局大盘总览,到某个数据库实例中单个对象(表,索引,函数)的增删改查详情都能一览无余。您可以随意上卷下钻横向跳转,浏览系统现状与历史趋势,并预测未来的演变。

pigsty-dashboard.jpg

此外,Pigsty 的监控系统模块部分还可以 独立使用 ——用它来监控现有的主机节点与数据库实例,或者是云上的 RDS 服务。只需要一个连接串一行命令,您就可以获得极致的 PostgreSQL 可观测性体验。

访问 截图画廊在线演示 获取更多详情。


久经考验的可靠性

开箱即用的高可用与时间点恢复能力,确保你的数据库坚如磐石!

对于软件缺陷或人为误操作造成的删表删库,Pigsty 提供了开箱即用的 PITR 时间点恢复能力,无需额外配置即默认启用。只要存储空间管够,基于 pgBackRest 的基础备份与 WAL 归档让您拥有快速回到恢复窗口内任意时间点的能力。您可以使用本地目录/磁盘、MINIO 模块部署的 Silo,亦或外部 S3 兼容对象存储服务保留更长的回溯期限,丰俭由人。

Pigsty 基于 Patroni、etcd 与 HAProxy 提供 高可用故障自愈架构。在节点、网络、仲裁和同步副本满足设计前提时,系统可自动完成主库故障转移;实际 RTO 与 RPO 取决于复制模式、故障类型、超时参数和客户端重连策略。

Pigsty 内置了 HAProxy 负载均衡器用于自动流量切换,提供 DNS/VIP/LVS 等多种接入方式供客户端选用。故障切换与主动切换对业务侧除零星闪断外几乎无感知,应用不需要修改连接串重启。极小的维护窗口需求带来了极大的灵活便利:您完全可以在无需应用配合的情况下滚动维护升级整个集群。硬件故障可以等到第二天再抽空善后处置的特性,让研发,运维与 DBA 都能安心睡个好觉。 许多大型组织与核心机构已经在生产环境中长时间使用 Pigsty,最大的部署有 25K CPU 核心与 200+ PostgreSQL 超大规格实例;在这一部署案例中,六七年内经历了数十次硬件故障与各类事故,DBA 换了几茬,但依然可以保持比 99.999% 更高的可用性战绩。

pigsty-ha.png


简单易用可维护

Infra as Code, 数据库即代码,声明式的 API 将数据库管理的复杂度来封装。

Pigsty 使用声明式的接口对外提供服务,将系统的可控制性拔高到一个全新水平:用户通过配置清单告诉 Pigsty “我想要什么样的数据库集群”,而不用去操心到底需要怎样去做。从效果上讲,这类似于 K8S 中的 CRD 与 Operator,但 Pigsty 可用于任何节点上的数据库与基础设施:不论是容器,虚拟机,还是物理机。

无论是创建/销毁集群,添加/移除从库,还是新增数据库/用户/服务/扩展/黑白名单规则,您只需要修改配置清单并运行 Pigsty 提供的幂等剧本,而 Pigsty 负责将系统调整到您期望的状态。 用户无需操心配置的细节,Pigsty 将自动根据机器的硬件配置进行调优,您只需要关心诸如集群叫什么名字,有几个实例放在哪几台机器上,使用什么配置模版:事务/分析/核心/微型,这些基础信息,研发也可以自助服务。但如果您愿意跳入兔子洞中,Pigsty 也提供了丰富且精细的控制参数,满足最龟毛 DBA 的苛刻定制需求。

除此之外,Pigsty 本身的安装部署也是一键傻瓜式的,所有依赖被预先打包,在安装时可以无需互联网访问。而安装所需的机器资源,也可以通过 Vagrant 或 Terraform 模板自动获取,让您在十几分钟内就可以从零在本地笔记本或云端虚拟机上拉起一套完整的 Pigsty 部署。本地沙箱环境可以跑在1核2G 的微型虚拟机中,提供与生产环境完全一致的功能模拟,可以用于开发、测试、演示与学习。

pigsty-iac.jpg


扎实的安全实践

Pigsty 提供数据库部署所需的基础安全能力,包括分层 HBA、内置角色与默认权限、SCRAM-SHA-256、页校验和、本地 CA、组件证书、备份、PITR、集中日志和防火墙配置。

默认配置面向受信内网中的开发、测试和演示。生产部署需要替换公开凭据,检查网络边界,按需强制 TLS,配置客户端证书验证,并建立备份恢复、权限审查和事件响应流程。

安全与合规 章节说明各项机制的默认状态和适用边界;安全考量 提供生产加固建议;合规实践 给出等保与 SOC 2 的参考映射。是否满足具体合规要求取决于部署范围、组织流程、持续证据和审计结论。

pigsty-acl.jpg


广泛的应用场景

使用预置的 Docker 模板,一键拉起使用 PostgreSQL 的海量软件!

在各类数据密集型应用中,数据库往往是最为棘手的部分。例如 Gitlab 企业版与社区版的核心区别就是底层 PostgreSQL 数据库的监控与高可用,如果您已经有了足够好的本地 PG RDS,完全可以拒绝为软件自带的土法手造数据库组件买单。

Pigsty 提供了 Docker 模块 与大量开箱即用的 Compose 模板。您可以使用 Pigsty 管理的高可用 PostgreSQL(以及 Redis 与 Silo)作为后端存储,以无状态的模式一键拉起这些软件: Gitlab、Gitea、Wiki.js、NocoDB、Odoo、Jira、Confluence、Habour、Mastodon、Discourse、KeyCloak、MatterMost 等等。 如果您的应用需要一个可靠的 PostgreSQL 数据库, Pigsty 也许是最简单的获取方案。

Pigsty 也提供了与 PostgreSQL 紧密联系的应用开发工具集:PGAdmin4、PGWeb、ByteBase、PostgREST、Kong、以及 EdgeDB、FerretDB、Supabase 这些使用 PostgreSQL 作为存储的"上层数据库"。 更奇妙的是,您完全可以基于 Pigsty 内置了的 Grafana 与 Postgres,以低代码的方式快速搭建起一个交互式的数据应用来,甚至还可以使用 Pigsty 内置的 ECharts 面板创造更有表现力的交互可视化作品。

Pigsty 为您的 AI 应用提供了一个功能强大的运行时,您的 Agent 可以在这个环境中利用 PostgreSQL 与可观测性世界的强大能力,快速构建起一个数据驱动的智能体。

pigsty-app.jpg


开源的自由软件

Pigsty 是基于 Apache-2.0 开源的自由软件,由热爱 PostgreSQL 的社区成员用热情浇灌

Pigsty 是完全 开源免费 的自由软件,它允许您在缺乏数据库专家的情况下,用几乎接近纯硬件的成本来运行企业级的 PostgreSQL 数据库服务。 作为对比,数据库厂商的“企业级数据库服务”与公有云厂商提供的 RDS 会收取底层硬件资源几倍到十几倍不等的 溢价 作为 “服务费”。

很多用户选择上云,正是因为自己搞不定数据库;很多用户使用 RDS,是因为别无他选。 我们将打破云厂商的垄断,为用户提供一个云中立的,更好的 RDS 开源替代: Pigsty 紧跟 PostgreSQL 上游主干,不会有供应商锁定,不会有恼人的 “授权费”,不会有节点数量限制,不会收集您的任何数据。您的所有的核心资产 —— 数据,都能"自主可控",掌握在自己手中。

Pigsty 本身旨在用数据库自动驾驶软件,替代大量无趣的人肉数据库运维工作,但再好的软件也没法解决所有的问题。 总会有一些的冷门低频疑难杂症需要专家介入处理。这也是为什么我们也提供专业的 订阅服务,来为有需要的企业级用户使用 PostgreSQL 提供兜底。 几万块的订阅咨询费不到顶尖 DBA 每年工资的几十分之一,让您彻底免除后顾之忧,把成本真正花在刀刃上。对于社区用户,我们亦 用爱发电,提供免费的支持与日常答疑。

pigsty-price.jpg

tooltip: { trigger: axis, formatter: $fn:ttfmt }
legend: { top: 4, itemGap: 16, data: [Oracle, 开源PG, 云数据库, Pigsty 云服务器, Pigsty 本地部署] }
grid: { left: 96, right: 36, bottom: 70, top: 50 }
xAxis:
  type: category
  name: CPU 核心数
  nameLocation: middle
  nameGap: 36
  boundaryGap: false
  data: [2, 4, 8, 12, 16, 24, 32, 52, 64, 104, 128, 196, 256, 384, 512]
yAxis:
  type: log
  logBase: 10
  min: 10
  name: 月成本(元)
  axisLabel: { formatter: $fn:yfmt }
  splitLine: { show: true, lineStyle: { type: dashed, opacity: 0.5 } }
series:
  - { name: Oracle, type: line, symbolSize: 7, lineStyle: { width: 3 }, itemStyle: { color: "#d62728" }, data: [45000, 65000, 105000, 145000, 185000, 265000, 345000, 545000, 665000, 1065000, 1305000, 1985000, 2585000, 3865000, 5145000] }
  - { name: 云数据库, type: line, symbolSize: 6, lineStyle: { width: 2 }, itemStyle: { color: "#ff7f0e" }, data: [800, 1600, 3200, 4800, 6400, 9600, 12800, 20800, 25600, 41600, 51200, 78400, 102400, 153600, 204800] }
  - { name: Pigsty 云服务器, type: line, symbolSize: 6, lineStyle: { width: 2 }, itemStyle: { color: "#2ca02c" }, data: [360, 720, 1440, 2160, 2880, 4320, 5760, 9360, 11520, 18720, 23040, 35280, 46080, 69120, 92160] }
  - { name: Pigsty 本地部署, type: line, symbolSize: 6, lineStyle: { width: 2 }, itemStyle: { color: "#9467bd" }, data: [38, 76, 152, 228, 304, 456, 608, 988, 1216, 1976, 2432, 3724, 4864, 7296, 9728] }

4.2 - 历史沿革

Pigsty 项目的由来与动机,过去发展的历史,未来的目标与愿景。

历史起源

Pigsty 项目始于 2018 ~ 2019 年,起源于 探探。 探探是一个互联网交友 App —— 中国的 Tinder,现已被陌陌收购。 探探这家公司是一个北欧风格的创业公司,有着一个瑞典工程师初创团队。

探探在技术上极有品味,使用 PostgreSQL 与 Go 作为核心技术栈。 探探整个系统架构参照 Instagram,一切围绕 PostgreSQL 数据库设计。 直到几百万日活,几百万 TPS,几百 TB 数据的量级下,数据组件 只用了 PostgreSQL。 几乎所有的业务逻辑都使用 PG 存储过程实现 —— 甚至包括 100ms 的推荐算法!称得上当时中国最复杂的 PostgreSQL 规模场景用例。

探探这种深度使用 PostgreSQL 特性的非典型研发模式,对工程师与 DBA 的水平提出了极高的要求。 而 Pigsty,就是我们用这种真实世界的大规模,高标准数据库集群场景打磨出的开源项目 —— 沉淀着我们作为顶尖 PostgreSQL 专家的经验与最佳实践。


发展过程

在最开始,Pigsty 并没有现在这样的愿景、目标与版图。而是为了提供一个供我们自己使用的 PostgreSQL 监控系统。 我们调研了市面上所有的方案,开源的、商业的、云的,datadog, pgwatch,……,没有一个能满足我们对于可观测性的需求。 因此我决定自己动手,基于 Grafana 与 Prometheus 自己动手打造一个,这就是 Pigsty 的前身与雏形。 Pigsty 作为监控系统的效果相当惊艳,帮助我们解决了无数管理问题。

随后,研发人员希望在本地的开发机上也有这样的监控系统,于是我们使用 Ansible 编写了置备剧本,将这套系统从一次性建设任务转变为了可重复使用,可复制的软件。 新版本允许用户使用 Vagrant 和 Terraform,用 Infra as Code 的方式快速拉起本地 DevBox 开发机,或生产环境服务器,并自动完成 PostgreSQL 与监控系统的部署。

接下来,我们重新设计了生产环境的 PostgreSQL 架构,引入了 Patroni 与 pgBackRest 解决了数据库的 高可用时间点恢复 问题。 开发了基于逻辑复制的不停机 迁移 方案,通过蓝绿部署将生产环境两百套数据库集群滚动升级至最新大版本。并将这些能力引入 Pigsty 中。

Pigsty 是我们做给自己使用的软件,“Eat dog food”最大的好处就是,我们自己既是开发者也更是用户 —— 我们自己作为甲方用户,非常了解自己需要什么,也不会在自己的需求上偷懒,更不用担心自己的工作全自动化后被开。

我们解决了一个又一个的问题,并将解决方案沉淀到 Pigsty 里。Pigsty 的定位,也从一个监控系统,逐渐发展成为一个开箱即用的 PostgreSQL 数据库发行版。 随即我们决定将 Pigsty 开源,并开始了一系列的技术分享与宣传,也开始有各行各业的外部用户使用起 Pigsty 并提出反馈意见。


全职创业

在 2022 年,Pigsty 项目获得了由陆奇博士发起的奇绩创坛的种子轮投资,我得以全职出来做这件事情。

作为一个开源项目,Pigsty 的发展相当不赖,在全职创业这几年里,截至 2026-07-11,Pigsty 在 GitHub 上的 Star 数从几百增长到了 5213;上了 HN 头条推荐,增长开始滚起雪球。 2025 年 11 月,Pigsty 荣获 PostgreSQL 生态大会颁发的 Magneto Award。2026 年,Pigsty 子项目 PGEXT.CLOUD 投中 PGCon.Dev 2026 演讲。 Pigsty 成为第一个站上这个 PostgreSQL 核心生态大会舞台上的中国开源项目。

从前 Pigsty 只能跑在 CentOS 7 上,现今已经基本覆盖了所有主流 Linux 发行版 (EL, Debian, Ubuntu),支持 16 个操作系统平台。 支持的 PG 大版本覆盖 14 - 18,维护、收录并整合了 PG 生态中的 575 个扩展插件。 其中,我本人维护了这里超过一半(360+)的扩展插件,并提供开箱即用的 RPM/DEB 包。 算上 Pigsty 本身,“基于开源,回馈开源”,为 PG 生态做一些贡献。

Pigsty 的定位,也在不断发展的过程中,从一个 PostgreSQL 数据库发行版,进一步扩展到了 开源云数据库。它真正对标的是云厂商的整个云数据库品牌。


公有云的反叛者

AWS、Azure、GCP、Aliyun 等公有云厂商为初创企业提供了许多便利,但它们是闭源的,并迫使用户以高额费用租赁基础资源。

我们认为,优秀的数据库服务,应该和优秀的数据库内核一样,普及到每一个用户手中,而不是必须花费高昂的代价去向赛博领主租赁。

云计算的敏捷与弹性价值主张很好,但它应该是自由、开源、普惠、本地优先的 —— 我们认为云计算宇宙中需要一个代表开源价值观的解决方案,在不牺牲云带来好处的前提下,将基础设施的控制权交还给用户。

因此,我们也在引领着一场 下云的运动与战役,作为公有云的反叛者,来重塑这个行业的价值观。


我们的愿景

我希望,未来的世界人人都有自由使用优秀服务的事实权利,而不是只能被圈养在几个赛博领主公有云巨头厂商的地盘上当赛博佃户甚至赛博农奴。

这正是 Pigsty 要做的事 —— 一个更好的,开源免费的 RDS 替代。让用户能够在任何地方(包括云服务器)上,一键拉起比云 RDS 更好的数据库服务。

Pigsty 是对 PostgreSQL 的彻底补完,更是对云数据库的辛辣嘲讽。 它本意是“猪圈”,但也是 Postgres In Great STYle 的缩写,即“全盛状态下的 PostgreSQL”。

Pigsty 本身是一款完全开源免费的软件,能够让您在没有数据库专家的情况下,自建水平达到 90 分的 PostgreSQL 数据库服务。 我们靠提供 精品咨询服务 来维持运营,为您搭建从 90 分到 100 分的体系,并提供质保、答疑、与兜底。

建设良好的系统也许跑个几年都不会遇到需要 “兜底” 的问题,但数据库的问题一但出现就不是小问题。 很多时候,专家的经验更是能够一言化腐朽为神奇,而我们为有需求的客户提供这样的精品咨询 —— 我们认为这是一种更加公正、合理、可持续的模式。


关于团队

我是冯若航,Pigsty 的作者,Pigsty 的所有代码几乎都由我 一人开发

软件领域依然存在个人英雄主义,独一无二的个体才能够创造出独一无二的作品 —— 我希望 Pigsty 成为这样的作品。

如果您对我感兴趣,这里是我的个人主页:https://vonng.com/

墨天轮风云人物访谈录 —— 冯若航

90后,辞职创业,说要卷死云数据库

4.3 - 活动新闻

与 Pigsty 和 PostgreSQL 相关的活动事件与新闻,以及最新活动预告!

最近新闻


版本发布

Pigsty 发布注记

版本 发布时间 摘要 地址
v4.4.0 2026-07-10 PG19 Beta,531 个扩展,内核与软件包更新,Pig CLI 改进 v4.4.0
v4.3.0 2026-05-01 510 扩展,Infra / PGSQL / 内核包批量更新,Ubuntu 26 支持 v4.3.0
v4.2.2 2026-03-23 Insforge 应用自建,Infra 包批量更新,新增 pdu,pgdog v4.2.2
v4.2.1 2026-03-06 弃用 PG 13 支持,464 扩展 v4.2.1
v4.2.0 2026-02-28 例行小版本更新,六大 PG 内核集中更新 v4.2.0
v4.1.0 2026-02-12 操作系统与数据库小版本更新,Agent Native CLI,批量 Bug 修复 v4.1.0
v4.0.0 2026-01-28 Victoria 可观测性,安全加固,JUICE/VIBE 模块,Apache-2.0 v4.0.0
v3.7.0 2025-12-02 PG18 成为默认,437 扩展,EL10/Debian13,PGEXT.CLOUD v3.7.0
v3.6.1 2025-08-15 例行 PG 小版本更新,PGDG 中国区域镜像 v3.6.1
v3.6.0 2025-07-30 pgactive,MinIO/ETCD 改进,安装简化,配置梳理 v3.6.0
v3.5.0 2025-06-16 PG18 Beta,421 扩展,监控升级,代码重构 v3.5.0
v3.4.1 2025-04-05 OpenHalo,OrioleDB,MySQL 兼容性,pgAdmin 改进 v3.4.1
v3.4.0 2025-03-30 备份增强,自动 Certbot 证书,Ivory 跨平台,AGE 扩展 v3.4.0
v3.3.0 2025-02-24 404扩展,Odoo/Dify/Supabase 应用模板,DocumentDB 支持 v3.3.0
v3.2.2 2025-01-23 390扩展,Omnigres 支持,Mooncake,Citus13 与 PG17 支持 v3.2.2
v3.2.1 2025-01-12 350扩展,Ivory4,Citus 强化,Odoo 模板 v3.2.1
v3.2.0 2024-12-24 扩展管理 CLI,Grafana 强化,ARM64 扩展补完 v3.2.0
v3.1.0 2024-11-22 PG 17 作为默认大版本,配置简化,Ubuntu 24 与 ARM 支持,MinIO 改进 v3.1.0
v3.0.4 2024-10-30 PG 17 扩展,OLAP 全家桶,pg_duckdb v3.0.4
v3.0.3 2024-09-27 PostgreSQL 17,Etcd 运维优化,IvorySQL 3.4,PostGIS 3.5 v3.0.3
v3.0.2 2024-09-07 精简安装模式,PolarDB 15支持,监控视图更新 v3.0.2
v3.0.1 2024-08-31 例行问题修复,Patroni 4支持,Oracle 兼容性改进 v3.0.1
v3.0.0 2024-08-25 333个扩展插件,可插拔内核,MSSQL,Oracle,PolarDB 兼容性 v3.0.0
v2.7.0 2024-05-20 扩展大爆炸,新增20+强力扩展插件,与多款 Docker 应用 v2.7.0
v2.6.0 2024-02-28 PG 16 作为默认大版本,引入 ParadeDB 与 DuckDB 等扩展 v2.6.0
v2.5.1 2023-12-01 例行小版本更新,PG16 重要扩展支持 v2.5.1
v2.5.0 2023-09-24 Ubuntu/Debian 支持:bullseye, bookworm, jammy, focal v2.5.0
v2.4.1 2023-09-24 Supabase/PostgresML 支持与各种新扩展:graphql, jwt, pg_net, vault v2.4.1
v2.4.0 2023-09-14 PG16,监控 RDS,服务咨询支持,新扩展:中文分词全文检索/图/HTTP/嵌入等 v2.4.0
v2.3.1 2023-09-01 带 HNSW 的 PGVector,PG 16 RC1, 文档翻新,中文文档,例行问题修复 v2.3.1
v2.3.0 2023-08-20 主机 VIP, ferretdb, nocodb, MySQL 存根,CVE 修复 v2.3.0
v2.2.0 2023-08-04 仪表盘 & 置备重做,UOS 兼容性 v2.2.0
v2.1.0 2023-06-10 支持 PostgreSQL 12 ~ 16beta v2.1.0
v2.0.2 2023-03-31 新增 pgvector 支持,修复 MinIO CVE v2.0.2
v2.0.1 2023-03-21 v2 错误修复,安全增强,升级 Grafana 版本 v2.0.1
v2.0.0 2023-02-28 架构大升级,兼容性、安全性、可维护性显著增强 v2.0.0
v1.5.1 2022-06-18 Grafana 安全性修复 v1.5.1
v1.5.0 2022-05-31 Docker 应用程序支持 v1.5.0
v1.4.1 2022-04-20 错误修复 & 英文文档完整翻译 v1.4.1
v1.4.0 2022-03-31 MatrixDB 支持,分离 INFRA/NODES/PGSQL/REDIS 模块 v1.4.0
v1.3.0 2021-11-30 PGCAT 重整 & PGSQL 增强 & Redis Beta 支持 v1.3.0
v1.2.0 2021-11-03 默认 PGSQL 版本升级至 14 v1.2.0
v1.1.0 2021-10-12 主页,JupyterLab, PGWEB, Pev2 & pgbadger v1.1.0
v1.0.0 2021-07-26 v1 正式版,监控系统重整 v1.0.0
v0.9.0 2021-04-04 Pigsty 图形界面,命令行界面,日志集成 v0.9.0
v0.8.0 2021-03-28 服务置备,定制对外暴露的数据库服务 v0.8.0
v0.7.0 2021-03-01 仅监控部署,监控现有 PostgreSQL 实例 v0.7.0
v0.6.0 2021-02-19 架构增强,将 PG 与 Consul 解耦 v0.6.0
v0.5.0 2021-01-07 支持在配置中定义业务数据库/用户 v0.5.0
v0.4.0 2020-12-14 支持 PostgreSQL 13,添加官方文档 v0.4.0
v0.3.0 2020-10-22 虚拟机置备方案正式定稿 v0.3.0
v0.2.0 2020-07-10 PG 监控系统第六版正式发布 v0.2.0
v0.1.0 2020-06-20 在生产仿真测试环境中验证通过 v0.1.0
v0.0.5 2020-08-19 离线安装模式:无需互联网访问即可交付 v0.0.5
v0.0.4 2020-07-27 将 Ansible 剧本重构为 Role Refactor playbooks into ansible roles v0.0.4
v0.0.3 2020-06-22 接口设计改进 v0.0.3
v0.0.2 2020-04-30 首次提交 v0.0.2
v0.0.1 2019-05-15 概念原型 v0.0.1

会议与演讲

日期 类型 活动 主题
2025-11-29 获奖&演讲 第八届 PostgreSQL 生态大会(杭州) PostgreSQL Magneto Award,世界级 Postgres 元发行版
2025-05-16 闪电演讲 PGConf.Dev 2025(蒙特利尔) Extension Delivery: 让您的 PGEXT 触达用户
2025-05-12 主题演讲 PGEXT.DAY, PGCon.Dev 2025 PostgreSQL 生态中缺失的包管理器与扩展仓库
2025-04-19 实战工坊 PostgreSQL 数据库技术峰会 使用 Pigsty 部署 PG 生态伙伴:Dify, Odoo, Supabase
2025-04-11 直播主持 OSCHINA 数智 Talk 刷屏的 MCP 是炒作还是革命?
2025-01-15 直播分享 开源老将与新秀第四期 PostgreSQL 扩展吞噬数据库世界?PG 包管理器 pig 与自建 RDS Pigsty
2025-01-09 颁奖典礼 OSCHINA 2024 年度杰出贡献专家 年度杰出贡献专家
2025-01-06 圆桌论坛 中国 PostgreSQL 数据库生态大会 PostgreSQL 扩展正在吞噬数据库世界
2024-11-23 播客 技术乱炖 Podcast 来自 Linux 基金会:为什么最近都在关注"卡脖子"?
2024-08-21 媒体专访 蓝色科技浪潮 Pigsty 作者冯若航专访:简化 PG 管理,推动中国开源社区
2024-08-15 技术大会 GOTC 全球开源技术峰会 PostgreSQL AI/ML/RAG 扩展生态与最佳实践
2024-07-12 主题演讲 第十三届 PG 中国技术大会 数据库世界的未来:扩展,服务,与 Postgres
2024-05-31 非正式会议 PGCon.Dev 2024 全球 PG 开发者大会 Unconference 内置 Prometheus 指标导出器
2024-05-28 专题研讨 PGCon.Dev 2024 全球 PG 开发者大会 扩展峰会 Extension in Core & Binary Packing
2024-05-10 直播辩论 三人行·云计算泥石流系列 第三期 公有云是骗局吗?
2024-04-17 直播辩论 三人行·云计算泥石流系列 第二期 云数据库是智商税吗?
2024-04-16 圆桌论坛 Cloudflare Immerse 深圳 赛博菩萨圆桌论坛
2024-04-12 技术大会 2024 数据技术嘉年华 Pigsty:解决 PostgreSQL 运维难题
2024-03-31 直播辩论 三人行·云计算泥石流系列 第一期 罗永浩卖云,我们却在下云?
2024-01-24 直播主持 OSCHINA 开源漫谈 第九期 DBA 会被云干掉吗?
2023-12-20 直播辩论 开源漫谈第七期 上云 or 下云,割韭菜还是降本增效?
2023-11-24 技术大会 大模型时代的向量数据库 圆桌讨论:大模型时代向量数据库新未来
2023-09-08 人物专访 墨天轮风云人物访谈 冯若航:不想当段子手的技术狂,不是一位好的开源创始人
2023-08-16 技术大会 DTCC 2023 DBA 之夜:PostgreSQL vs MySQL 的开源协议问题
2023-08-09 直播辩论 开源漫谈第一期 MySQL vs PostgreSQL,谁是世界第一?
2023-07-01 技术大会 SACC 2023 专题研讨会8:FinOps 实践:云成本管理与优化
2023-05-12 线下活动 PostgreSQL 中国社区 温州站线下沙龙 PG With DB4AI: 向量数据库 PGVECTOR & AI4DB: 数据库自动驾驶 Pigsty
2023-04-08 技术大会 数据库嘉年华 2023 更好的开源 RDS 替代:Pigsty
2023-04-01 技术大会 PostgreSQL 中国社区 西安站线下沙龙 PG 高可用与容灾最佳实践
2023-03-23 公开直播 Bytebase x Pigsty 管理 PostgreSQL 的最佳实践:Bytebase x Pigsty
2023-03-04 技术大会 PostgreSQL 中国技术大会 炮打 RDS,Pigsty v2.0 发布
2023-02-01 技术大会 DTCC 2022 开源 RDS 替代:开箱即用、自动驾驶的数据库发行版 Pigsty
2022-07-21 直播辩论 云吞噬开源,那开源有机会反击吗? 云吞噬开源,那开源有机会反击吗?
2022-07-04 人物专访 专题采访:创造者说 90 后,辞职创业,说要卷死云数据库
2022-06-28 公开直播 贝斯的圆桌趴 |DBA 福音 - SQL 审核最佳实践
2022-06-12 公开路演 奇绩创坛 S22 路演日 好用省钱的数据库发行版 Pigsty
2022-06-05 视频直播 PG 中文社区直播分享 Pigstyv1.5 快速上手新特性介绍与生产集群搭建

4.4 - 发展规划

未来功能的规划,新功能的发布节奏,待办事项列表。

版本发布策略

Pigsty 使用语义化版本号,<主版本>.<次版本>.<修订号>。Alpha / Beta / RC 版本会在版本号后添加后缀,如 -a1-b1-c1

主版本更新意味着不兼容的基础性变化与重大新特性;次版本更新通常表示普通功能特性更新,较小的 API 变动;修订版本更新意味着 Bug 修复与软件包版本更新。

Pigsty 计划每年发布一次主版本更新,次版本更新通常跟随 PostgreSQL 小版本更新节奏,在 PostgreSQL 新版本发布后最迟一个月内跟进。 Pigsty 通常每年计划 4 - 6 个小版本,完整发布历史请参考 发行注记

使用具体的版本号进行部署

Pigsty 使用 main 主干分支进行开发,请始终使用带有版本号的 Release

除非您清楚知道自己在做什么,否则请勿使用 GitHub 的 main 分支,总是检出特定版本使用。


列入考虑的新特性

  • Agent Native CLI - PIG
  • DBA Agent - 基本集成
  • Grafana Dashboard 改进
  • Boar 管理平台

这里是我们的 活跃议题路线图


扩展插件与软件包

关于扩展支持的路线图,可以在这里找到:https://pgext.cloud/e/roadmap

考虑纳入

暂不考虑

4.5 - 加入社区

Pigsty 是一个 Build in Public 的项目,我们在 GitHub 上非常活跃,中文区用户主要活跃于微信群组中。

GitHub

我们的 GitHub 仓库地址是:https://github.com/pgsty/pigsty,欢迎点个 ⭐️ 关注 我们。

我们欢迎任何人 提交新 Issue 或创建 Pull Request,提出功能建议并参与 Pigsty 贡献。

Star History Chart

请注意,关于 Pigsty 文档的问题,请在 github.com/pgsty/pigsty.cc 仓库中提交 Issue

在本站按 K(macOS)或 CtrlK,可以直接搜索文档、扩展与博客文章。


维护者

Pigsty 由维护者与社区共同建设。

2 位贡献者 GitHub

微信群组

中文区用户主要活跃于微信群组中,目前有七个活跃的群组,1群-4群已经满员,其他群需要添加小助手微信拉入。

加入微信社群,请用搜索 “Pigsty小助手”,(微信号 pigsty-cc) 备注或发送 “加群” ,小助手会将您拉入群组中。

Pigsty 中文社区

海外社群

Telegram: https://t.me/joinchat/gV9zfZraNPM3YjFh

Discord: https://discord.gg/j5pG8qfKxU

您也可以通过邮件联系我: [email protected]


社区求助

当您使用 Pigsty 遇到问题时,可以向社区求助,您提供的信息越丰富,就越有可能在社区得到帮助。

请参考 社区求助指南,尽可能提供足够的信息,以便社区成员帮助您解决问题。以下是求助提问的参考模板:

发生了什么事? (必选项)

Pigsty 版本号与操作系统版本 (必选项)

$ grep version pigsty.yml 

$ cat /etc/os-release

$ uname -a

一些云厂商对标准操作系统发行版进行了定制,您可以告诉我们使用的是哪一家云厂商的什么操作系统镜像。 如果您在安装操作系统后对环境进行了定制与修改,或者在您的局域网中有特定的安全规则与防火墙配置,也请在提问时告知我们。

Pigsty 配置文件

请不要忘记抹掉任何敏感信息:密码,内部密钥,敏感配置等。

cat ~/pigsty/pigsty.yml

你期待发生什么?

请描述正常情况下应该发生什么事情,实际发生的情况与期待的情况有何偏离?

如何复现此问题?

请尽可能详细地告诉我们复现此问题的方法与步骤。

监控截图

如果你在使用 Pigsty 提供的监控系统,可以提供 相关 的截图。

错误日志

请尽可能提供与错误有关的日志。请不要粘贴类似 “Failed to start xxx service” 之类没有信息量的内容

您可以从 Grafana / VictoriaLogs 中查询日志,或从以下位置获取日志:

  • Syslog: /var/log/messages (rhel) or /var/log/syslog (debian)
  • Postgres: /pg/log/postgres/*
  • Patroni: /pg/log/patroni/*
  • Pgbouncer: /pg/log/pgbouncer/*
  • Pgbackrest: /pg/log/pgbackrest/*
journalctl -u patroni
journalctl -u <service name>

您已经搜索过 Issue/网站/FAQ 了吗?

在 FAQ 中,我们提供了许多常见问题的解答,请在提问前检查

您也可以从 Github Issue 与 Discussion 中搜索相关问题:

有什么其他信息是我们需要知道的吗?

您提供的信息与上下文越丰富,我们越有可能帮助您解决问题。

4.6 - 隐私政策

Pigsty 软件与网站会收集哪些用户数据,以及我们将如何处理您的数据并保护您的隐私权?

Pigsty软件

当您安装 Pigsty 软件时,如果在网络隔离的环境中使用离线软件包安装,我们不会收到任何关于您的数据

如果您选择在线安装,那么在下载相关软件包时,我们的服务器或云供应商的服务器会自动在日志中记录来访机器的 IP 地址和/或主机名,和您下载的软件包名称。 除非法律要求,我们不会与其他组织共享这些信息。(实话说,吃饱了撑着才会去看这些东西)

Pigsty 使用的主域名为:pigsty.io,中国大陆请使用中文备案镜像站点 pigsty.cc


Pigsty网站

当您访问我们的网站时,我们的服务器会自动在 Nginx 日志中记录您的 IP 地址和/或主机名。 仅当您决定通过完成调查或在我们的某个网站上注册为用户来向我们发送此类信息时,我们才会存储您的电子邮件地址、姓名和地点等信息

我们收集这些信息是为了帮助我们改进网站内容、定制网页布局以及出于技术和支持目的联系人员。除非法律要求,我们不会与其他组织共享您的电子邮件地址。

本网站使用 Google Analytics,这是 Google, Inc.(“Google”)提供的一项网络分析服务。谷歌分析使用“cookies”,即放置在您计算机上的文本文件,帮助网站分析用户如何使用该网站。

cookie 生成的有关您使用网站的信息(包括您的 IP 地址)将被传输至 Google 位于美国的服务器并由其存储。谷歌将使用这些信息来评估您对网站的使用情况,为网站运营商编制网站活动报告,并提供与网站活动和互联网使用相关的其他服务。 如果法律要求,或者第三方代表 Google 处理信息,Google 还可能会将此信息传输给第三方。 Google 不会将您的 IP 地址与 Google 持有的任何其他数据关联起来。 您可以通过在浏览器上选择适当的设置来拒绝使用 cookie,但请注意,如果您这样做,您可能无法使用本网站的全部功能。使用本网站即表示您同意 Google 以上述方式和目的处理有关您的数据。

如果您对此政策有任何疑问或意见,或要求删除个人数据,您可以通过发送邮件至 [email protected] 与我们联系

4.7 - 开源协议

Pigsty 使用的开源协议 —— Apache-2.0,它授予您什么样的权利,又有哪些限制?

协议摘要

Pigsty 项目主体使用 Apache-2.0 开源许可证;Pigsty 文档网站使用 CC by 4.0 许可证。 项目协议地址:https://github.com/pgsty/pigsty/blob/main/LICENSE


Pigsty 项目主体

Pigsty 软件主体采用 Apache License 2.0 许可证。 这是一种宽松的开源许可证,允许您自由地使用、修改和分发本软件,包括用于商业目的,而无需公开您的源代码或使用相同许可证。

本协议授权您 本协议不提供 本协议的条件
商用 商标使用权 包含本许可证与版权声明
修改 责任与担保 声明对原始代码的修改
分发
专利授权
私人使用

Pigsty 文档网站

Pigsty 的文档与网站(包括但不限于:pigsty.ccpigsty.iopgsty.com)均使用 Creative Commons Attribution 4.0 International (CC BY 4.0) 许可证。 CC BY 4.0 是一种知识共享许可证,允许您自由地分享与演绎本站的内容,但是您必须给出 适当的署名,提供指向许可证的链接,并 指出是否有对原始内容进行了修改

本协议授权您 本协议不提供 本协议的条件
商用 商标使用权 署名(注明原作者)
修改 责任与担保 标明修改内容
分发 专利授权 提供许可证链接
私人使用

SBOM 清单

以下为 Pigsty 项目所使用或相关的开源软件及其开源协议。

575 个 PostgreSQL 扩展插件的许可证请参考 PostgreSQL 扩展许可证清单

模块 软件名称 许可证 必要性,用途与说明 必要性
PGSQL PostgreSQL PostgreSQL License PostgreSQL 内核 必选
PGSQL patroni MIT License 提供 PostgreSQL 高可用能力 必选
ETCD etcd Apache License 2.0 提供高可用共识与分布式配置存储 必选
INFRA Ansible GPLv3 管控工具,执行剧本,发起管控命令 必选
INFRA Nginx BSD-2 暴露 Web 系统界面,提供本地软件源 建议
PGSQL pgbackrest MIT License 提供 PITR 备份/恢复管理能力 建议
PGSQL pgbouncer ISC License 提供 PostgreSQL 连接池化能力 建议
PGSQL vip-manager BSD 2-Clause License 提供自动将 L2 VIP 绑定到 PG 集群主库的能力 建议
PGSQL pg_exporter Apache License 2.0 提供监控 PostgreSQL 与 PgBouncer 的能力 建议
NODE node_exporter Apache License 2.0 提供主机节点监控能力 建议
NODE haproxy HAPROXY’s License (GPLv2) 提供负载均衡,对外暴露服务的能力 建议
INFRA Grafana AGPLv3 提供数据库可视化平台 建议
INFRA VictoriaMetrics Apache License 2.0 提供监控时序数据库存储,指标采集与监控告警 建议
INFRA VictoriaLogs Apache License 2.0 提供集中式日志收集存储查询平台 建议
INFRA DNSMASQ GPLv2 / GPLv3 提供 DNS 解析服务,提供集群名查询能力 建议
MINIO Silo AGPLv3 当前 MINIO 模块唯一支持的对象存储服务 可选
INFRA MinIO 历史分支 AGPLv3 历史/仓库软件包;不是 v4.5 MINIO 后端 可选
INFRA RustFS Apache License 2.0 仓库保留软件包;不是 v4.5 MINIO 后端 可选
NODE keepalived MIT License 提供绑定在节点集群上的 VIP 可选
REDIS Redis BSD 3-Clause 默认缓存引擎,使用 Redis 7.2 BSD 分支 可选
REDIS Valkey BSD 3-Clause 可通过 redis_type: valkey 选择的缓存引擎 可选
REDIS Redis Exporter MIT License 提供 Redis 监控能力 可选
MONGO FerretDB Apache License 2.0 提供基于 PG 的 MongoDB 兼容能力 可选
DOCKER docker-ce Apache License 2.0 提供容器管理能力 可选
CLOUD SealOS Apache License 2.0 提供快速部署,复制,打包 K8S 集群的能力 可选
DUCKDB DuckDB MIT 提供简单易用的高性能分析能力 可选
External Vagrant Business Source License 1.1 拉起本地测试环境虚拟机 可选
External Terraform Business Source License 1.1 一键申请云资源用于部署 可选
External Virtualbox GPLv2 虚拟机管理软件 可选

必要性等级说明:

  • 必选:提供 Pigsty 关键性核心能力,不提供关闭停用选项
  • 建议:Pigsty 默认启用 的组件,可以通过配置选项停用
  • 可选:Pigsty 默认支持但不启用的组件,可通过配置启用

Apache-2.0 许可证原文


                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright (C) 2018-2026  Ruohang Feng, @Vonng ([email protected])

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

4.8 - 赞助我们

Pigsty 的赞助者,投资人名单,感谢你们对本项目的支持!

赞助我们

Pigsty 是一个开源免费的自由软件,由 PostgreSQL 社区成员用热情浇灌而成,旨在整合 PostgreSQL 生态的力量,推广 PostgreSQL 的普及。 如果我们的工作帮到了您,请考虑赞助或者支持一下我们的项目:

  • 直接打钱赞助我们,用最直接有力的鼓舞表达您的真挚支持!
  • 考虑采购我们的 技术支持服务,我们可以提供专业的 PostgreSQL 高可用集群部署与维护服务,让您的预算花得物有所值!
  • 通过文章,讲座,视频分享您使用 Pigsty 的案例与经验。
  • 允许我们在 “这些用户使用了 Pigsty” 中提及您的组织。
  • 向有需求的朋友,同事与客户提名/推荐我们的项目与服务。
  • 关注我们的 微信公众号 并转发相关技术文章至群组与朋友圈。

天使投资人

Pigsty 是由 奇绩创坛 (原 YC 中国,MiraclePlus) S22 所投资的项目,感谢奇绩创坛与陆奇博士对本项目的支持!


赞助者

感谢我们的赞助者 Vercel,为 Pigsty 网站提供了赞助与网站托管基础设施。

Vercel OSS Program

感谢我们的赞助者 Jet Brains,为 Pigsty 提供了 JetBrains Open Source License 计划的支持。

JetBrains logo.

4.9 - 行业案例

Pigsty 在各个领域与行业的客户/应用案例

根据 Google Analytics PV 与下载量,Pigsty 目前有约 10 万用户,一半来自中国大陆,一半来自全球其他地区。 遍布互联网、云计算、金融、自动驾驶、制造业、科技创新、ISV 与军工等多个行业。 如果您在 使用 Pigsty 并且愿意与我们分享您的案例与 Logo,欢迎联系我们,我们提供一次的免费咨询支持。

互联网

探探:两百台+物理机,用于 PostgreSQL 与 Redis 服务

哔哩:用于支持 PostgreSQL 创新业务

云厂商

Bitdeer:比特小鹿,提供 PG DBaaS

Oracle OCI:使用 Pigsty 交付 PostgreSQL 集群。

金融行业

AirWallex:监控 200+ GCP PostgreSQL 数据库

影视行业

影视飓风:自建 PG RDS / Victoria Metrics

自动驾驶

Momenta:自动驾驶,管理自建 PostgreSQL 集群

制造业

华峰集团:使用 Pigsty 交付 PostgreSQL 集群作为化工时序数据仓库

科技创新

北京领雾科技:云上 PostgreSQL 下云自建

Motphys:自建 PostgreSQL 支持 Gitlab

赛陇生物科技:自建 Supabase

杭州零码科技:自建 PostgreSQL

ISV

内蒙古豪德天沐科技有限公司

上海元芳

DSG

军工

北京某部队

上海某部队

电科36所

机械工业研究所

航天一院

4.10 - 订阅服务

Pigsty 专业版/企业版订阅服务:当您遇到与 PostgreSQL 和 Pigsty 有关的疑难杂症时,订阅服务可以为您兜底。

Pigsty 旨在聚集 PG 生态的合力,并用自动驾驶的数据库管控软件帮助用户用好世界上 最流行 的数据库 PostgreSQL。

尽管 Pigsty 本身已经解决了 PG 使用中的诸多问题。但想真正达到企业级服务的质量,原厂提供的专家支持与兜底服务不可或缺。 我们深知专业的商业支持服务对于企业客户的重要性,因此,Pigsty 企业版在开源版本的基础上提供了一系列增值服务,帮助用户更好地用好 PostgreSQL 与 Pigsty,供有需求的客户按需选用。

如果您有下列需求,欢迎考虑 Pigsty 订阅服务:

  • 在关键场景中运行数据库,需要严格 SLA 保障兜底。
  • 希望对 Pigsty 与 PostgreSQL 相关疑难杂症提供兜底。
  • 希望获取关于 PostgreSQL / Pigsty 生产环境最佳实践的指导。
  • 希望有专家帮助解读监控图表,分析定位性能瓶颈与故障根因,给出意见。
  • 希望根据现有资源与业务需求,规划满足安全/容灾/合规要求的数据库架构。
  • 需要将其他数据库迁移至 PostgreSQL 数据库,或对历史遗留实例迁移与改造。
  • 希望支持国产信创操作系统/国产信创 ARM 芯片架构,提供中文/本地化界面支持。
  • 建设基于 Victoria / Grafana 技术栈的可观测性体系,数据大盘,可视化应用。
  • 下云并寻求 RDS for PostgreSQL 的开源替代 —— 云中立,无供应商锁定的解决方案。
  • 希望获取关于 Redis / ETCD / Silo,以及 TimescaleDB / Citus 等扩展的专业支持。
  • 希望将 Pigsty 作为 SaaS / PaaS / DBaaS 对外销售,或基于此发行版提供技术服务/云服务。

订阅计划

除了 开源版 之外,Pigsty 提供两种不同的订阅服务档位:专业版企业版,您可以根据自身的实际情况与需求选购。

Pigsty 开源版(OSS)开源免费

无规模限制,无质保承诺

许可协议:Apache-2.0
**PG 支持:**18(默认),14–18 可选
**架构支持:**x86_64,Arm64
**OS 支持:**三系最新小版本

  • EL 9.8 / 10.2
  • Debian 12.15 / 13.6
  • Ubuntu 22.04.5 / 24.04.4 / 26.04.0

功能:核心模块
**SLA:**无 SLA 承诺

社区公益支持答疑:

**支持:**无人天支持选项
**仓库:**全球 CF 托管仓库

适合自给自足的开源老司机。

Pigsty 专业版(PRO)150,000 ¥ / 年

普通用户的默认之选

**许可协议:**商业许可证
**PG 支持:**14–18
**架构支持:**x86_64,Arm64
**OS 支持:**八系大小版本

  • EL 8 / 9 / 10 兼容
  • Debian 12 / 13
  • Ubuntu 22 / 24 / 26

功能:所有模块(信创除外)
**SLA:**工作日时效内响应

提供专家咨询服务:

  • 软件缺陷修复
  • 疑难杂症分析
  • 专家工单答疑

**支持:**每年包含 1 人天
**交付:**标准离线软件包
**仓库:**中国大陆镜像站

普通用户的默认之选。

Pigsty 企业版(ENTERPRISE)400,000 ¥ / 年

严格 SLA 的关键场景

**许可协议:**商业许可证
**PG 支持:**14–18+(旧版本按需定制)
**架构支持:**x86_64,Arm64
**OS 支持:**按需定制

  • EL, Debian, Ubuntu
  • 云上 Linux 操作系统
  • 国产操作系统与 ARM

功能:所有模块
**SLA:**7 x 24 (< 1h)

提供企业级专家咨询服务:

  • 软件缺陷修复
  • 疑难杂症分析
  • 专家答疑解惑
  • 备份合规建议
  • 升级路径支持
  • 性能瓶颈定位
  • 年度架构评估
  • 扩展插件收录
  • DBaaS & OEM 用例

**支持:**每年包含 2 人天
**仓库:**中国大陆镜像站
**交付:**定制离线软件包
信创:PolarDB-O 支持

适合严格 SLA 的关键场景。


Pigsty开源版

Pigsty 开源版使用 Apache-2.0 许可证, 提供了完整核心功能,无需任何费用,但也不承诺任何质保服务。如果您发现了 Pigsty 的缺陷,我们非常欢迎您在 Github 上提出 Issue

Pigsty 开源软件支持七个当前验证基线:EL 9.8 / 10.2、Debian 12.15 / 13.6、Ubuntu 22.04.5 / 24.04.4 / 26.04.0,并覆盖 x86_64aarch64v4.4.0 社区版历史制品基于 EL 10.1、Debian 13.6、Ubuntu 24.04.4 发布双架构离线包,共 6 个制品;历史制品的制作基线不等同于当前推荐操作系统,详见 离线安装说明

使用 Pigsty 开源版本,可以让初级研发工程师 / 运维工程师拥有专业 DBA 70%+ 的能力,在缺少数据库专家的情况下,也能够轻松搭建一个高可用,高性能,易维护,安全可靠的 PostgreSQL 数据库集群。

代号 操作系统发行版版本 x86_64 aarch64 PG18 PG17 PG16 PG15 PG14
EL10 RHEL 10 / Rocky10 / Alma10 el10.x86_64 el10.aarch64
EL9 RHEL 9 / Rocky9 / Alma9 el9.x86_64 el9.aarch64
U26 Ubuntu 26.04 (resolute) u26.x86_64 u26.aarch64
U24 Ubuntu 24.04 (noble) u24.x86_64 u24.aarch64
U22 Ubuntu 22.04 (jammy) u22.x86_64 u22.aarch64
D13 Debian 13 (trixie) d13.x86_64 d13.aarch64
D12 Debian 12 (bookworm) d12.x86_64 d12.aarch64

= 首要支持, = 选配支持


Pigsty专业版

专业版订阅: 起售价格 ¥ 150,000 / 年

Pigsty 专业版订阅提供了完整的功能模块,以及对于 Pigsty 本身的质保。关于 PostgreSQL 本身与扩展插件的缺陷,我们将尽最大努力通过 PostgreSQL 全球开发者社区进行反馈与修复。

Pigsty 专业版构建于开源版基础之上,完全兼容开源版本的所有功能,并提供额外的功能模块,与更为宽广的数据库 / 操作系统版本兼容选项:我们将针对八个主流操作系统发行版(EL8/9/10、Debian 12/13、Ubuntu 22/24/26)的 所有小版本 提供构建选项。

Pigsty 专业版包含了对 PostgreSQL 14 - 18 的支持,并持续跟进上游 PostgreSQL 小版本更新(活跃大版本通常做到当日或准当日可用),确保您可以通过滚动升级的方式,平滑迁移到最新的 PostgreSQL 大版本上。

Pigsty 专业版订阅允许您使用中国大陆镜像站点软件仓库,无需翻墙代理即可访问;同时我们将针对您使用的精准操作系统大小版本定制离线软件安装包,确保在断网环境下也能正常安装交付,做到自主可控。

Pigsty 专业版订阅提供了标准的专家咨询服务,包括疑难杂症分析,DBA 答疑解惑,备份合规建议等,我们承诺在工作日(5x8)时效内响应您的问题,并且每年提供 1 人天支持,以及可选的人天加购选项。

Pigsty 专业版使用商业许可证,提供额外的功能模块、技术支持与质保服务。

Pigsty 专业版的起售价格 ¥150,000 / 年,相当于 9 vCPU 的 AWS 高可用 RDS PG 年费, 或月薪 一万元 的初级运维工程师。

代号 操作系统发行版版本 x86_64 Arm64 PG18 PG17 PG16 PG15 PG14
EL10 RHEL 10 / Rocky10 / Alma10 el10.x86_64 el10.aarch64
EL9 RHEL 9 / Rocky9 / Alma9 el9.x86_64 el9.aarch64
EL8 RHEL 8 / Rocky8 / Alma8 / Anolis8 el8.x86_64 el8.aarch64
U26 Ubuntu 26.04 (resolute) u26.x86_64 u26.aarch64
U24 Ubuntu 24.04 (noble) u24.x86_64 u24.aarch64
U22 Ubuntu 22.04 (jammy) u22.x86_64 u22.aarch64
D13 Debian 13 (trixie) d13.x86_64 d13.aarch64
D12 Debian 12 (bookworm) d12.x86_64 d12.aarch64

Pigsty企业版

企业版订阅: 起售价格 ¥ 400,000 / 年

Pigsty 企业版订阅包含 Pigsty 专业版订阅提供的全部服务内容,和以下增值服务项:

Pigsty 企业版订阅提供最为广泛的数据库/操作系统版本支持范围,包括对过保操作系统(EL7, D11),国产操作系统,云厂商操作系统,以及过保数据库大版本(PG12+ 按需定制)的延长支持,以及对 Arm64 架构芯片的完整支持。

Pigsty 企业版订阅提供了信创,国产化解决方案,允许您在 Pigsty 中使用 PolarDB v2.0 (此内核许可需单独采购)内核替换原生 PostgreSQL 内核,以满足国产化合规要求。

Pigsty 企业版订阅提供了更高标准的企业级咨询服务,承诺 7x24 提供 (< 1h) 的响应时间 SLA,并可提供更多种类的咨询支持:版本升级,性能瓶颈定位,年度架构评估,扩展插件收录等。

Pigsty 企业版订阅每年自带 2 人天支持,以及可选的人天加购选项,用于解决各种更为棘手复杂耗时的问题。

Pigsty 企业版允许您将 Pigsty 用于 DBaaS 用途,建设云数据库服务对外出售。

Pigsty 企业版的起步价格为 ¥400,000 / 年,相当于 24 vCPU 的 AWS 高可用 RDS 年费,或月薪 三万元 的运维专家。

代号 操作系统发行版版本 x86_64 aarch64 PG18 PG17 PG16 PG15 PG14 PG13 PG12
EL10 RHEL 10 / Rocky10 / Alma10 el10.x86_64 el10.aarch64
EL9 RHEL 9 / Rocky9 / Alma9 el9.x86_64 el9.aarch64
EL8 RHEL 8 / Rocky8 / Alma8 / Anolis8 el8.x86_64 el8.aarch64
U26 Ubuntu 26.04 (resolute) u26.x86_64 u26.aarch64
U24 Ubuntu 24.04 (noble) u24.x86_64 u24.aarch64
U22 Ubuntu 22.04 (jammy) u22.x86_64 u22.aarch64
D13 Debian 13 (trixie) d13.x86_64 d13.aarch64
D12 Debian 12 (bookworm) d12.x86_64 d12.aarch64
D11 Debian 11 (bullseye) d11.x86_64 d11.aarch64
EL7 RHEL7 / CentOS7 / UOS … el7.x86_64 -

Pigsty订阅说明

功能差异

Pigsty 专业版/企业版相比开源版本,包含以下额外功能:

  • 命令行管理工具: 解锁 Pigsty 命令行工具(pig)的完整功能
  • 系统定制能力:针对精确的主流 Linux 操作系统发行版大小版本提供预制的离线安装包
  • 离线安装能力:在没有互联网访问的环境中(断网环境)实现 Pigsty 的完整安装
  • PG 内核多版本:允许用户自由指定并安装 PostgreSQL 生命周期内大版本的内核(14 - 18)
  • 内核替换能力:允许用户使用其他 PostgreSQL 系兼容内核,替换原生 PG 内核,以及离线安装这些内核的能力
    • Babelfish:提供 Microsoft SQL Server 线缆协议级兼容能力
    • IvorySQL:基于 PG 提供 Oracle 语法/类型/存储过程兼容能力
    • PolarDB PG:提供基于开源的 PolarDB for PostgreSQL 内核支持
    • PolarDB O:信创数据库,满足国产化合规要求的 Oracle 兼容内核(仅限企业版订阅
  • 扩展支持能力:针对 575 个可用 PG Extension,提供 PG 14-18 在主流操作系统上开箱即用的安装能力。
  • 完整功能模块:提供所有功能模块:
    • Supabase:可靠地自建生产级开源 Firebase
    • Silo:企业 PB 级对象存储规划与自建
    • DuckDB:提供完善的 DuckDB 支持,以及 PostgreSQL + DuckDB OLAP 扩展插件支持
    • Kafka:提供高可用的 Kafka 集群部署与监控
    • Kubernetes, VictoriaMetrics & VictoriaLogs
  • 国产操作系统支持:提供国产信创操作系统支持选项(仅限企业版订阅
  • 国产 ARM 架构支持:提供国产 ARM64 架构支持选项(仅限企业版订阅
  • 中国大陆镜像仓库:无需科学上网即可顺畅安装,提供境内 YUM/APT 仓库镜像与 DockerHub 访问代理。
  • 中文界面支持:监控系统中文版界面支持(Beta)

付费模式

Pigsty 订阅采用按年付费的模式,签订合同后,从合同约定日起计算一年的有效期。订阅合同到期前如果继续打款则视为自动续订。 连续订阅有折扣,第一次续签(第二年)享受 95 折优惠,第二次以及后续的续签享受订阅费用 9 折优惠,一次性订阅三年以上整体费用享受 85 折优惠。

在年度订阅合同终止后,您可以选择不续签订阅服务,Pigsty 将不再提供软件更新,技术支持,咨询服务,但您仍然可以继续使用已经安装版本的 Pigsty 专业版软件。 如果您订阅了 Pigsty 专业服务并选择不续订,在重新订阅时 无需 补齐中断期间的订阅费用,但所有折扣与优惠将重置。

Pigsty 的定价策略确保用户物有所值 —— 您可以立即获得顶尖 DBA 的数据库架构建设方案与管理最佳实践,并由其提供咨询答疑与服务支持兜底; 而付出的成本相比于全职雇佣数据库专家或使用云数据库极具竞争力。以下是市场上 企业级数据库专业服务市场定价参考

体面数据库专业服务的公允价格是 1 ~ 2 万元 / 年,计费单位为 vCPU,即一个 CPU 线程(1 Intel 核 = 2 vCPU 线程)。 而 Pigsty 提供国内顶尖的 PostgreSQL 专家服务,并采用 按节点计费 的模式,在当下常见的高核数服务器节点上,能为用户带来无可比拟的 降本增效 体验。


Pigsty专家服务

除了 Pigsty 订阅,Pigsty 还提供按需采购的 Pigsty x PostgreSQL 专家服务 —— 业界顶级数据库专家坐堂问诊。

专家顾问:300,000 ¥ / 三年


在三年内,提供 10 次关于 PostgreSQL 与 Pigsty 的复杂案例处理,以及不限量答疑。

专家支持:30,000 ¥ / 人·天


业界顶级专家现场支持,可用于架构咨询,故障分析,问题排查,数据库体检,监控解读,迁移评估,教学培训,上下云参谋等连续耗时场景。

专家咨询:3000 ¥ / 例


咨询任何您想要了解的问题,关于 Pigsty, PostgreSQL,数据库,云计算,AI…… 数据库老司机,云计算泥石流与您分享行业顶级洞察、认知与研判。

挂专家号:300 ¥ / 问题


给出一个关于 PostgreSQL / Pigsty / 数据库相关的问题的快速诊断意见与答复,不超过 5 分钟。

服务主体

Pigsty 目前由作者 冯若航 独资运营维护,商业主体为:

  • 海南诸夏云数据有限公司 / 91460000MAE6L87B94
  • 海口龙华辟技数据中心 / 92460000MAG0XJ569B
  • 海口龙华越航科技中心 / 92460000MACCYGBQ1N

PIGSTY® 与 PGSTY® 为海口龙华越航科技中心的注册商标。

商务咨询请发送邮件至 [email protected]。中国大陆地区用户欢迎添加微信号 RuohangFeng

Pigsty 是奇绩创坛 S22 被投项目,原主体 磐吉云数(北京)科技有限责任公司 已经清算剥离 Pigsty 业务,与 Pigsty 无关。

4.11 - 常见问题

解答关于 Pigsty 项目本身的常见问题。

Pigsty 是什么,不是什么?

Pigsty 是一个 PostgreSQL 数据库发行版,本地优先的开源 RDS 云数据库解决方案。 Pigsty 不是数据库管理系统(DBMS),而是管理 DBMS 的工具,发行版,解决方案,与最佳实践。

类比:数据库是车,那么 DBA 是司机,RDS 是出租车服务,Pigsty 则是自动驾驶软件。


Pigsty 解决什么问题?

用好数据库的能力 极为稀缺:要么高薪聘请数据库专家自建(雇司机),或从云厂商以天价租赁 RDS(打车),但现在你有新的选项:Pigsty(自动驾驶)。 Pigsty 帮用户用好数据库:让用户在没有 DBA 的情况下,以不到 RDS 1 / 10 的成本,自建质量效率更优的本地云数据库服务!


Pigsty 的目标用户是谁?

Pigsty 有两类典型目标用户,基本盘是 中大型公司 超大规模自建企业级/生产级 PostgreSQL RDS / DBaaS 服务。 Pigsty 通过极致的可定制性,可以实现最苛刻场景的数据库管理需求,并提供企业级的支持与服务保障。

与此同时,Pigsty 也针对个人开发者,缺乏 DBA 中小企业以及开源社区提供 “开箱即用” 的 PG RDS 自建方案。


Pigsty 为什么能帮您用好数据库?

Pigsty 沉淀了顶尖专家在最复杂,最大规模的甲方 PostgreSQL 场景中打磨得到的经验与最佳实践,产品化为可复制的软件: 一次性解决扩展安装,高可用,链接池,监控,备份恢复,参数优化,IaC 批量管理,一键安装,自动化运维等诸多问题。提前规避诸多陷阱,避免重复踩坑。


Pigsty 为何比 RDS 好用?

Pigsty 提供远超 RDS 的特性集与基础设施支持,包括 575 扩展插件与 12+ 内核支持。 Pigsty 提供 PG 生态中独一无二的专业级监控系统,与久经复杂场景打磨考验的架构最佳实践,简单易用。

且用探探,苹果,阿里等顶级甲方场景打磨而成,用激情与热爱持续浇灌,深度与成熟度绝非 RDS 大锅饭可比。


Pigsty 为何比 RDS 省钱?

Pigsty 允许您使用 10 ¥/核·月的纯硬件资源,运行 400¥-1400¥/核·月的 RDS 云数据库,并省去 DBA 的工资。通常,成规模的 Pigsty 部署总拥有成本(TCO)能比 RDS 低 90% 以上。

Pigsty 能够同时降低软件许可/服务/人力的开销,自建无需加人,让您将成本花在刀刃上。


Pigsty 对研发有什么帮助?

Pigsty 整合了 PG 生态最全的扩展(575),提供了 All in PG 解决方案:单一组件替代 Redis, Kafka, MySQL, ES, 向量数据库,OLAP / 大数据分析等专用组件。

极大提高研发效能与敏捷性的同时降低复杂度成本,而且研发能在 Pigsty 的加持下实现自助管理,自主 DevOps,无需 DBA。


Pigsty 对运维有什么帮助?

Pigsty 故障自愈的高可用架构确保硬件故障无需当场处理,让运维与 DBA 睡个好觉;监控助力问题分析与性能优化;IaC 赋能超大规模集群自动化管理。

运维在 Pigsty 加持下能兼职 DBA,而 DBA 则可以跳过系统建设阶段,节省大量工时并专注于高价值工作,或喝茶看报,学习 PG。


Pigsty 的作者是谁?

Pigsty 主体由冯若航一人开发,这是一位专注于 PostgreSQL 领域 10 年的开源贡献者,数据库专家与布道师, 曾任职于阿里,探探,苹果,全栈专家。现为一人公司创始人,提供专业咨询服务。

同时他也是技术 KOL,微信数据库个人公众号榜首 《非法加冯》 的主理人,全网粉丝六万+。


Pigsty 的生态位与影响力如何?

Pigsty 全球 PostgreSQL 生态中最有影响力的中国开源项目,共有约十万用户,一半来自海外。 Pigsty 也是 PostgreSQL 生态最活跃的开源项目之一,目前在扩展分发与监控系统上占据碾压性优势。

PGEXT.Cloud 是由 Pigsty 维护的 PostgreSQL 扩展仓库,拥有全球最多的 PostgreSQL 扩展分发量。 目前已经成为多家国际 PostgreSQL 厂商的软件供应链上游。

Pigsty 目前是 PostgreSQL 生态的主要发行版之一,也是云厂商 RDS 的挑战者,目前已经广泛应用于军工,政企,医疗,互联网,金融,制造业等各个行业。


Pigsty 适合什么规模的客户?

Pigsty 源于超大规模 PostgreSQL 自动化管理的需求,但已针对易用性进行深度优化,缺乏专业 DBA 能力的个人开发者与中小型企业也可以轻松上手使用。

最大规模部署为 25K vCPU,450万 QPS,六年+,最小规模部署可完整运行于 1c1g 虚拟机上作为 Demo / Devbox 使用。


Pigsty 提供哪些能力?

Pigsty 专注于整合 PostgreSQL 生态,提供 PostgreSQL 的最佳实践,但同时也支持一系列与 PostgreSQL 配合良好的开源软件。例如:

  • Etcd, Redis, Silo, DuckDB, Prometheus
  • FerretDB, Babelfish, IvorySQL, PolarDB, OrioleDB
  • OpenHalo, Supabase, Greenplum, Dify, Odoo, …

Pigsty 适用于哪些场景?

  • 运行大规模 PostgreSQL 集群用于业务
  • 自建 RDS,对象存储,缓存,数仓,Supabase, …
  • 自建 Odoo,Dify,Wiki,GitLab 等企业级应用
  • 运行监控基础设施,监控现有数据库与主机
  • 同时组合使用多种 PG 扩展插件
  • 大屏开发与交互式数据应用 Demo,数据可视化,Web 建站

Pigsty 开源免费吗?

Pigsty 是 100% 的开源软件 + 自由软件,在遵循开源许可证的前提下,您可以将其免费地,自由的用于各种商业目的。

我们珍视软件自由,对于非 DBaaS / OEM 用例,我们执行更为宽松的等效 Apache 2.0 许可证。请参阅许可证以获取更多详细信息。


Pigsty 提供商业支持吗?

Pigsty 软件本身开源免费,并提供丰俭由人的商业订阅,为 Pigsty & PostgreSQL 提供质保。 订阅提供更宽广的 OS/PG/芯片架构支持范围,以及专家咨询与支持。 Pigsty 商业订阅交付业界顶尖的管理/技术经验/解决方案, 帮助您节省宝贵的时间,替您扛雷,并为疑难杂症兜底。


Pigsty 支持国产信创吗?

Pigsty 软件本身不属于数据库,不受信创名录限制,且已有多个部队用例。但 Pigsty 开源版不提供任何形式的信创支持。 商业版订阅提供与阿里云合作的国产信创解决方案,支持使用具有信创资质的 PolarDB-O(需单独采购)作为 RDS 内核,能够运行于信创操作系统/芯片环境。


Pigsty 可以换 Logo 贴牌为自己的产品吗?

再分发 Pigsty 时,您必须保留原作品中的版权声明、专利声明、商标声明和归属声明, 并且需要在修改的文件中附上显著的变更说明,同时保留 LICENSE 文件的内容。 在此前提下,您可以更换 PIGSTY 的 Logo 与商标,但不得宣传为 “自己原创的作品”。 我们在企业版本中提供对 OEM 与贴牌的商业授权支持。


Pigsty 的服务主体

Pigsty 是奇绩创坛 S22 被投项目,原主体 磐吉云数(北京)科技有限责任公司 已经清算剥离 Pigsty 业务,与 Pigsty 无关。

Pigsty 目前由作者冯若航个人独资运营维护,商业主体为:

  • 海南诸夏云数据有限公司 / 91460000MAE6L87B94
  • 海口龙华辟技数据中心 / 92460000MAG0XJ569B
  • 海口龙华越航科技中心 / 92460000MACCYGBQ1N

PIGSTY® 与 PGSTY® 为海口龙华越航科技中心的注册商标。

4.12 - 同类对比

本文列出了与 Pigsty 生态位有重叠的产品与项目,并比较其在特性上的差异。

与 RDS 对比

Pigsty 是使用 Apache-2.0 开源的本地优先 RDS 替代,可以部署在您自己的物理机/虚拟机上,也可以部署在云服务器上。

因此,我们选择了全球份额第一的亚马逊云 AWS RDS for PostgreSQL,以及中国市场份额第一的阿里云 RDS for PostgreSQL 作为参照对象。

阿里云 RDS 与 AWS RDS 均为闭源云数据库服务,通过租赁模式,仅在公有云上对外提供。以下云厂商信息是 2024 年 2 月的存档,基于当时的 PostgreSQL 16 主干版本;“功能特性”表中的 Pigsty 列按当前口径维护,后续“重要扩展”版本表整体保留为同期历史快照。


功能特性

指标 Pigsty Aliyun RDS AWS RDS
大版本支持 14 - 18 13 - 18 13 - 18
只读从库 支持任意数量只读从库 备实例不对用户开放 备实例不对用户开放
读写分离 支持端口区分读写流量 独立收费组件 独立收费组件
快慢分离 支持离线 ETL 实例 未见相关特性 未见相关特性
异地灾备 支持备份集群 支持多可用区部署 支持多可用区部署
延迟从库 支持延迟实例 未见相关特性 未见相关特性
负载均衡 HAProxy / LVS 独立收费组件 独立收费组件
连接池 Pgbouncer 独立收费组件:RDS 独立收费组件:RDS Proxy
高可用 Patroni / etcd 需高可用版提供支持 需高可用版提供支持
时间点恢复 pgBackRest / Silo 提供备份支持 提供备份支持
指标监控 VictoriaMetrics / Exporter 免费基础版/收费进阶版 免费基础版/收费进阶版
日志采集 VictoriaLogs / Vector 基础支持 基础支持
可视化系统 Grafana / Echarts 提供基本监控 提供基本监控
告警聚合通知 Alertmanager 基础支持 基础支持

重要扩展

这里保留了一份基于 2024-02-28 可见信息的 PostgreSQL 16 扩展支持历史快照。表内版本与项目(包括后来归档并从目录移除的 pg_analytics)不代表 Pigsty v4.5.0 或云厂商的当前支持矩阵;当前 Pigsty 能力请以 扩展目录 为准,云服务能力请重新核对厂商文档。

扩展名称 Pigsty RDS / PGDG 官方仓库 阿里云 RDS AWS RDS
加装扩展 自由加装 不允许 不允许
地理空间 PostGIS 3.4.2 PostGIS 3.3.4 / Ganos 6.1 PostGIS 3.4.1
雷达点云 PG PointCloud 1.2.5 Ganos PointCloud 6.1
向量嵌入 PGVector 0.6.1 / Svector 0.5.6 pase 0.0.1 PGVector 0.6
机器学习 PostgresML 2.8.1
时序扩展 TimescaleDB 2.14.2
水平分布式 Citus 12.1
列存扩展 Hydra 1.1.1
全文检索 pg_bm25 0.5.6
图数据库 Apache AGE 1.5.0
GraphQL PG GraphQL 1.5.0
OLAP pg_analytics 0.5.6
消息队列 pgq 3.5.0
DuckDB duckdb_fdw 1.1
模糊分词 zhparser 1.1 / pg_bigm 1.2 zhparser 1.0 / pg_jieba pg_bigm 1.2
CDC 抽取 wal2json 2.5.3 wal2json 2.5
膨胀治理 pg_repack 1.5.0 pg_repack 1.4.8 pg_repack 1.5.0
AWS RDS PG 可用扩展

AWS RDS for PostgreSQL 16 可用扩展(已刨除 PG 自带扩展)

name pg16 pg15 pg14 pg13 pg12 pg11 pg10
amcheck 1.3 1.3 1.3 1.2 1.2 yes 1
auto_explain yes yes yes yes yes yes yes
autoinc 1 1 1 1 null null null
bloom 1 1 1 1 1 1 1
bool_plperl 1 1 1 1 null null null
btree_gin 1.3 1.3 1.3 1.3 1.3 1.3 1.2
btree_gist 1.7 1.7 1.6 1.5 1.5 1.5 1.5
citext 1.6 1.6 1.6 1.6 1.6 1.5 1.4
cube 1.5 1.5 1.5 1.4 1.4 1.4 1.2
dblink 1.2 1.2 1.2 1.2 1.2 1.2 1.2
dict_int 1 1 1 1 1 1 1
dict_xsyn 1 1 1 1 1 1 1
earthdistance 1.1 1.1 1.1 1.1 1.1 1.1 1.1
fuzzystrmatch 1.2 1.1 1.1 1.1 1.1 1.1 1.1
hstore 1.8 1.8 1.8 1.7 1.6 1.5 1.4
hstore_plperl 1 1 1 1 1 1 1
insert_username 1 1 1 1 null null null
intagg 1.1 1.1 1.1 1.1 1.1 1.1 1.1
intarray 1.5 1.5 1.5 1.3 1.2 1.2 1.2
isn 1.2 1.2 1.2 1.2 1.2 1.2 1.1
jsonb_plperl 1 1 1 1 1 null null
lo 1.1 1.1 1.1 1.1 1.1 1.1 1.1
ltree 1.2 1.2 1.2 1.2 1.1 1.1 1.1
moddatetime 1 1 1 1 null null null
old_snapshot 1 1 1 null null null null
pageinspect 1.12 1.11 1.9 1.8 1.7 1.7 1.6
pg_buffercache 1.4 1.3 1.3 1.3 1.3 1.3 1.3
pg_freespacemap 1.2 1.2 1.2 1.2 1.2 1.2 1.2
pg_prewarm 1.2 1.2 1.2 1.2 1.2 1.2 1.1
pg_stat_statements 1.1 1.1 1.9 1.8 1.7 1.6 1.6
pg_trgm 1.6 1.6 1.6 1.5 1.4 1.4 1.3
pg_visibility 1.2 1.2 1.2 1.2 1.2 1.2 1.2
pg_walinspect 1.1 1 null null null null null
pgcrypto 1.3 1.3 1.3 1.3 1.3 1.3 1.3
pgrowlocks 1.2 1.2 1.2 1.2 1.2 1.2 1.2
pgstattuple 1.5 1.5 1.5 1.5 1.5 1.5 1.5
plperl 1 1 1 1 1 1 1
plpgsql 1 1 1 1 1 1 1
pltcl 1 1 1 1 1 1 1
postgres_fdw 1.1 1.1 1.1 1 1 1 1
refint 1 1 1 1 null null null
seg 1.4 1.4 1.4 1.3 1.3 1.3 1.1
sslinfo 1.2 1.2 1.2 1.2 1.2 1.2 1.2
tablefunc 1 1 1 1 1 1 1
tcn 1 1 1 1 1 1 1
tsm_system_rows 1 1 1 1 1 1 1.1
tsm_system_time 1 1 1 1 1 1 1.1
unaccent 1.1 1.1 1.1 1.1 1.1 1.1 1.1
uuid-ossp 1.1 1.1 1.1 1.1 1.1 1.1 1.1
Aliyun RDS PG 可用扩展

阿里云 RDS for PostgreSQL 16 可用扩展(已刨除 PG 自带扩展)

name pg16 pg15 pg14 pg13 pg12 pg11 pg10 ali_desc
bloom 1 1 1 1 1 1 1 提供一种基于布鲁姆过滤器的索引访问方法。
btree_gin 1.3 1.3 1.3 1.3 1.3 1.3 1.2 提供一个为多种数据类型和所有 enum 类型实现 B 树等价行为的 GIN 操作符类示例。
btree_gist 1.7 1.7 1.6 1.5 1.5 1.5 1.5 提供一个为多种数据类型和所有 enum 类型实现 B 树等价行为的 GiST 操作符类示例。
citext 1.6 1.6 1.6 1.6 1.6 1.5 1.4 提供一种大小写不敏感的字符串类型。
cube 1.5 1.5 1.5 1.4 1.4 1.4 1.2 提供一种数据类型来表示多维立方体。
dblink 1.2 1.2 1.2 1.2 1.2 1.2 1.2 跨库操作表。
dict_int 1 1 1 1 1 1 1 附加全文搜索词典模板的示例。
earthdistance 1.1 1.1 1.1 1.1 1.1 1.1 1.1 提供两种不同的方法来计算地球表面的大圆距离。
fuzzystrmatch 1.2 1.1 1.1 1.1 1.1 1.1 1.1 判断字符串之间的相似性和距离。
hstore 1.8 1.8 1.8 1.7 1.6 1.5 1.4 在单一 PostgreSQL 值中存储键值对。
intagg 1.1 1.1 1.1 1.1 1.1 1.1 1.1 提供一个整数聚集器和一个枚举器。
intarray 1.5 1.5 1.5 1.3 1.2 1.2 1.2 提供一些有用的函数和操作符来操纵不含空值的整数数组。
isn 1.2 1.2 1.2 1.2 1.2 1.2 1.1 按照一个硬编码的前缀列表对输入进行验证,也被用来在输出时连接号码。
ltree 1.2 1.2 1.2 1.2 1.1 1.1 1.1 用于表示存储在一个层次树状结构中的数据的标签。
pg_buffercache 1.4 1.3 1.3 1.3 1.3 1.3 1.3 提供一种方法实时检查共享缓冲区。
pg_freespacemap 1.2 1.2 1.2 1.2 1.2 1.2 1.2 检查空闲空间映射(FSM)。
pg_prewarm 1.2 1.2 1.2 1.2 1.2 1.2 1.1 提供一种方便的方法把数据载入到操作系统缓冲区或者 PostgreSQL 缓冲区。
pg_stat_statements 1.1 1.1 1.9 1.8 1.7 1.6 1.6 提供一种方法追踪服务器执行的所有 SQL 语句的执行统计信息。
pg_trgm 1.6 1.6 1.6 1.5 1.4 1.4 1.3 提供字母数字文本相似度的函数和操作符,以及支持快速搜索相似字符串的索引操作符类。
pgcrypto 1.3 1.3 1.3 1.3 1.3 1.3 1.3 为 PostgreSQL 提供了密码函数。
pgrowlocks 1.2 1.2 1.2 1.2 1.2 1.2 1.2 提供一个函数来显示一个指定表的行锁定信息。
pgstattuple 1.5 1.5 1.5 1.5 1.5 1.5 1.5 提供多种函数来获得元组层的统计信息。
plperl 1 1 1 1 1 1 1 提供 perl 过程语言。
plpgsql 1 1 1 1 1 1 1 提供 SQL 过程语言。
pltcl 1 1 1 1 1 1 1 提供 tcl 过程语言。
postgres_fdw 1.1 1.1 1.1 1 1 1 1 跨库操作表。
sslinfo 1.2 1.2 1.2 1.2 1.2 1.2 1.2 提供当前客户端提供的 SSL 证书的有关信息。
tablefunc 1 1 1 1 1 1 1 包括多个返回表的函数。
tsm_system_rows 1 1 1 1 1 1 1 提供表采样方法 SYSTEM_ROWS。
tsm_system_time 1 1 1 1 1 1 1 提供了表采样方法 SYSTEM_TIME。
unaccent 1.1 1.1 1.1 1.1 1.1 1.1 1.1 文本搜索字典,它能从词位中移除重音(附加符号)。
uuid-ossp 1.1 1.1 1.1 1.1 1.1 1.1 1.1 提供函数使用几种标准算法之一产生通用唯一标识符(UUID)。
xml2 1.1 1.1 1.1 1.1 1.1 1.1 1.1 提供 XPath 查询和 XSLT 功能。

性能对比

指标 Pigsty Aliyun RDS AWS RDS
最佳性能 PGTPC on NVME SSD 评测 sysbench oltp_rw RDS PG 性能白皮书 sysbench oltp 场景 每核 QPS 4000 ~ 8000
存储规格:最高档容量 32TB / NVME SSD 32 TB / ESSD PL3 64 TB / io2 EBS Block Express
存储规格:最高档 IOPS 4K 随机读:最大3M,随机写 2000~350K 4K 随机读:最大 1M 16K 随机 IOPS: 256K
存储规格:最高档延迟 4K 随机读:75µs,随机写 15µs 4K 随机读:200µs 500µs / 推断为16K 随机 IO
存储规格:最高档可靠性 UBER < 1e-18,折合18个9 MTBF: 200万小时 5DWPD,持续三年 可靠性 9个9, 合 UBER 1e-9 存储与数据可靠性 持久性:99.999%,5个9 (0.001% 年故障率) io2 说明
存储规格:最高档成本 31.5 ¥/TB·月 ( 5年质保均摊 / 3.2T / 企业级 / MLC ) 3200¥/TB·月 (原价 6400¥,包月4000¥) 3年预付整体打5折才有此价格 1900 ¥/TB·月 使用最大规格 65536GB / 256K IOPS 最大优惠

可观测性

Pigsty 提供近 3000 类监控指标与 50+ 监控面板,覆盖数据库、主机、连接池、负载均衡等对象,提供完整的可观测性能力。

Pigsty 监控仪表盘

Pigsty 提供了 638 与 PostgreSQL 有关的监控指标,而 AWS RDS 只有 99 个,阿里云 RDS 更是只有个位数指标:

阿里云 RDS PostgreSQL 监控指标

此外,也有一些项目提供了监控 PostgreSQL 的能力,但都相对比较简单初级:


可维护性

指标 Pigsty Aliyun RDS AWS RDS
系统易用性 简单 简单 简单
配置管理 配置文件 / CMDB 基于 Ansible Inventory 可使用 Terraform 可使用 Terraform
变更方式 幂等剧本 基于 Ansible Playbook 控制台点击操作 控制台点击操作
参数调优 自动根据节点适配 四种预置模板 OLTP, OLAP, TINY, CRIT
Infra as Code 原生支持 可使用 Terraform 可使用 Terraform
可定制参数点 Pigsty Parameters 283 个
服务与支持 提供商业订阅支持兜底 提供售后工单支持 提供售后工单支持
无互联网部署 可离线安装部署 N/A N/A
数据库迁移 提供从现有 v10+ PG 实例基于逻辑复制不停机迁移至 Pigsty 托管实例的剧本 提供上云辅助迁移 Aliyun RDS 数据同步

成本

经验上看,软硬件资源的部分 RDS 单位成本是自建的 5 ~ 15 倍,租售比通常在一个月。详情请参考 成本分析

要素 指标 Pigsty Aliyun RDS AWS RDS
成本 软件授权/服务费用 免费,硬件约 20 - 40 ¥/核·月 200 ~ 400 ¥/核·月 400 ~ 1300 ¥/核·月
服务支持费用 服务约 100 ¥/ 核·月 包含在 RDS 成本中

其他本地数据库管控软件

一些提供管理 PostgreSQL 能力的软件与供应商


其他 Kubernetes Operator

Pigsty 拒绝在生产环境中使用 Kubernetes 管理数据库,因此与这些方案在生态位上存在差异。

  • PGO
  • StackGres
  • CloudNativePG
  • TemboOperator
  • PostgresOperator
  • PerconaOperator
  • Kubegres
  • KubeDB
  • KubeBlocks

更多信息请参阅:

4.12.1 - 成本对比

本文提供了一组成本数据,供您评估 Pigsty 自建,使用云数据库 RDS 所需的成本,以及常规的 DBA 薪酬参考。

总体概览

以下成本数据用于说明量级差异,云厂商价格与折扣会随时间、区域、实例规格和采购方式变化。

EC2 核·月 RDS 核·月
DHH 自建核月价格(192C 384G) 25.32 初级开源数据库 DBA 参考工资 15K/人·月
IDC 自建机房(独占物理机: 64C384G) 19.53 中级开源数据库 DBA 参考工资 30K/人·月
IDC 自建机房(容器,超卖500%) 7 高级开源数据库 DBA 参考工资 60K/人·月
UCloud 弹性虚拟机(8C16G,有超卖) 25 ORACLE 数据库授权 10000
阿里云 弹性服务器 2x 内存(独占无超卖) 107 阿里云 RDS PG 2x 内存(独占) 260
阿里云 弹性服务器 4x 内存(独占无超卖) 138 阿里云 RDS PG 4x 内存(独占) 320
阿里云 弹性服务器 8x 内存(独占无超卖) 180 阿里云 RDS PG 8x 内存(独占) 410
AWS C5D.METAL 96C 200G (按月无预付) 100 AWS RDS PostgreSQL db.T2 (2x) 440
AWS C5D.METAL 96C 200G (预付三年) 80 AWS RDS PostgreSQL db.M5 (4x) 611
AWS C7A.METAL 192C 384G (预付三年) 104.8 AWS RDS PostgreSQL db.R6G (8x) 786

RDS成本参考

付费模式 价格 折合每年(万¥)
IDC 自建(单物理机) ¥7.5w / 5年 1.5
IDC 自建(2~3台组 HA) ¥15w / 5年 3.0 ~ 4.5
阿里云 RDS 按需 ¥87.36/时 76.5
阿里云 RDS 月付(基准) ¥4.2w / 月 50
阿里云 RDS 年付(85折) ¥425095 / 年 42.5
阿里云 RDS 3年付(5折) ¥750168 / 3年 25
AWS 按需 $25,817 / 月 217
AWS 1年不预付 $22,827 / 月 191.7
AWS 3年全预付 12w$ + 17.5k$/月 175
AWS 中国/宁夏按需 ¥197,489 / 月 237
AWS 中国/宁夏1年不预付 ¥143,176 / 月 171
AWS 中国/宁夏3年全预付 ¥647k + 116k/月 160.6

我们可以对比一下自建与云数据库的成本差异:

方式 折合每年(万元)
IDC 托管服务器 64C / 384G / 3.2TB NVME SSD 660K IOPS (2~3台) 3.0 ~ 4.5
阿里云 RDS PG 高可用版 pg.x4m.8xlarge.2c, 64C / 256GB / 3.2TB ESSD PL3 25 ~ 50
AWS RDS PG 高可用版 db.m5.16xlarge, 64C / 256GB / 3.2TB io1 x 80k IOPS 160 ~ 217

ECS 成本参考

排除 NVMe SSD / ESSD PL3 后的纯算力价格对比

以阿里云为例,纯算力包月模式的价格是自建基准的 5 ~ 7 倍,预付五年的价格是自建的 2 倍

付费模式 单价(¥/核·月) 相对于标准价格 自建溢价倍率
按量付费(1.5倍) ¥ 202 160 % 9.2 ~ 11.2
包月(标准价格) ¥ 126 100 % 5.7 ~ 7.0
预付一年(65折) ¥ 83.7 66 % 3.8 ~ 4.7
预付二年(55折) ¥ 70.6 56 % 3.2 ~ 3.9
预付三年(44折) ¥ 55.1 44 % 2.5 ~ 3.1
预付四年(35折) ¥ 45 35 % 2.0 ~ 2.5
预付五年(30折) ¥ 38.5 30 % 1.8 ~ 2.1
DHH @ 2023 ¥ 22.0
探探 IDC 自建 ¥ 18.0

含 NVMe SSD / ESSD PL3 情况下的等效价格对比

包含常用规格后的 NVMe SSD 规格之后,纯算力包月模式的价格是自建基准的 11 ~ 14 倍,预付五年的价格是自建的 9 倍左右。

付费模式 单价(¥/核·月) + 40GB ESSD PL3 自建溢价比例
按量付费(1.5倍) ¥ 202 ¥ 362 14.3 ~ 18.6
包月(标准价格) ¥ 126 ¥ 286 11.3 ~ 14.7
预付一年(65折) ¥ 83.7 ¥ 244 9.6 ~ 12.5
预付二年(55折) ¥ 70.6 ¥ 230 9.1 ~ 11.8
预付三年(44折) ¥ 55.1 ¥ 215 8.5 ~ 11.0
预付四年(35折) ¥ 45 ¥ 205 8.1 ~ 10.5
预付五年(30折) ¥ 38.5 ¥ 199 7.9 ~ 10.2
DHH @ 2023 ¥ 25.3
探探 IDC 自建 ¥ 19.5

DHH 案例:192核配12.8TB Gen4 SSD (1c:66);探探案例: 64核配3.2T Gen3 MLC SSD (1c:50)。

云上价格每核配比40GB ESSD PL3(1核:4x 内存:40x 磁盘)计算。


EBS成本参考

评估因素 本地 PCI-E NVME SSD Aliyun ESSD PL3 AWS io2 Block Express
容量 32TB 32 TB 64 TB
IOPS 4K 随机读:600K ~ 1.1M 4K 随机写 200K ~ 350K 4K 随机读:最大 1M 16K 随机 IOPS: 256K
延迟 4K 随机读:75µs 4K 随机写:15µs 4K 随机读: 200µs 随机 IO:500µs 上下文推断为16K
可靠性 UBER < 1e-18,折合18个9 MTBF: 200万小时 5DWPD,持续三年 数据可靠性 9个9 存储与数据可靠性 持久性:99.999%,5个9 (0.001% 年故障率) io2 说明
成本 16 ¥/TB· ( 5年均摊 / 3.2T MLC ) 5 年质保,¥3000 零售 3200¥/TB· (原价 6400¥,包月4000¥) 3年预付整体打5折才有此价格 1900 ¥/TB· 使用最大规格 65536GB 256K IOPS 最优惠状态
SLA 5年质保 出问题直接换新 Aliyun RDS SLA 可用性 99.99%: 月费 15% 99%: 月费 30% 95%: 月费 100% Amazon RDS SLA 可用性 99.95%: 月费 15% 99%: 月费 25% 95%: 月费 100%

S3成本参考

Date $/GB·月 ¥/TB·5年 HDD ¥/TB SSD ¥/TB
2006.03 0.150 63000 2800
2010.11 0.140 58800 1680
2012.12 0.095 39900 420 15400
2014.04 0.030 12600 371 9051
2016.12 0.023 9660 245 3766
2023.12 0.023 9660 105 280
其他参考价 高性能存储 顶配底折价 与采购 NVMe SSD 价格参考
S3 Express 0.160 67200 DHH 12T 1400
EBS io2 0.125 + IOPS 114000 Shannon 3.2T 900

下云合集

曾几何时,“上云”近乎成为技术圈的政治正确,整整一代应用开发者的视野被云遮蔽。就让我们用实打实的数据分析与亲身经历,讲清楚公有云租赁模式的价值与陷阱 —— 在这个降本增效的时代中,供您借鉴与参考 —— 请看 《云计算泥石流:合订本

云基础资源篇


云商业模式篇


下云奥德赛篇


云故障复盘篇


RDS 翻车篇


云厂商画像篇

4.12.2 - 开源影响力

PG 生态开源项目的影响力比较,以 GitHub Star 数为主要指标。

中国 PostgreSQL 生态项目影响力

GitHub Star 数降序排列,最后更新时间为北京时间 2026-08-13。

项目 Star 作者 类型 简介
pgsty/pigsty 5521 冯若航 @ PGSTY 发行版 开箱即用的 PostgreSQL 发行版
polardb/PolarDB-for-PostgreSQL 3191 阿里云 内核 阿里云开源 PolarDB for PostgreSQL 内核
tensorchord/pgvecto.rs 2181 TensorChord 扩展 Rust 编写的向量检索扩展
tensorchord/VectorChord 1770 TensorChord 扩展 下一代向量检索扩展
Tencent/TBase 1439 腾讯云 内核 腾讯分布式 HTAP 数据库内核
apache/cloudberry 1315 HashData 内核 开源 MPP 数据仓库内核
IvorySQL/IvorySQL 1051 济南瀚高 内核 Oracle 兼容 PostgreSQL 分支
pgplex/pgschema 995 陈天舟 工具 声明式 Postgres Schema 迁移 CLI
amutu/zhparser 869 Jov 扩展 基于 SCWS 的中文全文分词扩展
opengauss-mirror/openGauss-server 784 华为 内核 早期 PG 9.2 内核分叉
HaloTech-Co-Ltd/openHalo 437 易景羲和 内核 MySQL 协议兼容的 PostgreSQL 内核
jaiminpan/pg_jieba 417 Pan Jiamin 扩展 基于结巴分词的中文全文检索扩展
alitrack/duckdb_fdw 409 李红艳 扩展 DuckDB 外部数据源包装器
tensorchord/VectorChord-bm25 375 TensorChord 扩展 PostgreSQL 原生 BM25 排序索引
pgsty/pg_exporter 359 冯若航 @ PGSTY 工具 PostgreSQL 与 Pgbouncer 指标采集器
ChenHuajun/pg_roaringbitmap 286 陈华军 @ 苏宁 扩展 PostgreSQL RoaringBitmap 位图扩展
pgsty/pig 199 冯若航 @ PGSTY 工具 PostgreSQL 扩展包管理器
tensorchord/pg_bestmatch.rs 101 TensorChord 扩展 在 PostgreSQL 内生成 BM25 稀疏向量
wublabdubdub/PDU-PostgreSQLDataUnloader 101 张晨 工具 PostgreSQL 数据库救援与数据卸载工具
tensorchord/pg_tokenizer.rs 45 TensorChord 扩展 全文检索 tokenizer 扩展
jaiminpan/pg_scws 41 Pan Jiamin 扩展 基于 SCWS 的中文分词扩展
pgsty/pgext 31 冯若航 @ PGSTY 工具 PG 扩展目录与元数据工具
tooltip:
  trigger: axis
  axisPointer: { type: shadow }
  formatter: $fn:tipfmt
grid: { left: 320, right: 72, top: 20, bottom: 26 }
xAxis:
  type: value
  max: 5600
  name: GitHub Star
  nameLocation: middle
  nameGap: 24
  axisLabel: { formatter: $fn:fnum }
  splitLine: { show: true, lineStyle: { type: dashed, opacity: 0.45 } }
yAxis:
  type: category
  inverse: true
  axisLabel:
    align: right
    margin: 8
    width: 300
    overflow: truncate
    fontSize: 11
    fontFamily: monospace
  data:
    - 'pgsty/pigsty'
    - 'polardb/PolarDB-for-PostgreSQL'
    - 'tensorchord/pgvecto.rs'
    - 'tensorchord/VectorChord'
    - 'Tencent/TBase'
    - 'apache/cloudberry'
    - 'IvorySQL/IvorySQL'
    - 'pgplex/pgschema'
    - 'amutu/zhparser'
    - 'opengauss-mirror/openGauss-server'
    - 'HaloTech-Co-Ltd/openHalo'
    - 'jaiminpan/pg_jieba'
    - 'alitrack/duckdb_fdw'
    - 'tensorchord/VectorChord-bm25'
    - 'pgsty/pg_exporter'
    - 'ChenHuajun/pg_roaringbitmap'
    - 'pgsty/pig'
    - 'tensorchord/pg_bestmatch.rs'
    - 'wublabdubdub/PDU-PostgreSQLDataUnloader'
    - 'tensorchord/pg_tokenizer.rs'
    - 'jaiminpan/pg_scws'
    - 'pgsty/pgext'
series:
  - name: Star
    type: bar
    barWidth: 20
    showBackground: true
    backgroundStyle: { color: "rgba(148, 163, 184, 0.16)" }
    itemStyle:
      color: $fn:barclr
      borderRadius: [0, 5, 5, 0]
    label:
      show: true
      position: right
      formatter: $fn:labfmt
      color: '#334155'
      fontWeight: 600
    data: [5521, 3191, 2181, 1770, 1439, 1315, 1051, 995, 869, 784, 437, 417, 409, 375, 359, 286, 199, 101, 101, 45, 41, 31]

PostgreSQL 发行版影响力指标

按 GitHub Star 数降序排列(商业产品无公开 Star 的统一置后),最后更新时间为北京时间 2026-08-13。

项目 Star 供应商 类型 许可证 简介
CloudNativePG 9133 EDB K8S 云原生 Apache-2.0 不依赖 Patroni 的主流 PG Operator。
Pigsty 5521 PGSTY Linux 原生 Apache-2.0 Ansible 驱动的一体化 PG 发行版。
Zalando Postgres Operator 5222 Zalando K8S 云原生 MIT 老牌 Patroni/Spilo 架构 PG Operator。
PGO 4436 Crunchy Data K8S 云原生 Apache-2.0 生产级 Operator,集成备份与监控。
Autobase 4332 vitabaks Linux 原生 MIT 支持 Patroni/etcd/Consul 自动化部署。
KubeBlocks 3102 ApeCloud K8S 云原生 AGPL-3.0 多数据库统一 Operator 平台。
StackGres 1426 OnGres K8S 云原生 AGPL-3.0 CRD/CLI/Web UI 一体化 PG Operator。
Kubegres 1350 Reactive Tech K8S 云原生 Apache-2.0 极简 Operator,基于原生流复制。
Tembo Operator 1263 Tembo K8S 云原生 未声明 场景化 Stacks 交付的 PG Operator。
pgEdge 744 pgEdge Linux 原生 PostgreSQL 分布式 PG 发行版,主打 Spock 多主复制。
KubeDB 733 AppsCode K8S 云原生 ACL-1.0 多数据库 Operator,配套 kubectl 插件。
Percona Operator for PostgreSQL 381 Percona K8S 云原生 Apache-2.0 Percona 生态内的 PG Operator。
EDB TPA 86 EDB Linux 原生 GPL-3.0 EDB 官方 Ansible 编排交付工具。
Percona Distribution for PostgreSQL - Percona Linux 原生 多种 整合 PG 与常用组件的发行版方案。
ClusterControl - ServerNines Linux 原生 商业 多数据库部署、监控、备份与切换平台。
CYBERTEC PGEE - CYBERTEC Linux 原生 商业 企业增强 PG 发行版,侧重安全与性能。
Crunchy Postgres for Ansible - Crunchy Data Linux 原生 商业 Crunchy 的裸机/VM PG 自动化方案。
EDB Postgres Advanced Server (EPAS) - EDB Linux 原生 商业 EDB 旗舰发行版,含 Oracle 兼容特性。

Star History Chart

其他资源

5 - 参考

详细的参考信息与列表:支持的操作系统,模块,参数,监控指标,数据库扩展,同类对比,术语表等。

5.1 - Linux 兼容性

Pigsty 兼容的 Linux 操作系统发行版大版本,以及芯片架构指令集

Pigsty 运行于 Linux 操作系统上,支持 amd64/x86_64arm64/aarch64 架构,支持 ELDebianUbuntu 三大主流 Linux 发行版。

Pigsty 不使用任何虚拟化容器化技术,直接运行于裸操作系统上。我们为三大主流 Linux 发行版生命周期内的主流大版本与两种架构提供支持。

概述

Pigsty 推荐使用的操作系统版本:Rocky Linux 9.8 / 10.2、Debian 12.15 / 13.6、Ubuntu 22.04.5 / 24.04.4 / 26.04.0。

发行版 架构 系统代码 PG18 PG17 PG16 PG15 PG14
RHEL / Rocky / Alma 10 x86_64 el10.x86_64
RHEL / Rocky / Alma 10 aarch64 el10.aarch64
RHEL / Rocky / Alma 9 x86_64 el9.x86_64
RHEL / Rocky / Alma 9 aarch64 el9.aarch64
Ubuntu 26.04 (resolute) x86_64 u26.x86_64
Ubuntu 26.04 (resolute) aarch64 u26.aarch64
Ubuntu 24.04 (noble) x86_64 u24.x86_64
Ubuntu 24.04 (noble) aarch64 u24.aarch64
Ubuntu 22.04 (jammy) x86_64 u22.x86_64
Ubuntu 22.04 (jammy) aarch64 u22.aarch64
Debian 13 (trixie) x86_64 d13.x86_64
Debian 13 (trixie) aarch64 d13.aarch64
Debian 12 (bookworm) x86_64 d12.x86_64
Debian 12 (bookworm) aarch64 d12.aarch64

以上七个小版本是当前验证基线。扩展仓库仍保留 EL8 双架构兼容性,因此完整软件包矩阵共有 16 个 Linux 平台;EL8 已进入退役过渡期,不再属于推荐部署基线。


EL

Pigsty 支持 RHEL / Rocky / Alma / Anolis / CentOS 8、9、10 版本。

EL 发行版 架构 系统代码 PG18 PG17 PG16 PG15 PG14
RHEL10 / Rocky10 / Alma10 x86_64 el10.x86_64
RHEL10 / Rocky10 / Alma10 aarch64 el10.aarch64
RHEL9 / Rocky9 / Alma9 x86_64 el9.x86_64
RHEL9 / Rocky9 / Alma9 aarch64 el9.aarch64
RHEL8 / Rocky8 / Alma8 x86_64 el8.x86_64
RHEL8 / Rocky8 / Alma8 aarch64 el8.aarch64
RHEL7 / CentOS7 x86_64 el7.x86_64
RHEL7 / CentOS7 aarch64 -
推荐使用 Rocky Linux 9.8 / 10.2

请注意,PGDG Yum 仓库 从 EL9 / EL10 开始,针对 EL 小版本 进行构建,目前建议使用的小版本为:9.8 / 10.2。 建议离线安装包/自建离线仓库与系统 EL 小版本(例如 Rocky Linux 9.8 / 10.2)保持一致,跨小版本可能因 OpenSSL 等依赖版本跳变导致不可用。

EL8 即将不再支持

EL8 将于 2029 年进入 EOL,建议尽早规划升级。鉴于 EL10 适配已经完成,我们将在下个版本移除对 EL8 的支持。

EL 7 @ 2024-06

Red Hat Enterprise Linux 7 已经于 2024年6月停止维护,PGDG 也不再为 PostgreSQL 16/17/18 提供 EL7 二进制包支持。

如需在老旧操作系统上获得运行支持,请考虑我们的 专业订阅服务


Ubuntu

Pigsty 支持 Ubuntu 26.04 / 24.04 / 22.04:

Ubuntu 发行版 架构 系统代码 PG18 PG17 PG16 PG15 PG14
Ubuntu 26.04 (resolute) x86_64 u26.x86_64
Ubuntu 26.04 (resolute) aarch64 u26.aarch64
Ubuntu 24.04 (noble) x86_64 u24.x86_64
Ubuntu 24.04 (noble) aarch64 u24.aarch64
Ubuntu 22.04 (jammy) x86_64 u22.x86_64
Ubuntu 22.04 (jammy) aarch64 u22.aarch64
推荐使用 Ubuntu 22.04.5 / 24.04.4 / 26.04.0 LTS

Ubuntu 26.04 是最新 LTS 基线;如果您希望采用更保守的 Ubuntu 生产环境基线,也可以继续使用 Ubuntu 24.04。


Debian

Pigsty 支持 Debian 12 / 13,推荐使用最新的 Debian 13.6。

Debian 发行版 架构 系统代码 PG18 PG17 PG16 PG15 PG14
Debian 13 (trixie) x86_64 d13.x86_64
Debian 13 (trixie) aarch64 d13.aarch64
Debian 12 (bookworm) x86_64 d12.x86_64
Debian 12 (bookworm) aarch64 d12.aarch64
Debian 11 (bullseye) x86_64 d11.x86_64(历史)
Debian 11 (bullseye) aarch64 -
推荐使用 Debian 12.15 / 13.6
Debian 11 EOL @ 2024-07

Debian 11 已经于 2024-07 进入 EOL。如需在老旧操作系统上获得扩展支持,请考虑我们的 专业订阅服务


Vagrant

当您使用本地虚拟机部署 Pigsty 时,可以考虑使用以下 Vagrant 操作系统镜像,这也是 Pigsty 开发测试使用的镜像。

系统 镜像
Rocky 8.10 cloud-image/rocky-8
Rocky 9.8 cloud-image/rocky-9
Rocky 10.2 cloud-image/rocky-10
Debian 12.15 cloud-image/debian-12
Debian 13.6 cloud-image/debian-13
Ubuntu 22.04.5 cloud-image/ubuntu-22.04
Ubuntu 24.04.4 cloud-image/ubuntu-24.04
Ubuntu 26.04.0 cloud-image/ubuntu-26.04

Terraform

当您使用云服务器部署 Pigsty 时,可以考虑在 Terraform 中使用以下操作系统基础镜像,以 阿里云 为例:

x86_64 阿里云镜像前缀
Rocky 8.10 rockylinux_8_10_x64
Rocky 9.8 rockylinux_9_8_x64
Rocky 10.2 rockylinux_10_2_x64
Ubuntu 22.04.5 ubuntu_22_04_x64_20G
Ubuntu 24.04.4 ubuntu_24_04_x64_20G
Ubuntu 26.04.0 ubuntu_26_04_x64_20G
Debian 12.15 debian_12_15_x64
Debian 13.6 debian_13_6_x64
aarch64 阿里云镜像前缀
Rocky 8.10 rockylinux_8_10_arm64
Rocky 9.8 rockylinux_9_8_arm64
Rocky 10.2 rockylinux_10_2_arm64
Ubuntu 22.04.5 ubuntu_22_04_arm64_20G
Ubuntu 24.04.4 ubuntu_24_04_arm64_20G
Ubuntu 26.04.0 ubuntu_26_04_arm64_20G
Debian 12.15 debian_12_15_arm64
Debian 13.6 debian_13_6_arm64

5.2 - 模块列表

本文列出了 Pigsty 中可用的功能模块,以及后续的功能模块规划。

正式模块

模块 类别 状态 文档入口 简介
PGSQL 核心 GA /docs/pgsql 高可用 PostgreSQL 集群,内置备份、监控、SOP 与扩展生态。
INFRA 核心 GA /docs/infra 本地软件仓库 + VictoriaMetrics/Logs/Traces + Grafana 等基础设施。
NODE 核心 GA /docs/node 节点初始化与收敛:系统调优、管理员、HAProxy、Vector、Keepalived 等。
ETCD 核心 GA /docs/etcd PostgreSQL 高可用 DCS(服务发现、配置、选主元数据)。
MINIO 扩展 GA /docs/minio 部署 Silo S3 兼容对象存储,可作为 PostgreSQL 备份仓库。
REDIS 扩展 GA /docs/redis Redis(默认)或 Valkey 的独立/哨兵/集群模式部署与监控。
DOCKER 扩展 GA /docs/docker Docker Daemon 及容器化应用运行基础能力。
JUICE 扩展 BETA /docs/juice JuiceFS 分布式文件系统,使用 PostgreSQL 作为元数据引擎。
VIBE 扩展 BETA /docs/vibe 浏览器化开发环境,集成 Code-Server、JupyterLab、Node.js、Claude Code 与 Codex CLI。
KAFKA 扩展 BETA /docs/kafka Apache Kafka 4.x dynamic KRaft 集群部署、安全基线与监控。

核心模块

Pigsty 提供了四个 基础 功能模块,对于提供完整高可用的 PostgreSQL 服务非常重要:

  • PGSQL:带有高可用,时间点恢复,IaC,SOP,监控系统,以及 575 个扩展插件的自治的 PostgreSQL 集群。
  • INFRA:本地软件仓库、VictoriaMetrics、VictoriaLogs、VictoriaTraces、Grafana、Alertmanager、Blackbox Exporter…
  • NODE:调整节点到所需状态、名称、时区、NTP、SSH、sudo、HAProxy、Vector、Keepalived
  • ETCD:分布式键值存储,用作高可用 Postgres 集群的 DCS:共识选主/配置管理/服务发现。

尽管这四个模块通常会同时安装,但单独使用也是可行的 —— 只有 NODE 模块通常是必选的。


扩展模块

Pigsty 提供了六个 扩展 功能模块,它们对于核心功能来说并非必须,但可以用于增强 PostgreSQL 的能力:

  • MINIO:S3 兼容对象存储模块,通过统一清单部署 Silo,可作为 PostgreSQL 备份仓库并提供对应监控。
  • REDIS:Redis 服务器,高性能数据结构服务器,支持独立主从、哨兵、集群模式生产部署,并带有完善的监控支持。
  • DOCKER:Docker Daemon 服务,允许用户一键拉起容器化的无状态软件工具模板,为 Pigsty 加装各种功能!
  • JUICE:JuiceFS 分布式文件系统模块,以 PostgreSQL 作为元数据引擎,提供可共享的 POSIX 存储能力。
  • VIBE:浏览器化开发环境模块,集成 Code-Server、JupyterLab、Node.js、Claude Code 与 Codex CLI。
  • KAFKA:Apache Kafka 4.x dynamic KRaft 集群,提供 TLS/SCRAM/ACL 安全基线、声明式 Topic/User 与完整监控。

生态模块

以下模块与 PostgreSQL 生态紧密相关,属于可选生态能力,不计入上述 10 个正式模块:

5.3 - 文件结构

Pigsty 的文件系统结构是如何设计与组织的,以及各个模块使用的目录结构。

Pigsty FHS

Pigsty 的主目录默认放置于 ~/pigsty,该目录下的文件结构如下所示:

~/pigsty 源码树

  • app/
    • 应用模板资源
  • bin/
    • 管理与运维脚本
  • files/
    • victoria/
      • 规则与运维脚本
    • grafana/
      • Grafana 仪表盘
    • postgres/
      • PostgreSQL 管理脚本
    • migration/
      • 数据迁移任务定义
    • pki/
      • 自签名 CA 与证书
  • roles/
    • Ansible 角色实现
  • templates/
    • Ansible 模板文件
  • vagrant/
    • Vagrant 沙箱定义
  • terraform/
    • Terraform 云资源模板
  • configure
  • ansible.cfg
  • pigsty.yml
  • *.yml

/infra/data/infra 的运行时软链接,集中存放可观测性数据与生成的配置:

/data/infra
metrics/           # VictoriaMetrics TSDB 数据
logs/              # VictoriaLogs 数据
traces/            # VictoriaTraces 数据
alertmgr/           # AlertManager 数据
rules/              # 规则定义(含 agent.yml)
targets/            # FileSD 监控目标
dashboards/         # Grafana 仪表盘定义
datasources/        # Grafana 数据源定义
prometheus.yml      # Victoria 的 Prometheus 兼容配置

CA FHS

Pigsty 的 自签名 CA 位于 Pigsty 主目录下的 files/pki/

你必须妥善保管 CA 的密钥文件files/pki/ca/ca.key,该密钥是在 deploy.ymlinfra.ymlca 角色负责生成的。

# pigsty/files/pki                           # (local_user) 0755
#  ^-----@ca                                 # (local_user) 0700
#         ^[email protected]                      # 0600,非常重要:保守其秘密
#         ^[email protected]                      # 0644,非常重要:在所有地方都受信任
#  ^-----@csr                                # (local_user) 0755,签名请求 csr
#  ^-----@misc                               # (local_user) 0755,杂项证书,已签发证书
#  ^-----@etcd                               # (local_user) 0755,etcd 服务器证书
#  ^-----@minio                              # (local_user) 0755,minio 服务器证书
#  ^-----@nginx                              # (local_user) 0755,nginx SSL 证书
#  ^-----@infra                              # (local_user) 0755,infra 客户端证书
#  ^-----@pgsql                              # (local_user) 0755,pgsql 服务器证书
#  ^-----@kafka                              # (local_user) 0755,kafka 服务器证书
#  ^-----@mysql                              # (local_user) 0755,mysql 服务器证书

被 Pigsty 所管理的节点将安装以下证书文件:

/etc/pki/ca.crt                             # root:root 0644,所有节点都添加的根证书
/etc/pki/ca-trust/source/anchors/ca.crt     # EL 系统受信任锚点
/usr/local/share/ca-certificates/ca.crt     # Debian/Ubuntu 系统受信任锚点

所有 infra 节点都会有以下证书:

/etc/pki/infra.crt                          # root:infra 0644,infra 节点证书
/etc/pki/infra.key                          # root:infra 0640,infra 节点密钥

当您的管理节点出现故障时,files/pki 目录与 pigsty.yml 文件应当在备份的管理节点上可用。你可以用 rsync 做到这一点。

# run on meta-1, rsync to meta2
cd ~/pigsty;
rsync -avz ./ meta-2:~/pigsty  

INFRA FHS

infra 角色会创建 infra_data(默认 /data/infra)并建立 /infra -> /data/infra 软链接。/data/infra 的权限为 root:infra 0771,子目录默认权限为 *:infra 0750,覆盖项如下:

# /infra -> /data/infra
# /data/infra                              # root:infra 0771
#  ^-----@pgadmin                          # 5050:5050 0700
#  ^-----@alertmgr                         # prometheus:infra 0700
#  ^-----@conf                             # root:infra 0750
#            ^-----patronictl.yml          # root:admin 0640
#  ^-----@tmp                              # root:infra 0750
#  ^-----@hosts                            # dnsmasq:dnsmasq 0755(DNS 记录)
#            ^-----default                 # root:root 0644
#  ^-----@datasources                      # root:infra 0750
#            ^-----*.json                  # 0600(register 生成)
#  ^-----@dashboards                       # grafana:infra 0750
#  ^-----@metrics                          # victoria:infra 0750
#  ^-----@logs                             # victoria:infra 0750
#  ^-----@traces                           # victoria:infra 0750
#  ^-----@bin                              # victoria:infra 0750
#            ^-----check|new|reload|status # root:infra 0755
#  ^-----@rules                            # victoria:infra 0750
#            ^-----agent.yml               # victoria:infra 0644
#            ^-----infra.yml               # victoria:infra 0644
#            ^-----node.yml                # victoria:infra 0644
#            ^-----pgsql.yml               # victoria:infra 0644
#            ^-----redis.yml               # victoria:infra 0644
#            ^-----etcd.yml                # victoria:infra 0644
#            ^-----minio.yml               # victoria:infra 0644
#            ^-----kafka.yml               # victoria:infra 0644
#            ^-----mysql.yml               # victoria:infra 0644
#  ^-----@targets                          # victoria:infra 0750
#            ^-----@infra                  # infra 组件目标(文件 0640)
#            ^-----@node                   # 节点目标(文件 0640)
#            ^-----@ping                   # ping 目标(文件 0640)
#            ^-----@etcd                   # etcd 目标(文件 0640)
#            ^-----@pgsql                  # pgsql 目标(文件 0640)
#            ^-----@pgrds                  # pgrds 目标(文件 0640)
#            ^-----@redis                  # redis 目标(文件 0640)
#            ^-----@minio                  # minio 目标(文件 0640)
#            ^-----@juice                  # juicefs 目标(文件 0640)
#            ^-----@mysql                  # mysql 目标(文件 0640)
#            ^-----@kafka                  # kafka 目标(文件 0640)
#            ^-----@docker                 # docker 目标(文件 0640)
#            ^-----@patroni                # patroni SSL 目标(文件 0640)
#  ^-----prometheus.yml                    # victoria:infra 0644

上述结构由以下实现生成:roles/infra/tasks/dir.ymlroles/infra/tasks/victoria.ymlroles/infra/tasks/register.ymlroles/infra/tasks/dns.ymlroles/infra/tasks/env.yml


NODE FHS

节点的数据目录由参数 node_data 指定,默认为 /data,由 root:root 持有,权限为 0755

多数核心组件的默认数据目录位于这个目录下;个别试点模块使用自身固定目录,如原生 MySQL 8.4 当前使用 /var/lib/mysql

/data                                 # root:root 0755
#  ^-----@postgres                    # postgres:postgres 0700(默认 pg_fs_main)
#  ^-----@backups                     # postgres:postgres 0700(默认 pg_fs_backup)
#  ^-----@redis                       # redis:redis 0700(多实例共用)
#  ^-----@minio                       # minio:minio 0750(单机单盘模式)
#  ^-----@etcd                        # etcd:etcd 0700(etcd_data)
#  ^-----@infra                       # root:infra 0771(infra 模块数据目录)
#  ^-----@docker                      # root:root 0755(Docker 数据目录)
#  ^-----@kafka                       # kafka:kafka 0700(kafka_data)
#  ^-----@...                         # 其他组件的数据目录

HAProxy

Pigsty 使用自带的 systemd 单元启动 HAProxy,并将主配置与服务片段分开管理:

/etc/systemd/system/haproxy.service   # Pigsty 渲染的 systemd 单元
/etc/haproxy/haproxy.cfg              # HAProxy 主配置
/etc/haproxy/conf.d/*.cfg             # 节点与 PostgreSQL 服务片段
/etc/default/haproxy                  # 可选的用户环境文件,Pigsty 不主动创建

如需在 /etc/default/haproxy 中追加启动参数,请使用 EXTRAOPTS,并保留默认的 -S /run/haproxy-master.sock;配置文件已经由 systemd 单元通过 -f 显式加载,不要再把 -f 写入 EXTRAOPTS


Victoria FHS

监控配置已经从旧的 /etc/prometheus 目录布局迁移为 /infra 运行时布局。主配置模板位于 roles/infra/templates/victoria/prometheus.yml,渲染结果为 /infra/prometheus.yml

files/victoria/bin/*files/victoria/rules/* 会被同步到 /infra/bin//infra/rules/,各模块再向 /infra/targets/* 注册 FileSD 目标。

# /infra
#  ^-----prometheus.yml              # Victoria 主配置(Prometheus 兼容格式)0644
#  ^-----@bin                        # 工具脚本(check/new/reload/status)0755
#  ^-----@rules                      # 记录与告警规则(*.yml 0644)
#            ^-----agent.yml         # Agent 预聚合规则
#            ^-----infra.yml         # infra 规则和告警
#            ^-----etcd.yml          # etcd 规则和告警
#            ^-----node.yml          # node 规则和告警
#            ^-----pgsql.yml         # pgsql 规则和告警
#            ^-----redis.yml         # redis 规则和告警
#            ^-----minio.yml         # minio 规则和告警
#            ^-----kafka.yml         # kafka 规则和告警
#            ^-----mysql.yml         # mysql 规则和告警
#  ^-----@targets                    # FileSD 服务发现目标(*.yml 0640)
#            ^-----@infra            # infra 静态目标
#            ^-----@node             # node 静态目标
#            ^-----@pgsql            # pgsql 静态目标
#            ^-----@pgrds            # pgsql 远程 RDS 目标
#            ^-----@redis            # redis 静态目标
#            ^-----@minio            # minio 静态目标
#            ^-----@mysql            # mysql 静态目标
#            ^-----@etcd             # etcd 静态目标
#            ^-----@ping             # ping 静态目标
#            ^-----@kafka            # kafka 静态目标
#            ^-----@juice            # juicefs 静态目标
#            ^-----@docker           # docker 静态目标
#            ^-----@patroni          # patroni 静态目标(启用 SSL 时)
# /etc/default/vmetrics              # vmetrics 启动参数(victoria:infra 0644)
# /etc/default/vlogs                 # vlogs 启动参数(victoria:infra 0644)
# /etc/default/vtraces               # vtraces 启动参数(victoria:infra 0644)
# /etc/default/vmalert               # vmalert 启动参数(victoria:infra 0644)
# /etc/alertmanager.yml              # 告警组件主配置(prometheus:infra 0644)
# /etc/default/alertmanager          # 告警组件环境变量(prometheus:infra 0640)
# /etc/blackbox.yml                  # 黑盒探测主配置(prometheus:infra 0644)
# /etc/default/blackbox_exporter     # 黑盒探测环境变量(prometheus:infra 0644)

Pigsty 自行渲染的 INFRA 单元统一位于 /etc/systemd/system/,包括 vmetricsvlogsvtracesvmalertalertmanagerblackbox_exporternginx_exporterdnsmasq;发行版软件包自带的单元目录不是这些角色的写入目标。


Postgres FHS

以下参数和内部变量均与 PostgreSQL 数据库目录结构相关:

  • pg_dbsu_home: Postgres 默认用户的家目录,默认为 /var/lib/pgsql
  • pg_bin_dir: Postgres 二进制目录,默认为 /usr/pgsql/bin/
  • pg_fs_main:Postgres 主数据目录,默认为 /data/postgres
  • pg_fs_backup:Postgres 备份盘挂载点,默认为 /data/backups(可选,也可以选择备份到主数据盘上的子目录)
  • pg_data:内部变量,固定表示 Postgres 数据目录软链 /pg/data
  • pg_cluster_dir:派生变量,{{ pg_fs_main }}/{{ pg_cluster }}-{{ pg_version }}
  • pg_backup_dir:派生变量,{{ pg_fs_backup }}/{{ pg_cluster }}-{{ pg_version }}
#--------------------------------------------------------------#
# 工作假设:
#   {{ pg_fs_main   }} 主数据目录,默认位置:`/data/postgres` [SSD]
#   {{ pg_fs_backup }} 备份数据盘,默认位置:`/data/backups`  [HDD]
#--------------------------------------------------------------#
# 默认配置(pg_cluster=pg-test, pg_version=18):
#     pg_fs_main = /data/postgres      高速SSD
#     pg_fs_backup = /data/backups     廉价HDD (可选)
#
#     /pg        -> /data/postgres/pg-test-18
#     /pg/data   -> /data/postgres/pg-test-18/data
#     /pg/backup -> /data/backups/pg-test-18/backup
#--------------------------------------------------------------#
- name: create pgsql directories
  tags: pg_dir
  become: true
  block:

    - name: create pgsql directories
      file: path={{ item.path }} state=directory owner={{ item.owner|default(pg_dbsu) }} group={{ item.group|default('postgres') }} mode={{ item.mode }}
      with_items:
        - { path: "{{ pg_fs_main }}"            ,mode: "0700" }
        - { path: "{{ pg_fs_backup }}"          ,mode: "0700" }
        - { path: "{{ pg_cluster_dir }}"        ,mode: "0700" }
        - { path: "{{ pg_cluster_dir }}/bin"    ,mode: "0700" }
        - { path: "{{ pg_cluster_dir }}/log"    ,mode: "0750" }
        - { path: "{{ pg_cluster_dir }}/tmp"    ,mode: "0700" }
        - { path: "{{ pg_cluster_dir }}/cert"   ,mode: "0700" }
        - { path: "{{ pg_cluster_dir }}/conf"   ,mode: "0700" }
        - { path: "{{ pg_cluster_dir }}/data"   ,mode: "0700" }
        - { path: "{{ pg_cluster_dir }}/spool"  ,mode: "0700" }
        - { path: "{{ pg_backup_dir }}/backup"  ,mode: "0700" }
        - { path: "/var/run/postgresql"         ,owner: root, group: root, mode: "0755" }

    - name: link pgsql directories
      file: src={{ item.src }} dest={{ item.dest }} state=link
      with_items:
        - { src: "{{ pg_backup_dir }}/backup" ,dest: "{{ pg_cluster_dir }}/backup" }
        - { src: "{{ pg_cluster_dir }}"       ,dest: "/pg" }

数据文件结构

# 真实目录
{{ pg_fs_main }}     /data/postgres                    # postgres:postgres 0700,主数据目录
{{ pg_cluster_dir }} /data/postgres/pg-test-18         # postgres:postgres 0700,集群目录
                     /data/postgres/pg-test-18/bin     # postgres:postgres 0700(脚本文件 root:postgres 0755)
                     /data/postgres/pg-test-18/log     # postgres:postgres 0750,日志目录
                     /data/postgres/pg-test-18/tmp     # postgres:postgres 0700,临时文件
                     /data/postgres/pg-test-18/cert    # postgres:postgres 0700,证书
                     /data/postgres/pg-test-18/conf    # postgres:postgres 0700,配置索引
                     /data/postgres/pg-test-18/data    # postgres:postgres 0700,主数据目录
                     /data/postgres/pg-test-18/spool   # postgres:postgres 0700,pgBackRest spool
                     /data/postgres/pg-test-18/backup  # -> /data/backups/pg-test-18/backup

{{ pg_fs_backup  }}  /data/backups                     # postgres:postgres 0700,可选备份盘目录/挂载点
{{ pg_backup_dir }}  /data/backups/pg-test-18          # postgres:postgres 0700,集群备份目录
                     /data/backups/pg-test-18/backup   # postgres:postgres 0700,实际备份位置

# 软链接
/pg             ->   /data/postgres/pg-test-18         # pg 根软链接
/pg/data        ->   /data/postgres/pg-test-18/data    # pg 数据目录
/pg/backup      ->   /data/backups/pg-test-18/backup   # pg 备份目录

二进制文件结构

在 EL 兼容发行版上(使用 yum),PostgreSQL 默认安装位置为

/usr/pgsql-${pg_version}/

Pigsty 会创建一个名为 /usr/pgsql 的软连接,指向由 pg_version 参数指定的实际版本,例如

/usr/pgsql -> /usr/pgsql-18

因此,默认的 pg_bin_dir/usr/pgsql/bin/,而该路径会被添加至系统的 PATH 环境变量中,定义文件为:/etc/profile.d/pgsql.sh.

export PATH="/usr/pgsql/bin:/pg/bin:$PATH"
export PGHOME=/usr/pgsql
export PGDATA=/pg/data

在 Ubuntu/Debian 上,PostgreSQL Deb 包的默认安装位置是:

/usr/lib/postgresql/${pg_version}/bin

Pigsty 渲染的 PostgreSQL 运行单元同样统一位于 /etc/systemd/system/,主要包括 patroni.servicepostgres.servicepgbouncer.servicepg_exporter.servicepgbackrest_exporter.servicepgbouncer_exporter.service,以及启用 VIP 时的 vip-manager.service


Pgbouncer FHS

Pgbouncer 使用与 {{ pg_dbsu }}(默认为 postgres)相同的用户运行,配置文件位于 /etc/pgbouncer

  • pgbouncer.ini:连接池主配置文件(postgres:postgres 0640
  • database.txt:定义连接池中的数据库(postgres:postgres 0600
  • useropts.txt:业务用户连接参数(postgres:postgres 0600
  • userlist.txt:由 /pg/bin/pgb-user 维护的用户密码文件
  • pgb_hba.conf:连接池访问控制文件(postgres:postgres 0600
/etc/pgbouncer/                # postgres:postgres 0750
/etc/pgbouncer/pgbouncer.ini   # postgres:postgres 0640
/etc/pgbouncer/database.txt    # postgres:postgres 0600
/etc/pgbouncer/useropts.txt    # postgres:postgres 0600
/etc/pgbouncer/userlist.txt    # postgres:postgres (由 pgb-user 维护)
/etc/pgbouncer/pgb_hba.conf    # postgres:postgres 0600
/pg/log/pgbouncer              # postgres:postgres 0750
/var/run/postgresql            # {{ pg_dbsu }}:postgres 0755(tmpfiles 维护)

Object Storage FHS

MINIO 模块当前只部署 Silo,但继续使用 minio_* 参数与目录命名保持兼容:

/etc/default/silo                             # root:minio 0640,服务环境变量
/etc/systemd/system/silo.service              # root:root 0644,Pigsty 渲染的单元
/data/minio/                                  # minio:minio 0750,默认数据目录
/infra/targets/minio/<cluster>-<seq>.yml      # victoria:infra 0640,FileSD 目标
/home/minio/.mcli/config.json                 # mcli 客户端别名(执行用户家目录亦会写入)

Silo 的证书位于 /home/minio/.minio/certs/。模块名、角色参数、数据目录和 FileSD 路径仍使用 MINIO / minio_* 兼容命名。


Redis FHS

Pigsty 使用同一套目录与实例命名管理 Redis 或 Valkey。

服务单元会按 redis_type 调用对应二进制(/bin/* 在多数发行版上与 /usr/bin/* 兼容):

/bin/redis-server  /bin/redis-cli    # redis_type: redis
/bin/valkey-server /bin/valkey-cli   # redis_type: valkey

对于一个名为 redis-test-1-6379 的 Redis 实例,与其相关的资源如下所示:

/etc/systemd/system/redis-test-1-6379.service         # root:root 0644(Pigsty 渲染)
/etc/systemd/system/redis_exporter.service            # root:root 0644(Pigsty 渲染)
/etc/redis/                                           # redis:redis 0700
/etc/redis/redis-test-1-6379.conf                     # redis:redis 0600
/data/redis/                                          # redis:redis 0700
/data/redis/redis-test-1-6379                         # redis:redis 0700
/data/redis/redis-test-1-6379/redis-test-1-6379.rdb   # RDB 文件
/data/redis/redis-test-1-6379/redis-test-1-6379.aof   # AOF 文件
/var/log/redis/                                       # redis:redis 0700
/var/log/redis/redis-test-1-6379.log                  # 日志
/var/run/redis/                                       # redis:redis 0700(开机 tmpfiles 为 0755)
/var/run/redis/redis-test-1-6379.pid                  # PID

Pigsty 渲染的 Redis/Valkey 实例与 exporter 单元统一放在 /etc/systemd/system/,实例单元使用 Type=notify;软件包自带的单元可能仍位于发行版目录,但不是角色写入的位置。

5.4 - 参数列表

Pigsty v4.x 配置参数总览与模块参数导航

本文是 Pigsty v4.x 的参数导航页,不重复展开每个参数的详细解释。 参数细节请进入各模块的 param 页面查看。

按照当前源码与参数参考页逐项对账,10 个正式模块合计 373 个公开参数。原生 MySQL 8.4 仍是试点模块,其 13 个公开参数单列,不计入正式模块合计。


模块参数导航

模块 参数组 参数量 说明
PGSQL 9 124 PostgreSQL 高可用集群配置
INFRA 10 73 软件仓库与 Victoria 可观测基础设施
NODE 11 73 节点初始化、系统调优与运维基线
ETCD 2 13 ETCD 集群与移除保护参数
MINIO 2 22 Silo 部署、观测与移除参数
REDIS 2 22 Redis/Valkey 部署与移除参数
DOCKER 1 8 Docker 引擎参数
JUICE 1 2 JuiceFS 实例与缓存参数
VIBE 1 18 Code/Jupyter/Node.js/Claude/Codex 配置
KAFKA 2 18 Kafka 部署参数与移除保护参数

试点模块:原生 MYSQL 8.4 当前公开 13 个参数,其中 11 个用于部署、2 个用于受保护移除;固定的端口、路径、软件版本和定时器不属于公开参数。


参数组速览


使用建议

  • 首次部署优先阅读:NODEINFRAPGSQL
  • 生产环境务必审查:*_safeguard、密码凭据、端口与网络暴露参数
  • 变更前先在单集群小范围验证,再扩展到全局参数

5.5 - 剧本列表

Pigsty v4.x 预置 Ansible 剧本导航与执行要点

本文汇总 Pigsty v4.x 各模块剧本入口与执行要点,详细任务标签请进入对应模块 playbook 文档。

模块剧本导航

模块 数量 剧本
INFRA 3 deploy.yml infra.yml infra-rm.yml
NODE 2 node.yml node-rm.yml
ETCD 2 etcd.yml etcd-rm.yml
PGSQL 7 pgsql.yml pgsql-rm.yml
pgsql-user.yml pgsql-db.yml
pgsql-monitor.yml pgsql-migration.yml pgsql-pitr.yml
REDIS 2 redis.yml redis-rm.yml
MINIO 2 minio.yml minio-rm.yml
DOCKER 1 docker.yml
JUICE 1 juice.yml
VIBE 1 vibe.yml
KAFKA 2 kafka.yml kafka-rm.yml
MYSQL(试点) 2 mysql.yml mysql-rm.yml

剧本总表

剧本 模块 主要用途
deploy.yml INFRA 一次性部署核心链路(Infra/Node/Etcd/PGSQL,按配置启用 MINIO)
infra.yml INFRA 初始化基础设施节点
infra-rm.yml INFRA 移除基础设施组件
node.yml NODE 节点纳管与基线配置
node-rm.yml NODE 节点去纳管
etcd.yml ETCD ETCD 安装/扩容
etcd-rm.yml ETCD ETCD 移除/缩容
pgsql.yml PGSQL 初始化 PostgreSQL 集群或新增实例
pgsql-rm.yml PGSQL 移除 PostgreSQL 集群/实例
pgsql-user.yml PGSQL 增加业务用户
pgsql-db.yml PGSQL 增加业务数据库
pgsql-monitor.yml PGSQL 纳管远程 PostgreSQL 监控
pgsql-migration.yml PGSQL 生成迁移手册与脚本
pgsql-pitr.yml PGSQL 时间点恢复(PITR)
redis.yml REDIS Redis 部署
redis-rm.yml REDIS Redis 移除
minio.yml MINIO Silo 部署
minio-rm.yml MINIO 移除 Silo、配置与可选数据
docker.yml DOCKER Docker 引擎部署
juice.yml JUICE JuiceFS 实例部署/移除
vibe.yml VIBE VIBE 开发环境部署
kafka.yml KAFKA 创建或收敛完整的 dynamic KRaft 集群
kafka-rm.yml KAFKA 移除 Kafka 集群,或安全退役单个成员
mysql.yml MYSQL 收敛原生 MySQL 8.4 单节点或三节点 InnoDB Cluster(试点)
mysql-rm.yml MYSQL 停止/退役原生 MySQL 实例或集群并保留本地状态(试点)

辅助剧本

以下剧本不归属于特定模块,提供一些辅助功能。

剧本 说明
cache.yml 构建离线安装包缓存
cert.yml 使用 Pigsty CA 签发证书
app.yml 使用 Docker Compose 安装应用模板
slim.yml 最小化组件安装场景

剧本使用注意事项

保护机制

多个模块提供了防误删保险,通过 *_safeguard 参数控制:

PGSQL、ETCD、MINIO、REDIS 与 KAFKA 的角色默认值均显式为 false;生产环境可在已初始化的集群上设置为 true。原生 MySQL 试点相反:mysql_safeguard 默认是 true,且即使显式关闭,也必须提供与目标实例或集群完全一致的 mysql_rm_confirm

当保护开关设置为 true 时,对应的 *-rm.yml 剧本会立即中止执行,防止误删。可以通过命令行参数强制覆盖:

./pgsql-rm.yml -l pg-test -e pg_safeguard=false
./etcd-rm.yml  -l etcd -e etcd_safeguard=false
./minio-rm.yml -l minio   -e minio_type=silo -e minio_safeguard=false
./redis-rm.yml -l redis-test -e redis_safeguard=false
./kafka-rm.yml -l kf-main -e kafka_safeguard=false
./mysql-rm.yml -l my-test -e mysql_safeguard=false -e mysql_rm_confirm=my-test

限制执行范围

执行剧本时建议使用 -l 参数限制命令执行的对象范围:

./pgsql.yml -l pg-meta            # 限制在集群 pg-meta 上执行
./node.yml -l 10.10.10.10         # 限制在特定节点上执行
./redis.yml -l redis-test         # 限制在 redis-test 集群上执行

在大规模部署上批量执行时,建议先在单集群灰度验证,再分批执行到全局。

幂等性

大部分剧本都是幂等的,可以重复执行。但需要注意:

  • infra.yml 默认 不会 清除数据,可安全重复执行。所有 clean 参数(vmetrics_cleanvlogs_cleanvtraces_cleangrafana_cleannginx_clean)默认均为 false
  • 如需清除基础设施数据重建,需显式设置对应的 clean 参数为 true
  • 重复执行 *-rm.yml 删除剧本需格外小心,确保在正确的目标上执行

任务标签

可以使用 -t 参数只执行特定的任务子集:

./pgsql.yml -l pg-test -t pg_service    # 只刷新集群 pg-test 的服务
./node.yml -t haproxy                   # 只在节点上设置 haproxy
./etcd.yml -t etcd_launch               # 只重启 etcd 服务

常用命令速查

INFRA 模块

./deploy.yml                     # 一次性部署核心链路
./infra.yml                      # 初始化基础设施
./infra-rm.yml                   # 移除基础设施
./cache.yml -l <infra-host>      # 从指定 Infra 节点的现有仓库创建离线安装包
./cert.yml -e cn=<name>          # 签发客户端证书

NODE 模块

./node.yml -l <cls|ip>           # 添加节点
./node-rm.yml -l <cls|ip>        # 移除节点
bin/node-add <cls|ip>            # 添加节点 (包装脚本)
bin/node-rm <cls|ip>             # 移除节点 (包装脚本)

ETCD 模块

./etcd.yml                       # 初始化 etcd 集群
./etcd-rm.yml -l etcd            # 默认删除该集群的本机数据与配置
bin/etcd-add <ip>                # 添加 etcd 成员 (包装脚本)
bin/etcd-rm <ip>                 # 移除 etcd 成员 (包装脚本)

PGSQL 模块

./pgsql.yml -l <cls>             # 初始化 PostgreSQL 集群
./pgsql-rm.yml -l <cls>          # 移除 PostgreSQL 集群
./pgsql-user.yml -l <cls> -e username=<user>   # 创建业务用户
./pgsql-db.yml -l <cls> -e dbname=<db>         # 创建业务数据库
./pgsql-monitor.yml -e clsname=<cls>           # 监控远程集群
./pgsql-migration.yml -e@files/migration/<cls>.yml  # 生成迁移手册
./pgsql-pitr.yml -l <cls> -e '{"pg_pitr": {}}'      # 执行 PITR 恢复

bin/pgsql-add <cls>              # 初始化集群 (包装脚本)
bin/pgsql-rm <cls>               # 移除集群 (包装脚本)
bin/pgsql-user <cls> <user>      # 创建用户 (包装脚本)
bin/pgsql-db <cls> <db>          # 创建数据库 (包装脚本)
bin/pgsql-svc <cls>              # 刷新服务 (包装脚本)
bin/pgsql-hba <cls>              # 重载 HBA (包装脚本)
bin/pgmon-add <cls>              # 监控远程集群 (包装脚本)

REDIS 模块

./redis.yml -l <cls>             # 初始化 Redis 集群
./redis-rm.yml -l <cls>          # 移除 Redis 集群

MINIO 模块

./minio.yml -l <cls>                       # 初始化 MINIO 模块的 Silo 集群
./minio-rm.yml -l <cls> -e minio_type=silo # 移除 Silo;该值必须显式确认

DOCKER 模块

./docker.yml -l <host>           # 安装 Docker
./app.yml -e app=<name>          # 部署 Docker Compose 应用

KAFKA 模块

./kafka.yml -l <cls>             # 创建/收敛完整 Kafka 集群
./kafka.yml -l <cls> --check     # 只读预检
./kafka-rm.yml -l <cls>          # 移除完整集群
./kafka-rm.yml -l <ip>           # 从集群退役单个成员

普通收敛的 -l 必须包含所选 Kafka 集群的全部已声明成员;kafka-rm.yml 才支持选择单个成员执行退役。

MYSQL 试点模块

./mysql.yml -l <cls> --check
./mysql.yml -l <cls>             # 只接受完整的 1 或 3 成员集群范围
./mysql-rm.yml -l <instance> --check \
  -e mysql_safeguard=false -e mysql_rm_confirm=<instance>
./mysql-rm.yml -l <cls> \
  -e mysql_safeguard=false -e mysql_rm_confirm=<cls>

mysql-rm.yml 会停止服务、写入退役标记并注销监控,但不会删除数据目录、备份、配置、证书、软件包或 InnoDB Cluster 元数据。

5.6 - 端口列表

Pigsty 中各个组件使用的端口一览,以及相关的配置参数与组件状态。

以下为 Pigsty 中各模块组件使用的默认端口及其对应参数,您可以按需调整,或者作为内部防火墙精细配置的参考。

模块 组件 端口 参数 状态
NODE node_exporter 9100 node_exporter_port ✅ 默认启用
NODE haproxy 9101 haproxy_exporter_port ✅ 默认启用
NODE vector 9598 vector_port ✅ 默认启用
NODE keepalived_exporter 9650 vip_exporter_port ⚠️ 按需启用
NODE chronyd 123 - ✅ 默认启用
DOCKER docker 9323 docker_exporter_port ⚠️ 按需启用
INFRA nginx 80 nginx_port ✅ 默认启用
INFRA nginx 443 nginx_ssl_port ✅ 默认启用
INFRA nginx_exporter 9113 nginx_exporter_port ✅ 默认启用
INFRA grafana 3000 grafana_port ✅ 默认启用
INFRA victoriaMetrics 8428 vmetrics_port ✅ 默认启用
INFRA victoriaLogs 9428 vlogs_port ✅ 默认启用
INFRA victoriaTraces 10428 vtraces_port ✅ 默认启用
INFRA vmalert 8880 vmalert_port ✅ 默认启用
INFRA alertmanager 9059 alertmanager_port ✅ 默认启用
INFRA blackbox_exporter 9115 blackbox_port ✅ 默认启用
INFRA dnsmasq 53 dns_port ✅ 默认启用
ETCD etcd 2379 etcd_port ✅ 默认启用
ETCD etcd 2380 etcd_peer_port ✅ 默认启用
MINIO Silo S3 API 9000 minio_port ⚠️ 按需启用
MINIO Silo 管理端口 9001 minio_admin_port ⚠️ 按需启用
REDIS Redis / Valkey 6379 redis_instances ⚠️ 按需启用
REDIS redis_exporter 9121 redis_exporter_port ⚠️ 按需启用
VIBE code-server 8443 code_port ⚠️ 按需启用
VIBE jupyterlab 8888 jupyter_port ⚠️ 按需启用
KAFKA broker 9092 kafka_port 🧪 BETA
KAFKA KRaft controller 9093 kafka_controller_port 🧪 BETA
KAFKA kafka_exporter 9308 kafka_exporter_port 🧪 BETA
KAFKA JMX exporter 9404 kafka_jmx_exporter_port 🧪 BETA
MYSQL mysqld 3306 固定值(当前试点不提供端口参数) 🧪 PILOT
MYSQL MySQL X Protocol 33060 固定值;单节点仅绑定回环地址,三节点拓扑对成员地址监听 🧪 PILOT
MYSQL Group Replication 33061 固定值;仅三节点 InnoDB Cluster 🧪 PILOT
MYSQL MySQL Router RW 6446 固定值;仅三节点 InnoDB Cluster 🧪 PILOT
MYSQL MySQL Router RO 6447 固定值;仅三节点 InnoDB Cluster 🧪 PILOT
MYSQL mysqld_exporter 9104 固定值;受 mysql_exporter_enabled 控制 🧪 PILOT
PGSQL postgres 5432 pg_port ✅ 默认启用
PGSQL pgbouncer 6432 pgbouncer_port ✅ 默认启用
PGSQL patroni 8008 patroni_port ✅ 默认启用
PGSQL pg_exporter 9630 pg_exporter_port ✅ 默认启用
PGSQL pgbouncer_exporter 9631 pgbouncer_exporter_port ✅ 默认启用
PGSQL pgbackrest_exporter 9854 pgbackrest_exporter_port ✅ 默认启用
PGSQL {{ pg_cluster }}-primary 5433 pg_default_services ✅ 默认启用
PGSQL {{ pg_cluster }}-replica 5434 pg_default_services ✅ 默认启用
PGSQL {{ pg_cluster }}-default 5436 pg_default_services ✅ 默认启用
PGSQL {{ pg_cluster }}-offline 5438 pg_default_services ✅ 默认启用
PGSQL {{ pg_cluster }}-<service> 543x pg_services ⚠️ 按需启用

原生 MySQL 试点的 MySQL Shell AdminAPI 复用 3306,XtraBackup 由本机 Systemd 定时任务调用,没有独立监听端口;MySQL Router 的 REST 管理接口被角色显式禁用。上表只列出当前角色实际管理的网络入口。

公网开放端口建议

如果您使用防火墙 zone 模式,建议通过 node_firewall_public_port 仅开放最小必要端口:

  • 最小管理面:22, 80, 443(推荐)
  • 需要公网直连数据库:额外开放 5432

不建议直接对公网开放:etcd2379/2380)、patroni8008)、各类 exporter(9xxx)、对象存储 S3/管理端口(9000/9001)、redis6379)、ferretdb27017/27018)、Kafka(9092/9093)及 MySQL Group Replication(33061)等内部组件端口。

node_firewall_mode: zone
node_firewall_public_port: [22, 80, 443]
# node_firewall_public_port: [22, 80, 443, 5432]  # only if public DB access is required

6 - 模板

开箱即用的配置模板,针对具体场景的配置示例,以及配置文件的详细解释。

您可以在 configure 时使用 -c 指定配置模板;参数值为相对 conf/ 的路径且不带 .yml 后缀。如果没有指定,将使用默认的 meta 模板。

6.1 - meta

Pigsty 默认使用的配置模板,单节点,覆盖核心功能,标准单机配置,在线安装,本地备份仓库。

meta 配置模板是 Pigsty 默认使用的模板,它的目标是在当前单节点上完成 Pigsty 核心功能 —— PostgreSQL 的部署。

为了实现最好的兼容性,meta 模板仅下载安装包含 最小必需 软件集合,以便在所有操作系统发行版与芯片架构上实现这一目标。


配置概览

  • 配置名称: meta
  • 节点数量: 单节点
  • 配置说明:Pigsty 默认使用的单节点安装配置模板,带有较完善的关键配置参数说明,与最小可用功能集合。
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:metaslimfat

使用方式:此配置模板为 Pigsty 默认配置模板,因此在 配置 时无需显式指定 -c meta 参数:

./configure [-i <primary_ip>]

例如,如果您想要安装 PG 16,而非默认的 PostgreSQL 18,可以在 configure 中使用 -v 参数:

./configure -v 16   # 也可使用 17、15、14;PG19 Beta 请改用 pg19 模板

配置内容

源文件地址:pigsty/conf/meta.yml

---
#==============================================================#
# File      :   meta.yml
# Desc      :   Pigsty default 1-node online install config
# Ctime     :   2020-05-22
# Mtime     :   2026-07-10
# Docs      :   https://pigsty.io/docs/conf/meta
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the default 1-node configuration template, with:
# INFRA, NODE, PGSQL, ETCD, MINIO, DOCKER, APP
# with basic pg extensions: postgis, pgvector
#
# Work with PostgreSQL 14-18 on all supported platform
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -g
#   ./deploy.yml

all:

  #==============================================================#
  # Clusters, Nodes, and Modules
  #==============================================================#
  children:

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql
    #----------------------------------------------#
    # this is an example single-node postgres cluster with pgvector installed, with one biz database & two biz users
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary } # <---- primary instance with read-write capability
        #x.xx.xx.xx: { pg_seq: 2, pg_role: replica } # <---- read only replica for read-only online traffic
        #x.xx.xx.xy: { pg_seq: 3, pg_role: offline } # <---- offline instance of ETL & interactive queries
      vars:
        pg_cluster: pg-meta

        # install, load, create pg extensions: https://pigsty.io/docs/pgsql/ext/
        pg_extensions: [ postgis, pgvector ]

        # define business users/roles : https://pigsty.io/docs/pgsql/config/user
        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  }

        # define business databases : https://pigsty.io/docs/pgsql/config/db
        pg_databases:
          - name: meta
            baseline: cmdb.sql
            comment: "pigsty meta database"
            schemas: [pigsty]
            # define extensions in database : https://pigsty.io/docs/pgsql/ext/create
            extensions: [ postgis, vector ]

        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # define (OPTIONAL) L2 VIP that bind to primary
        #pg_vip_enabled: true
        #pg_vip_address: 10.10.10.2/24


    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra
    #----------------------------------------------#
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }
      vars:
        repo_enabled: false   # disable in 1-node mode :  https://pigsty.io/docs/infra/admin/repo
        #repo_extra_packages: [ pg18-main ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------------------#
    # ETCD : https://pigsty.io/docs/etcd
    #----------------------------------------------#
    etcd:
      hosts:
        10.10.10.10: { etcd_seq: 1 }
      vars:
        etcd_cluster: etcd
        etcd_safeguard: false             # prevent purging running etcd instance?

    #----------------------------------------------#
    # MINIO : https://pigsty.io/docs/minio
    #----------------------------------------------#
    #minio:
    #  hosts:
    #    10.10.10.10: { minio_seq: 1 }
    #  vars:
    #    minio_cluster: minio
    #    minio_users:                      # list of minio user to be created
    #      - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
    #      - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
    #      - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }

    #----------------------------------------------#
    # DOCKER : https://pigsty.io/docs/docker
    # APP    : https://pigsty.io/docs/app
    #----------------------------------------------#
    # launch example pgadmin app with: ./app.yml (http://10.10.10.10:8885 [email protected] / pigsty)
    app:
      hosts: { 10.10.10.10: {} }
      vars:
        docker_enabled: true                # enabled docker with ./docker.yml
        #docker_registry_mirrors: ["https://docker.1panel.live","https://docker.1ms.run","https://docker.xuanyuan.me","https://registry-1.docker.io"]
        app: pgadmin                        # specify the default app name to be installed (in the apps)
        apps:                               # define all applications, appname: definition
          pgadmin:                          # pgadmin app definition (app/pgadmin -> /opt/pgadmin)
            conf:                           # override /opt/pgadmin/.env
              PGADMIN_DEFAULT_EMAIL: [email protected]
              PGADMIN_DEFAULT_PASSWORD: pigsty


  #==============================================================#
  # Global Parameters
  #==============================================================#
  vars:

    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    proxy_env:                        # global proxy env when downloading packages
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
      # http_proxy:  # set your proxy here: e.g http://user:[email protected]
      # https_proxy: # set your proxy here: e.g http://user:[email protected]
      # all_proxy:   # set your proxy here: e.g http://user:[email protected]
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name
      pgadmin : { domain: adm.pigsty ,endpoint: "${admin_ip}:8885" }
      #minio  : { domain: m.pigsty ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false             # do not overwrite node hostname on single node mode
    node_tune: oltp                       # node tuning specs: oltp,olap,tiny,crit
    node_etc_hosts: ['${admin_ip} i.pigsty sss.pigsty']
    node_repo_modules: 'node,infra,pgsql' # add these repos directly to the singleton node
    #node_repo_modules: local             # use this if you want to build & user local repo
    node_repo_remove: true                # remove existing node repo for node managed by pigsty
    #node_packages: [openssh-server]      # packages to be installed current nodes with the latest version
    node_firewall_public_port: [22, 80, 443, 5432]    # expose 5432 for demo convenience, remove in production!

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 18                      # default postgres version
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    pg_safeguard: false                 # prevent purging running postgres instance?
    pg_packages: [ pgsql-main, pgsql-common ]  # pg kernel and common utils
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------------------#
    # BACKUP : https://pigsty.io/docs/pgsql/backup
    #----------------------------------------------#
    # if you want to use minio as backup repo instead of 'local' fs, uncomment this, and configure `pgbackrest_repo`
    # you can also use external object storage as backup repo
    #pgbackrest_method: minio          # if you want to use minio as backup repo instead of 'local' fs, uncomment this
    #pgbackrest_repo:                  # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
    #  local:                          # default pgbackrest repo with local posix fs
    #    path: /pg/backup              # local backup directory, `/pg/backup` by default
    #    retention_full_type: count    # retention full backups by count
    #    retention_full: 2             # keep 2, at most 3 full backup when using local fs repo
    #  minio:                          # optional minio repo for pgbackrest
    #    type: s3                      # minio is s3-compatible, so s3 is used
    #    s3_endpoint: sss.pigsty       # minio endpoint domain name, `sss.pigsty` by default
    #    s3_region: us-east-1          # minio region, us-east-1 by default, useless for minio
    #    s3_bucket: pgsql              # minio bucket name, `pgsql` by default
    #    s3_key: pgbackrest            # minio user access key for pgbackrest
    #    s3_key_secret: S3User.Backup  # minio user secret key for pgbackrest
    #    s3_uri_style: path            # use path style uri for minio rather than host style
    #    path: /pgbackrest             # minio backup path, default is `/pgbackrest`
    #    storage_port: 9000            # minio port, 9000 by default
    #    storage_ca_file: /etc/pki/ca.crt  # minio ca file path, `/etc/pki/ca.crt` by default
    #    block: y                      # Enable block incremental backup
    #    bundle: y                     # bundle small files into a single file
    #    bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
    #    bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
    #    cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
    #    cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
    #    retention_full_type: time     # retention full backup by time on minio repo
    #    retention_full: 14            # keep full backup for last 14 days
    #  s3: # aliyun oss (s3 compatible) object storage service
    #    type: s3                      # oss is s3-compatible
    #    s3_endpoint: oss-cn-beijing-internal.aliyuncs.com
    #    s3_region: oss-cn-beijing
    #    s3_bucket: <your_bucket_name>
    #    s3_key: <your_access_key>
    #    s3_key_secret: <your_secret_key>
    #    s3_uri_style: host
    #    path: /pgbackrest
    #    bundle: y                     # bundle small files into a single file
    #    bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
    #    bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
    #    cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
    #    cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
    #    retention_full_type: time     # retention full backup by time on minio repo
    #    retention_full: 14            # keep full backup for last 14 days

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

meta 模板是 Pigsty 的 默认入门配置,专为快速上手设计。

适用场景

  • 首次体验 Pigsty 的用户
  • 开发测试环境的快速部署
  • 单机运行的小型生产环境
  • 作为更复杂部署的基础模板

关键特性

  • 在线安装模式,不构建本地软件源(repo_enabled: false
  • 默认安装 PostgreSQL 18,带有 postgispgvector 扩展
  • 包含完整的可观测基础设施(Grafana、VictoriaMetrics、VictoriaLogs 等)
  • 预置 Docker 与 pgAdmin 应用示例
  • Silo 备份存储默认禁用,可按需启用

注意事项

  • 默认密码为示例密码,生产环境 务必修改
  • 单节点模式的 etcd 无高可用保障,适合开发测试
  • 如需构建本地软件源,请使用 rich 模板

6.2 - rich

功能丰富的单节点配置,构建本地软件源,下载所有扩展,启用 Silo 备份,预置完整示例

配置模板 richmeta 的增强版本,专为需要完整功能体验的用户设计。

如果您希望构建本地软件源、使用 Silo 存储备份、运行 Docker 应用,或需要预置业务数据库,可以使用此模板。


配置概览

  • 配置名称: rich
  • 节点数量: 单节点
  • 配置说明:功能丰富的单节点配置,在 meta 基础上增加本地软件源、Silo 备份、完整扩展、Docker 应用示例
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:metaslimfat

此模板相比 meta 的主要增强:

  • 构建本地软件源(repo_enabled: true),下载所有 PG 扩展
  • 启用单节点 Silo 作为 PostgreSQL 备份存储
  • 预置 TimescaleDB、pgvector、pg_wait_sampling 等扩展
  • 包含详细的用户/数据库/服务定义注释示例
  • 添加 Redis 主从实例示例
  • 预置 pg-test 三节点高可用集群配置存根

启用方式:

./configure -c rich [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/rich.yml

---
#==============================================================#
# File      :   rich.yml
# Desc      :   Pigsty feature-rich 1-node online install config
# Ctime     :   2020-05-22
# Mtime     :   2025-12-12
# Docs      :   https://pigsty.io/docs/conf/rich
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the enhanced version of default meta.yml, which has:
# - almost all available postgres extensions
# - build local software repo for entire env
# - 1 node minio used as central backup repo
# - cluster stub for 3-node pg-test / redis
# - stub for nginx, certs, and website self-hosting config
# - detailed comments for database / user / service
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c rich
#   ./deploy.yml

all:

  #==============================================================#
  # Clusters, Nodes, and Modules
  #==============================================================#
  children:

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql
    #----------------------------------------------#
    # this is an example single-node postgres cluster with pgvector installed, with one biz database & two biz users
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary } # <---- primary instance with read-write capability
        #x.xx.xx.xx: { pg_seq: 2, pg_role: replica } # <---- read only replica for read-only online traffic
        #x.xx.xx.xy: { pg_seq: 3, pg_role: offline } # <---- offline instance of ETL & interactive queries
      vars:
        pg_cluster: pg-meta

        # install, load, create pg extensions: https://pigsty.io/docs/pgsql/ext/
        pg_extensions: [ postgis, timescaledb, pgvector, pg_wait_sampling ]
        pg_libs: 'timescaledb, pg_stat_statements, auto_explain, pg_wait_sampling'

        # define business users/roles : https://pigsty.io/docs/pgsql/config/user
        pg_users:
          - name: dbuser_meta               # REQUIRED, `name` is the only mandatory field of a user definition
            password: DBUser.Meta           # optional, the password. can be a scram-sha-256 hash string or plain text
            pgbouncer: true                 # optional, add this user to the pgbouncer user-list? false by default (production user should be true explicitly)
            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}
            #state: create                  # optional, create|absent, 'create' by default, use 'absent' to drop user
            #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 databases? 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
            #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)
            #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
            # Enhanced roles syntax (PG16+): roles can be string or object with options:
            #   - dbrole_readwrite                       # simple string: GRANT role
            #   - { name: role, admin: true }            # GRANT WITH ADMIN OPTION
            #   - { name: role, set: false }             # PG16: REVOKE SET OPTION
            #   - { name: role, inherit: false }         # PG16: REVOKE INHERIT OPTION
            #   - { name: role, state: absent }          # REVOKE membership
          - { name: dbuser_view ,password: DBUser.Viewer ,pgbouncer: true ,roles: [dbrole_readonly], comment: read-only viewer for meta database }
          #- {name: dbuser_bytebase ,password: DBUser.Bytebase ,pgbouncer: true ,roles: [dbrole_admin] ,comment: admin user for bytebase database   }
          #- {name: dbuser_remove ,state: absent }       # use state: absent to remove a user

        # define business databases : https://pigsty.io/docs/pgsql/config/db
        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
            #state: create                  # optional, create|absent|recreate, create by default
            baseline: cmdb.sql              # optional, database sql baseline path, (relative path among the ansible search path, e.g.: files/)
            schemas: [ pigsty ]             # optional, additional schemas to be created, array of schema names
            extensions:                     # optional, additional extensions to be installed: array of `{name[,schema]}`
              - vector                      # install pgvector for vector similarity search
              - postgis                     # install postgis for geospatial type & index
              - timescaledb                 # install timescaledb for time-series data
              - { name: pg_wait_sampling, schema: monitor } # install pg_wait_sampling on monitor schema
            comment: pigsty meta database   # optional, comment string for this database
            #pgbouncer: true                # optional, add this database to the pgbouncer database list? true by default
            #owner: postgres                # optional, database owner, current user if not specified
            #template: template1            # optional, which template to use, template1 by default
            #strategy: FILE_COPY            # optional, clone strategy: FILE_COPY or WAL_LOG (PG15+), default to PG's default
            #encoding: UTF8                 # optional, inherited from template / cluster if not defined (UTF8)
            #locale: C                      # optional, inherited from template / cluster if not defined (C)
            #lc_collate: C                  # optional, inherited from template / cluster if not defined (C)
            #lc_ctype: C                    # optional, inherited from template / cluster if not defined (C)
            #locale_provider: libc          # optional, locale provider: libc, icu, builtin (PG15+)
            #icu_locale: en-US              # optional, icu locale for icu locale provider (PG15+)
            #icu_rules: ''                  # optional, icu rules for icu locale provider (PG16+)
            #builtin_locale: C.UTF-8        # optional, builtin locale for builtin locale provider (PG17+)
            #tablespace: pg_default         # optional, default tablespace, pg_default by default
            #is_template: false             # optional, mark database as template, allowing clone by any user with CREATEDB privilege
            #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_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_connlimit: 100            # optional, max database connections at database level, default 100
          #- {name: bytebase ,owner: dbuser_bytebase ,revokeconn: true ,comment: bytebase primary database }

        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # define (OPTIONAL) L2 VIP that bind to primary
        #pg_vip_enabled: true
        #pg_vip_address: 10.10.10.2/24

    #----------------------------------------------#
    # PGSQL HA Cluster Example: 3-node pg-test
    #----------------------------------------------#
    #pg-test:
    #  hosts:
    #    10.10.10.11: { pg_seq: 1, pg_role: primary }   # primary instance, leader of cluster
    #    10.10.10.12: { pg_seq: 2, pg_role: replica }   # replica instance, follower of leader
    #    10.10.10.13: { pg_seq: 3, pg_role: replica, pg_offline_query: true } # replica with offline access
    #  vars:
    #    pg_cluster: pg-test           # define pgsql cluster name
    #    pg_users:  [{ name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] }]
    #    pg_databases: [{ name: test }]
    #    # define business service here: https://pigsty.io/docs/pgsql/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_vip_enabled: true
    #    pg_vip_address: 10.10.10.3/24
    #    pg_crontab:  # make a full backup on monday 1am, and an incremental backup during weekdays
    #      - '00 01 * * 1 /pg/bin/pg-backup full'
    #      - '00 01 * * 2,3,4,5,6,7 /pg/bin/pg-backup'

    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra
    #----------------------------------------------#
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }
      vars:
        repo_enabled: true    # build local repo, and install everything from it:  https://pigsty.io/docs/infra/admin/repo
        # and download all extensions into local repo
        repo_extra_packages: [ pg18-main ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------------------#
    # ETCD : https://pigsty.io/docs/etcd
    #----------------------------------------------#
    etcd:
      hosts:
        10.10.10.10: { etcd_seq: 1 }
      vars:
        etcd_cluster: etcd
        etcd_safeguard: false             # prevent purging running etcd instance?

    #----------------------------------------------#
    # MINIO : https://pigsty.io/docs/minio
    #----------------------------------------------#
    minio:
      hosts:
        10.10.10.10: { minio_seq: 1 }
      vars:
        minio_cluster: minio
        minio_users:                      # list of minio user to be created
          - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
          - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
          - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }

    #----------------------------------------------#
    # DOCKER : https://pigsty.io/docs/docker
    # APP    : https://pigsty.io/docs/app
    #----------------------------------------------#
    # OPTIONAL, launch example pgadmin app with: ./app.yml & ./app.yml -e app=bytebase
    app:
      hosts: { 10.10.10.10: {} }
      vars:
        docker_enabled: true                # enabled docker with ./docker.yml
        #docker_registry_mirrors: ["https://docker.1panel.live","https://docker.1ms.run","https://docker.xuanyuan.me","https://registry-1.docker.io"]
        app: pgadmin                        # specify the default app name to be installed (in the apps)
        apps:                               # define all applications, appname: definition

          # Admin GUI for PostgreSQL, launch with: ./app.yml
          pgadmin:                          # pgadmin app definition (app/pgadmin -> /opt/pgadmin)
            conf:                           # override /opt/pgadmin/.env
              PGADMIN_DEFAULT_EMAIL: [email protected]   # default user name
              PGADMIN_DEFAULT_PASSWORD: pigsty         # default password

          # Schema Migration GUI for PostgreSQL, launch with: ./app.yml -e app=bytebase
          bytebase:
            conf:
              BB_DOMAIN: http://ddl.pigsty  # replace it with your public domain name and postgres database url
              BB_PGURL: "postgresql://dbuser_bytebase:[email protected]:5432/bytebase?sslmode=prefer"

    #----------------------------------------------#
    # REDIS : https://pigsty.io/docs/redis
    #----------------------------------------------#
    # OPTIONAL, launch redis clusters with: ./redis.yml
    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 }



  #==============================================================#
  # Global Parameters
  #==============================================================#
  vars:

    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    proxy_env:                        # global proxy env when downloading packages
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
      # http_proxy:  # set your proxy here: e.g http://user:[email protected]
      # https_proxy: # set your proxy here: e.g http://user:[email protected]
      # all_proxy:   # set your proxy here: e.g http://user:[email protected]

    certbot_sign: false               # enable certbot to sign https certificate for infra portal
    certbot_email: [email protected]     # replace your email address to receive expiration notice
    infra_portal:                     # infra services exposed via portal
      home      : { domain: i.pigsty }     # default domain name
      pgadmin   : { domain: adm.pigsty ,endpoint: "${admin_ip}:8885" }
      bytebase  : { domain: ddl.pigsty ,endpoint: "${admin_ip}:8887" }
      minio     : { domain: m.pigsty ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }

      #website:   # static local website example stub
      #  domain: repo.pigsty              # external domain name for static site
      #  certbot: repo.pigsty             # use certbot to sign https certificate for this static site
      #  path: /www/pigsty                # path to the static site directory

      #supabase:  # dynamic upstream service example stub
      #  domain: supa.pigsty          # external domain name for upstream service
      #  certbot: supa.pigsty         # use certbot to sign https certificate for this upstream server
      #  endpoint: "10.10.10.10:8000" # path to the static site directory
      #  websocket: true              # add websocket support
      #  certbot: supa.pigsty         # certbot cert name, apply with `make cert`

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false             # do not overwrite node hostname on single node mode
    node_tune: oltp                       # node tuning specs: oltp,olap,tiny,crit
    node_etc_hosts:                       # add static domains to all nodes /etc/hosts
      - '${admin_ip} i.pigsty sss.pigsty'
      - '${admin_ip} adm.pigsty ddl.pigsty repo.pigsty supa.pigsty'
    node_repo_modules: local              # use pre-made local repo rather than install from upstream
    node_repo_remove: true                # remove existing node repo for node managed by pigsty
    #node_packages: [openssh-server]      # packages to be installed current nodes with latest version
    #node_timezone: Asia/Hong_Kong        # overwrite node timezone

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 18                      # default postgres version
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    pg_safeguard: false                 # prevent purging running postgres instance?
    pg_packages: [ pgsql-main, pgsql-common ]                 # pg kernel and common utils
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------------------#
    # BACKUP : https://pigsty.io/docs/pgsql/backup
    #----------------------------------------------#
    # if you want to use minio as backup repo instead of 'local' fs, uncomment this, and configure `pgbackrest_repo`
    # you can also use external object storage as backup repo
    pgbackrest_method: minio          # if you want to use minio as backup repo instead of 'local' fs, uncomment this
    pgbackrest_repo:                  # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
      local:                          # default pgbackrest repo with local posix fs
        path: /pg/backup              # local backup directory, `/pg/backup` by default
        retention_full_type: count    # retention full backups by count
        retention_full: 2             # keep 2, at most 3 full backups when using local fs repo
      minio:                          # optional minio repo for pgbackrest
        type: s3                      # minio is s3-compatible, so s3 is used
        s3_endpoint: sss.pigsty       # minio endpoint domain name, `sss.pigsty` by default
        s3_region: us-east-1          # minio region, us-east-1 by default, useless for minio
        s3_bucket: pgsql              # minio bucket name, `pgsql` by default
        s3_key: pgbackrest            # minio user access key for pgbackrest [CHANGE ACCORDING to minio_users.pgbackrest]
        s3_key_secret: S3User.Backup  # minio user secret key for pgbackrest [CHANGE ACCORDING to minio_users.pgbackrest]
        s3_uri_style: path            # use path style uri for minio rather than host style
        path: /pgbackrest             # minio backup path, default is `/pgbackrest`
        storage_port: 9000            # minio port, 9000 by default
        storage_ca_file: /etc/pki/ca.crt  # minio ca file path, `/etc/pki/ca.crt` by default
        block: y                      # Enable block incremental backup
        bundle: y                     # bundle small files into a single file
        bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
        cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
        retention_full_type: time     # retention full backup by time on minio repo
        retention_full: 14            # keep full backup for the last 14 days
      s3:                             # you can use cloud object storage as backup repo
        type: s3                      # Add your object storage credentials here!
        s3_endpoint: oss-cn-beijing-internal.aliyuncs.com
        s3_region: oss-cn-beijing
        s3_bucket: <your_bucket_name>
        s3_key: <your_access_key>
        s3_key_secret: <your_secret_key>
        s3_uri_style: host
        path: /pgbackrest
        bundle: y                     # bundle small files into a single file
        bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
        cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
        retention_full_type: time     # retention full backup by time on minio repo
        retention_full: 14            # keep full backup for the last 14 days
...

配置解读

rich 模板是 Pigsty 的 完整功能展示配置,适合需要深入体验所有功能的用户。

适用场景

  • 需要构建本地软件源的离线环境
  • 需要使用 Silo 作为 PostgreSQL 备份存储
  • 需要预先规划多个业务数据库和用户
  • 需要运行 Docker 应用(pgAdmin、Bytebase 等)
  • 希望了解配置参数完整用法的学习者

与 meta 的主要区别

  • 启用本地软件源构建(repo_enabled: true
  • 启用 Silo 存储备份(兼容预设 pgbackrest_method: minio
  • 预装 TimescaleDB、pg_wait_sampling 等额外扩展
  • 包含详细的参数注释,便于理解配置含义
  • 预置高可用集群存根配置(pg-test)

注意事项

  • ARM64 架构部分扩展不可用,请按需调整
  • 构建本地软件源需要较长时间和较大磁盘空间
  • 默认密码为示例密码,生产环境务必修改

6.3 - slim

精简安装配置模板,不部署监控基础设施,直接从互联网安装 PostgreSQL

slim 配置模板提供 精简安装 能力,在不部署 Infra 监控基础设施的前提下,直接从互联网安装 PostgreSQL 高可用集群。

当您只需要一个可用的数据库实例,不需要监控系统时,可以考虑使用 精简安装 模式。


配置概览

  • 配置名称: slim
  • 节点数量: 单节点
  • 配置说明:精简安装配置模板,不部署监控基础设施,直接安装 PostgreSQL
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:meta

启用方式:

./configure -c slim [-i <primary_ip>]
./slim.yml   # 执行精简安装

配置内容

源文件地址:pigsty/conf/slim.yml

---
#==============================================================#
# File      :   slim.yml
# Desc      :   Pigsty slim installation config template
# Ctime     :   2020-05-22
# Mtime     :   2025-12-28
# Docs      :   https://pigsty.io/docs/conf/slim
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for slim / minimal installation
# No monitoring & infra will be installed, just raw postgresql
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c slim
#   ./slim.yml

all:
  children:

    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 }  # three-member cluster keeps an odd voter count
      vars: # cluster level parameter override roles/etcd
        etcd_cluster: etcd  # mark etcd cluster name etcd

    #----------------------------------------------#
    # PostgreSQL Cluster
    #----------------------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
        #10.10.10.11: { pg_seq: 2, pg_role: replica } # you can add more!
        #10.10.10.12: { pg_seq: 3, pg_role: replica, pg_offline_query: true }
      vars:
        pg_cluster: pg-meta
        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  }
        pg_databases:
          - { name: meta, baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [ vector ]}
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

  vars:
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    nodename_overwrite: false           # do not overwrite node hostname on single node mode
    node_repo_modules: node,infra,pgsql # add these repos directly to the singleton node
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    pg_version: 18                      # Default PostgreSQL Major Version is 18
    pg_packages: [ pgsql-main, pgsql-common ]   # pg kernel and common utils
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

slim 模板是 Pigsty 的 精简安装配置,专为快速部署裸 PostgreSQL 集群设计。

适用场景

  • 仅需要 PostgreSQL 数据库,不需要监控系统
  • 资源有限的小型服务器或边缘设备
  • 快速部署测试用的临时数据库
  • 已有监控系统,只需要 PostgreSQL 高可用集群

关键特性

  • 使用 slim.yml 剧本而非 deploy.yml 进行安装
  • 从互联网直接安装软件,不构建本地软件源
  • 保留核心 PostgreSQL 高可用能力(Patroni + etcd + HAProxy)
  • 最小化软件包下载,加快安装速度
  • 默认使用 PostgreSQL 18

与 meta 的区别

  • slim 使用专用的 slim.yml 剧本,跳过 Infra 模块安装
  • 安装速度更快,资源占用更少
  • 适合"只要数据库"的场景

注意事项

  • 精简安装后无法通过 Grafana 查看数据库状态
  • 如需监控功能,请使用 metarich 模板
  • 可按需添加从库实现高可用

6.4 - fat

功能全测试模板,单节点安装所有扩展,构建包含 PG 14-18 全版本的本地软件源。

fat 配置模板是 Pigsty 的 功能全测试模板(Feature-All-Test),在单节点上安装所有扩展插件,并构建包含 PostgreSQL 14-18 全部五个大版本所有扩展的本地软件源。

这是一个用于测试与开发的全功能配置,适合需要完整软件包缓存或测试全部扩展的场景。


配置概览

  • 配置名称: fat
  • 节点数量: 单节点
  • 配置说明:功能全测试模板,安装所有扩展,构建包含 PG 14-18 全版本的本地软件源
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:metaslimfat

启用方式:

./configure -c fat [-i <primary_ip>]

如需指定特定 PostgreSQL 版本:

./configure -c fat -v 16   # 使用 PostgreSQL 16

配置内容

源文件地址:pigsty/conf/fat.yml

---
#==============================================================#
# File      :   fat.yml
# Desc      :   Pigsty Feature-All-Test config template
# Ctime     :   2020-05-22
# Mtime     :   2025-12-28
# Docs      :   https://pigsty.io/docs/conf/fat
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the 4-node sandbox for pigsty
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c fat [-v 18|17|16|15]
#   ./deploy.yml

all:

  #==============================================================#
  # Clusters, Nodes, and Modules
  #==============================================================#
  children:

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql
    #----------------------------------------------#
    # this is an example single-node postgres cluster with pgvector installed, with one biz database & two biz users
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary } # <---- primary instance with read-write capability
        #x.xx.xx.xx: { pg_seq: 2, pg_role: replica } # <---- read only replica for read-only online traffic
        #x.xx.xx.xy: { pg_seq: 3, pg_role: offline } # <---- offline instance of ETL & interactive queries
      vars:
        pg_cluster: pg-meta

        # install, load, create pg extensions: https://pigsty.io/docs/pgsql/ext/
        pg_extensions: [ pg18-main ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
        pg_libs: 'timescaledb, pg_stat_statements, auto_explain, pg_wait_sampling'

        # define business users/roles : https://pigsty.io/docs/pgsql/config/user
        pg_users:
          - name: dbuser_meta               # REQUIRED, `name` is the only mandatory field of a user definition
            password: DBUser.Meta           # optional, the password. can be a scram-sha-256 hash string or plain text
            pgbouncer: true                 # optional, add this user to the pgbouncer user-list? false by default (production user should be true explicitly)
            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}
            #state: create                   # optional, create|absent, 'create' by default, use 'absent' to drop user
            #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 databases? 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
            #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)
            #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
            # Enhanced roles syntax (PG16+): roles can be string or object with options:
            #   - dbrole_readwrite                       # simple string: GRANT role
            #   - { name: role, admin: true }            # GRANT WITH ADMIN OPTION
            #   - { name: role, set: false }             # PG16: REVOKE SET OPTION
            #   - { name: role, inherit: false }         # PG16: REVOKE INHERIT OPTION
            #   - { name: role, state: absent }          # REVOKE membership
          - { name: dbuser_view ,password: DBUser.Viewer ,pgbouncer: true ,roles: [dbrole_readonly], comment: read-only viewer for meta database }
          #- {name: dbuser_bytebase ,password: DBUser.Bytebase ,pgbouncer: true ,roles: [dbrole_admin] ,comment: admin user for bytebase database   }
          #- {name: dbuser_remove ,state: absent }       # use state: absent to remove a user

        # define business databases : https://pigsty.io/docs/pgsql/config/db
        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
            #state: create                  # optional, create|absent|recreate, create by default
            baseline: cmdb.sql              # optional, database sql baseline path, (relative path among the ansible search path, e.g.: files/)
            schemas: [ pigsty ]             # optional, additional schemas to be created, array of schema names
            extensions:                     # optional, additional extensions to be installed: array of `{name[,schema]}`
              - vector                      # install pgvector for vector similarity search
              - postgis                     # install postgis for geospatial type & index
              - timescaledb                 # install timescaledb for time-series data
              - { name: pg_wait_sampling, schema: monitor } # install pg_wait_sampling on monitor schema
            comment: pigsty meta database   # optional, comment string for this database
            #pgbouncer: true                # optional, add this database to the pgbouncer database list? true by default
            #owner: postgres                # optional, database owner, current user if not specified
            #template: template1            # optional, which template to use, template1 by default
            #strategy: FILE_COPY            # optional, clone strategy: FILE_COPY or WAL_LOG (PG15+), default to PG's default
            #encoding: UTF8                 # optional, inherited from template / cluster if not defined (UTF8)
            #locale: C                      # optional, inherited from template / cluster if not defined (C)
            #lc_collate: C                  # optional, inherited from template / cluster if not defined (C)
            #lc_ctype: C                    # optional, inherited from template / cluster if not defined (C)
            #locale_provider: libc          # optional, locale provider: libc, icu, builtin (PG15+)
            #icu_locale: en-US              # optional, icu locale for icu locale provider (PG15+)
            #icu_rules: ''                  # optional, icu rules for icu locale provider (PG16+)
            #builtin_locale: C.UTF-8        # optional, builtin locale for builtin locale provider (PG17+)
            #tablespace: pg_default         # optional, default tablespace, pg_default by default
            #is_template: false             # optional, mark database as template, allowing clone by any user with CREATEDB privilege
            #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_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_connlimit: 100            # optional, max database connections at database level, default 100
          #- {name: bytebase ,owner: dbuser_bytebase ,revokeconn: true ,comment: bytebase primary database }

        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # define (OPTIONAL) L2 VIP that bind to primary
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.2/24


    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra
    #----------------------------------------------#
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }
      vars:
        repo_enabled: true # build local repo:  https://pigsty.io/docs/infra/admin/repo
        #repo_extra_packages: [ pg18-main ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
        repo_packages: [
          node-bootstrap, infra-package, infra-addons, node-package1, node-package2, node-package3, pgsql-utility, extra-modules,
          pg18-full,pg18-time,pg18-gis,pg18-rag,pg18-fts,pg18-olap,pg18-feat,pg18-lang,pg18-type,pg18-util,pg18-func,pg18-admin,pg18-stat,pg18-sec,pg18-fdw,pg18-sim,pg18-etl,
          pg17-full,pg17-time,pg17-gis,pg17-rag,pg17-fts,pg17-olap,pg17-feat,pg17-lang,pg17-type,pg17-util,pg17-func,pg17-admin,pg17-stat,pg17-sec,pg17-fdw,pg17-sim,pg17-etl,
          pg16-full,pg16-time,pg16-gis,pg16-rag,pg16-fts,pg16-olap,pg16-feat,pg16-lang,pg16-type,pg16-util,pg16-func,pg16-admin,pg16-stat,pg16-sec,pg16-fdw,pg16-sim,pg16-etl,
          pg15-full,pg15-time,pg15-gis,pg15-rag,pg15-fts,pg15-olap,pg15-feat,pg15-lang,pg15-type,pg15-util,pg15-func,pg15-admin,pg15-stat,pg15-sec,pg15-fdw,pg15-sim,pg15-etl,
          pg14-full,pg14-time,pg14-gis,pg14-rag,pg14-fts,pg14-olap,pg14-feat,pg14-lang,pg14-type,pg14-util,pg14-func,pg14-admin,pg14-stat,pg14-sec,pg14-fdw,pg14-sim,pg14-etl,
          infra-extra, kafka-stack, java-runtime, sealos, tigerbeetle, polardb, ivorysql
        ]

    #----------------------------------------------#
    # ETCD : https://pigsty.io/docs/etcd
    #----------------------------------------------#
    etcd:
      hosts:
        10.10.10.10: { etcd_seq: 1 }
      vars:
        etcd_cluster: etcd
        etcd_safeguard: false             # prevent purging running etcd instance?

    #----------------------------------------------#
    # MINIO : https://pigsty.io/docs/minio
    #----------------------------------------------#
    minio:
      hosts:
        10.10.10.10: { minio_seq: 1 }
      vars:
        minio_cluster: minio
        minio_users:                      # list of minio user to be created
          - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
          - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
          - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }

    #----------------------------------------------#
    # DOCKER : https://pigsty.io/docs/docker
    # APP    : https://pigsty.io/docs/app
    #----------------------------------------------#
    # OPTIONAL, launch example pgadmin app with: ./app.yml & ./app.yml -e app=bytebase
    app:
      hosts: { 10.10.10.10: {} }
      vars:
        docker_enabled: true                # enabled docker with ./docker.yml
        #docker_registry_mirrors: ["https://docker.1panel.live","https://docker.1ms.run","https://docker.xuanyuan.me","https://registry-1.docker.io"]
        app: pgadmin                        # specify the default app name to be installed (in the apps)
        apps:                               # define all applications, appname: definition

          # Admin GUI for PostgreSQL, launch with: ./app.yml
          pgadmin:                          # pgadmin app definition (app/pgadmin -> /opt/pgadmin)
            conf:                           # override /opt/pgadmin/.env
              PGADMIN_DEFAULT_EMAIL: [email protected]   # default user name
              PGADMIN_DEFAULT_PASSWORD: pigsty         # default password

          # Schema Migration GUI for PostgreSQL, launch with: ./app.yml -e app=bytebase
          bytebase:
            conf:
              BB_DOMAIN: http://ddl.pigsty  # replace it with your public domain name and postgres database url
              BB_PGURL: "postgresql://dbuser_bytebase:[email protected]:5432/bytebase?sslmode=prefer"


  #==============================================================#
  # Global Parameters
  #==============================================================#
  vars:

    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    proxy_env:                        # global proxy env when downloading packages
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
      # http_proxy:  # set your proxy here: e.g http://user:[email protected]
      # https_proxy: # set your proxy here: e.g http://user:[email protected]
      # all_proxy:   # set your proxy here: e.g http://user:[email protected]

    certbot_sign: false               # enable certbot to sign https certificate for infra portal
    certbot_email: [email protected]     # replace your email address to receive expiration notice
    infra_portal:                     # domain names and upstream servers
      home         : { domain: i.pigsty }
      pgadmin      : { domain: adm.pigsty ,endpoint: "${admin_ip}:8885" }
      bytebase     : { domain: ddl.pigsty ,endpoint: "${admin_ip}:8887" ,websocket: true}
      minio        : { domain: m.pigsty ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }

      #website:   # static local website example stub
      #  domain: repo.pigsty              # external domain name for static site
      #  certbot: repo.pigsty             # use certbot to sign https certificate for this static site
      #  path: /www/pigsty                # path to the static site directory

      #supabase:  # dynamic upstream service example stub
      #  domain: supa.pigsty          # external domain name for upstream service
      #  certbot: supa.pigsty         # use certbot to sign https certificate for this upstream server
      #  endpoint: "10.10.10.10:8000" # path to the static site directory
      #  websocket: true              # add websocket support
      #  certbot: supa.pigsty         # certbot cert name, apply with `make cert`

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: true              # overwrite node hostname on multi-node template
    node_tune: oltp                       # node tuning specs: oltp,olap,tiny,crit
    node_etc_hosts:                       # add static domains to all nodes /etc/hosts
      - 10.10.10.10 i.pigsty sss.pigsty
      - 10.10.10.10 adm.pigsty ddl.pigsty repo.pigsty supa.pigsty
    node_repo_modules: local,node,infra,pgsql # use pre-made local repo rather than install from upstream
    node_repo_remove: true                # remove existing node repo for node managed by pigsty
    #node_packages: [openssh-server]      # packages to be installed current nodes with latest version
    #node_timezone: Asia/Hong_Kong        # overwrite node timezone

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 18                      # default postgres version
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    pg_safeguard: false                 # prevent purging running postgres instance?
    pg_packages: [ pgsql-main, pgsql-common ] # pg kernel and common utils
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------------------#
    # BACKUP : https://pigsty.io/docs/pgsql/backup
    #----------------------------------------------#
    # if you want to use minio as backup repo instead of 'local' fs, uncomment this, and configure `pgbackrest_repo`
    # you can also use external object storage as backup repo
    pgbackrest_method: minio          # if you want to use minio as backup repo instead of 'local' fs, uncomment this
    pgbackrest_repo:                  # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
      local:                          # default pgbackrest repo with local posix fs
        path: /pg/backup              # local backup directory, `/pg/backup` by default
        retention_full_type: count    # retention full backups by count
        retention_full: 2             # keep 2, at most 3 full backups when using local fs repo
      minio:                          # optional minio repo for pgbackrest
        type: s3                      # minio is s3-compatible, so s3 is used
        s3_endpoint: sss.pigsty       # minio endpoint domain name, `sss.pigsty` by default
        s3_region: us-east-1          # minio region, us-east-1 by default, useless for minio
        s3_bucket: pgsql              # minio bucket name, `pgsql` by default
        s3_key: pgbackrest            # minio user access key for pgbackrest [CHANGE ACCORDING to minio_users.pgbackrest]
        s3_key_secret: S3User.Backup  # minio user secret key for pgbackrest [CHANGE ACCORDING to minio_users.pgbackrest]
        s3_uri_style: path            # use path style uri for minio rather than host style
        path: /pgbackrest             # minio backup path, default is `/pgbackrest`
        storage_port: 9000            # minio port, 9000 by default
        storage_ca_file: /etc/pki/ca.crt  # minio ca file path, `/etc/pki/ca.crt` by default
        block: y                      # Enable block incremental backup
        bundle: y                     # bundle small files into a single file
        bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
        cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
        retention_full_type: time     # retention full backup by time on minio repo
        retention_full: 14            # keep full backup for the last 14 days
      s3:                             # you can use cloud object storage as backup repo
        type: s3                      # Add your object storage credentials here!
        s3_endpoint: oss-cn-beijing-internal.aliyuncs.com
        s3_region: oss-cn-beijing
        s3_bucket: <your_bucket_name>
        s3_key: <your_access_key>
        s3_key_secret: <your_secret_key>
        s3_uri_style: host
        path: /pgbackrest
        bundle: y                     # bundle small files into a single file
        bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
        cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
        retention_full_type: time     # retention full backup by time on minio repo
        retention_full: 14            # keep full backup for the last 14 days

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

fat 模板是 Pigsty 的 全功能测试配置,专为完整性测试和离线包构建设计。

关键特性

  • 全扩展安装:安装 PostgreSQL 18 的所有分类扩展包
  • 多版本软件源:本地软件源包含 PostgreSQL 14-18 全部五个大版本
  • 完整组件栈:包含 Silo 备份、Docker 应用、VIP 等功能
  • 企业级组件:包含 Kafka、PolarDB、IvorySQL、TigerBeetle 等

软件源内容

分类 说明
PostgreSQL 14-18 五个大版本的内核和全部扩展
扩展分类包 time, gis, rag, fts, olap, feat, lang, type, util, func, admin, stat, sec, fdw, sim, etl
企业组件 kafka-stack、Java 运行时、Sealos、TigerBeetle
数据库内核 PolarDB、IvorySQL

与 rich 的区别

  • fat 包含 PostgreSQL 14-18 全部五个版本,rich 只包含当前默认版本
  • fat 包含额外的企业组件(Kafka、PolarDB、IvorySQL 等)
  • fat 需要更大的磁盘空间和更长的构建时间

适用场景

  • Pigsty 开发测试与功能验证
  • 构建完整的多版本离线软件包
  • 需要测试全部扩展兼容性的场景
  • 企业环境预先缓存所有软件包

注意事项

  • 需要较大磁盘空间(建议 100GB+)用于存储所有软件包
  • 构建本地软件源需要较长时间
  • 部分扩展在 ARM64 架构不可用
  • 默认密码为示例密码,生产环境务必修改

6.5 - infra

仅安装可观测性基础设施,不包含 PostgreSQL 与 etcd 的专用配置模板

infra 配置模板仅部署 Pigsty 的可观测性基础设施组件(VictoriaMetrics/Grafana/VictoriaLogs/Nginx 等),不包含 PostgreSQL 与 etcd。

适用于需要独立监控栈的场景,例如监控外部 PostgreSQL/RDS 实例或其他数据源。


配置概览

  • 配置名称: infra
  • 节点数量: 单节点或多节点
  • 配置说明:仅安装可观测性基础设施,不包含 PostgreSQL 与 etcd
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:meta

启用方式:

./configure -c infra [-i <primary_ip>]
./infra.yml    # 仅执行 infra 剧本

配置内容

源文件地址:pigsty/conf/infra.yml

---
#==============================================================#
# File      :   infra.yml
# Desc      :   Infra Only Config
# Ctime     :   2025-12-16
# Mtime     :   2025-12-30
# Docs      :   https://pigsty.io/docs/conf/infra
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for deploy victoria stack alone
# tutorial: https://pigsty.io/docs/infra
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c infra
#   ./infra.yml

all:
  children:
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }
        #10.10.10.11: { infra_seq: 2 } # you can add more nodes if you want
        #10.10.10.12: { infra_seq: 3 } # don't forget to assign unique infra_seq for each node
      vars:
        docker_enabled: true            # enabled docker with ./docker.yml
        docker_registry_mirrors: ["https://docker.1panel.live","https://docker.1ms.run","https://docker.xuanyuan.me","https://registry-1.docker.io"]
        pg_exporters:     # bin/pgmon-add pg-rds
          20001: { pg_cluster: pg-rds ,pg_seq: 1 ,pg_host: 10.10.10.10 ,pg_exporter_url: 'postgres://postgres:[email protected]:5432/postgres' }

  vars:                                 # global variables
    version: v4.5.0                     # pigsty version string
    admin_ip: 10.10.10.10               # admin node ip address
    region: default                     # upstream mirror region: default,china,europe
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit
    infra_portal:                       # infra services exposed via portal
      home : { domain: i.pigsty }       # default domain name
    repo_enabled: false                 # online installation without repo
    node_repo_modules: node,infra,pgsql # add these repos directly
    #haproxy_enabled: false              # enable haproxy on infra node?
    #vector_enabled: false               # enable vector on infra node?

    # DON't FORGET TO CHANGE DEFAULT PASSWORDS!
    grafana_admin_password: pigsty
    haproxy_admin_password: pigsty
...

配置解读

infra 模板是 Pigsty 的 纯监控栈配置,专为独立部署可观测性基础设施设计。

适用场景

  • 监控外部 PostgreSQL 实例(RDS、自建等)
  • 需要独立的监控/告警平台
  • 已有 PostgreSQL 集群,仅需添加监控
  • 作为多集群监控的中央控制台

包含组件

  • VictoriaMetrics:时序数据库,存储监控指标
  • VictoriaLogs:日志聚合系统
  • VictoriaTraces:链路追踪系统
  • Grafana:可视化仪表盘
  • Alertmanager:告警管理
  • Nginx:反向代理和 Web 入口

不包含组件

  • PostgreSQL 数据库集群
  • etcd 分布式协调服务
  • Silo 对象存储

监控外部实例: 配置完成后,可通过 pgsql-monitor.yml 剧本添加外部 PostgreSQL 实例的监控:

pg_exporters:
  20001: { pg_cluster: pg-foo, pg_seq: 1, pg_host: 10.10.10.100 }
  20002: { pg_cluster: pg-bar, pg_seq: 1, pg_host: 10.10.10.101 }

注意事项

  • 此模板不会安装任何数据库
  • 如需完整功能,请使用 metarich 模板
  • 可根据需要添加多个 infra 节点实现高可用

6.6 - vibe

VIBE AI 编程沙箱配置模板,集成 Code-Server、JupyterLab、Claude Code、Codex CLI 与 JuiceFS 的 Web 开发环境

vibe 配置模板提供了一个开箱即用的 AI 编程沙箱,集成了 Code-Server(Web VS Code)、JupyterLab、Claude Code 可观测能力、Codex CLI、JuiceFS 分布式文件系统,以及功能丰富的 PostgreSQL 数据库。


配置概览

  • 配置名称: vibe
  • 节点数量: 单节点
  • 配置说明:VIBE AI 编程沙箱,Code-Server + JupyterLab + Claude Code + Codex CLI + JuiceFS + PostgreSQL
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:meta

启用方式:

./configure -c vibe [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/vibe.yml

---
#==============================================================#
# File      :   vibe.yml
# Desc      :   Pigsty ai vibe coding sandbox
# Ctime     :   2026-01-19
# Mtime     :   2026-06-28
# Docs      :   https://pigsty.io/docs/conf/vibe
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# VIBE CODING SANDBOX
# PostgreSQL with related extensions
# Code-Server, Jupyter, Claude Code, optional Codex CLI
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c vibe
#   ./deploy.yml
#   ./juice.yml     # pgfs: juicefs on pgsql, mount on /fs
#   ./vibe.yml      # code-server, jupyter, claude-code, and codex cli

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }} ,vars: { etcd_cluster: etcd  }}
    pgsql: { hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } } ,vars: { pg_cluster: pgsql }}

    # optional modules
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}
    #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 }

  vars:
    #----------------------------------------------#
    # INFRA: https://pigsty.io/docs/infra
    #----------------------------------------------#
    version: v4.5.0                     # pigsty version string
    admin_ip: 10.10.10.10               # admin node ip address
    region: default                     # upstream mirror region: default,china,europe
    infra_portal:                       # infra services exposed via portal
      home : { domain: i.pigsty }       # default domain name
    dns_enabled: false                  # disable dns service
    #blackbox_enabled: false            # disable blackbox exporter
    #alertmanager_enabled: false        # disable alertmanager
    infra_extra_services:               # home page navigation entries
      - { name: Code Server  ,url: '/code'             ,desc: 'VS Code Server'       ,icon: 'code'     }
      - { name: Jupyter      ,url: '/jupyter'          ,desc: 'Jupyter Notebook'     ,icon: 'jupyter'  }
      - { name: Claude Code  ,url: '/ui/d/claude-code' ,desc: 'Claude Observability' ,icon: 'claude'   }

    #----------------------------------------------#
    # NODE: https://pigsty.io/docs/node
    #----------------------------------------------#
    nodename_overwrite: false           # do not overwrite node hostname on single node mode
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit
    node_dns_method: none               # do not setup dns
    node_repo_modules: node,infra,pgsql # add these repos directly to the singleton node
    node_packages: [ openssh-server, juicefs, restic, rclone, uv, opencode, golang, asciinema, tmux ]
    docker_enabled: true                # enable docker service
    node_firewall_mode: zone            # default: trust intranet, expose selected public ports
    node_firewall_public_port: [22, 80, 443, 5432]    # expose 5432 for remote access, remove in production!
    #docker_registry_mirrors: ["https://docker.1panel.live","https://docker.1ms.run","https://docker.xuanyuan.me","https://registry-1.docker.io"]

    #----------------------------------------------#
    # PGSQL: https://pigsty.io/docs/pgsql
    #----------------------------------------------#
    pg_version: 18                      # Default PostgreSQL Major Version is 18
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    pg_packages: [ pgsql-main, patroni, pgbackrest, pg-exporter, pgbackrest-exporter ]
    pg_extensions: [ pg18-main ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
    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  }
    pg_databases:
      - { name: meta, baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [ postgis, timescaledb, vector, age ]}
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain, pg_wait_sampling'
    pg_hba_rules:
      - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
      # WARNING: devbox only. Remove world access in production.
      - { user: all ,db: all ,addr: world ,auth: pwd ,title: 'everyone world access with password'    ,order: 900 }
    pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ] # make a full backup every 1am
    patroni_mode: remove                # remove patroni after deployment
    pgbouncer_enabled: false            # disable pgbouncer pool
    pgbouncer_exporter_enabled: false   # disable pgbouncer_exporter on pgsql hosts?
    pgbackrest_exporter_enabled: false  # disable pgbackrest_exporter
    pg_default_services: []             # do not provision pg services
    #pg_reload: false                   # do not reload patroni/service

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty

    #----------------------------------------------#
    # OPTIONAL VIBE COMPONENTS
    #----------------------------------------------#
    code_enabled: true                # install & enable code-server via vibe role
    code_password: DBUser.Meta
    jupyter_enabled: true             # enable jupyter (disabled by default, enable for vibe sandbox)
    jupyter_password: DBUser.Meta
    juice_instances:
      jfs:
        path  : /fs
        meta  : postgres://dbuser_meta:[email protected]:5432/meta
        data  : --storage postgres --bucket 10.10.10.10:5432/meta --access-key dbuser_meta --secret-key DBUser.Meta
        port  : 9567

    # Claude Code is the default coding agent. Node.js is installed on demand when agents are enabled.
    nodejs_enabled: true              # standalone nodejs runtime
    npm_packages: []                  # extra global npm packages
    codex_enabled: true
    claude_enabled: true
    #claude_env:                      # use 3rd party Anthropic-compatible API service
    #  ANTHROPIC_BASE_URL: https://open.bigmodel.cn/api/anthropic
    #  ANTHROPIC_API_URL: https://open.bigmodel.cn/api/anthropic
    #  ANTHROPIC_AUTH_TOKEN: your_api_service_token
    #  ANTHROPIC_DEFAULT_OPUS_MODEL: "glm-5.2[1m]"
    #  ANTHROPIC_DEFAULT_SONNET_MODEL: "glm-5.2[1m]"
    #  ANTHROPIC_DEFAULT_HAIKU_MODEL: "glm-4.7"
    #  CLAUDE_CODE_AUTO_COMPACT_WINDOW: "1000000"

...

配置解读

vibe 模板是一个面向 AI 时代的 Web 编程沙箱,让您可以在浏览器中完成开发、数据分析、AI 应用构建等任务。

核心组件

组件 说明 访问方式
Code-Server VS Code 的 Web 版本,功能完整的代码编辑器 http://<ip>/code
JupyterLab 交互式数据科学笔记本,支持 Python/SQL http://<ip>/jupyter
Claude Code AI 编程助手运行环境与可观测性入口(可通过 claude_env 定制) 终端 / 仪表盘
Codex CLI OpenAI 代理编程 CLI;VIBE 只负责安装,不托管配置 终端
JuiceFS 基于 PostgreSQL 的分布式文件系统 挂载点 /fs
PostgreSQL 18 功能丰富的数据库,安装 pg18-main + 全类别扩展包组 5432 端口

模板显式安装的节点工具node_packages):

  • openssh-server, juicefs, restic, rclone
  • uv, opencode, golang
  • asciinema, tmux

PostgreSQL 扩展

此模板通过分类包组安装 PostgreSQL 18 的完整扩展集合:

pg18-main, pg18-time, pg18-gis, pg18-rag, pg18-fts, pg18-olap,
pg18-feat, pg18-lang, pg18-type, pg18-util, pg18-func, pg18-admin,
pg18-stat, pg18-sec, pg18-fdw, pg18-sim, pg18-etl

meta 业务库默认创建扩展为 postgistimescaledbvector,其余扩展可按需启用。


VIBE 模块组件

提供 AI 编程沙箱能力;vibe.yml 显式开启 Code-Server 与 Jupyter,默认安装 Claude Code 与 Codex CLI。

Code-Server:浏览器中的 VS Code

  • 完整的 VS Code 功能,支持扩展安装
  • 通过 Nginx 反向代理提供 HTTPS 访问
  • 支持 Open VSX 和 Microsoft 扩展商店
  • 模板显式参数:code_enabled, code_password
  • 其余可选参数:code_port, code_data, code_gallery

JupyterLab:交互式计算环境

  • 支持 Python/SQL/Markdown 笔记本
  • 预配置 Python venv 数据科学库
  • 通过 Nginx 反向代理提供 HTTPS 访问
  • 模板显式参数:jupyter_enabled, jupyter_password
  • 其余可选参数:jupyter_port, jupyter_data, jupyter_venv

Claude Code:AI 编程助手

  • 使用模块默认行为完成 Claude 运行环境配置
  • 可通过 claude_env 覆盖模型端点与 API 密钥
  • 提供 claude-code 仪表盘监控使用情况

Codex CLI:AI 编程助手

  • codex_enabled 控制,默认启用
  • VIBE 仅安装 @openai/codex,不写入 Codex 配置,也不接入 Claude Code 仪表盘

JuiceFS 文件系统

此模板使用 JuiceFS 提供分布式文件系统能力,特别之处在于:元数据和数据都存储在 PostgreSQL 中

架构特点

  • 元数据引擎:使用 PostgreSQL 存储文件系统元数据
  • 数据存储:使用 PostgreSQL 大对象(Large Object)存储文件数据
  • 挂载点:默认挂载到 /fs 目录(由 juice_instances.jfs.path 控制)
  • 监控端口9567 提供 Prometheus 指标

使用场景

  • 代码项目的持久化存储
  • Jupyter Notebook 的工作目录
  • AI 模型和数据集的存储
  • 多实例间的文件共享(扩展到多节点时)

配置示例

juice_instances:
  jfs:
    path  : /fs
    meta  : postgres://dbuser_meta:[email protected]:5432/meta
    data  : --storage postgres --bucket 10.10.10.10:5432/meta --access-key dbuser_meta --secret-key DBUser.Meta
    port  : 9567

部署步骤

# 1. 下载 Pigsty
curl -fsSL https://repo.pigsty.cc/get | bash; cd ~/pigsty

# 2. 使用 vibe 配置模板
./configure -c vibe

# 3. 修改密码(重要!)
vi pigsty.yml
# 修改 code_password、jupyter_password、数据库与基础设施默认密码

# 4. 部署基础设施和 PostgreSQL
./deploy.yml

# 5. 可选:部署 JuiceFS 文件系统
./juice.yml -l 10.10.10.10

# 6. 部署 VIBE 模块(Code-Server、JupyterLab、Claude Code、Codex CLI)
./vibe.yml -l 10.10.10.10

访问方式

部署完成后,通过浏览器访问:

# Code-Server(VS Code Web)
https://<domain>/code/
# 使用已轮换的 code_password

# JupyterLab
https://<domain>/jupyter/
# 使用已轮换的 jupyter_password Token

# Claude Code 仪表盘
https://<domain>/ui/d/claude-code
# 使用已轮换的 Grafana 管理凭据

# PostgreSQL
psql 'host=<ip> port=5432 dbname=meta user=dbuser_meta sslmode=require'

适用场景

  • AI 应用开发:构建 RAG、Agent、LLM 应用
  • 数据科学:使用 JupyterLab 进行数据分析和可视化
  • 远程开发:在云服务器上搭建 Web IDE 环境
  • 教学演示:提供一致的开发环境供学员使用
  • 快速原型:快速验证想法,无需配置本地环境
  • Claude Code 可观测性:监控 AI 编程助手的使用情况

注意事项

  • 必须修改密码code_passwordjupyter_password 默认值仅供测试
  • Jupyter 安全边界:模板监听 0.0.0.0:8888、允许任意 Origin、关闭 XSRF 校验,默认只依靠 Token;必须限制端口与门户来源,不得直接暴露公网
  • 网络安全:此模板默认开放 5432node_firewall_public_port)且包含 addr: world HBA 规则,生产环境请删除这些公网入口,并在需要时为门户增加 Basic Auth
  • 资源需求:建议至少 2 核 4GB 内存,SSD 磁盘
  • 精简架构:此模板禁用了 Patroni、PgBouncer 等高可用组件,适合单节点开发环境
  • Claude API:使用 Claude Code 需要配置 claude_env 中的 API 密钥

6.7 - docker

Pigsty Docker 容器化单机模板,适用于在容器内快速启动与体验 Pigsty。

docker 配置模板用于在 Docker 容器内运行 Pigsty,提供最小可用的单节点基础设施与 PostgreSQL 能力。


配置概览

  • 配置名称: docker
  • 节点数量: 单节点(容器环境)
  • 配置说明:容器内快速体验模板,使用 127.0.0.1 与精简系统能力,适配 Docker 场景。
  • 适用系统:容器镜像内置环境(建议配合官方 Pigsty Docker 镜像)
  • 适用架构:x86_64, aarch64
  • 相关配置:metavibe

启用方式:

./configure -c docker -i 127.0.0.1 -g

配置内容

源文件地址:pigsty/conf/docker.yml

---
#==============================================================#
# File      :   docker.yml
# Desc      :   Pigsty docker coding environment
# Ctime     :   2026-01-19
# Mtime     :   2026-01-27
# Docs      :   https://pigsty.io/docs/conf/docker
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# DOCKER CONFIG, use 127.0.0.1 inside docker
# mount the /data volume when running docker container
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c docker -i 127.0.0.1 -g
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }} ,vars: { etcd_cluster: etcd  }}
    pgsql: { hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary  }} ,vars: { pg_cluster: pgsql }}
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

  vars:

    #----------------------------------------------#
    # Infra
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10               # admin node ip address
    region: china                     # upstream mirror region: default|china|europe
    dns_enabled: false                # disable dnsmasq service on single node
    infra_portal:
      home : { domain: i.pigsty }
    proxy_env:                        # global proxy env when downloading packages
      no_proxy: "localhost,10.10.10.10,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
      # http_proxy:  # set your proxy here: e.g http://user:[email protected]
      # https_proxy: # set your proxy here: e.g http://user:[email protected]
      # all_proxy:   # set your proxy here: e.g http://user:[email protected]

    #----------------------------------------------#
    # Node
    #----------------------------------------------#
    nodename: pigsty
    node_id_from_pg: false
    node_tune: oltp
    node_write_etc_hosts: false
    node_dns_method: none
    node_ntp_enabled: false
    node_kernel_modules: []
    node_repo_remove: true
    node_repo_modules: 'node,infra,pgsql'


    #----------------------------------------------#
    # PGSQL: https://pigsty.io/docs/pgsql
    #----------------------------------------------#
    pg_version: 18                      # Default PostgreSQL Major Version is 18
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    pg_extensions: [ pg18-main ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
    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  }
    pg_databases:
      - { name: meta, baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [ postgis, timescaledb, vector ]}
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain, pg_wait_sampling'
    pg_hba_rules:
      - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
      - { user: all ,db: all ,addr: world ,auth: pwd ,title: 'everyone world access with password'    ,order: 900 }
    pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ] # make a full backup every 1am
    #pg_reload: false                   # do not reload patroni/service

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root

    #----------------------------------------------#
    # OPTIONAL
    #----------------------------------------------#
    #code_password: DBUser.Meta
    #jupyter_password: DBUser.Meta
    #juice_instances:  # dict of juicefs filesystems to deploy
    #  jfs:
    #    path  : /fs
    #    meta  : postgres://dbuser_meta:[email protected]:5432/meta
    #    data  : --storage postgres --bucket 10.10.10.10:5432/meta --access-key dbuser_meta --secret-key DBUser.Meta
    #    port  : 9567
    #node_packages: [ openssh-server, tmux, juicefs, restic, rclone, uv, code-server ]
    #npm_packages: [ '@anthropic-ai/claude-code' , 'happy-coder' ]
    #claude_env:
    #  ANTHROPIC_BASE_URL: https://open.bigmodel.cn/api/anthropic
    #  ANTHROPIC_API_URL: https://open.bigmodel.cn/api/anthropic
    #  ANTHROPIC_AUTH_TOKEN: your_api_service_token
    #  ANTHROPIC_MODEL: glm-4.7
    #  ANTHROPIC_SMALL_FAST_MODEL: glm-4.5-air
...

配置解读

docker 模板主要面向容器内开发与验证,默认配置特征如下:

  • 关闭本地仓库构建(repo_enabled: false),避免容器内额外仓库构建成本。
  • 精简节点行为:关闭 NTP、内核模块加载与 hosts 覆写(node_ntp_enabled: falsenode_kernel_modules: []node_write_etc_hosts: false)。
  • 默认 PostgreSQL 18,预置较完整扩展集合(pg18-* 扩展包组)。
  • 允许内网与公网密码访问(pg_hba_rules 包含 intraworld),便于演示与测试。
  • 预留可选能力(注释项):Code-Server、Jupyter、JuiceFS、Claude CLI 相关参数可按需启用。

注意事项:

  • 这是开发/演示导向模板,生产环境请收紧 pg_hba_rules 与密码策略。
  • 容器运行时建议挂载 /data,以持久化 PostgreSQL 与组件数据。

6.8 - pgsql

原生 PostgreSQL 内核,稳定支持 PostgreSQL 14 到 18,并提供 PG19 Beta 试用

pgsql 配置模板使用原生 PostgreSQL 内核,是 Pigsty 的默认数据库内核,稳定支持 PostgreSQL 14 到 18。当前 configure 也接受版本 19,但 PG19 仍是 Beta,建议使用专用 pg19 模板试用。


配置概览

  • 配置名称: pgsql
  • 节点数量: 单节点
  • 配置说明:原生 PostgreSQL 内核配置模板
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:meta

启用方式:

./configure -c pgsql [-i <primary_ip>]

如需指定非默认 PostgreSQL 版本(如 16):

./configure -c pgsql -v 16

配置内容

源文件地址:pigsty/conf/pgsql.yml

---
#==============================================================#
# File      :   pgsql.yml
# Desc      :   1-node PostgreSQL Config template
# Ctime     :   2025-02-23
# Mtime     :   2025-12-28
# Docs      :   https://pigsty.io/docs/conf/pgsql
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for basical PostgreSQL Kernel.
# Nothing special, just a basic setup with one node.
# tutorial: https://pigsty.io/docs/pgsql/kernel/postgres
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c pgsql
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }} ,vars: { etcd_cluster: etcd  }}
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

    #----------------------------------------------#
    # PostgreSQL Cluster
    #----------------------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-meta
        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  }
        pg_databases:
          - { name: meta, baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [ postgis, timescaledb, vector ]}
        pg_extensions: [ postgis, timescaledb, pgvector, pg_wait_sampling ]
        pg_libs: 'timescaledb, pg_stat_statements, auto_explain, pg_wait_sampling'
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

  vars:
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false             # do not overwrite node hostname on single node mode
    node_repo_modules: node,infra,pgsql # add these repos directly to the singleton node
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 18                      # Default PostgreSQL Major Version is 18
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    pg_packages: [ pgsql-main, pgsql-common ]   # pg kernel and common utils
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
    #repo_extra_packages: [ pg18-main ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

pgsql 模板是 Pigsty 的 标准内核配置,使用社区原生 PostgreSQL。

版本支持

  • PostgreSQL 18(默认)
  • PostgreSQL 17、16、15、14
  • PostgreSQL 19 Beta(试用;使用 ./configure -c pg19

适用场景

  • 需要使用最新 PostgreSQL 特性
  • 需要最广泛的扩展支持
  • 标准生产环境部署
  • meta 模板功能相同,显式声明使用原生内核

与 meta 的区别

  • pgsql 模板显式声明使用原生 PostgreSQL 内核
  • 适合需要明确区分不同内核类型的场景

6.9 - pg19

PostgreSQL 19 Beta 单节点试用模板,启用 PGDG Beta 仓库并保留默认备份能力

pg19 是 PostgreSQL 19 Beta 的单节点试用模板。它基于 meta 拓扑,但启用 beta 软件仓库,并将本地仓库的额外缓存范围缩小到 PGSQL 核心包,不预装扩展。


配置概览

  • 配置名称:pg19
  • 节点数量:单节点
  • PostgreSQL 版本:19 Beta
  • 适用场景:新版本功能验证、兼容性测试
  • 相关配置:metapgsql

启用方式:

./configure -c pg19 [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/pg19.yml

---
#==============================================================#
# File      :   pg19.yml
# Desc      :   Pigsty 1-node PostgreSQL 19 beta config
# Ctime     :   2026-06-11
# Mtime     :   2026-06-11
# Docs      :   https://pigsty.io/docs/conf/pg19
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the PostgreSQL 19 beta variant of meta.yml.
# It enables the PGDG beta repository and installs a minimal PG19 runtime.
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c pg19
#   ./deploy.yml

all:

  #==============================================================#
  # Clusters, Nodes, and Modules
  #==============================================================#
  children:

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql
    #----------------------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
        #x.xx.xx.xx: { pg_seq: 2, pg_role: replica }
        #x.xx.xx.xy: { pg_seq: 3, pg_role: offline }
      vars:
        pg_cluster: pg-meta

        # PG19 is beta; extension packages are intentionally not installed here.
        pg_extensions: []

        # define business users/roles : https://pigsty.io/docs/pgsql/config/user
        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  }

        # define business databases : https://pigsty.io/docs/pgsql/config/db
        pg_databases:
          - { name: meta, baseline: cmdb.sql, comment: "pigsty meta database", schemas: [pigsty] }

        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }

        pg_crontab:     # make a full backup every day at 1am
          - '00 01 * * * /pg/bin/pg-backup full'

        # define (OPTIONAL) L2 VIP that bind to primary
        #pg_vip_enabled: true
        #pg_vip_address: 10.10.10.2/24


    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra
    #----------------------------------------------#
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }
      vars:
        repo_enabled: false   # disable local repo in 1-node mode
        #repo_extra_packages: [ pgsql-core ]  # if local repo is enabled, mirror PG19 beta core packages

    #----------------------------------------------#
    # ETCD : https://pigsty.io/docs/etcd
    #----------------------------------------------#
    etcd:
      hosts:
        10.10.10.10: { etcd_seq: 1 }
      vars:
        etcd_cluster: etcd
        etcd_safeguard: false

    #----------------------------------------------#
    # MINIO : https://pigsty.io/docs/minio
    #----------------------------------------------#
    #minio:
    #  hosts:
    #    10.10.10.10: { minio_seq: 1 }
    #  vars:
    #    minio_cluster: minio
    #    minio_users:
    #      - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
    #      - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
    #      - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }

    #----------------------------------------------#
    # DOCKER : https://pigsty.io/docs/docker
    # APP    : https://pigsty.io/docs/app
    #----------------------------------------------#
    app:
      hosts: { 10.10.10.10: {} }
      vars:
        docker_enabled: true
        #docker_registry_mirrors: ["https://docker.1panel.live","https://docker.1ms.run","https://docker.xuanyuan.me","https://registry-1.docker.io"]
        app: pgadmin
        apps:
          pgadmin:
            conf:
              PGADMIN_DEFAULT_EMAIL: [email protected]
              PGADMIN_DEFAULT_PASSWORD: pigsty


  #==============================================================#
  # Global Parameters
  #==============================================================#
  vars:

    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    proxy_env:
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
      # http_proxy:  # set your proxy here: e.g http://user:[email protected]
      # https_proxy: # set your proxy here: e.g http://user:[email protected]
      # all_proxy:   # set your proxy here: e.g http://user:[email protected]
    infra_portal:
      home : { domain: i.pigsty }
      pgadmin : { domain: adm.pigsty ,endpoint: "${admin_ip}:8885" }
      #minio  : { domain: m.pigsty ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false             # do not overwrite node hostname on single node mode
    node_tune: oltp                       # node tuning specs: oltp,olap,tiny,crit
    node_etc_hosts: [ '${admin_ip} i.pigsty sss.pigsty' ]
    node_repo_modules: 'node,infra,pgsql,beta' # PG19 beta packages come from PGDG testing repo
    #node_repo_modules: local             # use this if you want to build & use local repo
    node_repo_remove: true                # remove existing node repo for node managed by pigsty
    node_firewall_public_port: [22, 80, 443, 5432]

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 19                      # PostgreSQL 19 beta
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    pg_safeguard: false                 # prevent purging running postgres instance?
    pg_extensions: []                   # do not install extension packages during PG19 beta trial
    repo_modules: node,infra,pgsql,beta # add PGDG testing repo when building a local repo
    repo_extra_packages: [ pgsql-core ] # only mirror PG19 beta core packages

    #----------------------------------------------#
    # BACKUP : https://pigsty.io/docs/pgsql/backup
    #----------------------------------------------#
    pgbackrest_enabled: true            # pgBackRest 2.59 supports PostgreSQL 19 beta2
    pgbackrest_exporter_enabled: true   # expose pgBackRest metrics to the monitoring system
    #pgbackrest_method: minio
    #pgbackrest_repo:
    #  minio:
    #    type: s3
    #    s3_endpoint: sss.pigsty
    #    s3_region: us-east-1
    #    s3_bucket: pgsql
    #    s3_key: pgbackrest
    #    s3_key_secret: S3User.Backup
    #    s3_uri_style: path
    #    path: /pgbackrest
    #    storage_port: 9000
    #    storage_ca_file: /etc/pki/ca.crt
    #    bundle: y
    #    bundle_limit: 20MiB
    #    bundle_size: 128MiB
    #    cipher_type: aes-256-cbc
    #    cipher_pass: pgBackRest
    #    retention_full_type: time
    #    retention_full: 14

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

模板的关键限制与默认值:

  • node_repo_modules: node,infra,pgsql,beta,从 PGDG Beta 仓库获取 PG19 软件包
  • repo_extra_packages: [pgsql-core],本地仓库只额外缓存 PGSQL 核心包;实例仍使用角色默认的 pgsql-main pgsql-common 安装集合
  • pg_extensions: [],不安装扩展包
  • pgbackrest_enabled: truepgbackrest_exporter_enabled: truepg-meta 保留每天 01:00 的全量备份任务
  • 保留 INFRA、ETCD、PGSQL 与可选 pgAdmin 的单节点体验

这是 Beta 试用配置,不是生产模板。不要通过 -v 19 把普通模板直接当作 PG19 生产配置;扩展兼容性、备份恢复和升级流程仍需分别验证。

6.10 - mssql

固定使用 PostgreSQL 17 兼容 Babelfish 内核,提供 SQL Server 协议与 T-SQL 兼容能力

mssql 配置模板使用 PostgreSQL 17 兼容的 Babelfish 内核替代原生 PostgreSQL,提供 Microsoft SQL Server 线缆协议(TDS)与 T-SQL 语法兼容能力。当前模板固定 pg_version: 17configure 不会用 -v 覆盖此固定内核版本。

从 Pigsty v4.2 以来,Babelfish 由 Pigsty 直接构建,不再使用 WiltonDB 仓库,可在所有 支持的 Linux 平台 上使用。

完整教程请参考:Babelfish (MSSQL) 内核使用说明


配置概览

  • 配置名称: mssql
  • 节点数量: 单节点
  • 配置说明:Babelfish(PG17)配置模板,提供 SQL Server 协议兼容
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:meta

启用方式:

./configure -c mssql [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/mssql.yml

---
#==============================================================#
# File      :   mssql.yml
# Desc      :   Babelfish (MSSQL Wire-Compatible) template
# Ctime     :   2020-08-01
# Mtime     :   2026-07-08
# Docs      :   https://pigsty.io/docs/conf/mssql
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for Babelfish Kernel made by Pigsty
# Which is a PostgreSQL 17/18 fork with SQL Server Compatibility
# tutorial: https://pigsty.io/docs/pgsql/kernel/babelfish
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c mssql [-v 17/18]
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }} ,vars: { etcd_cluster: etcd  }}
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

    #----------------------------------------------#
    # Babelfish Database Cluster
    #----------------------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-meta
        pg_users:
          - {name: dbuser_mssql ,password: DBUser.MSSQL ,superuser: true, pgbouncer: true ,roles: [dbrole_admin], comment: superuser & owner for babelfish  }
        pg_databases:
          - name: mssql
            baseline: mssql.sql
            extensions: [uuid-ossp, babelfishpg_common, babelfishpg_tsql, babelfishpg_tds, babelfishpg_money ]
            owner: dbuser_mssql
            parameters: { 'babelfishpg_tsql.migration_mode' : 'multi-db' }
            comment: babelfish cluster, a MSSQL compatible pg cluster
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # Babelfish Ad Hoc Settings
        pg_mode: mssql                     # Microsoft SQL Server Compatible Mode
        pg_version: 17
        pg_packages: [ babelfish, pgsql-common, sqlcmd ]
        pg_libs: 'babelfishpg_tds, pg_stat_statements, auto_explain' # preload Babelfish TDS listener
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: dbuser_mssql ,db: mssql ,addr: intra ,auth: md5 ,title: 'allow mssql dbsu intranet access'      ,order: 525 } # <--- use md5 auth method for mssql user
          - { user: all          ,db: all   ,addr: intra ,auth: md5 ,title: 'everyone intranet access with md5 pwd' ,order: 800 }
        pg_default_services: # route primary & replica service to mssql port 1433
          - { name: primary ,port: 5433 ,dest: 1433  ,check: /primary   ,selector: "[]" }
          - { name: replica ,port: 5434 ,dest: 1433  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
          - { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
          - { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]" }

  vars:
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false                 # do not overwrite node hostname on single node mode
    node_repo_modules: node,infra,pgsql       # babelfish kernel is in the pgsql repo
    node_tune: oltp                           # node tuning specs: oltp,olap,tiny,crit

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 17                            # Babelfish kernel is compatible with postgres 17
    pg_conf: oltp.yml                         # pgsql tuning specs: {oltp,olap,tiny,crit}.yml

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

mssql 模板让您可以使用 SQL Server Management Studio (SSMS) 或其他 SQL Server 客户端工具连接 PostgreSQL(Babelfish 协议层)。

关键特性

  • 使用 TDS 协议(端口 1433),兼容 SQL Server 客户端
  • 支持 T-SQL 语法,迁移成本低
  • 保留 PostgreSQL 的 ACID 特性和扩展生态(当前模板底层为 PG17)
  • 支持 multi-dbsingle-db 两种迁移模式
  • 默认包组为 babelfish + pgsql-common + sqlcmd
  • 默认创建扩展:uuid-osspbabelfishpg_commonbabelfishpg_tsqlbabelfishpg_tdsbabelfishpg_money
  • v4.2.0 起支持主流平台全覆盖(EL8/9/10、Debian 12/13、Ubuntu 22/24/26;x86_64 / aarch64

连接方式

# 使用 sqlcmd 命令行工具
sqlcmd -S 10.10.10.10,1433 -U dbuser_mssql -P DBUser.MSSQL -d mssql

# 使用 SSMS 或 Azure Data Studio
# Server: 10.10.10.10,1433
# Authentication: SQL Server Authentication
# Login: dbuser_mssql
# Password: DBUser.MSSQL

适用场景

  • 从 SQL Server 迁移到 PostgreSQL
  • 需要同时支持 SQL Server 和 PostgreSQL 客户端的应用
  • 希望利用 PostgreSQL 生态同时保持 T-SQL 兼容性

注意事项

  • 当前 mssql 模板固定使用 PostgreSQL 17 兼容内核;不要依赖 -v 切换该模板的大版本
  • 默认迁移模式为 multi-dbbabelfishpg_tsql.migration_mode),可按需改为 single-db
  • 部分 T-SQL 语法可能存在兼容性差异,请参考 Babelfish 兼容性文档
  • 需要使用 md5 认证方式(而非 scram-sha-256

6.11 - polar

PolarDB for PostgreSQL 内核,提供 Aurora 风格的存算分离能力

polar 配置模板使用阿里云 PolarDB for PostgreSQL 数据库内核替代原生 PostgreSQL,提供"云原生" Aurora 风格的存算分离能力。

完整教程请参考:PolarDB for PostgreSQL (POLAR) 内核使用说明;所有内核分支的差异与版本口径见 PGSQL 内核总览


配置概览

  • 配置名称: polar
  • 节点数量: 单节点
  • 配置说明:使用 PolarDB for PostgreSQL 内核
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:meta

启用方式:

./configure -c polar [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/polar.yml

---
#==============================================================#
# File      :   polar.yml
# Desc      :   Pigsty 1-node PolarDB Kernel Config Template
# Ctime     :   2020-08-05
# Mtime     :   2026-07-08
# Docs      :   https://pigsty.io/docs/conf/polar
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for PolarDB PG Kernel,
# Which is a PostgreSQL 17 fork with RAC flavor features
# tutorial: https://pigsty.io/docs/pgsql/kernel/polardb
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c polar
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }} ,vars: { etcd_cluster: etcd  }}
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

    #----------------------------------------------#
    # PolarDB Database Cluster
    #----------------------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-meta
        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]}
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # PolarDB Ad Hoc Settings
        pg_version: 17                            # PolarDB PG is based on PG 17
        pg_mode: polar                            # PolarDB PG Compatible mode
        pg_packages: [ polardb, pgsql-common ]    # Replace PG kernel with PolarDB kernel
        pg_exporter_exclude_database: 'template0,template1,postgres,polardb_admin'
        pg_default_roles:                         # PolarDB require replicator as superuser
          - { 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   ,superuser: true  ,replication: true ,roles: [pg_monitor, dbrole_readonly] ,comment: system replicator } # <- superuser is required for replication
          - { 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 }

  vars:                               # global variables
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false           # do not overwrite node hostname on single node mode
    node_repo_modules: node,infra,pgsql # add these repos directly to the singleton node
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 17                      # PolarDB is compatible with PG 17
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root

...

配置解读

polar 模板使用阿里云开源的 PolarDB for PostgreSQL 内核,提供云原生数据库能力。

关键特性

  • 存算分离架构,计算节点和存储节点可独立扩展
  • 支持一写多读,读副本秒级扩展
  • 兼容 PostgreSQL 生态,保持 SQL 兼容性
  • 支持共享存储场景,适合云环境部署
  • 默认 PolarDB 内核路径为 /usr/polar-17
  • 可用扩展以 PolarDB 17 内核为准,常用扩展可参考 pgauditpg_partmanpg_profilepg_repackpg_stat_kcachepg_cronpg_hint_plan

适用场景

  • 需要存算分离架构的云原生场景
  • 读多写少的业务负载
  • 需要快速扩展读副本的场景
  • 评估 PolarDB 特性的测试环境

注意事项

  • PolarDB 当前基于 PostgreSQL 17
  • 复制用户需要超级用户权限(与原生 PostgreSQL 不同)
  • 部分 PostgreSQL 扩展可能存在兼容性问题
  • 当前模板已提供 x86_64aarch64 软件包支持

6.12 - ivory

IvorySQL 内核,提供 Oracle 语法与 PL/SQL 兼容能力

ivory 配置模板使用瀚高的 IvorySQL 数据库内核替代原生 PostgreSQL,提供 Oracle 语法与 PL/SQL 兼容能力。

完整教程请参考:IvorySQL (Oracle兼容) 内核使用说明


配置概览

  • 配置名称: ivory
  • 节点数量: 单节点
  • 配置说明:使用 IvorySQL Oracle 兼容内核
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:meta

启用方式:

./configure -c ivory [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/ivory.yml

---
#==============================================================#
# File      :   ivory.yml
# Desc      :   IvorySQL 5 (Oracle Compatible) template
# Ctime     :   2024-08-05
# Mtime     :   2026-07-08
# Docs      :   https://pigsty.io/docs/conf/ivory
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for IvorySQL 5 Kernel,
# Which is a PostgreSQL 18 fork with Oracle Compatibility
# tutorial: https://pigsty.io/docs/pgsql/kernel/ivorysql
# Oracle compatible port (PGSQL Wire) is 1521
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c ivory
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }} ,vars: { etcd_cluster: etcd  }}
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

    #----------------------------------------------#
    # IvorySQL Database Cluster
    #----------------------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-meta
        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]}
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # IvorySQL Ad Hoc Settings
        pg_mode: ivory                                                 # Use IvorySQL Oracle Compatible Mode
        pg_packages: [ ivorysql, pgsql-common ]                        # install IvorySQL instead of postgresql kernel
        pg_libs: 'liboracle_parser, pg_stat_statements, auto_explain'  # pre-load oracle parser

  vars:                               # global variables
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false           # do not overwrite node hostname on single node mode
    node_repo_modules: node,infra,pgsql # add these repos directly to the singleton node
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 18                      # IvorySQL kernel is compatible with postgres 18
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

ivory 模板使用瀚高开源的 IvorySQL 内核,提供 Oracle 数据库兼容能力。

关键特性

  • 支持 Oracle PL/SQL 语法
  • 兼容 Oracle 数据类型(NUMBER、VARCHAR2 等)
  • 支持 Oracle 风格的包(Package)
  • 保留 PostgreSQL 的所有标准功能

适用场景

  • 从 Oracle 迁移到 PostgreSQL
  • 需要同时支持 Oracle 和 PostgreSQL 语法的应用
  • 希望利用 PostgreSQL 生态同时保持 PL/SQL 兼容性
  • 评估 IvorySQL 特性的测试环境

注意事项

  • IvorySQL 5 基于 PostgreSQL 18
  • 使用 liboracle_parser 需要加载到 shared_preload_libraries
  • pgbackrest 在 Oracle 兼容模式下可能存在校验问题,PITR 能力受限
  • 当前软件包矩阵覆盖 EL8/9/10、Debian 12/13、Ubuntu 22/24/26 与双架构;

6.13 - agens

AgensGraph 内核模板,提供属性图模型与 Cypher 查询能力

agens 配置模板使用 AgensGraph 数据库内核替代原生 PostgreSQL,提供属性图模型与 Cypher 查询能力。

完整教程请参考:AgensGraph 内核使用说明


配置概览

  • 配置名称: agens
  • 节点数量: 单节点
  • 配置说明:AgensGraph(PG17)图数据库内核配置
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:metapgsql

启用方式:

./configure -c agens [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/agens.yml

---
#==============================================================#
# File      :   agens.yml
# Desc      :   1-node AgensGraph (Graph DB) template
# Ctime     :   2026-02-26
# Mtime     :   2026-07-06
# Docs      :   https://pigsty.io/docs/conf/agens
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for AgensGraph Kernel,
# Which is a PostgreSQL 17 fork with graph capabilities.
# tutorial: https://pigsty.io/docs/pgsql/kernel/agensgraph
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c agens
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }} ,vars: { etcd_cluster: etcd  }}
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

    #----------------------------------------------#
    # AgensGraph Database Cluster
    #----------------------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-meta
        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]}
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # AgensGraph Ad Hoc Settings
        pg_mode: agens                                   # AgensGraph compatible mode
        pg_packages: [ agensgraph, pgsql-common ]        # install AgensGraph kernel package + common utils

  vars:
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false           # do not overwrite node hostname on single node mode
    node_repo_modules: node,infra,pgsql # add these repos directly to the singleton node
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 17                      # AgensGraph kernel is compatible with postgres 17
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

agens 模板在 pg-meta 集群中启用 pg_mode: agens,并使用 agensgraph 内核包替换标准 PostgreSQL 内核。

关键特性

  • 属性图模型能力(Vertex / Edge)
  • 支持 Cypher 查询语法,可与 SQL 混合使用
  • 兼容 PostgreSQL 生态与常规运维方式
  • 默认基于 PostgreSQL 17 兼容内核

适用场景

  • 图关系分析与路径查询
  • 社交关系、风控关联、知识图谱等图数据场景
  • 需要在 PostgreSQL 体系中引入图查询能力

注意事项

  • AgensGraph 当前模板固定使用 pg_version: 17
  • 默认模板为单节点快速启用,生产场景建议按需扩展高可用拓扑
  • 图模型与 Cypher 语义请结合 AgensGraph 官方文档进行设计

6.14 - pgedge

pgEdge 内核模板,提供面向边缘场景的多主分布式 PostgreSQL 能力

pgedge 配置模板使用 pgEdge 数据库内核替代原生 PostgreSQL,提供面向边缘场景的分布式与多主复制能力。

完整教程请参考:pgEdge 内核使用说明;所有内核分支的差异与版本口径见 PGSQL 内核总览


配置概览

  • 配置名称: pgedge
  • 节点数量: 单节点
  • 配置说明:pgEdge(PG18)分布式内核配置模板
  • 适用系统:d12, d13, u22, u24, u26(PG18 包);EL/RPM 平台请以当前 PGSQL 仓库的 pgedge_18 包可用性为准
  • 适用架构:x86_64, aarch64
  • 相关配置:metapgsql

启用方式:

./configure -c pgedge [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/pgedge.yml

---
#==============================================================#
# File      :   pgedge.yml
# Desc      :   1-node pgEdge (Distributed PG) template
# Ctime     :   2026-02-26
# Mtime     :   2026-07-08
# Docs      :   https://pigsty.io/docs/conf/pgedge
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for pgEdge Kernel,
# Which is a PostgreSQL 15/16/17/18 compatible fork, default to 18.
# tutorial: https://pigsty.io/docs/pgsql/kernel/pgedge
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c pgedge [-v 15/16/17/18]
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }} ,vars: { etcd_cluster: etcd  }}
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

    #----------------------------------------------#
    # pgEdge Database Cluster
    #----------------------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-meta
        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: [spock, snowflake, lolor]}
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # pgEdge Ad Hoc Settings
        pg_mode: pgedge                               # pgEdge compatible mode
        pg_packages: [ pgedge, pgsql-common ]         # install pgEdge kernel package + common utils
        pg_libs: 'spock, lolor, pg_stat_statements, auto_explain' # preload required libs for pgEdge logical replication

  vars:
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false           # do not overwrite node hostname on single node mode
    node_repo_modules: node,infra,pgsql # add these repos directly to the singleton node
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 18                      # pgEdge kernel is compatible with postgres 18
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

pgedge 模板在 pg-meta 集群中启用 pg_mode: pgedge,并预装 pgEdge 核心扩展用于逻辑复制与边缘分布式场景。

关键特性

  • 使用 pgedge 内核包替代标准 PostgreSQL(兼容 PG15/16/17/18,默认 PG18)
  • spocksnowflakelolorpgedge-$v 内核包交付,并在 meta 数据库中默认创建
  • 默认预加载 spocklolor,便于后续多主复制配置
  • 保留 Pigsty 的标准备份、监控与运维能力

适用场景

  • 多地域边缘部署与就近写入
  • 需要多主逻辑复制与冲突处理能力
  • 从单节点验证逐步扩展到分布式拓扑

注意事项

  • 当前模板用于单节点内核验证,生产多主需额外规划节点拓扑与复制策略
  • 默认 pg_version: 18,建议与目标集群版本保持一致
  • 进行跨地域复制前,请先评估网络时延与冲突处理策略

6.15 - mysql

OpenHalo 内核,提供 MySQL 协议与语法兼容能力

mysql 配置模板使用 OpenHalo 数据库内核替代原生 PostgreSQL,提供 MySQL 线缆协议与 SQL 语法兼容能力。


配置概览

  • 配置名称: mysql
  • 节点数量: 单节点
  • 配置说明:OpenHalo MySQL 兼容内核配置
  • 适用系统:EL 8/9/10、Debian 12/13、Ubuntu 22/24/26
  • 适用架构:x86_64aarch64
  • 相关配置:meta

启用方式:

./configure -c mysql [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/mysql.yml

---
#==============================================================#
# File      :   mysql.yml
# Desc      :   1-node OpenHaloDB (MySQL Compatible) template
# Ctime     :   2025-04-03
# Mtime     :   2026-07-08
# Docs      :   https://pigsty.io/docs/conf/mysql
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for OpenHalo PG Kernel,
# Which is a PostgreSQL 14 fork with MySQL Wire Compatibility
# tutorial: https://pigsty.io/docs/pgsql/kernel/openhalo
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c mysql
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }} ,vars: { etcd_cluster: etcd  }}
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

    #----------------------------------------------#
    # OpenHalo Database Cluster
    #----------------------------------------------#
    # connect with mysql client: mysql -h 10.10.10.10 -u dbuser_meta -D mysql (the actual database is 'postgres', and 'mysql' is a schema)
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-meta
        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: postgres, extensions: [aux_mysql]} # the mysql compatible database
          - {name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty]}
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # OpenHalo Ad Hoc Setting
        pg_mode: mysql                    # MySQL Compatible Mode by HaloDB
        pg_version: 14                    # OpenHaloDB is compatible with PG Major Version 14
        pg_packages: [ openhalo, pgsql-common ]  # install openhalodb instead of postgresql kernel

  vars:
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false           # do not overwrite node hostname on single node mode
    node_repo_modules: node,infra,pgsql # add these repos directly to the singleton node
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 14                      # OpenHalo is compatible with PG 14
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

mysql 模板使用 OpenHalo 内核,让您可以使用 MySQL 客户端工具连接 PostgreSQL。

关键特性

  • 使用 MySQL 协议(端口 3306),兼容 MySQL 客户端
  • 支持 MySQL SQL 语法子集
  • 保留 PostgreSQL 的 ACID 特性和存储引擎
  • 同时支持 PostgreSQL 和 MySQL 两种协议连接

连接方式

# 使用 MySQL 客户端
mysql -h 10.10.10.10 -P 3306 -u dbuser_meta -pDBUser.Meta

# 同时保留 PostgreSQL 连接能力
psql postgres://dbuser_meta:[email protected]:5432/meta

适用场景

  • 从 MySQL 迁移到 PostgreSQL
  • 需要同时支持 MySQL 和 PostgreSQL 客户端的应用
  • 希望利用 PostgreSQL 生态同时保持 MySQL 兼容性

注意事项

  • OpenHalo 基于 PostgreSQL 14,不支持更高版本特性
  • 部分 MySQL 语法可能存在兼容性差异
  • 当前 openhalo 包别名已覆盖 Pigsty 支持的 Linux 平台与双架构;实际安装仍以目标平台的软件仓库索引为准

6.16 - pgtde

Percona PostgreSQL 内核,提供透明数据加密 (pg_tde) 能力

pgtde 配置模板使用 Percona PostgreSQL 数据库内核,提供透明数据加密 (Transparent Data Encryption, TDE) 能力。


配置概览

  • 配置名称: pgtde
  • 节点数量: 单节点
  • 配置说明:Percona PostgreSQL 透明数据加密配置
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:meta

启用方式:

./configure -c pgtde [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/pgtde.yml

---
#==============================================================#
# File      :   pgtde.yml
# Desc      :   PG TDE with Percona PostgreSQL 1-node template
# Ctime     :   2025-07-04
# Mtime     :   2026-07-23
# Docs      :   https://pigsty.io/docs/conf/pgtde
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for Percona PostgreSQL Distribution
# with pg_tde, currently based on PostgreSQL 18
# tutorial: https://pigsty.io/docs/pgsql/kernel/percona
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c pgtde
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }} ,vars: { etcd_cluster: etcd  }}
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

    #----------------------------------------------#
    # Percona Postgres Database Cluster
    #----------------------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_mode: pgtde
        pg_cluster: pg-meta
        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  }
        pg_databases:
          - name: meta
            baseline: cmdb.sql
            comment: pigsty tde database
            schemas: [pigsty]
            extensions: [ vector, postgis, pg_tde ,pgaudit, { name: pg_stat_monitor, schema: monitor } ]
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # Percona PostgreSQL TDE Kernel Settings
        pg_packages: [ pgtde, pgsql-common ]  # install Pigsty private-prefix Percona packages
        pg_libs: 'pg_tde, pgaudit, pg_stat_statements, pg_stat_monitor, auto_explain'

  vars:
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false             # do not overwrite node hostname on single node mode
    node_repo_modules: node,infra,pgsql
    node_tune: oltp

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 18                      # Default Percona TDE PG Major Version is 18
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

pgtde 模板设置 pg_mode: pgtde 并安装 pgtde 包别名。Pigsty 会将私有 FHS 前缀 /usr/pgtde-$v(PostgreSQL 18 对应 /usr/pgtde-18)链接到稳定 入口 /usr/pgsql

关键特性

  • 透明数据加密:数据在磁盘上自动加密,对应用透明
  • 密钥管理:支持本地密钥和外部密钥管理系统 (KMS)
  • 表级加密:可选择性加密敏感表
  • 完整兼容:与原生 PostgreSQL 完全兼容

适用场景

  • 需要满足数据安全合规要求(如 PCI-DSS、HIPAA)
  • 存储敏感数据(如个人信息、金融数据)
  • 需要静态数据加密的场景
  • 对数据安全有严格要求的企业环境

使用方法

CREATE EXTENSION pg_tde;

SELECT pg_tde_add_database_key_provider_file(
    'local-file',
    '/secure/path/pg_tde_keys'
);
SELECT pg_tde_set_principal_key('app-principal-key', 'local-file');

-- 创建加密表
CREATE TABLE sensitive_data (
    id SERIAL PRIMARY KEY,
    ssn VARCHAR(11)
) USING tde_heap;

-- 或对现有表启用加密
ALTER TABLE existing_table SET ACCESS METHOD tde_heap;

注意事项

  • Percona PostgreSQL 基于 PostgreSQL 18
  • 加密会带来一定性能开销(通常 5-15%)
  • 需要妥善管理加密密钥
  • 上述发行版均提供 x86_64aarch64 软件包

6.17 - oriole

OrioleDB 内核,提供无膨胀的 OLTP 增强存储引擎

oriole 配置模板使用 OrioleDB 存储引擎替代 PostgreSQL 默认的 Heap 存储,提供无膨胀、高性能的 OLTP 能力。


配置概览

  • 配置名称: oriole
  • 节点数量: 单节点
  • 配置说明:OrioleDB 无膨胀存储引擎配置
  • PostgreSQL 大版本:161718
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:meta

启用方式:

./configure -c oriole [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/oriole.yml

---
#==============================================================#
# File      :   oriole.yml
# Desc      :   1-node OrioleDB (OLTP Enhancement) template
# Ctime     :   2025-04-05
# Mtime     :   2026-07-08
# Docs      :   https://pigsty.io/docs/conf/oriole
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for OrioleDB Kernel,
# Which is a Patched PostgreSQL 16/17/18 fork
# tutorial: https://pigsty.io/docs/pgsql/kernel/orioledb
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c oriole [-v 16/17/18]
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }} ,vars: { etcd_cluster: etcd  }}
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

    #----------------------------------------------#
    # OrioleDB Database Cluster
    #----------------------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-meta
        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: [orioledb]}
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # OrioleDB Ad Hoc Settings
        pg_mode: oriole                                         # OrioleDB compatible mode
        pg_packages: [ orioledb, pgsql-common ]                 # install OrioleDB kernel
        pg_libs: 'orioledb, pg_stat_statements, auto_explain'   # Load OrioleDB Extension

  vars:                               # global variables
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false           # do not overwrite node hostname on single node mode
    node_repo_modules: node,infra,pgsql # add these repos directly to the singleton node
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 18                      # OrioleDB Kernel is based on PG 16/17/18
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

oriole 模板使用 OrioleDB 存储引擎,从根本上解决 PostgreSQL 表膨胀问题。

关键特性

  • 无膨胀设计:使用 UNDO 日志而非多版本并发控制 (MVCC)
  • 无需 VACUUM:消除 autovacuum 带来的性能抖动
  • 行级 WAL:更高效的日志记录和复制
  • 压缩存储:内置数据压缩,减少存储空间

适用场景

  • 高频更新的 OLTP 工作负载
  • 对写入延迟敏感的应用
  • 需要稳定响应时间(消除 VACUUM 影响)
  • 大表频繁更新导致膨胀的场景

使用方法

-- 创建使用 OrioleDB 存储的表
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    customer_id INT,
    amount DECIMAL(10,2)
) USING orioledb;

-- 对现有表无法直接转换,需要重建

注意事项

  • OrioleDB 支持 PostgreSQL 16、17、18,默认模板使用 PG18,可通过 ./configure -c oriole -v 16/17/18 指定大版本
  • 需要将 orioledb 添加到 shared_preload_libraries
  • 部分 PostgreSQL 特性可能不完全支持
  • 请为所选 PostgreSQL 大版本与 OS 架构安装匹配的 OrioleDB 包

6.18 - PostgreSQL Mongo 模式

使用 DocumentDB 与 FerretDB Docker APP,让 PostgreSQL 提供 MongoDB 协议兼容能力。

mongo 配置模板是一个 PostgreSQL 部署模式,而不是独立的 Pigsty 模块。它由以下组件组成:

  • 由标准 PGSQL 模块管理的 PostgreSQL 18
  • documentdb 扩展及其预加载库
  • 通过 Pigsty Docker APP 工作流部署的无状态 FerretDB 代理

所有数据、高可用、备份、监控与生命周期管理仍由 PostgreSQL 负责;FerretDB 只提供 MongoDB 线协议兼容端点。


快速开始

模板默认部署在单节点 10.10.10.10 上,FerretDB 默认只监听本机回环地址。

如果尚未安装 mongosh,请单独安装,或使用其他兼容 MongoDB 协议的客户端。

./configure -c mongo
./deploy.yml
./docker.yml -l pg-meta
./app.yml -l pg-meta
mongosh 'mongodb://mongod:[email protected]:27017/'

模板声明了专用的 PostgreSQL 用户 mongod。FerretDB 默认启用认证,但尚未实现 MongoDB 授权角色;真正的安全边界仍然是 PostgreSQL。


架构

层次 实现 职责
数据层 PostgreSQL + DocumentDB 持久化、事务、高可用、PITR、ACL 与监控
协议层 FerretDB Docker APP 无状态的 MongoDB 线协议兼容
访问层 默认 127.0.0.1:27017 本机 MongoDB 客户端入口

容器通过 host.docker.internal 连接 Pigsty 本机的 5436 主库服务。默认 Mongo 端点不会暴露到网络;只有确实需要远程访问时才应修改 FERRETDB_BIND_ADDR


配置

源文件:pigsty/conf/mongo.yml

---
#==============================================================#
# File      :   mongo.yml
# Desc      :   PostgreSQL Mongo Mode (DocumentDB + FerretDB)
# Ctime     :   2025-02-23
# Mtime     :   2026-08-05
# Docs      :   https://pigsty.io/docs/conf/mongo
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the PostgreSQL Mongo mode template, powered by DocumentDB + FerretDB
# It provides a MongoDB wire-compatible endpoint backed by PostgreSQL
# This config template works with PostgreSQL 16, 17, 18
# tutorial: https://pigsty.io/docs/conf/mongo
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c mongo
#   ./deploy.yml
#   ./docker.yml -l pg-meta
#   ./app.yml -l pg-meta
#   # install mongosh separately if it is not already available
#   mongosh 'mongodb://mongod:[email protected]:27017/'

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }} ,vars: { repo_enabled: false }}
    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 }
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

    #----------------------------------#
    # PGSQL Database Cluster
    #----------------------------------#
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-meta
        pg_users:
          - { name: mongod      ,password: DBUser.Mongo  ,superuser: true  ,comment: FerretDB backend user }
          - { 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  }
        pg_databases:
          - { name: postgres, extensions: [ documentdb, postgis, vector, pg_cron, rum ]}  # run on the postgres database
        pg_hba_rules:
          - { user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes' }
          # WARNING: demo/dev only. Avoid world access for dbsu in production.
          - { user: postgres    , db: all ,addr: world ,auth: pwd ,title: 'dbsu password access everywhere' }
          - { user: all ,db: all ,addr: localhost ,order: 1  ,auth: trust ,title: 'documentdb localhost trust access' }
          - { user: all ,db: all ,addr: local     ,order: 1  ,auth: trust ,title: 'documentdb local     trust access' }
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_parameters: { cron.database_name: postgres }
        pg_extensions: [ documentdb, postgis, pgvector, pg_cron, rum ]
        pg_libs: 'pg_documentdb, pg_documentdb_core, pg_documentdb_extended_rum, pg_cron, pg_stat_statements, auto_explain'
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'

        # FerretDB Docker APP on the same node, exposed at 127.0.0.1:27017
        docker_enabled: true
        app: ferretdb
        apps:
          ferretdb:
            conf:
              FERRETDB_IMAGE: ghcr.io/ferretdb/ferretdb:2.7.0
              FERRETDB_POSTGRESQL_URL: 'postgres://mongod:[email protected]:5436/postgres?pool_min_conns=1&pool_max_conns=20'
              FERRETDB_BIND_ADDR: 127.0.0.1
              FERRETDB_PORT: 27017
              FERRETDB_LISTEN_ADDR: ':27017'
              FERRETDB_AUTH: true
              FERRETDB_TELEMETRY: disabled

    #--------------------------------------------------------------------------#
    # OPTIONAL: Three-node PostgreSQL + DocumentDB + FerretDB HA cluster
    # Uncomment this entire block and the two additional etcd members above.
    # Then run: ./docker.yml -l pg-mongo && ./app.yml -l pg-mongo
    # Endpoint: mongodb://mongod:[email protected]:27017/
    #--------------------------------------------------------------------------#
    # pg-mongo:
    #   hosts:
    #     10.10.10.11: { pg_seq: 1, pg_role: primary, vip_role: master }
    #     10.10.10.12: { pg_seq: 2, pg_role: replica, vip_role: backup }
    #     10.10.10.13: { pg_seq: 3, pg_role: replica, vip_role: backup }
    #   vars:
    #     pg_cluster: pg-mongo
    #     node_cluster: pg-mongo
    #     pg_users:
    #       - { name: mongod, password: DBUser.Mongo, superuser: true, comment: FerretDB backend user }
    #     pg_databases:
    #       - { name: postgres, extensions: [ documentdb, postgis, vector, pg_cron, rum ] }
    #     pg_hba_rules:
    #       - { user: all, db: all, addr: localhost, order: 1, auth: trust, title: 'documentdb localhost trust access' }
    #       - { user: all, db: all, addr: local, order: 1, auth: trust, title: 'documentdb local trust access' }
    #       - { user: mongod, db: postgres, addr: intra, order: 800, auth: pwd, title: 'ferretdb intranet access with password' }
    #     pg_parameters: { cron.database_name: postgres }
    #     pg_extensions: [ documentdb, postgis, pgvector, pg_cron, rum ]
    #     pg_libs: 'pg_documentdb, pg_documentdb_core, pg_documentdb_extended_rum, pg_cron, pg_stat_statements, auto_explain'
    #     pg_crontab:
    #       - '00 01 * * 1 /pg/bin/pg-backup full'
    #       - '00 01 * * 2,3,4,5,6,7 /pg/bin/pg-backup'
    #
    #     # FerretDB Docker cluster and HAProxy service
    #     docker_enabled: true
    #     app: ferretdb
    #     apps:
    #       ferretdb:
    #         conf:
    #           FERRETDB_IMAGE: ghcr.io/ferretdb/ferretdb:2.7.0
    #           FERRETDB_POSTGRESQL_URL: 'postgres://mongod:[email protected]:5436/postgres?pool_min_conns=1&pool_max_conns=20'
    #           FERRETDB_BIND_ADDR: '{{ inventory_hostname }}'
    #           FERRETDB_PORT: 27018
    #           FERRETDB_LISTEN_ADDR: ':27017'
    #           FERRETDB_AUTH: true
    #           FERRETDB_TELEMETRY: disabled
    #
    #     # HA Mongo endpoint: mongo.pigsty / 10.10.10.4:27017
    #     vip_enabled: true
    #     vip_vrid: 27
    #     vip_address: 10.10.10.4
    #     vip_preempt: false
    #     haproxy_services:
    #       - name: mongo
    #         port: 27017
    #         protocol: tcp
    #         balance: leastconn
    #         options:
    #           - option tcp-check
    #         servers:
    #           - { name: ferretdb-1, ip: 10.10.10.11, port: 27018, options: 'check port 27018' }
    #           - { name: ferretdb-2, ip: 10.10.10.12, port: 27018, options: 'check port 27018' }
    #           - { name: ferretdb-3, ip: 10.10.10.13, port: 27018, options: 'check port 27018' }

  vars:                               # global variables
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: false           # do not overwrite node hostname
    node_repo_modules: node,infra,pgsql # install from upstream repo directly
    node_tune: oltp                     # node tuning specs: oltp,olap,tiny,crit

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 18                      # default postgres version (16,17,18)
    pg_conf: oltp.yml                   # pgsql tuning specs: {oltp,olap,tiny,crit}.yml

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

FerretDB 参数是 apps.ferretdb.conf 下的普通 APP 覆盖项:

app: ferretdb
apps:
  ferretdb:
    conf:
      FERRETDB_IMAGE: ghcr.io/ferretdb/ferretdb:2.7.0
      FERRETDB_POSTGRESQL_URL: 'postgres://mongod:[email protected]:5436/postgres?pool_min_conns=1&pool_max_conns=20'
      FERRETDB_BIND_ADDR: 127.0.0.1
      FERRETDB_PORT: 27017
      FERRETDB_AUTH: true
      FERRETDB_TELEMETRY: disabled

后端集群统一使用标准 PostgreSQL 参数、剧本、仪表盘和管理流程;不再存在 mongo_* 参数组或独立的 mongo.yml 剧本。


可选高可用拓扑

模板中保留了注释状态的三节点 pg-mongo 示例。需要时取消该区块以及两个额外 etcd 成员的注释即可。

HA 模式下,每个 FerretDB 容器绑定 {{ inventory_hostname }}:27018,HAProxy 通过浮动端点 10.10.10.4:27017mongo.pigsty)暴露三个后端。PostgreSQL 故障转移仍由 Patroni 负责,FerretDB 始终保持无状态。


注意事项

  • 模板包含方便开发测试的 HBA 示例,生产环境请收紧。
  • 默认未启用客户端 MongoDB TLS。
  • 后端使用标准 PostgreSQL 与 Docker 仪表盘监控;不再提供独立 FERRET 模块或模块仪表盘。
  • FerretDB 或 DocumentDB 升级后应重新执行一次带认证的 CRUD 冒烟测试。

6.19 - ha/simu

20 节点生产环境仿真配置,用于大规模部署测试

ha/simu 配置模板是一个 20 节点的生产环境仿真配置,需要强大的宿主机方可运行。


配置概览

  • 配置名称: ha/simu
  • 节点数量: 20 节点,pigsty/vagrant/spec/simu.rb
  • 配置说明:20 节点的生产环境仿真配置,需要强大的宿主机方可运行。
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64

启用方式:

./configure -c ha/simu [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/ha/simu.yml

---
#==============================================================#
# File      :   simu.yml
# Desc      :   Pigsty Simubox: a 20 node prod simulation env
# Ctime     :   2023-07-20
# Mtime     :   2026-01-19
# Docs      :   https://pigsty.io/docs/conf/simu
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license
# Copyright :   2018-2025  Ruohang Feng / Vonng ([email protected])
#==============================================================#

all:

  children:

    #==========================================================#
    # infra: 3 nodes
    #==========================================================#
    # ./infra.yml -l infra
    # ./docker.yml -l infra (optional)
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }
        10.10.10.11: { infra_seq: 2, repo_enabled: false }
        10.10.10.12: { infra_seq: 3, repo_enabled: false }
      vars:
        docker_enabled: true
        node_tune: oltp         # use oltp template for infra nodes
        pg_conf: oltp.yml       # use oltp template for infra pgsql
        pg_exporters:           # bin/pgmon-add pg-meta2/pg-src2/pg-dst2
          20001: {pg_cluster: pg-meta2   ,pg_seq: 1 ,pg_host: 10.10.10.10, pg_databases: [{ name: meta }]}
          20002: {pg_cluster: pg-meta2   ,pg_seq: 2 ,pg_host: 10.10.10.11, pg_databases: [{ name: meta }]}
          20003: {pg_cluster: pg-meta2   ,pg_seq: 3 ,pg_host: 10.10.10.12, pg_databases: [{ name: meta }]}

          20004: {pg_cluster: pg-src2    ,pg_seq: 1 ,pg_host: 10.10.10.31, pg_databases: [{ name: src }]}
          20005: {pg_cluster: pg-src2    ,pg_seq: 2 ,pg_host: 10.10.10.32, pg_databases: [{ name: src }]}
          20006: {pg_cluster: pg-src2    ,pg_seq: 3 ,pg_host: 10.10.10.33, pg_databases: [{ name: src }]}

          20007: {pg_cluster: pg-dst2    ,pg_seq: 1 ,pg_host: 10.10.10.41, pg_databases: [{ name: dst }]}
          20008: {pg_cluster: pg-dst2    ,pg_seq: 2 ,pg_host: 10.10.10.42, pg_databases: [{ name: dst }]}
          20009: {pg_cluster: pg-dst2    ,pg_seq: 3 ,pg_host: 10.10.10.43, pg_databases: [{ name: dst }]}


    #==========================================================#
    # etcd: 5 nodes dedicated etcd cluster
    #==========================================================#
    # ./etcd.yml -l etcd;
    etcd:
      hosts:
        10.10.10.25: { etcd_seq: 1 }
        10.10.10.26: { etcd_seq: 2 }
        10.10.10.27: { etcd_seq: 3 }
        10.10.10.28: { etcd_seq: 4 }
        10.10.10.29: { etcd_seq: 5 }
      vars:
        etcd_cluster: etcd

    #==========================================================#
    # minio: 4 nodes dedicated minio cluster
    #==========================================================#
    # ./minio.yml -l minio;
    minio:
      hosts:
        10.10.10.21: { minio_seq: 1 }
        10.10.10.22: { minio_seq: 2 }
        10.10.10.23: { minio_seq: 3 }
        10.10.10.24: { minio_seq: 4 }
      vars:
        minio_cluster: minio
        minio_data: '/data{1...4}' # 4 node x 4 disk
        minio_users:                      # list of minio user to be created
          - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
          - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
          - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }


    #==========================================================#
    # proxy: 2 nodes used as dedicated haproxy server
    #==========================================================#
    # ./node.yml -l proxy
    proxy:
      hosts:
        10.10.10.18: { vip_role: master }
        10.10.10.19: { vip_role: backup }
      vars:
        vip_enabled: true
        vip_address: 10.10.10.20
        vip_vrid: 20
        haproxy_services:      # expose minio service : sss.pigsty:9000
          - name: minio        # [REQUIRED] service name, unique
            port: 9000         # [REQUIRED] service port, unique
            balance: leastconn # Use leastconn algorithm and minio health check
            options: [ "option httpchk", "option http-keep-alive", "http-check send meth OPTIONS uri /minio/health/live", "http-check expect status 200" ]
            servers:           # reload service with ./node.yml -t haproxy_config,haproxy_reload
              - { name: minio-1 ,ip: 10.10.10.21 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
              - { name: minio-2 ,ip: 10.10.10.22 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
              - { name: minio-3 ,ip: 10.10.10.23 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
              - { name: minio-4 ,ip: 10.10.10.24 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }

    #==========================================================#
    # pg-meta: reuse infra node as meta cmdb
    #==========================================================#
    # ./pgsql.yml -l pg-meta
    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 }
      vars:
        pg_cluster: pg-meta
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.2/24
        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 }
          - {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     }
          - {name: dbuser_noco     ,password: DBUser.Noco     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for nocodb service      }
        pg_databases:
          - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [{name: vector}]}
          - { 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 }
          - { name: noco     ,owner: dbuser_noco     ,revokeconn: true ,comment: nocodb database }
        pg_libs: 'pg_stat_statements, auto_explain' # add timescaledb to shared_preload_libraries

    #==========================================================#
    # pg-src: dedicate 3 node source cluster
    #==========================================================#
    # ./pgsql.yml -l pg-src
    pg-src:
      hosts:
        10.10.10.31: { pg_seq: 1, pg_role: primary }
        10.10.10.32: { pg_seq: 2, pg_role: replica }
        10.10.10.33: { pg_seq: 3, pg_role: replica }
      vars:
        pg_cluster: pg-src
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.3/24
        pg_users:  [{ name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] }]
        pg_databases: [{ name: src }]


    #==========================================================#
    # pg-dst: dedicate 3 node destination cluster
    #==========================================================#
    # ./pgsql.yml -l pg-dst
    pg-dst:
      hosts:
        10.10.10.41: { pg_seq: 1, pg_role: primary }
        10.10.10.42: { pg_seq: 2, pg_role: replica }
        10.10.10.43: { pg_seq: 3, pg_role: replica }
      vars:
        pg_cluster: pg-dst
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.4/24
        pg_users: [ { name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] } ]
        pg_databases: [ { name: dst } ]


    #==========================================================#
    # redis-meta: reuse the 5 etcd nodes as redis sentinel
    #==========================================================#
    # ./redis.yml -l redis-meta
    redis-meta:
      hosts:
        10.10.10.25: { redis_node: 1 , redis_instances: { 26379: {} } }
        10.10.10.26: { redis_node: 2 , redis_instances: { 26379: {} } }
        10.10.10.27: { redis_node: 3 , redis_instances: { 26379: {} } }
        10.10.10.28: { redis_node: 4 , redis_instances: { 26379: {} } }
        10.10.10.29: { redis_node: 5 , redis_instances: { 26379: {} } }
      vars:
        redis_cluster: redis-meta
        redis_password: 'redis.meta'
        redis_mode: sentinel
        redis_max_memory: 256MB
        redis_sentinel_monitor:  # primary list for redis sentinel, use cls as name, primary ip:port
          - { name: redis-src, host: 10.10.10.31, port: 6379 ,password: redis.src, quorum: 1 }
          - { name: redis-dst, host: 10.10.10.41, port: 6379 ,password: redis.dst, quorum: 1 }

    #==========================================================#
    # redis-src: reuse pg-src 3 nodes for redis
    #==========================================================#
    # ./redis.yml -l redis-src
    redis-src:
      hosts:
        10.10.10.31: { redis_node: 1 , redis_instances: {6379: {  } }}
        10.10.10.32: { redis_node: 2 , redis_instances: {6379: { replica_of: '10.10.10.31 6379' }, 6380: { replica_of: '10.10.10.32 6379' } }}
        10.10.10.33: { redis_node: 3 , redis_instances: {6379: { replica_of: '10.10.10.31 6379' }, 6380: { replica_of: '10.10.10.33 6379' } }}
      vars:
        redis_cluster: redis-src
        redis_password: 'redis.src'
        redis_max_memory: 64MB

    #==========================================================#
    # redis-dst: reuse pg-dst 3 nodes for redis
    #==========================================================#
    # ./redis.yml -l redis-dst
    redis-dst:
      hosts:
        10.10.10.41: { redis_node: 1 , redis_instances: {6379: {  }                               }}
        10.10.10.42: { redis_node: 2 , redis_instances: {6379: { replica_of: '10.10.10.41 6379' } }}
        10.10.10.43: { redis_node: 3 , redis_instances: {6379: { replica_of: '10.10.10.41 6379' } }}
      vars:
        redis_cluster: redis-dst
        redis_password: 'redis.dst'
        redis_max_memory: 64MB

    #==========================================================#
    # pg-tmp: reuse proxy nodes as pgsql cluster
    #==========================================================#
    # ./pgsql.yml -l pg-tmp
    pg-tmp:
      hosts:
        10.10.10.18: { pg_seq: 1 ,pg_role: primary }
        10.10.10.19: { pg_seq: 2 ,pg_role: replica }
      vars:
        pg_cluster: pg-tmp
        pg_users: [ { name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] } ]
        pg_databases: [ { name: tmp } ]

    #==========================================================#
    # pg-etcd: reuse etcd nodes as pgsql cluster
    #==========================================================#
    # ./pgsql.yml -l pg-etcd
    pg-etcd:
      hosts:
        10.10.10.25: { pg_seq: 1 ,pg_role: primary }
        10.10.10.26: { pg_seq: 2 ,pg_role: replica }
        10.10.10.27: { pg_seq: 3 ,pg_role: replica }
        10.10.10.28: { pg_seq: 4 ,pg_role: replica }
        10.10.10.29: { pg_seq: 5 ,pg_role: offline }
      vars:
        pg_cluster: pg-etcd
        pg_users: [ { name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] } ]
        pg_databases: [ { name: etcd } ]

    #==========================================================#
    # pg-minio: reuse minio nodes as pgsql cluster
    #==========================================================#
    # ./pgsql.yml -l pg-minio
    pg-minio:
      hosts:
        10.10.10.21: { pg_seq: 1 ,pg_role: primary }
        10.10.10.22: { pg_seq: 2 ,pg_role: replica }
        10.10.10.23: { pg_seq: 3 ,pg_role: replica }
        10.10.10.24: { pg_seq: 4 ,pg_role: replica }
      vars:
        pg_cluster: pg-minio
        pg_users: [ { name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] } ]
        pg_databases: [ { name: minio } ]

  #============================================================#
  # Global Variables
  #============================================================#
  vars:

    #==========================================================#
    # INFRA
    #==========================================================#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    infra_portal:                     # infra services exposed via portal
      home         : { domain: i.pigsty }     # default domain name
      minio        : { domain: m.pigsty    ,endpoint: "10.10.10.21:9001" ,scheme: https ,websocket: true }
      postgrest    : { domain: api.pigsty  ,endpoint: "127.0.0.1:8884" }
      pgadmin      : { domain: adm.pigsty  ,endpoint: "127.0.0.1:8885" }
      pgweb        : { domain: cli.pigsty  ,endpoint: "127.0.0.1:8886" }
      bytebase     : { domain: ddl.pigsty  ,endpoint: "127.0.0.1:8887" }
      jupyter      : { domain: lab.pigsty  ,endpoint: "127.0.0.1:8888"  , websocket: true }
      supa         : { domain: supa.pigsty ,endpoint: "10.10.10.10:8000", websocket: true }

    #==========================================================#
    # NODE
    #==========================================================#
    node_id_from_pg: true             # use nodename rather than pg identity as hostname
    node_tune: tiny                   # use small node template
    node_firewall_mode: zone          # default: trust intranet, expose selected public ports
    node_timezone: Asia/Hong_Kong     # use Asia/Hong_Kong Timezone
    node_dns_servers:                 # DNS servers in /etc/resolv.conf
      - 10.10.10.10
      - 10.10.10.11
    node_etc_hosts:
      - 10.10.10.10 i.pigsty
      - 10.10.10.20 sss.pigsty        # point minio service domain to the L2 VIP of proxy cluster
    node_ntp_servers:                 # NTP servers in /etc/chrony.conf
      - pool cn.pool.ntp.org iburst
      - pool 10.10.10.10 iburst
    node_admin_ssh_exchange: false    # exchange admin ssh key among node cluster

    #==========================================================#
    # PGSQL
    #==========================================================#
    pg_conf: tiny.yml
    pgbackrest_method: minio          # USE THE HA MINIO THROUGH A LOAD BALANCER
    pg_dbsu_ssh_exchange: false       # do not exchange dbsu ssh key among pgsql cluster
    pgbackrest_repo:                  # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
      local:                          # default pgbackrest repo with local posix fs
        path: /pg/backup              # local backup directory, `/pg/backup` by default
        retention_full_type: count    # retention full backups by count
        retention_full: 2             # keep 2, at most 3 full backup when using local fs repo
      minio:                          # optional minio repo for pgbackrest
        type: s3                      # minio is s3-compatible, so s3 is used
        s3_endpoint: sss.pigsty       # minio endpoint domain name, `sss.pigsty` by default
        s3_region: us-east-1          # minio region, us-east-1 by default, useless for minio
        s3_bucket: pgsql              # minio bucket name, `pgsql` by default
        s3_key: pgbackrest            # minio user access key for pgbackrest
        s3_key_secret: S3User.Backup  # minio user secret key for pgbackrest
        s3_uri_style: path            # use path style uri for minio rather than host style
        path: /pgbackrest             # minio backup path, default is `//pgbackrest`
        storage_port: 9000            # minio port, 9000 by default
        storage_ca_file: /etc/pki/ca.crt  # minio ca file path, `/etc/pki/ca.crt` by default
        block: y                      # Enable block incremental backup
        bundle: y                     # bundle small files into a single file
        bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
        cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
        retention_full_type: time     # retention full backup by time on minio repo
        retention_full: 14            # keep full backup for last 14 days
    pg_crontab:  # make a full backup on monday 1am, and an incremental backup during weekdays
      - '00 01  * * * /pg/bin/pg-backup'
      - '00 05 * * *  /pg/bin/pg-vacuum'
    pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
      - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }

    #==========================================================#
    # Repo
    #==========================================================#
    repo_packages: [
      node-bootstrap, infra-package, infra-addons, node-package1, node-package2, node-package3, pgsql-utility, extra-modules,
      pg18-core ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl
    ]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

ha/simu 模板是一个 大规模生产环境仿真配置,用于测试和验证复杂场景。

架构组成

  • 2 节点高可用 INFRA(监控/告警/Nginx/DNS)
  • 5 节点高可用 ETCD 和 MINIO(Silo,多磁盘)
  • 2 节点 Proxy(HAProxy + Keepalived VIP)
  • 多套 PostgreSQL 集群:
    • pg-meta:2 节点高可用
    • pg-v14~v18:单节点多版本测试
    • pg-pitr:单节点 PITR 测试
    • pg-test:4 节点高可用
    • pg-src/pg-dst:3+2 节点复制测试
    • pg-citus:10 节点分布式集群
  • 多种 Redis 模式:主从、哨兵、集群

适用场景

  • 大规模部署测试与验证
  • 高可用故障演练
  • 性能基准测试
  • 新功能预览与评估

注意事项

  • 需要强大的宿主机(推荐 64GB+ 内存)
  • 使用 Vagrant 虚拟机模拟

6.20 - ha/octo

八节点紧凑高可用仿真模板:三节点 INFRA、五节点 etcd、八节点对象存储与两套 PostgreSQL 集群。

ha/octo 使用 vagrant/spec/deci.rb 的前八个节点,构造一套紧凑的高可用仿真环境。它用于验证多模块共置、VIP、远程备份和较大成员规模,不应未经容量、安全和故障域评审直接作为生产蓝图。


配置概览

  • 配置名称:ha/octo
  • 节点地址:10.10.10.1010.10.10.17
  • INFRA:3 节点;仅首节点构建并服务本地软件仓库,三节点可按注释另行安装 Docker
  • ETCD:5 节点,部署在后五个节点
  • 对象存储:8 节点单盘集群;模板未覆盖 minio_type,部署与移除角色都默认使用 Silo,删除前仍须核对该值、精确目标和数据盘路径
  • pg-meta:3 节点 PostgreSQL,VIP 10.10.10.2/24
  • pg-test:5 节点 PostgreSQL,其中最后一个实例角色为 offline,VIP 10.10.10.3/24
  • 备份:通过 sss.pigsty:9002 使用对象存储仓库,并保留本地仓库
./configure -c ha/octo
./deploy.yml

该模板依赖固定的八节点地址和 VIP。用于其他环境时,必须同步修改主机地址、VIP、网卡、DNS、仓库节点和所有公开示例凭据。


配置内容

源文件地址:pigsty/conf/ha/octo.yml

---
#==============================================================#
# File      :   octo.yml
# Desc      :   Pigsty 8-node compact HA simulation config
# Ctime     :   2026-07-29
# Mtime     :   2026-07-29
# Docs      :   https://pigsty.io/docs/conf
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# Use the first 8 nodes from `vagrant/spec/deci.rb`:
#
#  node  address      vagrant name  modules
#  1     10.10.10.10  meta-0        infra(repo,docker), minio-1, pg-meta-1
#  2     10.10.10.11  meta-1        infra(docker),      minio-2, pg-meta-2
#  3     10.10.10.12  meta-2        infra(docker),      minio-3, pg-meta-3
#  4     10.10.10.13  node-3        etcd-1, minio-4, pg-test-1
#  5     10.10.10.14  node-4        etcd-2, minio-5, pg-test-2
#  6     10.10.10.15  node-5        etcd-3, minio-6, pg-test-3
#  7     10.10.10.16  node-6        etcd-4, minio-7, pg-test-4
#  8     10.10.10.17  node-7        etcd-5, minio-8, pg-test-5 (offline)
#
# Nodes 10.10.10.18 and 10.10.10.19 from the deci template are unused.

all:

  #============================================================#
  # Clusters, Nodes, and Modules
  #============================================================#
  children:

    # 3-node infra cluster; only node 1 builds and serves the repo
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1, repo_enabled: true }
        10.10.10.11: { infra_seq: 2, repo_enabled: false }
        10.10.10.12: { infra_seq: 3, repo_enabled: false }
      vars:
        docker_enabled: true          # install with ./docker.yml -l infra

    # 5-node etcd cluster, co-located with pg-test
    etcd:
      hosts:
        10.10.10.13: { etcd_seq: 1 }
        10.10.10.14: { etcd_seq: 2 }
        10.10.10.15: { etcd_seq: 3 }
        10.10.10.16: { etcd_seq: 4 }
        10.10.10.17: { etcd_seq: 5 }
      vars:
        etcd_cluster: etcd

    # 8-node single-drive MinIO cluster, spanning all nodes
    minio:
      hosts:
        10.10.10.10: { minio_seq: 1, vip_role: master }
        10.10.10.11: { minio_seq: 2 }
        10.10.10.12: { minio_seq: 3 }
        10.10.10.13: { minio_seq: 4 }
        10.10.10.14: { minio_seq: 5 }
        10.10.10.15: { minio_seq: 6 }
        10.10.10.16: { minio_seq: 7 }
        10.10.10.17: { minio_seq: 8 }
      vars:
        minio_cluster: minio
        minio_data: /data/minio       # 8 nodes x 1 disk
        minio_users:
          - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
          - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
          - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }

        # HA MinIO endpoint: https://sss.pigsty:9002
        vip_enabled: true
        vip_vrid: 128
        vip_address: 10.10.10.9
        haproxy_services:
          - name: minio
            port: 9002
            balance: leastconn
            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' }
              - { name: minio-4 ,ip: 10.10.10.13 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
              - { name: minio-5 ,ip: 10.10.10.14 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
              - { name: minio-6 ,ip: 10.10.10.15 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
              - { name: minio-7 ,ip: 10.10.10.16 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
              - { name: minio-8 ,ip: 10.10.10.17 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }

    # 3-node PostgreSQL meta cluster, co-located with infra
    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 }
      vars:
        pg_cluster: pg-meta
        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 ] }
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.2/24
        pg_crontab:
          - '00 01 * * * /pg/bin/pg-backup full'

    # 5-node PostgreSQL test cluster; node 8 is the offline instance
    pg-test:
      hosts:
        10.10.10.13: { pg_seq: 1, pg_role: primary }
        10.10.10.14: { pg_seq: 2, pg_role: replica }
        10.10.10.15: { pg_seq: 3, pg_role: replica }
        10.10.10.16: { pg_seq: 4, pg_role: replica }
        10.10.10.17: { pg_seq: 5, pg_role: offline }
      vars:
        pg_cluster: pg-test
        pg_users:
          - { name: test ,password: test ,pgbouncer: true ,roles: [ dbrole_admin ] }
        pg_databases:
          - { name: test }
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.3/24
        pg_crontab:
          - '00 01 * * 1 /pg/bin/pg-backup full'
          - '00 01 * * 2,3,4,5,6,7 /pg/bin/pg-backup'

  #============================================================#
  # Global Parameters
  #============================================================#
  vars:
    version: v4.5.0
    admin_ip: 10.10.10.10
    region: default
    node_tune: oltp
    pg_conf: oltp.yml

    proxy_env:
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
      # http_proxy:
      # https_proxy:
      # all_proxy:

    infra_portal:
      home:  { domain: i.pigsty }
      minio: { domain: m.pigsty ,endpoint: "10.10.10.10:9001" ,scheme: https ,websocket: true }

    # Node 1 serves the local repository; every node installs from it
    repo_remove: true
    node_repo_remove: true
    node_repo_modules: local
    repo_extra_packages: [ pg18-main ]
    pg_version: 18

    # MinIO VIP and pgBackRest object-storage repository
    minio_endpoint: https://sss.pigsty:9002
    node_etc_hosts:
      - '${admin_ip} i.pigsty'
      - '10.10.10.9 sss.pigsty'
    pgbackrest_method: minio
    pgbackrest_repo:
      local:
        path: /pg/backup
        retention_full_type: count
        retention_full: 2
      minio:
        type: s3
        s3_endpoint: sss.pigsty
        s3_region: us-east-1
        s3_bucket: pgsql
        s3_key: pgbackrest
        s3_key_secret: S3User.Backup
        s3_uri_style: path
        path: /pgbackrest
        storage_port: 9002
        storage_ca_file: /etc/pki/ca.crt
        block: y
        bundle: y
        bundle_limit: 20MiB
        bundle_size: 128MiB
        cipher_type: aes-256-cbc
        cipher_pass: pgBackRest
        retention_full_type: time
        retention_full: 14

    # Default credentials for this disposable sample
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root

...

配置解读

  • 三个 INFRA 节点与五个 etcd 节点分置;PostgreSQL 的 pg-metapg-test 分别与这两组节点共置。
  • 对象存储跨越全部八个节点,并通过 Keepalived VIP 10.10.10.9 与 HAProxy 9002 暴露 sss.pigsty。当前默认引擎是 Silo,但模块和变量继续使用 minio_* 兼容命名。
  • pg-meta 每天做一次全量备份;pg-test 每周全量、其余日期增量备份,统一写入加密的 S3 pgBackRest 仓库。
  • repo_enabled: false 的两个 INFRA 副本不会构建本地仓库;所有节点仍从首节点的 local 仓库安装软件包。
  • 模板末尾的数据库、Grafana、Patroni、HAProxy、Silo 与 etcd 密码只适合一次性仿真,真实环境必须全部轮换。

如只需要常规最小高可用部署,优先使用 ha/trio;需要更大规模的全场景仿真,参见 ha/simu

6.21 - ha/full

四节点完整功能演示环境,带有两套 PostgreSQL 集群、Silo、Redis 等组件示例

ha/full 配置模板是 Pigsty 推荐的沙箱演示环境,使用四个节点部署两套 PostgreSQL 集群,用于测试和演示 Pigsty 各方面的能力。

Pigsty 大部分教程和示例都基于此模板的沙箱环境。


配置概览

  • 配置名称: ha/full
  • 节点数量: 四节点
  • 配置说明:四节点完整功能演示环境,带有两套 PostgreSQL 集群、Silo、Redis 等组件示例
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:ha/trioha/safedemo/demo

启用方式:

./configure -c ha/full [-i <primary_ip>]

配置生成后,需要修改其他三个节点的 IP 地址。


配置内容

源文件地址:pigsty/conf/ha/full.yml

---
#==============================================================#
# File      :   full.yml
# Desc      :   Pigsty Local Sandbox 4-node Demo Config
# Ctime     :   2020-05-22
# Mtime     :   2026-01-16
# Docs      :   https://pigsty.io/docs/conf/full
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#


all:

  #==============================================================#
  # Clusters, Nodes, and Modules
  #==============================================================#
  children:

    # infra: monitor, alert, repo, etc..
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }
      vars:
        docker_enabled: true      # enabled docker with ./docker.yml
        #docker_registry_mirrors: ["https://docker.1panel.live","https://docker.1ms.run","https://docker.xuanyuan.me","https://registry-1.docker.io"]
        #repo_extra_packages: [ pg18-main ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    # etcd cluster for HA postgres DCS
    etcd:
      hosts:
        10.10.10.10: { etcd_seq: 1 }
      vars:
        etcd_cluster: etcd

    # minio (single node, used as backup repo)
    minio:
      hosts:
        10.10.10.10: { minio_seq: 1 }
      vars:
        minio_cluster: minio
        minio_users:                      # list of minio user to be created
          - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
          - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
          - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }

    # postgres cluster: pg-meta
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-meta
        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 ] }
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.2/24


    # pgsql 3 node ha cluster: pg-test
    pg-test:
      hosts:
        10.10.10.11: { pg_seq: 1, pg_role: primary }   # primary instance, leader of cluster
        10.10.10.12: { pg_seq: 2, pg_role: replica }   # replica instance, follower of leader
        10.10.10.13: { pg_seq: 3, pg_role: replica, pg_offline_query: true } # replica with offline access
      vars:
        pg_cluster: pg-test           # define pgsql cluster name
        pg_users:  [{ name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] }]
        pg_databases: [{ name: test }]
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.3/24
        pg_crontab:  # make a full backup on monday 1am, and an incremental backup during weekdays
          - '00 01 * * 1 /pg/bin/pg-backup full'
          - '00 01 * * 2,3,4,5,6,7 /pg/bin/pg-backup'

    #----------------------------------#
    # redis ms, sentinel, native 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 }


  #==============================================================#
  # Global Parameters
  #==============================================================#
  vars:
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    node_tune: oltp                   # node tuning specs: oltp,olap,tiny,crit
    pg_conf: oltp.yml                 # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    proxy_env:                        # global proxy env when downloading packages
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
      # http_proxy:  # set your proxy here: e.g http://user:[email protected]
      # https_proxy: # set your proxy here: e.g http://user:[email protected]
      # all_proxy:   # set your proxy here: e.g http://user:[email protected]
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name
      #minio : { domain: m.pigsty ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }

    #----------------------------------#
    # MinIO Related Options
    #----------------------------------#
    node_etc_hosts: [ '${admin_ip} i.pigsty sss.pigsty' ]
    pgbackrest_method: minio          # if you want to use minio as backup repo instead of 'local' fs, uncomment this
    pgbackrest_repo:                  # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
      local:                          # default pgbackrest repo with local posix fs
        path: /pg/backup              # local backup directory, `/pg/backup` by default
        retention_full_type: count    # retention full backups by count
        retention_full: 2             # keep 2, at most 3 full backup when using local fs repo
      minio:                          # optional minio repo for pgbackrest
        type: s3                      # minio is s3-compatible, so s3 is used
        s3_endpoint: sss.pigsty       # minio endpoint domain name, `sss.pigsty` by default
        s3_region: us-east-1          # minio region, us-east-1 by default, useless for minio
        s3_bucket: pgsql              # minio bucket name, `pgsql` by default
        s3_key: pgbackrest            # minio user access key for pgbackrest
        s3_key_secret: S3User.Backup  # minio user secret key for pgbackrest
        s3_uri_style: path            # use path style uri for minio rather than host style
        path: /pgbackrest             # minio backup path, default is `/pgbackrest`
        storage_port: 9000            # minio port, 9000 by default
        storage_ca_file: /etc/pki/ca.crt  # minio ca file path, `/etc/pki/ca.crt` by default
        block: y                      # Enable block incremental backup
        bundle: y                     # bundle small files into a single file
        bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
        cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
        retention_full_type: time     # retention full backup by time on minio repo
        retention_full: 14            # keep full backup for last 14 days

    #----------------------------------#
    # Repo, Node, Packages
    #----------------------------------#
    repo_remove: true                 # remove existing repo on admin node during repo bootstrap
    node_repo_remove: true            # remove existing node repo for node managed by pigsty
    repo_extra_packages: [ pg18-main ] #,pg18-core ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
    pg_version: 18                    # default postgres version
    #pg_extensions: [pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl ,pg18-olap]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

ha/full 模板是 Pigsty 的 完整功能演示配置,展示了多种组件的协同工作。

组件概览

组件 节点分布 说明
INFRA 节点1 监控/告警/Nginx/DNS
ETCD 节点1 DCS 服务
Silo 节点1 S3 兼容存储
pg-meta 节点1 单节点 PostgreSQL
pg-test 节点2-4 三节点高可用 PostgreSQL
redis-ms 节点1 Redis 主从模式
redis-meta 节点2 Redis 哨兵模式
redis-test 节点3-4 Redis 原生集群模式

适用场景

  • Pigsty 功能演示与学习
  • 开发测试环境
  • 评估高可用架构
  • Redis 不同模式对比测试

与 ha/trio 的区别

  • 增加了第二套 PostgreSQL 集群(pg-test)
  • 增加了三种模式的 Redis 集群示例
  • 基础设施使用单节点(而非三节点)

注意事项

  • 此模板主要用于演示和测试,生产环境请参考 ha/trioha/safe
  • 默认启用 MINIO 对象存储备份;当前源码默认后端为 Silo,如不需要可注释相关配置

6.22 - ha/safe

三节点高可用与安全加固配置示例。

ha/safe 基于三节点高可用拓扑,示范 TLS、客户端证书、口令检查、备份加密和 CRIT 参数模板等安全配置。它是可修改的配置样例,不是合规认证模板。


配置概览

  • 配置名称:ha/safe
  • 节点数量:3 个 INFRA、etcd 和 PostgreSQL 节点;可选延迟副本
  • 适用系统:el8el9el10d12d13u22u24u26
  • 适用架构:x86_64;部分安全扩展没有 ARM64 软件包
  • 相关配置:ha/trioha/full

生成配置:

./configure -c ha/safe -g [-i <primary_ip>]

-g 只能随机化配置向导识别的凭据。生成后仍需手工替换 Silo 用户、pgBackRest cipher_pass 和其他模板示例值。


加固内容

配置项 模板行为 边界与后续操作
PostgreSQL HBA 主要 TCP 规则使用 ssl,公网管理员使用 cert 本地 ident 和部分 localhost pwd 规则保留
PgBouncer pgbouncer_sslmode: require 客户端仍需按需要验证服务端证书
Patroni REST API 启用 HTTPS,并限制监听地址 仍使用 Basic Auth,应轮换口令
口令检查 pg_libs 中预加载 passwordcheck 只影响新设置或修改的口令
用户有效期 内置用户和示例业务用户设置 expire_in: 7300 20 年不是轮换策略,应按组织要求缩短
监听地址 PostgreSQL 收敛到 ${ip},${vip},${lo} 仍需配合防火墙和 HBA
备份 使用 Silo,启用 AES-256-CBC pgBR.${pg_cluster} 是可预测示例值,必须替换
PostgreSQL 参数 pg-meta 使用 crit.yml 严格同步模式可能在无同步副本时阻塞写入
日志 CRIT 记录连接和断开事件 SQL 细粒度审计需另行启用 pgaudit
安全扩展 安装 passwordcheckcredcheckpgaudit 等软件包 安装不等于预加载、创建或配置
延迟副本 提供注释掉的 1 小时延迟集群示例 默认不会创建,需要显式启用

使用前检查

  • 替换所有公开示例凭据,重点检查 minio_userspgbackrest_repo、业务用户和 API 口令;
  • 确认 3 个节点位于独立故障域,并按实际网络修改 IP、VIP 和域名;
  • 为数据库客户端配置 sslmode=verify-full 与可信 CA;
  • 确认严格同步模式的可用性影响符合业务要求;
  • 根据需要预加载并配置 pgauditcredcheck 等扩展;
  • 检查 ARM64 环境中的扩展软件包可用性;
  • 完成备份恢复、故障切换和证书验证测试。

安全机制说明见 安全模型身份认证加密通信数据安全


配置内容

源文件:pigsty/conf/ha/safe.yml

---
#==============================================================#
# File      :   safe.yml
# Desc      :   Pigsty 3-node security enhance template
# Ctime     :   2020-05-22
# Mtime     :   2025-12-12
# Docs      :   https://pigsty.io/docs/conf/safe
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#


#===== SECURITY ENHANCEMENT CONFIG TEMPLATE WITH 3 NODES ======#
#   * 3 infra nodes, 3 etcd nodes, single minio node
#   * 3-instance pgsql cluster with an extra delayed instance
#   * crit.yml templates, no data loss, checksum enforced
#   * enforce ssl on postgres & pgbouncer, use postgres by default
#   * enforce an expiration date for all users (20 years by default)
#   * enforce strong password policy with passwordcheck extension
#   * enforce changing default password for all users
#   * log connections and disconnections
#   * restrict listen ip address for postgres/patroni/pgbouncer


all:
  children:

    infra: # infra cluster for proxy, monitor, alert, etc
      hosts: # 1 for common usage, 3 nodes for production
        10.10.10.10: { infra_seq: 1 } # identity required
        10.10.10.11: { infra_seq: 2, repo_enabled: false }
        10.10.10.12: { infra_seq: 3, repo_enabled: false }
      vars: { patroni_watchdog_mode: 'off' }

    minio: # minio cluster, s3 compatible object storage
      hosts: { 10.10.10.10: { minio_seq: 1 } }
      vars: { minio_cluster: minio }

    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 }  # three-member cluster keeps an odd voter count
      vars: # cluster level parameter override roles/etcd
        etcd_cluster: etcd  # mark etcd cluster name etcd
        etcd_safeguard: false # safeguard against purging

    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: Pleas3-ChangeThisPwd ,expire_in: 7300 ,pgbouncer: true ,roles: [ dbrole_admin ]    ,comment: pigsty admin user }
          - { name: dbuser_view , password: Make.3ure-Compl1ance  ,expire_in: 7300 ,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: vector } ] }
        pg_services:
          - { name: standby , ip: "*" ,port: 5435 , dest: default ,selector: "[]" , backup: "[? pg_role == `primary`]" }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'
        pg_listen: '${ip},${vip},${lo}'
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.2/24

    # 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 }


  ####################################################################
  #                          Parameters                              #
  ####################################################################
  vars: # global variables
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    node_tune: oltp                   # node tuning specs: oltp,olap,tiny,crit
    pg_conf: oltp.yml                 # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    #docker_registry_mirrors: ["https://docker.1panel.live","https://docker.1ms.run","https://docker.xuanyuan.me","https://registry-1.docker.io"]
    patroni_ssl_enabled: true         # secure patroni RestAPI communications with SSL?
    pgbouncer_sslmode: require        # pgbouncer client ssl mode: disable|allow|prefer|require|verify-ca|verify-full, disable by default
    pg_default_service_dest: postgres # default service destination to postgres instead of pgbouncer
    pgbackrest_method: minio          # pgbackrest repo method: local,minio,[user-defined...]

    #----------------------------------#
    # MinIO Related Options
    #----------------------------------#
    minio_users: # and configure `pgbackrest_repo` & `minio_users` accordingly
      - { access_key: dba , secret_key: S3User.DBA.Strong.Password, policy: consoleAdmin }
      - { access_key: pgbackrest , secret_key: Min10.bAckup ,policy: readwrite }
    pgbackrest_repo: # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
      local: # default pgbackrest repo with local posix fs
        path: /pg/backup              # local backup directory, `/pg/backup` by default
        retention_full_type: count    # retention full backups by count
        retention_full: 2             # keep 2, at most 3 full backup when using local fs repo
      minio: # optional minio repo for pgbackrest
        s3_key: pgbackrest            # <-------- CHANGE THIS, SAME AS `minio_users` access_key
        s3_key_secret: Min10.bAckup   # <-------- CHANGE THIS, SAME AS `minio_users` secret_key
        cipher_pass: 'pgBR.${pg_cluster}'  # <-------- CHANGE THIS, you can use cluster name as part of password
        type: s3                      # minio is s3-compatible, so s3 is used
        s3_endpoint: sss.pigsty       # minio endpoint domain name, `sss.pigsty` by default
        s3_region: us-east-1          # minio region, us-east-1 by default, useless for minio
        s3_bucket: pgsql              # minio bucket name, `pgsql` by default
        s3_uri_style: path            # use path style uri for minio rather than host style
        path: /pgbackrest             # minio backup path, default is `/pgbackrest`
        storage_port: 9000            # minio port, 9000 by default
        storage_ca_file: /etc/pki/ca.crt  # minio ca file path, `/etc/pki/ca.crt` by default
        block: y                      # Enable block incremental backup
        bundle: y                     # bundle small files into a single file
        bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
        retention_full_type: time     # retention full backup by time on minio repo
        retention_full: 14            # keep full backup for last 14 days


    #----------------------------------#
    # Access Control
    #----------------------------------#
    # add passwordcheck_cracklib extension to enforce strong password policy
    pg_libs: '$libdir/passwordcheck_cracklib, pg_stat_statements, auto_explain'
    pg_extensions:
      - passwordcheck_cracklib, supautils, pgsodium, pg_vault, pg_session_jwt, pg_anon, pgsmcrypto, pgauditlogtofile, pgaudit #, pgaudit17, pgaudit16, pgaudit15, pgaudit14
      - pg_auth_mon, credcheck, pgcryptokey, pg_jobmon, logerrors, login_hook, set_user, pgextwlist, pg_auditor, sslutils, pg_noset #pg_tde #pg_snakeoil
    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, order by `order`
      - { user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'   ,order: 100}
      - { user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident'  ,order: 150}
      - { user: '${repl}'    ,db: replication ,addr: localhost ,auth: ssl   ,title: 'replicator replication from localhost' ,order: 200}
      - { user: '${repl}'    ,db: replication ,addr: intra     ,auth: ssl   ,title: 'replicator replication from intranet'  ,order: 250}
      - { user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: ssl   ,title: 'replicator postgres db from intranet'  ,order: 300}
      - { user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password'  ,order: 350}
      - { user: '${monitor}' ,db: all         ,addr: infra     ,auth: ssl   ,title: 'monitor from infra host with password' ,order: 400}
      - { user: '${admin}'   ,db: all         ,addr: infra     ,auth: ssl   ,title: 'admin @ infra nodes with pwd & ssl'    ,order: 450}
      - { user: '${admin}'   ,db: all         ,addr: world     ,auth: cert  ,title: 'admin @ everywhere with ssl & cert'    ,order: 500}
      - { user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: ssl   ,title: 'pgbouncer read/write via local socket' ,order: 550}
      - { user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: ssl   ,title: 'read/write biz user via password'      ,order: 600}
      - { user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: ssl   ,title: 'allow etl offline tasks from intranet' ,order: 650}
    pgb_default_hba_rules: # pgbouncer host-based authentication rules, order by `order`
      - { user: '${dbsu}'    ,db: pgbouncer   ,addr: local     ,auth: peer  ,title: 'dbsu local admin access with os ident' ,order: 100}
      - { user: 'all'        ,db: all         ,addr: localhost ,auth: pwd   ,title: 'allow all user local access with pwd'  ,order: 150}
      - { user: '${monitor}' ,db: pgbouncer   ,addr: intra     ,auth: ssl   ,title: 'monitor access via intranet with pwd'  ,order: 200}
      - { user: '${monitor}' ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other monitor access addr'  ,order: 250}
      - { user: '${admin}'   ,db: all         ,addr: intra     ,auth: ssl   ,title: 'admin access via intranet with pwd'    ,order: 300}
      - { user: '${admin}'   ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other admin access addr'    ,order: 350}
      - { user: 'all'        ,db: all         ,addr: intra     ,auth: ssl   ,title: 'allow all user intra access with pwd'  ,order: 400}

    #----------------------------------#
    # Repo, Node, Packages
    #----------------------------------#
    repo_remove: true                 # remove existing repo on admin node during repo bootstrap
    node_repo_remove: true            # remove existing node repo for node managed by pigsty
    #node_selinux_mode: enforcing     # set selinux mode: enforcing,permissive,disabled
    node_firewall_mode: zone          # firewall mode: zone (default), off (disable), none (skip & self-managed)
    repo_extra_packages: [ pg18-main ] #,pg18-core ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
    pg_version: 18                    # default postgres version
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    #grafana_admin_username: admin
    grafana_admin_password: You.Have2Use-A_VeryStrongPassword
    grafana_view_password: DBUser.Viewer
    #pg_admin_username: dbuser_dba
    pg_admin_password: PessWorb.Should8eStrong-eNough
    #pg_monitor_username: dbuser_monitor
    pg_monitor_password: MekeSuerYour.PassWordI5secured
    #pg_replication_username: replicator
    pg_replication_password: doNotUseThis-PasswordFor.AnythingElse
    #patroni_username: postgres
    patroni_password: don.t-forget-to-change-thEs3-password
    #haproxy_admin_username: admin
    haproxy_admin_password: GneratePasswordWith-pwgen-s-16-1
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

6.23 - ha/trio

三节点标准高可用配置模板,PostgreSQL、ETCD 与 Silo 均可容忍单节点故障。

三节点是实现多数派高可用的最小规格。ha/trio 将 INFRA、ETCD、PGSQL 与 Silo 分布在三台服务器上;PostgreSQL、ETCD 和对象存储都可以在一台服务器宕机时继续服务。


配置概览

  • 配置名称: ha/trio
  • 节点数量: 三节点
  • 配置说明:三节点标准高可用架构,包含三节点单盘 Silo 与统一 S3 高可用入口
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:ha/dualha/fullha/safe

启用方式:

./configure -c ha/trio [-i <primary_ip>]

配置生成后,需要将占位 IP 10.10.10.1110.10.10.12 修改为实际的节点 IP 地址。


配置内容

源文件地址:pigsty/conf/ha/trio.yml

---
#==============================================================#
# File      :   trio.yml
# Desc      :   Pigsty 3-node security enhance template
# Ctime     :   2020-05-23
# Mtime     :   2026-08-14
# Docs      :   https://pigsty.io/docs/conf/trio
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# 3 infra node, 3 etcd node, 3 pgsql node, and 3 minio nodes
all:  # top level object
  #==============================================================#
  # Clusters, Nodes, and Modules
  #==============================================================#
  children:
    #----------------------------------#
    # infra: monitor, alert, repo, etc..
    #----------------------------------#
    infra: # infra cluster for proxy, monitor, alert, etc
      hosts: # 1 for common usage, 3 nodes for production
        10.10.10.10: { infra_seq: 1 } # identity required
        10.10.10.11: { infra_seq: 2, repo_enabled: false }
        10.10.10.12: { infra_seq: 3, repo_enabled: false }
      vars:
        patroni_watchdog_mode: 'off' # do not fencing infra

    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 }  # three-member cluster keeps an odd voter count
      vars: # cluster level parameter override roles/etcd
        etcd_cluster: etcd  # mark etcd cluster name etcd
        etcd_safeguard: false # safeguard against purging

    # compact 3-node x 1-drive Silo cluster: EC:1, tolerates one node failure
    # use a dedicated local mount for /data/minio; do not expand a 1-node cluster in place
    minio: # minio cluster, s3 compatible object storage
      hosts:
        10.10.10.10: { minio_seq: 1, vip_role: master }
        10.10.10.11: { minio_seq: 2 }
        10.10.10.12: { minio_seq: 3 }
      vars:
        minio_cluster: minio
        minio_data: /data/minio
        minio_users:
          - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
          - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
          - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }
        vip_enabled: true
        vip_vrid: 128
        vip_address: 10.10.10.9
        haproxy_services:
          - name: minio
            port: 9002
            balance: leastconn
            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' }

    pg-meta:  # 3 instance postgres cluster `pg-meta`
      hosts:  # pg-meta-3 is marked as offline readable replica
        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:   # cluster level parameters
        pg_cluster: pg-meta
        pg_users: # https://pigsty.io/docs/pgsql/config/user
          - { 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: vector } ] }
        pg_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.2/24


  #==============================================================#
  # Global Parameters
  #==============================================================#
  vars:
    #----------------------------------#
    # Meta Data
    #----------------------------------#
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    node_tune: oltp                   # node tuning specs: oltp,olap,tiny,crit
    pg_conf: oltp.yml                 # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    #docker_registry_mirrors: ["https://docker.1panel.live","https://docker.1ms.run","https://docker.xuanyuan.me","https://registry-1.docker.io"]
    proxy_env:                        # global proxy env when downloading packages
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
      # http_proxy:  # set your proxy here: e.g http://user:[email protected]
      # https_proxy: # set your proxy here: e.g http://user:[email protected]
      # all_proxy:   # set your proxy here: e.g http://user:[email protected]
    infra_portal:                     # infra services exposed via portal
      home         : { domain: i.pigsty }     # default domain name
      minio        : { domain: m.pigsty ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }

    #----------------------------------#
    # Repo, Node, Packages
    #----------------------------------#
    repo_remove: true                 # remove existing repo on admin node during repo bootstrap
    node_repo_remove: true            # remove existing node repo for node managed by pigsty
    repo_extra_packages: [ pg18-main ] #,pg18-core ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
    pg_version: 18                    # default postgres version
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------#
    # MinIO Related Options
    #----------------------------------#
    minio_endpoint: https://sss.pigsty:9002
    node_etc_hosts:
      - '${admin_ip} i.pigsty'        # static dns record that point to repo node
      - '10.10.10.9 sss.pigsty'       # static dns record that point to minio vip
    pgbackrest_method: minio          # if you want to use minio as backup repo instead of 'local' fs, uncomment this
    pgbackrest_repo:                  # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
      local:                          # default pgbackrest repo with local posix fs
        path: /pg/backup              # local backup directory, `/pg/backup` by default
        retention_full_type: count    # retention full backups by count
        retention_full: 2             # keep 2, at most 3 full backup when using local fs repo
      minio:                          # optional minio repo for pgbackrest
        type: s3                      # minio is s3-compatible, so s3 is used
        s3_endpoint: sss.pigsty       # minio endpoint domain name, `sss.pigsty` by default
        s3_region: us-east-1          # minio region, us-east-1 by default, useless for minio
        s3_bucket: pgsql              # minio bucket name, `pgsql` by default
        s3_key: pgbackrest            # minio user access key for pgbackrest
        s3_key_secret: S3User.Backup  # minio user secret key for pgbackrest
        s3_uri_style: path            # use path style uri for minio rather than host style
        path: /pgbackrest             # minio backup path, default is `/pgbackrest`
        storage_port: 9002            # minio ha endpoint exposed by haproxy
        storage_ca_file: /etc/pki/ca.crt  # minio ca file path, `/etc/pki/ca.crt` by default
        block: y                      # Enable block incremental backup
        bundle: y                     # bundle small files into a single file
        bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
        cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
        retention_full_type: time     # retention full backup by time on minio repo
        retention_full: 14            # keep full backup for last 14 days

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root

...

配置解读

ha/trio 模板是 Pigsty 的 标准高可用配置,提供真正的故障自动恢复能力。

架构说明

  • 三节点 INFRA:VictoriaMetrics/Grafana/Nginx 分布式部署
  • 三节点 ETCD:DCS 多数派选举,容忍单点故障
  • 三节点 PostgreSQL:一主两从,自动故障转移
  • 三节点 Silo:每节点一个数据目录,默认 EC:1(2 份数据、1 份校验)
  • S3 高可用入口:Keepalived VIP 10.10.10.9 与三节点 HAProxy 9002

高可用保障

  • ETCD 三节点可容忍一节点故障,保持多数派
  • PostgreSQL 主库故障时,Patroni 自动选举新主
  • L2 VIP 随主库漂移,应用无需修改连接配置
  • Silo 在一个节点或一个数据盘不可用时仍保持读写仲裁
  • sss.pigsty 指向对象存储 VIP,pgBackRest 与 mcli 统一通过 https://sss.pigsty:9002 访问

对象存储

  • minio_data: /data/minio 配置的是文件系统目录,不是 /dev/sdb 之类的裸设备。
  • 分布式 Silo 会拒绝根文件系统上的数据目录。/data/minio 必须位于独立挂载的 /data 文件系统中,或者自身就是独立挂载点。
  • 数据盘可以是本地盘、云盘、独立分区或 LVM 逻辑卷;生产环境应优先使用独立持久化磁盘,并让三台节点容量接近。
  • 可用 findmnt -T /data/minio 检查实际挂载点。如果结果仍是 /,说明它只是根盘上的普通目录。
  • 三节点单盘拓扑的原始容量利用率约为三分之二,适合资源受限的紧凑高可用部署;需要更高容量、吞吐与磁盘冗余时应使用多机多盘拓扑。
  • 既有单节点对象存储不能通过直接增加两个成员原地变成该拓扑;应创建新的三节点集群并迁移对象。

模板中的 S3 API 是高可用入口;Portal 中的管理控制台仍连接首节点 9001,不属于该 API 高可用链路。

适用场景

  • 生产环境最小高可用部署
  • 需要自动故障转移的关键业务
  • 作为更大规模部署的基础架构

扩展建议

  • 需要更强数据安全性,参考 ha/safe 模板
  • 需要更多演示功能,参考 ha/full 模板
  • 对象存储容量或性能要求较高时,使用每节点多盘的 Silo 集群

6.24 - ha/dual

双节点配置模板,有限高可用部署,允许宕机特定一台服务器。

ha/dual 模板使用双节点部署,实现一主一备的"半高可用"架构。如果您只有两台服务器,这是一个务实的选择。


配置概览

  • 配置名称: ha/dual
  • 节点数量: 双节点
  • 配置说明:两节点有限高可用部署,允许特定一台服务器宕机
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:ha/trioslim

启用方式:

./configure -c ha/dual [-i <primary_ip>]

配置生成后,需要将占位 IP 10.10.10.11 修改为实际的备库节点 IP 地址。


配置内容

源文件地址:pigsty/conf/ha/dual.yml

---
#==============================================================#
# File      :   dual.yml
# Desc      :   Pigsty deployment example for two nodes
# Ctime     :   2020-05-22
# Mtime     :   2025-12-12
# Docs      :   https://pigsty.io/docs/conf/dual
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#


# It is recommended to use at least three nodes in production deployment.
# But sometimes, there are only two nodes available, that's dual.yml for
#
# In this setup, we have two nodes, .10 (admin_node) and .11 (pgsql_primary):
#
# If .11 is down, .10 will take over since the dcs:etcd is still alive
# If .10 is down, .11 (pgsql primary) will still be functioning as a primary if:
#   - Only dcs:etcd is down
#   - Only pgsql is down
# if both etcd & pgsql are down (e.g. node down), the primary will still demote itself.


all:
  children:

    # infra cluster for proxy, monitor, alert, etc..
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }

    # etcd cluster for ha postgres
    etcd: { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }

    # minio cluster, optional backup repo for pgbackrest
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio } }

    # postgres cluster 'pg-meta' with single primary instance
    pg-meta:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: replica }
        10.10.10.11: { pg_seq: 2, pg_role: primary }  # <----- use this as primary by default
      vars:
        pg_cluster: pg-meta
        pg_databases: [ { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [ pigsty ] ,extensions: [ { name: vector }] } ]
        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_hba_rules:   # https://pigsty.io/docs/pgsql/config/hba
          - { user: all ,db: all ,addr: intra ,auth: pwd ,title: 'everyone intranet access with password' ,order: 800 }
        pg_crontab:     # https://pigsty.io/docs/pgsql/admin/crontab
          - '00 01 * * * /pg/bin/pg-backup full'
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.2/24

  vars:                               # global parameters
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    node_tune: oltp                   # node tuning specs: oltp,olap,tiny,crit
    pg_conf: oltp.yml                 # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    #docker_registry_mirrors: ["https://docker.1panel.live","https://docker.1ms.run","https://docker.xuanyuan.me","https://registry-1.docker.io"]
    infra_portal:                     # domain names and upstream servers
      home   : { domain: i.pigsty }
      #minio : { domain: m.pigsty ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }

    #----------------------------------#
    # Repo, Node, Packages
    #----------------------------------#
    repo_remove: true                 # remove existing repo on admin node during repo bootstrap
    node_repo_remove: true            # remove existing node repo for node managed by pigsty
    repo_extra_packages: [ pg18-main ] #,pg18-core ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
    pg_version: 18                    # default postgres version
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

ha/dual 模板是 Pigsty 的 双节点有限高可用配置,专为只有两台服务器的场景设计。

架构说明

  • 节点 A (10.10.10.10):管理节点,运行 Infra + etcd + PostgreSQL 备库
  • 节点 B (10.10.10.11):数据节点,仅运行 PostgreSQL 主库

故障场景分析

故障节点 影响 是否自动恢复
节点 B 宕机 主库切换到节点 A 自动
节点 A etcd 宕机 主库继续运行(无 DCS) 需人工
节点 A pgsql 宕机 主库继续运行 需人工
节点 A 完全宕机 主库降级为单机 需人工

适用场景

  • 仅有两台服务器的预算受限环境
  • 可接受部分故障场景需要人工介入
  • 作为三节点高可用的过渡方案

注意事项

  • 真正的高可用需要至少三节点(DCS 需要多数派)
  • 建议尽快升级到三节点架构
  • L2 VIP 需要网络环境支持(同一广播域)

6.25 - ha/citus

13 节点 Citus 分布式 PostgreSQL 集群,1 协调组 + 5 工作组高可用配置,提供水平扩展与分片能力

ha/citus 配置模板部署一套完整的 Citus 分布式 PostgreSQL 集群,包含 1 个基础设施节点、1 组协调节点和 5 组工作节点(共 12 个 Citus 节点),提供透明的水平扩展与数据分片能力。


配置概览

  • 配置名称: ha/citus
  • 节点数量: 13 节点(1 基础设施 + 1 协调组 × 2 + 5 工作组 × 2)
  • 配置说明:Citus 分布式 PostgreSQL 高可用集群
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64
  • 相关配置:metaha/trio

启用方式:

./configure -c ha/citus

备注:这是一个 13 节点模板,您需要在生成配置后修改各节点的 IP 地址


配置内容

源文件地址:pigsty/conf/ha/citus.yml

---
#==============================================================#
# File      :   citus.yml
# Desc      :   13-node Citus (6-group Distributive) Config Template
# Ctime     :   2020-05-22
# Mtime     :   2025-01-20
# Docs      :   https://pigsty.io/docs/conf/citus
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# This is the config template for Citus Distributive Cluster
# tutorial: https://pigsty.io/docs/pgsql/kernel/citus
# we will use the local repo for cluster bootstrapping
#
# Topology:
#   - pg-citus0: coordinator (10.10.10.10)         VIP: 10.10.10.19
#   - pg-citus1: worker group 1 (10.10.10.21, 22)  VIP: 10.10.10.29
#   - pg-citus2: worker group 2 (10.10.10.31, 32)  VIP: 10.10.10.39
#   - pg-citus3: worker group 3 (10.10.10.41, 42)  VIP: 10.10.10.49
#   - pg-citus4: worker group 4 (10.10.10.51, 52)  VIP: 10.10.10.59
#   - pg-citus5: worker group 5 (10.10.10.61, 62)  VIP: 10.10.10.69
#   - pg-citus6: worker group 6 (10.10.10.71, 72)  VIP: 10.10.10.79
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c citus
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }}}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }}, vars: { etcd_cluster: etcd }}
    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-meta
        pg_users:
          - { name: dbuser_meta ,password: DBUser.Meta   ,pgbouncer: true ,roles: [dbrole_admin   ] ,comment: pigsty admin user }
        pg_databases:
          - name: meta
            baseline: cmdb.sql
            comment: "pigsty meta database"
            schemas: [pigsty]
            extensions: [ postgis, vector ]
        pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ] # make a full backup every day 1am

    #----------------------------------------------------------#
    # pg-citus: 6 cluster groups, 12 nodes total
    #----------------------------------------------------------#
    pg-citus:
      hosts:

        # coordinator (group 0) on infra node
        10.10.10.21: { pg_group: 0, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.29/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.22: { pg_group: 0, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.29/24 ,pg_seq: 2, pg_role: replica }

        # worker group 2
        10.10.10.31: { pg_group: 1, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.39/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.32: { pg_group: 1, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.39/24 ,pg_seq: 2, pg_role: replica }

        # worker group 3
        10.10.10.41: { pg_group: 2, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.49/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.42: { pg_group: 2, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.49/24 ,pg_seq: 2, pg_role: replica }

        # worker group 4
        10.10.10.51: { pg_group: 3, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.59/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.52: { pg_group: 3, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.59/24 ,pg_seq: 2, pg_role: replica }

        # worker group 5
        10.10.10.61: { pg_group: 4, pg_cluster: pg-citus5 ,pg_vip_address: 10.10.10.69/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.62: { pg_group: 4, pg_cluster: pg-citus5 ,pg_vip_address: 10.10.10.69/24 ,pg_seq: 2, pg_role: replica }

        # worker group 6
        10.10.10.71: { pg_group: 5, pg_cluster: pg-citus6 ,pg_vip_address: 10.10.10.79/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.72: { pg_group: 5, pg_cluster: pg-citus6 ,pg_vip_address: 10.10.10.79/24 ,pg_seq: 2, pg_role: replica }

      vars:
        pg_mode: citus                            # pgsql cluster mode: citus
        pg_shard: pg-citus                        # citus shard name: pg-citus
        pg_primary_db: citus                      # primary database used by citus
        pg_dbsu_password: DBUser.Postgres         # enable dbsu password access for citus
        pg_extensions: [ citus, postgis, pgvector, topn, pg_cron, hll ]
        pg_libs: 'citus, pg_cron, pg_stat_statements'
        pg_users: [{ name: dbuser_citus ,password: DBUser.Citus ,pgbouncer: true ,roles: [ dbrole_admin ] }]
        pg_databases: [{ name: citus ,owner: dbuser_citus ,extensions: [ citus, vector, topn, pg_cron, hll ] }]
        pg_parameters:
          cron.database_name: citus
          citus.node_conninfo: 'sslrootcert=/pg/cert/ca.crt sslmode=verify-full'
        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'  }
        pg_vip_enabled: true
        pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ] # make a full backup every day 1am

  vars:
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0
    admin_ip: 10.10.10.10
    region: default
    infra_portal:
      home : { domain: i.pigsty }

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: true
    node_repo_modules: node,infra,pgsql
    node_tune: oltp

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 18  # PostgreSQL 14-18
    pg_conf: oltp.yml
    pg_packages: [ pgsql-main, pgsql-common ]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

集群拓扑

此配置部署一套完整的 Citus 分布式集群,拓扑结构如下:

集群 节点 IP 地址 VIP 角色
pg-meta 1 10.10.10.10 - 基础设施 + CMDB
pg-citus1 2 10.10.10.21, 22 10.10.10.29 协调节点(group 0)
pg-citus2 2 10.10.10.31, 32 10.10.10.39 工作节点(group 1)
pg-citus3 2 10.10.10.41, 42 10.10.10.49 工作节点(group 2)
pg-citus4 2 10.10.10.51, 52 10.10.10.59 工作节点(group 3)
pg-citus5 2 10.10.10.61, 62 10.10.10.69 工作节点(group 4)
pg-citus6 2 10.10.10.71, 72 10.10.10.79 工作节点(group 5)

架构说明

  • pg-meta:基础设施节点,运行 Grafana、VictoriaMetrics、etcd 等组件,同时部署一个独立的 CMDB 数据库
  • pg-citus1:Citus 协调节点(group 0),负责接收客户端查询并路由到工作节点,1 主 1 从高可用配置
  • pg-citus2~6:Citus 工作节点(group 1~5),存储分片数据,每组 1 主 1 从,通过 Patroni 实现自动故障转移
  • VIP:每个节点组配置 L2 VIP,由 vip-manager 管理,确保故障转移时客户端连接自动切换

配置解读

ha/citus 模板部署生产级 Citus 分布式集群,适合需要水平扩展的大规模数据场景。

关键特性

  • 水平扩展:5 个工作组可线性扩展存储和计算能力
  • 高可用:每个工作组 1 主 1 从,支持自动故障转移
  • L2 VIP:每组配置虚拟 IP,故障切换对应用透明
  • SSL 加密:节点间通信使用 SSL 证书加密
  • 透明分片:数据自动分布到多个工作节点

预装扩展

pg_extensions: [ citus, postgis, pgvector, topn, pg_cron, hll ]
pg_libs: 'citus, pg_cron, pg_stat_statements'

安全配置

  • 启用 pg_dbsu_password,允许超级用户密码访问(Citus 节点间通信需要)
  • HBA 规则要求所有连接使用 SSL 认证
  • 节点间使用证书验证:sslmode=verify-full

部署步骤

# 1. 下载 Pigsty
curl -fsSL https://repo.pigsty.cc/get | bash; cd ~/pigsty

# 2. 使用 ha/citus 配置模板
./configure -c ha/citus

# 3. 修改 IP 地址和密码
vi pigsty.yml

# 4. 部署完整集群
./deploy.yml

部署完成后,Citus 会自动注册所有工作节点。可通过以下命令验证:

-- 连接到任意协调节点
psql -h 10.10.10.29 -U dbuser_citus -d citus

-- 查看工作节点状态
SELECT * FROM citus_get_active_worker_nodes();

-- 查看分片分布
SELECT * FROM citus_shards;

使用示例

创建分布式表

-- 创建表
CREATE TABLE events (
    tenant_id INT,
    event_id BIGSERIAL,
    event_time TIMESTAMPTZ DEFAULT now(),
    payload JSONB,
    PRIMARY KEY (tenant_id, event_id)
);

-- 按 tenant_id 分片
SELECT create_distributed_table('events', 'tenant_id');

-- 插入数据(自动路由到对应分片)
INSERT INTO events (tenant_id, payload)
VALUES (1, '{"type": "click"}');

-- 查询(自动并行执行)
SELECT tenant_id, count(*)
FROM events
GROUP BY tenant_id;

创建引用表(小表复制到所有节点):

CREATE TABLE tenants (
    tenant_id INT PRIMARY KEY,
    name TEXT
);

SELECT create_reference_table('tenants');

适用场景

  • 多租户 SaaS:按租户 ID 分片,实现租户数据隔离和并行查询
  • 实时分析:大规模事件数据的实时聚合分析
  • 时序数据:结合 TimescaleDB 处理海量时序数据
  • 水平扩展:单表数据量超过单机容量时的扩展方案

注意事项

  • PostgreSQL 版本:Citus 支持 PostgreSQL 14~18,此模板默认使用 PG18
  • 分布列选择:合理选择分布列(通常是租户 ID 或时间戳)对性能至关重要
  • 跨分片限制:外键约束必须包含分布列,部分 DDL 操作有限制
  • 网络要求pg_vip_interface 默认为 auto,特殊网络环境可显式指定网卡
  • 架构限制:Citus 扩展不支持 ARM64 架构

6.26 - demo/bare

只声明 INFRA、ETCD 与单节点 PostgreSQL 的最小可读配置示例

demo/bare 是最小化的 Pigsty 配置示例,只保留三个核心分组和三个全局参数,用于展示一份可工作的 Inventory 骨架。


配置概览

  • 配置名称:demo/bare
  • 节点数量:单节点
  • 模块:INFRA、ETCD、PGSQL
  • 相关配置:metaslim
./configure -c demo/bare [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/demo/bare.yml

---
all:
  children:
    infra:   { hosts: { 10.10.10.10: { infra_seq: 1 } } }
    etcd:    { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }
    pg-meta: { hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }, vars: { pg_cluster: pg-meta } }
  vars:
    version: v4.5.0
    admin_ip: 10.10.10.10
    region: default
...

配置解读

该模板依赖 Pigsty 参数默认值,没有预置业务用户、数据库、扩展、备份策略或安全加固。它适合学习配置层级或作为最小定制起点;正式环境应显式补齐密码、HBA、备份与防护参数。

6.27 - demo/el

Enterprise Linux (RHEL/Rocky/Alma) 专用配置模板

demo/el 配置模板是针对 Enterprise Linux 系列发行版(RHEL、Rocky Linux、Alma Linux、Oracle Linux)优化的配置模板。


配置概览

  • 配置名称: demo/el
  • 节点数量: 单节点
  • 配置说明:Enterprise Linux 专用配置模板
  • 适用系统:el8, el9, el10
  • 适用架构:x86_64, aarch64
  • 相关配置:metademo/debian

启用方式:

./configure -c demo/el [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/demo/el.yml

---
#==============================================================#
# File      :   el.yml
# Desc      :   Default parameters for EL System in Pigsty
# Ctime     :   2020-05-22
# Mtime     :   2026-08-02
# Docs      :   https://pigsty.io/docs/conf/el
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#


#==============================================================#
#                        Sandbox (4-node)                      #
#==============================================================#
# admin user : vagrant  (nopass ssh & sudo already set)        #
# 1.  meta    :    10.10.10.10     (2 Core | 4GB)    pg-meta   #
# 2.  node-1  :    10.10.10.11     (1 Core | 1GB)    pg-test-1 #
# 3.  node-2  :    10.10.10.12     (1 Core | 1GB)    pg-test-2 #
# 4.  node-3  :    10.10.10.13     (1 Core | 1GB)    pg-test-3 #
# (replace these ip if your 4-node env have different ip addr) #
# VIP 2: (l2 vip is available inside same LAN )                #
#     pg-meta --->  10.10.10.2 ---> 10.10.10.10                #
#     pg-test --->  10.10.10.3 ---> 10.10.10.1{1,2,3}          #
#==============================================================#


all:

  ##################################################################
  #                            CLUSTERS                            #
  ##################################################################
  # meta nodes, nodes, pgsql, redis, pgsql clusters are defined as
  # k:v pair inside `all.children`. Where the key is cluster name
  # and value is cluster definition consist of two parts:
  # `hosts`: cluster members ip and instance level variables
  # `vars` : cluster level variables
  ##################################################################
  children:                                 # groups definition

    # infra cluster for proxy, monitor, alert, etc..
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }

    # etcd cluster for ha postgres
    etcd: { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }

    # minio cluster, s3 compatible object storage
    minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio } }

    #----------------------------------#
    # pgsql cluster: pg-meta (CMDB)    #
    #----------------------------------#
    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary , pg_offline_query: true } }
      vars:
        pg_cluster: pg-meta

        # define business databases here: https://pigsty.io/docs/pgsql/config/db
        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
            #state: create                  # optional, create|absent|recreate, create by default
            baseline: cmdb.sql              # optional, database sql baseline path, (relative path among ansible search path, e.g: files/)
            schemas: [pigsty]               # optional, additional schemas to be created, array of schema names
            extensions:                     # optional, additional extensions to be installed: array of `{name[,schema]}`
              - { name: vector }            # install pgvector extension on this database by default
            comment: pigsty meta database   # optional, comment string for this database
            #pgbouncer: true                # optional, add this database to pgbouncer database list? true by default
            #owner: postgres                # optional, database owner, current user if not specified
            #template: template1            # optional, which template to use, template1 by default
            #strategy: FILE_COPY            # optional, clone strategy: FILE_COPY or WAL_LOG (PG15+), default to PG's default
            #encoding: UTF8                 # optional, inherited from template / cluster if not defined (UTF8)
            #locale: C                      # optional, inherited from template / cluster if not defined (C)
            #lc_collate: C                  # optional, inherited from template / cluster if not defined (C)
            #lc_ctype: C                    # optional, inherited from template / cluster if not defined (C)
            #locale_provider: libc          # optional, locale provider: libc, icu, builtin (PG15+)
            #icu_locale: en-US              # optional, icu locale for icu locale provider (PG15+)
            #icu_rules: ''                  # optional, icu rules for icu locale provider (PG16+)
            #builtin_locale: C.UTF-8        # optional, builtin locale for builtin locale provider (PG17+)
            #tablespace: pg_default         # optional, default tablespace, pg_default by default
            #is_template: false             # optional, mark database as template, allowing clone by any user with CREATEDB privilege
            #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_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_connlimit: 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 }

        # define business users here: https://pigsty.io/docs/pgsql/config/user
        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
            pgbouncer: true                 # optional, add this user to pgbouncer user-list? false by default (production user should be true explicitly)
            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}
            #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
            #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)
            #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_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    }

        # define business service here: https://pigsty.io/docs/pgsql/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'

        # define pg extensions: https://pigsty.io/docs/pgsql/ext/
        pg_libs: 'pg_stat_statements, auto_explain' # add timescaledb to shared_preload_libraries
        #pg_extensions: [] # extensions to be installed on this cluster

        # define HBA rules here: https://pigsty.io/docs/pgsql/config/hba
        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_crontab:  # make a full backup 1 am everyday
          - '00 01 * * * /pg/bin/pg-backup full'

    #----------------------------------#
    # pgsql cluster: pg-test (3 nodes) #
    #----------------------------------#
    # pg-test --->  10.10.10.3 ---> 10.10.10.1{1,2,3}
    pg-test:                          # define the new 3-node cluster pg-test
      hosts:
        10.10.10.11: { pg_seq: 1, pg_role: primary }   # primary instance, leader of cluster
        10.10.10.12: { pg_seq: 2, pg_role: replica }   # replica instance, follower of leader
        10.10.10.13: { pg_seq: 3, pg_role: replica, pg_offline_query: true } # replica with offline access
      vars:
        pg_cluster: pg-test           # define pgsql cluster name
        pg_users:  [{ name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] }]
        pg_databases: [{ name: test }] # create a database and user named 'test'
        node_tune: tiny
        pg_conf: tiny.yml
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.3/24
        pg_crontab:  # make a full backup on monday 1am, and an incremental backup during weekdays
          - '00 01 * * 1 /pg/bin/pg-backup full'
          - '00 01 * * 2,3,4,5,6,7 /pg/bin/pg-backup'

    #----------------------------------#
    # redis ms, sentinel, native 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 }


  ####################################################################
  #                             VARS                                 #
  ####################################################################
  vars:                               # global variables


    #================================================================#
    #                         VARS: INFRA                            #
    #================================================================#

    #-----------------------------------------------------------------
    # META
    #-----------------------------------------------------------------
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    language: en                      # default language: en, zh
    proxy_env:                        # global proxy env when downloading packages
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
      # http_proxy:  # set your proxy here: e.g http://user:[email protected]
      # https_proxy: # set your proxy here: e.g http://user:[email protected]
      # all_proxy:   # set your proxy here: e.g http://user:[email protected]

    #-----------------------------------------------------------------
    # CA
    #-----------------------------------------------------------------
    ca_create: true                   # create ca if not exists? or just abort
    ca_cn: pigsty-ca                  # ca common name, fixed as pigsty-ca
    cert_validity: 7300d              # cert validity, 20 years by default

    #-----------------------------------------------------------------
    # INFRA_IDENTITY
    #-----------------------------------------------------------------
    #infra_seq: 1                     # infra node identity, explicitly required
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name
    infra_data: /data/infra           # default data path for infrastructure data
    infra_services:                   # home page navigation entries
      - { name: Metrics            ,url: '/vmetrics/vmui/'         ,desc: 'VictoriaMetrics Query UI'    ,icon: metrics  ,name_cn: '指标查询' ,desc_cn: 'VictoriaMetrics 指标查询界面' }
      - { name: Logs               ,url: '/vlogs/select/vmui/'     ,desc: 'VictoriaLogs Query UI'       ,icon: logs     ,name_cn: '日志查询' ,desc_cn: 'VictoriaLogs 日志查询界面' }
      - { name: Traces             ,url: '/vtraces/select/vmui/'   ,desc: 'VictoriaTraces Query UI'     ,icon: traces   ,name_cn: '链路追踪' ,desc_cn: 'VictoriaTraces 链路查询界面' }
      - { name: Monitor Targets    ,url: '/vmetrics/targets'       ,desc: 'Prometheus Scrape Targets'   ,icon: target   ,name_cn: '监控目标' ,desc_cn: 'VictoriaMetrics 监控对象列表' }
      - { name: Alert Rules        ,url: '/vmalert/vmalert/groups' ,desc: 'VMAlert alert/record Rules'  ,icon: alert    ,name_cn: '告警规则' ,desc_cn: 'VMAlert 告警规则管理' }
      - { name: Alert Manager      ,url: '/alertmgr/#/alerts'      ,desc: 'Alert Manage & Silence'      ,icon: alertmgr ,name_cn: '告警管理' ,desc_cn: 'AlertManager 告警管理与屏蔽' }
      - { name: CA Certificate     ,url: '/ca.crt'                 ,desc: 'Self-Signed CA Certificate'  ,icon: lock     ,name_cn: 'CA 证书'  ,desc_cn: 'Pigsty 自签CA根证书' }
      - { name: Software Repo      ,url: '/pigsty'                 ,desc: 'Local YUM/APT Repository'    ,icon: package  ,name_cn: '软件仓库' ,desc_cn: '本地 YUM/APT 软件源' }
      - { name: Explain Visualizer ,url: '/pev'                    ,desc: 'Postgres EXPLAIN Visualizer' ,icon: search   ,name_cn: '执行计划' ,desc_cn: 'PG 执行计划可视化工具' }
    infra_extra_services: []          # extra services to be added on infra home page

    #-----------------------------------------------------------------
    # REPO
    #-----------------------------------------------------------------
    repo_enabled: true                # create a yum repo on this infra node?
    repo_home: /www                   # repo home dir, `/www` by default
    repo_name: pigsty                 # repo name, pigsty by default
    repo_endpoint: http://${admin_ip}:80 # access point to this repo by domain or ip:port
    repo_remove: true                 # remove existing upstream repo
    repo_modules: infra,node,pgsql    # which repo modules are installed in repo_upstream
    repo_upstream:                    # where to download
      - { name: pigsty-local   ,description: 'Pigsty Local'       ,module: local   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://${admin_ip}/pigsty'  } ,meta: { module_hotfixes: 1 }} # used by intranet nodes
      - { name: pigsty-infra   ,description: 'Pigsty INFRA'       ,module: infra   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/yum/infra/$basearch' ,china: 'https://repo.pigsty.cc/yum/infra/$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pigsty-pgsql   ,description: 'Pigsty PGSQL'       ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/yum/pgsql/el$releasever.$basearch' ,china: 'https://repo.pigsty.cc/yum/pgsql/el$releasever.$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: nginx          ,description: 'Nginx Repo'         ,module: infra   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://nginx.org/packages/rhel/$releasever/$basearch/' } ,meta: { module_hotfixes: 1 }}
      - { name: docker-ce      ,description: 'Docker CE'          ,module: infra   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.docker.com/linux/centos/$releasever/$basearch/stable'    ,china: 'https://mirrors.cloud.tencent.com/docker-ce/linux/centos/$releasever/$basearch/stable https://repo.huaweicloud.com/docker-ce/linux/centos/$releasever/$basearch/stable https://mirrors.aliyun.com/docker-ce/linux/centos/$releasever/$basearch/stable' ,europe: 'https://mirrors.xtom.de/docker-ce/linux/centos/$releasever/$basearch/stable' }}
      - { name: baseos         ,description: 'EL 8+ BaseOS'       ,module: node    ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://dl.rockylinux.org/pub/rocky/$releasever/BaseOS/$basearch/os/'     ,china: 'https://mirrors.cloud.tencent.com/rocky/$releasever/BaseOS/$basearch/os/ https://repo.huaweicloud.com/rockylinux/$releasever/BaseOS/$basearch/os/ https://mirrors.aliyun.com/rockylinux/$releasever/BaseOS/$basearch/os/'         ,europe: 'https://mirrors.xtom.de/rocky/$releasever/BaseOS/$basearch/os/'     }}
      - { name: appstream      ,description: 'EL 8+ AppStream'    ,module: node    ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://dl.rockylinux.org/pub/rocky/$releasever/AppStream/$basearch/os/'  ,china: 'https://mirrors.cloud.tencent.com/rocky/$releasever/AppStream/$basearch/os/ https://repo.huaweicloud.com/rockylinux/$releasever/AppStream/$basearch/os/ https://mirrors.aliyun.com/rockylinux/$releasever/AppStream/$basearch/os/'      ,europe: 'https://mirrors.xtom.de/rocky/$releasever/AppStream/$basearch/os/'  }}
      - { name: extras         ,description: 'EL 8+ Extras'       ,module: node    ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://dl.rockylinux.org/pub/rocky/$releasever/extras/$basearch/os/'     ,china: 'https://mirrors.cloud.tencent.com/rocky/$releasever/extras/$basearch/os/ https://repo.huaweicloud.com/rockylinux/$releasever/extras/$basearch/os/ https://mirrors.aliyun.com/rockylinux/$releasever/extras/$basearch/os/'         ,europe: 'https://mirrors.xtom.de/rocky/$releasever/extras/$basearch/os/'     }}
      - { name: powertools     ,description: 'EL 8 PowerTools'    ,module: node    ,releases: [8     ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://dl.rockylinux.org/pub/rocky/$releasever/PowerTools/$basearch/os/' ,china: 'https://mirrors.cloud.tencent.com/rocky/$releasever/PowerTools/$basearch/os/ https://repo.huaweicloud.com/rockylinux/$releasever/PowerTools/$basearch/os/ https://mirrors.aliyun.com/rockylinux/$releasever/PowerTools/$basearch/os/'     ,europe: 'https://mirrors.xtom.de/rocky/$releasever/PowerTools/$basearch/os/' }}
      - { name: crb            ,description: 'EL 9 CRB'           ,module: node    ,releases: [  9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://dl.rockylinux.org/pub/rocky/$releasever/CRB/$basearch/os/'        ,china: 'https://mirrors.cloud.tencent.com/rocky/$releasever/CRB/$basearch/os/ https://repo.huaweicloud.com/rockylinux/$releasever/CRB/$basearch/os/ https://mirrors.aliyun.com/rockylinux/$releasever/CRB/$basearch/os/'            ,europe: 'https://mirrors.xtom.de/rocky/$releasever/CRB/$basearch/os/'        }}
      - { name: epel           ,description: 'EL 8+ EPEL'         ,module: node    ,releases: [8,9   ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://mirrors.edge.kernel.org/fedora-epel/$releasever/Everything/$basearch/' ,china: 'https://mirrors.cloud.tencent.com/epel/$releasever/Everything/$basearch/ https://repo.huaweicloud.com/epel/$releasever/Everything/$basearch/ https://mirrors.aliyun.com/epel/$releasever/Everything/$basearch/'         ,europe: 'https://mirrors.xtom.de/epel/$releasever/Everything/$basearch/'     }}
      - { name: epel           ,description: 'EL 10 EPEL'         ,module: node    ,releases: [    10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://mirrors.edge.kernel.org/fedora-epel/$releasever/Everything/$basearch/'   ,china: 'https://mirrors.cloud.tencent.com/epel/$releasever/Everything/$basearch/ https://repo.huaweicloud.com/epel/$releasever/Everything/$basearch/ https://mirrors.aliyun.com/epel/$releasever/Everything/$basearch/'       ,europe: 'https://mirrors.xtom.de/epel/$releasever/Everything/$basearch/'     }}
      - { name: pgdg-common    ,description: 'PostgreSQL Common'  ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-$releasever-$basearch'          ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/common/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/common/redhat/rhel-$releasever-$basearch'          ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/common/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg14         ,description: 'PostgreSQL 14'      ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-$releasever-$basearch'          ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/14/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/14/redhat/rhel-$releasever-$basearch'          ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/14/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg15         ,description: 'PostgreSQL 15'      ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/15/redhat/rhel-$releasever-$basearch'          ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/15/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/15/redhat/rhel-$releasever-$basearch'          ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/15/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg16         ,description: 'PostgreSQL 16'      ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/16/redhat/rhel-$releasever-$basearch'          ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/16/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/16/redhat/rhel-$releasever-$basearch'          ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/16/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg17         ,description: 'PostgreSQL 17'      ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/17/redhat/rhel-$releasever-$basearch'          ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/17/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/17/redhat/rhel-$releasever-$basearch'          ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/17/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg18         ,description: 'PostgreSQL 18'      ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-$releasever-$basearch'          ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/18/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/18/redhat/rhel-$releasever-$basearch'          ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/18/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg-beta      ,description: 'PostgreSQL Testing' ,module: beta    ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/testing/19/redhat/rhel-$releasever-$basearch'  ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/testing/19/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/testing/19/redhat/rhel-$releasever-$basearch'  ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/testing/19/redhat/rhel-$releasever-$basearch'  } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg-beta      ,description: 'PostgreSQL Testing' ,module: beta    ,releases: [  9,10] ,arch: [        aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/testing/19/redhat/rhel-$releasever-$basearch'  ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/testing/19/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/testing/19/redhat/rhel-$releasever-$basearch'  ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/testing/19/redhat/rhel-$releasever-$basearch'  } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg-extras    ,description: 'PostgreSQL Extra'   ,module: extra   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/extras/redhat/rhel-$releasever-$basearch'      ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/extras/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/extras/redhat/rhel-$releasever-$basearch'      ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/extras/redhat/rhel-$releasever-$basearch'      } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg14-nonfree ,description: 'PostgreSQL 14+'     ,module: extra   ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/non-free/14/redhat/rhel-$releasever-$basearch' ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/non-free/14/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/non-free/14/redhat/rhel-$releasever-$basearch' ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/non-free/14/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg15-nonfree ,description: 'PostgreSQL 15+'     ,module: extra   ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/non-free/15/redhat/rhel-$releasever-$basearch' ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/non-free/15/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/non-free/15/redhat/rhel-$releasever-$basearch' ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/non-free/15/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg16-nonfree ,description: 'PostgreSQL 16+'     ,module: extra   ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/non-free/16/redhat/rhel-$releasever-$basearch' ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/non-free/16/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/non-free/16/redhat/rhel-$releasever-$basearch' ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/non-free/16/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg17-nonfree ,description: 'PostgreSQL 17+'     ,module: extra   ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/non-free/17/redhat/rhel-$releasever-$basearch' ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/non-free/17/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/non-free/17/redhat/rhel-$releasever-$basearch' ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/non-free/17/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg18-nonfree ,description: 'PostgreSQL 18+'     ,module: extra   ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/non-free/18/redhat/rhel-$releasever-$basearch' ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/yum/non-free/18/redhat/rhel-$releasever-$basearch https://repo.pigsty.cc/yum/pgdg/non-free/18/redhat/rhel-$releasever-$basearch' ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/non-free/18/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: timescaledb    ,description: 'TimescaleDB'        ,module: extra   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packagecloud.io/timescale/timescaledb/el/$releasever/$basearch'  }}
      - { name: percona        ,description: 'Percona TDE'        ,module: percona ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/yum/percona/el$releasever.$basearch' ,china: 'https://repo.pigsty.cc/yum/percona/el$releasever.$basearch' ,origin: 'http://repo.percona.com/ppg-18.4/yum/release/$releasever/RPMS/$basearch'  } ,meta: { module_hotfixes: 1 }}
      - { name: wiltondb       ,description: 'WiltonDB'           ,module: mssql   ,releases: [8,9   ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/yum/mssql/el$releasever.$basearch', china: 'https://repo.pigsty.cc/yum/mssql/el$releasever.$basearch' , origin: 'https://download.copr.fedorainfracloud.org/results/wiltondb/wiltondb/epel-$releasever-$basearch/' }}
      - { name: groonga        ,description: 'Groonga'            ,module: groonga ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.groonga.org/almalinux/$releasever/$basearch/' }}
      - { name: mysql          ,description: 'MySQL 8.4 LTS'      ,module: mysql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.mysql.com/yum/mysql-8.4-community/el/$releasever/$basearch/' } ,meta: { module_hotfixes: 1 }}
      - { name: mongo          ,description: 'MongoDB'            ,module: mongo   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/8.0/$basearch/' }}
      - { name: redis          ,description: 'Redis'              ,module: redis   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://rpmfind.net/linux/remi/enterprise/$releasever/redis72/$basearch/' } ,meta: { module_hotfixes: 1 }}
      - { name: grafana        ,description: 'Grafana'            ,module: grafana ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://rpm.grafana.com', china: 'https://mirrors.cloud.tencent.com/grafana/yum/rpm/' }}
      - { name: kubernetes     ,description: 'Kubernetes'         ,module: kube    ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://pkgs.k8s.io/core:/stable:/v1.36/rpm/', china: 'https://mirrors.ustc.edu.cn/kubernetes/core:/stable:/v1.36/rpm/' }}
      - { name: gitlab-ee      ,description: 'Gitlab EE'          ,module: gitlab  ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.gitlab.com/gitlab/gitlab-ee/el/$releasever/$basearch' }}
      - { name: gitlab-ce      ,description: 'Gitlab CE'          ,module: gitlab  ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.gitlab.com/gitlab/gitlab-ce/el/$releasever/$basearch' }}
      - { name: clickhouse     ,description: 'ClickHouse'         ,module: click   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.clickhouse.com/rpm/stable/', china: 'https://repo.huaweicloud.com/clickhouse/rpm/stable/' }}

    repo_packages: [ node-bootstrap, infra-package, infra-addons, node-package1, node-package2, node-package3, pgsql-utility, extra-modules ]
    repo_extra_packages: [ pgsql-main ]
    repo_url_packages: []

    #-----------------------------------------------------------------
    # INFRA_PACKAGE
    #-----------------------------------------------------------------
    infra_packages:                   # packages to be installed on infra nodes
      - grafana,grafana-plugins,grafana-victorialogs-ds,grafana-victoriametrics-ds,victoria-metrics,victoria-logs,victoria-traces,vmutils,vlogscli,alertmanager
      - node-exporter,blackbox-exporter,nginx-exporter,pg-exporter,pev2,nginx,dnsmasq,ansible,etcd,python3-requests,redis,mcli,restic,certbot,python3-certbot-nginx

    #-----------------------------------------------------------------
    # NGINX
    #-----------------------------------------------------------------
    nginx_enabled: true               # enable nginx on this infra node?
    nginx_clean: false                # clean existing nginx config during init?
    nginx_exporter_enabled: true      # enable nginx_exporter on this infra node?
    nginx_exporter_port: 9113         # nginx_exporter listen port, 9113 by default
    nginx_sslmode: enable             # nginx ssl mode? disable,enable,enforce
    nginx_cert_validity: 397d         # nginx self-signed cert validity, 397d by default
    nginx_home: /www                  # nginx content dir, `/www` by default (soft link to nginx_data)
    nginx_data: /data/nginx           # nginx actual data dir, /data/nginx by default
    nginx_users: { admin : pigsty }   # nginx basic auth users: name and pass dict
    nginx_port: 80                    # nginx listen port, 80 by default
    nginx_ssl_port: 443               # nginx ssl listen port, 443 by default
    certbot_sign: false               # sign nginx cert with certbot during setup?
    certbot_email: [email protected]     # certbot email address, used for free ssl
    certbot_options: ''               # certbot extra options

    #-----------------------------------------------------------------
    # DNS
    #-----------------------------------------------------------------
    dns_enabled: true                 # setup dnsmasq on this infra node?
    dns_port: 53                      # dns server listen port, 53 by default
    dns_records:                      # dynamic dns records resolved by dnsmasq
      - "${admin_ip} i.pigsty"
      - "${admin_ip} m.pigsty supa.pigsty api.pigsty adm.pigsty cli.pigsty ddl.pigsty"

    #-----------------------------------------------------------------
    # VICTORIA
    #-----------------------------------------------------------------
    vmetrics_enabled: true            # enable victoria-metrics on this infra node?
    vmetrics_clean: false             # whether clean existing victoria metrics data during init?
    vmetrics_port: 8428               # victoria-metrics listen port, 8428 by default
    vmetrics_scrape_interval: 10s     # victoria global scrape interval, 10s by default
    vmetrics_scrape_timeout: 8s       # victoria global scrape timeout, 8s by default
    vmetrics_options: >-
      -retentionPeriod=15d
      -promscrape.fileSDCheckInterval=5s
    vlogs_enabled: true               # enable victoria-logs on this infra node?
    vlogs_clean: false                # clean victoria-logs data during init?
    vlogs_port: 9428                  # victoria-logs listen port, 9428 by default
    vlogs_options: >-
      -retentionPeriod=15d
      -retention.maxDiskSpaceUsageBytes=50GiB
      -insert.maxLineSizeBytes=1MB
      -search.maxQueryDuration=120s
    vtraces_enabled: true             # enable victoria-traces on this infra node?
    vtraces_clean: false                # clean victoria-trace data during inti?
    vtraces_port: 10428               # victoria-traces listen port, 10428 by default
    vtraces_options: >-
      -retentionPeriod=15d
      -retention.maxDiskSpaceUsageBytes=50GiB
    vmalert_enabled: true             # enable vmalert on this infra node?
    vmalert_port: 8880                # vmalert listen port, 8880 by default
    vmalert_options: ''              # vmalert extra server options

    #-----------------------------------------------------------------
    # PROMETHEUS
    #-----------------------------------------------------------------
    blackbox_enabled: true            # setup blackbox_exporter on this infra node?
    blackbox_port: 9115               # blackbox_exporter listen port, 9115 by default
    blackbox_options: ''              # blackbox_exporter extra server options
    alertmanager_enabled: true        # setup alertmanager on this infra node?
    alertmanager_port: 9059           # alertmanager listen port, 9059 by default
    alertmanager_options: ''          # alertmanager extra server options
    exporter_metrics_path: /metrics   # exporter metric path, `/metrics` by default

    #-----------------------------------------------------------------
    # GRAFANA
    #-----------------------------------------------------------------
    grafana_enabled: true             # enable grafana on this infra node?
    grafana_port: 3000                # default listen port for grafana
    grafana_clean: false              # clean grafana data during init?
    grafana_admin_username: admin     # grafana admin username, `admin` by default
    grafana_admin_password: pigsty    # grafana admin password, `pigsty` by default
    grafana_auth_proxy: false         # enable grafana auth proxy?
    grafana_pgurl: ''                 # external postgres database url for grafana if given
    grafana_view_password: DBUser.Viewer # password for grafana meta pg datasource


    #================================================================#
    #                         VARS: NODE                             #
    #================================================================#

    #-----------------------------------------------------------------
    # NODE_IDENTITY
    #-----------------------------------------------------------------
    #nodename:           # [INSTANCE] # node instance identity, use hostname if missing, optional
    node_cluster: nodes   # [CLUSTER] # node cluster identity, use 'nodes' if missing, optional
    nodename_overwrite: true          # overwrite node's hostname with nodename?
    nodename_exchange: false          # exchange nodename among play hosts?
    node_id_from_pg: true             # use postgres identity as node identity if applicable?

    #-----------------------------------------------------------------
    # NODE_DNS
    #-----------------------------------------------------------------
    node_write_etc_hosts: true        # modify `/etc/hosts` on target node?
    node_default_etc_hosts:           # static dns records in `/etc/hosts`
      - "${admin_ip} i.pigsty"
    node_etc_hosts: []                # extra static dns records in `/etc/hosts`
    node_dns_method: add              # how to handle dns servers: add,none,overwrite
    node_dns_servers: ['${admin_ip}'] # dynamic nameserver in `/etc/resolv.conf`
    node_dns_options:                 # dns resolv options in `/etc/resolv.conf`
      - options single-request-reopen timeout:1

    #-----------------------------------------------------------------
    # NODE_PACKAGE
    #-----------------------------------------------------------------
    node_repo_modules: local          # upstream repo to be added on node, local by default
    node_repo_remove: true            # remove existing repo on node?
    node_packages: [openssh-server]   # packages to be installed current nodes with latest version
    node_default_packages:            # default packages to be installed on all nodes
      - lz4,unzip,bzip2,pv,jq,git,ncdu,make,patch,bash,lsof,wget,uuid,tuned,nvme-cli,numactl,sysstat,iotop,htop,rsync,tcpdump
      - python3,python3-pip,socat,lrzsz,net-tools,ipvsadm,telnet,ca-certificates,openssl,keepalived,etcd,haproxy,chrony,pig
      - zlib,yum,audit,bind-utils,readline,vim-minimal,node-exporter,grubby,openssh-server,openssh-clients,chkconfig,vector
    node_uv_env: /data/venv           # uv venv path, empty string to skip
    node_pip_packages: ''             # pip packages to install in uv venv

    #-----------------------------------------------------------------
    # NODE_SEC
    #-----------------------------------------------------------------
    node_selinux_mode: permissive     # set selinux mode: enforcing,permissive,disabled
    node_firewall_mode: zone          # firewall mode: zone (default), off (disable), none (skip & self-managed)
    node_firewall_intranet:           # which intranet cidr considered as internal network
      - 10.0.0.0/8
      - 192.168.0.0/16
      - 172.16.0.0/12
    node_firewall_public_port:        # expose these ports to public network in (zone, strict) mode
      - 22                            # enable ssh access
      - 80                            # enable http access
      - 443                           # enable https access
      - 5432                          # enable postgres access

    #-----------------------------------------------------------------
    # NODE_TUNE
    #-----------------------------------------------------------------
    node_disable_numa: false          # disable node numa, reboot required
    node_disable_swap: false          # disable node swap, use with caution
    node_static_network: true         # preserve dns resolver settings after reboot
    node_disk_prefetch: false         # setup disk prefetch on HDD to increase performance
    node_kernel_modules: [ softdog, ip_vs, ip_vs_rr, ip_vs_wrr, ip_vs_sh ]
    node_hugepage_count: 0            # number of 2MB hugepage, take precedence over ratio
    node_hugepage_ratio: 0            # node mem hugepage ratio, 0 disable it by default
    node_overcommit_ratio: 0          # node mem overcommit ratio, 0 disable it by default
    node_tune: oltp                   # node tuned profile: none,oltp,olap,crit,tiny
    node_sysctl_params:              # sysctl parameters in k:v format in addition to tuned
      fs.nr_open: 8388608

    #-----------------------------------------------------------------
    # NODE_ADMIN
    #-----------------------------------------------------------------
    node_data: /data                  # node main data directory, `/data` by default
    node_admin_enabled: true          # create a admin user on target node?
    node_admin_uid: 88                # uid and gid for node admin user
    node_admin_username: dba          # name of node admin user, `dba` by default
    node_admin_sudo: nopass           # admin sudo privilege, all,nopass. nopass by default
    node_admin_ssh_exchange: true     # exchange admin ssh key among node cluster
    node_admin_pk_current: true       # add current user's ssh pk to admin authorized_keys
    node_admin_pk_list: []            # ssh public keys to be added to admin user
    node_aliases: {}                  # extra shell aliases to be added, k:v dict

    #-----------------------------------------------------------------
    # NODE_TIME
    #-----------------------------------------------------------------
    node_timezone: ''                 # setup node timezone, empty string to skip
    node_ntp_enabled: true            # enable chronyd time sync service?
    node_ntp_servers:                 # ntp servers in `/etc/chrony.conf`
      - pool pool.ntp.org iburst
    node_crontab_overwrite: true      # overwrite or append to `/etc/crontab`?
    node_crontab: [ ]                 # crontab entries in `/etc/crontab`

    #-----------------------------------------------------------------
    # NODE_VIP
    #-----------------------------------------------------------------
    vip_enabled: false                # enable vip on this node cluster?
    # vip_address:         [IDENTITY] # node vip address in ipv4 format, required if vip is enabled
    # vip_vrid:            [IDENTITY] # required, integer, 1-254, should be unique among same VLAN
    vip_role: backup                  # optional, `master|backup`, backup by default, use as init role
    vip_preempt: false                # optional, `true/false`, false by default, enable vip preemption
    vip_interface: auto               # node vip network interface to listen, `auto` by default
    vip_dns_suffix: ''                # node vip dns name suffix, empty string by default
    vip_auth_pass: ''                 # empty to use '<cls>-<vrid>' as the default
    vip_exporter_port: 9650           # keepalived exporter listen port, 9650 by default

    #-----------------------------------------------------------------
    # HAPROXY
    #-----------------------------------------------------------------
    haproxy_enabled: true             # enable haproxy on this node?
    haproxy_clean: false              # cleanup all existing haproxy config?
    haproxy_reload: true              # reload haproxy after config?
    haproxy_auth_enabled: true        # enable authentication for haproxy admin page
    haproxy_admin_username: admin     # haproxy admin username, `admin` by default
    haproxy_admin_password: pigsty    # haproxy admin password, `pigsty` by default
    haproxy_exporter_port: 9101       # haproxy admin/exporter port, 9101 by default
    haproxy_client_timeout: 24h       # client side connection timeout, 24h by default
    haproxy_server_timeout: 24h       # server side connection timeout, 24h by default
    haproxy_services: []              # list of haproxy service to be exposed on node

    #-----------------------------------------------------------------
    # NODE_EXPORTER
    #-----------------------------------------------------------------
    node_exporter_enabled: true       # setup node_exporter on this node?
    node_exporter_port: 9100          # node exporter listen port, 9100 by default
    node_exporter_options: '--no-collector.softnet --no-collector.nvme --collector.tcpstat --collector.processes'

    #-----------------------------------------------------------------
    # VECTOR
    #-----------------------------------------------------------------
    vector_enabled: true              # enable vector log collector?
    vector_clean: false               # purge vector data dir during init?
    vector_data: /data/vector         # vector data dir, /data/vector by default
    vector_port: 9598                 # vector metrics port, 9598 by default
    vector_read_from: beginning       # vector read from beginning or end
    vector_log_endpoint: [ infra ]    # if defined, sending vector log to this endpoint.


    #================================================================#
    #                        VARS: DOCKER                            #
    #================================================================#
    docker_enabled: false             # enable docker on this node?
    docker_data: /data/docker         # docker data directory, /data/docker by default
    docker_storage_driver: overlay2   # docker storage driver, can be zfs, btrfs
    docker_cgroups_driver: systemd    # docker cgroup fs driver: cgroupfs,systemd
    docker_registry_mirrors: []       # docker registry mirror list
    docker_exporter_port: 9323        # docker metrics exporter port, 9323 by default
    docker_image: []                  # docker image to be pulled after bootstrap
    docker_image_cache: /tmp/docker/*.tgz # docker image cache glob pattern

    #================================================================#
    #                         VARS: ETCD                             #
    #================================================================#
    #etcd_seq: 1                      # etcd instance identifier, explicitly required
    etcd_cluster: etcd                # etcd cluster & group name, etcd by default
    etcd_safeguard: false             # prevent purging running etcd instance?
    etcd_data: /data/etcd             # etcd data directory, /data/etcd by default
    etcd_port: 2379                   # etcd client port, 2379 by default
    etcd_peer_port: 2380              # etcd peer port, 2380 by default
    etcd_init: new                    # etcd initial cluster state, new or existing
    etcd_election_timeout: 1000       # etcd election timeout, 1000ms by default
    etcd_heartbeat_interval: 100      # etcd heartbeat interval, 100ms by default
    etcd_root_password: Etcd.Root     # etcd root password for RBAC, change it!


    #================================================================#
    #                         VARS: MINIO                            #
    #================================================================#
    #minio_seq: 1                     # minio instance identifier, REQUIRED
    #minio_cluster:                   # minio cluster identifier, REQUIRED (define in cluster vars)
    minio_user: minio                 # minio os user, `minio` by default
    minio_https: true                 # use https for minio, true by default
    minio_node: '${minio_cluster}-${minio_seq}.pigsty' # minio node name pattern
    minio_data: '/data/minio'         # minio data dir(s), use {x...y} to specify multi drivers
    #minio_volumes:                   # minio data volumes, override defaults if specified
    minio_domain: sss.pigsty          # minio external domain name, `sss.pigsty` by default
    minio_port: 9000                  # minio service port, 9000 by default
    minio_admin_port: 9001            # minio console port, 9001 by default
    minio_access_key: minioadmin      # root access key, `minioadmin` by default
    minio_secret_key: S3User.MinIO    # root secret key, `S3User.MinIO` by default
    minio_extra_vars: ''              # extra environment variables
    minio_provision: true             # run minio provisioning tasks?
    minio_alias: sss                  # alias name for local minio deployment
    #minio_endpoint: https://sss.pigsty:9000 # if not specified, overwritten by defaults
    minio_buckets:                    # list of minio bucket to be created
      - { name: pgsql }
      - { name: meta ,versioning: true }
      - { name: data }
    minio_users:                      # list of minio user to be created
      - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
      - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
      - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }
    minio_safeguard: false            # prevent purging running minio instance?
    minio_rm_data: true               # purging minio data and config?
    minio_rm_pkg: false               # uninstall minio packages?


    #================================================================#
    #                         VARS: REDIS                            #
    #================================================================#
    #redis_cluster:        <CLUSTER> # redis cluster name, required identity parameter
    #redis_node: 1            <NODE> # redis node sequence number, node int id required
    #redis_instances: {}      <NODE> # redis instances definition on this redis node
    redis_fs_main: /data/redis        # redis main data directory, `/data/redis` by default
    redis_exporter_enabled: true      # install redis exporter on redis nodes?
    redis_exporter_port: 9121         # redis exporter listen port, 9121 by default
    redis_exporter_options: ''        # cli args and extra options for redis exporter
    redis_type: redis                 # redis implementation: redis or valkey
    redis_mode: standalone            # redis mode: standalone,cluster,sentinel
    redis_conf: redis.conf            # redis config template path, except sentinel
    redis_bind_address: '0.0.0.0'     # redis bind address, empty string will use host ip
    redis_max_memory: 1GB             # max memory used by each redis instance
    redis_mem_policy: allkeys-lru     # redis memory eviction policy
    redis_password: ''                # redis password, empty string will disable password
    redis_rdb_save: ['1200 1']        # redis rdb save directives, disable with empty list
    redis_aof_enabled: false          # enable redis append only file?
    redis_rename_commands: {}         # rename redis dangerous commands
    redis_cluster_replicas: 1         # replica number for one master in redis cluster
    redis_sentinel_monitor: []        # sentinel master list, works on sentinel cluster only
    redis_safeguard: false            # prevent purging running redis instance?
    redis_rm_data: true               # remove redis data dir?
    redis_rm_pkg: false               # uninstall selected engine & redis-exporter packages?


    #================================================================#
    #                         VARS: PGSQL                            #
    #================================================================#

    #-----------------------------------------------------------------
    # PG_IDENTITY
    #-----------------------------------------------------------------
    pg_mode: pgsql          #CLUSTER  # pgsql cluster mode: pgsql,citus,mssql,mysql,ivory,pgtde,polar,gpsql,agens,oriole,pgedge
    # pg_cluster:           #CLUSTER  # pgsql cluster name, required identity parameter
    # pg_seq: 0             #INSTANCE # pgsql instance seq number, required identity parameter
    # pg_role: replica      #INSTANCE # pgsql role, required, could be primary,replica,offline
    # pg_instances: {}      #INSTANCE # define multiple pg instances on node in `{port:ins_vars}` format
    # pg_upstream:          #INSTANCE # repl upstream ip addr for standby cluster or cascade replica
    # pg_shard:             #CLUSTER  # pgsql shard name, optional identity for sharding clusters
    # pg_group: 0           #CLUSTER  # pgsql shard index number, optional identity for sharding clusters
    # gp_role: master       #CLUSTER  # greenplum role of this cluster, could be master or segment
    pg_offline_query: false #INSTANCE # set to true to enable offline queries on this instance

    #-----------------------------------------------------------------
    # PG_BUSINESS
    #-----------------------------------------------------------------
    # postgres business object definition, overwrite in group vars
    pg_users: []                      # postgres business users
    pg_databases: []                  # postgres business databases
    pg_services: []                   # postgres business services
    pg_hba_rules: []                  # business hba rules for postgres
    pgb_hba_rules: []                 # business hba rules for pgbouncer
    pg_crontab: []                    # postgres crontab entries for dbsu
    # global credentials, overwrite in global vars
    pg_dbsu_password: ''              # dbsu password, empty string means no dbsu password by default
    pg_replication_username: replicator
    pg_replication_password: DBUser.Replicator
    pg_admin_username: dbuser_dba
    pg_admin_password: DBUser.DBA
    pg_monitor_username: dbuser_monitor
    pg_monitor_password: DBUser.Monitor

    #-----------------------------------------------------------------
    # PG_INSTALL
    #-----------------------------------------------------------------
    pg_dbsu: postgres                 # os dbsu name, postgres by default, better not change it
    pg_dbsu_uid: 26                   # os dbsu uid and gid, 26 for default postgres users and groups
    pg_dbsu_sudo: limit               # dbsu sudo privilege, none,limit,all,nopass. limit by default
    pg_dbsu_home: /var/lib/pgsql      # postgresql home directory, `/var/lib/pgsql` by default
    pg_dbsu_ssh_exchange: true        # exchange postgres dbsu ssh key among same pgsql cluster
    pg_version: 18                    # postgres major version to be installed, 18 by default
    pg_bin_dir: /usr/pgsql/bin        # postgres binary dir, `/usr/pgsql/bin` by default
    pg_log_dir: /pg/log/postgres      # postgres log dir, `/pg/log/postgres` by default
    pg_packages:                      # pg packages to be installed, alias can be used
      - pgsql-main pgsql-common
    pg_extensions: []                 # pg extensions to be installed, alias can be used

    #-----------------------------------------------------------------
    # PG_BOOTSTRAP
    #-----------------------------------------------------------------
    pg_data: /pg/data                 # postgres data directory, `/pg/data` by default
    pg_fs_main: /data/postgres        # postgres main data directory, `/data/postgres` by default
    pg_fs_backup: /data/backups       # postgres backup data directory, `/data/backups` by default
    pg_storage_type: SSD              # storage type for pg main data, SSD,HDD, SSD by default
    pg_dummy_filesize: 64MiB          # size of `/pg/dummy`, hold 64MB disk space for emergency use
    pg_listen: '0.0.0.0'              # postgres/pgbouncer listen addresses, comma separated list
    pg_port: 5432                     # postgres listen port, 5432 by default
    pg_localhost: /var/run/postgresql # postgres unix socket dir for localhost connection
    patroni_enabled: true             # if disabled, no postgres cluster will be created during init
    patroni_mode: default             # patroni working mode: default,pause,remove
    pg_namespace: /pg                 # top level key namespace in etcd, used by patroni & vip
    patroni_port: 8008                # patroni listen port, 8008 by default
    patroni_log_dir: /pg/log/patroni  # patroni log dir, `/pg/log/patroni` by default
    patroni_ssl_enabled: false        # secure patroni RestAPI communications with SSL?
    patroni_watchdog_mode: 'off'      # patroni watchdog mode: automatic,required,off. off by default
    patroni_username: postgres        # patroni restapi username, `postgres` by default
    patroni_password: Patroni.API     # patroni restapi password, `Patroni.API` by default
    pg_etcd_password: ''              # etcd password for this pg cluster, '' to use pg_cluster
    pg_primary_db: postgres           # primary database name, used by citus,etc... ,postgres by default
    pg_parameters: {}                 # extra parameters in postgresql.auto.conf
    pg_files: []                      # extra files to be copied to postgres data directory (e.g. license)
    pg_conf: oltp.yml                 # config template: oltp,olap,crit,tiny. `oltp.yml` by default
    pg_max_conn: auto                 # postgres max connections, `auto` will use recommended value
    pg_shared_buffer_ratio: 0.25      # postgres shared buffers ratio, 0.25 by default, 0.1~0.4
    pg_io_method: worker              # io method for postgres, auto,fsync,worker,io_uring, worker by default
    pg_rto: norm                      # shared rto mode for patroni & haproxy: fast,norm,safe,wide
    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 ]
      norm: [ 30  ,5  ,10 ,25 ,5  ,'2s' ,'1s'   ,'2s' ,3 ,3 ]
      safe: [ 60  ,10 ,20 ,45 ,10 ,'3s' ,'1.5s' ,'3s' ,3 ,3 ]
      wide: [ 120 ,20 ,30 ,95 ,15 ,'4s' ,'2s'   ,'4s' ,3 ,3 ]
    pg_rpo: 1048576                   # recovery point objective in bytes, `1MiB` at most by default
    pg_libs: 'pg_stat_statements, auto_explain'  # preloaded libraries, `pg_stat_statements,auto_explain` by default
    pg_delay: 0                       # replication apply delay for standby cluster leader
    pg_checksum: true                 # enable data checksum for postgres cluster?
    pg_pwd_enc: scram-sha-256         # password encryption algorithm
    pg_encoding: UTF8                 # database cluster encoding, `UTF8` by default
    pg_locale: C                      # database cluster local, `C` by default
    pg_lc_collate: C                  # database cluster collate, `C` by default
    pg_lc_ctype: C                    # database character type, `C` by default
    #pgsodium_key: ""                 # pgsodium key, 64 hex digit, default to sha256(pg_cluster)
    #pgsodium_getkey_script: ""       # pgsodium getkey script path, pgsodium_getkey by default

    #-----------------------------------------------------------------
    # PG_PROVISION
    #-----------------------------------------------------------------
    pg_provision: true                # provision postgres cluster after bootstrap
    pg_init: pg-init                  # provision init script for cluster template, `pg-init` by default
    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  ,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 }
    pg_default_privileges:            # default privileges when created by admin user
      - 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
    pg_default_schemas: [ monitor ]   # default schemas to be created
    pg_default_extensions:            # default extensions to be created
      - { name: pg_stat_statements ,schema: monitor }
      - { name: pgstattuple        ,schema: monitor }
      - { name: pg_buffercache     ,schema: monitor }
      - { name: pageinspect        ,schema: monitor }
      - { name: pg_prewarm         ,schema: monitor }
      - { name: pg_visibility      ,schema: monitor }
      - { name: pg_freespacemap    ,schema: monitor }
      - { name: postgres_fdw       ,schema: public  }
      - { name: file_fdw           ,schema: public  }
      - { name: btree_gist         ,schema: public  }
      - { name: btree_gin          ,schema: public  }
      - { name: pg_trgm            ,schema: public  }
      - { name: intagg             ,schema: public  }
      - { name: intarray           ,schema: public  }
      - { name: pg_repack }
    pg_reload: true                   # reload postgres after hba changes
    pg_default_hba_rules:             # postgres default host-based authentication rules, order by `order`
      - {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  ,order: 100}
      - {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' ,order: 150}
      - {user: '${repl}'    ,db: replication ,addr: localhost ,auth: pwd   ,title: 'replicator replication from localhost',order: 200}
      - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: pwd   ,title: 'replicator replication from intranet' ,order: 250}
      - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: pwd   ,title: 'replicator postgres db from intranet' ,order: 300}
      - {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' ,order: 350}
      - {user: '${monitor}' ,db: all         ,addr: infra     ,auth: pwd   ,title: 'monitor from infra host with password',order: 400}
      - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: pwd   ,title: 'admin @ intranet nodes with pwd'      ,order: 450}
      - {user: '${admin}'   ,db: all         ,addr: world     ,auth: ssl   ,title: 'admin @ everywhere with ssl & pwd'    ,order: 500}
      - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: pwd   ,title: 'pgbouncer read/write via local socket',order: 550}
      - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: pwd   ,title: 'read/write biz user via password'     ,order: 600}
      - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: pwd   ,title: 'allow etl offline tasks from intranet',order: 650}
    pgb_default_hba_rules:            # pgbouncer default host-based authentication rules, order by `order`
      - {user: '${dbsu}'    ,db: pgbouncer   ,addr: local     ,auth: peer  ,title: 'dbsu local admin access with os ident',order: 100}
      - {user: 'all'        ,db: all         ,addr: localhost ,auth: pwd   ,title: 'allow all user local access with pwd' ,order: 150}
      - {user: '${monitor}' ,db: pgbouncer   ,addr: intra     ,auth: pwd   ,title: 'monitor access via intranet with pwd' ,order: 200}
      - {user: '${monitor}' ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other monitor access addr' ,order: 250}
      - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: pwd   ,title: 'admin access via intranet with pwd'   ,order: 300}
      - {user: '${admin}'   ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other admin access addr'   ,order: 350}
      - {user: 'all'        ,db: all         ,addr: intra     ,auth: pwd   ,title: 'allow all user intra access with pwd' ,order: 400}

    #-----------------------------------------------------------------
    # PG_BACKUP
    #-----------------------------------------------------------------
    pgbackrest_enabled: true          # enable pgbackrest on pgsql host?
    pgbackrest_log_dir: /pg/log/pgbackrest # pgbackrest log dir, `/pg/log/pgbackrest` by default
    pgbackrest_method: local          # pgbackrest repo method: local,minio,[user-defined...]
    pgbackrest_init_backup: true      # take a full backup after pgbackrest is initialized?
    pgbackrest_repo:                  # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
      local:                          # default pgbackrest repo with local posix fs
        path: /pg/backup              # local backup directory, `/pg/backup` by default
        retention_full_type: count    # retention full backups by count
        retention_full: 2             # keep 2, at most 3 full backups when using local fs repo
      minio:                          # optional minio repo for pgbackrest
        type: s3                      # minio is s3-compatible, so s3 is used
        s3_endpoint: sss.pigsty       # minio endpoint domain name, `sss.pigsty` by default
        s3_region: us-east-1          # minio region, us-east-1 by default, useless for minio
        s3_bucket: pgsql              # minio bucket name, `pgsql` by default
        s3_key: pgbackrest            # minio user access key for pgbackrest
        s3_key_secret: S3User.Backup  # minio user secret key for pgbackrest
        s3_uri_style: path            # use path style uri for minio rather than host style
        path: /pgbackrest             # minio backup path, default is `/pgbackrest`
        storage_port: 9000            # minio port, 9000 by default
        storage_ca_file: /etc/pki/ca.crt  # minio ca file path, `/etc/pki/ca.crt` by default
        block: y                      # Enable block incremental backup
        bundle: y                     # bundle small files into a single file
        bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
        cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
        retention_full_type: time     # retention full backup by time on minio repo
        retention_full: 14            # keep full backup for the the last 14 days

    #-----------------------------------------------------------------
    # PG_ACCESS
    #-----------------------------------------------------------------
    pgbouncer_enabled: true           # if disabled, pgbouncer will not be launched on pgsql host
    pgbouncer_port: 6432              # pgbouncer listen port, 6432 by default
    pgbouncer_log_dir: /pg/log/pgbouncer  # pgbouncer log dir, `/pg/log/pgbouncer` by default
    pgbouncer_auth_query: false       # query postgres to retrieve unlisted business users?
    pgbouncer_poolmode: transaction   # pooling mode: transaction,session,statement, transaction by default
    pgbouncer_sslmode: disable        # pgbouncer client ssl mode, disable by default
    pgbouncer_ignore_param: [ extra_float_digits, application_name, TimeZone, DateStyle, IntervalStyle, search_path ]
    pg_weight: 100          #INSTANCE # relative load balance weight in service, 100 by default, 0-255
    pg_service_provider: ''           # dedicate haproxy node group name, or empty string for local nodes by default
    pg_default_service_dest: pgbouncer # default service destination if svc.dest='default'
    pg_default_services:              # postgres default service definitions
      - { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
      - { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
      - { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
      - { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}
    pg_vip_enabled: false             # enable a l2 vip for pgsql primary? false by default
    pg_vip_address: 127.0.0.1/24      # vip address in `<ipv4>/<mask>` format, require if vip is enabled
    pg_vip_interface: auto            # vip network interface to listen, auto by default
    pg_dns_suffix: ''                 # pgsql dns suffix, '' by default
    pg_dns_target: auto               # auto, primary, vip, none, or ad hoc ip

    #-----------------------------------------------------------------
    # PG_MONITOR
    #-----------------------------------------------------------------
    pg_exporter_enabled: true              # enable pg_exporter on pgsql hosts?
    pg_exporter_config: pg_exporter.yml    # pg_exporter configuration file name
    pg_exporter_cache_ttls: '1,10,60,300'  # pg_exporter collector ttl stage in seconds, '1,10,60,300' by default
    pg_exporter_port: 9630                 # pg_exporter listen port, 9630 by default
    pg_exporter_params: 'sslmode=disable'  # extra url parameters for pg_exporter dsn
    pg_exporter_url: ''                    # overwrite auto-generate pg dsn if specified
    pg_exporter_auto_discovery: true       # enable auto database discovery? enabled by default
    pg_exporter_exclude_database: 'template0,template1,postgres' # csv of database that WILL NOT be monitored during auto-discovery
    pg_exporter_include_database: ''       # csv of database that WILL BE monitored during auto-discovery
    pg_exporter_connect_timeout: 200       # pg_exporter connect timeout in ms, 200 by default
    pg_exporter_options: ''                # overwrite extra options for pg_exporter
    pgbouncer_exporter_enabled: true       # enable pgbouncer_exporter on pgsql hosts?
    pgbouncer_exporter_port: 9631          # pgbouncer_exporter listen port, 9631 by default
    pgbouncer_exporter_url: ''             # overwrite auto-generate pgbouncer dsn if specified
    pgbouncer_exporter_options: ''         # overwrite extra options for pgbouncer_exporter
    pgbackrest_exporter_enabled: true      # enable pgbackrest_exporter on pgsql hosts?
    pgbackrest_exporter_port: 9854         # pgbackrest_exporter listen port, 9854 by default
    pgbackrest_exporter_options: >-
      --collect.interval=120
      --log.level=info

    #-----------------------------------------------------------------
    # PG_REMOVE
    #-----------------------------------------------------------------
    pg_safeguard: false               # stop pg_remove running if pg_safeguard is enabled, false by default
    pg_rm_data: true                  # remove postgres data during remove? true by default
    pg_rm_backup: true                # remove pgbackrest backup during primary remove? true by default
    pg_rm_pkg: true                   # uninstall postgres packages during remove? true by default

...

配置解读

demo/el 模板是针对 Enterprise Linux 系列发行版优化的配置。

支持的发行版

  • RHEL 8/9/10
  • Rocky Linux 8/9/10
  • Alma Linux 8/9/10
  • Oracle Linux 8/9

关键特性

  • 使用 EPEL 和 PGDG 软件源
  • 针对 YUM/DNF 包管理器优化
  • 支持 EL 系列特定的软件包名称

适用场景

  • 企业生产环境(推荐 RHEL/Rocky/Alma)
  • 需要长期支持和稳定性保障
  • 使用红帽生态系统的环境

6.28 - demo/debian

Debian/Ubuntu 专用配置模板

demo/debian 配置模板是针对 Debian 和 Ubuntu 发行版优化的配置模板。


配置概览

  • 配置名称: demo/debian
  • 节点数量: 单节点
  • 配置说明:Debian/Ubuntu 专用配置模板
  • 适用系统:d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:metademo/el

启用方式:

./configure -c demo/debian [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/demo/debian.yml

---
#==============================================================#
# File      :   debian.yml
# Desc      :   Default parameters for Debian/Ubuntu in Pigsty
# Ctime     :   2020-05-22
# Mtime     :   2026-08-02
# Docs      :   https://pigsty.io/docs/conf/debian
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#


#==============================================================#
#                        Sandbox (4-node)                      #
#==============================================================#
# admin user : vagrant  (nopass ssh & sudo already set)        #
# 1.  meta    :    10.10.10.10     (2 Core | 4GB)    pg-meta   #
# 2.  node-1  :    10.10.10.11     (1 Core | 1GB)    pg-test-1 #
# 3.  node-2  :    10.10.10.12     (1 Core | 1GB)    pg-test-2 #
# 4.  node-3  :    10.10.10.13     (1 Core | 1GB)    pg-test-3 #
# (replace these ip if your 4-node env have different ip addr) #
# VIP 2: (l2 vip is available inside same LAN )                #
#     pg-meta --->  10.10.10.2 ---> 10.10.10.10                #
#     pg-test --->  10.10.10.3 ---> 10.10.10.1{1,2,3}          #
#==============================================================#


all:

  ##################################################################
  #                            CLUSTERS                            #
  ##################################################################
  # meta nodes, nodes, pgsql, redis, pgsql clusters are defined as
  # k:v pair inside `all.children`. Where the key is cluster name
  # and value is cluster definition consist of two parts:
  # `hosts`: cluster members ip and instance level variables
  # `vars` : cluster level variables
  ##################################################################
  children:                                 # groups definition

    # infra cluster for proxy, monitor, alert, etc..
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }

    # etcd cluster for ha postgres
    etcd: { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }

    # minio cluster, s3 compatible object storage
    minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio } }

    #----------------------------------#
    # pgsql cluster: pg-meta (CMDB)    #
    #----------------------------------#
    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary , pg_offline_query: true } }
      vars:
        pg_cluster: pg-meta

        # define business databases here: https://pigsty.io/docs/pgsql/config/db
        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
            #state: create                  # optional, create|absent|recreate, create by default
            baseline: cmdb.sql              # optional, database sql baseline path, (relative path among ansible search path, e.g: files/)
            schemas: [pigsty]               # optional, additional schemas to be created, array of schema names
            extensions:                     # optional, additional extensions to be installed: array of `{name[,schema]}`
              - { name: vector }            # install pgvector extension on this database by default
            comment: pigsty meta database   # optional, comment string for this database
            #pgbouncer: true                # optional, add this database to pgbouncer database list? true by default
            #owner: postgres                # optional, database owner, current user if not specified
            #template: template1            # optional, which template to use, template1 by default
            #strategy: FILE_COPY            # optional, clone strategy: FILE_COPY or WAL_LOG (PG15+), default to PG's default
            #encoding: UTF8                 # optional, inherited from template / cluster if not defined (UTF8)
            #locale: C                      # optional, inherited from template / cluster if not defined (C)
            #lc_collate: C                  # optional, inherited from template / cluster if not defined (C)
            #lc_ctype: C                    # optional, inherited from template / cluster if not defined (C)
            #locale_provider: libc          # optional, locale provider: libc, icu, builtin (PG15+)
            #icu_locale: en-US              # optional, icu locale for icu locale provider (PG15+)
            #icu_rules: ''                  # optional, icu rules for icu locale provider (PG16+)
            #builtin_locale: C.UTF-8        # optional, builtin locale for builtin locale provider (PG17+)
            #tablespace: pg_default         # optional, default tablespace, pg_default by default
            #is_template: false             # optional, mark database as template, allowing clone by any user with CREATEDB privilege
            #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_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_connlimit: 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 }

        # define business users here: https://pigsty.io/docs/pgsql/config/user
        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
            pgbouncer: true                 # optional, add this user to pgbouncer user-list? false by default (production user should be true explicitly)
            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}
            #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
            #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)
            #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_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    }

        # define business service here: https://pigsty.io/docs/pgsql/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'

        # define pg extensions: https://pigsty.io/docs/pgsql/ext/
        pg_libs: 'pg_stat_statements, auto_explain' # add timescaledb to shared_preload_libraries
        #pg_extensions: [] # extensions to be installed on this cluster

        # define HBA rules here: https://pigsty.io/docs/pgsql/config/hba
        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_crontab:  # make a full backup 1 am everyday
          - '00 01 * * * /pg/bin/pg-backup full'

    #----------------------------------#
    # pgsql cluster: pg-test (3 nodes) #
    #----------------------------------#
    # pg-test --->  10.10.10.3 ---> 10.10.10.1{1,2,3}
    pg-test:                          # define the new 3-node cluster pg-test
      hosts:
        10.10.10.11: { pg_seq: 1, pg_role: primary }   # primary instance, leader of cluster
        10.10.10.12: { pg_seq: 2, pg_role: replica }   # replica instance, follower of leader
        10.10.10.13: { pg_seq: 3, pg_role: replica, pg_offline_query: true } # replica with offline access
      vars:
        pg_cluster: pg-test           # define pgsql cluster name
        pg_users:  [{ name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] }]
        pg_databases: [{ name: test }] # create a database and user named 'test'
        node_tune: tiny
        pg_conf: tiny.yml
        pg_vip_enabled: true
        pg_vip_address: 10.10.10.3/24
        pg_crontab:  # make a full backup on monday 1am, and an incremental backup during weekdays
          - '00 01 * * 1 /pg/bin/pg-backup full'
          - '00 01 * * 2,3,4,5,6,7 /pg/bin/pg-backup'

    #----------------------------------#
    # redis ms, sentinel, native 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 }


  ####################################################################
  #                             VARS                                 #
  ####################################################################
  vars:                               # global variables


    #================================================================#
    #                         VARS: INFRA                            #
    #================================================================#

    #-----------------------------------------------------------------
    # META
    #-----------------------------------------------------------------
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe
    language: en                      # default language: en, zh
    proxy_env:                        # global proxy env when downloading packages
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
      # http_proxy:  # set your proxy here: e.g http://user:[email protected]
      # https_proxy: # set your proxy here: e.g http://user:[email protected]
      # all_proxy:   # set your proxy here: e.g http://user:[email protected]

    #-----------------------------------------------------------------
    # CA
    #-----------------------------------------------------------------
    ca_create: true                   # create ca if not exists? or just abort
    ca_cn: pigsty-ca                  # ca common name, fixed as pigsty-ca
    cert_validity: 7300d              # cert validity, 20 years by default

    #-----------------------------------------------------------------
    # INFRA_IDENTITY
    #-----------------------------------------------------------------
    #infra_seq: 1                     # infra node identity, explicitly required
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name
    infra_data: /data/infra           # default data path for infrastructure data
    infra_services:                   # home page navigation entries
      - { name: Metrics            ,url: '/vmetrics/vmui/'         ,desc: 'VictoriaMetrics Query UI'    ,icon: metrics  ,name_cn: '指标查询' ,desc_cn: 'VictoriaMetrics 指标查询界面' }
      - { name: Logs               ,url: '/vlogs/select/vmui/'     ,desc: 'VictoriaLogs Query UI'       ,icon: logs     ,name_cn: '日志查询' ,desc_cn: 'VictoriaLogs 日志查询界面' }
      - { name: Traces             ,url: '/vtraces/select/vmui/'   ,desc: 'VictoriaTraces Query UI'     ,icon: traces   ,name_cn: '链路追踪' ,desc_cn: 'VictoriaTraces 链路查询界面' }
      - { name: Monitor Targets    ,url: '/vmetrics/targets'       ,desc: 'Prometheus Scrape Targets'   ,icon: target   ,name_cn: '监控目标' ,desc_cn: 'VictoriaMetrics 监控对象列表' }
      - { name: Alert Rules        ,url: '/vmalert/vmalert/groups' ,desc: 'VMAlert alert/record Rules'  ,icon: alert    ,name_cn: '告警规则' ,desc_cn: 'VMAlert 告警规则管理' }
      - { name: Alert Manager      ,url: '/alertmgr/#/alerts'      ,desc: 'Alert Manage & Silence'      ,icon: alertmgr ,name_cn: '告警管理' ,desc_cn: 'AlertManager 告警管理与屏蔽' }
      - { name: CA Certificate     ,url: '/ca.crt'                 ,desc: 'Self-Signed CA Certificate'  ,icon: lock     ,name_cn: 'CA 证书'  ,desc_cn: 'Pigsty 自签CA根证书' }
      - { name: Software Repo      ,url: '/pigsty'                 ,desc: 'Local YUM/APT Repository'    ,icon: package  ,name_cn: '软件仓库' ,desc_cn: '本地 YUM/APT 软件源' }
      - { name: Explain Visualizer ,url: '/pev'                    ,desc: 'Postgres EXPLAIN Visualizer' ,icon: search   ,name_cn: '执行计划' ,desc_cn: 'PG 执行计划可视化工具' }
    infra_extra_services: []          # extra services to be added on infra home page

    #-----------------------------------------------------------------
    # REPO
    #-----------------------------------------------------------------
    repo_enabled: true                # create a yum repo on this infra node?
    repo_home: /www                   # repo home dir, `/www` by default
    repo_name: pigsty                 # repo name, pigsty by default
    repo_endpoint: http://${admin_ip}:80 # access point to this repo by domain or ip:port
    repo_remove: true                 # remove existing upstream repo
    repo_modules: infra,node,pgsql    # which repo modules are installed in repo_upstream
    repo_upstream:                    # where to download
      - { name: pigsty-local   ,description: 'Pigsty Local'       ,module: local   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://${admin_ip}/pigsty ./' }}
      - { name: pigsty-pgsql   ,description: 'Pigsty PgSQL'       ,module: pgsql   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/apt/pgsql/${distro_codename} ${distro_codename} main', china: 'https://repo.pigsty.cc/apt/pgsql/${distro_codename} ${distro_codename} main' }}
      - { name: pigsty-infra   ,description: 'Pigsty Infra'       ,module: infra   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/apt/infra/ generic main' ,china: 'https://repo.pigsty.cc/apt/infra/ generic main' }}
      - { name: nginx          ,description: 'Nginx'              ,module: infra   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://nginx.org/packages/${distro_name} ${distro_codename} nginx' }}
      - { name: docker-ce      ,description: 'Docker'             ,module: infra   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.docker.com/linux/${distro_name} ${distro_codename} stable'                               ,china: 'https://mirrors.cloud.tencent.com/docker-ce/linux/${distro_name} ${distro_codename} stable' }}
      - { name: base           ,description: 'Debian Basic'       ,module: node    ,releases: [11,12,13         ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://deb.debian.org/debian/ ${distro_codename} main non-free-firmware'                                  ,china: 'https://mirrors.cloud.tencent.com/debian/ ${distro_codename} main non-free-firmware' }}
      - { name: updates        ,description: 'Debian Updates'     ,module: node    ,releases: [11,12,13         ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://deb.debian.org/debian/ ${distro_codename}-updates main non-free-firmware'                          ,china: 'https://mirrors.cloud.tencent.com/debian/ ${distro_codename}-updates main non-free-firmware' }}
      - { name: security       ,description: 'Debian Security'    ,module: node    ,releases: [11,12,13         ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://security.debian.org/debian-security ${distro_codename}-security main non-free-firmware'            ,china: 'https://mirrors.cloud.tencent.com/debian-security/ ${distro_codename}-security main non-free-firmware' }}
      - { name: base           ,description: 'Ubuntu Basic'       ,module: node    ,releases: [         22,24,26] ,arch: [x86_64         ] ,baseurl: { default: 'https://mirrors.edge.kernel.org/ubuntu/ ${distro_codename}           main universe multiverse restricted' ,china: 'https://mirrors.cloud.tencent.com/ubuntu/ ${distro_codename}           main restricted universe multiverse' }}
      - { name: updates        ,description: 'Ubuntu Updates'     ,module: node    ,releases: [         22,24,26] ,arch: [x86_64         ] ,baseurl: { default: 'https://mirrors.edge.kernel.org/ubuntu/ ${distro_codename}-updates   main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu/ ${distro_codename}-updates   main restricted universe multiverse' }}
      - { name: backports      ,description: 'Ubuntu Backports'   ,module: node    ,releases: [         22,24,26] ,arch: [x86_64         ] ,baseurl: { default: 'https://mirrors.edge.kernel.org/ubuntu/ ${distro_codename}-backports main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu/ ${distro_codename}-backports main restricted universe multiverse' }}
      - { name: security       ,description: 'Ubuntu Security'    ,module: node    ,releases: [         22,24,26] ,arch: [x86_64         ] ,baseurl: { default: 'https://mirrors.edge.kernel.org/ubuntu/ ${distro_codename}-security  main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu/ ${distro_codename}-security  main restricted universe multiverse' }}
      - { name: base           ,description: 'Ubuntu Basic'       ,module: node    ,releases: [         22,24,26] ,arch: [        aarch64] ,baseurl: { default: 'http://ports.ubuntu.com/ubuntu-ports/ ${distro_codename}             main universe multiverse restricted' ,china: 'https://mirrors.cloud.tencent.com/ubuntu-ports/ ${distro_codename}           main restricted universe multiverse' }}
      - { name: updates        ,description: 'Ubuntu Updates'     ,module: node    ,releases: [         22,24,26] ,arch: [        aarch64] ,baseurl: { default: 'http://ports.ubuntu.com/ubuntu-ports/ ${distro_codename}-updates     main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu-ports/ ${distro_codename}-updates   main restricted universe multiverse' }}
      - { name: backports      ,description: 'Ubuntu Backports'   ,module: node    ,releases: [         22,24,26] ,arch: [        aarch64] ,baseurl: { default: 'http://ports.ubuntu.com/ubuntu-ports/ ${distro_codename}-backports   main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu-ports/ ${distro_codename}-backports main restricted universe multiverse' }}
      - { name: security       ,description: 'Ubuntu Security'    ,module: node    ,releases: [         22,24,26] ,arch: [        aarch64] ,baseurl: { default: 'http://ports.ubuntu.com/ubuntu-ports/ ${distro_codename}-security    main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu-ports/ ${distro_codename}-security  main restricted universe multiverse' }}
      - { name: pgdg           ,description: 'PGDG'               ,module: pgsql   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://apt.postgresql.org/pub/repos/apt/ ${distro_codename}-pgdg main' ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/apt/ ${distro_codename}-pgdg main' }}
      - { name: pgdg-beta      ,description: 'PGDG Beta'          ,module: beta    ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://apt.postgresql.org/pub/repos/apt/ ${distro_codename}-pgdg-testing main 19' ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/apt/ ${distro_codename}-pgdg-testing main 19' }}
      - { name: timescaledb    ,description: 'TimescaleDB'        ,module: extra   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packagecloud.io/timescale/timescaledb/${distro_name}/ ${distro_codename} main' }}
      - { name: citus          ,description: 'Citus'              ,module: extra   ,releases: [11,12,   22      ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packagecloud.io/citusdata/community/${distro_name}/ ${distro_codename} main' } }
      - { name: percona        ,description: 'Percona TDE'        ,module: percona ,releases: [   12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/apt/percona ${distro_codename} main' ,china: 'https://repo.pigsty.cc/apt/percona ${distro_codename} main' ,origin: 'http://repo.percona.com/ppg-18.4/apt ${distro_codename} main' }}
      - { name: groonga        ,description: 'Groonga Debian'     ,module: groonga ,releases: [11,12,13         ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.groonga.org/debian/ ${distro_codename} main' }}
      - { name: groonga        ,description: 'Groonga Ubuntu'     ,module: groonga ,releases: [         22,24   ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://ppa.launchpadcontent.net/groonga/ppa/ubuntu/ ${distro_codename} main' }}
      - { name: mysql          ,description: 'MySQL 8.4 LTS'      ,module: mysql   ,releases: [   12,13,22,24   ] ,arch: [x86_64         ] ,baseurl: { default: 'https://repo.mysql.com/apt/${distro_name} ${distro_codename} mysql-8.4-lts', china: 'https://mirrors.ustc.edu.cn/mysql-repo/apt/${distro_name} ${distro_codename} mysql-8.4-lts' }}
      - { name: mongo          ,description: 'MongoDB'            ,module: mongo   ,releases: [   12,   22,24   ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.mongodb.org/apt/${distro_name} ${distro_codename}/mongodb-org/8.0 multiverse', china: 'https://mirrors.cloud.tencent.com/mongodb/apt/${distro_name} ${distro_codename}/mongodb-org/8.0 multiverse' }}
      - { name: redis          ,description: 'Redis'              ,module: redis   ,releases: [11,12,   22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.redis.io/deb ${distro_codename} main' }}
      - { name: llvm           ,description: 'LLVM'               ,module: llvm    ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://apt.llvm.org/${distro_codename}/ llvm-toolchain-${distro_codename} main' ,china: 'https://mirrors.tuna.tsinghua.edu.cn/llvm-apt/${distro_codename}/ llvm-toolchain-${distro_codename} main' }}
      - { name: haproxyd       ,description: 'Haproxy Debian'     ,module: haproxy ,releases: [   12            ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://haproxy.debian.net/ ${distro_codename}-backports-3.2 main' }}
      - { name: haproxyu       ,description: 'Haproxy Ubuntu'     ,module: haproxy ,releases: [            24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://ppa.launchpadcontent.net/vbernat/haproxy-3.2/ubuntu/ ${distro_codename} main' }}
      - { name: grafana        ,description: 'Grafana'            ,module: grafana ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://apt.grafana.com stable main' ,china: 'https://mirrors.cloud.tencent.com/grafana/apt/ stable main' }}
      - { name: kubernetes     ,description: 'Kubernetes'         ,module: kube    ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /', china: 'https://mirrors.ustc.edu.cn/kubernetes/core:/stable:/v1.36/deb/ /' }}
      - { name: gitlab-ee      ,description: 'Gitlab EE'          ,module: gitlab  ,releases: [11,12,13,22,24   ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.gitlab.com/gitlab/gitlab-ee/${distro_name}/ ${distro_codename} main' }}
      - { name: gitlab-ce      ,description: 'Gitlab CE'          ,module: gitlab  ,releases: [11,12,13,22,24   ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.gitlab.com/gitlab/gitlab-ce/${distro_name}/ ${distro_codename} main' }}
      - { name: clickhouse     ,description: 'ClickHouse'         ,module: click   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.clickhouse.com/deb/ stable main', china: 'https://repo.huaweicloud.com/clickhouse/deb/ stable main' }}

    repo_packages: [ node-bootstrap, infra-package, infra-addons, node-package1, node-package2, node-package3, pgsql-utility, extra-modules ]
    repo_extra_packages: [ pgsql-main ]
    repo_url_packages: []

    #-----------------------------------------------------------------
    # INFRA_PACKAGE
    #-----------------------------------------------------------------
    infra_packages:                   # packages to be installed on infra nodes
      - grafana,grafana-plugins,grafana-victorialogs-ds,grafana-victoriametrics-ds,victoria-metrics,victoria-logs,victoria-traces,vmutils,vlogscli,alertmanager
      - node-exporter,blackbox-exporter,nginx-exporter,pg-exporter,pev2,nginx,dnsmasq,ansible,etcd,python3-requests,redis,mcli,restic,certbot,python3-certbot-nginx

    #-----------------------------------------------------------------
    # NGINX
    #-----------------------------------------------------------------
    nginx_enabled: true               # enable nginx on this infra node?
    nginx_clean: false                # clean existing nginx config during init?
    nginx_exporter_enabled: true      # enable nginx_exporter on this infra node?
    nginx_exporter_port: 9113         # nginx_exporter listen port, 9113 by default
    nginx_sslmode: enable             # nginx ssl mode? disable,enable,enforce
    nginx_cert_validity: 397d         # nginx self-signed cert validity, 397d by default
    nginx_home: /www                  # nginx content dir, `/www` by default (soft link to nginx_data)
    nginx_data: /data/nginx           # nginx actual data dir, /data/nginx by default
    nginx_users: { admin : pigsty }   # nginx basic auth users: name and pass dict
    nginx_port: 80                    # nginx listen port, 80 by default
    nginx_ssl_port: 443               # nginx ssl listen port, 443 by default
    certbot_sign: false               # sign nginx cert with certbot during setup?
    certbot_email: [email protected]     # certbot email address, used for free ssl
    certbot_options: ''               # certbot extra options

    #-----------------------------------------------------------------
    # DNS
    #-----------------------------------------------------------------
    dns_enabled: true                 # setup dnsmasq on this infra node?
    dns_port: 53                      # dns server listen port, 53 by default
    dns_records:                      # dynamic dns records resolved by dnsmasq
      - "${admin_ip} i.pigsty"
      - "${admin_ip} m.pigsty supa.pigsty api.pigsty adm.pigsty cli.pigsty ddl.pigsty"

    #-----------------------------------------------------------------
    # VICTORIA
    #-----------------------------------------------------------------
    vmetrics_enabled: true            # enable victoria-metrics on this infra node?
    vmetrics_clean: false             # whether clean existing victoria metrics data during init?
    vmetrics_port: 8428               # victoria-metrics listen port, 8428 by default
    vmetrics_scrape_interval: 10s     # victoria global scrape interval, 10s by default
    vmetrics_scrape_timeout: 8s       # victoria global scrape timeout, 8s by default
    vmetrics_options: >-
      -retentionPeriod=15d
      -promscrape.fileSDCheckInterval=5s
    vlogs_enabled: true               # enable victoria-logs on this infra node?
    vlogs_clean: false                # clean victoria-logs data during init?
    vlogs_port: 9428                  # victoria-logs listen port, 9428 by default
    vlogs_options: >-
      -retentionPeriod=15d
      -retention.maxDiskSpaceUsageBytes=50GiB
      -insert.maxLineSizeBytes=1MB
      -search.maxQueryDuration=120s
    vtraces_enabled: true             # enable victoria-traces on this infra node?
    vtraces_clean: false                # clean victoria-trace data during inti?
    vtraces_port: 10428               # victoria-traces listen port, 10428 by default
    vtraces_options: >-
      -retentionPeriod=15d
      -retention.maxDiskSpaceUsageBytes=50GiB
    vmalert_enabled: true             # enable vmalert on this infra node?
    vmalert_port: 8880                # vmalert listen port, 8880 by default
    vmalert_options: ''              # vmalert extra server options

    #-----------------------------------------------------------------
    # PROMETHEUS
    #-----------------------------------------------------------------
    blackbox_enabled: true            # setup blackbox_exporter on this infra node?
    blackbox_port: 9115               # blackbox_exporter listen port, 9115 by default
    blackbox_options: ''              # blackbox_exporter extra server options
    alertmanager_enabled: true        # setup alertmanager on this infra node?
    alertmanager_port: 9059           # alertmanager listen port, 9059 by default
    alertmanager_options: ''          # alertmanager extra server options
    exporter_metrics_path: /metrics   # exporter metric path, `/metrics` by default

    #-----------------------------------------------------------------
    # GRAFANA
    #-----------------------------------------------------------------
    grafana_enabled: true             # enable grafana on this infra node?
    grafana_port: 3000                # default listen port for grafana
    grafana_clean: false              # clean grafana data during init?
    grafana_admin_username: admin     # grafana admin username, `admin` by default
    grafana_admin_password: pigsty    # grafana admin password, `pigsty` by default
    grafana_auth_proxy: false         # enable grafana auth proxy?
    grafana_pgurl: ''                 # external postgres database url for grafana if given
    grafana_view_password: DBUser.Viewer # password for grafana meta pg datasource


    #================================================================#
    #                         VARS: NODE                             #
    #================================================================#

    #-----------------------------------------------------------------
    # NODE_IDENTITY
    #-----------------------------------------------------------------
    #nodename:           # [INSTANCE] # node instance identity, use hostname if missing, optional
    node_cluster: nodes   # [CLUSTER] # node cluster identity, use 'nodes' if missing, optional
    nodename_overwrite: true          # overwrite node's hostname with nodename?
    nodename_exchange: false          # exchange nodename among play hosts?
    node_id_from_pg: true             # use postgres identity as node identity if applicable?

    #-----------------------------------------------------------------
    # NODE_DNS
    #-----------------------------------------------------------------
    node_write_etc_hosts: true        # modify `/etc/hosts` on target node?
    node_default_etc_hosts:           # static dns records in `/etc/hosts`
      - "${admin_ip} i.pigsty"
    node_etc_hosts: []                # extra static dns records in `/etc/hosts`
    node_dns_method: add              # how to handle dns servers: add,none,overwrite
    node_dns_servers: ['${admin_ip}'] # dynamic nameserver in `/etc/resolv.conf`
    node_dns_options:                 # dns resolv options in `/etc/resolv.conf`
      - options single-request-reopen timeout:1

    #-----------------------------------------------------------------
    # NODE_PACKAGE
    #-----------------------------------------------------------------
    node_repo_modules: local          # upstream repo to be added on node, local by default
    node_repo_remove: true            # remove existing repo on node?
    node_packages: [openssh-server]   # packages to be installed current nodes with latest version
    node_default_packages:            # default packages to be installed on all nodes
      - lz4,unzip,bzip2,pv,jq,git,ncdu,make,patch,bash,lsof,wget,uuid,tuned,nvme-cli,numactl,sysstat,iotop,htop,rsync,tcpdump
      - python3,python3-pip,socat,lrzsz,net-tools,ipvsadm,telnet,ca-certificates,openssl,keepalived,etcd,haproxy,chrony,pig
      - zlib1g,acl,dnsutils,libreadline-dev,vim-tiny,node-exporter,openssh-server,openssh-client,vector
    node_uv_env: /data/venv           # uv venv path, empty string to skip
    node_pip_packages: ''             # pip packages to install in uv venv

    #-----------------------------------------------------------------
    # NODE_SEC
    #-----------------------------------------------------------------
    node_selinux_mode: permissive     # set selinux mode: enforcing,permissive,disabled
    node_firewall_mode: zone          # firewall mode: zone (default), off (disable), none (skip & self-managed)
    node_firewall_intranet:           # which intranet cidr considered as internal network
      - 10.0.0.0/8
      - 192.168.0.0/16
      - 172.16.0.0/12
    node_firewall_public_port:        # expose these ports to public network in (zone, strict) mode
      - 22                            # enable ssh access
      - 80                            # enable http access
      - 443                           # enable https access
      - 5432                          # enable postgres access

    #-----------------------------------------------------------------
    # NODE_TUNE
    #-----------------------------------------------------------------
    node_disable_numa: false          # disable node numa, reboot required
    node_disable_swap: false          # disable node swap, use with caution
    node_static_network: true         # preserve dns resolver settings after reboot
    node_disk_prefetch: false         # setup disk prefetch on HDD to increase performance
    node_kernel_modules: [ softdog, ip_vs, ip_vs_rr, ip_vs_wrr, ip_vs_sh ]
    node_hugepage_count: 0            # number of 2MB hugepage, take precedence over ratio
    node_hugepage_ratio: 0            # node mem hugepage ratio, 0 disable it by default
    node_overcommit_ratio: 0          # node mem overcommit ratio, 0 disable it by default
    node_tune: oltp                   # node tuned profile: none,oltp,olap,crit,tiny
    node_sysctl_params:              # sysctl parameters in k:v format in addition to tuned
      fs.nr_open: 8388608

    #-----------------------------------------------------------------
    # NODE_ADMIN
    #-----------------------------------------------------------------
    node_data: /data                  # node main data directory, `/data` by default
    node_admin_enabled: true          # create a admin user on target node?
    node_admin_uid: 88                # uid and gid for node admin user
    node_admin_username: dba          # name of node admin user, `dba` by default
    node_admin_sudo: nopass           # admin sudo privilege, all,nopass. nopass by default
    node_admin_ssh_exchange: true     # exchange admin ssh key among node cluster
    node_admin_pk_current: true       # add current user's ssh pk to admin authorized_keys
    node_admin_pk_list: []            # ssh public keys to be added to admin user
    node_aliases: {}                  # extra shell aliases to be added, k:v dict

    #-----------------------------------------------------------------
    # NODE_TIME
    #-----------------------------------------------------------------
    node_timezone: ''                 # setup node timezone, empty string to skip
    node_ntp_enabled: true            # enable chronyd time sync service?
    node_ntp_servers:                 # ntp servers in `/etc/chrony.conf`
      - pool pool.ntp.org iburst
    node_crontab_overwrite: true      # overwrite or append to `/etc/crontab`?
    node_crontab: [ ]                 # crontab entries in `/etc/crontab`

    #-----------------------------------------------------------------
    # NODE_VIP
    #-----------------------------------------------------------------
    vip_enabled: false                # enable vip on this node cluster?
    # vip_address:         [IDENTITY] # node vip address in ipv4 format, required if vip is enabled
    # vip_vrid:            [IDENTITY] # required, integer, 1-254, should be unique among same VLAN
    vip_role: backup                  # optional, `master|backup`, backup by default, use as init role
    vip_preempt: false                # optional, `true/false`, false by default, enable vip preemption
    vip_interface: auto               # node vip network interface to listen, `auto` by default
    vip_dns_suffix: ''                # node vip dns name suffix, empty string by default
    vip_auth_pass: ''                 # empty to use '<cls>-<vrid>' as the default
    vip_exporter_port: 9650           # keepalived exporter listen port, 9650 by default

    #-----------------------------------------------------------------
    # HAPROXY
    #-----------------------------------------------------------------
    haproxy_enabled: true             # enable haproxy on this node?
    haproxy_clean: false              # cleanup all existing haproxy config?
    haproxy_reload: true              # reload haproxy after config?
    haproxy_auth_enabled: true        # enable authentication for haproxy admin page
    haproxy_admin_username: admin     # haproxy admin username, `admin` by default
    haproxy_admin_password: pigsty    # haproxy admin password, `pigsty` by default
    haproxy_exporter_port: 9101       # haproxy admin/exporter port, 9101 by default
    haproxy_client_timeout: 24h       # client side connection timeout, 24h by default
    haproxy_server_timeout: 24h       # server side connection timeout, 24h by default
    haproxy_services: []              # list of haproxy service to be exposed on node

    #-----------------------------------------------------------------
    # NODE_EXPORTER
    #-----------------------------------------------------------------
    node_exporter_enabled: true       # setup node_exporter on this node?
    node_exporter_port: 9100          # node exporter listen port, 9100 by default
    node_exporter_options: '--no-collector.softnet --no-collector.nvme --collector.tcpstat --collector.processes'

    #-----------------------------------------------------------------
    # VECTOR
    #-----------------------------------------------------------------
    vector_enabled: true              # enable vector log collector?
    vector_clean: false               # purge vector data dir during init?
    vector_data: /data/vector         # vector data dir, /data/vector by default
    vector_port: 9598                 # vector metrics port, 9598 by default
    vector_read_from: beginning       # vector read from beginning or end
    vector_log_endpoint: [ infra ]    # if defined, sending vector log to this endpoint.


    #================================================================#
    #                        VARS: DOCKER                            #
    #================================================================#
    docker_enabled: false             # enable docker on this node?
    docker_data: /data/docker         # docker data directory, /data/docker by default
    docker_storage_driver: overlay2   # docker storage driver, can be zfs, btrfs
    docker_cgroups_driver: systemd    # docker cgroup fs driver: cgroupfs,systemd
    docker_registry_mirrors: []       # docker registry mirror list
    docker_exporter_port: 9323        # docker metrics exporter port, 9323 by default
    docker_image: []                  # docker image to be pulled after bootstrap
    docker_image_cache: /tmp/docker/*.tgz # docker image cache glob pattern

    #================================================================#
    #                         VARS: ETCD                             #
    #================================================================#
    #etcd_seq: 1                      # etcd instance identifier, explicitly required
    etcd_cluster: etcd                # etcd cluster & group name, etcd by default
    etcd_safeguard: false             # prevent purging running etcd instance?
    etcd_data: /data/etcd             # etcd data directory, /data/etcd by default
    etcd_port: 2379                   # etcd client port, 2379 by default
    etcd_peer_port: 2380              # etcd peer port, 2380 by default
    etcd_init: new                    # etcd initial cluster state, new or existing
    etcd_election_timeout: 1000       # etcd election timeout, 1000ms by default
    etcd_heartbeat_interval: 100      # etcd heartbeat interval, 100ms by default
    etcd_root_password: Etcd.Root     # etcd root password for RBAC, change it!


    #================================================================#
    #                         VARS: MINIO                            #
    #================================================================#
    #minio_seq: 1                     # minio instance identifier, REQUIRED
    #minio_cluster:                   # minio cluster identifier, REQUIRED (define in cluster vars)
    minio_user: minio                 # minio os user, `minio` by default
    minio_https: true                 # use https for minio, true by default
    minio_node: '${minio_cluster}-${minio_seq}.pigsty' # minio node name pattern
    minio_data: '/data/minio'         # minio data dir(s), use {x...y} to specify multi drivers
    #minio_volumes:                   # minio data volumes, override defaults if specified
    minio_domain: sss.pigsty          # minio external domain name, `sss.pigsty` by default
    minio_port: 9000                  # minio service port, 9000 by default
    minio_admin_port: 9001            # minio console port, 9001 by default
    minio_access_key: minioadmin      # root access key, `minioadmin` by default
    minio_secret_key: S3User.MinIO    # root secret key, `S3User.MinIO` by default
    minio_extra_vars: ''              # extra environment variables
    minio_provision: true             # run minio provisioning tasks?
    minio_alias: sss                  # alias name for local minio deployment
    #minio_endpoint: https://sss.pigsty:9000 # if not specified, overwritten by defaults
    minio_buckets:                    # list of minio bucket to be created
      - { name: pgsql }
      - { name: meta ,versioning: true }
      - { name: data }
    minio_users:                      # list of minio user to be created
      - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
      - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
      - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }
    minio_safeguard: false            # prevent purging running minio instance?
    minio_rm_data: true               # purging minio data and config?
    minio_rm_pkg: false               # uninstall minio packages?


    #================================================================#
    #                         VARS: REDIS                            #
    #================================================================#
    #redis_cluster:        <CLUSTER> # redis cluster name, required identity parameter
    #redis_node: 1            <NODE> # redis node sequence number, node int id required
    #redis_instances: {}      <NODE> # redis instances definition on this redis node
    redis_fs_main: /data/redis        # redis main data directory, `/data/redis` by default
    redis_exporter_enabled: true      # install redis exporter on redis nodes?
    redis_exporter_port: 9121         # redis exporter listen port, 9121 by default
    redis_exporter_options: ''        # cli args and extra options for redis exporter
    redis_type: redis                 # redis implementation: redis or valkey
    redis_mode: standalone            # redis mode: standalone,cluster,sentinel
    redis_conf: redis.conf            # redis config template path, except sentinel
    redis_bind_address: '0.0.0.0'     # redis bind address, empty string will use host ip
    redis_max_memory: 1GB             # max memory used by each redis instance
    redis_mem_policy: allkeys-lru     # redis memory eviction policy
    redis_password: ''                # redis password, empty string will disable password
    redis_rdb_save: ['1200 1']        # redis rdb save directives, disable with empty list
    redis_aof_enabled: false          # enable redis append only file?
    redis_rename_commands: {}         # rename redis dangerous commands
    redis_cluster_replicas: 1         # replica number for one master in redis cluster
    redis_sentinel_monitor: []        # sentinel master list, works on sentinel cluster only
    redis_safeguard: false            # prevent purging running redis instance?
    redis_rm_data: true               # remove redis data dir?
    redis_rm_pkg: false               # uninstall selected engine & redis-exporter packages?


    #================================================================#
    #                         VARS: PGSQL                            #
    #================================================================#

    #-----------------------------------------------------------------
    # PG_IDENTITY
    #-----------------------------------------------------------------
    pg_mode: pgsql          #CLUSTER  # pgsql cluster mode: pgsql,citus,mssql,mysql,ivory,pgtde,polar,gpsql,agens,oriole,pgedge
    # pg_cluster:           #CLUSTER  # pgsql cluster name, required identity parameter
    # pg_seq: 0             #INSTANCE # pgsql instance seq number, required identity parameter
    # pg_role: replica      #INSTANCE # pgsql role, required, could be primary,replica,offline
    # pg_instances: {}      #INSTANCE # define multiple pg instances on node in `{port:ins_vars}` format
    # pg_upstream:          #INSTANCE # repl upstream ip addr for standby cluster or cascade replica
    # pg_shard:             #CLUSTER  # pgsql shard name, optional identity for sharding clusters
    # pg_group: 0           #CLUSTER  # pgsql shard index number, optional identity for sharding clusters
    # gp_role: master       #CLUSTER  # greenplum role of this cluster, could be master or segment
    pg_offline_query: false #INSTANCE # set to true to enable offline queries on this instance

    #-----------------------------------------------------------------
    # PG_BUSINESS
    #-----------------------------------------------------------------
    # postgres business object definition, overwrite in group vars
    pg_users: []                      # postgres business users
    pg_databases: []                  # postgres business databases
    pg_services: []                   # postgres business services
    pg_hba_rules: []                  # business hba rules for postgres
    pgb_hba_rules: []                 # business hba rules for pgbouncer
    pg_crontab: []                    # postgres crontab entries for dbsu
    # global credentials, overwrite in global vars
    pg_dbsu_password: ''              # dbsu password, empty string means no dbsu password by default
    pg_replication_username: replicator
    pg_replication_password: DBUser.Replicator
    pg_admin_username: dbuser_dba
    pg_admin_password: DBUser.DBA
    pg_monitor_username: dbuser_monitor
    pg_monitor_password: DBUser.Monitor

    #-----------------------------------------------------------------
    # PG_INSTALL
    #-----------------------------------------------------------------
    pg_dbsu: postgres                 # os dbsu name, postgres by default, better not change it
    pg_dbsu_uid: 543                  # os dbsu uid and gid, 26 for default postgres users and groups
    pg_dbsu_sudo: limit               # dbsu sudo privilege, none,limit,all,nopass. limit by default
    pg_dbsu_home: /var/lib/pgsql      # postgresql home directory, `/var/lib/pgsql` by default
    pg_dbsu_ssh_exchange: true        # exchange postgres dbsu ssh key among same pgsql cluster
    pg_version: 18                    # postgres major version to be installed, 18 by default
    pg_bin_dir: /usr/pgsql/bin        # postgres binary dir, `/usr/pgsql/bin` by default
    pg_log_dir: /pg/log/postgres      # postgres log dir, `/pg/log/postgres` by default
    pg_packages:                      # pg packages to be installed, alias can be used
      - pgsql-main pgsql-common
    pg_extensions: []                 # pg extensions to be installed, alias can be used

    #-----------------------------------------------------------------
    # PG_BOOTSTRAP
    #-----------------------------------------------------------------
    pg_data: /pg/data                 # postgres data directory, `/pg/data` by default
    pg_fs_main: /data/postgres        # postgres main data directory, `/data/postgres` by default
    pg_fs_backup: /data/backups       # postgres backup data directory, `/data/backups` by default
    pg_storage_type: SSD              # storage type for pg main data, SSD,HDD, SSD by default
    pg_dummy_filesize: 64MiB          # size of `/pg/dummy`, hold 64MB disk space for emergency use
    pg_listen: '0.0.0.0'              # postgres/pgbouncer listen addresses, comma separated list
    pg_port: 5432                     # postgres listen port, 5432 by default
    pg_localhost: /var/run/postgresql # postgres unix socket dir for localhost connection
    patroni_enabled: true             # if disabled, no postgres cluster will be created during init
    patroni_mode: default             # patroni working mode: default,pause,remove
    pg_namespace: /pg                 # top level key namespace in etcd, used by patroni & vip
    patroni_port: 8008                # patroni listen port, 8008 by default
    patroni_log_dir: /pg/log/patroni  # patroni log dir, `/pg/log/patroni` by default
    patroni_ssl_enabled: false        # secure patroni RestAPI communications with SSL?
    patroni_watchdog_mode: 'off'      # patroni watchdog mode: automatic,required,off. off by default
    patroni_username: postgres        # patroni restapi username, `postgres` by default
    patroni_password: Patroni.API     # patroni restapi password, `Patroni.API` by default
    pg_etcd_password: ''              # etcd password for this pg cluster, '' to use pg_cluster
    pg_primary_db: postgres           # primary database name, used by citus,etc... ,postgres by default
    pg_parameters: {}                 # extra parameters in postgresql.auto.conf
    pg_files: []                      # extra files to be copied to postgres data directory (e.g. license)
    pg_conf: oltp.yml                 # config template: oltp,olap,crit,tiny. `oltp.yml` by default
    pg_max_conn: auto                 # postgres max connections, `auto` will use recommended value
    pg_shared_buffer_ratio: 0.25      # postgres shared buffers ratio, 0.25 by default, 0.1~0.4
    pg_io_method: worker              # io method for postgres, auto,fsync,worker,io_uring, worker by default
    pg_rto: norm                      # shared rto mode for patroni & haproxy: fast,norm,safe,wide
    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 ]
      norm: [ 30  ,5  ,10 ,25 ,5  ,'2s' ,'1s'   ,'2s' ,3 ,3 ]
      safe: [ 60  ,10 ,20 ,45 ,10 ,'3s' ,'1.5s' ,'3s' ,3 ,3 ]
      wide: [ 120 ,20 ,30 ,95 ,15 ,'4s' ,'2s'   ,'4s' ,3 ,3 ]
    pg_rpo: 1048576                   # recovery point objective in bytes, `1MiB` at most by default
    pg_libs: 'pg_stat_statements, auto_explain'  # preloaded libraries, `pg_stat_statements,auto_explain` by default
    pg_delay: 0                       # replication apply delay for standby cluster leader
    pg_checksum: true                 # enable data checksum for postgres cluster?
    pg_pwd_enc: scram-sha-256         # password encryption algorithm
    pg_encoding: UTF8                 # database cluster encoding, `UTF8` by default
    pg_locale: C                      # database cluster local, `C` by default
    pg_lc_collate: C                  # database cluster collate, `C` by default
    pg_lc_ctype: C                    # database character type, `C` by default
    #pgsodium_key: ""                 # pgsodium key, 64 hex digit, default to sha256(pg_cluster)
    #pgsodium_getkey_script: ""       # pgsodium getkey script path, pgsodium_getkey by default

    #-----------------------------------------------------------------
    # PG_PROVISION
    #-----------------------------------------------------------------
    pg_provision: true                # provision postgres cluster after bootstrap
    pg_init: pg-init                  # provision init script for cluster template, `pg-init` by default
    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  ,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 }
    pg_default_privileges:            # default privileges when created by admin user
      - 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
    pg_default_schemas: [ monitor ]   # default schemas to be created
    pg_default_extensions:            # default extensions to be created
      - { name: pg_stat_statements ,schema: monitor }
      - { name: pgstattuple        ,schema: monitor }
      - { name: pg_buffercache     ,schema: monitor }
      - { name: pageinspect        ,schema: monitor }
      - { name: pg_prewarm         ,schema: monitor }
      - { name: pg_visibility      ,schema: monitor }
      - { name: pg_freespacemap    ,schema: monitor }
      - { name: postgres_fdw       ,schema: public  }
      - { name: file_fdw           ,schema: public  }
      - { name: btree_gist         ,schema: public  }
      - { name: btree_gin          ,schema: public  }
      - { name: pg_trgm            ,schema: public  }
      - { name: intagg             ,schema: public  }
      - { name: intarray           ,schema: public  }
      - { name: pg_repack }
    pg_reload: true                   # reload postgres after hba changes
    pg_default_hba_rules:             # postgres default host-based authentication rules, order by `order`
      - {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  ,order: 100}
      - {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' ,order: 150}
      - {user: '${repl}'    ,db: replication ,addr: localhost ,auth: pwd   ,title: 'replicator replication from localhost',order: 200}
      - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: pwd   ,title: 'replicator replication from intranet' ,order: 250}
      - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: pwd   ,title: 'replicator postgres db from intranet' ,order: 300}
      - {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' ,order: 350}
      - {user: '${monitor}' ,db: all         ,addr: infra     ,auth: pwd   ,title: 'monitor from infra host with password',order: 400}
      - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: pwd   ,title: 'admin @ intranet nodes with pwd'      ,order: 450}
      - {user: '${admin}'   ,db: all         ,addr: world     ,auth: ssl   ,title: 'admin @ everywhere with ssl & pwd'    ,order: 500}
      - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: pwd   ,title: 'pgbouncer read/write via local socket',order: 550}
      - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: pwd   ,title: 'read/write biz user via password'     ,order: 600}
      - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: pwd   ,title: 'allow etl offline tasks from intranet',order: 650}
    pgb_default_hba_rules:            # pgbouncer default host-based authentication rules, order by `order`
      - {user: '${dbsu}'    ,db: pgbouncer   ,addr: local     ,auth: peer  ,title: 'dbsu local admin access with os ident',order: 100}
      - {user: 'all'        ,db: all         ,addr: localhost ,auth: pwd   ,title: 'allow all user local access with pwd' ,order: 150}
      - {user: '${monitor}' ,db: pgbouncer   ,addr: intra     ,auth: pwd   ,title: 'monitor access via intranet with pwd' ,order: 200}
      - {user: '${monitor}' ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other monitor access addr' ,order: 250}
      - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: pwd   ,title: 'admin access via intranet with pwd'   ,order: 300}
      - {user: '${admin}'   ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other admin access addr'   ,order: 350}
      - {user: 'all'        ,db: all         ,addr: intra     ,auth: pwd   ,title: 'allow all user intra access with pwd' ,order: 400}

    #-----------------------------------------------------------------
    # PG_BACKUP
    #-----------------------------------------------------------------
    pgbackrest_enabled: true          # enable pgbackrest on pgsql host?
    pgbackrest_log_dir: /pg/log/pgbackrest # pgbackrest log dir, `/pg/log/pgbackrest` by default
    pgbackrest_method: local          # pgbackrest repo method: local,minio,[user-defined...]
    pgbackrest_init_backup: true      # take a full backup after pgbackrest is initialized?
    pgbackrest_repo:                  # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
      local:                          # default pgbackrest repo with local posix fs
        path: /pg/backup              # local backup directory, `/pg/backup` by default
        retention_full_type: count    # retention full backups by count
        retention_full: 2             # keep 2, at most 3 full backups when using local fs repo
      minio:                          # optional minio repo for pgbackrest
        type: s3                      # minio is s3-compatible, so s3 is used
        s3_endpoint: sss.pigsty       # minio endpoint domain name, `sss.pigsty` by default
        s3_region: us-east-1          # minio region, us-east-1 by default, useless for minio
        s3_bucket: pgsql              # minio bucket name, `pgsql` by default
        s3_key: pgbackrest            # minio user access key for pgbackrest
        s3_key_secret: S3User.Backup  # minio user secret key for pgbackrest
        s3_uri_style: path            # use path style uri for minio rather than host style
        path: /pgbackrest             # minio backup path, default is `/pgbackrest`
        storage_port: 9000            # minio port, 9000 by default
        storage_ca_file: /etc/pki/ca.crt  # minio ca file path, `/etc/pki/ca.crt` by default
        block: y                      # Enable block incremental backup
        bundle: y                     # bundle small files into a single file
        bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
        cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
        retention_full_type: time     # retention full backup by time on minio repo
        retention_full: 14            # keep full backup for the the last 14 days

    #-----------------------------------------------------------------
    # PG_ACCESS
    #-----------------------------------------------------------------
    pgbouncer_enabled: true           # if disabled, pgbouncer will not be launched on pgsql host
    pgbouncer_port: 6432              # pgbouncer listen port, 6432 by default
    pgbouncer_log_dir: /pg/log/pgbouncer  # pgbouncer log dir, `/pg/log/pgbouncer` by default
    pgbouncer_auth_query: false       # query postgres to retrieve unlisted business users?
    pgbouncer_poolmode: transaction   # pooling mode: transaction,session,statement, transaction by default
    pgbouncer_sslmode: disable        # pgbouncer client ssl mode, disable by default
    pgbouncer_ignore_param: [ extra_float_digits, application_name, TimeZone, DateStyle, IntervalStyle, search_path ]
    pg_weight: 100          #INSTANCE # relative load balance weight in service, 100 by default, 0-255
    pg_service_provider: ''           # dedicate haproxy node group name, or empty string for local nodes by default
    pg_default_service_dest: pgbouncer # default service destination if svc.dest='default'
    pg_default_services:              # postgres default service definitions
      - { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
      - { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
      - { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
      - { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}
    pg_vip_enabled: false             # enable a l2 vip for pgsql primary? false by default
    pg_vip_address: 127.0.0.1/24      # vip address in `<ipv4>/<mask>` format, require if vip is enabled
    pg_vip_interface: auto            # vip network interface to listen, auto by default
    pg_dns_suffix: ''                 # pgsql dns suffix, '' by default
    pg_dns_target: auto               # auto, primary, vip, none, or ad hoc ip

    #-----------------------------------------------------------------
    # PG_MONITOR
    #-----------------------------------------------------------------
    pg_exporter_enabled: true              # enable pg_exporter on pgsql hosts?
    pg_exporter_config: pg_exporter.yml    # pg_exporter configuration file name
    pg_exporter_cache_ttls: '1,10,60,300'  # pg_exporter collector ttl stage in seconds, '1,10,60,300' by default
    pg_exporter_port: 9630                 # pg_exporter listen port, 9630 by default
    pg_exporter_params: 'sslmode=disable'  # extra url parameters for pg_exporter dsn
    pg_exporter_url: ''                    # overwrite auto-generate pg dsn if specified
    pg_exporter_auto_discovery: true       # enable auto database discovery? enabled by default
    pg_exporter_exclude_database: 'template0,template1,postgres' # csv of database that WILL NOT be monitored during auto-discovery
    pg_exporter_include_database: ''       # csv of database that WILL BE monitored during auto-discovery
    pg_exporter_connect_timeout: 200       # pg_exporter connect timeout in ms, 200 by default
    pg_exporter_options: ''                # overwrite extra options for pg_exporter
    pgbouncer_exporter_enabled: true       # enable pgbouncer_exporter on pgsql hosts?
    pgbouncer_exporter_port: 9631          # pgbouncer_exporter listen port, 9631 by default
    pgbouncer_exporter_url: ''             # overwrite auto-generate pgbouncer dsn if specified
    pgbouncer_exporter_options: ''         # overwrite extra options for pgbouncer_exporter
    pgbackrest_exporter_enabled: true      # enable pgbackrest_exporter on pgsql hosts?
    pgbackrest_exporter_port: 9854         # pgbackrest_exporter listen port, 9854 by default
    pgbackrest_exporter_options: >-
      --collect.interval=120
      --log.level=info

    #-----------------------------------------------------------------
    # PG_REMOVE
    #-----------------------------------------------------------------
    pg_safeguard: false               # stop pg_remove running if pg_safeguard is enabled, false by default
    pg_rm_data: true                  # remove postgres data during remove? true by default
    pg_rm_backup: true                # remove pgbackrest backup during primary remove? true by default
    pg_rm_pkg: true                   # uninstall postgres packages during remove? true by default

...

配置解读

demo/debian 模板是针对 Debian 和 Ubuntu 发行版优化的配置。

支持的发行版

  • Debian 12 (Bookworm)
  • Debian 13 (Trixie)
  • Ubuntu 22.04 LTS (Jammy)
  • Ubuntu 24.04 LTS (Noble)
  • Ubuntu 26.04 LTS (Resolute)

关键特性

  • 使用 PGDG APT 软件源
  • 针对 APT 包管理器优化
  • 支持 Debian/Ubuntu 特定的软件包名称

适用场景

  • 云服务器(Ubuntu 广泛使用)
  • 容器环境(Debian 常用作基础镜像)
  • 开发测试环境

6.29 - demo/demo

Pigsty 公开演示站点配置,展示如何配置 SSL 证书、暴露域名、安装全部扩展

demo/demo 配置模板是 Pigsty 公开演示站点使用的配置文件,展示了如何对外暴露网站、配置 SSL 证书、安装全部扩展插件。

如果您希望在云服务器上搭建自己的公开服务,可以参考此配置模板。


配置概览

  • 配置名称: demo/demo
  • 节点数量: 单节点
  • 配置说明:Pigsty 公开演示站点配置
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64
  • 相关配置:metarich

启用方式:

./configure -c demo/demo [-i <primary_ip>]

主要特性

此模板在 meta 基础上进行了以下增强:

  • 配置 SSL 证书和自定义域名(如 pigsty.cc
  • 下载并安装 PostgreSQL 18 所有可用扩展
  • 启用 Docker 并配置镜像加速
  • 部署 Silo 对象存储
  • 预置多个业务数据库和用户
  • 添加 Redis 主从实例示例
  • 添加 Kafka 样例集群

配置内容

源文件地址:pigsty/conf/demo/demo.yml

---
#==============================================================#
# File      :   demo.yml
# Desc      :   Pigsty Public Demo Configuration
# Ctime     :   2020-05-22
# Mtime     :   2025-12-12
# Docs      :   https://pigsty.io/docs/conf/demo
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#


all:
  children:

    # infra cluster for proxy, monitor, alert, etc..
    infra:
      hosts: { 10.10.10.10: { infra_seq: 1 } }
      vars:
        nodename: pigsty.cc       # overwrite the default hostname
        node_id_from_pg: false    # do not use the pg identity as hostname
        docker_enabled: true      # enable docker on this node
        docker_registry_mirrors: ["https://mirror.ccs.tencentyun.com", "https://docker.1ms.run"]
        # ./pgsql-monitor.yml -l infra     # monitor 'external' PostgreSQL instance
        pg_exporters:             # treat local postgres as RDS for demonstration purpose
          20001: { pg_cluster: pg-foo, pg_seq: 1, pg_host: 10.10.10.10 }
          #20002: { pg_cluster: pg-bar, pg_seq: 1, pg_host: 10.10.10.11 , pg_port: 5432 }
          #20003: { pg_cluster: pg-bar, pg_seq: 2, pg_host: 10.10.10.12 , pg_exporter_url: 'postgres://dbuser_monitor:[email protected]:5432/postgres?sslmode=disable' }
          #20004: { pg_cluster: pg-bar, pg_seq: 3, pg_host: 10.10.10.13 , pg_monitor_username: dbuser_monitor, pg_monitor_password: DBUser.Monitor }

    # etcd cluster for ha postgres
    etcd: { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }

    # minio cluster, s3 compatible object storage
    minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio } }

    # postgres example cluster: pg-meta
    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-meta
        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 }
          - {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     }
          - {name: dbuser_noco       ,password: DBUser.Noco       ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for nocodb service      }
          - {name: dbuser_odoo       ,password: DBUser.Odoo       ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for odoo service ,createdb: true } #,superuser: true}
          - {name: dbuser_mattermost ,password: DBUser.MatterMost ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for mattermost ,createdb: true }
        pg_databases:
          - {name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [{name: vector},{name: postgis},{name: timescaledb}]}
          - {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 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  }
          - {name: noco     ,owner: dbuser_noco     ,revokeconn: true ,comment: nocodb database     }
          #- {name: odoo     ,owner: dbuser_odoo     ,revokeconn: true ,comment: odoo main database  }
          - {name: mattermost ,owner: dbuser_mattermost ,revokeconn: true ,comment: mattermost main database }
        pg_hba_rules:
          - {user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes'}
        pg_libs: 'timescaledb,pg_stat_statements, auto_explain'  # add timescaledb to shared_preload_libraries
        pg_extensions: # extensions to be installed on this cluster
          - timescaledb timescaledb_toolkit pg_timeseries periods temporal_tables emaj table_version pg_cron pg_task pg_later pg_background
          - postgis pgrouting pointcloud pg_h3 q3c ogr_fdw geoip pg_polyline pg_geohash #mobilitydb
          - pgvector vchord pgvectorscale pg_vectorize pg_similarity smlar pg_summarize pg_tiktoken pg4ml #pgml
          - pg_search pgroonga pg_bigm zhparser pg_bestmatch vchord_bm25 hunspell
          - citus pg_duckdb pg_mooncake duckdb_fdw pg_parquet pg_fkpart pg_partman plproxy #pg_strom #hydra
          - age hll rum pg_graphql pg_jsonschema jsquery pg_hint_plan hypopg index_advisor pg_plan_filter imgsmlr pg_ivm pg_incremental pgmq pgq pg_cardano omnigres #rdkit
          - pg_tle plv8 pllua plprql pldebugger plpgsql_check plprofiler plsh pljava #plr #pgtap #faker #dbt2
          - pg_prefix pg_semver pgunit pgpdf pglite_fusion md5hash asn1oid pg_roaringbitmap pgfaceting pgsphere pg_country pg_xenophile pg_currency pgcollection pgmp numeral pg_rational pguint pg_uint128 hashtypes ip4r pg_uri pg_emailaddr pg_acl timestamp9 chkpass #pg_duration #debversion #pg_rrule
          - pg_gzip pg_bzip pg_zstd pg_http pg_net pg_curl pgjq pgjwt pg_smtp_client pg_html5_email_address url_encode pgsql_tweaks pg_extra_time pgpcre icu_ext pgqr pg_protobuf pg_envvar floatfile pg_readme ddl_historization data_historization pg_schedoc pg_hashlib pg_xxhash shacrypt cryptint pg_ecdsa pgsparql
          - pg_idkit pg_uuidv7 permuteseq pg_hashids sequential_uuids topn quantile lower_quantile count_distinct omnisketch ddsketch vasco pgxicor tdigest first_last_agg extra_window_functions floatvec aggs_for_vecs aggs_for_arrays pg_arraymath pg_math pg_random pg_base36 pg_base62 pg_base58 pg_financial
          - pg_repack pg_squeeze pg_dirtyread pgfincore pg_cooldown pg_ddlx pg_prioritize pg_checksums pg_readonly pg_upless pg_permissions pgautofailover pg_catcheck preprepare pgcozy pg_orphaned pg_crash pg_cheat_funcs pg_fio pg_savior safeupdate pg_drop_events table_log #pgagent #pgpool
          - pg_profile pg_tracing pg_show_plans pg_stat_kcache pg_stat_monitor pg_qualstats pg_store_plans pg_track_settings pg_wait_sampling system_stats pg_meta pgnodemx pg_sqlog bgw_replstatus pgmeminfo toastinfo pg_explain_ui pg_relusage pagevis powa
          - passwordcheck_cracklib supautils pgsodium pg_vault pg_session_jwt pg_anon pgsmcrypto pgaudit pgauditlogtofile pg_auth_mon credcheck pgcryptokey pg_jobmon logerrors login_hook set_user pg_snakeoil pgextwlist pg_auditor sslutils pg_noset #pg_tde
          - wrappers multicorn odbc_fdw jdbc_fdw mysql_fdw tds_fdw sqlite_fdw pgbouncer_fdw mongo_fdw redis_fdw pg_redis_pubsub kafka_fdw hdfs_fdw firebird_fdw aws_s3 log_fdw #oracle_fdw #db2_fdw
          - documentdb orafce pgtt session_variable pg_statement_rollback pg_dbms_metadata pg_dbms_lock pgmemcache #pg_dbms_job
          - pglogical pglogical_ticker pgl_ddl_deploy pg_failover_slots db_migrator wal2json wal2mongo decoderbufs decoder_raw mimeo pg_fact_loader pg_bulkload #repmgr

    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' }, 6381: { replica_of: '10.10.10.10 6379' } } } }
      vars: { redis_cluster: redis-ms ,redis_password: 'redis.ms' ,redis_max_memory: 64MB }

    # Kafka 4.x dynamic KRaft: combined broker/controller on the demo node
    kf-main:
      hosts: { 10.10.10.10: { kafka_seq: 1 } }
      vars:
        kafka_cluster: kf-main


  vars:                               # global variables
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: china                     # upstream mirror region: default|china|europe

    infra_portal:                     # infra services exposed via portal
      home         : { domain: i.pigsty }     # default domain name
      cc           : { domain: pigsty.cc      ,path:     "/www/pigsty.cc"   ,cert: /etc/cert/pigsty.cc.crt ,key: /etc/cert/pigsty.cc.key }
      minio        : { domain: m.pigsty.cc    ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }
      postgrest    : { domain: api.pigsty.cc  ,endpoint: "127.0.0.1:8884"   }
      pgadmin      : { domain: adm.pigsty.cc  ,endpoint: "127.0.0.1:8885"   }
      pgweb        : { domain: cli.pigsty.cc  ,endpoint: "127.0.0.1:8886"   }
      bytebase     : { domain: ddl.pigsty.cc  ,endpoint: "127.0.0.1:8887"   }
      jupyter      : { domain: lab.pigsty.cc  ,endpoint: "127.0.0.1:8888", websocket: true }
      gitea        : { domain: git.pigsty.cc  ,endpoint: "127.0.0.1:8889" }
      wiki         : { domain: wiki.pigsty.cc ,endpoint: "127.0.0.1:9002" }
      noco         : { domain: noco.pigsty.cc ,endpoint: "127.0.0.1:9003" }
      supa         : { domain: supa.pigsty.cc ,endpoint: "10.10.10.10:8000" ,websocket: true }
      dify         : { domain: dify.pigsty.cc ,endpoint: "10.10.10.10:8001" ,websocket: true }
      odoo         : { domain: odoo.pigsty.cc ,endpoint: "127.0.0.1:8069"   ,websocket: true }
      mm           : { domain: mm.pigsty.cc   ,endpoint: "10.10.10.10:8065" ,websocket: true }
    # scp -r ~/pgsty/cc/cert/*       pj:/etc/cert/       # copy https certs
    # scp -r ~/dev/pigsty.cc/public  pj:/www/pigsty.cc   # copy pigsty.cc website


    node_etc_hosts: [ "${admin_ip} i.pigsty sss.pigsty" ]
    node_timezone: Asia/Hong_Kong
    node_ntp_servers:
      - pool cn.pool.ntp.org iburst
      - pool ${admin_ip} iburst       # assume non-admin nodes does not have internet access
    pgbackrest_enabled: false         # do not take backups since this is disposable demo env
    # keep 3GiB metrics data at most on demo env
    vmetrics_options: >-
      -retentionPeriod=15d
      -retention.maxDiskSpaceUsageBytes=3GiB

    # install all postgresql18 extensions
    pg_version: 18                    # default postgres version
    repo_extra_packages: [ pg18-core ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl ,kafka-stack ,java-runtime]
    pg_extensions: [pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl ] #,pg18-olap]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

demo/demo 模板是 Pigsty 的 公开演示配置,展示了完整的生产级部署示例。

关键特性

  • 配置 HTTPS 证书和自定义域名
  • 安装所有可用的 PostgreSQL 扩展
  • 集成 Redis、Kafka 等组件
  • 配置 Docker 镜像加速

适用场景

  • 搭建公开演示站点
  • 需要完整功能展示的场景
  • 学习 Pigsty 高级配置

注意事项

  • 需要准备 SSL 证书文件
  • 需要配置 DNS 解析
  • 部分扩展在 ARM64 架构不可用

6.30 - demo/kernel

十节点 PostgreSQL 内核矩阵演示配置

demo/kernel 配置模板用于在一套配置中演示 Pigsty 支持的主要 PostgreSQL 内核与兼容分支。它面向功能验证和内核差异测试,不是生产模板。


配置概览

  • 配置名称: demo/kernel
  • 节点数量:10 个节点,其中 1 个同时承载 INFRA/ETCD 与 pg-citus
  • 配置说明:PostgreSQL 内核矩阵演示,覆盖 Citus、IvorySQL、Babelfish、PolarDB、Percona TDE、OrioleDB、OpenHalo、DocumentDB、AgensGraph、pgEdge
  • 适用系统:以各内核包实际支持的平台为准
  • 适用架构:以各内核包实际支持的平台为准
  • 相关配置:pgsqlmssqlmongo

启用方式:

./configure -c demo/kernel

备注:这是固定 IP 的演示模板,生成后需要按实际环境调整节点地址。


配置内容

源文件地址:pigsty/conf/demo/kernel.yml

---
#==============================================================#
# File      :   kernel.yml
# Desc      :   Pigsty 10-node kernel matrix demo
# Ctime     :   2025-03-25
# Mtime     :   2026-07-23
# Docs      :   https://pigsty.io/docs/conf
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#


all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } }, vars: { repo_enabled: false } }
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }

    # 1. Vanilla PostgreSQL + Citus in one kernel template
    pg-citus:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-citus
        pg_version: 18
        pg_packages: [ pgsql-main, pgsql-common, citus ]
        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  }
        pg_databases:
          - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [citus, postgis, vector] }
        pg_extensions: [ citus, postgis, timescaledb, pgvector ]
        pg_libs: 'citus, pg_stat_statements, auto_explain'

    # 2. IvorySQL kernel
    pg-ivory:
      hosts:
        10.10.10.11: { pg_seq: 1, pg_role: primary }
      vars:
        pg_mode: ivory
        pg_cluster: pg-ivory
        pg_version: 18
        pg_packages: [ ivorysql, pgsql-common ]
        pg_libs: 'liboracle_parser, pg_stat_statements, auto_explain'
        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  }
        pg_databases:
          - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] }

    # 3. Babelfish (MSSQL compatible) kernel
    pg-mssql:
      hosts:
        10.10.10.12: { pg_seq: 1, pg_role: primary }
      vars:
        pg_mode: mssql
        pg_cluster: pg-mssql
        pg_version: 17
        pg_packages: [ babelfish, pgsql-common, sqlcmd ]
        pg_users:
          - { name: dbuser_mssql ,password: DBUser.MSSQL ,superuser: true ,pgbouncer: true ,roles: [dbrole_admin] ,comment: superuser & owner for babelfish }
        pg_databases:
          - name: mssql
            baseline: mssql.sql
            extensions: [ uuid-ossp, babelfishpg_common, babelfishpg_tsql, babelfishpg_tds, babelfishpg_money ]
            owner: dbuser_mssql
            parameters: { 'babelfishpg_tsql.migration_mode' : 'multi-db' }
            comment: babelfish cluster, a MSSQL compatible pg cluster
        pg_libs: 'babelfishpg_tds, pg_stat_statements, auto_explain'
        pg_hba_rules:
          - { user: dbuser_mssql ,db: mssql ,addr: intra ,auth: md5 ,title: 'allow mssql dbsu intranet access'      ,order: 525 }
          - { user: all          ,db: all   ,addr: intra ,auth: md5 ,title: 'everyone intranet access with md5 pwd' ,order: 800 }
        pg_default_services:
          - { name: primary ,port: 5433 ,dest: 1433     ,check: /primary   ,selector: "[]" }
          - { name: replica ,port: 5434 ,dest: 1433     ,check: /read-only ,selector: "[]" ,backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
          - { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
          - { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" ,backup: "[? pg_role == `replica` && !pg_offline_query]" }

    # 4. PolarDB kernel
    pg-polar:
      hosts:
        10.10.10.13: { pg_seq: 1, pg_role: primary }
      vars:
        pg_mode: polar
        pg_cluster: pg-polar
        pg_version: 17
        pg_packages: [ polardb, pgsql-common ]
        pg_exporter_exclude_database: 'template0,template1,postgres,polardb_admin'
        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   ,superuser: true  ,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 }

    # 5. Percona pg_tde kernel
    pg-tde:
      hosts:
        10.10.10.14: { pg_seq: 1, pg_role: primary }
      vars:
        pg_mode: pgtde
        pg_cluster: pg-tde
        pg_version: 18
        pg_packages: [ pgtde, pgsql-common ]
        pg_libs: 'pg_tde, pgaudit, pg_stat_statements, pg_stat_monitor, auto_explain'
        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  }
        pg_databases:
          - name: meta
            baseline: cmdb.sql
            comment: pigsty tde database
            schemas: [pigsty]
            extensions: [ vector, postgis, pg_tde ,pgaudit, { name: pg_stat_monitor, schema: monitor } ]

    # 6. OrioleDB kernel
    pg-oriole:
      hosts:
        10.10.10.15: { pg_seq: 1, pg_role: primary }
      vars:
        pg_mode: oriole
        pg_cluster: pg-oriole
        pg_version: 18
        pg_packages: [ orioledb, pgsql-common ]
        pg_libs: 'orioledb, pg_stat_statements, auto_explain'
        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  }
        pg_databases:
          - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [orioledb] }

    # 7. OpenHaloDB (MySQL compatible) kernel
    pg-mysql:
      hosts:
        10.10.10.16: { pg_seq: 1, pg_role: primary }
      vars:
        pg_mode: mysql
        pg_cluster: pg-mysql
        pg_version: 14
        pg_packages: [ openhalo, pgsql-common ]
        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  }
        pg_databases:
          - { name: postgres ,extensions: [aux_mysql] }
          - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] }

    # 8. PostgreSQL Mongo mode with DocumentDB
    pg-mongo:
      hosts:
        10.10.10.17: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: pg-mongo
        pg_version: 18
        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  }
        pg_databases:
          - { name: postgres ,extensions: [documentdb, postgis, vector, pg_cron, rum] }
        pg_hba_rules:
          - { user: dbuser_view ,db: all ,addr: infra     ,auth: pwd   ,title: 'allow grafana dashboard access cmdb from infra nodes' }
          - { user: postgres    ,db: all ,addr: world     ,auth: pwd   ,title: 'dbsu password access everywhere (demo only)' }
          - { user: all         ,db: all ,addr: localhost ,order: 1    ,auth: trust ,title: 'documentdb localhost trust access' }
          - { user: all         ,db: all ,addr: local     ,order: 1    ,auth: trust ,title: 'documentdb local trust access' }
          - { user: all         ,db: all ,addr: intra     ,auth: pwd   ,order: 800  ,title: 'everyone intranet access with password' }
        pg_parameters: { cron.database_name: postgres }
        pg_extensions: [ documentdb, postgis, pgvector, pg_cron, rum ]
        pg_libs: 'pg_documentdb, pg_documentdb_core, pg_documentdb_extended_rum, pg_cron, pg_stat_statements, auto_explain'

    # 9. AgensGraph kernel
    pg-agens:
      hosts:
        10.10.10.18: { pg_seq: 1, pg_role: primary }
      vars:
        pg_mode: agens
        pg_cluster: pg-agens
        pg_version: 17
        pg_packages: [ agensgraph, pgsql-common ]
        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  }
        pg_databases:
          - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] }

    # 10. pgedge kernel (stock pigsty pgsql repo path)
    pg-edge:
      hosts:
        10.10.10.19: { pg_seq: 1, pg_role: primary }
      vars:
        pg_mode: pgedge
        pg_cluster: pg-edge
        pg_version: 18
        pg_packages: [ pgedge, pgsql-common ]
        pg_libs: 'spock, lolor, pg_stat_statements, auto_explain'
        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  }
        pg_databases:
          - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [spock, snowflake, lolor] }

  vars:
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    node_tune: oltp                   # node tuning specs: oltp,olap,tiny,crit
    pg_conf: oltp.yml                 # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    node_repo_modules: node,infra,pgsql
    proxy_env:
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
    infra_portal:
      home : { domain: i.pigsty }

    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

该模板用单节点集群展示不同内核的最低可用配置:

  • pg-citus:PostgreSQL 18 + Citus
  • pg-ivory:IvorySQL,兼容 PostgreSQL 18
  • pg-mssql:Babelfish,兼容 PostgreSQL 17
  • pg-polar:PolarDB for PostgreSQL,兼容 PostgreSQL 17
  • pg-tde:Percona PostgreSQL 18 + pg_tde
  • pg-oriole:OrioleDB,支持 PostgreSQL 16、17、18;当前演示配置默认使用 PG18
  • pg-mysql:OpenHalo,兼容 PostgreSQL 14
  • pg-mongo:PostgreSQL Mongo 模式的 DocumentDB 后端,默认 PostgreSQL 18
  • pg-agens:AgensGraph,兼容 PostgreSQL 17
  • pg-edge:pgEdge,兼容 PostgreSQL 18

注意事项

  • 不同内核的软件包支持平台不同,部署前应先确认目标系统的软件源可用性。
  • 该模板包含演示用途的宽松访问规则,生产环境请改用单独内核模板并收紧 HBA 与密码策略。

6.31 - demo/minio

四节点 x 四盘位的高可用 S3 对象存储集群演示;当前源码默认使用 Silo。

demo/minio 配置模板演示如何部署四节点 x 四盘位、总计十六盘的高可用 S3 对象存储集群。模板沿用 MINIO 模块的兼容命名,并显式设置 minio_type: silo;v4.5.0 当前源码只接受这一取值,部署与移除角色也都默认使用 silo。删除前仍应把该值连同精确目标、集群身份和数据盘路径一并核对。

更多教程,请参考 MINIO 模块文档。


配置概览

  • 配置名称: demo/minio
  • 节点数量: 四节点
  • 配置说明:高可用多节点多盘 S3 对象存储集群演示(当前默认 Silo)
  • 适用系统:el8, el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64, aarch64
  • 相关配置:meta

启用方式:

./configure -c demo/minio

备注:这是一个四节点模版,您需要在生成配置后修改其他三个节点的 IP 地址


配置内容

源文件地址:pigsty/conf/demo/minio.yml

---
#==============================================================#
# File      :   minio.yml
# Desc      :   pigsty: 4 node x 4 disk MNMD minio clusters
# Ctime     :   2023-01-07
# Mtime     :   2026-08-09
# Docs      :   https://pigsty.io/docs/minio
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# One pass installation with:
# ./deploy.yml
#==============================================================#
# 1.  minio-1 @ 10.10.10.10:9000 -  - (9002) svc <-x  10.10.10.9:9002
# 2.  minio-2 @ 10.10.10.11:9000 -xx- (9002) svc <-x <----------------
# 3.  minio-3 @ 10.10.10.12:9000 -xx- (9002) svc <-x  sss.pigsty:9002
# 4.  minio-4 @ 10.10.10.13:9000 -  - (9002) svc <-x  (intranet dns)
#==============================================================#
# use minio load balancer service (9002) instead of direct access (9000)
# mcli alias set sss https://sss.pigsty:9002 minioadmin S3User.MinIO
#==============================================================#
# https://min.io/docs/minio/linux/operations/install-deploy-manage/deploy-minio-multi-node-multi-drive.html
# MINIO_VOLUMES="https://minio-{1...4}.pigsty:9000/data{1...4}/minio"


all:
  children:

    # infra cluster for proxy, monitor, alert, etc...
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }

    # minio cluster with 4 nodes and 4 drivers per node
    minio:
      hosts:
        10.10.10.10: { minio_seq: 1 , nodename: minio-1 }
        10.10.10.11: { minio_seq: 2 , nodename: minio-2 }
        10.10.10.12: { minio_seq: 3 , nodename: minio-3 }
        10.10.10.13: { minio_seq: 4 , nodename: minio-4 }
      vars:
        minio_type: silo
        minio_cluster: minio
        minio_data: '/data{1...4}'
        minio_buckets:                    # list of minio bucket to be created
          - { name: pgsql }
          - { name: meta ,versioning: true }
          - { name: data }
        minio_users:                      # list of minio user to be created
          - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
          - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
          - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }

        # bind a node l2 vip (10.10.10.9) to minio cluster (optional)
        node_cluster: minio
        vip_enabled: true
        vip_vrid: 128
        vip_address: 10.10.10.9

        # expose minio service with haproxy on all nodes
        haproxy_services:
          - name: minio                    # [REQUIRED] service name, unique
            port: 9002                     # [REQUIRED] service port, unique
            balance: leastconn             # [OPTIONAL] load balancer algorithm
            options:                       # [OPTIONAL] minio health check
              - 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' }
              - { name: minio-4 ,ip: 10.10.10.13 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }

    #etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1 } } }
    #pgsql:
    #  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 }
    #    10.10.10.13: { pg_seq: 4 , pg_role: replica }
    #  vars:
    #    pg_cluster: pgsql
    #    pgbackrest_method: minio

  vars:
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe

    # build a local repo without PostgreSQL packages
    repo_modules: infra,node
    repo_packages: "{{ repo_packages_default | reject('equalto', 'pgsql-utility') | list }}"
    repo_extra_packages: []

    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

      # domain names to access minio web console via nginx web portal (optional)
      minio        : { domain: m.pigsty     ,endpoint: "10.10.10.10:9001" ,scheme: https ,websocket: true }
      minio10      : { domain: m10.pigsty   ,endpoint: "10.10.10.10:9001" ,scheme: https ,websocket: true }
      minio11      : { domain: m11.pigsty   ,endpoint: "10.10.10.11:9001" ,scheme: https ,websocket: true }
      minio12      : { domain: m12.pigsty   ,endpoint: "10.10.10.12:9001" ,scheme: https ,websocket: true }
      minio13      : { domain: m13.pigsty   ,endpoint: "10.10.10.13:9001" ,scheme: https ,websocket: true }

    minio_endpoint: https://sss.pigsty:9002   # explicit overwrite minio endpoint with haproxy port
    node_etc_hosts: ["10.10.10.9 sss.pigsty"] # domain name to access minio from all nodes (required)

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
...

配置解读

demo/minio 模板是对象存储生产部署的参考配置,展示了多节点多盘(MNMD)架构。其卷布局、HAProxy 健康检查与客户端仍使用 MinIO 兼容接口。

关键特性

  • 多节点多盘架构:4 节点 × 4 盘 = 16 盘纠删码组
  • L2 VIP 高可用:通过 Keepalived 绑定虚拟 IP
  • HAProxy 负载均衡:9002 端口统一访问入口
  • 细粒度权限:为不同应用创建独立用户和存储桶

访问方式

# 使用 mcli 配置 S3 别名(通过 HAProxy 负载均衡)
mcli alias set sss https://sss.pigsty:9002 minioadmin S3User.MinIO

# 列出存储桶
mcli ls sss/

# 使用控制台
# 访问 https://m.pigsty 或 https://m10-m13.pigsty

适用场景

  • 需要 S3 兼容对象存储的环境
  • PostgreSQL 备份存储(pgBackRest 远程仓库)
  • 大数据和 AI 工作负载的数据湖
  • 需要高可用对象存储的生产环境

注意事项

  • 每个节点需要准备 4 块独立磁盘挂载到 /data1 - /data4
  • 生产环境建议至少 4 节点以实现纠删码冗余
  • VIP 需要正确配置网络接口(vip_interface

6.32 - demo/redis

Redis 主从、Sentinel 与原生 Cluster 三种模式的四节点演示模板

demo/redis 在一份配置中演示 Pigsty Redis 模块支持的 standalone/replica、Sentinel 与原生 Cluster 模式。


配置概览

  • 配置名称:demo/redis
  • 节点数量:4 个
  • 集群:redis-msredis-metaredis-test
  • 相关配置:demo/demo
./configure -c demo/redis -s

配置内容

源文件地址:pigsty/conf/demo/redis.yml

---
#==============================================================#
# File      :   redis.yml
# Desc      :   pigsty config for redis clusters
# Ctime     :   2022-11-09
# Mtime     :   2026-08-02
# Docs      :   https://pigsty.io/docs/redis
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#


all:
  children:

    # infra cluster for proxy, monitor, alert, etc..
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }

    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 }


  vars:
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe

    #================================================================#
    #                         VARS: REDIS                            #
    #================================================================#
    # redis identity
    #redis_cluster:         <CLUSTER> # redis cluster name, required identity parameter
    #redis_node: 1             <NODE> # redis node sequence number, node int id required
    #redis_instances: {}       <NODE> # redis instances definition on this redis node

    # redis node
    redis_fs_main: /data/redis        # redis main data directory, `/data/redis` by default
    redis_exporter_enabled: true      # install redis exporter on redis nodes?
    redis_exporter_port: 9121         # redis exporter listen port, 9121 by default
    redis_exporter_options: ''        # cli args and extra options for redis exporter
    redis_type: redis                 # redis implementation: redis or valkey

    # redis instance
    redis_mode: standalone            # redis mode: standalone,cluster,sentinel
    redis_conf: redis.conf            # redis config template path, except sentinel
    redis_bind_address: '0.0.0.0'     # redis bind address, empty string will use host ip
    redis_max_memory: 32MB            # max memory used by each redis instance
    redis_mem_policy: allkeys-lru     # redis memory eviction policy
    redis_password: ''                # redis password, empty string will disable password
    redis_rdb_save: [ '1200 1' ]      # redis rdb save directives, disable with empty list
    redis_aof_enabled: false          # enable redis append only file?
    redis_rename_commands: { }        # rename redis dangerous commands
    redis_cluster_replicas: 1         # replica number for one master in redis cluster
    redis_sentinel_monitor: []        # sentinel master list, works on sentinel cluster only


    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    haproxy_admin_password: pigsty
...

配置解读

  • redis-ms:同一节点上的 6379 主实例与 6380 从实例
  • redis-meta:三个 Sentinel 实例,监控 redis-ms6379 主实例
  • redis-test:两个节点、每节点三个实例组成的原生 Redis Cluster
  • 每个实例设置较小的内存上限,适合功能演示

模板中的 IP、密码和内存值都是演示值,部署前应按实际拓扑修改,并使用 redis.yml 剧本安装 Redis 模块。

6.33 - demo/kafka

四节点 dynamic KRaft 示例:单节点明文开发集群与三节点 TLS/SCRAM 高可用基线

demo/kafka 在四个节点上声明两套 Kafka 4.x dynamic KRaft 集群:单节点明文开发集群 kf-meta,以及三节点 TLS/SCRAM/ACL 演示集群 kf-test


配置概览

  • 配置名称:demo/kafka
  • 节点数量:4 个
  • kf-meta:单节点 combined Broker/Controller,明文模式
  • kf-test:3 个 combined 节点,TLS/SCRAM/ACL,Topic 副本数 3、min.insync.replicas=2
  • 模块状态:KAFKA BETA
./configure -c demo/kafka -s
./deploy.yml
./kafka.yml -l kf-meta
./kafka.yml -l kf-test

deploy.yml 只部署核心链路,并不会自动执行 KAFKA 剧本。每次 kafka.yml 运行都应选择一个完整的 Kafka 集群;角色会拒绝只选中部分成员的收敛操作。


配置内容

源文件地址:pigsty/conf/demo/kafka.yml

---
#==============================================================#
# File      :   kafka.yml
# Desc      :   pigsty: 4 node kafka demo (dynamic KRaft)
# Ctime     :   2026-07-17
# Mtime     :   2026-07-17
# Docs      :   https://pigsty.io/docs/kafka
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# One pass installation with:
# ./deploy.yml
# ./kafka.yml -l kf-main
# ./kafka.yml -l kf-test
#==============================================================#
# 1.  kf-meta-1 @ 10.10.10.10:9092   single-node dev cluster (plaintext)
# 2.  kf-test-1 @ 10.10.10.11:9092 \
# 3.  kf-test-2 @ 10.10.10.12:9092 --- 3-node secure HA demo baseline (scram)
# 4.  kf-test-3 @ 10.10.10.13:9092 /   dynamic KRaft, TLS/SCRAM/ACL, RF=3/minISR=2
#==============================================================#
# kafka clients are cluster-aware and connect to every broker directly:
# bootstrap with e.g. 10.10.10.11:9092,10.10.10.12:9092,10.10.10.13:9092


all:
  children:

    # infra cluster for proxy, monitor, alert, etc..
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }

    # single-node kafka dev cluster: combined broker/controller, plaintext
    kf-meta:
      hosts:
        10.10.10.10: { kafka_seq: 1 }
      vars:
        kafka_cluster: kf-meta
        kafka_topics:
          - { name: quickstart.events ,partitions: 1 ,replication_factor: 1 ,config: { retention.ms: 86400000 } }

    # 3-node secure HA demo baseline: dynamic KRaft, TLS/SCRAM/ACL, RF=3/minISR=2
    kf-test:
      hosts:
        10.10.10.11: { kafka_seq: 1 }
        10.10.10.12: { kafka_seq: 2 }
        10.10.10.13: { kafka_seq: 3 }
      vars:
        kafka_cluster: kf-test
        kafka_security: scram
        kafka_heap_opts: '-Xms512M -Xmx512M' # 2GiB demo nodes cannot safely spare the 1GiB production default
        kafka_users:               # app principal with prefixed topic/group acls
          - name: test-app
            password: KafkaApp.Test
            acls:
              - { resource: topic   ,name: 'test.'       ,pattern: prefixed ,operations: [ Read, Write, Describe ] }
              - { resource: group   ,name: 'test.'       ,pattern: prefixed ,operations: [ Read ] }
              - { resource: cluster ,name: kafka-cluster ,operations: [ Describe, IdempotentWrite ] }
        kafka_topics:
          - name: test.events
            partitions: 3
            replication_factor: 3
            config: { min.insync.replicas: 2 ,cleanup.policy: delete ,retention.ms: 604800000 }

  vars:
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    infra_portal:                     # infra services exposed via portal
      home : { domain: i.pigsty }     # default domain name

    # kafka & java packages are required in the local repo for the kafka module (if using local repo)
    repo_extra_packages: [ kafka-stack ,java-runtime ]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
...

配置解读

  • kf-meta 创建 quickstart.events,用于单机开发与连通性测试。
  • kf-test 创建 test-app SCRAM 用户、前缀 ACL 与 test.events 三副本 Topic。
  • 在线安装时由平台映射安装 kafka-stackjava-runtime;若只使用本地仓库,必须先把这两个包组完整纳入仓库。
  • 模板中的地址和密码均为演示值,部署前应按实际拓扑与安全要求修改。

更多操作、安全与扩缩容约束参见 KAFKA 模块

6.34 - demo/mysql

原生 MySQL 8.4 试点模板:单节点实例与三节点 InnoDB Cluster

demo/mysql 是原生 MySQL 8.4 LTS 试点模块的四节点示例,与 conf/mysql.yml 中通过 OpenHalo 提供 MySQL 协议兼容的 PostgreSQL 内核不是同一实现。


配置概览

  • 配置名称:demo/mysql
  • 节点数量:4 个
  • my-meta:单节点 MySQL 8.4
  • my-test:三节点、单主模式 InnoDB Cluster,每个成员运行 MySQL Router
  • 模块状态:MYSQL PILOT,不计入正式模块数量
  • 平台边界:支持声明的 x86_64 RPM/DEB 平台及 EL9/EL10 aarch64;Oracle APT 当前没有 arm64 组件,因此 Debian/Ubuntu ARM 会被前置检查拒绝

模板中的所有 CHANGE_ME 值必须替换,且真实部署需要明确审批。先做只读预检:

ansible-playbook -i conf/demo/mysql.yml mysql.yml -l my-meta --check
ansible-playbook -i conf/demo/mysql.yml mysql.yml -l my-test --check

确认要写入活动清单后,再执行 ./configure -c demo/mysql,并对相同的完整集群范围依次运行 node.ymlmysql.yml--check 和真实收敛。三节点集群不接受部分成员范围。


配置内容

源文件地址:pigsty/conf/demo/mysql.yml

---
#==============================================================#
# File      :   mysql.yml
# Desc      :   MySQL 8.4 LTS standalone and three-node HA template
# Ctime     :   2026-07-16
# Mtime     :   2026-07-19
# Docs      :   https://pigsty.io/docs/mysql
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

# Canonical four-node MySQL platform example:
#   my-meta: one standalone member
#   my-test: three-member InnoDB Cluster in single-primary mode
#
# This file is a template, not the active deployment inventory. Replace every
# CHANGE_ME value and review the target addresses before configure or playbooks;
# MySQL preflight rejects any canonical CHANGE_ME credential left in place.
# Native Oracle 8.4 packages are admitted on x86_64 and EL9/EL10 aarch64. Oracle's
# APT repository currently has no arm64 component, so Ubuntu/Debian ARM is rejected.
#
# Read-only template preview (does not rewrite active pigsty.yml):
#   ansible-playbook -i conf/demo/mysql.yml mysql.yml -l my-meta --check
#   ansible-playbook -i conf/demo/mysql.yml mysql.yml -l my-test --check
# Each limit must include every declared member of the selected cluster group;
# partial HA member limits are rejected before any package or service change.
# After explicit approval to update active inventory, run ./configure -c demo/mysql,
# then repeat node.yml/mysql.yml --check with the same explicit limits.
# node.yml owns the shared trusted CA at /etc/pki/ca.crt; mysql.yml installs
# only MySQL/Router leaf certificates and requires node_ca to be complete.
#
# Real playbooks install/start services and require explicit approval.

all:
  children:
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }

    my-meta:
      hosts:
        10.10.10.10: { mysql_seq: 1 }
      vars: { mysql_cluster: my-meta, node_cluster: my-meta }

    my-test:
      hosts:
        10.10.10.11: { mysql_seq: 1 }
        10.10.10.12: { mysql_seq: 2 }
        10.10.10.13: { mysql_seq: 3 }
      vars: { mysql_cluster: my-test, node_cluster: my-test }

  vars:
    version: v4.5.0
    admin_ip: 10.10.10.10
    region: default                    # default | china; china uses USTC for MySQL

    repo_enabled: false               # use signed upstream repositories directly
    node_repo_modules: node,infra,mysql
    # For a Pigsty local/offline repository, enable repo and cache the complete
    # atomic platform set before provisioning targets:
    # repo_enabled: true
    # repo_extra_packages: [mysql]

    nodename_overwrite: false
    node_tune: oltp

    mysql_root_password: CHANGE_ME_MYSQL_ROOT
    mysql_monitor_password: CHANGE_ME_MYSQL_MONITOR
    mysql_cluster_password: CHANGE_ME_MYSQL_CLUSTER
    # Fixed MySQL 8.4, auto-tuned memory, daily local backup, and exporter are defaults.

    # Pigsty infrastructure credentials; replace before deployment.
    grafana_admin_password: CHANGE_ME_GRAFANA_ADMIN
    grafana_view_password: CHANGE_ME_GRAFANA_VIEW
    haproxy_admin_password: CHANGE_ME_HAPROXY
...

配置解读

  • MySQL 服务端、客户端、Shell、Router 与 XtraBackup 固定为 8.4 平台,不提供任意版本安装器。
  • 单节点使用 3306;三节点还使用 Group Replication 33061,并在每个成员提供 Router RW 6446 与 RO 6447
  • 默认启用每天一次的本地全量 XtraBackup 与 mysqld_exporter;当前试点不提供连续 binlog 归档、PITR 或自动恢复。
  • node.yml 负责安装共享信任锚 /etc/pki/ca.crt;MySQL 角色只签发并安装叶子证书。

完整约束与移除确认流程参见 原生 MySQL 试点文档

6.35 - build/oss

Pigsty 开源版离线软件包构建环境配置

build/oss 配置模板是 Pigsty 开源版离线软件包的构建环境配置,用于在多个操作系统上批量构建离线安装包。

此配置仅供开发者和贡献者使用。


配置概览

  • 配置名称: build/oss
  • 节点数量: 七节点(el9, el10, d12, d13, u22, u24, u26)
  • 配置说明:Pigsty 开源版离线软件包构建环境
  • 适用系统:el9, el10, d12, d13, u22, u24, u26
  • 适用架构:x86_64

启用方式:

cp conf/build/oss.yml pigsty.yml

备注:这是一个固定 IP 地址的构建模板,仅供内部使用


配置内容

源文件地址:pigsty/conf/build/oss.yml

---
#==============================================================#
# File      :   oss.yml
# Desc      :   Pigsty 3-node building env (PG18)
# Ctime     :   2024-10-22
# Mtime     :   2026-05-01
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

all:
  vars:
    version: v4.5.0
    admin_ip: 10.10.10.26
    region: china
    proxy_env:
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn,*.pigsty.cc"

    # building spec
    pg_version: 18
    repo_modules: infra,node,pgsql
    repo_packages: [ node-bootstrap, infra-package, infra-addons, node-package1, node-package2, node-package3, pgsql-utility, extra-modules ]
    pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap, pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    # OSS
    cache_pkg_dir: 'dist/${version}'
    repo_extra_packages: [pg18-core ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    # PRO
    #cache_pkg_dir: 'dist/${version}/pro'
    #repo_extra_packages: [
    #  pg18-main,pg18-time,pg18-gis,pg18-rag,pg18-fts,pg18-olap,pg18-feat,pg18-lang,pg18-type,pg18-util,pg18-func,pg18-admin,pg18-stat,pg18-sec,pg18-fdw,pg18-sim,pg18-etl,
    #  pg17-main,pg17-time,pg17-gis,pg17-rag,pg17-fts,pg17-olap,pg17-feat,pg17-lang,pg17-type,pg17-util,pg17-func,pg17-admin,pg17-stat,pg17-sec,pg17-fdw,pg17-sim,pg17-etl,
    #  pg16-main,pg16-time,pg16-gis,pg16-rag,pg16-fts,pg16-olap,pg16-feat,pg16-lang,pg16-type,pg16-util,pg16-func,pg16-admin,pg16-stat,pg16-sec,pg16-fdw,pg16-sim,pg16-etl,
    #  pg15-main,pg15-time,pg15-gis,pg15-rag,pg15-fts,pg15-olap,pg15-feat,pg15-lang,pg15-type,pg15-util,pg15-func,pg15-admin,pg15-stat,pg15-sec,pg15-fdw,pg15-sim,pg15-etl,
    #  pg14-main,pg14-time,pg14-gis,pg14-rag,pg14-fts,pg14-olap,pg14-feat,pg14-lang,pg14-type,pg14-util,pg14-func,pg14-admin,pg14-stat,pg14-sec,pg14-fdw,pg14-sim,pg14-etl,
    #  infra-extra, kafka-stack, java-runtime
    #]

  children:
    el9:  { hosts: { 10.10.10.9:  { pg_cluster: el9  ,pg_seq: 1 ,pg_role: primary }}}
    el10: { hosts: { 10.10.10.10: { pg_cluster: el10 ,pg_seq: 1 ,pg_role: primary }}}
    d12:  { hosts: { 10.10.10.12: { pg_cluster: d12  ,pg_seq: 1 ,pg_role: primary }}}
    d13:  { hosts: { 10.10.10.13: { pg_cluster: d13  ,pg_seq: 1 ,pg_role: primary }}}
    u22:  { hosts: { 10.10.10.22: { pg_cluster: u22  ,pg_seq: 1 ,pg_role: primary }}}
    u24:  { hosts: { 10.10.10.24: { pg_cluster: u24  ,pg_seq: 1 ,pg_role: primary }}}
    u26:  { hosts: { 10.10.10.26: { pg_cluster: u26  ,pg_seq: 1 ,pg_role: primary }}}
    etcd: { hosts: { 10.10.10.26:  { etcd_seq: 1 }}, vars: { etcd_cluster: etcd    }}
    infra:
      hosts:
        10.10.10.9:  { infra_seq: 1, admin_ip: 10.10.10.9  ,ansible_host: el9  }
        10.10.10.10: { infra_seq: 2, admin_ip: 10.10.10.10 ,ansible_host: el10 }
        10.10.10.12: { infra_seq: 3, admin_ip: 10.10.10.12 ,ansible_host: d12  }
        10.10.10.13: { infra_seq: 4, admin_ip: 10.10.10.13 ,ansible_host: d13  }
        10.10.10.22: { infra_seq: 5, admin_ip: 10.10.10.22 ,ansible_host: u22  }
        10.10.10.24: { infra_seq: 6, admin_ip: 10.10.10.24 ,ansible_host: u24  }
        10.10.10.26: { infra_seq: 7, admin_ip: 10.10.10.26 ,ansible_host: u26  }
      vars: { node_tune: oltp }

...

配置解读

build/oss 模板是 Pigsty 开源版离线软件包的构建配置。

构建内容

  • PostgreSQL 18 及所有分类扩展包
  • 基础设施软件包(Prometheus、Grafana、Nginx 等)
  • 节点软件包(监控代理、工具等)
  • 额外模块(extra-modules)

支持的操作系统

  • EL9 (Rocky/Alma/RHEL 9)
  • EL10 (Rocky 10 / RHEL 10)
  • Debian 12 (Bookworm)
  • Debian 13 (Trixie)
  • Ubuntu 22.04 (Jammy)
  • Ubuntu 24.04 (Noble)
  • Ubuntu 26.04 (Resolute)

构建流程

# 1. 准备构建环境
cp conf/build/oss.yml pigsty.yml

# 2. 在各节点上下载软件包
./infra.yml -t repo_build

# 3. 打包离线安装包
make cache

适用场景

  • Pigsty 开发者构建新版本
  • 贡献者测试新扩展
  • 企业用户自定义离线包

6.36 - build/dev

Pigsty 三节点本地构建与开发配置

build/dev 配置模板是 Pigsty 的三节点本地构建开发环境,用于在 EL9、Debian 12、Ubuntu 24 三类节点上验证仓库构建与包下载流程。

此配置仅供开发者和贡献者使用。


配置概览

  • 配置名称: build/dev
  • 节点数量:三节点(el9, d12, u24
  • 配置说明:本地构建开发环境,默认 PostgreSQL 18,构建 infra,node,pgsql 模块
  • 适用系统:el9, d12, u24
  • 适用架构:x86_64, aarch64
  • 相关配置:build/oss

启用方式:

cp conf/build/dev.yml pigsty.yml

备注:这是固定 IP 的开发构建模板,使用前需要按本地环境调整主机地址。


配置内容

源文件地址:pigsty/conf/build/dev.yml

---
#==============================================================#
# File      :   dev.yml
# Desc      :   Pigsty 3-node local build dev config
# Ctime     :   2025-07-17
# Mtime     :   2026-07-05
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

all:
  children:
    el9:  { hosts: { 10.10.10.9:  { pg_cluster: el9  ,pg_seq: 1 ,pg_role: primary }}}
    el10: { hosts: { 10.10.10.10: { pg_cluster: el10 ,pg_seq: 1 ,pg_role: primary }}}
    d12:  { hosts: { 10.10.10.12: { pg_cluster: d12  ,pg_seq: 1 ,pg_role: primary }}}
    d13:  { hosts: { 10.10.10.13: { pg_cluster: d13  ,pg_seq: 1 ,pg_role: primary }}}
    u22:  { hosts: { 10.10.10.22: { pg_cluster: u22  ,pg_seq: 1 ,pg_role: primary }}}
    u24:  { hosts: { 10.10.10.24: { pg_cluster: u24  ,pg_seq: 1 ,pg_role: primary }}}
    u26:  { hosts: { 10.10.10.26: { pg_cluster: u26  ,pg_seq: 1 ,pg_role: primary }}}
    etcd: { hosts: { 10.10.10.26:  { etcd_seq: 1 }}, vars: { etcd_cluster: etcd    }}
    infra:
      hosts:
        10.10.10.9:  { infra_seq: 1, admin_ip: 10.10.10.9  ,ansible_host: el9  }
        10.10.10.10: { infra_seq: 2, admin_ip: 10.10.10.10 ,ansible_host: el10 }
        10.10.10.12: { infra_seq: 3, admin_ip: 10.10.10.12 ,ansible_host: d12  }
        10.10.10.13: { infra_seq: 4, admin_ip: 10.10.10.13 ,ansible_host: d13  }
        10.10.10.22: { infra_seq: 5, admin_ip: 10.10.10.22 ,ansible_host: u22  }
        10.10.10.24: { infra_seq: 6, admin_ip: 10.10.10.24 ,ansible_host: u24  }
        10.10.10.26: { infra_seq: 7, admin_ip: 10.10.10.26 ,ansible_host: u26  }
      vars: { node_tune: oltp }

  vars:
    version: v4.5.0
    admin_ip: 10.10.10.26
    region: china
    proxy_env:
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn,*.pigsty.cc"

    # PRO
    #cache_pkg_dir: 'dist/${version}/pro'
    #repo_extra_packages: [
    #  pg18-main,pg18-time,pg18-gis,pg18-rag,pg18-fts,pg18-olap,pg18-feat,pg18-lang,pg18-type,pg18-util,pg18-func,pg18-admin,pg18-stat,pg18-sec,pg18-fdw,pg18-sim,pg18-etl,
    #  pg17-main,pg17-time,pg17-gis,pg17-rag,pg17-fts,pg17-olap,pg17-feat,pg17-lang,pg17-type,pg17-util,pg17-func,pg17-admin,pg17-stat,pg17-sec,pg17-fdw,pg17-sim,pg17-etl,
    #  pg16-main,pg16-time,pg16-gis,pg16-rag,pg16-fts,pg16-olap,pg16-feat,pg16-lang,pg16-type,pg16-util,pg16-func,pg16-admin,pg16-stat,pg16-sec,pg16-fdw,pg16-sim,pg16-etl,
    #  pg15-main,pg15-time,pg15-gis,pg15-rag,pg15-fts,pg15-olap,pg15-feat,pg15-lang,pg15-type,pg15-util,pg15-func,pg15-admin,pg15-stat,pg15-sec,pg15-fdw,pg15-sim,pg15-etl,
    #  pg14-main,pg14-time,pg14-gis,pg14-rag,pg14-fts,pg14-olap,pg14-feat,pg14-lang,pg14-type,pg14-util,pg14-func,pg14-admin,pg14-stat,pg14-sec,pg14-fdw,pg14-sim,pg14-etl,
    #  infra-extra, kafka-stack, java-runtime
    #]

    # building spec
    pg_version: 18
    cache_pkg_dir: 'dist/${version}'
    repo_modules: infra,node,pgsql
    repo_packages: [ node-bootstrap, infra-package, infra-addons, node-package1, node-package2, node-package3, pgsql-utility, extra-modules ]
    repo_extra_packages: [pg18-core ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
    pg_extensions:                 [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap, pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
    repo_upstream:
      # EL 7/8/9/10 REPOS
      - { name: pigsty-local   ,description: 'Pigsty Local'       ,module: local   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://${admin_ip}/pigsty' } ,meta: { skip_if_unavailable: 1 ,priority: 1 ,module_hotfixes: 1 }} # used by intranet nodes
      - { name: pigsty-infra   ,description: 'Pigsty INFRA'       ,module: infra   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/yum/infra/$basearch'               ,china: 'http://beta.pigsty.cc/yum/infra/$basearch' } ,meta: { priority: 12 ,module_hotfixes: 1 }}
      - { name: pigsty-pgsql   ,description: 'Pigsty PGSQL'       ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/yum/pgsql/el$releasever.$basearch' ,china: 'http://beta.pigsty.cc/yum/pgsql/el$releasever.$basearch' } ,meta: { priority: 11 ,module_hotfixes: 1 }}
      - { name: nginx          ,description: 'Nginx Repo'         ,module: infra   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://nginx.org/packages/rhel/$releasever/$basearch/' } ,meta: { module_hotfixes: 1 }}
      - { name: docker-ce      ,description: 'Docker CE'          ,module: infra   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.docker.com/linux/centos/$releasever/$basearch/stable'                       ,china: 'https://mirrors.cloud.tencent.com/docker-ce/linux/centos/$releasever/$basearch/stable https://repo.huaweicloud.com/docker-ce/linux/centos/$releasever/$basearch/stable https://mirrors.aliyun.com/docker-ce/linux/centos/$releasever/$basearch/stable'   ,europe: 'https://mirrors.xtom.de/docker-ce/linux/centos/$releasever/$basearch/stable' } ,meta: { skip_if_unavailable: 1 }}
      - { name: baseos         ,description: 'EL 8+ BaseOS'       ,module: node    ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://dl.rockylinux.org/pub/rocky/$releasever/BaseOS/$basearch/os/'                        ,china: 'https://mirrors.cloud.tencent.com/rocky/$releasever/BaseOS/$basearch/os/ https://repo.huaweicloud.com/rockylinux/$releasever/BaseOS/$basearch/os/ https://mirrors.aliyun.com/rockylinux/$releasever/BaseOS/$basearch/os/'             ,europe: 'https://mirrors.xtom.de/rocky/$releasever/BaseOS/$basearch/os/'     }}
      - { name: appstream      ,description: 'EL 8+ AppStream'    ,module: node    ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://dl.rockylinux.org/pub/rocky/$releasever/AppStream/$basearch/os/'                     ,china: 'https://mirrors.cloud.tencent.com/rocky/$releasever/AppStream/$basearch/os/ https://repo.huaweicloud.com/rockylinux/$releasever/AppStream/$basearch/os/ https://mirrors.aliyun.com/rockylinux/$releasever/AppStream/$basearch/os/'    ,europe: 'https://mirrors.xtom.de/rocky/$releasever/AppStream/$basearch/os/'  }}
      - { name: extras         ,description: 'EL 8+ Extras'       ,module: node    ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://dl.rockylinux.org/pub/rocky/$releasever/extras/$basearch/os/'                        ,china: 'https://mirrors.cloud.tencent.com/rocky/$releasever/extras/$basearch/os/ https://repo.huaweicloud.com/rockylinux/$releasever/extras/$basearch/os/ https://mirrors.aliyun.com/rockylinux/$releasever/extras/$basearch/os/'             ,europe: 'https://mirrors.xtom.de/rocky/$releasever/extras/$basearch/os/'     }}
      - { name: powertools     ,description: 'EL 8 PowerTools'    ,module: node    ,releases: [8     ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://dl.rockylinux.org/pub/rocky/$releasever/PowerTools/$basearch/os/'                    ,china: 'https://mirrors.cloud.tencent.com/rocky/$releasever/PowerTools/$basearch/os/ https://repo.huaweicloud.com/rockylinux/$releasever/PowerTools/$basearch/os/ https://mirrors.aliyun.com/rockylinux/$releasever/PowerTools/$basearch/os/' ,europe: 'https://mirrors.xtom.de/rocky/$releasever/PowerTools/$basearch/os/' }}
      - { name: crb            ,description: 'EL 9 CRB'           ,module: node    ,releases: [  9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://dl.rockylinux.org/pub/rocky/$releasever/CRB/$basearch/os/'                           ,china: 'https://mirrors.cloud.tencent.com/rocky/$releasever/CRB/$basearch/os/ https://repo.huaweicloud.com/rockylinux/$releasever/CRB/$basearch/os/ https://mirrors.aliyun.com/rockylinux/$releasever/CRB/$basearch/os/'                      ,europe: 'https://mirrors.xtom.de/rocky/$releasever/CRB/$basearch/os/'        }}
      - { name: epel           ,description: 'EL 8+ EPEL'         ,module: node    ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://mirrors.edge.kernel.org/fedora-epel/$releasever/Everything/$basearch/'               ,china: 'https://mirrors.cloud.tencent.com/epel/$releasever/Everything/$basearch/ https://repo.huaweicloud.com/epel/$releasever/Everything/$basearch/ https://mirrors.aliyun.com/epel/$releasever/Everything/$basearch/'                       ,europe: 'https://mirrors.xtom.de/epel/$releasever/Everything/$basearch/'     }}
      - { name: pgdg-common    ,description: 'PostgreSQL Common'  ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-$releasever-$basearch'      ,china: 'http://beta.pigsty.cc/yum/pgdg/common/redhat/rhel-$releasever-$basearch'      ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/common/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg14         ,description: 'PostgreSQL 14'      ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-$releasever-$basearch'          ,china: 'http://beta.pigsty.cc/yum/pgdg/14/redhat/rhel-$releasever-$basearch'          ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/14/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg15         ,description: 'PostgreSQL 15'      ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/15/redhat/rhel-$releasever-$basearch'          ,china: 'http://beta.pigsty.cc/yum/pgdg/15/redhat/rhel-$releasever-$basearch'          ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/15/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg16         ,description: 'PostgreSQL 16'      ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/16/redhat/rhel-$releasever-$basearch'          ,china: 'http://beta.pigsty.cc/yum/pgdg/16/redhat/rhel-$releasever-$basearch'          ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/16/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg17         ,description: 'PostgreSQL 17'      ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/17/redhat/rhel-$releasever-$basearch'          ,china: 'http://beta.pigsty.cc/yum/pgdg/17/redhat/rhel-$releasever-$basearch'          ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/17/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg18         ,description: 'PostgreSQL 18'      ,module: pgsql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/18/redhat/rhel-$releasever-$basearch'          ,china: 'http://beta.pigsty.cc/yum/pgdg/18/redhat/rhel-$releasever-$basearch'          ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/18/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg-beta      ,description: 'PostgreSQL Testing' ,module: beta    ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/testing/19/redhat/rhel-$releasever-$basearch'  ,china: 'http://beta.pigsty.cc/yum/pgdg/testing/19/redhat/rhel-$releasever-$basearch'  ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/testing/19/redhat/rhel-$releasever-$basearch'  } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg-beta      ,description: 'PostgreSQL Testing' ,module: beta    ,releases: [  9,10] ,arch: [        aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/testing/19/redhat/rhel-$releasever-$basearch'  ,china: 'http://beta.pigsty.cc/yum/pgdg/testing/19/redhat/rhel-$releasever-$basearch'  ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/testing/19/redhat/rhel-$releasever-$basearch'  } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg-extras    ,description: 'PostgreSQL Extra'   ,module: extra   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/extras/redhat/rhel-$releasever-$basearch'      ,china: 'http://beta.pigsty.cc/yum/pgdg/extras/redhat/rhel-$releasever-$basearch'      ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/extras/redhat/rhel-$releasever-$basearch'      } ,meta: { module_hotfixes: 1 }}
      - { name: pgdg14-nonfree ,description: 'PostgreSQL 14+'     ,module: extra   ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/non-free/14/redhat/rhel-$releasever-$basearch' ,china: 'http://beta.pigsty.cc/yum/pgdg/non-free/14/redhat/rhel-$releasever-$basearch' ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/non-free/14/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 ,skip_if_unavailable: 1 }}
      - { name: pgdg15-nonfree ,description: 'PostgreSQL 15+'     ,module: extra   ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/non-free/15/redhat/rhel-$releasever-$basearch' ,china: 'http://beta.pigsty.cc/yum/pgdg/non-free/15/redhat/rhel-$releasever-$basearch' ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/non-free/15/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 ,skip_if_unavailable: 1 }}
      - { name: pgdg16-nonfree ,description: 'PostgreSQL 16+'     ,module: extra   ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/non-free/16/redhat/rhel-$releasever-$basearch' ,china: 'http://beta.pigsty.cc/yum/pgdg/non-free/16/redhat/rhel-$releasever-$basearch' ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/non-free/16/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 ,skip_if_unavailable: 1 }}
      - { name: pgdg17-nonfree ,description: 'PostgreSQL 17+'     ,module: extra   ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/non-free/17/redhat/rhel-$releasever-$basearch' ,china: 'http://beta.pigsty.cc/yum/pgdg/non-free/17/redhat/rhel-$releasever-$basearch' ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/non-free/17/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 ,skip_if_unavailable: 1 }}
      - { name: pgdg18-nonfree ,description: 'PostgreSQL 18+'     ,module: extra   ,releases: [8,9,10] ,arch: [x86_64         ] ,baseurl: { default: 'https://download.postgresql.org/pub/repos/yum/non-free/18/redhat/rhel-$releasever-$basearch' ,china: 'http://beta.pigsty.cc/yum/pgdg/non-free/18/redhat/rhel-$releasever-$basearch' ,europe: 'https://mirrors.xtom.de/postgresql/repos/yum/non-free/18/redhat/rhel-$releasever-$basearch' } ,meta: { module_hotfixes: 1 ,skip_if_unavailable: 1 }}
      - { name: timescaledb    ,description: 'TimescaleDB'        ,module: extra   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packagecloud.io/timescale/timescaledb/el/$releasever/$basearch'  }}
      - { name: percona        ,description: 'Percona TDE'        ,module: percona ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/yum/percona/el$releasever.$basearch' ,china: 'http://beta.pigsty.cc/yum/percona/el$releasever.$basearch' ,origin: 'http://repo.percona.com/ppg-18.4/yum/release/$releasever/RPMS/$basearch'  } ,meta: { module_hotfixes: 1 }}
      - { name: groonga        ,description: 'Groonga'            ,module: groonga ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.groonga.org/almalinux/$releasever/$basearch/' }}
      - { name: mysql          ,description: 'MySQL 8.4 LTS'      ,module: mysql   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.mysql.com/yum/mysql-8.4-community/el/$releasever/$basearch/' } ,meta: { module_hotfixes: 1 }}
      - { name: mongo          ,description: 'MongoDB'            ,module: mongo   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/8.0/$basearch/' }}
      - { name: redis          ,description: 'Redis'              ,module: redis   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://rpmfind.net/linux/remi/enterprise/$releasever/redis72/$basearch/' } ,meta: { module_hotfixes: 1 }}
      - { name: grafana        ,description: 'Grafana'            ,module: grafana ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://rpm.grafana.com', china: 'https://mirrors.cloud.tencent.com/grafana/yum/rpm/' }}
      - { name: kubernetes     ,description: 'Kubernetes'         ,module: kube    ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://pkgs.k8s.io/core:/stable:/v1.36/rpm/', china: 'https://mirrors.ustc.edu.cn/kubernetes/core:/stable:/v1.36/rpm/' }}
      - { name: gitlab-ee      ,description: 'Gitlab EE'          ,module: gitlab  ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.gitlab.com/gitlab/gitlab-ee/el/$releasever/$basearch' }}
      - { name: gitlab-ce      ,description: 'Gitlab CE'          ,module: gitlab  ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.gitlab.com/gitlab/gitlab-ce/el/$releasever/$basearch' }}
      - { name: clickhouse     ,description: 'ClickHouse'         ,module: click   ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.clickhouse.com/rpm/stable/', china: 'https://repo.huaweicloud.com/clickhouse/rpm/stable/' }}

      # DEB 12/13 Ubuntu 22/24/26 REPOS
      - { name: pigsty-local   ,description: 'Pigsty Local'       ,module: local   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://${admin_ip}/pigsty ./' }}
      - { name: pigsty-pgsql   ,description: 'Pigsty PgSQL'       ,module: pgsql   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/apt/pgsql/${distro_codename} ${distro_codename} main' ,china: 'http://beta.pigsty.cc/apt/pgsql/${distro_codename} ${distro_codename} main' }}
      - { name: pigsty-infra   ,description: 'Pigsty Infra'       ,module: infra   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/apt/infra/ generic main'                              ,china: 'http://beta.pigsty.cc/apt/infra/ generic main' }}
      - { name: nginx          ,description: 'Nginx'              ,module: nginx   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://nginx.org/packages/${distro_name} ${distro_codename} nginx' }}
      - { name: docker-ce      ,description: 'Docker'             ,module: infra   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.docker.com/linux/${distro_name} ${distro_codename} stable'                               ,china: 'https://mirrors.cloud.tencent.com/docker-ce/linux/${distro_name} ${distro_codename} stable' }}
      - { name: base           ,description: 'Debian Basic'       ,module: node    ,releases: [11,12,13         ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://deb.debian.org/debian/ ${distro_codename} main non-free-firmware'                                  ,china: 'https://mirrors.cloud.tencent.com/debian/ ${distro_codename} main non-free-firmware' }}
      - { name: updates        ,description: 'Debian Updates'     ,module: node    ,releases: [11,12,13         ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://deb.debian.org/debian/ ${distro_codename}-updates main non-free-firmware'                          ,china: 'https://mirrors.cloud.tencent.com/debian/ ${distro_codename}-updates main non-free-firmware' }}
      - { name: security       ,description: 'Debian Security'    ,module: node    ,releases: [11,12,13         ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://security.debian.org/debian-security ${distro_codename}-security main non-free-firmware'            ,china: 'https://mirrors.cloud.tencent.com/debian-security/ ${distro_codename}-security main non-free-firmware' }}
      - { name: base           ,description: 'Ubuntu Basic'       ,module: node    ,releases: [         22,24,26] ,arch: [x86_64         ] ,baseurl: { default: 'https://mirrors.edge.kernel.org/ubuntu/ ${distro_codename}           main universe multiverse restricted' ,china: 'https://mirrors.cloud.tencent.com/ubuntu/ ${distro_codename}           main restricted universe multiverse' }}
      - { name: updates        ,description: 'Ubuntu Updates'     ,module: node    ,releases: [         22,24,26] ,arch: [x86_64         ] ,baseurl: { default: 'https://mirrors.edge.kernel.org/ubuntu/ ${distro_codename}-updates   main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu/ ${distro_codename}-updates   main restricted universe multiverse' }}
      - { name: backports      ,description: 'Ubuntu Backports'   ,module: node    ,releases: [         22,24,26] ,arch: [x86_64         ] ,baseurl: { default: 'https://mirrors.edge.kernel.org/ubuntu/ ${distro_codename}-backports main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu/ ${distro_codename}-backports main restricted universe multiverse' }}
      - { name: security       ,description: 'Ubuntu Security'    ,module: node    ,releases: [         22,24,26] ,arch: [x86_64         ] ,baseurl: { default: 'https://mirrors.edge.kernel.org/ubuntu/ ${distro_codename}-security  main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu/ ${distro_codename}-security  main restricted universe multiverse' }}
      - { name: base           ,description: 'Ubuntu Basic'       ,module: node    ,releases: [         22,24,26] ,arch: [        aarch64] ,baseurl: { default: 'http://ports.ubuntu.com/ubuntu-ports/ ${distro_codename}             main universe multiverse restricted' ,china: 'https://mirrors.cloud.tencent.com/ubuntu-ports/ ${distro_codename}           main restricted universe multiverse' }}
      - { name: updates        ,description: 'Ubuntu Updates'     ,module: node    ,releases: [         22,24,26] ,arch: [        aarch64] ,baseurl: { default: 'http://ports.ubuntu.com/ubuntu-ports/ ${distro_codename}-updates     main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu-ports/ ${distro_codename}-updates   main restricted universe multiverse' }}
      - { name: backports      ,description: 'Ubuntu Backports'   ,module: node    ,releases: [         22,24,26] ,arch: [        aarch64] ,baseurl: { default: 'http://ports.ubuntu.com/ubuntu-ports/ ${distro_codename}-backports   main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu-ports/ ${distro_codename}-backports main restricted universe multiverse' }}
      - { name: security       ,description: 'Ubuntu Security'    ,module: node    ,releases: [         22,24,26] ,arch: [        aarch64] ,baseurl: { default: 'http://ports.ubuntu.com/ubuntu-ports/ ${distro_codename}-security    main restricted universe multiverse' ,china: 'https://mirrors.cloud.tencent.com/ubuntu-ports/ ${distro_codename}-security  main restricted universe multiverse' }}
      - { name: pgdg           ,description: 'PGDG'               ,module: pgsql   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://beta.pigsty.cc/apt/pgdg/ ${distro_codename}-pgdg main' ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/apt/ ${distro_codename}-pgdg main' }}
      - { name: pgdg-beta      ,description: 'PGDG Beta'          ,module: beta    ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://beta.pigsty.cc/apt/pgdg/ ${distro_codename}-pgdg-testing main 19' ,china: 'https://mirrors.cloud.tencent.com/postgresql/repos/apt/ ${distro_codename}-pgdg-testing main 19' }}
      - { name: timescaledb    ,description: 'TimescaleDB'        ,module: extra   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packagecloud.io/timescale/timescaledb/${distro_name}/ ${distro_codename} main' }}
      - { name: citus          ,description: 'Citus'              ,module: extra   ,releases: [11,12,   22      ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packagecloud.io/citusdata/community/${distro_name}/ ${distro_codename} main' } }
      - { name: percona        ,description: 'Percona TDE'        ,module: percona ,releases: [   12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.pigsty.io/apt/percona ${distro_codename} main' ,china: 'http://beta.pigsty.cc/apt/percona ${distro_codename} main' }}
      - { name: groonga        ,description: 'Groonga Debian'     ,module: groonga ,releases: [11,12,13         ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.groonga.org/debian/ ${distro_codename} main' }}
      - { name: groonga        ,description: 'Groonga Ubuntu'     ,module: groonga ,releases: [         22,24   ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://ppa.launchpadcontent.net/groonga/ppa/ubuntu/ ${distro_codename} main' }}
      - { name: mysql          ,description: 'MySQL 8.4 LTS'      ,module: mysql   ,releases: [   12,13,22,24   ] ,arch: [x86_64         ] ,baseurl: { default: 'https://repo.mysql.com/apt/${distro_name} ${distro_codename} mysql-8.4-lts' ,china: 'https://mirrors.ustc.edu.cn/mysql-repo/apt/${distro_name} ${distro_codename} mysql-8.4-lts' }}
      - { name: mongo          ,description: 'MongoDB'            ,module: mongo   ,releases: [   12,   22,24   ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://repo.mongodb.org/apt/${distro_name} ${distro_codename}/mongodb-org/8.0 multiverse' ,china: 'https://mirrors.cloud.tencent.com/mongodb/apt/${distro_name} ${distro_codename}/mongodb-org/8.0 multiverse' }}
      - { name: redis          ,description: 'Redis'              ,module: redis   ,releases: [11,12,   22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.redis.io/deb ${distro_codename} main' }}
      - { name: llvm           ,description: 'LLVM'               ,module: llvm    ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://apt.llvm.org/${distro_codename}/ llvm-toolchain-${distro_codename} main' ,china: 'https://mirrors.tuna.tsinghua.edu.cn/llvm-apt/${distro_codename}/ llvm-toolchain-${distro_codename} main' }}
      - { name: haproxyd       ,description: 'Haproxy Debian'     ,module: haproxy ,releases: [   12            ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'http://haproxy.debian.net/ ${distro_codename}-backports-3.2 main' }}
      - { name: haproxyu       ,description: 'Haproxy Ubuntu'     ,module: haproxy ,releases: [            24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://ppa.launchpadcontent.net/vbernat/haproxy-3.2/ubuntu/ ${distro_codename} main' }}
      - { name: grafana        ,description: 'Grafana'            ,module: grafana ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://apt.grafana.com stable main' ,china: 'https://mirrors.cloud.tencent.com/grafana/apt/ stable main' }}
      - { name: kubernetes     ,description: 'Kubernetes'         ,module: kube    ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /', china: 'https://mirrors.ustc.edu.cn/kubernetes/core:/stable:/v1.36/deb/ /' }}
      - { name: gitlab-ee      ,description: 'Gitlab EE'          ,module: gitlab  ,releases: [11,12,13,22,24   ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.gitlab.com/gitlab/gitlab-ee/${distro_name}/ ${distro_codename} main' }}
      - { name: gitlab-ce      ,description: 'Gitlab CE'          ,module: gitlab  ,releases: [11,12,13,22,24   ] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.gitlab.com/gitlab/gitlab-ce/${distro_name}/ ${distro_codename} main' }}
      - { name: clickhouse     ,description: 'ClickHouse'         ,module: click   ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://packages.clickhouse.com/deb/ stable main', china: 'https://repo.huaweicloud.com/clickhouse/deb/ stable main' }}

...

配置解读

build/dev 主要用于验证 Pigsty 软件仓库构建链路,而不是面向普通生产安装。

关键特性

  • 默认 pg_version: 18
  • 本地缓存目录为 dist/${version}
  • 默认构建 infra,node,pgsql 三类模块
  • 预置 PostgreSQL 18 全类别扩展包组
  • 通过三类发行版节点覆盖 RPM 与 DEB 构建路径

适用场景

  • Pigsty 新版本构建验证
  • 软件仓库与镜像源调试
  • 扩展包下载与缓存测试

6.37 - demo/remote

使用 INFRA 节点上的 pg_exporter 监控远程 PostgreSQL 与云 RDS 的示例

demo/remote 不部署本地 PostgreSQL 集群,而是在 INFRA 节点上声明多个 pg_exporters,用于接入远程 PostgreSQL、PolarDB 或云 RDS。


配置概览

  • 配置名称:demo/remote
  • 本地节点数量:1 个 INFRA 节点
  • Exporter 示例端口:2000120016
  • 相关文档:PG Exporter
./configure -c demo/remote [-i <infra_ip>]

配置内容

源文件地址:pigsty/conf/demo/remote.yml

---
#==============================================================#
# File      :   remote.yml
# Desc      :   Monitoring Remote RDS with pigsty
# Ctime     :   2020-05-22
# Mtime     :   2025-12-12
# Docs      :   https://pigsty.io/docs/conf
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

all:
  children:

    infra:            # infra cluster for proxy, monitor, alert, etc..
      hosts: { 10.10.10.10: { infra_seq: 1 } }
      vars:           # install pg_exporter for remote postgres RDS on a group 'infra'
        pg_exporters: # list all remote instances here, alloc a unique unused local port as k
          20001: { pg_cluster: pg-foo, pg_seq: 1, pg_host: 10.10.10.10 }
          20002: { pg_cluster: pg-bar, pg_seq: 1, pg_host: 10.10.10.11 , pg_port: 5432 }
          20003: { pg_cluster: pg-bar, pg_seq: 2, pg_host: 10.10.10.12 , pg_exporter_url: 'postgres://dbuser_monitor:[email protected]:5432/postgres?sslmode=disable'}
          20004: { pg_cluster: pg-bar, pg_seq: 3, pg_host: 10.10.10.13 , pg_monitor_username: dbuser_monitor, pg_monitor_password: DBUser.Monitor }

          20011:
            pg_cluster: pg-polar                        # RDS Cluster Name (Identity, Explicitly Assigned, used as 'cls')
            pg_seq: 1                                   # RDS Instance Seq (Identity, Explicitly Assigned, used as part of 'ins')
            pg_host: pxx.polardbpg.rds.aliyuncs.com     # RDS Host Address
            pg_port: 1921                               # RDS Port
            pg_exporter_include_database: 'test'        # Only monitoring database in this list
            pg_monitor_username: dbuser_monitor         # monitor username, overwrite default
            pg_monitor_password: DBUser_Monitor         # monitor password, overwrite default
            pg_databases: [{ name: test }]              # database to be added to grafana datasource

          20012:
            pg_cluster: pg-polar                        # RDS Cluster Name (Identity, Explicitly Assigned, used as 'cls')
            pg_seq: 2                                   # RDS Instance Seq (Identity, Explicitly Assigned, used as part of 'ins')
            pg_host: pe-xx.polarpgmxs.rds.aliyuncs.com  # RDS Host Address
            pg_port: 1521                               # RDS Port
            pg_databases: [{ name: test }]              # database to be added to grafana datasource

          20014:
            pg_cluster: pg-rds
            pg_seq: 1
            pg_host: pgm-xx.pg.rds.aliyuncs.com
            pg_port: 5432
            pg_exporter_auto_discovery: true
            pg_exporter_include_database: 'rds'
            pg_monitor_username: dbuser_monitor
            pg_monitor_password: DBUser_Monitor
            pg_databases: [ { name: rds } ]

          20015:
            pg_cluster: pg-rdsha
            pg_seq: 1
            pg_host: pgm-2xx8wu.pg.rds.aliyuncs.com
            pg_port: 5432
            pg_exporter_auto_discovery: true
            pg_exporter_include_database: 'rds'
            pg_databases: [{ name: test }, {name: rds}]

          20016:
            pg_cluster: pg-rdsha
            pg_seq: 2
            pg_host: pgr-xx.pg.rds.aliyuncs.com
            pg_exporter_auto_discovery: true
            pg_exporter_include_database: 'rds'
            pg_databases: [{ name: test }, {name: rds}]
  
  
  vars:
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default,china,europe

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

每个 pg_exporters 条目使用一个唯一的本地监听端口,并声明远端实例的 pg_clusterpg_seqpg_host 与可选连接参数。模板同时展示完整 URL、拆分账号密码、数据库白名单与自动发现等写法。

示例主机名和凭据都是占位值。实际使用时只保留需要的条目,并使用最小权限监控账号;不要把真实 RDS 密码提交到版本库。

6.38 - demo/saas

传统单节点 SaaS 组件组合示例,包含 PostgreSQL、Silo、Redis 与多应用入口

demo/saas 是一个传统的功能丰富单节点示例,预置多组业务用户、数据库和应用入口,用于展示 PostgreSQL、Silo、Redis、Docker 与 Portal 的组合方式。


配置概览

  • 配置名称:demo/saas
  • 节点数量:单节点
  • 模块:INFRA、ETCD、MINIO、PGSQL、REDIS、DOCKER
  • 相关配置:richsupabase
./configure -c demo/saas [-i <primary_ip>]

配置内容

源文件地址:pigsty/conf/demo/saas.yml

---
#==============================================================#
# File      :   saas.yml (1-node)
# Desc      :   Feature rich 1-node template with all extensions
# Ctime     :   2020-05-22
# Mtime     :   2025-12-12
# Docs      :   https://pigsty.io/docs/conf
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#


all:

  #==============================================================#
  # Clusters, Nodes, and Modules
  #==============================================================#
  children:

    #----------------------------------#
    # infra: monitor, alert, repo, etc..
    #----------------------------------#
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }
      vars:
        docker_enabled: true      # enabled docker with ./docker.yml
        #docker_registry_mirrors: ["https://docker.1panel.live","https://docker.1ms.run","https://docker.xuanyuan.me","https://registry-1.docker.io"]

    #----------------------------------#
    # etcd cluster for HA postgres DCS
    #----------------------------------#
    etcd:
      hosts:
        10.10.10.10: { etcd_seq: 1 }
      vars:
        etcd_cluster: etcd

    #----------------------------------#
    # minio (OPTIONAL backup repo)
    #----------------------------------#
    minio:
      hosts:
        10.10.10.10: { minio_seq: 1 }
      vars:
        minio_cluster: minio
        minio_users:                      # list of minio user to be created
          - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
          - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
          - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }

    #----------------------------------#
    # pgsql (singleton on current node)
    #----------------------------------#
    # postgres cluster: pg-meta
    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-meta
        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 }
          - {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     }
          - {name: dbuser_noco     ,password: DBUser.Noco     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for nocodb service      }
          - {name: dbuser_odoo     ,password: DBUser.Odoo     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for odoo service ,createdb: true} #,superuser: true}
        pg_databases:
          - {name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [{name: vector},{name: postgis},{name: timescaledb}]}
          - {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 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  }
          - {name: noco     ,owner: dbuser_noco     ,revokeconn: true ,comment: nocodb database     }
          #- {name: odoo     ,owner: dbuser_odoo     ,revokeconn: true ,comment: odoo main database  }
        pg_hba_rules:
          - {user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes'}
        pg_libs: 'timescaledb,pg_stat_statements, auto_explain'  # add timescaledb to shared_preload_libraries
        node_crontab:  # make one full backup 1 am everyday
          - '00 01 * * * /pg/bin/pg-backup full'

    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 }


  vars:                               # global variables
    version: v4.5.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    node_tune: oltp                   # node tuning specs: oltp,olap,tiny,crit
    pg_conf: oltp.yml                 # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
    proxy_env:                        # global proxy env when downloading packages
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
      # http_proxy:  # set your proxy here: e.g http://user:[email protected]
      # https_proxy: # set your proxy here: e.g http://user:[email protected]
      # all_proxy:   # set your proxy here: e.g http://user:[email protected]
    infra_portal:                     # infra services exposed via portal
      home         : { domain: i.pigsty }     # default domain name
      minio        : { domain: m.pigsty    ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }
      postgrest    : { domain: api.pigsty  ,endpoint: "127.0.0.1:8884" }
      pgadmin      : { domain: adm.pigsty  ,endpoint: "127.0.0.1:8885" }
      pgweb        : { domain: cli.pigsty  ,endpoint: "127.0.0.1:8886" }
      bytebase     : { domain: ddl.pigsty  ,endpoint: "127.0.0.1:8887" }
      jupyter      : { domain: lab.pigsty  ,endpoint: "127.0.0.1:8888", websocket: true }
      gitea        : { domain: git.pigsty  ,endpoint: "127.0.0.1:8889" }
      wiki         : { domain: wiki.pigsty ,endpoint: "127.0.0.1:9002" }
      noco         : { domain: noco.pigsty ,endpoint: "127.0.0.1:9003" }
      supa         : { domain: supa.pigsty ,endpoint: "10.10.10.10:8000", websocket: true }
      dify         : { domain: dify.pigsty ,endpoint: "10.10.10.10:8001", websocket: true }
      odoo         : { domain: odoo.pigsty, endpoint: "127.0.0.1:8069"  , websocket: true }

    #----------------------------------#
    # MinIO Related Options
    #----------------------------------#
    pgbackrest_method: minio          # use minio as backup repo instead of 'local'
    pgbackrest_repo:                  # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
      local:                          # default pgbackrest repo with local posix fs
        path: /pg/backup              # local backup directory, `/pg/backup` by default
        retention_full_type: count    # retention full backups by count
        retention_full: 2             # keep 2, at most 3 full backup when using local fs repo
      minio:                          # optional minio repo for pgbackrest
        type: s3                      # minio is s3-compatible, so s3 is used
        s3_endpoint: sss.pigsty       # minio endpoint domain name, `sss.pigsty` by default
        s3_region: us-east-1          # minio region, us-east-1 by default, useless for minio
        s3_bucket: pgsql              # minio bucket name, `pgsql` by default
        s3_key: pgbackrest            # minio user access key for pgbackrest
        s3_key_secret: S3User.Backup  # minio user secret key for pgbackrest
        s3_uri_style: path            # use path style uri for minio rather than host style
        path: /pgbackrest             # minio backup path, default is `/pgbackrest`
        storage_port: 9000            # minio port, 9000 by default
        storage_ca_file: /etc/pki/ca.crt  # minio ca file path, `/etc/pki/ca.crt` by default
        block: y                      # Enable block incremental backup
        bundle: y                     # bundle small files into a single file
        bundle_limit: 20MiB           # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB           # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
        cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
        retention_full_type: time     # retention full backup by time on minio repo
        retention_full: 14            # keep full backup for last 14 days
    node_etc_hosts: [ "${admin_ip} i.pigsty sss.pigsty" ]
    dns_records: [ "${admin_ip} api.pigsty adm.pigsty cli.pigsty ddl.pigsty lab.pigsty git.pigsty wiki.pigsty noco.pigsty supa.pigsty dify.pigsty odoo.pigsty" ]

    #----------------------------------#
    # Safe Guard
    #----------------------------------#
    # you can enable these flags after bootstrap, to prevent purging running etcd / pgsql instances
    etcd_safeguard: false             # prevent purging running etcd instance?
    pg_safeguard: false               # prevent purging running postgres instance? false by default

    #----------------------------------#
    # Repo, Node, Packages
    #----------------------------------#
    repo_remove: true                 # remove existing repo on admin node during repo bootstrap
    node_repo_remove: true            # remove existing node repo for node managed by pigsty
    repo_extra_packages: [ pg17-core ,pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]
    pg_version: 18                    # default postgres version
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

模板预置 Grafana、Bytebase、Kong、Gitea、Wiki、NocoDB 与 Odoo 等数据库账号/数据库占位项,使用 Silo 作为 pgBackRest 仓库,并提供 Redis 主从示例和多个 Portal 域名。

这是兼容与参考用途的组合模板,并不等于所有应用都会自动安装。新部署优先选用 rich 与对应的 app/* 专用模板;部署前删除不需要的账号、数据库和入口并更换所有密码。

6.39 - demo/wool

面向中国区低配云主机的单节点 tiny 参数示例

demo/wool 是面向中国区低配云主机的单节点示例,默认使用 region: china、PostgreSQL 18 与 tiny 调优参数。


配置概览

  • 配置名称:demo/wool
  • 节点数量:单节点
  • 建议规格:约 2C/2G 的测试主机
  • 相关配置:metaslim
./configure -c demo/wool [-i <private_ip>]

配置内容

源文件地址:pigsty/conf/demo/wool.yml

---
#==============================================================#
# File      :   wool.yml
# Desc      :   Pigsty Aliyun ECS 羊毛机配置文件
# Ctime     :   2020-11-09
# Mtime     :   2025-12-12
# Docs      :   https://pigsty.io/docs/conf
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng ([email protected])
#==============================================================#

all:
  children:

    # 建议使用操作系统: RockyLinux 9.4
    # 这里的 10.10.10.10 都应该是你 ECS 的内网 IP 地址,用于安装 Infra/Etcd 模块
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }

    # 定义一个单节点的 PostgreSQL 数据库实例
    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-meta
        pg_databases:
          - { name: meta ,baseline: cmdb.sql ,schemas: [ pigsty ] }
        pg_users: # 最好把这里的两个样例用户的密码也修改一下
          - { name: dbuser_meta ,password: DBUser.Meta   ,roles: [ dbrole_admin ] }
          - { name: dbuser_view ,password: DBUser.Viewer ,roles: [ dbrole_readonly ] }
        pg_conf: tiny.yml   # 2C/2G 的云服务器,使用微型数据库配置模板
        node_tune: tiny     # 2C/2G 的云服务器,使用微型主机节点参数优化模板
        pgbackrest_enabled: false # 这么点磁盘空间,就别搞数据库物理备份了
        pg_version: 18           # 用 PostgreSQL 18

  vars:
    version: v4.5.0                   # pigsty version string
    region: china
    admin_ip: 10.10.10.10  # 这个 IP 地址应该是你 ECS 的内网IP地址
    infra_portal: # 如果你有自己的 DNS 域名,这里面的域名后缀 pigsty 换成你自己的 DNS 域名
      home : { domain: i.pigsty }     # default domain name
      minio: { domain: m.pigsty  ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }
      postgrest: { domain: api.pigsty  ,endpoint: "127.0.0.1:8884" }
      pgadmin: { domain: adm.pigsty  ,endpoint: "127.0.0.1:8885" }
      pgweb: { domain: cli.pigsty  ,endpoint: "127.0.0.1:8886" }
      bytebase: { domain: ddl.pigsty  ,endpoint: "127.0.0.1:8887" ,websocket: true }
      jupyter: { domain: lab.pigsty  ,endpoint: "127.0.0.1:8888", websocket: true }
      gitea: { domain: git.pigsty  ,endpoint: "127.0.0.1:8889" }
      wiki: { domain: wiki.pigsty ,endpoint: "127.0.0.1:9002" }
      noco: { domain: noco.pigsty ,endpoint: "127.0.0.1:9003" }
      supa: { domain: supa.pigsty ,endpoint: "10.10.10.10:8000", websocket: true }

    # 把这里的密码都改掉!你也不想别人随便来串门对吧!
    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...

配置解读

  • pg-meta 上显式设置 pg_conf: tiny.ymlnode_tune: tiny
  • 使用云主机内网 IP 替换 10.10.10.10
  • 默认禁用 pgBackRest,以减少低配测试机的磁盘占用
  • 预留多个 Portal 域名示例

该模板牺牲备份能力换取更低资源消耗,只适合临时测试。生产环境必须启用并验证备份、收紧网络规则、替换默认密码,并按实际 DNS 删除无用入口。

7 - 运维 SOP 索引

面向新手用户的 Pigsty 与 PostgreSQL 运维文档索引:按常见任务找到应读文档。

上手路线

顺序 要解决的问题 入口
1 Pigsty 由哪些模块组成? 积木式架构PGSQL 架构PGSQL 集群模型
2 怎么先跑起来? 快速上手图形界面快速上手 PostgreSQL
3 配置文件该怎么看? 声明式配置配置清单配置参数
4 生产部署要准备什么? 架构规划资源准备管理机制
5 怎么部署多节点集群? 生产部署执行剧本PGSQL 剧本
6 日常怎么管库? PGSQL 日常管理集群管理用户管理数据库管理
7 怎么验证可靠性? PG 高可用Patroni 管理备份恢复恢复操作

任务索引

任务 先看 操作入口
准备服务器、磁盘、网络、VIP 资源准备架构规划Linux 兼容性 生产部署
准备 SSH、Sudo、管理用户 管理机制 生产部署
本地或云上搭沙箱 沙箱环境 VagrantTerraform
单机体验 快速上手 ./configure -g./deploy.yml
多节点生产部署 部署生产部署 ./deploy.yml./pgsql.yml
离线环境部署 离线安装 软件仓库管理
选择配置模板 配置模板模板列表 ./configure -c <template>
规划集群名、库名、用户名 PGSQL 集群模型 pg_clusterpg_databasespg_users
创建数据库集群 集群实例配置 集群管理./pgsql.yml -l <cluster>
新增业务用户 用户/角色配置 用户管理./pgsql-user.yml -l <cluster>
新增业务数据库 数据库配置 数据库管理./pgsql-db.yml -l <cluster>
配置访问入口 服务/接入 pg_servicespg_default_services
修改 HBA HBA 配置 HBA 管理
主从切换 Patroni 管理 patronictl switchover
HA 故障演练 PG 高可用RPORTO 3坏2应急处理
配置 VIP HA 服务接入 配置 PG VIP
配置备份策略 备份策略 备份管理命令
做 PITR 时间点恢复 时间点恢复 恢复操作
误删数据、表、库 误删处理 手工恢复
克隆恢复集群 克隆数据库集群 Fork 实例
使用 Silo 存备份 MINIO 模块 Silo 配置备份仓库
查看监控告警 监控系统 PGSQL 监控PGSQL 仪表盘
排查数据库故障 PGSQL 常见问题 故障排查组件管理
扩容、缩容 PG 集群 集群实例配置 集群管理
升级 PostgreSQL 版本升级 内核版本
安装或启用扩展 扩展插件 扩展管理
迁移已有数据库 数据迁移 迁移剧本
做安全加固 安全考量 访问控制CA 与证书
管理域名与 Web 入口 域名管理 Nginx 管理
维护基础设施 INFRA 管理预案 infra.ymlinfra-rm.yml
维护 Etcd ETCD 配置 ETCD 管理ETCD FAQ
部署应用模板 应用 Docker 模块./app.yml

准备与部署

生产部署先看 架构规划资源准备。这两篇解决节点数量、磁盘、文件系统、网络、VIP、域名、软件源这些问题。

机器准备好以后,看 管理机制:管理用户、免密 SSH、Sudo、可达性、防火墙都在这里。系统版本和架构看 Linux 兼容性

第一次安装走 快速上手。多节点生产环境走 生产部署。没有互联网访问时,看 离线安装软件仓库管理

模板选择不用一开始想太复杂:单机默认看 meta;三节点 HA 看 ha/trio;更完整的 HA 看 ha/full;强调一致性看 ha/safe;资源紧张时看 ha/dualha/simu


命名与配置

先分清三个名字:集群名、数据库名、服务名。

pg_cluster 是 Pigsty 管理 PostgreSQL 集群的顶层名字,会影响实例名、服务名、备份 stanza、监控标签和很多文件路径。它不是一个可以随手改的显示名。命名规则看 PGSQL 集群模型;不同实例角色看 集群实例配置;服务名和连接入口看 服务/接入

数据库名和用户名是 PostgreSQL 里的逻辑对象。库名看 数据库配置数据库管理;用户和角色看 用户/角色配置用户管理;权限模型看 访问控制ACL 配置

经验上,集群名用小写字母、数字、短横线,例如 pg-metapg-testpg-user-prod。数据库对象名用 snake_case,别用中文、空格、大小写混用和 SQL 关键字。更完整的命名背景可以读 数据库集群管理概念与实体命名规范PostgreSQL 规约(2024版)

配置变更遵循一个习惯:先改 pigsty.yml,再执行对应剧本。配置结构看 声明式配置配置清单;参数含义看 配置参数参数列表;剧本入口看 执行剧本剧本列表


日常管理

数据库管理的总入口是 PGSQL 日常管理

操作 文档
创建、扩容、缩容、下线、克隆集群 集群管理
创建、修改、删除业务用户 用户管理
创建、修改、删除、重建数据库 数据库管理
刷新和排查 HBA HBA 管理
查看 HA 状态、切换、重启、重做从库 Patroni 管理
管理连接池 Pgbouncer 管理
启停 PostgreSQL、Patroni、Pgbouncer、Exporter 组件管理
管理备份、校验、清理、恢复 备份恢复
配置备份、Vacuum、Analyze 等定时任务 定时任务
升级版本与扩展 版本升级扩展管理

PostgreSQL 例行维护的背景文章可以看 PostgreSQL 例行维护


高可用演练

理解 HA 先看 PG 高可用。不要只看“能不能自动切换”,还要看 RPORTO:前者是最多能丢多少数据,后者是多久恢复服务。

接入层看 HA 服务接入服务/接入;组件关系看 PGSQL 架构;Etcd 的角色看 ETCD 配置

演练入口集中在三处:主动切换看 Patroni 管理;服务状态看 组件管理;极端故障看 3坏2应急处理。需要 VIP 时,再看 配置 PG VIP

背景文章可读 PostgreSQL 高可用到底怎么做?


备份与恢复

PITR 先读 时间点恢复,再读 工作原理实现架构策略权衡声明式恢复典型场景

配置和维护看 备份恢复备份策略备份机制备份仓库备份管理命令

真正恢复时,自动方式看 恢复操作,手工演练看 手工恢复。误删数据、表、库,看 误删处理。不想直接动原集群时,先看 克隆数据库集群Fork 实例

恢复前至少确认四件事:目标时间点或恢复点是否明确;备份和 WAL 是否连续;业务是否已经停写;是在原集群恢复,还是先拉一个新集群验数据。

背景文章可读 备份恢复手段概览PgBackRest2中文文档


监控与排障

监控总览看 监控系统。入口和域名看 图形界面。数据库指标、日志、告警看 PGSQL 监控PGSQL 仪表盘

非数据库模块的监控分别看 INFRA 监控NODE 监控ETCD 监控MINIO 监控

排障先看 PGSQL 常见问题,再看 故障排查。连接认证问题看 HBA 管理;HA 状态问题看 Patroni 管理;进程状态问题看 组件管理

PostgreSQL 通用排障文章:PG 服务器日志常规配置PostgreSQL 宏观查询优化之 pg_stat_statements故障档案:PostgreSQL 事务号回卷查找虚假索引表膨胀治理


扩缩容、升级、迁移

容量和拓扑设计看 架构规划资源准备PGSQL 集群模型

按模块扩缩容时,PGSQL 看 集群管理;NODE 看 NODE 管理;ETCD 看 ETCD 管理;MINIO 看 MINIO 管理;INFRA 看 INFRA 管理预案;REDIS 看 REDIS 管理

升级 PostgreSQL 看 版本升级内核版本。扩展相关看 扩展插件扩展管理扩展仓库软件包别名

迁移已有 PostgreSQL 看 数据迁移PGSQL 迁移剧本。低停机迁移的思路可以参考 迁移不停机

需要水平扩展时,再读 Citus 集群部署Citus 内核分支


安全与入口

部署安全先看 安全考量,安全模型看 安全与合规。PostgreSQL 权限看 访问控制ACL 配置;认证规则看 身份认证HBA 配置HBA 管理

证书看 CA 与证书。域名、Nginx、Web 入口看 域名管理Nginx 管理

生产环境至少要改默认密码,收紧 HBA,明确业务用户和管理用户边界,确认备份仓库的保留、加密和访问权限。


应用接入

应用连接数据库前,先读 服务/接入快速上手 PostgreSQL。连接池行为看 Pgbouncer 管理

使用 Pigsty 托管数据库、再部署无状态应用时,看 应用模板Docker 模块


常见误区

误区 该看哪里
pg_cluster 当成可以随便改的显示名 PGSQL 集群模型
把数据库名、集群名、服务名混为一谈 命名与配置服务/接入
只部署主库,不演练恢复 手工恢复恢复操作
以为 HA 就一定不丢数据 RPORTO
第一次故障切换直接在生产做 沙箱环境3坏2应急处理
忽略 Etcd ETCD 模块ETCD FAQ
只看备份成功,不验证恢复 备份恢复克隆数据库集群
改 HBA、证书、服务入口时没有回滚路径 安全合规HBA 管理Nginx 管理

延伸阅读

8 - 模块:PGSQL

使用 Pigsty v4.5 声明、部署、接入、监控、备份与管理 PostgreSQL 集群。

PGSQL 是 Pigsty 的核心模块:通过 Ansible 清单声明 PostgreSQL 集群,以 Patroni 与 etcd 提供高可用编排,以 pgBackRest 提供备份/PITR,并通过 HAProxy、VIP、DNS、PgBouncer 与完整可观测性栈提供数据库服务。

本页按 Pigsty v4.5.0 源码组织入口。具体默认值只在 参数参考 中维护,避免在模块首页复制一份会漂移的参数快照。


建模与配置

  • 集群模型:集群、实例、身份与角色。
  • 架构:Patroni、etcd、服务接入与可观测性关系。
  • 集群配置:主库、副本、离线实例、同步提交、备份集群、延迟集群与 Citus。
  • 内核:PostgreSQL 大版本、发行版与软件包选择。
  • 用户数据库HBAACL:业务对象与访问控制。
  • 服务接入:读写/只读服务、HAProxy、VIP、DNS 与连接池。
  • 扩展目录:当前打包的 575 个扩展及平台覆盖。

部署与管理

任务 入口
初始化集群或添加实例 集群管理 · pgsql.yml
创建或变更用户 用户管理 · pgsql-user.yml
创建或变更数据库 数据库管理 · pgsql-db.yml
HBA 与参数变更 HBA 管理 · 组件管理
Patroni 切换、维护与故障处理 Patroni 管理
扩展安装、创建、升级与移除 扩展管理
外部实例监控接入 pgsql-monitor.yml
迁移准备 迁移 · pgsql-migration.yml
移除实例或集群 安全移除流程 · pgsql-rm.yml

pgsql.ymlpgsql-user.ymlpgsql-db.yml 等真实执行会修改目标环境;pgsql-rm.yml 默认可能删除数据与备份。执行前先核对精确集群/节点与近期备份;移除操作还必须由操作者输入并确认精确目标。


备份与恢复

  • 备份与恢复总览:恢复能力、边界与入口。
  • 机制策略:基础备份、WAL、恢复窗口与保留策略。
  • 仓库:本地、S3/Silo 与其他 pgBackRest 仓库。
  • 日常管理:备份状态、检查、调度与清理。
  • 恢复操作:集群级 pgsql-pitr.yml、单节点 pig pitr 和低层 pig pb restore
  • 手工演练:在可丢弃沙箱中分阶段验证 PITR。

恢复是破坏性操作;生产环境必须保留独立、近期且验证过的备份,并把停服、恢复、数据验证、时间线提升、DCS 重建、副本重建和新全量备份当作不同关卡。


监控

当前源码 files/grafana/pgsql 包含 29 个 PostgreSQL/PGCAT 仪表盘,覆盖全局、集群、实例、数据库、表、查询、会话、事务、复制、服务、PgBouncer、PITR 与告警。


参数组

PGSQL 参数参考 是 v4.5.0 默认值与语义的唯一文档入口:

  • PG_ID:集群/实例身份。
  • PG_BUSINESS:用户、数据库、服务等业务对象。
  • PG_INSTALL:内核、软件包与扩展。
  • PG_BOOTSTRAP:Patroni 引导、复制与数据库初始化。
  • PG_PROVISION:库内对象与权限置备。
  • PG_BACKUP:pgBackRest 与备份仓库。
  • PG_ACCESS:PgBouncer、服务、VIP 与 DNS。
  • PG_MONITOR:exporter、监控注册与指标采集。
  • PG_REMOVE:移除保险与清理范围。

延伸阅读

8.1 - 集群配置

根据需求场景选择合适的实例与集群类型,配置出满足需求的 PostgreSQL 数据库集群。

Pigsty 是一个“配置驱动”的 PostgreSQL 平台:所有行为都来自 ~/pigsty/conf/*.yml 清单与 PGSQL 参数 的组合。

只要写好配置,你就能在几分钟内复刻出一套包含实例、用户、数据库、访问控制、扩展与调优策略的定制集群。


配置入口

  1. 准备清单:复制 pigsty/conf/*.yml 模板或从零开始编写 Ansible Inventory,将集群分组(all.children.<cls>.hosts)与全局变量(all.vars)写入同一个文件。
  2. 定义参数:在 vars 区块中覆盖需要的 PGSQL 参数。全局 → 集群 → 主机的覆盖顺序决定了最终值。
  3. 应用配置:运行 ./configure -c <conf>bin/pgsql-add <cls> 等剧本让配置落地。Pigsty 会根据参数生成 Patroni/pgbouncer/pgbackrest 等服务所需的配置文件。

Pigsty 默认的 Demo 清单 conf/pgsql.yml 就是一份最小化示例:一个 pg-meta 集群、全局 pg_version: 18、少量业务用户与数据库定义。你可以在此基础上扩展更多集群。


关注点与文档索引

Pigsty 的 PostgreSQL 配置可以从以下几个维度组合,后续文档会逐一展开“如何配置”:

  • 集群实例:通过 pg_cluster / pg_role / pg_seq / pg_upstream 定义实例拓扑(单机、主从、备份集群、延迟集群、Citus 等)。
  • 内核版本:使用 pg_versionpg_modepg_packagespg_extensionspg_conf 等参数挑选核心版本、风味和调优模板。
  • 用户/角色:在 pg_default_rolespg_users 中声明系统角色、业务账号、密码策略以及连接池属性。
  • 数据库对象:借助 pg_databasesbaselineschemasextensionspool_* 字段按需创建数据库并自动接入 pgbouncer/Grafana。
  • 访问控制 (HBA):利用 pg_default_hba_rulespg_hba_rules 维护主机级认证策略,保证不同角色/网络的访问边界。
  • 权限模型 (ACL):通过 pg_default_privilegespg_default_rolespg_revoke_public 等参数收敛对象权限,开箱即用地提供分层角色体系。

理解这些参数之后,你就可以针对任意业务需求写出“配置即基础设施”的声明式清单,Pigsty 会负责执行并确保幂等。


一个典型示例

下面的片段展示了如何在同一个配置文件中同时控制实例拓扑、内核版本、扩展、用户以及数据库:

all:
  children:
    pg-analytics:
      hosts:
        10.10.10.11: { pg_seq: 1, pg_role: primary }
        10.10.10.12: { pg_seq: 2, pg_role: replica, pg_offline_query: true }
      vars:
        pg_cluster: pg-analytics
        pg_conf: olap.yml
        pg_extensions: [ postgis, timescaledb, pgvector ]
        pg_databases:
          - { name: bi, owner: dbuser_bi, schemas: [mart], extensions: [timescaledb], pool_mode: session }
        pg_users:
          - { name: dbuser_bi, password: DBUser.BI, roles: [dbrole_admin], pgbouncer: true }
  vars:
    pg_version: 18
    pg_packages: [ pgsql-main, pgsql-common ]
    pg_hba_rules:
      - { user: dbuser_bi, db: bi, addr: intra, auth: ssl, title: 'BI 只允许内网 SSL 访问' }
  • pg-analytics 集群包含一个主库和一个离线副本。
  • 全局指定 pg_version: 18 与一套扩展示例,并加载 olap.yml 调优。
  • pg_databasespg_users 中声明业务对象,自动生成 schema/extension 与连接池条目。
  • 附加的 pg_hba_rules 限制了访问来源与认证方式。

修改并应用这份清单即可得到一套定制化的 PostgreSQL 集群,而无需手工逐项配置。

8.1.1 - 集群实例

根据需求场景选择合适的实例与集群类型,配置出满足需求的 PostgreSQL 数据库集群。

根据需求场景选择合适的实例与集群类型,配置出满足需求的 PostgreSQL 数据库集群。

您可以定义不同类型的实例和集群,下面是 Pigsty 中常见的几种 PostgreSQL 实例/集群类型:


读写主库

我们从最简单的情况开始:由一个主库(Primary)组成的单实例集群:

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-test

这段配置言简意赅,自我描述,仅由 身份参数 构成。为方便使用 -l pg-test 限定目标, 通常仍建议让 Ansible Group 分组名与 pg_cluster 一致,但这不是成员发现的硬约束; 当前源码会按各主机的 pg_cluster 身份计算实际成员,因此同一 PostgreSQL 集群可以跨越多个清单分组。

使用以下命令创建该集群:

bin/pgsql-add pg-test

Demo 展示,开发测试,承载临时需求,进行无关紧要的计算分析任务时,使用单一数据库实例可能并没有太大问题。但这样的单机集群没有 高可用,当出现硬件故障时,您需要使用 PITR 或其他恢复手段来确保集群的 RTO / RPO。为此,您可以考虑为集群添加若干个 只读从库


只读从库

要添加一台只读从库(Replica)实例,您可以在 pg-test 中添加一个新节点,并将其 pg_role 设置为 replica

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }  # <--- 新添加的从库
  vars:
    pg_cluster: pg-test

如果整个集群不存在,您可以直接 创建 这个完整的集群。 如果集群主库已经初始化好了,那么您可以向现有集群 添加 一个从库:

bin/pgsql-add pg-test               # 一次性初始化整个集群
bin/pgsql-add pg-test 10.10.10.12   # 添加从库到现有的集群

当集群主库出现故障时,只读实例(Replica)可以在高可用系统的帮助下接管主库的工作。除此之外,只读实例还可以用于执行只读查询:许多业务的读请求要比写请求多很多,而大部分只读查询负载都可以由从库实例承担。


离线从库

离线实例(Offline)是专门用于服务慢查询、ETL、OLAP 流量和交互式查询等的专用只读从库。慢查询/长事务对在线业务的性能与稳定性有不利影响,因此最好将它们与在线业务隔离开来。

要添加离线实例,请为其分配一个新实例,并将 pg_role 设置为 offline

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

专用离线实例的工作方式与常见的从库实例类似,但它在 pg-test-replica 服务中用作备份服务器。 也就是说,只有当所有 replica 实例都宕机时,离线和主实例才会提供此项只读服务。

许多情况下,数据库资源有限,单独使用一台服务器作为离线实例是不经济的做法。作为折中,您可以选择一台现有的从库实例,打上 pg_offline_query 标记,将其标记为一台可以承载"离线查询"的实例。在这种情况下,这台只读从库会同时承担在线只读请求与离线类查询。您可以使用 pg_default_hba_rulespg_hba_rules 对离线实例进行额外的访问控制。


同步备库

当启用同步备库(Sync Standby)时,PostgreSQL 将选择一个从库作为 同步备库,其他所有从库作为 候选者。 主数据库会等待备库实例刷新到磁盘,然后才确认提交,备库实例始终拥有最新的数据,没有复制延迟,主从切换至同步备库不会有数据丢失。

PostgreSQL 默认使用异步流复制,主库故障时可能丢失尚未复制的 WAL。pg_rpo 配置的是 Patroni 候选副本的采样落后阈值,并非实际丢失量硬上限;实际窗口还取决于写入速率、复制状态与 Patroni 采样时机。

但在某些关键场景中(例如,金融交易),数据丢失是完全不可接受的,或者,读取复制延迟是不可接受的。在这种情况下,您可以使用同步提交来解决这个问题。 要启用同步备库模式,您可以简单地使用 pg_conf 中的 crit.yml 模板。

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
    pg_conf: crit.yml   # <--- 使用 crit 模板

要在现有集群上启用同步备库,请 配置集群 并启用 synchronous_mode

$ pg edit-config pg-test    # 在管理员节点以管理员用户身份运行
+++
-synchronous_mode: false    # <--- 旧值
+synchronous_mode: true     # <--- 新值
 synchronous_mode_strict: false

应用这些更改?[y/N]: y

在这种情况下,PostgreSQL 配置项 synchronous_standby_names 由 Patroni 自动管理。 一台从库将被选拔为同步从库,它的 application_name 将被写入 PostgreSQL 主库配置文件中并应用生效。


法定人数提交

法定人数提交(Quorum Commit)提供了比同步备库更强大的控制能力:特别是当您有多个从库时,您可以设定提交成功的标准,实现更高/更低的一致性级别(以及可用性之间的权衡)。

如果想要 最少两个从 库来确认提交,可以通过 Patroni 配置集群,调整参数 synchronous_node_count 并应用生效

synchronous_mode: true          # 确保同步提交已经启用
synchronous_node_count: 2       # 指定“至少”有多少个从库提交成功,才算提交成功

如果你想要使用更多的同步从库,修改 synchronous_node_count 的取值即可。当集群的规模发生变化时,您应当确保这里的配置仍然是有效的,以避免服务不可用。

在这种情况下,PostgreSQL 配置项 synchronous_standby_names 由 Patroni 自动管理。

synchronous_standby_names = '2 ("pg-test-3","pg-test-2")'
示例:使用多个同步从库
$ pg edit-config pg-test
---
+synchronous_node_count: 2

Apply these changes? [y/N]: y

应用配置后,出现两个同步备库。

+ Cluster: pg-test (7080814403632534854) +---------+----+-----------+-----------------+
| Member    | Host        | Role         | State   | TL | Lag in MB | Tags            |
+-----------+-------------+--------------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.10 | Leader       | running |  1 |           | clonefrom: true |
| pg-test-2 | 10.10.10.11 | Sync Standby | running |  1 |         0 | clonefrom: true |
| pg-test-3 | 10.10.10.12 | Sync Standby | running |  1 |         0 | clonefrom: true |
+-----------+-------------+--------------+---------+----+-----------+-----------------+

另一种情景是,使用 任意 n 个 从库来确认提交。在这种情况下,配置的方式略有不同,例如,假设我们只需要任意一个从库确认提交:

synchronous_mode: quorum        # 使用法定人数提交
postgresql:
  parameters:                   # 修改 PostgreSQL 的配置参数 synchronous_standby_names ,使用 `ANY n ()` 语法
    synchronous_standby_names: 'ANY 1 (*)'  # 你可以指定具体的从库列表,或直接使用 * 通配所有从库。
示例:启用 ANY 法定人数提交
$ pg edit-config pg-test

+    synchronous_standby_names: 'ANY 1 (*)' # 在 ANY 模式下,需要使用此参数
- synchronous_node_count: 2  # 在 ANY 模式下, 不需要使用此参数

Apply these changes? [y/N]: y

应用后,配置生效,所有备库在 Patroni 中变为普通的 replica。但是在 pg_stat_replication 中可以看到 sync_state 会变为 quorum


备份集群

您可以克隆现有的集群,并创建一个备份集群(Standby Cluster),用于数据迁移、水平拆分、多区域部署,或灾难恢复。

在正常情况下,备份集群将追随上游集群并保持内容同步,您可以将备份集群提升,作为真正地独立集群。

备份集群的定义方式与正常集群的定义基本相同,除了在主库上额外定义了 pg_upstream 参数,备份集群的主库被称为 备份集群领导者 (Standby Leader)。

例如,下面定义了一个 pg-test 集群,以及其备份集群 pg-test2,其配置清单可能如下所示:

# pg-test 是原始集群
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars: { pg_cluster: pg-test }

# pg-test2 是 pg-test 的备份集群
pg-test2:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary , pg_upstream: 10.10.10.11 } # <--- pg_upstream 在这里定义
    10.10.10.13: { pg_seq: 2, pg_role: replica }
  vars: { pg_cluster: pg-test2 }

pg-test2 集群的主节点 pg-test2-1 将是 pg-test 的下游从库,并在 pg-test2 集群中充当备份集群领导者(Standby Leader)。

只需确保备份集群的主节点上配置了 pg_upstream 参数,以便自动从原始上游拉取备份。

bin/pgsql-add pg-test     # 创建原始集群
bin/pgsql-add pg-test2    # 创建备份集群
示例:更改复制上游

如有必要(例如,上游发生主从切换/故障转移),您可以通过 配置集群 更改备份集群的复制上游。

要这样做,只需将 standby_cluster.host 更改为新的上游 IP 地址并应用。

$ pg edit-config pg-test2

 standby_cluster:
   create_replica_methods:
   - basebackup
-  host: 10.10.10.13     # <--- 旧的上游
+  host: 10.10.10.12     # <--- 新的上游
   port: 5432

 Apply these changes? [y/N]: y
示例:提升备份集群

你可以随时将备份集群提升为独立集群,这样该集群就可以独立承载写入请求,并与原集群分叉。

为此,你必须 配置 该集群并完全擦除 standby_cluster 部分,然后应用。

$ pg edit-config pg-test2
-standby_cluster:
-  create_replica_methods:
-  - basebackup
-  host: 10.10.10.11
-  port: 5432

Apply these changes? [y/N]: y
示例:级联复制

如果您在一台从库上指定了 pg_upstream,而不是主库。那么可以配置集群的 级联复制(Cascade Replication)

在配置级联复制时,您必须使用集群中某一个实例的 IP 地址作为参数的值,否则初始化会报错。该从库从特定的实例进行流复制,而不是主库。

这台充当 WAL 中继器的实例被称为 桥接实例(Bridge Instance)。使用桥接实例可以分担主库发送 WAL 的负担,当您有几十台从库时,使用桥接实例级联复制是一个不错的注意。

pg-test:
 hosts: # pg-test-1 ---> pg-test-2 ---> pg-test-3
   10.10.10.11: { pg_seq: 1, pg_role: primary }
   10.10.10.12: { pg_seq: 2, pg_role: replica } # <--- 桥接实例
   10.10.10.13: { pg_seq: 3, pg_role: replica, pg_upstream: 10.10.10.12 }
   # ^--- 从 pg-test-2 (桥接)复制,而不是从 pg-test-1 (主节点) 
 vars: { pg_cluster: pg-test }

延迟集群

延迟集群(Delayed Cluster)是一种特殊类型的 备份集群,用于尽快恢复"意外删除"的数据。

例如,如果你希望有一个名为 pg-testdelay 的集群,其数据内容与一小时前的 pg-test 集群相同:

# pg-test 是原始集群
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars: { pg_cluster: pg-test }

# pg-testdelay 是 pg-test 的延迟集群
pg-testdelay:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary , pg_upstream: 10.10.10.11, pg_delay: 1d }
    10.10.10.13: { pg_seq: 2, pg_role: replica }
  vars: { pg_cluster: pg-testdelay }

你还可以在现有的 备份集群配置 一个"复制延迟"。

$ pg edit-config pg-testdelay
 standby_cluster:
   create_replica_methods:
   - basebackup
   host: 10.10.10.11
   port: 5432
+  recovery_min_apply_delay: 1h    # <--- 在此处添加延迟时长,例如1小时

Apply these changes? [y/N]: y

当某些元组和表格被意外删除时,你可以通过修改此参数的方式,将此延迟集群推进到适当的时间点,并从中读取数据,快速修复原始集群。

延迟集群需要额外的资源,但比起 PITR 要快得多,并且对系统的影响也小得多,对于非常关键的集群,可以考虑搭建延迟集群。


Citus集群

Pigsty 原生支持 Citus。可以参考 conf/ha/citus.yml 作为完整样例。

要定义一个 citus 集群,您需要指定以下参数:

  • pg_mode 必须设置为 citus,而不是默认的 pgsql
  • 在每个分片集群上都必须定义分片名 pg_shard 和分片号 pg_group
  • 必须定义 pg_primary_db 来指定由 Patroni 管理的 Citus 数据库。
  • 如果您想使用 pg_dbsupostgres 而不是默认的 pg_admin_username 来执行管理命令,那么 pg_dbsu_password 必须设置为非空的纯文本密码

此外,还需要额外的 hba 规则,允许从本地和其他数据节点进行 SSL 访问。如下所示:

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 }
        10.10.10.14: { pg_seq: 2, pg_role: replica }
      vars: { pg_cluster: pg-citus3 , pg_group: 3 }
  vars:                               # 所有 Citus 集群的全局参数
    pg_mode: citus                    # pgsql 集群模式需要设置为: citus
    pg_shard: pg-citus                # citus 水平分片名称: pg-citus
    pg_primary_db: meta               # citus 数据库名称:meta
    pg_dbsu_password: DBUser.Postgres # 如果使用 dbsu ,那么需要为其配置一个密码
    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'  }

在协调者节点上,您可以创建分布式表和引用表,并从任何数据节点查询它们。从 11.2 开始,任何 Citus 数据库节点都可以扮演协调者的角色了。

SELECT create_distributed_table('pgbench_accounts', 'aid'); SELECT truncate_local_data_after_distributing_table($$public.pgbench_accounts$$);
SELECT create_reference_table('pgbench_branches')         ; SELECT truncate_local_data_after_distributing_table($$public.pgbench_branches$$);
SELECT create_reference_table('pgbench_history')          ; SELECT truncate_local_data_after_distributing_table($$public.pgbench_history$$);
SELECT create_reference_table('pgbench_tellers')          ; SELECT truncate_local_data_after_distributing_table($$public.pgbench_tellers$$);

8.1.2 - 内核版本

如何选择合适的 PostgreSQL 内核与大版本。

在 Pigsty 中选择"内核"意味着确定 PostgreSQL 大版本、模式/发行版、需要安装的包以及要加载的调优模板。

Pigsty v4.5 当前源码支持 PostgreSQL 14 - 18,默认使用 18。下方内容展示如何通过配置文件完成这些选择。


大版本与软件包

  • pg_version:指定 PostgreSQL 主版本(默认 18)。Pigsty 会根据版本自动映射到正确的包名前缀。
  • pg_packages:定义需要安装的核心包集合,支持使用 包别名(默认 pgsql-main pgsql-common,包含内核 + patroni/pgbouncer/pgbackrest 等常用工具)。
  • pg_extensions:额外需要安装的扩展包列表,同样支持别名;缺省为空表示只装核心依赖。
all:
  vars:
    pg_version: 18
    pg_packages: [ pgsql-main, pgsql-common ]
    pg_extensions: [ postgis, timescaledb, pgvector, pgml ]

效果:Ansible 在安装阶段会拉取与 pg_version=18 对应的包,将扩展预装到系统中,随后数据库初始化脚本即可直接 CREATE EXTENSION

Pigsty 的离线仓库中不同版本的扩展支持范围不同:14 可用扩展相对较少,17/18 覆盖最广。若某扩展未预打包,可通过 repo_extra_packages 追加。


内核模式(pg_mode)

pg_mode 控制要部署的内核“风味”,默认 pgsql 表示标准 PostgreSQL。Pigsty 目前支持以下模式:

模式 场景
pgsql 标准 PostgreSQL,高可用 + 复制
citus Citus 分布式集群,需要额外的 pg_shard / pg_group
gpsql Cloudberry / Greenplum / MatrixDB
mssql Babelfish
mysql OpenGauss/HaloDB 兼容 MySQL 协议
polar 阿里 PolarDB(基于 pg polar 发行)
ivory IvorySQL(Oracle 兼容语法)
pgtde Percona PostgreSQL + pg_tde,使用 /usr/pgtde-$v
oriole OrioleDB 存储引擎
agens AgensGraph 图数据库内核
pgedge pgEdge 分布式复制内核

pg_mode 决定二进制路径、Patroni 集成方式及部分内核特定逻辑;它本身不会自动替你补齐所有软件包、扩展与业务数据库。实际部署时应使用匹配的 conf/*.yml 配置模板,或显式配置 pg_packagespg_extensionspg_libspg_databases。以下是一个精简的 Citus 示例:

all:
  children:
    pg-citus1:
      hosts: { 10.10.10.11: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus1, pg_group: 0 }
    pg-citus2:
      hosts: { 10.10.10.12: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus2, pg_group: 1 }
  vars:
    pg_mode: citus
    pg_shard: pg-citus
    pg_primary_db: citus
    pg_extensions: [ citus ]
    pg_libs: 'citus, pg_stat_statements'
    pg_databases:
      - { name: citus, extensions: [ citus ] }

conf/ha/citus.yml 提供了当前完整样例;上面的精简配置显式安装 Citus 包,并在 citus 数据库中创建扩展。


扩展与预置对象

除了系统包,你还可以通过以下参数控制数据库启动后自动加载的组件:

  • pg_libs:写入 shared_preload_libraries 的列表。例如 pg_libs: 'timescaledb, pg_stat_statements, auto_explain'
  • pg_default_extensions / pg_default_schemas:控制初始化脚本对 template1postgres 预创建的 schema、扩展。
  • pg_parameters:由 Pigsty 在配置阶段渲染进 postgresql.auto.conf;不要再手工执行 ALTER SYSTEM 管理同一批参数。

示例:启用 TimescaleDB、pgvector 并自定义一些系统参数。

pg-analytics:
  vars:
    pg_cluster: pg-analytics
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'
    pg_default_extensions:
      - { name: timescaledb }
      - { name: vector }
    pg_parameters:
      timescaledb.max_background_workers: 8

效果:初始化时 template1postgres 会创建默认扩展;新建且使用 template1 的业务库会继承这些对象。pg_parameters 则直接写入 postgresql.auto.conf


调优模板 (pg_conf)

pg_conf 指向 roles/pgsql/templates/*.yml 中的 Patroni 模板。Pigsty 内置四套通用模板:

模板 适用场景
oltp.yml 默认模板,面向 4–128 核的 TP 负载
olap.yml 针对分析场景优化
crit.yml 强调同步提交/最小延迟,适合金融等零丢失场景
tiny.yml 轻量机 / 边缘场景 / 资源受限环境

你可以直接替换模板或自定义一个 YAML 文件放在 templates/ 下,然后在集群 vars 里指定。

pg-ledger:
  hosts: { 10.10.10.21: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-ledger
    pg_conf: crit.yml
    pg_parameters:
      synchronous_commit: 'remote_apply'
      max_wal_senders: 16
      wal_keep_size: '2GB'

效果:拷贝 crit.yml 作为 Patroni 配置,叠加 pg_parameters 写入 postgresql.auto.conf,使实例立即以同步提交模式运行。


组合实例:一个完整示例

pg-rag:
  hosts:
    10.10.10.31: { pg_seq: 1, pg_role: primary }
    10.10.10.32: { pg_seq: 2, pg_role: replica }
  vars:
    pg_cluster: pg-rag
    pg_version: 18
    pg_mode: pgsql
    pg_conf: olap.yml
    pg_packages: [ pgsql-main, pgsql-common ]
    pg_extensions: [ pgvector, pgml, postgis ]
    pg_libs: 'pg_stat_statements, auto_explain'
    pg_parameters:
      max_parallel_workers: 8
      shared_buffers: '32GB'
  • 第一台主库 + 一台 replica,使用 olap.yml 调优。
  • 安装 PG18 + RAG 常用扩展;只有需要预加载的库才应写入 pg_libs
  • Patroni/pgbouncer/pgbackrest 由 Pigsty 生成,无需手工干预。

根据业务需要替换上述参数即可完成内核层的全部定制。

8.1.3 - 别名翻译

Pigsty 提供软件包别名翻译机制,可以屏蔽底层操作系统的二进制包细节差异,让安装更简易。

PostgreSQL 在不同操作系统上的软件包命名规则存在显著差异:

  • EL 系统(RHEL/Rocky/Alma/…)使用 pgvector_18postgis36_18* 这样的格式
  • Debian/Ubuntu 系统 使用 postgresql-18-pgvectorpostgresql-18-postgis-3 这样的格式

这种差异给用户带来了额外的认知负担:您需要记住不同系统的包名规则,还要处理 PostgreSQL 版本号嵌入的问题。

软件包别名

Pigsty 通过 软件包别名(Package Alias) 机制解决了这个问题:您只需使用统一的别名,Pigsty 会处理好所有细节:

# 使用别名 —— 简单、统一、跨平台
pg_extensions: [ postgis, pgvector, timescaledb ]

# 等效于 EL9 + PG18 上的实际包名
pg_extensions: [ postgis36_18*, pgvector_18*, timescaledb-tsl_18* ]

# 等效于 Ubuntu 24 + PG18 上的实际包名
pg_extensions: [ postgresql-18-postgis-3, postgresql-18-pgvector, postgresql-18-timescaledb-tsl ]

别名翻译

别名还可以将一组软件包归类为一个整体,例如 Pigsty 默认安装的软件包 —— pg_packages 的默认值是:

pg_packages:                      # pg packages to be installed, alias can be used
  - pgsql-main pgsql-common

Pigsty 将查询当前的操作系统别名清单(假设为 el10.x86_64),将其翻译为 PGSQL 内核,扩展,以及工具包:

pgsql-main:    "postgresql$v postgresql$v-server postgresql$v-libs postgresql$v-contrib postgresql$v-plperl postgresql$v-plpython3 postgresql$v-pltcl postgresql$v-llvmjit pg_repack_$v* wal2json_$v* pgvector_$v*"
pgsql-common:  "patroni patroni-etcd pgbouncer pgbackrest pg_exporter pgbackrest_exporter vip-manager"

接下来,Pigsty 又进一步通过当前指定的 PG 大版本(假设 pg_version = 18),将 pgsql-main 翻译为:

pg18-main:   "postgresql18 postgresql18-server postgresql18-libs postgresql18-contrib postgresql18-plperl postgresql18-plpython3 postgresql18-pltcl postgresql18-llvmjit pg_repack_18* wal2json_18* pgvector_18*"

通过这种方式,Pigsty 屏蔽了软件包的复杂性,让用户可以简单的指定自己想要的功能组件。


哪些变量可以使用别名?

您可以在以下四个参数中使用包别名,别名会根据翻译流程自动转换为实际的软件包名称:


别名列表

你可以在 Pigsty 项目源代码的 roles/node_id/vars/ 目录下,找到各操作系统与架构对应的别名映射文件:


工作原理

别名翻译流程

用户配置别名 --> 检测操作系统 -->  查找别名映射表 ---> 替换$v占位符 ---> 安装实际软件包
     ↓              ↓               ↓                               ↓
  postgis      el9.x86_64      postgis36_$v*                postgis36_18*
  postgis      u24.x86_64      postgresql-$v-postgis-3      postgresql-18-postgis-3

版本占位符

Pigsty 的别名系统使用 $v 作为 PostgreSQL 版本号的占位符。当您使用 pg_version 指定了 PostgreSQL 版本后,所有别名中的 $v 都会被替换为实际版本号。

例如,当 pg_version: 18 时:

别名定义 (EL) 展开结果
postgresql$v* postgresql18*
pgvector_$v* pgvector_18*
timescaledb-tsl_$v* timescaledb-tsl_18*
别名定义 (Debian/Ubuntu) 展开结果
postgresql-$v postgresql-18
postgresql-$v-pgvector postgresql-18-pgvector
postgresql-$v-timescaledb-tsl postgresql-18-timescaledb-tsl

通配符匹配

在 EL 系统上,许多别名使用 * 通配符来匹配相关的子包。例如:

  • postgis36_18* 会匹配 postgis36_18postgis36_18-clientpostgis36_18-utils
  • postgresql18* 会匹配 postgresql18postgresql18-serverpostgresql18-libspostgresql18-contrib

这种设计确保您无需逐一列出每个子包,一个别名即可安装完整的扩展。

8.1.4 - 用户/角色

如何通过配置来定制所需 PostgreSQL 用户与角色?

在本文中,“用户”(User) 指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的逻辑对象。

在 PostgreSQL 中,用户直接隶属于数据库集簇而非某个具体的数据库。因此在创建业务数据库和业务用户时,应当遵循"先用户,后数据库"的原则。

Pigsty 通过两个配置参数定义数据库集群中的角色与用户:

  • pg_default_roles:定义全局统一使用的角色和用户
  • pg_users:在数据库集群层面定义业务用户和角色

前者用于定义整套环境中共用的角色与用户,后者定义单个集群中特有的业务角色与用户。二者形式相同,均为用户定义对象的数组。 用户/角色按数组顺序逐一创建,因此后定义的用户可以属于先定义的角色。

默认情况下,所有带有 pgbouncer: true 标记的用户都会被添加到 Pgbouncer 连接池用户列表中。


定义用户

下面是 Pigsty 演示环境中默认集群 pg-meta 中的业务用户定义:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    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 }
      - {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     }
      - {name: dbuser_noco     ,password: DBUser.Noco     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for nocodb service      }
      - {name: dbuser_remove   ,state: absent }  # 使用 state: absent 删除用户

每个用户/角色定义都是一个复杂对象,可能包括以下字段,除了 name 字段外,其他字段均为可选字段:

- name: dbuser_meta               # 必选,`name` 是用户定义的唯一必选字段
  state: create                   # 可选,用户状态:create(创建,默认)、absent(删除)
  password: DBUser.Meta           # 可选,密码,可以是 scram-sha-256 哈希字符串或明文
  login: true                     # 可选,默认为 true,是否可以登录
  superuser: false                # 可选,默认为 false,是否是超级用户
  createdb: false                 # 可选,默认为 false,是否可以创建数据库
  createrole: false               # 可选,默认为 false,是否可以创建角色
  inherit: true                   # 可选,默认为 true,是否自动继承所属角色权限
  replication: false              # 可选,默认为 false,是否可以发起流复制连接
  bypassrls: false                # 可选,默认为 false,是否可以绕过行级安全
  connlimit: -1                   # 可选,用户连接数限制,默认 -1 不限制
  expire_in: 3650                 # 可选,从创建时起 N 天后过期(优先级比 expire_at 高)
  expire_at: '2030-12-31'         # 可选,过期日期,使用 YYYY-MM-DD 格式(优先级没 expire_in 高)
  comment: pigsty admin user      # 可选,用户备注信息
  roles: [dbrole_admin]           # 可选,所属角色数组
  parameters:                     # 可选,角色级配置参数
    search_path: public
  pgbouncer: true                 # 可选,是否加入连接池用户列表,默认 false
  pool_mode: transaction          # 可选,用户级别的池化模式,默认 transaction
  pool_connlimit: 100             # 可选,用户级别的连接池最大连接数;省略时继承全局默认 100

用户级连接池限额字段统一使用 pool_connlimit(对应 Pgbouncer max_user_connections)。


参数总览

所有参数中唯一 必选 的字段是 name,它应该是当前 PostgreSQL 集群中有效且唯一的用户名,其他参数都有合理的默认值,均为可选项。

字段 分类 类型 属性 说明
name 基本 string 必选 用户名,必须是有效且唯一的标识符
state 基本 enum 可选 用户状态:create(默认)、absent
password 基本 string 可变 用户密码,明文或哈希
comment 基本 string 可变 用户备注信息
login 权限 bool 可变 是否允许登录,默认 true
superuser 权限 bool 可变 是否为超级用户,默认 false
createdb 权限 bool 可变 是否可创建数据库,默认 false
createrole 权限 bool 可变 是否可创建角色,默认 false
inherit 权限 bool 可变 是否继承所属角色权限,默认 true
replication 权限 bool 可变 是否可进行复制,默认 false
bypassrls 权限 bool 可变 是否可绕过行级安全,默认 false
connlimit 权限 int 可变 连接数限制,-1 表示不限制
expire_in 有效期 int 可变 从当前日期起 N 天后过期(优先级高于 expire_at
expire_at 有效期 string 可变 过期日期,YYYY-MM-DD 格式
roles 角色 array 增量 所属角色数组,支持字符串或对象格式
parameters 参数 object 可变 角色级参数
pgbouncer 连接池 bool 可变 是否加入连接池,默认 false
pool_mode 连接池 enum 可变 池化模式:transaction(默认)
pool_connlimit 连接池 int 可变 连接池用户最大连接数

参数详情

name

字符串,必选参数,表示用户的名称,在一个数据库集群内必须唯一。

用户名必须是有效的 PostgreSQL 标识符,必须匹配正则表达式 ^[a-z_][a-z0-9_]{0,62}$: 以小写字母或下划线开头,只能包含小写字母、数字、下划线,最长 63 个字符。

- name: dbuser_app         # 标准命名
- name: app_readonly       # 下划线分隔
- name: _internal          # 下划线开头(用于内部角色)

state

枚举值,用于指定要对用户执行的操作,可以是 createabsent,默认值为 create

状态 说明
create 默认,创建用户,如果已存在则更新属性
absent 删除用户,使用 DROP ROLE
- name: dbuser_app             # state 默认为 create
- name: dbuser_old
  state: absent                # 删除用户

以下系统用户无法通过 state: absent 删除,这是为了防止误删关键系统用户导致集群故障:

password

字符串,可变参数,用于设置用户密码,不指定则用户无法使用密码登录。

密码可以是以下格式之一:

格式 示例 说明
明文密码 DBUser.Meta 不推荐,会被记录到配置文件和日志
SCRAM-SHA-256 SCRAM-SHA-256$4096:xxx$yyy:zzz 推荐,PostgreSQL 10+ 默认认证方式
MD5 哈希 md5... 兼容旧版本,不推荐新项目使用
# 明文密码(不推荐,会被记录到配置和日志中)
- name: dbuser_app
  password: MySecretPassword

# SCRAM-SHA-256 哈希(推荐)
- name: dbuser_app
  password: 'SCRAM-SHA-256$4096:xxx$yyy:zzz'

设置密码时,Pigsty 会临时屏蔽当前会话的日志记录以避免密码泄露:

SET log_statement TO 'none';
ALTER USER "dbuser_app" PASSWORD 'xxx';
SET log_statement TO DEFAULT;

如果你不希望在配置文件中记录明文密码,可以使用 SCRAM-SHA-256 哈希字符串代替明文密码。生成 SCRAM-SHA-256 哈希的方法:

# 使用 PostgreSQL 生成(需要先连接到数据库,数据库有 pgcrypto 扩展)
psql -c "SELECT encode(digest('password' || 'username', 'sha256'), 'hex')"

comment

字符串,可变参数,用于设置用户的备注信息,如果不指定,默认值为 business user {name}

用户备注信息通过 COMMENT ON ROLE 语句设置,支持中文和特殊字符(Pigsty 会自动转义单引号)。

- name: dbuser_app
  comment: '业务应用主账号'
COMMENT ON ROLE "dbuser_app" IS '业务应用主账号';

login

布尔值,可变参数,用于控制用户是否可以登录,默认值为 true

设置为 false 则创建的是无法登陆的 角色(Role)而非用户(User),通常用于权限分组。

在 PostgreSQL 中,CREATE USER 等价于 CREATE ROLE ... LOGIN

# 创建可登录用户
- name: dbuser_app
  login: true

# 创建角色(不可登录,用于权限分组)
- name: dbrole_custom
  login: false
  comment: 自定义权限角色
CREATE USER "dbuser_app" LOGIN;
CREATE USER "dbrole_custom" NOLOGIN;

superuser

布尔值,可变参数,用于指定用户是否为超级用户,默认值为 false

超级用户拥有数据库的全部权限,可以绕过所有权限检查。

- name: dbuser_admin
  superuser: true            # 危险:拥有全部权限
ALTER USER "dbuser_admin" SUPERUSER;

Pigsty 已经提供了默认的超级用户 pg_admin_usernamedbuser_dba) 除非绝对必要,否则不应创建额外的超级用户。

createdb

布尔值,可变参数,用于指定用户是否可以创建数据库,默认值为 false

- name: dbuser_dev
  createdb: true             # 允许创建数据库
ALTER USER "dbuser_dev" CREATEDB;

一些应用软件可能会要求自己创建数据库,例如 GiteaOdoo 等,因此您可能需要为这些应用的管理员用户启用 CREATEDB 权限。

createrole

布尔值,可变参数,用于指定用户是否可以创建其他角色,默认值为 false

拥有 CREATEROLE 权限的用户可以创建、修改、删除其他非超级用户角色。

- name: dbuser_admin
  createrole: true           # 允许管理其他角色
ALTER USER "dbuser_admin" CREATEROLE;

inherit

布尔值,可变参数,用于控制用户是否自动继承所属角色的权限,默认值为 true

设置为 false 时,用户需要通过 SET ROLE 显式切换角色才能使用所属角色的权限。

# 自动继承角色权限(默认)
- name: dbuser_app
  inherit: true
  roles: [dbrole_readwrite]

# 需要显式切换角色
- name: dbuser_special
  inherit: false
  roles: [dbrole_admin]
ALTER USER "dbuser_special" NOINHERIT;
-- 用户需要执行 SET ROLE dbrole_admin 才能获得该角色权限(必要但不充分)

replication

布尔值,可变参数,用于指定用户是否可以发起流复制连接,默认值为 false

通常只有复制用户(如 replicator)需要此权限。普通业务用户不应该拥有此权限,除非这是一个逻辑解码订阅者。

- name: replicator
  replication: true          # 允许流复制连接
  roles: [pg_monitor, dbrole_readonly]
ALTER USER "replicator" REPLICATION;

bypassrls

布尔值,可变参数,用于指定用户是否可以绕过行级安全(RLS)策略,默认值为 false

启用此权限后,用户可以访问所有行,即使表上定义了行级安全策略。此权限通常只授予管理员用户。

- name: dbuser_myappadmin
  bypassrls: true            # 绕过行级安全策略
ALTER USER "dbuser_myappadmin" BYPASSRLS;

connlimit

整数,可变参数,用于限制用户的最大并发连接数,默认值为 -1,表示不限制。

设置为正整数时,会限制该用户同时建立的最大数据库连接数。此限制不影响超级用户。

- name: dbuser_app
  connlimit: 100             # 最多 100 个并发连接

- name: dbuser_batch
  connlimit: 10              # 批处理用户限制连接数
ALTER USER "dbuser_app" CONNECTION LIMIT 100;

expire_in

整数,可变参数,用于指定用户从当前日期起多少天后过期。

此参数优先级高于 expire_at,如果同时指定两者,只有 expire_in 生效。

每次执行剧本时会根据当前日期重新计算过期时间,适合用于临时用户或需要定期续期的场景。

- name: temp_user
  expire_in: 30              # 30 天后过期

- name: contractor_user
  expire_in: 90              # 90 天后过期

执行时会计算实际过期日期并生成对应的 SQL:

-- expire_in: 30, 假设当前日期为 2025-01-01
ALTER USER "temp_user" VALID UNTIL '2025-01-31';

expire_at

字符串,可变参数,用于指定用户的过期日期,格式为 YYYY-MM-DD 或特殊值 infinity

此参数优先级低于 expire_in。使用 infinity 表示用户永不过期。

- name: contractor_user
  expire_at: '2024-12-31'    # 指定日期过期

- name: permanent_user
  expire_at: 'infinity'      # 永不过期
ALTER USER "contractor_user" VALID UNTIL '2024-12-31';
ALTER USER "permanent_user" VALID UNTIL 'infinity';

roles

数组,增量参数,用于定义用户所属的角色。数组元素可以是字符串或对象。

简单格式使用字符串直接指定角色名:

- name: dbuser_app
  roles:
    - dbrole_readwrite
    - pg_read_all_data
GRANT "dbrole_readwrite" TO "dbuser_app";
GRANT "pg_read_all_data" TO "dbuser_app";

完整格式使用对象定义,支持更精细的角色成员关系控制:

- name: dbuser_app
  roles:
    - dbrole_readwrite                            # 简单字符串:GRANT 角色
    - { name: dbrole_admin, admin: true }         # 带 ADMIN OPTION
    - { name: pg_monitor, set: false }            # PG16+: 不允许 SET ROLE
    - { name: pg_signal_backend, inherit: false } # PG16+: 不自动继承权限
    - { name: old_role, state: absent }           # 撤销角色成员关系

对象格式参数说明

参数 类型 说明
name string 角色名称(必选)
state enum grant(默认)或 absent/revoke:控制授予或撤销
admin bool true:WITH ADMIN OPTION,false:REVOKE ADMIN
set bool PG16+:true:WITH SET TRUE,false:REVOKE SET
inherit bool PG16+:true:WITH INHERIT TRUE,false:REVOKE INHERIT

PostgreSQL 16+ 新特性

PostgreSQL 16 引入了更细粒度的角色成员关系控制:

  • ADMIN OPTION:允许将角色授予其他用户
  • SET OPTION:允许使用 SET ROLE 切换到该角色
  • INHERIT OPTION:是否自动继承该角色的权限
# PostgreSQL 16+ 完整示例
- name: dbuser_app
  roles:
    # 普通成员关系
    - dbrole_readwrite

    # 可以将 dbrole_admin 授予其他用户
    - { name: dbrole_admin, admin: true }

    # 不能 SET ROLE 到 pg_monitor(只能通过继承使用权限)
    - { name: pg_monitor, set: false }

    # 不自动继承 pg_execute_server_program 的权限(需要显式 SET ROLE)
    - { name: pg_execute_server_program, inherit: false }

    # 撤销 old_role 的成员关系
    - { name: old_role, state: absent }

setinherit 选项仅在 PostgreSQL 16+ 中有效,在早期版本会被忽略并在生成的 SQL 中添加警告注释。

parameters

对象,可变参数,用于设置角色级别的配置参数。参数通过 ALTER ROLE ... SET 设置,会对该用户的所有会话生效。

- name: dbuser_analyst
  parameters:
    work_mem: '256MB'
    statement_timeout: '5min'
    search_path: 'analytics,public'
    log_statement: 'all'
ALTER USER "dbuser_analyst" SET "work_mem" = '256MB';
ALTER USER "dbuser_analyst" SET "statement_timeout" = '5min';
ALTER USER "dbuser_analyst" SET "search_path" = 'analytics,public';
ALTER USER "dbuser_analyst" SET "log_statement" = 'all';

使用特殊值 DEFAULT(大小写不敏感)可以将参数重置为 PostgreSQL 默认值:

- name: dbuser_app
  parameters:
    work_mem: DEFAULT          # 重置为默认值
    statement_timeout: '30s'   # 设置新值
ALTER USER "dbuser_app" SET "work_mem" = DEFAULT;
ALTER USER "dbuser_app" SET "statement_timeout" = '30s';

常用角色级参数:

参数 说明 示例值
work_mem 查询工作内存 '64MB'
statement_timeout 语句超时时间 '30s'
lock_timeout 锁等待超时 '10s'
idle_in_transaction_session_timeout 空闲事务超时 '10min'
search_path Schema 搜索路径 'app,public'
log_statement 日志记录级别 'ddl'
temp_file_limit 临时文件大小限制 '10GB'

您可以从数据库的 pg_db_role_setting 系统视图查询用户级别的参数设置。

pgbouncer

布尔值,可变参数,用于控制是否将用户添加到 Pgbouncer 连接池用户列表,默认值为 false

对于需要通过连接池访问数据库的生产用户,必须显式设置 pgbouncer: true。 默认为 false 是为了避免意外将内部用户暴露给连接池。

# 生产用户:需要连接池
- name: dbuser_app
  password: DBUser.App
  pgbouncer: true

# 内部用户:不需要连接池
- name: dbuser_internal
  password: DBUser.Internal
  pgbouncer: false           # 默认值,可省略

设置 pgbouncer: true 的用户会被添加到 /etc/pgbouncer/userlist.txt 文件中。

pool_mode

枚举值,可变参数,用于设置用户级别的池化模式,可选值为 transactionsessionstatement,默认值为 transaction

模式 说明 适用场景
transaction 事务结束后归还连接 大多数 OLTP 应用,默认推荐
session 会话结束后归还连接 需要会话状态的应用(如 SET 命令)
statement 每条语句后归还连接 简单无状态查询,极致复用
# DBA 用户使用 session 模式(可能需要 SET 命令等会话状态)
- name: dbuser_dba
  pgbouncer: true
  pool_mode: session

# 普通业务用户使用 transaction 模式
- name: dbuser_app
  pgbouncer: true
  pool_mode: transaction

用户级别的连接池参数通过 /etc/pgbouncer/useropts.txt 文件配置:

dbuser_dba      = pool_mode=session max_user_connections=16
dbuser_monitor  = pool_mode=session max_user_connections=8

pool_connlimit

整数,可变参数,用于设置用户级别的连接池最大连接数。省略时不生成用户级覆盖项,继承 Pigsty 在 pgbouncer.ini 中设置的全局默认值 100;PgBouncer 使用 0 表示不限制。

- name: dbuser_app
  pgbouncer: true
  pool_connlimit: 50         # 此用户最多使用 50 个连接池连接

ACL 系统

Pigsty 提供一套内置的访问控制 / ACL 模型,可以将以下默认业务角色分配给用户:

角色 权限说明 典型使用场景
dbrole_readwrite 全局读写访问 主属业务的生产账号
dbrole_readonly 全局只读访问 其他业务的只读访问
dbrole_admin 拥有 DDL 权限 业务管理员,需要建表的场景
dbrole_offline 独立只读访问;实例范围由 HBA 控制 个人用户,ETL/分析任务
# 典型业务用户配置
pg_users:
  - name: dbuser_app
    password: DBUser.App
    pgbouncer: true
    roles: [dbrole_readwrite]    # 生产账号,读写权限

  - name: dbuser_readonly
    password: DBUser.Readonly
    pgbouncer: true
    roles: [dbrole_readonly]     # 只读账号

  - name: dbuser_admin
    password: DBUser.Admin
    pgbouncer: true
    roles: [dbrole_admin]        # 管理员,可执行 DDL

  - name: dbuser_etl
    password: DBUser.ETL
    roles: [dbrole_offline]      # 分析账号;另用 HBA 限制实例范围

dbrole_offline 本身不会把用户限制到离线实例。若需要该边界,应为对应 HBA 规则设置 role: offline;详见 离线角色与实例隔离

如果您希望重新设计您自己的 ACL 系统,可以考虑定制以下参数和模板:


Pgbouncer 用户

默认情况下启用 Pgbouncer 作为连接池中间件。Pigsty 默认将 pg_users 中显式带有 pgbouncer: true 标志的所有用户添加到 Pgbouncer 用户列表中。

Pgbouncer 连接池中的用户在 /etc/pgbouncer/userlist.txt 中列出:

"postgres" ""
"dbuser_wiki" "SCRAM-SHA-256$4096:+77dyhrPeFDT/TptHs7/7Q==$KeatuohpKIYzHPCt/tqBu85vI11o9mar/by0hHYM2W8=:X9gig4JtjoS8Y/o1vQsIX/gY1Fns8ynTXkbWOjUfbRQ="
"dbuser_view" "SCRAM-SHA-256$4096:DFoZHU/DXsHL8MJ8regdEw==$gx9sUGgpVpdSM4o6A2R9PKAUkAsRPLhLoBDLBUYtKS0=:MujSgKe6rxcIUMv4GnyXJmV0YNbf39uFRZv724+X1FE="
"dbuser_monitor" "SCRAM-SHA-256$4096:fwU97ZMO/KR0ScHO5+UuBg==$CrNsmGrx1DkIGrtrD1Wjexb/aygzqQdirTO1oBZROPY=:L8+dJ+fqlMQh7y4PmVR/gbAOvYWOr+KINjeMZ8LlFww="
"dbuser_meta" "SCRAM-SHA-256$4096:leB2RQPcw1OIiRnPnOMUEg==$eyC+NIMKeoTxshJu314+BmbMFpCcspzI3UFZ1RYfNyU=:fJgXcykVPvOfro2MWNkl5q38oz21nSl1dTtM65uYR1Q="

用户级别的连接池参数使用另一个单独的文件 /etc/pgbouncer/useropts.txt 进行维护:

dbuser_dba      = pool_mode=session max_user_connections=16
dbuser_monitor  = pool_mode=session max_user_connections=8

当您 创建用户 时,Pgbouncer 的用户列表定义文件将会被刷新,并通过在线重载配置的方式生效,不会影响现有的连接。

Pgbouncer 使用和 PostgreSQL 相同的 dbsu 运行,默认为 postgres 操作系统用户。您可以使用 pgb 别名,使用 dbsu 访问 Pgbouncer 管理功能。

pgbouncer_auth_query 参数允许您使用动态查询来完成连接池用户认证,当您不想手动管理连接池中的用户时,这是一种便捷的方案。


相关资源

关于用户管理操作,请参考 用户管理 一节。

关于用户的访问权限,请参考 访问控制:角色体系

8.1.5 - 数据库

如何通过配置来定制所需 PostgreSQL 数据库?

在本文中,“数据库”(Database) 指的是使用 SQL 命令 CREATE DATABASE 创建的,数据库集簇内的逻辑对象。

一组 PostgreSQL 服务器可以同时服务于多个 数据库 (Database)。在 Pigsty 中,你可以在集群配置中 定义 好所需的数据库。

Pigsty 会对默认模板数据库 template1 进行修改与定制,创建默认模式,安装默认扩展,配置默认权限,新创建的数据库默认会从 template1 继承这些设置。 您也可以通过 template 参数指定其他模板数据库,实现瞬间 数据库克隆

默认情况下,所有业务数据库都会被 1:1 添加到 Pgbouncer 连接池 中;pg_exporter 默认会通过 自动发现 机制查找所有业务数据库并进行库内对象监控。 所有数据库也会添加到所有 INFRA节点 上的 Grafana 中, 注册为 PostgreSQL 数据源供 PGCAT 监控面板使用。


定义数据库

业务数据库定义在数据库集群参数 pg_databases 中,这是一个数据库定义构成的对象数组。 在集群初始化时,数组内的数据库按照 定义顺序 依次创建,因此后面定义的数据库可以使用先前定义的数据库作为 模板

下面是 Pigsty 演示环境中默认集群 pg-meta 中的数据库定义:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_databases:
      - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [{name: postgis, schema: public}, {name: timescaledb}]}
      - { 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 }
      - { name: noco     ,owner: dbuser_noco     ,revokeconn: true ,comment: nocodb database }

每个数据库定义都是一个复杂对象,可能包括以下字段,除了 name 字段外,其他字段均为可选字段:

- name: meta                      # 必选,`name` 是数据库定义的唯一必选字段
  state: create                   # 可选,数据库状态:create(创建,默认)、absent(删除)、recreate(重建)
  baseline: cmdb.sql              # 可选,数据库 sql 的基线定义文件路径(ansible 搜索路径中的相对路径,如 files/)
  pgbouncer: true                 # 可选,是否将此数据库添加到 pgbouncer 数据库列表?默认为 true
  schemas: [pigsty]               # 可选,要创建的附加模式,由模式名称字符串组成的数组
  extensions:                     # 可选,要安装的附加扩展: 扩展对象的数组
    - { name: postgis , schema: public }  # 可以指定将扩展安装到某个模式中,也可以不指定(不指定则安装到 search_path 首位模式中)
    - { name: timescaledb }               # 例如有的扩展会创建并使用固定的模式,就不需要指定模式。
  comment: pigsty meta database   # 可选,数据库的说明与备注信息
  owner: postgres                 # 可选,数据库所有者,不指定则为当前用户
  template: template1             # 可选,要使用的模板,默认为 template1,目标必须是一个模板数据库
  strategy: FILE_COPY             # 可选,克隆策略:FILE_COPY 或 WAL_LOG(PG15+),不指定使用 PG 默认
  encoding: UTF8                  # 可选,不指定则继承模板/集群配置(UTF8)
  locale: C                       # 可选,不指定则继承模板/集群配置(C)
  lc_collate: C                   # 可选,不指定则继承模板/集群配置(C)
  lc_ctype: C                     # 可选,不指定则继承模板/集群配置(C)
  locale_provider: libc           # 可选,本地化提供者:libc、icu、builtin(PG15+)
  icu_locale: en-US               # 可选,ICU 本地化规则(PG15+)
  icu_rules: ''                   # 可选,ICU 排序规则(PG16+)
  builtin_locale: C.UTF-8         # 可选,内置本地化提供者规则(PG17+)
  tablespace: pg_default          # 可选,默认表空间,默认为 'pg_default'
  is_template: false              # 可选,是否标记为模板数据库,允许任何有 CREATEDB 权限的用户克隆
  allowconn: true                 # 可选,是否允许连接,默认为 true。显式设置 false 将完全禁止连接到此数据库
  revokeconn: false               # 可选,撤销公共连接权限。设为 true 时仅为属主、管理员、监控与复制用户保留 CONNECT
  register_datasource: true       # 可选,是否将此数据库注册到 grafana 数据源?默认为 true,显式设置为 false 会跳过注册
  connlimit: -1                   # 可选,数据库连接限制,默认为 -1 ,不限制,设置为正整数则会限制连接数。
  parameters:                     # 可选,数据库级参数,通过 ALTER DATABASE SET 设置
    work_mem: '64MB'
    statement_timeout: '30s'
  pool_auth_user: dbuser_meta     # 可选,连接到此 pgbouncer 数据库的所有连接都将使用此用户进行验证(启用 pgbouncer_auth_query 才有用)
  pool_mode: transaction          # 可选,数据库级别的 pgbouncer 池化模式,默认为 transaction
  pool_size: 50                   # 可选,数据库级别的 pgbouncer 默认池子大小,默认为 50
  pool_reserve: 30                # 可选,数据库级别的 pgbouncer 池子保留空间,默认为 30,当默认池子不够用时,最多再申请这么多条突发连接。
  pool_size_min: 0                # 可选,数据库级别的 pgbouncer 池的最小大小,默认为 0
  pool_connlimit: 100             # 可选,数据库级别的最大数据库连接数,默认为 100

自 Pigsty v4.1.0 起,数据库连接池参数统一使用 pool_reservepool_connlimit,旧别名 pool_size_reserve / pool_max_db_conn 已收敛。


参数总览

所有参数中唯一 必选 的字段是 name,它应该是当前 PostgreSQL 集群中有效且唯一的数据库名称,其他参数都有合理的默认值,均为可选项。 带有 “不可变” 标记的参数仅在数据库创建时生效,创建后无法修改,若需更改则必须删除并重建数据库。

字段 分类 类型 属性 说明
name 基本 string 必选 数据库名称,必须是有效且唯一的标识符
state 基本 enum 可选 数据库状态:create(默认)、absentrecreate
owner 基本 string 可变 数据库属主,不指定则为 postgres
comment 基本 string 可变 数据库备注信息
template 模板 string 不可变 创建时使用的模板数据库,默认 template1
strategy 模板 enum 不可变 克隆策略:FILE_COPYWAL_LOG(PG15+)
encoding 编码 string 不可变 字符编码,默认继承模板(UTF8
locale 编码 string 不可变 本地化规则,默认继承模板(C
lc_collate 编码 string 不可变 排序规则,默认继承模板(C
lc_ctype 编码 string 不可变 字符分类,默认继承模板(C
locale_provider 编码 enum 不可变 本地化提供者:libcicubuiltin(PG15+)
icu_locale 编码 string 不可变 ICU 本地化规则(PG15+)
icu_rules 编码 string 不可变 ICU 排序定制规则(PG16+)
builtin_locale 编码 string 不可变 内置本地化规则(PG17+)
tablespace 存储 string 可变 默认表空间,修改会触发数据迁移
is_template 权限 bool 可变 是否标记为模板数据库
allowconn 权限 bool 可变 是否允许连接,默认 true
revokeconn 权限 bool 可变 是否回收 PUBLIC 的 CONNECT 权限
connlimit 权限 int 可变 连接数限制,-1 表示不限制
baseline 初始化 string 可变 SQL 基线文件路径,每次置备该数据库时执行
schemas 初始化 (string|object)[] 可变 要创建的模式定义数组
extensions 初始化 (string|object)[] 可变 要安装的扩展定义数组
parameters 初始化 object 可变 数据库级参数
pgbouncer 连接池 bool 可变 是否加入连接池,默认 true
pool_mode 连接池 enum 可变 池化模式:transaction(默认)
pool_size 连接池 int 可变 默认池大小,默认 50
pool_size_min 连接池 int 可变 最小池大小,默认 0
pool_reserve 连接池 int 可变 保留池大小,默认 30
pool_connlimit 连接池 int 可变 最大数据库连接数,默认 100
pool_auth_user 连接池 string 可变 认证查询用户
register_datasource 监控 bool 可变 是否注册到 Grafana 数据源,默认 true

参数详情

name

字符串,必选参数,表示数据库的名称,在一个数据库集群内必须唯一。

当前角色没有对数据库名称实施这一正则校验,SQL 中也会用双引号引用名称;但名称同时参与临时文件路径与 Shell/SQL 命令拼接。为保证整条自动化链路安全可用,建议限制为 63 字节以内,并遵循 ^[A-Za-z_][A-Za-z0-9_$]{0,62}$,不要使用空格、引号、斜杠或其他特殊字符。

- name: myapp              # 简单命名
- name: my_application     # 下划线分隔
- name: app_v2             # 包含版本号

state

枚举值,用于指定要对数据库执行的操作,可以是 createabsentrecreate,默认值为 create

状态 说明
create 默认,创建或修改数据库,如果已经存在,则将可变参数调整到描述的状态
absent 删除数据库,使用 DROP DATABASE WITH (FORCE)
recreate 先删除再创建,用于重置数据库
- name: myapp                # state 默认为 create
- name: olddb
  state: absent              # 删除数据库
- name: testdb
  state: recreate            # 重建数据库

owner

字符串,指定数据库的属主用户,默认不指定,不指定则为数据库 pg_dbsu,即 postgres 用户。

要指定数据库的 owner,被指定的用户必须已存在。修改 owner 会执行:旧 Owner 在数据库上的权限不会被撤回。

数据库属主具有对数据库的完全控制权限,包括创建模式、表、扩展等对象的权限,对于多租户场景尤为有用。

ALTER DATABASE "myapp" OWNER TO "new_owner";
GRANT ALL PRIVILEGES ON DATABASE "myapp" TO "new_owner";

comment

字符串,用于设置数据库的备注信息,如果不指定,默认值为 business database {name}

数据库备注信息通过 COMMENT ON DATABASE 语句设置,支持中文和特殊字符(Pigsty 会自动转义单引号)。 备注信息会存储在共享对象注释目录 pg_shdescription 中,可以通过 \l+ 命令查看。

COMMENT ON DATABASE "myapp" IS '我的应用主数据库';
- name: myapp
  comment: 我的应用主数据库

template

字符串,不可变参数,用于指定创建数据库时使用的模板数据库,默认值为 template1

PostgreSQL 的 CREATE DATABASE 本质上是对模板数据库进行复制,新数据库会继承模板中的所有对象、扩展、模式、权限设置等。 Pigsty 会在集群初始化阶段对 template1 进行定制配置,因此新建数据库默认会继承这些设置。

模板 说明
template1 默认模板,包含 Pigsty 预配置的扩展、模式和权限设置
template0 干净模板,使用不同于集群默认的本地化提供者时,必须使用此模板
自定义数据库 可以使用已有数据库作为模板进行克隆

使用 icubuiltin 本地化提供者时,必须指定 template: template0,因为 template1 已有本地化设置无法覆盖。 使用其他

- name: myapp_icu
  template: template0        # 使用 ICU 时必须指定 template0
  locale_provider: icu
  icu_locale: zh-Hans

使用 template0 时,监控所需的扩展与 Schema,以及角色的默认权限都不再自动创建,这允许你从一个完全干净的模板开始定制数据库。

strategy

枚举值,不可变参数,用于指定从模板克隆数据库的策略,可选值为 FILE_COPYWAL_LOG,此参数在 PostgreSQL 15 及以上版本可用。

策略 说明 适用场景
FILE_COPY 直接复制数据文件,并在前后执行检查点 大模板、希望减少 WAL 量
WAL_LOG 逐块复制并写入 WAL,PG15+ 默认 小模板、不阻塞模板上的连接

WAL_LOG 策略的优势是复制过程中不会阻塞模板数据库上的连接,但对于较大的模板效率不如 FILE_COPY。 在 PostgreSQL 14 及更早版本中,此参数会被忽略。

- name: cloned_db
  template: source_db
  strategy: WAL_LOG          # 使用 WAL 日志方式克隆

encoding

字符串,不可变参数,用于指定数据库的字符编码,如果不指定则继承模板数据库的编码设置,通常为 UTF8

如果没有特殊原因,强烈建议使用 UTF8 编码。字符编码在数据库创建后无法修改,如需更改必须重建数据库。

- name: legacy_db
  template: template0        # 指定非默认编码时使用 template0
  encoding: LATIN1

locale

字符串,不可变参数,用于指定数据库的本地化规则,相当于同时设置 lc_collatelc_ctype,如果不指定则继承模板数据库的设置,通常为 C

本地化规则决定了字符串的排序顺序和字符分类行为。使用 CPOSIX 可获得最佳性能和跨平台一致性, 使用特定语言的本地化规则(如 zh_CN.UTF-8)可以获得符合该语言习惯的排序结果。

- name: chinese_db
  template: template0
  locale: zh_CN.UTF-8        # 中文本地化
  encoding: UTF8

lc_collate

字符串,不可变参数,用于指定字符串的排序规则,如果不指定则继承模板数据库的设置,通常为 C

排序规则决定了 ORDER BY 和比较操作的结果。常用值包括:C(字节序,最快)、C.UTF-8en_US.UTF-8zh_CN.UTF-8。 此参数在数据库创建后无法修改。

- name: myapp
  template: template0
  lc_collate: en_US.UTF-8    # 英文排序规则
  lc_ctype: en_US.UTF-8

lc_ctype

字符串,不可变参数,用于指定字符分类规则,决定字符的大小写、数字、字母等分类,如果不指定则继承模板数据库的设置,通常为 C

字符分类规则影响 upper()lower()、正则表达式中的 \w 等函数的行为。此参数在数据库创建后无法修改。

locale_provider

枚举值,不可变参数,用于指定本地化的实现提供者,可选值为 libcicubuiltin,此参数在 PostgreSQL 15 及以上版本可用,默认值为 libc

提供者 版本 说明
libc - 使用操作系统 C 库,传统默认方式,行为因系统而异
icu PG15+ 使用 ICU 库,跨平台一致,支持更多语言
builtin PG17+ PostgreSQL 内置实现,最高效,仅支持 C/C.UTF-8

使用 icubuiltin 提供者时,必须指定 template: template0,并配合相应的 icu_localebuiltin_locale 参数。

- name: fast_db
  template: template0
  locale_provider: builtin   # 使用内置提供者,最高效
  builtin_locale: C.UTF-8

icu_locale

字符串,不可变参数,用于指定 ICU 本地化规则标识符,此参数在 PostgreSQL 15 及以上版本、且 locale_providericu 时可用。

ICU 本地化标识符遵循 BCP 47 标准,常用值包括:

说明
en-US 美式英语
en-GB 英式英语
zh-Hans 简体中文
zh-Hant 繁体中文
ja-JP 日语
ko-KR 韩语
- name: chinese_app
  template: template0
  locale_provider: icu
  icu_locale: zh-Hans        # 简体中文 ICU 排序
  encoding: UTF8

icu_rules

字符串,不可变参数,用于自定义 ICU 排序规则,此参数在 PostgreSQL 16 及以上版本可用。

ICU 规则允许对默认排序行为进行微调,使用 ICU 排序规则语法

- name: custom_sort_db
  template: template0
  locale_provider: icu
  icu_locale: en-US
  icu_rules: '&V << w <<< W'  # 自定义 V/W 排序顺序

builtin_locale

字符串,不可变参数,用于指定内置本地化提供者的规则,此参数在 PostgreSQL 17 及以上版本、且 locale_providerbuiltin 时可用,可选值为 CC.UTF-8

builtin 提供者是 PostgreSQL 17 新增的内置本地化实现,比 libc 更快,且行为跨平台完全一致。 适合只需要 CC.UTF-8 排序规则的场景。

- name: fast_db
  template: template0
  locale_provider: builtin
  builtin_locale: C.UTF-8    # 内置 UTF-8 支持
  encoding: UTF8

tablespace

字符串,可变参数,用于指定数据库的默认表空间,默认值为 pg_default

修改现有数据库的表空间会触发数据物理迁移,PostgreSQL 会将数据库中的所有对象移动到新表空间,对于大数据库可能需要较长时间,慎用。

- name: archive_db
  tablespace: slow_hdd       # 归档数据使用慢速存储
ALTER DATABASE "archive_db" SET TABLESPACE "slow_hdd";

is_template

布尔值,可变参数,用于指定是否将数据库标记为模板数据库,默认值为 false

设置为 true 后,任何拥有 CREATEDB 权限的用户都可以使用此数据库作为模板克隆新数据库。 模板数据库通常用于预装标准模式、扩展和数据,方便快速创建具有相同配置的新数据库。

- name: app_template
  is_template: true          # 标记为模板,允许普通用户克隆
  schemas: [core, api]
  extensions: [postgis, pg_trgm]

删除标记为 is_template: true 的数据库时,Pigsty 会先执行 ALTER DATABASE ... IS_TEMPLATE false 取消模板标记,然后再删除。

allowconn

布尔值,可变参数,用于控制是否允许连接到此数据库,默认值为 true

设置为 false 会在数据库层面完全禁止连接,任何用户(包括超级用户)都无法连接到此数据库。 此参数通常用于维护或归档用途。

- name: archive_db
  allowconn: false           # 禁止任何连接
ALTER DATABASE "archive_db" ALLOW_CONNECTIONS false;

revokeconn

布尔值,可变参数,用于控制是否回收 PUBLIC 角色的 CONNECT 权限,默认值为 false

设置为 true 时,Pigsty 会执行以下权限变更:

  • 回收 PUBLIC 的 CONNECT 权限,普通用户将无法连接
  • 授予复制用户(replicator)和监控用户(dbuser_monitor)连接权限
  • 授予管理员用户(dbuser_dba)和数据库属主连接权限,并附带 WITH GRANT OPTION

设置为 false 时,会恢复 PUBLIC 的 CONNECT 权限。

- name: secure_db
  owner: dbuser_secure
  revokeconn: true           # 回收公共连接权限,只有指定用户可连接

connlimit

整数,可变参数,用于限制数据库的最大并发连接数,默认值为 -1,表示不限制。

设置为正整数时,会限制同时连接到此数据库的最大会话数。此限制不影响超级用户。

- name: limited_db
  connlimit: 50              # 最多允许 50 个并发连接
ALTER DATABASE "limited_db" CONNECTION LIMIT 50;

baseline

字符串,用于指定数据库置备时要执行的 SQL 基线文件路径。

基线文件通常包含表结构定义、初始数据、存储过程等,用于初始化新数据库。 路径是相对于 Ansible 搜索路径的相对路径,通常放在 files/ 目录下。

只要定义了 baseline,当前角色在每次为该数据库执行置备任务时都会运行该文件,即使数据库已经存在;state: recreate 时也会重新执行。因此基线 SQL 应设计为幂等脚本,或避免在现有数据库上重复执行。

- name: myapp
  baseline: myapp_schema.sql  # 会查找 files/myapp_schema.sql

schemas

数组,可变参数(支持增删),用于定义要在数据库中创建或删除的模式。数组元素可以是字符串或对象。

简单格式使用字符串直接指定模式名,仅支持创建操作:

schemas:
  - app
  - api
  - core

完整格式使用对象定义,支持指定模式属主和删除操作:

schemas:
  - name: app                # 模式名(必选)
    owner: dbuser_app        # 模式属主(可选),生成 AUTHORIZATION 子句
  - name: deprecated
    state: absent            # 删除模式(使用 CASCADE)

创建模式时使用 IF NOT EXISTS,已存在则跳过;删除模式时使用 CASCADE,会同时删除模式内的所有对象。

CREATE SCHEMA IF NOT EXISTS "app" AUTHORIZATION "dbuser_app";
DROP SCHEMA IF EXISTS "deprecated" CASCADE;

extensions

数组,可变参数(支持增删),用于定义要在数据库中安装或卸载的扩展。数组元素可以是字符串或对象。

简单格式使用字符串直接指定扩展名,仅支持安装操作:

extensions:
  - postgis
  - pg_trgm
  - vector

完整格式使用对象定义,支持指定安装模式、版本和卸载操作:

extensions:
  - name: vector             # 扩展名(必选)
    schema: public           # 安装到指定模式(可选)
    version: '0.5.1'         # 指定版本(可选)
  - name: old_extension
    state: absent            # 卸载扩展(使用 CASCADE)

安装扩展时使用 IF NOT EXISTS ... CASCADE;如果扩展已存在,PostgreSQL 会给出 NOTICE 并跳过,同时可自动安装依赖扩展。卸载扩展时使用 CASCADE,会同时删除依赖此扩展的对象。

CREATE EXTENSION IF NOT EXISTS "vector" WITH SCHEMA "public" VERSION '0.5.1' CASCADE;
DROP EXTENSION IF EXISTS "old_extension" CASCADE;

parameters

对象,可变参数,用于设置数据库级别的配置参数。参数通过 ALTER DATABASE ... SET 设置,会对连接到此数据库的所有会话生效。

- name: analytics
  parameters:
    work_mem: '256MB'
    maintenance_work_mem: '512MB'
    statement_timeout: '5min'
    search_path: 'analytics,public'

使用特殊值 DEFAULT(大小写不敏感)可以将参数重置为 PostgreSQL 默认值:

parameters:
  work_mem: DEFAULT          # 重置为默认值
  statement_timeout: '30s'   # 设置新值
ALTER DATABASE "myapp" SET "work_mem" = DEFAULT;
ALTER DATABASE "myapp" SET "statement_timeout" = '30s';

pgbouncer

布尔值,可变参数,用于控制是否将数据库添加到 Pgbouncer 连接池列表,默认值为 true

设置为 false 时,数据库不会出现在 Pgbouncer 的数据库列表中,客户端无法通过连接池访问此数据库。 适用于内部管理数据库或需要直连的特殊场景。

- name: internal_db
  pgbouncer: false           # 不通过连接池访问

pool_mode

枚举值,可变参数,用于设置此数据库在 Pgbouncer 中的池化模式,可选值为 transactionsessionstatement,默认值为 transaction

模式 说明 适用场景
transaction 事务结束后归还连接 大多数 OLTP 应用,默认推荐
session 会话结束后归还连接 需要会话级状态的应用
statement 每条语句后归还连接 简单无状态查询,极致复用
- name: session_app
  pool_mode: session         # 使用会话级池化

pool_size

整数,可变参数,用于设置此数据库在 Pgbouncer 中的默认连接池大小,默认值为 50

连接池大小决定了此数据库连接池允许使用的常规后端连接上限;预热连接数由 pool_size_min 控制。请根据应用负载调整。

- name: high_load_db
  pool_size: 128             # 高负载应用使用更大的池

pool_size_min

整数,可变参数,用于设置此数据库在 Pgbouncer 中的最小连接池大小,默认值为 0

设置大于 0 的值会让 Pgbouncer 预先创建指定数量的后端连接,用于连接预热,减少首次请求的延迟。

- name: latency_sensitive
  pool_size_min: 10          # 预热 10 个连接

pool_reserve

整数,可变参数,用于设置此数据库在 Pgbouncer 中的保留连接数,默认值为 30

当默认池不够用时,Pgbouncer 最多可以额外申请 pool_reserve 个连接来处理突发流量。

- name: bursty_db
  pool_size: 50
  pool_reserve: 30           # 常规池用尽后最多再增加 30 个连接

pool_connlimit

整数,可变参数,用于设置通过 Pgbouncer 连接池访问此数据库的最大连接数,默认值为 100

此限制是 Pgbouncer 层面的限制,与数据库本身的 connlimit 参数独立。

- name: limited_pool_db
  pool_connlimit: 50         # 连接池最多 50 个连接

pool_auth_user

字符串,可变参数,用于指定 Pgbouncer 认证查询使用的用户。

此参数需要配合 pgbouncer_auth_query 参数启用才生效。 设置后,所有通过 Pgbouncer 连接到此数据库的请求都会使用指定用户执行认证查询来验证密码。

- name: myapp
  pool_auth_user: dbuser_monitor  # 使用监控用户执行认证查询

register_datasource

布尔值,可变参数,用于控制是否将此数据库注册到 Grafana 作为 PostgreSQL 数据源,默认值为 true

设置为 false 可以跳过 Grafana 数据源注册。适用于临时数据库、测试数据库,或不希望在监控系统中出现的内部数据库。

- name: temp_db
  register_datasource: false  # 不注册到 Grafana

模板继承

许多参数如果不显式指定,会从模板数据库继承。默认模板是 template1,其编码设置由集群初始化参数决定:

集群参数 默认值 说明
pg_encoding UTF8 集群默认字符编码
pg_locale C / C-UTF-8 (如果支持) 集群默认本地化
pg_lc_collate C / C-UTF-8 (如果支持) 集群默认排序规则
pg_lc_ctype C / C-UTF-8 (如果支持) 集群默认字符分类

新创建的数据库默认会从 template1 数据库 Fork 出来,这个模版数据库会在 PG_PROVISION 阶段进行定制修改: 配置好扩展、模式以及默认权限,因此新创建的数据库也会继承这些配置,除非您显式使用一个其他的数据库作为模板。


深度定制

Pigsty 提供了丰富的定制参数与配置旋钮,如果你想定制模板数据库,请参考以下资源:

如果上面这些配置仍然无法满足您的需求,您可以使用 pg_init 指定自定义的集群初始化脚本进行定制:


本地化提供者

PostgreSQL 15+ 引入了 locale_provider 参数,支持不同的本地化实现。这些属性只能在数据库创建时指定,之后无法修改。

Pigsty 在 configure 配置向导中会根据 PG 与操作系统版本,优先使用 PG 内置的 C.UTF-8/C 本地化提供者。 数据库在默认情况下继承集群的本地化设置。如果您要为数据库指定一个不同于集群默认的本地化提供者,则必须使用 template0 作为模板数据库。

使用 ICU 提供者(PG15+)

- name: myapp_icu
  template: template0        # ICU 必须使用 template0
  locale_provider: icu
  icu_locale: en-US          # ICU 本地化规则
  encoding: UTF8

使用内置提供者(PG17+)

- name: myapp_builtin
  template: template0
  locale_provider: builtin
  builtin_locale: C.UTF-8    # 内置本地化规则
  encoding: UTF8

提供者对比libc(传统方式,依赖操作系统)、icu(PG15+,跨平台一致,功能丰富)、builtin(PG17+,最高效的 C/C.UTF-8 排序)。


连接池

Pgbouncer 连接池可以优化短连接性能,降低并发征用,以避免过高的连接数冲垮数据库,并在数据库迁移时提供额外的灵活处理空间。

Pigsty 会默认为 PostgreSQL 实例 1:1 配置启用一个连接池, 使用和 PostgreSQL 同样的 pg_dbsu 运行,默认为 postgres 操作系统用户。 连接池与数据库使用 /var/run/postgresql Unix Socket 通信。

Pigsty 默认将 pg_databases 中的所有数据库都添加到 pgbouncer 的数据库列表中。 您可以通过在数据库定义中显式设置 pgbouncer: false 来禁用特定数据库的 pgbouncer 连接池支持。 pgbouncer 数据库列表与其配置参数在 /etc/pgbouncer/database.txt 中定义。

meta                        = host=/var/run/postgresql mode=session
grafana                     = host=/var/run/postgresql mode=transaction
bytebase                    = host=/var/run/postgresql auth_user=dbuser_meta
kong                        = host=/var/run/postgresql pool_size=32 reserve_pool=64
gitea                       = host=/var/run/postgresql min_pool_size=10
wiki                        = host=/var/run/postgresql
noco                        = host=/var/run/postgresql
mongo                       = host=/var/run/postgresql

当您 创建数据库 时,Pgbouncer 的数据库列表定义文件将会被刷新,并通过在线重载配置的方式生效,正常不会影响现有的连接。

8.1.6 - HBA 规则

Pigsty 中 PostgreSQL 与 PgBouncer 的 HBA(Host-Based Authentication)规则配置参考。

概述

HBA(Host-Based Authentication)控制“谁可以从哪里、以什么方式连接到数据库”。认证模型和默认规则说明见 身份认证。 Pigsty 通过 pg_default_hba_rulespg_hba_rules 让 HBA 规则也能以声明式配置形式管理。

Pigsty 在集群初始化或 HBA 刷新时渲染以下配置文件:

配置文件 路径 说明
PostgreSQL HBA /pg/data/pg_hba.conf PostgreSQL 服务器的 HBA 规则
PgBouncer HBA /etc/pgbouncer/pgb_hba.conf 连接池 PgBouncer 的 HBA 规则

HBA 规则由以下参数控制:

参数 层级 说明
pg_default_hba_rules G PostgreSQL 全局默认 HBA 规则
pg_hba_rules G/C/I PostgreSQL 集群/实例级追加规则
pgb_default_hba_rules G PgBouncer 全局默认 HBA 规则
pgb_hba_rules G/C/I PgBouncer 集群/实例级追加规则

规则支持以下特性:

  • 按角色过滤:规则支持 role 字段,根据实例的 pg_role 自动筛选生效
  • 按顺序排序:规则支持 order 字段,控制规则在最终配置文件中的位置
  • 两种写法:支持别名形式(简化语法)和原始形式(直接 HBA 文本)

刷新 HBA

修改配置后,需要重新渲染配置文件并让服务重载:

bin/pgsql-hba <cls>                   # 刷新整个集群的 HBA 规则(推荐)
bin/pgsql-hba <cls> <ip>...           # 刷新集群中指定实例的 HBA 规则

脚本内部执行以下剧本命令:

./pgsql.yml -l <cls> -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload -e pg_reload=true

仅刷新 PostgreSQL./pgsql.yml -l <cls> -t pg_hba,pg_reload -e pg_reload=true

仅刷新 Pgbouncer./pgsql.yml -l <cls> -t pgbouncer_hba,pgbouncer_reload

不要直接编辑配置文件

不要直接编辑 /pg/data/pg_hba.conf/etc/pgbouncer/pgb_hba.conf,下次执行 playbook 时会被覆盖。 所有变更应在 pigsty.yml 中进行,然后执行 bin/pgsql-hba 刷新。


参数详解

pg_default_hba_rules

PostgreSQL 全局默认 HBA 规则列表,通常定义在 all.vars 中,为所有 PostgreSQL 集群提供基础访问控制。

  • 类型:rule[],层级:全局 (G)
pg_default_hba_rules:
  - {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  ,order: 100}
  - {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' ,order: 150}
  - {user: '${repl}'    ,db: replication ,addr: localhost ,auth: pwd   ,title: 'replicator replication from localhost',order: 200}
  - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: pwd   ,title: 'replicator replication from intranet' ,order: 250}
  - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: pwd   ,title: 'replicator postgres db from intranet' ,order: 300}
  - {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' ,order: 350}
  - {user: '${monitor}' ,db: all         ,addr: infra     ,auth: pwd   ,title: 'monitor from infra host with password',order: 400}
  - {user: '${admin}'   ,db: all         ,addr: infra     ,auth: ssl   ,title: 'admin @ infra nodes with pwd & ssl'   ,order: 450}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: ssl   ,title: 'admin @ everywhere with ssl & pwd'    ,order: 500}
  - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: pwd   ,title: 'pgbouncer read/write via local socket',order: 550}
  - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: pwd   ,title: 'read/write biz user via password'     ,order: 600}
  - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: pwd   ,title: 'allow etl offline tasks from intranet',order: 650}

pg_hba_rules

PostgreSQL 集群/实例级 HBA 追加规则,可在集群或实例级别覆盖,与默认规则合并后按 order 排序。

  • 类型:rule[],层级:全局/集群/实例 (G/C/I),默认值:[]
pg_hba_rules:
  - {user: app_user, db: app_db, addr: intra, auth: pwd, title: 'app user access'}

pgb_default_hba_rules

Pgbouncer 全局默认 HBA 规则列表,通常定义在 all.vars 中。

  • 类型:rule[],层级:全局 (G)
pgb_default_hba_rules:
  - {user: '${dbsu}'    ,db: pgbouncer   ,addr: local     ,auth: peer  ,title: 'dbsu local admin access with os ident',order: 100}
  - {user: 'all'        ,db: all         ,addr: localhost ,auth: pwd   ,title: 'allow all user local access with pwd' ,order: 150}
  - {user: '${monitor}' ,db: pgbouncer   ,addr: intra     ,auth: pwd   ,title: 'monitor access via intranet with pwd' ,order: 200}
  - {user: '${monitor}' ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other monitor access addr' ,order: 250}
  - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: pwd   ,title: 'admin access via intranet with pwd'   ,order: 300}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other admin access addr'   ,order: 350}
  - {user: 'all'        ,db: all         ,addr: intra     ,auth: pwd   ,title: 'allow all user intra access with pwd' ,order: 400}

pgb_hba_rules

Pgbouncer 集群/实例级 HBA 追加规则。

  • 类型:rule[],层级:全局/集群/实例 (G/C/I),默认值:[]

注意:Pgbouncer HBA 不支持 db: replication


规则字段

每条 HBA 规则是一个 YAML 字典,支持以下字段:

字段 类型 必需 默认值 说明
user string all 用户名,支持 all、变量占位符、+rolename
db string all 数据库名,支持 allreplication、具体库名
addr string 是* - 地址别名或 CIDR,见 地址别名
auth string pwd 认证方式别名,见 认证方式
title string - 规则说明/注释,会渲染为配置文件中的注释
role string common 实例角色过滤,见 角色过滤
order int 1000 排序权重,数字小的排前面,见 排序机制
rules list 是* - 原始 HBA 文本行列表,与 addr 二选一

addrrules 必须指定其一。使用 rules 时可以直接写原始 HBA 格式。


地址别名

Pigsty 提供地址别名,简化 HBA 规则编写:

别名 展开为 说明
local Unix socket 本地 Unix 套接字连接
localhost Unix socket + 127.0.0.1/32 + ::1/128 本地回环地址
admin ${admin_ip}/32 管理员 IP 地址
infra 所有 infra 组节点 IP 基础设施节点列表
cluster 当前集群所有成员 IP 同一集群内的所有实例
intra / intranet 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 内网 CIDR 网段
world / all 0.0.0.0/0 + ::/0 任意地址(IPv4 + IPv6)
<CIDR> 直接使用 192.168.1.0/2410.1.1.100/32

内网 CIDR 可通过 node_firewall_intranet 参数自定义:

node_firewall_intranet:
  - 10.0.0.0/8
  - 172.16.0.0/12
  - 192.168.0.0/16

认证方式

Pigsty 提供认证方式别名,简化配置:

别名 实际方式 连接类型 说明
pwd scram-sha-256md5 host 根据 pg_pwd_enc 自动选择
ssl scram-sha-256md5 hostssl 强制 SSL + 密码
ssl-sha scram-sha-256 hostssl 强制 SSL + SCRAM-SHA-256
ssl-md5 md5 hostssl 强制 SSL + MD5
cert cert hostssl 客户端证书认证
trust trust host 无条件信任(危险)
deny / reject reject host 拒绝连接
ident ident host OS 用户映射(PostgreSQL)
peer peer local OS 用户映射(Pgbouncer/本地)

pg_pwd_enc 默认为 scram-sha-256,可设为 md5 以兼容老客户端。


用户变量

HBA 规则支持以下用户占位符,渲染时自动替换为实际用户名:

占位符 默认值 对应参数
${dbsu} postgres pg_dbsu
${repl} replicator pg_replication_username
${monitor} dbuser_monitor pg_monitor_username
${admin} dbuser_dba pg_admin_username

角色过滤

HBA 规则的 role 字段控制规则在哪些实例上生效:

角色 说明
common 默认值,所有实例都生效
primary 仅主库实例生效
replica 仅从库实例生效
offline 仅离线实例生效(pg_role: offlinepg_offline_query: true
standby 备库实例
delayed 延迟从库实例

角色过滤基于实例的 pg_role 变量进行匹配,不匹配的规则会被注释掉(以 # 开头)。

pg_hba_rules:
  # 仅在主库生效:写入用户只能连主库
  - {user: writer, db: all, addr: intra, auth: pwd, role: primary, title: 'writer only on primary'}

  # 仅在离线实例生效:ETL 任务专用网络
  - {user: '+dbrole_offline', db: all, addr: '172.20.0.0/16', auth: ssl, role: offline, title: 'offline dedicated'}

排序机制

PostgreSQL HBA 是 首条匹配生效,规则顺序至关重要。Pigsty 通过 order 字段控制规则渲染顺序。

Order 区间约定

区间 用途
0 - 99 用户高优先规则(在所有默认规则之前)
100 - 650 默认规则区(间隔 50,便于插入)
1000+ 用户规则默认值(不填 order 时追加到最后)

PostgreSQL 默认规则 Order 分配

Order 规则说明
100 dbsu local ident
150 dbsu replication local
200 replicator localhost
250 replicator intra replication
300 replicator intra postgres
350 monitor localhost
400 monitor infra
450 admin infra ssl
500 admin world ssl
550 dbrole_readonly localhost
600 dbrole_readonly intra
650 dbrole_offline intra

Pgbouncer 默认规则 Order 分配

Order 规则说明
100 dbsu local peer
150 all localhost pwd
200 monitor pgbouncer intra
250 monitor world deny
300 admin intra pwd
350 admin world deny
400 all intra pwd

写法示例

别名形式:使用 Pigsty 提供的简化语法

pg_hba_rules:
  - title: allow grafana view access
    role: primary
    user: dbuser_view
    db: meta
    addr: infra
    auth: ssl

渲染结果:

# allow grafana view access [primary]
hostssl  meta               dbuser_view        10.10.10.10/32     scram-sha-256

原始形式:直接使用 PostgreSQL HBA 语法

pg_hba_rules:
  - title: allow intranet password access
    role: common
    rules:
      - host all all 10.0.0.0/8 scram-sha-256
      - host all all 172.16.0.0/12 scram-sha-256
      - host all all 192.168.0.0/16 scram-sha-256

渲染结果:

# allow intranet password access [common]
host all all 10.0.0.0/8 scram-sha-256
host all all 172.16.0.0/12 scram-sha-256
host all all 192.168.0.0/16 scram-sha-256

常见配置场景

黑名单 IP:使用 order: 0 确保最先匹配

pg_hba_rules:
  - {user: all, db: all, addr: '10.1.1.100/32', auth: deny, order: 0, title: 'block bad ip'}

白名单应用服务器:高优先级允许特定 IP

pg_hba_rules:
  - {user: app_user, db: app_db, addr: '192.168.1.10/32', auth: ssl, order: 50, title: 'app server'}

管理员强制证书:覆盖默认的 SSL 密码认证

pg_hba_rules:
  - {user: '${admin}', db: all, addr: world, auth: cert, order: 10, title: 'admin cert only'}

离线实例专用网络:仅在 offline 实例生效

pg_hba_rules:
  - {user: '+dbrole_offline', db: all, addr: '172.20.0.0/16', auth: ssl-sha, role: offline, title: 'etl network'}

按数据库限制访问:敏感库仅允许特定网段

pg_hba_rules:
  - {user: fin_user, db: finance_db, addr: '10.20.0.0/16', auth: ssl, title: 'finance only'}
  - {user: hr_user, db: hr_db, addr: '10.30.0.0/16', auth: ssl, title: 'hr only'}

Pgbouncer 专用规则:注意不支持 db: replication

pgb_hba_rules:
  - {user: '+dbrole_readwrite', db: all, addr: world, auth: ssl, title: 'app via pgbouncer'}

完整集群示例

pg-prod:
  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-prod

    pg_hba_rules:
      # 黑名单:已知恶意 IP(最高优先级)
      - {user: all, db: all, addr: '10.1.1.100/32', auth: deny, order: 0, title: 'blacklist'}

      # 应用服务器白名单(高优先级)
      - {user: app_user, db: app_db, addr: '192.168.1.0/24', auth: ssl, order: 50, title: 'app servers'}

      # ETL 任务:仅离线实例
      - {user: etl_user, db: all, addr: '172.20.0.0/16', auth: pwd, role: offline, title: 'etl tasks'}

      # 集群内监控访问
      - {user: '${monitor}', db: all, addr: cluster, auth: pwd, order: 380, title: 'cluster monitor'}

    pgb_hba_rules:
      # 应用通过连接池
      - {user: '+dbrole_readwrite', db: all, addr: '192.168.1.0/24', auth: ssl, title: 'app via pgbouncer'}

验证与排查

查看当前 HBA 规则

psql -c "TABLE pg_hba_file_rules"         # 通过 SQL 查看(推荐)
cat /pg/data/pg_hba.conf                  # 查看 PostgreSQL HBA 文件
cat /etc/pgbouncer/pgb_hba.conf           # 查看 Pgbouncer HBA 文件
grep '^#' /pg/data/pg_hba.conf | head -20 # 查看规则标题(验证 order)

测试连接认证

psql -h <host> -p 5432 -U <user> -d <db> -c "SELECT 1"

常见问题排查

错误信息 可能原因 解决方案
no pg_hba.conf entry for host... 没有匹配的 HBA 规则 添加对应规则并刷新
password authentication failed 密码错误或加密方式不兼容 检查密码和 pg_pwd_enc
规则不生效 未刷新或 order 被覆盖 执行 bin/pgsql-hba 并检查顺序

注意事项

  1. 顺序敏感:PostgreSQL HBA 首条匹配生效,善用 order 字段
  2. 角色匹配:确保 role 字段与目标实例的 pg_role 一致
  3. 地址格式:CIDR 必须正确,如 10.0.0.0/8 而非 10.0.0.0/255.0.0.0
  4. PgBouncer 限制:不支持 db: replication
  5. TLS 前提sslcert 要求服务端 TLS;客户端仍需使用 verify-full 验证服务端身份
  6. 测试优先:修改 HBA 前建议先在测试环境验证
  7. 扩缩容刷新:使用 addr: cluster 的规则在集群成员变化后需要刷新

相关文档

8.1.7 - 参数配置

如何配置集群、实例、用户和数据库级别的 PostgreSQL 参数

PostgreSQL 参数可以在多个层级进行配置,不同层级的参数设置具有不同的作用范围和优先级。 Pigsty 支持在四个层级配置 PostgreSQL 参数,从全局到局部依次为:

层级 作用范围 配置方式 存储位置
集群级 整个集群所有实例 Patroni DCS / 调优模板 etcd + postgresql.conf
实例级 单个 PostgreSQL 实例 pg_parameters / ALTER SYSTEM postgresql.auto.conf
数据库级 特定数据库的所有会话 pg_databases[].parameters pg_db_role_setting
用户级 特定用户的所有会话 pg_users[].parameters pg_db_role_setting

参数优先级从低到高:集群级 < 实例级 < 数据库级 < 用户级 < 会话级SET 命令)。 高优先级的设置会覆盖低优先级的设置。

关于 PostgreSQL 参数的完整说明,请参阅 PostgreSQL 官方文档:服务器配置


集群级参数

集群级参数是整个 PostgreSQL 集群共享的配置,所有实例(主库和从库)都会使用相同的参数值。 在 Pigsty 中,集群级参数通过 Patroni 管理,存储在分布式配置存储(DCS,默认为 etcd)中。

Pigsty 提供了四种预置的 Patroni 参数优化模板,针对不同的使用场景进行了优化,通过 pg_conf 参数指定:

模板 适用场景 特点
oltp.yml 在线事务处理 低延迟、高并发,默认推荐
olap.yml 在线分析处理 大查询、高吞吐,适合数仓
crit.yml 核心金融业务 最大持久性,牺牲部分性能换取安全
tiny.yml 微型实例 资源受限环境,适合开发测试

调优模板文件位于 Pigsty 安装目录的 roles/pgsql/templates/ 目录下,包含了根据硬件规格自动计算的参数值。 这些模板会在集群初始化时渲染为 Patroni 配置文件 /etc/patroni/patroni.yml。更多详情请参阅 场景模板

在集群创建前,您可以通过调整这些 Patroni 配置模板来修改集群的 初始化参数。 一旦集群初始化完成,后续的参数修改应通过 Patroni 的 配置管理 机制进行。

Patroni DCS 配置

Patroni 将集群配置存储在 DCS(分布式配置存储,默认为 etcd)中,确保集群所有成员使用一致的配置。

配置存储结构

/pigsty/                          # 命名空间(patroni_namespace)
  └── pg-meta/                    # 集群名称(pg_cluster)
      ├── config                  # 集群配置(所有成员共享)
      ├── leader                  # 当前主库信息
      ├── members/                # 成员注册信息
      │   ├── pg-meta-1
      │   └── pg-meta-2
      └── ...

配置渲染流程

  1. 初始化阶段:调优模板(如 oltp.yml)通过 Jinja2 渲染为 /etc/patroni/patroni.yml
  2. 启动阶段:Patroni 读取本地配置,将 PostgreSQL 参数写入 DCS
  3. 运行阶段:Patroni 定期从 DCS 同步配置到本地 PostgreSQL

本地缓存机制

每个 Patroni 实例会在本地缓存 DCS 配置,位于 /pg/conf/<instance>.yml

  • 启动时:从 DCS 加载配置,缓存到本地
  • 运行时:定期同步 DCS 配置到本地缓存
  • DCS 不可用时:使用本地缓存继续运行(但无法进行主从切换)

配置文件层次

Patroni 会将 DCS 中的配置渲染到本地 PostgreSQL 配置文件,形成以下层次结构:

/pg/data/
├── postgresql.conf          # 主配置文件(由 Patroni 动态管理)
├── postgresql.base.conf     # 基础配置(通过 include 指令加载)
├── postgresql.auto.conf     # 实例级覆盖配置(ALTER SYSTEM 写入)
├── pg_hba.conf              # 客户端认证配置
└── pg_ident.conf            # 用户映射配置

配置加载顺序(优先级从低到高):

  1. postgresql.conf:Patroni 动态生成,包含 DCS 中的集群参数
  2. postgresql.base.conf:通过 include 指令加载,包含静态基础配置
  3. postgresql.auto.conf:PostgreSQL 自动加载,用于实例级参数覆盖

由于 postgresql.auto.conf 最后加载,其中的参数会覆盖前面文件中的同名参数。


实例级参数

实例级参数仅对单个 PostgreSQL 实例生效,用于覆盖集群级配置或设置实例特定的参数。 实例级参数会写入 postgresql.auto.conf 文件,由于该文件最后加载,可以覆盖集群级的任何参数。

这是一项非常有用的技术:您可以为特定实例设置不同于集群的参数值,例如:

  • 为从库设置 hot_standby_feedback = on
  • 为特定实例调整 work_memmaintenance_work_mem
  • 为延迟从库设置 recovery_min_apply_delay

使用 pg_parameters

在 Pigsty 配置中,使用 pg_parameters 参数定义实例级配置:

pg-meta:
  hosts:
    10.10.10.10:
      pg_seq: 1
      pg_role: primary
      pg_parameters:                              # 实例级参数
        log_statement: all                        # 仅此实例记录所有 SQL
  vars:
    pg_cluster: pg-meta
    pg_parameters:                                # 集群默认的实例参数
      log_timezone: Asia/Shanghai
      log_min_duration_statement: 1000

使用 ./pgsql.yml -l <cls> -t pg_param 子任务,可以将参数配置应用生效,这些参数会被渲染到 postgresql.auto.conf 文件中。

参数覆盖层次

pg_parameters 可以在 Ansible 配置的不同层次定义,优先级从低到高:

all:
  vars:
    pg_parameters:                    # 全局默认
      log_statement: none

  children:
    pg-meta:
      vars:
        pg_parameters:                # 集群级覆盖
          log_statement: ddl
      hosts:
        10.10.10.10:
          pg_parameters:              # 实例级覆盖(最高优先级)
            log_statement: all

使用 ALTER SYSTEM

除了通过配置文件,还可以在运行时使用 SQL 命令 ALTER SYSTEM 修改实例级参数:

-- 设置参数
ALTER SYSTEM SET work_mem = '256MB';
ALTER SYSTEM SET log_min_duration_statement = 1000;

-- 重置为默认值
ALTER SYSTEM RESET work_mem;
ALTER SYSTEM RESET ALL;  -- 重置所有 ALTER SYSTEM 设置

-- 重新加载配置使其生效
SELECT pg_reload_conf();

ALTER SYSTEM 会将参数写入 postgresql.auto.conf 文件。

注意:在 Pigsty 管理的集群中,postgresql.auto.conf 由 Ansible 通过 pg_parameters 管理。 手动使用 ALTER SYSTEM 修改的参数可能会在下次执行 playbook 时被覆盖。 建议通过修改 pigsty.yml 中的 pg_parameters 来管理实例级参数。

列表类型参数

PostgreSQL 中有一类特殊的参数接受逗号分隔的列表值。在 YAML 配置文件中配置这类参数时, 整个值必须用引号包裹,否则 YAML 解析器会将其解释为数组而导致错误:

# ✓ 正确:用引号包裹整个值
pg_parameters:
  shared_preload_libraries: 'timescaledb, pg_stat_statements'
  search_path: '"$user", public, app'

# ✗ 错误:不加引号会导致 YAML 解析错误
pg_parameters:
  shared_preload_libraries: timescaledb, pg_stat_statements   # YAML 会解析为数组!

Pigsty 会自动识别以下列表类型参数,在渲染到配置文件时 不添加外层引号

参数 说明 示例值
shared_preload_libraries 预加载共享库 'timescaledb, pg_stat_statements'
search_path Schema 搜索路径 '"$user", public, app'
local_preload_libraries 本地预加载库 'auto_explain'
session_preload_libraries 会话预加载库 'pg_hint_plan'
log_destination 日志输出目标 'csvlog, stderr'
unix_socket_directories Unix Socket 目录 '/var/run/postgresql, /tmp'
temp_tablespaces 临时表空间 'ssd_space, hdd_space'
debug_io_direct 直接 I/O 模式(PG16+) 'data, wal'

渲染示例

# pigsty.yml 配置(YAML 中需要引号)
pg_parameters:
  shared_preload_libraries: 'timescaledb, pg_stat_statements'
  search_path: '"$user", public, app'
  work_mem: 64MB
# 渲染后的 postgresql.auto.conf(列表参数无外层引号)
shared_preload_libraries = timescaledb, pg_stat_statements
search_path = "$user", public, app
work_mem = '64MB'

数据库级参数

数据库级参数针对特定数据库生效,连接到该数据库的所有会话都会应用这些参数设置。 通过 ALTER DATABASE ... SET 实现,存储在系统表 pg_db_role_setting 中。

配置方式

pg_databases 中使用 parameters 字段定义:

pg_databases:
  - name: analytics
    owner: dbuser_analyst
    parameters:
      work_mem: 256MB                              # 分析库需要更多内存
      maintenance_work_mem: 1GB                    # 大表维护操作
      statement_timeout: 10min                     # 允许长查询
      search_path: '"$user", public, mart'         # 列表参数需要引号

与实例级参数相同,列表类型参数值在 YAML 中需要用引号包裹。

参数渲染规则

数据库级参数通过 ALTER DATABASE ... SET 语句设置。Pigsty 会根据参数类型自动选择正确的语法:

列表类型参数search_pathtemp_tablespaceslocal_preload_librariessession_preload_librarieslog_destination)不加外层引号:

ALTER DATABASE "analytics" SET "search_path" = "$user", public, mart;

标量参数 使用引号包裹值:

ALTER DATABASE "analytics" SET "work_mem" = '256MB';
ALTER DATABASE "analytics" SET "statement_timeout" = '10min';

注意:虽然 log_destination 在数据库级参数白名单中,但由于其 contextsighup, 实际上无法在数据库级别生效。此参数应在实例级(pg_parameters)配置。

查看数据库参数

-- 查看特定数据库的参数设置
SELECT datname, unnest(setconfig) AS setting
FROM pg_db_role_setting drs
JOIN pg_database d ON d.oid = drs.setdatabase
WHERE drs.setrole = 0 AND datname = 'analytics';

手动管理

-- 设置参数
ALTER DATABASE analytics SET work_mem = '256MB';
ALTER DATABASE analytics SET search_path = "$user", public, myschema;

-- 重置参数
ALTER DATABASE analytics RESET work_mem;
ALTER DATABASE analytics RESET ALL;

用户级参数

用户级参数针对特定数据库用户生效,该用户的所有会话都会应用这些参数设置。 通过 ALTER USER ... SET 实现,同样存储在系统表 pg_db_role_setting 中。

配置方式

pg_userspg_default_roles 中使用 parameters 字段定义:

pg_users:
  - name: dbuser_analyst
    password: DBUser.Analyst
    parameters:
      work_mem: 256MB                              # 分析查询需要更多内存
      statement_timeout: 5min                      # 允许较长的查询时间
      search_path: '"$user", public, analytics'    # 列表参数需要引号
      log_statement: all                           # 记录所有 SQL

参数渲染规则

用户级参数的渲染规则与数据库级参数相同:

列表类型参数search_pathtemp_tablespaceslocal_preload_librariessession_preload_libraries)不加外层引号:

ALTER USER "dbuser_analyst" SET "search_path" = "$user", public, analytics;

标量参数 使用引号包裹:

ALTER USER "dbuser_analyst" SET "work_mem" = '256MB';
ALTER USER "dbuser_analyst" SET "statement_timeout" = '5min';

特殊值 DEFAULT

使用 DEFAULT(大小写不敏感)可以将参数重置为 PostgreSQL 默认值:

parameters:
  work_mem: DEFAULT          # 重置为默认值
  statement_timeout: 30s     # 设置具体值
ALTER USER "dbuser_app" SET "work_mem" = DEFAULT;
ALTER USER "dbuser_app" SET "statement_timeout" = '30s';

查看用户参数

-- 查看特定用户的参数设置
SELECT rolname, unnest(setconfig) AS setting
FROM pg_db_role_setting drs
JOIN pg_roles r ON r.oid = drs.setrole
WHERE rolname = 'dbuser_analyst';

手动管理

-- 设置参数
ALTER USER dbuser_app SET work_mem = '128MB';
ALTER USER dbuser_app SET search_path = "$user", public, myschema;

-- 重置参数
ALTER USER dbuser_app RESET work_mem;
ALTER USER dbuser_app RESET ALL;

参数优先级

当同一参数在多个层级设置时,PostgreSQL 按以下优先级应用(从低到高):

postgresql.conf           ← 集群级参数(Patroni DCS)
postgresql.auto.conf      ← 实例级参数(pg_parameters / ALTER SYSTEM)
数据库级                    ← ALTER DATABASE SET
用户级                      ← ALTER USER SET
会话级                      ← SET 命令

关于数据库级与用户级的优先级

当用户连接到特定数据库时,如果同一参数在数据库级和用户级都有设置, PostgreSQL 会使用 用户级参数,因为用户级优先级更高。

示例场景

# 数据库级:analytics 数据库 work_mem = 256MB
pg_databases:
  - name: analytics
    parameters:
      work_mem: 256MB

# 用户级:analyst 用户 work_mem = 512MB
pg_users:
  - name: analyst
    parameters:
      work_mem: 512MB
  • analyst 用户连接到 analytics 数据库时:work_mem = 512MB(用户级优先)
  • 当其他用户连接到 analytics 数据库时:work_mem = 256MB(数据库级生效)
  • analyst 用户连接到其他数据库时:work_mem = 512MB(用户级生效)

8.1.8 - 访问控制

Pigsty 内置角色、用户、默认权限与数据库 ACL 的配置参考。

访问控制由角色、对象权限、数据库 ACL 与 HBA 共同决定。本节聚焦配置参数;设计与边界见 访问控制概念

Pigsty 预置了一套精简的 ACL 模型,通过以下参数描述:

  • pg_default_roles:系统角色与系统用户。
  • pg_users:业务用户与角色。
  • pg_default_privileges:管理员/属主新建对象时的默认权限。
  • pg_revoke_publicpg_default_schemaspg_default_extensions:控制 template1 的默认行为。

这些参数应与 HBA 和数据库定义一起管理,形成可复现的访问控制配置。


默认角色体系(pg_default_roles)

默认包含 4 个业务角色 + 4 个系统用户:

名称 类型 说明
dbrole_readonly NOLOGIN 所有业务共用,拥有 SELECT/USAGE
dbrole_readwrite NOLOGIN 继承只读角色,并拥有 INSERT/UPDATE/DELETE
dbrole_admin NOLOGIN 继承 pg_monitor + 读写角色,可建对象和触发器
dbrole_offline NOLOGIN 独立只读角色;实例范围需要通过 HBA 显式限制
postgres 用户 系统超级用户,与 pg_dbsu 同名
replicator 用户 用于流复制与备份,继承监控与只读权限
dbuser_dba 用户 主要管理员账号,同时同步到 pgbouncer
dbuser_monitor 用户 监控账号,具备 pg_monitor 权限,默认记录慢 SQL

这些定义位于 pg_default_roles。该参数是完整列表;自定义时应复制并保留所需的默认角色和系统用户,再按依赖顺序添加新角色。更改角色名称后,还必须同步更新 HBA、默认权限和脚本中的引用。


默认用户与凭据参数

系统用户的用户名/密码由以下参数控制:

参数 默认值 作用
pg_dbsu postgres 数据库/系统超级用户
pg_dbsu_password 空字符串 dbsu 密码(默认不启用)
pg_replication_username replicator 复制用户名称
pg_replication_password DBUser.Replicator 复制用户密码
pg_admin_username dbuser_dba 管理员用户名
pg_admin_password DBUser.DBA 管理员密码
pg_monitor_username dbuser_monitor 监控用户
pg_monitor_password DBUser.Monitor 监控用户密码

修改这些参数后,应同步更新 pg_default_roles 中对应用户的定义,避免用户名和角色属性不一致。


业务角色与授权(pg_users)

业务用户通过 pg_users 声明(详细字段见 用户配置),其中 roles 字段控制授予的业务角色。

示例:创建只读/读写用户各一名:

pg_users:
  - { name: app_reader,  password: DBUser.Reader,  roles: [dbrole_readonly],  pgbouncer: true }
  - { name: app_writer,  password: DBUser.Writer,  roles: [dbrole_readwrite], pgbouncer: true }

业务用户通过继承 dbrole_* 获得默认对象权限;数据库 CONNECT 权限和 pg_hba_rules 继续控制可连接的数据库和来源。

需要更细粒度的 ACL 时,可在 baseline SQL 或后续剧本中使用标准 GRANT / REVOKE,并将额外授权纳入审查。


默认权限模板(pg_default_privileges)

pg_default_privileges 会应用到 pg_dbsupg_admin_usernamedbrole_admin,并应用到每个已声明的数据库属主。默认模板如下:

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

由上述身份创建的对象会自动应用对应权限。其他对象创建者需要单独配置 ALTER DEFAULT PRIVILEGES

额外提示:

  • pg_revoke_public 默认为 true,意味着自动撤销 PUBLIC 在数据库和 public schema 上的 CREATE 权限。
  • pg_default_schemaspg_default_extensions 控制在 template1/postgres 中预创建的 schema/扩展,通常用于监控对象(monitor schema、pg_stat_statements 等)。

常见配置场景

为合作方提供只读账号

pg_users:
  - name: partner_ro
    password: Partner.Read
    roles: [dbrole_readonly]
pg_hba_rules:
  - { user: partner_ro, db: analytics, addr: 203.0.113.0/24, auth: ssl }

该配置为合作方增加一条从指定网段通过 TLS 访问 analytics 的 HBA 规则。pg_hba_rules 不会删除范围更宽的默认规则;若要求该账号只能访问此数据库,还应收敛默认 HBA,并配置数据库 CONNECT 权限。

为业务管理员赋予 DDL 能力

pg_users:
  - name: app_admin
    password: DBUser.AppAdmin
    roles: [dbrole_admin]

app_admin 可以继承 dbrole_admin 的 DDL 权限。要让新对象应用 dbrole_admin 的默认权限,应先执行 SET ROLE dbrole_admin;如果 app_admin 是已声明的数据库属主,也可以直接以属主身份创建对象。

自定义默认权限

pg_default_privileges:
  - GRANT INSERT,UPDATE,DELETE ON TABLES TO dbrole_admin
  - GRANT SELECT,UPDATE ON SEQUENCES TO dbrole_admin
  - GRANT SELECT ON TABLES TO reporting_group

该参数会替换完整的默认权限列表。引用的角色必须先创建;变更只影响之后创建的对象,已有对象需要另行授权。


与其他组件的协同

  • HBA 规则:使用 pg_hba_rules 绑定角色、数据库和来源。要限制 dbrole_offline,应为其规则设置 role: offline
  • PgBouncerpgbouncer: true 的用户会被写入 userlist.txtpool_mode/pool_connlimit 可以控制连接池层面的配额。
  • 数据库监控dbuser_monitor 的权限来自 pg_default_roles。新增监控用户时,应授予 pg_monitor,并检查 monitor schema 的访问权限。

这些参数可以与配置清单一起版本化;实际权限仍应通过数据库系统目录定期核对。


相关文档

8.2 - 服务/接入

分离读写操作,正确路由流量,稳定可靠地交付 PostgreSQL 集群提供的能力。

分离读写操作,正确路由流量,稳定可靠地交付 PostgreSQL 集群提供的能力。

服务 是一种抽象:它是数据库集群对外提供能力的形式,并封装了底层集群的细节。

服务对于生产环境中的 稳定接入 至关重要,在 高可用 集群自动故障时方显其价值,单机用户 通常不需要操心这个概念。


单机用户

“服务” 的概念是给生产环境用的,个人用户/单机集群可以不折腾,直接拿实例名/IP 地址访问数据库。

例如,Pigsty 默认的单节点 pg-meta.meta 数据库,就可以直接用下面三个不同的用户连接上去。

psql postgres://dbuser_dba:[email protected]/meta     # 直接用 DBA 超级用户连上去
psql postgres://dbuser_meta:[email protected]/meta   # 用默认的业务管理员用户连上去
psql postgres://dbuser_view:DBUser.Viewer@pg-meta/meta     # 用默认的只读用户走实例域名连上去

服务概述

在真实世界生产环境中,我们会使用基于复制的主从数据库集群。集群中有且仅有一个实例作为领导者(主库)可以接受写入。 而其他实例(从库)则会从持续从集群领导者获取变更日志,与领导者保持一致。同时,从库还可以承载只读请求,在读多写少的场景下可以显著分担主库的负担, 因此对集群的写入请求与只读请求进行区分,是一种十分常见的实践。

此外对于高频短连接的生产环境,我们还会通过连接池中间件(Pgbouncer)对请求进行池化,减少连接与后端进程的创建开销。但对于 ETL 与变更执行等场景,我们又需要绕过连接池,直接访问数据库。 同时,高可用集群在故障时会出现故障切换(Failover),故障切换会导致集群的领导者出现变更。因此高可用的数据库方案要求写入流量可以自动适配集群的领导者变化。 这些不同的访问需求(读写分离,池化与直连,故障切换自动适配)最终抽象出 服务 (Service)的概念。

通常来说,数据库集群都必须提供这种最基础的服务:

  • 读写服务(primary):可以读写数据库

对于生产数据库集群,至少应当提供这两种服务:

  • 读写服务(primary):写入数据:只能由主库所承载。
  • 只读服务(replica):读取数据:可以由从库承载,没有从库时也可由主库承载

此外,根据具体的业务场景,可能还会有其他的服务,例如:

  • 默认直连服务(default):允许(管理)用户,绕过连接池直接访问数据库的服务
  • 离线从库服务(offline):不承接线上只读流量的专用从库,用于 ETL 与分析查询
  • 同步从库服务(standby):没有复制延迟的只读服务,由 同步备库/主库处理只读查询
  • 延迟从库服务(delayed):访问同一个集群在一段时间之前的旧数据,由 延迟从库 来处理

默认服务

Pigsty 默认为每个 PostgreSQL 数据库集群提供四种不同的服务,以下是默认服务及其定义:

服务 端口 描述
primary 5433 生产读写,连接到主库连接池(6432)
replica 5434 生产只读,连接到备库连接池(6432)
default 5436 管理,ETL 写入,直接访问主库(5432)
offline 5438 OLAP、ETL、个人用户、交互式查询

以默认的 pg-meta 集群为例,它提供四种默认服务:

psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5433/meta   # pg-meta-primary : 通过主要的 pgbouncer(6432) 进行生产读写
psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5434/meta   # pg-meta-replica : 通过备份的 pgbouncer(6432) 进行生产只读
psql postgres://dbuser_dba:DBUser.DBA@pg-meta:5436/meta     # pg-meta-default : 通过主要的 postgres(5432) 直接连接
psql postgres://dbuser_stats:DBUser.Stats@pg-meta:5438/meta # pg-meta-offline : 通过离线的 postgres(5432) 直接连接

从示例集群 架构图 上可以看出这四种服务的工作方式:

pigsty-ha.png

这里 pg-meta 的实际 DNS 目标由 pg_dns_target 决定:默认 auto 在启用 L2 VIP 时指向 VIP,否则指向清单中的主实例 IP。默认配置并不启用 VIP,详见 服务接入


服务实现

在 Pigsty 中,服务使用 节点 上的 haproxy 来实现,通过主机节点上的不同端口进行区分。

Pigsty 所纳管的每个节点上都默认启用了 Haproxy 以对外暴露服务,而数据库节点也不例外。 集群中的节点尽管从数据库的视角来看有主从之分,但从服务的视角来看,每个节点都是相同的: 这意味着即使您访问的是从库节点,只要使用正确的服务端口,就依然可以使用到主库读写的服务。 这样的设计可以屏蔽复杂度:所以您只要可以访问 PostgreSQL 集群上的任意一个实例,就可以完整的访问到所有服务。

这样的设计类似于 Kubernetes 中的 NodePort 服务,同样在 Pigsty 中,每一个服务都包括以下两个核心要素:

  1. 通过 NodePort 暴露的访问端点(端口号,从哪访问?)
  2. 通过 Selectors 选择的目标实例(实例列表,谁来承载?)

Pigsty 的服务交付边界止步于集群的 HAProxy,用户可以用各种手段访问这些负载均衡器,请参考 接入服务

所有的服务都通过配置文件进行声明,例如,PostgreSQL 默认服务就是由 pg_default_services 参数所定义的:

pg_default_services:
- { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
- { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
- { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
- { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}

您也可以在 pg_services 中定义额外的服务,参数 pg_default_servicespg_services 都是由 服务定义 对象组成的数组。


定义服务

Pigsty 允许您定义自己的服务:

  • pg_default_services:所有 PostgreSQL 集群统一对外暴露的服务,默认有四个。
  • pg_services:额外的 PostgreSQL 服务,可以视需求在全局或集群级别定义。
  • haproxy_services:直接定制 HAProxy 服务内容,可以用于其他组件的接入

对于 PostgreSQL 集群来说,通常只需要关注前两者即可。 每一条服务定义都会在所有相关 HAProxy 实例的配置目录下生成一个新的配置文件:/etc/haproxy/conf.d/<pg_cluster>-<service>.cfg 下面是一个自定义的服务样例 standby:当您想要对外提供没有复制延迟的只读服务时,就可以在 pg_services 新增这条记录:

- name: standby                   # 必选,服务名称,最终的 svc 名称会使用 `pg_cluster` 作为前缀,例如:pg-meta-standby
  port: 5435                      # 必选,暴露的服务端口(作为 kubernetes 服务节点端口模式)
  ip: "*"                         # 可选,服务绑定的 IP 地址,默认情况下为所有 IP 地址
  selector: "[]"                  # 必选,服务成员选择器,使用 JMESPath 来筛选配置清单
  backup: "[? pg_role == `primary`]"  # 可选,服务成员选择器(备份),也就是当默认选择器选中的实例都宕机后,服务才会由这里选中的实例成员来承载
  dest: default                   # 可选,目标端口,default|postgres|pgbouncer|<port_number>,默认为 'default',即由 pg_default_service_dest 决定
  check: /sync                    # 可选,健康检查 URL 路径,默认为 /,这里使用 Patroni API:/sync ,只有同步备库和主库才会返回 200 健康状态码 
  maxconn: 5000                   # 可选,允许的前端连接最大数,默认为5000
  balance: roundrobin             # 可选,haproxy 负载均衡算法(默认为 roundrobin,其他选项: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-test 上将会被转换为 HAProxy 配置文件 /etc/haproxy/conf.d/pg-test-standby.cfg

#---------------------------------------------------------------------
# service: pg-test-standby @ 10.10.10.11:5435
#---------------------------------------------------------------------
# service instances 10.10.10.11, 10.10.10.13, 10.10.10.12
# service backups   10.10.10.11
listen pg-test-standby
    bind *:5435            # <--- 绑定了所有IP地址上的 5435 端口
    mode tcp               # <--- 负载均衡器工作在 TCP 协议上
    maxconn 5000           # <--- 最大连接数为 5000,可按需调大
    balance roundrobin     # <--- 负载均衡算法为 rr 轮询,还可以使用 leastconn 
    option httpchk         # <--- 启用 HTTP 健康检查
    option http-keep-alive # <--- 保持HTTP连接
    http-check send meth OPTIONS uri /sync   # <---- 这里使用 /sync ,Patroni 健康检查 API ,只有同步备库和主库才会返回 200 健康状态码。 
    http-check expect status 200             # <---- 健康检查返回代码 200 代表正常
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers: # pg-test 集群全部三个实例都被 selector: "[]" 圈中,成为 pg-test-standby 服务的后端;/sync 健康检查只放行主库和同步备库。
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100 backup  # <----- 唯独主库满足条件 pg_role == `primary`, 被 backup selector 选中。
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100         #        因此作为服务的兜底实例:平时不承载请求,其他从库全部宕机后,才会承载只读请求,从而最大避免了读写服务受到只读服务的影响
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100         #        

在这里,pg-test 集群全部三个实例都被 selector: "[]" 给圈中了,渲染进入 pg-test-standby 服务的后端服务器列表中。但是因为还有 /sync 健康检查,Patroni Rest API 只有在主库和 同步备库 上才会返回代表健康的 HTTP 200 状态码,因此只有主库和同步备库才能真正承载请求。 此外,主库因为满足条件 pg_role == primary, 被 backup selector 选中,被标记为了备份服务器,只有当没有其他实例(也就是同步备库)可以满足需求时,才会顶上。


Primary服务

Primary 服务可能是生产环境中最关键的服务,它在 5433 端口提供对数据库集群的读写能力,服务定义如下:

- { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
  • 选择器参数 selector: "[]" 意味着所有集群成员都将被包括在 Primary 服务中
  • 但只有主库能够通过健康检查(check: /primary),实际承载 Primary 服务的流量。
  • 目的地参数 dest: default 意味着 Primary 服务的目的地受到 pg_default_service_dest 参数的影响
  • dest 默认值 default 会被替换为 pg_default_service_dest 的值,默认为 pgbouncer
  • 默认情况下 Primary 服务的目的地默认是主库上的连接池,也就是由 pgbouncer_port 指定的端口,默认为 6432

如果 pg_default_service_dest 的值为 postgres,那么 primary 服务的目的地就会绕过连接池,直接使用 PostgreSQL 数据库的端口(pg_port,默认值 5432),对于一些不希望使用连接池的场景,这个参数非常实用。

示例:pg-test-primary 的 haproxy 配置
listen pg-test-primary
    bind *:5433         # <--- primary 服务默认使用 5433 端口
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /primary # <--- primary 服务默认使用 Patroni RestAPI /primary 健康检查
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100

Patroni 的 高可用 机制确保任何时候最多只会有一个实例的 /primary 健康检查为真,因此 Primary 服务将始终将流量路由到主实例。

使用 Primary 服务而不是直连数据库的一个好处是,如果集群因为某种情况出现了双主(比如在没有 watchdog 的情况下 kill -9杀死主库 Patroni),Haproxy 在这种情况下仍然可以避免脑裂,因为它只会在 Patroni 存活且返回主库状态时才会分发流量。


Replica服务

Replica 服务在生产环境中的重要性仅次于 Primary 服务,它在 5434 端口提供对数据库集群的只读能力,服务定义如下:

- { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
  • 选择器参数 selector: "[]" 意味着所有集群成员都将被包括在 Replica 服务中
  • 所有实例都能够通过健康检查(check: /read-only),承载 Replica 服务的流量。
  • 备份选择器:[? pg_role == 'primary' || pg_role == 'offline' ] 将主库和 离线从库 标注为备份服务器。
  • 只有当所有 普通从库 都宕机后,Replica 服务才会由主库或离线从库来承载。
  • 目的地参数 dest: default 意味着 Replica 服务的目的地也受到 pg_default_service_dest 参数的影响
  • dest 默认值 default 会被替换为 pg_default_service_dest 的值,默认为 pgbouncer,这一点和 Primary服务 相同
  • 默认情况下 Replica 服务的目的地默认是从库上的连接池,也就是由 pgbouncer_port 指定的端口,默认为 6432
示例:pg-test-replica 的 haproxy 配置
listen pg-test-replica
    bind *:5434
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /read-only
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100 backup
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100

Replica 服务非常灵活:如果有存活的专用 Replica 实例,那么它会优先使用这些实例来承载只读请求,只有当从库实例全部宕机后,才会由主库来兜底只读请求。对于常见的一主一从双节点集群就是:只要从库活着就用从库,从库挂了再用主库。

此外,除非专用只读实例全部宕机,Replica 服务也不会使用专用 Offline 实例,这样就避免了在线快查询与离线慢查询混在一起,相互影响。


Default服务

Default 服务在 5436 端口上提供服务,它是 Primary 服务的变体。

Default 服务总是绕过连接池直接连到主库上的 PostgreSQL,这对于管理连接、ETL 写入、CDC 数据变更捕获等都很有用。

- { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }

如果 pg_default_service_dest 被修改为 postgres,那么可以说 Default 服务除了端口和名称内容之外,与 Primary 服务是完全等价的。在这种情况下,您可以考虑将 Default 从默认服务中剔除。

示例:pg-test-default 的 haproxy 配置
listen pg-test-default
    bind *:5436         # <--- 除了监听端口/目标端口和服务名,其他配置和 primary 服务一模一样
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /primary
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:5432 check port 8008 weight 100
    server pg-test-3 10.10.10.13:5432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:5432 check port 8008 weight 100

Offline服务

Offline 服务在 5438 端口上提供服务,它绕开连接池直接访问 PostgreSQL 数据库,通常用于慢查询/分析查询/ETL 读取/个人用户交互式查询,其服务定义如下:

- { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}

Offline 服务将流量直接路由到专用的 离线从库 上,或者带有 pg_offline_query 标记的普通 只读实例

  • 选择器参数从集群中筛选出了两种实例:pg_role = offline 的离线从库,或是带有 pg_offline_query = true 标记的普通 只读实例
  • 专用离线从库和打标记的普通从库主要的区别在于:前者默认不承载 Replica服务 的请求,避免快慢请求混在一起,而后者默认会承载。
  • 备份选择器参数从集群中筛选出了一种实例:不带 offline 标记的普通从库,这意味着如果离线实例或者带 Offline 标记的普通从库挂了之后,其他普通的从库可以用来承载 Offline 服务。
  • 健康检查 /replica 只会针对从库返回 200, 主库会返回错误,因此 Offline 服务 永远不会将流量分发到主库实例上去,哪怕集群中只剩这一台主库。
  • 同时,主库实例既不会被选择器圈中,也不会被备份选择器圈中,因此它永远不会承载 Offline 服务。因此 Offline 服务总是可以避免用户访问主库,从而避免对主库的影响。
示例:pg-test-offline 的 haproxy 配置
listen pg-test-offline
    bind *:5438
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /replica
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-3 10.10.10.13:5432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:5432 check port 8008 weight 100 backup

Offline 服务提供受限的只读服务,通常用于两类查询:交互式查询(个人用户),慢查询长事务(分析/ETL)。

Offline 服务需要额外的维护照顾:HAProxy 的 /replica 健康检查会在主从切换后自动拒绝新主库,但 selector 使用的是配置清单中的静态 pg_role / pg_offline_query 标签。对于一主一从、仅从库承载 Offline 查询的精简集群,切换后可能暂时没有合格后端。 仅重载未修改的清单并不会把原主库加入 Offline 后端。需要先按新的规划调整清单标签(或 pg_offline_query)再 重载服务,或者将主库切回原节点。

如果您的业务模型较为简单,您可以考虑剔除 Default 服务与 Offline 服务,使用 Primary 服务与 Replica 服务直连数据库。


重载服务

当集群成员发生变化(添加/删除副本)、服务定义或静态选择标签变化、相对权重调整时,需要 重载服务。Primary/Replica 服务的正常主备切换由 Patroni 健康检查自动接管,不需要为此单独重载。

bin/pgsql-svc <cls> [ip...]         # 为 lb 集群或 lb 实例重载服务
# ./pgsql.yml -t pg_service         # 重载服务的实际 ansible 任务

接入服务

Pigsty 的服务交付边界止步于集群的 HAProxy,用户可以用各种手段访问这些负载均衡器。

典型的做法是使用 DNS 或 VIP 接入,将其绑定在集群所有或任意数量的负载均衡器上。

pigsty-access.jpg

你可以使用不同的 主机 & 端口 组合,它们以不同的方式提供 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

组合

# 通过集群域名访问(以下示例假定已启用 L2 VIP;未启用时默认指向清单主实例 IP)
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://[email protected]:5432/test # L2 VIP -> 主直接访问
postgres://[email protected]:6432/test # L2 VIP -> 主连接池 -> 主
postgres://[email protected]:5433/test # L2 VIP -> HAProxy -> 主连接池 -> 主
postgres://[email protected]:5434/test # L2 VIP -> HAProxy -> 备份连接池 -> 备份
postgres://[email protected]:5436/test # L2 VIP -> HAProxy -> 主直接连接 (用于管理员)
postgres://[email protected]: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://[email protected]:5432/test # 数据库实例直接连接 (直接指定实例, 没有自动流量分配)
postgres://[email protected]:6432/test # 连接池 -> 数据库
postgres://[email protected]:5433/test # HAProxy -> 连接池 -> 数据库读/写
postgres://[email protected]:5434/test # HAProxy -> 连接池 -> 数据库只读
postgres://[email protected]:5436/test # HAProxy -> 数据库直接连接
postgres://[email protected]:5438/test # HAProxy -> 数据库离线读/写

# 智能客户端:自动进行读写分离
postgres://[email protected]:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=primary
postgres://[email protected]:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=prefer-standby

覆盖服务

你可以通过多种方式覆盖默认的服务配置,一种常见的需求是让 Primary服务Replica服务 绕过 Pgbouncer 连接池,直接访问 PostgreSQL 数据库。

为了实现这一点,你可以将 pg_default_service_dest 更改为 postgres,这样所有服务定义中 svc.dest='default' 的服务都会使用 postgres 而不是默认的 pgbouncer 作为目标。

如果您已经将 Primary服务 指向了 PostgreSQL,那么 default服务 就会比较多余,可以考虑移除。

如果您不需要区分个人交互式查询,分析/ETL 慢查询,可以考虑从默认服务列表 pg_default_services 中移除 Offline服务

如果您不需要只读从库来分担在线只读流量,也可以从默认服务列表中移除 Replica服务


委托服务

Pigsty 通过节点上的 haproxy 暴露 PostgreSQL 服务。整个集群中的所有 haproxy 实例都使用相同的 服务定义 进行配置。

但是,你可以将 pg 服务委托给特定的节点分组(例如,专门的 haproxy 负载均衡器集群),而不是 PostgreSQL 集群成员上的 haproxy。

为此,你需要使用 pg_default_services 覆盖默认的服务定义,并将 pg_service_provider 设置为代理组名称。

例如,此配置将在端口 10013 的 proxy haproxy 节点组上公开 pg 集群的主服务。

pg_service_provider: proxy       # 使用端口 10013 上的 `proxy` 组的负载均衡器
pg_default_services:  [{ name: primary ,port: 10013 ,dest: postgres  ,check: /primary   ,selector: "[]" }]

用户需要确保每个委托服务的端口,在代理集群中都是 唯一 的。

在 20 节点生产环境仿真 沙箱 中提供了一个使用专用负载均衡器集群的例子:conf/ha/simu.yml

8.3 - PostgreSQL 安全

PostgreSQL 身份认证、访问控制、加密通信、数据保护与安全运维入口。

PostgreSQL 安全由身份认证、权限控制、网络边界、加密通信、数据保护和运维流程共同构成。Pigsty 提供这些机制的配置入口,但部署方仍需根据环境完成加固、验证和持续审计。


概念与边界

主题 内容
安全与合规 默认状态、能力边界与加固路径
身份认证 HBA、SCRAM、证书认证与凭据管理
访问控制 内置角色、默认权限、数据库 ACL 与实例访问边界
加密通信 CA、TLS、服务端身份验证与证书轮换
数据安全 页校验和、复制、备份、PITR、审计与日志
合规实践 上线检查、控制映射与证据要求

配置参考

  • HBA 配置:声明 PostgreSQL 与 PgBouncer 的认证规则。
  • 访问控制配置:配置默认角色、业务用户、对象权限与数据库 ACL。
  • 用户配置:定义用户属性、角色成员关系和连接池选项。
  • CRIT 参数模板:同步复制、校验和、日志与 watchdog 等关键参数。

管理与验证

  • 用户管理:创建、更新和删除用户。
  • HBA 管理:刷新规则、检查生效配置并排查认证问题。
  • 安全考量:生产部署的加固与验收清单。
  • 安全建议:安装前最基本的密码、网络和文件检查。

配置清单描述期望状态。验收时还应检查运行节点上的 HBA、证书、监听端口和敏感文件,并通过 PostgreSQL 系统目录核对实际角色与权限。

8.4 - 日常管理

数据库日常管理任务标准操作指南(SOP)

8.4.1 - 管理 PostgreSQL 数据库集群

创建/销毁 PostgreSQL 集群,以及对现有集群进行扩容,缩容,克隆集群。

速查手册

操作 快捷命令 说明
创建集群 bin/pgsql-add <cls> 创建新的 PostgreSQL 集群
扩容集群 bin/pgsql-add <cls> <ip...> 为现有集群添加从库副本
缩容集群 bin/pgsql-rm <cls> <ip...> 从集群中移除指定实例
销毁集群 bin/pgsql-rm <cls> 销毁整个 PostgreSQL 集群
刷新服务 bin/pgsql-svc <cls> [ip...] 重载集群的负载均衡配置
刷新HBA bin/pgsql-hba <cls> [ip...] 重载集群的 HBA 访问规则
克隆集群 - 通过备份集群或 PITR 克隆

其他管理任务,请参考:高可用管理管理用户管理数据库


创建集群

要创建一个新的 PostgreSQL 集群,请首先在 配置清单定义集群,然后 纳管节点 并进行初始化:

脚本
bin/node-add  <cls>     # 添加分组 <cls> 下的节点
剧本
./node.yml  -l <cls>    # 直接使用 Ansible 剧本添加分组 <cls> 下的节点
示例
bin/node-add pg-test    # 例子,添加 pg-test 分组下的节点,实际执行 ./node.yml -l pg-test

在被纳管的节点上,可以使用以下命令创建集群:(针对 <cls> 分组执行 pgsql.yml 剧本)

脚本
bin/pgsql-add <cls>     # 创建 PostgreSQL 集群 <cls>
剧本
./pgsql.yml -l <cls>    # 直接使用 Ansible 剧本创建 PostgreSQL 集群 <cls>
示例
bin/pgsql-add pg-test   # 例子,创建 pg-test 集群

示例:创建三节点 PG 集群 pg-test

demo/pgsql.cast
针对已经存在的集群重新执行创建存在风险

如果您在已经存在的集群上重新执行创建操作,Pigsty 不会移除已有的数据文件,但现有服务配置会被覆盖,集群会发生 重启! 此外,如果你在 数据库定义 中指定了 baseline SQL,它也会重新执行,如果里面包含删除/覆盖逻辑,可能会导致 数据丢失


扩容集群

若要将新从库添加到 现有的 PostgreSQL 集群 中,您需要将 实例定义 添加到 配置清单all.children.<cls>.hosts 中。

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 }

扩容集群的操作与 创建集群 非常类似,首先需要将扩容的节点纳入 Pigsty 管理:添加节点

脚本
bin/node-add <ip>       # 添加 IP 地址为 <ip> 的节点
剧本
./node.yml -l <ip>      # 直接使用 Ansible 剧本添加 <ip> 对应的节点
示例
bin/node-add 10.10.10.13    # 例子,添加 IP 为 10.10.10.13 的节点,实际执行 ./node.yml -l 10.10.10.13

然后在新节点上运行以下命令以扩容集群(针对新节点安装 PGSQL 模块,使用与现有集群相同的 pg_cluster

脚本
bin/pgsql-add <cls> <ip>  # 添加 IP 地址为 <ip> 的节点
剧本
./pgsql.yml -l <ip>       # 核心逻辑:使用 Ansible 剧本在 <ip> 节点上安装 PGSQL 模块
示例
bin/pgsql-add pg-test 10.10.10.13   # 示例,为 pg-test 集群扩容 IP 为 10.10.10.13 的节点

扩容完成后,您应当 刷新服务 以将新成员添加至负载均衡器中以实际承载流量。

示例:为两节点集群 pg-test 扩容一个新从库 10.10.10.13

demo/pgsql-append.cast

缩容集群

若要从 现有的 PostgreSQL 集群 中移除副本,您需要从 配置清单all.children.<cls>.hosts 中移除对应的 实例定义

缩容会停止实例并默认删除其数据目录。操作前先执行 pig pg list <cls>pig pb info,确认目标不是主库、存在近期可恢复备份, 并让操作者输入精确的 <ip>,确认后方可实际执行。

缩容集群首先需要卸载目标节点上的 PGSQL 模块(针对 <ip> 执行 pgsql-rm.yml 剧本):

脚本
bin/pgsql-rm <cls> <ip>   # 从集群 <cls> 中移除 <ip> 节点上的 PostgreSQL 实例
剧本
./pgsql-rm.yml -l <ip>    # 直接使用 Ansible 剧本移除 <ip> 节点上的 PostgreSQL 实例
示例
bin/pgsql-rm pg-test 10.10.10.13  # 例子,从 pg-test 集群移除 10.10.10.13 节点

移除 PGSQL 模块后,您可以选择将节点从 Pigsty 管理中移除:移除节点(可选):

脚本
bin/node-rm <ip>          # 从 Pigsty 管理中移除 <ip> 节点
剧本
./node-rm.yml -l <ip>     # 直接使用 Ansible 剧本从 Pigsty 管理中移除 <ip> 节点
示例
bin/node-rm 10.10.10.13   # 例子,从 Pigsty 管理中移除 10.10.10.13 节点

缩容完成后,您应当从 配置清单 中移除该实例的定义,然后 刷新服务 以将它从负载均衡器中踢除。

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 }

示例:从三节点集群 pg-test 中缩容一个从库 10.10.10.13

demo/pgsql-shrink.cast

销毁集群

销毁集群需要在集群的所有节点上卸载 PGSQL 模块(针对 <cls> 执行 pgsql-rm.yml 剧本):

这是不可逆的数据删除:先用 pig pg list <cls>pig pb info 核对状态和近期备份,决定是否保留独立备份副本, 并要求操作者输入精确集群名。下面命令会直接执行相应的销毁操作。

脚本
bin/pgsql-rm <cls>        # 销毁整个 PostgreSQL 集群 <cls>
剧本
./pgsql-rm.yml -l <cls>   # 直接使用 Ansible 剧本销毁整个 PostgreSQL 集群 <cls>
示例
bin/pgsql-rm pg-test      # 例子,销毁 pg-test 集群

销毁 PGSQL 模块后,您可以选择将节点一并从 Pigsty 管理中移除:移除节点(可选,如果还有其他服务可以保留):

脚本
bin/node-rm <cls>         # 从 Pigsty 管理中移除 <cls> 分组下的所有节点
剧本
./node-rm.yml -l <cls>    # 直接使用 Ansible 剧本从 Pigsty 管理中移除 <cls> 分组下的所有节点
示例
bin/node-rm pg-test       # 例子,从 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 }

示例:销毁三节点 PG 集群 pg-test

demo/pgsql-rm.cast

注意:如果为这个集群配置了 pg_safeguard(或全局设置为 true),pgsql-rm.yml 将中止执行,以避免意外销毁集群。 您可以使用剧本命令行参数明确地覆盖它,以强制执行销毁。 此外默认情况下,集群的备份仓库将同集群一并删除。如果你希望保留备份(例如在使用集中式备份仓库时),可以设置 pg_rm_backup=false 参数:

./pgsql-rm.yml -l pg-meta -e pg_safeguard=false    # 强制销毁受保护的 pg 集群 pg-meta
./pgsql-rm.yml -l pg-meta -e pg_rm_backup=false    # 在销毁集群过程中保留其备份仓库

刷新服务

PostgreSQL 集群通过主机节点上的 HAProxy 对外提供 服务。 当服务定义变化、实例权重变化,或者集群成员发生变化时(例如集群 扩容 / 缩容),您需要刷新服务以更新负载均衡器的静态成员配置。默认 Primary/Replica 服务通过 Patroni REST API 健康检查识别当前角色,正常的主从切换或故障转移会自动改道,不要求重新生成 HAProxy 配置。

要在整个集群或特定实例上刷新服务配置(针对 <cls><ip> 执行 pgsql.ymlpg_service 子任务):

脚本
bin/pgsql-svc <cls>           # 刷新整个集群 <cls> 的服务配置
bin/pgsql-svc <cls> <ip...>   # 刷新集群 <cls> 中指定实例的服务配置
剧本
./pgsql.yml -l <cls> -t pg_service -e pg_reload=true        # 刷新整个集群的服务配置
./pgsql.yml -l <ip>  -t pg_service -e pg_reload=true        # 刷新指定实例的服务配置
示例
bin/pgsql-svc pg-test                 # 例子,刷新 pg-test 集群的服务配置
bin/pgsql-svc pg-test 10.10.10.13     # 例子,刷新 pg-test 集群中 10.10.10.13 实例的服务配置

备注:如果您使用集中式的专用负载均衡集群(pg_service_provider),那么只有刷新集群主库时才会更新负载均衡配置。

示例:刷新集群 pg-test 的服务配置

demo/pgsql-svc.cast
示例:重载 PG 服务以踢除一个实例

asciicast


刷新HBA

当您修改了 HBA 相关配置后,需要刷新 HBA 规则以应用更改。(pg_hba_rules / pgb_hba_rules) 如果您有任何特定于清单角色的 HBA 规则,或者在 IP 地址段中引用了集群成员的别名,那么修改 pg_role 标签或集群扩缩容后也可能需要刷新 HBA。这里的角色筛选使用静态清单变量,不会随 Patroni 主从切换自动改变。

要在整个集群或特定实例上刷新 PG 和 Pgbouncer 的 HBA 规则(针对 <cls><ip> 执行 pgsql.yml 的 HBA 相关子任务):

脚本
bin/pgsql-hba <cls>           # 刷新整个集群 <cls> 的 HBA 规则
bin/pgsql-hba <cls> <ip...>   # 刷新集群 <cls> 中指定实例的 HBA 规则
剧本
./pgsql.yml -l <cls> -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload -e pg_reload=true   # 刷新整个集群
./pgsql.yml -l <ip>  -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload -e pg_reload=true   # 刷新指定实例
示例
bin/pgsql-hba pg-test                 # 例子,刷新 pg-test 集群的 HBA 规则
bin/pgsql-hba pg-test 10.10.10.13     # 例子,刷新 pg-test 集群中 10.10.10.13 实例的 HBA 规则

示例:刷新集群 pg-test 的 HBA 规则

demo/pgsql-hba.cast

配置集群

PostgreSQL 的配置参数由 Patroni 管理,初始参数由 Patroni 配置模板 指定。 集群初始化之后,配置存储在 Etcd 中,并由 Patroni 进行动态管理,并在集群中同步与共享。 Patroni 本身的 配置参数 大部分可以通过 patronictl 命令行工具修改。 其余参数(例如,etcd DCS 配置,日志/RestAPI 等配置)则可以通过下面的子任务进行更新。例如,当 etcd 集群成员发生变动时,你可以刷新 Patroni 配置:

./pgsql.yml -l pg-test -t pg_conf                   # 更新 Patroni 配置文件
ansible pg-test -b -a 'systemctl reload patroni'    # 重载 Patroni 服务

您可以在不同层次上覆盖 Patroni 集中管理的默认,例如单独 为实例指定配置参数; 单独为 为用户指定配置参数,或者 为数据库指定配置参数


克隆集群

有两种克隆集群的方式:使用 备份集群 功能,或者使用 时间点恢复 功能。 前者配置简单,无需备份仓库,但需要可达的复制上游,只能克隆指定集群的最新状态;后者依赖集中式的 备份仓库(例如 Silo),可以克隆到恢复窗口内的任意时间点。

方式 优点 缺点 适用场景
备份集群 无需备份仓库 需要可达上游,只能克隆最新状态 灾备,读写分离,迁移
PITR 可恢复到窗口内任意时点 依赖集中式备份仓库 误操作恢复,数据审计

使用备份集群克隆

备份集群(Standby Cluster)通过流复制从上游集群持续同步数据,是克隆集群最简单的方式。 只需在新集群主库上指定 pg_upstream 参数,即可自动从上游集群拉取数据。

# pg-test 是原始集群
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars: { pg_cluster: pg-test }

# pg-test2 是 pg-test 的备份集群(克隆)
pg-test2:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary, pg_upstream: 10.10.10.11 }  # 指定上游
    10.10.10.13: { pg_seq: 2, pg_role: replica }
  vars: { pg_cluster: pg-test2 }

使用以下命令创建备份集群:

脚本
bin/pgsql-add pg-test2    # 创建备份集群,自动从上游 pg-test 克隆数据
剧本
./pgsql.yml -l pg-test2   # 直接使用 Ansible 剧本创建备份集群

备份集群会持续追随上游集群,保持数据同步。您可以随时将其 提升 为独立集群:

示例:提升备份集群为独立集群

通过 配置集群 擦除 standby_cluster 配置段,即可将备份集群提升为独立集群:

$ pg edit-config pg-test2
-standby_cluster:
-  create_replica_methods:
-  - basebackup
-  host: 10.10.10.11
-  port: 5432

Apply these changes? [y/N]: y

提升后,pg-test2 将成为可以独立承载写入请求的独立集群,与原集群 pg-test 分叉。

示例:更改复制上游

如果上游集群发生主从切换,您可以通过 配置集群 更改备份集群的复制上游:

$ pg edit-config pg-test2

 standby_cluster:
   create_replica_methods:
   - basebackup
-  host: 10.10.10.11     # <--- 旧的上游
+  host: 10.10.10.14     # <--- 新的上游
   port: 5432

Apply these changes? [y/N]: y

使用 PITR 克隆

时间点恢复(PITR)允许您将集群恢复到恢复窗口内的任意时间点。 此方式依赖集中式的 备份仓库(如 Silo/S3),但功能更加强大。

要使用 PITR 克隆集群,在配置中添加 pg_pitr 参数指定恢复目标:

# 从 pg-meta 集群的备份克隆一个新集群 pg-meta2
pg-meta2:
  hosts: { 10.10.10.12: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta2
    pg_pitr:
      cluster: pg-meta                    # 从 pg-meta 的备份恢复
      time: '2025-01-10 10:00:00+00'      # 恢复到指定时间点
      archive: false                       # 独立恢复阶段禁用归档
      action: promote                      # 完成重放后提升并启动集群

使用 pgsql-pitr.yml 剧本执行克隆:

剧本
./pgsql-pitr.yml -l pg-meta2    # 使用上面显式声明的 action: promote
命令行
# 也可以通过命令行参数指定 PITR 选项
./pgsql-pitr.yml -l pg-meta2 -e '{"pg_pitr": {"cluster": "pg-meta", "time": "2025-01-10 10:00:00+00", "archive": false, "action": "promote"}}'

PITR 支持多种恢复目标类型:

目标类型 参数示例 说明
时间点 time: "2025-01-10 10:00:00+00" 恢复到指定时间戳
事务 ID xid: "250000" 恢复到指定事务之前/之后
恢复点 name: "before_migration" 恢复到命名恢复点
LSN lsn: "0/4001C80" 恢复到指定 WAL 位置
最新 pg_pitr: {} 恢复到 WAL 归档末尾
PITR 恢复后处理

跨集群恢复完成后,按 克隆善后 处理归档与 stanza。

更多 PITR 的详细用法,请参考 恢复操作;跨集群恢复后的归档与 stanza 处理见 克隆数据库集群

8.4.2 - 管理 PostgreSQL 业务用户

用户管理:创建、修改、删除用户,管理角色成员关系,连接池用户配置

快速上手

Pigsty 使用声明式管理方式,首先在 配置清单定义用户,然后使用 bin/pgsql-user <cls> <username> 创建或修改用户。

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_users: [{ name: dbuser_app, password: 'DBUser.App', pgbouncer: true }]  # <--- 在这里定义用户列表!
脚本
bin/pgsql-user <cls> <username>    # 在 <cls> 集群上创建/修改 <username> 用户
剧本
./pgsql-user.yml -l pg-meta -e username=dbuser_app    # 直接使用剧本在 <cls> 集群上创建/修改 <username> 用户
示例
bin/pgsql-user pg-meta dbuser_app    # 在 pg-meta 集群上创建/修改 dbuser_app 用户

关于用户定义参数的完整参考,请查阅 用户配置。角色与权限模型参见 访问控制,认证与凭据管理参见 身份认证

namepgsql-user.yml 查找用户定义的键,剧本不会执行角色重命名。需要更名时,应先创建新角色,迁移所有权、成员关系与客户端凭据,完成切换和验证后再删除旧角色;不要把“删除后重建”当作无损的重命名操作。

操作 快捷命令 说明
创建用户 bin/pgsql-user <cls> <user> 创建新的业务用户或角色
修改用户 bin/pgsql-user <cls> <user> 修改已存在用户的属性
删除用户 bin/pgsql-user <cls> <user> 依赖感知的破坏性删除(需设置 state: absent
demo/pgsql-user.cast

创建用户

定义在 pg_users 里面的用户会在 PostgreSQL 集群创建 的时候在 pg_user 任务中自动创建。

要在现有的 PostgreSQL 集群上创建新的业务用户,请将 用户定义 添加到 all.children.<cls>.pg_users,然后执行:

脚本
bin/pgsql-user <cls> <username>   # 创建用户 <username>
剧本
./pgsql-user.yml -l <cls> -e username=<username>   # 直接使用 Ansible 剧本创建用户
示例
bin/pgsql-user pg-meta dbuser_app    # 例子,在 pg-meta 集群中创建 dbuser_app 用户

示例配置:创建名为 dbuser_app 的业务用户

#all.children.pg-meta.vars.pg_users: # 省略上级缩进
  - name: dbuser_app
    password: DBUser.App
    pgbouncer: true
    roles: [dbrole_readwrite]
    comment: application user for myapp

执行效果:在主库上创建用户 dbuser_app,设置密码,授予 dbrole_readwrite 角色权限, 将用户添加到 Pgbouncer 连接池,在每个实例上重载 Pgbouncer 配置使其立即生效。

建议使用剧本创建用户

如果您需要手工创建用户,那么需要自行确保 Pgbouncer 连接池用户列表同步。


修改用户

修改用户与创建用户使用相同的命令,剧本是幂等的。当目标用户已存在时,Pigsty 会修改目标用户的属性使其符合配置。

脚本
bin/pgsql-user <cls> <user>   # 修改用户 <user> 的属性
剧本
./pgsql-user.yml -l <cls> -e username=<user>   # 幂等操作,可重复执行
示例
bin/pgsql-user pg-meta dbuser_app    # 修改 dbuser_app 用户的属性使其符合配置

不可直接修改的属性:用户的 name 是声明式定义的身份键,剧本不会把一个现有角色重命名为另一个角色。应按“创建新角色 → 迁移所有权/权限与客户端 → 验证 → 删除旧角色”的顺序完成更名。

其他属性均可修改,以下是一些常见的修改示例:

修改密码:更新配置中的 password 字段后执行剧本。密码修改时会临时禁用日志记录,避免密码泄露到日志中。

- name: dbuser_app
  password: NewSecretPassword     # 修改密码

修改权限属性:通过配置相应的布尔标志来修改用户权限。

- name: dbuser_app
  superuser: false           # 超级用户(谨慎使用!)
  createdb: true             # 允许创建数据库
  createrole: false          # 允许创建角色
  inherit: true              # 自动继承角色权限
  replication: false         # 允许流复制连接
  bypassrls: false           # 绕过行级安全策略
  connlimit: 50              # 限制连接数,-1 不限制

修改用户有效期:使用 expire_in 设置相对过期时间(N 天后过期),或 expire_at 设置绝对过期日期。expire_in 优先级更高,每次执行剧本时会重新计算,适合需要定期续期的临时用户。

- name: temp_user
  expire_in: 30                   # 30 天后过期(相对时间)

- name: contractor_user
  expire_at: '2024-12-31'         # 指定日期过期(绝对时间)

- name: permanent_user
  expire_at: 'infinity'           # 永不过期

修改角色成员关系:通过 roles 数组配置角色成员关系,支持简单格式和扩展格式。角色成员关系是增量操作,不会移除未声明的现有角色。使用 state: absent 可以显式撤销角色。

- name: dbuser_app
  roles:
    - dbrole_readwrite                      # 简单形式:授予角色
    - { name: dbrole_admin, admin: true }   # 带 ADMIN OPTION(可以将此角色授予其他用户)
    - { name: pg_monitor, set: false }      # PG16+: 不允许 SET ROLE
    - { name: old_role, state: absent }     # 撤销角色成员关系

管理用户参数:通过 parameters 字典配置用户级参数,会生成 ALTER USER ... SET 语句。使用特殊值 DEFAULT 可将参数重置为 PostgreSQL 默认值。

- name: dbuser_analyst
  parameters:
    work_mem: '256MB'
    statement_timeout: '5min'
    search_path: 'analytics,public'
    log_statement: DEFAULT        # 重置为默认值

连接池配置:设置 pgbouncer: true 将用户添加到连接池,可选配置 pool_mode(池化模式:transaction/session/statement)和 pool_connlimit(用户最大连接数)。

- name: dbuser_app
  pgbouncer: true                 # 添加到连接池
  pool_mode: transaction          # 池化模式
  pool_connlimit: 50              # 用户最大连接数

删除用户

删除用户会终止连接、转移对象所有权、撤销授权并执行 DROP ROLE,属于不可逆操作。先确认精确的集群名、用户名、继任所有者与近期备份,再将目标用户的 state 设置为 absent 并执行实际变更。

脚本
bin/pgsql-user <cls> <user>   # 确认后实际删除;配置中必须为 state: absent
剧本
./pgsql-user.yml -l <cls> -e username=<user>   # 直接使用 Ansible 剧本删除用户
示例
bin/pgsql-user pg-meta dbuser_old    # 删除 dbuser_old 用户(配置中已设置 state: absent)

配置示例

pg_users:
  - name: dbuser_old
    state: absent

删除操作会:在主库调用 pg-drop-role <user> postgres --force,先禁用登录并终止活跃连接,将数据库、表空间以及每个可连接数据库中的对象所有权转移给 postgres,执行 DROP OWNED 清理授权,撤销角色成员关系,最后执行 DROP ROLE。脚本在 /tmp/pg_drop_role_<user>_<timestamp>.log 保存执行前的审计快照。

保护机制:Ansible 任务会跳过 postgres 以及清单中配置的复制、管理和监控用户。直接运行 pg-drop-role 时,脚本只硬编码保护默认名称 postgresreplicatordbuser_dbadbuser_monitor;如果改过系统用户名,直接脚本不会自动识别它们,必须额外谨慎。

依赖感知,但不是事务性删除

pg-drop-role 会在 REASSIGN OWNED 失败时跳过对应数据库的 DROP OWNED,但整个跨数据库流程不是一个事务;中途失败可能留下 NOLOGIN、已转移的部分对象或残余依赖。v4.5 的 Ansible 删除任务还使用 ignore_errors,因此剧本最终状态不能代替核验。执行后必须确认角色已消失、继任所有权正确、应用已切换,并检查审计日志。

v4.5 的 pgsql-user.yml 会重载 Pgbouncer,但不会可靠地从 /etc/pgbouncer/userlist.txt 清除已删除角色。删除后应在每个集群实例检查:

sudo -iu postgres psql -AXtwc "SELECT 1 FROM pg_roles WHERE rolname = 'dbuser_old';"
grep -n '^"dbuser_old"[[:space:]]' /etc/pgbouncer/userlist.txt

若仍有精确匹配的 Pgbouncer 条目,应在受控变更中移除该行、重载 Pgbouncer 并验证应用连接;不要用模糊匹配批量删除。


手工删除用户

如果需要手动删除用户,可以直接使用 pg-drop-role 脚本:

# 检查依赖关系(只读操作)
pg-drop-role dbuser_old --check

# 预览删除操作(不实际执行)
pg-drop-role dbuser_old --dry-run -v

# 确认近期备份、精确用户名与继任所有者后,才执行实际删除
pg-drop-role dbuser_old dbuser_new

# 仅当已明确同意终止连接时使用 --force
pg-drop-role dbuser_old dbuser_new --force

常见用例

下面是一些常见的用户配置示例:

创建基本业务用户

- name: dbuser_app
  password: DBUser.App
  pgbouncer: true
  roles: [dbrole_readwrite]
  comment: application user

创建只读用户

- name: dbuser_readonly
  password: DBUser.Readonly
  pgbouncer: true
  roles: [dbrole_readonly]

创建管理员用户(可执行 DDL)

- name: dbuser_admin
  password: DBUser.Admin
  pgbouncer: true
  pool_mode: session
  roles: [dbrole_admin]
  parameters:
    log_statement: 'all'

创建临时用户(30天后过期)

- name: temp_contractor
  password: TempPassword
  expire_in: 30
  roles: [dbrole_readonly]

创建角色(不可登录,用于权限分组)

- name: custom_role
  login: false
  comment: custom role for special permissions

创建带高级角色选项的用户(PG16+)

- name: dbuser_special
  password: DBUser.Special
  pgbouncer: true
  roles:
    - dbrole_readwrite
    - { name: dbrole_admin, admin: true }
    - { name: pg_monitor, set: false }
    - { name: pg_execute_server_program, inherit: false }

查询用户

以下是一些常用的 SQL 查询,用于查看用户信息:

查看所有用户

SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb,
       rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolvaliduntil
FROM pg_roles WHERE rolname NOT LIKE 'pg_%' ORDER BY rolname;

查看用户的角色成员关系

SELECT r.rolname AS member, g.rolname AS role, m.admin_option, m.set_option, m.inherit_option
FROM pg_auth_members m
JOIN pg_roles r ON r.oid = m.member
JOIN pg_roles g ON g.oid = m.roleid
WHERE r.rolname = 'dbuser_app';

查看用户级参数设置

SELECT rolname, setconfig FROM pg_db_role_setting s
JOIN pg_roles r ON r.oid = s.setrole WHERE s.setdatabase = 0;

查看即将过期的用户

SELECT rolname, rolvaliduntil, rolvaliduntil - CURRENT_TIMESTAMP AS time_remaining
FROM pg_roles WHERE rolvaliduntil IS NOT NULL
  AND rolvaliduntil < CURRENT_TIMESTAMP + INTERVAL '30 days'
ORDER BY rolvaliduntil;

连接池管理

在用户定义中配置的 连接池参数 会在创建/修改用户时应用到 Pgbouncer 连接池中。

设置 pgbouncer: true 的用户会被添加到 /etc/pgbouncer/userlist.txt 文件中。用户级别的连接池参数(pool_modepool_connlimit)通过 /etc/pgbouncer/useropts.txt 文件配置。

您可以使用 postgres 操作系统用户,使用 pgb 别名访问 Pgbouncer 管理数据库。更多连接池管理操作,请参考 Pgbouncer 管理


管理默认用户密码

要修改普通用户的密码, 按照上面 修改用户 的说明,更新配置中的 password 字段并执行剧本即可。 不过修改 默认用户 的密码会稍微复杂一些,因为它们的密码还在多个地方被其他服务引用。

参数 默认值 对应用户 用途
pg_admin_password DBUser.DBA dbuser_dba 管理员用户密码
pg_monitor_password DBUser.Monitor dbuser_monitor 监控用户密码
pg_replication_password DBUser.Replicator replicator 复制用户密码

这三个账号属于 pg_default_roles,不在 pg_users 中。pgsql-user.yml 只查找 pg_users,因此不应通过命令行临时覆盖 pg_users 来轮换默认密码:这既会改变本次剧本看到的业务用户列表,也会把明文密码留在 shell 历史中。

使用以下通用顺序一次轮换一个账号:

  1. pigsty.yml(或实际使用的清单)中持久化新的密码参数,不要把明文密码写进命令行。
  2. 在当前主库上以超级用户打开交互式 psql,使用 \password <username> 修改数据库角色密码;该元命令会交互读取密码。
  3. 使用下面对应的刷新剧本,并核对 -l 限定的集群/节点。
  4. 保留当前管理会话,验证 PostgreSQL 直连、Pgbouncer、复制、Exporter 和 Grafana 数据源,再轮换下一个账号。
# 在目标集群当前主库上,交互修改数据库角色密码
sudo -iu postgres psql -d postgres
\password dbuser_dba       # 或 dbuser_monitor / replicator

随后按账号刷新所有消费者;下列命令中的 <cls>infra 必须替换/限定为实际目标:

# 管理员 dbuser_dba:PG 节点 .pgpass、Pgbouncer、Infra 管理端与 pgAdmin 文件
./pgsql.yml -l <cls> -t pg_pass,pgbouncer_user,pgbouncer_reload -e pg_reload=true
./infra.yml -l infra -t env_pgpass,env_pgscv,env_pgadmin

# 监控用户 dbuser_monitor:PG 节点 .pgpass、Pgbouncer、两个 Exporter 与 Grafana 数据源
./pgsql.yml -l <cls> -t pg_pass,pgbouncer_user,pgbouncer_reload,pg_exporter,pgbouncer_exporter,add_ds -e pg_reload=true
./infra.yml -l infra -t env_pgpass

# 复制用户 replicator:Patroni 配置、PG 节点 .pgpass 与 Infra .pgpass
./pgsql.yml -l <cls> -t pg_conf,pg_pass,patroni_reload -e pg_reload=true
./infra.yml -l infra -t env_pgpass

复制密码在数据库角色与所有 Patroni 节点之间不一致时,新建复制连接会失败,因此应安排维护窗口并快速完成验证。若部署了 VIBE 等会把管理员连接串写入工作区上下文的模块,还应按模块文档重新渲染对应文件。

检查 Infra .pgpass 重复项

v4.5 的 env_pgpass 使用 lineinfile 添加新记录,不会按用户名自动删除旧密码;libpq 又采用第一条匹配记录。刷新后应在每个目标 Infra 节点检查每个系统用户名是否只有一条匹配记录,并通过受控编辑删掉旧项(不要把密码打印到终端或日志):

awk -F: '$4=="dbuser_dba" || $4=="dbuser_monitor" || $4=="replicator" {print NR, $4}' ~/.pgpass

Patroni REST API 的 patroni_password 不是 PostgreSQL 角色密码。修改清单后,应分别刷新目标 PostgreSQL 集群和 Infra 管理端:

./pgsql.yml -l <cls> -t pg_conf,patroni_reload -e pg_reload=true
./infra.yml -l infra -t env_patroni

执行后用 patronictlpig pg list <cls> 验证认证与集群状态。

8.4.3 - 管理 PostgreSQL 业务数据库

数据库管理:创建、修改、删除、重建数据库,使用模板克隆数据库

快速上手

Pigsty 使用声明式管理方式,首先在 配置清单定义数据库,然后使用 bin/pgsql-db <cls> <dbname> 创建或修改数据库。

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_databases: [{ name: some_db }]  # <--- 在这里定义数据库列表!
脚本
bin/pgsql-db <cls> <dbname>    # 在 <cls> 集群上创建/修改 <dbname> 数据库
剧本
./pgsql-db.yml -l pg-meta -e dbname=some_db    # 直接使用剧本在 <cls> 集群上创建/修改 <dbname> 数据库
示例
bin/pgsql-db pg-meta some_db    # 在 pg-meta 集群上创建/修改 some_db 数据库

关于数据库定义参数的完整参考,请查阅 数据库配置。数据库访问权限见 访问控制:数据库隔离

请注意,部分数据库参数仅能在 创建时 指定。修改这些参数需要先删除再创建数据库(使用 state: recreate 重建数据库)。

操作 快捷命令 说明
创建数据库 bin/pgsql-db <cls> <db> 创建新的业务数据库
修改数据库 bin/pgsql-db <cls> <db> 修改已存在数据库的属性
删除数据库 bin/pgsql-db <cls> <db> 删除数据库(需设置 state: absent
重建数据库 bin/pgsql-db <cls> <db> 先删再建(需设置 state: recreate
克隆数据库 bin/pgsql-db <cls> <db> 使用模板克隆数据库
demo/pgsql-db.cast

创建数据库

定义在 pg_databases 里面的数据库会在 PostgreSQL 集群创建 的时候在 pg_db 任务中自动创建。

要在现有的 PostgreSQL 集群上创建新的业务数据库,请将 数据库定义 添加到 all.children.<cls>.pg_databases,然后执行:

脚本
bin/pgsql-db <cls> <dbname>   # 创建数据库 <dbname>
剧本
./pgsql-db.yml -l <cls> -e dbname=<dbname>   # 直接使用 Ansible 剧本创建数据库
示例
bin/pgsql-db pg-meta myapp    # 例子,在 pg-meta 集群中创建 myapp 数据库

示例配置:创建名为 myapp 的业务数据库

#all.children.pg-meta.vars.pg_databases: # 省略上级缩进
  - name: myapp
    owner: dbuser_myapp
    schemas: [app]
    extensions:
      - { name: pg_trgm }
      - { name: btree_gin }
    comment: my application database

执行效果:在主库上创建数据库 myapp,设置数据库所有者为 dbuser_myapp,创建 schema app, 启用扩展 pg_trgmbtree_gin,数据库将默认添加到 Pgbouncer 连接池,并注册为 Grafana PG 数据源。

建议使用剧本创建数据库

如果您需要手工创建数据库,那么需要自行确保 pgbouncer 连接池 / grafana 数据源同步。


修改数据库

修改数据库与创建数据库使用相同的命令,在没有定义 baseline SQL 的情况下剧本是幂等的。

当目标数据库已存在时,Pigsty 会修改目标数据库的属性使其符合配置。然而,一些属性只能在数据库创建时设置。

脚本
bin/pgsql-db <cls> <db>   # 修改数据库 <db> 的属性
剧本
./pgsql-db.yml -l <cls> -e dbname=<db>   # 幂等操作,可重复执行
示例
bin/pgsql-db pg-meta myapp    # 修改 myapp 数据库的属性使其符合配置

不可修改的属性:以下属性在数据库创建后无法修改,需要使用 state: recreate 重建数据库:

  • name(数据库名称)、template(模板数据库)、strategy(克隆策略)。
  • encoding(字符编码)、locale/lc_collate/lc_ctype(本地化设置)、locale_provider/icu_locale/icu_rules/builtin_locale(本地化提供者设置)

其他属性均可修改,以下是一些常见的修改示例:

修改属主:更新配置中的 owner 字段后执行剧本,会执行 ALTER DATABASE ... OWNER TO 并授予相应权限。

- name: myapp
  owner: dbuser_new_owner     # 修改为新属主

修改连接限制:通过 connlimit 限制数据库的最大连接数。

- name: myapp
  connlimit: 100              # 限制最大 100 个连接

回收公共连接权限:设置 revokeconn: true 会回收 PUBLIC 的 CONNECT 权限,仅允许属主、DBA、监控用户和复制用户连接。

- name: myapp
  owner: dbuser_myapp
  revokeconn: true            # 回收 PUBLIC 的 CONNECT 权限

管理数据库参数:通过 parameters 字典配置数据库级参数,会生成 ALTER DATABASE ... SET 语句。使用特殊值 DEFAULT 可将参数重置为默认值。

- name: myapp
  parameters:
    work_mem: '256MB'
    maintenance_work_mem: '512MB'
    statement_timeout: '30s'
    search_path: DEFAULT      # 重置为默认值

管理模式(Schema):通过 schemas 数组配置模式,支持简单格式和指定属主的完整格式。使用 state: absent 删除模式(CASCADE)。

- name: myapp
  schemas:
    - app                                   # 简单形式
    - { name: core, owner: dbuser_myapp }   # 指定属主
    - { name: deprecated, state: absent }   # 删除模式

管理扩展(Extension):通过 extensions 数组配置扩展,支持简单格式和指定 schema/版本的完整格式。使用 state: absent 卸载扩展(CASCADE)。

- name: myapp
  extensions:
    - postgis                                 # 简单形式
    - { name: vector, schema: public }        # 指定 schema
    - { name: pg_trgm, state: absent }        # 卸载扩展
CASCADE 警告

删除模式或卸载扩展使用 CASCADE 选项,会同时删除依赖该模式/扩展的所有对象。请确保理解影响范围后再执行删除操作。

连接池配置:默认情况下所有业务数据库都会添加到 Pgbouncer 连接池。可配置 pgbouncer(是否加入连接池)、pool_mode(池化模式)、pool_size(默认池大小)、pool_reserve(保留连接数)、pool_size_min(最小池大小)、pool_connlimit(最大数据库连接)、pool_auth_user(认证查询用户)等参数。

- name: myapp
  pgbouncer: true              # 是否加入连接池(默认 true)
  pool_mode: transaction       # 池化模式:transaction/session/statement
  pool_size: 50                # 默认池大小
  pool_reserve: 30             # 保留池大小
  pool_size_min: 0             # 最小池大小
  pool_connlimit: 100          # 最大数据库连接
  pool_auth_user: dbuser_meta  # 认证查询使用用户(配合 pgbouncer_auth_query)

自 Pigsty v4.1.0 起,数据库连接池参数统一使用 pool_reservepool_connlimit,旧别名 pool_size_reserve / pool_max_db_conn 已收敛。


删除数据库

要删除数据库,将其 state 设置为 absent 并执行剧本:

脚本
bin/pgsql-db <cls> <db>   # 删除数据库 <db>(需在配置中设置 state: absent)
剧本
./pgsql-db.yml -l <cls> -e dbname=<db>   # 直接使用 Ansible 剧本删除数据库
示例
bin/pgsql-db pg-meta olddb    # 删除 olddb 数据库(配置中已设置 state: absent)

配置示例

pg_databases:
  - name: olddb
    state: absent

删除操作会:如果数据库标记为 is_template: true,先执行 ALTER DATABASE ... IS_TEMPLATE false;使用 DROP DATABASE ... WITH (FORCE) 强制删除数据库(PG13+)并终止所有活动连接;从 Pgbouncer 连接池中移除该数据库;从 Grafana 数据源中取消注册。

保护机制:系统数据库 postgrestemplate0template1 无法删除。删除操作仅在主库上执行,流复制会自动同步到从库。

危险操作警告

删除数据库是 不可逆 操作,会永久删除该数据库中的所有数据。执行前请确保:已有最新的数据库备份、已确认没有业务在使用该数据库、已通知相关干系人。 Pigsty 不对任何因删除数据库导致的数据丢失承担责任,使用需自担风险。


重建数据库

recreate 状态用于重建数据库,等效于先删除再创建:

脚本
bin/pgsql-db <cls> <db>   # 重建数据库 <db>(需在配置中设置 state: recreate)
剧本
./pgsql-db.yml -l <cls> -e dbname=<db>   # 直接使用 Ansible 剧本重建数据库
示例
bin/pgsql-db pg-meta testdb    # 重建 testdb 数据库(配置中已设置 state: recreate)

配置示例

pg_databases:
  - name: testdb
    state: recreate
    owner: dbuser_test
    baseline: test_init.sql    # 重建后执行初始化

适用场景:测试环境重置、清空开发数据库、修改不可变属性(编码、本地化等)、恢复数据库到初始状态。

与手动 DROP + CREATE 的区别:单条命令完成,无需两次操作;自动保留 Pgbouncer 和 Grafana 配置;执行后自动加载 baseline 初始化脚本。


克隆数据库

你可以通过 PG 的 template 机制复制一个 PostgreSQL 数据库,在克隆期间,不允许有任何连接到模版数据库的活动连接。

脚本
bin/pgsql-db <cls> <db>   # 克隆数据库 <db>(需在配置中指定 template)
剧本
./pgsql-db.yml -l <cls> -e dbname=<db>   # 直接使用 Ansible 剧本克隆数据库
示例
bin/pgsql-db pg-meta meta_dev    # 克隆创建 meta_dev 数据库(配置中已指定 template: meta)

配置示例

pg_databases:
  - name: meta                   # 源数据库

  - name: meta_dev
    template: meta               # 以 meta 作为模板
    strategy: FILE_COPY          # PG15+ 克隆策略,PG18 瞬间生效

瞬间克隆(PG18+):如果使用 PostgreSQL 18 以上版本,Pigsty 默认设置了 file_copy_method,配合 strategy: FILE_COPY 可以在约 200ms 内完成数据库克隆,而不需要复制数据文件。例如克隆一个 30 GB 的数据库,普通克隆用时 18 秒,瞬间克隆仅需 200 毫秒。

手动克隆:确保清理掉所有连接到模版数据库的连接后执行:

SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'meta';
CREATE DATABASE meta_dev TEMPLATE meta STRATEGY FILE_COPY;

局限性与注意事项:瞬间克隆仅在支持的文件系统上可用(xfs,btrfs,zfs,apfs);不要使用 postgres 数据库作为模版数据库进行克隆;在高并发环境中使用瞬间克隆需要谨慎,需在克隆窗口(200ms)内清理掉所有连接到模版数据库的连接。


连接池管理

在数据库定义中配置的 连接池参数 会在创建/修改数据库时应用到 Pgbouncer 连接池中。

默认情况下所有业务数据库都会添加到 Pgbouncer 连接池(pgbouncer: true)。数据库会被添加到 /etc/pgbouncer/database.txt 文件中,数据库级别的连接池参数(pool_auth_userpool_modepool_sizepool_reservepool_size_minpool_connlimit)通过此文件配置。

您可以使用 postgres 操作系统用户,使用 pgb 别名访问 Pgbouncer 管理数据库。更多连接池管理操作,请参考 Pgbouncer 管理

8.4.4 - 管理 Patroni 高可用

使用 Patroni 管理 PG 集群高可用,包括,修改参数,查看状态,主从切换,重启,重做从库等操作。

概览

Pigsty 使用 Patroni 管理 PostgreSQL 集群,它可以用来修改集群配置,查看集群状态,执行主从切换,重启集群,重做从库等操作。

要使用 Patroni 进行管理,您需要有以下两种身份之一:

Patroni 提供了 patronictl 命令行工具用于管理,Pigsty 提供了封装的快捷命令 pg 来简化其操作。

通过 pg 别名使用 patronictl
pg ()
{
    local patroni_conf="/infra/conf/patronictl.yml";
    if [ ! -r ${patroni_conf} ]; then
        patroni_conf="/etc/patroni/patroni.yml";
        if [ ! -r ${patroni_conf} ]; then
            echo "error: patronictl config not found";
            return 1;
        fi;
    fi;
    patronictl -c ${patroni_conf} "$@"
}

可用命令

命令 功能 说明
edit-config 修改配置 交互式修改集群的 Patroni/PostgreSQL 配置
list 查看状态 列出集群成员及其状态
switchover 主动切换 将主库角色切换到指定从库(计划内维护)
failover 故障切换 强制故障转移到指定从库(紧急情况)
restart 重启实例 重启 PostgreSQL 实例以应用需要重启的参数
reload 重载配置 重载 Patroni 配置(无需重启)
reinit 重做从库 重新初始化从库(擦除数据并重新复制)
pause 暂停自动切换 暂停 Patroni 的自动故障转移功能
resume 恢复自动切换 恢复 Patroni 的自动故障转移功能
history 查看历史 显示集群的故障转移历史记录
show-config 显示配置 显示集群当前的配置(只读)
query 执行查询 在集群成员上执行 SQL 查询
topology 查看拓扑 显示集群的复制拓扑结构
version 查看版本 显示 Patroni 版本信息
remove 移除成员 从 DCS 中移除集群成员(危险操作)

修改配置

使用 edit-config 子命令可以交互式修改集群的 Patroni 与 PostgreSQL 配置。该命令会打开一个编辑器,让您修改存储在 DCS(分布式配置存储)中的集群配置,修改后会自动应用到所有集群成员。您可以更改 Patroni 本身的参数(如 ttlloop_waitsynchronous_mode 等),以及 postgresql.parameters 中的 PostgreSQL 参数。

pg edit-config <cls>                  # 交互式编辑集群配置
pg edit-config <cls> --force          # 跳过确认提示直接应用
pg edit-config <cls> -p <k>=<v>       # 修改 PostgreSQL 参数(--pg 简写)
pg edit-config <cls> -s <k>=<v>       # 修改 Patroni 参数(--set 简写)
demo/pgsql-config.cast

以下是一些常见的配置修改示例:

# 修改 PostgreSQL 参数:慢查询阈值(会询问是否应用)
pg edit-config pg-test -p log_min_duration_statement=1000

# 修改 PostgreSQL 参数并跳过确认
pg edit-config pg-test -p log_min_duration_statement=1000 --force

# 修改多个 PostgreSQL 参数
pg edit-config pg-test -p work_mem=256MB -p maintenance_work_mem=1GB --force

# 修改 Patroni 参数:增大故障检测时间窗口(增大 RTO)
pg edit-config pg-test -s loop_wait=15 -s ttl=60 --force

# 修改 Patroni 参数:启用同步复制模式
pg edit-config pg-test -s synchronous_mode=true --force

# 修改 Patroni 参数:启用严格同步模式(至少一个同步从库才允许写入)
pg edit-config pg-test -s synchronous_mode_strict=true --force

# 修改需要重启的参数(修改后需执行 pg restart)
pg edit-config pg-test -p shared_buffers=4GB --force
pg edit-config pg-test -p shared_preload_libraries='timescaledb, pg_stat_statements' --force
pg edit-config pg-test -p max_connections=200 --force

部分参数修改后需要重启 PostgreSQL 才能生效,您可以使用 pg list 检查集群状态,带 * 标记的实例表示需要重启。然后使用 pg restart 命令重启集群使配置生效。 您也可以使用 curl 或编写程序直接调用 Patroni 提供的 REST API 来修改配置:

# 查看当前配置
curl -s 10.10.10.11:8008/config | jq .

# 通过 API 修改参数(需要认证)
curl -u 'postgres:Patroni.API' \
     -d '{"postgresql":{"parameters": {"log_min_duration_statement":200}}}' \
     -s -X PATCH http://10.10.10.11:8008/config | jq .

查看状态

使用 list 子命令可以查看集群成员及其状态。输出结果会显示每个实例的名称、主机地址、角色、运行状态、时间线和复制延迟等信息。这是日常运维中最常用的命令之一,用于快速了解集群的健康状况。

pg list <cls>                         # 查看指定集群的状态
pg list                               # 列出所有集群(需要在管理节点上执行)
pg list <cls> -e                      # 显示扩展信息(--extended)
pg list <cls> -t                      # 显示时间戳(--timestamp)
pg list <cls> -f json                 # 以 JSON 格式输出(--format)
pg list <cls> -W 5                    # 每 5 秒刷新一次(--watch)

输出示例:

+ Cluster: pg-test (7322261897169354773) -----+----+--------------+
| Member    | Host        | Role    | State   | TL | Lag in MB    |
+-----------+-------------+---------+---------+----+--------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  1 |              |
| pg-test-2 | 10.10.10.12 | Replica | running |  1 |            0 |
| pg-test-3 | 10.10.10.13 | Replica | running |  1 |            0 |
+-----------+-------------+---------+---------+----+--------------+

输出列说明:Member 是实例名称,由 pg_cluster-pg_seq 组成;Host 是实例所在主机的 IP 地址;Role 表示角色,包括 Leader(主库)、Replica(从库)、Sync Standby(同步从库)、Standby Leader(级联复制的级联主库)等;State 表示运行状态,常见值包括 running(正常运行)、streaming(流复制中)、in archive recovery(归档恢复中)、starting(启动中)、stopped(已停止)等;TL 是时间线编号(Timeline),每次主从切换后会递增;Lag in MB 是复制延迟,以 MB 为单位,主库不显示此值。

如果某个实例需要重启才能应用配置更改,实例名称后会显示 * 标记:

+ Cluster: pg-test (7322261897169354773) -------+----+--------------+
| Member      | Host        | Role    | State   | TL | Lag in MB    |
+-------------+-------------+---------+---------+----+--------------+
| pg-test-1 * | 10.10.10.11 | Leader  | running |  1 |              |
| pg-test-2 * | 10.10.10.12 | Replica | running |  1 |            0 |
+-------------+-------------+---------+---------+----+--------------+

主动切换

使用 switchover 子命令可以执行计划内的主从切换。Switchover 是一种优雅的切换方式:Patroni 会先确保从库完全同步,然后让主库降级为从库,最后提升目标从库为新主库。这个过程通常只需要几秒钟,期间会有短暂的写入不可用。适用于主库所在主机需要维护、升级、或者需要将主库迁移到性能更好的节点等场景。

pg switchover <cls>                   # 交互式切换,会提示选择目标从库
pg switchover <cls> --leader <old>    # 指定当前主库名称
pg switchover <cls> --candidate <new> # 指定目标从库名称
pg switchover <cls> --scheduled <time> # 定时切换,格式如 2024-12-01T03:00
pg switchover <cls> --force           # 跳过确认提示

执行切换前请确保所有从库复制状态正常(状态为 runningstreaming),复制延迟在可接受范围内,并已通知相关业务方。

# 交互式切换(推荐,会显示当前拓扑并提示选择)
$ pg switchover pg-test
Current cluster topology
+ Cluster: pg-test (7322261897169354773) -----+----+--------------+
| Member    | Host        | Role    | State   | TL | Lag in MB    |
+-----------+-------------+---------+---------+----+--------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  1 |              |
| pg-test-2 | 10.10.10.12 | Replica | running |  1 |            0 |
| pg-test-3 | 10.10.10.13 | Replica | running |  1 |            0 |
+-----------+-------------+---------+---------+----+--------------+
Primary [pg-test-1]:
Candidate ['pg-test-2', 'pg-test-3'] []: pg-test-2
When should the switchover take place (e.g. 2024-01-01T12:00) [now]:
Are you sure you want to switchover cluster pg-test, demoting current leader pg-test-1? [y/N]: y

# 非交互式切换(指定主库和候选从库)
pg switchover pg-test --leader pg-test-1 --candidate pg-test-2 --force

# 定时切换(在凌晨 3 点执行,适合维护窗口)
pg switchover pg-test --leader pg-test-1 --candidate pg-test-2 --scheduled "2024-12-01T03:00"

切换完成后,请使用 pg list 确认新的集群拓扑。


故障切换

使用 failover 子命令可以执行紧急故障切换。与 switchover 不同,failover 用于主库已经不可用的紧急情况。它会直接提升一个从库为新主库,而不等待原主库的确认。由于从库可能尚未完全同步所有数据,使用 failover 可能会导致少量数据丢失。因此,在非紧急情况下请优先使用 switchover

pg failover <cls>                     # 交互式故障切换
pg failover <cls> --candidate <new>   # 指定要提升的从库
pg failover <cls> --force             # 跳过确认提示

故障切换示例:

# 交互式故障切换
$ pg failover pg-test
Candidate ['pg-test-2', 'pg-test-3'] []: pg-test-2
Are you sure you want to failover cluster pg-test? [y/N]: y
Successfully failed over to "pg-test-2"

# 非交互式故障切换(紧急情况快速执行)
pg failover pg-test --candidate pg-test-2 --force

Switchover 与 Failover 的区别:Switchover 用于计划内维护,要求原主库在线,执行前会确保数据完全同步,不会丢失数据;Failover 用于紧急故障恢复,原主库可以离线,会直接提升从库,可能丢失未同步的数据。日常维护、升级请使用 Switchover;只有在主库彻底故障无法恢复时才使用 Failover。

当前内置 Patroni 的 failover 子命令没有 --leader 选项;需要校验或指定原主库时应使用计划内的 switchover --leader ...,故障切换只指定候选从库。


重启实例

使用 restart 子命令可以重启 PostgreSQL 实例,通常用于应用需要重启才能生效的参数更改。直接对整个集群执行时,patronictl 会逐个提交所选成员,但不保证“从库优先、主库最后”的顺序。若需要明确的 leader-last 顺序,应先按角色重启从库,再单独重启主库。

pg restart <cls>                      # 重启整个集群的所有实例
pg restart <cls> <member>             # 重启指定实例
pg restart <cls> --role leader        # 仅重启主库
pg restart <cls> --role replica       # 仅重启所有从库
pg restart <cls> --pending            # 仅重启标记为需要重启的实例
pg restart <cls> --scheduled <time>   # 定时重启
pg restart <cls> --timeout <sec>      # 设置重启超时时间(秒)
pg restart <cls> --force              # 跳过确认提示

当您修改了需要重启才能生效的参数(如 shared_buffersshared_preload_librariesmax_connectionsmax_worker_processes 等)后,需要使用此命令重启实例。

# 查看哪些实例需要重启(名称后带 * 标记)
$ pg list pg-test
+ Cluster: pg-test (7322261897169354773) -------+----+--------------+
| Member      | Host        | Role    | State   | TL | Lag in MB    |
+-------------+-------------+---------+---------+----+--------------+
| pg-test-1 * | 10.10.10.11 | Leader  | running |  1 |              |
| pg-test-2 * | 10.10.10.12 | Replica | running |  1 |            0 |
+-------------+-------------+---------+---------+----+--------------+

# 重启单个从库实例
pg restart pg-test pg-test-2

# 重启整个集群的所有成员(不承诺 leader-last 顺序)
pg restart pg-test --force

# 仅重启需要重启的实例
pg restart pg-test --pending --force

# 显式按“从库优先、主库最后”执行
pg restart pg-test --role replica --force
pg restart pg-test --role leader --force

# 定时重启(在维护窗口执行)
pg restart pg-test --scheduled "2024-12-01T03:00"

# 设置重启超时时间为 300 秒
pg restart pg-test --timeout 300 --force

重载配置

使用 reload 子命令可以重载 Patroni 配置,无需重启 PostgreSQL。该命令会让 Patroni 重新读取配置文件,并将不需要重启的参数变更应用到 PostgreSQL(通过 pg_reload_conf())。相比 restartreload 更加轻量,不会中断数据库连接和正在执行的查询。

pg reload <cls>                       # 重载整个集群的配置
pg reload <cls> <member>              # 重载指定实例的配置
pg reload <cls> --role leader         # 仅重载主库
pg reload <cls> --role replica        # 仅重载所有从库
pg reload <cls> --force               # 跳过确认提示

大多数 PostgreSQL 参数可以通过 reload 生效,只有少数参数(位于 postmaster 上下文的参数,例如 shared_buffersmax_connectionsshared_preload_librariesarchive_mode 等)需要重启 PostgreSQL 才能生效。

# 重载整个集群
pg reload pg-test

# 重载单个实例
pg reload pg-test pg-test-1

# 强制重载,跳过确认
pg reload pg-test --force

重做从库

使用 reinit 子命令可以重新初始化从库。该操作会删除从库上的所有数据,再按 Patroni 的 create_replica_methods 顺序重建:Pigsty 默认先尝试 basebackup(即 pg_basebackup);启用远程 pgBackRest 仓库时还会配置 pgbackrest 作为后备方法。适用于从库数据损坏无法修复、从库落后太多导致 WAL 已被清理无法追赶、或从库配置错误需要重置等场景。

pg reinit <cls> <member>              # 重新初始化指定从库
pg reinit <cls> <member> --force      # 跳过确认提示
pg reinit <cls> <member> --wait       # 等待重建完成后再返回

⚠️ 警告:此操作会删除目标实例的所有数据!只能对从库执行,不能对主库执行。

# 重新初始化从库(会提示确认)
$ pg reinit pg-test pg-test-2
Are you sure you want to reinitialize members pg-test-2? [y/N]: y
Success: reinitialize for member pg-test-2

# 强制重新初始化,跳过确认
pg reinit pg-test pg-test-2 --force

# 重新初始化并等待完成
pg reinit pg-test pg-test-2 --force --wait

重建过程中,可以使用 pg list 查看进度。从库状态会显示为 creating replica

+ Cluster: pg-test (7322261897169354773) --------------+----+------+
| Member    | Host        | Role    | State            | TL | Lag  |
+-----------+-------------+---------+------------------+----+------+
| pg-test-1 | 10.10.10.11 | Leader  | running          |  2 |      |
| pg-test-2 | 10.10.10.12 | Replica | creating replica |    |    ? |
+-----------+-------------+---------+------------------+----+------+

暂停自动切换

使用 pause 子命令可以暂停 Patroni 的自动故障转移功能。暂停后,即使主库故障,Patroni 也不会自动提升从库为新主库。适用于计划内维护窗口(避免维护操作误触发切换)、调试问题时防止集群状态变化、或需要手动控制切换时机等场景。

pg pause <cls>                        # 暂停自动故障转移
pg pause <cls> --wait                 # 暂停并等待所有成员确认

⚠️ 警告:暂停期间如果主库故障,集群将不会自动恢复!请确保在维护完成后及时使用 resume 恢复。

# 暂停自动切换
$ pg pause pg-test
Success: cluster management is paused

# 查看集群状态(底部会显示 Maintenance mode: on)
$ pg list pg-test
+ Cluster: pg-test (7322261897169354773) -----+----+--------------+
| Member    | Host        | Role    | State   | TL | Lag in MB    |
+-----------+-------------+---------+---------+----+--------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  1 |              |
| pg-test-2 | 10.10.10.12 | Replica | running |  1 |            0 |
+-----------+-------------+---------+---------+----+--------------+
 Maintenance mode: on

恢复自动切换

使用 resume 子命令可以恢复 Patroni 的自动故障转移功能。维护完成后应立即执行此命令,以确保集群在主库故障时能够自动恢复。

pg resume <cls>                       # 恢复自动故障转移
pg resume <cls> --wait                # 恢复并等待所有成员确认
# 恢复自动切换
$ pg resume pg-test
Success: cluster management is resumed

# 确认已恢复(Maintenance mode 提示消失)
$ pg list pg-test

查看历史

使用 history 子命令可以查看集群的故障转移历史记录。每次主从切换(无论是自动故障转移还是手动切换)都会生成一条新的时间线记录。

pg history <cls>                      # 显示故障转移历史
pg history <cls> -f json              # 以 JSON 格式输出
pg history <cls> -f yaml              # 以 YAML 格式输出
$ pg history pg-test
+----+-----------+------------------------------+---------------------------+
| TL |       LSN | Reason                       | Timestamp                 |
+----+-----------+------------------------------+---------------------------+
|  1 | 0/5000060 | no recovery target specified | 2024-01-15T10:30:00+08:00 |
|  2 | 0/6000000 | switchover to pg-test-2      | 2024-01-20T14:00:00+08:00 |
|  3 | 0/7000028 | failover to pg-test-1        | 2024-01-25T09:15:00+08:00 |
+----+-----------+------------------------------+---------------------------+

输出列说明:TL 是时间线编号(Timeline),每次切换后递增,用于区分不同的主库历史;LSN 是切换时的日志序列号(Log Sequence Number),标识切换发生时的 WAL 位置;Reason 是切换原因,可能是 switchover to xxx(手动切换)、failover to xxx(故障转移)或 no recovery target specified(初始化);Timestamp 是切换发生的时间戳。


显示配置

使用 show-config 子命令可以查看集群当前存储在 DCS 中的配置。这是一个只读操作,如需修改配置请使用 edit-config 命令。

pg show-config <cls>                  # 显示集群配置
$ pg show-config pg-test
loop_wait: 10
maximum_lag_on_failover: 1048576
postgresql:
  parameters:
    archive_command: pgbackrest --stanza=pg-test archive-push %p
    max_connections: 100
    shared_buffers: 256MB
    log_min_duration_statement: 1000
  use_pg_rewind: true
  use_slots: true
retry_timeout: 10
ttl: 30
synchronous_mode: false

执行查询

使用 query 子命令可以在集群成员上快速执行 SQL 查询。这是一个方便的调试工具,适合快速检查集群状态或执行简单查询。生产环境中的复杂查询建议使用 psql 或应用程序连接。

pg query <cls> -c "<sql>"             # 在主库上执行查询
pg query <cls> -c "<sql>" -m <member> # 在指定实例上执行(--member)
pg query <cls> -c "<sql>" -r leader   # 在主库上执行(--role)
pg query <cls> -c "<sql>" -r replica  # 在所有从库上执行
pg query <cls> -f <file>              # 从文件读取 SQL 执行
pg query <cls> -c "<sql>" -U <user>   # 指定用户名(--username)
pg query <cls> -c "<sql>" -d <db>     # 指定数据库(--dbname)
pg query <cls> -c "<sql>" --format json  # 以 JSON 格式输出
# 查看主库当前连接数
pg query pg-test -c "SELECT count(*) FROM pg_stat_activity"

# 查看 PostgreSQL 版本
pg query pg-test -c "SELECT version()"

# 在所有从库上查看复制状态
pg query pg-test -c "SELECT pg_is_in_recovery(), pg_last_wal_replay_lsn()" -r replica

# 在指定实例上执行
pg query pg-test -c "SELECT pg_is_in_recovery()" -m pg-test-2

# 使用指定用户和数据库
pg query pg-test -c "SELECT current_user, current_database()" -U postgres -d postgres

# 以 JSON 格式输出结果
pg query pg-test -c "SELECT * FROM pg_stat_replication" --format json

查看拓扑

使用 topology 子命令可以以树形结构查看集群的复制拓扑。与 list 相比,topology 更直观地展示了主从复制关系,特别适合级联复制(Cascading Replication)场景。

pg topology <cls>                     # 显示复制拓扑
$ pg topology pg-test
+ Cluster: pg-test (7322261897169354773) -------+----+--------------+
| Member      | Host        | Role    | State   | TL | Lag in MB    |
+-------------+-------------+---------+---------+----+--------------+
| pg-test-1   | 10.10.10.11 | Leader  | running |  1 |              |
| + pg-test-2 | 10.10.10.12 | Replica | running |  1 |            0 |
| + pg-test-3 | 10.10.10.13 | Replica | running |  1 |            0 |
+-------------+-------------+---------+---------+----+--------------+

在级联复制场景中,拓扑图会清晰展示复制链路层级,例如 pg-test-3pg-test-2 复制,而 pg-test-2 从主库 pg-test-1 复制。


查看版本

使用 version 子命令可以查看 patronictl 的版本信息。

pg version                            # 显示 patronictl 版本
$ pg version
patronictl version 4.1.0

移除成员

使用 remove 子命令可以从 DCS(分布式配置存储)中移除集群或成员的元数据。这是一个危险操作,仅移除 DCS 中的元数据,不会停止 PostgreSQL 服务或删除数据文件。错误使用可能导致集群状态不一致。

pg remove <cls>                       # 从 DCS 中移除整个集群的元数据

通常情况下您不需要使用此命令。如需正确移除集群或实例,请使用 Pigsty 提供的 bin/pgsql-rm 脚本或 pgsql-rm.yml 剧本。 只有在以下特殊情况下才考虑使用 remove:DCS 中存在孤立的元数据需要清理(例如节点已物理移除但元数据残留),或集群已通过其他方式销毁需要清理残留信息。

# 移除整个集群的元数据(需要多次确认)
$ pg remove pg-test
Please confirm the cluster name to remove: pg-test
You are about to remove all information in DCS for pg-test, please type: "Yes I am aware": Yes I am aware

8.4.5 - 管理 PostgreSQL HBA 认证规则

HBA 管理:刷新规则、验证配置、故障排查、PgBouncer HBA

快速上手

Pigsty 使用声明式管理方式,首先在 配置清单定义 HBA 规则,然后使用 bin/pgsql-hba <cls> 刷新规则。

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_hba_rules:                            # <--- 在这里定义 HBA 规则列表!
      - {user: dbuser_app, db: app, addr: intra, auth: pwd, title: 'app access'}
      - {user: dbuser_api, db: all, addr: world, auth: ssl, title: 'api ssl access'}
脚本
bin/pgsql-hba <cls>              # 刷新集群的 PostgreSQL 和 Pgbouncer HBA 规则
bin/pgsql-hba <cls> <ip>...      # 刷新集群中特定实例的 HBA 规则
剧本
./pgsql.yml -l <cls> -t pg_hba,pg_reload                 # 仅刷新 PostgreSQL HBA
./pgsql.yml -l <cls> -t pgbouncer_hba,pgbouncer_reload   # 仅刷新 Pgbouncer HBA
./pgsql.yml -l <cls> -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload  # 同时刷新两者
示例
bin/pgsql-hba pg-meta                      # 刷新 pg-meta 集群的 HBA 规则
bin/pgsql-hba pg-meta 10.10.10.10          # 仅刷新特定实例
bin/pgsql-hba pg-meta 10.10.10.11 10.10.10.12  # 刷新多个实例

关于规则语法,请查阅 HBA 配置;关于认证方法、默认边界与凭据管理,请参考 身份认证

操作 说明 风险
刷新 HBA 规则 重新渲染配置文件并重载服务
验证 HBA 规则 查看当前生效规则,测试连接认证 只读
常见管理场景 添加规则、封禁 IP、角色区分、扩容刷新
故障排查 连接被拒绝、认证失败、规则未生效 -
Pgbouncer HBA Pgbouncer 连接池的 HBA 管理
demo/pgsql-hba.cast

刷新 HBA 规则

修改 pigsty.yml 中的 HBA 规则后,需要重新渲染配置文件并让服务重载。

脚本
bin/pgsql-hba <cls>              # 刷新整个集群的 HBA 规则(PostgreSQL + Pgbouncer)
bin/pgsql-hba <cls> <ip>...      # 刷新特定实例(多个 IP 空格分隔)
剧本
./pgsql.yml -l <cls> -t pg_hba,pg_reload                 # 仅刷新 PostgreSQL HBA
./pgsql.yml -l <cls> -t pgbouncer_hba,pgbouncer_reload   # 仅刷新 Pgbouncer HBA
./pgsql.yml -l <cls> -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload  # 同时刷新两者
示例
bin/pgsql-hba pg-meta                      # 刷新 pg-meta 集群
bin/pgsql-hba pg-meta 10.10.10.10          # 仅刷新 10.10.10.10 实例

执行效果:根据配置清单中的 HBA 规则定义,渲染 PostgreSQL 和 Pgbouncer 的 HBA 配置文件,然后重载服务使配置生效。

配置文件位置

服务 配置文件路径 模板文件
PostgreSQL /pg/data/pg_hba.conf roles/pgsql/templates/pg_hba.conf
Pgbouncer /etc/pgbouncer/pgb_hba.conf roles/pgsql/templates/pgbouncer.hba
不要直接编辑配置文件

直接编辑 /pg/data/pg_hba.conf/etc/pgbouncer/pgb_hba.conf 虽然可以临时生效,但下次执行 Ansible 剧本时会被覆盖。所有 HBA 规则变更应在 pigsty.yml 中进行,然后执行 bin/pgsql-hba 刷新。

相关 Tags

Tag 说明
pg_hba 渲染 PostgreSQL HBA 配置文件
pg_reload 重载 PostgreSQL 配置(需配合 pg_reload=true
pgbouncer_hba 渲染 Pgbouncer HBA 配置文件
pgbouncer_reload 重载 Pgbouncer 配置

验证 HBA 规则

刷新 HBA 规则后,可以通过以下方式验证配置是否正确生效。

查看当前生效的 HBA 规则

SQL
-- 查看 PostgreSQL HBA 规则(推荐)
TABLE pg_hba_file_rules;

-- 查看特定数据库的匹配规则
SELECT * FROM pg_hba_file_rules WHERE database @> ARRAY['mydb']::text[];
Bash
# 查看 PostgreSQL HBA 配置文件
cat /pg/data/pg_hba.conf

# 查看 Pgbouncer HBA 配置文件
cat /etc/pgbouncer/pgb_hba.conf

# 查看配置文件头部(确认是否更新)
head -20 /pg/data/pg_hba.conf
测试连接
# 测试特定用户从特定地址的连接
psql -h <host> -p 5432 -U <user> -d <database> -c "SELECT 1"

# 测试通过 Pgbouncer 连接
psql -h <host> -p 6432 -U <user> -d <database> -c "SELECT 1"

检查 HBA 配置语法

# 重载配置(会验证语法)
psql -c "SELECT pg_reload_conf()"

# 如果有语法错误,查看日志
tail -f /pg/log/postgresql-*.log

常见管理场景

添加新的 HBA 规则

在集群配置的 pg_hba_rules 中添加规则,然后执行刷新:

pg-meta:
  vars:
    pg_hba_rules:
      - {user: new_user, db: new_db, addr: '192.168.1.0/24', auth: pwd, title: 'new app access'}
bin/pgsql-hba pg-meta

紧急封禁 IP

当发现恶意 IP 时,可以添加高优先级(order: 0)的拒绝规则:

pg_hba_rules:
  - {user: all, db: all, addr: '10.1.1.100/32', auth: deny, order: 0, title: 'emergency block'}
bin/pgsql-hba pg-meta    # 立即刷新生效

按角色区分规则

为主库和从库配置不同的 HBA 规则,使用 role 参数:

pg_hba_rules:
  # 仅主库允许写入用户
  - {user: writer, db: all, addr: intra, auth: pwd, role: primary, title: 'writer on primary'}
  # 从库允许只读用户
  - {user: reader, db: all, addr: world, auth: ssl, role: replica, title: 'reader on replica'}

执行刷新后,规则会根据实例的 pg_role 自动启用或禁用。

集群扩容后刷新 HBA

当集群新增实例后,使用 addr: cluster 的规则需要刷新才能包含新成员:

./pgsql.yml -l 10.10.10.14       # 扩容新实例
bin/pgsql-hba pg-meta            # 刷新所有实例的 HBA(包含新成员 IP)

主从切换后刷新 HBA

Patroni 故障转移后,实例的 pg_role 可能与配置不一致。如果 HBA 规则使用了 role 过滤,需要更新配置并刷新:

# 更新 pigsty.yml 中的角色定义后刷新
bin/pgsql-hba pg-meta

故障排查

连接被拒绝

症状FATAL: no pg_hba.conf entry for host "x.x.x.x", user "xxx", database "xxx"

排查步骤

  1. 检查当前 HBA 规则,确认是否有匹配的规则:
psql -c "TABLE pg_hba_file_rules"
  1. 确认客户端 IP、用户名、数据库是否匹配任何规则

  2. 检查规则顺序(HBA 是首条匹配生效)

  3. 在配置清单中添加对应规则并刷新:

bin/pgsql-hba <cls>

认证失败

症状FATAL: password authentication failed for user "xxx"

排查步骤

  1. 确认密码正确
  2. 检查密码加密方式(pg_pwd_enc)与客户端兼容性
  3. 检查用户是否存在:
SELECT * FROM pg_roles WHERE rolname = 'xxx';

HBA 规则未生效

排查步骤

  1. 确认已执行刷新命令
  2. 检查 Ansible 执行是否成功
  3. 确认 PostgreSQL 已重载:
psql -c "SELECT pg_reload_conf()"
  1. 检查配置文件是否更新:
head -20 /pg/data/pg_hba.conf

规则顺序问题

HBA 是首条匹配生效,如果规则未按预期工作:

  1. 检查规则定义中的 order
  2. 使用 psql -c "TABLE pg_hba_file_rules" 查看实际顺序
  3. 调整 order 值(数字越小优先级越高)

Pgbouncer HBA

Pgbouncer 的 HBA 管理与 PostgreSQL 类似,但有一些差异。

配置差异

差异点 PostgreSQL Pgbouncer
配置文件 /pg/data/pg_hba.conf /etc/pgbouncer/pgb_hba.conf
复制连接 支持 db: replication 不支持
本地认证 使用 ident 使用 peer

刷新 Pgbouncer HBA

脚本
bin/pgsql-hba <cls>    # 同时刷新 PostgreSQL 和 Pgbouncer
剧本
./pgsql.yml -l <cls> -t pgbouncer_hba,pgbouncer_reload   # 仅刷新 Pgbouncer HBA
查看
cat /etc/pgbouncer/pgb_hba.conf    # 查看 Pgbouncer HBA 规则

最佳实践

  1. 始终在配置文件中管理:不要直接编辑 pg_hba.conf,所有变更通过 pigsty.yml
  2. 测试环境先验证:HBA 变更可能导致连接问题,先在测试环境验证
  3. 使用 order 控制优先级:黑名单规则使用 order: 0,确保优先匹配
  4. 及时刷新:添加/删除实例、主从切换后及时刷新 HBA
  5. 最小权限原则:只开放必要的访问,避免使用 addr: world + auth: trust
  6. 监控认证失败:关注 pg_stat_activity 中的认证失败记录
  7. 备份配置:重要变更前备份 pigsty.yml

相关文档

8.4.6 - Pgbouncer 连接池管理

使用 Pgbouncer 管理连接池,包括暂停、恢复、禁用、启用、重连、终止、重载等操作。

概览

Pigsty 使用 Pgbouncer 作为 PostgreSQL 的连接池中间件,默认监听 6432 端口,代理访问本机 5432 端口上的 PostgreSQL 实例。

这是一个 可选组件,如果您并没有海量连接,也不需要事务池化与查询监控指标,可以关闭连接池,直连数据库,或者保留但不使用。


用户与数据库管理

Pgbouncer 中的用户和数据库由 Pigsty 自动管理,并在 创建数据库创建用户 时自动应用 数据库配置用户配置

数据库管理:在 pg_databases 中定义的数据库,默认会自动添加到 Pgbouncer。设置 pgbouncer: false 可以排除特定数据库。

pg_databases:
  - name: mydb                # 默认加入连接池
    pool_auth_user: dbuser_meta # 可选,认证查询用户(配合 pgbouncer_auth_query)
    pool_mode: transaction    # 数据库级池化模式
    pool_size: 50             # 默认池大小
    pool_reserve: 30          # 保留池大小
    pool_size_min: 0          # 最小池大小
    pool_connlimit: 100       # 最大数据库连接数
  - name: internal
    pgbouncer: false          # 不加入连接池

用户管理:在 pg_users 中定义的用户,需要显式设置 pgbouncer: true 才会加入连接池用户列表。

pg_users:
  - name: dbuser_app
    password: DBUser.App
    pgbouncer: true           # 加入连接池用户列表
    pool_mode: transaction    # 用户级池化模式
    pool_connlimit: 50        # 用户级最大连接数

自 Pigsty v4.1.0 起,数据库连接池参数统一使用 pool_reservepool_connlimit,旧别名 pool_size_reserve / pool_max_db_conn 已收敛。


服务管理

在 Pigsty 中,PostgreSQL 集群的 Primary 服务 与 Replica 服务默认指向 Pgbouncer 6432 端口, 如果您想要让这两个服务绕过连接池直接访问 PostgreSQL 实例,可以定制 pg_services,或将 pg_default_service_dest 设置为 postgres


配置管理

Pgbouncer 的配置文件位于 /etc/pgbouncer/ 目录,由 Pigsty 统一生成与管理:

文件 说明
pgbouncer.ini 主配置文件,连接池级别参数
database.txt 数据库列表,数据库级别参数
userlist.txt 用户密码列表
useropts.txt 用户级别的连接池参数
pgb_hba.conf HBA 访问控制规则

Pigsty 会自动管理 database.txtuserlist.txt,在 创建数据库创建用户 时自动更新这些文件。

您也可以手动编辑配置文件后执行 RELOAD 使其生效:

# 编辑配置
$ vim /etc/pgbouncer/pgbouncer.ini

# 重载生效:通过 systemctl
$ sudo systemctl reload pgbouncer

# 重载生效,本身是 pg_dbsu / postgres 用户
$ pgb -c "RELOAD;"

连接池管理

Pgbouncer 使用和 PostgreSQL 相同的 dbsu 运行,默认为 postgres 操作系统用户。Pigsty 提供了快捷命令 pgb 来简化管理操作:

alias pgb='psql -p6432 -dpgbouncer'

您可以在数据库节点上使用 pgb 命令连接到 Pgbouncer 管理控制台,执行管理命令和监控查询。

$ pgb
pgbouncer=# SHOW POOLS;
pgbouncer=# SHOW CLIENTS;
pgbouncer=# SHOW SERVERS;
命令 功能 说明
PAUSE 暂停 暂停数据库连接,等待事务完成后断开服务端连接
RESUME 恢复 恢复被 PAUSE/KILL/SUSPEND 暂停的数据库
DISABLE 禁用 拒绝指定数据库的新客户端连接
ENABLE 启用 允许指定数据库的新客户端连接
RECONNECT 重连 优雅地关闭并重建服务端连接
KILL 终止 立即断开指定数据库的所有客户端和服务端连接
KILL_CLIENT 杀客户端 终止指定的客户端连接
SUSPEND 挂起 刷新缓冲区并停止监听,用于在线重启
SHUTDOWN 关闭 关闭 Pgbouncer 进程
RELOAD 重载 重新加载配置文件
WAIT_CLOSE 等待关闭 等待 RECONNECT/RELOAD 后的服务端连接释放
监控命令 监控 查看连接池状态、客户端、服务端等信息

PAUSE

使用 PAUSE 命令暂停数据库连接。Pgbouncer 会根据池化模式等待活动事务/会话完成后断开服务端连接。新的客户端请求会被阻塞直到执行 RESUME

PAUSE [db];           -- 暂停指定数据库,不指定则暂停所有数据库

典型使用场景:

  • 在线切换后端数据库(如主从切换后更新连接目标)
  • 执行需要断开所有连接的维护操作
  • 配合 SUSPEND 实现 Pgbouncer 在线重启
$ pgb -c "PAUSE mydb;"        # 暂停 mydb 数据库
$ pgb -c "PAUSE;"             # 暂停所有数据库

暂停后,SHOW DATABASES 会显示 paused 状态:

pgbouncer=# SHOW DATABASES;
   name   |   host    | port | database | ... | paused | disabled
----------+-----------+------+----------+-----+--------+----------
 mydb     | /var/run  | 5432 | mydb     | ... |      1 |        0

RESUME

使用 RESUME 命令恢复被 PAUSEKILLSUSPEND 暂停的数据库,允许新的连接请求并恢复正常服务。

RESUME [db];          -- 恢复指定数据库,不指定则恢复所有数据库
$ pgb -c "RESUME mydb;"       # 恢复 mydb 数据库
$ pgb -c "RESUME;"            # 恢复所有数据库

DISABLE

使用 DISABLE 命令禁用指定数据库,拒绝所有新的客户端连接请求。已存在的连接不受影响。

DISABLE db;           -- 禁用指定数据库(必须指定数据库名)

典型使用场景:

  • 临时下线某个数据库进行维护
  • 阻止新连接以便安全地进行数据库迁移
  • 逐步下线即将删除的数据库
$ pgb -c "DISABLE mydb;"      # 禁用 mydb,新连接被拒绝

ENABLE

使用 ENABLE 命令启用之前被 DISABLE 禁用的数据库,重新接受新的客户端连接。

ENABLE db;            -- 启用指定数据库(必须指定数据库名)
$ pgb -c "ENABLE mydb;"       # 启用 mydb,允许新连接

RECONNECT

使用 RECONNECT 命令优雅地重建服务端连接。Pgbouncer 会在连接释放回池后关闭它们,并在需要时建立新连接。

RECONNECT [db];       -- 重建指定数据库的服务端连接,不指定则重建所有

典型使用场景:

  • 后端数据库 IP 地址变更后刷新连接
  • 主从切换后重新路由流量
  • DNS 更新后重建连接
$ pgb -c "RECONNECT mydb;"    # 重建 mydb 的服务端连接
$ pgb -c "RECONNECT;"         # 重建所有服务端连接

执行 RECONNECT 后,可以使用 WAIT_CLOSE 等待旧连接完全释放。


KILL

使用 KILL 命令立即断开指定数据库的所有客户端和服务端连接。与 PAUSE 不同,KILL 不等待事务完成,直接强制断开。

KILL [db];            -- 终止指定数据库的所有连接,不指定则终止所有(admin 除外)
$ pgb -c "KILL mydb;"         # 强制断开 mydb 的所有连接
$ pgb -c "KILL;"              # 强制断开所有数据库的连接(admin 除外)

执行 KILL 后,新连接会被阻塞直到执行 RESUME


KILL_CLIENT

使用 KILL_CLIENT 命令终止指定的客户端连接。客户端 ID 可以从 SHOW CLIENTS 输出中获取。

KILL_CLIENT id;       -- 终止指定 ID 的客户端连接
# 查看客户端连接
$ pgb -c "SHOW CLIENTS;"

# 终止特定客户端(假设 ptr 列显示的 ID 为 0x1234567890)
$ pgb -c "KILL_CLIENT 0x1234567890;"

SUSPEND

使用 SUSPEND 命令挂起 Pgbouncer。Pgbouncer 会刷新所有 socket 缓冲区并停止监听数据,直到执行 RESUME

SUSPEND;              -- 挂起 Pgbouncer

SUSPEND 主要用于实现 Pgbouncer 的在线重启(零停机升级):

# 1. 挂起当前 Pgbouncer
$ pgb -c "SUSPEND;"

# 2. 启动新的 Pgbouncer 进程(使用 -R 选项接管 socket)
$ pgbouncer -R /etc/pgbouncer/pgbouncer.ini

# 3. 新进程接管后,旧进程自动退出

SHUTDOWN

使用 SHUTDOWN 命令关闭 Pgbouncer 进程。支持多种关闭模式:

SHUTDOWN;                      -- 立即关闭
SHUTDOWN WAIT_FOR_SERVERS;     -- 等待服务端连接释放后关闭
SHUTDOWN WAIT_FOR_CLIENTS;     -- 等待客户端断开后关闭(零停机滚动重启)
模式 说明
SHUTDOWN 立即关闭 Pgbouncer 进程
WAIT_FOR_SERVERS 停止接受新连接,等待服务端连接释放后退出
WAIT_FOR_CLIENTS 停止接受新连接,等待所有客户端断开后退出,适用于滚动重启
$ pgb -c "SHUTDOWN WAIT_FOR_CLIENTS;"   # 优雅关闭,等待客户端断开

RELOAD

使用 RELOAD 命令重新加载 Pgbouncer 配置文件。可以动态更新大部分配置参数,无需重启进程。

RELOAD;               -- 重载配置文件
$ pgb -c "RELOAD;"              # 通过管理控制台重载
$ systemctl reload pgbouncer    # 通过 systemd 重载
$ kill -SIGHUP $(cat /run/postgresql/pgbouncer.pid)  # 通过信号重载

Pigsty 提供了重载 Pgbouncer 配置的剧本任务:

./pgsql.yml -l <cls> -t pgbouncer_reload    # 重载集群的 Pgbouncer 配置

WAIT_CLOSE

使用 WAIT_CLOSE 命令等待服务端连接完成关闭。通常在 RECONNECTRELOAD 后使用,确保旧连接已全部释放。

WAIT_CLOSE [db];      -- 等待指定数据库的服务端连接关闭,不指定则等待所有
# 完整的连接重建流程
$ pgb -c "RECONNECT mydb;"
$ pgb -c "WAIT_CLOSE mydb;"    # 等待旧连接释放

监控命令

Pgbouncer 提供了丰富的 SHOW 命令用于监控连接池状态:

命令 说明
SHOW HELP 显示可用命令帮助
SHOW DATABASES 显示数据库配置和状态
SHOW POOLS 显示连接池统计信息
SHOW CLIENTS 显示客户端连接列表
SHOW SERVERS 显示服务端连接列表
SHOW USERS 显示用户配置
SHOW STATS 显示统计信息(请求数、字节数等)
SHOW STATS_TOTALS 显示累计统计信息
SHOW STATS_AVERAGES 显示平均统计信息
SHOW CONFIG 显示当前配置参数
SHOW MEM 显示内存使用情况
SHOW DNS_HOSTS 显示 DNS 缓存的主机名
SHOW DNS_ZONES 显示 DNS 缓存的区域
SHOW SOCKETS 显示打开的 socket 信息
SHOW ACTIVE_SOCKETS 显示活动的 socket
SHOW LISTS 显示内部列表计数
SHOW FDS 显示文件描述符使用情况
SHOW STATE 显示 Pgbouncer 运行状态
SHOW VERSION 显示 Pgbouncer 版本

常用监控示例:

# 查看连接池状态
$ pgb -c "SHOW POOLS;"

# 查看客户端连接
$ pgb -c "SHOW CLIENTS;"

# 查看服务端连接
$ pgb -c "SHOW SERVERS;"

# 查看统计信息
$ pgb -c "SHOW STATS;"

# 查看数据库状态
$ pgb -c "SHOW DATABASES;"

更多监控命令的详细说明,请参考 Pgbouncer 官方文档


Unix 信号

Pgbouncer 支持通过 Unix 信号进行控制,这在无法连接管理控制台时非常有用:

信号 等效命令 说明
SIGHUP RELOAD 重载配置文件
SIGTERM SHUTDOWN WAIT_FOR_CLIENTS 优雅关闭,等待客户端断开
SIGINT SHUTDOWN WAIT_FOR_SERVERS 优雅关闭,等待服务端释放
SIGQUIT SHUTDOWN 立即关闭
SIGUSR1 PAUSE 暂停所有数据库
SIGUSR2 RESUME 恢复所有数据库
# 通过信号重载配置
$ kill -SIGHUP $(cat /run/postgresql/pgbouncer.pid)

# 通过信号优雅关闭
$ kill -SIGTERM $(cat /run/postgresql/pgbouncer.pid)

# 通过信号暂停
$ kill -SIGUSR1 $(cat /run/postgresql/pgbouncer.pid)

# 通过信号恢复
$ kill -SIGUSR2 $(cat /run/postgresql/pgbouncer.pid)

流量切换

Pigsty 管理的数据库路由位于 /etc/pgbouncer/database.txt。要将某个数据库的 Pgbouncer 流量切换到其他节点,需要修改该文件、重载配置,再让已有服务端连接排空并重建:

# 1. 仅把 mydb 的后端目标改为 10.10.10.12
$ sed -i -E '/^mydb[[:space:]]*=/ s#host=[^[:space:]]+#host=10.10.10.12#' /etc/pgbouncer/database.txt

# 2. 重载配置
$ pgb -c "RELOAD;"

# 3. 重建该数据库的连接并等待旧连接释放
$ pgb -c "RECONNECT mydb;"
$ pgb -c "WAIT_CLOSE mydb;"

当前源码附带的 pgb-route 函数只修改 /etc/pgbouncer/pgbouncer.ini;该文件仅 include database.txt,并不包含 Pigsty 生成的逐库 host= 路由。因此它不会改变托管数据库的后端目标,请不要用它替代上述操作。

8.4.7 - 管理 PostgreSQL 组件服务

使用 systemctl 管理 PostgreSQL 集群中的各个组件服务:启动、停止、重启、重载与状态检查。

概述

Pigsty 的 PGSQL 模块由多个组件构成,每个组件都以 systemd 服务的形式运行在节点上。(pgbackrest 除外)

了解这些组件及其管理方式,对于维护生产环境中的 PostgreSQL 集群非常重要。

组件 端口 服务名 说明
Patroni 8008 patroni 高可用管理器,负责 PostgreSQL 的生命周期管理
PostgreSQL 5432 postgres 占位服务,默认不使用,应急使用
Pgbouncer 6432 pgbouncer 连接池中间件,业务流量入口
PgBackRest - - pgBackRest 没有守护服务
HAProxy 543x haproxy 负载均衡器,暴露数据库服务
pg_exporter 9630 pg_exporter PostgreSQL 监控指标导出器
pgbouncer_exporter 9631 pgbouncer_exporter Pgbouncer 监控指标导出器
vip-manager - vip-manager 可选,管理 L2 VIP 地址漂移
重要提示

不要直接使用 systemctl 管理 PostgreSQL 服务。PostgreSQL 由 Patroni 托管,应通过 patronictl 命令进行管理。 直接操作 PostgreSQL 可能导致 Patroni 状态不一致,触发意外的故障转移。postgres 服务是 Patroni 服务失效时的应急逃生窗口。


命令速查

操作 命令
启动服务 systemctl start <service>
停止服务 systemctl stop <service>
重启服务 systemctl restart <service>
重载配置 systemctl reload <service>
查看状态 systemctl status <service>
查看日志 journalctl -u <service> -f
开机启动 systemctl enable <service>
禁用启动 systemctl disable <service>

常用组件服务名:patronipgbouncerhaproxypg_exporterpgbouncer_exportervip-manager


Patroni

Patroni 是 PostgreSQL 的高可用管理器,负责 PostgreSQL 的启动、停止、故障检测与自动故障转移。 它是 PGSQL 模块的核心组件,PostgreSQL 进程由 Patroni 托管,不应直接通过 systemctl 管理 postgres 服务。

启动 Patroni

systemctl start patroni     # 启动 Patroni(同时启动 PostgreSQL)

启动 Patroni 后,它会自动拉起 PostgreSQL 进程。首次启动时,Patroni 会根据角色决定行为:

  • 主库:初始化或恢复数据目录
  • 从库:从主库克隆数据并建立复制

停止 Patroni

systemctl stop patroni      # 停止 Patroni(同时停止 PostgreSQL)

停止 Patroni 时,它会优雅地关闭 PostgreSQL 进程。注意:如果这是主库,且未暂停自动切换,可能触发故障转移。

重启 Patroni

systemctl restart patroni   # 重启 Patroni(同时重启 PostgreSQL)

重启会导致短暂的服务中断。对于生产环境,建议使用 pg restart 命令进行滚动重启。

重载 Patroni

systemctl reload patroni    # 重载 Patroni 配置

重载会让 Patroni 重新读取配置文件,并将可热加载的参数应用到 PostgreSQL。

查看状态与日志

systemctl status patroni    # 查看 Patroni 服务状态
journalctl -u patroni -f    # 实时查看 Patroni 日志
journalctl -u patroni -n 100 --no-pager  # 查看最近 100 行日志

配置文件位置/etc/patroni/patroni.yml

最佳实践:使用 patronictl 而非 systemctl 管理 PostgreSQL 集群。


Pgbouncer

Pgbouncer 是轻量级的 PostgreSQL 连接池中间件。 业务流量通常通过 Pgbouncer(6432 端口)而非直接连接 PostgreSQL(5432 端口),以实现连接复用和保护数据库。

启动 Pgbouncer

systemctl start pgbouncer

停止 Pgbouncer

systemctl stop pgbouncer

注意:停止 Pgbouncer 会中断所有通过连接池的业务连接。

重启 Pgbouncer

systemctl restart pgbouncer

重启会断开所有现有连接。如果只是配置变更,建议使用 reload

重载 Pgbouncer

systemctl reload pgbouncer

重载会重新读取配置文件(用户列表、连接池参数等),不会断开现有连接。

查看状态与日志

systemctl status pgbouncer
journalctl -u pgbouncer -f

配置文件位置

  • 主配置:/etc/pgbouncer/pgbouncer.ini
  • HBA 规则:/etc/pgbouncer/pgb_hba.conf
  • 用户列表:/etc/pgbouncer/userlist.txt
  • 数据库列表:/etc/pgbouncer/database.txt

管理控制台

psql -p 6432 -U postgres -d pgbouncer  # 连接到 Pgbouncer 管理控制台

常用管理命令:

SHOW POOLS;      -- 查看连接池状态
SHOW CLIENTS;    -- 查看客户端连接
SHOW SERVERS;    -- 查看后端服务器连接
SHOW STATS;      -- 查看统计信息
RELOAD;          -- 重载配置
PAUSE;           -- 暂停所有连接池
RESUME;          -- 恢复所有连接池

HAProxy

HAProxy 是高性能的负载均衡器,负责将流量分发到正确的 PostgreSQL 实例。 Pigsty 使用 HAProxy 暴露 服务,根据角色(主库/从库)和健康状态进行流量调度。

启动 HAProxy

systemctl start haproxy

停止 HAProxy

systemctl stop haproxy

注意:停止 HAProxy 会中断所有通过负载均衡器的连接。

重启 HAProxy

systemctl restart haproxy

重载 HAProxy

systemctl reload haproxy

HAProxy 支持优雅重载,不会断开现有连接。配置变更后推荐使用 reload

查看状态与日志

systemctl status haproxy
journalctl -u haproxy -f

配置文件位置:主配置为 /etc/haproxy/haproxy.cfg,Pigsty 生成的服务片段位于 /etc/haproxy/conf.d/

管理界面

HAProxy 提供 Web 管理界面,默认监听在 9101 端口:

http://<node_ip>:9101/haproxy

默认认证:用户名 admin,密码由 haproxy_admin_password 配置。


pg_exporter

pg_exporter 是 PostgreSQL 的 Prometheus 监控指标导出器,负责采集数据库性能指标。

启动 pg_exporter

systemctl start pg_exporter

停止 pg_exporter

systemctl stop pg_exporter

停止后,Prometheus 将无法采集该实例的 PostgreSQL 监控指标。

重启 pg_exporter

systemctl restart pg_exporter

查看状态与日志

systemctl status pg_exporter
journalctl -u pg_exporter -f

配置文件位置/etc/pg_exporter.yml

验证指标采集

curl -s localhost:9630/metrics | head -20

pgbouncer_exporter

pgbouncer_exporter 是 Pgbouncer 的 Prometheus 监控指标导出器。

启动/停止/重启

systemctl start pgbouncer_exporter
systemctl stop pgbouncer_exporter
systemctl restart pgbouncer_exporter

查看状态与日志

systemctl status pgbouncer_exporter
journalctl -u pgbouncer_exporter -f

验证指标采集

curl -s localhost:9631/metrics | head -20

vip-manager

vip-manager 是可选组件,用于管理 L2 VIP 地址漂移。 当启用 pg_vip_enabled 时,vip-manager 会将 VIP 绑定到当前主库节点。

启动 vip-manager

systemctl start vip-manager

停止 vip-manager

systemctl stop vip-manager

停止后,VIP 地址会从当前节点释放。

重启 vip-manager

systemctl restart vip-manager

查看状态与日志

systemctl status vip-manager
journalctl -u vip-manager -f

配置文件位置/etc/default/vip-manager

验证 VIP 绑定

ip addr show           # 查看网络接口,检查 VIP 是否绑定
pg list <cls>          # 确认主库位置

启动顺序与依赖

PGSQL 模块组件的推荐启动顺序:

1. patroni          # 首先启动 Patroni(会自动启动 PostgreSQL)
2. pgbouncer        # 然后启动连接池
3. haproxy          # 启动负载均衡器
4. pg_exporter      # 启动监控导出器
5. pgbouncer_exporter
6. vip-manager      # 最后启动 VIP 管理器(如果启用)

停止顺序应相反。Pigsty 剧本会自动处理这些依赖关系。

批量启动所有服务

systemctl start patroni pgbouncer haproxy pg_exporter pgbouncer_exporter

批量停止所有服务

systemctl stop pgbouncer_exporter pg_exporter haproxy pgbouncer patroni

常见故障排查

服务启动失败

systemctl status <service>        # 查看服务状态
journalctl -u <service> -n 50     # 查看最近日志
journalctl -u <service> --since "5 min ago"  # 查看最近 5 分钟日志

Patroni 无法启动

现象 可能原因 解决方案
无法连接 etcd etcd 集群不可用 检查 etcd 服务状态
数据目录权限错误 文件所有权不是 postgres chown -R postgres:postgres /pg/data
端口被占用 PostgreSQL 残留进程 pg_ctl stop -D /pg/datakill

Pgbouncer 无法启动

现象 可能原因 解决方案
配置文件语法错误 INI 格式错误 检查 /etc/pgbouncer/pgbouncer.ini
端口被占用 6432 端口已被使用 lsof -i :6432
userlist.txt 权限 文件权限不正确 chmod 600 /etc/pgbouncer/userlist.txt

HAProxy 无法启动

现象 可能原因 解决方案
配置文件语法错误 主配置或服务片段格式错误 haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d -c -q
端口被占用 服务端口冲突 lsof -i :5433

相关文档

8.4.8 - 管理 PostgreSQL 定时任务

配置 Crontab 定期调度 PostgreSQL 备份任务,执行备份 / Vacuum Freeze / Analyze 任务,以及处理表膨胀

Pigsty 使用 crontab 来管理定时任务,用于执行例行备份,冻结老化事务,重整膨胀表索引等维护工作。

速查手册

操作 快捷命令 说明
配置定时任务 ./pgsql.yml -t pg_crontab -l <cls> 应用 pg_crontab 配置
查看定时任务 crontab -l 以 postgres 用户查看
物理备份 pg-backup [full|diff|incr] 使用 pgBackRest 执行备份
事务冻结 pg-vacuum [database...] 冻结老化事务,预防 XID 回卷
膨胀治理 pg-repack [database...] 在线重整膨胀的表与索引

其他管理任务,请参考:备份管理监控系统高可用管理


配置定时任务

使用 pg_crontab 参数配置 PostgreSQL 数据库超级用户(pg_dbsu,默认 postgres)的定时任务。

下面 pg-meta 集群配置了每天凌晨1点进行全量备份的定时任务,pg-test 配置了每周一全量备份,其余日期增量备份的定时任务。

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_crontab:
      - '00 01 * * * /pg/bin/pg-backup'
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
  vars:
    pg_cluster: pg-test
    pg_crontab:
      - '00 01 * * 1            /pg/bin/pg-backup full'
      - '00 01 * * 2,3,4,5,6,7  /pg/bin/pg-backup'

推荐的维护计划

pg_crontab:
  - '00 01 * * * /pg/bin/pg-backup full'    # 每天凌晨1点全量备份
  - '00 03 * * 0 /pg/bin/pg-vacuum'         # 每周日凌晨3点执行 vacuum freeze
  - '00 04 * * 1 /pg/bin/pg-repack'         # 每周一凌晨4点执行 repack
任务 频率 时机 说明
pg-backup 每天 凌晨 全量或增量备份,视业务需求而定
pg-vacuum 每周一次 周日凌晨 冻结老化事务,预防 XID 回卷
pg-repack 每周/每月 业务低峰期 重整膨胀表索引,回收空间
仅在主库执行

pg-backuppg-vacuumpg-repack 脚本会自动检测当前节点角色,只有主库才会实际执行,从库会直接退出。

因此可以安全地在所有节点配置相同的定时任务,故障切换后新主库会自动继续执行维护任务。


应用定时任务

定时任务会在 pgsql.yml 剧本执行时(pg_crontab 任务)自动写入对应操作系统发行版的默认位置:

  • EL(RHEL/Rocky/Alma):/var/spool/cron/postgres
  • Debian/Ubuntu:/var/spool/cron/crontabs/postgres
剧本
./pgsql.yml -l pg-meta -t pg_crontab     # 应用 pg_crontab 配置到指定集群
./pgsql.yml -l 10.10.10.10 -t pg_crontab # 仅针对特定主机
手工
# 以 postgres 用户编辑定时任务
sudo -u postgres crontab -e

# 或直接编辑 crontab 文件
sudo vi /var/spool/cron/postgres           # EL 系列
sudo vi /var/spool/cron/crontabs/postgres  # Debian/Ubuntu

每次执行剧本都会 全量覆盖刷新 定时任务配置。


查看定时任务

使用 pg_dbsu 操作系统用户执行以下命令查看定时任务:

crontab -l

# Pigsty Managed Crontab for postgres
SHELL=/bin/bash
PATH=/usr/pgsql/bin:/pg/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin
MAILTO=""
00 01 * * * /pg/bin/pg-backup

如果您不熟悉 Crontab 的语法,可以参考 Crontab Guru 的解释。


pg-backup

pg-backup 是 Pigsty 提供的物理备份脚本,基于 pgBackRest 实现,支持全量、差异、增量三种备份模式。

基本用法

pg-backup                # 执行增量备份(默认),如果没有全量备份则自动执行全量备份
pg-backup full           # 执行全量备份
pg-backup diff           # 执行差异备份(基于最近的全量备份)
pg-backup incr           # 执行增量备份(基于最近的任意备份)

备份类型说明

类型 参数 说明
全量备份 full 完整备份所有数据,恢复时只需要该备份
差异备份 diff 备份自上次全量备份以来的变更,恢复时需要全量+差异
增量备份 incr 备份自上次任意备份以来的变更,恢复时需要完整链路

执行条件

  • 脚本必须在 主库 上以 postgres 用户身份运行
  • 脚本会自动检测当前节点角色,从库执行时会直接退出(exit 1)
  • /etc/pgbackrest/pgbackrest.conf 中自动获取 stanza 名称

常用定时任务配置

每日全量
pg_crontab:
  - '00 01 * * * /pg/bin/pg-backup full'    # 每天凌晨1点全量备份
周全量+日增量
pg_crontab:
  - '00 01 * * 1            /pg/bin/pg-backup full'  # 周一全量备份
  - '00 01 * * 2,3,4,5,6,7  /pg/bin/pg-backup'       # 其他日期增量备份
周全量+日差异
pg_crontab:
  - '00 01 * * 1            /pg/bin/pg-backup full'  # 周一全量备份
  - '00 01 * * 2,3,4,5,6,7  /pg/bin/pg-backup diff'  # 其他日期差异备份

更多备份恢复操作,请参考 备份管理 章节。


pg-vacuum

pg-vacuum 是 Pigsty 提供的事务冻结脚本,用于执行 VACUUM FREEZE 操作,防止事务 ID(XID)回卷导致数据库停机。

基本用法

基本
pg-vacuum                    # 冻结所有数据库中的老化表
pg-vacuum mydb               # 仅处理指定数据库
选项
pg-vacuum -n mydb            # 空跑模式,只显示不执行
pg-vacuum -a 80000000 mydb   # 使用自定义年龄阈值(默认1亿)
pg-vacuum -r 50 mydb         # 使用自定义老化比例阈值(默认40%)
手工SQL
-- 对整个数据库执行 VACUUM FREEZE
VACUUM FREEZE;

-- 对特定表执行 VACUUM FREEZE
VACUUM FREEZE schema.table_name;

命令选项

选项 说明 默认值
-h, --help 显示帮助信息 -
-n, --dry-run 空跑模式,只显示不执行 false
-a, --age 年龄阈值,超过此值的表需要冻结 100000000
-r, --ratio 老化比例阈值,超过则全库冻结(%) 40

工作逻辑

  1. 检查数据库的 datfrozenxid 年龄,如果低于阈值则跳过该库
  2. 计算老化页面比例(超过年龄阈值的表页面占总页面的百分比)
  3. 如果老化比例 > 40%,执行全库 VACUUM FREEZE ANALYZE
  4. 否则,仅对超过年龄阈值的表执行 VACUUM FREEZE ANALYZE

脚本会设置 vacuum_cost_limit = 10000vacuum_cost_delay = 1ms 以控制 I/O 影响。

执行条件

  • 脚本必须在 主库 上以 pg_dbsu postgres 用户身份运行
  • 使用文件锁 /tmp/pg-vacuum.lock 防止并发执行
  • 自动跳过 template0template1postgres 系统数据库

常用定时任务配置

建议将 vacuum 任务与备份/Repack 任务分开执行,避免冲突。

pg_crontab:
  - '00 03 * * 0 /pg/bin/pg-vacuum'     # 每周日凌晨3点执行

pg-repack

pg-repack 是 Pigsty 提供的膨胀治理脚本,基于 pg_repack 扩展实现,用于在线重整膨胀的表与索引。

基本用法

基本
pg-repack                    # 重整所有数据库中的膨胀表与索引
pg-repack mydb               # 仅重整指定数据库
pg-repack mydb1 mydb2        # 重整多个数据库
选项
pg-repack -n mydb            # 空跑模式,只显示不执行
pg-repack -t mydb            # 仅重整表
pg-repack -i mydb            # 仅重整索引
pg-repack -T 30 -j 4 mydb    # 自定义锁超时(秒)和并行度
手工
# 直接使用 pg_repack 命令重整特定表
pg_repack dbname -t schema.table

# 直接使用 pg_repack 命令重整特定索引
pg_repack dbname -i schema.index

命令选项

选项 说明 默认值
-h, --help 显示帮助信息 -
-n, --dry-run 空跑模式,只显示不执行 false
-t, --table 仅重整表 false
-i, --index 仅重整索引 false
-T, --timeout 锁等待超时时间(秒) 10
-j, --jobs 并行作业数 2

自动选择阈值

脚本会根据表和索引的大小与膨胀率,自动选择需要重整的对象:

表膨胀阈值

大小范围 膨胀率阈值 最大数量
< 256MB > 40% 64
256MB - 2GB > 30% 16
2GB - 8GB > 20% 4
8GB - 64GB > 15% 1

索引膨胀阈值

大小范围 膨胀率阈值 最大数量
< 128MB > 40% 64
128MB - 1GB > 35% 16
1GB - 8GB > 30% 4
8GB - 64GB > 20% 1

超过 64GB 的巨型表/索引会被跳过并给出提示,需要手动处理。

执行条件

  • 脚本必须在 主库 上以 postgres 用户身份运行
  • 需要安装 pg_repack 扩展(Pigsty 默认安装)
  • 需要 monitor schema 中的 pg_table_bloatpg_index_bloat 视图
  • 使用文件锁 /tmp/pg-repack.lock 防止并发执行
  • 自动跳过 template0template1postgres 系统数据库
锁等待

重整期间不会影响正常读写,但重整完毕的 切换瞬间 需要获取表上的 AccessExclusive 锁阻塞一切访问。对于高吞吐量业务,建议在业务低峰期或维护窗口进行。

常用定时任务配置

pg_crontab:
  - '00 04 * * 1 /pg/bin/pg-repack'     # 每周一凌晨4点执行

您可以通过 Pigsty 的 PGCAT Database - Table Bloat 面板确认数据库中的膨胀情况,并选择膨胀率较高的表与索引进行重整。

更多细节请参考:关系膨胀的治理


移除定时任务

当使用 pgsql-rm.yml 剧本移除 PostgreSQL 集群时,会自动删除 postgres 用户的 crontab 文件。

./pgsql-rm.yml -l <cls> -t pg_crontab    # 仅移除定时任务
./pgsql-rm.yml -l <cls>                  # 移除整个集群(包含定时任务)

相关文档

8.4.9 - 升级 PostgreSQL 大小版本

版本升级:小版本滚动升级、大版本迁移、扩展升级

快速上手

PostgreSQL 版本升级分为两种类型:小版本升级大版本升级,两者的风险和复杂度差异很大。

类型 示例 停机时间 数据兼容性 风险等级
小版本升级 17.2 → 17.3 秒级(滚动重启) 完全兼容
大版本升级 17 → 18 分钟级 需要升级数据目录
小版本
# 滚动升级:先从库后主库
ansible <cls> -b -a 'yum upgrade -y postgresql17*'
pg restart --role replica --force <cls>
pg switchover <cls>
pg restart <cls> <old-primary> --force
大版本
# 推荐:逻辑复制迁移
bin/pgsql-add pg-new              # 创建新版本集群
# 配置逻辑复制同步数据...
# 切换流量到新集群
扩展
ansible <cls> -b -a 'yum upgrade -y postgis36_17*'
psql -c 'ALTER EXTENSION postgis UPDATE;'

关于在线迁移的详细流程,请参考 在线迁移 文档。

操作 说明 风险
小版本升级 更新软件包,滚动重启
小版本降级 回退到之前的小版本
大版本升级 逻辑复制或 pg_upgrade
扩展升级 升级扩展软件包和扩展对象

小版本升级

小版本升级(如 17.2 → 17.3)是最常见的升级场景,通常用于应用安全补丁和 Bug 修复。数据目录完全兼容,通过滚动重启即可完成。

升级策略:推荐采用 滚动升级 方式:先升级从库,再通过主从切换升级原主库,最小化服务中断。

1. 更新软件仓库 → 2. 升级从库软件包 → 3. 重启从库
4. 主从切换 → 5. 升级原主库软件包 → 6. 重启原主库

步骤一:准备软件包

确保本地软件仓库中有最新版本的 PostgreSQL 包,并刷新节点缓存:

仓库
cd ~/pigsty
./infra.yml -t repo_upstream      # 添加上游仓库(需要互联网)
./infra.yml -t repo_build         # 重建本地仓库
EL
ansible <cls> -b -a 'yum clean all'
ansible <cls> -b -a 'yum makecache'
Debian
ansible <cls> -b -a 'apt clean'
ansible <cls> -b -a 'apt update'

步骤二:升级从库

在所有从库上升级软件包并验证版本:

EL
ansible <cls> -b -a 'yum upgrade -y postgresql17*'
ansible <cls> -b -a '/usr/pgsql/bin/pg_ctl --version'
Debian
ansible <cls> -b -a 'apt install -y postgresql-17'
ansible <cls> -b -a '/usr/lib/postgresql/17/bin/pg_ctl --version'

重启所有从库以应用新版本:

pg restart --role replica --force <cls>

步骤三:切换主库

执行主从切换,将主库角色转移到已升级的从库:

pg switchover <cls>
# 或非交互式:
pg switchover --leader <old-primary> --candidate <new-primary> --scheduled=now --force <cls>

步骤四:升级原主库

原主库现在已降级为从库,升级软件包并重启:

EL
ansible <old-primary-ip> -b -a 'yum upgrade -y postgresql17*'
Debian
ansible <old-primary-ip> -b -a 'apt install -y postgresql-17'
pg restart <cls> <old-primary-name> --force

步骤五:验证

确认所有实例版本一致:

pg list <cls>
pg query <cls> -c "SELECT version()"

小版本降级

在极少数情况下(如新版本引入 Bug),可能需要将 PostgreSQL 降级到之前的版本。

步骤一:获取旧版本包

EL
cd ~/pigsty; ./infra.yml -t repo_upstream     # 添加上游仓库
cd /www/pigsty; repotrack postgresql17-*-17.1 # 下载指定版本的包
cd ~/pigsty; ./infra.yml -t repo_create       # 重建仓库元数据
刷新缓存
ansible <cls> -b -a 'yum clean all'
ansible <cls> -b -a 'yum makecache'

步骤二:执行降级

EL
ansible <cls> -b -a 'yum downgrade -y postgresql17*'
Debian
ansible <cls> -b -a 'apt install -y postgresql-17=17.1*'

步骤三:重启集群

pg restart --force <cls>

大版本升级

大版本升级(如 17 → 18)涉及数据格式变更,需要使用专用工具进行数据迁移。

方式 停机时间 复杂度 适用场景
逻辑复制迁移 秒级切换 生产环境,要求最小停机
pg_upgrade 原地升级 分钟~小时 测试环境,数据量较小
推荐方案

对于生产环境,推荐使用 逻辑复制迁移 方式:创建新版本集群,通过逻辑复制同步数据,然后进行蓝绿切换。这种方式停机时间最短,且可以随时回滚。详见 在线迁移

逻辑复制迁移

逻辑复制迁移是生产环境大版本升级的推荐方式,核心步骤:

1. 创建新版本目标集群 → 2. 配置逻辑复制同步数据 → 3. 验证数据一致性
4. 切换应用流量到新集群 → 5. 下线旧集群

步骤一:创建新版本集群

pg-meta-new:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-meta-new
    pg_version: 18                    # 新版本
bin/pgsql-add pg-meta-new

步骤二:配置逻辑复制

-- 源集群(旧版本)主库:创建发布
CREATE PUBLICATION upgrade_pub FOR ALL TABLES;

-- 目标集群(新版本)主库:创建订阅
CREATE SUBSCRIPTION upgrade_sub
  CONNECTION 'host=10.10.10.11 port=5432 dbname=mydb user=replicator password=xxx'
  PUBLICATION upgrade_pub;

步骤三:等待同步完成

-- 目标集群:检查订阅状态
SELECT * FROM pg_stat_subscription;

-- 源集群:检查复制槽 LSN
SELECT slot_name, confirmed_flush_lsn FROM pg_replication_slots;

步骤四:切换流量

确认数据同步完成后:停止应用写入源集群 → 等待最后的数据同步 → 切换应用连接到新集群 → 删除订阅,下线源集群。

-- 目标集群:删除订阅
DROP SUBSCRIPTION upgrade_sub;

详细的迁移流程请参考 在线迁移 文档。

pg_upgrade 原地升级

pg_upgrade 是 PostgreSQL 官方提供的大版本升级工具,适用于测试环境或可接受较长停机时间的场景。

重要警告

原地升级会导致较长的停机时间,且回滚困难。生产环境请优先考虑逻辑复制迁移方式。

步骤一:安装新版本软件包

./pgsql.yml -l <cls> -t pg_pkg -e pg_version=18

步骤二:停止 Patroni

pg pause <cls>                        # 暂停自动故障转移
systemctl stop patroni                # 停止 Patroni(会停止 PostgreSQL)

步骤三:运行 pg_upgrade

sudo su - postgres
mkdir -p /data/postgres/pg-meta-18/data

# 预检(-c 参数只检查不执行)
/usr/pgsql-18/bin/pg_upgrade \
  -b /usr/pgsql-17/bin -B /usr/pgsql-18/bin \
  -d /data/postgres/pg-meta-17/data \
  -D /data/postgres/pg-meta-18/data \
  -v -c

# 执行升级
/usr/pgsql-18/bin/pg_upgrade \
  -b /usr/pgsql-17/bin -B /usr/pgsql-18/bin \
  -d /data/postgres/pg-meta-17/data \
  -D /data/postgres/pg-meta-18/data \
  --link -j 8 -v

步骤四:更新链接并启动

rm -rf /usr/pgsql && ln -s /usr/pgsql-18 /usr/pgsql
rm -rf /pg && ln -s /data/postgres/pg-meta-18 /pg
# 编辑 /etc/patroni/patroni.yml 更新路径
systemctl start patroni
pg resume <cls>

步骤五:后处理

/usr/pgsql-18/bin/vacuumdb --all --analyze-in-stages
./delete_old_cluster.sh   # pg_upgrade 生成的清理脚本

扩展升级

升级 PostgreSQL 版本时,通常也需要升级相关扩展插件。

升级扩展软件包

EL
ansible <cls> -b -a 'yum upgrade -y postgis36_17 timescaledb-2-postgresql-17* pgvector_17*'
Debian
ansible <cls> -b -a 'apt install -y postgresql-17-postgis-3 postgresql-17-pgvector'

升级扩展版本

软件包升级后,在数据库中执行扩展升级:

-- 查看可升级的扩展
SELECT name, installed_version, default_version FROM pg_available_extensions
WHERE installed_version IS NOT NULL AND installed_version <> default_version;

-- 升级扩展
ALTER EXTENSION postgis UPDATE;
ALTER EXTENSION timescaledb UPDATE;
ALTER EXTENSION vector UPDATE;

-- 检查扩展版本
SELECT extname, extversion FROM pg_extension;
扩展兼容性

大版本升级前,请确认所有使用的扩展都支持目标 PostgreSQL 版本。某些扩展可能需要先卸载再重新安装,请查阅扩展文档。


注意事项

  1. 备份优先:任何升级操作前都应进行完整备份
  2. 测试验证:先在测试环境验证升级流程
  3. 扩展兼容:确认所有扩展支持目标版本
  4. 回滚预案:准备好回滚方案,特别是大版本升级
  5. 监控观察:升级后密切监控数据库性能和错误日志
  6. 文档记录:记录升级过程中的所有操作和问题

相关文档

8.4.10 - 管理 PostgreSQL 扩展插件

扩展管理:下载、安装、配置、启用、更新、卸载扩展

快速上手

Pigsty 提供 575 扩展,使用扩展涉及四个步骤:下载安装配置启用

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_extensions: [ postgis, timescaledb, pgvector ]           # <--- 安装扩展软件包
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'    # <--- 配置预加载扩展
    pg_databases:
      - name: meta
        extensions: [ postgis, timescaledb, vector ]            # <--- 在数据库中启用
脚本
bin/pgsql-ext <cls>           # 在 <cls> 集群上安装配置中定义的扩展
bin/pgsql-ext <cls> [ext...]  # 在 <cls> 集群上安装命令行参数给出的扩展
剧本
./pgsql.yml -l pg-meta -t pg_ext    # 使用剧本安装扩展
示例
bin/pgsql-ext pg-meta                         # 在 pg-meta 集群上安装定义的扩展
bin/pgsql-ext pg-meta pg_duckdb pg_mooncake   # 安装指定扩展

关于扩展的完整参考,请查阅 扩展插件 章节。关于可用扩展列表,请参考 扩展目录

操作 快捷命令 说明
下载扩展 ./infra.yml -t repo_build 将扩展下载到本地仓库
安装扩展 bin/pgsql-ext <cls> 在集群节点上安装扩展软件包
配置扩展 pg edit-config <cls> -p 将扩展添加到预加载库(需重启)
启用扩展 psql -c 'CREATE EXT ...' 在数据库中创建扩展对象
更新扩展 ALTER EXTENSION UPDATE 更新扩展软件包与扩展对象
移除扩展 DROP EXTENSION 删除扩展对象,卸载软件包
demo/pgsql-ext.cast

安装扩展

定义在 pg_extensions 里面的扩展会在 PostgreSQL 集群创建 的时候在 pg_extension 任务中自动安装。

要在现有的 PostgreSQL 集群上安装扩展,请将扩展添加到 all.children.<cls>.pg_extensions,然后执行:

脚本
bin/pgsql-ext <cls>   # 在 <cls> 集群上安装扩展
剧本
./pgsql.yml -l <cls> -t pg_extension   # 直接使用 Ansible 剧本安装扩展
示例
bin/pgsql-ext pg-meta    # 在 pg-meta 集群上安装配置中定义的扩展

示例配置:在集群上安装 PostGIS、TimescaleDB 和 PGVector

#all.children.pg-meta.vars: # 省略上级缩进
pg_extensions: [ postgis, timescaledb, pgvector ]

执行效果:在集群所有节点上安装扩展软件包。Pigsty 会自动将 包别名 翻译为对应操作系统和 PostgreSQL 版本的实际包名。

安装前,确保软件源可用

安装扩展前请确保节点已配置正确的软件源 —— 扩展已经在本地仓库中 下载好,或者已经 配置扩展仓库


手工安装

如果您不想使用 Pigsty 配置来管理 PostgreSQL 扩展,可以在命令行中直接传递要安装的扩展列表:

脚本
bin/pgsql-ext pg-meta pg_duckdb pg_mooncake   # 在 pg-meta 集群上安装指定扩展
剧本
./pgsql.yml -l pg-meta -t pg_ext -e '{"pg_extensions": ["pg_duckdb", "pg_mooncake"]}'

您也可以使用 pig 包管理器命令行工具在单个节点上安装扩展,同样会自动进行 包别名 解析。

pig install postgis timescaledb       # 安装多个扩展
pig install pgvector -v 18            # 针对特定 PG 大版本安装

ansible pg-test -b -a 'pig install pg_duckdb'   # 使用 Ansible 在集群上批量安装

您也可以 直接使用操作系统包管理器 (apt/dnf) 进行安装,但您必须知道具体操作系统/PG 下的 RPM/DEB 包名:

# EL 系统(RHEL、Rocky、Alma、Oracle Linux)
sudo yum install -y pgvector_18*

# Debian / Ubuntu 系统
sudo apt install -y postgresql-18-pgvector

下载扩展

要想安装扩展,您需要确保节点上配置的 扩展仓库 包含待安装的扩展:

  • 单机安装 时无需操心,上游仓库已经直接添加到节点上。
  • 离线安装 时无需操心,绝大部分扩展都已经包含在离线安装包里,个别扩展需要在线安装。
  • 使用本地仓库的 生产多节点部署,要看情况,如果在本地仓库创建的时候 repo_packages / repo_extra_packages 中包含了扩展包, 则意味着已经下载到了本地,可以直接安装,否则需要先下载扩展包到本地仓库。或者直接为节点 配置上游仓库 在线安装。

Pigsty 的默认配置在安装过程中会自动下载主流扩展到本地仓库。如需额外扩展,添加到 repo_extra_packages 后重建仓库:

repo_extra_packages: [ pgvector, postgis, timescaledb ]
脚本
make repo         # 快捷方式 = repo-build + node-repo
make repo-build   # 快捷方式,重建 Infra 上的软件仓库(下载软件包与依赖)
make node-repo    # 快捷方式,刷新节点上的软件源缓存,更新对 Infra 软件仓库的引用
剧本
./deploy.yml -t repo_build,node_repo  # 一次性执行两个任务
./infra.yml -t repo_build     # 重新下载软件包到本地仓库
./node.yml  -t node_repo      # 刷新节点软件源缓存

配置仓库

您也可以选择直接让所有节点都使用上游仓库(生产环境不推荐),跳过下载步骤,直接从互联网 上游扩展仓库 安装

./node.yml -t node_repo -e node_repo_modules=node,pgsql   # 添加 PGDG 与 Pigsty 上游仓库

配置扩展

部分扩展需要预加载到 shared_preload_libraries 才能使用,修改后需要 重启数据库 生效。

您可以用 pg_libs 参数作为它的默认值,在配置预加载的扩展,但是这个参数只在集群初始化时生效,后面修改就无效了。

pg-meta:
  vars:
    pg_cluster: pg-meta
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'   # 预加载扩展
    pg_extensions: [ timescaledb, postgis, pgvector ]          # 安装扩展包

对于已有集群,您可以参考 修改配置 的介绍,修改 shared_preload_libraries 参数:

pg edit-config pg-meta --force -p shared_preload_libraries='timescaledb, pg_stat_statements, auto_explain'
pg restart pg-meta   # 修改 pg-meta 集群的参数,并重启集群使配置生效

请确保扩展软件包已正确安装后再添加预加载配置,如果 shared_preload_libraries 中的扩展不存在或加载失败,PostgreSQL 将 无法启动。 此外,请通过 Patroni 管理集群的配置变更,避免使用 ALTER SYSTEM 或者 pg_parameters 单独修改实例配置。 如果主库和从库配置不一致,可能导致启动失败或复制中断。


启用扩展

安装扩展软件包后,需要在数据库中执行 CREATE EXTENSION 才能使用扩展提供的功能。

集群初始化时启用

数据库定义 中通过 extensions 数组声明要启用的扩展:

pg_databases:
  - name: meta
    extensions:
      - vector                             # 简单形式
      - { name: postgis, schema: public }  # 指定 Schema

手动启用

SQL
CREATE EXTENSION vector;                      -- 创建扩展
CREATE EXTENSION postgis SCHEMA public;       -- 指定 Schema
CREATE EXTENSION IF NOT EXISTS vector;        -- 幂等创建
CREATE EXTENSION postgis_topology CASCADE;    -- 自动安装依赖
psql
psql -d meta -c 'CREATE EXTENSION vector;'                  # 在 meta 数据库创建扩展
psql -d meta -c 'CREATE EXTENSION postgis SCHEMA public;'   # 指定 Schema
剧本
# 修改数据库定义后使用剧本启用扩展
bin/pgsql-db pg-meta meta    # 创建/修改数据库会自动启用定义的扩展

执行效果:在数据库中创建扩展对象(函数、类型、操作符、索引方法等),之后即可使用扩展提供的功能。


更新扩展

扩展更新涉及两个层面:软件包更新扩展对象更新

更新软件包

pig
pig update pgvector                           # 使用 pig 更新扩展
yum
sudo yum update pgvector_18 # EL
apt
sudo apt upgrade postgresql-18-pgvector  # Debian/Ubuntu

更新扩展对象

-- 查看可升级的扩展
SELECT name, installed_version, default_version FROM pg_available_extensions
WHERE installed_version IS NOT NULL AND installed_version <> default_version;

-- 更新扩展到最新版本
ALTER EXTENSION vector UPDATE;

-- 更新到指定版本
ALTER EXTENSION vector UPDATE TO '0.8.1';
更新注意事项

更新扩展前建议备份数据库。预加载扩展更新后可能需要重启 PostgreSQL。某些扩展版本升级可能不兼容,请查阅扩展文档。


移除扩展

移除扩展涉及两个层面:删除扩展对象卸载软件包

删除扩展对象

DROP EXTENSION vector;              -- 删除扩展
DROP EXTENSION vector CASCADE;      -- 级联删除(删除依赖对象)

移除预加载

如果是预加载扩展,需从 shared_preload_libraries 中移除并重启:

pg edit-config pg-meta --force -p shared_preload_libraries='pg_stat_statements, auto_explain'
pg restart pg-meta   # 重启使配置生效

卸载软件包(可选)

pig
pig remove pgvector                           # 使用 pig 卸载
yum
sudo yum remove pgvector_18*                  # EL 系统
apt
sudo apt remove postgresql-18-pgvector        # Debian/Ubuntu
CASCADE 警告

使用 CASCADE 删除扩展会同时删除所有依赖该扩展的对象(表、索引、视图等)。请先检查依赖关系再执行删除。


查询扩展

以下是一些常用的 SQL 查询,用于查看扩展信息:

查看已启用的扩展

SELECT extname, extversion, nspname AS schema
FROM pg_extension e JOIN pg_namespace n ON e.extnamespace = n.oid
ORDER BY extname;

查看可用扩展

SELECT name, default_version, installed_version, comment
FROM pg_available_extensions
WHERE installed_version IS NOT NULL   -- 仅显示已安装的
ORDER BY name;

检查扩展是否可用

SELECT * FROM pg_available_extensions WHERE name = 'vector';

查看扩展依赖关系

SELECT e.extname, d.refobjid::regclass AS depends_on
FROM pg_extension e
JOIN pg_depend d ON d.objid = e.oid
WHERE d.deptype = 'e' AND e.extname = 'postgis_topology';

查看扩展对象

SELECT classid::regclass, objid, deptype
FROM pg_depend
WHERE refobjid = (SELECT oid FROM pg_extension WHERE extname = 'vector');

psql 快捷命令

\dx                    # 列出已启用的扩展
\dx+ vector            # 显示扩展详情

添加仓库

如需直接从上游安装扩展,可手动添加软件仓库。

使用 Pigsty 剧本添加

./node.yml -t node_repo -e node_repo_modules=node,pgsql        # 添加 PGDG 与 Pigsty 仓库
./node.yml -t node_repo -e node_repo_modules=node,pgsql,local  # 包括本地仓库

YUM 仓库(EL 系统)

# Pigsty 仓库
curl -fsSL https://repo.pigsty.io/key | sudo tee /etc/pki/rpm-gpg/RPM-GPG-KEY-pigsty >/dev/null
curl -fsSL https://repo.pigsty.io/yum/repo | sudo tee /etc/yum.repos.d/pigsty.repo >/dev/null

# 中国大陆镜像
curl -fsSL https://repo.pigsty.cc/key | sudo tee /etc/pki/rpm-gpg/RPM-GPG-KEY-pigsty >/dev/null
curl -fsSL https://repo.pigsty.cc/yum/repo | sudo tee /etc/yum.repos.d/pigsty.repo >/dev/null

APT 仓库(Debian/Ubuntu)

curl -fsSL https://repo.pigsty.io/key | sudo gpg --dearmor -o /etc/apt/keyrings/pigsty.gpg
sudo tee /etc/apt/sources.list.d/pigsty.list > /dev/null <<EOF
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.io/apt/infra generic main
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.io/apt/pgsql $(lsb_release -cs) main
EOF
sudo apt update

# 中国大陆镜像:将 repo.pigsty.io 替换为 repo.pigsty.cc

常见问题

扩展名与包名的区别

名称 说明 示例
扩展名 CREATE EXTENSION 使用的名称 vector
包别名 Pigsty 配置中使用的标准化名称 pgvector
包名 操作系统实际的包名 pgvector_18*postgresql-18-pgvector

预加载扩展无法启动

如果 shared_preload_libraries 中的扩展不存在或加载失败,PostgreSQL 将无法启动。解决方法:

  1. 确保扩展软件包已正确安装
  2. 或从 shared_preload_libraries 中移除该扩展(编辑 /pg/data/postgresql.conf

扩展依赖问题

某些扩展依赖于其他扩展,需按顺序创建或使用 CASCADE

CREATE EXTENSION postgis;                    -- 先创建基础扩展
CREATE EXTENSION postgis_topology;           -- 再创建依赖扩展
-- 或
CREATE EXTENSION postgis_topology CASCADE;   -- 自动创建依赖

扩展版本不兼容

查看当前 PostgreSQL 版本支持的扩展版本:

SELECT * FROM pg_available_extension_versions WHERE name = 'vector';

相关资源

8.5 - 备份恢复

配置备份策略与备份仓库,管理备份,执行时间点恢复:pgBackRest 引擎与 Pigsty 封装层的完整实操手册。

Pigsty 使用 pgBackRest 管理 PostgreSQL 备份 —— 这可能是 PostgreSQL 生态中最强大的开源备份工具, 支持增量备份、并行处理、加密、Silo/S3 对象存储等众多特性。 每个 PGSQL 集群默认都预配置了备份与 WAL 归档,开箱即用。

本章是备份恢复的 实操手册:配置方法、管理命令、恢复操作与演练教程。 设计理念与心智模型(为什么、如何权衡)请参阅概念层文档 时间点恢复

所有的备份恢复操作,最终都会落实为 pgBackRest 命令。Pigsty 在它之上提供了三层封装,按需选用:

层次 接口 形态 适用场景
集群编排 pg_pitr 参数 + pgsql-pitr.yml 剧本 Ansible 剧本 生产集群恢复:编排 HA、etcd 与多节点
实例编排 pig pitr 命令行工具 单节点恢复:在数据库节点上直接编排执行
命令原语 pig pb / pb 别名 / pg-backup 脚本 pgBackRest 封装 备份、查询、清理,以及非托管实例的裸恢复
底层引擎 pgbackrest 原生命令 一切封装的最终执行者
章节 内容
机制 pgBackRest 核心概念(stanza / 仓库 / 保留 / 时间线)与 Pigsty 的封装映射
策略 设计备份策略:调度计划、恢复窗口与磁盘空间规划
仓库 配置备份仓库:本地、Silo、外部 S3,加密、版本控制与锁定
管理 备份管理命令手册:启停、手动备份、查看、清理、Stanza 管理
恢复 执行时间点恢复:恢复目标、分步执行、参数参考
克隆 用 PITR 克隆数据库集群:找回数据、恢复演练
示例 沙箱教程:使用 pgBackRest 原语手工执行恢复
免责声明

Pigsty 尽最大努力提供可靠的 PITR 解决方案,但我们不对 PITR 操作导致的数据丢失承担任何责任,使用需自担风险。如需专业支持,请考虑我们的 专业服务

恢复操作会覆盖目标数据

执行 PITR 前必须先核对 pig pg list <目标集群>pig pb info,确认近期可用备份和恢复窗口, 由操作者复述精确的目标集群与恢复点,再执行目标限定的 ./pgsql-pitr.yml -l <目标集群> ...pgsql-pitr.yml 只打印计划,不会暂停等待确认;生产恢复还需要维护窗口和独立验证过的备份。


快速上手

  1. 设计备份策略:用 pg_crontab 声明定时备份计划,用 pgbackrest_repo 选择备份仓库
  2. 管理备份:用 pg-backup 手动备份,用 pb info 查看备份状态
  3. 执行恢复:用 pg_pitr 参数声明恢复目标,运行 pgsql-pitr.yml 剧本
pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ]
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": { "time": "2025-07-13 10:00:00+00", "action": "promote" }}'

8.5.1 - 备份机制

pgBackRest 的概念体系(stanza、仓库、备份链、保留策略、时间线)与 Pigsty 封装层的参数映射:理解每条命令背后发生了什么。

Pigsty 的备份恢复功能,最终都会落实为 pgBackRest 命令的执行。 所以要真正掌握这套系统,需要理解两件事:pgBackRest 本身的概念体系(stanza、仓库、备份链、保留、时间线), 以及 Pigsty 各层封装如何映射到它(参数如何变成命令行选项)。本页依次讲清这两部分。


pgBackRest 核心概念

Stanza:集群的备份身份

Stanza(节)是 pgBackRest 中一套 PostgreSQL 集群备份配置的名称,也是仓库内隔离不同集群的命名空间。 Pigsty 将 stanza 直接映射为集群名 pg_cluster: 集群 pg-meta 的备份就存储在仓库的 backup/pg-meta/archive/pg-meta/ 目录下, 多套集群可以安全共享同一个仓库。

Stanza 记录着源集群的 system-id 与主版本号,写入备份前会核对身份 —— 这正是 克隆集群 后需要 stanza-upgrade 善后的原因。 Stanza 由 stanza-create 创建(Pigsty 在集群初始化时自动完成), 版本升级后用 stanza-upgrade 更新。

仓库:备份存放在哪里

仓库(Repository)是备份与 WAL 归档的存储后端,在配置中以 repo1-* 系列选项定义: repo1-type 决定类型(POSIX 文件系统、S3、Azure、GCS、SFTP),repo1-path 决定路径, repo1-cipher-* 决定加密,repo1-retention-* 决定保留策略。 Pigsty 通过 pgbackrest_repo 参数生成这些配置,详见 备份仓库

备份链与备份标签

pgBackRest 支持三种备份类型,后两种依赖前面的备份构成 备份链

类型 内容 标签后缀
全量备份(full) 完整复制数据库集群 F
差异备份(diff) 相对最近一次 全量 的变化 D
增量备份(incr) 相对最近一次 任意备份 的变化 I

每个备份都有唯一的 备份标签(label),命名规则本身就描述了备份链: 20250715-013657F 是一个全量备份,20250715-013657F_20250715-013724D 是基于它的差异备份, 20250715-013657F_20250715-013730I 是增量备份 —— 下划线前的部分标识它所依附的全量备份。 恢复时用 --set 指定从哪个备份集开始还原,默认自动选择目标时间点前最近的一个。

保留策略:仓库如何不被撑爆

保留策略(Retention)决定旧备份何时被清除。repo1-retention-full 配合 repo1-retention-full-typecount 按份数 / time 按天数)控制全量备份的保留; 全量备份过期时,依附它的差异/增量备份与对应的 WAL 归档一并清除。 Pigsty 默认启用 expire-auto,每次备份完成后自动执行过期清理,也可用 expire 命令手动触发。

time 表示 最短时间窗口,不是“只保留最近 N 天内的全量备份”。只有在仓库中还存在另一份年龄达到 N 天的全量备份时, 更老的全量备份才会过期。因此 retention_full: 14 配合每周全备,稳态会保留三条全量备份链,恢复窗口约为 14~21 天。

WAL 归档:保留下来的历史

PostgreSQL 的 archive_command 在每个 WAL 段写满(或 archive_timeout 超时)后触发, Pigsty 将其配置为 archive-push,把 WAL 推入仓库; 恢复时则由 restore_command 调用 archive-get 按需拉取。 Pigsty 启用了异步归档(archive-async=y),经由 /pg/spool 假脱机目录批量推送,避免归档拖慢主库。

时间线:分叉的历史

每次恢复提升(或故障切换)都会开启一条新的 时间线(Timeline),旧时间线的 WAL 仍保留在仓库中。 恢复时可用 --target-timeline 指定沿哪条时间线重放(默认 latest), 这使得"恢复错了再恢复一次"成为可能。完整心智模型见概念层 工作原理

恢复机制:restore 命令做了什么

理解 restore 命令的行为,就理解了 PITR 的执行过程。它做两件事:

  1. 重建数据目录:从备份集还原数据文件。带 --delta 选项(Pigsty 默认启用)时执行增量还原 —— 校验现有文件,只重写与备份不一致的部分,大幅缩短大库的还原时间。
  2. 写入恢复配置:生成 recovery.signal 标记与恢复参数(restore_commandrecovery_target_*), 使 PostgreSQL 下次启动时进入恢复模式,从仓库拉取 WAL 重放至目标点。

因此 restore 命令返回成功只是完成了一半:真正的恢复发生在 PostgreSQL 启动之后的 WAL 重放阶段。 重放到达目标后的行为由 --target-action 决定:pause 暂停等待检查、promote 提升开启新时间线、shutdown 停机。

恢复目标的参数组合是固定句式:--type 指定目标类型,--target 给出目标值, 可选的 --target-exclusive 控制边界、--target-timeline 选择时间线、--set 指定起点备份:

pgbackrest --stanza=pg-meta restore                                        # 恢复到 WAL 归档末尾
pgbackrest --stanza=pg-meta --type=immediate restore                       # 恢复到最近一致点
pgbackrest --stanza=pg-meta --type=time --target='2025-07-13 10:00:00+00' restore
pgbackrest --stanza=pg-meta --type=xid  --target='250000' --target-exclusive restore
pgbackrest --stanza=pg-meta --type=name --target='my-restore-point' restore
pgbackrest --stanza=pg-meta --type=lsn  --target='0/4001C80' --target-action=promote restore

实际观察

您可以使用 pg_dbsu 用户(默认 postgres)直接执行 pgbackrest 命令, 观察上述概念的实际形态 —— 注意备份标签的命名、备份大小的差异,以及 info 输出中的备份链引用关系:

备份命令

full
$ pgbackrest --stanza=pg-meta --type=full backup
2025-07-15 01:36:57.007 P00   INFO: backup command begin 2.54.2: --annotation=pg_cluster=pg-meta ...
2025-07-15 01:36:57.030 P00   INFO: execute non-exclusive backup start: backup begins after the requested immediate checkpoint completes
2025-07-15 01:36:57.105 P00   INFO: backup start archive = 000000010000000000000006, lsn = 0/6000028
2025-07-15 01:36:58.540 P00   INFO: new backup label = 20250715-013657F
2025-07-15 01:36:58.588 P00   INFO: full backup size = 44.5MB, file total = 1437
2025-07-15 01:36:58.589 P00   INFO: backup command end: completed successfully (1584ms)
diff
$ pgbackrest --stanza=pg-meta --type=diff backup
2025-07-15 01:37:24.952 P00   INFO: backup command begin 2.54.2: ...
2025-07-15 01:37:24.985 P00   INFO: last backup label = 20250715-013657F, version = 2.54.2
2025-07-15 01:37:26.337 P00   INFO: new backup label = 20250715-013657F_20250715-013724D
2025-07-15 01:37:26.381 P00   INFO: diff backup size = 424.3KB, file total = 1437
2025-07-15 01:37:26.381 P00   INFO: backup command end: completed successfully (1431ms)
incr
$ pgbackrest --stanza=pg-meta --type=incr backup
2025-07-15 01:37:30.305 P00   INFO: backup command begin 2.54.2: ...
2025-07-15 01:37:30.337 P00   INFO: last backup label = 20250715-013657F_20250715-013724D, version = 2.54.2
2025-07-15 01:37:31.356 P00   INFO: new backup label = 20250715-013657F_20250715-013730I
2025-07-15 01:37:31.403 P00   INFO: incr backup size = 8.3KB, file total = 1437
2025-07-15 01:37:31.403 P00   INFO: backup command end: completed successfully (1099ms)
info
$ pgbackrest --stanza=pg-meta info
stanza: pg-meta
    status: ok
    cipher: aes-256-cbc

    db (current)
        wal archive min/max (17): 000000010000000000000001/00000001000000000000000A

        full backup: 20250715-013657F
            timestamp start/stop: 2025-07-15 01:36:57+00 / 2025-07-15 01:36:58+00
            wal start/stop: 000000010000000000000006 / 000000010000000000000006
            database size: 44.5MB, database backup size: 44.5MB
            repo1: backup size: 8.7MB

        diff backup: 20250715-013657F_20250715-013724D
            timestamp start/stop: 2025-07-15 01:37:24+00 / 2025-07-15 01:37:26+00
            database size: 44.5MB, database backup size: 424.3KB
            repo1: backup size: 94KB
            backup reference total: 1 full

        incr backup: 20250715-013657F_20250715-013730I
            timestamp start/stop: 2025-07-15 01:37:30+00 / 2025-07-15 01:37:31+00
            database size: 44.5MB, database backup size: 8.3KB
            repo1: backup size: 504B
            backup reference total: 1 full, 1 diff

Pigsty 的封装层次

在原生命令之上,Pigsty 提供了逐层升高的封装,每一层都只是对下一层的参数化调用,没有黑魔法:

层次 接口 它实际做什么
集群编排 pg_pitr + pgsql-pitr.yml 编排整个集群的恢复:暂停 HA → 停库 → 渲染配置并调用 pgbackrest restore → 输出控制信息 → 清理 etcd → 拉起 HA
实例编排 pig pitr 单节点编排:预检 → 停 Patroni/PG → 调用 pgbackrest restore → 可选启动 PG,Patroni 保持停止
命令原语 pig pb / pb 别名 / pg-backup 自动填充 --stanza 与 DBSU 身份,转发给 pgbackrest 对应子命令
底层引擎 pgbackrest 读取 /etc/pgbackrest/pgbackrest.conf,实际执行备份/归档/恢复

命令原语层

pb 是登录 shell 内置的别名函数:从配置文件解析出 stanza 后转发,让您少敲一个参数:

pb() (
    stanza=$(grep -o '\[[^][]*]' /etc/pgbackrest/pgbackrest.conf | head -n1 | sed 's/.*\[\([^]]*\)].*/\1/')
    pgbackrest --stanza="${stanza}" "$@"
)
pb info     # = pgbackrest --stanza=pg-meta info
pb backup   # = pgbackrest --stanza=pg-meta backup

pg-backup 脚本在此基础上增加了 角色检查(只在主库执行,从库直接退出),供 crontab 安全调用:

pg-backup full   # = pgbackrest --stanza=pg-meta --type=full backup(仅主库执行)
pg-backup diff   # = pgbackrest --stanza=pg-meta --type=diff backup
pg-backup incr   # = pgbackrest --stanza=pg-meta --type=incr backup(默认,无全量时自动升级为全量)

pig pb 提供了更完善的封装:自动检测 stanza、自动以 DBSU 身份执行(root 下 su、普通用户 sudo)、 备份前检查主库角色、恢复前显示执行计划并要求确认。完整子命令表见 管理命令

参数如何映射

Pigsty 恢复接口的每个参数,都对应一个 pgbackrest 选项 —— 三层接口共用同一套语义:

pg_pitr 字段 pig pitr 选项 pgbackrest 选项 含义
cluster --stanza --stanza 从哪个集群的备份恢复(源 stanza)
type + time/xid/lsn/name --time/--xid/--lsn/--name --type + --target 恢复目标
(type: default) --default 不传 --type/--target 重放到 WAL 归档末尾
(type: immediate) --immediate --type=immediate 恢复到最近一致点
exclusive --exclusive / -X --target-exclusive 停在目标之前(排除目标点)
action --target-action --target-action 到达目标后:pause / promote / shutdown
timeline --target-timeline / -T --target-timeline 目标时间线,默认 latest
set --set / -b --set 从哪个备份集开始还原
db_include / db_exclude --db-include / --db-exclude 选择性恢复部分数据库
link_map --link-map 表空间/目录软链接映射
process process-max 恢复并行进程数
data --data / -D --pg1-path 恢复到哪个数据目录
repo repo1-*(渲染临时配置) 覆盖备份仓库定义;pig pitr --repo 仅选择现有配置中的仓库编号

选择性恢复仍是物理恢复:未包含或被排除的数据库会以稀疏清零文件还原,以便 PostgreSQL 完成恢复,但这些数据库本身不可访问, 恢复后需要显式删除。它不是 pg_dump 那样的逻辑子集恢复。

配置如何渲染

pgbackrest_repo 中被 pgbackrest_method 选中的仓库定义,会按简单规则渲染进 /etc/pgbackrest/pgbackrest.conf: 键名的下划线替换为连字符,加上 repo1- 前缀 —— 因此 pgBackRest 支持的仓库级配置项 可以直接写入参数:

pgbackrest_repo:
  minio:
    type: s3                  # ----> repo1-type=s3
    s3_endpoint: sss.pigsty   # ----> repo1-s3-endpoint=sss.pigsty
    cipher_type: aes-256-cbc  # ----> repo1-cipher-type=aes-256-cbc
    retention_full: 14        # ----> repo1-retention-full=14

执行 pgsql-pitr.yml 时,Pigsty 会另行渲染一份临时配置 /pg/conf/pitr.conf(避免污染常规配置), 该剧本启动恢复期间的 PostgreSQL 日志写入 /pg/tmp/recovery.log


定时备份

Pigsty 使用 Linux crontab 调度备份任务:pg_crontab 参数中的条目 会写入 postgres 用户的 crontab。因为 pg-backup 自带角色检查,同一份 crontab 可以下发到集群所有节点 —— 故障切换后,新主库会自动接续后续定时备份。

pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ]
pg_crontab:
  - '00 01 * * 1 /pg/bin/pg-backup full'
  - '00 01 * * 2,3,4,5,6,7 /pg/bin/pg-backup'

修改后用剧本应用变更:

./pgsql.yml -t pg_crontab -l pg-meta    # 更新 pg-meta 集群的 crontab

如何选择备份频率与保留策略,请参阅 备份策略


部署细节

pgBackRest 组件在 pgsql.yml 剧本中完成安装与配置:

  • pg_packages 中的 pgsql-common 组安装,二进制位于 /usr/bin/pgbackrest
  • pg_backup 子任务负责渲染配置、创建 stanza;由 pgbackrest_enabled 控制(默认启用)
  • 集群初始化后默认尝试执行一次 初始全量备份,且只在备份成功后留下 /etc/pgbackrest/initial.done 标记防止重复; 由 pgbackrest_init_backup 控制

文件层次

路径 用途
/usr/bin/pgbackrest 二进制,来自 PGDG 仓库的 pgbackrest
/etc/pgbackrest/pgbackrest.conf 主配置文件(stanza + 仓库定义)
/pg/backup 本地仓库数据目录(local 仓库时使用)
/pg/spool 异步归档的假脱机目录
/pg/log/pgbackrest/ 备份/归档/恢复日志,pgbackrest_log_dir
/pg/conf/pitr.conf PITR 过程中的临时 pgbackrest 配置
/pg/tmp/recovery.log PITR 过程中的 PostgreSQL 恢复日志

监控

每个节点运行 pgbackrest_exporter 服务(端口 pgbackrest_exporter_port9854), 将备份状态导出为监控指标(参见 pgBackRest 监控指标)。 可通过 pgbackrest_exporter_options 定制, 或将 pgbackrest_exporter_enabled 设为 false 禁用。

8.5.2 - 备份策略

设计并配置备份策略:备份频率决定恢复速度,保留策略决定恢复窗口与空间占用,两张推演图帮您做出量化决策。

备份策略要回答三个问题:何时 备份(调度计划)、何处 存放(备份仓库)、 保留多久(保留策略)。本页给出两套久经考验的预设策略及其量化推演 —— 背后的权衡逻辑请参阅概念层文档 策略权衡

备份频率与恢复速度直接相关:恢复时需要从最近的基础备份开始重放 WAL 日志到目标时间点, 备份越频繁,需要重放的 WAL 越少,恢复越快;而保留策略与仓库空间直接相关:窗口越长,占用空间越大。


每日全量备份

对于生产数据库,建议从最简单的每日全量备份策略开始。Pigsty 随附的标准 pigsty.yml 集群示例采用这一策略, 配合默认的 local 本地仓库(保留最近 2 个全量备份)使用:

pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ]
pgbackrest_method: local          # 选择备份仓库方法:`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             # 使用本地文件系统仓库时,保留2个,最多3个全量备份

假设您的数据库大小为 100GB,每天写入 10GB 数据,备份耗时 1 小时。 下图将「恢复窗口」与「存储空间占用」合并到同一时间轴(0~108h)上推演该策略的稳态行为: 恢复窗口在 24~48 小时 之间循环,备份占用约为 2 个全量备份加上 1~2 天的 WAL 归档。 在实践中,您需要准备至少 3~5 倍 数据库大小的备份磁盘,才能从容使用该默认策略。

tooltip: { trigger: axis, formatter: $fn:tipMerged, axisPointer: { type: line, snap: true, label: { show: false } } }
axisPointer: { link: [ { xAxisIndex: [0, 1] } ] }
legend: { show: false, bottom: 10, itemGap: 18, data: ["首要备份", "次要备份", "WAL归档", "瞬时备份"] }
grid:
  - { left: 82, right: "10%", top: 42, height: 218, containLabel: false }
  - { left: 82, right: "10%", top: 286, height: 218, containLabel: false }
xAxis:
  - type: category
    gridIndex: 0
    position: bottom
    boundaryGap: false
    data: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108]
    name: 时间 h
    nameLocation: end
    nameGap: 10
    nameTextStyle: { align: left, verticalAlign: top, padding: [8, 0, 0, 0] }
    axisLabel: { interval: 11, formatter: $fn:fmtHour }
    axisLine: { show: true, symbol: [none, arrow], symbolSize: [10, 14], lineStyle: { width: 1.6, color: "#4b5563" } }
    axisTick: { show: true, length: 6 }
    splitLine: { show: true, lineStyle: { type: dashed, width: 1, opacity: 0.28, color: "#9ca3af" } }
    minorTick: { show: true, splitNumber: 12, length: 3 }
    minorSplitLine: { show: true, lineStyle: { type: dotted, width: 1, opacity: 0.14, color: "#9ca3af" } }
  - type: category
    gridIndex: 1
    position: top
    boundaryGap: true
    data: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108]
    axisLabel: { show: false }
    axisLine: { show: true, lineStyle: { width: 1.6, color: "#4b5563" } }
    axisTick: { show: true, length: 6 }
    splitLine: { show: true, lineStyle: { type: dashed, width: 1, opacity: 0.22, color: "#9ca3af" } }
yAxis:
  - type: value
    gridIndex: 0
    min: 0
    max: 52
    interval: 5
    name: 恢复窗口 h
    nameLocation: end
    nameRotate: 0
    nameGap: 8
    nameTextStyle: { align: left, verticalAlign: bottom, padding: [0, 0, 8, 4] }
    axisLabel: { formatter: $fn:fmtWin }
    axisLine: { show: true, symbol: [none, arrow], symbolSize: [10, 14], lineStyle: { width: 1.6, color: "#4b5563" } }
    axisTick: { show: true, length: 6 }
    splitLine: { show: true, lineStyle: { type: dashed, width: 1, opacity: 0.35, color: "#9ca3af" } }
    minorTick: { show: true, splitNumber: 5, length: 3 }
    minorSplitLine: { show: true, lineStyle: { type: dotted, width: 1, opacity: 0.18, color: "#9ca3af" } }
  - type: value
    gridIndex: 1
    min: 0
    max: 350
    interval: 50
    inverse: true
    name: 存储空间 GB
    nameLocation: end
    nameRotate: 0
    nameGap: 8
    nameTextStyle: { align: left, verticalAlign: top, padding: [10, 0, 0, 4] }
    axisLabel: { formatter: $fn:fmtGbTick }
    axisLine: { show: true, symbol: [arrow, none], symbolSize: [10, 14], lineStyle: { width: 1.6, color: "#4b5563" } }
    axisTick: { show: true, length: 6 }
    splitLine: { show: true, lineStyle: { type: dashed, width: 1, opacity: 0.32, color: "#9ca3af" } }
series: [ { name: 恢复窗口, type: line, smooth: false, symbol: none, showSymbol: false, xAxisIndex: 0, yAxisIndex: 0, lineStyle: { width: 3, color: "#f2a000" }, itemStyle: { color: "#f2a000" }, data: [[0,0],[1,0],[2,1],[3,2],[4,3],[5,4],[6,5],[7,6],[8,7],[9,8],[10,9],[11,10],[12,11],[13,12],[14,13],[15,14],[16,15],[17,16],[18,17],[19,18],[20,19],[21,20],[22,21],[23,22],[24,23],[25,24],[26,25],[27,26],[28,27],[29,28],[30,29],[31,30],[32,31],[33,32],[34,33],[35,34],[36,35],[37,36],[38,37],[39,38],[40,39],[41,40],[42,41],[43,42],[44,43],[45,44],[46,45],[47,46],[48,47],[49,48],[49,24],[50,25],[51,26],[52,27],[53,28],[54,29],[55,30],[56,31],[57,32],[58,33],[59,34],[60,35],[61,36],[62,37],[63,38],[64,39],[65,40],[66,41],[67,42],[68,43],[69,44],[70,45],[71,46],[72,47],[73,48],[73,24],[74,25],[75,26],[76,27],[77,28],[78,29],[79,30],[80,31],[81,32],[82,33],[83,34],[84,35],[85,36],[86,37],[87,38],[88,39],[89,40],[90,41],[91,42],[92,43],[93,44],[94,45],[95,46],[96,47],[97,48],[97,24],[98,25],[99,26],[100,27],[101,28],[102,29],[103,30],[104,31],[105,32],[106,33],[107,34],[108,35]], markLine: { symbol: none, label: { show: false }, data: [ { xAxis: 0, lineStyle: { color: "#59a14f", type: "solid", width: 1.4, opacity: 0.75 } }, { xAxis: 24, lineStyle: { color: "#59a14f", type: "solid", width: 1.4, opacity: 0.75 } }, { xAxis: 48, lineStyle: { color: "#59a14f", type: "solid", width: 1.4, opacity: 0.75 } }, { xAxis: 72, lineStyle: { color: "#59a14f", type: "solid", width: 1.4, opacity: 0.75 } }, { xAxis: 96, lineStyle: { color: "#59a14f", type: "solid", width: 1.4, opacity: 0.75 } }, { xAxis: 1, lineStyle: { color: "#336791", type: "solid", width: 1.4, opacity: 0.8 } }, { xAxis: 25, lineStyle: { color: "#336791", type: "solid", width: 1.4, opacity: 0.8 } }, { xAxis: 49, lineStyle: { color: "#336791", type: "solid", width: 1.4, opacity: 0.8 } }, { xAxis: 73, lineStyle: { color: "#336791", type: "solid", width: 1.4, opacity: 0.8 } }, { xAxis: 97, lineStyle: { color: "#336791", type: "solid", width: 1.4, opacity: 0.8 } }, { yAxis: 24, label: { show: true, formatter: "稳态下限 24h", position: "end", distance: 12, color: "#2563eb" }, lineStyle: { color: "#2563eb", type: "dashdot", width: 1.4, opacity: 0.75 } }, { yAxis: 48, label: { show: true, formatter: "窗口峰值 48h", position: "end", distance: 12, color: "#7c3aed" }, lineStyle: { color: "#7c3aed", type: "dashdot", width: 1.4, opacity: 0.75 } } ] } }, { name: 首要备份, type: bar, stack: used, xAxisIndex: 1, yAxisIndex: 1, barWidth: 5, itemStyle: { color: "#59a14f" }, data: [0,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100] }, { name: 次要备份, type: bar, stack: used, xAxisIndex: 1, yAxisIndex: 1, barWidth: 5, itemStyle: { color: "#4e79a7" }, data: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100] }, { name: WAL归档, type: bar, stack: used, xAxisIndex: 1, yAxisIndex: 1, barWidth: 5, itemStyle: { color: "#edc949" }, data: [0,0.42,0.83,1.25,1.67,2.08,2.5,2.92,3.33,3.75,4.17,4.58,5,5.42,5.83,6.25,6.67,7.08,7.5,7.92,8.33,8.75,9.17,9.58,10,10.42,10.83,11.25,11.67,12.08,12.5,12.92,13.33,13.75,14.17,14.58,15,15.42,15.83,16.25,16.67,17.08,17.5,17.92,18.33,18.75,19.17,19.58,20,10.42,10.83,11.25,11.67,12.08,12.5,12.92,13.33,13.75,14.17,14.58,15,15.42,15.83,16.25,16.67,17.08,17.5,17.92,18.33,18.75,19.17,19.58,20,10.42,10.83,11.25,11.67,12.08,12.5,12.92,13.33,13.75,14.17,14.58,15,15.42,15.83,16.25,16.67,17.08,17.5,17.92,18.33,18.75,19.17,19.58,20,10.42,10.83,11.25,11.67,12.08,12.5,12.92,13.33,13.75,14.17,14.58,15] }, { name: 瞬时备份, type: bar, stack: used, xAxisIndex: 1, yAxisIndex: 1, barWidth: 5, itemStyle: { color: "#9ca3af", opacity: 0.75 }, data: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0] } ]

全量 + 增量备份

如果使用 Silo / S3 作为集中式备份仓库,存储空间不再受本地磁盘限制, 此时可以用「周全量 + 每日增量」配合两周保留策略,换取更长的恢复窗口:

pg_crontab:  # 周一凌晨1点全量备份,其余每日增量备份
  - '00 01 * * 1           /pg/bin/pg-backup full'
  - '00 01 * * 2,3,4,5,6,7 /pg/bin/pg-backup'
pgbackrest_method: minio
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository
  minio:                          # 可选的 minio 仓库
    type: s3                      # minio 兼容 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  # 对象存储用户密钥
    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`
    block: y                      # 启用块级增量备份
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包大小限制,对象存储建议 20MiB
    bundle_size: 128MiB           # 文件包目标大小,对象存储建议 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # 仓库加密密码
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 按时间保留 14 天

同样假设数据库 100GB、每日增量与 WAL 均按 10GB 粗估,下图推演 30 天内恢复窗口与存储占用的变化: retention_full_type: time 会确保至少留下一份年龄达到 14 天的全量备份,周全备时恢复窗口在 14~21 天 之间循环。 按这组未压缩假设,稳态占用约为 560~690GB,新全量完成、旧链过期前的瞬时峰值约为 790GB; 实际占用取决于 WAL 量、块级增量命中率与 zstd 压缩率。

tooltip: { trigger: axis, formatter: $fn:tipMerged30, axisPointer: { type: line, snap: true, label: { show: false } } }
axisPointer: { link: [ { xAxisIndex: [0, 1] } ] }
legend: { show: false, bottom: 10, itemGap: 18, data: ["基础全量", "追加全量", "增量备份", "WAL归档"] }
grid:
  - { left: 82, right: "10%", top: 42, height: 218, containLabel: false }
  - { left: 82, right: "10%", top: 302, height: 218, containLabel: false }
xAxis:
  - type: value
    gridIndex: 0
    position: bottom
    boundaryGap: false
    min: 0
    max: 31
    interval: 1
    name: 时间
    nameLocation: end
    nameGap: 10
    nameTextStyle: { align: left, verticalAlign: top, padding: [8, 0, 0, 0] }
    axisLabel: { formatter: $fn:fmtDay30 }
    axisLine: { show: true, symbol: [none, arrow], symbolSize: [10, 14], lineStyle: { width: 1.6, color: "#4b5563" } }
    axisTick: { show: true, length: 6 }
    splitLine: { show: true, lineStyle: { type: dashed, width: 1, opacity: 0.28, color: "#9ca3af" } }
    minorTick: { show: true, splitNumber: 4, length: 3 }
    minorSplitLine: { show: true, lineStyle: { type: dotted, width: 1, opacity: 0.14, color: "#9ca3af" } }
  - type: category
    gridIndex: 1
    position: top
    boundaryGap: true
    z: 10
    data: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
    axisLabel: { show: false }
    axisLine: { show: true, lineStyle: { width: 1.6, color: "#4b5563" } }
    axisTick: { show: true, alignWithLabel: true, length: 6 }
    splitLine: { show: true, lineStyle: { type: dashed, width: 1, opacity: 0.22, color: "#9ca3af" } }
yAxis:
  - type: value
    gridIndex: 0
    min: 0
    max: 576
    interval: 72
    name: 恢复窗口 h
    nameLocation: end
    nameRotate: 0
    nameGap: 8
    nameTextStyle: { align: left, verticalAlign: bottom, padding: [0, 0, 8, 4] }
    axisLabel: { formatter: $fn:fmtWin30 }
    axisLine: { show: true, symbol: [none, arrow], symbolSize: [10, 14], lineStyle: { width: 1.6, color: "#4b5563" } }
    axisTick: { show: true, length: 6 }
    splitLine: { show: true, lineStyle: { type: dashed, width: 1, opacity: 0.35, color: "#9ca3af" } }
    minorTick: { show: true, splitNumber: 4, length: 3 }
    minorSplitLine: { show: true, lineStyle: { type: dotted, width: 1, opacity: 0.18, color: "#9ca3af" } }
  - type: value
    gridIndex: 1
    min: 0
    max: 800
    interval: 100
    inverse: true
    z: 10
    name: 存储空间 GB
    nameLocation: end
    nameRotate: 0
    nameGap: 8
    nameTextStyle: { align: left, verticalAlign: top, padding: [10, 0, 0, 4] }
    axisLabel: { formatter: $fn:fmtGbTick30 }
    axisLine: { show: true, symbol: [arrow, none], symbolSize: [10, 14], lineStyle: { width: 1.6, color: "#4b5563" } }
    axisTick: { show: true, length: 6 }
    splitLine: { show: true, lineStyle: { type: dashed, width: 1, opacity: 0.32, color: "#9ca3af" } }
series:
  - { name: 恢复窗口, type: line, smooth: false, symbol: none, showSymbol: false, xAxisIndex: 0, yAxisIndex: 0, lineStyle: { width: 3, color: "#f28e2c" }, itemStyle: { color: "#f28e2c" }, data: [[1,0],[2,24],[3,48],[4,72],[5,96],[6,120],[7,144],[8,168],[9,192],[10,216],[11,240],[12,264],[13,288],[14,312],[15,336],[16,360],[17,384],[18,408],[19,432],[20,456],[21,480],[22,504],[22,336],[23,360],[24,384],[25,408],[26,432],[27,456],[28,480],[29,504],[29,336],[30,360]], markLine: { symbol: none, label: { show: false }, data: [ { xAxis: 1, lineStyle: { color: "#336791", type: "solid", width: 1.4, opacity: 0.65 } }, { xAxis: 8, lineStyle: { color: "#336791", type: "solid", width: 1.4, opacity: 0.65 } }, { xAxis: 15, lineStyle: { color: "#336791", type: "solid", width: 1.4, opacity: 0.65 } }, { xAxis: 22, lineStyle: { color: "#336791", type: "solid", width: 1.4, opacity: 0.65 } }, { xAxis: 29, lineStyle: { color: "#336791", type: "solid", width: 1.4, opacity: 0.65 } }, { yAxis: 336, label: { show: true, formatter: "窗口下限 14d", position: "end", distance: 12, color: "#2563eb" }, lineStyle: { color: "#2563eb", type: "dashdot", width: 1.4, opacity: 0.72 } }, { yAxis: 504, label: { show: true, formatter: "窗口上限 21d", position: "end", distance: 12, color: "#7c3aed" }, lineStyle: { color: "#7c3aed", type: "dashdot", width: 1.4, opacity: 0.72 } } ] } }
  - { name: 基础全量, type: bar, stack: used, xAxisIndex: 1, yAxisIndex: 1, barWidth: 16, itemStyle: { color: "#59a14f" }, data: [100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100] }
  - { name: 追加全量, type: bar, stack: used, xAxisIndex: 1, yAxisIndex: 1, barWidth: 16, itemStyle: { color: "#4e79a7" }, data: [0,0,0,0,0,0,0,100,100,100,100,100,100,100,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200] }
  - { name: 增量备份, type: bar, stack: used, xAxisIndex: 1, yAxisIndex: 1, barWidth: 16, itemStyle: { color: "#76b7b2" }, data: [0,10,20,30,40,50,60,60,70,80,90,100,110,120,120,130,140,150,160,170,180,120,130,140,150,160,170,180,120,130] }
  - { name: WAL归档, type: bar, stack: used, xAxisIndex: 1, yAxisIndex: 1, barWidth: 16, itemStyle: { color: "#edc949" }, data: [0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,140,150,160,170,180,190,200,140,150] }

空间规划

两套策略的空间需求可以按以下经验公式粗估(实际占用受压缩与块级增量影响,通常更低):

策略 恢复窗口 空间粗估 建议预留
每日全量,保留 2 份(local) 24~48 小时 2 × 全量 + 1~2 天 WAL 数据库大小的 3~5 倍
周全量 + 日增量,按时间保留 14 天(minio) 14~21 天 3 × 全量 + 12~18 份增量 + 14~21 天 WAL 按实测压缩率与 WAL 量规划

注意 瞬时峰值:新的全量备份成功完成后,旧备份才会参与过期计算,因此仓库会短暂多出一份全量备份, 同时保留尚未清理的旧备份链与 WAL。空间规划必须覆盖这个峰值而非只看清理后的稳态。

WAL 归档的增长与写入负载成正比。批量导数、VACUUM FULL、大规模 UPDATE 都会瞬间产生大量 WAL, 如果备份仓库空间紧张,请在此类操作前后关注仓库水位(监控指标 开箱即用)。


应用策略变更

备份策略的三类变更,分别用对应的剧本任务应用:

./pgsql.yml -t pg_crontab -l pg-meta    # 变更调度计划(pg_crontab)后:更新 crontab
./pgsql.yml -t pg_backup  -l pg-meta    # 变更仓库定义(pgbackrest_repo / pgbackrest_method)后:重新渲染配置并初始化 stanza
pg-backup full                          # 切换仓库后:立即执行一次全量备份,建立新仓库中的恢复起点

注意:切换 pgbackrest_method 到新仓库后,旧仓库中的备份不会自动迁移; 在新仓库完成首次全量备份之前,恢复窗口存在缺口。

8.5.3 - 备份仓库

配置备份存储仓库:本地磁盘、Silo 与外部 S3 对象存储,保留策略、加密、版本控制与对象锁定。

备份存储在哪里,由两个参数决定:pgbackrest_repo 定义所有候选仓库, pgbackrest_method 选择实际使用哪一个。 仓库定义中的键值会 按固定规则 渲染为 pgbackrest 的 repo1-* 配置项, 因此 pgBackRest 支持的任何仓库选项 都可以直接写入。 v4.5.0 每次只把 pgbackrest_method 选中的一个字典项渲染为 repo1;候选项同时存在并不等于多仓备份。


默认仓库

Pigsty 预置了两个仓库定义:localminio

  • local默认选项,使用本地 /pg/backup 目录(软链接指向 pg_fs_backup/data/backups
  • minio:使用 MINIO 模块部署的 Silo 或任意 S3 兼容对象存储(Pigsty 支持,默认不启用)
pgbackrest_method: local          # 选择备份仓库方法:`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             # 使用本地文件系统仓库时,保留2个,最多3个全量备份
  minio:                          # 可选的 minio 仓库
    type: s3                      # minio 兼容 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`
    block: y                      # 启用块级增量备份
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包大小限制,对象存储建议 20MiB
    bundle_size: 128MiB           # 文件包目标大小,对象存储建议 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 按时间保留 14 天

两套仓库的预置策略有意不同:local 不加密、不打包、按份数保留,追求简单与恢复速度; minio 加密(AES-256-CBC)、打包(bundle)、块级增量(block)、按时间保留两周,面向生产容灾。

生产环境请修改默认密码

使用远程仓库时,请务必修改默认的 cipher_pass 加密密码与 s3_key_secret 访问密钥。 示例中的 pgBackRestS3User.Backup 是公开默认值,不能直接用于生产环境。 加密密码一旦遗失,仓库中的备份将无法解密恢复 —— 请与备份分开妥善保管,具体要求参阅 部署安全


保留策略

如果只备份不清理,仓库迟早被撑爆。保留策略在仓库定义中声明,由 pgBackRest 在每次备份后自动执行清理 (全量备份过期时,依附它的差异/增量备份与对应 WAL 归档一并清除):

  • retention_full_type: count + retention_full: 2:按份数保留 —— 保留最近 2 个全量备份(新备份完成前短暂存在第 3 个)
  • retention_full_type: time + retention_full: 14:按时间保留 —— 至少留下一份年龄达到 14 天的全量备份后,才会删除更老的备份

保留策略与恢复窗口、空间占用的量化关系,请参阅 备份策略; 手动清理过期备份的方法,请参阅 管理命令


使用 Silo 仓库

MINIO 模块 当前部署 Silo S3 兼容对象存储。 只有把对象存储部署在数据库主机或站点的故障域之外时,它才提供独立的容灾副本。部署对象存储集群后,将备份方法切换为 minio

all:
  vars:
    pgbackrest_method: minio      # 使用 minio 作为默认备份仓库
  children:                       # 定义一个单节点 minio SNSD 集群
    minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio, minio_type: silo }}

Pigsty 的 minio 仓库预设通过域名(默认 sss.pigsty)和 HTTPS 端点访问对象存储, 并使用自签名 CA(/etc/pki/ca.crt)验证这条链路。 默认的 pgsql 桶与 pgbackrest 访问用户在 MINIO 模块初始化时自动创建。

对于严肃的生产部署,建议使用经过验证的多节点对象存储集群(MNMD,纠删码容错),参阅 MINIO 配置

pgbackrest_method: minio 是 Pigsty 的 S3 兼容仓库预设名,并不要求服务端必须由 MINIO 模块管理。独立部署和管理的 MinIO、RustFS 或其他 S3 兼容服务也可以使用该预设,但其安装、升级、证书和数据生命周期不在当前 MINIO 角色的支持范围内。


使用 S3 / 云对象存储

如果您只有一个节点,最有意义的备份策略就是使用云厂商的对象存储服务(AWS S3、阿里云 OSS 等), 以极低的成本获得异地容灾能力。定义一个新仓库并切换过去即可:

pgbackrest_method: s3             # 使用 'pgbackrest_repo.s3' 作为备份仓库
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository

  s3:                             # 阿里云 OSS(S3 兼容)对象存储服务示例
    type: s3                      # oss 兼容 S3 协议
    s3_endpoint: oss-cn-beijing-internal.aliyuncs.com
    s3_region: oss-cn-beijing
    s3_bucket: <your_bucket_name>
    s3_key: <your_access_key>
    s3_key_secret: <your_secret_key>
    s3_uri_style: host            # 云厂商对象存储通常使用主机风格 URI
    path: /pgbackrest
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包大小限制,对象存储建议 20MiB
    bundle_size: 128MiB           # 文件包目标大小,对象存储建议 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 按时间保留 14 天

  local:                          # 保留默认本地仓库定义,便于随时切换
    path: /pg/backup
    retention_full_type: count
    retention_full: 2

除 S3 兼容存储外,pgBackRest 还支持以下后端,配置方式参阅官方用户指南:


多集群共享仓库

一个集中式仓库可以同时服务多套 PostgreSQL 集群:pgBackRest 用 stanza (即 pg_cluster)隔离各集群的备份与归档,互不干扰。 这也是 克隆集群 的基础 —— 新集群可以直接从共享仓库中读取源集群的备份进行恢复。

因此,请确保同一仓库下的集群名称 全局唯一,即使它们分属不同的部署环境。


仓库版本控制

对象存储的 版本控制(Versioning)为仓库提供同一存储系统内的版本保护:即使备份文件被覆盖或删除,历史版本仍有机会找回。 它与当前仓库共享同一故障域和管理平面,不能替代独立的异地或离线副本。 您可以在 minio_buckets 中为桶添加 versioning 标志启用:

minio_buckets:
  - { name: pgsql ,versioning: true }
  - { name: meta  ,versioning: true }
  - { name: data }

配合 pgBackRest 的 repo-target-time 选项, 甚至可以把整个仓库"回滚"到过去某一时刻的状态读取 —— 相当于对备份系统本身做时间点恢复。


仓库锁定

部分对象存储(Silo、MinIO、S3 等)支持 对象锁定(Object Lock / WORM):对对象版本配置保留模式与期限后, 锁定版本在保留期内不可修改、不可永久删除。这是对抗勒索攻击的重要防线,但普通删除仍可能写入 Delete Marker, 暂时隐藏当前对象;恢复时需要保留版本与版本管理能力。

minio_buckets 中添加 lock 标志,只会在创建桶时启用对象锁定能力与版本控制:

minio_buckets:
  - { name: pgsql ,lock: true }
  - { name: meta  ,versioning: true }
  - { name: data }

这一步还没有给新对象设置 WORM 保留期。您还需要在 Silo / MinIO 中使用 mcli retention set 或控制台配置默认的 GOVERNANCE / COMPLIANCE 模式与期限,并用 mcli retention info 验证。GOVERNANCE 可以被拥有 bypass 权限的主体绕过; COMPLIANCE 在期限内连 root 用户也不能解除。

锁定会改变 过期清理移除集群备份 的行为:pgBackRest 可以让对象在逻辑上过期,但被锁定的历史版本仍会占用空间,直到保留期结束。上线前应在测试桶中验证 备份、expire、删除标记清理和版本恢复的完整流程。


切换仓库

变更仓库定义或切换 pgbackrest_method 后,需要重新渲染配置、初始化 stanza,并尽快建立新仓库中的恢复起点:

./pgsql.yml -t pg_backup -l pg-meta           # 重新配置并创建 stanza
sudo -iu postgres pg-backup full              # 在当前主库执行全量备份,建立新仓库中的第一个恢复点

旧仓库中的备份不会自动迁移,但在其保留期内仍可作为恢复来源使用(通过 pg_pitr.repo 指定)。

8.5.4 - 管理命令

备份管理命令手册:启用与移除备份,手动备份,查看与清理,Stanza 管理,日志排查,以及替代备份工具。

备份管理命令应以数据库超级用户(pg_dbsu,默认 postgres)身份在数据库节点上执行。 您可以按习惯选择三种等价的入口:

  • pig pbpig 命令行工具 的封装 —— 自动检测 stanza、自动切换 DBSU 身份、带安全检查,推荐使用
  • pb:登录 shell 的别名函数,自动填充 --stanza 后转发给 pgbackrest
  • pgbackrest:原生命令,完整选项参阅 pgBackRest 命令参考

命令一览

pig 命令 别名 对应 pgbackrest 命令 说明
pig pb info i info 查看备份与归档状态
pig pb list ls 列出仓库中的 stanza 与备份
pig pb backup [full/diff/incr] b backup 执行备份(自动检查主库角色)
pig pb restore r restore 恢复(显示计划并确认,详见 恢复操作
pig pb expire e expire 按保留策略清理过期备份(--plan 预览)
pig pb create c stanza-create 创建 stanza
pig pb upgrade u stanza-upgrade 升级 stanza(版本升级或克隆善后)
pig pb delete d stanza-delete 删除 stanza 及其全部备份
pig pb check ck check 校验备份配置与归档链路
pig pb start up start 恢复 pgbackrest 操作
pig pb stop dw stop 暂停 pgbackrest 操作
pig pb log [list/show/tail] l 查看 pgbackrest 日志

启用备份

如果集群创建时 pgbackrest_enabledtrue(默认),备份已自动启用。 若创建时禁用了备份,或修改了仓库配置,可用 pg_backup 子任务补充配置:

./pgsql.yml -t pg_backup -l pg-meta   # 配置 pgbackrest,创建 stanza

集群初始化后 Pigsty 会自动尝试执行一次初始全量备份;只有备份命令成功后才写入 /etc/pgbackrest/initial.done,失败会被剧本忽略且不会留下标记。该文件只防止初始化任务重复执行,最终仍应使用 pig pb info(或 pgbackrest info)核对仓库中的实际备份状态。 定时备份计划通过 pg_crontab 声明,详见 备份策略


移除备份

pig pb delete 是只删除备份 stanza 的首选入口。它会在实际执行前交互确认;多 stanza 配置还要求显式给出目标。核对目标后执行:

pig pb info -s pg-meta           # 核对当前备份链与恢复窗口
pig pb delete -s pg-meta         # 输入精确 stanza 名确认后才执行

移除主实例(pg_role = primary)时,pgsql-rm.yml 默认也会尝试删除该集群的备份 stanza。以下命令会直接修改或删除状态:

./pgsql-rm.yml -l pg-meta                          # 移除集群及其备份
./pgsql-rm.yml -l pg-meta -e pg_rm_backup=false    # 移除集群但保留备份
./pgsql-rm.yml -l pg-meta -t pg_backup             # 仅删除备份相关状态

执行前应确认近期备份可用、记录恢复需求,并由操作者再次输入精确的集群/stanza 名。使用 pg_rm_backup(设为 false)可以在移除集群时保留备份。

pgsql-rm.yml -t pg_backup 会在主库上强制执行 pgbackrest stanza-delete,删除本地仓库目录(仅 local 模式),并移除 pgBackRest 配置与初始备份标记;该任务会忽略部分删除错误。因此执行后必须再次检查仓库,不能把剧本“成功”当成备份已物理清空的证明。只需要删除 stanza 时,优先使用上面的 pig pb delete,它提供计划与确认保护。

如果备份仓库为对象版本配置了 对象锁定保留期, 删除可能只写入 Delete Marker,被锁定的历史版本会继续占用空间,直到保留期结束。

备份删除

删除备份可能造成永久数据丢失。执行前必须确认目标集群/stanza、核对近期备份与替代恢复副本,并保留 pig pb info/删除计划的审计记录。


手动备份

crontab 之外,随时可以手动触发备份。pg-backup 脚本与 pig pb backup 都带主库角色检查,在从库上执行会直接退出,不会产生错误的备份:

pg-backup            # 增量备份(仓库中无全量备份时自动升级为全量)
pg-backup full       # 全量备份
pg-backup diff       # 差异备份(相对最近一次全量)
pg-backup incr       # 增量备份(相对最近一次任意备份)

pig pb backup full   # 等价:pig 封装,自动检测 stanza 与 DBSU

备份期间会显著占用磁盘 I/O 与网络带宽(并行度已限制在 2~4 进程),建议安排在业务低峰执行。


查看备份

pb info 列出仓库中当前 stanza 的备份与 WAL 归档状态:

pb info          # = pgbackrest --stanza=pg-meta info
pig pb info      # 等价
pig pb list      # 列出仓库中所有 stanza

输出解读的关键是 备份标签20250715-013657F 为全量备份(F),..._20250715-013724D 为差异备份(D),..._20250715-013730I 为增量备份(I)—— 下划线前的部分标识备份链所依附的全量备份。wal archive min/max 显示 WAL 归档范围, 它与最早的全量备份共同描述 恢复窗口

监控系统同样提供备份状态的持续观测:pgbackrest_exporter(端口 9854)导出的 指标 覆盖最近备份时间、类型、大小与错误状态,可直接用于告警。


清理过期备份

保留策略默认在每次备份后自动执行(expire-auto)。手动触发或预览清理计划:

pig pb expire --plan    # 预览将被清理的备份(dry-run,不实际删除)
pig pb expire           # 按保留策略执行清理

Stanza 管理

Stanza 记录集群的备份身份(system-id 与主版本), 以下场景需要手动管理:

pig pb create             # 创建 stanza:新仓库初始化(Pigsty 集群初始化时自动执行)
pig pb upgrade            # 升级 stanza:PostgreSQL 大版本升级后,或克隆恢复出新集群后
pig pb delete -s pg-meta  # 交互确认后删除全部备份与归档,危险操作!

最常见的手动场景是 克隆集群的善后: 从其他集群的备份恢复出新集群后,stanza 中记录的 system-id 与新集群不符, 必须执行 stanza-upgrade 之后,新集群的备份才能写入仓库。


检查与启停

pig pb check     # 端到端校验:配置、归档推送、仓库可达性
pig pb stop      # 暂停 pgbackrest 操作(维护窗口,阻止新备份/归档启动)
pig pb start     # 恢复 pgbackrest 操作

check 命令会实际推送一个 WAL 段并确认其到达仓库,是排查"归档不工作"问题的第一步。


查看日志

pig pb log           # 列出日志文件
pig pb log tail      # 跟踪最新日志
ls /pg/log/pgbackrest/   # 日志目录:备份、归档、恢复各有独立日志文件

使用 pgsql-pitr.yml 时,PostgreSQL 的恢复日志位于 /pg/tmp/recovery.log


替代备份工具

pg-basebackup

Pigsty 另备有不依赖 pgbackrest 的独立备份脚本 /pg/bin/pg-basebackup, 它使用原生 pg_basebackup 生成单文件物理备份(lz4 压缩 tarball),默认写入 /pg/backup。 适合在不便使用备份仓库时快速留存一份物理副本:

pg-basebackup                        # 生成 /pg/backup/backup_<tag>_<date>.tar.lz4
pg-basebackup --dst /tmp --file backup.tar.lz4   # 指定输出位置与文件名

mkdir -p /tmp/data                   # 解压提取
cat /pg/backup/backup_pg-meta_20250713.tar.lz4 | unlz4 -d -c | tar -xC /tmp/data
加密选项为遗留实现

pg-basebackup -e 使用 OpenSSL RC4 加密 —— 这是一个已被淘汰的弱加密算法,仅作混淆用途, 不应作为机密性保障。需要加密备份时,请使用 pgbackrest 仓库的 AES-256 加密(cipher_type: aes-256-cbc)。

逻辑备份

pg_dump 生成的逻辑备份 不能 用于 PITR,但它是跨大版本迁移、导出部分数据、长期归档快照的正确工具。 物理备份与逻辑备份互为补充,严肃的生产环境通常两者兼备。这是 PostgreSQL 自带的工具,请参阅 官方文档

8.5.5 - 恢复操作

执行时间点恢复:pgsql-pitr.yml 剧本、pig pitr 命令与 pig pb restore 原语,恢复目标、分步执行与完整参数参考。

Pigsty 提供三个层次的恢复入口,共用 同一套参数语义,按场景选用:

入口 适用场景 特点
pgsql-pitr.yml 剧本 生产集群恢复 编排整个集群:HA 暂停、多节点、etcd 清理、恢复控制信息输出
pig pitr 命令 单节点集群 / 节点本机操作 无需管理节点,在数据库节点上直接编排执行
pig pb restore 原语 非 Patroni 托管的实例 pgbackrest restore 的直接封装,最精细的控制

手把手的沙箱演练教程请参阅 手工恢复; 用恢复克隆出新集群(不影响生产的推荐姿势)请参阅 克隆数据库集群

PITR 会覆盖目标集群

pgsql-pitr.yml 会暂停 HA、停止 Patroni/PostgreSQL、以 pgbackrest --force restore 覆盖目标数据目录, 随后删除目标集群的 etcd 前缀并重建 HA;它只打印计划,不会等待人工确认。 执行任何实质恢复前,必须先用 pig pg list <目标集群> 核对当前拓扑、用 pig pb info 核对近期备份与恢复窗口, 由操作者复述并确认精确的目标集群与恢复点。生产恢复仍应安排维护窗口并保留独立、已验证的备份。


快速上手

要将 pg-meta 集群回滚到之前的时间点,声明 pg_pitr 参数并运行剧本:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_pitr: { time: '2025-07-13 10:00:00+00', action: promote }   # 一步执行:到达目标后显式提升
pig pg list pg-meta
pig pb info
./pgsql-pitr.yml -l pg-meta

参数也可以通过命令行临时传入,两种方式等价:

./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": { "time": "2025-07-13 10:00:00+00", "action": "promote" }}'
命令行传参请使用合法 JSON

-e 传入的参数必须是合法 JSON:键与字符串值都要加双引号,例如 {"pg_pitr": {"time": "...", "archive": true}}。 布尔值不加引号,字符串必须加 —— 引号缺失会导致参数解析失败或静默取错值。

剧本会依次执行:暂停 Patroni 高可用 → 停止集群进程 → 执行 pgbackrest 增量还原 → 启动 PostgreSQL 并等待进入一致恢复状态 → 用 pg_controldata 打印控制信息 → 清理 etcd 元数据 → 重新拉起集群与高可用。 执行过程的第一步会打印完整的恢复计划(源集群、目标、还原命令),但不会暂停等待确认;上面的一步式示例因此显式声明了 action: promote。 如果需要在目标点检查数据,请使用下文的 分步执行,并显式选择 action: pause


恢复目标

pg_pitr 支持 六类恢复目标,其中四类目标值互斥,只能指定一个:

恢复目标类型

default/latest
pg_pitr: { }  # 恢复到最新状态(WAL 归档流末尾)
time
pg_pitr: { time: "2025-07-13 10:00:00+00" }
lsn
pg_pitr: { lsn: "0/4001C80" }
xid
pg_pitr: { xid: "250000" }
name
pg_pitr: { name: "some_restore_point" }
immediate
pg_pitr: { type: "immediate" }

未指定任何目标时,重放全部 WAL 归档恢复到最新状态(内部类型 default); immediate 类型在到达第一个一致点后立即停止,用于最快恢复出可用实例(例如验证备份)。

按时间恢复

最常用的目标。时间应为合法的 PostgreSQL TIMESTAMP 格式,建议带时区:YYYY-MM-DD HH:MM:SS+TZ

./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": { "time": "2025-07-13 10:00:00+00", "action": "promote" }}'

按名称恢复

在高危变更前用 pg_create_restore_point 打点,恢复时便有了无歧义的目标:

SELECT pg_create_restore_point('before_migration');
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": { "name": "before_migration", "action": "promote" }}'

按事务 ID 恢复

如果误删数据的事务号已知(从监控仪表盘或 CSVLOG 的 TXID 字段获取), 配合 exclusive 精确停在该事务 之前,一条数据都不多丢:

./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": { "xid": "250000", "exclusive": true, "action": "promote" }}'

按 LSN 恢复

LSN(日志序列号)标识 WAL 流中的精确位置, 可从 Pigsty 仪表盘的 PG LSN 面板获取;需要时可以用 timeline 指定目标时间线(默认 latest):

./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": { "lsn": "0/4001C80", "timeline": "1", "action": "promote" }}'
包含与排除

恢复目标默认是"包含"(inclusive)的:目标点上的事务会被重放。 exclusive: true 排除目标点本身 —— 例如 xid: 250000, exclusive: true 时,最后被重放的是 249999 号之前已提交的事务。 仅适用于 timexidlsn 目标,对应 PostgreSQL 的 recovery_target_inclusive


恢复来源

默认从本集群自己的备份恢复,三个字段可以改变恢复来源:

  • cluster:源 stanza —— 使用共享仓库中 其他集群 的备份恢复(克隆集群 的基础)
  • repo:临时指定备份仓库定义(格式同 pgbackrest_repo 的仓库条目),例如从旧仓库或异地仓库恢复
  • set:从指定的 备份标签 开始还原(默认自动选择目标点前最近的备份集,用 pb info 查看可用标签)
./pgsql-pitr.yml -l pg-meta2 -e '{"pg_pitr": { "cluster": "pg-meta", "archive": false, "action": "promote" }}'           # 用 pg-meta 的备份恢复 pg-meta2
./pgsql-pitr.yml -l pg-meta2 -e '{"pg_pitr": { "cluster": "pg-meta", "time": "2025-07-14 08:00:00+00", "archive": false, "action": "promote" }}' # 并指定时间点

分步执行

一步到位固然方便,但在生产事故中,您可能希望亲手控制每个阶段。剧本的任务树支持用 tags 三步走:

# 确认备份、恢复点和精确目标 pg-meta 后,按顺序执行;不要跳过阶段间检查
./pgsql-pitr.yml -l pg-meta -t down     # 第一步:暂停 HA,停止 patroni 与 postgres
./pgsql-pitr.yml -l pg-meta -t pitr     # 第二步:执行还原与重放,打印恢复控制信息
./pgsql-pitr.yml -l pg-meta -t up       # 第三步:清理 etcd,拉起集群,恢复 HA
# down                 : # 停止高可用并关闭 patroni 和 postgres
#   - pause            : # 暂停 patroni 自动故障切换
#   - stop             : # 停止 patroni 和 postgres 服务
#     - stop_patroni   : # 停止 patroni 服务
#     - stop_postgres  : # 停止 postgres 服务
# pitr                 : # 执行 PITR 过程
#   - config           : # 生成 pgbackrest 配置和恢复脚本
#   - restore          : # 运行 pgbackrest 恢复命令
#   - recovery         : # 启动 postgres 并完成恢复
#   - verify           : # 验证恢复后的集群控制数据
# up:                  : # 启动 postgres / patroni 并恢复高可用
#   - etcd             : # 启动前清理 etcd 元数据
#   - start            : # 启动 patroni 和 postgres 服务
#     - start_postgres : # 启动 postgres 服务
#     - start_patroni  : # 启动 patroni 服务
#   - resume           : # 恢复 patroni 自动故障切换

每步之间您可以检查状态:down 之后确认进程已停;pitr 阶段返回后,先查看 /pg/tmp/recovery.log, 并用 pg_is_in_recovery()pg_is_wal_replay_paused()pg_last_wal_replay_lsn()pg_last_xact_replay_timestamp() 确认是否已经到达目标,再结合业务查询抽查数据。pg_controldata /pg/data 提供的是检查点与时间线摘要,不能单独证明时间、XID 或 LSN 目标已经命中。 使用 action: pause 时,确认无误后先提升实例,再执行 up;如果恢复目标选错了,可在 up 之前调整 pg_pitr 重跑 pitr 阶段。 pause / shutdown 需要配合这种分阶段流程才能形成明确的人工门;一步式执行应显式使用 action: promote

SELECT pg_is_in_recovery(), pg_is_wal_replay_paused(),
       pg_last_wal_replay_lsn(), pg_last_xact_replay_timestamp();
pg_ctl -D /pg/data promote              # action: pause 验证通过后执行
./pgsql-pitr.yml -l pg-meta -t up       # 清理 etcd,拉起 Patroni,恢复 HA
重跑 pitr 阶段

backup: true 会把当前数据目录搬到 /pg/data-backup,而再次运行时会先删除已有的 /pg/data-backup。 因此剧本支持分阶段执行,但不能把带 backup: true 的恢复笼统视为幂等操作。


PITR 参数定义

pg_pitr 的完整字段如下。恢复目标、目标动作与原数据保留方式都建议显式声明:

pg_pitr:                         # 定义 PITR 恢复任务
  cluster: pg-meta               # 恢复来源集群(源 stanza),默认为本集群 pg_cluster
  type: default                  # 目标类型:default | time | xid | name | lsn | immediate
  time: "2025-07-13 10:00:00+00" # 恢复目标:时间点(与 xid / name / lsn 互斥)
  name: "some_restore_point"     # 恢复目标:命名恢复点(与 time / xid / lsn 互斥)
  xid: "250000"                  # 恢复目标:事务 ID(与 time / name / lsn 互斥)
  lsn: "0/4001C80"               # 恢复目标:日志序列号(与 time / xid / name 互斥)
  exclusive: false               # 排除目标点本身,默认包含(仅 time / xid / lsn 有效)
  timeline: latest               # 目标时间线,可为整数,默认 latest
  set: latest                    # 从哪个备份标签开始还原,默认自动选择
  action: pause                  # 到达目标后动作:pause / promote / shutdown
                                 # 指定恢复目标时未声明 action,实际默认 pause
  archive: true                  # 保留原归档配置;探索性恢复设为 false(archive-mode=off)
  backup: false                  # 恢复前将原数据目录搬到 /pg/data-backup;重跑会覆盖已有备份目录
  db_exclude: []                 # 排除的数据库(选择性恢复)
  db_include: []                 # 只恢复指定数据库(选择性恢复)
  link_map:                      # 目录软链接映射(表空间 / WAL 分盘)
    pg_wal: '/data/wal'
    pg_xact: '/data/pg_xact'
  process: 4                     # 恢复并行进程数,默认为节点 CPU 核数
  repo: {}                       # 临时指定恢复来源仓库(格式同 pgbackrest_repo 条目)
  data: /pg/data                 # 恢复到的数据目录
  port: 5432                     # 恢复实例的监听端口

每个字段与 pgbackrest 选项的对应关系,见 参数映射表


单实例:pig pitr

在数据库节点上,pig pitr 无需 Ansible 环境即可执行单节点恢复编排: 预检(校验目标、stanza 与备份存在性)→ 停止 Patroni 与 PostgreSQL → 执行还原 → 按参数决定是否启动 PostgreSQL → 恢复后指引。

pig pitr -t "2025-07-13 10:00:00+00"    # 恢复到时间点
pig pitr --xid 250000 -X                # 恢复到事务 250000 之前(-X = --exclusive)
pig pitr --name before_migration        # 恢复到命名还原点
pig pitr -d                             # 恢复到 WAL 归档末尾(--default)
pig pitr -I --no-restart                # 只还原并准备 immediate 恢复,PostgreSQL 保持停止
pig pitr -t "..." --plan                # 只显示执行计划,不实际执行

常用选项:-b/--set 指定备份集,-T/--target-timeline 指定时间线,--target-action 指定到达目标后的动作, -D/--data 恢复到其他数据目录(此时必须配合 --no-restart)。 默认只用安全的 fast 模式停库,失败即中止 —— 除非显式给出 --force-stop,才允许升级为强制停库。 对于 Patroni 托管的数据目录,命令恢复后会让 Patroni 保持停止;验证数据后再执行 pig pt startpig pitr 不清理 etcd、不重建副本,也不会自动把实例重新加入 HA 集群。 完整选项参阅 pig pitr 命令手册


原语:pig pb restore

对于 不由 Patroni 托管 的实例(或已明确停管的场景),可以使用最底层的恢复原语 —— 它是 pgbackrest restore 的直接封装,自动处理 stanza、DBSU 与时间格式, 执行前显示恢复计划并要求确认:

pig pb restore --time "2025-07-13 10:00"     # 时间可省略时区与秒,自动按本地时区规范化
pig pb restore --set 20250715-013657F        # 从指定备份集恢复
pig pb restore -d                            # 恢复到归档末尾

两道内置的安全边界值得了解:

  • Patroni 托管实例会被硬拒绝:若 Patroni 服务活跃且目标是其托管的数据目录,pig pb restore 直接报错退出 —— 因为 Patroni 会立刻把恢复到一半的实例重新拉起。托管实例请使用 pig pitrpgsql-pitr.yml
  • PostgreSQL 必须已停止:实例仍在运行时拒绝执行。

-- 之后可透传原生 pgbackrest 选项(如 --tablespace-map--link-all), 但恢复目标、stanza、仓库等关键选项已被封装接管,不允许透传覆盖。详见 pig pb 命令手册


恢复后处理

恢复完成后,剧本会打印控制信息并重建高可用,但仍有三件事需要确认:

  1. 核对数据:按 分步执行 中的方法检查恢复目标与业务数据。

  2. 重建备份:如果是从其他集群克隆恢复,需要执行 stanza 善后; 无论何种恢复,都建议尽快执行一次全量备份,在新时间线上重建恢复起点:

    pg-backup full
  3. 恢复归档:探索性恢复若设置了 archive: false,归档已被关闭,验证完成后必须恢复 (archive_mode 是 postmaster 参数,需要重启生效)。先确认维护窗口、当前主库和复制状态,再由操作者明确批准重启:

    psql -c 'ALTER SYSTEM RESET archive_mode;'
    pg restart pg-meta   # 重启集群使归档配置生效
    pg-backup full       # 执行新的全量备份

8.5.6 - 克隆数据库集群

用 PITR 把一个集群的历史状态恢复到另一个集群:找回误删数据、执行恢复演练,以及必不可少的 Stanza 善后。

克隆是恢复能力最有价值的用法:不动生产集群,把它的历史状态恢复到另一套集群上。 误删数据后从克隆库中导回、定期演练验证备份可用性、审计取证查看历史状态、把测试环境重置为生产某刻的快照 —— 这些场景的操作方式完全相同,本页给出完整流程。

目标集群需要能访问源集群的备份仓库、允许被覆盖,并使用兼容的 PostgreSQL 主版本。使用集中式仓库(Silo / S3)时, 仓库中以 stanza 隔离的各集群备份,对持有相应凭据的目标集群可见。

克隆会覆盖目标集群

先用 pig pg list <目标集群> 核对目标拓扑、用 pig pb info 核对源 stanza 的近期备份与恢复窗口, 并由操作者确认精确的源集群、目标集群和恢复点后实施恢复。 目标集群上原有的数据会被覆盖;生产操作仍需维护窗口和独立、已验证的备份。


克隆现有集群

假设四节点沙箱中有 pg-metapg-test 两套集群,共享 Silo 备份仓库。 要把 pg-test 重置为 pg-meta最新状态,只需在 pg_pitr 中把恢复来源指向 pg-meta 的 stanza:

pig pg list pg-test
pig pb info
./pgsql-pitr.yml -l pg-test -e '{"pg_pitr": { "cluster": "pg-meta", "archive": false, "action": "promote" }}'

配合恢复目标,可以克隆到恢复窗口内的 任意时间点 —— 例如把 pg-test 重置为 pg-meta 在 2025 年 12 月 26 日 15:30 的状态:

./pgsql-pitr.yml -l pg-test -e '{"pg_pitr": { "cluster": "pg-meta", "time": "2025-12-26 15:30:00+08", "archive": false, "action": "promote" }}'

跨集群克隆显式设置 archive: false,在独立恢复阶段关闭归档;Patroni 接管后按下面的步骤处理目标 stanza 与归档。

目标集群也可以是全新创建的空集群:先用标准流程 创建集群(如 pg-meta2), 再对它执行跨集群 PITR,即完成了"从备份仓库引导新集群"。

pgBackRest 的还原是增量的(delta):只重写与备份不一致的文件。 因此对反复执行的演练、或已通过 备份集群(Standby Cluster) 物理复制拉齐过数据的目标集群,克隆速度会显著快于首次全量还原。

误删数据的典型找回流程到这里只剩最后一步:在克隆集群中验证数据无误后, 用 pg_dump 导出受影响的表/库,导回生产集群。全库原地回滚是最后手段,而不是第一反应。


克隆善后

克隆出的新集群带着 源集群的数据,但备份仓库中它自己的 stanza 仍记录着 原来的身份(system-id)。 pgBackRest 写入备份前会核对身份,不一致即拒绝 —— 这个保护机制防止新集群的备份污染源集群的备份历史。

因此,确认克隆结果符合预期后,必须执行三步善后,新集群的备份链路才能恢复正常。 其中集群重启是服务变更:先核对主库、复制状态和维护窗口,并获得明确批准:

pb stanza-upgrade                          # 1. 升级 stanza,接纳新集群的 system-id(仅跨集群克隆需要)
psql -c 'ALTER SYSTEM RESET archive_mode;' # 2. 恢复归档(本文跨集群示例显式设置了 archive: false)
pg restart pg-test                         #    archive_mode 为 postmaster 参数,重启生效
pg-backup full                             # 3. 全量备份,让新集群从此刻起拥有自己的备份历史

跳过善后的后果是可预期的:下一次例行备份会因身份核对失败而报错, 在此期间新集群 没有备份保护(如果关闭了归档,也不会产生新的 WAL 归档):

postgres@pg-test-1:~$ pb backup
INFO: backup command begin 2.57.0: --annotation=pg_cluster=pg-test ... --stanza=pg-test --start-fast
ERROR: [051]: PostgreSQL version 18, system-id 7588470953413201282 do not match stanza version 18, system-id 7588470974940466058
       HINT: is this the correct stanza?
INFO: backup command end: aborted with exception [051]

重建备份身份

stanza-upgrade 让新集群沿用原 stanza 继续写备份。如果您希望新集群拥有 全新的备份历史 (例如克隆出的集群将长期独立演化),也可以选择彻底重建其备份配置 —— 声明式方式:

pig pb info -s pg-test           # 核对现有备份与恢复窗口
pig pb delete -s pg-test         # 输入精确 stanza 名确认后执行
./pgsql.yml -t pg_backup -l pg-test          # 创建全新 stanza
pg-backup full                               # 建立第一个恢复点

或者用 pgbackrest 原语 手动完成同样的事情:

pig pb stop                       # 暂停 pgbackrest 操作
pig pb delete -s pg-test          # 确认精确目标后删除
pig pb start                      # 恢复 pgbackrest 操作
pig pb create -s pg-test          # 以当前集群身份重建 stanza
pig pb backup full -s pg-test     # 建立第一个恢复点
重建会永久丢弃旧恢复历史

只有在已经核对近期备份、保留了需要的独立恢复副本,并由操作者确认精确的 pg-test stanza 后,才可执行删除。对象锁定仓库中的历史版本可能继续保留并占用空间;删除命令成功不等于底层版本已经物理清空。


在线副本:备份集群

克隆得到的是 静态的时间点快照。如果需要的是持续跟随源集群的 在线副本, 应使用 备份集群(Standby Cluster,基于流复制); 需要"一直落后一小时"的快速反悔窗口,则使用 延迟集群

三者互为补充:备份集群提供实时副本,延迟集群提供固定延迟的反悔窗口, PITR 克隆提供恢复窗口内的历史快照 —— 且不需要提前准备在线副本。


恢复演练

克隆是 不触碰生产集群的恢复演练:目标集群会被覆盖,但它能端到端验证备份系统的每个环节。 建议将以下演练纳入例行运维(每季度,或每次重大变更后):

  1. 选定演练目标:生产集群恢复窗口内的某个时间点;
  2. 向演练集群执行跨集群 PITR,记录耗时 —— 这就是实测的 PITR RTO;
  3. 验证数据完整性:行数抽查、关键业务表校验、应用连通测试;
  4. 执行 克隆善后,确认演练集群自身备份恢复正常(验证善后流程本身也是演练的一部分);
  5. 记录结果:恢复耗时、发现的问题、文档与实际操作的出入。

沙箱环境中使用 pgbackrest 原语手工执行恢复的完整教程,参阅 手工恢复; 在同一台机器上用 XFS 快照快速 Fork 实例的进阶技巧,参阅 Fork 实例

8.6 - 数据迁移

如何将现有的 PostgreSQL 集群以最小的停机时间迁移至新的、由 Pigsty 管理的 PostgreSQL 集群?

Pigsty 内置了一个剧本 pgsql-migration.yml,基于逻辑复制来实现在线数据库迁移。

通过预生成的自动化脚本,应用停机时间可以缩减到几秒内。但请注意,逻辑复制需要 PostgreSQL 10 以上的版本才能工作。

当然如果您有充足的停机时间预算,那么总是可以使用 pg_dump | psql 的方式进行停机迁移。


定义迁移任务

想要使用 Pigsty 提供的在线迁移剧本,您需要创建一个定义文件,来描述迁移任务的细节。

请查看任务定义文件示例作为参考: files/migration/pg-meta.yml

这个迁移任务要将 pg-meta.meta 在线迁移到 pg-test.test,前者称为 源集群(SRC), 后者称为 宿集群(DST)

pg-meta-1	10.10.10.10  --> pg-test-1	10.10.10.11 (10.10.10.12,10.10.10.13)

基于逻辑复制的迁移以数据库为单位,您需要指定需要迁移的数据库名称,以及数据库源宿集群主节点的 IP 地址,以及超级用户的连接信息。

---
#-----------------------------------------------------------------
# PG_MIGRATION
#-----------------------------------------------------------------
context_dir: ~/migration  # 迁移手册 & 脚本的放置目录
#-----------------------------------------------------------------
# SRC Cluster (旧集群)
#-----------------------------------------------------------------
src_cls: pg-meta      # 源集群名称                  <必填>
src_db: meta          # 源数据库名称                <必填>
src_ip: 10.10.10.10   # 源集群主 IP                <必填>
#src_pg: ''            # 如果定义,使用此作为源 dbsu pgurl 代替:
#                      # postgres://{{ pg_admin_username }}@{{ src_ip }}/{{ src_db }}
#                      # 例如: 'postgres://dbuser_dba:[email protected]:5432/meta'
#sub_conn: ''          # 如果定义,使用此作为订阅连接字符串代替:
#                      # host={{ src_ip }} dbname={{ src_db }} user={{ pg_replication_username }}'
#                      # 例如: 'host=10.10.10.10 dbname=meta user=replicator password=DBUser.Replicator'
#-----------------------------------------------------------------
# DST Cluster (新集群)
#-----------------------------------------------------------------
dst_cls: pg-test      # 宿集群名称                  <必填>
dst_db: test          # 宿数据库名称                 <必填>
dst_ip: 10.10.10.11   # 宿集群主 IP                <必填>
#dst_pg: ''            # 如果定义,使用此作为目标 dbsu pgurl 代替:
#                      # postgres://{{ pg_admin_username }}@{{ dst_ip }}/{{ dst_db }}
#                      # 例如: 'postgres://dbuser_dba:[email protected]:5432/test'
#-----------------------------------------------------------------
# PGSQL
#-----------------------------------------------------------------
pg_dbsu: postgres
pg_replication_username: replicator
pg_replication_password: DBUser.Replicator
pg_admin_username: dbuser_dba
pg_admin_password: DBUser.DBA
pg_monitor_username: dbuser_monitor
pg_monitor_password: DBUser.Monitor
#-----------------------------------------------------------------
...

默认情况下,源宿集群两侧的超级用户连接串会使用全局的管理员用户和各自主库的 IP 地址拼接而成,但您总是可以通过 src_pgdst_pg 参数来覆盖这些默认值。 同理,您也可以通过 sub_conn 参数来覆盖订阅连接串的默认值。


生成迁移计划

此剧本不会主动完成集群的迁移工作,但它会生成迁移所需的操作手册与自动化脚本。

默认情况下,你会在 ~/migration/pg-meta.meta 下找到迁移上下文目录。 按照 README.md 的说明,依次执行这些脚本,你就可以完成数据库迁移了!

# 激活迁移上下文:启用相关环境变量
. ~/migration/pg-meta.meta/activate

# 这些脚本用于检查 src 集群状态,并帮助在 pigsty 中生成新的集群定义
./check-user     # 检查 src 用户
./check-db       # 检查 src 数据库
./check-hba      # 检查 src hba 规则
./check-repl     # 检查 src 复制身份
./check-misc     # 检查 src 特殊对象

# 这些脚本用于在现有的 src 集群和由 pigsty 管理的 dst 集群之间建立逻辑复制,除序列外的数据将实时同步
./copy-schema    # 将模式复制到目标
./create-pub     # 在 src 上创建发布
./create-sub     # 在 dst 上创建订阅
./copy-progress  # 打印逻辑复制进度
./copy-diff      # 通过计数表快速比较 src 和 dst 的差异

# 这些脚本将在线迁移中运行,该迁移将停止 src 集群,复制序列号(逻辑复制不复制序列号!)
./copy-seq [n]   # 同步序列号,如果给出了 n,则会应用额外的偏移

# 你必须根据你的访问方式(dns,vip,haproxy,pgbouncer等),将应用流量切换至新的集群!
#./disable-src   # 将 src 集群访问限制为管理节点和新集群(你的实现)
#./re-routing    # 从 SRC 到 DST 重新路由应用流量!(你的实现)

# 然后进行清理以删除订阅和发布
./drop-sub       # 迁移后在 dst 上删除订阅
./drop-pub       # 迁移后在 src 上删除发布

注意事项

如果担心拷贝序列号时出现主键冲突,您可以在拷贝时将所有序列号向前推进一段距离,例如 +1000,你可以使用 ./copy-seq 加一个参数 1000 来实现这一点。

你必须实现自己的 ./re-routing 脚本,以将你的应用流量从 src 路由到 dst。 因为我们不知道你的流量是如何路由的(例如 dns, VIP, haproxy 或 pgbouncer)。 当然,您也可以手动完成这项操作…

你可以实现一个 ./disable-src 脚本来限制应用对 src 集群的访问,这是可选的:如果你能确保所有应用流量都在 ./re-routing 中干净利落地切完,其实不用这一步。

但如果您有未知来源的各种访问无法梳理干净,那么最好使用更为彻底的方式:更改 HBA 规则并重新加载来实现(推荐),或者只是简单粗暴地关停源主库上的 postgres、pgbouncer 或 haproxy 进程。

8.7 - 任务教程

如何去完成单个任务。每个任务页面是一般通过给出若干步骤展示如何执行完成某事。

8.7.1 - 故障排查

常见故障与分析排查思路

本文档列举了 PostgreSQL 和 Pigsty 中可能出现的故障,以及定位、处理、分析问题的 SOP。


磁盘空间写满

磁盘空间写满是最常见的故障类型。

现象

当数据库所在磁盘空间耗尽时,PostgreSQL 将无法正常工作,可能出现以下现象:数据库日志反复报错"no space left on device"(磁盘空间不足), 新数据无法写入,甚至 PostgreSQL 可能触发 PANIC 强制关闭。

Pigsty 带有 NodeFsSpaceFull 告警规则,当文件系统可用空间不足 10% 时触发告警。 使用监控系统 NODE Instance 面板查阅 FS 指标面板定位问题。

诊断

您也可以登录数据库节点,使用 df -h 查看各挂载盘符使用率,确定哪个分区被写满。 对于数据库节点,重点检查以下目录及其大小,以判断是哪个类别的文件占满了空间:

  • 数据目录/pg/data/base):存放表和索引的数据文件,大量写入与临时文件需要关注
  • WAL 目录(如 pg/data/pg_wal):存放 PG WAL,WAL 堆积/复制槽保留是常见的磁盘写满原因。
  • 数据库日志目录(如 pg/log):如果 PG 日志未及时轮转写大量报错写入,也可能占用大量空间。
  • 本地备份目录(如 data/backups):使用 pgBackRest 等在本机保存备份时,也有可能撑满磁盘。

如果问题出在 Pigsty 管理节点或监控节点,还需考虑:

  • 监控数据:VictoriaMetrics 的时序指标和 VictoriaLogs 日志存储都会占用磁盘,可检查保留策略。
  • 对象存储数据:Pigsty 集成的 Silo 对象存储可能会被用于 PG 备份保存。

明确占用空间最大的目录后,可进一步使用 du -sh <目录> 深入查找特定大型文件或子目录。

处理

磁盘写满属于紧急问题,需立即采取措施释放空间并保证数据库继续运行。 当数据盘并未与系统盘区分时,写满磁盘可能导致 Shell 命令无法执行。这种情况下,可以删除 /pg/dummy 占位文件,释放少量应急空间以便 shell 命令恢复正常。 如果数据库由于 pg_wal 写满已经宕机,清理空间后需要重启数据库服务并仔细检查数据完整性。


事务号回卷

PostgreSQL 循环使用 32 位事务 ID (XID),耗尽时会出现"事务号回卷"故障(XID Wraparound)。

现象

第一阶段的典型征兆是 PGSQL Persist - Age Usage 面板年龄饱和度进入警告区域。 数据库日志开始出现:WARNING: database "postgres" must be vacuumed within xxxxxxxx transactions 字样的信息。

若问题持续恶化,PostgreSQL 会进入保护模式:当剩余事务 ID 不到约100万时数据库切换为只读模式;达到上限约21亿(2^31)时则拒绝任何新事务并迫使服务器停机以避免数据错误。

诊断

PostgreSQL 与 Pigsty 默认启用自动垃圾回收(AutoVacuum),因此此类故障出现通常有更深层次的根因。 常见的原因包括:超长事务(SAGE),Autovacuum 配置失当,复制槽阻塞,资源不足,存储引擎/扩展 BUG,磁盘坏块。

首先定位年龄最大的数据库,然后可通过 Pigsty PGCAT Database - Tables 面板来确认表的年龄分布。 同时查阅数据库错误日志,通常可以找到定位根因的线索。

处理

  1. 立即冻结老事务:如果数据库尚未进入只读保护状态,立刻对受影响的库执行一次手动 VACUUM FREEZE。可以从老化最严重的表开始逐个冻结,而不是整库一起做,以加快效果。使用超级用户连接数据库,针对识别出的 relfrozenxid 最大的表运行 VACUUM FREEZE 表名;,优先冻结那些 XID 年龄最大的表元组。这样可以迅速回收大量事务 ID 空间。
  2. 单用户模式救援:如果数据库已经拒绝写入或宕机保护,此时需要启动数据库到单用户模式执行冻结操作。在单用户模式下运行 VACUUM FREEZE database_name; 对整个数据库进行冻结清理。完成后再以多用户模式重启数据库。这样做可以解除回卷锁定,让数据库重新可写。需要注意在单用户模式下操作要非常谨慎,并确保有足够的事务 ID 余量完成冻结。
  3. 备用节点接管:在某些复杂场景(例如遭遇硬件问题导致 vacuum 无法完成),可考虑提升集群中的只读备节点为主,以获取一个相对干净的环境来处理冻结。例如主库因坏块导致无法 vacuum,此时可以手动 Failover 提升备库为新的主库,再对其进行紧急 vacuum freeze。确保新主库已冻结老事务后,再将负载切回来。

连接耗尽

PostgreSQL 有一个最大连接数配置 (max_connections),当客户端连接数超过此上限时,新的连接请求将被拒绝。典型现象是在应用端看到数据库无法连接,并报出类似 FATAL: remaining connection slots are reserved for non-replication superuser connectionstoo many clients already 的错误。 这表示普通连接数已用完,仅剩下保留给超管或复制的槽位

诊断

连接耗尽通常由客户端大量并发请求引起。您可以通过 PGCAT Instance / PGCAT Database / PGCAT Locks 直接查阅数据库当前的活跃会话。 并判断是什么样的查询填满了系统,并进行进一步的处理。特别需要关注是否存在大量 Idle in Transaction 状态的连接以及长时间运行的事务(以及慢查询)。

处理

杀查询:对于已经耗尽导致业务受阻的情况,通常立即使用 pg_terminate_backend(pid) 进行紧急降压。 对于使用连接池的情况,则可以调整连接池大小参数,并执行 reload 重载的方式减少数据库层面的连接数量。

您也可以修改 max_connections 参数为更大的值,但本参数需要重启数据库后才能生效。


etcd 配额写满

etcd 配额写满将导致 PG 高可用控制面失效,无法进行配置变更。

诊断

Pigsty 在实现高可用时使用 etcd 作为分布式配置存储(DCS),etcd 自身有一个存储配额(默认约为2GB)。 当 etcd 存储用量达到配额上限时,etcd 将拒绝写入操作,报错 “etcdserver: mvcc: database space exceeded"。在这种情况下,Patroni 无法向 etcd 写入心跳或更新配置,从而导致集群管理功能失效。

解决

在 Pigsty v2.0.0 - v2.5.1 之间的版本默认受此问题影响。Pigsty v2.6.0 为部署的 etcd 新增了自动压实的配置项,如果您仅将其用于 PG 高可用租约,则常规用例下不会再有此问题。


有缺陷的存储引擎

目前,TimescaleDB 的试验性存储引擎 Hypercore 被证实存在缺陷,已经出现 VACUUM 无法回收出现 XID 回卷故障的案例。 请使用该功能的用户及时迁移至 PostgreSQL 原生表或者 TimescaleDB 默认引擎

详细介绍:《PG新存储引擎故障案例

8.7.2 - 误删处理

处理误删数据,误删表,误删数据库

误删数据

如果是小批量 DELETE 误操作,可以考虑使用 pg_surgery 或者 pg_dirtyread 扩展进行原地手术恢复。

-- 立即关闭此表上的 Auto Vacuum 并中止 Auto Vacuum 本表的 worker 进程
ALTER TABLE public.some_table SET (autovacuum_enabled = off, toast.autovacuum_enabled = off);

CREATE EXTENSION pg_dirtyread;
SELECT * FROM pg_dirtyread('tablename') AS t(col1 type1, col2 type2, ...);

如果被删除的数据已经被 VACUUM 回收,那么使用通用的误删处理流程。

误删对象

当出现 DROP/DELETE 类误操作,通常按照以下流程决定恢复方案。

  1. 确认此数据是否可以通过业务系统或其他数据系统找回,如果可以,直接从业务侧修复。
  2. 确认是否有延迟从库,如果有,推进延迟从库至误删时间点,查询出来恢复。
  3. 如果数据已经确认删除,确认备份信息,恢复范围是否覆盖误删时间点,如果覆盖,开始 PITR
  4. 确认是整集群原地 PITR 回滚,还是先 克隆新集群 验证数据,还是用从库来重放,并执行恢复策略

误删集群

如果出现整个数据库集群通过 Pigsty 管理命令被误删的情况,例如错误的执行 pgsql-rm.yml 剧本或 bin/pgsql-rm 命令。 除非您指定了 pg_rm_backup 参数为 false,否则备份会与数据库集群一起被删除。

警告:在这种情况,您的数据将无法找回!请务必三思而后行!

建议:对于生产环境,您可以在配置清单中全局配置此参数为 false,在移除集群时保留备份。

8.7.3 - 手工 PITR 演练

在隔离沙箱中分阶段执行、验证并收尾 PostgreSQL 时间点恢复。

本教程在 Pigsty v4.5.0 的四节点沙箱中演练 PostgreSQL 时间点恢复。核心路径使用 pgsql-pitr.ymldown → pitr → up 三阶段,让操作者在覆盖数据、提升时间线和重建 HA 之前分别停下来验证。

如果只恢复当前节点,可使用 pig pitr;如果需要直接控制 pgBackRest,可参考 pg-pitr 低层工具

只在可丢弃沙箱中照做

恢复会停止 Patroni/PostgreSQL,并以 pgbackrest --force restore 覆盖目标 PGDATA;up 阶段还会删除目标集群的 etcd 前缀并重建 Patroni 状态。剧本会打印计划,但 没有交互确认。生产操作前必须由操作者明确说出并确认精确集群名与恢复点,核对近期可用且独立验证过的备份,使用完全相同的 -l、变量与标签先运行 --check,并安排维护窗口。本教程不授权在任何生产环境执行这些命令。


准备隔离沙箱

使用 Vagrant 或其他可丢弃的四节点实验环境,并选用自带 Silo 备份仓库的 ha/full 模板:

curl -fsSL https://repo.pigsty.io/get | bash
cd ~/pigsty
./configure -c ha/full
./deploy.yml

ha/full 定义单节点 pg-meta、三节点 pg-test 与 Silo/pgBackRest 仓库。本教程以下使用精确目标 pg-meta,避免把示例选择器复制到其他环境。

初始部署和备份都会改变沙箱状态;生产环境必须另行履行部署与备份审批流程。


建立恢复证据

先只读检查拓扑、备份链与 WAL 范围:

pig pg list pg-meta
sudo -iu postgres pig pb info
sudo -iu postgres pig pb check

info 中至少应有 status: ok 的可用备份,并且归档 WAL 覆盖目标时间。check 能检查当前 stanza 与归档链路,但不能替代真实恢复演练或独立副本验证。

在沙箱中,可以运行 Pigsty 心跳脚本生成易验证的时间序列:

sudo -iu postgres /pg/bin/pg-heartbeat

记录以下信息,随后停止负载:

  • 准备恢复到的带时区时间戳;
  • 该时刻前后的心跳、LSN 与事务边界;
  • 当前主库、时间线和备份标签;
  • 目标集群名 pg-meta 与目标节点。

对真实业务表的检查需要单独授权;本教程只使用沙箱心跳数据。


声明恢复任务

在沙箱清单的 pg-meta.vars 中声明恢复目标:

pg_pitr:
  cluster: pg-meta
  time: "2026-08-13 10:00:00+08"
  action: pause
  archive: true
  backup: false
  • cluster 是备份源 stanza;缺省为目标 pg_cluster
  • action: pause 让 PostgreSQL 到达目标后暂停,给人工验证留下闸门。
  • archive: true 保留归档设置。
  • backup: true 不是安全备份替代品:它会先删除已有的 <pg_data>-backup,再移动当前 PGDATA,因此这里保持 false

也可以用 -e 临时传入同一对象,但三个阶段与预检必须逐字复用同一份有效 JSON,避免变量漂移。


完整预检

在任何停服或写入动作前,对完整工作流执行同目标预检:

./pgsql-pitr.yml -l pg-meta --check

检查 Ansible 解析出的唯一目标确实是 pg-meta,并核对输出中的:

  • 源 stanza、恢复类型、时间、时间线与动作;
  • 目标 pg_data、端口和仓库;
  • 表空间/软链接映射;
  • archivebackup 行为。

--check 只验证清单、变量和任务选择,不能证明 pgBackRest 备份能够恢复。目标、备份或变量一旦变化,就必须重新预检。


阶段一:停服

只有在操作者再次确认精确目标 pg-meta、恢复点与维护窗口后,才执行:

./pgsql-pitr.yml -l pg-meta -t down

down 会尝试暂停 Patroni 自动故障转移,停止所有目标成员的 Patroni,并在 PostgreSQL 仍运行时执行 immediate shutdown。随后在每个目标节点确认服务确实停止;不要只相信剧本返回码:

sudo systemctl is-active patroni
sudo -iu postgres pg_ctl -D /pg/data status

预期分别为 inactive 和“server is not running”。如果任何成员仍在运行,停止流程并排障,不要进入恢复阶段。


阶段二:恢复并验证

再次核对 pg_pitr 与目标节点后执行破坏性的恢复阶段:

./pgsql-pitr.yml -l pg-meta -t pitr

该阶段会:

  1. 生成 /pg/conf/pitr.conf/pg/bin/pg-restore
  2. 根据 backup 决定是否移动原 PGDATA;
  3. 创建目标目录并运行带 --forcedelta=y 的 pgBackRest restore;
  4. 直接启动 PostgreSQL并等待日志出现 consistent recovery state;
  5. 打印 pg_controldata 摘要。

控制信息只能证明数据目录具有可读的控制状态,不能证明指定时间、XID 或业务状态正确。使用 action: pause 时,确认 WAL 已到达并暂停在目标附近:

sudo -iu postgres psql -p 5432 -Atqc \
  'SELECT pg_is_in_recovery(), pg_is_wal_replay_paused(), pg_last_wal_replay_lsn(), pg_last_xact_replay_timestamp()'

然后只检查获授权的最小数据范围;在沙箱中可检查心跳记录。若目标不对:

  1. 保持所有 Patroni 停止;
  2. 停止手工启动的 PostgreSQL;
  3. 修改恢复目标并重新运行完整 --check
  4. 再执行 pitr 阶段。

不要运行 up,也不要让旧时间线上的副本重新接入。


提升与阶段三:重建 HA

只有操作者确认恢复结果正确且接受创建新时间线后,才提升恢复实例:

sudo -iu postgres pg_ctl -D /pg/data promote
sudo -iu postgres psql -p 5432 -Atqc 'SELECT pg_is_in_recovery()'

预期结果为 f。提升不是只读验证,也不能无损撤销。

在所有 Patroni 成员仍停止、精确目标仍为 pg-meta 的前提下,再执行:

./pgsql-pitr.yml -l pg-meta -t up

up 会在主库节点对应的 etcd 中删除 /pg/pg-meta/ 前缀(实际前缀还受 pg_namespace/Citus 配置影响),停止手工 PostgreSQL,启动主库 Patroni,再逐个启动副本并恢复 HA。etcd 删除任务设置了错误容忍,因此成功返回也不能证明旧 DCS 状态已正确清除。


恢复后验收

逐项验证,不要把“服务启动”当成恢复完成:

pig pg list pg-meta
sudo -iu postgres psql -Atqc \
  "SELECT pg_is_in_recovery(), pg_current_wal_lsn(), current_setting('archive_mode')"
sudo -iu postgres pig pb check

还应确认:

  • 只有预期成员成为主库,副本来自新时间线且复制正常;
  • HAProxy/VIP/DNS 和应用流量只指向已验收的实例;
  • 恢复点附近的数据与事件边界正确;
  • archive_modearchive_command 和新 WAL 归档正常;
  • 监控、告警与备份仓库没有旧集群残留。

确认新时间线稳定后,按审批流程执行新的全量备份并再次核验:

sudo -iu postgres pg-backup full
sudo -iu postgres pig pb info

如果本次恢复显式使用了 archive: false,它会写入 archive-mode=off。只有在验证恢复结果并确认维护窗口后,才重置该覆盖项并通过受控重启使 archive_mode 生效;默认 archive: true 不需要这一步。


多节点与跨集群恢复

  • 多节点恢复后,旧时间线副本不能未经验证直接重新加入;up 会逐个启动副本并等待克隆/恢复,必须监控完成状态。
  • 从另一 stanza 恢复时,pg_pitr.cluster 是源,-l 仍是被覆盖的目标。把两者分别写进变更单并逐一复述。
  • 跨集群恢复通常应使用 archive: false,避免测试目标向源 stanza 写入 WAL;验收并完成 stanza 善后 后再启用自己的归档。
  • link_mapdataport 与临时 repo 会改变真正的数据与存储目标,必须纳入 --check 和人工复核。

相关文档

8.7.4 - 克隆与旁路恢复 PostgreSQL 实例

使用 pg-fork 创建本机物理副本,并以 pg-pitr 对停止的数据目录执行低层恢复。

Pigsty v4.5.0 提供两个本机 Shell 工具:

  • pg-fork:复制一个 PostgreSQL 数据目录,并为副本设置独立端口。
  • pg-pitr:调用 pgBackRest,将一个 已停止 的数据目录恢复到指定目标。

它们适合沙箱演练、旁路取证和临时测试,不是完整的 Patroni 集群恢复编排器。托管实例优先使用 pig pitr;多节点集群优先使用分阶段的 pgsql-pitr.yml

先确认路径、备份和停机状态

pg-fork 会递归删除已存在的目标目录;pg-pitr 会用备份覆盖目标目录。两者在非交互环境都可能不经确认直接执行。真实运行前必须核对源与目标的绝对路径、端口、表空间、精确集群/实例身份,并确认有独立、近期且经过验证的备份。不要把刚创建的 CoW 克隆当作独立备份。


pg-fork

pg-fork 在当前节点上复制 PostgreSQL 数据目录。以数据库操作系统用户(通常为 postgres,至少属于 postgres 组)执行:

pg-fork 1                         # /pg/data -> /pg/data1,目标端口 15432
pg-fork 2 -d /pg/data1            # /pg/data1 -> /pg/data2,目标端口 25432
pg-fork 3 -D /srv/pg-clone -P 55432

参数

pg-fork <FORK_ID> [options]
参数 含义 默认值
<FORK_ID> 单个数字 19,用于推导默认目录和端口 必填
-d, --data <path> 源数据目录 $PG_DATA/pg/data
-D, --dst <path> 目标数据目录 /pg/data<FORK_ID>
-p, --port <port> 源实例端口 $PG_PORT5432
-P, --dst-port <port> 目标实例端口 <FORK_ID>5432
-s, --skip 跳过在线备份 API,强制冷拷贝
-y, --yes 跳过交互确认

脚本会拒绝相同的规范化源/目标路径,但不会判断自定义目标目录是否属于其他重要数据。目标目录存在时,它会在复制前执行递归删除。

热备份与冷拷贝

默认情况下,脚本用目标端口连接源实例,在同一个 psql 会话中执行:

  1. CHECKPOINT
  2. pg_backup_start()
  3. rm -rf <目标>cp -a --reflink=auto
  4. pg_backup_stop(wait_for_archive => false)

如果无法通过指定端口连接源实例,脚本会 自动降级为冷拷贝,而不是中止。-s 也会强制冷拷贝。只有确认源实例已经完全停止时,冷拷贝才是安全的;postmaster.pid 只能作为警告线索,不能证明进程状态。

同一文件系统上,脚本会将以下文件系统识别为快速 CoW 模式:启用 reflink 的 XFS、Btrfs、Bcachefs 和 OCFS2。其他文件系统或跨文件系统目标仍执行 cp --reflink=auto,但可能退化为完整复制。脚本帮助中的 ZFS 描述比当前探测逻辑更宽;v4.5.0 实现不会把 ZFS 标记为已确认的快速 CoW 模式。

副本配置

复制成功后,pg-fork 会:

  • 删除目标中的 postmaster.pidpostmaster.optsstandby.signal
  • 清空目标中的物理复制槽目录;
  • 在目标 postgresql.auto.conf 中设置独立 portarchive_mode=off 与本地 log_directory
  • 删除 primary_conninfoprimary_slot_name 与旧的 recovery_target* 覆盖项。

脚本不会检查目标端口是否空闲,也不会调整内存参数。启动副本前,至少核对:

postgres -D /pg/data1 -C port
postgres -D /pg/data1 -C archive_mode
postgres -D /pg/data1 -C shared_buffers
pg_ctl -D /pg/data1 status
外部表空间不会被隔离

cp -a 会保留 pg_tblspc 中的符号链接;pg-fork 不会复制或重映射 PGDATA 之外的表空间。直接启动这样的副本可能访问甚至修改源实例的表空间。存在外部表空间时,必须先独立复制并重映射所有表空间,或不要使用此脚本创建可写副本。

交互边界

只有标准输入是终端且没有 -y 时,脚本才询问 Proceed with fork? [y/N]。管道、CI、cron 等非交互调用不会出现该确认。因此自动化必须在调用前自行完成严格的绝对路径白名单与目标存在性检查;不要为了方便默认添加 -y


pg-pitr

pg-pitr 是低层 pgBackRest restore 包装器。它不暂停或启动 Patroni,不停止或启动 PostgreSQL,不清理 DCS,也不重建副本。

恢复目标

实际执行至少要明确理解一个恢复目标。无参数调用只显示帮助:

参数 pgBackRest 语义
-d, --default 不设置停止目标,重放到可用 WAL 末尾
-i, --immediate 到达所选备份的一致性点后停止
-t, --time <timestamp> 恢复到指定时间
-n, --name <restore-point> 恢复到命名还原点
-l, --lsn <lsn> 恢复到指定 LSN
-x, --xid <xid> 恢复到指定事务 ID

-S/--set(兼容别名 -b/--backup)只选择 从哪个备份集开始恢复,不是停止目标。例如,-S 20251225-120000F -d 仍会继续重放到 WAL 末尾;若要在该备份一致后立即停止,应组合 -S ... -i

针对 timenamelsnxidimmediate,pgBackRest 的有效默认动作是抵达目标后暂停;-P/--promote 改为自动提升。-X/--exclusive 只应与 timelsnxid 这类明确边界配合使用。

其他选项

参数 含义
-D, --data <path> 目标数据目录,必须是绝对路径;默认 /pg/data
-s, --stanza <name> pgBackRest stanza;默认从配置取第一个非 global stanza
-T, --timeline <value> latestcurrent 或正整数时间线
-P, --promote 对有停止目标的恢复设置自动提升
-v, --verbose 启用 pgBackRest info 级控制台日志
-c, --check, --dry-run 只打印将执行的命令
-y, --yes 跳过五秒倒计时
-- <args> 将额外参数原样传给 pgBackRest

-c 是命令渲染检查,不会证明备份/WAL 可用,也不会检查 PostgreSQL 或 Patroni 已停止。额外 pgBackRest 参数也没有由包装器做冲突过滤;传递仓库、表空间或链接映射参数时必须单独审查最终命令。

安全执行顺序

以下示例只展示单个已隔离目标目录的低层流程;生产集群恢复应使用完整 runbook:

# 1. 只读核验备份与恢复窗口
pig pb info

# 2. 核对目标实例已经停止;Patroni 托管实例还要先停止 Patroni
pg_ctl -D /pg/data1 status

# 3. 打印并人工审查准确命令,不写数据
pg-pitr -D /pg/data1 -t "2026-08-13 10:00:00+08" -c

# 4. 只有在操作者再次确认绝对目标、备份与停机状态后,才去掉 -c
pg-pitr -D /pg/data1 -t "2026-08-13 10:00:00+08"

实际执行拒绝 root,并在发现目标目录中存在 postmaster.pid 时中止;即使 PID 已失效,也要求人工确认后清理。它没有 y/N 问答:交互终端只有五秒可中断倒计时,非交互环境没有倒计时并直接进入 restore。

恢复后由操作者启动实例并验证:

pg_ctl -D /pg/data1 start
psql -p 15432 -Atqc \
  'SELECT pg_is_in_recovery(), pg_is_wal_replay_paused(), pg_last_xact_replay_timestamp()'

只有恢复目标、允许访问的业务数据、时间线和归档设置全部验证无误后,才决定是否提升。提升会创建新时间线,不是可撤销的“查看”动作。pg-pitr 本身不会关闭归档;不要机械执行脚本结尾的通用“enable archive_mode”提示,应先查看有效值,只纠正本次恢复明确造成的覆盖项。

旁路恢复的额外风险

/pg/data1 之类的自定义目录恢复时,pgBackRest 可能从备份恢复 postgresql.auto.conf,覆盖 pg-fork 写入的独立端口。启动前重新检查 portarchive_mode、socket、日志与内存设置。

备份中若包含外部表空间或链接,旁路恢复还可能使用原路径。需要隔离时,应在 -- 后提供经过审查的 pgBackRest --tablespace-map--link-map 等参数,并检查打印出的完整命令;否则不要在与生产实例相同的主机上启动恢复副本。


推荐的克隆验证流程

  1. 核对源实例、目标绝对路径、目标端口、表空间与独立备份。
  2. 在交互终端运行 pg-fork <id>,确认脚本显示的是热备份而非意外降级的冷拷贝。
  3. 不启动副本,先用 pg-pitr -D <clone> ... -c 检查恢复命令。
  4. 明确确认目标后执行恢复;随后重新检查副本端口和所有外部路径。
  5. 启动副本,在隔离端口上验证恢复状态和经授权的数据。
  6. 只有需要形成新主库时才提升;否则停止副本并按经过验证的精确路径清理。

这种旁路验证可以降低对当前 PGDATA 的直接影响,但仍会读取同一个备份仓库、占用主机资源,并可能触及外部表空间;它不是无风险沙箱。


相关文档

8.7.5 - 为 PostgreSQL 集群启用 HugePage

为 PostgreSQL 集群启用大页,减少大内存实例的页表开销并提高性能

使用 node_hugepage_countnode_hugepage_ratio/pg/bin/pg-tune-hugepage

如果你计划启用大页(HugePage),请考虑使用 node_hugepage_countnode_hugepage_ratio,并配合 ./node.yml -t node_tune 进行应用。

大页对于数据库来说有利有弊,利是内存是专门管理的,不用担心被挪用,降低数据库 OOM 风险。缺点是某些场景下可能对性能由负面影响。

在 PostgreSQL 启动前,您需要分配 足够多的 大页,浪费的部分可以使用 pg-tune-hugepage 脚本对其进行回收,不过此脚本仅 PostgreSQL 15+ 可用。

如果你的 PostgreSQL 已经在运行,你可以使用下面的办法启动大页(仅 PG15+ 可用):

sync; echo 3 > /proc/sys/vm/drop_caches   # 刷盘,释放系统缓存(请做好数据库性能受到冲击的准备)
sudo /pg/bin/pg-tune-hugepage             # 将 nr_hugepages 写入 /etc/sysctl.d/hugepage.conf
pg restart <cls>                          # 重启 postgres 以使用 hugepage

8.7.6 - 3坏2应急处理

高可用典型场景处理预案:三节点坏了两个节点,高可用不生效了,怎么从紧急状态中恢复?

如果经典3节点高可用部署同时出现两台(多数主体)故障,系统通常无法自动完成故障切换,需要人工介入:

首先判断另外两台服务器的情况,如果短时间内可以拉起,优先选择拉起另外两台服务。否则进入 紧急止血流程

紧急止血流程假设您的管理节点故障,只有单台普通数据库节点存活,在这种情况下,最快的恢复操作流程为:

  • 调整 HAProxy 配置,将流量指向主库。
  • 关闭 Patroni,手动提升 PostgreSQL 从库为主库。

调整HAProxy配置

如果你通过其他方式绕开 HAProxy 访问集群,那么可以跳过这一步。 如果你通过 HAProxy 方式访问数据库集群,那么你需要调整负载均衡配置,将读写流量手工指向主库。

  • 编辑 /etc/haproxy/conf.d/<pg_cluster>-primary.cfg 配置文件,其中 <pg_cluster> 为你的 PostgreSQL 集群名称,例如 pg-meta
  • 将健康检查配置选项注释,停止进行健康检查。
  • 将服务器列表中,其他两台故障的机器注释掉,只保留当前主库服务器。
listen pg-meta-primary
    bind *:5433
    mode tcp
    maxconn 5000
    balance roundrobin

    # 注释掉以下四行健康检查配置
    #option httpchk                               # <---- remove this
    #option http-keep-alive                       # <---- remove this
    #http-check send meth OPTIONS uri /primary    # <---- remove this
    #http-check expect status 200                 # <---- remove this

    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    server pg-meta-1 10.10.10.10:6432 check port 8008 weight 100

    # 注释掉其他两台故障的机器
    #server pg-meta-2 10.10.10.11:6432 check port 8008 weight 100 <---- comment this
    #server pg-meta-3 10.10.10.12:6432 check port 8008 weight 100 <---- comment this

配置调整完成后,先不着急执行 systemctl reload haproxy 重载生效,等待后续主库提升后一起执行。 以上配置的效果是,HAProxy 将不再进行主库健康检查(默认使用 Patroni),而是直接将写入流量指向当前主库


手工提升备库

登陆目标服务器,切换至 dbsu 用户,执行 CHECKPOINT 刷盘后,关闭 Patroni,重启 PostgreSQL 并执行 Promote。

sudo su - postgres                     # 切换到数据库 dbsu 用户
psql -c 'checkpoint; checkpoint;'      # 两次 Checkpoint 刷脏页,避免PG后重启耗时过久
sudo systemctl stop patroni            # 关闭 Patroni
pg-restart                             # 重新拉起 PostgreSQL
pg-promote                             # 将 PostgreSQL 从库提升为主库
psql -c 'SELECT pg_is_in_recovery();'  # 如果结果为 f,表示已经提升为主库

如果你上面调整了 HAProxy 配置,那么现在可以执行 systemctl reload haproxy 重载 HAProxy 配置,将流量指向新的主库。

systemctl reload haproxy                # 重载 HAProxy 配置,将写入流量指向当前实例

避免脑裂

紧急止血后,第二优先级问题为:避免脑裂。用户应当防止另外两台服务器重新上线后,与当前主库形成脑裂,导致数据不一致。

简单的做法是:

  • 将另外两台服务器直接 断电/断网,确保它们不会在不受控的情况下再次上线。
  • 调整应用使用的数据库连接串,将其 HOST 直接指向唯一幸存服务器上的主库。

然后应当根据具体情况,决定下一步的操作:

  • A:这两台服务器是临时故障(比如断网断电),可以原地修复后继续服务
  • B:这两台故障服务器是永久故障(比如硬件损坏),将移除并下线。

临时故障后的复原

如果另外两台服务器是临时故障,可以修复后继续服务,那么可以按照以下步骤进行修复与重建:

  • 每次处理一台故障服务器,优先处理 管理节点 / INFRA 管理节点
  • 启动故障服务器,并在启动后关停 Patroni

ETCD 集群在法定人数恢复后,将恢复工作,此时可以启动幸存服务器(当前主库)上的 Patroni,接管现有 PostgreSQL,并重新获取集群领导者身份。 Patroni 启动后进入维护模式。

sudo systemctl restart patroni
pg pause <pg_cluster>

在另外两台实例上以 postgres 用户身份创建 touch /pg/data/standby.signal 标记文件将其标记为从库,然后拉起 Patroni:

sudo -iu postgres touch /pg/data/standby.signal
sudo systemctl restart patroni

确认 Patroni 集群身份/角色正常后,退出维护模式:

pg resume <pg_cluster>

永久故障后的复原

出现永久故障后,首先需要恢复管理节点上的 ~/pigsty 目录,主要是需要 pigsty.ymlfiles/pki/ca/ca.key 两个核心文件。

如果您无法取回或没有备份这两个文件,您可以选择部署一套新的 Pigsty,并通过 备份集群 的方式将现有集群迁移至新部署中。

请定期备份 pigsty 目录(例如使用 Git 进行版本管理)。建议吸取教训,下次不要犯这样的错误。

配置修复

您可以将幸存的节点作为新的管理节点,将 ~/pigsty 目录拷贝到新的管理节点上,然后开始调整配置。 例如,将原本默认的管理节点 10.10.10.10 替换为幸存节点 10.10.10.12

all:
  vars:
    admin_ip: 10.10.10.12               # 使用新的管理节点地址
    node_etc_hosts: [10.10.10.12 h.pigsty a.pigsty p.pigsty g.pigsty sss.pigsty]
    infra_portal: {}                    # 一并修改其他引用旧管理节点 IP (10.10.10.10) 的配置

  children:

    infra:                              # 调整 Infra 集群
      hosts:
        # 10.10.10.10: { infra_seq: 1 } # 老的 Infra 节点
        10.10.10.12: { infra_seq: 3 }   # 新增 Infra 节点

    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

    pg-meta:                            # 调整 PGSQL 集群配置
      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 }
        10.10.10.12: { pg_seq: 3, pg_role: primary , pg_offline_query: true }
      vars:
        pg_cluster: pg-meta

ETCD修复

然后执行以下命令,将 ETCD 重置为单节点集群:

./etcd.yml -e etcd_safeguard=false -e etcd_clean=true

根据 ETCD重载配置 的说明,调整对 ETCD Endpoint 的引用。

INFRA修复

如果幸存节点上没有 INFRA 模块,请在当前节点上配置新的 INFRA 模块并安装。执行以下命令,将 INFRA 模块部署到幸存节点上:

./infra.yml -l 10.10.10.12

修复当前节点的监控

./node.yml -t monitor

PGSQL修复

./pgsql.yml -t pg_conf                            # 重新生成 PG 配置文件
systemctl reload patroni                          # 在幸存节点上重载 Patroni 配置

各模块修复后,您可以参考标准扩容流程,将新的节点加入集群,恢复集群的高可用性。

8.7.7 - 使用 VIP-Manager 为 PostgreSQL 集群配置二层 VIP

您可以在 PostgreSQL 集群上绑定一个可选的 L2 VIP —— 前提条件是:集群中的所有节点都在一个二层网络中。

这个 L2 VIP 强制使用 Master - Backup 模式,Master 始终指向在数据库集群主库实例所在的节点。

这个 VIP 由 VIP-Manager 组件管理,它会从 DCS (etcd) 中直接读取由 Patroni 写入的 Leader Key,从而判断自己是否是 Master。


启用VIP

在 PostgreSQL 集群上定义 pg_vip_enabled 参数为 true,即可在集群上启用 VIP 组件。当然您也可以在全局配置中启用此配置项。

# pgsql 3 node ha cluster: pg-test
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }   # primary instance, leader of cluster
    10.10.10.12: { pg_seq: 2, pg_role: replica }   # replica instance, follower of leader
    10.10.10.13: { pg_seq: 3, pg_role: replica, pg_offline_query: true } # replica with offline access
  vars:
    pg_cluster: pg-test           # define pgsql cluster name
    pg_users:  [{ name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] }]
    pg_databases: [{ name: test }]

    # 启用 L2 VIP
    pg_vip_enabled: true
    pg_vip_address: 10.10.10.3/24
    #pg_vip_interface: auto

请注意,pg_vip_address 必须是一个合法的 IP 地址,带有网段,且在当前二层网络中可用。

pg_vip_interface 默认为 auto, 此时 Pigsty 会根据 inventory 中的 IPv4 地址自动探测各实例使用的网卡。 如果自动探测不适用于非标准路由或策略路由环境,可以为每个实例显式指定合法的网卡名称,例如:

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary , pg_vip_interface: eth0  }
    10.10.10.12: { pg_seq: 2, pg_role: replica , pg_vip_interface: eth1  }
    10.10.10.13: { pg_seq: 3, pg_role: replica , pg_vip_interface: ens33 }
  vars:
    pg_cluster: pg-test           # define pgsql cluster name
    pg_users:  [{ name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] }]
    pg_databases: [{ name: test }]

    # 启用 L2 VIP
    pg_vip_enabled: true
    pg_vip_address: 10.10.10.3/24

使用以下命令,刷新 PG 的 vip-manager 配置并重启生效:

./pgsql.yml -t pg_vip 

8.7.8 - Citus 集群部署

如何部署 Citus 高可用分布式集群?

Citus 是一个 PostgreSQL 扩展,可以将 PostgreSQL 原地转换为一个分布式数据库,并实现在多个节点上水平扩展,以处理大量数据和大量查询。

Patroni 在 v3.0 后,提供了对 Citus 原生高可用的支持,简化了 Citus 集群的搭建,Pigsty 也对此提供了原生支持。

说明

Citus 13.x 支持 PostgreSQL 18、17、16、15、14 五个大版本。Pigsty 扩展仓库提供了 Citus ARM64 软件包。


Citus集群

Pigsty 原生支持 Citus。当前完整配置模板见 conf/ha/citus.yml

下面先使用一个简化的四节点拓扑说明关键参数:一个两节点协调者集群 pg-citus0,以及两个单节点 Worker 集群 pg-citus1pg-citus2。它不是当前完整模板的逐行摘录。

pg-citus:
  hosts:
    10.10.10.10: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.2/24 ,pg_seq: 1, pg_role: primary }
    10.10.10.11: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.2/24 ,pg_seq: 2, pg_role: replica }
    10.10.10.12: { pg_group: 1, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.3/24 ,pg_seq: 1, pg_role: primary }
    10.10.10.13: { pg_group: 2, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.4/24 ,pg_seq: 1, pg_role: primary }
  vars:
    pg_mode: citus                            # pgsql cluster mode: citus
    pg_version: 18                            # citus 13.x supports PG 14-18
    pg_shard: pg-citus                        # citus shard name: pg-citus
    pg_primary_db: citus                      # primary database used by citus
    pg_vip_enabled: true                      # enable vip for citus cluster
    pg_vip_interface: auto                    # auto detect vip interface for every member
    pg_dbsu_password: DBUser.Postgres         # all dbsu password access for citus cluster
    pg_extensions: [ citus, postgis, pgvector, topn, pg_cron, hll ]  # install these extensions
    pg_libs: 'citus, pg_cron, pg_stat_statements' # 显式预加载 citus,且置于首位
    pg_users: [{ name: dbuser_citus ,password: DBUser.Citus ,pgbouncer: true ,roles: [ dbrole_admin ]    }]
    pg_databases: [{ name: citus ,owner: dbuser_citus ,extensions: [ citus, vector, topn, pg_cron, hll ] }]
    pg_parameters:
      cron.database_name: citus
      citus.node_conninfo: 'sslrootcert=/pg/cert/ca.crt sslmode=verify-full'
    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'  }

相比标准 PostgreSQL 集群,Citus 集群的配置有一些特殊之处,首先,你需要确保 Citus 扩展被下载,安装,加载并启用,这涉及到以下四个参数

  • repo_packages:必须包含 citus 扩展,或者你需要使用带有 Citus 扩展的 PostgreSQL 离线安装包。
  • pg_extensions:必须包含 citus 扩展,即你必须在每个节点上安装 citus 扩展。
  • pg_libs:必须显式包含 citus,并将其置于首位;当前 Patroni 模板直接使用该参数生成 shared_preload_libraries
  • pg_databases: 这里要定义一个首要数据库,该数据库必须安装 citus 扩展。

其次,你需要确保 Citus 集群的配置正确:

  • pg_mode: 必须设置为 citus,从而告知 Patroni 使用 Citus 模式。
  • pg_primary_db:必须指定一个首要数据库的名称,该数据库必须安装 citus 扩展,这里名为 citus
  • pg_shard:必须指定一个统一的名称,字符串,作为所有水平分片 PG 集群的集群名称前缀,这里为 pg-citus
  • pg_group:必须指定一个分片号,从零开始依次分配的整数,0 号固定代表协调者集群,其他为 Worker 集群。
  • pg_cluster 必须在每个物理 PostgreSQL 集群间唯一。通常采用 pg_shard 加序号的命名约定,但当前角色不强制它与 pg_group 按字符串拼接结果相等。
  • pg_dbsu_password:必须设置为非空的纯文本密码,否则 Citus 无法正常工作。
  • pg_parameters:建议设置 citus.node_conninfo 参数,强制要求 SSL 访问并要求节点间验证客户端证书。

配置完成后,您可以像创建普通 PostgreSQL 集群一样,使用 pgsql.yml 部署 Citus 集群。


管理Citus集群

定义好 Citus 集群后,部署 Citus 集群同样使用的剧本 pgsql.yml

./pgsql.yml -l pg-citus    # 部署 Citus 集群 pg-citus

使用任意成员的 DBSU(postgres)用户,都能通过 patronictlalias: pg) 列出 Citus 集群的状态:

$ pg list
+ Citus cluster: pg-citus ----------+---------+-----------+----+-----------+--------------------+
| Group | Member      | Host        | Role    | State     | TL | Lag in MB | Tags               |
+-------+-------------+-------------+---------+-----------+----+-----------+--------------------+
|     0 | pg-citus0-1 | 10.10.10.10 | Leader  | running   |  1 |           | clonefrom: true    |
|       |             |             |         |           |    |           | conf: tiny.yml     |
|       |             |             |         |           |    |           | spec: 20C.40G.125G |
|       |             |             |         |           |    |           | version: '16'      |
+-------+-------------+-------------+---------+-----------+----+-----------+--------------------+
|     1 | pg-citus1-1 | 10.10.10.11 | Leader  | running   |  1 |           | clonefrom: true    |
|       |             |             |         |           |    |           | conf: tiny.yml     |
|       |             |             |         |           |    |           | spec: 10C.20G.125G |
|       |             |             |         |           |    |           | version: '16'      |
+-------+-------------+-------------+---------+-----------+----+-----------+--------------------+
|     2 | pg-citus2-1 | 10.10.10.12 | Leader  | running   |  1 |           | clonefrom: true    |
|       |             |             |         |           |    |           | conf: tiny.yml     |
|       |             |             |         |           |    |           | spec: 10C.20G.125G |
|       |             |             |         |           |    |           | version: '16'      |
+-------+-------------+-------------+---------+-----------+----+-----------+--------------------+
|     2 | pg-citus2-2 | 10.10.10.13 | Replica | streaming |  1 |         0 | clonefrom: true    |
|       |             |             |         |           |    |           | conf: tiny.yml     |
|       |             |             |         |           |    |           | spec: 10C.20G.125G |
|       |             |             |         |           |    |           | version: '16'      |
+-------+-------------+-------------+---------+-----------+----+-----------+--------------------+

您可以将每个水平分片集群视为一个独立的 PGSQL 集群,使用 pg (patronictl) 命令管理它们。 但是务必注意,当你使用 pg 命令管理 Citus 集群时,需要额外使用 --group 参数指定集群分片号

pg list pg-citus --group 0   # 需要使用 --group 0 指定集群分片号

Citus 中有一个名为 pg_dist_node 的系统表,用于记录 Citus 集群的节点信息,Patroni 会自动维护该表。

PGURL=postgres://postgres:[email protected]/citus

psql $PGURL -c 'SELECT * FROM pg_dist_node;'       # 查看节点信息
 nodeid | groupid |  nodename   | nodeport | noderack | hasmetadata | isactive | noderole  | nodecluster | metadatasynced | shouldhaveshards
--------+---------+-------------+----------+----------+-------------+----------+-----------+-------------+----------------+------------------
      1 |       0 | 10.10.10.10 |     5432 | default  | t           | t        | primary   | default     | t              | f
      4 |       1 | 10.10.10.12 |     5432 | default  | t           | t        | primary   | default     | t              | t
      5 |       2 | 10.10.10.13 |     5432 | default  | t           | t        | primary   | default     | t              | t
      6 |       0 | 10.10.10.11 |     5432 | default  | t           | t        | secondary | default     | t              | f

此外,你还可以查看用户认证信息(仅限超级用户访问):

$ psql $PGURL -c 'SELECT * FROM pg_dist_authinfo;'   # 查看节点认证信息(仅限超级用户访问)

然后,你可以使用普通业务用户(例如,具有 DDL 权限的 dbuser_citus)来访问 Citus 集群:

psql postgres://dbuser_citus:[email protected]/citus -c 'SELECT * FROM pg_dist_node;'

使用Citus集群

在使用 Citus 集群时,我们强烈建议您先阅读 Citus 官方文档,了解其架构设计与核心概念。

其中核心是了解 Citus 中的五种表,以及其特点与应用场景:

  • 分布式表(Distributed Table)
  • 参考表(Reference Table)
  • 本地表(Local Table)
  • 本地管理表(Local Management Table)
  • 架构表(Schema Table)

在协调者节点上,您可以创建分布式表和引用表,并从任何数据节点查询它们。从 11.2 开始,任何 Citus 数据库节点都可以扮演协调者的角色了。

我们可以使用 pgbench 来创建一些表,并将其中的主表(pgbench_accounts)分布到各个节点上,然后将其他小表作为引用表:

PGURL=postgres://dbuser_citus:[email protected]/citus
pgbench -i $PGURL

psql $PGURL <<-EOF
SELECT create_distributed_table('pgbench_accounts', 'aid'); SELECT truncate_local_data_after_distributing_table('public.pgbench_accounts');
SELECT create_reference_table('pgbench_branches')         ; SELECT truncate_local_data_after_distributing_table('public.pgbench_branches');
SELECT create_reference_table('pgbench_history')          ; SELECT truncate_local_data_after_distributing_table('public.pgbench_history');
SELECT create_reference_table('pgbench_tellers')          ; SELECT truncate_local_data_after_distributing_table('public.pgbench_tellers');
EOF

执行读写测试:

pgbench -nv -P1 -c10 -T500 postgres://dbuser_citus:[email protected]/citus      # 直连协调者 5432 端口
pgbench -nv -P1 -c10 -T500 postgres://dbuser_citus:[email protected]:6432/citus # 通过连接池,减少客户端连接数压力,可以有效提高整体吞吐。
pgbench -nv -P1 -c10 -T500 postgres://dbuser_citus:[email protected]/citus      # 任意 primary 节点都可以作为 coordinator
pgbench --select-only -nv -P1 -c10 -T500 postgres://dbuser_citus:[email protected]/citus # 可以发起只读查询

更严肃的生产部署

要将 Citus 用于生产环境,您通常需要为 Coordinator 和每个 Worker 集群设置流复制物理副本。

当前 conf/ha/citus.yml 在 13 台主机上定义了 1 个 pg-meta 实例,以及 12 个 Citus 实例(6 个双节点物理集群,pg_group 为 0–5)。下面的 10 节点片段是另一种独立的生产拓扑示例,并非当前模板内容。

pg-citus: # citus group
  hosts:
    10.10.10.50: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.60/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.51: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.60/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.52: { pg_group: 1, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.61/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.53: { pg_group: 1, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.61/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.54: { pg_group: 2, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.62/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.55: { pg_group: 2, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.62/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.56: { pg_group: 3, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.63/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.57: { pg_group: 3, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.63/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.58: { pg_group: 4, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.64/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.59: { pg_group: 4, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.64/24 ,pg_seq: 1, pg_role: replica }
  vars:
    pg_mode: citus                            # pgsql cluster mode: citus
    pg_version: 18                            # citus 13.x supports PG 14-18
    pg_shard: pg-citus                        # citus shard name: pg-citus
    pg_primary_db: citus                      # primary database used by citus
    pg_vip_enabled: true                      # enable vip for citus cluster
    pg_vip_interface: auto                    # auto detect vip interface for every member
    pg_dbsu_password: DBUser.Postgres         # enable dbsu password access for citus
    pg_extensions: [ citus, postgis, pgvector, topn, pg_cron, hll ]  # install these extensions
    pg_libs: 'citus, pg_cron, pg_stat_statements' # citus will be added by patroni automatically
    pg_users: [{ name: dbuser_citus ,password: DBUser.Citus ,pgbouncer: true ,roles: [ dbrole_admin ]    }]
    pg_databases: [{ name: citus ,owner: dbuser_citus ,extensions: [ citus, vector, topn, pg_cron, hll ] }]
    pg_parameters:
      cron.database_name: citus
      citus.node_conninfo: 'sslrootcert=/pg/cert/ca.crt sslmode=verify-full'
    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'  }

我们将在后续教程中覆盖一系列关于 Citus 的高级主题

  • 读写分离
  • 故障处理
  • 一致性备份与恢复
  • 高级监控与问题诊断
  • 连接池

8.8 - 监控系统

Pigsty 监控系统架构概览,以及如何监控现存的 PostgreSQL 实例?

本文介绍了 Pigsty 的监控系统架构,包括监控指标,日志,与目标管理的方式。以及如何 监控现有PG集群 与远程 RDS服务


监控概览

Pigsty 使用现代的可观测技术栈对 PostgreSQL 进行监控:

  • 使用 Grafana 进行指标可视化和 PostgreSQL 数据源。
  • 使用 VictoriaMetrics 来采集 PostgreSQL / Pgbouncer / Patroni / HAProxy / Node 的指标
  • 使用 VictoriaLogs 来记录 PostgreSQL / Pgbouncer / Patroni / pgBackRest 以及主机组件的日志
  • Pigsty 提供了开箱即用的 Grafana 仪表盘,展示与 PostgreSQL 有关的方方面面。

监控指标

PostgreSQL 本身的监控指标完全由 pg_exporter 配置文件所定义:roles/pg_monitor/templates/pg_exporter.yml。 它们会进一步由 VictoriaMetrics/vmalert 兼容的记录与告警规则加工处理:files/victoria/rules/pgsql.yml

Pigsty 使用三个身份标签:clsinsip,它们将附加到所有指标和日志上。此外,Pgbouncer 的监控指标,主机节点 NODE,与负载均衡器的监控指标也会被 Pigsty 所使用,并尽可能地使用相同的标签以便于关联分析。

- { cls: pg-meta, ins: pg-meta-1, ip: 10.10.10.10 }
- { cls: pg-test, ins: pg-test-1, ip: 10.10.10.11 }
- { cls: pg-test, ins: pg-test-2, ip: 10.10.10.12 }
- { cls: pg-test, ins: pg-test-3, ip: 10.10.10.13 }

日志

与 PostgreSQL 有关的日志由 vector 负责收集,并发送至 infra 节点上的 VictoriaLogs 日志存储/查询服务。

目标管理

VictoriaMetrics 的监控目标在 /infra/targets/pgsql/ 下的静态文件中定义,每个实例都有一个相应的文件。以 pg-meta-1 为例:

# pg-meta-1 [primary] @ 10.10.10.10
- labels: { cls: pg-meta, ins: pg-meta-1, ip: 10.10.10.10 }
  targets:
    - 10.10.10.10:9630    # <--- pg_exporter 用于PostgreSQL指标
    - 10.10.10.10:9631    # <--- pgbouncer_exporter 用于 Pgbouncer 指标
    - 10.10.10.10:8008    # <--- patroni指标(未启用 API SSL 时)
    - 10.10.10.10:9854    # <--- pgbackrest_exporter 用于备份指标

当全局标志 patroni_ssl_enabled 被设置时,Patroni 目标会单独写入 /infra/targets/patroni/<ins>.yml,因为此时使用 HTTPS 抓取端点。当您 监控RDS 实例时,监控目标会放在 /infra/targets/pgrds/ 目录下,并以 集群 为单位进行管理。

当使用 bin/pgsql-rmpgsql-rm.yml 移除集群时,相应监控目标会被移除。您也可以使用:

bin/pgmon-rm <cls|ins>    # 从所有 infra 节点中移除监控目标

远程 RDS 监控目标会被放置于 /infra/targets/pgrds/<cls>.yml,它们由 pgsql-monitor.yml 剧本或 bin/pgmon-add 脚本创建。


监控模式

Pigsty 提供三种监控模式,以适应不同的监控需求。

事项\等级 L1 L2 L3
名称 基础部署 托管部署 标准部署
英文 RDS MANAGED FULL
场景 只有连接串,例如 RDS DB 已存在,节点可管理 实例由 Pigsty 创建
PGCAT 功能 ✅ 完整可用 ✅ 完整可用 ✅ 完整可用
PGSQL 功能 ✅ 限 PG 指标 ✅ 限 PG 与节点指标 ✅ 完整功能
连接池指标 ❌ 不可用 ⚠️ 选装 ✅ 预装项
负载均衡器指标 ❌ 不可用 ⚠️ 选装 ✅ 预装项
PGLOG 功能 ❌ 不可用 ⚠️ 选装 ✅ 预装项
PG Exporter ⚠️ 部署于 Infra 节点 ✅ 部署于 DB 节点 ✅ 部署于 DB 节点
Node Exporter ❌ 不部署 ✅ 部署于 DB 节点 ✅ 部署于 DB 节点
侵入 DB 节点 ✅ 无侵入 ⚠️ 安装 Exporter ⚠️ 完全由 Pigsty 管理
监控现有实例 ✅ 可支持 ✅ 可支持 ❌ 仅用于 Pigsty 托管实例
监控用户与视图 人工创建 人工创建 Pigsty 自动创建
部署使用剧本 bin/pgmon-add <cls> 部分执行 pgsql.yml/node.yml pgsql.yml
所需权限 Infra 节点可达的 PGURL DB 节点 ssh 与 sudo 权限 DB 节点 ssh 与 sudo 权限
功能概述 PGCAT + PGRDS 大部分功能 完整功能

由 Pigsty 完全管理的数据库会自动纳入监控,并拥有最好的监控支持,通常不需要任何配置。对于现有的 PostgreSQL 集群或者 RDS 服务,如果目标 DB 节点 可以被 Pigsty 所管理(ssh 可达,sudo 可用),那么您可以考虑 托管部署,实现与 Pigsty 基本类似的监控管理体验。如果您 只能通过 PGURL(数据库连接串)的方式访问目标数据库,例如远程的 RDS 服务,则可以考虑使用 精简模式 监控目标数据库。


监控现有集群

如果目标 DB 节点可以被 Pigsty 所管理ssh 可达且 sudo 可用),那么您可以使用 pgsql.yml 剧本中的 pg_exporter 任务, 使用与标准部署相同的方式,在目标节点上部署监控组件:PG Exporter。您也可以使用该剧本的 pgbouncerpgbouncer_exporter 任务在已有实例节点上部署连接池及其监控。此外,您也可以使用 node.yml 中的 node_exporterhaproxyvector 部署主机监控,负载均衡,日志收集组件。从而获得与原生 Pigsty 数据库实例完全一致的使用体验。

现有集群的定义方式与 Pigsty 所管理的集群定义方式完全相同,您只是选择性执行 pgsql.yml 剧本中的部分任务,而不是执行整个剧本。

./node.yml  -l <cls> -t node_repo,node_pkg           # 在主机节点上添加 INFRA节点的 YUM 源并安装软件包。
./node.yml  -l <cls> -t node_exporter,node_register  # 配置主机监控,并加入 VictoriaMetrics
./node.yml  -l <cls> -t vector                       # 配置主机日志采集,并发送至 VictoriaLogs
./pgsql.yml -l <cls> -t pg_exporter,pg_register      # 配置 PostgreSQL 监控,并注册至 Victoria/Grafana

因为目标数据库集群已存在,所以您需要手工在目标数据库集群上 创建监控用户、模式与扩展


监控RDS

如果您 只能通过 PGURL(数据库连接串)的方式访问目标数据库,那么可以参照这里的说明进行配置。在这种模式下,Pigsty 在 INFRA节点 上部署对应的 PG Exporter,抓取远端数据库指标信息。如下图所示:

------ infra ------
|                 |
| victoria-metrics|            v---- pg-foo-1 ----v
|       ^         |  metrics   |         ^        |
|   pg_exporter <-|------------|----  postgres    |
|   (port: 20001) |            | 10.10.10.10:5432 |
|       ^         |            ^------------------^
|       ^         |                      ^
|       ^         |            v---- pg-foo-2 ----v
|       ^         |  metrics   |         ^        |
|   pg_exporter <-|------------|----  postgres    |
|   (port: 20002) |            | 10.10.10.11:5433 |
-------------------            ^------------------^

在这种模式下,监控系统不会有主机,连接池,负载均衡器,高可用组件的相关指标,但数据库本身,以及数据目录(Catalog)中的实时状态信息仍然可用。Pigsty 提供了两个专用的监控面板,专注于 PostgreSQL 本身的监控指标: PGRDS ClusterPGRDS Instance,总览与数据库内监控则复用现有监控面板。因为 Pigsty 不能管理您的 RDS,所以用户需要在目标数据库上提前 配置好监控对象

监控外部 Postgres 实例时的局限性
  • PgBouncer 连接池指标不可用
  • Patroni 高可用组件指标不可用
  • 主机节点监控指标不可用,以及节点 HAProxy,Keepalived 指标亦不可用。
  • 日志收集与日志衍生指标不可用

下面我们使用沙箱环境作为示例:现在我们假设 pg-meta 集群是一个有待监控的 RDS 实例 pg-foo-1,而 pg-test 集群则是一个有待监控的 RDS 集群 pg-bar

  1. 在目标上创建监控模式、用户和权限。详情请参考 监控对象配置

  2. 在配置清单中声明集群。例如,假设我们想要监控“远端”的 pg-meta & pg-test 集群:

    infra:            # 代理、监控、警报等的infra集群..
      hosts: { 10.10.10.10: { infra_seq: 1 } }
      vars:           # 在组'infra'上为远程postgres RDS安装pg_exporter
        pg_exporters: # 在此列出所有远程实例,为k分配一个唯一的未使用的本地端口
          20001: { pg_cluster: pg-foo, pg_seq: 1, pg_host: 10.10.10.10 , pg_databases: [{ name: meta }] } # 注册 meta 数据库为 Grafana 数据源
    
          20002: { pg_cluster: pg-bar, pg_seq: 1, pg_host: 10.10.10.11 , pg_port: 5432 } # 几种不同的连接串拼接方法
          20003: { pg_cluster: pg-bar, pg_seq: 2, pg_host: 10.10.10.12 , pg_exporter_url: 'postgres://dbuser_monitor:[email protected]:5432/postgres?sslmode=disable'}
          20004: { pg_cluster: pg-bar, pg_seq: 3, pg_host: 10.10.10.13 , pg_monitor_username: dbuser_monitor, pg_monitor_password: DBUser.Monitor }

    其中, pg_databases 字段中所列出的数据库,将会被注册至 Grafana 中,成为一个 PostgreSQL 数据源,为 PGCAT 监控面板提供数据支持。如果您不想使用 PGCAT,将注册数据库到 Grafana 中,只需要将 pg_databases 设置为空数组或直接留空即可。

    pigsty-monitor.jpg
  3. 执行添加监控命令:bin/pgmon-add <clsname>

    bin/pgmon-add pg-foo  # 将 pg-foo 集群纳入监控
    bin/pgmon-add pg-bar  # 将 pg-bar 集群纳入监控
  4. 要删除远程集群的监控目标,可以使用 bin/pgmon-rm <clsname>

    bin/pgmon-rm pg-foo  # 将 pg-foo 从 Pigsty 监控中移除
    bin/pgmon-rm pg-bar  # 将 pg-bar 从 Pigsty 监控中移除

您可以使用更多的参数来覆盖默认 pg_exporter 的选项,下面是一个使用 Pigsty 监控阿里云 RDS 与 PolarDB 的配置样例:

示例:监控阿里云 RDS for PostgreSQL 与 PolarDB

详情请参考:remote.yml

infra:            # 代理、监控、警报等的infra集群..
  hosts: { 10.10.10.10: { infra_seq: 1 } }
  vars:
    pg_exporters:   # 在此列出所有待监控的远程 RDS PG 实例

      20001:        # 分配一个唯一的未使用的本地端口,供本地监控 Agent 使用,这里是一个 PolarDB 的主库
        pg_cluster: pg-polar                  # RDS 集群名 (身份参数,手工指定分配监控系统内名称)
        pg_seq: 1                             # RDS 实例号 (身份参数,手工指定分配监控系统内名称)
        pg_host: pc-2ze379wb1d4irc18x.polardbpg.rds.aliyuncs.com # RDS 主机地址
        pg_port: 1921                         # RDS 端口(从控制台连接信息获取)
        pg_exporter_auto_discovery: true      # 启用新数据库自动发现功能
        pg_exporter_include_database: 'test'  # 仅监控这个列表中的数据库(多个数据库用逗号分隔)
        pg_monitor_username: dbuser_monitor   # 监控用的用户名,覆盖全局配置
        pg_monitor_password: DBUser_Monitor   # 监控用的密码,覆盖全局配置
        pg_databases: [{ name: test }]        # 希望启用PGCAT的数据库列表,只要name字段即可,register_datasource设置为false则不注册。

      20002:       # 这是一个 PolarDB  从库
        pg_cluster: pg-polar                  # RDS 集群名 (身份参数,手工指定分配监控系统内名称)
        pg_seq: 2                             # RDS 实例号 (身份参数,手工指定分配监控系统内名称)
        pg_host: pe-2ze7tg620e317ufj4.polarpgmxs.rds.aliyuncs.com # RDS 主机地址
        pg_port: 1521                         # RDS 端口(从控制台连接信息获取)
        pg_exporter_auto_discovery: true      # 启用新数据库自动发现功能
        pg_exporter_include_database: 'test,postgres'  # 仅监控这个列表中的数据库(多个数据库用逗号分隔)
        pg_monitor_username: dbuser_monitor   # 监控用的用户名
        pg_monitor_password: DBUser_Monitor   # 监控用的密码
        pg_databases: [ { name: test } ]        # 希望启用PGCAT的数据库列表,只要name字段即可,register_datasource设置为false则不注册。

      20004: # 这是一个基础版的单节点 RDS for PostgreSQL 实例
        pg_cluster: pg-rds                    # RDS 集群名 (身份参数,手工指定分配监控系统内名称)
        pg_seq: 1                             # RDS 实例号 (身份参数,手工指定分配监控系统内名称)
        pg_host: pgm-2zern3d323fe9ewk.pg.rds.aliyuncs.com  # RDS 主机地址
        pg_port: 5432                         # RDS 端口(从控制台连接信息获取)
        pg_exporter_auto_discovery: true      # 启用新数据库自动发现功能
        pg_exporter_include_database: 'rds'   # 仅监控这个列表中的数据库(多个数据库用逗号分隔)
        pg_monitor_username: dbuser_monitor   # 监控用的用户名
        pg_monitor_password: DBUser_Monitor   # 监控用的密码
        pg_databases: [ { name: rds } ]       # 希望启用PGCAT的数据库列表,只要name字段即可,register_datasource设置为false则不注册。

      20005: # 这是一个高可用版的 RDS for PostgreSQL 集群主库
        pg_cluster: pg-rdsha                  # RDS 集群名 (身份参数,手工指定分配监控系统内名称)
        pg_seq: 1                             # RDS 实例号 (身份参数,手工指定分配监控系统内名称)
        pg_host: pgm-2ze3d35d27bq08wu.pg.rds.aliyuncs.com  # RDS 主机地址
        pg_port: 5432                         # RDS 端口(从控制台连接信息获取)
        pg_exporter_include_database: 'rds'   # 仅监控这个列表中的数据库(多个数据库用逗号分隔)
        pg_databases: [ { name: rds }, {name : test} ]  # 将这两个数据库纳入 PGCAT 管理,注册为 Grafana 数据源

      20006: # 这是一个高可用版的 RDS for PostgreSQL 集群只读实例(从库)
        pg_cluster: pg-rdsha                  # RDS 集群名 (身份参数,手工指定分配监控系统内名称)
        pg_seq: 2                             # RDS 实例号 (身份参数,手工指定分配监控系统内名称)
        pg_host: pgr-2zexqxalk7d37edt.pg.rds.aliyuncs.com  # RDS 主机地址
        pg_port: 5432                         # RDS 端口(从控制台连接信息获取)
        pg_exporter_include_database: 'rds'   # 仅监控这个列表中的数据库(多个数据库用逗号分隔)
        pg_databases: [ { name: rds }, {name : test} ]  # 将这两个数据库纳入 PGCAT 管理,注册为 Grafana 数据源

监控对象配置

当您想要监控现有实例时,不论是 RDS,还是自建的 PostgreSQL 实例,您都需要在目标数据库上进行一些配置,以便 Pigsty 可以访问它们。

为了将外部现存 PostgreSQL 实例纳入监控,您需要有一个可用于访问该实例/集群的连接串。任何可达连接串(业务用户,超级用户)均可使用,但我们建议使用一个专用监控用户以避免权限泄漏。

  • 监控用户:默认使用的用户名为 dbuser_monitor, 该用户属于 pg_monitor 角色组,或确保具有相关视图访问权限。
  • 监控认证:默认使用密码访问,您需要确保 HBA 策略允许监控用户从管理机或 DB 节点本地访问数据库。
  • 监控模式:固定使用名称 monitor,用于安装额外的 监控视图 与扩展插件,非必选,但建议创建。
  • 监控扩展强烈建议 启用 PG 自带的监控扩展 pg_stat_statements
  • 监控视图:监控视图是可选项,可以提供更多的监控指标支持。

监控用户

以 Pigsty 默认使用的监控用户 dbuser_monitor 为例,在目标数据库集群创建以下用户。

CREATE USER dbuser_monitor;                                       -- 创建监控用户
COMMENT ON ROLE dbuser_monitor IS 'system monitor user';          -- 监控用户备注
GRANT pg_monitor TO dbuser_monitor;                               -- 授予监控用户 pg_monitor 权限,否则一些指标将无法采集

ALTER USER dbuser_monitor PASSWORD 'DBUser.Monitor';              -- 按需修改监控用户密码(强烈建议修改!但请与Pigsty配置一致)
ALTER USER dbuser_monitor SET log_min_duration_statement = 1000;  -- 建议设置此参数,避免日志塞满监控慢查询
ALTER USER dbuser_monitor SET search_path = monitor,public;       -- 建议设置此参数,避免 pg_stat_statements 扩展无法生效

请注意,这里创建的监控用户与密码需要与 pg_monitor_usernamepg_monitor_password 保持一致。


监控认证

配置数据库 pg_hba.conf 文件,添加以下规则以允许监控用户从本地,以及管理机使用密码访问所有数据库。

# allow local role monitor with password
local   all  dbuser_monitor                    md5
host    all  dbuser_monitor  127.0.0.1/32      md5
host    all  dbuser_monitor  <管理机器IP地址>/32 md5

如果您的 RDS 不支持定义 HBA,那么把安装 Pigsty 机器的内网 IP 地址开白即可。


监控模式

监控模式 可选项,即使没有,Pigsty 监控系统的主体也可以正常工作,但我们强烈建议设置此模式。

CREATE SCHEMA IF NOT EXISTS monitor;               -- 创建监控专用模式
GRANT USAGE ON SCHEMA monitor TO dbuser_monitor;   -- 允许监控用户使用

监控扩展

监控扩展是可选项,但我们强烈建议启用 pg_stat_statements 扩展该扩展提供了关于查询性能的重要数据。

注意:该扩展必须列入数据库参数 shared_preload_libraries 中方可生效,而修改该参数需要重启数据库。

CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "monitor";

请注意,您应当在默认的管理数据库 postgres 中安装此扩展。有些时候,RDS 不允许您在 postgres 数据库中创建监控模式, 在这种情况下,您可以将 pg_stat_statements 插件安装到默认的 public 下,只要确保监控用户的 search_path 按照上面的配置,能够找到 pg_stat_statements 视图即可。

CREATE EXTENSION IF NOT EXISTS "pg_stat_statements";
ALTER USER dbuser_monitor SET search_path = monitor,public; -- 建议设置此参数,避免 pg_stat_statements 扩展无法生效

监控视图

监控视图提供了若干常用的预处理结果,并对某些需要高权限的监控指标进行权限封装(例如共享内存分配),便于查询与使用。强烈建议在所有需要监控的数据库中创建

监控模式与监控视图定义

下列 SQL 便于理解监控对象;当前 Pigsty 实际渲染的完整定义以 roles/pgsql/templates/pg-init-template.sql 为准,当前模板还包含对安全搜索路径与权限边界的额外加固。

----------------------------------------------------------------------
-- Table bloat estimate : monitor.pg_table_bloat
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_table_bloat CASCADE;
CREATE OR REPLACE VIEW monitor.pg_table_bloat AS
SELECT CURRENT_CATALOG AS datname, nspname, relname , tblid , bs * tblpages AS size,
       CASE WHEN tblpages - est_tblpages_ff > 0 THEN (tblpages - est_tblpages_ff)/tblpages::FLOAT ELSE 0 END AS ratio
FROM (
         SELECT ceil( reltuples / ( (bs-page_hdr)*fillfactor/(tpl_size*100) ) ) + ceil( toasttuples / 4 ) AS est_tblpages_ff,
                tblpages, fillfactor, bs, tblid, nspname, relname, is_na
         FROM (
                  SELECT
                      ( 4 + tpl_hdr_size + tpl_data_size + (2 * ma)
                          - CASE WHEN tpl_hdr_size % ma = 0 THEN ma ELSE tpl_hdr_size % ma END
                          - CASE WHEN ceil(tpl_data_size)::INT % ma = 0 THEN ma ELSE ceil(tpl_data_size)::INT % ma END
                          ) AS tpl_size, (heappages + toastpages) AS tblpages, heappages,
                      toastpages, reltuples, toasttuples, bs, page_hdr, tblid, nspname, relname, fillfactor, is_na
                  FROM (
                           SELECT
                               tbl.oid AS tblid, ns.nspname , tbl.relname, tbl.reltuples,
                               tbl.relpages AS heappages, coalesce(toast.relpages, 0) AS toastpages,
                               coalesce(toast.reltuples, 0) AS toasttuples,
                               coalesce(substring(array_to_string(tbl.reloptions, ' ') FROM 'fillfactor=([0-9]+)')::smallint, 100) AS fillfactor,
                               current_setting('block_size')::numeric AS bs,
                               CASE WHEN version()~'mingw32' OR version()~'64-bit|x86_64|ppc64|ia64|amd64' THEN 8 ELSE 4 END AS ma,
                               24 AS page_hdr,
                               23 + CASE WHEN MAX(coalesce(s.null_frac,0)) > 0 THEN ( 7 + count(s.attname) ) / 8 ELSE 0::int END
                                   + CASE WHEN bool_or(att.attname = 'oid' and att.attnum < 0) THEN 4 ELSE 0 END AS tpl_hdr_size,
                               sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 0) ) AS tpl_data_size,
                               bool_or(att.atttypid = 'pg_catalog.name'::regtype)
                                   OR sum(CASE WHEN att.attnum > 0 THEN 1 ELSE 0 END) <> count(s.attname) AS is_na
                           FROM pg_attribute AS att
                                    JOIN pg_class AS tbl ON att.attrelid = tbl.oid
                                    JOIN pg_namespace AS ns ON ns.oid = tbl.relnamespace
                                    LEFT JOIN pg_stats AS s ON s.schemaname=ns.nspname AND s.tablename = tbl.relname AND s.inherited=false AND s.attname=att.attname
                                    LEFT JOIN pg_class AS toast ON tbl.reltoastrelid = toast.oid
                           WHERE NOT att.attisdropped AND tbl.relkind = 'r' AND nspname NOT IN ('pg_catalog','information_schema')
                           GROUP BY 1,2,3,4,5,6,7,8,9,10
                       ) AS s
              ) AS s2
     ) AS s3
WHERE NOT is_na;
COMMENT ON VIEW monitor.pg_table_bloat IS 'postgres table bloat estimate';

GRANT SELECT ON monitor.pg_table_bloat TO pg_monitor;

----------------------------------------------------------------------
-- Index bloat estimate : monitor.pg_index_bloat
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_index_bloat CASCADE;
CREATE OR REPLACE VIEW monitor.pg_index_bloat AS
SELECT CURRENT_CATALOG AS datname, nspname, idxname AS relname, tblid, idxid, relpages::BIGINT * bs AS size,
       COALESCE((relpages - ( reltuples * (6 + ma - (CASE WHEN index_tuple_hdr % ma = 0 THEN ma ELSE index_tuple_hdr % ma END)
                                               + nulldatawidth + ma - (CASE WHEN nulldatawidth % ma = 0 THEN ma ELSE nulldatawidth % ma END))
                                  / (bs - pagehdr)::FLOAT  + 1 )), 0) / relpages::FLOAT AS ratio
FROM (
         SELECT nspname,idxname,indrelid AS tblid,indexrelid AS idxid,
                reltuples,relpages,
                current_setting('block_size')::INTEGER                                                               AS bs,
                (CASE WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8 ELSE 4 END)  AS ma,
                24                                                                                                   AS pagehdr,
                (CASE WHEN max(COALESCE(pg_stats.null_frac, 0)) = 0 THEN 2 ELSE 6 END)                               AS index_tuple_hdr,
                sum((1.0 - COALESCE(pg_stats.null_frac, 0.0)) *
                    COALESCE(pg_stats.avg_width, 1024))::INTEGER                                                     AS nulldatawidth
         FROM pg_attribute
                  JOIN (
             SELECT pg_namespace.nspname,
                    ic.relname                                                   AS idxname,
                    ic.reltuples,
                    ic.relpages,
                    pg_index.indrelid,
                    pg_index.indexrelid,
                    tc.relname                                                   AS tablename,
                    regexp_split_to_table(pg_index.indkey::TEXT, ' ') :: INTEGER AS attnum,
                    pg_index.indexrelid                                          AS index_oid
             FROM pg_index
                      JOIN pg_class ic ON pg_index.indexrelid = ic.oid
                      JOIN pg_class tc ON pg_index.indrelid = tc.oid
                      JOIN pg_namespace ON pg_namespace.oid = ic.relnamespace
                      JOIN pg_am ON ic.relam = pg_am.oid
             WHERE pg_am.amname = 'btree' AND ic.relpages > 0 AND nspname NOT IN ('pg_catalog', 'information_schema')
         ) ind_atts ON pg_attribute.attrelid = ind_atts.indexrelid AND pg_attribute.attnum = ind_atts.attnum
                  JOIN pg_stats ON pg_stats.schemaname = ind_atts.nspname
             AND ((pg_stats.tablename = ind_atts.tablename AND pg_stats.attname = pg_get_indexdef(pg_attribute.attrelid, pg_attribute.attnum, TRUE))
                 OR (pg_stats.tablename = ind_atts.idxname AND pg_stats.attname = pg_attribute.attname))
         WHERE pg_attribute.attnum > 0
         GROUP BY 1, 2, 3, 4, 5, 6
     ) est;
COMMENT ON VIEW monitor.pg_index_bloat IS 'postgres index bloat estimate (btree-only)';

GRANT SELECT ON monitor.pg_index_bloat TO pg_monitor;

----------------------------------------------------------------------
-- Relation Bloat : monitor.pg_bloat
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_bloat CASCADE;
CREATE OR REPLACE VIEW monitor.pg_bloat AS
SELECT coalesce(ib.datname, tb.datname)                                                   AS datname,
       coalesce(ib.nspname, tb.nspname)                                                   AS nspname,
       coalesce(ib.tblid, tb.tblid)                                                       AS tblid,
       coalesce(tb.nspname || '.' || tb.relname, ib.nspname || '.' || ib.tblid::RegClass) AS tblname,
       tb.size                                                                            AS tbl_size,
       CASE WHEN tb.ratio < 0 THEN 0 ELSE round(tb.ratio::NUMERIC, 6) END                 AS tbl_ratio,
       (tb.size * (CASE WHEN tb.ratio < 0 THEN 0 ELSE tb.ratio::NUMERIC END)) ::BIGINT    AS tbl_wasted,
       ib.idxid,
       ib.nspname || '.' || ib.relname                                                    AS idxname,
       ib.size                                                                            AS idx_size,
       CASE WHEN ib.ratio < 0 THEN 0 ELSE round(ib.ratio::NUMERIC, 5) END                 AS idx_ratio,
       (ib.size * (CASE WHEN ib.ratio < 0 THEN 0 ELSE ib.ratio::NUMERIC END)) ::BIGINT    AS idx_wasted
FROM monitor.pg_index_bloat ib
         FULL OUTER JOIN monitor.pg_table_bloat tb ON ib.tblid = tb.tblid;

COMMENT ON VIEW monitor.pg_bloat IS 'postgres relation bloat detail';
GRANT SELECT ON monitor.pg_bloat TO pg_monitor;

----------------------------------------------------------------------
-- monitor.pg_index_bloat_human
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_index_bloat_human CASCADE;
CREATE OR REPLACE VIEW monitor.pg_index_bloat_human AS
SELECT idxname                            AS name,
       tblname,
       idx_wasted                         AS wasted,
       pg_size_pretty(idx_size)           AS idx_size,
       round(100 * idx_ratio::NUMERIC, 2) AS idx_ratio,
       pg_size_pretty(idx_wasted)         AS idx_wasted,
       pg_size_pretty(tbl_size)           AS tbl_size,
       round(100 * tbl_ratio::NUMERIC, 2) AS tbl_ratio,
       pg_size_pretty(tbl_wasted)         AS tbl_wasted
FROM monitor.pg_bloat
WHERE idxname IS NOT NULL;
COMMENT ON VIEW monitor.pg_index_bloat_human IS 'postgres index bloat info in human-readable format';
GRANT SELECT ON monitor.pg_index_bloat_human TO pg_monitor;


----------------------------------------------------------------------
-- monitor.pg_table_bloat_human
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_table_bloat_human CASCADE;
CREATE OR REPLACE VIEW monitor.pg_table_bloat_human AS
SELECT tblname                                          AS name,
       idx_wasted + tbl_wasted                          AS wasted,
       pg_size_pretty(idx_wasted + tbl_wasted)          AS all_wasted,
       pg_size_pretty(tbl_wasted)                       AS tbl_wasted,
       pg_size_pretty(tbl_size)                         AS tbl_size,
       tbl_ratio,
       pg_size_pretty(idx_wasted)                       AS idx_wasted,
       pg_size_pretty(idx_size)                         AS idx_size,
       round(idx_wasted::NUMERIC * 100.0 / idx_size, 2) AS idx_ratio
FROM (SELECT datname,
             nspname,
             tblname,
             coalesce(max(tbl_wasted), 0)                         AS tbl_wasted,
             coalesce(max(tbl_size), 1)                           AS tbl_size,
             round(100 * coalesce(max(tbl_ratio), 0)::NUMERIC, 2) AS tbl_ratio,
             coalesce(sum(idx_wasted), 0)                         AS idx_wasted,
             coalesce(sum(idx_size), 1)                           AS idx_size
      FROM monitor.pg_bloat
      WHERE tblname IS NOT NULL
      GROUP BY 1, 2, 3
     ) d;
COMMENT ON VIEW monitor.pg_table_bloat_human IS 'postgres table bloat info in human-readable format';
GRANT SELECT ON monitor.pg_table_bloat_human TO pg_monitor;


----------------------------------------------------------------------
-- Activity Overview: monitor.pg_session
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_session CASCADE;
CREATE OR REPLACE VIEW monitor.pg_session AS
SELECT coalesce(datname, 'all') AS datname, numbackends, active, idle, ixact, max_duration, max_tx_duration, max_conn_duration
FROM (
         SELECT datname,
                count(*)                                         AS numbackends,
                count(*) FILTER ( WHERE state = 'active' )       AS active,
                count(*) FILTER ( WHERE state = 'idle' )         AS idle,
                count(*) FILTER ( WHERE state = 'idle in transaction'
                    OR state = 'idle in transaction (aborted)' ) AS ixact,
                max(extract(epoch from now() - state_change))
                FILTER ( WHERE state = 'active' )                AS max_duration,
                max(extract(epoch from now() - xact_start))      AS max_tx_duration,
                max(extract(epoch from now() - backend_start))   AS max_conn_duration
         FROM pg_stat_activity
         WHERE backend_type = 'client backend'
           AND pid <> pg_backend_pid()
         GROUP BY ROLLUP (1)
         ORDER BY 1 NULLS FIRST
     ) t;
COMMENT ON VIEW monitor.pg_session IS 'postgres activity group by session';
GRANT SELECT ON monitor.pg_session TO pg_monitor;


----------------------------------------------------------------------
-- Sequential Scan: monitor.pg_seq_scan
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_seq_scan CASCADE;
CREATE OR REPLACE VIEW monitor.pg_seq_scan AS
SELECT schemaname                                                        AS nspname,
       relname,
       seq_scan,
       seq_tup_read,
       seq_tup_read / seq_scan                                           AS seq_tup_avg,
       idx_scan,
       n_live_tup + n_dead_tup                                           AS tuples,
       round(n_live_tup * 100.0::NUMERIC / (n_live_tup + n_dead_tup), 2) AS live_ratio
FROM pg_stat_user_tables
WHERE seq_scan > 0
  and (n_live_tup + n_dead_tup) > 0
ORDER BY seq_scan DESC;
COMMENT ON VIEW monitor.pg_seq_scan IS 'table that have seq scan';
GRANT SELECT ON monitor.pg_seq_scan TO pg_monitor;
查看共享内存分配的函数(PG13 以上可用)
DROP FUNCTION IF EXISTS monitor.pg_shmem() CASCADE;
CREATE OR REPLACE FUNCTION monitor.pg_shmem() RETURNS SETOF
    pg_shmem_allocations SET search_path = '' AS $$ SELECT * FROM pg_shmem_allocations;$$ LANGUAGE SQL SECURITY DEFINER;
COMMENT ON FUNCTION monitor.pg_shmem() IS 'security wrapper for system view pg_shmem';
REVOKE ALL ON FUNCTION monitor.pg_shmem() FROM PUBLIC;
REVOKE ALL ON FUNCTION monitor.pg_shmem() FROM dbrole_readonly;
REVOKE ALL ON FUNCTION monitor.pg_shmem() FROM dbrole_offline;
GRANT EXECUTE ON FUNCTION monitor.pg_shmem() TO pg_monitor;

8.9 - 监控面板

Pigsty 为 PostgreSQL 提供了诸多开箱即用的 Grafana 监控仪表盘

Pigsty 为 PostgreSQL 提供了诸多开箱即用的 Grafana 监控仪表盘: Demo & Gallery

当前源码共提供 31 个 PostgreSQL 相关面板:files/grafana/pgsql 中有 29 个 PostgreSQL / PGCAT 面板,files/grafana/app 中另有 2 个 PGLOG 面板。它们按层次分为总览、集群、实例、数据库四大类,按数据来源分为 PGSQLPGCATPGLOG 三类。

pigsty-dashboard.jpg

总览

概览

  • pgsql-overview:PGSQL 模块的主仪表板
  • pgsql-alert:PGSQL 的全局关键指标和警报事件
  • pgsql-shard:关于水平分片的 PGSQL 集群的概览,例如 citus / gpsql 集群

集群

  • pgsql-cluster:一个 PGSQL 集群的主仪表板
  • pgrds-cluster:PGSQL Cluster 的 RDS 版本,专注于所有 PostgreSQL 本身的指标
  • pgsql-activity:关注 PGSQL 集群的会话/负载/QPS/TPS/锁定情况
  • pgsql-replication:关注 PGSQL 集群复制、插槽和发布/订阅
  • pgsql-service:关注 PGSQL 集群服务、代理、路由和负载均衡
  • pgsql-databases:关注所有实例的数据库 CRUD、慢查询和表统计信息
  • pgsql-patroni:关注集群高可用状态,Patroni 组件状态
  • pgsql-pitr:关注集群 PITR 过程的上下文,用于辅助时间点恢复

实例

  • pgsql-instance:单个 PGSQL 实例的主仪表板
  • pgrds-instance:PGSQL Instance 的 RDS 版本,专注于所有 PostgreSQL 本身的指标
  • pgcat-instance:直接从数据库目录获取的实例信息
  • pgsql-proxy:单个 haproxy 负载均衡器的详细指标
  • pgsql-pgbouncer:单个 Pgbouncer 连接池实例中的指标总览
  • pgsql-persist:持久性指标:WAL、XID、检查点、存档、IO
  • pgsql-session:单个实例中的会话和活动/空闲时间的指标
  • pgsql-xacts:关于事务、锁、TPS/QPS 相关的指标
  • pgsql-exporter:Postgres 与 Pgbouncer 监控组件自我监控指标

数据库

  • pgsql-database:单个 PGSQL 数据库的主仪表板
  • pgcat-database:直接从数据库目录获取的数据库信息
  • pgsql-tables:单个数据库内的表/索引访问指标
  • pgsql-table:单个表的详细信息(QPS/RT/索引/序列…)
  • pgcat-table:直接从数据库目录获取的单个表的详细信息(统计/膨胀…)
  • pgsql-query:单个查询的详细信息(QPS/RT)
  • pgcat-query:直接从数据库目录获取的单个查询的详细信息(SQL/统计)
  • pgcat-schema:直接从数据库目录获取关于模式的信息(表/索引/序列…)
  • pgcat-locks:直接从数据库目录获取的关于活动与锁等待的信息

总览

PGSQL Overview:PGSQL 模块的主仪表板

PGSQL Overview

pgsql-overview.jpg

PGSQL Alert:PGSQL 全局核心指标总览与告警事件一览

PGSQL Alert

pgsql-alert.jpg

PGSQL Shard:展示一个 PGSQL 水平分片集群内的横向指标对比:例如 CITUS / GPSQL 集群。

PGSQL Shard

pgsql-shard.jpg


集群

PGSQL Cluster:一个 PGSQL 集群的主仪表板

PGSQL Cluster

pgsql-cluster.jpg

PGRDS Cluster:PGSQL Cluster 的 RDS 版本,专注于所有 PostgreSQL 本身的指标

PGRDS Cluster

pgrds-cluster.jpg

PGSQL Service:关注 PGSQL 集群服务、代理、路由和负载均衡。

PGSQL Service

pgsql-service.jpg

PGSQL Activity:关注 PGSQL 集群的会话/负载/QPS/TPS/锁定情况

PGSQL Activity

pgsql-activity.jpg

PGSQL Replication:关注 PGSQL 集群复制、插槽和发布/订阅。

PGSQL Replication

pgsql-replication.jpg

PGSQL Databases:关注所有实例的数据库 CRUD、慢查询和表统计信息。

PGSQL Databases

pgsql-databases.jpg

PGSQL Patroni:关注集群高可用状态,Patroni 组件状态

PGSQL Patroni

pgsql-patroni.jpg

PGSQL PITR:关注集群 PITR 过程的上下文,用于辅助时间点恢复

PGSQL PITR

pgsql-patroni.jpg


实例

PGSQL Instance:单个 PGSQL 实例的主仪表板

PGSQL Instance

pgsql-instance.jpg

PGRDS Instance:PGSQL Instance 的 RDS 版本,专注于所有 PostgreSQL 本身的指标

PGRDS Instance

pgrds-instance.jpg

PGSQL Proxy:单个 haproxy 负载均衡器的详细指标

PGSQL Proxy

pgsql-proxy.jpg

PGSQL Pgbouncer:单个 Pgbouncer 连接池实例中的指标总览

PGSQL Pgbouncer

pgsql-pgbouncer.jpg

PGSQL Persist:持久性指标:WAL、XID、检查点、存档、IO

PGSQL Persist

pgsql-persist.jpg

PGSQL Xacts:关于事务、锁、TPS/QPS 相关的指标

PGSQL Xacts

pgsql-xacts.jpg

PGSQL Session:单个实例中的会话和活动/空闲时间的指标

PGSQL Session

pgsql-session.jpg

PGSQL Exporter:Postgres/Pgbouncer 监控组件自我监控指标

PGSQL Exporter

pgsql-exporter.jpg


数据库

PGSQL Database:单个 PGSQL 数据库的主仪表板

PGSQL Database

pgsql-database.jpg

PGSQL Tables:单个数据库内的表/索引访问指标

PGSQL Tables

pgsql-tables.jpg

PGSQL Table:单个表的详细信息(QPS/RT/索引/序列…)

PGSQL Table

pgsql-table.jpg

PGSQL Query:单类查询的详细信息(QPS/RT)

PGSQL Query

pgsql-query.jpg


PGCAT

PGCAT Instance:直接从数据库目录获取的实例信息

PGCAT Instance

pgcat-instance.jpg

PGCAT Database:直接从数据库目录获取的数据库信息

PGCAT Database

pgcat-database.jpg

PGCAT Schema:直接从数据库目录获取关于模式的信息(表/索引/序列…)

PGCAT Schema

pgcat-schema.jpg

PGCAT Table:直接从数据库目录获取的单个表的详细信息(统计/膨胀…)

PGCAT Table

pgcat-table.jpg

PGCAT Query:直接从数据库目录获取的单类查询的详细信息(SQL/统计)

PGCAT Query

pgcat-query.jpg

PGCAT Locks:直接从数据库目录获取的关于活动与锁等待的信息

PGCAT Locks

pgcat-locks.jpg


PGLOG

PGLOG Overview:总览 Pigsty CMDB 中的 CSV 日志样本

PGLOG Overview

pglog-overview.jpg

PGLOG Overview:Pigsty CMDB 中的 CSV 日志样本中某一条会话的日志详情

PGLOG Session

pglog-session.jpg


画廊

详情请参考 pigsty/wiki/gallery

PGSQL Overview

pgsql-overview.jpg

PGSQL Shard

pgsql-shard.jpg

PGSQL Cluster

pgsql-cluster.jpg

PGSQL Service

pgsql-service.jpg

PGSQL Activity

pgsql-activity.jpg

PGSQL Replication

pgsql-replication.jpg

PGSQL Databases

pgsql-databases.jpg

PGSQL Instance

pgsql-instance.jpg

PGSQL Proxy

pgsql-proxy.jpg

PGSQL Pgbouncer

pgsql-pgbouncer.jpg

PGSQL Session

pgsql-session.jpg

PGSQL Xacts

pgsql-xacts.jpg

PGSQL Persist

pgsql-persist.jpg

PGSQL Database

pgsql-database.jpg

PGSQL Tables

pgsql-tables.jpg

PGSQL Table

pgsql-table.jpg

PGSQL Query

pgsql-query.jpg

PGCAT Instance

pgcat-instance.jpg

PGCAT Database

pgcat-database.jpg

PGCAT Schema

pgcat-schema.jpg

PGCAT Table

pgcat-table.jpg

PGCAT Lock

pgcat-locks.jpg

PGCAT Query

pgcat-query.jpg

PGLOG Overview

pglog-overview.jpg

PGLOG Session

pglog-session.jpg

8.9.1 - 总览面板

PostgreSQL 模块全局总览类监控面板

PostgreSQL 模块全局总览类监控面板,包括:

8.9.1.1 - PGSQL Overview

PGSQL 模块的主仪表板

PGSQL 模块的主仪表板:Demo

PGSQL Overview 是 PostgreSQL 模块的主仪表板,提供整个 PGSQL 模块的全局概览视图。

pgsql-overview

8.9.1.2 - PGSQL Alert

PGSQL 的全局关键指标和警报事件

PGSQL 的全局关键指标和警报事件:Demo

PGSQL Alert 仪表板展示 PGSQL 全局核心指标总览与告警事件一览。

pgsql-alert

8.9.1.3 - PGSQL Shard

关于水平分片的 PGSQL 集群的概览

关于水平分片的 PGSQL 集群的概览:Demo

PGSQL Shard 仪表板展示一个 PGSQL 水平分片集群内的横向指标对比,例如 Citus / GPSQL 集群。

pgsql-shard

8.9.2 - 集群面板

PostgreSQL 集群级别监控面板

PostgreSQL 集群级别监控面板,包括:

  • PGSQL Cluster:一个 PGSQL 集群的主仪表板
  • PGRDS Cluster:PGSQL Cluster 的 RDS 版本,专注于 PostgreSQL 本身的指标
  • PGSQL Activity:关注 PGSQL 集群的会话/负载/QPS/TPS/锁定情况
  • PGSQL Replication:关注 PGSQL 集群复制、插槽和发布/订阅
  • PGSQL Service:关注 PGSQL 集群服务、代理、路由和负载均衡
  • PGSQL Databases:关注所有实例的数据库 CRUD、慢查询和表统计信息
  • PGSQL Patroni:关注集群高可用状态,Patroni 组件状态
  • PGSQL PITR:关注集群 PITR 过程的上下文,用于辅助时间点恢复

8.9.2.1 - PGSQL Cluster

一个 PGSQL 集群的主仪表板

一个 PGSQL 集群的主仪表板:Demo

PGSQL Cluster 是单个 PostgreSQL 集群的主仪表板,提供集群级别的核心指标概览。

pgsql-cluster

8.9.2.2 - PGRDS Cluster

PGSQL Cluster 的 RDS 版本,专注于 PostgreSQL 本身的指标

PGSQL Cluster 的 RDS 版本:Demo

PGRDS Cluster 是 PGSQL Cluster 的 RDS 版本,专注于所有 PostgreSQL 本身的指标,适用于云数据库 RDS 监控场景。

pgrds-cluster

8.9.2.3 - PGSQL Activity

关注 PGSQL 集群的会话/负载/QPS/TPS/锁定情况

关注 PGSQL 集群的会话/负载/QPS/TPS/锁定情况:Demo

PGSQL Activity 仪表板关注 PGSQL 集群的会话、负载、QPS、TPS 以及锁定情况。

pgsql-activity

8.9.2.4 - PGSQL Replication

关注 PGSQL 集群复制、插槽和发布/订阅

关注 PGSQL 集群复制、插槽和发布/订阅:Demo

PGSQL Replication 仪表板关注 PGSQL 集群的复制状态、复制插槽和发布/订阅信息。

pgsql-replication

8.9.2.5 - PGSQL Service

关注 PGSQL 集群服务、代理、路由和负载均衡

关注 PGSQL 集群服务、代理、路由和负载均衡:Demo

PGSQL Service 仪表板关注 PGSQL 集群的服务、代理、路由和负载均衡状态。

pgsql-service

8.9.2.6 - PGSQL Databases

关注所有实例的数据库 CRUD、慢查询和表统计信息

关注所有实例的数据库 CRUD、慢查询和表统计信息:Demo

PGSQL Databases 仪表板关注集群中所有实例的数据库 CRUD、慢查询和表统计信息。

pgsql-databases

8.9.2.7 - PGSQL Patroni

关注集群高可用状态,Patroni 组件状态

关注集群高可用状态,Patroni 组件状态:Demo

PGSQL Patroni 仪表板关注集群的高可用状态以及 Patroni 组件的运行状态。

pgsql-patroni

8.9.2.8 - PGSQL PITR

关注集群 PITR 过程的上下文,用于辅助时间点恢复

关注集群 PITR 过程的上下文:Demo

PGSQL PITR 仪表板关注集群 PITR 过程的上下文,用于辅助时间点恢复操作。

pgsql-pitr

8.9.3 - 实例面板

PostgreSQL 实例级别监控面板

PostgreSQL 实例级别监控面板,包括:

  • PGSQL Instance:单个 PGSQL 实例的主仪表板
  • PGRDS Instance:PGSQL Instance 的 RDS 版本,专注于 PostgreSQL 本身的指标
  • PGCAT Instance:直接从数据库目录获取的实例信息
  • PGSQL Persist:持久性指标:WAL、XID、检查点、存档、IO
  • PGSQL Proxy:单个 HAProxy 负载均衡器的详细指标
  • PGSQL Pgbouncer:单个 Pgbouncer 连接池实例中的指标总览
  • PGSQL Session:单个实例中的会话和活动/空闲时间的指标
  • PGSQL Xacts:关于事务、锁、TPS/QPS 相关的指标
  • PGSQL Exporter:Postgres 与 Pgbouncer 监控组件自我监控指标

8.9.3.1 - PGSQL Instance

单个 PGSQL 实例的主仪表板

单个 PGSQL 实例的主仪表板:Demo

PGSQL Instance 是单个 PostgreSQL 实例的主仪表板,提供实例级别的核心指标概览。

pgsql-instance

8.9.3.2 - PGRDS Instance

PGSQL Instance 的 RDS 版本,专注于 PostgreSQL 本身的指标

PGSQL Instance 的 RDS 版本:Demo

PGRDS Instance 是 PGSQL Instance 的 RDS 版本,专注于所有 PostgreSQL 本身的指标,适用于云数据库 RDS 监控场景。

pgrds-instance

8.9.3.3 - PGCAT Instance

直接从数据库目录获取的实例信息

直接从数据库目录获取的实例信息:Demo

PGCAT Instance 仪表板展示直接从数据库系统目录获取的实例信息。

pgcat-instance

8.9.3.4 - PGSQL Persist

持久性指标:WAL、XID、检查点、存档、IO

持久性指标:WAL、XID、检查点、存档、IO:Demo

PGSQL Persist 仪表板关注持久性相关指标:WAL、XID、检查点、存档和 IO。

pgsql-persist

8.9.3.5 - PGSQL Proxy

单个 HAProxy 负载均衡器的详细指标

单个 HAProxy 负载均衡器的详细指标:Demo

PGSQL Proxy 仪表板展示单个 HAProxy 负载均衡器的详细指标。

pgsql-proxy

8.9.3.6 - PGSQL Pgbouncer

单个 Pgbouncer 连接池实例中的指标总览

单个 Pgbouncer 连接池实例中的指标总览:Demo

PGSQL Pgbouncer 仪表板展示单个 Pgbouncer 连接池实例中的指标总览。

pgsql-pgbouncer

8.9.3.7 - PGSQL Session

单个实例中的会话和活动/空闲时间的指标

单个实例中的会话和活动/空闲时间的指标:Demo

PGSQL Session 仪表板展示单个实例中的会话和活动/空闲时间的指标。

pgsql-session

8.9.3.8 - PGSQL Xacts

关于事务、锁、TPS/QPS 相关的指标

关于事务、锁、TPS/QPS 相关的指标:Demo

PGSQL Xacts 仪表板关注事务、锁、TPS/QPS 相关的指标。

pgsql-xacts

8.9.3.9 - PGSQL Exporter

Postgres 与 Pgbouncer 监控组件自我监控指标

Postgres 与 Pgbouncer 监控组件自我监控指标:Demo

PGSQL Exporter 仪表板展示 Postgres 与 Pgbouncer 监控组件的自我监控指标。

pgsql-exporter

8.9.4 - 数据库面板

PostgreSQL 数据库级别监控面板

PostgreSQL 数据库级别监控面板,包括:

  • PGSQL Database:单个 PGSQL 数据库的主仪表板
  • PGCAT Database:直接从数据库目录获取的数据库信息
  • PGSQL Tables:单个数据库内的表/索引访问指标
  • PGSQL Table:单个表的详细信息(QPS/RT/索引/序列……)
  • PGCAT Table:直接从数据库目录获取的单个表的详细信息
  • PGSQL Query:单类查询的详细信息(QPS/RT)
  • PGCAT Query:直接从数据库目录获取的单类查询的详细信息
  • PGCAT Locks:直接从数据库目录获取的关于活动与锁等待的信息
  • PGCAT Schema:直接从数据库目录获取关于模式的信息

8.9.4.1 - PGSQL Database

单个 PGSQL 数据库的主仪表板

单个 PGSQL 数据库的主仪表板:Demo

PGSQL Database 是单个 PostgreSQL 数据库的主仪表板,提供数据库级别的核心指标概览。

pgsql-database

8.9.4.2 - PGCAT Database

直接从数据库目录获取的数据库信息

直接从数据库目录获取的数据库信息:Demo

PGCAT Database 仪表板展示直接从数据库系统目录获取的数据库信息。

pgcat-database

8.9.4.3 - PGSQL Tables

单个数据库内的表/索引访问指标

单个数据库内的表/索引访问指标:Demo

PGSQL Tables 仪表板展示单个数据库内的表和索引访问指标。

pgsql-tables

8.9.4.4 - PGSQL Table

单个表的详细信息(QPS/RT/索引/序列……)

单个表的详细信息:Demo

PGSQL Table 仪表板展示单个表的详细信息,包括 QPS、RT、索引、序列等指标。

pgsql-table

8.9.4.5 - PGCAT Table

直接从数据库目录获取的单个表的详细信息

直接从数据库目录获取的单个表的详细信息:Demo

PGCAT Table 仪表板展示直接从数据库系统目录获取的单个表的详细信息,包括统计和膨胀信息。

pgcat-table

8.9.4.6 - PGSQL Query

单类查询的详细信息(QPS/RT)

单类查询的详细信息:Demo

PGSQL Query 仪表板展示单类查询的详细信息,包括 QPS 和 RT 指标。

pgsql-query

8.9.4.7 - PGCAT Query

直接从数据库目录获取的单类查询的详细信息

直接从数据库目录获取的单类查询的详细信息:Demo

PGCAT Query 仪表板展示直接从数据库系统目录获取的单类查询的详细信息,包括 SQL 和统计信息。

pgcat-query

8.9.4.8 - PGCAT Locks

直接从数据库目录获取的关于活动与锁等待的信息

直接从数据库目录获取的关于活动与锁等待的信息:Demo

PGCAT Locks 仪表板展示直接从数据库系统目录获取的关于活动与锁等待的信息。

pgcat-locks

8.9.4.9 - PGCAT Schema

直接从数据库目录获取关于模式的信息

直接从数据库目录获取关于模式的信息:Demo

PGCAT Schema 仪表板展示直接从数据库系统目录获取的关于模式的信息,包括表、索引、序列等。

pgcat-schema

8.10 - 指标列表

Pigsty PGSQL 模块提供的完整监控指标列表与释义

PGSQL 模块包含有 638 类可用监控指标。

Metric Name Type Labels Description
ALERTS Unknown category, job, level, ins, severity, ip, alertname, alertstate, instance, cls N/A
ALERTS_FOR_STATE Unknown category, job, level, ins, severity, ip, alertname, instance, cls N/A
cls:pressure1 Unknown job, cls N/A
cls:pressure15 Unknown job, cls N/A
cls:pressure5 Unknown job, cls N/A
go_gc_duration_seconds summary job, ins, ip, instance, quantile, cls A summary of the pause duration of garbage collection cycles.
go_gc_duration_seconds_count Unknown job, ins, ip, instance, cls N/A
go_gc_duration_seconds_sum Unknown job, ins, ip, instance, cls N/A
go_goroutines gauge job, ins, ip, instance, cls Number of goroutines that currently exist.
go_info gauge version, job, ins, ip, instance, cls Information about the Go environment.
go_memstats_alloc_bytes gauge job, ins, ip, instance, cls Number of bytes allocated and still in use.
go_memstats_alloc_bytes_total counter job, ins, ip, instance, cls Total number of bytes allocated, even if freed.
go_memstats_buck_hash_sys_bytes gauge job, ins, ip, instance, cls Number of bytes used by the profiling bucket hash table.
go_memstats_frees_total counter job, ins, ip, instance, cls Total number of frees.
go_memstats_gc_sys_bytes gauge job, ins, ip, instance, cls Number of bytes used for garbage collection system metadata.
go_memstats_heap_alloc_bytes gauge job, ins, ip, instance, cls Number of heap bytes allocated and still in use.
go_memstats_heap_idle_bytes gauge job, ins, ip, instance, cls Number of heap bytes waiting to be used.
go_memstats_heap_inuse_bytes gauge job, ins, ip, instance, cls Number of heap bytes that are in use.
go_memstats_heap_objects gauge job, ins, ip, instance, cls Number of allocated objects.
go_memstats_heap_released_bytes gauge job, ins, ip, instance, cls Number of heap bytes released to OS.
go_memstats_heap_sys_bytes gauge job, ins, ip, instance, cls Number of heap bytes obtained from system.
go_memstats_last_gc_time_seconds gauge job, ins, ip, instance, cls Number of seconds since 1970 of last garbage collection.
go_memstats_lookups_total counter job, ins, ip, instance, cls Total number of pointer lookups.
go_memstats_mallocs_total counter job, ins, ip, instance, cls Total number of mallocs.
go_memstats_mcache_inuse_bytes gauge job, ins, ip, instance, cls Number of bytes in use by mcache structures.
go_memstats_mcache_sys_bytes gauge job, ins, ip, instance, cls Number of bytes used for mcache structures obtained from system.
go_memstats_mspan_inuse_bytes gauge job, ins, ip, instance, cls Number of bytes in use by mspan structures.
go_memstats_mspan_sys_bytes gauge job, ins, ip, instance, cls Number of bytes used for mspan structures obtained from system.
go_memstats_next_gc_bytes gauge job, ins, ip, instance, cls Number of heap bytes when next garbage collection will take place.
go_memstats_other_sys_bytes gauge job, ins, ip, instance, cls Number of bytes used for other system allocations.
go_memstats_stack_inuse_bytes gauge job, ins, ip, instance, cls Number of bytes in use by the stack allocator.
go_memstats_stack_sys_bytes gauge job, ins, ip, instance, cls Number of bytes obtained from system for stack allocator.
go_memstats_sys_bytes gauge job, ins, ip, instance, cls Number of bytes obtained from system.
go_threads gauge job, ins, ip, instance, cls Number of OS threads created.
ins:pressure1 Unknown job, ins, ip, cls N/A
ins:pressure15 Unknown job, ins, ip, cls N/A
ins:pressure5 Unknown job, ins, ip, cls N/A
patroni_cluster_unlocked gauge job, ins, ip, instance, cls, scope Value is 1 if the cluster is unlocked, 0 if locked.
patroni_dcs_last_seen gauge job, ins, ip, instance, cls, scope Epoch timestamp when DCS was last contacted successfully by Patroni.
patroni_failsafe_mode_is_active gauge job, ins, ip, instance, cls, scope Value is 1 if failsafe mode is active, 0 if inactive.
patroni_is_paused gauge job, ins, ip, instance, cls, scope Value is 1 if auto failover is disabled, 0 otherwise.
patroni_master gauge job, ins, ip, instance, cls, scope Value is 1 if this node is the leader, 0 otherwise.
patroni_pending_restart gauge job, ins, ip, instance, cls, scope Value is 1 if the node needs a restart, 0 otherwise.
patroni_postgres_in_archive_recovery gauge job, ins, ip, instance, cls, scope Value is 1 if Postgres is replicating from archive, 0 otherwise.
patroni_postgres_running gauge job, ins, ip, instance, cls, scope Value is 1 if Postgres is running, 0 otherwise.
patroni_postgres_server_version gauge job, ins, ip, instance, cls, scope Version of Postgres (if running), 0 otherwise.
patroni_postgres_streaming gauge job, ins, ip, instance, cls, scope Value is 1 if Postgres is streaming, 0 otherwise.
patroni_postgres_timeline counter job, ins, ip, instance, cls, scope Postgres timeline of this node (if running), 0 otherwise.
patroni_postmaster_start_time gauge job, ins, ip, instance, cls, scope Epoch seconds since Postgres started.
patroni_primary gauge job, ins, ip, instance, cls, scope Value is 1 if this node is the leader, 0 otherwise.
patroni_replica gauge job, ins, ip, instance, cls, scope Value is 1 if this node is a replica, 0 otherwise.
patroni_standby_leader gauge job, ins, ip, instance, cls, scope Value is 1 if this node is the standby_leader, 0 otherwise.
patroni_sync_standby gauge job, ins, ip, instance, cls, scope Value is 1 if this node is a sync standby replica, 0 otherwise.
patroni_up Unknown job, ins, ip, instance, cls N/A
patroni_version gauge job, ins, ip, instance, cls, scope Patroni semver without periods.
patroni_xlog_location counter job, ins, ip, instance, cls, scope Current location of the Postgres transaction log, 0 if this node is not the leader.
patroni_xlog_paused gauge job, ins, ip, instance, cls, scope Value is 1 if the Postgres xlog is paused, 0 otherwise.
patroni_xlog_received_location counter job, ins, ip, instance, cls, scope Current location of the received Postgres transaction log, 0 if this node is not a replica.
patroni_xlog_replayed_location counter job, ins, ip, instance, cls, scope Current location of the replayed Postgres transaction log, 0 if this node is not a replica.
patroni_xlog_replayed_timestamp gauge job, ins, ip, instance, cls, scope Current timestamp of the replayed Postgres transaction log, 0 if null.
pg:cls:active_backends Unknown job, cls N/A
pg:cls:active_time_rate15m Unknown job, cls N/A
pg:cls:active_time_rate1m Unknown job, cls N/A
pg:cls:active_time_rate5m Unknown job, cls N/A
pg:cls:age Unknown job, cls N/A
pg:cls:buf_alloc_rate1m Unknown job, cls N/A
pg:cls:buf_clean_rate1m Unknown job, cls N/A
pg:cls:buf_flush_backend_rate1m Unknown job, cls N/A
pg:cls:buf_flush_checkpoint_rate1m Unknown job, cls N/A
pg:cls:cpu_count Unknown job, cls N/A
pg:cls:cpu_usage Unknown job, cls N/A
pg:cls:cpu_usage_15m Unknown job, cls N/A
pg:cls:cpu_usage_1m Unknown job, cls N/A
pg:cls:cpu_usage_5m Unknown job, cls N/A
pg:cls:db_size Unknown job, cls N/A
pg:cls:file_size Unknown job, cls N/A
pg:cls:ixact_backends Unknown job, cls N/A
pg:cls:ixact_time_rate1m Unknown job, cls N/A
pg:cls:lag_bytes Unknown job, cls N/A
pg:cls:lag_seconds Unknown job, cls N/A
pg:cls:leader Unknown job, ins, ip, instance, cls N/A
pg:cls:load1 Unknown job, cls N/A
pg:cls:load15 Unknown job, cls N/A
pg:cls:load5 Unknown job, cls N/A
pg:cls:lock_count Unknown job, cls N/A
pg:cls:locks Unknown job, cls, mode N/A
pg:cls:log_size Unknown job, cls N/A
pg:cls:lsn_rate1m Unknown job, cls N/A
pg:cls:members Unknown job, ins, ip, cls N/A
pg:cls:num_backends Unknown job, cls N/A
pg:cls:partition Unknown job, cls N/A
pg:cls:receiver Unknown state, slot_name, job, appname, ip, cls, sender_host, sender_port N/A
pg:cls:rlock_count Unknown job, cls N/A
pg:cls:saturation1 Unknown job, cls N/A
pg:cls:saturation15 Unknown job, cls N/A
pg:cls:saturation5 Unknown job, cls N/A
pg:cls:sender Unknown pid, usename, address, job, ins, appname, ip, cls N/A
pg:cls:session_time_rate1m Unknown job, cls N/A
pg:cls:size Unknown job, cls N/A
pg:cls:slot_count Unknown job, cls N/A
pg:cls:slot_retained_bytes Unknown job, cls N/A
pg:cls:standby_count Unknown job, cls N/A
pg:cls:sync_state Unknown job, cls N/A
pg:cls:timeline Unknown job, cls N/A
pg:cls:tup_deleted_rate1m Unknown job, cls N/A
pg:cls:tup_fetched_rate1m Unknown job, cls N/A
pg:cls:tup_inserted_rate1m Unknown job, cls N/A
pg:cls:tup_modified_rate1m Unknown job, cls N/A
pg:cls:tup_returned_rate1m Unknown job, cls N/A
pg:cls:wal_size Unknown job, cls N/A
pg:cls:xact_commit_rate15m Unknown job, cls N/A
pg:cls:xact_commit_rate1m Unknown job, cls N/A
pg:cls:xact_commit_rate5m Unknown job, cls N/A
pg:cls:xact_rollback_rate15m Unknown job, cls N/A
pg:cls:xact_rollback_rate1m Unknown job, cls N/A
pg:cls:xact_rollback_rate5m Unknown job, cls N/A
pg:cls:xact_total_rate15m Unknown job, cls N/A
pg:cls:xact_total_rate1m Unknown job, cls N/A
pg:cls:xact_total_sigma15m Unknown job, cls N/A
pg:cls:xlock_count Unknown job, cls N/A
pg:db:active_backends Unknown datname, job, ins, ip, instance, cls N/A
pg:db:active_time_rate15m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:active_time_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:active_time_rate5m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:age Unknown datname, job, ins, ip, instance, cls N/A
pg:db:age_deriv1h Unknown datname, job, ins, ip, instance, cls N/A
pg:db:age_exhaust Unknown datname, job, ins, ip, instance, cls N/A
pg:db:blk_io_time_seconds_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:blk_read_time_seconds_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:blk_write_time_seconds_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:blks_access_1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:blks_hit_1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:blks_hit_ratio1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:blks_read_1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:conn_limit Unknown datname, job, ins, ip, instance, cls N/A
pg:db:conn_usage Unknown datname, job, ins, ip, instance, cls N/A
pg:db:db_size Unknown datname, job, ins, ip, instance, cls N/A
pg:db:ixact_backends Unknown datname, job, ins, ip, instance, cls N/A
pg:db:ixact_time_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:lock_count Unknown datname, job, ins, ip, instance, cls N/A
pg:db:num_backends Unknown datname, job, ins, ip, instance, cls N/A
pg:db:rlock_count Unknown datname, job, ins, ip, instance, cls N/A
pg:db:session_time_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:temp_bytes_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:temp_files_1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:tup_deleted_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:tup_fetched_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:tup_inserted_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:tup_modified_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:tup_returned_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:wlock_count Unknown datname, job, ins, ip, instance, cls N/A
pg:db:xact_commit_rate15m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:xact_commit_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:xact_commit_rate5m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:xact_rollback_rate15m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:xact_rollback_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:xact_rollback_rate5m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:xact_total_rate15m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:xact_total_rate1m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:xact_total_rate5m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:xact_total_sigma15m Unknown datname, job, ins, ip, instance, cls N/A
pg:db:xlock_count Unknown datname, job, ins, ip, instance, cls N/A
pg:env:active_backends Unknown job N/A
pg:env:active_time_rate15m Unknown job N/A
pg:env:active_time_rate1m Unknown job N/A
pg:env:active_time_rate5m Unknown job N/A
pg:env:age Unknown job N/A
pg:env:cpu_count Unknown job N/A
pg:env:cpu_usage Unknown job N/A
pg:env:cpu_usage_15m Unknown job N/A
pg:env:cpu_usage_1m Unknown job N/A
pg:env:cpu_usage_5m Unknown job N/A
pg:env:ixact_backends Unknown job N/A
pg:env:ixact_time_rate1m Unknown job N/A
pg:env:lag_bytes Unknown job N/A
pg:env:lag_seconds Unknown job N/A
pg:env:lsn_rate1m Unknown job N/A
pg:env:session_time_rate1m Unknown job N/A
pg:env:tup_deleted_rate1m Unknown job N/A
pg:env:tup_fetched_rate1m Unknown job N/A
pg:env:tup_inserted_rate1m Unknown job N/A
pg:env:tup_modified_rate1m Unknown job N/A
pg:env:tup_returned_rate1m Unknown job N/A
pg:env:xact_commit_rate15m Unknown job N/A
pg:env:xact_commit_rate1m Unknown job N/A
pg:env:xact_commit_rate5m Unknown job N/A
pg:env:xact_rollback_rate15m Unknown job N/A
pg:env:xact_rollback_rate1m Unknown job N/A
pg:env:xact_rollback_rate5m Unknown job N/A
pg:env:xact_total_rate15m Unknown job N/A
pg:env:xact_total_rate1m Unknown job N/A
pg:env:xact_total_sigma15m Unknown job N/A
pg:ins:active_backends Unknown job, ins, ip, instance, cls N/A
pg:ins:active_time_rate15m Unknown job, ins, ip, instance, cls N/A
pg:ins:active_time_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:active_time_rate5m Unknown job, ins, ip, instance, cls N/A
pg:ins:age Unknown job, ins, ip, instance, cls N/A
pg:ins:blks_hit_ratio1m Unknown job, ins, ip, instance, cls N/A
pg:ins:buf_alloc_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:buf_clean_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:buf_flush_backend_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:buf_flush_checkpoint_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:ckpt_1h Unknown job, ins, ip, instance, cls N/A
pg:ins:ckpt_req_1m Unknown job, ins, ip, instance, cls N/A
pg:ins:ckpt_timed_1m Unknown job, ins, ip, instance, cls N/A
pg:ins:conn_limit Unknown job, ins, ip, instance, cls N/A
pg:ins:conn_usage Unknown job, ins, ip, instance, cls N/A
pg:ins:cpu_count Unknown job, ins, ip, instance, cls N/A
pg:ins:cpu_usage Unknown job, ins, ip, instance, cls N/A
pg:ins:cpu_usage_15m Unknown job, ins, ip, instance, cls N/A
pg:ins:cpu_usage_1m Unknown job, ins, ip, instance, cls N/A
pg:ins:cpu_usage_5m Unknown job, ins, ip, instance, cls N/A
pg:ins:db_size Unknown job, ins, ip, instance, cls N/A
pg:ins:file_size Unknown job, ins, ip, instance, cls N/A
pg:ins:fs_size Unknown job, ins, ip, instance, cls N/A
pg:ins:is_leader Unknown job, ins, ip, instance, cls N/A
pg:ins:ixact_backends Unknown job, ins, ip, instance, cls N/A
pg:ins:ixact_time_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:lag_bytes Unknown job, ins, ip, instance, cls N/A
pg:ins:lag_seconds Unknown job, ins, ip, instance, cls N/A
pg:ins:load1 Unknown job, ins, ip, instance, cls N/A
pg:ins:load15 Unknown job, ins, ip, instance, cls N/A
pg:ins:load5 Unknown job, ins, ip, instance, cls N/A
pg:ins:lock_count Unknown job, ins, ip, instance, cls N/A
pg:ins:locks Unknown job, ins, ip, mode, instance, cls N/A
pg:ins:log_size Unknown job, ins, ip, instance, cls N/A
pg:ins:lsn_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:mem_size Unknown job, ins, ip, instance, cls N/A
pg:ins:num_backends Unknown job, ins, ip, instance, cls N/A
pg:ins:rlock_count Unknown job, ins, ip, instance, cls N/A
pg:ins:saturation1 Unknown job, ins, ip, cls N/A
pg:ins:saturation15 Unknown job, ins, ip, cls N/A
pg:ins:saturation5 Unknown job, ins, ip, cls N/A
pg:ins:session_time_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:slot_retained_bytes Unknown job, ins, ip, instance, cls N/A
pg:ins:space_usage Unknown job, ins, ip, instance, cls N/A
pg:ins:status Unknown job, ins, ip, instance, cls N/A
pg:ins:sync_state Unknown job, ins, instance, cls N/A
pg:ins:target_count Unknown job, cls, ins N/A
pg:ins:timeline Unknown job, ins, ip, instance, cls N/A
pg:ins:tup_deleted_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:tup_fetched_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:tup_inserted_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:tup_modified_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:tup_returned_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:wal_size Unknown job, ins, ip, instance, cls N/A
pg:ins:wlock_count Unknown job, ins, ip, instance, cls N/A
pg:ins:xact_commit_rate15m Unknown job, ins, ip, instance, cls N/A
pg:ins:xact_commit_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:xact_commit_rate5m Unknown job, ins, ip, instance, cls N/A
pg:ins:xact_rollback_rate15m Unknown job, ins, ip, instance, cls N/A
pg:ins:xact_rollback_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:xact_rollback_rate5m Unknown job, ins, ip, instance, cls N/A
pg:ins:xact_total_rate15m Unknown job, ins, ip, instance, cls N/A
pg:ins:xact_total_rate1m Unknown job, ins, ip, instance, cls N/A
pg:ins:xact_total_rate5m Unknown job, ins, ip, instance, cls N/A
pg:ins:xact_total_sigma15m Unknown job, ins, ip, instance, cls N/A
pg:ins:xlock_count Unknown job, ins, ip, instance, cls N/A
pg:query:call_rate1m Unknown datname, query, job, ins, ip, instance, cls N/A
pg:query:rt_1m Unknown datname, query, job, ins, ip, instance, cls N/A
pg:table:scan_rate1m Unknown datname, relname, job, ins, ip, instance, cls N/A
pg_activity_count gauge datname, state, job, ins, ip, instance, cls Count of connection among (datname,state)
pg_activity_max_conn_duration gauge datname, state, job, ins, ip, instance, cls Max backend session duration since state change among (datname, state)
pg_activity_max_duration gauge datname, state, job, ins, ip, instance, cls Max duration since last state change among (datname, state)
pg_activity_max_tx_duration gauge datname, state, job, ins, ip, instance, cls Max transaction duration since state change among (datname, state)
pg_archiver_failed_count counter job, ins, ip, instance, cls Number of failed attempts for archiving WAL files
pg_archiver_finish_count counter job, ins, ip, instance, cls Number of WAL files that have been successfully archived
pg_archiver_last_failed_time counter job, ins, ip, instance, cls Time of the last failed archival operation
pg_archiver_last_finish_time counter job, ins, ip, instance, cls Time of the last successful archive operation
pg_archiver_reset_time gauge job, ins, ip, instance, cls Time at which archive statistics were last reset
pg_backend_count gauge type, job, ins, ip, instance, cls Database backend process count by backend_type
pg_bgwriter_buffers_alloc counter job, ins, ip, instance, cls Number of buffers allocated
pg_bgwriter_buffers_backend counter job, ins, ip, instance, cls Number of buffers written directly by a backend
pg_bgwriter_buffers_backend_fsync counter job, ins, ip, instance, cls Number of times a backend had to execute its own fsync call
pg_bgwriter_buffers_checkpoint counter job, ins, ip, instance, cls Number of buffers written during checkpoints
pg_bgwriter_buffers_clean counter job, ins, ip, instance, cls Number of buffers written by the background writer
pg_bgwriter_checkpoint_sync_time counter job, ins, ip, instance, cls Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in seconds
pg_bgwriter_checkpoint_write_time counter job, ins, ip, instance, cls Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in seconds
pg_bgwriter_checkpoints_req counter job, ins, ip, instance, cls Number of requested checkpoints that have been performed
pg_bgwriter_checkpoints_timed counter job, ins, ip, instance, cls Number of scheduled checkpoints that have been performed
pg_bgwriter_maxwritten_clean counter job, ins, ip, instance, cls Number of times the background writer stopped a cleaning scan because it had written too many buffers
pg_bgwriter_reset_time counter job, ins, ip, instance, cls Time at which bgwriter statistics were last reset
pg_boot_time gauge job, ins, ip, instance, cls unix timestamp when postmaster boot
pg_checkpoint_checkpoint_lsn counter job, ins, ip, instance, cls Latest checkpoint location
pg_checkpoint_elapse gauge job, ins, ip, instance, cls Seconds elapsed since latest checkpoint in seconds
pg_checkpoint_full_page_writes gauge job, ins, ip, instance, cls Latest checkpoint’s full_page_writes enabled
pg_checkpoint_newest_commit_ts_xid counter job, ins, ip, instance, cls Latest checkpoint’s newestCommitTsXid
pg_checkpoint_next_multi_offset counter job, ins, ip, instance, cls Latest checkpoint’s NextMultiOffset
pg_checkpoint_next_multixact_id counter job, ins, ip, instance, cls Latest checkpoint’s NextMultiXactId
pg_checkpoint_next_oid counter job, ins, ip, instance, cls Latest checkpoint’s NextOID
pg_checkpoint_next_xid counter job, ins, ip, instance, cls Latest checkpoint’s NextXID xid
pg_checkpoint_next_xid_epoch counter job, ins, ip, instance, cls Latest checkpoint’s NextXID epoch
pg_checkpoint_oldest_active_xid counter job, ins, ip, instance, cls Latest checkpoint’s oldestActiveXID
pg_checkpoint_oldest_commit_ts_xid counter job, ins, ip, instance, cls Latest checkpoint’s oldestCommitTsXid
pg_checkpoint_oldest_multi_dbid gauge job, ins, ip, instance, cls Latest checkpoint’s oldestMulti’s DB OID
pg_checkpoint_oldest_multi_xid counter job, ins, ip, instance, cls Latest checkpoint’s oldestMultiXid
pg_checkpoint_oldest_xid counter job, ins, ip, instance, cls Latest checkpoint’s oldestXID
pg_checkpoint_oldest_xid_dbid gauge job, ins, ip, instance, cls Latest checkpoint’s oldestXID’s DB OID
pg_checkpoint_prev_tli counter job, ins, ip, instance, cls Latest checkpoint’s PrevTimeLineID
pg_checkpoint_redo_lsn counter job, ins, ip, instance, cls Latest checkpoint’s REDO location
pg_checkpoint_time counter job, ins, ip, instance, cls Time of latest checkpoint
pg_checkpoint_tli counter job, ins, ip, instance, cls Latest checkpoint’s TimeLineID
pg_conf_reload_time gauge job, ins, ip, instance, cls seconds since last configuration reload
pg_db_active_time counter datname, job, ins, ip, instance, cls Time spent executing SQL statements in this database, in seconds
pg_db_age gauge datname, job, ins, ip, instance, cls Age of database calculated from datfrozenxid
pg_db_allow_conn gauge datname, job, ins, ip, instance, cls If false(0) then no one can connect to this database.
pg_db_blk_read_time counter datname, job, ins, ip, instance, cls Time spent reading data file blocks by backends in this database, in seconds
pg_db_blk_write_time counter datname, job, ins, ip, instance, cls Time spent writing data file blocks by backends in this database, in seconds
pg_db_blks_access counter datname, job, ins, ip, instance, cls Number of times disk blocks that accessed read+hit
pg_db_blks_hit counter datname, job, ins, ip, instance, cls Number of times disk blocks were found already in the buffer cache
pg_db_blks_read counter datname, job, ins, ip, instance, cls Number of disk blocks read in this database
pg_db_cks_fail_time gauge datname, job, ins, ip, instance, cls Time at which the last data page checksum failure was detected in this database
pg_db_cks_fails counter datname, job, ins, ip, instance, cls Number of data page checksum failures detected in this database, -1 for not enabled
pg_db_confl_confl_bufferpin counter datname, job, ins, ip, instance, cls Number of queries in this database that have been canceled due to pinned buffers
pg_db_confl_confl_deadlock counter datname, job, ins, ip, instance, cls Number of queries in this database that have been canceled due to deadlocks
pg_db_confl_confl_lock counter datname, job, ins, ip, instance, cls Number of queries in this database that have been canceled due to lock timeouts
pg_db_confl_confl_snapshot counter datname, job, ins, ip, instance, cls Number of queries in this database that have been canceled due to old snapshots
pg_db_confl_confl_tablespace counter datname, job, ins, ip, instance, cls Number of queries in this database that have been canceled due to dropped tablespaces
pg_db_conflicts counter datname, job, ins, ip, instance, cls Number of queries canceled due to conflicts with recovery in this database
pg_db_conn_limit gauge datname, job, ins, ip, instance, cls Sets maximum number of concurrent connections that can be made to this database. -1 means no limit.
pg_db_datid gauge datname, job, ins, ip, instance, cls OID of the database
pg_db_deadlocks counter datname, job, ins, ip, instance, cls Number of deadlocks detected in this database
pg_db_frozen_xid gauge datname, job, ins, ip, instance, cls All transaction IDs before this one have been frozened
pg_db_is_template gauge datname, job, ins, ip, instance, cls If true(1), then this database can be cloned by any user with CREATEDB privileges
pg_db_ixact_time counter datname, job, ins, ip, instance, cls Time spent idling while in a transaction in this database, in seconds
pg_db_numbackends gauge datname, job, ins, ip, instance, cls Number of backends currently connected to this database
pg_db_reset_time counter datname, job, ins, ip, instance, cls Time at which database statistics were last reset
pg_db_session_time counter datname, job, ins, ip, instance, cls Time spent by database sessions in this database, in seconds
pg_db_sessions counter datname, job, ins, ip, instance, cls Total number of sessions established to this database
pg_db_sessions_abandoned counter datname, job, ins, ip, instance, cls Number of database sessions to this database that were terminated because connection to the client was lost
pg_db_sessions_fatal counter datname, job, ins, ip, instance, cls Number of database sessions to this database that were terminated by fatal errors
pg_db_sessions_killed counter datname, job, ins, ip, instance, cls Number of database sessions to this database that were terminated by operator intervention
pg_db_temp_bytes counter datname, job, ins, ip, instance, cls Total amount of data written to temporary files by queries in this database.
pg_db_temp_files counter datname, job, ins, ip, instance, cls Number of temporary files created by queries in this database
pg_db_tup_deleted counter datname, job, ins, ip, instance, cls Number of rows deleted by queries in this database
pg_db_tup_fetched counter datname, job, ins, ip, instance, cls Number of rows fetched by queries in this database
pg_db_tup_inserted counter datname, job, ins, ip, instance, cls Number of rows inserted by queries in this database
pg_db_tup_modified counter datname, job, ins, ip, instance, cls Number of rows modified by queries in this database
pg_db_tup_returned counter datname, job, ins, ip, instance, cls Number of rows returned by queries in this database
pg_db_tup_updated counter datname, job, ins, ip, instance, cls Number of rows updated by queries in this database
pg_db_xact_commit counter datname, job, ins, ip, instance, cls Number of transactions in this database that have been committed
pg_db_xact_rollback counter datname, job, ins, ip, instance, cls Number of transactions in this database that have been rolled back
pg_db_xact_total counter datname, job, ins, ip, instance, cls Number of transactions in this database
pg_downstream_count gauge state, job, ins, ip, instance, cls Count of corresponding state
pg_exporter_agent_up Unknown job, ins, ip, instance, cls N/A
pg_exporter_last_scrape_time gauge job, ins, ip, instance, cls seconds exporter spending on scrapping
pg_exporter_query_cache_ttl gauge datname, query, job, ins, ip, instance, cls times to live of query cache
pg_exporter_query_scrape_duration gauge datname, query, job, ins, ip, instance, cls seconds query spending on scrapping
pg_exporter_query_scrape_error_count gauge datname, query, job, ins, ip, instance, cls times the query failed
pg_exporter_query_scrape_hit_count gauge datname, query, job, ins, ip, instance, cls numbers been scrapped from this query
pg_exporter_query_scrape_metric_count gauge datname, query, job, ins, ip, instance, cls numbers of metrics been scrapped from this query
pg_exporter_query_scrape_total_count gauge datname, query, job, ins, ip, instance, cls times exporter server was scraped for metrics
pg_exporter_scrape_duration gauge job, ins, ip, instance, cls seconds exporter spending on scrapping
pg_exporter_scrape_error_count counter job, ins, ip, instance, cls times exporter was scraped for metrics and failed
pg_exporter_scrape_total_count counter job, ins, ip, instance, cls times exporter was scraped for metrics
pg_exporter_server_scrape_duration gauge datname, job, ins, ip, instance, cls seconds exporter server spending on scrapping
pg_exporter_server_scrape_error_count Unknown datname, job, ins, ip, instance, cls N/A
pg_exporter_server_scrape_total_count gauge datname, job, ins, ip, instance, cls times exporter server was scraped for metrics
pg_exporter_server_scrape_total_seconds gauge datname, job, ins, ip, instance, cls seconds exporter server spending on scrapping
pg_exporter_up gauge job, ins, ip, instance, cls always be 1 if your could retrieve metrics
pg_exporter_uptime gauge job, ins, ip, instance, cls seconds since exporter primary server inited
pg_flush_lsn counter job, ins, ip, instance, cls primary only, location of current wal syncing
pg_func_calls counter datname, funcname, job, ins, ip, instance, cls Number of times this function has been called
pg_func_self_time counter datname, funcname, job, ins, ip, instance, cls Total time spent in this function itself, not including other functions called by it, in ms
pg_func_total_time counter datname, funcname, job, ins, ip, instance, cls Total time spent in this function and all other functions called by it, in ms
pg_in_recovery gauge job, ins, ip, instance, cls server is in recovery mode? 1 for yes 0 for no
pg_index_idx_blks_hit counter datname, relname, job, ins, relid, ip, instance, cls, idxname Number of buffer hits in this index
pg_index_idx_blks_read counter datname, relname, job, ins, relid, ip, instance, cls, idxname Number of disk blocks read from this index
pg_index_idx_scan counter datname, relname, job, ins, relid, ip, instance, cls, idxname Number of index scans initiated on this index
pg_index_idx_tup_fetch counter datname, relname, job, ins, relid, ip, instance, cls, idxname Number of live table rows fetched by simple index scans using this index
pg_index_idx_tup_read counter datname, relname, job, ins, relid, ip, instance, cls, idxname Number of index entries returned by scans on this index
pg_index_relpages gauge datname, relname, job, ins, relid, ip, instance, cls, idxname Size of the on-disk representation of this index in pages
pg_index_reltuples gauge datname, relname, job, ins, relid, ip, instance, cls, idxname Estimate relation tuples
pg_insert_lsn counter job, ins, ip, instance, cls primary only, location of current wal inserting
pg_io_evictions counter type, job, ins, object, ip, context, instance, cls Number of times a block has been written out from a shared or local buffer
pg_io_extend_time counter type, job, ins, object, ip, context, instance, cls Time spent in extend operations in seconds
pg_io_extends counter type, job, ins, object, ip, context, instance, cls Number of relation extend operations, each of the size specified in op_bytes.
pg_io_fsync_time counter type, job, ins, object, ip, context, instance, cls Time spent in fsync operations in seconds
pg_io_fsyncs counter type, job, ins, object, ip, context, instance, cls Number of fsync calls. These are only tracked in context normal
pg_io_hits counter type, job, ins, object, ip, context, instance, cls The number of times a desired block was found in a shared buffer.
pg_io_op_bytes gauge type, job, ins, object, ip, context, instance, cls The number of bytes per unit of I/O read, written, or extended. 8192 by default
pg_io_read_time counter type, job, ins, object, ip, context, instance, cls Time spent in read operations in seconds
pg_io_reads counter type, job, ins, object, ip, context, instance, cls Number of read operations, each of the size specified in op_bytes.
pg_io_reset_time gauge type, job, ins, object, ip, context, instance, cls Timestamp at which these statistics were last reset
pg_io_reuses counter type, job, ins, object, ip, context, instance, cls The number of times an existing buffer in reused
pg_io_write_time counter type, job, ins, object, ip, context, instance, cls Time spent in write operations in seconds
pg_io_writeback_time counter type, job, ins, object, ip, context, instance, cls Time spent in writeback operations in seconds
pg_io_writebacks counter type, job, ins, object, ip, context, instance, cls Number of units of size op_bytes which the process requested the kernel write out to permanent storage.
pg_io_writes counter type, job, ins, object, ip, context, instance, cls Number of write operations, each of the size specified in op_bytes.
pg_is_in_recovery gauge job, ins, ip, instance, cls 1 if in recovery mode
pg_is_wal_replay_paused gauge job, ins, ip, instance, cls 1 if wal play paused
pg_lag gauge job, ins, ip, instance, cls replica only, replication lag in seconds
pg_last_replay_time gauge job, ins, ip, instance, cls time when last transaction been replayed
pg_lock_count gauge datname, job, ins, ip, mode, instance, cls Number of locks of corresponding mode and database
pg_lsn counter job, ins, ip, instance, cls log sequence number, current write location
pg_meta_info gauge cls, extensions, version, job, ins, primary_conninfo, conf_path, hba_path, ip, cluster_id, instance, listen_port, wal_level, ver_num, cluster_name, data_dir constant 1
pg_query_calls counter datname, query, job, ins, ip, instance, cls Number of times the statement was executed
pg_query_exec_time counter datname, query, job, ins, ip, instance, cls Total time spent executing the statement, in seconds
pg_query_io_time counter datname, query, job, ins, ip, instance, cls Total time the statement spent reading and writing blocks, in seconds
pg_query_rows counter datname, query, job, ins, ip, instance, cls Total number of rows retrieved or affected by the statement
pg_query_sblk_dirtied counter datname, query, job, ins, ip, instance, cls Total number of shared blocks dirtied by the statement
pg_query_sblk_hit counter datname, query, job, ins, ip, instance, cls Total number of shared block cache hits by the statement
pg_query_sblk_read counter datname, query, job, ins, ip, instance, cls Total number of shared blocks read by the statement
pg_query_sblk_written counter datname, query, job, ins, ip, instance, cls Total number of shared blocks written by the statement
pg_query_wal_bytes counter datname, query, job, ins, ip, instance, cls Total amount of WAL bytes generated by the statement
pg_receive_lsn counter job, ins, ip, instance, cls replica only, location of wal synced to disk
pg_recovery_backup_end_lsn counter job, ins, ip, instance, cls Backup end location
pg_recovery_backup_start_lsn counter job, ins, ip, instance, cls Backup start location
pg_recovery_min_lsn counter job, ins, ip, instance, cls Minimum recovery ending location
pg_recovery_min_timeline counter job, ins, ip, instance, cls Min recovery ending loc’s timeline
pg_recovery_prefetch_block_distance gauge job, ins, ip, instance, cls How many blocks ahead the prefetcher is looking
pg_recovery_prefetch_hit counter job, ins, ip, instance, cls Number of blocks not prefetched because they were already in the buffer pool
pg_recovery_prefetch_io_depth gauge job, ins, ip, instance, cls How many prefetches have been initiated but are not yet known to have completed
pg_recovery_prefetch_prefetch counter job, ins, ip, instance, cls Number of blocks prefetched because they were not in the buffer pool
pg_recovery_prefetch_reset_time counter job, ins, ip, instance, cls Time at which these recovery prefetch statistics were last reset
pg_recovery_prefetch_skip_fpw gauge job, ins, ip, instance, cls Number of blocks not prefetched because a full page image was included in the WAL
pg_recovery_prefetch_skip_init counter job, ins, ip, instance, cls Number of blocks not prefetched because they would be zero-initialized
pg_recovery_prefetch_skip_new counter job, ins, ip, instance, cls Number of blocks not prefetched because they didn’t exist yet
pg_recovery_prefetch_skip_rep counter job, ins, ip, instance, cls Number of blocks not prefetched because they were already recently prefetched
pg_recovery_prefetch_wal_distance gauge job, ins, ip, instance, cls How many bytes ahead the prefetcher is looking
pg_recovery_require_record gauge job, ins, ip, instance, cls End-of-backup record required
pg_recv_flush_lsn counter state, slot_name, job, ins, ip, instance, cls, sender_host, sender_port Last write-ahead log location already received and flushed to disk
pg_recv_flush_tli counter state, slot_name, job, ins, ip, instance, cls, sender_host, sender_port Timeline number of last write-ahead log location received and flushed to disk
pg_recv_init_lsn counter state, slot_name, job, ins, ip, instance, cls, sender_host, sender_port First write-ahead log location used when WAL receiver is started
pg_recv_init_tli counter state, slot_name, job, ins, ip, instance, cls, sender_host, sender_port First timeline number used when WAL receiver is started
pg_recv_msg_recv_time gauge state, slot_name, job, ins, ip, instance, cls, sender_host, sender_port Receipt time of last message received from origin WAL sender
pg_recv_msg_send_time gauge state, slot_name, job, ins, ip, instance, cls, sender_host, sender_port Send time of last message received from origin WAL sender
pg_recv_pid gauge state, slot_name, job, ins, ip, instance, cls, sender_host, sender_port Process ID of the WAL receiver process
pg_recv_reported_lsn counter state, slot_name, job, ins, ip, instance, cls, sender_host, sender_port Last write-ahead log location reported to origin WAL sender
pg_recv_reported_time gauge state, slot_name, job, ins, ip, instance, cls, sender_host, sender_port Time of last write-ahead log location reported to origin WAL sender
pg_recv_time gauge state, slot_name, job, ins, ip, instance, cls, sender_host, sender_port Time of current snapshot
pg_recv_write_lsn counter state, slot_name, job, ins, ip, instance, cls, sender_host, sender_port Last write-ahead log location already received and written to disk, but not flushed.
pg_relkind_count gauge datname, job, ins, ip, instance, cls, relkind Number of relations of corresponding relkind
pg_repl_backend_xmin counter pid, usename, address, job, ins, appname, ip, instance, cls This standby’s xmin horizon reported by hot_standby_feedback.
pg_repl_client_port gauge pid, usename, address, job, ins, appname, ip, instance, cls TCP port number that the client is using for communication with this WAL sender, or -1 if a Unix socket is used
pg_repl_flush_diff gauge pid, usename, address, job, ins, appname, ip, instance, cls Last log position flushed to disk by this standby server diff with current lsn
pg_repl_flush_lag gauge pid, usename, address, job, ins, appname, ip, instance, cls Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written and flushed it
pg_repl_flush_lsn counter pid, usename, address, job, ins, appname, ip, instance, cls Last write-ahead log location flushed to disk by this standby server
pg_repl_launch_time counter pid, usename, address, job, ins, appname, ip, instance, cls Time when this process was started, i.e., when the client connected to this WAL sender
pg_repl_lsn counter pid, usename, address, job, ins, appname, ip, instance, cls Current log position on this server
pg_repl_replay_diff gauge pid, usename, address, job, ins, appname, ip, instance, cls Last log position replayed into the database on this standby server diff with current lsn
pg_repl_replay_lag gauge pid, usename, address, job, ins, appname, ip, instance, cls Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written, flushed and applied it
pg_repl_replay_lsn counter pid, usename, address, job, ins, appname, ip, instance, cls Last write-ahead log location replayed into the database on this standby server
pg_repl_reply_time gauge pid, usename, address, job, ins, appname, ip, instance, cls Send time of last reply message received from standby server
pg_repl_sent_diff gauge pid, usename, address, job, ins, appname, ip, instance, cls Last log position sent to this standby server diff with current lsn
pg_repl_sent_lsn counter pid, usename, address, job, ins, appname, ip, instance, cls Last write-ahead log location sent on this connection
pg_repl_state gauge pid, usename, address, job, ins, appname, ip, instance, cls Current WAL sender encoded state 0-4 for streaming startup catchup backup stopping
pg_repl_sync_priority gauge pid, usename, address, job, ins, appname, ip, instance, cls Priority of this standby server for being chosen as the synchronous standby
pg_repl_sync_state gauge pid, usename, address, job, ins, appname, ip, instance, cls Encoded synchronous state of this standby server, 0-3 for async potential sync quorum
pg_repl_time counter pid, usename, address, job, ins, appname, ip, instance, cls Current timestamp in unix epoch
pg_repl_write_diff gauge pid, usename, address, job, ins, appname, ip, instance, cls Last log position written to disk by this standby server diff with current lsn
pg_repl_write_lag gauge pid, usename, address, job, ins, appname, ip, instance, cls Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written it
pg_repl_write_lsn counter pid, usename, address, job, ins, appname, ip, instance, cls Last write-ahead log location written to disk by this standby server
pg_replay_lsn counter job, ins, ip, instance, cls replica only, location of wal applied
pg_seq_blks_hit counter datname, job, ins, ip, instance, cls, seqname Number of buffer hits in this sequence
pg_seq_blks_read counter datname, job, ins, ip, instance, cls, seqname Number of disk blocks read from this sequence
pg_seq_last_value counter datname, job, ins, ip, instance, cls, seqname The last sequence value written to disk
pg_setting_block_size gauge job, ins, ip, instance, cls pg page block size, 8192 by default
pg_setting_data_checksums gauge job, ins, ip, instance, cls whether data checksum is enabled, 1 enabled 0 disabled
pg_setting_max_connections gauge job, ins, ip, instance, cls number of concurrent connections to the database server
pg_setting_max_locks_per_transaction gauge job, ins, ip, instance, cls no more than this many distinct objects can be locked at any one time
pg_setting_max_prepared_transactions gauge job, ins, ip, instance, cls maximum number of transactions that can be in the prepared state simultaneously
pg_setting_max_replication_slots gauge job, ins, ip, instance, cls maximum number of replication slots
pg_setting_max_wal_senders gauge job, ins, ip, instance, cls maximum number of concurrent connections from standby servers
pg_setting_max_worker_processes gauge job, ins, ip, instance, cls maximum number of background processes that the system can support
pg_setting_wal_log_hints gauge job, ins, ip, instance, cls whether wal_log_hints is enabled, 1 enabled 0 disabled
pg_size_bytes gauge datname, job, ins, ip, instance, cls File size in bytes
pg_slot_active gauge slot_name, job, ins, ip, instance, cls True(1) if this slot is currently actively being used
pg_slot_catalog_xmin counter slot_name, job, ins, ip, instance, cls The oldest transaction affecting the system catalogs that this slot needs the database to retain.
pg_slot_confirm_lsn counter slot_name, job, ins, ip, instance, cls The address (LSN) up to which the logical slot’s consumer has confirmed receiving data.
pg_slot_reset_time counter slot_name, job, ins, ip, instance, cls When statistics were last reset
pg_slot_restart_lsn counter slot_name, job, ins, ip, instance, cls The address (LSN) of oldest WAL which still might be required by the consumer of this slot
pg_slot_retained_bytes gauge slot_name, job, ins, ip, instance, cls Size of bytes that retained for this slot
pg_slot_safe_wal_size gauge slot_name, job, ins, ip, instance, cls bytes that can be written to WAL which will not make slot into lost
pg_slot_spill_bytes counter slot_name, job, ins, ip, instance, cls Bytes that spilled to disk due to logical decode mem exceeding
pg_slot_spill_count counter slot_name, job, ins, ip, instance, cls Xacts that spilled to disk due to logical decode mem exceeding (a xact can be spilled multiple times)
pg_slot_spill_txns counter slot_name, job, ins, ip, instance, cls Xacts that spilled to disk due to logical decode mem exceeding (subtrans included)
pg_slot_stream_bytes counter slot_name, job, ins, ip, instance, cls Bytes that streamed to decoding output plugin after mem exceed
pg_slot_stream_count counter slot_name, job, ins, ip, instance, cls Xacts that streamed to decoding output plugin after mem exceed (a xact can be streamed multiple times)
pg_slot_stream_txns counter slot_name, job, ins, ip, instance, cls Xacts that streamed to decoding output plugin after mem exceed
pg_slot_temporary gauge slot_name, job, ins, ip, instance, cls True(1) if this is a temporary replication slot.
pg_slot_total_bytes counter slot_name, job, ins, ip, instance, cls Number of decoded bytes sent to the decoding output plugin for this slot
pg_slot_total_txns counter slot_name, job, ins, ip, instance, cls Number of decoded xacts sent to the decoding output plugin for this slot
pg_slot_wal_status gauge slot_name, job, ins, ip, instance, cls WAL reserve status 0-3 means reserved,extended,unreserved,lost, -1 means other
pg_slot_xmin counter slot_name, job, ins, ip, instance, cls The oldest transaction that this slot needs the database to retain.
pg_slru_blks_exists counter job, ins, ip, instance, cls Number of blocks checked for existence for this SLRU
pg_slru_blks_hit counter job, ins, ip, instance, cls Number of times disk blocks were found already in the SLRU, so that a read was not necessary
pg_slru_blks_read counter job, ins, ip, instance, cls Number of disk blocks read for this SLRU
pg_slru_blks_written counter job, ins, ip, instance, cls Number of disk blocks written for this SLRU
pg_slru_blks_zeroed counter job, ins, ip, instance, cls Number of blocks zeroed during initializations
pg_slru_flushes counter job, ins, ip, instance, cls Number of flushes of dirty data for this SLRU
pg_slru_reset_time counter job, ins, ip, instance, cls Time at which these statistics were last reset
pg_slru_truncates counter job, ins, ip, instance, cls Number of truncates for this SLRU
pg_ssl_disabled gauge job, ins, ip, instance, cls Number of client connection that does not use ssl
pg_ssl_enabled gauge job, ins, ip, instance, cls Number of client connection that use ssl
pg_sync_standby_enabled gauge job, ins, ip, names, instance, cls Synchronous commit enabled, 1 if enabled, 0 if disabled
pg_table_age gauge datname, relname, job, ins, ip, instance, cls Age of this table in vacuum cycles
pg_table_analyze_count counter datname, relname, job, ins, ip, instance, cls Number of times this table has been manually analyzed
pg_table_autoanalyze_count counter datname, relname, job, ins, ip, instance, cls Number of times this table has been analyzed by the autovacuum daemon
pg_table_autovacuum_count counter datname, relname, job, ins, ip, instance, cls Number of times this table has been vacuumed by the autovacuum daemon
pg_table_frozenxid counter datname, relname, job, ins, ip, instance, cls All txid before this have been frozen on this table
pg_table_heap_blks_hit counter datname, relname, job, ins, ip, instance, cls Number of buffer hits in this table
pg_table_heap_blks_read counter datname, relname, job, ins, ip, instance, cls Number of disk blocks read from this table
pg_table_idx_blks_hit counter datname, relname, job, ins, ip, instance, cls Number of buffer hits in all indexes on this table
pg_table_idx_blks_read counter datname, relname, job, ins, ip, instance, cls Number of disk blocks read from all indexes on this table
pg_table_idx_scan counter datname, relname, job, ins, ip, instance, cls Number of index scans initiated on this table
pg_table_idx_tup_fetch counter datname, relname, job, ins, ip, instance, cls Number of live rows fetched by index scans
pg_table_kind gauge datname, relname, job, ins, ip, instance, cls Relation kind r/table/114
pg_table_n_dead_tup gauge datname, relname, job, ins, ip, instance, cls Estimated number of dead rows
pg_table_n_ins_since_vacuum gauge datname, relname, job, ins, ip, instance, cls Estimated number of rows inserted since this table was last vacuumed
pg_table_n_live_tup gauge datname, relname, job, ins, ip, instance, cls Estimated number of live rows
pg_table_n_mod_since_analyze gauge datname, relname, job, ins, ip, instance, cls Estimated number of rows modified since this table was last analyzed
pg_table_n_tup_del counter datname, relname, job, ins, ip, instance, cls Number of rows deleted
pg_table_n_tup_hot_upd counter datname, relname, job, ins, ip, instance, cls Number of rows HOT updated (i.e with no separate index update required)
pg_table_n_tup_ins counter datname, relname, job, ins, ip, instance, cls Number of rows inserted
pg_table_n_tup_mod counter datname, relname, job, ins, ip, instance, cls Number of rows modified (insert + update + delete)
pg_table_n_tup_newpage_upd counter datname, relname, job, ins, ip, instance, cls Number of rows updated where the successor version goes onto a new heap page
pg_table_n_tup_upd counter datname, relname, job, ins, ip, instance, cls Number of rows updated (includes HOT updated rows)
pg_table_ncols gauge datname, relname, job, ins, ip, instance, cls Number of columns in the table
pg_table_pages gauge datname, relname, job, ins, ip, instance, cls Size of the on-disk representation of this table in pages
pg_table_relid gauge datname, relname, job, ins, ip, instance, cls Relation oid of this table
pg_table_seq_scan counter datname, relname, job, ins, ip, instance, cls Number of sequential scans initiated on this table
pg_table_seq_tup_read counter datname, relname, job, ins, ip, instance, cls Number of live rows fetched by sequential scans
pg_table_size_bytes gauge datname, relname, job, ins, ip, instance, cls Total bytes of this table (including toast, index, toast index)
pg_table_size_indexsize gauge datname, relname, job, ins, ip, instance, cls Bytes of all related indexes of this table
pg_table_size_relsize gauge datname, relname, job, ins, ip, instance, cls Bytes of this table itself (main, vm, fsm)
pg_table_size_toastsize gauge datname, relname, job, ins, ip, instance, cls Bytes of toast tables of this table
pg_table_tbl_scan counter datname, relname, job, ins, ip, instance, cls Number of scans initiated on this table
pg_table_tup_read counter datname, relname, job, ins, ip, instance, cls Number of live rows fetched by scans
pg_table_tuples counter datname, relname, job, ins, ip, instance, cls All txid before this have been frozen on this table
pg_table_vacuum_count counter datname, relname, job, ins, ip, instance, cls Number of times this table has been manually vacuumed (not counting VACUUM FULL)
pg_timestamp gauge job, ins, ip, instance, cls database current timestamp
pg_up gauge job, ins, ip, instance, cls last scrape was able to connect to the server: 1 for yes, 0 for no
pg_uptime gauge job, ins, ip, instance, cls seconds since postmaster start
pg_version gauge job, ins, ip, instance, cls server version number
pg_wait_count gauge datname, job, ins, event, ip, instance, cls Count of WaitEvent on target database
pg_wal_buffers_full counter job, ins, ip, instance, cls Number of times WAL data was written to disk because WAL buffers became full
pg_wal_bytes counter job, ins, ip, instance, cls Total amount of WAL generated in bytes
pg_wal_fpi counter job, ins, ip, instance, cls Total number of WAL full page images generated
pg_wal_records counter job, ins, ip, instance, cls Total number of WAL records generated
pg_wal_reset_time counter job, ins, ip, instance, cls When statistics were last reset
pg_wal_sync counter job, ins, ip, instance, cls Number of times WAL files were synced to disk via issue_xlog_fsync request
pg_wal_sync_time counter job, ins, ip, instance, cls Total amount of time spent syncing WAL files to disk via issue_xlog_fsync request, in seconds
pg_wal_write counter job, ins, ip, instance, cls Number of times WAL buffers were written out to disk via XLogWrite request.
pg_wal_write_time counter job, ins, ip, instance, cls Total amount of time spent writing WAL buffers to disk via XLogWrite request in seconds
pg_write_lsn counter job, ins, ip, instance, cls primary only, location of current wal writing
pg_xact_xmax counter job, ins, ip, instance, cls First as-yet-unassigned txid. txid >= this are invisible.
pg_xact_xmin counter job, ins, ip, instance, cls Earliest txid that is still active
pg_xact_xnum gauge job, ins, ip, instance, cls Current active transaction count
pgbouncer:cls:load1 Unknown job, cls N/A
pgbouncer:cls:load15 Unknown job, cls N/A
pgbouncer:cls:load5 Unknown job, cls N/A
pgbouncer:db:conn_usage Unknown datname, job, ins, ip, instance, host, cls, real_datname, port N/A
pgbouncer:db:conn_usage_reserve Unknown datname, job, ins, ip, instance, host, cls, real_datname, port N/A
pgbouncer:db:pool_current_conn Unknown datname, job, ins, ip, instance, host, cls, real_datname, port N/A
pgbouncer:db:pool_disabled Unknown datname, job, ins, ip, instance, host, cls, real_datname, port N/A
pgbouncer:db:pool_max_conn Unknown datname, job, ins, ip, instance, host, cls, real_datname, port N/A
pgbouncer:db:pool_paused Unknown datname, job, ins, ip, instance, host, cls, real_datname, port N/A
pgbouncer:db:pool_reserve_size Unknown datname, job, ins, ip, instance, host, cls, real_datname, port N/A
pgbouncer:db:pool_size Unknown datname, job, ins, ip, instance, host, cls, real_datname, port N/A
pgbouncer:ins:free_clients Unknown job, ins, ip, instance, cls N/A
pgbouncer:ins:free_servers Unknown job, ins, ip, instance, cls N/A
pgbouncer:ins:load1 Unknown job, ins, ip, instance, cls N/A
pgbouncer:ins:load15 Unknown job, ins, ip, instance, cls N/A
pgbouncer:ins:load5 Unknown job, ins, ip, instance, cls N/A
pgbouncer:ins:login_clients Unknown job, ins, ip, instance, cls N/A
pgbouncer:ins:pool_databases Unknown job, ins, ip, instance, cls N/A
pgbouncer:ins:pool_users Unknown job, ins, ip, instance, cls N/A
pgbouncer:ins:pools Unknown job, ins, ip, instance, cls N/A
pgbouncer:ins:used_clients Unknown job, ins, ip, instance, cls N/A
pgbouncer_database_current_connections gauge datname, job, ins, ip, instance, host, cls, real_datname, port Current number of connections for this database
pgbouncer_database_disabled gauge datname, job, ins, ip, instance, host, cls, real_datname, port True(1) if this database is currently disabled, else 0
pgbouncer_database_max_connections gauge datname, job, ins, ip, instance, host, cls, real_datname, port Maximum number of allowed connections for this database
pgbouncer_database_min_pool_size gauge datname, job, ins, ip, instance, host, cls, real_datname, port Minimum number of server connections
pgbouncer_database_paused gauge datname, job, ins, ip, instance, host, cls, real_datname, port True(1) if this database is currently paused, else 0
pgbouncer_database_pool_size gauge datname, job, ins, ip, instance, host, cls, real_datname, port Maximum number of server connections
pgbouncer_database_reserve_pool gauge datname, job, ins, ip, instance, host, cls, real_datname, port Maximum number of additional connections for this database
pgbouncer_exporter_agent_up Unknown job, ins, ip, instance, cls N/A
pgbouncer_exporter_last_scrape_time gauge job, ins, ip, instance, cls seconds exporter spending on scrapping
pgbouncer_exporter_query_cache_ttl gauge datname, query, job, ins, ip, instance, cls times to live of query cache
pgbouncer_exporter_query_scrape_duration gauge datname, query, job, ins, ip, instance, cls seconds query spending on scrapping
pgbouncer_exporter_query_scrape_error_count gauge datname, query, job, ins, ip, instance, cls times the query failed
pgbouncer_exporter_query_scrape_hit_count gauge datname, query, job, ins, ip, instance, cls numbers been scrapped from this query
pgbouncer_exporter_query_scrape_metric_count gauge datname, query, job, ins, ip, instance, cls numbers of metrics been scrapped from this query
pgbouncer_exporter_query_scrape_total_count gauge datname, query, job, ins, ip, instance, cls times exporter server was scraped for metrics
pgbouncer_exporter_scrape_duration gauge job, ins, ip, instance, cls seconds exporter spending on scrapping
pgbouncer_exporter_scrape_error_count counter job, ins, ip, instance, cls times exporter was scraped for metrics and failed
pgbouncer_exporter_scrape_total_count counter job, ins, ip, instance, cls times exporter was scraped for metrics
pgbouncer_exporter_server_scrape_duration gauge datname, job, ins, ip, instance, cls seconds exporter server spending on scrapping
pgbouncer_exporter_server_scrape_total_count gauge datname, job, ins, ip, instance, cls times exporter server was scraped for metrics
pgbouncer_exporter_server_scrape_total_seconds gauge datname, job, ins, ip, instance, cls seconds exporter server spending on scrapping
pgbouncer_exporter_up gauge job, ins, ip, instance, cls always be 1 if your could retrieve metrics
pgbouncer_exporter_uptime gauge job, ins, ip, instance, cls seconds since exporter primary server inited
pgbouncer_in_recovery gauge job, ins, ip, instance, cls server is in recovery mode? 1 for yes 0 for no
pgbouncer_list_items gauge job, ins, ip, instance, list, cls Number of corresponding pgbouncer object
pgbouncer_pool_active_cancel_clients gauge datname, job, ins, ip, instance, user, cls, pool_mode Client connections that have forwarded query cancellations to the server and are waiting for the server response.
pgbouncer_pool_active_cancel_servers gauge datname, job, ins, ip, instance, user, cls, pool_mode Server connections that are currently forwarding a cancel request
pgbouncer_pool_active_clients gauge datname, job, ins, ip, instance, user, cls, pool_mode Client connections that are linked to server connection and can process queries
pgbouncer_pool_active_servers gauge datname, job, ins, ip, instance, user, cls, pool_mode Server connections that are linked to a client
pgbouncer_pool_cancel_clients gauge datname, job, ins, ip, instance, user, cls, pool_mode Client connections that have not forwarded query cancellations to the server yet.
pgbouncer_pool_cancel_servers gauge datname, job, ins, ip, instance, user, cls, pool_mode cancel requests have completed that were sent to cancel a query on this server
pgbouncer_pool_idle_servers gauge datname, job, ins, ip, instance, user, cls, pool_mode Server connections that are unused and immediately usable for client queries
pgbouncer_pool_login_servers gauge datname, job, ins, ip, instance, user, cls, pool_mode Server connections currently in the process of logging in
pgbouncer_pool_maxwait gauge datname, job, ins, ip, instance, user, cls, pool_mode How long the first(oldest) client in the queue has waited, in seconds, key metric
pgbouncer_pool_maxwait_us gauge datname, job, ins, ip, instance, user, cls, pool_mode Microsecond part of the maximum waiting time.
pgbouncer_pool_tested_servers gauge datname, job, ins, ip, instance, user, cls, pool_mode Server connections that are currently running reset or check query
pgbouncer_pool_used_servers gauge datname, job, ins, ip, instance, user, cls, pool_mode Server connections that have been idle for more than server_check_delay (means have to run check query)
pgbouncer_pool_waiting_clients gauge datname, job, ins, ip, instance, user, cls, pool_mode Client connections that have sent queries but have not yet got a server connection
pgbouncer_stat_avg_query_count gauge datname, job, ins, ip, instance, cls Average queries per second in last stat period
pgbouncer_stat_avg_query_time gauge datname, job, ins, ip, instance, cls Average query duration, in seconds
pgbouncer_stat_avg_recv gauge datname, job, ins, ip, instance, cls Average received (from clients) bytes per second
pgbouncer_stat_avg_sent gauge datname, job, ins, ip, instance, cls Average sent (to clients) bytes per second
pgbouncer_stat_avg_wait_time gauge datname, job, ins, ip, instance, cls Time spent by clients waiting for a server, in seconds (average per second).
pgbouncer_stat_avg_xact_count gauge datname, job, ins, ip, instance, cls Average transactions per second in last stat period
pgbouncer_stat_avg_xact_time gauge datname, job, ins, ip, instance, cls Average transaction duration, in seconds
pgbouncer_stat_total_query_count gauge datname, job, ins, ip, instance, cls Total number of SQL queries pooled by pgbouncer
pgbouncer_stat_total_query_time counter datname, job, ins, ip, instance, cls Total number of seconds spent when executing queries
pgbouncer_stat_total_received counter datname, job, ins, ip, instance, cls Total volume in bytes of network traffic received by pgbouncer
pgbouncer_stat_total_sent counter datname, job, ins, ip, instance, cls Total volume in bytes of network traffic sent by pgbouncer
pgbouncer_stat_total_wait_time counter datname, job, ins, ip, instance, cls Time spent by clients waiting for a server, in seconds
pgbouncer_stat_total_xact_count gauge datname, job, ins, ip, instance, cls Total number of SQL transactions pooled by pgbouncer
pgbouncer_stat_total_xact_time counter datname, job, ins, ip, instance, cls Total number of seconds spent when in a transaction
pgbouncer_up gauge job, ins, ip, instance, cls last scrape was able to connect to the server: 1 for yes, 0 for no
pgbouncer_version gauge job, ins, ip, instance, cls server version number
process_cpu_seconds_total counter job, ins, ip, instance, cls Total user and system CPU time spent in seconds.
process_max_fds gauge job, ins, ip, instance, cls Maximum number of open file descriptors.
process_open_fds gauge job, ins, ip, instance, cls Number of open file descriptors.
process_resident_memory_bytes gauge job, ins, ip, instance, cls Resident memory size in bytes.
process_start_time_seconds gauge job, ins, ip, instance, cls Start time of the process since unix epoch in seconds.
process_virtual_memory_bytes gauge job, ins, ip, instance, cls Virtual memory size in bytes.
process_virtual_memory_max_bytes gauge job, ins, ip, instance, cls Maximum amount of virtual memory available in bytes.
promhttp_metric_handler_requests_in_flight gauge job, ins, ip, instance, cls Current number of scrapes being served.
promhttp_metric_handler_requests_total counter code, job, ins, ip, instance, cls Total number of scrapes by HTTP status code.
scrape_duration_seconds Unknown job, ins, ip, instance, cls N/A
scrape_samples_post_metric_relabeling Unknown job, ins, ip, instance, cls N/A
scrape_samples_scraped Unknown job, ins, ip, instance, cls N/A
scrape_series_added Unknown job, ins, ip, instance, cls N/A
up Unknown job, ins, ip, instance, cls N/A

8.11 - 参数列表

PGSQL 模块提供的 PostgreSQL 相关配置参数详解

PGSQL 模块需要在 Pigsty 管理的节点上安装(即节点已经配置了 NODE 模块),同时还要求您的部署中有一套可用的 ETCD 集群来存储集群元数据。

在单个节点上安装 PGSQL 模块将创建一个独立的 PGSQL 服务器/实例,即 主实例。 在额外节点上安装将创建 只读副本,可以作为备用实例,并用于承载分担只读请求。 您还可以创建用于 ETL/OLAP/交互式查询的 离线 实例, 使用 同步备库法定人数提交 来提高数据一致性, 甚至搭建 备份集群延迟集群 以快速应对人为失误与软件缺陷导致的数据损失。

您可以定义多个 PGSQL 集群并进一步组建一个水平分片集群: Pigsty 支持原生的 citus 集群组,可以将您的标准 PGSQL 集群原地升级为一个分布式的数据库集群。


参数组 功能说明
PG_ID PostgreSQL 集群与实例的身份标识参数
PG_BUSINESS 业务用户、数据库、服务与访问控制规则定义
PG_INSTALL PostgreSQL 安装相关:版本、路径、软件包
PG_BOOTSTRAP PostgreSQL 集群初始化引导:Patroni 高可用
PG_PROVISION PostgreSQL 集群模板置备:角色、权限、扩展
PG_BACKUP pgBackRest 备份与恢复配置
PG_ACCESS 服务暴露、连接池、VIP、DNS 等客户端访问配置
PG_MONITOR PostgreSQL 监控 Exporter 配置
PG_REMOVE PostgreSQL 实例清理与卸载配置

参数概览


PG_ID 参数组用于定义 PostgreSQL 集群与实例的身份标识,包括集群名称、实例序号、角色、分片等核心身份参数。

参数 类型 级别 说明
pg_mode enum C pgsql 集群模式:pgsql,citus,mssql,mysql,ivory,pgtde,polar,gpsql,agens,oriole,pgedge
pg_cluster string C pgsql 集群名称,必选身份参数
pg_seq int I pgsql 实例号,必选身份参数
pg_role enum I pgsql 实例角色,必选身份参数,可为 primary、replica、standby、offline、delayed
pg_instances dict I 在一个节点上定义多个 pg 实例,使用 {port:ins_vars} 格式
pg_upstream ip I 级联从库或备份集群的复制上游节点 IP 地址
pg_shard string C pgsql 分片名;水平分片集群建议显式指定
pg_group int C pgsql 分片号,可使用非负整数;水平分片集群建议显式指定
gp_role enum C 这个集群的 greenplum 角色,可以是 master 或 segment
pg_exporters dict C 在该节点上设置额外的 pg_exporters 用于监控远程 postgres 实例
pg_offline_query bool I 设置为 true 将此只读实例标记为特殊的离线从库,承载 Offline 服务,允许离线查询

PG_BUSINESS 参数组用于定义业务用户、数据库、服务与访问控制规则,以及默认的系统用户凭据。

参数 类型 级别 说明
pg_users user[] C postgres 业务用户
pg_databases database[] C postgres 业务数据库
pg_services service[] C postgres 业务服务
pg_hba_rules hba[] C postgres 的业务 hba 规则
pgb_hba_rules hba[] C pgbouncer 的业务 hba 规则
pg_crontab string[] C postgres dbsu 的定时任务
pg_replication_username username G postgres 复制用户名,默认为 replicator
pg_replication_password password G postgres 复制密码,默认为 DBUser.Replicator
pg_admin_username username G postgres 管理员用户名,默认为 dbuser_dba
pg_admin_password password G postgres 管理员明文密码,默认为 DBUser.DBA
pg_monitor_username username G postgres 监控用户名,默认为 dbuser_monitor
pg_monitor_password password G postgres 监控密码,默认为 DBUser.Monitor
pg_dbsu_password password G/C dbsu 密码,默认为空字符串意味着不设置 dbsu 密码,最好不要设置。

PG_INSTALL 参数组用于配置 PostgreSQL 安装相关选项,包括版本、路径、软件包与扩展插件。

参数 类型 级别 说明
pg_dbsu username C 操作系统 dbsu 名称,默认为 postgres,最好不要更改
pg_dbsu_uid int C 操作系统 dbsu uid 和 gid,对于默认的 postgres 用户和组为 26
pg_dbsu_sudo enum C dbsu sudo 权限,none,limit,all,nopass,默认为 limit
pg_dbsu_home path C postgresql 主目录,默认为 /var/lib/pgsql
pg_dbsu_ssh_exchange bool C 在 pgsql 集群之间交换 postgres dbsu ssh 密钥
pg_version enum C 要安装的 postgres 主版本,默认为 18
pg_bin_dir path C postgres 二进制目录,默认为 /usr/pgsql/bin
pg_log_dir path C postgres 日志目录,默认为 /pg/log/postgres
pg_packages string[] C 要安装的 pg 包,${pg_version} 将被替换为实际主版本号
pg_extensions string[] C 要安装的 pg 扩展,${pg_version} 将被替换为实际主版本号

PG_BOOTSTRAP 参数组用于配置 PostgreSQL 集群初始化引导,包括 Patroni 高可用、存储路径、连接、编码等核心设置。

参数 类型 级别 说明
pg_data path C PostgreSQL 数据目录,默认为 /pg/data
pg_fs_main path C postgres 主数据的挂载点/路径,默认为 /data/postgres
pg_fs_backup path C pg 备份数据的挂载点/路径,默认为 /data/backups
pg_storage_type enum C pg 主数据的存储类型,SSD、HDD,默认为 SSD,影响自动优化的参数。
pg_dummy_filesize size C /pg/dummy 的大小,默认保留 64MB 磁盘空间用于紧急抢修
pg_listen ip(s) C/I postgres/pgbouncer 的监听地址,用逗号分隔的 IP 列表,默认为 0.0.0.0
pg_port port C postgres 监听端口,默认为 5432
pg_localhost path C postgres 的 Unix 套接字目录,用于本地连接
pg_namespace path C 在 etcd 中的顶级键命名空间,被 patroni & vip 用于高可用管理
patroni_enabled bool C 如果禁用,初始化期间不会创建 postgres 集群
patroni_mode enum C patroni 工作模式:default,pause,remove
patroni_port port C patroni 监听端口,默认为 8008
patroni_log_dir path C patroni 日志目录,默认为 /pg/log/patroni
patroni_ssl_enabled bool G 使用 SSL 保护 patroni RestAPI 通信?
patroni_watchdog_mode enum C patroni 看门狗模式:automatic,required,off,默认为 off
patroni_username username C patroni restapi 用户名,默认为 postgres
patroni_password password C patroni restapi 密码,默认为 Patroni.API
pg_primary_db string C 指定集群中首要使用的数据库名,Citus 等模式会用到,默认为 postgres
pg_parameters dict C 覆盖 postgresql.auto.conf 中的 PostgreSQL 参数
pg_files path[] C 拷贝至 PGDATA 目录中的额外文件列表 (例如许可证文件)
pg_conf enum C 配置模板:oltp,olap,crit,tiny,默认为 oltp.yml
pg_max_conn int C postgres 最大连接数,auto 将使用推荐值
pg_shared_buffer_ratio float C postgres 共享缓冲区内存比率,默认为 0.25,范围 0.1~0.4
pg_rto enum C RTO 模式:fast,norm,safe,wide,默认 norm
pg_rto_plan dict G RTO 预设配置,定义 Patroni HA 与 HAProxy 健康检查的超时参数
pg_rpo int C Patroni 故障切换候选从库的采样落后阈值,默认为 1MiB
pg_libs string C 预加载的库,默认为 pg_stat_statements,auto_explain
pg_delay interval I 备份集群主库的 WAL 重放应用延迟,用于制备延迟从库
pg_checksum bool C 为 postgres 集群启用数据校验和?
pg_pwd_enc enum C 密码加密算法:固定为 scram-sha-256
pg_encoding enum C 数据库集群编码,默认为 UTF8
pg_locale enum C 数据库集群本地化设置,默认为 C
pg_lc_collate enum C 数据库集群排序,默认为 C
pg_lc_ctype enum C 数据库字符类型,默认为 C
pg_io_method enum C PostgreSQL IO 方法:auto, sync, worker, io_uring
pg_etcd_password password C 此 PostgreSQL 集群在 etcd 中使用的密码,默认使用集群名
pgsodium_key string C pgsodium 加密主密钥,64 位十六进制数字,默认使用 sha256(pg_cluster)
pgsodium_getkey_script path C pgsodium 获取密钥脚本路径,默认使用模板中的 pgsodium_getkey

PG_PROVISION 参数组用于配置 PostgreSQL 集群模板置备,包括默认角色、权限、模式、扩展与 HBA 规则。

参数 类型 级别 说明
pg_provision bool C 在引导后置备 postgres 集群内部的业务对象?
pg_init string G/C 为集群模板提供初始化脚本,默认为 pg-init
pg_default_roles role[] G/C postgres 集群中的默认预定义角色和系统用户
pg_default_privileges string[] G/C 由管理员用户创建数据库内对象时的默认权限
pg_default_schemas string[] G/C 要创建的默认模式列表
pg_default_extensions extension[] G/C 要创建的默认扩展列表
pg_reload bool A 更改 HBA 后,是否立即重载 postgres 配置
pg_default_hba_rules hba[] G/C postgres 基于主机的认证规则,全局 PG 默认 HBA
pgb_default_hba_rules hba[] G/C pgbouncer 默认的基于主机的认证规则,全局 PGB 默认 HBA

PG_BACKUP 参数组用于配置 pgBackRest 备份与恢复,包括仓库类型、路径、保留策略等。

参数 类型 级别 说明
pgbackrest_enabled bool C 在 pgsql 主机上启用 pgbackrest?
pgbackrest_log_dir path C pgbackrest 日志目录,默认为 /pg/log/pgbackrest
pgbackrest_method enum C pgbackrest 使用的仓库:local,minio,等…
pgbackrest_init_backup bool C pgbackrest 初始化完成后是否立即执行全量备份?默认为 true
pgbackrest_repo dict G/C pgbackrest 仓库定义

PG_ACCESS 参数组用于配置服务暴露、连接池、VIP、DNS 等客户端访问相关选项。

参数 类型 级别 说明
pgbouncer_enabled bool C 如果禁用,则不会配置 pgbouncer 连接池
pgbouncer_port port C pgbouncer 监听端口,默认为 6432
pgbouncer_log_dir path C pgbouncer 日志目录,默认为 /pg/log/pgbouncer
pgbouncer_auth_query bool C 使用 AuthQuery 来从 postgres 获取未列出的业务用户?
pgbouncer_poolmode enum C 池化模式:transaction,session,statement,默认为 transaction
pgbouncer_sslmode enum C pgbouncer 客户端 SSL 模式,默认为禁用
pgbouncer_ignore_param string[] C pgbouncer 忽略的启动参数列表
pg_weight int I 在服务中的相对负载均衡权重,默认为 100,范围 0-255
pg_service_provider string G/C 专用的 haproxy 节点组名称,或默认空字符,使用本地节点上的 haproxy
pg_default_service_dest enum G/C 如果 svc.dest=‘default’,默认服务指向哪里?postgres 或 pgbouncer
pg_default_services service[] G/C postgres 默认服务定义列表,全局共用。
pg_vip_enabled bool C 是否为 pgsql 主节点启用 L2 VIP?默认不启用
pg_vip_address cidr4 C vip 地址的格式为 <ipv4>/<mask>,启用 vip 时为必选参数
pg_vip_interface string C/I 监听的 vip 网络接口,默认为 auto
pg_dns_suffix string C pgsql dns 后缀,默认为空
pg_dns_target enum C PG DNS 解析到哪里?auto、primary、vip、none 或者特定的 IP 地址

PG_MONITOR 参数组用于配置 PostgreSQL 监控 Exporter,包括 pg_exporter、pgbouncer_exporter 和 pgbackrest_exporter。

参数 类型 级别 说明
pg_exporter_enabled bool C 在 pgsql 主机上启用 pg_exporter 吗?
pg_exporter_config string C pg_exporter 配置文件/模板名称
pg_exporter_cache_ttls string C pg_exporter 收集器阶梯 TTL 配置,默认为 ‘1,10,60,300’
pg_exporter_port port C pg_exporter 监听端口,默认为 9630
pg_exporter_params string C pg_exporter dsn 中传入的额外 URL 参数
pg_exporter_url pgurl C 如果指定,则覆盖自动生成的 postgres DSN 连接串
pg_exporter_auto_discovery bool C 监控是否启用自动数据库发现?默认启用
pg_exporter_exclude_database string C 启用自动发现时,排除在外的数据库名称列表,用逗号分隔
pg_exporter_include_database string C 启用自动发现时,只监控这个列表中的数据库,名称用逗号分隔
pg_exporter_connect_timeout int C pg_exporter 连接超时,单位毫秒,默认为 200
pg_exporter_options arg C pg_exporter 的额外命令行参数选项
pgbouncer_exporter_enabled bool C 在 pgsql 主机上启用 pgbouncer_exporter 吗?
pgbouncer_exporter_port port C pgbouncer_exporter 监听端口,默认为 9631
pgbouncer_exporter_url pgurl C 如果指定,则覆盖自动生成的 pgbouncer dsn 连接串
pgbouncer_exporter_options arg C pgbouncer_exporter 的额外命令行参数选项
pgbackrest_exporter_enabled bool C 在 pgsql 主机上启用 pgbackrest_exporter 吗?
pgbackrest_exporter_port port C pgbackrest_exporter 监听端口,默认为 9854
pgbackrest_exporter_options arg C pgbackrest_exporter 的额外命令行参数选项

PG_REMOVE 参数组用于配置 PostgreSQL 实例清理与卸载行为,包括数据目录、备份、软件包的删除控制。

参数 类型 级别 说明
pg_rm_data bool G/C/A 删除 pgsql 实例时是否清理 postgres 数据目录?
pg_rm_backup bool G/C/A 删除主库时是否一并清理 pgbackrest 备份?
pg_rm_pkg bool G/C/A 删除 pgsql 实例时是否卸载相关软件包?
pg_safeguard bool G/C/A 防误删保险,阻止误执行 pgsql 清理操作?默认为 false

PG_ID

以下是一些常用的参数,用于标识 PGSQL 模块中的 实体:集群、实例、服务等…

# pg_cluster:           #CLUSTER  # pgsql 集群名称,必需的标识参数
# pg_seq: 0             #INSTANCE # pgsql 实例序列号,必需的标识参数
# pg_role: replica      #INSTANCE # pgsql 角色,必需的,可以是 primary,replica,offline
# pg_instances: {}      #INSTANCE # 在节点上定义多个 pg 实例,使用 `{port:ins_vars}` 格式
# pg_upstream:          #INSTANCE # 备用集群或级联副本的 repl 上游 ip 地址
# pg_shard:             #CLUSTER  # pgsql 分片名称,分片集群的可选标识
# pg_group: 0           #CLUSTER  # pgsql 分片索引号,分片集群的可选标识
# gp_role: master       #CLUSTER  # 此集群的 greenplum 角色,可以是 master 或 segment
pg_offline_query: false #INSTANCE # 设置为 true 以在此实例上启用离线查询

您必须显式指定这些 身份参数,它们没有默认值:

名称 类型 级别 扩展说明
pg_cluster string C PG 数据库集群名称
pg_seq number I PG 数据库实例 ID
pg_role enum I PG 数据库实例角色
pg_shard string C 数据库分片名称
pg_group number C 数据库分片序号
  • pg_cluster:它标识集群的名称,该名称在集群级别配置。
  • pg_role:在实例级别配置,标识 ins 的角色。只有 primary 角色会特别处理。如果不填写,默认为 replica 角色和特殊的 delayedoffline 角色。
  • pg_seq:用于在集群内标识 ins,通常是从 0 或 1 递增的整数,一旦分配就不会更改。
  • {{ pg_cluster }}-{{ pg_seq }} 用于唯一标识 ins,即 pg_instance
  • {{ pg_cluster }}-{{ pg_role }} 用于标识集群内的服务,即 pg_service
  • pg_shardpg_group 用于水平分片集群,仅用于 citus、greenplum 和 matrixdb。

pg_clusterpg_rolepg_seq 是核心 标识参数,对于任何 Postgres 集群都是 必选 的,并且必须显式指定。以下是一个示例:

pg-test:
  hosts:
    10.10.10.11: {pg_seq: 1, pg_role: replica}
    10.10.10.12: {pg_seq: 2, pg_role: primary}
    10.10.10.13: {pg_seq: 3, pg_role: replica}
  vars:
    pg_cluster: pg-test

所有其他参数都可以从全局配置或默认配置继承,但标识参数必须 明确指定手动分配

pg_mode

参数名称: pg_mode, 类型: enum, 层次:C

PostgreSQL 集群模式,默认值为 pgsql,即标准的 PostgreSQL 集群。

可用的模式选项包括:

  • pgsql:标准的 PostgreSQL 集群
  • citus:Citus 分布式数据库集群
  • mssql:Babelfish MSSQL 线缆协议兼容内核
  • mysql:OpenHalo/HaloDB MySQL 线协议兼容内核
  • ivory:IvorySQL Oracle 兼容内核
  • pgtde:带 pg_tde 的 Percona PostgreSQL 内核
  • polar:PolarDB for PostgreSQL 内核
  • gpsql:Greenplum 并行数据库集群(监控)
  • agens:AgensGraph 图数据库内核
  • oriole:OrioleDB 存储引擎内核
  • pgedge:pgEdge 分布式复制内核

pg_shardpg_group 分别有 pg_cluster0 作为默认值;当 pg_mode 设置为 citusgpsql 并包含多个物理集群时,应显式设置这两个参数来定义水平分片集群的身份。

在这两种情况下,每一个 PostgreSQL 集群都是一组更大的业务单元的一部分。

pg_cluster

参数名称: pg_cluster, 类型: string, 层次:C

PostgreSQL 集群名称,必选的身份标识参数,没有默认值

集群名将用作资源的命名空间。

当前角色校验要求集群名匹配 ^[A-Za-z0-9-]+$,且不能命名为 root。为保持 DNS、服务名与运维脚本中的命名一致,仍建议采用小写字母开头、仅含小写字母、数字与连字符的名称。

pg_seq

参数名称: pg_seq, 类型: int, 层次:I

PostgreSQL 实例序列号,必选的身份标识参数,无默认值。

此实例的序号,在其 集群 内是唯一分配的,通常使用自然数,从0或1开始分配,通常不会回收重用。

pg_role

参数名称: pg_role, 类型: enum, 层次:I

PostgreSQL 实例角色,必选的身份标识参数,无默认值。当前校验接受:primaryreplicastandbyofflinedelayed

常用的服务成员标签如下:

  • primary:主实例,在集群中有且仅有一个。
  • replica:用于承载在线只读流量的副本,高负载下可能会有轻微复制延迟(10ms~100ms, 100KB)。
  • offline:用于处理离线只读流量的离线副本,如统计分析/ETL/个人查询等。

standbydelayed 也是合法的清单角色值,但当前角色逻辑不会仅凭这两个字符串自动创建备份集群或延迟复制;相应拓扑仍需通过 pg_upstreampg_delay 配置。按角色筛选的 HBA 规则会直接使用这些清单标签。

pg_instances

参数名称: pg_instances, 类型: dict, 层次:I

使用 {port:ins_vars} 的形式在一台主机上定义多个 PostgreSQL 实例。

此参数是为在单个节点上的多实例部署保留的参数,Pigsty 尚未实现此功能,并强烈建议独占节点部署。

pg_upstream

参数名称: pg_upstream, 类型: ip, 层次:I

备份集群 或级联从库的上游实例 IP 地址。

在集群的 primary 实例上设置 pg_upstream,表示此集群是一个 备份集群,该实例将作为 standby leader,从上游集群接收并应用更改。

对非 primary 实例设置 pg_upstream 参数将指定一个具体实例作为物理复制的上游,如果与主实例 ip 地址不同,此实例将成为 级联副本。确保上游 IP 地址是同一集群中的另一个实例是用户的责任。

pg_shard

参数名称: pg_shard, 类型: string, 层次:C

PostgreSQL 水平分片名称,默认值为 pg_cluster。对于包含多个物理集群的水平分片集群(例如 Citus 集群),建议显式指定。

当多个标准的 PostgreSQL 集群一起以水平分片方式为同一业务提供服务时,Pigsty 将此组集群标记为 水平分片集群

pg_shard 是分片组名称。它通常是 pg_cluster 的前缀。

例如,如果我们有一个分片组 pg-citus,并且其中有4个集群,它们的标识参数将是:

cls pg_shard: pg-citus
cls pg_group = 0:   pg-citus0
cls pg_group = 1:   pg-citus1
cls pg_group = 2:   pg-citus2
cls pg_group = 3:   pg-citus3

pg_group

参数名称: pg_group, 类型: int, 层次:C

PostgreSQL 水平分片集群的分片索引号,默认值为 0。对于包含多个物理集群的水平分片集群(例如 Citus 集群),建议显式指定。

此参数与 pg_shard 配对使用,通常可以使用非负整数作为索引号。

gp_role

参数名称: gp_role, 类型: enum, 层次:C

PostgreSQL 集群的 Greenplum/Matrixdb 角色,可以是 mastersegment

  • master:标记 postgres 集群为 greenplum 主实例(协调节点),这是默认值。
  • segment 标记 postgres 集群为 greenplum 段集群(数据节点)。

此参数仅用于 Greenplum/MatrixDB 数据库 (pg_modegpsql),对于普通的 PostgreSQL 集群没有意义。

pg_exporters

参数名称: pg_exporters, 类型: dict, 层次:C

额外用于 监控 远程 PostgreSQL 实例的 Exporter 定义,默认值:{}

如果您希望监控远程 PostgreSQL 实例,请在监控系统所在节点(Infra 节点)集群上的 pg_exporters 参数中定义它们,并使用 pgsql-monitor.yml 剧本来完成部署。

pg_exporters: # list all remote instances here, alloc a unique unused local port as k
    20001: { pg_cluster: pg-foo, pg_seq: 1, pg_host: 10.10.10.10 }
    20004: { pg_cluster: pg-foo, pg_seq: 2, pg_host: 10.10.10.11 }
    20002: { pg_cluster: pg-bar, pg_seq: 1, pg_host: 10.10.10.12 }
    20003: { pg_cluster: pg-bar, pg_seq: 1, pg_host: 10.10.10.13 }

pg_offline_query

参数名称: pg_offline_query, 类型: bool, 层次:I

设置为 true,将此实例标记为可承载离线查询,默认为 false

该标记会使实例进入默认 offline 服务的候选集合,并使 role: offline 的 HBA 规则在该实例上生效。它本身不会授予连接权限;用户能否连接仍取决于生成的 HBA 规则、数据库 CONNECT 权限和角色属性。

带有此标记的实例在效果上类似于为实例设置 pg_role = offline,唯一的区别在于 offline 实例默认不会承载 replica 服务的请求,是作为专用的离线/分析从库实例而存在的。

没有专用离线实例时,可以在普通从库的实例层配置中启用该参数。若要将 dbrole_offline 限制到这些实例,还需为对应 HBA 规则显式设置 role: offline


PG_BUSINESS

定制集群模板:用户,数据库,服务,权限规则。

用户需 重点关注 此部分参数,因为这里是业务声明自己所需数据库对象的地方。

默认 的数据库用户及其凭据,生产环境必须修改这些用户的密码。

# postgres business object definition, overwrite in group vars
pg_users: []                      # postgres business users
pg_databases: []                  # postgres business databases
pg_services: []                   # postgres business services
pg_hba_rules: []                  # business hba rules for postgres
pgb_hba_rules: []                 # business hba rules for pgbouncer
pg_crontab: []                    # crontab entries for postgres dbsu
# global credentials, overwrite in global vars
pg_dbsu_password: ''              # dbsu password, empty string means no dbsu password by default
pg_replication_username: replicator
pg_replication_password: DBUser.Replicator
pg_admin_username: dbuser_dba
pg_admin_password: DBUser.DBA
pg_monitor_username: dbuser_monitor
pg_monitor_password: DBUser.Monitor

pg_users

参数名称: pg_users, 类型: user[], 层次:C

PostgreSQL 业务用户列表,需要在 PG 集群层面进行定义。默认值为:[] 空列表。

每一个数组元素都是一个 用户/角色 定义,例如:

- name: dbuser_meta               # 必选,`name` 是用户定义的唯一必选字段
  state: create                   # 可选,用户状态:create(创建,默认)、absent(删除)
  password: DBUser.Meta           # 可选,密码,可以是 scram-sha-256 哈希字符串或明文
  login: true                     # 可选,默认为 true,是否可以登录
  superuser: false                # 可选,默认为 false,是否是超级用户
  createdb: false                 # 可选,默认为 false,是否可以创建数据库
  createrole: false               # 可选,默认为 false,是否可以创建角色
  inherit: true                   # 可选,默认为 true,是否自动继承所属角色权限
  replication: false              # 可选,默认为 false,是否可以发起流复制连接
  bypassrls: false                # 可选,默认为 false,是否可以绕过行级安全
  connlimit: -1                   # 可选,用户连接数限制,默认 -1 不限制
  expire_in: 3650                 # 可选,从创建时起 N 天后过期(优先级比 expire_at 高)
  expire_at: '2030-12-31'         # 可选,过期日期,使用 YYYY-MM-DD 格式(优先级没 expire_in 高)
  comment: pigsty admin user      # 可选,用户备注信息
  roles: [dbrole_admin]           # 可选,所属角色数组
  parameters:                     # 可选,角色级配置参数
    search_path: public
  pgbouncer: true                 # 可选,是否加入连接池用户列表,默认 false
  pool_mode: transaction          # 可选,用户级别的池化模式,默认 transaction
  pool_connlimit: 100             # 可选,用户级连接池最大连接数;省略时继承 Pigsty 全局默认 100

用户级连接池限额字段统一使用 pool_connlimit(对应 Pgbouncer max_user_connections)。

pg_databases

参数名称: pg_databases, 类型: database[], 层次:C

PostgreSQL 业务数据库列表,需要在 PG 集群层面进行定义。默认值为:[] 空列表。

每一个数组元素都是一个 业务数据库 定义,例如:

- name: meta                      # 必选,`name` 是数据库定义的唯一必选字段
  state: create                   # 可选,数据库状态:create(创建,默认)、absent(删除)、recreate(重建)
  baseline: cmdb.sql              # 可选,数据库 sql 的基线定义文件路径(ansible 搜索路径中的相对路径,如 files/)
  pgbouncer: true                 # 可选,是否将此数据库添加到 pgbouncer 数据库列表?默认为 true
  schemas: [pigsty]               # 可选,要创建的附加模式,由模式名称字符串组成的数组
  extensions:                     # 可选,要安装的附加扩展:扩展对象的数组
    - { name: postgis , schema: public }  # 可以指定将扩展安装到某个模式中,也可以不指定(不指定则安装到 search_path 首位模式中)
    - { name: timescaledb }               # 例如有的扩展会创建并使用固定的模式,就不需要指定模式。
  comment: pigsty meta database   # 可选,数据库的说明与备注信息
  owner: postgres                 # 可选,数据库所有者,不指定则为当前用户
  template: template1             # 可选,要使用的模板,默认为 template1,目标必须是一个模板数据库
  strategy: FILE_COPY             # 可选,克隆策略:FILE_COPY 或 WAL_LOG(PG15+),不指定使用 PG 默认
  encoding: UTF8                  # 可选,不指定则继承模板/集群配置(UTF8)
  locale: C                       # 可选,不指定则继承模板/集群配置(C)
  lc_collate: C                   # 可选,不指定则继承模板/集群配置(C)
  lc_ctype: C                     # 可选,不指定则继承模板/集群配置(C)
  locale_provider: libc           # 可选,本地化提供者:libc、icu、builtin(PG15+)
  icu_locale: en-US               # 可选,ICU 本地化规则(PG15+)
  icu_rules: ''                   # 可选,ICU 排序规则(PG16+)
  builtin_locale: C.UTF-8         # 可选,内置本地化提供者规则(PG17+)
  tablespace: pg_default          # 可选,默认表空间,默认为 'pg_default'
  is_template: false              # 可选,是否标记为模板数据库,允许任何有 CREATEDB 权限的用户克隆
  allowconn: true                 # 可选,是否允许连接,默认为 true。显式设置 false 将完全禁止连接到此数据库
  revokeconn: false               # 可选,撤销公共连接权限。默认为 false,设置为 true 时,属主和管理员之外用户的 CONNECT 权限会被回收
  register_datasource: true       # 可选,是否将此数据库注册到 grafana 数据源?默认为 true,显式设置为 false 会跳过注册
  connlimit: -1                   # 可选,数据库连接限制,默认为 -1 ,不限制,设置为正整数则会限制连接数
  parameters:                     # 可选,数据库级参数,通过 ALTER DATABASE SET 设置
    work_mem: '64MB'
    statement_timeout: '30s'
  pool_auth_user: dbuser_meta     # 可选,连接到此 pgbouncer 数据库的所有连接都将使用此用户进行验证(启用 pgbouncer_auth_query 才有用)
  pool_mode: transaction          # 可选,数据库级别的 pgbouncer 池化模式,默认为 transaction
  pool_size: 50                   # 可选,数据库级别的 pgbouncer 默认池子大小,默认为 50
  pool_reserve: 30                # 可选,数据库级别的 pgbouncer 池子保留空间,默认为 30,当默认池子不够用时,最多再申请这么多条突发连接
  pool_size_min: 0                # 可选,数据库级别的 pgbouncer 池的最小大小,默认为 0
  pool_connlimit: 100             # 可选,数据库级别的最大数据库连接数,默认为 100

自 Pigsty v4.1.0 起,数据库连接池参数统一使用 pool_reservepool_connlimit,旧别名 pool_size_reserve / pool_max_db_conn 已收敛。

在每个数据库定义对象中,只有 name 是必选字段,其他的字段都是可选项。

pg_services

参数名称: pg_services, 类型: service[], 层次:C

PostgreSQL 服务列表,需要在 PG 集群层面进行定义。默认值为:[],空列表。

用于在数据库集群层面定义额外的服务,数组中的每一个对象定义了一个 服务,一个完整的服务定义样例如下:

- name: standby                   # 必选,服务名称,最终的 svc 名称会使用 `pg_cluster` 作为前缀,例如:pg-meta-standby
  port: 5435                      # 必选,暴露的服务端口(作为 kubernetes 服务节点端口模式)
  ip: "*"                         # 可选,服务绑定的 IP 地址,默认情况下为所有 IP 地址
  selector: "[]"                  # 必选,服务成员选择器,使用 JMESPath 来筛选配置清单
  backup: "[? pg_role == `primary`]"  # 可选,服务成员选择器(备份),也就是当默认选择器选中的实例都宕机后,服务才会由这里选中的实例成员来承载
  dest: default                   # 可选,目标端口,default|postgres|pgbouncer|<port_number>,默认为 'default',Default的意思就是使用 pg_default_service_dest 的取值来最终决定
  check: /sync                    # 可选,健康检查 URL 路径,默认为 /,这里使用 Patroni API:/sync ,只有同步备库和主库才会返回 200 健康状态码
  maxconn: 5000                   # 可选,允许的前端连接最大数,默认为5000
  balance: roundrobin             # 可选,haproxy 负载均衡算法(默认为 roundrobin,其他选项: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'
  # 注意:健康检查相关参数(inter, fastinter, downinter, rise, fall)现在由 pg_rto_plan 统一控制
  # 默认 norm 模式参数:inter 2s fastinter 1s downinter 2s rise 3 fall 3

请注意,本参数用于在集群层面添加额外的服务。如果您想在全局定义所有 PostgreSQL 数据库都要提供的服务,可以使用 pg_default_services 参数。

pg_hba_rules

参数名称: pg_hba_rules, 类型: hba[], 层次:C

数据库集群/实例的客户端 IP 黑白名单规则。默认为:[] 空列表。

对象数组,每一个对象都代表一条规则, hba 规则对象的定义形式如下:

- title: allow intranet password access
  role: common
  rules:
    - host   all  all  10.0.0.0/8      md5
    - host   all  all  172.16.0.0/12   md5
    - host   all  all  192.168.0.0/16  md5
  • title: 规则的标题名称,会被渲染为 HBA 文件中的注释。
  • rules:规则数组,每个元素是一条标准的 HBA 规则字符串。
  • role:规则的应用范围,哪些实例角色会启用这条规则?
    • common:对于所有实例生效
    • primary, replica,offline: 只针对特定的角色 pg_role 实例生效。
    • 特例:role: 'offline' 的规则除了会应用在 pg_role : offline 的实例上,对于带有 pg_offline_query 标记的实例也生效。

除了上面这种原生 HBA 规则定义形式,Pigsty 还提供了另外一种更为简便的别名形式:

- addr: 'intra'    # world|intra|infra|admin|local|localhost|cluster|<cidr>
  auth: 'pwd'      # trust|pwd|ssl|cert|deny|<official auth method>
  user: 'all'      # all|${dbsu}|${repl}|${admin}|${monitor}|<user>|<group>
  db: 'all'        # all|replication|....
  rules: []        # raw hba string precedence over above all
  title: allow intranet password access

pg_default_hba_rules 与本参数基本类似,但它是用于定义全局的 HBA 规则,而本参数通常用于定制某个集群/实例的 HBA 规则。

pgb_hba_rules

参数名称: pgb_hba_rules, 类型: hba[], 层次:C

Pgbouncer 业务 HBA 规则,默认值为: [], 空数组。

此参数与 pg_hba_rules 基本类似,都是 hba 规则对象的数组,区别在于本参数是为 Pgbouncer 准备的。

pgb_default_hba_rules 与本参数基本类似,但它是用于定义全局连接池 HBA 规则,而本参数通常用于定制某个连接池集群/实例的 HBA 规则。

pg_crontab

参数名称: pg_crontab, 类型: string[], 层次:C

PostgreSQL 数据库超级用户(dbsu,默认 postgres)的定时任务列表,默认值为:[] 空数组。

每个数组元素是一行 crontab 条目,使用标准的用户 crontab 格式:分 时 日 月 周 命令无需指定用户名)。

pg_crontab:
  - '00 01 * * * /pg/bin/pg-backup full'      # 每天凌晨 1 点全量备份
  - '00 13 * * * /pg/bin/pg-backup'           # 每天下午 1 点增量备份

此参数会将定时任务写入 postgres 用户的个人 crontab 文件:

  • EL 系统:/var/spool/cron/postgres
  • Debian 系统:/var/spool/cron/crontabs/postgres

注意:此参数用于取代在 node_crontab 中配置 postgres 用户任务的旧做法。 因为 node_crontab 在 NODE 初始化阶段写入 /etc/crontab,此时 postgres 用户可能尚未创建,会导致 cron 报错。

移除集群时,此 crontab 文件会被一并删除。

pg_replication_username

参数名称: pg_replication_username, 类型: username, 层次:G

PostgreSQL 物理复制用户名,默认使用 replicator,不建议修改此参数。

pg_replication_password

参数名称: pg_replication_password, 类型: password, 层次:G

PostgreSQL 物理复制用户密码,默认值为:DBUser.Replicator

警告

请在生产环境中修改此密码!

pg_admin_username

参数名称: pg_admin_username, 类型: username, 层次:G

PostgreSQL / Pgbouncer 管理员名称,默认为:dbuser_dba

这是全局使用的数据库管理员,具有数据库的 Superuser 权限与连接池的流量管理权限,请务必控制使用范围。

pg_admin_password

参数名称: pg_admin_password, 类型: password, 层次:G

PostgreSQL / Pgbouncer 管理员密码,默认为: DBUser.DBA

警告

请在生产环境中修改此密码!

pg_monitor_username

参数名称: pg_monitor_username, 类型: username, 层次:G

PostgreSQL/Pgbouncer 监控用户名,默认为:dbuser_monitor

这是一个用于监控的数据库/连接池用户,不建议修改此用户名。

但如果您的现有数据库使用了不同的监控用户,可以在指定监控目标时使用此参数传入使用的监控用户名。

pg_monitor_password

参数名称: pg_monitor_password, 类型: password, 层次:G

PostgreSQL/Pgbouncer 监控用户使用的密码,默认为:DBUser.Monitor

请尽可能不要在密码中使用 @:/ 这些容易与 URL 分隔符混淆的字符,减少不必要的麻烦。

警告

请在生产环境中修改此密码!

pg_dbsu_password

参数名称: pg_dbsu_password, 类型: password, 层次:G/C

PostgreSQL pg_dbsu 超级用户密码,默认是空字符串,即不为其设置密码。

我们不建议为 dbsu 配置密码登陆,这会增大攻击面。例外情况是:pg_mode = citus,这时候需要为每个分片集群的 dbsu 配置密码,以便在分片集群内部进行连接。


PG_INSTALL

本节负责安装 PostgreSQL 及其扩展。如果您希望安装不同大版本与扩展插件,修改 pg_versionpg_extensions 即可,不过请注意,并不是所有扩展都在所有大版本可用。

pg_dbsu: postgres                 # os 数据库超级用户名称,默认为 postgres,最好不要更改
pg_dbsu_uid: 26                   # os 数据库超级用户 uid 和 gid,默认为 26,适用于默认的 postgres 用户和组
pg_dbsu_sudo: limit               # 数据库超级用户 sudo 权限,可选 none,limit,all,nopass。默认为 limit
pg_dbsu_home: /var/lib/pgsql      # postgresql 主目录,默认为 `/var/lib/pgsql`
pg_dbsu_ssh_exchange: true        # 是否在相同的 pgsql 集群中交换 postgres 数据库超级用户的 ssh 密钥
pg_version: 18                    # 要安装的 postgres 主版本,默认为 18
pg_bin_dir: /usr/pgsql/bin        # postgres 二进制目录,默认为 `/usr/pgsql/bin`
pg_log_dir: /pg/log/postgres      # postgres 日志目录,默认为 `/pg/log/postgres`
pg_packages:                      # pg packages to be installed, alias can be used
  - pgsql-main pgsql-common
pg_extensions: []                 # pg extensions to be installed, alias can be used

pg_dbsu

参数名称: pg_dbsu, 类型: username, 层次:C

PostgreSQL 使用的操作系统 dbsu 用户名, 默认为 postgres,改这个用户名是不太明智的。

不过在特定情况下,您可能会使用到不同于 postgres 的用户名,例如在安装配置 Greenplum / MatrixDB 时,需要使用 gpadmin / mxadmin 作为相应的操作系统超级用户。

pg_dbsu_uid

参数名称: pg_dbsu_uid, 类型: int, 层次:C

操作系统数据库超级用户的 uid 和 gid,26 是 PGDG RPM 默认的 postgres 用户 UID/GID。

对于 Debian/Ubuntu 系统,没有默认值,且 26 号用户经常被占用。因此 Pigsty 在检测到安装环境为 Debian 系,且 uid 为 26 时,会自动使用替换的 pg_dbsu_uid = 543

pg_dbsu_sudo

参数名称: pg_dbsu_sudo, 类型: enum, 层次:C

数据库超级用户的 sudo 权限,可以是 nonelimitallnopass。默认为 limit

  • none:无 Sudo 权限

  • limit:有限的 sudo 权限,用于执行与数据库相关的组件的 systemctl 命令(默认选项)。

  • all:完全的 sudo 权限,需要密码。

  • nopass:不需要密码的完全 sudo 权限(不推荐)。

  • 默认值为 limit,只允许执行 sudo systemctl <start|stop|reload> <postgres|patroni|pgbouncer|...>

pg_dbsu_home

参数名称: pg_dbsu_home, 类型: path, 层次:C

postgresql 主目录,默认为 /var/lib/pgsql,与官方的 pgdg RPM 保持一致。

pg_dbsu_ssh_exchange

参数名称: pg_dbsu_ssh_exchange, 类型: bool, 层次:C

是否在同一 PostgreSQL 集群中交换操作系统 dbsu 的 ssh 密钥?

默认值为 true,意味着同一集群中的数据库超级用户可以互相 ssh 访问。

交换范围由当前清单中实际匹配同一 pg_clusterpg_cluster_members 决定,不依赖存在一个与集群同名的 Ansible Group。执行时的 -l 仍会限制本次剧本目标,请确保限域覆盖需要配置的成员。

pg_version

参数名称: pg_version, 类型: enum, 层次:C

要安装的 postgres 主版本,默认为 18

请注意,PostgreSQL 的物理流复制不能跨主要版本,因此最好不要在实例级别上配置此项。

您可以使用 pg_packagespg_extensions 中的参数来为特定的 PG 大版本安装不同的软件包与扩展。

pg_bin_dir

参数名称: pg_bin_dir, 类型: path, 层次:C

PostgreSQL 二进制程序目录,默认为 /usr/pgsql/bin

默认值是在安装过程中手动创建的软链接,指向安装的特定的 Postgres 版本目录。

例如 /usr/pgsql -> /usr/pgsql-15。在 Ubuntu/Debian 上则指向 /usr/lib/postgresql/15/bin

更多详细信息,请查看 PGSQL 文件结构

pg_log_dir

参数名称: pg_log_dir, 类型: path, 层次:C

PostgreSQL 日志目录,默认为:/pg/log/postgres,Vector 日志代理会使用此变量收集 PostgreSQL 日志。

请注意,如果日志目录 pg_log_dir 以数据库目录 pg_data 作为前缀,则不会显式创建(数据库目录初始化时自动创建)。

pg_packages

参数名称: pg_packages, 类型: string[], 层次:C

要安装的 PostgreSQL 软件包(RPM/DEB),这是一个包名数组,元素可以是空格或逗号分隔的包别名。

Pigsty v4 将默认值收敛为两个别名:

pg_packages:
  - pgsql-main pgsql-common
  • pgsql-main:映射到当前平台上的 PostgreSQL 内核、客户端、PL 语言以及 pg_repackwal2jsonpgvector 等核心扩展。
  • pgsql-common:映射到运行数据库必需的配套组件,例如 Patroni、Pgbouncer、pgBackRest、pg_exporter、vip-manager 等守护进程。

别名的具体定义可以在 roles/node_id/vars/ 中的 pg_package_map 查到,Pigsty 会先根据操作系统和架构解析别名,再将 $v/${pg_version} 替换为实际主版本 pg_version,最后安装真实的软件包。这样可以屏蔽不同发行版之间的包名差异。

如果需要额外的软件包(例如特定 FDW 或扩展),可以直接在 pg_packages 中追加别名或真实包名。但请记得保留 pgsql-main pgsql-common,否则会缺失核心组件。

pg_extensions

参数名称: pg_extensions, 类型: string[], 层次:G/C

要安装的 PostgreSQL 扩展包(RPM/DEB),这是一个由扩展包名或别名组成的数组。

从 v4 开始默认值为空列表 [],Pigsty 不再强制安装大体量扩展,用户可以按需选择,避免占用额外的磁盘与依赖。

如果需要安装扩展,请像下面这样填充:

pg_extensions:
  - postgis timescaledb pgvector
  - pgsql-fdw     # 使用别名一次性安装常用 FDW

pg_package_map 中提供了大量别名,方便在不同发行版之间屏蔽包名差异。下面给出当前 v4.5 EL9 映射中的单扩展别名与分类包组示例;其他平台及 PostgreSQL 大版本的实际可用范围可能不同:

pg_extensions: # extensions to be installed on this cluster
  - timescaledb postgis pgvector pg_search pg_duckdb pg_repack wal2json
  # 也可以按分类安装当前平台映射中的整组软件包;通常只选择确实需要的组
  # - pgsql-time pgsql-gis pgsql-rag pgsql-fts pgsql-olap
  # - pgsql-feat pgsql-lang pgsql-type pgsql-util pgsql-func
  # - pgsql-admin pgsql-stat pgsql-sec pgsql-fdw pgsql-sim pgsql-etl

完整映射请以目标平台的 roles/node_id/vars/<os>.<arch>.yml 与当前 扩展目录 为准。pg_analyticsspat 已从 v4.5 目录及当前主流平台映射中移除;不要沿用旧版示例安装它们。


PG_BOOTSTRAP

使用 Patroni 引导拉起 PostgreSQL 集群,并设置 1:1 对应的 Pgbouncer 连接池。

它还会使用 PG_PROVISION 中定义的默认角色、用户、权限、模式、扩展来初始化数据库集群

以下为 PGSQL 引导阶段的可配置参数。内部变量 pg_data 固定表示 /pg/data 软链,不应在配置清单中覆盖;需要调整实际主数据目录位置时,请配置 pg_fs_main

pg_fs_main: /data/postgres        # postgres main data directory, `/data/postgres` by default
pg_fs_backup: /data/backups       # postgres backup data directory, `/data/backups` by default
pg_storage_type: SSD              # storage type for pg main data, SSD,HDD, SSD by default
pg_dummy_filesize: 64MiB          # size of `/pg/dummy`, hold 64MB disk space for emergency use
pg_listen: '0.0.0.0'              # postgres/pgbouncer listen addresses, comma separated list
pg_port: 5432                     # postgres listen port, 5432 by default
pg_localhost: /var/run/postgresql # postgres unix socket dir for localhost connection
patroni_enabled: true             # if disabled, no postgres cluster will be created during init
patroni_mode: default             # patroni working mode: default,pause,remove
pg_namespace: /pg                 # top level key namespace in etcd, used by patroni & vip
patroni_port: 8008                # patroni listen port, 8008 by default
patroni_log_dir: /pg/log/patroni  # patroni log dir, `/pg/log/patroni` by default
patroni_ssl_enabled: false        # secure patroni RestAPI communications with SSL?
patroni_watchdog_mode: off        # patroni watchdog mode: automatic,required,off. off by default
patroni_username: postgres        # patroni restapi username, `postgres` by default
patroni_password: Patroni.API     # patroni restapi password, `Patroni.API` by default
pg_etcd_password: ''              # etcd password for this pg cluster, '' to use pg_cluster
pg_primary_db: postgres           # primary database name, used by citus,etc... ,postgres by default
pg_parameters: {}                 # extra parameters in postgresql.auto.conf
pg_files: []                      # extra files to be copied to postgres data directory (e.g. license)
pg_conf: oltp.yml                 # config template: oltp,olap,crit,tiny. `oltp.yml` by default
pg_max_conn: auto                 # postgres max connections, `auto` will use recommended value
pg_shared_buffer_ratio: 0.25      # postgres shared buffers ratio, 0.25 by default, 0.1~0.4
pg_io_method: worker              # io method for postgres, auto,sync,worker,io_uring, worker by default
pg_rto: norm                      # shared rto mode: fast,norm,safe,wide
pg_rpo: 1048576                   # recovery point objective in bytes, `1MiB` at most by default
pg_libs: 'pg_stat_statements, auto_explain'  # preloaded libraries, `pg_stat_statements,auto_explain` by default
pg_delay: 0                       # replication apply delay for standby cluster leader
pg_checksum: true                 # enable data checksum for postgres cluster?
pg_pwd_enc: scram-sha-256         # passwords encryption algorithm: fixed to scram-sha-256
pg_encoding: UTF8                 # database cluster encoding, `UTF8` by default
pg_locale: C                      # database cluster local, `C` by default
pg_lc_collate: C                  # database cluster collate, `C` by default
pg_lc_ctype: C                    # database character type, `C` by default
#pgsodium_key: ""                 # pgsodium key, 64 hex digit, default to sha256(pg_cluster)
#pgsodium_getkey_script: ""       # pgsodium getkey script path, pgsodium_getkey by default

pg_data

内部变量名称: pg_data, 类型: path

pg_data 是 Pigsty 内部变量,不是用户配置参数。它固定表示 Postgres 数据目录软链 /pg/data

该软链指向底层实际数据目录,在 Patroni 模板、维护脚本与清理流程中被多处引用,请不要在 pigsty.yml 中覆盖或修改它。需要调整实际主数据目录位置时,请配置 pg_fs_main。参阅 PGSQL文件结构 获取详细信息。

pg_fs_main

参数名称: pg_fs_main, 类型: path, 层次:C

PostgreSQL 主数据盘的挂载点/文件系统路径,默认为 /data/postgres

默认值:/data/postgres,它将直接用作 PostgreSQL 主数据目录的父目录。

建议使用 NVME SSD 作为 PostgreSQL 主数据存储,Pigsty 默认为 SSD 存储进行了优化,但是也支持 HDD。

您可以更改 pg_storage_typeHDD 以针对 HDD 存储进行优化。

pg_fs_backup

参数名称: pg_fs_backup, 类型: path, 层次:C

PostgreSQL 备份数据盘的挂载点/文件系统路径,默认为 /data/backups

如果您使用的是默认的 pgbackrest_method = local,建议为备份存储使用一个单独的磁盘。

备份磁盘应足够大,以容纳所有的备份,至少足以容纳3个基础备份+2天的 WAL 归档。 通常容量不是什么大问题,因为您可以使用便宜且大的机械硬盘作为备份盘。

建议为备份存储使用一个单独的磁盘,否则 Pigsty 将回退到主数据磁盘,并占用主数据盘的容量与 IO。

pg_storage_type

参数名称: pg_storage_type, 类型: enum, 层次:C

PostgreSQL 数据存储介质的类型:SSDHDD,默认为 SSD

默认值:SSD,它会影响一些调优参数,如 random_page_costeffective_io_concurrency

pg_dummy_filesize

参数名称: pg_dummy_filesize, 类型: size, 层次:C

/pg/dummy 的大小,默认值为 64MiB,用于紧急使用的64MB 磁盘空间。

当磁盘已满时,删除占位符文件可以为紧急使用释放一些空间,建议生产使用至少 8GiB

pg_listen

参数名称: pg_listen, 类型: ip, 层次:C

PostgreSQL / Pgbouncer 的监听地址,默认为 0.0.0.0(所有 ipv4 地址)。

您可以在此变量中使用占位符,例如:'${ip},${lo}''${ip},${vip},${lo}'

  • ${ip}:转换为 inventory_hostname,它是配置清单中定义的首要内网 IP 地址。
  • ${vip}:如果启用了 pg_vip_enabled,将使用 pg_vip_address 的主机部分。
  • ${lo}:将替换为 127.0.0.1

对于高安全性要求的生产环境,建议限制监听的 IP 地址。

pg_port

参数名称: pg_port, 类型: port, 层次:C

PostgreSQL 服务器监听的端口,默认为 5432

pg_localhost

参数名称: pg_localhost, 类型: path, 层次:C

本地主机连接 PostgreSQL 使用的 Unix 套接字目录,默认值为 /var/run/postgresql

PostgreSQL 和 Pgbouncer 本地连接的 Unix 套接字目录,pg_exporter 和 patroni 都会优先使用 Unix 套接字访问 PostgreSQL。

pg_namespace

参数名称: pg_namespace, 类型: path, 层次:C

etcd 中使用的顶级命名空间,由 patroni 和 vip-manager 使用,默认值是:/pg,不建议更改。

patroni_enabled

参数名称: patroni_enabled, 类型: bool, 层次:C

是否启用 Patroni?默认值为:true

如果禁用,则在初始化期间不会创建 Postgres 集群。Pigsty 将跳过拉起 patroni 的任务,当试图向现有的 postgres 实例添加一些组件时,可以使用此参数。

patroni_mode

参数名称: patroni_mode, 类型: enum, 层次:C

Patroni 工作模式:defaultpauseremove。默认值:default

  • default:正常使用 Patroni 引导 PostgreSQL 集群
  • pause:与 default 相似,但在引导后进入维护模式
  • remove:使用 Patroni 初始化集群,然后删除 Patroni 并使用原始 PostgreSQL。

patroni_port

参数名称: patroni_port, 类型: port, 层次:C

patroni 监听端口,默认为 8008,不建议更改。

Patroni API 服务器在此端口上监听健康检查和 API 请求。

patroni_log_dir

参数名称: patroni_log_dir, 类型: path, 层次:C

patroni 日志目录,默认为 /pg/log/patroni,由 Vector 日志代理收集。

patroni_ssl_enabled

参数名称: patroni_ssl_enabled, 类型: bool, 层次:G

使用 SSL 保护 patroni RestAPI 通信吗?默认值为 false

此参数是一个全局标志,只能在部署之前预先设置。因为如果为 patroni 启用了 SSL,您将必须使用 HTTPS 而不是 HTTP 执行健康检查、获取指标,调用 API。

patroni_watchdog_mode

参数名称: patroni_watchdog_mode, 类型: string, 层次:C

patroni 看门狗模式:automaticrequiredoff,默认值为 off

在主库故障的情况下,Patroni 可以使用 看门狗 来强制关机旧主库节点以避免脑裂。

  • off:不使用 看门狗。完全不进行 Fencing (默认行为)
  • automatic:如果内核启用了 softdog 模块并且看门狗属于 dbsu,则启用 watchdog
  • required:强制启用 watchdog,如果 softdog 不可用则拒绝启动 Patroni/PostgreSQL。

默认值为 off,您不应该在 Infra 节点 启用看门狗,数据一致性优先于可用性的关键系统,特别是与钱有关的业务集群可以考虑打开此选项。

注意:当使用 pg_conf = crit 配置模板时,off 会被自动提升为 automatic,以确保关键业务系统的数据一致性。

请注意,如果您的所有访问流量都使用 HAproxy 健康检查 服务接入,正常是不存在脑裂风险的。

patroni_username

参数名称: patroni_username, 类型: username, 层次:C

Patroni REST API 用户名,默认为 postgres,与 patroni_password 配对使用。

Patroni 的危险 REST API (比如重启集群)由额外的用户名/密码保护,查看 配置集群Patroni RESTAPI 以获取详细信息。

patroni_password

参数名称: patroni_password, 类型: password, 层次:C

Patroni REST API 密码,默认为 Patroni.API

警告

务必在生产环境中修改此参数!

pg_primary_db

参数名称: pg_primary_db, 类型: string, 层次:C

指定集群中的主数据库名称,用于 citus 等业务数据库,默认为 postgres

例如,在使用 Patroni 管理高可用的 Citus 集群时,您必须选择一个 “主数据库”。

此外,在这里指定的数据库名称,将在 PGSQL 模块安装完成后,显示在打印的连接串中。

pg_parameters

参数名称: pg_parameters, 类型: dict, 层次:G/C/I

可用于指定并管理 postgresql.auto.conf 中的配置参数。

当集群所有实例完成初始化后,pg_param 任务将会把本字典中的 key / value 键值对依次覆盖写入 /pg/data/postgresql.auto.conf 中。

说明

请不要手工修改该配置文件,或通过 ALTER SYSTEM 修改集群配置参数;这些修改会在下一次配置同步时被覆盖。

该变量的优先级大于 Patroni / DCS 中的集群配置(即优先级高于集群配置,由 Patroni edit-config 编辑的配置),因此通常可以在实例级别覆盖集群默认参数。

当您的集群成员有着不同的规格(不推荐的行为!)时,您可以通过本参数对每个实例的配置进行精细化管理。

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary , pg_parameters: { shared_buffers: '5GB' } }
    10.10.10.12: { pg_seq: 2, pg_role: replica , pg_parameters: { shared_buffers: '4GB' } }
    10.10.10.13: { pg_seq: 3, pg_role: replica , pg_parameters: { shared_buffers: '3GB' } }

请注意,一些 重要的集群参数(对主从库参数值有要求)是 Patroni 直接通过命令行参数管理的,具有最高优先级,无法通过此方式覆盖,对于这些参数,您必须使用 Patroni edit-config 进行管理与配置。

在主从上必须保持一致的 PostgreSQL 参数(不一致会导致从库无法启动!):

  • wal_level
  • max_connections
  • max_locks_per_transaction
  • max_worker_processes
  • max_prepared_transactions
  • track_commit_timestamp

在主从上最好保持一致的参数(考虑到主从切换的可能性):

  • listen_addresses
  • port
  • cluster_name
  • hot_standby
  • wal_log_hints
  • max_wal_senders
  • max_replication_slots
  • wal_keep_segments
  • wal_keep_size

您可以设置不存在的参数(例如来自扩展的 GUC,从而配置 ALTER SYSTEM 无法修改的“尚未存在”的参数),但将现有配置修改为非法值可能会导致 PostgreSQL 无法启动,请谨慎配置!

pg_files

参数名称: pg_files, 类型: path[], 层次:C

用于指定需要拷贝至 PGDATA 目录的文件列表,默认为空数组:[]

在本参数中指定的文件将会被拷贝至 {{ pg_data }} 目录下,这主要用于下发特殊商业版本 PostgreSQL 内核要求的 License 文件。

目前仅有 PolarDB (Oracle 兼容)内核需要许可证文件,例如,您可以将 license.lic 文件放置在 files/ 目录下,并在 pg_files 中指定:

pg_files: [ license.lic ]

pg_conf

参数名称: pg_conf, 类型: enum, 层次:C

配置模板:{oltp,olap,crit,tiny}.yml,默认为 oltp.yml

  • tiny.yml:为小节点、虚拟机、小型演示优化(1-8核,1-16GB)
  • oltp.yml:为 OLTP 工作负载和延迟敏感应用优化(4C8GB+)(默认模板)
  • olap.yml:为 OLAP 工作负载和吞吐量优化(4C8G+)
  • crit.yml:为数据一致性和关键应用优化(4C8G+)

默认值:oltp.yml,但是 配置 程序将在当前节点为小节点时将此值设置为 tiny.yml

您可以拥有自己的模板,只需将其放在templates/<mode>.yml下,并将此值设置为模板名称即可使用。

pg_max_conn

参数名称: pg_max_conn, 类型: int, 层次:C

PostgreSQL 服务器最大连接数。你可以选择一个介于 50 到 5000 之间的值,或使用 auto 选择推荐值。

默认值为 auto,会根据 pg_confpg_default_service_dest 来设定最大连接数。

  • tiny: 100
  • olap: 200
  • oltp: 200 (pgbouncer) / 1000 (postgres)
    • pg_default_service_dest = pgbouncer : 200
    • pg_default_service_dest = postgres : 1000
  • crit: 200 (pgbouncer) / 1000 (postgres)
    • pg_default_service_dest = pgbouncer : 200
    • pg_default_service_dest = postgres : 1000

不建议将此值设定为超过 5000,否则你还需要手动增加 haproxy 服务的连接限制。

Pgbouncer 的事务池可以缓解过多的 OLTP 连接问题,因此默认情况下不建议设置很大的连接数。

对于 OLAP 场景, pg_default_service_dest 修改为 postgres 可以绕过连接池。

pg_shared_buffer_ratio

参数名称: pg_shared_buffer_ratio, 类型: float, 层次:C

Postgres 共享缓冲区内存比例,默认为 0.25,正常范围在 0.1~0.4 之间。

默认值:0.25,意味着节点内存的 25% 将被用作 PostgreSQL 的分片缓冲区。如果您想为 PostgreSQL 启用大页,那么此参数值应当适当小于 node_hugepage_ratio

将此值设定为大于 0.4(40%)通常不是好主意,但在极端情况下可能有用。

注意,共享缓冲区只是 PostgreSQL 中共享内存的一部分,要计算总共享内存,使用 show shared_memory_size_in_huge_pages;

pg_rto

参数名称: pg_rto, 类型: enum, 层次:C

恢复时间目标(RTO)模式,用于控制 Patroni 与 HAProxy 的超时参数,默认为 norm

Pigsty 提供四种预设的 RTO 模式,分别针对不同的网络条件与部署场景进行了优化:

模式 适用场景 网络条件 源码目标 RTO Patroni TTL 误切风险
fast 同机柜/同交换机 < 1ms,极稳定 < 30s 20s 较高
norm 同机房(默认) 1-5ms,正常 < 45s 30s 中等
safe 同省跨机房 10-50ms,跨机房 < 90s 60s 较低
wide 跨地域/跨洲 100-200ms,公网 < 150s 120s 极低

减小 RTO 可以加快故障恢复速度,但会增加误切风险(网络抖动被误判为故障)。您需要根据实际网络条件选择合适的模式。 更多详情请参阅 RTO 利弊权衡 文档。

当前模板只识别这四个字符串键;其他值(包括数字)不会按秒数映射,而会回退到 norm。如需自定义时间组合,请修改 pg_rto_plan 并用新增的键名作为 pg_rto

pg_rto: norm   # 默认模式,适合同机房部署
pg_rto: safe   # 跨机房部署推荐
# pg_rto: 30   # 非法键;当前模板会回退到 norm,请勿用数字表达秒数

pg_rto_plan

参数名称: pg_rto_plan, 类型: dict, 层次:G

RTO 预设配置字典,定义了 Patroni 高可用与 HAProxy 健康检查的具体超时参数,默认值包含四种预设模式:

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

每个模式是一个包含 10 个参数的数组,用于同时控制 Patroni 和 HAProxy 的超时行为:

索引 参数名 组件 说明
0 ttl Patroni 主库锁 TTL(秒)
1 loop_wait Patroni 主循环休眠间隔(秒)
2 retry_timeout Patroni DCS/PostgreSQL 重试超时
3 primary_start_timeout Patroni 主库恢复等待时间
4 safety_margin Patroni Watchdog 安全边界
5 inter HAProxy 健康检查间隔
6 fastinter HAProxy 状态变化时的快速检查间隔
7 downinter HAProxy 服务器宕机时的检查间隔
8 rise HAProxy 标记为 UP 所需的连续成功检查次数
9 fall HAProxy 标记为 DOWN 所需的连续失败检查次数

此参数允许用户通过覆盖默认值来自定义 RTO 行为,或添加新的 RTO 模式。例如,如果您需要一个更激进的 RTO 配置:

pg_rto_plan:
  ultra: [ 10, 2, 3, 8, 2, '0.5s', '0.25s', '0.5s', 2, 2 ]  # 极速模式,仅限低延迟环境

注意:修改此参数需要谨慎,不恰当的超时配置可能导致集群不稳定或频繁误切换。

pg_rpo

参数名称: pg_rpo, 类型: int, 层次:C

以字节为单位的候选从库落后阈值,默认值:1048576(1MiB)。该值写入 Patroni 的 maximum_lag_on_failover,用于判断从库是否有资格参与故障切换;它不是实际数据丢失量的硬上限。 异步复制下,实际最坏丢失还取决于写入速率以及 Patroni 对主库 WAL 位置的采样时机。

当主节点宕机并且所有副本都滞后时,你必须做出一个艰难的选择,在可用性和一致性之间进行权衡

  • 提升一个落后副本成为新的主库,并尽快恢复服务,但接受可能的数据丢失。
  • 等待主库重新上线(可能永远不会),或人工干预以避免任何数据丢失。

你可以使用 crit.yml conf 模板来确保在故障转移期间没有数据丢失,但这会牺牲一些性能。

pg_libs

参数名称: pg_libs, 类型: string, 层次:C

预加载的动态共享库,默认为 pg_stat_statements,auto_explain,这是两个 PostgreSQL 自带的扩展,强烈建议启用。

对于现有集群,您可以直接 配置集群shared_preload_libraries 参数并应用生效。

如果您想使用 TimescaleDB 或 Citus 扩展,您需要将 timescaledbcitus 添加到此列表中。timescaledbcitus 应当放在这个列表的最前面,例如:

citus,timescaledb,pg_stat_statements,auto_explain

其他需要动态加载的扩展也可以添加到这个列表中,例如 pg_cronpgml 等,通常 citustimescaledb 有着最高的优先级,应该添加到列表的最前面。

pg_delay

参数名称: pg_delay, 类型: interval, 层次:I

延迟备库复制延迟,默认值:0

如果此值被设置为一个正值,备用集群主库在应用 WAL 变更之前将被延迟这个时间。设置为 1h 意味着该集群中的数据将始终滞后原集群一个小时。

查看 延迟备用集群 以获取详细信息。

pg_checksum

参数名称: pg_checksum, 类型: bool, 层次:C

为 PostgreSQL 集群启用数据校验和吗?默认值是 true,启用。

这个参数只能在 PGSQL 部署之前设置(但你可以稍后手动启用它)。

数据校验和可以帮助检测磁盘损坏和硬件故障,从 Pigsty v3.5 开始默认启用此功能以确保数据完整性。

pg_pwd_enc

参数名称: pg_pwd_enc, 类型: enum, 层次:C

密码加密算法,Pigsty v4 以后固定为 scram-sha-256

所有新建用户都会使用 SCRAM 凭据。md5 已被淘汰,如需兼容旧客户端,请在业务连接池或客户端驱动中升级至 SCRAM。

pg_encoding

参数名称: pg_encoding, 类型: enum, 层次:C

数据库集群编码,默认为 UTF8

不建议使用其他非 UTF8 系编码。

pg_locale

参数名称: pg_locale, 类型: enum, 层次:C

数据库集群本地化规则集 (Locale),默认为 C

此参数控制数据库的默认 Locale 设置,影响排序规则、字符分类等行为。使用 CPOSIX 可以获得最佳的性能和可预测的排序行为。

如果您需要特定语言的本地化支持,可以设置为相应的 Locale,例如 en_US.UTF-8zh_CN.UTF-8。请注意,Locale 设置会影响索引的排序顺序,因此在集群初始化后无法更改。

pg_lc_collate

参数名称: pg_lc_collate, 类型: enum, 层次:C

数据库集群本地化排序规则,默认为 C

除非您知道自己在做什么,否则不建议修改集群级别的本地排序规则设置。

pg_lc_ctype

参数名称: pg_lc_ctype, 类型: enum, 层次:C

数据库字符集 CTYPE,默认为 C

从 Pigsty v3.5 开始,为了与 pg_lc_collate 保持一致,默认值改为 C

pg_io_method

参数名称: pg_io_method, 类型: enum, 层次:C

PostgreSQL 的 IO 方法,默认为 worker。可选值包括:

  • auto:根据操作系统自动选择,在 Debian 系列或 EL 10+ 上使用 io_uring,否则使用 worker
  • sync:使用传统的同步 IO 方式
  • worker:使用后台工作进程处理 IO(默认选项)
  • io_uring:使用 Linux 的 io_uring 异步 IO 接口

此参数只会由当前调优模板写入 PostgreSQL 18 及以上版本的配置,用于选择异步 I/O 执行方式。

  • PostgreSQL 18 提供 workerio_uringsync 三个实际 GUC 枚举值;auto 是 Pigsty 模板的选择逻辑,并不是 PostgreSQL 自身的枚举值。
  • PostgreSQL 18 默认使用 worker,通过后台工作进程执行异步 I/O。
  • 如果您使用 Debian 12/Ubuntu 22+ 或 EL 10+ 系统,并希望获得最佳 IO 性能,可以考虑设置为 io_uring

请注意,在不支持 io_uring 的系统上设置此值可能导致 PostgreSQL 启动失败,因此 autoworker 是更安全的选择。

pg_etcd_password

参数名称: pg_etcd_password, 类型: password, 层次:C

此 PostgreSQL 集群在 etcd 中使用的密码,默认为空字符串 ''

如果设置为空字符串,则会使用 pg_cluster 参数值作为密码(对于 Citus 集群则使用 pg_shard 参数值)。

此密码用于 Patroni 连接 etcd 以及 vip-manager 访问 etcd 时的认证。

pgsodium_key

参数名称: pgsodium_key, 类型: string, 层次:C

用于 pgsodium 扩展的加密主密钥,由 64 位十六进制数字组成。

默认不设置此参数,如果未指定,Pigsty 会使用 sha256(pg_cluster) 的值自动生成一个确定性的密钥。

pgsodium 是一个基于 libsodium 的 PostgreSQL 扩展,提供加密函数和透明列加密功能。 如果您需要使用 pgsodium 的加密功能,建议显式指定一个安全的随机密钥,并妥善保管。

生成随机密钥的命令示例:

openssl rand -hex 32   # 生成 64 位十六进制密钥

pgsodium_getkey_script

参数名称: pgsodium_getkey_script, 类型: path, 层次:C

pgsodium 获取密钥脚本的路径,默认使用 Pigsty 模板中的 pgsodium_getkey 脚本。

此脚本用于在 PostgreSQL 启动时获取 pgsodium 的主密钥。默认脚本会从环境变量或配置文件中读取密钥。

如果您有自定义的密钥管理需求(如使用 HashiCorp Vault、AWS KMS 等),可以提供自定义脚本路径。

PG_PROVISION

如果说 PG_BOOTSTRAP 是创建一个新的集群,那么 PG_PROVISION 就是在集群中创建默认的对象,包括:

pg_provision: true                # 在引导后提供postgres集群
pg_init: pg-init                  # 集群模板的初始化脚本,默认为`pg-init`
pg_default_roles:                 # postgres集群中的默认角色和用户
  - { 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, dbrole_readonly] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }
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
pg_default_schemas: [ monitor ]   # 默认模式
pg_default_extensions:            # 默认扩展
  - { name: pg_stat_statements ,schema: monitor }
  - { name: pgstattuple        ,schema: monitor }
  - { name: pg_buffercache     ,schema: monitor }
  - { name: pageinspect        ,schema: monitor }
  - { name: pg_prewarm         ,schema: monitor }
  - { name: pg_visibility      ,schema: monitor }
  - { name: pg_freespacemap    ,schema: monitor }
  - { name: postgres_fdw       ,schema: public  }
  - { name: file_fdw           ,schema: public  }
  - { name: btree_gist         ,schema: public  }
  - { name: btree_gin          ,schema: public  }
  - { name: pg_trgm            ,schema: public  }
  - { name: intagg             ,schema: public  }
  - { name: intarray           ,schema: public  }
  - { name: pg_repack }
pg_reload: true                   # HBA变化后是否重载配置?
pg_default_hba_rules:             # postgres 默认 HBA 规则集,按 order 排序
  - {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  ,order: 100}
  - {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' ,order: 150}
  - {user: '${repl}'    ,db: replication ,addr: localhost ,auth: pwd   ,title: 'replicator replication from localhost',order: 200}
  - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: pwd   ,title: 'replicator replication from intranet' ,order: 250}
  - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: pwd   ,title: 'replicator postgres db from intranet' ,order: 300}
  - {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' ,order: 350}
  - {user: '${monitor}' ,db: all         ,addr: infra     ,auth: pwd   ,title: 'monitor from infra host with password',order: 400}
  - {user: '${admin}'   ,db: all         ,addr: infra     ,auth: ssl   ,title: 'admin @ infra nodes with pwd & ssl'   ,order: 450}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: ssl   ,title: 'admin @ everywhere with ssl & pwd'    ,order: 500}
  - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: pwd   ,title: 'pgbouncer read/write via local socket',order: 550}
  - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: pwd   ,title: 'read/write biz user via password'     ,order: 600}
  - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: pwd   ,title: 'allow etl offline tasks from intranet',order: 650}
pgb_default_hba_rules:            # pgbouncer 默认 HBA 规则集,按 order 排序
  - {user: '${dbsu}'    ,db: pgbouncer   ,addr: local     ,auth: peer  ,title: 'dbsu local admin access with os ident',order: 100}
  - {user: 'all'        ,db: all         ,addr: localhost ,auth: pwd   ,title: 'allow all user local access with pwd' ,order: 150}
  - {user: '${monitor}' ,db: pgbouncer   ,addr: intra     ,auth: pwd   ,title: 'monitor access via intranet with pwd' ,order: 200}
  - {user: '${monitor}' ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other monitor access addr' ,order: 250}
  - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: pwd   ,title: 'admin access via intranet with pwd'   ,order: 300}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other admin access addr'   ,order: 350}
  - {user: 'all'        ,db: all         ,addr: intra     ,auth: pwd   ,title: 'allow all user intra access with pwd' ,order: 400}

pg_provision

参数名称: pg_provision, 类型: bool, 层次:C

在集群拉起后,完整本节定义的 PostgreSQL 集群置备工作。默认值为 true

如果禁用,不会置备 PostgreSQL 集群。对于一些特殊的 “PostgreSQL” 集群,比如 Greenplum,可以关闭此选项跳过置备阶段。

pg_init

参数名称: pg_init, 类型: string, 层次:G/C

用于初始化数据库模板的 Shell 脚本位置,默认为 pg-init,该脚本会被拷贝至 /pg/bin/pg-init 后执行。

该脚本位于 roles/pgsql/templates/pg-init

你可以在该脚本中添加自己的逻辑,或者提供一个新的脚本放置在 templates/ 目录下,并将 pg_init 设置为新的脚本名称。使用自定义脚本时请保留现有的初始化逻辑。

pg_default_roles

参数名称: pg_default_roles, 类型: role[], 层次:G/C

Postgres 集群中的默认角色和用户。

Pigsty 有一个内置的角色系统,请查看 PGSQL 访问控制:角色体系 了解详情。

pg_default_roles:                 # postgres集群中的默认角色和用户
  - { 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, dbrole_readonly] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }

pg_default_privileges

参数名称: pg_default_privileges, 类型: string[], 层次:G/C

每个数据库中的默认权限(DEFAULT PRIVILEGE)设置:

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

Pigsty 基于默认角色系统提供相应的默认权限设置,请查看 PGSQL 访问控制:默认权限 了解详情。

pg_default_schemas

参数名称: pg_default_schemas, 类型: string[], 层次:G/C

要创建的默认模式,默认值为:[ monitor ],这将在所有数据库上创建一个 monitor 模式,用于放置各种监控扩展、表、视图、函数。

pg_default_extensions

参数名称: pg_default_extensions, 类型: extension[], 层次:G/C

要在所有数据库中默认创建启用的扩展列表,默认值:

pg_default_extensions: # default extensions to be created
  - { name: pg_stat_statements ,schema: monitor }
  - { name: pgstattuple        ,schema: monitor }
  - { name: pg_buffercache     ,schema: monitor }
  - { name: pageinspect        ,schema: monitor }
  - { name: pg_prewarm         ,schema: monitor }
  - { name: pg_visibility      ,schema: monitor }
  - { name: pg_freespacemap    ,schema: monitor }
  - { name: postgres_fdw       ,schema: public  }
  - { name: file_fdw           ,schema: public  }
  - { name: btree_gist         ,schema: public  }
  - { name: btree_gin          ,schema: public  }
  - { name: pg_trgm            ,schema: public  }
  - { name: intagg             ,schema: public  }
  - { name: intarray           ,schema: public  }
  - { name: pg_repack }

唯一的三方扩展是 pg_repack,这对于数据库维护很重要,所有其他扩展都是内置的 PostgreSQL Contrib 扩展插件。

监控相关的扩展默认安装在 monitor 模式中,该模式由 pg_default_schemas 创建。

pg_reload

参数名称: pg_reload, 类型: bool, 层次:A

在 hba 更改后重新加载 PostgreSQL,默认值为 true

当您想在应用 HBA 更改之前进行检查时,将其设置为 false 以禁用自动重新加载配置。

pg_default_hba_rules

参数名称: pg_default_hba_rules, 类型: hba[], 层次:G/C

PostgreSQL 基于主机的认证规则,全局默认规则定义。默认值为:

pg_default_hba_rules:             # postgres default host-based authentication rules, order by `order`
  - {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  ,order: 100}
  - {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' ,order: 150}
  - {user: '${repl}'    ,db: replication ,addr: localhost ,auth: pwd   ,title: 'replicator replication from localhost',order: 200}
  - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: pwd   ,title: 'replicator replication from intranet' ,order: 250}
  - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: pwd   ,title: 'replicator postgres db from intranet' ,order: 300}
  - {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' ,order: 350}
  - {user: '${monitor}' ,db: all         ,addr: infra     ,auth: pwd   ,title: 'monitor from infra host with password',order: 400}
  - {user: '${admin}'   ,db: all         ,addr: infra     ,auth: ssl   ,title: 'admin @ infra nodes with pwd & ssl'   ,order: 450}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: ssl   ,title: 'admin @ everywhere with ssl & pwd'    ,order: 500}
  - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: pwd   ,title: 'pgbouncer read/write via local socket',order: 550}
  - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: pwd   ,title: 'read/write biz user via password'     ,order: 600}
  - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: pwd   ,title: 'allow etl offline tasks from intranet',order: 650}

默认规则面向受信内网中的常规部署,并非公网或合规场景的加固基线。默认的 +dbrole_offline 规则没有 role 字段,因此会应用到所有实例;若需实例隔离,应复制完整默认列表,并将该规则设为 role: offline。详见 身份认证访问控制

本参数为 HBA 规则对象组成的数组,在形式上与 pg_hba_rules 完全一致。 建议在全局配置统一的 pg_default_hba_rules,针对特定集群使用 pg_hba_rules 进行额外定制。两个参数中的规则都会依次应用,后者优先级更高。

pgb_default_hba_rules

参数名称: pgb_default_hba_rules, 类型: hba[], 层次:G/C

pgbouncer default host-based authentication rules, array or hba rule object.

default value provides a fair enough security level for common scenarios, check PGSQL Authentication for details.

pgb_default_hba_rules:            # pgbouncer default host-based authentication rules, order by `order`
  - {user: '${dbsu}'    ,db: pgbouncer   ,addr: local     ,auth: peer  ,title: 'dbsu local admin access with os ident',order: 100}
  - {user: 'all'        ,db: all         ,addr: localhost ,auth: pwd   ,title: 'allow all user local access with pwd' ,order: 150}
  - {user: '${monitor}' ,db: pgbouncer   ,addr: intra     ,auth: pwd   ,title: 'monitor access via intranet with pwd' ,order: 200}
  - {user: '${monitor}' ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other monitor access addr' ,order: 250}
  - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: pwd   ,title: 'admin access via intranet with pwd'   ,order: 300}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other admin access addr'   ,order: 350}
  - {user: 'all'        ,db: all         ,addr: intra     ,auth: pwd   ,title: 'allow all user intra access with pwd' ,order: 400}

默认的 Pgbouncer HBA 规则很简单:

  1. 允许从 本地 使用密码登陆
  2. 允许从内网网断使用密码登陆

用户可以按照自己的需求进行定制。

本参数在形式上与 pgb_hba_rules 完全一致,建议在全局配置统一的 pgb_default_hba_rules,针对特定集群使用 pgb_hba_rules 进行额外定制。两个参数中的规则都会依次应用,后者优先级更高。


PG_BACKUP

本节定义了用于 pgBackRest 的变量,它被用于 PGSQL 时间点恢复 PITR。

查看 PGSQL 备份 & PITR 以获取详细信息;手工演练见 PITR 教程

pgbackrest_enabled: true          # 在 pgsql 主机上启用 pgBackRest 吗?
pgbackrest_log_dir: /pg/log/pgbackrest # pgbackrest 日志目录,默认为 `/pg/log/pgbackrest`
pgbackrest_method: local          # pgbackrest 仓库方法:local, minio, [用户定义...]
pgbackrest_init_backup: true      # pgbackrest 初始化完成后是否立即执行全量备份?
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`
    block: y                      # 启用块级增量备份(pgBackRest 2.46+)
    bundle: y                     # 将小文件打包成一个文件
    bundle_limit: 20MiB           # 对象存储文件打包阈值,默认 20MiB
    bundle_size: 128MiB           # 对象存储文件打包目标大小,默认 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 在 minio 仓库上按时间保留完整备份
    retention_full: 14            # 保留过去 14 天的完整备份

pgbackrest_enabled

参数名称: pgbackrest_enabled, 类型: bool, 层次:C

是否在 PGSQL 节点上启用 pgBackRest?默认值为: true

启用后,各节点都会获得 pgBackRest 配置;使用本地文件系统仓库(local)时,每个成员都会创建各自的本地 stanza。 初始与定时备份只由当前主库执行,从库上的 pg-backup 会因角色检查而退出。非本地仓库只在未定义 pg_upstream 的主库上初始化共享 stanza。

pgbackrest_log_dir

参数名称: pgbackrest_log_dir, 类型: path, 层次:C

pgBackRest 日志目录,默认为 /pg/log/pgbackrest,Vector 日志代理会引用此参数收集日志。

pgbackrest_method

参数名称: pgbackrest_method, 类型: enum, 层次:C

pgBackRest 仓库方法:默认可选项为:localminio 或其他用户定义的方法,默认为 local

此参数用于确定用于 pgBackRest 的仓库,所有可用的仓库方法都在 pgbackrest_repo 中定义。

Pigsty 默认使用 local 备份仓库,这将在主实例的 /pg/backup 目录上创建一个备份仓库。底层存储路径由 pg_fs_backup 指定。

pgbackrest_init_backup

参数名称: pgbackrest_init_backup, 类型: bool, 层次:C

在 pgBackRest 初始化完成后是否立即执行一次全量备份?默认为 true

此任务仅在集群主库(primary)且未定义 pg_upstream 时尝试执行。任务对备份错误使用 ignore_errors, 因此启用此参数不等于保证已经存在基础备份;只有命令成功后才会写入 /etc/pgbackrest/initial.done。 部署后必须用 pig pb info(或 pb info)核验实际备份。

pgbackrest_repo

参数名称: pgbackrest_repo, 类型: dict, 层次:G/C

pgBackRest 仓库文档:https://pgbackrest.org/configuration.html#section-repository

默认值包括 localminio 两个候选仓库,定义如下。pgbackrest_method 只选择其中一个, v4.5.0 模板只将被选项渲染为 pgBackRest 的 repo1;同时列出两个字典项不表示双仓同时备份:

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`
    block: y                      # 启用块级增量备份(pgBackRest 2.46+)
    bundle: y                     # 将小文件打包成一个文件
    bundle_limit: 20MiB           # 对象存储文件打包阈值,默认 20MiB
    bundle_size: 128MiB           # 对象存储文件打包目标大小,默认 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 在 minio 仓库上按时间保留完整备份
    retention_full: 14            # 保留过去 14 天的完整备份

您可以定义新的备份仓库,例如使用 AWS S3,GCP 或其他云供应商的 S3 兼容存储服务。

块级增量备份 (Block Incremental Backup):从 pgBackRest 2.46 版本开始支持 block: y 选项,可以实现块级增量备份。 这意味着在增量备份时,pgBackRest 只会备份发生变化的数据块,而不是整个变化的文件,从而大幅减少备份数据量和备份时间。 此功能对于大型数据库特别有用,建议在对象存储仓库上启用此选项。


PG_ACCESS

本节负责数据库访问路径,包括:

  • 在每个 PGSQL 节点上部署 Pgbouncer 连接池并设定默认行为
  • 通过本地或专用 haproxy 节点发布服务端口
  • 绑定可选的 L2 VIP、注册 DNS 记录
pgbouncer_enabled: true           # if disabled, pgbouncer will not be launched on pgsql host
pgbouncer_port: 6432              # pgbouncer listen port, 6432 by default
pgbouncer_log_dir: /pg/log/pgbouncer  # pgbouncer log dir, `/pg/log/pgbouncer` by default
pgbouncer_auth_query: false       # query postgres to retrieve unlisted business users?
pgbouncer_poolmode: transaction   # pooling mode: transaction,session,statement, transaction by default
pgbouncer_sslmode: disable        # pgbouncer client ssl mode, disable by default
pgbouncer_ignore_param: [ extra_float_digits, application_name, TimeZone, DateStyle, IntervalStyle, search_path ]
pg_weight: 100          #INSTANCE # relative load balance weight in service, 100 by default, 0-255
pg_service_provider: ''           # dedicate haproxy node group name, or empty string for local nodes by default
pg_default_service_dest: pgbouncer # default service destination if svc.dest='default'
pg_default_services:              # postgres default service definitions
  - { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
  - { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
  - { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
  - { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}
pg_vip_enabled: false             # enable a l2 vip for pgsql primary? false by default
pg_vip_address: 127.0.0.1/24      # vip address in `<ipv4>/<mask>` format, require if vip is enabled
pg_vip_interface: auto            # vip network interface to listen, auto by default
pg_dns_suffix: ''                 # pgsql dns suffix, '' by default
pg_dns_target: auto               # auto, primary, vip, none, or ad hoc ip

pgbouncer_enabled

参数名称: pgbouncer_enabled, 类型: bool, 层次:C

默认值为 true,如果禁用,将不会在 PGSQL节点 上配置连接池 Pgbouncer。

pgbouncer_port

参数名称: pgbouncer_port, 类型: port, 层次:C

Pgbouncer 监听端口,默认为 6432

pgbouncer_log_dir

参数名称: pgbouncer_log_dir, 类型: path, 层次:C

Pgbouncer 日志目录,默认为 /pg/log/pgbouncer,Vector 日志代理会根据此参数收集 Pgbouncer 日志。

pgbouncer_auth_query

参数名称: pgbouncer_auth_query, 类型: bool, 层次:C

是否允许 Pgbouncer 查询 PostgreSQL,以允许未显式列出的用户通过连接池访问 PostgreSQL?默认值是 false

如果启用,pgbouncer 用户将使用 SELECT username, password FROM monitor.pgbouncer_auth($1) 对 postgres 数据库进行身份验证,否则,只有带有 pgbouncer: true 的业务用户才被允许连接到 Pgbouncer 连接池。

pgbouncer_poolmode

参数名称: pgbouncer_poolmode, 类型: enum, 层次:C

Pgbouncer 连接池池化模式:transaction,session,statement,默认为 transaction

  • session:会话级池化,具有最佳的功能兼容性。
  • transaction:事务级池化,具有更好的性能(许多小连接),可能会破坏某些会话级特性,如 NOTIFY/LISTEN 等…
  • statements:语句级池化,用于简单的只读查询。

如果您的应用出现功能兼容性问题,可以考虑修改此参数为 session

pgbouncer_sslmode

参数名称: pgbouncer_sslmode, 类型: enum, 层次:C

Pgbouncer 客户端 ssl 模式,默认为 disable

注意,启用 SSL 可能会对你的 pgbouncer 产生巨大的性能影响。

  • disable:如果客户端请求 TLS 则忽略(默认)
  • allow:如果客户端请求 TLS 则使用。如果没有则使用纯 TCP。不验证客户端证书。
  • prefer:与 allow 相同。
  • require:客户端必须使用 TLS。如果没有则拒绝客户端连接。不验证客户端证书。
  • verify-ca:客户端必须使用有效的客户端证书的 TLS。
  • verify-full:与 verify-ca 相同。

pgbouncer_ignore_param

参数名称: pgbouncer_ignore_param, 类型: string[], 层次:C

PgBouncer 忽略的启动参数列表,默认值为:

[ extra_float_digits, application_name, TimeZone, DateStyle, IntervalStyle, search_path ]

这些参数会被配置到 PgBouncer 配置文件中的 ignore_startup_parameters 选项。当客户端连接时设置这些参数时,PgBouncer 不会因为连接池中的连接参数不匹配而创建新的连接。

这允许不同的客户端使用相同的连接池,即使它们设置了不同的这些参数值。此参数在 Pigsty v3.5 中新增。


pg_weight

参数名称: pg_weight, 类型: int, 层次:I

服务中的相对负载均衡权重,默认为100,范围0-255。

默认值: 100。您必须在实例变量中定义它,并 重载服务 以生效。

pg_service_provider

参数名称: pg_service_provider, 类型: string, 层次:G/C

专用的 haproxy 节点组名,或默认为本地节点的空字符串。

如果指定,PostgreSQL 服务将注册到专用的 haproxy 节点组,而不是当下的 PGSQL 集群节点。

请记住为每个服务在专用的 haproxy 节点上分配 唯一 的端口!

例如,如果我们在3节点的 pg-test 集群上定义以下参数:

pg_service_provider: infra       # use load balancer on group `infra`
pg_default_services:             # alloc port 10001 and 10002 for pg-test primary/replica service  
  - { name: primary ,port: 10001 ,dest: postgres  ,check: /primary   ,selector: "[]" }
  - { name: replica ,port: 10002 ,dest: postgres  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }

pg_default_service_dest

参数名称: pg_default_service_dest, 类型: enum, 层次:G/C

当定义一个 服务 时,如果 svc.dest='default',此参数将用作默认值。

默认值: pgbouncer,意味着5433主服务和5434副本服务将默认将流量路由到 pgbouncer。

如果您不想使用 pgbouncer,将其设置为 postgres。流量将直接路由到 postgres。

pg_default_services

参数名称: pg_default_services, 类型: service[], 层次:G/C

postgres 默认服务定义

默认值是四个默认服务定义,如 PGSQL Service 所述

pg_default_services:               # postgres default service definitions
  - { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
  - { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
  - { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
  - { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}

pg_vip_enabled

参数名称: pg_vip_enabled, 类型: bool, 层次:C

为 PGSQL 集群启用 L2 VIP 吗?默认值是 false,表示不创建 L2 VIP。

启用 L2 VIP 后,会有一个 VIP 绑定在集群主实例节点上,由 vip-manager 管理,根据 etcd 中的数据进行判断。

L2 VIP 只能在相同的 L2 网络中使用,这可能会对您的网络拓扑产生额外的限制。

pg_vip_address

参数名称: pg_vip_address, 类型: cidr4, 层次:C

如果启用 vip,则需要<ipv4>/<mask>格式的 vip 地址。

默认值: 127.0.0.1/24。这个值由两部分组成:ipv4mask,用 / 分隔。

pg_vip_interface

参数名称: pg_vip_interface, 类型: string, 层次:C/I

vip network interface to listen, auto by default.

L2 VIP 监听的网卡接口,默认为 auto。Pigsty 会根据 inventory 中的实例 IP 自动探测对应网卡。

它应该是您节点的首要网卡名,即您在配置清单中使用的 IP 地址。

自动探测不适用于非标准路由、策略路由等特殊网络环境时,您可以在实例变量上显式覆盖:

pg-test:
    hosts:
        10.10.10.11: {pg_seq: 1, pg_role: replica ,pg_vip_interface: eth0 }
        10.10.10.12: {pg_seq: 2, pg_role: primary ,pg_vip_interface: eth1 }
        10.10.10.13: {pg_seq: 3, pg_role: replica ,pg_vip_interface: eth2 }
    vars:
      pg_vip_enabled: true          # 为这个集群启用L2 VIP,默认绑定到主实例
      pg_vip_address: 10.10.10.3/24 # L2网络CIDR: 10.10.10.0/24, vip地址: 10.10.10.3
      # pg_vip_interface: eth1      # 如果您的节点有统一的接口,您可以在这里定义它

pg_dns_suffix

参数名称: pg_dns_suffix, 类型: string, 层次:C

PostgreSQL DNS 名称后缀,默认为空字符串。

在默认情况下,PostgreQL 集群名会作为 DNS 域名注册到 Infra 节点的 dnsmasq 中对外提供解析。

您可以通过本参数指定一个域名后缀,这样会使用 {{ pg_cluster }}{{ pg_dns_suffix }} 作为集群 DNS 名称。

例如,如果您将 pg_dns_suffix 设置为 .db.vip.company.tld,那么 pg-test 的集群 DNS 名称将是 pg-test.db.vip.company.tld

pg_dns_target

参数名称: pg_dns_target, 类型: enum, 层次:C

Could be: auto, primary, vip, none, or an ad hoc ip address, which will be the target IP address of cluster DNS record.

default values: auto , which will bind to pg_vip_address if pg_vip_enabled, or fallback to cluster primary instance ip address.

  • vip:bind to pg_vip_address
  • primary:resolve to cluster primary instance ip address
  • auto:resolve to pg_vip_address if pg_vip_enabled, or fallback to cluster primary instance ip address.
  • none:do not bind to any ip address
  • <ipv4>:bind to the given IP address

可以是:autoprimaryvipnone 或一个特定的 IP 地址,它将是集群 DNS 记录的解析目标 IP 地址。

默认值: auto,如果 pg_vip_enabled,将绑定到 pg_vip_address,否则会回退到集群主实例的 IP 地址。

  • vip:绑定到 pg_vip_address
  • primary:解析为集群主实例 IP 地址
  • auto:如果 pg_vip_enabled,解析为 pg_vip_address,或回退到集群主实例 ip 地址。
  • none:不绑定到任何 ip 地址
  • <ipv4>:绑定到指定的 IP 地址

PG_MONITOR

PG_MONITOR 组的参数用于监控 PostgreSQL 数据库、Pgbouncer 连接池与 pgBackRest 备份系统的状态。

此参数组定义了三个 Exporter 的配置:pg_exporter 用于监控 PostgreSQL,pgbouncer_exporter 用于监控连接池,pgbackrest_exporter 用于监控备份状态。

pg_exporter_enabled: true              # 在 pgsql 主机上启用 pg_exporter 吗?
pg_exporter_config: pg_exporter.yml    # pg_exporter 配置文件名
pg_exporter_cache_ttls: '1,10,60,300'  # pg_exporter 收集器 ttl 阶段(秒),默认为 '1,10,60,300'
pg_exporter_port: 9630                 # pg_exporter 监听端口,默认为 9630
pg_exporter_params: 'sslmode=disable'  # pg_exporter dsn 的额外 url 参数
pg_exporter_url: ''                    # 如果指定,将覆盖自动生成的 pg dsn
pg_exporter_auto_discovery: true       # 启用自动数据库发现?默认启用
pg_exporter_exclude_database: 'template0,template1,postgres' # 在自动发现过程中不会被监控的数据库的 csv 列表
pg_exporter_include_database: ''       # 在自动发现过程中将被监控的数据库的 csv 列表
pg_exporter_connect_timeout: 200       # pg_exporter 连接超时(毫秒),默认为 200
pg_exporter_options: ''                # 覆盖 pg_exporter 的额外选项
pgbouncer_exporter_enabled: true       # 在 pgsql 主机上启用 pgbouncer_exporter 吗?
pgbouncer_exporter_port: 9631          # pgbouncer_exporter 监听端口,默认为 9631
pgbouncer_exporter_url: ''             # 如果指定,将覆盖自动生成的 pgbouncer dsn
pgbouncer_exporter_options: ''         # 覆盖 pgbouncer_exporter 的额外选项
pgbackrest_exporter_enabled: true      # 在 pgsql 主机上启用 pgbackrest_exporter 吗?
pgbackrest_exporter_port: 9854         # pgbackrest_exporter 监听端口,默认为 9854
pgbackrest_exporter_options: >-        # 覆盖 pgbackrest_exporter 的额外选项
  --collect.interval=120
  --log.level=info

pg_exporter_enabled

参数名称: pg_exporter_enabled, 类型: bool, 层次:C

是否在 PGSQL 节点上启用 pg_exporter?默认值为:true

PG Exporter 用于监控 PostgreSQL 数据库实例,如果不想安装 pg_exporter 可以设置为 false

pg_exporter_config

参数名称: pg_exporter_config, 类型: string, 层次:C

pg_exporter 的收集器配置文件名,默认值:pg_exporter.yml。Pgbouncer Exporter 使用独立且固定的 pgbouncer_exporter.yml 模板,不受此参数影响。

默认模板位于 roles/pg_monitor/templates/pg_exporter.yml。若要使用自定义文件,需要将其放在 Ansible 的模板搜索路径中,并在这里填写对应模板名。

pg_exporter_cache_ttls

参数名称: pg_exporter_cache_ttls, 类型: string, 层次:C

pg_exporter 收集器 TTL 阶梯(秒),默认为 ‘1,10,60,300’

默认值:1,10,60,300,它将为不同的度量收集器使用不同的 TTL 值: 1s, 10s, 60s, 300s。

PG Exporter 内置了缓存机制,避免多个 Prometheus 重复抓取对数据库产生不当影响,所有指标收集器按 TTL 分为四类:

ttl_fast: "{{ pg_exporter_cache_ttls.split(',')[0]|int }}"         # critical queries
ttl_norm: "{{ pg_exporter_cache_ttls.split(',')[1]|int }}"         # common queries
ttl_slow: "{{ pg_exporter_cache_ttls.split(',')[2]|int }}"         # slow queries (e.g table size)
ttl_slowest: "{{ pg_exporter_cache_ttls.split(',')[3]|int }}"      # ver slow queries (e.g bloat)

例如,在默认配置下,存活类指标默认最多缓存 1s,大部分普通指标会缓存 10s(应当与监控抓取间隔 vmetrics_scrape_interval 相同)。 少量变化缓慢的查询会有 60s 的 TTL,极个别大开销监控查询会有 300s 的 TTL。

pg_exporter_port

参数名称: pg_exporter_port, 类型: port, 层次:C

pg_exporter 监听端口号,默认值为:9630

pg_exporter_params

参数名称: pg_exporter_params, 类型: string, 层次:C

pg_exporter 所使用 DSN 中额外的 URL PATH 参数。

默认值:sslmode=disable,它将禁用用于监控连接的 SSL(因为默认使用本地 unix 套接字)。

pg_exporter_url

参数名称: pg_exporter_url, 类型: pgurl, 层次:C

如果指定了本参数,将会覆盖自动生成的 PostgreSQL DSN,使用指定的 DSN 连接 PostgreSQL。默认值为空字符串。

如果没有指定此参数,PG Exporter 默认会使用以下的连接串访问 PostgreSQL:

postgres://{{ pg_monitor_username }}:{{ pg_monitor_password }}@{{ pg_host }}:{{ pg_port }}/postgres{% if pg_exporter_params != '' %}?{{ pg_exporter_params }}{% endif %}

当您想监控一个远程的 PostgreSQL 实例时,或者需要使用不同的监控用户/密码,配置选项时,可以使用这个参数。

pg_exporter_auto_discovery

参数名称: pg_exporter_auto_discovery, 类型: bool, 层次:C

启用自动数据库发现吗? 默认启用:true

PG Exporter 默认会连接到 DSN 中指定的数据库 (默认为管理数据库 postgres) 收集全局指标,如果您希望收集所有业务数据库的指标,可以开启此选项。 PG Exporter 会自动发现目标 PostgreSQL 实例中的所有数据库,并在这些数据库中收集 库级监控指标

pg_exporter_exclude_database

参数名称: pg_exporter_exclude_database, 类型: string, 层次:C

如果启用了数据库自动发现(默认启用),在这个参数指定的列表中的数据库将不会被监控。 默认值为: template0,template1,postgres,即管理数据库 postgres 与模板数据库会被排除在自动监控的数据库之外。

作为例外,DSN 中指定的数据库不受此参数影响,例如,PG Exporter 如果连接的是 postgres 数据库,那么即使 postgres 在此列表中,也会被监控。

pg_exporter_include_database

参数名称: pg_exporter_include_database, 类型: string, 层次:C

如果启用了数据库自动发现(默认启用),在这个参数指定的列表中的数据库才会被监控。默认值为空字符串,即不启用此功能。

参数的形式是由逗号分隔的数据库名称列表,例如:db1,db2,db3

此参数相对于 [pg_exporter_exclude_database] 有更高的优先级,相当于白名单模式。如果您只希望监控特定的数据库,可以使用此参数。

pg_exporter_connect_timeout

参数名称: pg_exporter_connect_timeout, 类型: int, 层次:C

pg_exporter 连接超时(毫秒),默认为 200 (单位毫秒)

当 PG Exporter 尝试连接到 PostgreSQL 数据库时,最多会等待多长时间?超过这个时间,PG Exporter 将会放弃连接并报错。

默认值 200毫秒 对于绝大多数场景(例如:同可用区监控)都是足够的,但是如果您监控的远程 PostgreSQL 位于另一个大洲,您可能需要增加此值以避免连接超时。

pg_exporter_options

参数名称: pg_exporter_options, 类型: arg, 层次:C

传给 PG Exporter 的命令行参数,默认值为:"" 空字符串。

当使用空字符串时,会使用默认的命令参数:

{% if pg_exporter_options != '' %}
PG_EXPORTER_OPTS='--web.listen-address=:{{ pg_exporter_port }} {{ pg_exporter_options }}'
{% else %}
PG_EXPORTER_OPTS='--web.listen-address=:{{ pg_exporter_port }} --log.level=info'
{% endif %}

注意,请不要在本参数中覆盖 pg_exporter_port 的端口配置。

pgbouncer_exporter_enabled

参数名称: pgbouncer_exporter_enabled, 类型: bool, 层次:C

在 PGSQL 节点上,是否启用 pgbouncer_exporter?默认值为:true

pgbouncer_exporter_port

参数名称: pgbouncer_exporter_port, 类型: port, 层次:C

pgbouncer_exporter 监听端口号,默认值为:9631

pgbouncer_exporter_url

参数名称: pgbouncer_exporter_url, 类型: pgurl, 层次:C

如果指定了本参数,将会覆盖自动生成的 pgbouncer DSN,使用指定的 DSN 连接 pgbouncer。默认值为空字符串。

如果没有指定此参数,Pgbouncer Exporter 默认会使用以下的连接串访问 Pgbouncer:

postgres://{{ pg_monitor_username }}:{{ pg_monitor_password }}@:{{ pgbouncer_port }}/pgbouncer?host={{ pg_localhost }}&sslmode=disable

当您想监控一个远程的 Pgbouncer 实例时,或者需要使用不同的监控用户/密码,配置选项时,可以使用这个参数。

pgbouncer_exporter_options

参数名称: pgbouncer_exporter_options, 类型: arg, 层次:C

传给 Pgbouncer Exporter 的命令行参数,默认值为:"" 空字符串。

当使用空字符串时,会使用默认的命令参数:

{% if pgbouncer_exporter_options != '' %}
PG_EXPORTER_OPTS='--web.listen-address=:{{ pgbouncer_exporter_port }} {{ pgbouncer_exporter_options }}'
{% else %}
PG_EXPORTER_OPTS='--web.listen-address=:{{ pgbouncer_exporter_port }} --log.level=info'
{% endif %}

注意,请不要在本参数中覆盖 pgbouncer_exporter_port 的端口配置。

pgbackrest_exporter_enabled

参数名称: pgbackrest_exporter_enabled, 类型: bool, 层次:C

是否在 PGSQL 节点上启用 pgbackrest_exporter?默认值为:true

pgbackrest_exporter 用于监控 pgBackRest 备份系统的状态,包括备份的大小、时间、类型、持续时长等关键指标。

pgbackrest_exporter_port

参数名称: pgbackrest_exporter_port, 类型: port, 层次:C

pgbackrest_exporter 监听端口号,默认值为:9854

此端口会注册到 VictoriaMetrics 兼容的抓取目标中,用于采集备份相关指标。

pgbackrest_exporter_options

参数名称: pgbackrest_exporter_options, 类型: arg, 层次:C

传给 pgbackrest_exporter 的命令行参数,默认值为:

pgbackrest_exporter_options: >-
  --collect.interval=120
  --log.level=info

即每 120 秒采集一次,日志级别为 info。设置此参数会整体覆盖默认参数。


PG_REMOVE

pgsql-rm.yml 会调用 pg_remove 角色来安全地移除 PostgreSQL 实例。本节参数用于控制清理行为,避免误删。

pg_rm_data: true                  # remove postgres data during remove? true by default
pg_rm_backup: true                # remove pgbackrest backup during primary remove? true by default
pg_rm_pkg: true                   # uninstall postgres packages during remove? true by default
pg_safeguard: false               # stop pg_remove running if pg_safeguard is enabled, false by default

pg_rm_data

参数名称: pg_rm_data, 类型: bool, 层次:G/C/A

删除 PGSQL 实例时是否清理 pg_data 以及软链,默认值 true

该开关既影响 pgsql-rm.yml,也影响其他触发 pg_remove 的场景。设为 false 可以保留数据目录,便于手动检查或重新挂载。

pg_rm_backup

参数名称: pg_rm_backup, 类型: bool, 层次:G/C/A

删除主库时是否一并清理 pgBackRest 仓库与配置,默认值 true

该参数仅对 pg_role=primary 的主实例生效:pg_remove 会先停止 pgBackRest、删除当前集群的 stanza,并在 pgbackrest_method == 'local' 时移除 pg_fs_backup 中的数据。备用集群或上游备份不会受到影响。

pg_rm_pkg

参数名称: pg_rm_pkg, 类型: bool, 层次:G/C/A

在清理 PGSQL 实例时是否卸载 pg_packages 安装的所有软件包,默认值 true

如果只想暂时停机并保留二进制文件,可将其设为 false,否则 pg_remove 会调用系统包管理器彻底卸载 PostgreSQL 相关组件。

pg_safeguard

参数名称: pg_safeguard, 类型: bool, 层次:G/C/A

防误删保险,默认值为 false。当显式设置为 true 时,pg_remove 会立即终止并提示,必须使用 -e pg_safeguard=false 或在变量中关闭后才会继续。

建议在生产环境批量清理前先开启此开关,确认命令与目标节点无误后再解除,以避免误操作导致实例被删除。

8.12 - 预置剧本

如何使用 ansible 剧本来管理 PostgreSQL 集群

Pigsty 提供了一系列剧本,用于集群上下线扩缩容,用户/数据库管理,监控、备份恢复或迁移已有实例。

剧本 功能
pgsql.yml 初始化 PostgreSQL 集群或添加新的从库
pgsql-rm.yml 移除 PostgreSQL 集群,或移除某个实例
pgsql-user.yml 在现有的 PostgreSQL 集群中添加新的业务用户
pgsql-db.yml 在现有的 PostgreSQL 集群中添加新的业务数据库
pgsql-monitor.yml 将远程 PostgreSQL 实例纳入监控中
pgsql-migration.yml 为现有的 PostgreSQL 集群生成迁移手册和脚本
pgsql-pitr.yml 执行 PostgreSQL 时间点恢复 (PITR)

保护机制

使用 PGSQL 剧本时需要 特别注意,剧本 pgsql.ymlpgsql-rm.yml 使用不当会有误删数据库的风险!

  • 在执行时添加 -l 参数,限制命令执行的对象范围,并确保自己在正确的目标上执行正确的任务。
  • 限制范围通常以一个数据库集群为宜,使用不带参数的 pgsql.yml 在生产环境中是一个高危操作,务必三思而后行。
  • 移除前核对 pig pg list <cluster>pig pb info,确认近期备份,并让操作者输入精确目标。

出于防止误删的目的,Pigsty 的 PGSQL 模块提供了防误删保险,由 pg_safeguard 参数控制。 当 pg_safeguard 设置为 true 时,pgsql-rm.yml 剧本会立即中止执行,防止误删数据库集群。

# 将会中止执行,保护数据安全
./pgsql-rm.yml -l pg-test -e pg_safeguard=true

# 通过命令行参数强制覆盖保护开关
./pgsql-rm.yml -l pg-test -e pg_safeguard=false

除了 pg_safeguard 外,pgsql-rm.yml 还提供了更细粒度的控制参数:

参数 默认值 说明
pg_safeguard false 防误删保险,设为 true 时剧本会中止执行
pg_rm_data true 是否移除 PostgreSQL 数据目录
pg_rm_backup true 是否移除 pgBackRest 备份数据(仅主库移除时生效)
pg_rm_pkg true 是否卸载 PostgreSQL 软件包

这些参数允许你根据实际需求精确控制移除行为:

# 移除实例的服务、监控、DCS 注册等组件,但保留数据目录
./pgsql-rm.yml -l pg-test -e pg_rm_data=false

# 移除集群但保留备份数据
./pgsql-rm.yml -l pg-test -e pg_rm_backup=false

# 移除集群并卸载软件包
./pgsql-rm.yml -l pg-test -e pg_rm_pkg=true

pgsql.yml

剧本 pgsql.yml 用于初始化 PostgreSQL 集群或添加新的从库。

下面是使用此剧本初始化沙箱环境中 PostgreSQL 集群的过程:

asciicast

基本用法

./pgsql.yml -l pg-meta            # 初始化集群 pg-meta
./pgsql.yml -l 10.10.10.13        # 初始化/添加实例 10.10.10.13
./pgsql.yml -l pg-test -t pg_service  # 刷新集群 pg-test 的服务
./pgsql.yml -l pg-test -t pg_hba,pgbouncer_hba,pgbouncer_reload -e pg_reload=true  # 重载HBA规则

包装脚本

Pigsty 提供了便捷的包装脚本简化常见操作:

bin/pgsql-add pg-meta             # 初始化 pgsql 集群 pg-meta
bin/pgsql-add 10.10.10.10         # 初始化 pgsql 实例 10.10.10.10
bin/pgsql-add pg-test 10.10.10.13 # 添加 10.10.10.13 到集群 pg-test(自动刷新服务)
bin/pgsql-svc pg-test             # 刷新 pg-test 的 haproxy 服务(成员变更时使用)
bin/pgsql-hba pg-test             # 重载 pg-test 的 pg/pgb HBA 规则

任务列表

本剧本包含以下子任务:

# pg_install              : 安装 postgres 软件包与扩展
#   - pg_dbsu             : 设置 postgres 超级用户
#     - pg_dbsu_create    : 创建 dbsu 用户
#     - pg_dbsu_sudo      : 配置 dbsu sudo 权限
#     - pg_ssh            : 交换 dbsu SSH 密钥
#   - pg_pkg              : 安装 postgres 软件包
#     - pg_pre            : 安装前置任务
#     - pg_ext            : 安装 postgres 扩展包
#     - pg_post           : 安装后置任务
#   - pg_link             : 将 pgsql 版本 bin 链接到 /usr/pgsql
#   - pg_path             : 将 pgsql bin 添加到系统路径
#   - pg_dir              : 创建 postgres 目录并设置 FHS
#   - pg_bin              : 同步 /pg/bin 脚本
#   - pg_alias            : 配置 pgsql/psql 别名
#   - pg_dummy            : 创建 dummy 占位文件
#
# pg_bootstrap            : 引导 postgres 集群
#   - pg_config           : 生成 postgres 配置
#     - pg_conf           : 生成 patroni 配置
#     - pg_key            : 生成 pgsodium 密钥
#   - pg_cert             : 为 postgres 签发证书
#     - pg_cert_private   : 检查 pg 私钥是否存在
#     - pg_cert_issue     : 签发 pg 服务端证书
#     - pg_cert_copy      : 复制密钥与证书到 pg 节点
#   - pg_launch           : 启动 patroni 主库与从库
#     - pg_watchdog       : 授予 postgres watchdog 权限
#     - pg_primary        : 启动 patroni/postgres 主库
#     - pg_init           : 使用角色/模板初始化 pg 集群
#     - pg_pass           : 将 .pgpass 文件写入 pg 主目录
#     - pg_replica        : 启动 patroni/postgres 从库
#     - pg_hba            : 生成 pg HBA 规则
#     - patroni_reload    : 重新加载 patroni 配置
#     - pg_patroni        : 必要时暂停或移除 patroni
#
# pg_provision            : 创建 postgres 业务用户与数据库
#   - pg_user             : 创建 postgres 业务用户
#     - pg_user_config    : 渲染创建用户的 sql
#     - pg_user_create    : 在 postgres 上创建用户
#   - pg_db               : 创建 postgres 业务数据库
#     - pg_db_drop        : 删除数据库(state=absent/recreate时)
#     - pg_db_config      : 渲染创建数据库的 sql
#     - pg_db_create      : 在 postgres 上创建数据库
#
# pg_backup               : 初始化 postgres PITR 备份
#   - pgbackrest          : 配置 pgbackrest 备份
#     - pgbackrest_config : 生成 pgbackrest 配置
#     - pgbackrest_init   : 初始化 pgbackrest 仓库
#     - pgbackrest_backup : 引导后进行初始备份
#
# pg_crontab              : 配置 postgres dbsu 定时任务
#
# pg_access               : 初始化 postgres 服务访问层
#   - pgbouncer           : 部署 pgbouncer 连接池
#     - pgbouncer_dir     : 创建 pgbouncer 目录
#     - pgbouncer_config  : 生成 pgbouncer 配置
#       - pgbouncer_hba   : 生成 pgbouncer hba 配置
#       - pgbouncer_user  : 生成 pgbouncer 用户列表
#     - pgbouncer_launch  : 启动 pgbouncer 服务
#     - pgbouncer_reload  : 重载 pgbouncer 配置
#   - pg_vip              : 使用 vip-manager 绑定 VIP 到主库
#     - pg_vip_config     : 生成 vip-manager 配置
#     - pg_vip_launch     : 启动 vip-manager 绑定 vip
#   - pg_dns              : 将 DNS 名称注册到基础设施 dnsmasq
#     - pg_dns_ins        : 注册 pg 实例名称
#     - pg_dns_cls        : 注册 pg 集群名称
#   - pg_service          : 使用 haproxy 暴露 pgsql 服务
#     - pg_service_config : 为 pg 服务生成本地 haproxy 配置
#     - pg_service_reload : 使用 haproxy 暴露 postgres 服务
#
# pg_monitor              : 设置 pgsql 监控并注册到基础设施
#   - pg_exporter         : 配置并启动 pg_exporter
#   - pgbouncer_exporter  : 配置并启动 pgbouncer_exporter
#   - pgbackrest_exporter : 配置并启动 pgbackrest_exporter
#   - pg_register         : 将 pgsql 注册到监控/日志/数据源
#     - add_metrics       : 将 pg 注册为 victoria 监控目标
#     - add_logs          : 将 pg 注册为 vector 日志来源
#     - add_ds            : 将 pg 数据库注册为 grafana 数据源

以下管理任务使用到了此剧本

注意事项

  • 单独针对某一集群从库执行此剧本时,用户应当确保 集群主库已经完成初始化!
  • 扩容完成后,您需要 重载服务重载HBA,包装脚本 bin/pgsql-add 会自动完成这些任务。

集群扩容时,如果 Patroni 拉起从库的时间过长,Ansible 剧本可能会因为超时而中止:

  • 典型错误信息为:wait for postgres/patroni replica 任务执行很长时间后中止
  • 但制作从库的进程会继续,例如制作从库需超过1天的场景,后续处理请参考 FAQ:制作从库失败。

pgsql-rm.yml

剧本 pgsql-rm.yml 用于移除 PostgreSQL 集群,或移除某个实例。

下面是使用此剧本移除沙箱环境中 PostgreSQL 集群的过程:

asciicast

基本用法

./pgsql-rm.yml -l pg-test          # 移除集群 pg-test
./pgsql-rm.yml -l 10.10.10.13      # 移除实例 10.10.10.13

命令行参数

本剧本可以使用以下命令行参数控制其行为:

./pgsql-rm.yml -l pg-test          # 移除集群 pg-test
    -e pg_safeguard=false          # 防误删保险,默认关闭,开启时需强制覆盖
    -e pg_rm_data=true             # 是否一并移除 PostgreSQL 数据目录,默认移除
    -e pg_rm_backup=true           # 是否一并移除 pgBackRest 备份(仅主库),默认移除
    -e pg_rm_pkg=true              # 是否卸载 PostgreSQL 软件包,默认卸载

包装脚本

bin/pgsql-rm pg-meta               # 移除 pgsql 集群 pg-meta
bin/pgsql-rm pg-test 10.10.10.13   # 从集群 pg-test 移除实例 10.10.10.13

任务列表

本剧本包含以下子任务:

# pg_safeguard           : 如果 pg_safeguard 启用则中止执行
#
# pg_monitor             : 从监控系统移除注册
#   - pg_deregister      : 从基础设施移除 pg 监控目标
#     - rm_metrics       : 从 VictoriaMetrics 目标目录移除监控目标
#     - rm_ds            : 从 grafana 移除数据源
#     - rm_logs          : 从 vector 移除日志目标
#   - pg_exporter        : 移除 pg_exporter
#   - pgbouncer_exporter : 移除 pgbouncer_exporter
#   - pgbackrest_exporter: 移除 pgbackrest_exporter
#
# pg_access              : 移除 pg 服务访问层
#   - dns                : 移除 pg DNS 记录
#   - vip                : 移除 vip-manager
#   - pg_service         : 从 haproxy 移除 pg 服务
#   - pgbouncer          : 移除 pgbouncer 连接中间件
#
# pg_crontab             : 移除 postgres dbsu 定时任务
#
# postgres               : 移除 postgres 实例
#   - pg_replica         : 移除所有从库
#   - pg_primary         : 移除主库
#   - pg_meta            : 从 etcd 移除元数据
#
# pg_backup              : 移除备份仓库(使用 pg_rm_backup=false 禁用)
# pg_data                : 移除 postgres 数据(使用 pg_rm_data=false 禁用)
# pg_pkg                 : 卸载 pg 软件包(默认启用;使用 pg_rm_pkg=false 禁用)
#   - pg_ext             : 单独卸载 postgres 扩展

以下管理任务使用到了此剧本

注意事项

  • 请不要直接对还有从库的集群主库单独执行此剧本,否则抹除主库后,其余从库会自动触发高可用自动故障切换。总是先下线所有从库后,再下线主库,当一次性下线整个集群时不需要操心此问题。
  • 实例下线后请刷新集群服务,当您从集群中下线掉某一个从库实例时,它仍然存留于在负载均衡器的配置文件中。因为健康检查无法通过,所以下线后的实例不会对集群产生影响。但您应当在恰当的时间点 重载服务,确保生产环境与配置清单的一致性。

pgsql-user.yml

剧本 pgsql-user.yml 用于在现有的 PostgreSQL 集群中添加新的业务用户。

基本用法

./pgsql-user.yml -l pg-meta -e username=dbuser_meta

包装脚本

bin/pgsql-user pg-meta dbuser_meta  # 在集群 pg-meta 上创建用户 dbuser_meta

工作流程

  1. 在配置清单中定义用户: all.children.<pg_cluster>.vars.pg_users[i]
  2. 执行剧本时指定集群和用户名: pgsql-user.yml -l <pg_cluster> -e username=<name>

剧本会:

  1. /pg/tmp/pg-user-{{ user.name }}.sql 生成用户创建 SQL
  2. 在集群主库上执行用户创建/更新 SQL
  3. 若启用 pgbouncer_enabled: true,更新 /etc/pgbouncer/userlist.txtuseropts.txt
  4. 重载 pgbouncer 使配置生效

用户定义示例

pg_users:
  - name: dbuser_meta               # 必填,用户名是唯一必须的字段
    password: DBUser.Meta           # 可选,密码可以是 scram-sha-256 哈希或明文
    login: true                     # 可选,是否可登录,默认 true
    superuser: false                # 可选,是否超级用户,默认 false
    createdb: false                 # 可选,是否可创建数据库,默认 false
    createrole: false               # 可选,是否可创建角色,默认 false
    inherit: true                   # 可选,是否继承权限,默认 true
    replication: false              # 可选,是否可复制,默认 false
    bypassrls: false                # 可选,是否绕过 RLS,默认 false
    pgbouncer: true                 # 可选,是否添加到 pgbouncer 用户列表,默认 false
    connlimit: -1                   # 可选,连接数限制,-1 表示无限制
    expire_in: 3650                 # 可选,N 天后过期(覆盖 expire_at)
    expire_at: '2030-12-31'         # 可选,指定过期日期
    comment: pigsty admin user      # 可选,用户注释
    roles: [dbrole_admin]           # 可选,所属角色
    parameters: {}                  # 可选,角色级参数
    pool_mode: transaction          # 可选,pgbouncer 用户级连接池模式
    pool_connlimit: 100             # 可选,用户级最大连接数;省略时继承全局默认 100

详情请参考:管理SOP:创建用户


pgsql-db.yml

剧本 pgsql-db.yml 用于在现有的 PostgreSQL 集群中添加新的业务数据库。

基本用法

./pgsql-db.yml -l pg-meta -e dbname=meta

包装脚本

bin/pgsql-db pg-meta meta  # 在集群 pg-meta 上创建数据库 meta

工作流程

  1. 在配置清单中定义数据库: all.children.<pg_cluster>.vars.pg_databases[i]
  2. 执行剧本时指定集群和数据库名: pgsql-db.yml -l <pg_cluster> -e dbname=<name>

剧本会:

  1. /pg/tmp/pg-db-{{ database.name }}.sql 生成数据库创建 SQL
  2. 在集群主库上执行数据库创建/更新 SQL
  3. 如果 db.register_datasource 为 true,将数据库注册为 grafana 数据源
  4. 更新 /etc/pgbouncer/database.txt 并重载 pgbouncer

数据库定义示例

pg_databases:
  - name: meta                      # 必填,数据库名是唯一必须的字段
    baseline: cmdb.sql              # 可选,数据库初始化 SQL 文件路径
    pgbouncer: true                 # 可选,是否添加到 pgbouncer,默认 true
    schemas: [pigsty]               # 可选,额外创建的 schema
    extensions:                     # 可选,要安装的扩展
      - { name: postgis, schema: public }
      - { name: timescaledb }
    comment: pigsty meta database   # 可选,数据库注释
    owner: postgres                 # 可选,数据库所有者
    template: template1             # 可选,模板数据库
    encoding: UTF8                  # 可选,字符编码
    locale: C                       # 可选,区域设置
    tablespace: pg_default          # 可选,默认表空间
    allowconn: true                 # 可选,是否允许连接
    revokeconn: false               # 可选,是否回收 public 连接权限
    register_datasource: true       # 可选,是否注册到 grafana 数据源
    connlimit: -1                   # 可选,连接数限制
    pool_auth_user: dbuser_meta     # 可选,认证查询使用的用户(配合 pgbouncer_auth_query)
    pool_mode: transaction          # 可选,pgbouncer 连接池模式
    pool_size: 50                   # 可选,pgbouncer 默认池大小
    pool_reserve: 30                # 可选,pgbouncer 保留池大小
    pool_size_min: 0                # 可选,pgbouncer 最小池大小
    pool_connlimit: 100             # 可选,pgbouncer 最大数据库连接数

详情请参考:管理SOP:创建数据库


pgsql-monitor.yml

剧本 pgsql-monitor.yml 用于将远程 PostgreSQL 实例纳入 Pigsty 监控体系。

基本用法

./pgsql-monitor.yml -e clsname=pg-foo  # 监控远程集群 pg-foo

包装脚本

bin/pgmon-add pg-foo              # 监控一个远程 pgsql 集群 pg-foo
bin/pgmon-add pg-foo pg-bar       # 同时监控多个集群

配置方式

首先需要在 infra 组变量中定义 pg_exporters

infra:
  hosts:
    10.10.10.10:
      pg_exporters:  # 列出所有远程实例,分配唯一的未使用本地端口
        20001: { pg_cluster: pg-foo, pg_seq: 1, pg_host: 10.10.10.10 }
        20002: { pg_cluster: pg-foo, pg_seq: 2, pg_host: 10.10.10.11 }

架构示意

     ------ infra ------
     |                 |
     | victoria-metrics|            v---- pg-foo-1 ----v
     |       ^         |  metrics   |         ^        |
     |   pg_exporter <-|------------|----  postgres    |
     |   (port: 20001) |            | 10.10.10.10:5432 |
     |       ^         |            ^------------------^
     |       ^         |                      ^
     |       ^         |            v---- pg-foo-2 ----v
     |       ^         |  metrics   |         ^        |
     |   pg_exporter <-|------------|----  postgres    |
     |   (port: 20002) |            | 10.10.10.11:5433 |
     -------------------            ^------------------^

可配置参数

pg_exporter_config: pg_exporter.yml    # pg_exporter 配置文件名
pg_exporter_cache_ttls: '1,10,60,300'  # pg_exporter 采集器 TTL 阶段
pg_exporter_port: 9630                 # pg_exporter 监听端口
pg_exporter_params: 'sslmode=disable'  # DSN 额外 URL 参数
pg_exporter_url: ''                    # 直接覆盖自动生成的 DSN
pg_exporter_auto_discovery: true       # 是否启用自动数据库发现
pg_exporter_exclude_database: 'template0,template1,postgres'  # 排除的数据库
pg_exporter_include_database: ''       # 仅包含的数据库
pg_exporter_connect_timeout: 200       # 连接超时(毫秒)
pg_monitor_username: dbuser_monitor    # 监控用户名
pg_monitor_password: DBUser.Monitor    # 监控密码

远程数据库配置

远程 PostgreSQL 实例需要创建监控用户:

CREATE USER dbuser_monitor;
COMMENT ON ROLE dbuser_monitor IS 'system monitor user';
ALTER USER dbuser_monitor PASSWORD 'DBUser.Monitor';
GRANT pg_monitor TO dbuser_monitor;
CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "monitor";

限制

  • 仅 postgres 指标可用
  • node、pgbouncer、patroni、haproxy 指标不可用

详情请参考:管理SOP:监控现有PG


pgsql-migration.yml

剧本 pgsql-migration.yml 用于为现有的 PostgreSQL 集群生成基于逻辑复制的零停机迁移手册和脚本。

基本用法

./pgsql-migration.yml -e@files/migration/pg-meta.yml

工作流程

  1. 定义迁移任务配置文件(如 files/migration/pg-meta.yml
  2. 执行剧本生成迁移手册与脚本
  3. 按照手册逐步执行脚本完成迁移

迁移任务定义示例

# files/migration/pg-meta.yml
context_dir: ~/migration           # 迁移手册与脚本输出目录
src_cls: pg-meta                   # 源集群名称(必填)
src_db: meta                       # 源数据库名称(必填)
src_ip: 10.10.10.10                # 源集群主库 IP(必填)
dst_cls: pg-test                   # 目标集群名称(必填)
dst_db: test                       # 目标数据库名称(必填)
dst_ip: 10.10.10.11                # 目标集群主库 IP(必填)

# 可选参数
pg_dbsu: postgres
pg_replication_username: replicator
pg_replication_password: DBUser.Replicator
pg_admin_username: dbuser_dba
pg_admin_password: DBUser.DBA
pg_monitor_username: dbuser_monitor
pg_monitor_password: DBUser.Monitor

详情请参考:管理SOP:迁移数据库集群


pgsql-pitr.yml

剧本 pgsql-pitr.yml 用于执行 PostgreSQL 时间点恢复 (Point-In-Time Recovery)。

基本用法

# 恢复到最新状态(WAL 归档流末端)
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": {}}'

# 恢复到指定时间点
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": {"time": "2025-07-13 10:00:00+00"}}'

# 恢复到指定 LSN
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": {"lsn": "0/4001C80"}}'

# 恢复到指定事务 ID
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": {"xid": "250000"}}'

# 恢复到命名还原点
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": {"name": "some_restore_point"}}'

# 从其他集群备份恢复
./pgsql-pitr.yml -l pg-test -e '{"pg_pitr": {"cluster": "pg-meta"}}'

PITR 任务参数

pg_pitr:                           # 定义 PITR 任务
  cluster: "pg-meta"               # 源集群名称(恢复其他集群的备份时使用)
  type: default                    # 恢复目标类型: default, time, xid, name, lsn, immediate
  time: "2025-01-01 10:00:00+00"   # 恢复目标:时间点
  name: "some_restore_point"       # 恢复目标:命名还原点
  xid: "100000"                    # 恢复目标:事务 ID
  lsn: "0/3000000"                 # 恢复目标:日志序列号
  set: latest                      # 从哪个备份集恢复,默认 latest
  timeline: latest                 # 目标时间线,可以是整数,默认 latest
  exclusive: false                 # 是否排除目标点,默认 false
  action: pause                    # 恢复后动作: pause, promote, shutdown
  archive: true                    # 是否保留归档设置,默认 true;探索性恢复可设为 false
  backup: false                    # 恢复前是否备份现有数据到 /pg/data-backup?默认 false
  db_include: []                   # 仅包含这些数据库
  db_exclude: []                   # 排除这些数据库
  link_map: {}                     # 表空间链接映射
  process: 4                       # 并行恢复进程数,默认使用 node_cpu
  repo: {}                         # 恢复源仓库配置
  data: /pg/data                   # 恢复数据目录
  port: 5432                       # 恢复实例监听端口

任务列表

本剧本包含以下子任务:

# down                 : 停止 HA 并关闭 patroni 和 postgres
#   - pause            : 暂停 patroni 自动故障转移
#   - stop             : 停止 patroni 和 postgres 服务
#     - stop_patroni   : 停止 patroni 服务
#     - stop_postgres  : 停止 postgres 服务
#
# pitr                 : 执行 PITR 恢复过程
#   - config           : 生成 pgbackrest 配置和恢复脚本
#   - backup           : 执行可选的原始数据备份
#   - restore          : 运行 pgbackrest restore 命令
#   - recovery         : 启动 postgres 并完成恢复
#   - verify           : 验证恢复的集群控制数据
#
# up                   : 启动 postgres/patroni 并恢复 HA
#   - etcd             : 启动前清理 etcd 元数据
#   - start            : 启动 patroni 和 postgres 服务
#     - start_postgres : 启动 postgres 服务
#     - start_patroni  : 启动 patroni 服务
#   - resume           : 恢复 patroni 自动故障转移

恢复目标类型说明

类型 说明 示例
default 恢复到 WAL 归档流末端(最新状态) {"pg_pitr": {}}
time 恢复到指定时间点 {"pg_pitr": {"time": "2025-07-13 10:00:00"}}
xid 恢复到指定事务 ID {"pg_pitr": {"xid": "250000"}}
name 恢复到命名还原点 {"pg_pitr": {"name": "before_ddl"}}
lsn 恢复到指定 LSN {"pg_pitr": {"lsn": "0/4001C80"}}
immediate 恢复到一致性状态后立即停止 {"pg_pitr": {"type": "immediate"}}

详情请参考:备份恢复教程

8.13 - 扩展插件

利用 PostgreSQL 扩展的协同超能力

Pigsty 提供 575 个已打包扩展,覆盖时序、地理、向量、全文检索、分析、特性增强等 16 大类别,开箱即用。

在 Pigsty 中使用扩展涉及四个核心步骤:下载安装配置/加载启用

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_databases:
      - name: meta
        extensions: [ postgis, timescaledb, vector ]   # 启用:在数据库中创建扩展
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain' # 配置:预加载扩展库
    pg_extensions: [ postgis, timescaledb, pgvector ]  # 安装:安装扩展软件包
Pigsty PostgreSQL 扩展生态

8.13.1 - 快速开始

使用扩展的四步流程速览

在 Pigsty 中使用扩展需要四个步骤:下载安装配置启用

  1. 下载:将扩展软件包下载到本地仓库(默认本地仓库只保证基础内核与 pgsql-main 包集)
  2. 安装:在集群节点上安装扩展软件包
  3. 配置:部分扩展需要预加载或配置参数
  4. 启用:在数据库中执行 CREATE EXTENSION 创建扩展

声明式配置

在 Pigsty 配置清单中声明扩展,集群初始化时自动完成安装与启用:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_databases:
      - name: meta
        extensions: [ postgis, timescaledb, vector ]   # 在数据库中启用扩展
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain' # 预加载扩展库
    pg_extensions: [ postgis, timescaledb, pgvector ]  # 安装扩展软件包

执行 ./pgsql.yml 初始化集群后,postgistimescaledbvector 三个扩展即在 meta 数据库中可用。


命令式操作

对于已有集群,可以使用命令行方式添加扩展:

# 1. 安装扩展软件包
./pgsql.yml -l pg-meta -t pg_extension -e '{"pg_extensions":["pgvector"]}'

# 2. 预加载扩展(如需要,修改后需重启)
pg edit-config pg-meta --force -p shared_preload_libraries='timescaledb, pg_stat_statements, auto_explain'

# 3. 在数据库中启用扩展
psql -d meta -c 'CREATE EXTENSION vector;'

也可以使用 pig 包管理器安装扩展包,然后在数据库内执行 CREATE EXTENSION

pig install pgvector                         # 安装扩展包
psql -d meta -c 'CREATE EXTENSION vector;'   # 在数据库中启用

流程速查

步骤 参数/命令 说明
下载 repo_extra_packages 指定下载到本地仓库的扩展包
安装 pg_extensions 指定集群要安装的扩展包
配置 pg_libs 预加载扩展到 shared_preload_libraries
启用 pg_databases.extensions 在数据库中自动执行 CREATE EXTENSION

详细说明请参阅各子章节:下载安装配置启用

8.13.2 - 扩展简介

PostgreSQL 扩展的核心概念与 Pigsty 扩展生态

扩展是 PostgreSQL 的灵魂所在。Pigsty 收录了 575 个预编译、开箱即用的扩展插件,充分释放 PostgreSQL 的潜能。


扩展是什么

PostgreSQL 扩展(Extension)是一种模块化机制,允许在不修改核心代码的情况下增强数据库功能。 一个扩展通常包含三部分:

  • 控制文件.control):必需,包含扩展元数据
  • SQL 脚本.sql):可选,定义函数、类型、操作符等数据库对象
  • 动态库.so):可选,提供 C 语言实现的高性能功能

扩展可以为 PostgreSQL 添加:新数据类型、索引方法、函数与操作符、外部数据访问、过程语言、性能监控、安全审计等能力。


核心扩展

Pigsty 收录的扩展中,以下是最具代表性的:

扩展 说明
PostGIS 地理空间数据类型与索引,GIS 事实标准
TimescaleDB 时序数据库,支持持续聚合、列存储、自动压缩
PGVector 向量数据类型与 HNSW/IVFFlat 索引,AI 应用必备
Citus 分布式数据库,水平分片扩展能力
pg_duckdb 嵌入 DuckDB 分析引擎,OLAP 加速
pg_search ParadeDB 搜索扩展,提供 BM25 与全文检索能力
Apache AGE 图数据库,支持 OpenCypher 查询语言
pg_graphql 原生 GraphQL 查询支持

绝大多数扩展可以并存甚至组合使用,产生 1+1 远大于 2 的协同效应。


扩展类别

Pigsty 将扩展划分为 16 个类别:

类别 别名 说明 典型扩展
时序 time 时序数据处理 timescaledb, pg_cron, periods
地理 gis 地理空间数据 postgis, h3, pgrouting
向量 rag 向量检索与 AI pgvector, vchord, pg_vectorize
搜索 fts 全文检索 pgroonga, zhparser, pg_bigm
分析 olap OLAP 与分析 pg_duckdb, pg_mooncake, citus
特性 feat 功能增强 age, pg_graphql, hll, rum
语言 lang 过程语言 plpython3u, pljava, plv8
类型 type 数据类型 hstore, ltree, ip4r
工具 util 实用工具 http, pg_net, pgjwt
函数 func 函数库 pg_uuidv7, topn, tdigest
管理 admin 运维管理 pg_repack, pg_squeeze, pgagent
统计 stat 监控统计 pg_stat_statements, pg_qualstats, auto_explain
安全 sec 安全审计 pgaudit, pgsodium, pg_tde
外联 fdw 外部数据访问 postgres_fdw, mysql_fdw, oracle_fdw
兼容 sim 数据库兼容 orafce, babelfish
同步 etl 数据同步 pglogical, wal2json, decoderbufs

使用类别别名可以批量安装整个类别的扩展,例如 pg_extensions: [ pgsql-gis, pgsql-rag ]


预定义扩展集

Pigsty 提供了若干预定义的扩展集(Stack),方便按场景选用:

扩展集 包含扩展
gis-stack postgis, pgrouting, pointcloud, h3, q3c, ogr_fdw
rag-stack pgvector, vchord, pgvectorscale, pg_similarity, pg_tiktoken
fts-stack pgroonga, pg_bigm, zhparser, hunspell
olap-stack pg_duckdb, pg_mooncake, timescaledb, pg_partman, plproxy
feat-stack age, hll, rum, pg_graphql, pg_jsonschema, jsquery
stat-stack pg_show_plans, pg_stat_kcache, pg_qualstats, pg_wait_sampling
supa-stack pg_graphql, pg_jsonschema, wrappers, pgvector, pgsodium, vault

pg_extensions 中直接使用这些名称即可安装整套扩展。


扩展资源

8.13.3 - 软件包

扩展包别名与类别命名规则

Pigsty 使用 包别名 机制简化扩展的安装与管理。


包别名机制

管理扩展涉及多个层面的名称映射:

层面 示例 pgvector 示例 postgis
扩展名 vector postgis, postgis_topology, …
包别名 pgvector postgis
RPM 包名 pgvector_18 postgis36_18*
DEB 包名 postgresql-18-pgvector postgresql-18-postgis-3*

Pigsty 提供 包别名 抽象层,让用户无需关心具体的 RPM/DEB 包名:

pg_extensions: [ pgvector, postgis, timescaledb ]  # 使用包别名

Pigsty 会根据操作系统和 PostgreSQL 版本自动翻译为正确的包名。

说明

CREATE EXTENSION 使用的是 扩展名(如 vector),而非包别名(pgvector)。


类别别名

所有扩展被划分为 16 个类别,可使用类别别名批量安装:

# 使用通用类别别名(自动适配当前 PG 版本)
pg_extensions: [ pgsql-gis, pgsql-rag, pgsql-fts ]

# 或使用版本特定的类别别名
pg_extensions: [ pg18-gis, pg18-rag, pg18-fts ]

olap 类别外,所有类别的扩展都可以同时安装。olap 类别中存在互斥:pg_duckdbpg_mooncake 冲突。


类别列表

类别 说明 典型扩展
time 时序类 timescaledb, pg_cron, periods
gis 地理类 postgis, h3, pgrouting
rag 向量类 pgvector, pgml, vchord
fts 搜索类 pg_trgm, zhparser, pgroonga
olap 分析类 citus, pg_duckdb, pg_mooncake
feat 特性类 age, pg_graphql, rum
lang 语言类 plpython3u, pljava, plv8
type 类型类 hstore, ltree, citext
util 工具类 http, pg_net, pgjwt
func 函数类 pgcrypto, uuid-ossp, pg_uuidv7
admin 管理类 pg_repack, pgagent, pg_squeeze
stat 统计类 pg_stat_statements, pg_qualstats, auto_explain
sec 安全类 pgaudit, pgcrypto, pgsodium
fdw 外部类 postgres_fdw, mysql_fdw, oracle_fdw
sim 兼容类 orafce, babelfishpg_tds
etl 数据类 pglogical, wal2json, decoderbufs

查阅扩展目录

您可以在 Pigsty 扩展目录 网站上查阅所有可用扩展的详细信息,包括:

  • 扩展名称、描述、版本
  • 支持的 PostgreSQL 版本
  • 支持的操作系统发行版
  • 安装方式、预加载需求
  • 许可证、来源仓库

8.13.4 - 下载扩展

从软件仓库下载扩展包到本地

在安装扩展前,需要确保扩展软件包已下载到本地仓库或可从上游获取。


默认行为

Pigsty 默认会把基础 PostgreSQL 18 内核包下载到本地软件仓库。默认额外下载集为 repo_extra_packages_default: [ pgsql-main ],包含 PostgreSQL 内核、客户端、过程语言,以及 pg_repackwal2jsonpgvector 等基础扩展包。

如果需要 575 个扩展目录中的其他扩展,请显式加入 repo_extra_packages;Pigsty 不会在默认安装时把全部扩展都下载到本地。

使用本地仓库的优势:

  • 加速安装,避免重复下载
  • 减少网络流量消耗
  • 提高交付可靠性
  • 确保版本一致性

下载新扩展

要下载额外的扩展,将其添加到 repo_extra_packages 并重建仓库:

all:
  vars:
    repo_extra_packages: [ pgvector, postgis, timescaledb, pg_duckdb ]
# 重新下载软件包到本地仓库
./infra.yml -t repo_build

# 刷新所有节点的软件源缓存
./node.yml -t node_repo

使用上游仓库

也可以直接从互联网上游仓库安装,无需预先下载:

# 在节点上添加上游软件源
./node.yml -t node_repo -e node_repo_modules=node,pgsql

这种方式适合:

  • 快速测试最新版本
  • 安装冷门扩展
  • 网络条件良好的环境

但可能面临:

  • 网络不稳定影响安装
  • 版本不一致风险

扩展来源

扩展软件包来自两个主要源:

仓库 说明
PGDG PostgreSQL 官方仓库,提供核心扩展
Pigsty Pigsty 补充仓库,提供额外扩展

Pigsty 仓库只收录 PGDG 仓库中不存在的扩展。一旦某扩展进入 PGDG 仓库,Pigsty 仓库会移除或与其保持一致。

仓库地址:

详细的仓库配置请参阅 扩展仓库

8.13.5 - 安装扩展

在集群节点上安装扩展软件包

Pigsty 使用操作系统的包管理器(yum/apt)安装扩展软件包。


相关参数

两个参数用于指定要安装的扩展:

参数 用途 默认行为
pg_packages 全局通用软件包 确保存在(不升级)
pg_extensions 集群特定扩展 安装最新版本

pg_packages 通常用于指定所有集群都需要的基础组件(PostgreSQL 内核、Patroni、pgBouncer 等)和必选扩展。

pg_extensions 用于指定特定集群需要的扩展。

pg_packages:                           # 全局基础包
  - pgsql-main pgsql-common
pg_extensions:                         # 集群扩展
  - postgis timescaledb pgvector

集群初始化时安装

在集群配置中声明扩展,初始化时自动安装:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_extensions: [ postgis, timescaledb, pgvector, pg_duckdb ]

执行 ./pgsql.yml 初始化集群时,扩展会自动安装。


已有集群安装扩展

对于已初始化的集群,有多种方式安装扩展:

使用 Pigsty 剧本

# 修改配置后使用剧本安装
./pgsql.yml -l pg-meta -t pg_extension

# 或直接在命令行指定扩展
./pgsql.yml -l pg-meta -t pg_extension -e '{"pg_extensions":["pg_duckdb"]}'

使用 pig 包管理器

# 使用 pig 安装扩展
pig install pg_duckdb

# 批量安装
ansible pg-meta -b -a 'pig install pg_duckdb pgvector'

直接使用包管理器

# EL 系统
sudo yum install -y pg_duckdb_18*

# Debian/Ubuntu 系统
sudo apt install -y postgresql-18-pg-duckdb

使用包别名

Pigsty 支持使用标准化的包别名,自动翻译为对应 PG 版本的包名:

pg_extensions:
  - pgvector           # 自动翻译为 pgvector_18* (EL) 或 postgresql-18-pgvector (Debian)
  - postgis            # 自动翻译为 postgis36_18* (EL) 或 postgresql-18-postgis-3* (Debian)
  - pgsql-gis          # 类别别名,安装整个 GIS 类别的扩展

也可以直接使用原始包名:

pg_extensions:
  - pgvector_18*                    # EL 系统的原始包名
  - postgresql-18-pgvector          # Debian 系统的原始包名

包别名定义参见:


验证安装

安装后可在数据库中验证:

-- 查看已安装的扩展
SELECT * FROM pg_available_extensions WHERE name = 'vector';

-- 查看扩展文件是否存在
\dx

8.13.6 - 配置扩展

预加载扩展库与配置扩展参数

部分扩展需要预加载动态库或配置参数后才能使用,本节介绍如何配置扩展。


预加载扩展

大多数扩展安装后可直接使用 CREATE EXTENSION 启用,但部分使用 PostgreSQL Hook 机制的扩展需要 预加载

预加载通过 shared_preload_libraries 参数指定,修改后需 重启数据库 生效。

需要预加载的扩展

以下是常见的需要预加载的扩展:

扩展 说明
timescaledb 时序数据库扩展,必须放在最前面
citus 分布式数据库扩展,必须放在最前面
pg_stat_statements SQL 语句统计,Pigsty 默认启用
auto_explain 自动记录慢查询执行计划,Pigsty 默认启用
pg_cron 定时任务调度
pg_net 异步 HTTP 请求
pg_tle 可信语言扩展
pgaudit 审计日志
pg_stat_kcache 内核统计信息
pg_squeeze 在线表空间回收
pgml PostgresML 机器学习

完整列表请参阅 扩展目录(带 LOAD 标记)。

预加载顺序

shared_preload_libraries 中扩展的加载顺序很重要:

  • timescaledbcitus 必须放在 最前面
  • 如果同时使用,citus 应在 timescaledb 之前
  • 统计类扩展应在 pg_stat_statements 之后,以使用相同的 query_id
pg_libs: 'citus, timescaledb, pg_stat_statements, auto_explain'

集群初始化时配置

在创建新集群时,使用 pg_libs 参数指定预加载的扩展:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'
    pg_extensions: [ timescaledb, postgis, pgvector ]

pg_libs 的值将在集群初始化时写入 shared_preload_libraries

默认值

pg_libs 的默认值是 pg_stat_statements, auto_explain,这两个 Contrib 扩展提供基本的可观测性:

  • pg_stat_statements:跟踪所有 SQL 语句的执行统计
  • auto_explain:自动记录慢查询的执行计划

已有集群修改配置

对于已初始化的集群,使用 patronictl 修改 shared_preload_libraries

# 添加 timescaledb 到预加载库
pg edit-config pg-meta --force -p shared_preload_libraries='timescaledb, pg_stat_statements, auto_explain'

# 重启集群使配置生效
pg restart pg-meta

也可以直接修改 postgresql.conf 或使用 ALTER SYSTEM

ALTER SYSTEM SET shared_preload_libraries = 'timescaledb, pg_stat_statements, auto_explain';

修改后需重启 PostgreSQL 服务生效。


扩展参数配置

许多扩展有可配置的参数,可以在以下位置设置:

集群初始化时

使用 pg_parameters 参数指定:

pg-meta:
  vars:
    pg_cluster: pg-meta
    pg_libs: 'pg_cron, pg_stat_statements, auto_explain'
    pg_parameters:
      cron.database_name: postgres           # pg_cron 使用的数据库
      pg_stat_statements.track: all          # 跟踪所有语句
      auto_explain.log_min_duration: 1000    # 记录超过 1 秒的查询

运行时修改

使用 ALTER SYSTEMpatronictl

-- 修改参数
ALTER SYSTEM SET pg_stat_statements.track = 'all';

-- 重新加载配置
SELECT pg_reload_conf();
# 使用 patronictl 修改
pg edit-config pg-meta --force -p 'pg_stat_statements.track=all'

注意事项

  1. 预加载错误会阻止启动:如果 shared_preload_libraries 中的扩展不存在或加载失败,PostgreSQL 将无法启动。确保扩展已正确安装后再添加预加载。

  2. 修改需重启shared_preload_libraries 的修改需要重启 PostgreSQL 服务才能生效。

  3. 部分功能可用:某些扩展在不预加载的情况下可以部分使用,但完整功能需要预加载。

  4. 查看当前配置:使用以下命令查看当前的预加载库:

SHOW shared_preload_libraries;

8.13.7 - 启用扩展

在数据库中创建和启用扩展

安装扩展软件包后,需要在数据库中执行 CREATE EXTENSION 才能使用扩展功能。


查看可用扩展

安装扩展软件包后,可以查看可用的扩展:

-- 查看所有可用扩展
SELECT * FROM pg_available_extensions;

-- 查看特定扩展
SELECT * FROM pg_available_extensions WHERE name = 'vector';

-- 查看已启用的扩展
SELECT * FROM pg_extension;

创建扩展

使用 CREATE EXTENSION 在数据库中启用扩展:

-- 创建扩展
CREATE EXTENSION vector;

-- 创建扩展到指定 Schema
CREATE EXTENSION postgis SCHEMA public;

-- 自动安装依赖的扩展
CREATE EXTENSION postgis_topology CASCADE;

-- 如果不存在则创建
CREATE EXTENSION IF NOT EXISTS vector;
说明

CREATE EXTENSION 使用的是 扩展名(如 vector),而非包别名(pgvector)。


集群初始化时启用

pg_databases 中声明扩展,集群初始化时自动创建:

pg-meta:
  vars:
    pg_cluster: pg-meta
    pg_databases:
      - name: meta
        extensions:
          - { name: vector }                         # 使用默认 Schema
          - { name: postgis, schema: public }        # 指定 Schema
          - { name: pg_stat_statements, schema: monitor }

Pigsty 会在数据库创建后自动执行 CREATE EXTENSION


需要预加载的扩展

部分扩展需要先添加到 shared_preload_libraries 并重启后才能创建:

pg-meta:
  vars:
    pg_cluster: pg-meta
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'
    pg_databases:
      - name: meta
        extensions:
          - { name: timescaledb }  # 需要预加载

如果未预加载就尝试创建,会收到错误信息。

需要预加载的常见扩展:timescaledb, citus, pg_cron, pg_net, pgaudit 等。详见 配置扩展


扩展依赖

某些扩展依赖于其他扩展,需要按顺序创建:

-- postgis_topology 依赖 postgis
CREATE EXTENSION postgis;
CREATE EXTENSION postgis_topology;

-- 或使用 CASCADE 自动安装依赖
CREATE EXTENSION postgis_topology CASCADE;

不需要创建的扩展

少数扩展不通过 SQL 接口对外服务,无需执行 CREATE EXTENSION

扩展 说明
wal2json 逻辑解码插件,直接在复制槽中使用
decoderbufs 逻辑解码插件
decoder_raw 逻辑解码插件

这些扩展安装后即可使用,例如:

-- 使用 wal2json 创建逻辑复制槽
SELECT * FROM pg_create_logical_replication_slot('test_slot', 'wal2json');

查看扩展信息

-- 查看扩展详情
\dx+ vector

-- 查看扩展包含的对象
SELECT * FROM pg_extension_config_dump('vector');

-- 查看扩展版本
SELECT extversion FROM pg_extension WHERE extname = 'vector';

8.13.8 - 更新扩展

升级 PostgreSQL 扩展版本

扩展更新涉及两个层面:软件包更新(操作系统层面)和 扩展对象更新(数据库层面)。


更新软件包

使用包管理器更新扩展的软件包:

# EL 系统
sudo yum update pgvector_18*

# Debian/Ubuntu 系统
sudo apt update && sudo apt upgrade postgresql-18-pgvector

使用 Pigsty 批量更新:

# 更新指定集群的扩展包
./pgsql.yml -l pg-meta -t pg_extension -e '{"pg_extensions":["pgvector"]}'

# 使用 pig 包管理器
pig update pgvector

更新扩展对象

软件包更新后,数据库中的扩展对象可能需要同步更新。

查看可更新的扩展

-- 查看已安装扩展及其版本
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE installed_version IS NOT NULL;

-- 查看可升级的扩展
SELECT name, installed_version, default_version
FROM pg_available_extensions
WHERE installed_version IS NOT NULL
  AND installed_version <> default_version;

执行扩展更新

-- 更新到最新版本
ALTER EXTENSION pgvector UPDATE;

-- 更新到指定版本
ALTER EXTENSION pgvector UPDATE TO '0.8.0';

查看更新路径

-- 查看扩展的可用升级路径
SELECT * FROM pg_extension_update_paths('pgvector');

注意事项

  1. 备份优先:更新扩展前建议先备份数据库,特别是涉及数据类型变更的扩展。

  2. 检查兼容性:某些扩展的大版本升级可能不兼容,需查阅扩展的升级文档。

  3. 预加载扩展:如果更新的是需要预加载的扩展(如 timescaledb),更新后可能需要重启数据库。

  4. 依赖关系:如果其他扩展依赖于被更新的扩展,需要按依赖顺序更新。

  5. 复制环境:在主从复制环境中,应先在从库测试更新,确认无误后再更新主库。


常见问题

更新失败

如果 ALTER EXTENSION UPDATE 失败,可能是因为:

  • 没有可用的升级路径
  • 扩展正在被使用
  • 权限不足
-- 查看扩展依赖
SELECT * FROM pg_depend WHERE refobjid = (SELECT oid FROM pg_extension WHERE extname = 'pgvector');

回滚更新

PostgreSQL 扩展通常不支持直接回滚。如需回滚:

  1. 从备份恢复
  2. 或者:卸载新版本扩展,安装旧版本软件包,重新创建扩展

8.13.9 - 移除扩展

卸载 PostgreSQL 扩展

移除扩展涉及两个层面:删除扩展对象(数据库层面)和 卸载软件包(操作系统层面)。


删除扩展对象

使用 DROP EXTENSION 从数据库中删除扩展:

-- 删除扩展
DROP EXTENSION pgvector;

-- 如果有依赖对象,需要级联删除
DROP EXTENSION pgvector CASCADE;

警告CASCADE 会删除所有依赖于该扩展的对象(表、函数、视图等),请谨慎使用。

查看扩展依赖

删除前建议先检查依赖关系:

-- 查看依赖于某扩展的对象
SELECT
    classid::regclass,
    objid,
    deptype
FROM pg_depend
WHERE refobjid = (SELECT oid FROM pg_extension WHERE extname = 'pgvector');

-- 查看使用了扩展类型的表
SELECT
    c.relname AS table_name,
    a.attname AS column_name,
    t.typname AS type_name
FROM pg_attribute a
JOIN pg_class c ON a.attrelid = c.oid
JOIN pg_type t ON a.atttypid = t.oid
WHERE t.typname = 'vector';

移除预加载

如果扩展在 shared_preload_libraries 中,删除后需要从预加载列表移除:

# 修改 shared_preload_libraries,移除扩展
pg edit-config pg-meta --force -p shared_preload_libraries='pg_stat_statements, auto_explain'

# 重启使配置生效
pg restart pg-meta

卸载软件包

从数据库中删除扩展后,可以选择卸载软件包:

# EL 系统
sudo yum remove pgvector_18*

# Debian/Ubuntu 系统
sudo apt remove postgresql-18-pgvector

# 使用 pig 包管理器
pig remove pgvector

通常保留软件包不会有问题,仅在需要释放磁盘空间或解决冲突时才需要卸载。


注意事项

  1. 数据丢失风险:使用 CASCADE 会删除依赖对象,可能导致数据丢失。

  2. 应用兼容性:删除扩展前确保应用程序不再使用该扩展的功能。

  3. 预加载顺序:如果删除的是预加载扩展,务必同时从 shared_preload_libraries 中移除,否则数据库可能无法启动。

  4. 主从环境:在主从复制环境中,DROP EXTENSION 会自动复制到从库。


操作顺序

完整的扩展移除流程:

# 1. 检查依赖关系
psql -d mydb -c "SELECT * FROM pg_depend WHERE refobjid = (SELECT oid FROM pg_extension WHERE extname = 'pgvector');"

# 2. 删除数据库中的扩展
psql -d mydb -c "DROP EXTENSION pgvector;"

# 3. 如果是预加载扩展,从 shared_preload_libraries 移除
pg edit-config pg-meta --force -p shared_preload_libraries='pg_stat_statements, auto_explain'

# 4. 重启数据库(如果修改了预加载配置)
pg restart pg-meta

# 5. 可选:卸载软件包
sudo yum remove pgvector_18*

8.13.10 - 默认扩展

Pigsty 默认安装的 PostgreSQL 扩展

Pigsty 在初始化 PostgreSQL 集群时,会默认安装和启用一些核心扩展。


默认安装的扩展

通过 pg_packages 默认安装的扩展:

扩展 说明
pg_repack 在线处理表膨胀,重要的维护工具
wal2json 逻辑解码输出 JSON 格式变更,CDC 场景常用
pgvector 向量数据类型与索引,默认随 pgsql-main 安装

pg_extensions 的默认值为空数组 []。如需安装其他扩展,可以按需声明,例如:

扩展 说明
postgis 地理空间数据库扩展
timescaledb 时序数据库扩展
pgvector 向量数据类型与索引

默认启用的扩展

通过 pg_default_extensions 在所有数据库中默认启用的扩展:

扩展 Schema 说明
pg_stat_statements monitor SQL 语句执行统计
pgstattuple monitor 元组级统计信息
pg_buffercache monitor 缓冲区缓存检查
pageinspect monitor 页面级检查
pg_prewarm monitor 关系预热
pg_visibility monitor 可见性映射检查
pg_freespacemap monitor 空闲空间映射检查
postgres_fdw public PostgreSQL 外部数据包装器
file_fdw public 文件外部数据包装器
btree_gist public B-tree GiST 操作符类
btree_gin public B-tree GIN 操作符类
pg_trgm public 三元组匹配
intagg public 整数聚合器
intarray public 整数数组函数
pg_repack repack 在线重组表

这些扩展提供基础的监控、运维和功能增强能力。


默认预加载的扩展

通过 pg_libs 默认预加载到 shared_preload_libraries 的扩展:

扩展 说明
pg_stat_statements 跟踪所有 SQL 语句的执行统计
auto_explain 自动记录慢查询的执行计划

这两个扩展提供基本的可观测性,强烈建议保留。


自定义默认扩展

可以通过修改配置参数来自定义默认安装和启用的扩展:

all:
  vars:
    # 修改默认安装的扩展包
    pg_packages:
      - pgsql-main pgsql-common
      - pg_repack_$v* wal2json_$v*

    # 修改默认安装的扩展
    pg_extensions: [ postgis, timescaledb, pgvector ]

    # 修改默认预加载的扩展
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'

    # 修改默认启用的扩展
    pg_default_extensions:
      - { name: pg_stat_statements, schema: monitor }
      - { name: pg_repack }
      # ... 添加更多

详细的扩展使用方法请参阅:

8.13.11 - 扩展仓库

Pigsty 扩展软件仓库配置

Pigsty 提供补充扩展仓库,在 PGDG 官方仓库基础上提供额外的扩展包。


YUM 仓库

适用于 EL 8/9/10 及其兼容系统(RHEL、Rocky、AlmaLinux、CentOS 等)。

添加仓库

# 添加 GPG 公钥
curl -fsSL https://repo.pigsty.io/key | sudo tee /etc/pki/rpm-gpg/RPM-GPG-KEY-pigsty >/dev/null

# 添加仓库配置
curl -fsSL https://repo.pigsty.io/yum/repo | sudo tee /etc/yum.repos.d/pigsty.repo >/dev/null

# 刷新缓存
sudo yum makecache

中国大陆镜像

curl -fsSL https://repo.pigsty.cc/key | sudo tee /etc/pki/rpm-gpg/RPM-GPG-KEY-pigsty >/dev/null
curl -fsSL https://repo.pigsty.cc/yum/repo | sudo tee /etc/yum.repos.d/pigsty.repo >/dev/null

仓库地址


APT 仓库

适用于 Debian 12/13 和 Ubuntu 22.04/24.04/26.04 及其兼容系统。

添加仓库

# 添加 GPG 公钥
curl -fsSL https://repo.pigsty.io/key | sudo gpg --dearmor -o /etc/apt/keyrings/pigsty.gpg

# 获取发行版代号并添加仓库
distro_codename=$(lsb_release -cs)
sudo tee /etc/apt/sources.list.d/pigsty.list > /dev/null <<EOF
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.io/apt/infra generic main
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.io/apt/pgsql/${distro_codename} ${distro_codename} main
EOF

# 刷新缓存
sudo apt update

中国大陆镜像

curl -fsSL https://repo.pigsty.cc/key | sudo gpg --dearmor -o /etc/apt/keyrings/pigsty.gpg

distro_codename=$(lsb_release -cs)
sudo tee /etc/apt/sources.list.d/pigsty.list > /dev/null <<EOF
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.cc/apt/infra generic main
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.cc/apt/pgsql/${distro_codename} ${distro_codename} main
EOF

仓库地址


GPG 签名

所有软件包均使用 GPG 签名:

  • 指纹: 9592A7BC7A682E7333376E09E7935D8DB9BD8B20
  • 短 ID: B9BD8B20

仓库策略

Pigsty 仓库遵循以下原则:

  1. 补充性:只收录 PGDG 仓库中不存在的扩展
  2. 一致性:扩展进入 PGDG 仓库后,Pigsty 仓库会移除或保持一致
  3. 兼容性:支持 PostgreSQL 14-18 多个大版本
  4. 多平台:支持 x86_64 和 aarch64 架构

相关资源

8.14 - 内核分支

如何在 Pigsty 中使用其他 PostgreSQL 内核分支?例如 Citus,Babelfish,IvorySQL,PolarDB 等

在 Pigsty 中,您可以使用不同 “风味” 的 PostgreSQL 分支替换 “原生 PG 内核”,实现特殊的功能与效果。

Pigsty 支持多种 PostgreSQL 内核和兼容分支,让您能够在同一套运维体系中获得兼容性、多主复制、图查询、MPP 数仓、透明加密等不同能力。

需要注意的是,不同内核在 Pigsty 中的交付深度并不完全一致: 像 PostgreSQL、Citus、Babelfish、IvorySQL、PolarDB、AgensGraph、pgEdge 已经有较明确的模板与配置方式; 像 Cloudberry / Greenplum 则更多通过 gpsql 模式统一纳管,MPP 初始化与扩缩容仍建议使用上游工具链。

内核 关键特性 描述
PostgreSQL 原生内核,扩展齐备 原版 PostgreSQL,配备 575 扩展
Supabase 后端即服务 基于 PostgreSQL 的 BaaS,Firebase 替代方案
Citus 水平分布式扩展,多租户 通过原生扩展实现分布式 PostgreSQL
Babelfish SQL Server 兼容 SQL Server 线协议兼容(PG17/18)
IvorySQL Oracle 兼容 Oracle 语法和 PL/SQL 兼容
OpenHalo MySQL 兼容 MySQL 线协议兼容
Percona 透明数据加密 带有 pg_tde 的 Percona 发行版
DocumentDB MongoDB 迁移 DocumentDB + FerretDB,兼容 MongoDB 线协议
OrioleDB OLTP 优化 Zheap,无膨胀,S3 存储
PolarDB Aurora 风格 RAC RAC,中国国产合规
Cloudberry 开源 MPP 数仓 gpsql 模式接入的 Cloudberry 分支
AgensGraph 属性图 + Cypher 在 PostgreSQL 体系内提供图查询能力
pgEdge Spock 多主复制 面向边缘场景的分布式 PostgreSQL 发行版
PostgreSQL 分支与兼容内核

版本

内核 Debian / Ubuntu EL
PostgreSQL / Citus PostgreSQL 18.6 (Ubuntu 18.6-1.pgdg26.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0, 64-bit PostgreSQL 18.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), 64-bit
IvorySQL PostgreSQL 18.4 (IvorySQL 5.4) on x86_64-pc-linux-gnu, compiled by gcc (GCC) 9.5.0, 64-bit PostgreSQL 18.4 (IvorySQL 5.4) on x86_64-pc-linux-gnu, compiled by gcc (GCC) 9.5.0, 64-bit
Babelfish Babelfish 17.7 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0, 64-bit Babelfish 17.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), 64-bit
PolarDB PostgreSQL 17.10 (PolarDB 17.10.1.0 build accf02e2) on x86_64-linux-gnu PostgreSQL 17.10 (PolarDB 17.10.1.0 build accf02e2) on x86_64-linux-gnu
Percona PostgreSQL 18.4 - Percona Server for PostgreSQL 18.4.1 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0, 64-bit PostgreSQL 18.4 - Percona Server for PostgreSQL 18.4.1 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.3.1 20250617 (Red Hat 14.3.1-2), 64-bit
OrioleDB OrioleDB 18.4 (OrioleDB 1.8-beta16) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0, 64-bit OrioleDB 18.4 (OrioleDB 1.8-beta16) on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), 64-bit
OpenHalo openHalo 14.18 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0, 64-bit openHalo 14.18 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), 64-bit
DocumentDB PostgreSQL 18.6 (Ubuntu 18.6-1.pgdg26.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0, 64-bit PostgreSQL 18.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), 64-bit
AgensGraph PostgreSQL 17.10 (AgensGraph 2.17.0) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0, 64-bit PostgreSQL 17.10 (AgensGraph 2.17.0) on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), 64-bit
pgEdge PostgreSQL 18.4 (pgEdge 5.0.10) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0, 64-bit PostgreSQL 18.4 (pgEdge 5.0.10) on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4), 64-bit
Cloudberry PostgreSQL 14.4 (Apache Cloudberry 2.0.0-incubating build 1) on aarch64-unknown-linux-gnu, compiled by gcc (GCC) 11.5.0 20240719 (Red Hat 11.5.0-11), 64-bit

8.14.1 - PostgreSQL

带有 575 个扩展的原版 PostgreSQL 内核

PostgreSQL 是世界上最先进和最受欢迎的开源数据库。

默认安装 PostgreSQL 18,支持 PostgreSQL 14 ~ 18,并提供 575 个 PG 扩展。


快速开始

使用 pgsql 配置模板 安装 Pigsty。

./configure -c pgsql     # 使用 postgres 内核
./deploy.yml             # 部署 Pigsty 核心链路与原生 PostgreSQL

大多数 配置模板 默认使用 PostgreSQL 内核,例如:

  • meta : 默认,带有核心扩展(vector、postgis、timescale)的 postgres
  • rich:安装了所有扩展的 postgres
  • slim:仅 postgres,无监控基础设施
  • ha/full:用于 HA 演示的 4 节点沙盒
  • pgsql:最小的 postgres 内核配置示例

配置

原版 PostgreSQL 内核不需要特殊调整:

pg-meta:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-meta
    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  }
    pg_databases:
      - { name: meta, baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [ vector ]}
    pg_hba_rules:
      - { user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes' }
    pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ] # 每天凌晨 1 点进行全量备份
    pg_packages: [ pgsql-main, pgsql-common ]   # pg 内核和通用工具
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

版本选择

要使用不同的 PostgreSQL 主版本,您可以使用 -v 参数进行配置:

./configure -c pgsql            # 默认就是 postgresql 18,无需显式指定
./configure -c pgsql -v 18      # 显式指定 postgresql 18
./configure -c pgsql -v 17      # 使用 postgresql 17
./configure -c pgsql -v 16      # 使用 postgresql 16
./configure -c pgsql -v 15      # 使用 postgresql 15
./configure -c pgsql -v 14      # 使用 postgresql 14

如果 PostgreSQL 集群已经安装,您需要在安装新版本之前卸载它:

./pgsql-rm.yml -l pg-meta # 卸载 pg-meta 集群

扩展生态

Pigsty 为 PostgreSQL 提供了丰富的扩展生态,详情请参考 扩展目录

8.14.2 - Supabase

如何使用 Pigsty 自建 Supabase,一键拉起开源 Firebase 替代,后端全栈全家桶。

Supabase —— Build in a weekend, Scale to millions

Supabase 是一个开源的 Firebase 替代,对 PostgreSQL 进行了封装,并提供了认证,开箱即用的 API,边缘函数,实时订阅,对象存储,向量嵌入能力。 这是一个低代码的一站式后端平台,能让你几乎告别大部分后端开发的工作,只需要懂数据库设计与前端即可快速出活!

Supabase 的口号是:“花个周末写写,随便扩容至百万”。诚然,在小微规模(4c8g)内的 Supabase 极有性价比,堪称赛博菩萨。 —— 但当你真的增长到百万用户时 —— 确实应该认真考虑托管自建 Supabase 了 —— 无论是出于功能,性能,还是成本上的考虑。

Pigsty 为您提供完整的 Supabase 一键自建方案。自建的 Supabase 可以享受完整的 PostgreSQL 监控,IaC,PITR 与高可用, 而且相比 Supabase 云服务,提供了多达 575 个开箱即用的 PostgreSQL 扩展,并能够更充分地利用现代硬件的性能与成本优势。

完整自建教程,请参考:《Supabase自建手册

Supabase

快速上手

Pigsty 默认提供的 supabase.yml 配置模板定义了一套单节点 Supabase。

首先,使用 Pigsty 标准安装流程 安装 Supabase 所需的 Silo 与 PostgreSQL 实例:

 curl -fsSL https://repo.pigsty.io/get | bash
./bootstrap          # 环境检查,安装依赖
./configure -c supabase  # 重要:请在配置文件中修改密码等关键信息!
./deploy.yml         # 安装 Pigsty,拉起 PGSQL 与 MINIO!

请在部署 Supabase 前,根据您的实际情况,修改 pigsty.yml 配置文件中 关于 Supabase 的参数(主要是密码!)

然后使用当前仓库根目录的 docker.ymlapp.yml 完成剩余工作,安装容器运行时并拉起 conf/supabase.yml 中定义的 Supabase 应用:

./docker.yml       # 安装 Docker 模块
./app.yml          # 拉起 Supabase 无状态部分!

中国区域用户注意,请您配置合适的 Docker 镜像站点或代理服务器绕过 GFW 以拉取 DockerHub 镜像。 对于 专业订阅,我们提供在没有互联网访问的情况下,离线安装 Pigsty 与 Supabase 的能力。

Pigsty 默认通过管理节点/INFRA 节点上的 Nginx 对外暴露 Web 服务,您可以在本地添加 supa.pigsty 的 DNS 解析指向该节点, 然后通过浏览器访问 https://supa.pigsty 即可进入 Supabase Studio 管理界面。

默认用户名与密码:supabase / pigsty

demo/supabase.cast

配置细节

./configure -c supabase 会生成 ~/pigsty/pigsty.yml。在执行 ./deploy.yml 之前,请至少检查并修改其中的密码、密钥、域名等敏感配置。

更完整的配置说明请参阅:《Supabase自建手册》。

8.14.3 - Citus

使用 Pigsty 部署原生高可用的 Citus 水平分片集群,将 PostgreSQL 无缝伸缩到多套分片并加速 OLTP/OLAP 查询。

Pigsty 原生支持 Citus。这是一个基于原生 PostgreSQL 内核的分布式水平扩展插件。

Citus

安装

Citus 是一个 PostgreSQL 扩展插件,可以按照标准插件安装的流程,在原生 PostgreSQL 集群上加装启用。

./pgsql.yml -t pg_extension -e '{"pg_extensions":["citus"]}'

配置

要定义一个 citus 集群,您需要指定以下参数:

  • pg_mode 必须设置为 citus,而不是默认的 pgsql
  • 在每个分片集群上都必须定义分片名 pg_shard 和分片号 pg_group
  • 必须定义 pg_primary_db 来指定由 Patroni 管理的 Citus 数据库。
  • 如果您想使用 pg_dbsupostgres 而不是默认的 pg_admin_username 来执行管理命令,那么 pg_dbsu_password 必须设置为非空的纯文本密码

此外,还需要额外的 hba 规则,允许从本地和其他数据节点进行 SSL 访问。

您可以将每个 Citus 集群分别定义为独立的分组,像标准的 PostgreSQL 集群一样;当前完整模板见 conf/ha/citus.yml

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 }
        10.10.10.14: { pg_seq: 2, pg_role: replica }
      vars: { pg_cluster: pg-citus3 , pg_group: 3 }
  vars:                               # 所有 Citus 集群的全局参数
    pg_mode: citus                    # pgsql 集群模式需要设置为: citus
    pg_shard: pg-citus                # citus 水平分片名称: pg-citus
    pg_primary_db: meta               # citus 数据库名称:meta
    pg_dbsu_password: DBUser.Postgres # 如果使用 dbsu ,那么需要为其配置一个密码
    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'  }

您也可以在一个分组内指定所有 Citus 集群成员的身份参数,如 conf/ha/citus.yml 所示:

#==========================================================#
# pg-citus: 10 node citus cluster (5 x primary-replica pair)
#==========================================================#
pg-citus: # citus group
  hosts:
    10.10.10.50: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.60/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.51: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.60/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.52: { pg_group: 1, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.61/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.53: { pg_group: 1, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.61/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.54: { pg_group: 2, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.62/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.55: { pg_group: 2, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.62/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.56: { pg_group: 3, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.63/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.57: { pg_group: 3, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.63/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.58: { pg_group: 4, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.64/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.59: { pg_group: 4, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.64/24 ,pg_seq: 1, pg_role: replica }
  vars:
    pg_mode: citus                    # pgsql cluster mode: citus
    pg_shard: pg-citus                # citus shard name: pg-citus
    pg_primary_db: test               # primary database used by citus
    pg_dbsu_password: DBUser.Postgres # all dbsu password access for citus cluster
    pg_vip_enabled: true
    pg_vip_interface: auto
    pg_extensions: [ 'citus postgis timescaledb pgvector' ]
    pg_libs: 'citus, timescaledb, pg_stat_statements, auto_explain' # citus will be added by patroni automatically
    pg_users: [ { name: test ,password: test ,pgbouncer: true ,roles: [ dbrole_admin ] } ]
    pg_databases: [ { name: test ,owner: test ,extensions: [ { name: citus }, { name: postgis } ] } ]
    pg_hba_rules:
      - { user: 'all' ,db: all  ,addr: 10.10.10.0/24 ,auth: trust ,title: 'trust citus cluster members'        }
      - { 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'  }

使用

您可以像访问普通集群一样,访问任意节点:

pgbench -i postgres://test:test@pg-citus0/test
pgbench -nv -P1 -T1000 -c 2 postgres://test:test@pg-citus0/test

默认情况下,您对某一个 Shard 进行的变更,都只发生在这套集群上,而不会同步到其他 Shard。

如果你希望将写入分布到所有 Shard,可以使用 Citus 提供的 API 函数,将表标记为:

  • 水平分片表(自动分区,需要指定分区键)
  • 引用表(全量复制:不需要指定分区键):

从 Citus 11.2 开始,任何 Citus 数据库节点都可以扮演协调者的角色,即,任意一个主节点都可以写入:

psql -h pg-citus0 -d test -c "SELECT create_distributed_table('pgbench_accounts', 'aid'); SELECT truncate_local_data_after_distributing_table('public.pgbench_accounts');"
psql -h pg-citus0 -d test -c "SELECT create_reference_table('pgbench_branches')         ; SELECT truncate_local_data_after_distributing_table('public.pgbench_branches');"
psql -h pg-citus0 -d test -c "SELECT create_reference_table('pgbench_history')          ; SELECT truncate_local_data_after_distributing_table('public.pgbench_history');"
psql -h pg-citus0 -d test -c "SELECT create_reference_table('pgbench_tellers')          ; SELECT truncate_local_data_after_distributing_table('public.pgbench_tellers');"

将表分布出去后,你可以在其他节点上也访问到:

psql -h pg-citus1 -d test -c '\dt+'

例如,全表扫描可以发现执行计划已经变为分布式计划

vagrant@meta-1:~$ psql -h pg-citus3 -d test -c 'explain select * from pgbench_accounts'
                                               QUERY PLAN
---------------------------------------------------------------------------------------------------------
 Custom Scan (Citus Adaptive)  (cost=0.00..0.00 rows=100000 width=352)
   Task Count: 32
   Tasks Shown: One of 32
   ->  Task
         Node: host=10.10.10.52 port=5432 dbname=test
         ->  Seq Scan on pgbench_accounts_102008 pgbench_accounts  (cost=0.00..81.66 rows=3066 width=97)
(6 rows)

你可以从几个不同的主节点发起写入:

pgbench -nv -P1 -T1000 -c 2 postgres://test:test@pg-citus1/test
pgbench -nv -P1 -T1000 -c 2 postgres://test:test@pg-citus2/test
pgbench -nv -P1 -T1000 -c 2 postgres://test:test@pg-citus3/test
pgbench -nv -P1 -T1000 -c 2 postgres://test:test@pg-citus4/test

当某个节点出现故障时,Patroni 提供的原生高可用支持会将备用节点提升并自动顶上。

test=# select * from  pg_dist_node;
 nodeid | groupid |  nodename   | nodeport | noderack | hasmetadata | isactive | noderole | nodecluster | metadatasynced | shouldhaveshards
--------+---------+-------------+----------+----------+-------------+----------+----------+-------------+----------------+------------------
      1 |       0 | 10.10.10.51 |     5432 | default  | t           | t        | primary  | default     | t              | f
      2 |       2 | 10.10.10.54 |     5432 | default  | t           | t        | primary  | default     | t              | t
      5 |       1 | 10.10.10.52 |     5432 | default  | t           | t        | primary  | default     | t              | t
      3 |       4 | 10.10.10.58 |     5432 | default  | t           | t        | primary  | default     | t              | t
      4 |       3 | 10.10.10.56 |     5432 | default  | t           | t        | primary  | default     | t              | t

8.14.4 - Babelfish

在 Pigsty 中使用 Babelfish(PG17/18)提供 SQL Server 协议/T-SQL 兼容能力

Babelfish 是一个提供 MS SQL Server 线缆协议兼容性的内核分支 + 扩展,由 AWS 开源。


概览

Pigsty 允许您使用 mssql 模式部署 Babelfish 内核,在 PostgreSQL 上提供:

  • SQL Server 线缆协议兼容(TDS 协议,1433 端口)
  • T-SQL 语法兼容
  • 与 Pigsty 现有能力(高可用、备份、监控、IaC)统一集成

在 Pigsty v4 中,Babelfish 支持 PostgreSQL 17/18,默认模板使用 pg_version: 17,并已经纳入 Pigsty 标准交付链路。支持所有 Linux 平台。


快速开始

使用 Pigsty 内置模板:

./configure -c mssql [-v 17/18]
./deploy.yml

部署完成后可直接使用 SQL Server 客户端连接:

sqlcmd -S <ip>,1433 -U dbuser_mssql -P DBUser.MSSQL -d mssql

关键配置

mssql 模板中的核心参数如下:

pg_mode: mssql
pg_version: 17  # optional: 18
pg_packages: [ babelfish, pgsql-common, sqlcmd ]
pg_libs: 'babelfishpg_tds, pg_stat_statements, auto_explain'

pg_databases:
  - name: mssql
    baseline: mssql.sql
    extensions:
      - { name: uuid-ossp }
      - { name: babelfishpg_common }
      - { name: babelfishpg_tsql }
      - { name: babelfishpg_tds }
      - { name: babelfishpg_money }
      - { name: pg_hint_plan }
      - { name: system_stats }
      - { name: tds_fdw }
    parameters: { 'babelfishpg_tsql.migration_mode': 'multi-db' }

pg_hba_rules:
  - { user: dbuser_mssql, db: mssql, addr: intra, auth: md5, order: 525 }

pg_default_services:
  - { name: primary, port: 5433, dest: 1433 }
  - { name: replica, port: 5434, dest: 1433 }

连接与端口

Babelfish 集群会同时提供两类访问:

  • PostgreSQL 协议:5432
  • SQL Server 协议(TDS):1433

通过 Pigsty 服务抽象,还可使用:

  • 5433 固定路由到主库 1433
  • 5434 路由到可读节点 1433
# 主库写入
sqlcmd -S <任意节点IP>,5433 -U dbuser_mssql -P DBUser.MSSQL

# 读库查询
sqlcmd -S <任意节点IP>,5434 -U dbuser_mssql -P DBUser.MSSQL

注意事项

  • Babelfish 认证规则需使用 md5,而不是默认 scram-sha-256
  • 默认迁移模式为 multi-db,如需 single-db 可修改 babelfishpg_tsql.migration_mode
  • 并非所有原生 PostgreSQL 扩展都可直接在 Babelfish 内核使用;请以包可用性与兼容性测试为准。
  • 生产环境请收紧 HBA 与网络暴露策略,不要沿用演示级开放配置。

相关文档


可用扩展

Babelfish 内核共有 55 个可用扩展,去除 PG Contrib 自带扩展之后,还有以下额外扩展:

扩展名 版本号 说明
babelfishpg_common 5.4.0 Transact SQL Datatype Support
babelfishpg_money 1.1.0 babelfishpg_money
babelfishpg_tds 1.0.0 TDS protocol extension
babelfishpg_tsql 5.4.0 Transact SQL compatibility

8.14.5 - IvorySQL

使用瀚高开源的 IvorySQL 内核,基于 PostgreSQL 集群实现 Oracle 语法/PLSQL 兼容性。

IvorySQL 是一个开源的,旨在基于 PG 提供 “Oracle 兼容性” 的 PostgreSQL 内核分支。


概览

Pigsty PGSQL 仓库直接提供 IvorySQL 5.4 软件包,兼容 PostgreSQL 18.4,并覆盖当前支持的 EL、Debian、Ubuntu 与双架构平台。 在线安装使用 Pigsty 的 pgsql 仓库;商业版同时提供对应平台的离线交付方案。

IvorySQL

当前 Pigsty 的 ivorysql 包别名指向 IvorySQL 5,兼容 PostgreSQL 18。不同发行版的真实包名由 roles/node_id/vars/ 中的平台变量映射,例如 EL 使用 ivorysql5,Debian/Ubuntu 使用 ivorysql-5

最后一个支持 EL7 的 IvorySQL 版本为 3.3,对应 PostgreSQL 16.3;最后一个基于 PostgreSQL 17 的版本为 IvorySQL 4.4


安装

使用 Pigsty 内置的 ivory 配置模板安装:

./configure -c ivory
./deploy.yml

配置

以下参数需要针对 IvorySQL 数据库集群进行配置:

#----------------------------------#
# Ivory SQL Configuration
#----------------------------------#
node_repo_modules: node,infra,pgsql       # use Pigsty node/infra/pgsql repos
pg_mode: ivory                    # IvorySQL Oracle Compatible Mode
pg_packages: [ ivorysql, pgsql-common ]
pg_libs: 'liboracle_parser, pg_stat_statements, auto_explain'
pg_extensions: [ ]                # do not install any vanilla postgresql extensions

使用 Oracle 兼容性模式时,需要动态加载 liboracle_parser 扩展插件。


客户端访问

IvorySQL 5 等效于 PostgreSQL 18,任何兼容 PostgreSQL 线缆协议的客户端工具都可以访问 IvorySQL 集群。


可用扩展

IvorySQL 内核共有 95 个可用扩展,去除 PG Contrib 自带扩展之后,还有以下额外扩展:

扩展名 版本号 说明
address_standardizer 3.5.4 Used to parse an address into constituent elements. Generally used to support geocoding address normalization step.
address_standardizer_data_us 3.5.4 Address Standardizer US dataset example
age 1.7.0 AGE database extension
ddlx 0.31 DDL eXtractor functions
gb18030_2022 1.0 support gb18030 2022 with extension
http 1.7 HTTP client for PostgreSQL, allows web page retrieval inside the database.
ivorysql_ora 1.0 Oracle Compatible extenison on Postgres Database
ora_btree_gin 1.0 support for indexing oracle datatypes in GIN
ora_btree_gist 1.0 support for oracle indexing common datatypes in GiST
pg_bigm 1.2 text similarity measurement and index searching based on bigrams
pg_cron 1.6 Job scheduler for PostgreSQL
pg_curl 2.4 PostgreSQL cURL allows most curl actions, including data transfer with URL syntax via HTTP, HTTPS, FTP, FTPS, GOPHER, TFTP, SCP, SFTP, SMB, TELNET, DICT, LDAP, LDAPS, FILE, IMAP, SMTP, POP3, RTSP and RTMP
pg_get_functiondef 1.0 Get function’s definition
pg_hint_plan 1.8.0 optimizer hints for PostgreSQL
pg_jieba 1.1.1 a parser for full-text search of Chinese
pg_partman 5.3.1 Extension to manage partitioned tables by time or ID
pg_show_plans 2.1 show query plans of all currently running SQL statements
pg_stat_monitor 2.3 The pg_stat_monitor is a PostgreSQL Query Performance Monitoring tool, based on PostgreSQL contrib module pg_stat_statements. pg_stat_monitor provides aggregated statistics, client information, plan details including plan, and histogram information.
pg_textsearch 0.1.0 Full-text search with BM25 ranking
pgagent 4.2 A PostgreSQL job scheduler
pgaudit 18.0 provides auditing functionality
pgroonga 4.0.4 Super fast and all languages supported full text search index based on Groonga
pgroonga_database 4.0.4 PGroonga database management module
pgrouting 3.8.0 pgRouting Extension
plisql 1.0 PL/iSQL procedural language
plpgsql_check 2.8 extended check for plpgsql functions
postgis 3.5.4 PostGIS geometry and geography spatial types and functions
postgis_raster 3.5.4 PostGIS raster types and functions
postgis_sfcgal 3.5.4 PostGIS SFCGAL functions
postgis_tiger_geocoder 3.5.4 PostGIS tiger geocoder and reverse geocoder
postgis_topology 3.5.4 PostGIS topology spatial types and functions
redis_fdw 1.0 Foreign data wrapper for querying a Redis server
system_stats 3.0 EnterpriseDB system statistics for PostgreSQL
vector 0.8.1 vector data type and ivfflat and hnsw access methods
zhparser 2.3 a parser for full-text search of Chinese

请注意,Pigsty 不对使用 IvorySQL 内核承担任何质保责任,使用此内核遇到的任何问题与需求请联系原厂解决。

8.14.6 - PolarDB PG

使用阿里云开源的 PolarDB for PostgreSQL 内核提供国产信创资质支持,与类似 Oracle RAC 的使用体验。

概览

Pigsty 允许使用 PolarDB 创建带有 “国产化信创资质” 的 PostgreSQL 集群!

PolarDB for PostgreSQL 当前以 PostgreSQL 17 为基线,Pigsty 中的 polar 模板、默认路径与扩展说明也已经同步到 PG17。任何兼容 PostgreSQL 线缆协议的客户端工具都可以访问 PolarDB 集群。

Pigsty 的 PGSQL 仓库中提供了 PolarDB PG 开源版安装包,但不会在 Pigsty 安装时下载到本地软件仓库。

PolarDB for PostgreSQL

安装

使用 Pigsty 内置模板:

./configure -c polar
./deploy.yml

变更摘要

从 Pigsty v4.4 开始,PolarDB PG 内核将直接使用 pigsty 构建打包的版本,主要变化如下:

项目 旧文档 / 旧默认值 当前值
内核基线 PostgreSQL 15 PostgreSQL 17
默认 PolarDB 路径 /u01/polardb_pg /usr/polar-17
支持架构 x86_64 x86_64, aarch64
可用扩展数 旧文档正文写为 61 pg_available_extensions 查询结果为 93,过滤 contrib 后为 34
复制用户要求 replicator 需要 SUPERUSER 保持不变

配置

以下参数需要针对 PolarDB 数据库集群进行特殊配置:

#----------------------------------#
# PGSQL & PolarDB
#----------------------------------#
pg_version: 17
pg_mode: polar
pg_packages: [ polardb, pgsql-common ]
pg_exporter_exclude_database: 'template0,template1,postgres,polardb_admin'
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   ,superuser: true  ,replication: true ,roles: [pg_monitor, dbrole_readonly] ,comment: system replicator } # <- superuser is required for replication
  - { 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 }

默认 polar 内核安装目录已调整为 /usr/polar-17。这里特别注意,PolarDB PG 要求 replicator 复制用户为 SUPERUSER,与原生 PG 不同。


扩展列表

PolarDB PG 内核共有 93 个可用扩展,去除 PG Contrib 自带扩展之后,还有以下额外扩展:

扩展名 版本号 说明
hll 2.18 type for storing hyperloglog data
ip4r 2.4
log_fdw 1.4 foreign-data wrapper for Postgres log file access
pase 0.0.1 ant ai similarity search
pg_bigm 1.2 text similarity measurement and index searching based on bigrams
pg_cron 1.5 Job scheduler for PostgreSQL
pg_cron_preload 1.0 polardb pg extend catalog
pg_hint_plan 1.7.0 optimizer hints for PostgreSQL
pg_jieba 1.1.0 a parser for full-text search of Chinese
pg_partman 5.2.4 Extension to manage partitioned tables by time or ID
pg_profile 4.10 PostgreSQL load profile repository and report builder
pg_repack 1.5.1-1 Reorganize tables in PostgreSQL databases with minimal locks
pg_similarity 1.0 support similarity queries
pg_squeeze 1.9 A tool to remove unused space from a relation.
pg_stat_kcache 2.3.0 Kernel statistics gathering
pgaudit 17.1 provides auditing functionality
pgtap 1.3.3 Unit testing for PostgreSQL
pldbgapi 1.1 server-side support for debugging PL/pgSQL functions
polar_advisor 1.1 polar_advisor
polar_feature_utils 1.0 PolarDB feature utilization
polar_io_stat 1.0 polar io stat in multi dimension
polar_monitor 1.3 monitor functions for PolarDB
polar_monitor_preload 1.0 examine the polardb information
polar_parameter_manager 1.2 Extension to select parameters for manger.
polar_proxy_utils 1.0 Extension to provide operations about proxy.
polar_resource_manager 1.0 a background process that forcibly frees user session process memory
polar_smgrperf 1.0 smgr perf test extension
polar_tde_utils 1.0 Internal extension for TDE
polar_vfs 1.0 polar virtual file system for different storage
polar_worker 1.1 polar_worker
prefix 1.2.0 Prefix Range module for PostgreSQL
roaringbitmap 0.5 support for Roaring Bitmaps
sequential_uuids 1.0.3 generator of sequential UUIDs
varbitx 1.1 varbit functions pack

8.14.7 - PolarDB Oracle

使用阿里云商业版本的 PolarDB for Oracle 内核(闭源,PG14,仅在特殊企业版定制中可用)

Pigsty 允许使用 PolarDB 创建带有 “国产化信创资质” 的 PolarDB for Oracle 集群!

根据 【安全可靠测评结果公告(2023年第1号)】,附表三、集中式数据库。PolarDB v2.0 属于自主可控,安全可靠的国产信创数据库。

PolarDB for Oracle 是基于 PolarDB for PostgreSQL 进行二次开发的 Oracle 兼容版本,两者共用同一套内核,通过 --compatibility-mode 参数进行区分。

我们与阿里云内核团队合作,提供基于 PolarDB v2.0 内核与 Pigsty 的完整数据库解决方案,请联系销售咨询,或在阿里云市场自行采购。

PolarDB for Oracle 内核目前仅在 EL7 (CentOS 7) 系统中可用。

PolarDB for Oracle

扩展

目前 PolarDB 2.0 (Oracle 兼容) 内核自带了以下 188 个扩展插件:

name default_version comment
cube 1.5 data type for multidimensional cubes
ip4r 2.4 NULL
adminpack 2.1 administrative functions for PostgreSQL
dict_xsyn 1.0 text search dictionary template for extended synonym processing
amcheck 1.4 functions for verifying relation integrity
autoinc 1.0 functions for autoincrementing fields
hstore 1.8 data type for storing sets of (key, value) pairs
bloom 1.0 bloom access method - signature file based index
earthdistance 1.1 calculate great-circle distances on the surface of the Earth
hstore_plperl 1.0 transform between hstore and plperl
bool_plperl 1.0 transform between bool and plperl
file_fdw 1.0 foreign-data wrapper for flat file access
bool_plperlu 1.0 transform between bool and plperlu
fuzzystrmatch 1.1 determine similarities and distance between strings
hstore_plperlu 1.0 transform between hstore and plperlu
btree_gin 1.3 support for indexing common datatypes in GIN
hstore_plpython2u 1.0 transform between hstore and plpython2u
btree_gist 1.6 support for indexing common datatypes in GiST
hll 2.17 type for storing hyperloglog data
hstore_plpython3u 1.0 transform between hstore and plpython3u
citext 1.6 data type for case-insensitive character strings
hstore_plpythonu 1.0 transform between hstore and plpythonu
hypopg 1.3.1 Hypothetical indexes for PostgreSQL
insert_username 1.0 functions for tracking who changed a table
dblink 1.2 connect to other PostgreSQL databases from within a database
decoderbufs 0.1.0 Logical decoding plugin that delivers WAL stream changes using a Protocol Buffer format
intagg 1.1 integer aggregator and enumerator (obsolete)
dict_int 1.0 text search dictionary template for integers
intarray 1.5 functions, operators, and index support for 1-D arrays of integers
isn 1.2 data types for international product numbering standards
jsonb_plperl 1.0 transform between jsonb and plperl
jsonb_plperlu 1.0 transform between jsonb and plperlu
jsonb_plpython2u 1.0 transform between jsonb and plpython2u
jsonb_plpython3u 1.0 transform between jsonb and plpython3u
jsonb_plpythonu 1.0 transform between jsonb and plpythonu
lo 1.1 Large Object maintenance
log_fdw 1.0 foreign-data wrapper for csvlog
ltree 1.2 data type for hierarchical tree-like structures
ltree_plpython2u 1.0 transform between ltree and plpython2u
ltree_plpython3u 1.0 transform between ltree and plpython3u
ltree_plpythonu 1.0 transform between ltree and plpythonu
moddatetime 1.0 functions for tracking last modification time
old_snapshot 1.0 utilities in support of old_snapshot_threshold
oracle_fdw 1.2 foreign data wrapper for Oracle access
oss_fdw 1.1 foreign-data wrapper for OSS access
pageinspect 2.1 inspect the contents of database pages at a low level
pase 0.0.1 ant ai similarity search
pg_bigm 1.2 text similarity measurement and index searching based on bigrams
pg_freespacemap 1.2 examine the free space map (FSM)
pg_hint_plan 1.4 controls execution plan with hinting phrases in comment of special form
pg_buffercache 1.5 examine the shared buffer cache
pg_prewarm 1.2 prewarm relation data
pg_repack 1.4.8-1 Reorganize tables in PostgreSQL databases with minimal locks
pg_sphere 1.0 spherical objects with useful functions, operators and index support
pg_cron 1.5 Job scheduler for PostgreSQL
pg_jieba 1.1.0 a parser for full-text search of Chinese
pg_stat_kcache 2.2.1 Kernel statistics gathering
pg_stat_statements 1.9 track planning and execution statistics of all SQL statements executed
pg_surgery 1.0 extension to perform surgery on a damaged relation
pg_trgm 1.6 text similarity measurement and index searching based on trigrams
pg_visibility 1.2 examine the visibility map (VM) and page-level visibility info
pg_wait_sampling 1.1 sampling based statistics of wait events
pgaudit 1.6.2 provides auditing functionality
pgcrypto 1.3 cryptographic functions
pgrowlocks 1.2 show row-level locking information
pgstattuple 1.5 show tuple-level statistics
pgtap 1.2.0 Unit testing for PostgreSQL
pldbgapi 1.1 server-side support for debugging PL/pgSQL functions
plperl 1.0 PL/Perl procedural language
plperlu 1.0 PL/PerlU untrusted procedural language
plpgsql 1.0 PL/pgSQL procedural language
plpython2u 1.0 PL/Python2U untrusted procedural language
plpythonu 1.0 PL/PythonU untrusted procedural language
plsql 1.0 Oracle compatible PL/SQL procedural language
pltcl 1.0 PL/Tcl procedural language
pltclu 1.0 PL/TclU untrusted procedural language
polar_bfile 1.0 The BFILE data type enables access to binary file LOBs that are stored in file systems outside Database
polar_bpe 1.0 polar_bpe
polar_builtin_cast 1.1 Internal extension for builtin casts
polar_builtin_funcs 2.0 implement polar builtin functions
polar_builtin_type 1.5 polar_builtin_type for PolarDB
polar_builtin_view 1.5 polar_builtin_view
polar_catalog 1.2 polardb pg extend catalog
polar_channel 1.0 polar_channel
polar_constraint 1.0 polar_constraint
polar_csn 1.0 polar_csn
polar_dba_views 1.0 polar_dba_views
polar_dbms_alert 1.2 implement polar_dbms_alert - supports asynchronous notification of database events.
polar_dbms_application_info 1.0 implement polar_dbms_application_info - record names of executing modules or transactions in the database.
polar_dbms_pipe 1.1 implements polar_dbms_pipe - package lets two or more sessions in the same instance communicate.
polar_dbms_aq 1.2 implement dbms_aq - provides an interface to Advanced Queuing.
polar_dbms_lob 1.3 implement dbms_lob - provides subprograms to operate on BLOBs, CLOBs, and NCLOBs.
polar_dbms_output 1.2 implement polar_dbms_output - enables you to send messages from stored procedures.
polar_dbms_lock 1.0 implement polar_dbms_lock - provides an interface to Oracle Lock Management services.
polar_dbms_aqadm 1.3 polar_dbms_aqadm - procedures to manage Advanced Queuing configuration and administration information.
polar_dbms_assert 1.0 implement polar_dbms_assert - provide an interface to validate properties of the input value.
polar_dbms_metadata 1.0 implement polar_dbms_metadata - provides a way for you to retrieve metadata from the database dictionary.
polar_dbms_random 1.0 implement polar_dbms_random - a built-in random number generator, not intended for cryptography
polar_dbms_crypto 1.1 implement dbms_crypto - provides an interface to encrypt and decrypt stored data.
polar_dbms_redact 1.0 implement polar_dbms_redact - provides an interface to mask data from queries by an application.
polar_dbms_debug 1.1 server-side support for debugging PL/SQL functions
polar_dbms_job 1.0 polar_dbms_job
polar_dbms_mview 1.1 implement polar_dbms_mview - enables to refresh materialized views.
polar_dbms_job_preload 1.0 polar_dbms_job_preload
polar_dbms_obfuscation_toolkit 1.1 implement polar_dbms_obfuscation_toolkit - enables an application to get data md5.
polar_dbms_rls 1.1 implement polar_dbms_rls - a fine-grained access control administrative built-in package
polar_multi_toast_utils 1.0 polar_multi_toast_utils
polar_dbms_session 1.2 implement polar_dbms_session - support to set preferences and security levels.
polar_odciconst 1.0 implement ODCIConst - Provide some built-in constants in Oracle.
polar_dbms_sql 1.2 implement polar_dbms_sql - provides an interface to execute dynamic SQL.
polar_osfs_toolkit 1.0 osfs library tools and functions extension
polar_dbms_stats 14.0 stabilize plans by fixing statistics
polar_monitor 1.5 monitor functions for PolarDB
polar_osfs_utils 1.0 osfs library utils extension
polar_dbms_utility 1.3 implement polar_dbms_utility - provides various utility subprograms.
polar_parameter_check 1.0 kernel extension for parameter validation
polar_dbms_xmldom 1.0 implement dbms_xmldom and dbms_xmlparser - support standard DOM interface and xml parser object
polar_parameter_manager 1.1 Extension to select parameters for manger.
polar_faults 1.0.0 simulate some database faults for end user or testing system.
polar_monitor_preload 1.1 examine the polardb information
polar_proxy_utils 1.0 Extension to provide operations about proxy.
polar_feature_utils 1.2 PolarDB feature utilization
polar_global_awr 1.0 PolarDB Global AWR Report
polar_publication 1.0 support polardb pg logical replication
polar_global_cache 1.0 polar_global_cache
polar_px 1.0 Parallel Execution extension
polar_serverless 1.0 polar serverless extension
polar_resource_manager 1.0 a background process that forcibly frees user session process memory
polar_sys_context 1.1 implement polar_sys_context - returns the value of parameter associated with the context namespace at the current instant.
polar_gpc 1.3 polar_gpc
polar_tde_utils 1.0 Internal extension for TDE
polar_gtt 1.1 polar_gtt
polar_utl_encode 1.2 implement polar_utl_encode - provides functions that encode RAW data into a standard encoded format
polar_htap 1.1 extension for PolarDB HTAP
polar_htap_db 1.0 extension for PolarDB HTAP database level operation
polar_io_stat 1.0 polar io stat in multi dimension
polar_utl_file 1.0 implement utl_file - support PL/SQL programs can read and write operating system text files
polar_ivm 1.0 polar_ivm
polar_sql_mapping 1.2 Record error sqls and mapping them to correct one
polar_stat_sql 1.0 Kernel statistics gathering, and sql plan nodes information gathering
tds_fdw 2.0.2 Foreign data wrapper for querying a TDS database (Sybase or Microsoft SQL Server)
xml2 1.1 XPath querying and XSLT
polar_upgrade_catalogs 1.1 Upgrade catalogs for old version instance
polar_utl_i18n 1.1 polar_utl_i18n
polar_utl_raw 1.0 implement utl_raw - provides SQL functions for manipulating RAW datatypes.
timescaledb 2.9.2 Enables scalable inserts and complex queries for time-series data
polar_vfs 1.0 polar virtual file system for different storage
polar_worker 1.0 polar_worker
postgres_fdw 1.1 foreign-data wrapper for remote PostgreSQL servers
refint 1.0 functions for implementing referential integrity (obsolete)
roaringbitmap 0.5 support for Roaring Bitmaps
tsm_system_time 1.0 TABLESAMPLE method which accepts time in milliseconds as a limit
vector 0.5.0 vector data type and ivfflat and hnsw access methods
rum 1.3 RUM index access method
unaccent 1.1 text search dictionary that removes accents
seg 1.4 data type for representing line segments or floating-point intervals
sequential_uuids 1.0.2 generator of sequential UUIDs
uuid-ossp 1.1 generate universally unique identifiers (UUIDs)
smlar 1.0 compute similary of any one-dimensional arrays
varbitx 1.1 varbit functions pack
sslinfo 1.2 information about SSL certificates
tablefunc 1.0 functions that manipulate whole tables, including crosstab
tcn 1.0 Triggered change notifications
zhparser 1.0 a parser for full-text search of Chinese
address_standardizer 3.3.2 Ganos PostGIS address standardizer
address_standardizer_data_us 3.3.2 Ganos PostGIS address standardizer data us
ganos_fdw 6.0 Ganos Spatial FDW extension for POLARDB
ganos_geometry 6.0 Ganos geometry lite extension for POLARDB
ganos_geometry_pyramid 6.0 Ganos Geometry Pyramid extension for POLARDB
ganos_geometry_sfcgal 6.0 Ganos geometry lite sfcgal extension for POLARDB
ganos_geomgrid 6.0 Ganos geometry grid extension for POLARDB
ganos_importer 6.0 Ganos Spatial importer extension for POLARDB
ganos_networking 6.0 Ganos networking
ganos_pointcloud 6.0 Ganos pointcloud extension For POLARDB
ganos_pointcloud_geometry 6.0 Ganos_pointcloud LIDAR data and ganos_geometry data for POLARDB
ganos_raster 6.0 Ganos raster extension for POLARDB
ganos_scene 6.0 Ganos scene extension for POLARDB
ganos_sfmesh 6.0 Ganos surface mesh extension for POLARDB
ganos_spatialref 6.0 Ganos spatial reference extension for POLARDB
ganos_trajectory 6.0 Ganos trajectory extension for POLARDB
ganos_vomesh 6.0 Ganos volumn mesh extension for POLARDB
postgis_tiger_geocoder 3.3.2 Ganos PostGIS tiger geocoder
postgis_topology 3.3.2 Ganos PostGIS topology

8.14.8 - Percona

支持 TDE 透明加密的 Percona Postgres 发行版

Percona Postgres 是一个带有 pg_tde(透明数据加密)扩展的补丁 Postgres 内核。

Pigsty 从 v4.4.0 起将 Percona PostgreSQL 打包到私有前缀 /usr/pgtde-$v,v4.5.0 延续这一布局 (PostgreSQL 18 对应 /usr/pgtde-18)。pgtde 包别名会同时安装内核包 与 contrib 包,其中包含 pg_tde、PostGIS、pgvector、wal2json、pg_repack、 pgaudit、pg_stat_monitor 等常用组件。


快速开始

使用 Pigsty 标准安装流程,配合 pgtde 配置模板。

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty;
./configure -c pgtde     # 使用 percona postgres 内核
./deploy.yml             # 部署 Pigsty 核心链路与 Percona PostgreSQL

配置

需要调整以下参数来部署 Percona 集群:

pg-meta:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary }
  vars:
    pg_mode: pgtde
    pg_cluster: pg-meta
    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  }
    pg_databases:
      - name: meta
        baseline: cmdb.sql
        comment: pigsty tde database
        schemas: [pigsty]
        extensions: [ vector, postgis, pg_tde ,pgaudit, { name: pg_stat_monitor, schema: monitor } ]
    pg_hba_rules:
      - { user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes' }
    pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ] # 每天凌晨 1 点进行全量备份

    # Percona PostgreSQL TDE 内核设置
    pg_packages: [ pgtde, pgsql-common ]
    pg_libs: 'pg_tde, pgaudit, pg_stat_statements, pg_stat_monitor, auto_explain'

pgtde 软件包由 Pigsty 的 pgsql 仓库模块提供,此模板不再依赖旧的 percona 仓库模块。


可用扩展

Percona Postgres 内核共有 73 个可用扩展,去除 PG Contrib 自带扩展之后,还有以下额外扩展:

扩展名 版本号 说明
address_standardizer 3.5.7 Used to parse an address into constituent elements. Generally used to support geocoding address normalization step.
address_standardizer_data_us 3.5.7 Address Standardizer US dataset example
pg_repack 1.5.3 Reorganize tables in PostgreSQL databases with minimal locks
pg_stat_monitor 2.3.2 The pg_stat_monitor is a PostgreSQL Query Performance Monitoring tool, based on PostgreSQL contrib module pg_stat_statements. pg_stat_monitor provides aggregated statistics, client information, plan details including plan, and histogram information.
pg_tde 2.2.1 pg_tde access method
pgaudit 18.0 provides auditing functionality
postgis 3.5.7 PostGIS geometry and geography spatial types and functions
postgis_raster 3.5.7 PostGIS raster types and functions
postgis_sfcgal 3.5.7 PostGIS SFCGAL functions
postgis_tiger_geocoder 3.5.7 PostGIS tiger geocoder and reverse geocoder
postgis_topology 3.5.7 PostGIS topology spatial types and functions
set_user 4.2.0 similar to SET ROLE but with added logging
vector 0.8.3 vector data type and ivfflat and hnsw access methods

关键特性

  • 透明数据加密:使用 pg_tde 扩展提供静态数据加密
  • PostgreSQL 18 兼容:基于 Percona PostgreSQL 18 包集
  • 企业级扩展:包含 pgaudit、pg_stat_monitor 等企业级功能
  • 完整生态:支持 pgvector、PostGIS 等流行扩展

注意:目前处于稳定阶段 - 在生产使用前请彻底评估。

8.14.9 - PostgresML

如何使用 Pigsty 部署 PostgresML,在数据库内进行机器学习、模型训练、推理、Embedding 与 RAG。

PostgresML 是一个 PostgreSQL 扩展,支持最新的大语言模型(LLM)、向量操作、经典机器学习以及传统的 Postgres 应用负载。

PostgresML (pgml) 是一个用 Rust 编写的 PostgreSQL 扩展。您可以运行独立的 Docker 镜像,但本文档不是 docker-compose 模板介绍,仅供参考。

PostgresML 官方支持 Ubuntu 22.04,但我们也为 EL 8/9 维护了 RPM 版本,如果您不需要 CUDA 和 NVIDIA 相关功能的话。

您需要在数据库节点上能够访问互联网,以便从 PyPI 下载 Python 依赖,并从 HuggingFace 下载模型。

警告

pgml 上游项目已经不再维护


配置

PostgresML 是一个用 Rust 编写的扩展。Pigsty 在 EL8/EL9 以及 Debian/Ubuntu 平台维护了 PG14-17 的预编译包。

创建新集群

PostgresML 2.10.0 可用于 PostgreSQL 14-17。下面示例使用 PG17;如果使用 PG14-16,只需把 pg_version 改为对应主版本。

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    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_hba_rules:
      - {user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes'}
    pg_version: 17
    pg_libs: 'pgml, pg_stat_statements, auto_explain'
    pg_extensions: [ pgml, pgvector, wal2json, pg_repack ]

Pigsty 会把 pgml 包别名解析为平台真实包名:EL 为 pgml_$v,Debian/Ubuntu 为 postgresql-$v-pgml。同时需要将 pgml 添加到 pg_libs 中。

在现有集群上启用

要在现有集群上启用 pgml,可以使用 Ansible 的 package 模块安装:

ansible pg-meta -m package -b -a 'name=pgml_17'
# ansible el8,el9 -m package -b -a 'name=pgml_17'              # EL 8/9
# ansible u22,u24 -m package -b -a 'name=postgresql-17-pgml'   # Debian/Ubuntu

Python 依赖

您还需要在集群节点上安装 PostgresML 的 Python 依赖。官方教程:安装指南

安装 Python 和 PIP

确保已安装 python3pipvenv

# Ubuntu 22.04 (python3.10),需要使用 apt 安装 pip 和 venv
sudo apt install -y python3 python3-pip python3-venv

对于 EL 8 / EL9 及兼容发行版,可以使用 python3.11:

# EL 8/9,可以升级默认的 pip 和 virtualenv
sudo yum install -y python3.11 python3.11-pip       # 安装最新的 python3.11
python3.11 -m pip install --upgrade pip virtualenv  # 在 EL8 / EL9 上使用 python3.11
使用 PyPI 镜像

对于中国大陆用户,建议使用清华大学 PyPI 镜像

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple    # 设置全局镜像(推荐)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package        # 单次安装时使用

安装依赖包

创建 Python 虚拟环境,并使用 piprequirements.txtrequirements-xformers.txt 安装依赖。

如果您使用的是 EL 8/9,需要将以下命令中的 python3 替换为 python3.11

su - postgres;                          # 使用数据库超级用户创建虚拟环境
mkdir -p /data/pgml; cd /data/pgml;     # 创建虚拟环境目录
python3    -m venv /data/pgml           # 创建虚拟环境目录(Ubuntu 22.04)
source /data/pgml/bin/activate          # 激活虚拟环境

# 写入 Python 依赖并使用 pip 安装
cat > /data/pgml/requirments.txt <<EOF
accelerate==0.22.0
auto-gptq==0.4.2
bitsandbytes==0.41.1
catboost==1.2
ctransformers==0.2.27
datasets==2.14.5
deepspeed==0.10.3
huggingface-hub==0.17.1
InstructorEmbedding==1.0.1
lightgbm==4.1.0
orjson==3.9.7
pandas==2.1.0
rich==13.5.2
rouge==1.0.1
sacrebleu==2.3.1
sacremoses==0.0.53
scikit-learn==1.3.0
sentencepiece==0.1.99
sentence-transformers==2.2.2
tokenizers==0.13.3
torch==2.0.1
torchaudio==2.0.2
torchvision==0.15.2
tqdm==4.66.1
transformers==4.33.1
xgboost==2.0.0
langchain==0.0.287
einops==0.6.1
pynvml==11.5.0
EOF

# 在虚拟环境中使用 pip 安装依赖
python3 -m pip install -r /data/pgml/requirments.txt
python3 -m pip install xformers==0.0.21 --no-dependencies

# 此外,有 3 个 Python 包需要使用 sudo 全局安装!
sudo python3 -m pip install xgboost lightgbm scikit-learn

启用 PostgresML

在所有集群节点上安装 pgml 扩展和 Python 依赖后,就可以在 PostgreSQL 集群上启用 pgml 了。

使用 patronictl 命令 配置集群,将 pgml 添加到 shared_preload_libraries,并在 pgml.venv 中指定您的虚拟环境目录:

shared_preload_libraries: pgml, timescaledb, pg_stat_statements, auto_explain
pgml.venv: '/data/pgml'

然后重启数据库集群,并使用 SQL 命令创建扩展:

CREATE EXTENSION vector;        -- 建议同时安装 pgvector!
CREATE EXTENSION pgml;          -- 在当前数据库中创建 PostgresML
SELECT pgml.version();          -- 打印 PostgresML 版本信息

如果一切正常,您应该会看到类似以下输出:

# create extension pgml;
INFO:  Python version: 3.11.2 (main, Oct  5 2023, 16:06:03) [GCC 8.5.0 20210514 (Red Hat 8.5.0-18)]
INFO:  Scikit-learn 1.3.0, XGBoost 2.0.0, LightGBM 4.1.0, NumPy 1.26.1
CREATE EXTENSION

# SELECT pgml.version(); -- 打印 PostgresML 版本信息
 version
---------
 2.7.8

大功告成!更多详情请参阅 PostgresML 官方文档:https://postgresml.org/docs/guides/use-cases/

8.14.10 - openHalo

MySQL 兼容的 Postgres 14 分支

OpenHalo 是一个开源的 PostgreSQL 内核,提供 MySQL 线协议兼容性。

openHalo 基于 PostgreSQL 14.18 内核版本,提供与 MySQL 5.7.32-log / 8.0 版本的线协议兼容性。Pigsty 通过 pg_mode: mysqlopenhalo 包别名交付。

Pigsty 在所有支持的 Linux 平台上为 OpenHalo 提供部署支持。


快速开始

使用 Pigsty 的 标准安装流程mysql 配置模板。

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty;
./configure -c mysql    # 使用 MySQL(openHalo)配置模板
./deploy.yml            # 安装,生产部署请先在 pigsty.yml 中修改密码

对于生产部署,请确保在运行安装剧本之前修改 pigsty.yml 配置文件中的密码参数。


配置

pg-meta:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-meta
    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: postgres, extensions: [ aux_mysql ]} # mysql 兼容数据库
      - {name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty]}
    pg_hba_rules:
      - {user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes'}
    pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ] # 每天凌晨 1 点进行全量备份

    # OpenHalo 临时设置
    pg_mode: mysql                    # HaloDB 的 MySQL 兼容模式
    pg_version: 14                    # 当前 HaloDB 兼容 PG 主版本 14
    pg_packages: [ openhalo, pgsql-common ]    # 安装 openHalo 而不是 PostgreSQL 原生内核

OpenHalo 提供了一个独有的扩展 aux_mysql,它包含了 MySQL 兼容性所需的函数和类型。请确保在 pg_databases 配置中为 postgres 数据库启用此扩展,以获得完整的 MySQL 兼容功能。


使用

访问 MySQL 时,实际连接使用的是 postgres 数据库。请注意,MySQL 中的"数据库"概念实际上对应于 PostgreSQL 中的"Schema"。 因此,use mysql 实际上使用的是 postgres 数据库内的 mysql Schema。

用于 MySQL 的用户名和密码与 PostgreSQL 中的相同。您可以使用标准的 PostgreSQL 方法管理用户和权限。

客户端访问

OpenHalo 提供 MySQL 线协议兼容性,默认监听端口 3306,允许 MySQL 客户端和驱动程序直接连接。

Pigsty 的 conf/mysql 配置默认安装 mysql 客户端工具。

您可以使用以下命令访问 MySQL:

mysql -h 127.0.0.1 -u dbuser_dba

目前,OpenHalo 官方确保 Navicat 可以正常访问此 MySQL 端口,但 Intellij IDEA 的 DataGrip 访问会导致错误。


配置

Pigsty 默认配置了 database_compat_mode 值为 mysql,启用 MySQL 兼容性模式。您可以进一步调整以下参数来调整 MySQL 兼容性设置:

mysql.listener_on = true	                    # (enable MySQL listener; change requires restart)
mysql.port = 3306                              # (second_port is for MySQL mode; change requires restart)
mysql.halo_mysql_version = '5.7.32-log'        # (change requires restart)
mysql.ci_collation = true                      # (change requires restart)
mysql.explicit_defaults_for_timestamp = false  # (change requires restart)
mysql.auto_rollback_tx_on_error = false        # (change requires restart)

修改说明

Pigsty 安装的 OpenHalo 内核基于 HaloTech-Co-Ltd/openHalo 内核进行了少量修改:

  • 将默认数据库名称从 halo0root 改回 postgres
  • 从默认版本号中删除 1.0. 前缀,恢复为 14.18(否则 Patroni 会报错)
  • 修改默认配置文件以启用 MySQL 兼容性并默认监听端口 3306

请注意,Pigsty 不为使用 OpenHalo 内核提供任何保证。使用此内核时遇到的任何问题或需求应与原始供应商联系。

警告:目前该内核处于 beta1 阶段 - 在生产使用前请自行评估风险。


可用扩展

OpenHalo 内核共有 59 个可用扩展,去除 PG Contrib 自带扩展之后,还有以下额外扩展:

扩展名 版本号 说明
aux_mysql 1.5 MySQL Supplementary Extension
hstore_plpython2u 1.0 transform between hstore and plpython2u
hstore_plpythonu 1.0 transform between hstore and plpythonu
jsonb_plpython2u 1.0 transform between jsonb and plpython2u
jsonb_plpythonu 1.0 transform between jsonb and plpythonu
ltree_plpython2u 1.0 transform between ltree and plpython2u
ltree_plpythonu 1.0 transform between ltree and plpythonu

8.14.11 - Greenplum

使用 Pigsty 部署/监控 Greenplum 集群,构建大规模并行处理(MPP)的 PostgreSQL 数据仓库集群!

Pigsty 支持部署 Greenplum 集群,及其衍生发行版 YMatrixDB,并提供了将现有 Greenplum 部署纳入 Pigsty 监控的能力。


概览

Greenplum / YMatrix 集群部署能力仅在专业版本/企业版本中提供,目前不对外开源。


安装

Pigsty 提供了 Greenplum 6 (@el7) 与 Greenplum 7 (@el8) 的安装包,开源版本用户可以自行安装配置。

# EL 7 Only (Greenplum6)
./node.yml -t node_install  -e '{"node_repo_modules":"pgsql","node_packages":["open-source-greenplum-db-6"]}'

# EL 8 Only (Greenplum7)
./node.yml -t node_install  -e '{"node_repo_modules":"pgsql","node_packages":["open-source-greenplum-db-7"]}'

配置

要定义 Greenplum 集群,需要用到 pg_mode = gpsql,并使用额外的身份参数 pg_shardgp_role

#================================================================#
#                        GPSQL Clusters                          #
#================================================================#

#----------------------------------#
# cluster: mx-mdw (gp master)
#----------------------------------#
mx-mdw:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary , nodename: mx-mdw-1 }
  vars:
    gp_role: master          # this cluster is used as greenplum master
    pg_shard: mx             # pgsql sharding name & gpsql deployment name
    pg_cluster: mx-mdw       # this master cluster name is mx-mdw
    pg_databases:
      - { name: matrixmgr , extensions: [ { name: matrixdbts } ] }
      - { name: meta }
    pg_users:
      - { name: meta , password: DBUser.Meta , pgbouncer: true }
      - { name: dbuser_monitor , password: DBUser.Monitor , roles: [ dbrole_readonly ], superuser: true }

    pgbouncer_enabled: true                # enable pgbouncer for greenplum master
    pgbouncer_exporter_enabled: false      # enable pgbouncer_exporter for greenplum master
    pg_exporter_params: 'host=127.0.0.1&sslmode=disable'  # use 127.0.0.1 as local monitor host

#----------------------------------#
# cluster: mx-sdw (gp master)
#----------------------------------#
mx-sdw:
  hosts:
    10.10.10.11:
      nodename: mx-sdw-1        # greenplum segment node
      pg_instances:             # greenplum segment instances
        6000: { pg_cluster: mx-seg1, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633 }
        6001: { pg_cluster: mx-seg2, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634 }
    10.10.10.12:
      nodename: mx-sdw-2
      pg_instances:
        6000: { pg_cluster: mx-seg2, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633  }
        6001: { pg_cluster: mx-seg3, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634  }
    10.10.10.13:
      nodename: mx-sdw-3
      pg_instances:
        6000: { pg_cluster: mx-seg3, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633 }
        6001: { pg_cluster: mx-seg1, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634 }
  vars:
    gp_role: segment               # these are nodes for gp segments
    pg_shard: mx                   # pgsql sharding name & gpsql deployment name
    pg_cluster: mx-sdw             # these segment clusters name is mx-sdw
    pg_preflight_skip: true        # skip preflight check (since pg_seq & pg_role & pg_cluster not exists)
    pg_exporter_config: pg_exporter_basic.yml                             # use basic config to avoid segment server crash
    pg_exporter_params: 'options=-c%20gp_role%3Dutility&sslmode=disable'  # use gp_role = utility to connect to segments

此外,PG Exporter 需要额外的连接参数,才能连接到 Greenplum Segment 实例上采集监控指标。

8.14.12 - OrioleDB

PostgreSQL 的下一代 OLTP 引擎

OrioleDB 是一个 PostgreSQL 存储引擎扩展,声称能够提供 4 倍 OLTP 性能,没有 xid 环绕和表膨胀问题,并具有"云原生"(数据存储在 S3)能力。

OrioleDB 当前在 Pigsty 中支持 PostgreSQL 16、17、18 三个兼容系,当前基线版本为 OrioleDB 1.8 beta16。

您可以使用 Pigsty 将 OrioleDB 作为 RDS 运行。pg_mode 仍使用 oriole 选择 /usr/oriole-$v 安装路径, orioledb 包别名会按 pg_version 解析为版本化内核包,例如 orioledb-16orioledb-17orioledb-18


快速开始

按照 Pigsty 标准安装 流程,使用 oriole 配置模板。

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty;
./configure -c oriole    # 使用 OrioleDB 配置模板
./deploy.yml             # 使用 OrioleDB 安装 Pigsty

对于生产部署,请确保在运行 install 剧本之前修改 pigsty.yml 配置中的密码参数。


配置

pg-meta:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-meta
    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: [orioledb]}
    pg_hba_rules:
      - {user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes'}
    pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ] # 每天凌晨 1 点进行全量备份

    # OrioleDB 临时设置
    pg_mode: oriole                                         # oriole 兼容模式
    pg_version: 18                                          # OrioleDB 支持 PG 16、17、18
    pg_packages: [ orioledb, pgsql-common ]                 # 安装 OrioleDB 内核
    pg_libs: 'orioledb, pg_stat_statements, auto_explain'   # 加载 OrioleDB 扩展

使用

要使用 OrioleDB,请安装 orioledb 包别名;Pigsty 会按平台与 pg_version 解析为对应的 PG16、PG17 或 PG18 内核包。

使用 pgbench 初始化类似 TPC-B 的表,包含 100 个仓库:

pgbench -is 100 meta
pgbench -nv -P1 -c10 -S -T1000 meta
pgbench -nv -P1 -c50 -S -T1000 meta
pgbench -nv -P1 -c10    -T1000 meta
pgbench -nv -P1 -c50    -T1000 meta

接下来,您可以使用 orioledb 存储引擎重建这些表并观察性能差异:

-- 创建 OrioleDB 表
CREATE TABLE pgbench_accounts_o (LIKE pgbench_accounts INCLUDING ALL) USING orioledb;
CREATE TABLE pgbench_branches_o (LIKE pgbench_branches INCLUDING ALL) USING orioledb;
CREATE TABLE pgbench_history_o (LIKE pgbench_history INCLUDING ALL) USING orioledb;
CREATE TABLE pgbench_tellers_o (LIKE pgbench_tellers INCLUDING ALL) USING orioledb;

-- 从常规表复制数据到 OrioleDB 表
INSERT INTO pgbench_accounts_o SELECT * FROM pgbench_accounts;
INSERT INTO pgbench_branches_o SELECT * FROM pgbench_branches;
INSERT INTO pgbench_history_o SELECT  * FROM pgbench_history;
INSERT INTO pgbench_tellers_o SELECT * FROM pgbench_tellers;

-- 删除原始表并重命名 OrioleDB 表
DROP TABLE pgbench_accounts, pgbench_branches, pgbench_history, pgbench_tellers;
ALTER TABLE pgbench_accounts_o RENAME TO pgbench_accounts;
ALTER TABLE pgbench_branches_o RENAME TO pgbench_branches;
ALTER TABLE pgbench_history_o RENAME TO pgbench_history;
ALTER TABLE pgbench_tellers_o RENAME TO pgbench_tellers;

关键特性

  • 无 XID 回绕:消除事务 ID 回绕维护
  • 无表膨胀:高级存储管理防止表膨胀
  • 云存储:对 S3 兼容对象存储的原生支持
  • OLTP 优化:专为事务工作负载设计
  • 改进性能:更好的空间利用率和查询性能

注意:OrioleDB 仍处于快速迭代阶段,生产使用前请按目标版本单独评估。


可用扩展

OrioleDB 内核共有 53 个可用扩展,去除 PG Contrib 自带扩展之后,还有以下额外扩展:

扩展名 版本号 说明
orioledb 1.8 OrioleDB – the next generation transactional engine

8.14.13 - Cloudberry

在 Pigsty 中使用 Cloudberry 开源 MPP 数仓内核,通过 gpsql 模式统一纳管节点、监控与配置。

Cloudberry 是一个源自 Greenplum 社区的开源 MPP 数据仓库内核,适合大规模并行分析场景。


概览

在 Pigsty 中,Cloudberry 沿用 gpsql 模式接入,与 Greenplum / MatrixDB 共享一套身份模型、监控逻辑与目录约定。

  • 内核包名:cloudberry
  • 模式标识:pg_mode: gpsql
  • 角色标识:gp_role: master | segment
  • 当前仓库版本:Cloudberry 2.1.0
  • 当前主包版本:DEB 2.1.0-2PIGSTY,RPM 2.1.0-3PIGSTY
  • 默认二进制目录:/usr/cloudberry

需要特别说明的是,Pigsty 当前对 Cloudberry 的支持重点在于:软件包交付、节点管理、监控纳管、访问控制与配置编排。 对于 MPP 集群初始化、扩容、重平衡和上游专有运维动作,仍建议使用 Cloudberry 官方工具链完成。

当前 Pigsty 仓库同时提供 DEB 与 RPM 的 cloudberrycloudberry-backupcloudberry-pxf 包。


安装

当前版本暂未提供独立的 cloudberry 一键模板。更常见的使用方式是:

  1. 将目标节点纳入 Pigsty 管理。
  2. 安装 cloudberry 内核包。
  3. 通过 gpsql 模式描述 coordinator / segment 拓扑。
  4. 使用 Pigsty 统一接入监控、账号、访问控制与备份体系。

如果只是为节点安装内核包,可直接执行:

./node.yml -t node_repo    -e '{"node_repo_modules":"local,node,pgsql"}'
./node.yml -t node_install -e '{"node_packages":["cloudberry"]}'

如果是已有 Cloudberry 集群纳管,建议先保留原有初始化方式,再逐步补齐 Pigsty inventory 与监控配置。


配置

Cloudberry 使用 gpsql 模式,而不是单独的 cloudberry 模式。与原生 PostgreSQL 相比,至少需要额外关注 pg_shardgp_role 两个身份参数;如需显式标注分片组,也可以补充 pg_group

下面是一个最小可读的拓扑示例:

all:
  children:
    cb-mdw:
      hosts:
        10.10.10.10: { pg_seq: 1, pg_role: primary }
      vars:
        pg_cluster: cb-mdw
        pg_mode: gpsql
        pg_shard: cb
        gp_role: master
        pg_packages: [ cloudberry, pgsql-common ]

    cb-sdw:
      hosts:
        10.10.10.11:
          nodename: cb-sdw-1
          pg_instances:
            6000: { pg_cluster: cb-seg1, pg_seq: 1, pg_role: primary, pg_exporter_port: 9633 }
        10.10.10.12:
          nodename: cb-sdw-2
          pg_instances:
            6000: { pg_cluster: cb-seg2, pg_seq: 1, pg_role: primary, pg_exporter_port: 9633 }
      vars:
        pg_cluster: cb-sdw
        pg_mode: gpsql
        pg_shard: cb
        gp_role: segment
        pg_preflight_skip: true
        pg_packages: [ cloudberry, pgsql-common ]
        pg_exporter_config: pg_exporter_basic.yml
        pg_exporter_params: 'options=-c%20gp_role%3Dutility&sslmode=disable'

其中有两点最容易忽略:

  • gp_role: master 用于 coordinator / master 节点,业务访问通常落在这里。
  • gp_role: segment 节点采集监控时,通常需要让 pg_exporterutility 模式连接。

客户端访问

对业务侧来说,Cloudberry 仍然暴露 PostgreSQL 线缆协议,绝大多数兼容 PostgreSQL 的客户端、驱动与 BI 工具都可以接入。

但需要注意:

  • 应用与分析查询应连接到 master / coordinator,而不是直接访问 segment 节点。
  • segment 节点更适合承载数据与计算分片,以及被 Pigsty 纳入监控采集。
  • 如果需要统一接入地址,可以继续使用 Pigsty 的 HAProxy / PgBouncer / DNS 服务抽象。

扩展与生态

Cloudberry 虽然源自 PostgreSQL 生态,但它不是“原生 PostgreSQL + 若干扩展”那么简单。 对于 Pigsty 主仓库中现成的扩展包,需要分两类看待:

  • 纯 SQL 或与内核 ABI 耦合较弱的对象,通常更容易适配。
  • 依赖 PGXS / 内核 C ABI 的扩展,往往需要针对 Cloudberry 的版本和编译链重新验证甚至重编译。

如果你的业务依赖 postgis、向量、FDW、审计或自定义 C 扩展,请先在目标 Cloudberry 版本上单独做兼容性验证,不要直接照搬原生 PostgreSQL 的扩展清单。


注意事项

  • Cloudberry 当前没有单独的 Pigsty 配置模板,使用时应以 gpsql 模式手工描述拓扑。
  • 当前仓库交付重点是包、配置与监控,并不替代 Cloudberry 官方的 MPP 初始化与扩缩容工具。
  • 由于这是 MPP 分布式内核,Patroni / PgBouncer / PgBackRest 的原生 PostgreSQL 经验并不能无条件套用到所有节点角色。
  • 如果你只需要 PostgreSQL 水平扩展而不是完整 MPP 数仓,通常应优先考虑 Citus

相关文档

8.14.14 - Neon

使用 Neon 开源的 Serverless 版本 PostgreSQL 内核,自建灵活伸缩,Scale To Zero,灵活分叉的 PG 服务。

Neon 采用了存储与计算分离架构,提供了丝滑的自动扩缩容,Scale to Zero,以及数据库版本分叉等独家能力。

Neon 官网:https://neon.tech/

Neon 编译后的二进制产物过于庞大,目前不对开源版用户提供,目前处于试点阶段,有需求请联系 Pigsty 销售。

8.14.15 - AgensGraph

在 Pigsty 中使用 AgensGraph(PG17)图数据库内核,在 PostgreSQL 体系内获得属性图与 Cypher/SQL 混合查询能力。

AgensGraph 是基于 PostgreSQL 的属性图数据库内核,支持 openCypher 查询,并允许 Cypher 与 SQL 混合使用。


概览

Pigsty 通过 pg_mode: agens 接入 AgensGraph,并保留标准 PostgreSQL 集群的大部分运维体验。

  • 内核包:agensgraph
  • 模式标识:pg_mode: agens
  • 当前模板版本:AgensGraph 2.17.0
  • 当前版本字符串:PostgreSQL 17.10 (AgensGraph 2.17.0)
  • 当前内置模板:agens
  • 适用场景:关系数据之上叠加图关系分析、路径查询、知识图谱、风控关联

对客户端来说,AgensGraph 仍然暴露 PostgreSQL 线缆协议,常规 PG 客户端、驱动与连接池都可以直接接入。 和原生 PostgreSQL 的主要区别不在“如何连接”,而在“库内多了图模型对象、Cypher 语法与 agtype 数据类型”。


安装

使用 Pigsty 内置模板:

./configure -c agens
./deploy.yml

agens 模板会自动启用 pg_mode: agens 并安装 agensgraph 内核包。部署完成后可直接核对内核版本:

psql -d meta -c "SELECT version();"

配置

AgensGraph 在 Pigsty 中的关键配置如下:

all:
  vars:
    node_repo_modules: node,infra,pgsql
    pg_version: 17

  children:
    pg-meta:
      vars:
        pg_mode: agens
        pg_packages: [ agensgraph, pgsql-common ]

AgensGraph 不需要像 pgEdge / Babelfish 那样额外预加载一组专有库,因此大多数 Pigsty 的标准 HA、备份、监控、访问控制与 IaC 用法都保持不变。 如果你的负载以图遍历和复杂路径查询为主,通常应重点关注 work_memshared_buffers 与代价参数,而不是简单沿用默认 OLTP 习惯。


使用

连接到数据库后,通常先创建图并设置 graph_path

CREATE GRAPH g;
SET graph_path = g;

创建标签、顶点和边:

CREATE VLABEL person;
CREATE ELABEL knows;

CREATE (:person {name: 'Jack'});
CREATE (:person {name: 'Emily'})-[:knows]->(:person {name: 'Tom'});

执行图查询与更新:

MATCH (:person {name: 'Emily'})-[:knows]->(v:person)
RETURN v.name;

MATCH (v:person {name: 'Jack'})
SET v.age = '24';

如需在 SQL 中混合调用 Cypher,可使用 cypher()

SELECT *
FROM cypher('g', $$ MATCH (v:person) RETURN v.name $$) AS (name agtype);

在实际项目里,更常见的做法是把“关系表 + 图标签 + Cypher 查询”混合使用: 普通事务、权限与备份仍沿用 PostgreSQL 的工作流,而图分析逻辑放在 AgensGraph 提供的图对象与 cypher() 接口中完成。


注意事项

  • AgensGraph 当前固定在 PG17 兼容系,规划扩展生态时不要按 PG18 的可用性来假定。
  • agens 默认模板为单节点快速启用,生产环境建议按需扩展为高可用拓扑。
  • 并非所有 PostgreSQL 三方扩展都保证可直接用于 AgensGraph 内核,建议先做兼容性验证。
  • 图对象与关系对象可以共存于同一数据库中,但生产上通常更建议规划清晰的数据库或命名约定,避免图模型与普通业务对象互相污染。
  • 请结合业务图模型规模调优内存与代价参数,避免直接沿用默认值。
  • 使用 AgensGraph 内核遇到兼容或语义问题时,建议优先对照官方手册与上游 Issue 排查。

相关文档


可用扩展

AgensGraph 内核共有 60 个可用扩展,去除 PG Contrib 自带扩展之后,还有以下额外扩展:

扩展名 版本号 说明
meta 1.0 Utility functions for agensgraph

8.14.16 - pgEdge

在 Pigsty 中使用 pgEdge(PG15~18)内核,借助 Spock 多主逻辑复制构建面向边缘场景的分布式 PostgreSQL。

pgEdge 是面向边缘场景的分布式 PostgreSQL 发行版,核心能力建立在 Spock 多主逻辑复制之上。


概览

Pigsty 通过 pg_mode: pgedge 接入 pgEdge,并用标准 PG 集群编排流程交付其核心组件:

  • pgedge:PG15、PG16、PG17、PG18 兼容内核,模板默认使用 PG18
  • spock:多主(active-active)逻辑复制
  • snowflake:分布式唯一序列
  • lolor:大对象逻辑复制兼容层

当前 Pigsty 仓库中提供 pgedge-15pgedge-16pgedge-17pgedge-18 四个版本化内核包,模板默认使用 pg_version: 18spocksnowflakelolor 的控制文件、SQL 文件和动态库随 pgedge-$v 内核包一起交付,不再作为独立 pg_extensions 包安装项。 对客户端来说,pgEdge 仍然是 PostgreSQL 线缆协议,psql、JDBC/ODBC、DBeaver 等工具都可以直接接入。

Pigsty 提供的是“先验证单节点内核,再扩展到多节点复制拓扑”的交付路径: 模板会开箱即用地完成内核、扩展、监控、备份与访问控制,但真正的多主拓扑编排仍需要你根据业务一致性和冲突策略来设计。


安装

使用 Pigsty 内置模板:

./configure -c pgedge
./deploy.yml

模板默认在 meta 数据库预装 spocksnowflakelolor。部署完成后可用以下命令核对版本和扩展:

psql -d meta -c "SELECT version();"
psql -d meta -c "SELECT extname, extversion FROM pg_extension WHERE extname IN ('spock','snowflake','lolor') ORDER BY 1;"

模板与完整参数见:pgedge 配置模板


配置

pgedge 模板的关键参数如下(与 conf/pgedge.yml 一致):

pg_mode: pgedge
pg_version: 18
pg_packages: [ pgedge, pgsql-common ]
pg_libs: 'spock, lolor, pg_stat_statements, auto_explain'
pg_databases:
  - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [spock, snowflake, lolor] }

如果计划扩展为多节点多主,建议额外显式配置逻辑复制容量和 snowflake.node

pg_parameters:
  wal_level: logical
  max_replication_slots: 16
  max_wal_senders: 16
  'snowflake.node': 1

其中 snowflake.node 必须在每个写节点上保持唯一,否则分布式 ID 会冲突。


使用

在 Pigsty 中,常见使用路径是“先单节点验证内核,再扩展为多节点 Spock 复制拓扑”。

如果你在业务数据库中也需要这些能力,请先创建扩展:

CREATE EXTENSION IF NOT EXISTS spock;
CREATE EXTENSION IF NOT EXISTS snowflake;
CREATE EXTENSION IF NOT EXISTS lolor;

随后再使用 Spock SQL API 或 pgEdge CLI 建立节点、复制集和订阅关系。 对于已有使用 serial / identity 的业务表,建议在多主写入前先完成 snowflake 序列规划,否则跨节点写入很容易出现主键冲突。


注意事项

  • pgEdge 的复制是“按数据库”组织的,不是一次性把整个实例自动变成全库多主。
  • 参与复制的表应具备 PRIMARY KEY 或合适的 REPLICA IDENTITY
  • UNLOGGEDTEMPORARY 表不会进入 Spock 逻辑复制。
  • Spock 的配置与运维通常需要超级用户权限,生产环境应明确权限边界。
  • 如果业务依赖 large object 复制,应显式使用 lolor,不要假定原生 large object 会自动正确同步。
  • 跨地域多主不是“开关一开即可用”的功能,网络时延、冲突解决策略与写入模型都要先评估。

相关文档


可用扩展

pgEdge 内核共有 63 个可用扩展,去除 PG Contrib 自带扩展之后,还有以下额外扩展:

扩展名 版本号 说明
lolor 1.2.2 Large Objects support for logical replication
snowflake 2.5.0 Snowflake style IDs for PostgreSQL
spock 5.0.10 PostgreSQL Logical Replication

8.14.17 - DocumentDB

DocumentDB + FerretDB 组合提供 MongoDB 线协议兼容能力

DocumentDB 是微软开源维护的 PostgreSQL 文档数据库扩展,FerretDB 是构建在其上的无状态协议转换代理。 两者组合,让标准 PostgreSQL 内核对外提供 MongoDB 线协议兼容端点——使用 MongoDB 驱动的应用程序可以直接对接,请求被转换为对 PostgreSQL 的操作。

与其他内核分支不同,这不是一个独立的 PostgreSQL 分叉:数据层运行原生 PostgreSQL 16 - 18 内核,由标准 PGSQL 模块管理, 持久化、事务、高可用、备份、监控与访问控制均由 PostgreSQL 侧负责;FerretDB 以 Pigsty Docker APP 的形式部署,只承担协议转换。

Pigsty 是 FerretDB 社区的合作伙伴,提供 FerretDB 与 DocumentDB 扩展的二进制打包, 并通过 mongo 配置模板开箱即用地交付整套组合。


快速开始

使用 Pigsty 的 标准安装流程mongo 配置模板:

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty;
./configure -c mongo    # 使用 Mongo(DocumentDB + FerretDB)配置模板
./deploy.yml            # 安装,生产部署请先在 pigsty.yml 中修改密码
./docker.yml -l pg-meta # 在 pg-meta 节点上安装 Docker
./app.yml -l pg-meta    # 部署 FerretDB Docker APP

FerretDB 默认监听本机回环地址的 27017 端口,使用 mongosh 或任意 MongoDB 兼容客户端即可访问:

mongosh 'mongodb://mongod:[email protected]:27017/'

配置

源文件:pigsty/conf/mongo.yml,完整模板说明见 Mongo 配置模板 文档。

PostgreSQL 侧的关键配置是 documentdb 扩展及其预加载库,以及供 FerretDB 使用的后端超级用户:

pg-meta:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-meta
    pg_users:
      - { name: mongod ,password: DBUser.Mongo ,superuser: true ,comment: FerretDB backend user }
    pg_databases:
      - { name: postgres, extensions: [ documentdb, postgis, vector, pg_cron, rum ]}
    pg_extensions: [ documentdb, postgis, pgvector, pg_cron, rum ]
    pg_libs: 'pg_documentdb, pg_documentdb_core, pg_documentdb_extended_rum, pg_cron, pg_stat_statements, auto_explain'

FerretDB 作为 Docker APP 部署,参数是 apps.ferretdb.conf 下的普通覆盖项, 容器通过 host.docker.internal 连接本机 5436 主库直连服务:

docker_enabled: true
app: ferretdb
apps:
  ferretdb:
    conf:
      FERRETDB_IMAGE: ghcr.io/ferretdb/ferretdb:2.7.0
      FERRETDB_POSTGRESQL_URL: 'postgres://mongod:[email protected]:5436/postgres?pool_min_conns=1&pool_max_conns=20'
      FERRETDB_BIND_ADDR: 127.0.0.1
      FERRETDB_PORT: 27017
      FERRETDB_AUTH: true
      FERRETDB_TELEMETRY: disabled

高可用

因为 FerretDB 完全无状态,高可用拓扑与标准 PostgreSQL 集群一致:模板中保留了注释状态的三节点 pg-mongo 示例, 每个节点各跑一个 FerretDB 容器(绑定本机 27018),由 HAProxy 汇聚为浮动端点 10.10.10.4:27017mongo.pigsty)对外服务。

PostgreSQL 侧的故障转移仍由 Patroni 与 etcd 负责,Mongo 端点在主库切换后自动恢复可用。


注意事项

  • FerretDB 默认启用认证(FERRETDB_AUTH: true),但尚未实现 MongoDB 授权角色体系,真正的安全边界仍是 PostgreSQL 的用户与 HBA 规则。
  • 默认未启用客户端 MongoDB TLS,Mongo 端点也不会暴露到网络;确有远程访问需求时才应修改 FERRETDB_BIND_ADDR
  • 后端集群统一使用标准 PostgreSQL 参数、剧本与仪表盘,不存在独立的 FERRET 模块或 mongo_* 参数组。
  • FerretDB 或 DocumentDB 升级后,建议重新执行一次带认证的 CRUD 冒烟测试。

8.15 - 场景模板

使用 Pigsty 预置的四种场景化 Patroni 模版,或者基于这些模板自定义您的配置模板

Pigsty 提供四种预置的 Patroni/PostgreSQL 配置模板,针对不同的使用场景进行了参数优化:

模板 CPU 核心 适用场景 特点
/docs/pgsql/template/oltp.yml 4-128C OLTP 事务处理 高并发、低延迟、高吞吐
/docs/pgsql/template/olap.yml 4-128C OLAP 分析处理 大查询、高并行、长事务
/docs/pgsql/template/crit.yml 4-128C 一致性优先业务 一致性优先、详细审计
/docs/pgsql/template/tiny.yml 1-3C 微型实例 资源受限、低配环境

您可以通过 pg_conf 参数来选择使用哪个配置模板,默认为 /docs/pgsql/template/oltp.yml

通常,数据库调优模板 pg_conf 应当与机器调优模板 node_tune 配套使用。

四套标准模板都将 wal_level 设为 logical。从 PostgreSQL 18.6 起,服务端新增 output_plugin_libraries 安全白名单;Pigsty 默认允许内置的 pgoutputtest_decoding 与默认随 pgsql-main 安装的 wal2json。如果要使用其他逻辑解码输出插件,应在评审其代码与权限边界后,将准确的库名加入 pg_parameters;Patroni 会在不支持该参数的旧 PostgreSQL 版本上过滤模板项。


使用模板

要使用特定的配置模板,只需在集群定义中设置 pg_conf 参数。 建议同时设置 node_tune 参数,使操作系统级别的调优与数据库调优保持一致:

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
  vars:
    pg_cluster: pg-test
    pg_conf: oltp.yml    # PostgreSQL 配置模板(默认值)
    node_tune: oltp      # 操作系统调优模板(默认值)

对于核心金融业务场景,您可以使用 /docs/pgsql/template/crit.yml 模板:

pg-finance:
  hosts:
    10.10.10.21: { pg_seq: 1, pg_role: primary }
    10.10.10.22: { pg_seq: 2, pg_role: replica }
    10.10.10.23: { pg_seq: 3, pg_role: replica }
  vars:
    pg_cluster: pg-finance
    pg_conf: crit.yml    # PostgreSQL 关键业务模板
    node_tune: crit      # 操作系统关键业务调优

对于低配虚拟机或开发环境,可以使用 /docs/pgsql/template/tiny.yml 模板:

pg-dev:
  hosts:
    10.10.10.31: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-dev
    pg_conf: tiny.yml    # PostgreSQL 微型实例模板
    node_tune: tiny      # 操作系统微型实例调优

模板对比

四种模板在关键参数上有显著差异,以适应不同的业务场景。以下是主要差异对比:

连接与内存

参数 OLTP OLAP CRIT TINY
max_connections 500/1000 500 500/1000 250
work_mem 范围 64MB-1GB 64MB-8GB 64MB-1GB 16MB-256MB
maintenance_work_mem 25% 共享缓冲区 50% 共享缓冲区 25% 共享缓冲区 25% 共享缓冲区
max_locks_per_transaction 1-2x maxconn 2-4x maxconn 1-2x maxconn 1-2x maxconn

并行查询

参数 OLTP OLAP CRIT TINY
max_worker_processes max(cpu+16, 24) max(cpu+20, 28) max(cpu+16, 24) max(cpu+12, 20)
max_parallel_workers 50% cpu 80% cpu 50% cpu 50% cpu
max_parallel_workers_per_gather 20% cpu (max 8) 50% cpu 0(禁用) 0(禁用)
parallel_setup_cost 2000 1000 2000 1000
parallel_tuple_cost 0.2 0.1 0.2 0.1

同步复制

参数 OLTP OLAP CRIT TINY
synchronous_mode 取决于 pg_rpo 取决于 pg_rpo 强制开启 取决于 pg_rpo
data_checksums 可选 可选 强制开启 可选

Vacuum 配置

参数 OLTP OLAP CRIT TINY
vacuum_cost_delay 20ms 10ms 20ms 20ms
vacuum_cost_limit 2000 10000 2000 2000
autovacuum_max_workers 3 3 3 2

超时与安全

参数 OLTP OLAP CRIT TINY
idle_in_transaction_session_timeout 10min 禁用 1min 10min
log_min_duration_statement 100ms 1000ms 100ms 100ms
default_statistics_target 400 1000 400 200
track_activity_query_size 8KB 8KB 32KB 8KB
log_connections 仅授权 仅授权 全部阶段 默认

IO 配置(PG18)

参数 OLTP OLAP CRIT TINY
io_workers 25% cpu (4-16) 50% cpu (4-32) 25% cpu (4-8) 3
temp_file_limit 1/20 磁盘,上限 100GB 1/5 磁盘,上限 400GB 1/20 磁盘,上限 100GB 1/20 磁盘,上限 100GB

选择建议

  • OLTP 模板:适用于大多数在线事务处理场景,是默认选择。适合电商、社交、游戏等高并发低延迟应用。

  • OLAP 模板:适用于数据仓库、BI 报表、ETL 等分析型负载。特点是允许大查询、高并行度、宽松的超时设置。

  • CRIT 模板:适用于金融交易、核心账务等对数据一致性和安全性有极高要求的场景。强制同步复制、数据校验和、完整审计日志。

  • TINY 模板:适用于开发测试环境、资源受限的虚拟机、树莓派等场景。最小化资源占用,禁用并行查询。


自定义模板

您可以基于现有模板创建自定义配置模板。模板文件位于 Pigsty 安装目录的 roles/pgsql/templates/ 下:

roles/pgsql/templates/
├── oltp.yml    # OLTP 事务处理模板(默认)
├── olap.yml    # OLAP 分析处理模板
├── crit.yml    # CRIT 关键业务模板
└── tiny.yml    # TINY 微型实例模板

创建自定义模板的步骤:

  1. 复制一个现有模板作为基础
  2. 根据需要修改参数
  3. 将模板放置在 roles/pgsql/templates/ 目录
  4. 在集群定义中通过 pg_conf 引用新模板

例如,创建一个名为 myapp.yml 的自定义模板:

cp roles/pgsql/templates/oltp.yml roles/pgsql/templates/myapp.yml
# 编辑 myapp.yml 进行自定义

然后在集群中使用:

pg-myapp:
  vars:
    pg_conf: myapp.yml

请注意,模板文件使用 Jinja2 模板语法,参数值会根据节点的实际资源(CPU、内存、磁盘)动态计算。


参数优化策略

了解更多关于模板参数优化的技术细节,请参阅 参数优化策略,其中详细介绍了:

  • 内存参数调整(共享缓冲区、工作内存、最大连接数)
  • CPU 参数调整(并行查询工作进程配置)
  • 存储空间参数(WAL 大小、临时文件限制)
  • 手工调整参数的方法

相关参数

  • pg_conf:指定使用的 PostgreSQL 配置模板
  • node_tune:指定使用的操作系统调优模板,应与 pg_conf 配套
  • pg_rto:恢复时间目标,影响故障切换超时
  • pg_rpo:候选副本落后阈值;设为 0 时通用模板启用同步复制
  • pg_max_conn:覆盖模板的最大连接数
  • pg_shared_buffer_ratio:共享缓冲区占内存比例
  • pg_storage_type:存储类型,影响 IO 相关参数

8.15.1 - 默认配置模板的参数优化策略说明

了解在 Pigsty 中,预置的四种 Patroni 场景化模板所采用的不同参数优化策略

Pigsty 默认提供了四套场景化参数模板,可以通过 pg_conf 参数指定并使用。

  • tiny.yml:为小节点、虚拟机、小型演示优化(模板标注为 1-3 核)
  • oltp.yml:为 OLTP 工作负载和延迟敏感应用优化(4C8GB+)(默认模板)
  • olap.yml:为 OLAP 工作负载和吞吐量优化(4C8G+)
  • crit.yml:为数据一致性和关键应用优化(4C8G+)

Pigsty 会针对这四种默认场景,采取不同的参数优化策略,如下所示:


内存参数调整

Pigsty 默认会检测系统的内存大小,并以此为依据设定最大连接数量与内存相关参数。

默认情况下,Pigsty 使用 25% 的内存作为 PostgreSQL 共享缓冲区;其余内存还会被连接、work_mem、后台进程及操作系统缓存共同使用。

默认情况下,如果用户没有设置一个 pg_max_conn 最大连接数,Pigsty 会根据以下规则使用默认值:

  • oltp: 500 (pgbouncer) / 1000 (postgres)
  • crit: 500 (pgbouncer) / 1000 (postgres)
  • tiny: 250
  • olap: 500

其中对于 OLTP 与 CRIT 模版来说,如果服务没有指向 pgbouncer 连接池,而是直接连接 postgres 数据库,最大连接会翻倍至 1000 条。

决定最大连接数后,work_mem 会根据共享内存数量 / 最大连接数计算得到,并限定在 64MB ~ 1GB 的范围内。

{% raw %}
{% if pg_max_conn != 'auto' and pg_max_conn|int >= 20 %}{% set pg_max_connections = pg_max_conn|int %}{% else %}{% if pg_default_service_dest|default('postgres') == 'pgbouncer' %}{% set pg_max_connections = 500 %}{% else %}{% set pg_max_connections = 1000 %}{% endif %}{% endif %}
{% set pg_max_prepared_transactions = pg_max_connections if 'citus' in pg_libs else 0 %}
{% set pg_max_locks_per_transaction = (2 * pg_max_connections)|int if 'citus' in pg_libs or 'timescaledb' in pg_libs else pg_max_connections %}
{% set pg_shared_buffers = (node_mem_mb|int * pg_shared_buffer_ratio|float) | round(0, 'ceil') | int %}
{% set pg_maintenance_mem = (pg_shared_buffers|int * 0.25)|round(0, 'ceil')|int %}
{% set pg_effective_cache_size = node_mem_mb|int - pg_shared_buffers|int  %}
{% set pg_workmem =  ([ ([ (pg_shared_buffers / pg_max_connections)|round(0,'floor')|int , 64 ])|max|int , 1024])|min|int %}
{% endraw %}

CPU参数调整

在 PostgreSQL 中,有 4 个与并行查询相关的重要参数,Pigsty 会自动根据当前系统的 CPU 核数进行参数优化。 模板先计算并行/扩展 worker 预算,然后在写入 max_worker_processes 时再额外增加 8 个保留槽。因此最终 GUC 比模板顶部的中间变量多 8。

OLTP 设置逻辑 范围限制
max_worker_processes max(CPU + 8, 16) + 8 max(CPU + 16, 24)
max_parallel_workers max(ceil(50% CPU), 2) 1/2 CPU 上取整,最少两个
max_parallel_maintenance_workers max(ceil(33% CPU), 2) 1/3 CPU 上取整,最少两个
max_parallel_workers_per_gather min(max(ceil(20% CPU), 2),8) 1/5 CPU 下取整,最少两个,最多 8 个
OLAP 设置逻辑 范围限制
max_worker_processes max(CPU + 12, 20) + 8 max(CPU + 20, 28)
max_parallel_workers max(ceil(80% CPU, 2)) 4/5 CPU 上取整,最少两个
max_parallel_maintenance_workers max(ceil(33% CPU), 2) 1/3 CPU 上取整,最少两个
max_parallel_workers_per_gather max(floor(50% CPU), 2) 1/2 CPU 上取整,最少两个
CRIT 设置逻辑 范围限制
max_worker_processes max(CPU + 8, 16) + 8 max(CPU + 16, 24)
max_parallel_workers max(ceil(50% CPU), 2) 1/2 CPU 上取整,最少两个
max_parallel_maintenance_workers max(ceil(33% CPU), 2) 1/3 CPU 上取整,最少两个
max_parallel_workers_per_gather 0, 按需启用
TINY 设置逻辑 范围限制
max_worker_processes max(CPU + 4, 12) + 8 max(CPU + 12, 20)
max_parallel_workers max(floor(50% CPU), 1) 50% CPU 下取整,最少 1 个
max_parallel_maintenance_workers max(floor(33% CPU), 1) 33% CPU 下取整,最少 1 个
max_parallel_workers_per_gather 0,按需启用 禁用单个查询的并行 gather

请注意,CRIT 和 TINY 模板直接通过设置 max_parallel_workers_per_gather = 0 关闭了并行查询。 用户可以按需在需要时设置此参数以启用并行查询。

OLTP 和 CRIT 模板都额外设置了以下参数,将并行查询的 Cost x 2,以降低使用并行查询的倾向。

parallel_setup_cost: 2000           # double from 100 to increase parallel cost
parallel_tuple_cost: 0.2            # double from 0.1 to increase parallel cost
min_parallel_table_scan_size: 32MB  # 4x default 8MB, prefer non-parallel scan
min_parallel_index_scan_size: 2MB   # 4x default 512kB, prefer non-parallel scan

请注意 max_worker_processes 参数的调整必须在重启后才能生效。此外,当从库的本参数配置值高于主库时,从库将无法启动。 此参数必须通过 patroni 配置管理进行调整,该参数由 Patroni 管理,用于确保主从配置一致,避免在故障切换时新从库无法启动。


存储空间参数

Pigsty 默认检测 /data/postgres 主数据目录所在磁盘的总空间,并以此作为依据指定下列参数:

{% raw %}
{% set pg_size_twentieth = ([([(node_fs_bytes|int / 21474836480)|round(0, 'ceil')|int, 1])|max, 100])|min %}
min_wal_size: {{ ([pg_size_twentieth, 200])|min }}GB                  # 1/20 disk size, max 200GB
max_wal_size: {{ ([pg_size_twentieth * 4, 2000])|min }}GB             # 2/10 disk size, max 2000GB
max_slot_wal_keep_size: {{ ([pg_size_twentieth * 6, 3000])|min }}GB   # 3/10 disk size, max 3000GB
temp_file_limit: {{ ([pg_size_twentieth, 200])|min }}GB               # 1/20 of disk size, max 200GB
{% endraw %}
  • pg_size_twentieth 先按磁盘容量的 1/20 向上取整,并限制在 1~100GB。
  • 因此前三种标准模板中,temp_file_limitmin_wal_size实际有效上限是 100GB
  • max_wal_size 的实际有效上限是 400GB。
  • max_slot_wal_keep_size 的实际有效上限是 600GB。

OLAP 模板将 temp_file_limit 设为 pg_size_twentieth × 4,实际有效上限是 400GB。模板行尾现有的 200GB/2TB/3TB 注释没有计入 pg_size_twentieth 自身的 100GB 上限,应以渲染表达式为准。


手工调整参数

除了使用 Pigsty 自动配置的参数外,您还可以手工调整 PostgreSQL 参数。

使用 pg edit-config <cluster> 命令可以交互式编辑集群配置:

pg edit-config pg-meta

或者使用 -p 参数直接设置参数:

pg edit-config -p log_min_duration_statement=1000 pg-meta
pg edit-config --force -p shared_preload_libraries='timescaledb, pg_cron, pg_stat_statements, auto_explain' pg-meta

您也可以使用 Patroni REST API 来修改配置:

curl -u 'postgres:Patroni.API' \
    -d '{"postgresql":{"parameters": {"log_min_duration_statement":200}}}' \
    -s -X PATCH http://10.10.10.10:8008/config | jq .

8.15.2 - OLTP 模板

针对在线事务处理负载优化的 PostgreSQL 配置模板

oltp.yml 是 Pigsty 的默认配置模板,针对 在线事务处理(OLTP)负载进行了优化。适用于 4-128 核 CPU 的服务器,特点是高并发连接、低延迟响应、高事务吞吐量。

建议同时使用 node_tune = oltp 进行操作系统级别的配套调优。


适用场景

OLTP 模板适用于以下场景:

  • 电商系统:订单处理、库存管理、用户交易
  • 社交应用:用户动态、消息推送、关注关系
  • 游戏后端:玩家数据、排行榜、游戏状态
  • SaaS 应用:多租户业务系统
  • Web 应用:常规的 CRUD 操作密集型应用

特征负载

  • 大量短事务(毫秒级)
  • 高并发连接(数百到数千)
  • 读写比例通常在 7:3 到 9:1
  • 对延迟敏感,要求快速响应
  • 数据一致性要求高

使用方法

oltp.yml 是默认模板,无需显式指定:

pg-oltp:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
  vars:
    pg_cluster: pg-oltp
    # pg_conf: oltp.yml  # PostgreSQL 配置模板(默认值)
    # node_tune: oltp    # 操作系统调优模板(默认值)

或显式指定:

pg-oltp:
  vars:
    pg_conf: oltp.yml    # PostgreSQL 配置模板
    node_tune: oltp      # 操作系统调优模板

参数详解

连接管理

max_connections: 500/1000   # 取决于是否使用 pgbouncer
superuser_reserved_connections: 10
  • pg_default_service_destpgbouncer 时,max_connections 设为 500
  • 当流量直连 PostgreSQL 时,max_connections 设为 1000
  • 可通过 pg_max_conn 参数覆盖

内存配置

OLTP 模板的内存分配策略:

参数 计算公式 说明
shared_buffers 内存 × pg_shared_buffer_ratio 默认比例 0.25
maintenance_work_mem shared_buffers × 25% 用于 VACUUM、CREATE INDEX
work_mem 64MB - 1GB 根据 shared_buffers/max_connections 计算
effective_cache_size 总内存 - shared_buffers 可用于缓存的预估内存

work_mem 计算逻辑

work_mem = min(max(shared_buffers / max_connections, 64MB), 1GB)

这确保每个连接有足够的排序/哈希内存,但不会过度分配。

并行查询

OLTP 模板对并行查询做了适度限制,以避免并行查询抢占过多资源影响其他事务:

max_worker_processes: max(cpu + 16, 24)
max_parallel_workers: 50% × cpu (最小2)
max_parallel_workers_per_gather: 20% × cpu (2-8)
max_parallel_maintenance_workers: 33% × cpu (最小2)

同时提高了并行查询的成本估算,让优化器倾向于串行执行:

parallel_setup_cost: 2000      # 默认值 1000 的两倍
parallel_tuple_cost: 0.2       # 默认值 0.1 的两倍
min_parallel_table_scan_size: 32MB   # 默认值 8MB 的四倍,倾向于不使用并行扫描
min_parallel_index_scan_size: 2MB    # 默认值 512kB 的四倍,倾向于不使用并行扫描

WAL 配置

min_wal_size: 磁盘/20 (实际最大100GB)
max_wal_size: 磁盘/5 (实际最大400GB)
max_slot_wal_keep_size: 磁盘×3/10 (实际最大600GB)
wal_buffers: 16MB
wal_writer_delay: 20ms
wal_writer_flush_after: 1MB
commit_delay: 20
commit_siblings: 10
checkpoint_timeout: 15min
checkpoint_completion_target: 0.80

这些设置平衡了数据安全性和写入性能。

Vacuum 配置

vacuum_cost_delay: 20ms         # 每轮 vacuum 后休眠
vacuum_cost_limit: 2000         # 每轮 vacuum 的代价上限
autovacuum_max_workers: 3
autovacuum_naptime: 1min
autovacuum_vacuum_scale_factor: 0.08    # 8% 表变化触发 vacuum
autovacuum_analyze_scale_factor: 0.04   # 4% 表变化触发 analyze
autovacuum_freeze_max_age: 1000000000

OLTP 模板使用保守的 vacuum 设置,避免 vacuum 操作影响在线事务性能。

查询优化

random_page_cost: 1.1           # SSD 优化
effective_io_concurrency: 200   # SSD 并发 IO
default_statistics_target: 400  # 统计信息精度

这些设置让优化器能够生成更好的查询计划。

日志与监控

log_min_duration_statement: 100         # 记录超过 100ms 的慢查询
log_statement: ddl                      # 记录 DDL 语句
log_checkpoints: on
log_lock_waits: on
log_temp_files: 1024                    # 记录超过 1MB 的临时文件
log_autovacuum_min_duration: 1s
track_io_timing: on
track_functions: all
track_activity_query_size: 8192

客户端超时

deadlock_timeout: 50ms
idle_in_transaction_session_timeout: 10min

10 分钟的空闲事务超时可以防止长时间持有锁的僵尸事务。

扩展配置

shared_preload_libraries: 'pg_stat_statements, auto_explain'

# auto_explain
auto_explain.log_min_duration: 1s
auto_explain.log_analyze: on
auto_explain.log_verbose: on
auto_explain.log_timing: on
auto_explain.log_nested_statements: true

# pg_stat_statements
pg_stat_statements.max: 10000
pg_stat_statements.track: all
pg_stat_statements.track_utility: off
pg_stat_statements.track_planning: off

与其他模板的对比

特性 OLTP OLAP CRIT
max_connections 500-1000 500 500-1000
work_mem 64MB-1GB 64MB-8GB 64MB-1GB
并行查询 适度限制 激进启用 禁用
vacuum 激进度 保守 激进 保守
事务超时 10min 禁用 1min
慢查询阈值 100ms 1000ms 100ms

为什么选择 OLTP 而非 OLAP?

  • 您的查询大多数是简单的点查和范围查询
  • 事务响应时间要求在毫秒级
  • 有大量并发连接
  • 不需要执行复杂的分析查询

为什么选择 OLTP 而非 CRIT?

  • 可以接受极小概率的数据丢失(异步复制)
  • 不需要完整的审计日志
  • 希望获得更好的写入性能

性能调优建议

连接池

对于高并发场景,强烈建议使用 PgBouncer 连接池:

pg-oltp:
  vars:
    pg_default_service_dest: pgbouncer  # 默认值
    pgbouncer_poolmode: transaction     # 事务级池化

只读分离

使用只读从库分担读取负载:

pg-oltp:
  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 }

监控指标

关注以下监控指标:

  • 连接数:活跃连接数、等待连接数
  • 事务率:TPS、提交/回滚比例
  • 响应时间:查询延迟百分位(p50/p95/p99)
  • 锁等待:锁等待时间、死锁次数
  • 复制延迟:从库延迟时间和字节数

参考资料

8.15.3 - OLAP 模板

针对在线分析处理负载优化的 PostgreSQL 配置模板

olap.yml 是针对 在线分析处理(OLAP)负载优化的配置模板。适用于 4-128 核 CPU 的服务器,特点是支持大查询、高并行度、宽松的超时设置和激进的 Vacuum 策略。

建议同时使用 node_tune = olap 进行操作系统级别的配套调优。


适用场景

OLAP 模板适用于以下场景:

  • 数据仓库:历史数据存储、多维分析
  • BI 报表:复杂报表查询、仪表盘数据源
  • ETL 处理:数据抽取、转换、加载
  • 数据分析:Ad-hoc 查询、数据探索
  • HTAP 混合负载:分析型从库

特征负载

  • 复杂查询(秒级到分钟级)
  • 低并发连接(数十到数百)
  • 读密集型,写入通常是批量操作
  • 对吞吐量敏感,可以容忍较高延迟
  • 需要扫描大量数据

使用方法

在集群定义中指定 pg_conf = olap.yml

pg-olap:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
  vars:
    pg_cluster: pg-olap
    pg_conf: olap.yml    # PostgreSQL 分析处理模板
    node_tune: olap      # 操作系统分析处理调优

也可以将 olap.yml 模板用于专用的离线从库:

pg-mixed:
  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, pg_conf: olap.yml }  # 离线分析从库
  vars:
    pg_cluster: pg-mixed
    pg_conf: oltp.yml    # 主库和在线从库使用 OLTP 模板
    node_tune: oltp      # 操作系统 OLTP 调优

参数详解

连接管理

max_connections: 500
superuser_reserved_connections: 10

OLAP 场景通常不需要大量连接,500 个连接足以应对大多数分析负载。

内存配置

OLAP 模板的内存分配策略更为激进:

参数 计算公式 说明
shared_buffers 内存 × pg_shared_buffer_ratio 默认比例 0.25
maintenance_work_mem shared_buffers × 50% 加速索引创建和 VACUUM
work_mem 64MB - 8GB 更大的排序/哈希内存
effective_cache_size 总内存 - shared_buffers 可用于缓存的预估内存

work_mem 计算逻辑(与 OLTP 不同):

work_mem = min(max(shared_buffers / max_connections, 64MB), 8GB)

更大的 work_mem 允许更大的排序和哈希操作在内存中完成,避免磁盘溢出。

锁与事务

max_locks_per_transaction: 2-4x maxconn   # OLTP 是 1-2x

OLAP 查询可能涉及更多表(分区表、大量 JOIN),因此需要更多的锁槽。

并行查询

OLAP 模板激进启用并行查询:

max_worker_processes: max(cpu + 20, 28)      # OLTP: max(cpu + 16, 24)
max_parallel_workers: 80% × cpu (最小2)      # OLTP: 50%
max_parallel_workers_per_gather: 50% × cpu   # OLTP: 20% (最大8)
max_parallel_maintenance_workers: 33% × cpu

并行查询成本保持默认值,让优化器更倾向于选择并行计划:

# parallel_setup_cost: 1000    # 默认值,不加倍
# parallel_tuple_cost: 0.1     # 默认值,不加倍

同时启用分区智能优化:

enable_partitionwise_join: on       # 分区表智能 JOIN
enable_partitionwise_aggregate: on  # 分区表智能聚合

IO 配置(PG18)

io_workers: 50% × cpu (4-32)    # OLTP: 25% (4-16)

更多的 IO 工作线程支持并行扫描大表。

WAL 配置

min_wal_size: 磁盘/20 (实际最大100GB)
max_wal_size: 磁盘/5 (实际最大400GB)
max_slot_wal_keep_size: 磁盘×3/10 (实际最大600GB)
temp_file_limit: 磁盘/5 (实际最大400GB)   # OLTP: 磁盘/20,实际最大100GB

更大的 temp_file_limit 允许更大的中间结果溢出到磁盘。

Vacuum 配置

OLAP 模板使用更激进的 vacuum 设置:

vacuum_cost_delay: 10ms         # OLTP: 20ms,更快的 vacuum
vacuum_cost_limit: 10000        # OLTP: 2000,每轮更多工作
autovacuum_max_workers: 3
autovacuum_naptime: 1min
autovacuum_vacuum_scale_factor: 0.08
autovacuum_analyze_scale_factor: 0.04

分析型数据库通常有大量批量写入,需要更激进的 vacuum 策略来回收空间。

查询优化

random_page_cost: 1.1
effective_io_concurrency: 200
default_statistics_target: 1000    # OLTP: 400,更精确的统计信息

更高的 default_statistics_target 提供更精确的查询计划,对复杂分析查询尤为重要。

日志与监控

log_min_duration_statement: 1000    # OLTP: 100ms,放宽慢查询阈值
log_statement: ddl
log_checkpoints: on
log_lock_waits: on
log_temp_files: 1024
log_autovacuum_min_duration: 1s
track_io_timing: on
track_cost_delay_timing: on         # PG18+,跟踪 vacuum 代价延迟
track_functions: all
track_activity_query_size: 8192

客户端超时

deadlock_timeout: 50ms
idle_in_transaction_session_timeout: 0   # OLTP: 10min,禁用

分析查询可能需要长时间持有事务,因此禁用空闲事务超时。


与 OLTP 模板的主要差异

参数 OLAP OLTP 差异原因
max_connections 500 500-1000 分析负载连接数少
work_mem 上限 8GB 1GB 支持更大的内存排序
maintenance_work_mem 50% buffer 25% buffer 加速索引创建
max_locks_per_transaction 2-4x 1-2x 更多表参与查询
max_parallel_workers 80% cpu 50% cpu 激进并行
max_parallel_workers_per_gather 50% cpu 20% cpu 激进并行
parallel_setup_cost 1000 2000 默认值,鼓励并行
parallel_tuple_cost 0.1 0.2 默认值,鼓励并行
enable_partitionwise_join on off 分区表优化
enable_partitionwise_aggregate on off 分区表优化
vacuum_cost_delay 10ms 20ms 激进 vacuum
vacuum_cost_limit 10000 2000 激进 vacuum
temp_file_limit 1/5 磁盘 1/20 磁盘 允许更大临时文件
io_workers 50% cpu 25% cpu 更多并行 IO
log_min_duration_statement 1000ms 100ms 放宽慢查询阈值
default_statistics_target 1000 400 更精确统计
idle_in_transaction_session_timeout 禁用 10min 允许长事务

性能调优建议

结合 TimescaleDB

OLAP 模板与 TimescaleDB 配合使用效果极佳:

pg-timeseries:
  vars:
    pg_conf: olap.yml
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'
    pg_extensions:
      - timescaledb

结合 pg_duckdb

对于极致的分析性能,可以结合 pg_duckdb:

pg-analytics:
  vars:
    pg_conf: olap.yml
    pg_libs: 'pg_duckdb, pg_stat_statements, auto_explain'

列式存储

考虑使用 Citus 的列式存储或 pg_mooncake:

pg_extensions:
  - citus_columnar  # 或 pg_mooncake

资源隔离

对于混合负载,建议将分析查询隔离到专用从库:

pg-mixed:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }               # OLTP 写入
    10.10.10.12: { pg_seq: 2, pg_role: replica }               # OLTP 读取
    10.10.10.13: { pg_seq: 3, pg_role: offline }               # OLAP 分析
  vars:
    pg_cluster: pg-mixed

监控指标

关注以下监控指标:

  • 查询时间:长查询的执行时间分布
  • 并行度:并行工作进程的使用率
  • 临时文件:临时文件的大小和数量
  • 磁盘 IO:顺序扫描和索引扫描的 IO 量
  • 缓存命中率:shared_buffers 和 OS 缓存的命中率

参考资料

8.15.4 - CRIT 模板

面向一致性优先业务的 PostgreSQL 参数模板,启用严格同步复制、数据校验和详细连接日志。

crit.yml 面向一致性和审计要求较高的事务型业务。它强制启用数据校验和与 Patroni 严格同步模式,增加连接日志,并调整部分 WAL、超时和并行查询参数。

该模板会增加写入延迟,并可能在没有可用同步副本时阻塞写入。使用前应确认一致性目标、故障域、客户端提交设置和可用性要求。

建议同时评估 node_tune: crit,但主机调优与数据库参数可以独立选择。


使用方法

pg-critical:
  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-critical
    pg_conf: crit.yml
    node_tune: crit

三节点拓扑可以在一个节点故障后保留重新选择同步副本的空间,但是否持续可写还取决于剩余节点状态、DCS、网络和同步副本选择。应在目标拓扑上执行故障演练。


严格同步复制

CRIT 不使用 pg_rpo 推导同步模式,而是固定启用:

synchronous_mode: true
synchronous_mode_strict: true

synchronous_mode_strict 禁止 Patroni 在没有同步副本时自动退回异步复制,因此主库会阻塞需要同步确认的写入。

在以下前提下,该模式以不丢失已确认事务为目标:

  • 会话没有将 synchronous_commit 降低为 localoff 等异步级别;
  • 提交时同步副本正常确认 WAL;
  • 故障切换只选择包含所需 WAL 的合格节点。

因此,RPO 结论必须结合客户端参数、复制状态和故障模型验证,不能只根据模板名称确定。

需要多个同步副本确认时,可以通过 Patroni 动态配置设置:

pg edit-config pg-critical
synchronous_node_count: 2

同步副本数量越多,可接受写入的节点条件越严格。


数据校验和

CRIT 初始化配置始终包含:

initdb:
  - data-checksums

这会忽略 pg_checksum 的关闭设置,并为新集群启用页级校验和。校验和用于发现写入后发生的页面损坏,不检测逻辑错误或所有内存错误。


连接与查询日志

CRIT 记录 DDL、执行时间超过 100 ms 的语句和连接断开事件:

log_statement: ddl
log_min_duration_statement: 100
log_disconnections: 'on'

PostgreSQL 18 及以上版本使用:

log_connections: 'receipt,authentication,authorization'

较早版本使用 log_connections: on。这些日志可以支持连接审计,但不等同于 SQL 细粒度审计。需要记录对象读写、角色或语句类别时,应另行启用 pgaudit

track_activity_query_size 设置为 32 KiB,以保留更长的活动查询文本。日志可能包含 SQL 和业务数据,应限制访问并设置合适的保留周期。


Watchdog

CRIT 会将默认关闭的 Patroni watchdog 模式转换为 automatic

watchdog:
  mode: automatic
  device: /dev/watchdog

automatic 仅在系统存在可用 watchdog 设备时启用。需要强制 fencing 时,应确认硬件、虚拟化平台和设备权限后显式使用 required;配置错误会影响主库启动和故障切换。


主要参数差异

参数 CRIT OLTP 默认 影响
synchronous_mode 固定启用 pg_rpo 推导 一致性优先
synchronous_mode_strict true 按通用模板 无同步副本时阻塞写入
data-checksums 强制启用 pg_checksum 控制 页面损坏检测
max_parallel_workers_per_gather 0 根据 CPU 计算 降低并行查询波动
wal_writer_delay 10ms 20ms 更频繁处理 WAL
wal_writer_flush_after 0 1MB 改变 WAL 刷写行为
idle_replication_slot_timeout 3d 7d 更快清理闲置复制槽
idle_in_transaction_session_timeout 1min 10min 更快终止空闲事务
track_activity_query_size 32KiB 8KiB 保留更长查询文本
log_connections 详细连接事件 PostgreSQL 18 默认记录授权 增加连接审计信息
log_disconnections on off 记录断开事件

CRIT 还会禁用单个查询的并行 gather,并调整并行成本、autovacuum、WAL 和统计参数。完整值以实际版本的 roles/pgsql/templates/crit.yml 为准。


预加载扩展

CRIT 使用 pg_libs 生成 shared_preload_libraries。由于角色默认值已经将 pg_libs 设置为:

pg_libs: 'pg_stat_statements, auto_explain'

单独选择 crit.yml 不会自动加载 passwordcheck。需要口令复杂度检查时应显式配置:

pg_libs: '$libdir/passwordcheck, pg_stat_statements, auto_explain'

ha/safe 已包含该覆盖值。需要 pgaudit 时,也应显式加入 pg_libs 并配置审计范围:

pg_libs: '$libdir/passwordcheck, pg_stat_statements, auto_explain, pgaudit'
pg_parameters:
  pgaudit.log: 'ddl, role, write'

性能与可用性影响

  • 同步提交需要等待同步副本,写入延迟至少包含副本网络与 WAL 持久化时间;
  • 严格同步模式在没有可用同步副本时阻塞写入;
  • 禁用并行 gather 可能降低大型查询吞吐,但减少并行执行造成的资源波动;
  • 更详细的日志和统计会增加 I/O、CPU 与存储占用;
  • 更短的空闲事务超时可能终止长时间保持事务但未执行语句的应用会话。

影响大小取决于硬件、网络、查询和客户端行为,应使用实际负载测试,不宜采用固定的延迟或吞吐百分比。


上线检查

  • 至少部署一个可用同步副本,并验证节点故障时的写入行为
  • 检查应用是否修改 synchronous_commit
  • 根据可用性要求选择 watchdog automaticrequired
  • 验证连接日志的采集、访问权限和保留周期
  • 需要口令检查或 SQL 审计时,显式配置 pg_libs 和扩展参数
  • 使用生产负载测试写入延迟、吞吐和空闲事务超时
  • 执行主库、同步副本、DCS 和网络分区故障演练

相关文档

8.15.5 - TINY 模板

针对微型实例和资源受限环境优化的 PostgreSQL 配置模板

tiny.yml 是针对 微型实例 和资源受限环境优化的配置模板。适用于 1-3 核 CPU 的服务器,特点是最小化资源占用、保守的内存分配、禁用并行查询。

建议同时使用 node_tune = tiny 进行操作系统级别的配套调优。


适用场景

TINY 模板适用于以下场景:

  • 开发测试:本地开发环境、CI/CD 测试
  • 低配虚拟机:1-2 核 CPU、1-4GB 内存的云主机
  • 边缘计算:树莓派、嵌入式设备
  • Demo 演示:快速体验 Pigsty 功能
  • 个人项目:资源有限的个人博客、小型应用

资源限制

  • 1-3 核 CPU
  • 1-8 GB 内存
  • 有限的磁盘空间
  • 可能与其他服务共享资源

使用方法

在集群定义中指定 pg_conf = tiny.yml

pg-dev:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-dev
    pg_conf: tiny.yml    # PostgreSQL 微型实例模板
    node_tune: tiny      # 操作系统微型实例调优

单节点开发环境:

pg-local:
  hosts:
    127.0.0.1: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-local
    pg_conf: tiny.yml    # PostgreSQL 微型实例模板
    node_tune: tiny      # 操作系统微型实例调优

参数详解

连接管理

max_connections: 250   # OLTP: 500-1000,减少连接开销
superuser_reserved_connections: 10

微型实例不需要处理大量并发连接,250 个连接足以应对开发测试场景。

内存配置

TINY 模板使用保守的内存分配策略:

参数 计算公式 说明
shared_buffers 内存 × pg_shared_buffer_ratio 默认比例 0.25
maintenance_work_mem shared_buffers × 25% 用于 VACUUM、CREATE INDEX
work_mem 16MB - 256MB 更小的排序/哈希内存
effective_cache_size 总内存 - shared_buffers 可用于缓存的预估内存

work_mem 计算逻辑(与 OLTP 不同):

work_mem = min(max(shared_buffers / max_connections, 16MB), 256MB)

更小的 work_mem 上限(256MB vs OLTP 的 1GB)避免内存溢出。

并行查询(完全禁用)

TINY 模板完全禁用了并行查询:

max_worker_processes: max(cpu + 12, 20)     # OLTP: max(cpu + 16, 24)
max_parallel_workers: 50% × cpu (最小1)      # OLTP: 50% (最小2)
max_parallel_workers_per_gather: 0           # 禁用并行查询
max_parallel_maintenance_workers: 33% × cpu (最小1)

max_parallel_workers_per_gather: 0 确保查询不会启动并行工作进程,避免在低核心环境下争抢资源。

IO 配置(PG18)

io_workers: 3   # 固定值,OLTP: 25% cpu (4-16)

固定的低 IO 工作线程数量,适合资源受限环境。

Vacuum 配置

vacuum_cost_delay: 20ms
vacuum_cost_limit: 2000
autovacuum_max_workers: 2          # OLTP: 3,减少一个工作进程
autovacuum_naptime: 1min
# autovacuum_vacuum_scale_factor 使用默认值
# autovacuum_analyze_scale_factor 使用默认值

减少 autovacuum 工作进程数量,降低后台资源占用。

查询优化

random_page_cost: 1.1
effective_io_concurrency: 200
default_statistics_target: 200     # OLTP: 400,降低统计精度以节省空间

较低的 default_statistics_target 减少 pg_statistic 表的大小。

日志配置

log_min_duration_statement: 100    # 与 OLTP 相同
log_statement: ddl
log_checkpoints: on
log_lock_waits: on
log_temp_files: 1024
# log_connections 使用默认设置(不额外记录)

TINY 模板不启用额外的连接日志,以减少日志量。

客户端超时

deadlock_timeout: 50ms
idle_in_transaction_session_timeout: 10min   # 与 OLTP 相同

扩展配置

shared_preload_libraries: 'pg_stat_statements, auto_explain'

pg_stat_statements.max: 2500      # OLTP: 10000,减少内存占用
pg_stat_statements.track: all
pg_stat_statements.track_utility: off
pg_stat_statements.track_planning: off

pg_stat_statements.max 从 10000 降到 2500,减少约 75% 的内存占用。


与 OLTP 模板的主要差异

参数 TINY OLTP 差异原因
max_connections 250 500-1000 减少连接开销
work_mem 上限 256MB 1GB 避免内存溢出
max_worker_processes max(cpu+12, 20) max(cpu+16, 24) 减少后台进程
max_parallel_workers_per_gather 0 20% cpu 禁用并行查询
autovacuum_max_workers 2 3 减少后台负载
default_statistics_target 200 400 节省空间
pg_stat_statements.max 2500 10000 减少内存占用
io_workers 3 25% cpu 固定低值

资源估算

以下是 TINY 模板在不同配置下的资源使用估算:

1 核 1GB 内存

shared_buffers: ~256MB
work_mem: ~16MB
maintenance_work_mem: ~64MB
max_connections: 250
max_worker_processes: 20

PostgreSQL 进程内存占用:约 400-600MB

2 核 4GB 内存

shared_buffers: ~1GB
work_mem: ~32MB
maintenance_work_mem: ~256MB
max_connections: 250
max_worker_processes: 20

PostgreSQL 进程内存占用:约 1.5-2GB

4 核 8GB 内存

此配置建议使用 OLTP 模板而非 TINY 模板:

pg-small:
  vars:
    pg_conf: oltp.yml   # 4核8GB可以使用OLTP模板

性能调优建议

进一步减少资源

如果资源极度受限,可以考虑:

pg_parameters:
  max_connections: 100           # 进一步减少
  shared_buffers: 128MB          # 进一步减少
  maintenance_work_mem: 32MB
  work_mem: 8MB

禁用不需要的扩展

pg_libs: 'pg_stat_statements'    # 只保留必要扩展

关闭不需要的功能

pg_parameters:
  track_io_timing: off           # 禁用 IO 时间跟踪
  track_functions: none          # 禁用函数跟踪

使用外部连接池

即使在微型实例上,使用 PgBouncer 也能显著提高并发能力:

pg-tiny:
  vars:
    pg_conf: tiny.yml
    pg_default_service_dest: pgbouncer
    pgbouncer_poolmode: transaction

云平台推荐规格

AWS

  • t3.micro:1 vCPU, 1GB RAM - 适合 TINY
  • t3.small:2 vCPU, 2GB RAM - 适合 TINY
  • t3.medium:2 vCPU, 4GB RAM - 可考虑 OLTP

阿里云

  • ecs.t6-c1m1.small:1 vCPU, 1GB RAM - 适合 TINY
  • ecs.t6-c1m2.small:1 vCPU, 2GB RAM - 适合 TINY
  • ecs.t6-c1m4.small:1 vCPU, 4GB RAM - 适合 TINY

腾讯云

  • SA2.SMALL1:1 vCPU, 1GB RAM - 适合 TINY
  • SA2.SMALL2:1 vCPU, 2GB RAM - 适合 TINY
  • SA2.SMALL4:1 vCPU, 4GB RAM - 适合 TINY

边缘设备部署

树莓派 4

pg-pi:
  hosts:
    192.168.1.100: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-pi
    pg_conf: tiny.yml       # PostgreSQL 微型实例模板
    node_tune: tiny         # 操作系统微型实例调优
    pg_storage_type: SSD    # 建议使用 SSD 存储

Docker 容器

pg-docker:
  hosts:
    172.17.0.2: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-docker
    pg_conf: tiny.yml       # PostgreSQL 微型实例模板
    node_tune: tiny         # 操作系统微型实例调优

升级到 OLTP

当您的应用增长,需要更多资源时,可以轻松升级到 OLTP 模板

  1. 升级虚拟机规格(4核 8GB 以上)
  2. 修改集群配置:
pg-growing:
  vars:
    pg_conf: oltp.yml    # 从 tiny.yml 改为 oltp.yml
    node_tune: oltp      # 从 tiny 改为 oltp
  1. 重新配置集群 或重新部署

参考资料

8.16 - 常见问题

PostgreSQL 常见问题答疑

我当前执行安装的用户为何不能使用 pg 管理别名?

从 Pigsty v4.0 开始,使用 pg 管理别名管理全局的 Patroni / PostgreSQL 集群的权限被收紧到了管理节点上的管理员分组(admin)。

node.yml 剧本创建的管理员(dba)默认具有此权限,而其他用户如果想要获得这个权限,需要你显式地将该用户加入到 admin 组中。

sudo usermod -aG admin <username>

PGSQL初始化失败:Fail to wait for postgres/patroni primary

这种错误信息存在多种可能,需要你 检查 Ansible,Systemd / Patroni / PostgreSQL 日志,找出真正的原因。

  • 可能性1:集群配置错误,找出错误的配置项修改并应用。
  • 可能性2:在部署中存在同名集群,或者之前的同名集群主节点被不正确地移除
  • 可能性3:在 DCS 中有同名集群残留的垃圾元数据。先用 etcdctl get --prefix /pg/<cls>/ 核对精确键空间;确认备份与完整集群名后,才可用 etcdctl del --prefix /pg/<cls>/ 清理。末尾 / 是边界,不能省略,否则会同时匹配名称以该集群名开头的其他集群。这是破坏性操作,优先使用受控的下线流程。
  • 可能性4:你的 PostgreSQL 或节点相关 RPM 包没有被成功安装
  • 可能性5:你的 Watchdog 内核模块没有正确启用加载
  • 可能性6:你在初始化数据库时指定的语言 Locale 不存在(例如,使用了 en_US.UTF8,但没有安装英文语言包或 Locale 支持)
  • 如果你遇到了其他的原因,欢迎提交 Issue 或向社区求助。

PGSQL初始化失败:Fail to wait for postgres/patroni replica

存在几种可能的原因:

立即失败:通常是由于配置错误、网络问题、损坏的 DCS 元数据等原因。你必须检查 /pg/log 找出实际原因。

过了一会儿失败:这可能是由于源实例数据损坏。查看 PGSQL FAQ:如何在数据损坏时创建副本?

过了很长时间再超时:如果 wait for postgres replica 任务耗时 30 分钟或更长时间并由于超时而失败,这对于大型集群(例如,1TB+,可能需要几小时创建一个副本)是很常见的。

在这种情况下,底层创建副本的过程仍在进行。你可以使用 pg list <cls> 检查集群状态并等待副本赶上主节点。然后使用以下命令继续以下任务,完成完整的从库初始化:

./pgsql.yml -t pg_hba,pg_reload,pg_backup,pgbouncer,pg_vip,pg_dns,pg_service,pg_exporter,pg_register -l <problematic_replica>

PGSQL初始化失败:ABORT due to pg_safeguard enabled

这意味着正准备清理的 PostgreSQL 实例打开了防误删保险, 禁用 pg_safeguard 以移除 Postgres 实例。

如果防误删保险 pg_safeguard 打开,那么你就不能使用 bin/pgsql-rmpgsql-rm.yml 剧本移除正在运行的 PGSQL 实例了。

要禁用 pg_safeguard,你可以在配置清单中将 pg_safeguard 设置为 false,或者在执行剧本时使用命令参数 -e pg_safeguard=false

./pgsql-rm.yml -e pg_safeguard=false -l <cls_to_remove>    # 强制覆盖 pg_safeguard

如何确保故障转移中数据不丢失?

使用 crit.yml 参数模板,设置 pg_rpo0,或 配置集群 为同步提交模式。

考虑使用 同步备库法定多数提交 来确保故障转移过程中的零数据丢失。

更多细节,可以参考 安全考量 - 可用性 的相关介绍。


磁盘写满了如何抢救?

如果磁盘写满了,连 Shell 命令都无法执行,rm -rf /pg/dummy 可以释放一些救命空间。

默认情况下,pg_dummy_filesize 设置为 64MB。在生产环境中,建议将其增加到 8GB 或更大。

它将被放置在 PGSQL 主数据磁盘上的 /pg/dummy 路径下。你可以删除该文件以释放一些紧急空间:

至少可以让你在该节点上运行一些 shell 脚本来进一步回收其他空间(例如日志/WAL,过时数据,WAL 归档与备份)。


当集群数据已经损坏时如何创建副本?

Pigsty 在所有实例的 patroni 配置中设置了 clonefrom: true 标签,标记该实例可用于创建副本。

如果某个实例有损坏的数据文件,导致创建新副本的时候出错中断,那么你可以设置 clonefrom: false 来避免从损坏的实例中拉取数据。具体操作如下

$ vi /etc/patroni/patroni.yml

tags:
  nofailover: false
  clonefrom: true      # ----------> change to false
  noloadbalance: false
  nosync: false
  version:  '18'
  spec: '4C.8G.50G'
  conf: 'oltp.yml'
  
$ systemctl reload patroni    # 重新加载 Patroni 配置

PostgreSQL 监控的性能损耗如何?

一个常规 PostgreSQL 实例抓取耗时大约 200ms。抓取间隔默认为 10 秒,对于一个生产多核数据库实例来说几乎微不足道。

请注意,Pigsty 默认开启了库内对象监控,所以如果您的数据库内有数以十万计的表/索引对象,抓取可能耗时会增加到几秒。

您可以修改 Prometheus 的抓取频率,请确保一点:抓取周期应当显著高于一次抓取的时长。


如何监控一个现存的 PostgreSQL 实例?

PGSQL Monitor 中提供了详细的监控配置说明。


如何手工从监控中移除 PostgreSQL 监控目标?

./pgsql-rm.yml -t rm_metrics -l <cls>     # 将集群 'cls' 的所有实例从 victoria 中移除
bin/pgmon-rm <ins>     # 用于从 Victoria 中移除单个实例 'ins' 的监控对象,特别适合移除添加的外部实例

8.17 - 其他说明

其他说明与杂项文档

8.17.1 - 用户/角色

用户/角色指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的逻辑对象。

在这里的上下文中,用户指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的逻辑对象。

在 PostgreSQL 中,用户直接隶属于数据库集簇而非某个具体的数据库。因此在创建业务数据库和业务用户时,应当遵循"先用户,后数据库"的原则。


定义用户

Pigsty 通过两个配置参数定义数据库集群中的角色与用户:

  • pg_default_roles:定义全局统一使用的角色和用户
  • pg_users:在数据库集群层面定义业务用户和角色

前者用于定义了整套环境中共用的角色与用户,后者定义单个集群中特有的业务角色与用户。二者形式相同,均为用户定义对象的数组。

你可以定义多个用户/角色,它们会按照先全局,后集群,最后按数组内排序的顺序依次创建,所以后面的用户可以属于前面定义的角色。

下面是 Pigsty 演示环境中默认集群 pg-meta 中的业务用户定义:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    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 }
      - {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     }
      - {name: dbuser_noco     ,password: DBUser.Noco     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for nocodb service      }

每个用户/角色定义都是一个 object,可能包括以下字段,以 dbuser_meta 用户为例:

- name: dbuser_meta               # 必需,`name` 是用户定义的唯一必选字段
  password: DBUser.Meta           # 可选,密码,可以是 scram-sha-256 哈希字符串或明文
  login: true                     # 可选,默认情况下可以登录
  superuser: false                # 可选,默认为 false,是超级用户吗?
  createdb: false                 # 可选,默认为 false,可以创建数据库吗?
  createrole: false               # 可选,默认为 false,可以创建角色吗?
  inherit: true                   # 可选,默认情况下,此角色可以使用继承的权限吗?
  replication: false              # 可选,默认为 false,此角色可以进行复制吗?
  bypassrls: false                # 可选,默认为 false,此角色可以绕过行级安全吗?
  pgbouncer: true                 # 可选,默认为 false,将此用户添加到 pgbouncer 用户列表吗?(使用连接池的生产用户应该显式定义为 true)
  connlimit: -1                   # 可选,用户连接限制,默认 -1 禁用限制
  expire_in: 3650                 # 可选,此角色过期时间:从创建时 + n天计算(优先级比 expire_at 更高)
  expire_at: '2030-12-31'         # 可选,此角色过期的时间点,使用 YYYY-MM-DD 格式的字符串指定一个特定日期(优先级没 expire_in 高)
  comment: pigsty admin user      # 可选,此用户/角色的说明与备注字符串
  roles: [dbrole_admin]           # 可选,默认角色为:dbrole_{admin,readonly,readwrite,offline}
  parameters: {}                  # 可选,使用 `ALTER ROLE SET` 针对这个角色,配置角色级的数据库参数
  pool_mode: transaction          # 可选,默认为 transaction 的 pgbouncer 池模式,用户级别
  pool_connlimit: 100             # 可选,用户级连接池最大连接数;省略时继承全局默认 100
  search_path: public             # 可选,根据 postgresql 文档的键值配置参数(例如:使用 pigsty 作为默认 search_path)
  • 唯一必需的字段是 name,它应该是 PostgreSQL 集群中的一个有效且唯一的用户名。
  • 角色不需要 password,但对于可登录的业务用户,通常是需要指定一个密码的。
  • password 可以是明文或 scram-sha-256 / md5 哈希字符串,请最好不要使用明文密码。
  • 用户/角色按数组顺序逐一创建,因此,请确保角色/分组的定义在成员之前。
  • loginsuperusercreatedbcreateroleinheritreplicationbypassrls 是布尔标志。
  • pgbouncer 默认是禁用的:要将业务用户添加到 pgbouncer 用户列表,您应当显式将其设置为 true

ACL 系统

Pigsty 提供一套内置的访问控制 / ACL 模型,可以将默认业务角色分配给用户:

  • dbrole_readwrite:全局读写访问的角色(主属业务使用的生产账号应当具有数据库读写权限)
  • dbrole_readonly:全局只读访问的角色(如果别的业务想要只读访问,可以使用此角色)
  • dbrole_admin:拥有 DDL 权限的角色 (业务管理员,需要在应用中建表的场景)
  • dbrole_offline:独立的只读角色,通常用于个人查询、ETL 和分析任务;实例范围需要通过 HBA 显式限制

如果您希望重新设计您自己的 ACL 系统,可以考虑定制以下参数和模板:


创建用户

pg_default_rolespg_users定义 的用户和角色,将在集群初始化的 PROVISION 阶段中自动逐一创建。 如果您希望在现有的集群上 创建用户,可以使用 bin/pgsql-user 工具。 将新用户/角色定义添加到 all.children.<cls>.pg_users,并使用以下方法创建该数据库:

bin/pgsql-user <cls> <username>    # pgsql-user.yml -l <cls> -e username=<username>

不同于数据库,创建用户的剧本总是幂等的。当目标用户已经存在时,Pigsty 会修改目标用户的属性使其符合配置。所以在现有集群上重复运行它通常不会有问题。

请使用剧本创建用户

我们不建议您手工创建新的业务用户,特别当您想要创建的用户使用默认的 pgbouncer 连接池时:除非您愿意手工负责维护 Pgbouncer 中的用户列表并与 PostgreSQL 保持一致。 使用 bin/pgsql-user 工具或 pgsql-user.yml 剧本创建新数据库时,会将此数据库一并添加到 Pgbouncer用户 列表中。


修改用户

修改 PostgreSQL 用户的属性的方式与 创建用户 相同。

首先,调整您的用户定义,修改需要调整的属性,然后执行以下命令应用:

bin/pgsql-user <cls> <username>    # pgsql-user.yml -l <cls> -e username=<username>

请注意,修改用户不会删除用户,而是通过 ALTER USER 命令修改用户属性;也不会回收用户的权限与分组,并使用 GRANT 命令授予新的角色。


Pgbouncer用户

默认情况下启用 Pgbouncer,并作为连接池中间件,其用户默认被管理。

Pigsty 默认将 pg_users 中显式带有 pgbouncer: true 标志的所有用户添加到 pgbouncer 用户列表中。

Pgbouncer 连接池中的用户在 /etc/pgbouncer/userlist.txt 中列出:

"postgres" ""
"dbuser_wiki" "SCRAM-SHA-256$4096:+77dyhrPeFDT/TptHs7/7Q==$KeatuohpKIYzHPCt/tqBu85vI11o9mar/by0hHYM2W8=:X9gig4JtjoS8Y/o1vQsIX/gY1Fns8ynTXkbWOjUfbRQ="
"dbuser_view" "SCRAM-SHA-256$4096:DFoZHU/DXsHL8MJ8regdEw==$gx9sUGgpVpdSM4o6A2R9PKAUkAsRPLhLoBDLBUYtKS0=:MujSgKe6rxcIUMv4GnyXJmV0YNbf39uFRZv724+X1FE="
"dbuser_monitor" "SCRAM-SHA-256$4096:fwU97ZMO/KR0ScHO5+UuBg==$CrNsmGrx1DkIGrtrD1Wjexb/aygzqQdirTO1oBZROPY=:L8+dJ+fqlMQh7y4PmVR/gbAOvYWOr+KINjeMZ8LlFww="
"dbuser_meta" "SCRAM-SHA-256$4096:leB2RQPcw1OIiRnPnOMUEg==$eyC+NIMKeoTxshJu314+BmbMFpCcspzI3UFZ1RYfNyU=:fJgXcykVPvOfro2MWNkl5q38oz21nSl1dTtM65uYR1Q="
"dbuser_kong" "SCRAM-SHA-256$4096:bK8sLXIieMwFDz67/0dqXQ==$P/tCRgyKx9MC9LH3ErnKsnlOqgNd/nn2RyvThyiK6e4=:CDM8QZNHBdPf97ztusgnE7olaKDNHBN0WeAbP/nzu5A="
"dbuser_grafana" "SCRAM-SHA-256$4096:HjLdGaGmeIAGdWyn2gDt/Q==$jgoyOB8ugoce+Wqjr0EwFf8NaIEMtiTuQTg1iEJs9BM=:ed4HUFqLyB4YpRr+y25FBT7KnlFDnan6JPVT9imxzA4="
"dbuser_gitea" "SCRAM-SHA-256$4096:l1DBGCc4dtircZ8O8Fbzkw==$tpmGwgLuWPDog8IEKdsaDGtiPAxD16z09slvu+rHE74=:pYuFOSDuWSofpD9OZhG7oWvyAR0PQjJBffgHZLpLHds="
"dbuser_dba" "SCRAM-SHA-256$4096:zH8niABU7xmtblVUo2QFew==$Zj7/pq+ICZx7fDcXikiN7GLqkKFA+X5NsvAX6CMshF0=:pqevR2WpizjRecPIQjMZOm+Ap+x0kgPL2Iv5zHZs0+g="
"dbuser_bytebase" "SCRAM-SHA-256$4096:OMoTM9Zf8QcCCMD0svK5gg==$kMchqbf4iLK1U67pVOfGrERa/fY818AwqfBPhsTShNQ=:6HqWteN+AadrUnrgC0byr5A72noqnPugItQjOLFw0Wk="

而用户级别的连接池参数则是使用另一个单独的文件: /etc/pgbouncer/useropts.txt 进行维护,比如:

dbuser_dba                  = pool_mode=session max_user_connections=16
dbuser_monitor              = pool_mode=session max_user_connections=8

当您 创建数据库 时,Pgbouncer 的数据库列表定义文件将会被刷新,并通过在线重载配置的方式生效,不会影响现有的连接。

Pgbouncer 使用和 PostgreSQL 同样的 dbsu 运行,默认为 postgres 操作系统用户,您可以使用 pgb 别名,使用 dbsu 访问 pgbouncer 管理功能。

连接池用户配置文件 userlist.txtuseropts.txt 会在您 创建用户 时自动刷新,并通过在线重载配置的方式生效,正常不会影响现有的连接。

请注意,pgbouncer_auth_query 参数允许你使用动态查询来完成连接池用户认证,当您懒得管理连接池中的用户时,这是一种折中的方案。

8.17.2 - 数据库

数据库指的是使用 SQL 命令 CREATE DATABASE 创建的,数据库集簇内的逻辑对象。

在这里的上下文中,数据库指的是使用 SQL 命令 CREATE DATABASE 创建的,数据库集簇内的逻辑对象。

一组 PostgreSQL 服务器可以同时服务于多个 数据库 (Database)。在 Pigsty 中,你可以在集群配置中 定义 好所需的数据库。

Pigsty 会对默认模板数据库 template1 进行修改与定制,创建默认模式,安装默认扩展,配置默认权限,新创建的数据库默认会从 template1 继承这些设置。

默认情况下,所有业务数据库都会被1:1添加到 Pgbouncer 连接池中;pg_exporter 默认会通过 自动发现 机制查找所有业务数据库并进行库内对象监控。


定义数据库

业务数据库定义在数据库集群参数 pg_databases 中,这是一个数据库定义构成的对象数组。 数组内的数据库按照 定义顺序 依次创建,因此后面定义的数据库可以使用先前定义的数据库作为 模板

下面是 Pigsty 演示环境中默认集群 pg-meta 中的数据库定义:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_databases:
      - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [{name: postgis, schema: public}, {name: timescaledb}]}
      - { 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 }
      - { name: noco     ,owner: dbuser_noco     ,revokeconn: true ,comment: nocodb database }

每个数据库定义都是一个 object,可能包括以下字段,以 meta 数据库为例:

- name: meta                      # 必选,`name` 是数据库定义的唯一必选字段
  baseline: cmdb.sql              # 可选,数据库 sql 的基线定义文件路径(ansible 搜索路径中的相对路径,如 files/)
  pgbouncer: true                 # 可选,是否将此数据库添加到 pgbouncer 数据库列表?默认为 true
  schemas: [pigsty]               # 可选,要创建的附加模式,由模式名称字符串组成的数组
  extensions:                     # 可选,要安装的附加扩展: 扩展对象的数组
    - { name: postgis , schema: public }  # 可以指定将扩展安装到某个模式中,也可以不指定(不指定则安装到 search_path 首位模式中)
    - { name: timescaledb }               # 例如有的扩展会创建并使用固定的模式,就不需要指定模式。
  comment: pigsty meta database   # 可选,数据库的说明与备注信息
  owner: postgres                 # 可选,数据库所有者,默认为 postgres
  template: template1             # 可选,要使用的模板,默认为 template1,目标必须是一个模板数据库
  encoding: UTF8                  # 可选,数据库编码,默认为 UTF8(必须与模板数据库相同)
  locale: C                       # 可选,数据库地区设置,默认为 C(必须与模板数据库相同)
  lc_collate: C                   # 可选,数据库 collate 排序规则,默认为 C(必须与模板数据库相同),没有理由不建议更改。
  lc_ctype: C                     # 可选,数据库 ctype 字符集,默认为 C(必须与模板数据库相同)
  tablespace: pg_default          # 可选,默认表空间,默认为 'pg_default'
  allowconn: true                 # 可选,是否允许连接,默认为 true。显式设置 false 将完全禁止连接到此数据库
  revokeconn: false               # 可选,撤销公共连接权限。默认为 false,设置为 true 时,属主和管理员之外用户的 CONNECT 权限会被回收
  register_datasource: true       # 可选,是否将此数据库注册到 grafana 数据源?默认为 true,显式设置为 false 会跳过注册
  connlimit: -1                   # 可选,数据库连接限制,默认为 -1 ,不限制,设置为正整数则会限制连接数。
  pool_auth_user: dbuser_meta     # 可选,连接到此 pgbouncer 数据库的所有连接都将使用此用户进行验证(启用 pgbouncer_auth_query 才有用)
  pool_mode: transaction          # 可选,数据库级别的 pgbouncer 池化模式,默认为 transaction
  pool_size: 50                   # 可选,数据库级别的 pgbouncer 默认池子大小,默认为 50
  pool_reserve: 30                # 可选,数据库级别的 pgbouncer 池子保留空间,默认为 30,当默认池子不够用时,最多再申请这么多条突发连接。
  pool_size_min: 0                # 可选,数据库级别的 pgbouncer 池的最小大小,默认为 0
  pool_connlimit: 100           # 可选,数据库级别的最大数据库连接数,默认为 100

唯一必选的字段是 name,它应该是当前 PostgreSQL 集群中有效且唯一的数据库名称,其他参数都有合理的默认值。

  • name:数据库名称,必选项
  • baseline:SQL 文件路径(Ansible 搜索路径,通常位于 files),用于初始化数据库内容。
  • owner:数据库属主,默认为 postgres
  • template:数据库创建时使用的模板,默认为 template1
  • encoding:数据库默认字符编码,默认为 UTF8,默认与实例保持一致。建议不要配置与修改。
  • locale:数据库默认的本地化规则,默认为 C,建议不要配置,与实例保持一致。
  • lc_collate:数据库默认的本地化字符串排序规则,默认与实例设置相同,建议不要修改,必须与模板数据库一致。强烈建议不要配置,或配置为 C
  • lc_ctype:数据库默认的 LOCALE,默认与实例设置相同,建议不要修改或设置,必须与模板数据库一致。建议配置为 C 或 en_US.UTF8
  • allowconn:是否允许连接至数据库,默认为 true,不建议修改。
  • revokeconn:是否回收连接至数据库的权限?默认为 false。如果为 true,则数据库上的 PUBLIC CONNECT 权限会被回收。只有默认用户(dbsu|monitor|admin|replicator|owner)可以连接。此外,admin|owner 会拥有 GRANT OPTION,可以赋予其他用户连接权限。
  • tablespace:数据库关联的表空间,默认为 pg_default
  • connlimit:数据库连接数限制,默认为 -1,即没有限制。
  • extensions:对象数组,每一个对象定义了一个数据库中的 扩展,以及其安装的 模式
  • parameters:KV 对象,每一个 KV 定义了一个需要针对数据库通过 ALTER DATABASE 修改的参数。
  • pgbouncer:布尔选项,是否将该数据库加入到 Pgbouncer 中。所有数据库都会加入至 Pgbouncer 列表,除非显式指定 pgbouncer: false
  • comment:数据库备注信息。
  • pool_auth_user:启用 pgbouncer_auth_query 时,连接到此 pgbouncer 数据库的所有连接都将使用这里指定的用户执行认证查询。你需要使用一个具有访问 pg_shadow 表权限的用户。
  • pool_mode:数据库级别的 pgbouncer 池化模式,默认为 transaction,即事物池化。如果留空,会使用 pgbouncer_poolmode 参数作为默认值。
  • pool_size:数据库级别的 pgbouncer 默认池子大小,默认为 50
  • pool_reserve:数据库级别的 pgbouncer 池子保留空间,默认为 30,当默认池子不够用时,最多再申请这么多条突发连接。
  • pool_size_min: 数据库级别的 pgbouncer 池的最小大小,默认为 0
  • pool_connlimit: 数据库级别的 pgbouncer 连接池最大数据库连接数,默认为 100

新创建的数据库默认会从 template1 数据库 Fork 出来,这个模版数据库会在 PG_PROVISION 阶段进行定制修改: 配置好扩展,模式以及默认权限,因此新创建的数据库也会继承这些配置,除非您显式使用一个其他的数据库作为模板。

关于数据库访问权限,请参考 访问控制:数据库隔离


创建数据库

pg_databases定义 的数据库将在集群初始化时自动创建。 如果您希望在现有集群上 创建数据库,可以使用 bin/pgsql-db 包装脚本。 将新的数据库定义添加到 all.children.<cls>.pg_databases 中,并使用以下命令创建该数据库:

bin/pgsql-db <cls> <dbname>    # pgsql-db.yml -l <cls> -e dbname=<dbname>

下面是新建数据库时的一些注意事项:

创建数据库的剧本默认为幂等剧本,不过当您当使用 baseline 脚本时就不一定了:这种情况下,通常不建议在现有数据库上重复执行此操作,除非您确定所提供的 baseline SQL 也是幂等的。

我们不建议您手工创建新的数据库,特别当您使用默认的 pgbouncer 连接池时:除非您愿意手工负责维护 Pgbouncer 中的数据库列表并与 PostgreSQL 保持一致。 使用 pgsql-db 工具或 pgsql-db.yml 剧本创建新数据库时,会将此数据库一并添加到 Pgbouncer 数据库 列表中。

如果您的数据库定义有一个非常规 owner(默认为 dbsu postgres),那么请确保在创建该数据库前,属主用户已经存在。 最佳实践永远是在创建数据库之前 创建 用户


Pgbouncer数据库

Pigsty 会默认为 PostgreSQL 实例 1:1 配置启用一个 Pgbouncer 连接池,使用 /var/run/postgresql Unix Socket 通信。

连接池可以优化短连接性能,降低并发征用,以避免过高的连接数冲垮数据库,并在数据库迁移时提供额外的灵活处理空间。

Pigsty 默认将 pg_databases 中的所有数据库都添加到 pgbouncer 的数据库列表中。 您可以通过在数据库 定义 中显式设置 pgbouncer: false 来禁用特定数据库的 pgbouncer 连接池支持。

Pgbouncer 数据库列表在 /etc/pgbouncer/database.txt 中定义,数据库定义中关于连接池的参数会体现在这里:

meta                        = host=/var/run/postgresql mode=session
grafana                     = host=/var/run/postgresql mode=transaction
bytebase                    = host=/var/run/postgresql auth_user=dbuser_meta
kong                        = host=/var/run/postgresql pool_size=32 reserve_pool=64
gitea                       = host=/var/run/postgresql min_pool_size=10
wiki                        = host=/var/run/postgresql
noco                        = host=/var/run/postgresql
mongo                       = host=/var/run/postgresql

当您 创建数据库 时,Pgbouncer 的数据库列表定义文件将会被刷新,并通过在线重载配置的方式生效,正常不会影响现有的连接。

Pgbouncer 使用和 PostgreSQL 同样的 dbsu 运行,默认为 postgres 操作系统用户,您可以使用 pgb 别名,使用 dbsu 访问 pgbouncer 管理功能。

若要把某个托管数据库的 Pgbouncer 流量切换到其他节点,应修改实际承载路由的 /etc/pgbouncer/database.txt,然后依次重载配置并重建已有服务端连接:

# 仅修改 mydb 的后端目标
sed -i -E '/^mydb[[:space:]]*=/ s#host=[^[:space:]]+#host=10.10.10.12#' /etc/pgbouncer/database.txt
pgb -c "RELOAD;"
pgb -c "RECONNECT mydb;"
pgb -c "WAIT_CLOSE mydb;"

当前源码附带的 pgb-route 函数只修改 /etc/pgbouncer/pgbouncer.ini,而 Pigsty 管理的数据库路由位于被该文件 include 的 database.txt 中,因此它不会改变这些托管路由;请勿用它替代上述操作。

8.17.3 - 服务/接入

分离读写操作,正确路由流量,稳定可靠地交付 PostgreSQL 集群提供的能力。

分离读写操作,正确路由流量,稳定可靠地交付 PostgreSQL 集群提供的能力。

服务 是一种抽象:它是数据库集群对外提供能力的形式,并封装了底层集群的细节。

服务对于生产环境中的 稳定接入 至关重要,在 高可用 集群自动故障时方显其价值,单机用户 通常不需要操心这个概念。


单机用户

“服务” 的概念是给生产环境用的,个人用户/单机集群可以不折腾,直接拿实例名/IP 地址访问数据库。

例如,Pigsty 默认的单节点 pg-meta.meta 数据库,就可以直接用下面三个不同的用户连接上去。

psql postgres://dbuser_dba:[email protected]/meta     # 直接用 DBA 超级用户连上去
psql postgres://dbuser_meta:[email protected]/meta   # 用默认的业务管理员用户连上去
psql postgres://dbuser_view:DBUser.Viewer@pg-meta/meta     # 用默认的只读用户走实例域名连上去

服务概述

在真实世界生产环境中,我们会使用基于复制的主从数据库集群。集群中有且仅有一个实例作为领导者(主库)可以接受写入。 而其他实例(从库)则会从持续从集群领导者获取变更日志,与领导者保持一致。同时,从库还可以承载只读请求,在读多写少的场景下可以显著分担主库的负担, 因此对集群的写入请求与只读请求进行区分,是一种十分常见的实践。

此外对于高频短连接的生产环境,我们还会通过连接池中间件(Pgbouncer)对请求进行池化,减少连接与后端进程的创建开销。但对于 ETL 与变更执行等场景,我们又需要绕过连接池,直接访问数据库。 同时,高可用集群在故障时会出现故障切换(Failover),故障切换会导致集群的领导者出现变更。因此高可用的数据库方案要求写入流量可以自动适配集群的领导者变化。 这些不同的访问需求(读写分离,池化与直连,故障切换自动适配)最终抽象出 服务 (Service)的概念。

通常来说,数据库集群都必须提供这种最基础的服务:

  • 读写服务(primary):可以读写数据库

对于生产数据库集群,至少应当提供这两种服务:

  • 读写服务(primary):写入数据:只能由主库所承载。
  • 只读服务(replica):读取数据:可以由从库承载,没有从库时也可由主库承载

此外,根据具体的业务场景,可能还会有其他的服务,例如:

  • 默认直连服务(default):允许(管理)用户,绕过连接池直接访问数据库的服务
  • 离线从库服务(offline):不承接线上只读流量的专用从库,用于 ETL 与分析查询
  • 同步从库服务(standby):没有复制延迟的只读服务,由 同步备库/主库处理只读查询
  • 延迟从库服务(delayed):访问同一个集群在一段时间之前的旧数据,由 延迟从库 来处理

默认服务

Pigsty 默认为每个 PostgreSQL 数据库集群提供四种不同的服务,以下是默认服务及其定义:

服务 端口 描述
primary 5433 生产读写,连接到主库连接池(6432)
replica 5434 生产只读,连接到备库连接池(6432)
default 5436 管理,ETL 写入,直接访问主库(5432)
offline 5438 OLAP、ETL、个人用户、交互式查询

以默认的 pg-meta 集群为例,它提供四种默认服务:

psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5433/meta   # pg-meta-primary : 通过主要的 pgbouncer(6432) 进行生产读写
psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5434/meta   # pg-meta-replica : 通过备份的 pgbouncer(6432) 进行生产只读
psql postgres://dbuser_dba:DBUser.DBA@pg-meta:5436/meta     # pg-meta-default : 通过主要的 postgres(5432) 直接连接
psql postgres://dbuser_stats:DBUser.Stats@pg-meta:5438/meta # pg-meta-offline : 通过离线的 postgres(5432) 直接连接

从示例集群 架构图 上可以看出这四种服务的工作方式:

pigsty-ha.png

这里 pg-meta 的实际 DNS 目标由 pg_dns_target 决定:默认 auto 在启用 L2 VIP 时指向 VIP,否则指向清单中的主实例 IP。默认配置并不启用 VIP,详见 服务接入


服务实现

在 Pigsty 中,服务使用 节点 上的 haproxy 来实现,通过主机节点上的不同端口进行区分。

Pigsty 所纳管的每个节点上都默认启用了 Haproxy 以对外暴露服务,而数据库节点也不例外。 集群中的节点尽管从数据库的视角来看有主从之分,但从服务的视角来看,每个节点都是相同的: 这意味着即使您访问的是从库节点,只要使用正确的服务端口,就依然可以使用到主库读写的服务。 这样的设计可以屏蔽复杂度:所以您只要可以访问 PostgreSQL 集群上的任意一个实例,就可以完整的访问到所有服务。

这样的设计类似于 Kubernetes 中的 NodePort 服务,同样在 Pigsty 中,每一个服务都包括以下两个核心要素:

  1. 通过 NodePort 暴露的访问端点(端口号,从哪访问?)
  2. 通过 Selectors 选择的目标实例(实例列表,谁来承载?)

Pigsty 的服务交付边界止步于集群的 HAProxy,用户可以用各种手段访问这些负载均衡器,请参考 接入服务

所有的服务都通过配置文件进行声明,例如,PostgreSQL 默认服务就是由 pg_default_services 参数所定义的:

pg_default_services:
- { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
- { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
- { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
- { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}

您也可以在 pg_services 中定义额外的服务,参数 pg_default_servicespg_services 都是由 服务定义 对象组成的数组。


定义服务

Pigsty 允许您定义自己的服务:

  • pg_default_services:所有 PostgreSQL 集群统一对外暴露的服务,默认有四个。
  • pg_services:额外的 PostgreSQL 服务,可以视需求在全局或集群级别定义。
  • haproxy_services:直接定制 HAProxy 服务内容,可以用于其他组件的接入

对于 PostgreSQL 集群来说,通常只需要关注前两者即可。 每一条服务定义都会在所有相关 HAProxy 实例的配置目录下生成一个新的配置文件:/etc/haproxy/conf.d/<pg_cluster>-<service>.cfg 下面是一个自定义的服务样例 standby:当您想要对外提供没有复制延迟的只读服务时,就可以在 pg_services 新增这条记录:

- name: standby                   # 必选,服务名称,最终的 svc 名称会使用 `pg_cluster` 作为前缀,例如:pg-meta-standby
  port: 5435                      # 必选,暴露的服务端口(作为 kubernetes 服务节点端口模式)
  ip: "*"                         # 可选,服务绑定的 IP 地址,默认情况下为所有 IP 地址
  selector: "[]"                  # 必选,服务成员选择器,使用 JMESPath 来筛选配置清单
  backup: "[? pg_role == `primary`]"  # 可选,服务成员选择器(备份),也就是当默认选择器选中的实例都宕机后,服务才会由这里选中的实例成员来承载
  dest: default                   # 可选,目标端口,default|postgres|pgbouncer|<port_number>,默认为 'default',即由 pg_default_service_dest 决定
  check: /sync                    # 可选,健康检查 URL 路径,默认为 /,这里使用 Patroni API:/sync ,只有同步备库和主库才会返回 200 健康状态码 
  maxconn: 5000                   # 可选,允许的前端连接最大数,默认为5000
  balance: roundrobin             # 可选,haproxy 负载均衡算法(默认为 roundrobin,其他选项: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-test 上将会被转换为 HAProxy 配置文件 /etc/haproxy/conf.d/pg-test-standby.cfg

#---------------------------------------------------------------------
# service: pg-test-standby @ 10.10.10.11:5435
#---------------------------------------------------------------------
# service instances 10.10.10.11, 10.10.10.13, 10.10.10.12
# service backups   10.10.10.11
listen pg-test-standby
    bind *:5435            # <--- 绑定了所有IP地址上的 5435 端口
    mode tcp               # <--- 负载均衡器工作在 TCP 协议上
    maxconn 5000           # <--- 最大连接数为 5000,可按需调大
    balance roundrobin     # <--- 负载均衡算法为 rr 轮询,还可以使用 leastconn 
    option httpchk         # <--- 启用 HTTP 健康检查
    option http-keep-alive # <--- 保持HTTP连接
    http-check send meth OPTIONS uri /sync   # <---- 这里使用 /sync ,Patroni 健康检查 API ,只有同步备库和主库才会返回 200 健康状态码。 
    http-check expect status 200             # <---- 健康检查返回代码 200 代表正常
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers: # pg-test 集群全部三个实例都被 selector: "[]" 圈中,成为 pg-test-standby 服务的后端;/sync 健康检查只放行主库和同步备库。
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100 backup  # <----- 唯独主库满足条件 pg_role == `primary`, 被 backup selector 选中。
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100         #        因此作为服务的兜底实例:平时不承载请求,其他从库全部宕机后,才会承载只读请求,从而最大避免了读写服务受到只读服务的影响
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100         #        

在这里,pg-test 集群全部三个实例都被 selector: "[]" 给圈中了,渲染进入 pg-test-standby 服务的后端服务器列表中。但是因为还有 /sync 健康检查,Patroni Rest API 只有在主库和 同步备库 上才会返回代表健康的 HTTP 200 状态码,因此只有主库和同步备库才能真正承载请求。 此外,主库因为满足条件 pg_role == primary, 被 backup selector 选中,被标记为了备份服务器,只有当没有其他实例(也就是同步备库)可以满足需求时,才会顶上。


Primary服务

Primary 服务可能是生产环境中最关键的服务,它在 5433 端口提供对数据库集群的读写能力,服务定义如下:

- { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
  • 选择器参数 selector: "[]" 意味着所有集群成员都将被包括在 Primary 服务中
  • 但只有主库能够通过健康检查(check: /primary),实际承载 Primary 服务的流量。
  • 目的地参数 dest: default 意味着 Primary 服务的目的地受到 pg_default_service_dest 参数的影响
  • dest 默认值 default 会被替换为 pg_default_service_dest 的值,默认为 pgbouncer
  • 默认情况下 Primary 服务的目的地默认是主库上的连接池,也就是由 pgbouncer_port 指定的端口,默认为 6432

如果 pg_default_service_dest 的值为 postgres,那么 primary 服务的目的地就会绕过连接池,直接使用 PostgreSQL 数据库的端口(pg_port,默认值 5432),对于一些不希望使用连接池的场景,这个参数非常实用。

示例:pg-test-primary 的 haproxy 配置
listen pg-test-primary
    bind *:5433         # <--- primary 服务默认使用 5433 端口
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /primary # <--- primary 服务默认使用 Patroni RestAPI /primary 健康检查
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100

Patroni 的 高可用 机制确保任何时候最多只会有一个实例的 /primary 健康检查为真,因此 Primary 服务将始终将流量路由到主实例。

使用 Primary 服务而不是直连数据库的一个好处是,如果集群因为某种情况出现了双主(比如在没有 watchdog 的情况下 kill -9杀死主库 Patroni),Haproxy 在这种情况下仍然可以避免脑裂,因为它只会在 Patroni 存活且返回主库状态时才会分发流量。


Replica服务

Replica 服务在生产环境中的重要性仅次于 Primary 服务,它在 5434 端口提供对数据库集群的只读能力,服务定义如下:

- { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
  • 选择器参数 selector: "[]" 意味着所有集群成员都将被包括在 Replica 服务中
  • 所有实例都能够通过健康检查(check: /read-only),承载 Replica 服务的流量。
  • 备份选择器:[? pg_role == 'primary' || pg_role == 'offline' ] 将主库和 离线从库 标注为备份服务器。
  • 只有当所有 普通从库 都宕机后,Replica 服务才会由主库或离线从库来承载。
  • 目的地参数 dest: default 意味着 Replica 服务的目的地也受到 pg_default_service_dest 参数的影响
  • dest 默认值 default 会被替换为 pg_default_service_dest 的值,默认为 pgbouncer,这一点和 Primary服务 相同
  • 默认情况下 Replica 服务的目的地默认是从库上的连接池,也就是由 pgbouncer_port 指定的端口,默认为 6432
示例:pg-test-replica 的 haproxy 配置
listen pg-test-replica
    bind *:5434
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /read-only
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100 backup
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100

Replica 服务非常灵活:如果有存活的专用 Replica 实例,那么它会优先使用这些实例来承载只读请求,只有当从库实例全部宕机后,才会由主库来兜底只读请求。对于常见的一主一从双节点集群就是:只要从库活着就用从库,从库挂了再用主库。

此外,除非专用只读实例全部宕机,Replica 服务也不会使用专用 Offline 实例,这样就避免了在线快查询与离线慢查询混在一起,相互影响。


Default服务

Default 服务在 5436 端口上提供服务,它是 Primary 服务的变体。

Default 服务总是绕过连接池直接连到主库上的 PostgreSQL,这对于管理连接、ETL 写入、CDC 数据变更捕获等都很有用。

- { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }

如果 pg_default_service_dest 被修改为 postgres,那么可以说 Default 服务除了端口和名称内容之外,与 Primary 服务是完全等价的。在这种情况下,您可以考虑将 Default 从默认服务中剔除。

示例:pg-test-default 的 haproxy 配置
listen pg-test-default
    bind *:5436         # <--- 除了监听端口/目标端口和服务名,其他配置和 primary 服务一模一样
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /primary
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:5432 check port 8008 weight 100
    server pg-test-3 10.10.10.13:5432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:5432 check port 8008 weight 100

Offline服务

Offline 服务在 5438 端口上提供服务,它绕开连接池直接访问 PostgreSQL 数据库,通常用于慢查询/分析查询/ETL 读取/个人用户交互式查询,其服务定义如下:

- { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}

Offline 服务将流量直接路由到专用的 离线从库 上,或者带有 pg_offline_query 标记的普通 只读实例

  • 选择器参数从集群中筛选出了两种实例:pg_role = offline 的离线从库,或是带有 pg_offline_query = true 标记的普通 只读实例
  • 专用离线从库和打标记的普通从库主要的区别在于:前者默认不承载 Replica服务 的请求,避免快慢请求混在一起,而后者默认会承载。
  • 备份选择器参数从集群中筛选出了一种实例:不带 offline 标记的普通从库,这意味着如果离线实例或者带 Offline 标记的普通从库挂了之后,其他普通的从库可以用来承载 Offline 服务。
  • 健康检查 /replica 只会针对从库返回 200, 主库会返回错误,因此 Offline 服务 永远不会将流量分发到主库实例上去,哪怕集群中只剩这一台主库。
  • 同时,主库实例既不会被选择器圈中,也不会被备份选择器圈中,因此它永远不会承载 Offline 服务。因此 Offline 服务总是可以避免用户访问主库,从而避免对主库的影响。
示例:pg-test-offline 的 haproxy 配置
listen pg-test-offline
    bind *:5438
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /replica
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-3 10.10.10.13:5432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:5432 check port 8008 weight 100 backup

Offline 服务提供受限的只读服务,通常用于两类查询:交互式查询(个人用户),慢查询长事务(分析/ETL)。

Offline 服务需要额外的维护照顾:HAProxy 的 /replica 健康检查会在主从切换后自动拒绝新主库,但 selector 使用的是配置清单中的静态 pg_role / pg_offline_query 标签。对于一主一从、仅从库承载 Offline 查询的精简集群,切换后可能暂时没有合格后端。 仅重载未修改的清单并不会把原主库加入 Offline 后端。需要先按新的规划调整清单标签(或 pg_offline_query)再 重载服务,或者将主库切回原节点。

如果您的业务模型较为简单,您可以考虑剔除 Default 服务与 Offline 服务,使用 Primary 服务与 Replica 服务直连数据库。


重载服务

当集群成员发生变化(添加/删除副本)、服务定义或静态选择标签变化、相对权重调整时,需要 重载服务。Primary/Replica 服务的正常主备切换由 Patroni 健康检查自动接管,不需要为此单独重载。

bin/pgsql-svc <cls> [ip...]         # 为 lb 集群或 lb 实例重载服务
# ./pgsql.yml -t pg_service         # 重载服务的实际 ansible 任务

接入服务

Pigsty 的服务交付边界止步于集群的 HAProxy,用户可以用各种手段访问这些负载均衡器。

典型的做法是使用 DNS 或 VIP 接入,将其绑定在集群所有或任意数量的负载均衡器上。

pigsty-access.jpg

你可以使用不同的 主机 & 端口 组合,它们以不同的方式提供 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

组合

# 通过集群域名访问(以下示例假定已启用 L2 VIP;未启用时默认指向清单主实例 IP)
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://[email protected]:5432/test # L2 VIP -> 主直接访问
postgres://[email protected]:6432/test # L2 VIP -> 主连接池 -> 主
postgres://[email protected]:5433/test # L2 VIP -> HAProxy -> 主连接池 -> 主
postgres://[email protected]:5434/test # L2 VIP -> HAProxy -> 备份连接池 -> 备份
postgres://[email protected]:5436/test # L2 VIP -> HAProxy -> 主直接连接 (用于管理员)
postgres://[email protected]: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://[email protected]:5432/test # 数据库实例直接连接 (直接指定实例, 没有自动流量分配)
postgres://[email protected]:6432/test # 连接池 -> 数据库
postgres://[email protected]:5433/test # HAProxy -> 连接池 -> 数据库读/写
postgres://[email protected]:5434/test # HAProxy -> 连接池 -> 数据库只读
postgres://[email protected]:5436/test # HAProxy -> 数据库直接连接
postgres://[email protected]:5438/test # HAProxy -> 数据库离线读/写

# 智能客户端:自动进行读写分离
postgres://[email protected]:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=primary
postgres://[email protected]:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=prefer-standby

覆盖服务

你可以通过多种方式覆盖默认的服务配置,一种常见的需求是让 Primary服务Replica服务 绕过 Pgbouncer 连接池,直接访问 PostgreSQL 数据库。

为了实现这一点,你可以将 pg_default_service_dest 更改为 postgres,这样所有服务定义中 svc.dest='default' 的服务都会使用 postgres 而不是默认的 pgbouncer 作为目标。

如果您已经将 Primary服务 指向了 PostgreSQL,那么 default服务 就会比较多余,可以考虑移除。

如果您不需要区分个人交互式查询,分析/ETL 慢查询,可以考虑从默认服务列表 pg_default_services 中移除 Offline服务

如果您不需要只读从库来分担在线只读流量,也可以从默认服务列表中移除 Replica服务


委托服务

Pigsty 通过节点上的 haproxy 暴露 PostgreSQL 服务。整个集群中的所有 haproxy 实例都使用相同的 服务定义 进行配置。

但是,你可以将 pg 服务委托给特定的节点分组(例如,专门的 haproxy 负载均衡器集群),而不是 PostgreSQL 集群成员上的 haproxy。

为此,你需要使用 pg_default_services 覆盖默认的服务定义,并将 pg_service_provider 设置为代理组名称。

例如,此配置将在端口 10013 的 proxy haproxy 节点组上公开 pg 集群的主服务。

pg_service_provider: proxy       # 使用端口 10013 上的 `proxy` 组的负载均衡器
pg_default_services:  [{ name: primary ,port: 10013 ,dest: postgres  ,check: /primary   ,selector: "[]" }]

用户需要确保每个委托服务的端口,在代理集群中都是 唯一 的。

在 20 节点生产环境仿真 沙箱 中提供了一个使用专用负载均衡器集群的例子:conf/ha/simu.yml

8.17.4 - 认证 / HBA

Pigsty 中基于主机的身份认证 HBA(Host-Based Authentication)详解。

Pigsty 中基于主机的身份认证 HBA(Host-Based Authentication)详解。

认证是 访问控制默认权限 的基础,PostgreSQL 支持多种 认证 方法。

这里主要介绍 HBA:Host Based Authentication,HBA 规则定义了哪些用户能够通过哪些方式从哪些地方访问哪些数据库。


客户端认证

要连接到 PostgreSQL 数据库,用户必须先经过认证(默认使用密码)。

您可以在连接字符串中提供密码(不安全)或使用 PGPASSWORD 环境变量或 .pgpass 文件传递密码。参考 psql 文档和 PostgreSQL连接字符串 以获取更多详细信息。

psql 'host=<host> port=<port> dbname=<dbname> user=<username> password=<password>'
psql postgres://<username>:<password>@<host>:<port>/<dbname>
PGPASSWORD=<password>; psql -U <username> -h <host> -p <port> -d <dbname>

例如,连接 Pigsty 默认的 meta 数据库,可以使用以下连接串:

psql 'host=10.10.10.10 port=5432 dbname=meta user=dbuser_dba password=DBUser.DBA'
psql postgres://dbuser_dba:[email protected]:5432/meta
PGPASSWORD=DBUser.DBA; psql -U dbuser_dba -h 10.10.10.10 -p 5432 -d meta

默认配置下,Pigsty 会启用服务端 SSL 加密,但不验证客户端 SSL 证书。要使用客户端 SSL 证书连接,你可以使用 PGSSLCERTPGSSLKEY 环境变量或 sslkeysslcert 参数提供客户端参数。

psql 'postgres://dbuser_dba:[email protected]:5432/meta?sslkey=/path/to/dbuser_dba.key&sslcert=/path/to/dbuser_dba.crt'

客户端证书(CN = 用户名)可以使用本地 CA 与 cert.yml 剧本签发。


定义HBA

在 Pigsty 中,有四个与 HBA 规则有关的参数:

这些都是 HBA 规则对象的数组,每个 HBA 规则都是以下两种形式之一的对象:

1. 原始形式

原始形式的 HBA 与 PostgreSQL pg_hba.conf 的格式几乎完全相同:

- title: allow intranet password access
  role: common
  rules:
    - host   all  all  10.0.0.0/8      md5
    - host   all  all  172.16.0.0/12   md5
    - host   all  all  192.168.0.0/16  md5

在这种形式中,rules 字段是字符串数组,每一行都是条原始形式的 HBA规则title 字段会被渲染为一条注释,解释下面规则的作用。

role 字段用于说明该规则适用于哪些实例角色,当实例的 pg_rolerole 相同时,HBA 规则将被添加到这台实例的 HBA 中。

  • role: common 的 HBA 规则将被添加到所有实例上。
  • role: primary 的 HBA 规则只会添加到主库实例上。
  • role: replica 的 HBA 规则只会添加到从库实例上。
  • role: offline 的 HBA 规则将被添加到离线实例上(pg_role = offlinepg_offline_query = true

2. 别名形式

别名形式允许您用更简单清晰便捷的方式维护 HBA 规则:它用 addrauthuserdb 字段替换了 rulestitleroleorder 字段则仍然生效。

- addr: 'intra'    # world|intra|infra|admin|local|localhost|cluster|<cidr>
  auth: 'pwd'      # trust|pwd|ssl|cert|deny|<official auth method>
  user: 'all'      # all|${dbsu}|${repl}|${admin}|${monitor}|<user>|<group>
  db: 'all'        # all|replication|....
  rules: []        # raw hba string precedence over above all
  title: allow intranet password access
  order: 100       # 排序权重,数字小的排前面(可选,默认追加到最后)
  • addr: where 哪些 IP 地址段受本条规则影响?
    • world:所有的 IP 地址
    • intra:所有的内网 IP 地址段: '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'
    • infra:Infra 节点的 IP 地址
    • admin: admin_ip 管理节点的 IP 地址
    • local:本地 Unix Socket
    • localhost:本地 Unix Socket 以及 TCP 127.0.0.1/32 环回地址
    • cluster:同一个 PostgresQL 集群所有成员的 IP 地址
    • <cidr>:一个特定的 CIDR 地址块或 IP 地址
  • auth: how 本条规则指定的认证方式?
    • deny:拒绝访问
    • trust:直接信任,不需要认证
    • pwd:密码认证,根据 pg_pwd_enc 参数选用 md5scram-sha-256 认证
    • sha/scram-sha-256:强制使用 scram-sha-256 密码认证方式。
    • md5: md5 密码认证方式,但也可以兼容 scram-sha-256 认证,不建议使用。
    • ssl:在密码认证 pwd 的基础上,强制要求启用 SSL
    • ssl-md5:在密码认证 md5 的基础上,强制要求启用 SSL
    • ssl-sha:在密码认证 sha 的基础上,强制要求启用 SSL
    • os/ident:使用操作系统用户的身份进行 ident 认证
    • peer:使用 peer 认证方式,类似于 os ident
    • cert:使用基于客户端 SSL 证书的认证方式,证书 CN 为用户名
  • user: who:哪些用户受本条规则影响?
  • db: which:哪些数据库受本条规则影响?
    • all:所有数据库
    • replication:允许建立复制连接(不指定特定数据库)
    • 某个特定的数据库

3. 定义位置

通常,全局的 HBA 定义在 all.vars 中,如果您想要修改全局默认的 HBA 规则,可以从 conf/ha/full.yml 模板中复制一份到 all.vars 中进行修改。

而集群特定的 HBA 规则定义在数据库的集群级配置中:

下面是一些集群 HBA 规则的定义例子:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_hba_rules:
      - { user: dbuser_view ,db: all    ,addr: infra        ,auth: pwd  ,title: '允许 dbuser_view 从基础设施节点密码访问所有库'}
      - { user: all         ,db: all    ,addr: 100.0.0.0/8  ,auth: pwd  ,title: '允许所有用户从K8S网段密码访问所有库'          }
      - { user: '${admin}'  ,db: world  ,addr: 0.0.0.0/0    ,auth: cert ,title: '允许管理员用户从任何地方用客户端证书登陆'       }

重载HBA

HBA 是一个静态的规则配置文件,修改后需要重载才能生效。默认的 HBA 规则集合因为不涉及 Role 与集群成员,所以通常不需要重载。

如果您设计的 HBA 使用了特定的实例角色限制,或者集群成员限制,那么当集群实例成员发生变化(新增/下线/主从切换),一部分 HBA 规则的生效条件/涉及范围发生变化,通常也需要 重载HBA 以反映最新变化。

要重新加载 postgres/pgbouncer 的 hba 规则:

bin/pgsql-hba <cls>                 # 重新加载集群 `<cls>` 的 hba 规则
bin/pgsql-hba <cls> ip1 ip2...      # 重新加载特定实例的 hba 规则

底层实际执行的 Ansible 剧本命令为:

./pgsql.yml -l <cls> -e pg_reload=true -t pg_hba,pg_reload
./pgsql.yml -l <cls> -e pg_reload=true -t pgbouncer_hba,pgbouncer_reload

默认HBA

Pigsty 有一套默认的 HBA 规则,对于绝大多数场景来说,它已经足够安全了。这些规则使用别名形式,因此基本可以自我解释。

pg_default_hba_rules:             # postgres 全局默认的HBA规则,按 order 排序
  - {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  ,order: 100}
  - {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' ,order: 150}
  - {user: '${repl}'    ,db: replication ,addr: localhost ,auth: pwd   ,title: 'replicator replication from localhost',order: 200}
  - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: pwd   ,title: 'replicator replication from intranet' ,order: 250}
  - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: pwd   ,title: 'replicator postgres db from intranet' ,order: 300}
  - {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' ,order: 350}
  - {user: '${monitor}' ,db: all         ,addr: infra     ,auth: pwd   ,title: 'monitor from infra host with password',order: 400}
  - {user: '${admin}'   ,db: all         ,addr: infra     ,auth: ssl   ,title: 'admin @ infra nodes with pwd & ssl'   ,order: 450}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: ssl   ,title: 'admin @ everywhere with ssl & pwd'    ,order: 500}
  - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: pwd   ,title: 'pgbouncer read/write via local socket',order: 550}
  - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: pwd   ,title: 'read/write biz user via password'     ,order: 600}
  - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: pwd   ,title: 'allow etl offline tasks from intranet',order: 650}
pgb_default_hba_rules:            # pgbouncer 全局默认的HBA规则,按 order 排序
  - {user: '${dbsu}'    ,db: pgbouncer   ,addr: local     ,auth: peer  ,title: 'dbsu local admin access with os ident',order: 100}
  - {user: 'all'        ,db: all         ,addr: localhost ,auth: pwd   ,title: 'allow all user local access with pwd' ,order: 150}
  - {user: '${monitor}' ,db: pgbouncer   ,addr: intra     ,auth: pwd   ,title: 'monitor access via intranet with pwd' ,order: 200}
  - {user: '${monitor}' ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other monitor access addr' ,order: 250}
  - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: pwd   ,title: 'admin access via intranet with pwd'   ,order: 300}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other admin access addr'   ,order: 350}
  - {user: 'all'        ,db: all         ,addr: intra     ,auth: pwd   ,title: 'allow all user intra access with pwd' ,order: 400}

注意order 字段控制规则渲染顺序。0-99 用于高优先规则(如黑名单),100-650 为默认规则区间,1000+ 用于追加规则。详见 HBA 配置

示例:渲染 pg_hba.conf
#==============================================================#
# File      :   pg_hba.conf
# Desc      :   Postgres HBA Rules for pg-meta-1 [primary]
# Time      :   2023-01-11 15:19
# Host      :   pg-meta-1 @ 10.10.10.10:5432
# Path      :   /pg/data/pg_hba.conf
# Note      :   ANSIBLE MANAGED, DO NOT CHANGE!
# Author    :   Ruohang Feng ([email protected])
# License   :   Apache-2.0
#==============================================================#

# addr alias
# local     : /var/run/postgresql
# admin     : 10.10.10.10
# infra     : 10.10.10.10
# intra     : 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16

# user alias
# dbsu    :  postgres
# repl    :  replicator
# monitor :  dbuser_monitor
# admin   :  dbuser_dba

# dbsu access via local os user ident [default]
local    all                postgres                              ident

# dbsu replication from local os ident [default]
local    replication        postgres                              ident

# replicator replication from localhost [default]
local    replication        replicator                            scram-sha-256
host     replication        replicator         127.0.0.1/32       scram-sha-256

# replicator replication from intranet [default]
host     replication        replicator         10.0.0.0/8         scram-sha-256
host     replication        replicator         172.16.0.0/12      scram-sha-256
host     replication        replicator         192.168.0.0/16     scram-sha-256

# replicator postgres db from intranet [default]
host     postgres           replicator         10.0.0.0/8         scram-sha-256
host     postgres           replicator         172.16.0.0/12      scram-sha-256
host     postgres           replicator         192.168.0.0/16     scram-sha-256

# monitor from localhost with password [default]
local    all                dbuser_monitor                        scram-sha-256
host     all                dbuser_monitor     127.0.0.1/32       scram-sha-256

# monitor from infra host with password [default]
host     all                dbuser_monitor     10.10.10.10/32     scram-sha-256

# admin @ infra nodes with pwd & ssl [default]
hostssl  all                dbuser_dba         10.10.10.10/32     scram-sha-256

# admin @ everywhere with ssl & pwd [default]
hostssl  all                dbuser_dba         0.0.0.0/0          scram-sha-256

# pgbouncer read/write via local socket [default]
local    all                +dbrole_readonly                      scram-sha-256
host     all                +dbrole_readonly   127.0.0.1/32       scram-sha-256

# read/write biz user via password [default]
host     all                +dbrole_readonly   10.0.0.0/8         scram-sha-256
host     all                +dbrole_readonly   172.16.0.0/12      scram-sha-256
host     all                +dbrole_readonly   192.168.0.0/16     scram-sha-256

# allow etl offline tasks from intranet [default]
host     all                +dbrole_offline    10.0.0.0/8         scram-sha-256
host     all                +dbrole_offline    172.16.0.0/12      scram-sha-256
host     all                +dbrole_offline    192.168.0.0/16     scram-sha-256

# allow application database intranet access [common] [DISABLED]
#host    kong            dbuser_kong         10.0.0.0/8          md5
#host    bytebase        dbuser_bytebase     10.0.0.0/8          md5
#host    grafana         dbuser_grafana      10.0.0.0/8          md5
示例:渲染 pgb_hba.conf
#==============================================================#
# File      :   pgb_hba.conf
# Desc      :   Pgbouncer HBA Rules for pg-meta-1 [primary]
# Time      :   2023-01-11 15:28
# Host      :   pg-meta-1 @ 10.10.10.10:5432
# Path      :   /etc/pgbouncer/pgb_hba.conf
# Note      :   ANSIBLE MANAGED, DO NOT CHANGE!
# Author    :   Ruohang Feng ([email protected])
# License   :   Apache-2.0
#==============================================================#

# PGBOUNCER HBA RULES FOR pg-meta-1 @ 10.10.10.10:6432
# ansible managed: 2023-01-11 14:30:58

# addr alias
# local     : /var/run/postgresql
# admin     : 10.10.10.10
# infra     : 10.10.10.10
# intra     : 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16

# user alias
# dbsu    :  postgres
# repl    :  replicator
# monitor :  dbuser_monitor
# admin   :  dbuser_dba

# dbsu local admin access with os ident [default]
local    pgbouncer          postgres                              peer

# allow all user local access with pwd [default]
local    all                all                                   scram-sha-256
host     all                all                127.0.0.1/32       scram-sha-256

# monitor access via intranet with pwd [default]
host     pgbouncer          dbuser_monitor     10.0.0.0/8         scram-sha-256
host     pgbouncer          dbuser_monitor     172.16.0.0/12      scram-sha-256
host     pgbouncer          dbuser_monitor     192.168.0.0/16     scram-sha-256

# reject all other monitor access addr [default]
host     all                dbuser_monitor     0.0.0.0/0          reject

# admin access via intranet with pwd [default]
host     all                dbuser_dba         10.0.0.0/8         scram-sha-256
host     all                dbuser_dba         172.16.0.0/12      scram-sha-256
host     all                dbuser_dba         192.168.0.0/16     scram-sha-256

# reject all other admin access addr [default]
host     all                dbuser_dba         0.0.0.0/0          reject

# allow all user intra access with pwd [default]
host     all                all                10.0.0.0/8         scram-sha-256
host     all                all                172.16.0.0/12      scram-sha-256
host     all                all                192.168.0.0/16     scram-sha-256

安全加固

对于那些需要更高安全性的场合,我们提供了一个安全加固的配置模板 conf/ha/safe.yml,使用了以下的默认 HBA 规则集:

pg_default_hba_rules:             # postgres host-based auth rules by default, order by `order`
  - {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  ,order: 100}
  - {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' ,order: 150}
  - {user: '${repl}'    ,db: replication ,addr: localhost ,auth: ssl   ,title: 'replicator replication from localhost',order: 200}
  - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: ssl   ,title: 'replicator replication from intranet' ,order: 250}
  - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: ssl   ,title: 'replicator postgres db from intranet' ,order: 300}
  - {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' ,order: 350}
  - {user: '${monitor}' ,db: all         ,addr: infra     ,auth: ssl   ,title: 'monitor from infra host with password',order: 400}
  - {user: '${admin}'   ,db: all         ,addr: infra     ,auth: ssl   ,title: 'admin @ infra nodes with pwd & ssl'   ,order: 450}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: cert  ,title: 'admin @ everywhere with ssl & cert'   ,order: 500}
  - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: ssl   ,title: 'pgbouncer read/write via local socket',order: 550}
  - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: ssl   ,title: 'read/write biz user via password'     ,order: 600}
  - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: ssl   ,title: 'allow etl offline tasks from intranet',order: 650}
pgb_default_hba_rules:            # pgbouncer host-based authentication rules, order by `order`
  - {user: '${dbsu}'    ,db: pgbouncer   ,addr: local     ,auth: peer  ,title: 'dbsu local admin access with os ident',order: 100}
  - {user: 'all'        ,db: all         ,addr: localhost ,auth: pwd   ,title: 'allow all user local access with pwd' ,order: 150}
  - {user: '${monitor}' ,db: pgbouncer   ,addr: intra     ,auth: ssl   ,title: 'monitor access via intranet with pwd' ,order: 200}
  - {user: '${monitor}' ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other monitor access addr' ,order: 250}
  - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: ssl   ,title: 'admin access via intranet with pwd'   ,order: 300}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other admin access addr'   ,order: 350}
  - {user: 'all'        ,db: all         ,addr: intra     ,auth: ssl   ,title: 'allow all user intra access with pwd' ,order: 400}

认证方法与默认边界见 身份认证,生产加固步骤见 安全考量

8.17.5 - 访问控制

PostgreSQL 访问控制的概念、配置与管理入口。

Pigsty 的访问控制文档已按用途拆分:

  • 访问控制概念:角色模型、默认权限、数据库 ACL 和实例隔离边界。
  • 访问控制配置pg_default_rolespg_userspg_default_privileges 等参数。
  • 身份认证:HBA、SCRAM、证书认证与凭据管理。
  • HBA 配置:PostgreSQL 与 PgBouncer 规则语法。
  • 用户管理:在现有集群中创建、更新和删除用户。

dbrole_offline 只提供独立的只读对象权限,不会自动限制实例范围。若要仅允许其访问离线实例,应为对应 HBA 规则显式设置 role: offline,并验证在线与离线实例生成的 pg_hba.conf

9 - 模块:INFRA

可独立使用且可选的基础设施,为 PostgreSQL 提供 NTP,DNS,可观测性等基础服务。

配置 | 管理 | 剧本 | 监控 | 参数


概览

每一套 Pigsty 部署都会提供一套基础架构组件,为纳管的节点与数据库集群提供服务,组件包括:

组件 端口 描述
Nginx 80/443 Web 服务门户、本地软件仓库与统一入口
Grafana 3000 可视化平台,提供监控大屏、巡检与数据应用
VictoriaMetrics 8428 时序数据库与 VMUI,可兼容 Prometheus API
VictoriaLogs 9428 集中式日志数据库,接收 Vector 推送的结构化日志
VictoriaTraces 10428 链路追踪与事件存储,可用于慢 SQL / 请求追踪
VMAlert 8880 告警规则评估器,基于 VictoriaMetrics 指标触发告警
AlertManager 9059 告警聚合与分发,接收 VMAlert 发送的通知
BlackboxExporter 9115 ICMP/TCP/HTTP 黑盒探测
DNSMASQ 53 DNS 服务器,提供内部域名解析
Chronyd 123 NTP 时间服务器
PostgreSQL 5432 CMDB 与默认数据库
Ansible - 运行剧本、编排所有基础设施

在 Pigsty 中,PGSQL 模块会使用到 INFRA节点 上的一些服务,具体来说包括:

  • 数据库集群/主机节点的域名,依赖 INFRA 节点的 DNSMASQ 解析
  • 在数据库节点软件上 安装,需要用到 INFRA 节点上的 Nginx 托管的本地 yum/apt 软件源。
  • 数据库集群/节点的监控 指标,会被 INFRA 节点上的 VictoriaMetrics 拉取并存储,可通过 VMUI / PromQL 访问。
  • 数据库与节点运行日志由 Vector 收集,统一推送到 INFRA 上的 VictoriaLogs,支持在 Grafana 中检索。
  • VMAlert 根据 VictoriaMetrics 中的指标 评估 告警规则,并将事件转发到 Alertmanager。
  • 用户会从 Infra/Admin 节点上使用 Ansible 或其他工具发起对数据库节点的 管理
    • 执行集群创建,扩缩容,实例/集群回收
    • 创建业务用户、业务数据库、修改服务、HBA 修改;
    • 执行日志采集、垃圾清理,备份,巡检等
  • 数据库节点默认会从 INFRA/ADMIN 节点上的 NTP 服务器同步时间
  • 如果没有专用集群,高可用组件 Patroni 会使用 INFRA 节点上的 etcd 作为高可用 DCS。
  • 如果没有专用集群,备份组件 pgbackrest 会使用 INFRA 节点上的 minio 作为可选的集中备份仓库。

Nginx

Nginx 是 Pigsty 所有 WebUI 类服务的访问入口,默认使用管理节点80端口。

有许多带有 WebUI 的基础设施组件通过 Nginx 对外暴露服务,例如 Grafana、VictoriaMetrics(VMUI)、AlertManager,以及 HAProxy 流量管理页等,此外 yum/apt 仓库等静态文件资源也通过 Nginx 对外提供服务。

Nginx 默认通过 i.pigsty 的子路径暴露内置 Web 服务,也可以根据 infra_portal 的内容,通过 域名 区分并转发至对应的上游组件。 如果您使用了其他的域名,或者公网域名,可以在这里进行相应修改:

infra_portal:  # domain names and upstream servers
  home         : { domain: i.pigsty }
  grafana      : { domain: g.pigsty ,endpoint: "${admin_ip}:3000" , websocket: true }
  vmetrics     : { domain: p.pigsty ,endpoint: "${admin_ip}:8428" }   # VMUI
  alertmanager : { domain: a.pigsty ,endpoint: "${admin_ip}:9059" }
  blackbox     : { endpoint: "${admin_ip}:9115" }
  vmalert      : { endpoint: "${admin_ip}:8880" }
  #logs         : { domain: logs.pigsty ,endpoint: "${admin_ip}:9428" }
  #minio        : { domain: m.pigsty    ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }

Pigsty 强烈建议使用域名访问 Pigsty UI 系统,而不是直接通过 IP+ 端口的方式访问,基于以下几个理由:

  • 使用域名便于启用 HTTPS 流量加密,可以将访问收拢至 Nginx,审计一切请求,并方便地集成认证机制。
  • 一些组件默认只监听 127.0.0.1,因此只能通过 Nginx 代理访问。
  • 域名更容易记忆,并提供了额外的配置灵活性。

如果您没有可用的互联网域名或本地 DNS 解析,您可以在 /etc/hosts (MacOS/Linux)或 C:\Windows\System32\drivers\etc\hosts (Windows)中添加本地静态解析记录。

Nginx 相关配置参数位于:配置:INFRA - NGINX


本地软件仓库

Pigsty 会在安装时首先建立一个本地软件源,以加速后续软件安装。

该软件源由 Nginx 提供服务,默认位于为 /www/pigsty,可以访问 http://i.pigsty/pigsty 使用。

Pigsty 的离线软件包即是将已建立的软件源目录(RPM/APT)打成压缩包。当前源码使用 SOW 创建仓库;如果 /www/pigsty/repo_complete 已存在,则认为本地源已经完整构建并跳过上游下载。该文件包含 SHA-256 校验内容,不只是一个空标记。

Repo 定义文件位于 /www/pigsty.repo,默认可以通过 http://${admin_ip}/pigsty.repo 获取

curl -L http://i.pigsty/pigsty.repo -o /etc/yum.repos.d/pigsty.repo

您也可以在没有 Nginx 的情况下直接使用文件本地源:

[pigsty-local]
name=Pigsty local $releasever - $basearch
baseurl=file:///www/pigsty/
enabled=1
gpgcheck=0

本地软件仓库相关配置参数位于:配置:INFRA - REPO


Victoria 可观测性套件

Pigsty v4 使用 VictoriaMetrics 家族提供统一的监控、日志与链路追踪能力:

  • VictoriaMetrics 默认监听 8428 端口,可通过 https://i.pigsty/vmetrics/ 访问 VMUI,兼容 Prometheus API;也可通过在 infra_portal 中配置独立域名访问。
  • VMAlert 负责评估 /infra/rules/*.yml 中的告警规则,监听 8880 端口,并将告警事件发送到 Alertmanager。
  • VictoriaLogs 监听 9428 端口,支持 https://i.pigsty/vlogs/ 查询界面。所有节点默认运行 Vector,将系统日志、PostgreSQL 日志等结构化后推送至 VictoriaLogs。
  • VictoriaTraces 监听 10428 端口,用于慢 SQL / Trace 采集,Grafana 以 Jaeger 数据源方式访问。
  • Alertmanager 监听 9059 端口,可通过 https://i.pigsty/alertmgr/ 管理告警通知;如在 infra_portal 中配置 a.pigsty,也可通过独立域名访问。完成 SMTP、Webhook 等配置后即可推送消息。
  • Blackbox Exporter 默认监听 9115 端口,用于 Ping/TCP/HTTP 探测,可通过 https://i.pigsty/blackbox/ 访问。

更多信息请参阅:配置:INFRA - VICTORIA配置:INFRA - PROMETHEUS


Grafana

Grafana 是 Pigsty 的 WebUI 核心,默认监听 3000 端口,可以通过 https://i.pigsty/ui/ 或直接访问 IP:3000;如在 infra_portal 中配置 g.pigsty,也可通过独立域名访问。

Pigsty 预置了针对 VictoriaMetrics / Logs / Traces 的数据源(vmetrics-*vlogs-*vtraces-*),以及大量 Dashboard,可通过 URL 进行联动跳转,快速定位问题。

Grafana 也可作为通用低代码可视化平台使用,因此 Pigsty 默认安装了 ECharts、victoriametrics-datasource 等插件,方便构建监控大屏或巡检报表。

Grafana 相关配置参数位于:配置:INFRA - GRAFANA


Ansible

Pigsty 默认会在元节点上安装 Ansible,Ansible 是一个流行的运维工具,采用声明式的配置风格与幂等的剧本设计,可以极大降低系统维护的复杂度。


DNSMASQ

DNSMASQ 提供环境内的 DNS 解析 服务,其他模块的域名将会注册到 INFRA 节点上的 DNSMASQ 服务中。

DNS 记录默认放置于所有 INFRA 节点的 /etc/dnsmasq.d/pigsty/ 目录中。

DNSMASQ 相关配置参数位于:配置:INFRA - DNS


Chronyd

NTP 服务用于同步环境内所有节点的时间(可选)

NTP 相关配置参数位于:配置:NODES - NTP


PostgreSQL

Pigsty 的元数据库(CMDB)通常使用 PostgreSQL,默认监听 5432 端口,用于存储 Pigsty 元数据并支撑部分内置应用。 更多信息请参阅:PGSQL 模块与 配置:INFRA - META


配置

要在节点上安装 INFRA 模块,首先需要在配置清单中的 infra 分组中将其加入,并分配实例号 infra_seq

# 配置单个 INFRA 节点
infra: { hosts: { 10.10.10.10: { infra_seq: 1 } }}

# 配置两个 INFRA 节点
infra:
  hosts:
    10.10.10.10: { infra_seq: 1 }
    10.10.10.11: { infra_seq: 2 }

然后,使用 infra.yml 剧本在节点上初始化 INFRA 模块即可。


管理

下面是与 INFRA 模块相关的一些管理任务:


安装卸载Infra模块

./infra.yml     # 在 infra 分组上安装 INFRA 模块
./infra-rm.yml  # 全量移除 INFRA(包括数据与软件包)

infra-rm.yml 没有防误删开关;不带标签会删除 infra_datanginx_datanginx_home(默认 /www)与 /var/lib/grafana。 只需停服或注销时请使用标签,完整边界见 预置剧本


管理本地软件仓库

您可以使用以下剧本子任务,管理 Infra 节点上的本地 RPM/APT 软件源:

./infra.yml -t repo              #从互联网或离线包中创建本地软件源

./infra.yml -t repo_dir          # 创建本地软件源
./infra.yml -t repo_check        # 检查本地软件源是否已经存在?
./infra.yml -t repo_prepare      # 如果存在,直接使用已有的本地软件源
./infra.yml -t repo_build        # 如果不存在,从上游构建本地软件源
./infra.yml     -t repo_upstream     # 处理 /etc/yum.repos.d 中的上游仓库文件
./infra.yml     -t repo_remove       # 如果 repo_remove == true,则删除现有的仓库文件
./infra.yml     -t repo_add          # 将上游仓库文件添加到 /etc/yum.repos.d (或 /etc/apt/sources.list.d)
./infra.yml     -t repo_url_pkg      # 从由 repo_url_packages 定义的互联网下载包
./infra.yml     -t repo_cache        # 使用 yum makecache / apt update 创建上游软件源元数据缓存
./infra.yml     -t repo_boot_pkg     # 安装 SOW,以及 dnf/yum 下载工具
./infra.yml     -t repo_pkg          # 从上游仓库下载包 & 依赖项
./infra.yml     -t repo_create       # 使用 sow create --pigsty 原子创建 RPM/APT 元数据
./infra.yml     -t repo_use          # 将新建的仓库添加到 /etc/yum.repos.d | /etc/apt/sources.list.d 用起来
./infra.yml -t repo_nginx        # 如果没有 nginx 在服务,启动一个 nginx 作为 Web Server

其中最常用的命令为:

./infra.yml     -t repo_upstream     # 向 INFRA 节点添加 repo_upstream 中定义的上游软件源
./infra.yml     -t repo_pkg          # 从上游仓库下载包及其依赖项。
./infra.yml     -t repo_create       # 使用 SOW 创建/更新本地 RPM/APT 仓库元数据

管理基础设施组件

您可以使用以下剧本子任务,管理 Infra 节点 上的各个基础设施组件

./infra.yml -t infra           # 配置基础设施
./infra.yml -t infra_user      # 设置 infra 操作系统用户组
./infra.yml -t infra_dir       # 创建基础设施数据、配置与运行目录
./infra.yml -t infra_env       # 配置管理节点环境:env_patroni, env_pg, env_pgadmin, env_etcd, env_pglog, env_var
./infra.yml -t infra_pkg       # 安装 INFRA 所需的软件包:infra_packages
./infra.yml -t infra_cert      # 为 infra 组件颁发证书
./infra.yml -t dns             # 配置 DNSMasq:dns_config, dns_record, dns_launch
./infra.yml -t nginx           # 配置 Nginx:nginx_config, nginx_cert, nginx_static, nginx_launch, nginx_certbot, nginx_reload, nginx_exporter
./infra.yml -t victoria        # 配置 VictoriaMetrics/Logs/Traces:vmetrics|vlogs|vtraces|vmalert
./infra.yml -t alertmanager    # 配置 AlertManager:alertmanager_config, alertmanager_launch
./infra.yml -t blackbox        # 配置 Blackbox Exporter:blackbox_config, blackbox_launch
./infra.yml -t grafana         # 配置 Grafana:grafana_clean, grafana_config, grafana_launch, grafana_provision
./infra.yml -t infra_register  # 将 infra 组件注册到 VictoriaMetrics / Grafana

其他常用的任务包括:

./infra.yml -t nginx_index                        # 重新渲染 Nginx 首页内容
./infra.yml -t nginx_config,nginx_reload          # 重新渲染 Nginx 网站门户配置,对外暴露新的上游服务。
./infra.yml -t vmetrics_config,vmetrics_launch    # 重新生成 VictoriaMetrics 主配置文件,并重启服务
./infra.yml -t vlogs_config,vlogs_launch          # 重新渲染 VictoriaLogs 配置
./infra.yml -t vmetrics_clean                     # 清理 VictoriaMetrics 存储数据目录
./infra.yml -t grafana_provision                  # 重新加载 Grafana 仪表盘与数据源定义

剧本

Pigsty 提供了三个与 INFRA 模块相关的剧本:

  • infra.yml:在 infra 节点上初始化 pigsty 基础设施
  • infra-rm.yml:从 infra 节点移除基础设施组件
  • deploy.yml:一次性部署 NODE、INFRA、ETCD、MINIO 与 PGSQL 核心链路

infra.yml

INFRA 模块剧本 infra.yml 用于在 Infra节点 上初始化 pigsty 基础设施

执行该剧本将完成以下任务

  • 配置元节点的目录与环境变量
  • 下载并建立一个本地软件源,加速后续安装。(若使用离线软件包,则跳过下载阶段)
  • 将当前元节点作为一个普通节点纳入 Pigsty 管理
  • 部署 基础设施 组件,包括 VictoriaMetrics/Logs/Traces、VMAlert、Grafana、Alertmanager、Blackbox Exporter 等

该剧本默认在 INFRA 节点 上执行

  • Pigsty 默认将使用 当前执行此剧本的节点 作为 Pigsty 的 Infra节点ADMIN节点
  • Pigsty 在 配置过程 中默认会将当前节点标记为 Infra/Admin 节点,并使用 当前节点首要 IP 地址 替换配置模板中的占位 IP 地址 10.10.10.10
  • 该节点除了可以发起管理,部署有基础设施,与一个部署普通托管节点并无区别。
  • 单机安装时,ETCD 也会安装在此节点上,提供 DCS 服务

本剧本的一些注意事项

  • 本剧本为幂等剧本,重复执行默认不会清理历史数据与 Grafana 数据。
  • 如需保留历史监控数据,请先将 vmetrics_cleanvlogs_cleanvtraces_clean 设置为 false
  • 如果将 vmetrics_cleanvlogs_cleanvtraces_cleangrafana_clean 设为 true,对应组件数据会在执行时被清理。
  • 当离线软件源 /www/pigsty/repo_complete 存在时,本剧本会跳过从互联网下载软件的任务。完整执行该剧本耗时约5-8分钟,视机器配置而异。
  • 不使用离线软件包而直接从互联网原始上游下载软件时,可能耗时10-20分钟,根据您的网络条件而异。

asciicast


infra-rm.yml

INFRA 模块剧本 infra-rm.yml 用于从 INFRA节点 上移除 pigsty 基础设施

常用子任务包括:

./infra-rm.yml               # 全量移除:注销、停服、删配置/环境/数据并卸载软件包
./infra-rm.yml -t deregister # 仅注销监控目标、数据源与日志采集
./infra-rm.yml -t service    # 停止 INFRA 上的基础设施服务
./infra-rm.yml -t data       # 移除 INFRA 数据
./infra-rm.yml -t package    # 卸载软件包

全量执行没有防误删开关,并会删除 infra_datanginx_datanginx_home(默认 /www)和 /var/lib/grafana;执行前请先备份要保留的数据。


deploy.yml

INFRA 模块剧本 deploy.yml 用于在 所有节点 上一次性部署 NODE、INFRA、ETCD、MINIO 与 PGSQL 核心链路。Docker、Redis、Kafka、原生 MySQL、JUICE 与 VIBE 等可选模块需要另行执行各自的剧本。

该剧本在 剧本:一次性安装 中有更详细的介绍。


监控

Pigsty Home:Pigsty 监控系统主页

Pigsty Home Dashboard

pigsty.jpg

INFRA Overview:Pigsty 基础设施自监控概览

INFRA Overview Dashboard

infra-overview.jpg

Nginx Instance:Nginx 监控指标与日志

Nginx Overview Dashboard

nginx-overview.jpg

Grafana Instance:Grafana 监控指标与日志

Grafana Overview Dashboard

grafana-overview.jpg

VictoriaMetrics Instance:VictoriaMetrics 抓取、查询与存储指标

VMAlert Instance:告警规则评估与队列状态

Alertmanager Instance:告警聚合、通知管道与 Silences

VictoriaLogs Instance:日志写入速率、查询负载与索引命中

VictoriaTraces Instance:Trace/KV 存储与 Jaeger 接口

Logs Instance:基于 Vector + VictoriaLogs 的节点日志检索

Logs Instance Dashboard

logs-instance.jpg

CMDB Overview:CMDB 可视化

CMDB Overview Dashboard

cmdb-overview.jpg

ETCD Overview:etcd 监控指标与日志

ETCD Overview Dashboard

etcd-overview.jpg


参数

INFRA 模块有下列10个参数组。

  • META:Pigsty 元数据
  • CA:自签名公私钥基础设施/CA
  • INFRA_ID:基础设施门户,Nginx 域名
  • REPO:本地软件源
  • INFRA_PACKAGE:基础设施软件包
  • NGINX:Nginx 网络服务器
  • DNS:DNSMASQ 域名服务器
  • VICTORIA:VictoriaMetrics / Logs / Traces 套件
  • PROMETHEUS:Alertmanager 与 Blackbox Exporter
  • GRAFANA:Grafana 可观测性全家桶
参数速览

为保持与 Pigsty 版本一致,请参阅 《参数列表》 获取最新的默认值、类型与层级说明。

9.1 - 集群配置

如何配置 Infra 节点?定制 Nginx 服务器的配置与本地软件仓库的内容?配置 DNS,NTP 与监控组件的方法。

配置说明

INFRA 主要用于提供 监控 基础设施,对于 PostgreSQL 数据库是 可选项

除非手工配置了对 INFRA 节点上 DNS/NTP 服务的依赖,否则 INFRA 模块故障通常不影响 PostgreSQL 数据库集群运行。

单个 INFRA 节点足以应对绝大部分场景。生产环境建议使用 2~3 个 INFRA 节点实现高可用。

通常出于提高资源利用率的考虑,PostgreSQL 高可用依赖的 ETCD 模块可以与 INFRA 模块共用节点。

使用 3 个以上的 INFRA 节点意义不大,但可以使用更多 ETCD 节点(如 5 个)提高 DCS 服务可用性。


配置样例

在配置清单中的 infra 分组加入节点 IP,并分配 Infra 实例号 infra_seq

默认单个 INFRA 节点配置:

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } }}

默认情况下,10.10.10.10 占位符在配置过程中被替换为当前节点首要 IP 地址。

使用 infra.yml 剧本在节点上初始化 INFRA 模块。

更多节点

两个 INFRA 节点配置:

all:
  children:
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }
        10.10.10.11: { infra_seq: 2 }

三个 INFRA 节点配置(含参数):

all:
  children:
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }
        10.10.10.11: { infra_seq: 2, repo_enabled: false }
        10.10.10.12: { infra_seq: 3, repo_enabled: false }
      vars:
        grafana_clean: false
        vmetrics_clean: false
        vlogs_clean: false
        vtraces_clean: false

Infra 高可用

Infra 模块中的大部分组件都属于"无状态/相同状态",对于这类组件,高可用只需要操心"负载均衡"问题。

高可用可通过 Keepalived L2 VIP 或 HAProxy 四层负载均衡实现。二层互通网络推荐使用 Keepalived L2 VIP。

配置示例:

infra:
  hosts:
    10.10.10.10: { infra_seq: 1 }
    10.10.10.11: { infra_seq: 2 }
    10.10.10.12: { infra_seq: 3 }
  vars:
    vip_enabled: true
    vip_vrid: 128
    vip_address: 10.10.10.8
    vip_interface: eth1

    infra_portal:
      home         : { domain: i.pigsty }
      grafana      : { domain: g.pigsty ,endpoint: "10.10.10.8:3000" , websocket: true }
      vmetrics     : { domain: p.pigsty ,endpoint: "10.10.10.8:8428" }
      alertmanager : { domain: a.pigsty ,endpoint: "10.10.10.8:9059" }
      blackbox     : { endpoint: "10.10.10.8:9115" }
      vmalert      : { endpoint: "10.10.10.8:8880" }

需要设置 VIP 相关参数并在 infra_portal 中修改各 Infra 服务端点。


Nginx配置

请参阅 Nginx 参数配置Nginx 管理


本地仓库配置

请参阅 Repo 参数配置


DNS配置

请参阅 DNS 参数配置教程:DNS


NTP配置

请参阅 NTP 参数配置

9.2 - 参数列表

INFRA 模块提供了 10 组共 70+ 个配置参数

INFRA 模块负责配置 Pigsty 的基础设施组件:本地软件源、Nginx、DNSMasq、VictoriaMetrics、VictoriaLogs、Grafana、Alertmanager、Blackbox Exporter 等监控告警基础设施。

Pigsty v4.x 使用 VictoriaMetrics 替代 Prometheus,使用 VictoriaLogs 替代 Loki,实现了更优秀的可观测性方案。

参数组 功能说明
META Pigsty 元信息:版本、管理 IP、区域、语言、代理
CA 自签名 CA 证书管理
INFRA_ID 基础设施节点身份标识与服务门户
REPO 本地软件仓库配置
INFRA_PACKAGE 基础设施节点软件包安装
NGINX Nginx Web 服务器与反向代理配置
DNS DNSMasq 域名解析服务配置
VICTORIA VictoriaMetrics/Logs/Traces 可观测性套件
PROMETHEUS Alertmanager 与 Blackbox Exporter
GRAFANA Grafana 可视化平台配置

参数概览

META 参数组用于定义 Pigsty 的元信息,包括版本号、管理节点 IP、软件源区域、默认语言以及代理设置。

参数 类型 级别 说明
version string G pigsty 版本字符串
admin_ip ip G 管理节点 IP 地址
region enum G 上游镜像区域:default,china,europe
language enum G 默认语言,en 或 zh
proxy_env dict G 下载包时使用的全局代理环境变量

CA 参数组用于配置 Pigsty 自签名 CA 证书管理,包括是否创建 CA、CA 名称以及证书有效期。

参数 类型 级别 说明
ca_create bool G 私钥缺失时是否允许创建?默认为 true
ca_cn string G CA CN 名称,固定为 pigsty-ca
cert_validity interval G 证书有效期,默认为 20 年

INFRA_ID 参数组用于定义基础设施节点的身份标识,包括节点序号、服务门户配置以及数据目录。

参数 类型 级别 说明
infra_seq int I 基础设施节点序号,必选身份参数
infra_portal dict G 通过 Nginx 门户暴露的基础设施服务列表
infra_data path G 基础设施数据目录,默认为 /data/infra
infra_services service[] G 首页内置导航入口列表
infra_extra_services service[] G 追加到首页的导航入口,默认为 []

REPO 参数组用于配置本地软件仓库,包括仓库启用开关、目录路径、上游源定义以及要下载的软件包列表。

参数 类型 级别 说明
repo_enabled bool G/I 在此基础设施节点上创建软件仓库?
repo_home path G 软件仓库主目录,默认为 /www
repo_name string G 软件仓库名称,默认为 pigsty
repo_endpoint url G 仓库的访问点:域名或 ip:port 格式
repo_remove bool G/A 构建本地仓库时是否移除现有上游仓库源定义文件?
repo_modules string G/A 启用的上游仓库模块列表,用逗号分隔
repo_upstream upstream[] G 上游仓库源定义:从哪里下载上游包?
repo_packages string[] G 从上游仓库下载哪些软件包?
repo_extra_packages string[] G/C/I 从上游仓库下载哪些额外的软件包?
repo_url_packages string[] G 使用 URL 下载的额外软件包列表

INFRA_PACKAGE 参数组用于定义在基础设施节点上安装的软件包(RPM/DEB)。

参数 类型 级别 说明
infra_packages string[] G 在基础设施节点上要安装的软件包

NGINX 参数组用于配置 Nginx Web 服务器与反向代理,包括启用开关、端口、SSL 模式、证书以及基础认证。

参数 类型 级别 说明
nginx_enabled bool G/I 在此基础设施节点上启用 nginx?
nginx_clean bool G/A 初始化时清理现有 nginx 配置?
nginx_exporter_enabled bool G/I 在此基础设施节点上启用 nginx_exporter?
nginx_exporter_port port G nginx_exporter 监听端口,默认为 9113
nginx_sslmode enum G nginx SSL 模式?disable,enable,enforce
nginx_cert_validity duration G nginx 自签名证书有效期,默认为 397d
nginx_home path G nginx 内容目录,默认为 /www,软链接到 nginx_data
nginx_data path G nginx 实际数据目录,默认为 /data/nginx
nginx_users dict G nginx 基础认证用户:用户名和密码字典
nginx_port port G nginx 监听端口,默认为 80
nginx_ssl_port port G nginx SSL 监听端口,默认为 443
certbot_sign bool G/A 是否使用 certbot 签署证书?
certbot_email string G/A certbot 通知邮箱地址
certbot_options string G/A certbot 额外的命令行参数

DNS 参数组用于配置 DNSMasq 域名解析服务,包括启用开关、监听端口以及动态 DNS 记录。

参数 类型 级别 说明
dns_enabled bool G/I 在此基础设施节点上设置 dnsmasq?
dns_port port G DNS 服务器监听端口,默认为 53
dns_records string[] G 由 dnsmasq 解析的动态 DNS 记录

VICTORIA 参数组用于配置 VictoriaMetrics/Logs/Traces 可观测性套件,包括启用开关、端口、数据保留策略等。

参数 类型 级别 说明
vmetrics_enabled bool G/I 在此基础设施节点上启用 VictoriaMetrics?
vmetrics_clean bool G/A 初始化时清理 VictoriaMetrics 数据?
vmetrics_port port G VictoriaMetrics 监听端口,默认为 8428
vmetrics_scrape_interval interval G 全局抓取间隔,默认为 10s
vmetrics_scrape_timeout interval G 全局抓取超时,默认为 8s
vmetrics_options arg G VictoriaMetrics 额外命令行参数
vlogs_enabled bool G/I 在此基础设施节点上启用 VictoriaLogs?
vlogs_clean bool G/A 初始化时清理 VictoriaLogs 数据?
vlogs_port port G VictoriaLogs 监听端口,默认为 9428
vlogs_options arg G VictoriaLogs 额外命令行参数
vtraces_enabled bool G/I 在此基础设施节点上启用 VictoriaTraces?
vtraces_clean bool G/A 初始化时清理 VictoriaTraces 数据?
vtraces_port port G VictoriaTraces 监听端口,默认为 10428
vtraces_options arg G VictoriaTraces 额外命令行参数
vmalert_enabled bool G/I 在此基础设施节点上启用 VMAlert?
vmalert_port port G VMAlert 监听端口,默认为 8880
vmalert_options arg G VMAlert 额外命令行参数

PROMETHEUS 参数组用于配置 Alertmanager 与 Blackbox Exporter,提供告警管理和网络探测功能。

参数 类型 级别 说明
blackbox_enabled bool G/I 在此基础设施节点上设置 blackbox_exporter?
blackbox_port port G blackbox_exporter 监听端口,默认为 9115
blackbox_options arg G blackbox_exporter 额外的命令行参数选项
alertmanager_enabled bool G/I 在此基础设施节点上设置 alertmanager?
alertmanager_port port G AlertManager 监听端口,默认为 9059
alertmanager_options arg G alertmanager 额外的命令行参数选项
exporter_metrics_path path G exporter 指标路径,默认为 /metrics

GRAFANA 参数组用于配置 Grafana 可视化平台,包括启用开关、端口、管理员凭据以及数据源配置。

参数 类型 级别 说明
grafana_enabled bool G/I 在此基础设施节点上启用 Grafana?
grafana_port port G Grafana 监听端口,默认为 3000
grafana_clean bool G/A 初始化 Grafana 期间清除数据?
grafana_admin_username username G Grafana 管理员用户名,默认为 admin
grafana_admin_password password G Grafana 管理员密码,默认为 pigsty
grafana_auth_proxy bool G 启用 Grafana 身份代理?
grafana_pgurl url G 外部 PostgreSQL 数据库 URL(用于 Grafana 持久化)
grafana_view_password password G Grafana 元数据库 PG 数据源密码

META

这一小节指定了一套 Pigsty 部署的元数据:包括版本号,管理员节点 IP 地址,软件源镜像上游 区域,默认语言,以及下载软件包时使用的 http(s) 代理。

version: v4.5.0                   # pigsty 版本号
admin_ip: 10.10.10.10             # 管理节点IP地址
region: default                   # 上游镜像区域:default,china,europe
language: en                      # 默认语言: en 或 zh
proxy_env:                        # 全局HTTPS代理,用于下载、安装软件包。
  no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
  # http_proxy:  # set your proxy here: e.g http://user:[email protected]
  # https_proxy: # set your proxy here: e.g http://user:[email protected]
  # all_proxy:   # set your proxy here: e.g http://user:[email protected]

version

参数名称: version, 类型: string, 层次:G

Pigsty 版本号字符串,当前源码默认值为:v4.5.0

Pigsty 内部会使用版本号进行功能控制与内容渲染,请勿随意修改此参数。

Pigsty 使用语义化版本号,版本号字符串通常以字符 v 开头,例如 v4.5.0

admin_ip

参数名称: admin_ip, 类型: ip, 层次:G

管理节点的 IP 地址,默认为占位符 IP 地址:10.10.10.10

由该参数指定的节点将被视为管理节点,通常指向安装 Pigsty 时的第一个节点,即中控节点。

默认值 10.10.10.10 是一个占位符,会在 configure 过程中被替换为实际的管理节点 IP 地址。

许多参数都会引用此参数,例如:

在这些参数中,字符串 ${admin_ip} 会被替换为 admin_ip 的真实取值。使用这种机制,您可以为不同的节点指定不同的中控管理节点。

region

参数名称: region, 类型: enum, 层次:G

上游镜像的区域,默认可选值为:defaultchinaeurope,默认为: default

如果一个不同于 default 的区域被设置,且在 repo_upstream 中有对应的条目,将会使用该条目对应 baseurl 代替 default 中的 baseurl

例如,如果您的区域被设置为 china,那么 Pigsty 会尝试使用中国地区的上游软件镜像站点以加速下载,如果某个上游软件仓库没有对应的中国地区镜像,那么会使用默认的上游镜像站点替代。 同时,在 repo_url_packages 中定义的 URL 地址,也会进行从 repo.pigsty.iorepo.pigsty.cc 的替换,以使用国内的镜像源。

language

参数名称: language, 类型: enum, 层次:G

默认语言设置,可选值为 en(英文) 或 zh(中文),默认为 en

此参数会影响 Pigsty 生成的部分配置与内容的语言偏好,例如 Grafana 面板的初始语言设置等。

如果您是中国用户,建议将此参数设置为 zh,以获得更好的中文支持体验。

proxy_env

参数名称: proxy_env, 类型: dict, 层次:G

下载包时使用的全局代理环境变量,默认值指定了 no_proxy,即不使用代理的地址列表:

proxy_env:
  no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.myqcloud.com,*.tsinghua.edu.cn"
  #http_proxy: 'http://username:[email protected]'
  #https_proxy: 'http://username:[email protected]'
  #all_proxy: 'http://username:[email protected]'

当您在中国大陆地区从互联网上游安装时,特定的软件包可能会被墙,您可以使用代理来解决这个问题。

请注意,如果使用了 Docker 模块,那么这里的代理服务器配置也会写入 Docker Daemon 配置文件中。

请注意,如果在 ./configure 过程中指定了 -x 参数,那么当前环境中的代理配置信息将会被自动填入到生成的 pigsty.yaml 文件中。


CA

Pigsty 使用自签名 CA 证书,用于支持高级安全特性,例如 HTTPS 访问、PostgreSQL SSL 连接等。

ca_create: true                   # CA 私钥缺失时是否允许创建?默认为 true
ca_cn: pigsty-ca                  # CA CN名称,固定为 pigsty-ca
cert_validity: 7300d              # 证书有效期,默认为 20 年

ca_create

参数名称: ca_create, 类型: bool, 层次:G

如果 CA 私钥不存在,是否允许创建?默认值为 true

当设置为 true 时,如果 files/pki/ca/ca.key 不存在,Pigsty 将自动创建新的 CA 私钥;如果 ca.crt 不存在,则使用现有或新建的私钥签发 CA 证书。

如果您已经有了一对 CA 公私钥对,可以将其复制到 files/pki/ca 目录下:

  • files/pki/ca/ca.crt:CA 公钥证书
  • files/pki/ca/ca.key:CA 私钥文件

Pigsty 将复用现有的 CA 公私钥对。如果私钥不存在且此参数设置为 false,则会报错终止;仅缺少 ca.crt 时仍会用现有私钥重新签发证书。因此,请始终把匹配的 ca.keyca.crt 成对备份和恢复,避免出现证书与私钥不匹配的状态。

请务必保留并备份好部署过程中新生成的 CA 私钥文件,这对于后续签发新证书至关重要。

说明

Pigsty v3.x 使用的是 ca_method 参数(取值为 createrecreatecopy),v4.x 简化为布尔类型的 ca_create

ca_cn

参数名称: ca_cn, 类型: string, 层次:G

CA CN(Common Name)名称,固定为 pigsty-ca,不建议修改。

你可以使用以下命令来查看节点上的 Pigsty CA 证书详情:

openssl x509 -text -in /etc/pki/ca.crt

cert_validity

参数名称: cert_validity, 类型: interval, 层次:G

签发证书的有效期,默认为 20 年,对绝大多数场景都足够了。默认值为: 7300d

此参数影响由 Pigsty CA 签发的所有证书的有效期,包括:

  • PostgreSQL 服务器证书
  • Patroni API 证书
  • etcd 服务器/客户端证书
  • 其他内部服务证书

注意:Nginx 使用的 HTTPS 证书有效期由 nginx_cert_validity 单独控制,因为现代浏览器对网站证书有效期有更严格的要求(最长 397 天)。


INFRA_ID

基础设施身份标识与门户定义。

#infra_seq: 1                     # 基础设施节点序号,必选身份参数
infra_portal:                     # 通过 Nginx 门户暴露的基础设施服务
  home : { domain: i.pigsty }     # 默认首页服务器定义
infra_data: /data/infra           # 基础设施默认数据目录
infra_services: [...]             # 首页内置导航入口
infra_extra_services: []          # 追加到首页的导航入口

infra_seq

参数名称: infra_seq, 类型: int, 层次:I

基础设施节点序号,必选身份参数,必须在基础设施节点上显式指定,所以不提供默认值。

此参数用于在多个基础设施节点的部署中唯一标识每个节点,通常使用从 1 开始的正整数。

示例配置:

infra:
  hosts:
    10.10.10.10: { infra_seq: 1 }
    10.10.10.11: { infra_seq: 2 }

infra_portal

参数名称: infra_portal, 类型: dict, 层次:G

通过 Nginx 门户暴露的基础设施服务列表。v4.x 的默认值非常简洁:

infra_portal:
  home : { domain: i.pigsty }     # 默认首页服务器定义

Pigsty 会根据实际启用的组件自动配置相应的反向代理,用户通常只需要定义首页域名即可。

每条记录由一个 Key 与一个 Value 字典组成,name 作为键,代表组件名称,value 是一个可以配置以下参数的对象:

  • name: 必填,指定 Nginx 服务器的名称
    • 默认记录:home 是固定名称,请不要修改。
    • 作为 Nginx 配置文件名称的一部分,对应配置文件:/etc/nginx/conf.d/<name>.conf
    • 没有 domain 字段的 Nginx 服务器不会生成配置文件,但会被用作引用。
  • domain: 可选,当服务需要通过 Nginx 对外暴露时为 必填 字段,指定使用的域名
    • 在 Pigsty 自签名 Nginx HTTPS 证书中,域名将被添加到 Nginx SSL 证书的 SAN 字段
    • Pigsty 网页交叉引用将使用这里的默认域名
  • endpoint:通常作为 path 的替代,指定上游服务器地址。设置 endpoint 表示这是一个反向代理服务器
    • 配置中可以使用 ${admin_ip} 作为占位符,在部署时会被动态替换为 admin_ip
    • 默认反向代理服务器使用 endpoint.conf 作为配置模板
    • 反向代理服务器还可以配置 websocket 和 scheme 参数
  • path:通常作为 endpoint 的替代,指定本地文件服务器路径。设置 path 表示这是一个本地 Web 服务器
    • 本地 Web 服务器使用 path.conf 作为配置模板
    • 本地 Web 服务器还可以配置 index 参数,是否启用文件索引页
  • certbot:Certbot 证书名称,如果配置,将使用 Certbot 申请证书
    • 如果多个服务器指定相同的 certbot,Pigsty 会合并证书申请,最终证书名称为此 certbot 的值
  • cert:证书文件路径,如果配置,将覆盖默认证书路径
  • key:证书密钥文件路径,如果配置,将覆盖默认证书密钥路径
  • websocket:是否启用 WebSocket 支持
    • 只有反向代理服务器可以配置此参数,如果启用将允许上游使用 WebSocket 连接
  • scheme:上游服务器使用的协议,如果配置,将覆盖默认协议
    • 默认为 http,如果配置为 https 将强制使用 HTTPS 连接到上游服务器
  • index:是否启用文件索引页
    • 只有本地 Web 服务器可以配置此参数,如果启用将启用 autoindex 配置自动生成目录索引页
  • log:Nginx 日志文件路径
    • 如果指定,访问日志将写入此文件,否则根据服务器类型使用默认日志文件
    • 反向代理服务器使用 /var/log/nginx/<name>.log 作为默认日志文件路径
    • 本地 Web 服务器使用默认 Access 日志
  • conf:Nginx 配置文件路径
  • config:Nginx 配置代码块
    • 直接注入到 Nginx Server 配置块中的配置文本
  • enforce_https:将 HTTP 重定向到 HTTPS
    • 可以通过 nginx_sslmode: enforce 指定全局配置
    • 此配置不影响默认的 home 服务器,它将始终同时监听 80 和 443 端口以确保兼容性

infra_data

参数名称: infra_data, 类型: path, 层次:G

基础设施数据目录,默认值为 /data/infra

此目录用于存放基础设施组件的数据文件,包括:

  • VictoriaMetrics 时序数据库数据
  • VictoriaLogs 日志数据
  • VictoriaTraces 追踪数据
  • 其他基础设施组件的持久化数据

建议将此目录放置在独立的数据盘上,以便于管理和扩展。

infra_services

参数名称:infra_services,类型:service[],层次:G

Pigsty 首页的内置导航入口列表。当前默认入口包括 Metrics、Logs、Traces、Monitor Targets、Alert Rules、Alert Manager、CA Certificate、Software Repo 与 Explain Visualizer。

每项可使用 nameurldescicon 以及对应中文字段 name_cndesc_cn 定义显示内容。此参数会整体覆盖默认列表;只想增加入口时应优先使用 infra_extra_services

infra_extra_services

参数名称:infra_extra_services,类型:service[],层次:G

追加到 infra_services 后的首页导航入口列表,默认值为 []。其项目结构与 infra_services 相同,例如:

infra_extra_services:
  - { name: My Service, url: 'https://example.com', desc: 'External Service', icon: 'database' }

REPO

本节配置是关于本地软件仓库的。 Pigsty 默认会在基础设施节点上启用一个本地软件仓库(APT / YUM)。

在初始化过程中,Pigsty 会从互联网上游仓库(由 repo_upstream 指定)下载所有软件包及其依赖项(由 repo_packages 指定)到 {{ nginx_home }} / {{ repo_name }} (默认为 /www/pigsty),所有软件及其依赖的总大小约为 1GB 左右。

当前候选软件包版本为 SOW 0.3.0,源码使用 SOW 统一生成 RPM/APT 元数据。创建成功后,仓库目录中的 repo_complete 同时是 SHA-256 校验清单与完成标记;检测到该文件时,Pigsty 默认跳过下载和重建,直接使用已有仓库。强制重建需要执行 ./infra.yml -t repo_build -e repo_build=true

repo_createcache_create 都直接调用 sow create --pigsty,不再回退到 createrepo_cdpkg-scanpackages。旧离线包或旧本地仓库若不含 SOW,必须先刷新介质或从 Pigsty INFRA 仓库安装 SOW。

如果某些软件包的下载速度太慢,您可以通过使用 proxy_env 配置项来设置下载代理来完成首次下载,或直接下载预打包的 离线软件包,离线软件包本质上就是在同样操作系统上构建好的本地软件源。

repo_enabled: true                # 在此 Infra 节点上创建本地软件仓库?
repo_home: /www                   # 软件仓库主目录,默认为 /www
repo_name: pigsty                 # 软件仓库名称,默认为 pigsty
repo_endpoint: http://${admin_ip}:80 # 仓库访问端点
repo_remove: true                 # 移除现有上游仓库定义
repo_modules: infra,node,pgsql    # 启用的上游仓库模块
#repo_upstream: []                # 上游仓库定义(从操作系统变量继承)
#repo_packages: []                # 要下载的软件包(从操作系统变量继承)
#repo_extra_packages: []          # 额外要下载的软件包
repo_url_packages: []             # 通过 URL 下载的额外软件包

repo_enabled

参数名称: repo_enabled, 类型: bool, 层次:G/I

是否在当前的基础设施节点上启用本地软件源?默认为: true,即所有 Infra 节点都会设置一个本地软件仓库。

如果您有多个基础设施节点,可以只保留 1~2 个节点作为软件仓库,其他节点可以通过设置此参数为 false 来避免重复软件下载构建。

repo_home

参数名称: repo_home, 类型: path, 层次:G

本地软件仓库的家目录,默认为 Nginx 的根目录,也就是: /www

全新安装且该路径不存在时,角色会创建指向 nginx_data 的软链接;已经存在的目录或软链接会原样保留。通常不建议修改此目录;如需修改,应与 nginx_home 保持一致。

repo_name

参数名称: repo_name, 类型: string, 层次:G

本地仓库名称,默认为 pigsty,更改此仓库的名称是不明智的行为。

最终的仓库路径为 {{ repo_home }}/{{ repo_name }},默认为 /www/pigsty

repo_endpoint

参数名称: repo_endpoint, 类型: url, 层次:G

其他节点访问此仓库时使用的端点,默认值为:http://${admin_ip}:80

Pigsty 默认会在基础设施节点 80/443 端口启动 Nginx,对外提供本地软件源(静态文件)服务。

如果您修改了 nginx_portnginx_ssl_port,或者使用了不同于中控节点的基础设施节点,请相应调整此参数。

如果您使用了域名,可以在 node_default_etc_hostsnode_etc_hosts、或者 dns_records 中添加解析。

repo_remove

参数名称: repo_remove, 类型: bool, 层次:G/A

在构建本地软件源时,是否移除现有的上游仓库定义?默认值: true

当启用此参数时,/etc/yum.repos.d 中所有已有仓库文件会被移动备份至 /etc/yum.repos.d/backup,在 Debian 系上是移除 /etc/apt/sources.list/etc/apt/sources.list.d,将文件备份至 /etc/apt/backup 中。

因为操作系统已有的源内容不可控,使用 Pigsty 验证过的上游软件源可以提高从互联网下载软件包的成功率与速度。

但在一些特定情况下(例如您的操作系统是某种 EL/Deb 兼容版,许多软件包使用了自己的私有源),您可能需要保留现有的上游仓库定义,此时可以将此参数设置为 false

repo_modules

参数名称: repo_modules, 类型: string, 层次:G/A

哪些上游仓库模块会被添加到本地软件源中,默认值: infra,node,pgsql

当 Pigsty 尝试添加上游仓库时,会根据此参数的值来过滤 repo_upstream 中的条目,只有 module 字段与此参数值匹配的条目才会被添加到本地软件源中。

构建阶段会自动把 infra 加入实际模块列表,以确保可以安装 SOW;即使用户覆盖 repo_modules 时漏写 infra,该引导依赖仍会被补齐。

模块以逗号分隔,可用的模块列表请参考 repo_upstream 中的定义,常见模块包括:

  • local:本地 Pigsty 仓库
  • infra:基础设施软件包(Nginx、Docker 等)
  • node:操作系统基础软件包
  • pgsql:PostgreSQL 相关软件包
  • extra:额外的 PostgreSQL 扩展
  • docker:Docker 相关
  • redis:Redis 相关
  • mongo:MongoDB 相关
  • mysql:MySQL 相关
  • 等等…

repo_upstream

参数名称: repo_upstream, 类型: upstream[], 层次:G

构建本地软件源时,从哪里下载上游软件包?本参数没有默认值,如果用户不在配置文件中显式指定,则会从根据当前节点的操作系统族,从定义于 roles/node_id/vars 中的 repo_upstream_default 变量中加载获取。

Pigsty 为当前支持的操作系统版本(EL 8/9/10、Debian 12/13、Ubuntu 22/24/26)预置了完整的上游仓库定义,包括:

  • 操作系统基础仓库(BaseOS、AppStream、EPEL 等)
  • PostgreSQL 官方 PGDG 仓库
  • Pigsty 扩展仓库
  • 各种第三方软件仓库(Docker、Nginx、Grafana 等)

每个上游仓库定义包含以下字段:

- name: pigsty-pgsql              # 仓库名称
  description: 'Pigsty PGSQL'     # 仓库描述
  module: pgsql                   # 所属模块
  releases: [8,9,10]              # 支持的操作系统版本
  arch: [x86_64, aarch64]         # 支持的 CPU 架构
  baseurl:                        # 仓库 URL,按区域配置
    default: 'https://repo.pigsty.io/yum/pgsql/el$releasever.$basearch'
    china: 'https://repo.pigsty.cc/yum/pgsql/el$releasever.$basearch'
  # meta: { module_hotfixes: 1 } # 仅在明确替代 EL 模块流时启用

RPM 上游仓库默认保留系统原生 DNF 模块过滤;只有确实要替代模块流的软件源才应显式设置 meta.module_hotfixes。Pigsty 聚合本地仓库自身会以 module_hotfixes=1 使用,但不会生成伪造的 modules.yaml / ModuleMD 元数据。

用户通常不需要修改此参数,除非有特殊的仓库需求。详细的仓库定义请参考 roles/node_id/vars/ 目录下对应操作系统的配置文件。

repo_packages

参数名称: repo_packages, 类型: string[], 层次:G

字符串数组类型,每一行都是 由空格分隔 的软件包列表字符串,指定将要使用 repotrackapt download 下载到本地的软件包(及其依赖)。

本参数没有默认值,即默认值为未定义状态。如果该参数没有被显式定义,那么 Pigsty 会从 roles/node_id/vars 中定义的 repo_packages_default 变量中加载获取默认值,默认值为:

[ node-bootstrap, infra-package, infra-addons, node-package1, node-package2, node-package3, pgsql-utility, extra-modules ]

该参数中的每个元素,都会在上述文件中定义的 package_map 中,根据特定的操作系统发行版大版本进行翻译。例如在 EL 系统上会翻译为:

node-bootstrap:          "ansible python3 python3-requests python3-jmespath python3-cryptography dnf-utils sow sshpass"
infra-package:           "nginx dnsmasq etcd haproxy vip-manager node-exporter keepalived-exporter pg-exporter pgbackrest-exporter redis-exporter redis valkey silo mcli sow pig"
infra-addons:            "grafana grafana-plugins grafana-victoriametrics-ds grafana-victorialogs-ds victoria-metrics victoria-logs victoria-traces vlogscli vmutils vector alertmanager"

作为一个使用约定,repo_packages 中通常包括了那些与 PostgreSQL 大版本号无关的软件包(例如 Infra,Node 和 PGDG Common 等部分),而 PostgreSQL 大版本相关的软件包(内核,扩展),通常在 repo_extra_packages 中指定,方便用户切换 PG 大版本。

repo_extra_packages

参数名称: repo_extra_packages, 类型: string[], 层次:G/C/I

用于在不修改 repo_packages 的基础上,指定额外需要下载的软件包(通常是 PG 大版本相关的软件包),默认值为空列表。

如果该参数没有被显式定义,那么 Pigsty 会从 roles/node_id/vars 中定义的 repo_extra_packages_default 变量中加载获取默认值,默认值为:

[ pgsql-main ]

该参数中的元素会进行包名翻译,其中 $v 会被替换为 pg_version,即当前 PG 大版本号(默认为 18)。

这里的 pgsql-main 在 EL 系统上会翻译为:

postgresql$v postgresql$v-server postgresql$v-libs postgresql$v-contrib postgresql$v-plperl postgresql$v-plpython3 postgresql$v-pltcl postgresql$v-llvmjit pg_repack_$v* wal2json_$v* pgvector_$v*

通常用户可以在这里指定 PostgreSQL 大版本相关的软件包,而不影响 repo_packages 中定义的其他 PG 大版本无关的软件包。

repo_url_packages

参数名称: repo_url_packages, 类型: object[] | string[], 层次:G

直接使用 URL 从互联网上下载的软件包,默认为空数组: []

您可以直接在本参数中使用 URL 字符串作为数组元素,也可以使用对象结构,显式指定 URL 与文件名称。

请注意,本参数会受到 region 变量的影响,如果您在中国大陆地区,Pigsty 会自动将 URL 替换为国内镜像站点,即将 URL 里的 repo.pigsty.io 替换为 repo.pigsty.cc


INFRA_PACKAGE

这些软件包只会在 INFRA 节点上安装。

infra_packages

参数名称: infra_packages, 类型: string[], 层次:G

字符串数组类型,每一行都是 由空格分隔 的软件包列表字符串,指定将要在 Infra 节点上安装的软件包列表。

本参数没有单一的跨平台默认值。如果用户不显式指定,Pigsty 会根据操作系统版本与 CPU 架构,从 roles/node_id/vars 对应的平台文件中加载 infra_packages_default

例如,当前 EL 9 x86_64 的平台映射值为:

infra_packages_default:
  - grafana,grafana-plugins,grafana-victorialogs-ds,grafana-victoriametrics-ds,victoria-metrics,victoria-logs,victoria-traces,vmutils,vlogscli,alertmanager
  - node-exporter,blackbox-exporter,nginx-exporter,pg-exporter,pev2,nginx,dnsmasq,ansible,etcd,python3-requests,redis,mcli,restic,certbot,python3-certbot-nginx

当前 Debian 13 x86_64 的平台映射值为:

infra_packages_default:
  - grafana,grafana-plugins,grafana-victorialogs-ds,grafana-victoriametrics-ds,victoria-metrics,victoria-logs,victoria-traces,vmutils,vlogscli,alertmanager
  - node-exporter,blackbox-exporter,nginx-exporter,pg-exporter,pev2,nginx,dnsmasq,ansible,etcd,python3-requests,redis,mcli,restic,certbot,python3-certbot-nginx
说明

v4.x 使用 VictoriaMetrics 套件替代了 Prometheus 和 Loki,因此软件包列表与 v3.x 有显著差异。


NGINX

Pigsty 会通过 Nginx 代理所有的 Web 服务访问:Home Page、Grafana、VictoriaMetrics 等等。 以及其他可选的工具,如 PGWeb、Jupyter Lab、Pgadmin、Bytebase 等等,还有一些静态资源和报告,如 pevschemaspypgbadger

最重要的是,Nginx 还作为本地软件仓库(Yum/Apt)的 Web 服务器,用于存储和分发 Pigsty 的软件包。

nginx_enabled: true               # 在此 Infra 节点上启用 Nginx?
nginx_clean: false                # 初始化时清理现有 Nginx 配置?
nginx_exporter_enabled: true      # 启用 nginx_exporter?
nginx_exporter_port: 9113         # nginx_exporter 监听端口
nginx_sslmode: enable             # SSL 模式:disable,enable,enforce
nginx_cert_validity: 397d         # 自签名证书有效期
nginx_home: /www                  # Nginx 内容目录(软链接)
nginx_data: /data/nginx           # Nginx 实际数据目录
nginx_users: {}                   # 基础认证用户字典
nginx_port: 80                    # HTTP 端口
nginx_ssl_port: 443               # HTTPS 端口
certbot_sign: false               # 使用 certbot 签署证书?
certbot_email: [email protected]     # certbot 邮箱
certbot_options: ''               # certbot 额外选项

nginx_enabled

参数名称: nginx_enabled, 类型: bool, 层次:G/I

是否在当前的 Infra 节点上启用 Nginx?默认值为: true

Nginx 是 Pigsty 基础设施的核心组件,负责:

  • 提供本地软件仓库服务
  • 反向代理 Grafana、VictoriaMetrics 等 Web 服务
  • 托管静态文件和报告

nginx_clean

参数名称: nginx_clean, 类型: bool, 层次:G/A

初始化时是否清理现有的 Nginx 配置?默认值为: false

当设置为 true 时,在 Nginx 初始化过程中会删除 /etc/nginx/conf.d/ 下的所有现有配置文件,确保一个干净的起点。

如果您是首次部署或希望完全重建 Nginx 配置,可以将此参数设置为 true

nginx_exporter_enabled

参数名称: nginx_exporter_enabled, 类型: bool, 层次:G/I

在此基础设施节点上启用 nginx_exporter?默认值为: true

如果禁用此选项,还会一并禁用 /nginx 健康检查 stub,当您安装使用的 Nginx 版本不支持此功能时可以考虑关闭此开关。

nginx_exporter_port

参数名称: nginx_exporter_port, 类型: port, 层次:G

nginx_exporter 监听端口,默认值为 9113

nginx_exporter 用于收集 Nginx 的运行指标,供 VictoriaMetrics 抓取监控。

nginx_sslmode

参数名称: nginx_sslmode, 类型: enum, 层次:G

Nginx 的 SSL 工作模式?有三种选择:disable , enable , enforce, 默认值为 enable,即启用 SSL,但不强制使用。

  • disable:只监听 nginx_port 指定的端口服务 HTTP 请求。
  • enable:同时会监听 nginx_ssl_port 指定的端口服务 HTTPS 请求。
  • enforce:所有链接都会被渲染为默认使用 https://
    • 同时会将 infra_portal 中非默认服务器的 80 端口重定向到 443 端口

nginx_cert_validity

参数名称: nginx_cert_validity, 类型: duration, 层次:G

Nginx 自签名证书的有效期,默认值为 397d(约13个月)。

现代浏览器要求网站证书的有效期最多为 397 天,因此这是默认值。不建议设置更长的有效期,否则浏览器可能会拒绝信任该证书。

nginx_home

参数名称: nginx_home, 类型: path, 层次:G

Nginx 服务器静态文件目录,默认为: /www

这是一个软链接,实际指向 nginx_data 目录。此目录包含静态资源和软件仓库文件。

最好不要随意修改此参数,修改时需要与 repo_home 参数保持一致。

nginx_data

参数名称: nginx_data, 类型: path, 层次:G

Nginx 实际数据目录,默认为 /data/nginx

这是 Nginx 静态文件的实际存储位置,nginx_home 是指向此目录的软链接。

建议将此目录放置在数据盘上,以便于管理大量的软件包文件。

nginx_users

参数名称: nginx_users, 类型: dict, 层次:G

Nginx 基础认证(Basic Auth)用户字典,默认为空字典 {}

格式为 { username: password } 的键值对,例如:

nginx_users:
  admin: pigsty
  viewer: readonly

这些用户可用于保护某些需要认证的 Nginx 端点。

nginx_port

参数名称: nginx_port, 类型: port, 层次:G

Nginx 默认监听的端口(提供 HTTP 服务),默认为 80 端口,最好不要修改这个参数。

当您的服务器 80 端口被占用时,可以考虑修改此参数,但需要同时修改 repo_endpoint 并确保相关节点能够通过新的端口访问本地软件仓库。

nginx_ssl_port

参数名称: nginx_ssl_port, 类型: port, 层次:G

Nginx SSL 默认监听的端口,默认为 443,最好不要修改这个参数。

certbot_sign

参数名称: certbot_sign, 类型: bool, 层次:G/A

是否在安装过程中使用 certbot 签署 Nginx 证书?默认值为 false

当设置为 true 时,Pigsty 会在执行 infra.ymldeploy.yml 剧本(nginx 角色)期间使用 certbot 自动从 Let’s Encrypt 申请免费 SSL 证书。

infra_portal 定义的域名中,如果定义了 certbot 参数,Pigsty 将使用 certbot 为 domain 域名申请证书,证书名称将是 certbot 参数的值。如果多个服务器/域名指定了相同的 certbot 参数,Pigsty 会合并并为这些域名申请一个证书,使用 certbot 参数的值作为证书名称。

启用此选项需要:

  • 当前节点可以通过公共域名访问,并且 DNS 解析已正确指向当前节点的公网 IP
  • 当前节点可以访问 Let’s Encrypt API 接口

此选项默认禁用,您可以在安装后手动执行 make cert 命令来手动执行,它实际上调用渲染好的 /etc/nginx/sign-cert 脚本,使用 certbot 更新或申请证书。

certbot_email

参数名称: certbot_email, 类型: string, 层次:G/A

用于接收证书过期提醒邮件的电子邮件地址,默认值为 [email protected]

certbot_sign 设置为 true 时,建议提供此参数。Let’s Encrypt 会在证书即将过期时向此邮箱发送提醒邮件。

certbot_options

参数名称: certbot_options, 类型: string, 层次:G/A

传递给 certbot 的额外配置参数,默认值为空字符串。

您可以通过此参数向 certbot 传递额外的命令行选项,例如 --dry-run,则 certbot 不会实际申请证书,而是进行预览和测试。


DNS

Pigsty 默认会在 Infra 节点上启用 DNSMASQ 服务,用于解析一些辅助域名,例如 i.pigstym.pigstysupa.pigstyapi.pigsty 等。

解析记录会记录在 Infra 节点的 /etc/dnsmasq.d/pigsty/default 文件中。 要使用这个 DNS 服务器,您必须将 nameserver <ip> 添加到 /etc/resolv.conf 中,node_dns_servers 参数可以解决这个问题。

dns_enabled: true                 # 在此 Infra 节点上设置 dnsmasq?
dns_port: 53                      # DNS 服务器监听端口
dns_records:                      # 动态 DNS 记录
  - "${admin_ip} i.pigsty"
  - "${admin_ip} m.pigsty supa.pigsty api.pigsty adm.pigsty cli.pigsty ddl.pigsty"

dns_enabled

参数名称: dns_enabled, 类型: bool, 层次:G/I

是否在这个 Infra 节点上启用 DNSMASQ 服务?默认值为: true

如果你不想使用默认的 DNS 服务器(比如你已经有了外部的 DNS 服务器,或者您的供应商不允许您使用 DNS 服务器)可以将此值设置为 false 来禁用它。 并使用 node_default_etc_hostsnode_etc_hosts 静态解析记录代替。

dns_port

参数名称: dns_port, 类型: port, 层次:G

DNSMASQ 的默认监听端口,默认是 53,不建议修改 DNS 服务默认端口。

dns_records

参数名称: dns_records, 类型: string[], 层次:G

由 dnsmasq 负责解析的动态 DNS 记录,一般用于将一些辅助域名解析到管理节点。这些记录会被写入到基础设施节点的 /etc/dnsmasq.d/pigsty/default 文件中。

v4.x 默认值:

dns_records:
  - "${admin_ip} i.pigsty"
  - "${admin_ip} m.pigsty supa.pigsty api.pigsty adm.pigsty cli.pigsty ddl.pigsty"

这里使用 ${admin_ip} 占位符,在部署时会被替换为实际的 admin_ip 值。

常见的域名用途:

  • i.pigsty:Pigsty 首页
  • m.pigsty:常用于 Silo 控制台(可选)
  • p.pigsty:常用于 VictoriaMetrics Web UI(当在 infra_portal 中显式配置时)
  • api.pigsty:API 服务
  • adm.pigsty:管理服务
  • 其他根据实际部署需求自定义

VICTORIA

Pigsty v4.x 使用 VictoriaMetrics 套件替代 Prometheus 和 Loki,提供更优秀的可观测性解决方案:

  • VictoriaMetrics:替代 Prometheus,作为时序数据库存储监控指标
  • VictoriaLogs:替代 Loki,作为日志聚合存储
  • VictoriaTraces:分布式追踪存储
  • VMAlert:替代 Prometheus Alerting,进行告警规则评估
vmetrics_enabled: true            # 启用 VictoriaMetrics?
vmetrics_clean: false             # 初始化时清理数据?
vmetrics_port: 8428               # 监听端口
vmetrics_scrape_interval: 10s     # 全局抓取间隔
vmetrics_scrape_timeout: 8s       # 全局抓取超时
vmetrics_options: >-
  -retentionPeriod=15d
  -promscrape.fileSDCheckInterval=5s
vlogs_enabled: true               # 启用 VictoriaLogs?
vlogs_clean: false                # 初始化时清理数据?
vlogs_port: 9428                  # 监听端口
vlogs_options: >-
  -retentionPeriod=15d
  -retention.maxDiskSpaceUsageBytes=50GiB
  -insert.maxLineSizeBytes=1MB
  -search.maxQueryDuration=120s
vtraces_enabled: true             # 启用 VictoriaTraces?
vtraces_clean: false              # 初始化时清理数据?
vtraces_port: 10428               # 监听端口
vtraces_options: >-
  -retentionPeriod=15d
  -retention.maxDiskSpaceUsageBytes=50GiB
vmalert_enabled: true             # 启用 VMAlert?
vmalert_port: 8880                # 监听端口
vmalert_options: ''               # 额外命令行参数

vmetrics_enabled

参数名称: vmetrics_enabled, 类型: bool, 层次:G/I

是否在当前 Infra 节点上启用 VictoriaMetrics?默认值为 true

VictoriaMetrics 是 Pigsty v4.x 的核心监控组件,替代 Prometheus 作为时序数据库,负责:

  • 从各个 Exporter 抓取监控指标
  • 存储时序数据
  • 提供 PromQL 兼容的查询接口
  • 支持 Grafana 数据源

vmetrics_clean

参数名称: vmetrics_clean, 类型: bool, 层次:G/A

初始化 VictoriaMetrics 时是否清理现有数据?默认值为 false

当设置为 true 时,在初始化过程中会删除已有的时序数据。谨慎使用此选项,除非您确定要重建监控数据。

vmetrics_port

参数名称: vmetrics_port, 类型: port, 层次:G

VictoriaMetrics 监听端口,默认值为 8428

此端口用于:

  • HTTP API 访问
  • Web UI 访问
  • Prometheus 兼容的远程写入/读取
  • Grafana 数据源连接

vmetrics_scrape_interval

参数名称: vmetrics_scrape_interval, 类型: interval, 层次:G

VictoriaMetrics 全局指标抓取周期,默认值为 10s

在生产环境,10秒 - 30秒是一个较为合适的抓取周期。如果您需要更精细的监控数据粒度,可以调整此参数,但会增加存储和 CPU 开销。

vmetrics_scrape_timeout

参数名称: vmetrics_scrape_timeout, 类型: interval, 层次:G

VictoriaMetrics 全局抓取超时,默认为 8s

设置抓取超时可以有效避免监控系统查询导致的雪崩,设置原则是本参数必须小于并接近 vmetrics_scrape_interval,确保每次抓取时长不超过抓取周期。

vmetrics_options

参数名称: vmetrics_options, 类型: arg, 层次:G

VictoriaMetrics 的额外命令行参数,默认值:

vmetrics_options: >-
  -retentionPeriod=15d
  -promscrape.fileSDCheckInterval=5s

常用参数说明:

  • -retentionPeriod=15d:数据保留期限,默认 15 天
  • -promscrape.fileSDCheckInterval=5s:文件服务发现刷新间隔

您可以根据需要添加其他 VictoriaMetrics 支持的参数。

vlogs_enabled

参数名称: vlogs_enabled, 类型: bool, 层次:G/I

是否在当前 Infra 节点上启用 VictoriaLogs?默认值为 true

VictoriaLogs 替代 Loki 作为日志聚合存储,负责:

  • 接收来自 Vector 的日志数据
  • 存储和索引日志
  • 提供日志查询接口
  • 支持 Grafana VictoriaLogs 数据源

vlogs_clean

参数名称: vlogs_clean, 类型: bool, 层次:G/A

初始化 VictoriaLogs 时是否清理现有数据?默认值为 false

vlogs_port

参数名称: vlogs_port, 类型: port, 层次:G

VictoriaLogs 监听端口,默认值为 9428

vlogs_options

参数名称: vlogs_options, 类型: arg, 层次:G

VictoriaLogs 的额外命令行参数,默认值:

vlogs_options: >-
  -retentionPeriod=15d
  -retention.maxDiskSpaceUsageBytes=50GiB
  -insert.maxLineSizeBytes=1MB
  -search.maxQueryDuration=120s

常用参数说明:

  • -retentionPeriod=15d:日志保留期限,默认 15 天
  • -retention.maxDiskSpaceUsageBytes=50GiB:最大磁盘使用量
  • -insert.maxLineSizeBytes=1MB:单行日志最大大小
  • -search.maxQueryDuration=120s:查询最大执行时间

vtraces_enabled

参数名称: vtraces_enabled, 类型: bool, 层次:G/I

是否在当前 Infra 节点上启用 VictoriaTraces?默认值为 true

VictoriaTraces 用于分布式追踪数据的存储和查询,支持 Jaeger、Zipkin 等追踪协议。

vtraces_clean

参数名称: vtraces_clean, 类型: bool, 层次:G/A

初始化 VictoriaTraces 时是否清理现有数据?默认值为 false

vtraces_port

参数名称: vtraces_port, 类型: port, 层次:G

VictoriaTraces 监听端口,默认值为 10428

vtraces_options

参数名称: vtraces_options, 类型: arg, 层次:G

VictoriaTraces 的额外命令行参数,默认值:

vtraces_options: >-
  -retentionPeriod=15d
  -retention.maxDiskSpaceUsageBytes=50GiB

vmalert_enabled

参数名称: vmalert_enabled, 类型: bool, 层次:G/I

是否在当前 Infra 节点上启用 VMAlert?默认值为 true

VMAlert 负责告警规则评估,替代 Prometheus Alerting 功能,与 Alertmanager 配合使用。

vmalert_port

参数名称: vmalert_port, 类型: port, 层次:G

VMAlert 监听端口,默认值为 8880

vmalert_options

参数名称: vmalert_options, 类型: arg, 层次:G

VMAlert 的额外命令行参数,默认值为空字符串。


PROMETHEUS

此部分现在主要包含 Blackbox Exporter 和 Alertmanager 的配置。

说明

Pigsty v4.x 使用 VictoriaMetrics 替代 Prometheus;旧的 prometheus_*pushgateway_* 参数已不再是当前接口,指标存储与规则评估请使用 VICTORIA 中的 vmetrics_*vmalert_* 参数。

blackbox_enabled: true            # 启用 blackbox_exporter?
blackbox_port: 9115               # blackbox_exporter 监听端口
blackbox_options: ''              # 额外命令行参数
alertmanager_enabled: true        # 启用 alertmanager?
alertmanager_port: 9059           # alertmanager 监听端口
alertmanager_options: ''          # 额外命令行参数
exporter_metrics_path: /metrics   # exporter 指标路径

blackbox_enabled

参数名称: blackbox_enabled, 类型: bool, 层次:G/I

是否在当前 Infra 节点上启用 BlackboxExporter?默认值为 true

BlackboxExporter 会向节点 IP 地址、VIP 地址、PostgreSQL VIP 地址发送 ICMP 报文测试网络连通性,还可以进行 HTTP、TCP、DNS 等探测。

blackbox_port

参数名称: blackbox_port, 类型: port, 层次:G

Blackbox Exporter 监听端口,默认值为 9115

blackbox_options

参数名称: blackbox_options, 类型: arg, 层次:G

BlackboxExporter 的额外命令行参数,默认值:空字符串。

alertmanager_enabled

参数名称: alertmanager_enabled, 类型: bool, 层次:G/I

是否在当前 Infra 节点上启用 AlertManager?默认值为 true

AlertManager 负责接收来自 VMAlert 的告警通知,并进行告警分组、抑制、静默、路由等处理。

alertmanager_port

参数名称: alertmanager_port, 类型: port, 层次:G

AlertManager 监听端口,默认值为 9059

如果您修改了此端口,请确保相应更新 infra_portal 中 alertmanager 条目的 endpoint 配置(如果有定义的话)。

alertmanager_options

参数名称: alertmanager_options, 类型: arg, 层次:G

AlertManager 的额外命令行参数,默认值:空字符串。

exporter_metrics_path

参数名称: exporter_metrics_path, 类型: path, 层次:G

监控 exporter 暴露指标的 HTTP 端点路径,默认为: /metrics,不建议修改此参数。

此参数定义了所有 Exporter 暴露监控指标的标准路径。


GRAFANA

Pigsty 使用 Grafana 作为监控系统前端。它也可以作为数据分析与可视化平台,或者用于低代码数据应用开发,制作数据应用原型等目的。

grafana_enabled: true             # 启用 Grafana?
grafana_port: 3000                # Grafana 监听端口
grafana_clean: false              # 初始化时清理数据?
grafana_admin_username: admin     # 管理员用户名
grafana_admin_password: pigsty    # 管理员密码
grafana_auth_proxy: false         # 启用身份代理?
grafana_pgurl: ''                 # 外部 PostgreSQL URL
grafana_view_password: DBUser.Viewer  # PG 数据源密码

grafana_enabled

参数名称: grafana_enabled, 类型: bool, 层次:G/I

是否在 Infra 节点上启用 Grafana?默认值为: true,即所有基础设施节点默认都会安装启用 Grafana。

grafana_port

参数名称: grafana_port, 类型: port, 层次:G

Grafana 监听端口,默认值为 3000

如果您需要直接访问 Grafana(不通过 Nginx 反向代理),可以使用此端口。

grafana_clean

参数名称: grafana_clean, 类型: bool, 层次:G/A

是否在初始化 Grafana 时一并清理其数据文件?默认为:false

如果设置为 true,初始化 Grafana 时会移除 /var/lib/grafana/grafana.db,确保 Grafana 是一个全新安装。

如果您希望保留现有的 Grafana 配置(如仪表盘、用户、数据源等),请将此参数保留为 false

grafana_admin_username

参数名称: grafana_admin_username, 类型: username, 层次:G

Grafana 管理员用户名,默认为 admin

grafana_admin_password

参数名称: grafana_admin_password, 类型: password, 层次:G

Grafana 管理员密码,默认为 pigsty

重要提示:请务必在生产部署中修改此密码参数!

grafana_auth_proxy

参数名称: grafana_auth_proxy, 类型: bool, 层次:G

是否启用 Grafana 身份代理?默认为 false

当启用时,Grafana 会信任反向代理(Nginx)传递的用户身份信息,实现单点登录(SSO)功能。

这通常用于与外部身份认证系统集成的场景。

grafana_pgurl

参数名称: grafana_pgurl, 类型: url, 层次:G

外部 PostgreSQL 数据库 URL,用于 Grafana 持久化存储。默认为空字符串。

如果指定,Grafana 将使用此 PostgreSQL 数据库替代默认的 SQLite 数据库存储其配置数据。

格式示例:postgres://grafana:password@pg-meta:5432/grafana?sslmode=disable

这对于需要 Grafana 高可用部署或数据持久化的场景非常有用。

grafana_view_password

参数名称: grafana_view_password, 类型: password, 层次:G

Grafana 元数据库 PG 数据源使用的只读用户密码,默认为 DBUser.Viewer

此密码用于 Grafana 连接 PostgreSQL CMDB 数据源,以只读方式查询元数据。

9.3 - 预置剧本

如何使用预置的 ansible 剧本来管理 INFRA 集群,常用管理命令速查。

Pigsty 提供了三个与 INFRA 模块相关的剧本:

  • deploy.yml:在所有节点上一次性部署 NODE、INFRA、ETCD、MINIO 与 PGSQL 核心模块
  • infra.yml:在 infra 节点上初始化 pigsty 基础设施
  • infra-rm.yml:从 infra 节点移除基础设施组件

deploy.yml

在所有节点上一次性部署 NODE、INFRA、ETCD、MINIO 与 PGSQL 核心模块,解决 INFRA/NODE 循环依赖问题。

该剧本会交叉执行 infra.ymlnode.yml 的子任务,按以下顺序完成核心组件的部署:

  1. id:生成节点与 PostgreSQL 身份标识
  2. ca:在本地创建自签名 CA 证书
  3. repo:在 infra 节点上创建本地软件仓库
  4. node-init:初始化节点与 HAProxy
  5. infra:初始化 Nginx、DNS、VictoriaMetrics、Grafana 等
  6. node-monitor:初始化 node-exporter、vector
  7. etcd:初始化 etcd(PostgreSQL 高可用必需)
  8. minio:初始化 Silo(可选)
  9. pgsql:初始化 PostgreSQL 集群并配置 PostgreSQL 监控

该剧本等效于依次执行以下五个剧本:

./infra.yml -l infra    # 在 infra 分组上部署基础设施
./node.yml              # 在所有节点上初始化节点
./etcd.yml              # 初始化 etcd 集群
./minio.yml             # 初始化 MINIO(Silo)集群(可选)
./pgsql.yml             # 初始化 PostgreSQL 集群

deploy.yml 当前不部署 Docker 模块;需要 Docker 时,应另行设置 docker_enabled: true 并单独执行 docker.yml


infra.yml

在配置文件的 infra 分组所定义的 Infra 节点 上初始化基础设施模块。

执行该剧本将完成以下任务:

  • 配置 Infra 节点 的目录与环境变量
  • 下载并创建本地软件仓库,加速后续安装
  • 将当前 Infra 节点 作为普通节点纳入 Pigsty 管理
  • 部署基础设施组件(VictoriaMetrics/Logs/Traces、VMAlert、Grafana、Alertmanager、Blackbox Exporter 等)

剧本注意事项

  • 本剧本为幂等剧本,重复执行默认不会清理历史数据与 Grafana 数据
  • 如需保留历史监控数据,请先将 vmetrics_cleanvlogs_cleanvtraces_clean 设置为 false
  • 如果设置 grafana_cleantrue,Grafana 数据库会被清理,原有仪表盘与配置会丢失
  • 当本地软件仓库 /www/pigsty/repo_complete 存在时,本剧本会跳过互联网下载;该文件是 SOW 生成的 SHA-256 清单与完成标记
  • 完整执行该剧本耗时约1~3分钟,视机器配置与网络条件而异

可用任务列表

# ca: create self-signed CA on localhost files/pki
#   - ca_dir        : create CA directory
#   - ca_private    : generate ca private key: files/pki/ca/ca.key
#   - ca_cert       : signing ca cert: files/pki/ca/ca.crt
#
# id: generate node identity
#
# repo: bootstrap a local yum repo from internet or offline packages
#   - repo_dir      : create repo directory
#   - repo_check    : check repo exists
#   - repo_prepare  : use existing repo if exists
#   - repo_build    : build repo from upstream if not exists
#     - repo_upstream    : handle upstream repo files in /etc/yum.repos.d
#       - repo_remove    : remove existing repo file if repo_remove == true
#       - repo_add       : add upstream repo files to /etc/yum.repos.d
#     - repo_url_pkg     : download packages from internet defined by repo_url_packages
#     - repo_cache       : make upstream yum cache with yum makecache
#     - repo_boot_pkg    : install sow and dnf/yum download utilities
#     - repo_pkg         : download packages & dependencies from upstream repo
#     - repo_create      : atomically create RPM/APT metadata with sow create --pigsty
#     - repo_use         : add newly built repo into /etc/yum.repos.d
#   - repo_nginx    : launch a nginx for repo if no nginx is serving
#
# node/haproxy/monitor: setup infra node as a common node
#   - node_name, node_hosts, node_resolv, node_firewall, node_ca, node_repo, node_pkg
#   - node_feature, node_kernel, node_tune, node_sysctl, node_profile, node_ulimit
#   - node_data, node_admin, node_timezone, node_ntp, node_crontab, node_vip
#   - haproxy_install, haproxy_config, haproxy_launch, haproxy_reload
#   - haproxy_register, node_exporter, node_register, vector
#
# infra: setup infra components
#   - infra_user     : setup infra os user group
#   - infra_dir      : create infra data/config/runtime directories
#   - infra_env      : env_patroni, env_pg, env_pgadmin, env_etcd, env_pglog, env_var
#   - infra_pkg      : install infra packages
#   - infra_cert     : issue cert for infra components
#   - dns            : dns_config, dns_record, dns_launch
#   - nginx          : nginx_dir, nginx_config, nginx_cert, nginx_static, nginx_launch, nginx_certbot, nginx_reload, nginx_exporter
#   - victoria       : vmetrics/vlogs/vtraces clean, config & launch; vmalert_config, vmalert_launch
#   - alertmanager   : alertmanager_config, alertmanager_launch
#   - blackbox       : blackbox_config, blackbox_launch
#   - grafana        : grafana_clean, grafana_dir, grafana_config, grafana_launch, grafana_provision
#   - infra_register : add_metrics, add_logs, add_ds

infra-rm.yml

从配置文件 infra 分组定义的 Infra 节点 上移除 Pigsty 基础设施。

常用子任务包括:

./infra-rm.yml               # 执行全部阶段:注销、停服、删配置/环境/数据并卸载软件包
./infra-rm.yml -t deregister # 仅注销监控目标、Grafana 数据源与 Nginx 日志采集
./infra-rm.yml -t service    # 停止 INFRA 上的基础设施服务
./infra-rm.yml -t config     # 删除 INFRA 配置与 Systemd Unit
./infra-rm.yml -t env        # 删除管理用户环境文件
./infra-rm.yml -t data       # 移除 INFRA 数据
./infra-rm.yml -t package    # 卸载 INFRA 软件包
全量移除会删除数据

infra-rm.yml 没有防误删开关;不带标签执行时会运行上面所有阶段。data 阶段会递归删除 infra_data(默认 /data/infra)、nginx_data(默认 /data/nginx)、nginx_home(默认 /www)与 /var/lib/grafana,其中包括监控/日志/追踪数据、软件仓库和 Grafana 本地数据。只想停服或注销时必须使用相应标签;全量执行前必须备份需要保留的数据,并核对精确的 infra 目标。

9.4 - 监控告警

如何在 Pigsty 中对基础设施进行自监控?

本文介绍 Pigsty 中 INFRA 模块的监控面板与告警规则。


监控面板

Pigsty 针对 Infra 模块提供了以下监控面板:

面板 描述
Pigsty Home Pigsty 监控系统主页
INFRA Overview Pigsty 基础设施自监控概览
Nginx Instance Nginx 监控指标与日志
Grafana Instance Grafana 监控指标与日志
VictoriaMetrics Instance VictoriaMetrics 抓取/查询状态
VMAlert Instance 告警规则执行情况
Alertmanager Instance 告警聚合与通知
VictoriaLogs Instance 日志写入、查询与索引
Logs Instance 查阅单个节点上的日志信息
VictoriaTraces Instance Trace 存储与查询
Inventory CMDB CMDB 可视化
ETCD Overview etcd 集群监控

告警规则

Pigsty 针对 INFRA 模块提供了以下两条告警规则:

告警规则 描述
InfraDown 基础设施组件出现宕机
AgentDown 监控 Agent 代理出现宕机

可在 files/victoria/rules/infra.yml 中修改或添加新的基础设施告警规则。

告警规则配置

################################################################
#                Infrastructure Alert Rules                    #
################################################################
- name: infra-alert
  rules:

    #==============================================================#
    #                       Infra Aliveness                        #
    #==============================================================#
    # infra components (victoria,grafana) down for 1m triggers a P1 alert
    - alert: InfraDown
      expr: infra_up < 1
      for: 1m
      labels: { level: 0, severity: CRIT, category: infra }
      annotations:
        summary: "CRIT InfraDown {{ $labels.type }}@{{ $labels.instance }}"
        description: |
          infra_up[type={{ $labels.type }}, instance={{ $labels.instance }}] = {{ $value  | printf "%.2f" }} < 1

    #==============================================================#
    #                       Agent Aliveness                        #
    #==============================================================#

    # agent aliveness are determined directly by exporter aliveness
    # including: node_exporter, pg_exporter, pgbouncer_exporter, haproxy_exporter
    - alert: AgentDown
      expr: agent_up < 1
      for: 1m
      labels: { level: 0, severity: CRIT, category: infra }
      annotations:
        summary: 'CRIT AgentDown {{ $labels.ins }}@{{ $labels.instance }}'
        description: |
          agent_up[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value  | printf "%.2f" }} < 1

9.5 - 指标列表

Pigsty INFRA 模块提供的完整监控指标列表与释义

注意:Pigsty v4.0 已将 Prometheus/Loki 替换为 VictoriaMetrics/Logs/Traces。以下指标清单仍基于 v3.x 生成,仅供排查旧版本问题参考。若需获取最新指标,请在 https://p.pigsty (VMUI) 或 Grafana 中直接查询,后续版本会重新生成与 Victoria 套件一致的指标速查表。

INFRA 指标

INFRA 模块包含有 964 类可用监控指标。

Metric Name Type Labels Description
alertmanager_alerts gauge ins, instance, ip, job, cls, state How many alerts by state.
alertmanager_alerts_invalid_total counter version, ins, instance, ip, job, cls The total number of received alerts that were invalid.
alertmanager_alerts_received_total counter version, ins, instance, ip, status, job, cls The total number of received alerts.
alertmanager_build_info gauge revision, version, ins, instance, ip, tags, goarch, goversion, job, cls, branch, goos A metric with a constant ‘1’ value labeled by version, revision, branch, goversion from which alertmanager was built, and the goos and goarch for the build.
alertmanager_cluster_alive_messages_total counter ins, instance, ip, peer, job, cls Total number of received alive messages.
alertmanager_cluster_enabled gauge ins, instance, ip, job, cls Indicates whether the clustering is enabled or not.
alertmanager_cluster_failed_peers gauge ins, instance, ip, job, cls Number indicating the current number of failed peers in the cluster.
alertmanager_cluster_health_score gauge ins, instance, ip, job, cls Health score of the cluster. Lower values are better and zero means ’totally healthy’.
alertmanager_cluster_members gauge ins, instance, ip, job, cls Number indicating current number of members in cluster.
alertmanager_cluster_messages_pruned_total counter ins, instance, ip, job, cls Total number of cluster messages pruned.
alertmanager_cluster_messages_queued gauge ins, instance, ip, job, cls Number of cluster messages which are queued.
alertmanager_cluster_messages_received_size_total counter ins, instance, ip, msg_type, job, cls Total size of cluster messages received.
alertmanager_cluster_messages_received_total counter ins, instance, ip, msg_type, job, cls Total number of cluster messages received.
alertmanager_cluster_messages_sent_size_total counter ins, instance, ip, msg_type, job, cls Total size of cluster messages sent.
alertmanager_cluster_messages_sent_total counter ins, instance, ip, msg_type, job, cls Total number of cluster messages sent.
alertmanager_cluster_peer_info gauge ins, instance, ip, peer, job, cls A metric with a constant ‘1’ value labeled by peer name.
alertmanager_cluster_peers_joined_total counter ins, instance, ip, job, cls A counter of the number of peers that have joined.
alertmanager_cluster_peers_left_total counter ins, instance, ip, job, cls A counter of the number of peers that have left.
alertmanager_cluster_peers_update_total counter ins, instance, ip, job, cls A counter of the number of peers that have updated metadata.
alertmanager_cluster_reconnections_failed_total counter ins, instance, ip, job, cls A counter of the number of failed cluster peer reconnection attempts.
alertmanager_cluster_reconnections_total counter ins, instance, ip, job, cls A counter of the number of cluster peer reconnections.
alertmanager_cluster_refresh_join_failed_total counter ins, instance, ip, job, cls A counter of the number of failed cluster peer joined attempts via refresh.
alertmanager_cluster_refresh_join_total counter ins, instance, ip, job, cls A counter of the number of cluster peer joined via refresh.
alertmanager_config_hash gauge ins, instance, ip, job, cls Hash of the currently loaded alertmanager configuration.
alertmanager_config_last_reload_success_timestamp_seconds gauge ins, instance, ip, job, cls Timestamp of the last successful configuration reload.
alertmanager_config_last_reload_successful gauge ins, instance, ip, job, cls Whether the last configuration reload attempt was successful.
alertmanager_dispatcher_aggregation_groups gauge ins, instance, ip, job, cls Number of active aggregation groups
alertmanager_dispatcher_alert_processing_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
alertmanager_dispatcher_alert_processing_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
alertmanager_http_concurrency_limit_exceeded_total counter ins, instance, method, ip, job, cls Total number of times an HTTP request failed because the concurrency limit was reached.
alertmanager_http_request_duration_seconds_bucket Unknown ins, instance, method, ip, le, job, cls, handler N/A
alertmanager_http_request_duration_seconds_count Unknown ins, instance, method, ip, job, cls, handler N/A
alertmanager_http_request_duration_seconds_sum Unknown ins, instance, method, ip, job, cls, handler N/A
alertmanager_http_requests_in_flight gauge ins, instance, method, ip, job, cls Current number of HTTP requests being processed.
alertmanager_http_response_size_bytes_bucket Unknown ins, instance, method, ip, le, job, cls, handler N/A
alertmanager_http_response_size_bytes_count Unknown ins, instance, method, ip, job, cls, handler N/A
alertmanager_http_response_size_bytes_sum Unknown ins, instance, method, ip, job, cls, handler N/A
alertmanager_integrations gauge ins, instance, ip, job, cls Number of configured integrations.
alertmanager_marked_alerts gauge ins, instance, ip, job, cls, state How many alerts by state are currently marked in the Alertmanager regardless of their expiry.
alertmanager_nflog_gc_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
alertmanager_nflog_gc_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
alertmanager_nflog_gossip_messages_propagated_total counter ins, instance, ip, job, cls Number of received gossip messages that have been further gossiped.
alertmanager_nflog_maintenance_errors_total counter ins, instance, ip, job, cls How many maintenances were executed for the notification log that failed.
alertmanager_nflog_maintenance_total counter ins, instance, ip, job, cls How many maintenances were executed for the notification log.
alertmanager_nflog_queries_total counter ins, instance, ip, job, cls Number of notification log queries were received.
alertmanager_nflog_query_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
alertmanager_nflog_query_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
alertmanager_nflog_query_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
alertmanager_nflog_query_errors_total counter ins, instance, ip, job, cls Number notification log received queries that failed.
alertmanager_nflog_snapshot_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
alertmanager_nflog_snapshot_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
alertmanager_nflog_snapshot_size_bytes gauge ins, instance, ip, job, cls Size of the last notification log snapshot in bytes.
alertmanager_notification_latency_seconds_bucket Unknown integration, ins, instance, ip, le, job, cls N/A
alertmanager_notification_latency_seconds_count Unknown integration, ins, instance, ip, job, cls N/A
alertmanager_notification_latency_seconds_sum Unknown integration, ins, instance, ip, job, cls N/A
alertmanager_notification_requests_failed_total counter integration, ins, instance, ip, job, cls The total number of failed notification requests.
alertmanager_notification_requests_total counter integration, ins, instance, ip, job, cls The total number of attempted notification requests.
alertmanager_notifications_failed_total counter integration, ins, instance, ip, reason, job, cls The total number of failed notifications.
alertmanager_notifications_total counter integration, ins, instance, ip, job, cls The total number of attempted notifications.
alertmanager_oversize_gossip_message_duration_seconds_bucket Unknown ins, instance, ip, le, key, job, cls N/A
alertmanager_oversize_gossip_message_duration_seconds_count Unknown ins, instance, ip, key, job, cls N/A
alertmanager_oversize_gossip_message_duration_seconds_sum Unknown ins, instance, ip, key, job, cls N/A
alertmanager_oversized_gossip_message_dropped_total counter ins, instance, ip, key, job, cls Number of oversized gossip messages that were dropped due to a full message queue.
alertmanager_oversized_gossip_message_failure_total counter ins, instance, ip, key, job, cls Number of oversized gossip message sends that failed.
alertmanager_oversized_gossip_message_sent_total counter ins, instance, ip, key, job, cls Number of oversized gossip message sent.
alertmanager_peer_position gauge ins, instance, ip, job, cls Position the Alertmanager instance believes it’s in. The position determines a peer’s behavior in the cluster.
alertmanager_receivers gauge ins, instance, ip, job, cls Number of configured receivers.
alertmanager_silences gauge ins, instance, ip, job, cls, state How many silences by state.
alertmanager_silences_gc_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
alertmanager_silences_gc_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
alertmanager_silences_gossip_messages_propagated_total counter ins, instance, ip, job, cls Number of received gossip messages that have been further gossiped.
alertmanager_silences_maintenance_errors_total counter ins, instance, ip, job, cls How many maintenances were executed for silences that failed.
alertmanager_silences_maintenance_total counter ins, instance, ip, job, cls How many maintenances were executed for silences.
alertmanager_silences_queries_total counter ins, instance, ip, job, cls How many silence queries were received.
alertmanager_silences_query_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
alertmanager_silences_query_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
alertmanager_silences_query_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
alertmanager_silences_query_errors_total counter ins, instance, ip, job, cls How many silence received queries did not succeed.
alertmanager_silences_snapshot_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
alertmanager_silences_snapshot_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
alertmanager_silences_snapshot_size_bytes gauge ins, instance, ip, job, cls Size of the last silence snapshot in bytes.
blackbox_exporter_build_info gauge revision, version, ins, instance, ip, tags, goarch, goversion, job, cls, branch, goos A metric with a constant ‘1’ value labeled by version, revision, branch, goversion from which blackbox_exporter was built, and the goos and goarch for the build.
blackbox_exporter_config_last_reload_success_timestamp_seconds gauge ins, instance, ip, job, cls Timestamp of the last successful configuration reload.
blackbox_exporter_config_last_reload_successful gauge ins, instance, ip, job, cls Blackbox exporter config loaded successfully.
blackbox_module_unknown_total counter ins, instance, ip, job, cls Count of unknown modules requested by probes
cortex_distributor_ingester_clients gauge ins, instance, ip, job, cls The current number of ingester clients.
cortex_dns_failures_total Unknown ins, instance, ip, job, cls N/A
cortex_dns_lookups_total Unknown ins, instance, ip, job, cls N/A
cortex_frontend_query_range_duration_seconds_bucket Unknown ins, instance, method, ip, le, job, cls, status_code N/A
cortex_frontend_query_range_duration_seconds_count Unknown ins, instance, method, ip, job, cls, status_code N/A
cortex_frontend_query_range_duration_seconds_sum Unknown ins, instance, method, ip, job, cls, status_code N/A
cortex_ingester_flush_queue_length gauge ins, instance, ip, job, cls The total number of series pending in the flush queue.
cortex_kv_request_duration_seconds_bucket Unknown ins, instance, role, ip, le, kv_name, type, operation, job, cls, status_code N/A
cortex_kv_request_duration_seconds_count Unknown ins, instance, role, ip, kv_name, type, operation, job, cls, status_code N/A
cortex_kv_request_duration_seconds_sum Unknown ins, instance, role, ip, kv_name, type, operation, job, cls, status_code N/A
cortex_member_consul_heartbeats_total Unknown ins, instance, ip, job, cls N/A
cortex_prometheus_notifications_alertmanagers_discovered gauge ins, instance, ip, user, job, cls The number of alertmanagers discovered and active.
cortex_prometheus_notifications_dropped_total Unknown ins, instance, ip, user, job, cls N/A
cortex_prometheus_notifications_queue_capacity gauge ins, instance, ip, user, job, cls The capacity of the alert notifications queue.
cortex_prometheus_notifications_queue_length gauge ins, instance, ip, user, job, cls The number of alert notifications in the queue.
cortex_prometheus_rule_evaluation_duration_seconds summary ins, instance, ip, user, job, cls, quantile The duration for a rule to execute.
cortex_prometheus_rule_evaluation_duration_seconds_count Unknown ins, instance, ip, user, job, cls N/A
cortex_prometheus_rule_evaluation_duration_seconds_sum Unknown ins, instance, ip, user, job, cls N/A
cortex_prometheus_rule_group_duration_seconds summary ins, instance, ip, user, job, cls, quantile The duration of rule group evaluations.
cortex_prometheus_rule_group_duration_seconds_count Unknown ins, instance, ip, user, job, cls N/A
cortex_prometheus_rule_group_duration_seconds_sum Unknown ins, instance, ip, user, job, cls N/A
cortex_query_frontend_connected_schedulers gauge ins, instance, ip, job, cls Number of schedulers this frontend is connected to.
cortex_query_frontend_queries_in_progress gauge ins, instance, ip, job, cls Number of queries in progress handled by this frontend.
cortex_query_frontend_retries_bucket Unknown ins, instance, ip, le, job, cls N/A
cortex_query_frontend_retries_count Unknown ins, instance, ip, job, cls N/A
cortex_query_frontend_retries_sum Unknown ins, instance, ip, job, cls N/A
cortex_query_scheduler_connected_frontend_clients gauge ins, instance, ip, job, cls Number of query-frontend worker clients currently connected to the query-scheduler.
cortex_query_scheduler_connected_querier_clients gauge ins, instance, ip, job, cls Number of querier worker clients currently connected to the query-scheduler.
cortex_query_scheduler_inflight_requests summary ins, instance, ip, job, cls, quantile Number of inflight requests (either queued or processing) sampled at a regular interval. Quantile buckets keep track of inflight requests over the last 60s.
cortex_query_scheduler_inflight_requests_count Unknown ins, instance, ip, job, cls N/A
cortex_query_scheduler_inflight_requests_sum Unknown ins, instance, ip, job, cls N/A
cortex_query_scheduler_queue_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
cortex_query_scheduler_queue_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
cortex_query_scheduler_queue_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
cortex_query_scheduler_queue_length Unknown ins, instance, ip, user, job, cls N/A
cortex_query_scheduler_running gauge ins, instance, ip, job, cls Value will be 1 if the scheduler is in the ReplicationSet and actively receiving/processing requests
cortex_ring_member_heartbeats_total Unknown ins, instance, ip, job, cls N/A
cortex_ring_member_tokens_owned gauge ins, instance, ip, job, cls The number of tokens owned in the ring.
cortex_ring_member_tokens_to_own gauge ins, instance, ip, job, cls The number of tokens to own in the ring.
cortex_ring_members gauge ins, instance, ip, job, cls, state Number of members in the ring
cortex_ring_oldest_member_timestamp gauge ins, instance, ip, job, cls, state Timestamp of the oldest member in the ring.
cortex_ring_tokens_total gauge ins, instance, ip, job, cls Number of tokens in the ring
cortex_ruler_clients gauge ins, instance, ip, job, cls The current number of ruler clients in the pool.
cortex_ruler_config_last_reload_successful gauge ins, instance, ip, user, job, cls Boolean set to 1 whenever the last configuration reload attempt was successful.
cortex_ruler_config_last_reload_successful_seconds gauge ins, instance, ip, user, job, cls Timestamp of the last successful configuration reload.
cortex_ruler_config_updates_total Unknown ins, instance, ip, user, job, cls N/A
cortex_ruler_managers_total gauge ins, instance, ip, job, cls Total number of managers registered and running in the ruler
cortex_ruler_ring_check_errors_total Unknown ins, instance, ip, job, cls N/A
cortex_ruler_sync_rules_total Unknown ins, instance, ip, reason, job, cls N/A
deprecated_flags_inuse_total Unknown ins, instance, ip, job, cls N/A
go_cgo_go_to_c_calls_calls_total Unknown ins, instance, ip, job, cls N/A
go_cpu_classes_gc_mark_assist_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
go_cpu_classes_gc_mark_dedicated_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
go_cpu_classes_gc_mark_idle_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
go_cpu_classes_gc_pause_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
go_cpu_classes_gc_total_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
go_cpu_classes_idle_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
go_cpu_classes_scavenge_assist_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
go_cpu_classes_scavenge_background_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
go_cpu_classes_scavenge_total_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
go_cpu_classes_total_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
go_cpu_classes_user_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
go_gc_cycles_automatic_gc_cycles_total Unknown ins, instance, ip, job, cls N/A
go_gc_cycles_forced_gc_cycles_total Unknown ins, instance, ip, job, cls N/A
go_gc_cycles_total_gc_cycles_total Unknown ins, instance, ip, job, cls N/A
go_gc_duration_seconds summary ins, instance, ip, job, cls, quantile A summary of the pause duration of garbage collection cycles.
go_gc_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
go_gc_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
go_gc_gogc_percent gauge ins, instance, ip, job, cls Heap size target percentage configured by the user, otherwise 100. This value is set by the GOGC environment variable, and the runtime/debug.SetGCPercent function.
go_gc_gomemlimit_bytes gauge ins, instance, ip, job, cls Go runtime memory limit configured by the user, otherwise math.MaxInt64. This value is set by the GOMEMLIMIT environment variable, and the runtime/debug.SetMemoryLimit function.
go_gc_heap_allocs_by_size_bytes_bucket Unknown ins, instance, ip, le, job, cls N/A
go_gc_heap_allocs_by_size_bytes_count Unknown ins, instance, ip, job, cls N/A
go_gc_heap_allocs_by_size_bytes_sum Unknown ins, instance, ip, job, cls N/A
go_gc_heap_allocs_bytes_total Unknown ins, instance, ip, job, cls N/A
go_gc_heap_allocs_objects_total Unknown ins, instance, ip, job, cls N/A
go_gc_heap_frees_by_size_bytes_bucket Unknown ins, instance, ip, le, job, cls N/A
go_gc_heap_frees_by_size_bytes_count Unknown ins, instance, ip, job, cls N/A
go_gc_heap_frees_by_size_bytes_sum Unknown ins, instance, ip, job, cls N/A
go_gc_heap_frees_bytes_total Unknown ins, instance, ip, job, cls N/A
go_gc_heap_frees_objects_total Unknown ins, instance, ip, job, cls N/A
go_gc_heap_goal_bytes gauge ins, instance, ip, job, cls Heap size target for the end of the GC cycle.
go_gc_heap_live_bytes gauge ins, instance, ip, job, cls Heap memory occupied by live objects that were marked by the previous GC.
go_gc_heap_objects_objects gauge ins, instance, ip, job, cls Number of objects, live or unswept, occupying heap memory.
go_gc_heap_tiny_allocs_objects_total Unknown ins, instance, ip, job, cls N/A
go_gc_limiter_last_enabled_gc_cycle gauge ins, instance, ip, job, cls GC cycle the last time the GC CPU limiter was enabled. This metric is useful for diagnosing the root cause of an out-of-memory error, because the limiter trades memory for CPU time when the GC’s CPU time gets too high. This is most likely to occur with use of SetMemoryLimit. The first GC cycle is cycle 1, so a value of 0 indicates that it was never enabled.
go_gc_pauses_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
go_gc_pauses_seconds_count Unknown ins, instance, ip, job, cls N/A
go_gc_pauses_seconds_sum Unknown ins, instance, ip, job, cls N/A
go_gc_scan_globals_bytes gauge ins, instance, ip, job, cls The total amount of global variable space that is scannable.
go_gc_scan_heap_bytes gauge ins, instance, ip, job, cls The total amount of heap space that is scannable.
go_gc_scan_stack_bytes gauge ins, instance, ip, job, cls The number of bytes of stack that were scanned last GC cycle.
go_gc_scan_total_bytes gauge ins, instance, ip, job, cls The total amount space that is scannable. Sum of all metrics in /gc/scan.
go_gc_stack_starting_size_bytes gauge ins, instance, ip, job, cls The stack size of new goroutines.
go_godebug_non_default_behavior_execerrdot_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_gocachehash_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_gocachetest_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_gocacheverify_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_http2client_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_http2server_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_installgoroot_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_jstmpllitinterp_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_multipartmaxheaders_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_multipartmaxparts_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_multipathtcp_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_panicnil_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_randautoseed_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_tarinsecurepath_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_tlsmaxrsasize_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_x509sha1_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_x509usefallbackroots_events_total Unknown ins, instance, ip, job, cls N/A
go_godebug_non_default_behavior_zipinsecurepath_events_total Unknown ins, instance, ip, job, cls N/A
go_goroutines gauge ins, instance, ip, job, cls Number of goroutines that currently exist.
go_info gauge version, ins, instance, ip, job, cls Information about the Go environment.
go_memory_classes_heap_free_bytes gauge ins, instance, ip, job, cls Memory that is completely free and eligible to be returned to the underlying system, but has not been. This metric is the runtime’s estimate of free address space that is backed by physical memory.
go_memory_classes_heap_objects_bytes gauge ins, instance, ip, job, cls Memory occupied by live objects and dead objects that have not yet been marked free by the garbage collector.
go_memory_classes_heap_released_bytes gauge ins, instance, ip, job, cls Memory that is completely free and has been returned to the underlying system. This metric is the runtime’s estimate of free address space that is still mapped into the process, but is not backed by physical memory.
go_memory_classes_heap_stacks_bytes gauge ins, instance, ip, job, cls Memory allocated from the heap that is reserved for stack space, whether or not it is currently in-use. Currently, this represents all stack memory for goroutines. It also includes all OS thread stacks in non-cgo programs. Note that stacks may be allocated differently in the future, and this may change.
go_memory_classes_heap_unused_bytes gauge ins, instance, ip, job, cls Memory that is reserved for heap objects but is not currently used to hold heap objects.
go_memory_classes_metadata_mcache_free_bytes gauge ins, instance, ip, job, cls Memory that is reserved for runtime mcache structures, but not in-use.
go_memory_classes_metadata_mcache_inuse_bytes gauge ins, instance, ip, job, cls Memory that is occupied by runtime mcache structures that are currently being used.
go_memory_classes_metadata_mspan_free_bytes gauge ins, instance, ip, job, cls Memory that is reserved for runtime mspan structures, but not in-use.
go_memory_classes_metadata_mspan_inuse_bytes gauge ins, instance, ip, job, cls Memory that is occupied by runtime mspan structures that are currently being used.
go_memory_classes_metadata_other_bytes gauge ins, instance, ip, job, cls Memory that is reserved for or used to hold runtime metadata.
go_memory_classes_os_stacks_bytes gauge ins, instance, ip, job, cls Stack memory allocated by the underlying operating system. In non-cgo programs this metric is currently zero. This may change in the future.In cgo programs this metric includes OS thread stacks allocated directly from the OS. Currently, this only accounts for one stack in c-shared and c-archive build modes, and other sources of stacks from the OS are not measured. This too may change in the future.
go_memory_classes_other_bytes gauge ins, instance, ip, job, cls Memory used by execution trace buffers, structures for debugging the runtime, finalizer and profiler specials, and more.
go_memory_classes_profiling_buckets_bytes gauge ins, instance, ip, job, cls Memory that is used by the stack trace hash map used for profiling.
go_memory_classes_total_bytes gauge ins, instance, ip, job, cls All memory mapped by the Go runtime into the current process as read-write. Note that this does not include memory mapped by code called via cgo or via the syscall package. Sum of all metrics in /memory/classes.
go_memstats_alloc_bytes counter ins, instance, ip, job, cls Total number of bytes allocated, even if freed.
go_memstats_alloc_bytes_total counter ins, instance, ip, job, cls Total number of bytes allocated, even if freed.
go_memstats_buck_hash_sys_bytes gauge ins, instance, ip, job, cls Number of bytes used by the profiling bucket hash table.
go_memstats_frees_total counter ins, instance, ip, job, cls Total number of frees.
go_memstats_gc_sys_bytes gauge ins, instance, ip, job, cls Number of bytes used for garbage collection system metadata.
go_memstats_heap_alloc_bytes gauge ins, instance, ip, job, cls Number of heap bytes allocated and still in use.
go_memstats_heap_idle_bytes gauge ins, instance, ip, job, cls Number of heap bytes waiting to be used.
go_memstats_heap_inuse_bytes gauge ins, instance, ip, job, cls Number of heap bytes that are in use.
go_memstats_heap_objects gauge ins, instance, ip, job, cls Number of allocated objects.
go_memstats_heap_released_bytes gauge ins, instance, ip, job, cls Number of heap bytes released to OS.
go_memstats_heap_sys_bytes gauge ins, instance, ip, job, cls Number of heap bytes obtained from system.
go_memstats_last_gc_time_seconds gauge ins, instance, ip, job, cls Number of seconds since 1970 of last garbage collection.
go_memstats_lookups_total counter ins, instance, ip, job, cls Total number of pointer lookups.
go_memstats_mallocs_total counter ins, instance, ip, job, cls Total number of mallocs.
go_memstats_mcache_inuse_bytes gauge ins, instance, ip, job, cls Number of bytes in use by mcache structures.
go_memstats_mcache_sys_bytes gauge ins, instance, ip, job, cls Number of bytes used for mcache structures obtained from system.
go_memstats_mspan_inuse_bytes gauge ins, instance, ip, job, cls Number of bytes in use by mspan structures.
go_memstats_mspan_sys_bytes gauge ins, instance, ip, job, cls Number of bytes used for mspan structures obtained from system.
go_memstats_next_gc_bytes gauge ins, instance, ip, job, cls Number of heap bytes when next garbage collection will take place.
go_memstats_other_sys_bytes gauge ins, instance, ip, job, cls Number of bytes used for other system allocations.
go_memstats_stack_inuse_bytes gauge ins, instance, ip, job, cls Number of bytes in use by the stack allocator.
go_memstats_stack_sys_bytes gauge ins, instance, ip, job, cls Number of bytes obtained from system for stack allocator.
go_memstats_sys_bytes gauge ins, instance, ip, job, cls Number of bytes obtained from system.
go_sched_gomaxprocs_threads gauge ins, instance, ip, job, cls The current runtime.GOMAXPROCS setting, or the number of operating system threads that can execute user-level Go code simultaneously.
go_sched_goroutines_goroutines gauge ins, instance, ip, job, cls Count of live goroutines.
go_sched_latencies_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
go_sched_latencies_seconds_count Unknown ins, instance, ip, job, cls N/A
go_sched_latencies_seconds_sum Unknown ins, instance, ip, job, cls N/A
go_sql_stats_connections_blocked_seconds unknown ins, instance, db_name, ip, job, cls The total time blocked waiting for a new connection.
go_sql_stats_connections_closed_max_idle unknown ins, instance, db_name, ip, job, cls The total number of connections closed due to SetMaxIdleConns.
go_sql_stats_connections_closed_max_idle_time unknown ins, instance, db_name, ip, job, cls The total number of connections closed due to SetConnMaxIdleTime.
go_sql_stats_connections_closed_max_lifetime unknown ins, instance, db_name, ip, job, cls The total number of connections closed due to SetConnMaxLifetime.
go_sql_stats_connections_idle gauge ins, instance, db_name, ip, job, cls The number of idle connections.
go_sql_stats_connections_in_use gauge ins, instance, db_name, ip, job, cls The number of connections currently in use.
go_sql_stats_connections_max_open gauge ins, instance, db_name, ip, job, cls Maximum number of open connections to the database.
go_sql_stats_connections_open gauge ins, instance, db_name, ip, job, cls The number of established connections both in use and idle.
go_sql_stats_connections_waited_for unknown ins, instance, db_name, ip, job, cls The total number of connections waited for.
go_sync_mutex_wait_total_seconds_total Unknown ins, instance, ip, job, cls N/A
go_threads gauge ins, instance, ip, job, cls Number of OS threads created.
grafana_access_evaluation_count unknown ins, instance, ip, job, cls number of evaluation calls
grafana_access_evaluation_duration_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_access_evaluation_duration_count Unknown ins, instance, ip, job, cls N/A
grafana_access_evaluation_duration_sum Unknown ins, instance, ip, job, cls N/A
grafana_access_permissions_duration_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_access_permissions_duration_count Unknown ins, instance, ip, job, cls N/A
grafana_access_permissions_duration_sum Unknown ins, instance, ip, job, cls N/A
grafana_aggregator_discovery_aggregation_count_total Unknown ins, instance, ip, job, cls N/A
grafana_alerting_active_alerts gauge ins, instance, ip, job, cls amount of active alerts
grafana_alerting_active_configurations gauge ins, instance, ip, job, cls The number of active Alertmanager configurations.
grafana_alerting_alertmanager_config_match gauge ins, instance, ip, job, cls The total number of match
grafana_alerting_alertmanager_config_match_re gauge ins, instance, ip, job, cls The total number of matchRE
grafana_alerting_alertmanager_config_matchers gauge ins, instance, ip, job, cls The total number of matchers
grafana_alerting_alertmanager_config_object_matchers gauge ins, instance, ip, job, cls The total number of object_matchers
grafana_alerting_discovered_configurations gauge ins, instance, ip, job, cls The number of organizations we’ve discovered that require an Alertmanager configuration.
grafana_alerting_dispatcher_aggregation_groups gauge ins, instance, ip, job, cls Number of active aggregation groups
grafana_alerting_dispatcher_alert_processing_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_dispatcher_alert_processing_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_execution_time_milliseconds summary ins, instance, ip, job, cls, quantile summary of alert execution duration
grafana_alerting_execution_time_milliseconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_execution_time_milliseconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_nflog_gc_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_nflog_gc_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_nflog_gossip_messages_propagated_total Unknown ins, instance, ip, job, cls N/A
grafana_alerting_nflog_queries_total Unknown ins, instance, ip, job, cls N/A
grafana_alerting_nflog_query_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_alerting_nflog_query_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_nflog_query_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_nflog_query_errors_total Unknown ins, instance, ip, job, cls N/A
grafana_alerting_nflog_snapshot_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_nflog_snapshot_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_nflog_snapshot_size_bytes gauge ins, instance, ip, job, cls Size of the last notification log snapshot in bytes.
grafana_alerting_notification_latency_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_alerting_notification_latency_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_notification_latency_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_schedule_alert_rules gauge ins, instance, ip, job, cls The number of alert rules that could be considered for evaluation at the next tick.
grafana_alerting_schedule_alert_rules_hash gauge ins, instance, ip, job, cls A hash of the alert rules that could be considered for evaluation at the next tick.
grafana_alerting_schedule_periodic_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_alerting_schedule_periodic_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_schedule_periodic_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_schedule_query_alert_rules_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_alerting_schedule_query_alert_rules_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_schedule_query_alert_rules_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_scheduler_behind_seconds gauge ins, instance, ip, job, cls The total number of seconds the scheduler is behind.
grafana_alerting_silences_gc_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_silences_gc_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_silences_gossip_messages_propagated_total Unknown ins, instance, ip, job, cls N/A
grafana_alerting_silences_queries_total Unknown ins, instance, ip, job, cls N/A
grafana_alerting_silences_query_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_alerting_silences_query_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_silences_query_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_silences_query_errors_total Unknown ins, instance, ip, job, cls N/A
grafana_alerting_silences_snapshot_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_silences_snapshot_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_silences_snapshot_size_bytes gauge ins, instance, ip, job, cls Size of the last silence snapshot in bytes.
grafana_alerting_state_calculation_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_alerting_state_calculation_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_alerting_state_calculation_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_alerting_state_history_writes_bytes_total Unknown ins, instance, ip, job, cls N/A
grafana_alerting_ticker_interval_seconds gauge ins, instance, ip, job, cls Interval at which the ticker is meant to tick.
grafana_alerting_ticker_last_consumed_tick_timestamp_seconds gauge ins, instance, ip, job, cls Timestamp of the last consumed tick in seconds.
grafana_alerting_ticker_next_tick_timestamp_seconds gauge ins, instance, ip, job, cls Timestamp of the next tick in seconds before it is consumed.
grafana_api_admin_user_created_total Unknown ins, instance, ip, job, cls N/A
grafana_api_dashboard_get_milliseconds summary ins, instance, ip, job, cls, quantile summary for dashboard get duration
grafana_api_dashboard_get_milliseconds_count Unknown ins, instance, ip, job, cls N/A
grafana_api_dashboard_get_milliseconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_api_dashboard_save_milliseconds summary ins, instance, ip, job, cls, quantile summary for dashboard save duration
grafana_api_dashboard_save_milliseconds_count Unknown ins, instance, ip, job, cls N/A
grafana_api_dashboard_save_milliseconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_api_dashboard_search_milliseconds summary ins, instance, ip, job, cls, quantile summary for dashboard search duration
grafana_api_dashboard_search_milliseconds_count Unknown ins, instance, ip, job, cls N/A
grafana_api_dashboard_search_milliseconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_api_dashboard_snapshot_create_total Unknown ins, instance, ip, job, cls N/A
grafana_api_dashboard_snapshot_external_total Unknown ins, instance, ip, job, cls N/A
grafana_api_dashboard_snapshot_get_total Unknown ins, instance, ip, job, cls N/A
grafana_api_dataproxy_request_all_milliseconds summary ins, instance, ip, job, cls, quantile summary for dataproxy request duration
grafana_api_dataproxy_request_all_milliseconds_count Unknown ins, instance, ip, job, cls N/A
grafana_api_dataproxy_request_all_milliseconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_api_login_oauth_total Unknown ins, instance, ip, job, cls N/A
grafana_api_login_post_total Unknown ins, instance, ip, job, cls N/A
grafana_api_login_saml_total Unknown ins, instance, ip, job, cls N/A
grafana_api_models_dashboard_insert_total Unknown ins, instance, ip, job, cls N/A
grafana_api_org_create_total Unknown ins, instance, ip, job, cls N/A
grafana_api_response_status_total Unknown ins, instance, ip, job, cls, code N/A
grafana_api_user_signup_completed_total Unknown ins, instance, ip, job, cls N/A
grafana_api_user_signup_invite_total Unknown ins, instance, ip, job, cls N/A
grafana_api_user_signup_started_total Unknown ins, instance, ip, job, cls N/A
grafana_apiserver_audit_event_total Unknown ins, instance, ip, job, cls N/A
grafana_apiserver_audit_requests_rejected_total Unknown ins, instance, ip, job, cls N/A
grafana_apiserver_client_certificate_expiration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_apiserver_client_certificate_expiration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_apiserver_client_certificate_expiration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_apiserver_envelope_encryption_dek_cache_fill_percent gauge ins, instance, ip, job, cls [ALPHA] Percent of the cache slots currently occupied by cached DEKs.
grafana_apiserver_flowcontrol_seat_fair_frac gauge ins, instance, ip, job, cls [ALPHA] Fair fraction of server’s concurrency to allocate to each priority level that can use it
grafana_apiserver_storage_data_key_generation_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_apiserver_storage_data_key_generation_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_apiserver_storage_data_key_generation_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_apiserver_storage_data_key_generation_failures_total Unknown ins, instance, ip, job, cls N/A
grafana_apiserver_storage_envelope_transformation_cache_misses_total Unknown ins, instance, ip, job, cls N/A
grafana_apiserver_tls_handshake_errors_total Unknown ins, instance, ip, job, cls N/A
grafana_apiserver_webhooks_x509_insecure_sha1_total Unknown ins, instance, ip, job, cls N/A
grafana_apiserver_webhooks_x509_missing_san_total Unknown ins, instance, ip, job, cls N/A
grafana_authn_authn_failed_authentication_total Unknown ins, instance, ip, job, cls N/A
grafana_authn_authn_successful_authentication_total Unknown ins, instance, ip, client, job, cls N/A
grafana_authn_authn_successful_login_total Unknown ins, instance, ip, client, job, cls N/A
grafana_aws_cloudwatch_get_metric_data_total Unknown ins, instance, ip, job, cls N/A
grafana_aws_cloudwatch_get_metric_statistics_total Unknown ins, instance, ip, job, cls N/A
grafana_aws_cloudwatch_list_metrics_total Unknown ins, instance, ip, job, cls N/A
grafana_build_info gauge revision, version, ins, instance, edition, ip, goversion, job, cls, branch A metric with a constant ‘1’ value labeled by version, revision, branch, and goversion from which Grafana was built
grafana_build_timestamp gauge revision, version, ins, instance, edition, ip, goversion, job, cls, branch A metric exposing when the binary was built in epoch
grafana_cardinality_enforcement_unexpected_categorizations_total Unknown ins, instance, ip, job, cls N/A
grafana_database_conn_idle gauge ins, instance, ip, job, cls The number of idle connections
grafana_database_conn_in_use gauge ins, instance, ip, job, cls The number of connections currently in use
grafana_database_conn_max_idle_closed_seconds unknown ins, instance, ip, job, cls The total number of connections closed due to SetConnMaxIdleTime
grafana_database_conn_max_idle_closed_total Unknown ins, instance, ip, job, cls N/A
grafana_database_conn_max_lifetime_closed_total Unknown ins, instance, ip, job, cls N/A
grafana_database_conn_max_open gauge ins, instance, ip, job, cls Maximum number of open connections to the database
grafana_database_conn_open gauge ins, instance, ip, job, cls The number of established connections both in use and idle
grafana_database_conn_wait_count_total Unknown ins, instance, ip, job, cls N/A
grafana_database_conn_wait_duration_seconds unknown ins, instance, ip, job, cls The total time blocked waiting for a new connection
grafana_datasource_request_duration_seconds_bucket Unknown datasource, ins, instance, method, ip, le, datasource_type, job, cls, code N/A
grafana_datasource_request_duration_seconds_count Unknown datasource, ins, instance, method, ip, datasource_type, job, cls, code N/A
grafana_datasource_request_duration_seconds_sum Unknown datasource, ins, instance, method, ip, datasource_type, job, cls, code N/A
grafana_datasource_request_in_flight gauge datasource, ins, instance, ip, datasource_type, job, cls A gauge of outgoing data source requests currently being sent by Grafana
grafana_datasource_request_total Unknown datasource, ins, instance, method, ip, datasource_type, job, cls, code N/A
grafana_datasource_response_size_bytes_bucket Unknown datasource, ins, instance, ip, le, datasource_type, job, cls N/A
grafana_datasource_response_size_bytes_count Unknown datasource, ins, instance, ip, datasource_type, job, cls N/A
grafana_datasource_response_size_bytes_sum Unknown datasource, ins, instance, ip, datasource_type, job, cls N/A
grafana_db_datasource_query_by_id_total Unknown ins, instance, ip, job, cls N/A
grafana_disabled_metrics_total Unknown ins, instance, ip, job, cls N/A
grafana_emails_sent_failed unknown ins, instance, ip, job, cls Number of emails Grafana failed to send
grafana_emails_sent_total Unknown ins, instance, ip, job, cls N/A
grafana_encryption_cache_reads_total Unknown ins, instance, method, ip, hit, job, cls N/A
grafana_encryption_ops_total Unknown ins, instance, ip, success, operation, job, cls N/A
grafana_environment_info gauge version, ins, instance, ip, job, cls, commit A metric with a constant ‘1’ value labeled by environment information about the running instance.
grafana_feature_toggles_info gauge ins, instance, ip, job, cls info metric that exposes what feature toggles are enabled or not
grafana_frontend_boot_css_time_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_frontend_boot_css_time_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_frontend_boot_css_time_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_frontend_boot_first_contentful_paint_time_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_frontend_boot_first_contentful_paint_time_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_frontend_boot_first_contentful_paint_time_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_frontend_boot_first_paint_time_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_frontend_boot_first_paint_time_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_frontend_boot_first_paint_time_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_frontend_boot_js_done_time_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_frontend_boot_js_done_time_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_frontend_boot_js_done_time_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_frontend_boot_load_time_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_frontend_boot_load_time_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_frontend_boot_load_time_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_frontend_plugins_preload_ms_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_frontend_plugins_preload_ms_count Unknown ins, instance, ip, job, cls N/A
grafana_frontend_plugins_preload_ms_sum Unknown ins, instance, ip, job, cls N/A
grafana_hidden_metrics_total Unknown ins, instance, ip, job, cls N/A
grafana_http_request_duration_seconds_bucket Unknown ins, instance, method, ip, le, job, cls, status_code, handler N/A
grafana_http_request_duration_seconds_count Unknown ins, instance, method, ip, job, cls, status_code, handler N/A
grafana_http_request_duration_seconds_sum Unknown ins, instance, method, ip, job, cls, status_code, handler N/A
grafana_http_request_in_flight gauge ins, instance, ip, job, cls A gauge of requests currently being served by Grafana.
grafana_idforwarding_idforwarding_failed_token_signing_total Unknown ins, instance, ip, job, cls N/A
grafana_idforwarding_idforwarding_token_signing_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_idforwarding_idforwarding_token_signing_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_idforwarding_idforwarding_token_signing_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_idforwarding_idforwarding_token_signing_from_cache_total Unknown ins, instance, ip, job, cls N/A
grafana_idforwarding_idforwarding_token_signing_total Unknown ins, instance, ip, job, cls N/A
grafana_instance_start_total Unknown ins, instance, ip, job, cls N/A
grafana_ldap_users_sync_execution_time summary ins, instance, ip, job, cls, quantile summary for LDAP users sync execution duration
grafana_ldap_users_sync_execution_time_count Unknown ins, instance, ip, job, cls N/A
grafana_ldap_users_sync_execution_time_sum Unknown ins, instance, ip, job, cls N/A
grafana_live_client_command_duration_seconds summary ins, instance, method, ip, job, cls, quantile Client command duration summary.
grafana_live_client_command_duration_seconds_count Unknown ins, instance, method, ip, job, cls N/A
grafana_live_client_command_duration_seconds_sum Unknown ins, instance, method, ip, job, cls N/A
grafana_live_client_num_reply_errors unknown ins, instance, method, ip, job, cls, code Number of errors in replies sent to clients.
grafana_live_client_num_server_disconnects unknown ins, instance, ip, job, cls, code Number of server initiated disconnects.
grafana_live_client_recover unknown ins, instance, ip, recovered, job, cls Count of recover operations.
grafana_live_node_action_count unknown action, ins, instance, ip, job, cls Number of node actions called.
grafana_live_node_build gauge version, ins, instance, ip, job, cls Node build info.
grafana_live_node_messages_received_count unknown ins, instance, ip, type, job, cls Number of messages received.
grafana_live_node_messages_sent_count unknown ins, instance, ip, type, job, cls Number of messages sent.
grafana_live_node_num_channels gauge ins, instance, ip, job, cls Number of channels with one or more subscribers.
grafana_live_node_num_clients gauge ins, instance, ip, job, cls Number of clients connected.
grafana_live_node_num_nodes gauge ins, instance, ip, job, cls Number of nodes in cluster.
grafana_live_node_num_subscriptions gauge ins, instance, ip, job, cls Number of subscriptions.
grafana_live_node_num_users gauge ins, instance, ip, job, cls Number of unique users connected.
grafana_live_transport_connect_count unknown ins, instance, ip, transport, job, cls Number of connections to specific transport.
grafana_live_transport_messages_sent unknown ins, instance, ip, transport, job, cls Number of messages sent over specific transport.
grafana_loki_plugin_parse_response_duration_seconds_bucket Unknown endpoint, ins, instance, ip, le, status, job, cls N/A
grafana_loki_plugin_parse_response_duration_seconds_count Unknown endpoint, ins, instance, ip, status, job, cls N/A
grafana_loki_plugin_parse_response_duration_seconds_sum Unknown endpoint, ins, instance, ip, status, job, cls N/A
grafana_page_response_status_total Unknown ins, instance, ip, job, cls, code N/A
grafana_plugin_build_info gauge version, signature_status, ins, instance, plugin_type, ip, plugin_id, job, cls A metric with a constant ‘1’ value labeled by pluginId, pluginType and version from which Grafana plugin was built
grafana_plugin_request_duration_milliseconds_bucket Unknown endpoint, ins, instance, target, ip, le, plugin_id, job, cls N/A
grafana_plugin_request_duration_milliseconds_count Unknown endpoint, ins, instance, target, ip, plugin_id, job, cls N/A
grafana_plugin_request_duration_milliseconds_sum Unknown endpoint, ins, instance, target, ip, plugin_id, job, cls N/A
grafana_plugin_request_duration_seconds_bucket Unknown endpoint, ins, instance, target, ip, le, status, plugin_id, source, job, cls N/A
grafana_plugin_request_duration_seconds_count Unknown endpoint, ins, instance, target, ip, status, plugin_id, source, job, cls N/A
grafana_plugin_request_duration_seconds_sum Unknown endpoint, ins, instance, target, ip, status, plugin_id, source, job, cls N/A
grafana_plugin_request_size_bytes_bucket Unknown endpoint, ins, instance, target, ip, le, plugin_id, source, job, cls N/A
grafana_plugin_request_size_bytes_count Unknown endpoint, ins, instance, target, ip, plugin_id, source, job, cls N/A
grafana_plugin_request_size_bytes_sum Unknown endpoint, ins, instance, target, ip, plugin_id, source, job, cls N/A
grafana_plugin_request_total Unknown endpoint, ins, instance, target, ip, status, plugin_id, job, cls N/A
grafana_process_cpu_seconds_total Unknown ins, instance, ip, job, cls N/A
grafana_process_max_fds gauge ins, instance, ip, job, cls Maximum number of open file descriptors.
grafana_process_open_fds gauge ins, instance, ip, job, cls Number of open file descriptors.
grafana_process_resident_memory_bytes gauge ins, instance, ip, job, cls Resident memory size in bytes.
grafana_process_start_time_seconds gauge ins, instance, ip, job, cls Start time of the process since unix epoch in seconds.
grafana_process_virtual_memory_bytes gauge ins, instance, ip, job, cls Virtual memory size in bytes.
grafana_process_virtual_memory_max_bytes gauge ins, instance, ip, job, cls Maximum amount of virtual memory available in bytes.
grafana_prometheus_plugin_backend_request_count unknown endpoint, ins, instance, ip, status, errorSource, job, cls The total amount of prometheus backend plugin requests
grafana_proxy_response_status_total Unknown ins, instance, ip, job, cls, code N/A
grafana_public_dashboard_request_count unknown ins, instance, ip, job, cls counter for public dashboards requests
grafana_registered_metrics_total Unknown ins, instance, ip, stability_level, deprecated_version, job, cls N/A
grafana_rendering_queue_size gauge ins, instance, ip, job, cls size of rendering queue
grafana_search_dashboard_search_failures_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_search_dashboard_search_failures_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_search_dashboard_search_failures_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_search_dashboard_search_successes_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
grafana_search_dashboard_search_successes_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
grafana_search_dashboard_search_successes_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
grafana_stat_active_users gauge ins, instance, ip, job, cls number of active users
grafana_stat_total_orgs gauge ins, instance, ip, job, cls total amount of orgs
grafana_stat_total_playlists gauge ins, instance, ip, job, cls total amount of playlists
grafana_stat_total_service_account_tokens gauge ins, instance, ip, job, cls total amount of service account tokens
grafana_stat_total_service_accounts gauge ins, instance, ip, job, cls total amount of service accounts
grafana_stat_total_service_accounts_role_none gauge ins, instance, ip, job, cls total amount of service accounts with no role
grafana_stat_total_teams gauge ins, instance, ip, job, cls total amount of teams
grafana_stat_total_users gauge ins, instance, ip, job, cls total amount of users
grafana_stat_totals_active_admins gauge ins, instance, ip, job, cls total amount of active admins
grafana_stat_totals_active_editors gauge ins, instance, ip, job, cls total amount of active editors
grafana_stat_totals_active_viewers gauge ins, instance, ip, job, cls total amount of active viewers
grafana_stat_totals_admins gauge ins, instance, ip, job, cls total amount of admins
grafana_stat_totals_alert_rules gauge ins, instance, ip, job, cls total amount of alert rules in the database
grafana_stat_totals_annotations gauge ins, instance, ip, job, cls total amount of annotations in the database
grafana_stat_totals_correlations gauge ins, instance, ip, job, cls total amount of correlations
grafana_stat_totals_dashboard gauge ins, instance, ip, job, cls total amount of dashboards
grafana_stat_totals_dashboard_versions gauge ins, instance, ip, job, cls total amount of dashboard versions in the database
grafana_stat_totals_data_keys gauge ins, instance, ip, job, cls, active total amount of data keys in the database
grafana_stat_totals_datasource gauge ins, instance, ip, plugin_id, job, cls total number of defined datasources, labeled by pluginId
grafana_stat_totals_editors gauge ins, instance, ip, job, cls total amount of editors
grafana_stat_totals_folder gauge ins, instance, ip, job, cls total amount of folders
grafana_stat_totals_library_panels gauge ins, instance, ip, job, cls total amount of library panels in the database
grafana_stat_totals_library_variables gauge ins, instance, ip, job, cls total amount of library variables in the database
grafana_stat_totals_public_dashboard gauge ins, instance, ip, job, cls total amount of public dashboards
grafana_stat_totals_rule_groups gauge ins, instance, ip, job, cls total amount of alert rule groups in the database
grafana_stat_totals_viewers gauge ins, instance, ip, job, cls total amount of viewers
infra_up Unknown ins, instance, ip, job, cls N/A
jaeger_tracer_baggage_restrictions_updates_total Unknown result, ins, instance, ip, job, cls N/A
jaeger_tracer_baggage_truncations_total Unknown ins, instance, ip, job, cls N/A
jaeger_tracer_baggage_updates_total Unknown result, ins, instance, ip, job, cls N/A
jaeger_tracer_finished_spans_total Unknown ins, instance, ip, sampled, job, cls N/A
jaeger_tracer_reporter_queue_length gauge ins, instance, ip, job, cls Current number of spans in the reporter queue
jaeger_tracer_reporter_spans_total Unknown result, ins, instance, ip, job, cls N/A
jaeger_tracer_sampler_queries_total Unknown result, ins, instance, ip, job, cls N/A
jaeger_tracer_sampler_updates_total Unknown result, ins, instance, ip, job, cls N/A
jaeger_tracer_span_context_decoding_errors_total Unknown ins, instance, ip, job, cls N/A
jaeger_tracer_started_spans_total Unknown ins, instance, ip, sampled, job, cls N/A
jaeger_tracer_throttled_debug_spans_total Unknown ins, instance, ip, job, cls N/A
jaeger_tracer_throttler_updates_total Unknown result, ins, instance, ip, job, cls N/A
jaeger_tracer_traces_total Unknown ins, instance, ip, sampled, job, cls, state N/A
kv_request_duration_seconds_bucket Unknown ins, instance, role, ip, le, kv_name, type, operation, job, cls, status_code N/A
kv_request_duration_seconds_count Unknown ins, instance, role, ip, kv_name, type, operation, job, cls, status_code N/A
kv_request_duration_seconds_sum Unknown ins, instance, role, ip, kv_name, type, operation, job, cls, status_code N/A
legacy_grafana_alerting_ticker_interval_seconds gauge ins, instance, ip, job, cls Interval at which the ticker is meant to tick.
legacy_grafana_alerting_ticker_last_consumed_tick_timestamp_seconds gauge ins, instance, ip, job, cls Timestamp of the last consumed tick in seconds.
legacy_grafana_alerting_ticker_next_tick_timestamp_seconds gauge ins, instance, ip, job, cls Timestamp of the next tick in seconds before it is consumed.
logql_query_duration_seconds_bucket Unknown ins, instance, query_type, ip, le, job, cls N/A
logql_query_duration_seconds_count Unknown ins, instance, query_type, ip, job, cls N/A
logql_query_duration_seconds_sum Unknown ins, instance, query_type, ip, job, cls N/A
loki_azure_blob_egress_bytes_total Unknown ins, instance, ip, job, cls N/A
loki_boltdb_shipper_apply_retention_last_successful_run_timestamp_seconds gauge ins, instance, ip, job, cls Unix timestamp of the last successful retention run
loki_boltdb_shipper_compact_tables_operation_duration_seconds gauge ins, instance, ip, job, cls Time (in seconds) spent in compacting all the tables
loki_boltdb_shipper_compact_tables_operation_last_successful_run_timestamp_seconds gauge ins, instance, ip, job, cls Unix timestamp of the last successful compaction run
loki_boltdb_shipper_compact_tables_operation_total Unknown ins, instance, ip, status, job, cls N/A
loki_boltdb_shipper_compactor_running gauge ins, instance, ip, job, cls Value will be 1 if compactor is currently running on this instance
loki_boltdb_shipper_open_existing_file_failures_total Unknown ins, instance, ip, component, job, cls N/A
loki_boltdb_shipper_query_time_table_download_duration_seconds unknown ins, instance, ip, component, job, cls, table Time (in seconds) spent in downloading of files per table at query time
loki_boltdb_shipper_request_duration_seconds_bucket Unknown ins, instance, ip, le, component, operation, job, cls, status_code N/A
loki_boltdb_shipper_request_duration_seconds_count Unknown ins, instance, ip, component, operation, job, cls, status_code N/A
loki_boltdb_shipper_request_duration_seconds_sum Unknown ins, instance, ip, component, operation, job, cls, status_code N/A
loki_boltdb_shipper_tables_download_operation_duration_seconds gauge ins, instance, ip, component, job, cls Time (in seconds) spent in downloading updated files for all the tables
loki_boltdb_shipper_tables_sync_operation_total Unknown ins, instance, ip, status, component, job, cls N/A
loki_boltdb_shipper_tables_upload_operation_total Unknown ins, instance, ip, status, component, job, cls N/A
loki_build_info gauge revision, version, ins, instance, ip, tags, goarch, goversion, job, cls, branch, goos A metric with a constant ‘1’ value labeled by version, revision, branch, goversion from which loki was built, and the goos and goarch for the build.
loki_bytes_per_line_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_bytes_per_line_count Unknown ins, instance, ip, job, cls N/A
loki_bytes_per_line_sum Unknown ins, instance, ip, job, cls N/A
loki_cache_corrupt_chunks_total Unknown ins, instance, ip, job, cls N/A
loki_cache_fetched_keys unknown ins, instance, ip, job, cls Total count of keys requested from cache.
loki_cache_hits unknown ins, instance, ip, job, cls Total count of keys found in cache.
loki_cache_request_duration_seconds_bucket Unknown ins, instance, method, ip, le, job, cls, status_code N/A
loki_cache_request_duration_seconds_count Unknown ins, instance, method, ip, job, cls, status_code N/A
loki_cache_request_duration_seconds_sum Unknown ins, instance, method, ip, job, cls, status_code N/A
loki_cache_value_size_bytes_bucket Unknown ins, instance, method, ip, le, job, cls N/A
loki_cache_value_size_bytes_count Unknown ins, instance, method, ip, job, cls N/A
loki_cache_value_size_bytes_sum Unknown ins, instance, method, ip, job, cls N/A
loki_chunk_fetcher_cache_dequeued_total Unknown ins, instance, ip, job, cls N/A
loki_chunk_fetcher_cache_enqueued_total Unknown ins, instance, ip, job, cls N/A
loki_chunk_fetcher_cache_skipped_buffer_full_total Unknown ins, instance, ip, job, cls N/A
loki_chunk_fetcher_fetched_size_bytes_bucket Unknown ins, instance, ip, le, source, job, cls N/A
loki_chunk_fetcher_fetched_size_bytes_count Unknown ins, instance, ip, source, job, cls N/A
loki_chunk_fetcher_fetched_size_bytes_sum Unknown ins, instance, ip, source, job, cls N/A
loki_chunk_store_chunks_per_query_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_chunk_store_chunks_per_query_count Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_chunks_per_query_sum Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_deduped_bytes_total Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_deduped_chunks_total Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_fetched_chunk_bytes_total Unknown ins, instance, ip, user, job, cls N/A
loki_chunk_store_fetched_chunks_total Unknown ins, instance, ip, user, job, cls N/A
loki_chunk_store_index_entries_per_chunk_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_chunk_store_index_entries_per_chunk_count Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_index_entries_per_chunk_sum Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_index_lookups_per_query_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_chunk_store_index_lookups_per_query_count Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_index_lookups_per_query_sum Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_series_post_intersection_per_query_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_chunk_store_series_post_intersection_per_query_count Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_series_post_intersection_per_query_sum Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_series_pre_intersection_per_query_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_chunk_store_series_pre_intersection_per_query_count Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_series_pre_intersection_per_query_sum Unknown ins, instance, ip, job, cls N/A
loki_chunk_store_stored_chunk_bytes_total Unknown ins, instance, ip, user, job, cls N/A
loki_chunk_store_stored_chunks_total Unknown ins, instance, ip, user, job, cls N/A
loki_consul_request_duration_seconds_bucket Unknown ins, instance, ip, le, kv_name, operation, job, cls, status_code N/A
loki_consul_request_duration_seconds_count Unknown ins, instance, ip, kv_name, operation, job, cls, status_code N/A
loki_consul_request_duration_seconds_sum Unknown ins, instance, ip, kv_name, operation, job, cls, status_code N/A
loki_delete_request_lookups_failed_total Unknown ins, instance, ip, job, cls N/A
loki_delete_request_lookups_total Unknown ins, instance, ip, job, cls N/A
loki_discarded_bytes_total Unknown ins, instance, ip, reason, job, cls, tenant N/A
loki_discarded_samples_total Unknown ins, instance, ip, reason, job, cls, tenant N/A
loki_distributor_bytes_received_total Unknown ins, instance, retention_hours, ip, job, cls, tenant N/A
loki_distributor_ingester_appends_total Unknown ins, instance, ip, ingester, job, cls N/A
loki_distributor_lines_received_total Unknown ins, instance, ip, job, cls, tenant N/A
loki_distributor_replication_factor gauge ins, instance, ip, job, cls The configured replication factor.
loki_distributor_structured_metadata_bytes_received_total Unknown ins, instance, retention_hours, ip, job, cls, tenant N/A
loki_experimental_features_in_use_total Unknown ins, instance, ip, job, cls N/A
loki_index_chunk_refs_total Unknown ins, instance, ip, status, job, cls N/A
loki_index_request_duration_seconds_bucket Unknown ins, instance, ip, le, component, operation, job, cls, status_code N/A
loki_index_request_duration_seconds_count Unknown ins, instance, ip, component, operation, job, cls, status_code N/A
loki_index_request_duration_seconds_sum Unknown ins, instance, ip, component, operation, job, cls, status_code N/A
loki_inflight_requests gauge ins, instance, method, ip, route, job, cls Current number of inflight requests.
loki_ingester_autoforget_unhealthy_ingesters_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_blocks_per_chunk_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_ingester_blocks_per_chunk_count Unknown ins, instance, ip, job, cls N/A
loki_ingester_blocks_per_chunk_sum Unknown ins, instance, ip, job, cls N/A
loki_ingester_checkpoint_creations_failed_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_checkpoint_creations_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_checkpoint_deletions_failed_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_checkpoint_deletions_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_checkpoint_duration_seconds summary ins, instance, ip, job, cls, quantile Time taken to create a checkpoint.
loki_ingester_checkpoint_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
loki_ingester_checkpoint_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
loki_ingester_checkpoint_logged_bytes_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_age_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_ingester_chunk_age_seconds_count Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_age_seconds_sum Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_bounds_hours_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_ingester_chunk_bounds_hours_count Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_bounds_hours_sum Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_compression_ratio_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_ingester_chunk_compression_ratio_count Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_compression_ratio_sum Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_encode_time_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_ingester_chunk_encode_time_seconds_count Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_encode_time_seconds_sum Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_entries_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_ingester_chunk_entries_count Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_entries_sum Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_size_bytes_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_ingester_chunk_size_bytes_count Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_size_bytes_sum Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_stored_bytes_total Unknown ins, instance, ip, job, cls, tenant N/A
loki_ingester_chunk_utilization_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_ingester_chunk_utilization_count Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunk_utilization_sum Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunks_created_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_chunks_flushed_total Unknown ins, instance, ip, reason, job, cls N/A
loki_ingester_chunks_stored_total Unknown ins, instance, ip, job, cls, tenant N/A
loki_ingester_client_request_duration_seconds_bucket Unknown ins, instance, ip, le, operation, job, cls, status_code N/A
loki_ingester_client_request_duration_seconds_count Unknown ins, instance, ip, operation, job, cls, status_code N/A
loki_ingester_client_request_duration_seconds_sum Unknown ins, instance, ip, operation, job, cls, status_code N/A
loki_ingester_limiter_enabled gauge ins, instance, ip, job, cls Whether the ingester’s limiter is enabled
loki_ingester_memory_chunks gauge ins, instance, ip, job, cls The total number of chunks in memory.
loki_ingester_memory_streams gauge ins, instance, ip, job, cls, tenant The total number of streams in memory per tenant.
loki_ingester_memory_streams_labels_bytes gauge ins, instance, ip, job, cls Total bytes of labels of the streams in memory.
loki_ingester_received_chunks unknown ins, instance, ip, job, cls The total number of chunks received by this ingester whilst joining.
loki_ingester_samples_per_chunk_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_ingester_samples_per_chunk_count Unknown ins, instance, ip, job, cls N/A
loki_ingester_samples_per_chunk_sum Unknown ins, instance, ip, job, cls N/A
loki_ingester_sent_chunks unknown ins, instance, ip, job, cls The total number of chunks sent by this ingester whilst leaving.
loki_ingester_shutdown_marker gauge ins, instance, ip, job, cls 1 if prepare shutdown has been called, 0 otherwise
loki_ingester_streams_created_total Unknown ins, instance, ip, job, cls, tenant N/A
loki_ingester_streams_removed_total Unknown ins, instance, ip, job, cls, tenant N/A
loki_ingester_wal_bytes_in_use gauge ins, instance, ip, job, cls Total number of bytes in use by the WAL recovery process.
loki_ingester_wal_disk_full_failures_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_wal_duplicate_entries_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_wal_logged_bytes_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_wal_records_logged_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_wal_recovered_bytes_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_wal_recovered_chunks_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_wal_recovered_entries_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_wal_recovered_streams_total Unknown ins, instance, ip, job, cls N/A
loki_ingester_wal_replay_active gauge ins, instance, ip, job, cls Whether the WAL is replaying
loki_ingester_wal_replay_duration_seconds gauge ins, instance, ip, job, cls Time taken to replay the checkpoint and the WAL.
loki_ingester_wal_replay_flushing gauge ins, instance, ip, job, cls Whether the wal replay is in a flushing phase due to backpressure
loki_internal_log_messages_total Unknown ins, instance, ip, level, job, cls N/A
loki_kv_request_duration_seconds_bucket Unknown ins, instance, role, ip, le, kv_name, type, operation, job, cls, status_code N/A
loki_kv_request_duration_seconds_count Unknown ins, instance, role, ip, kv_name, type, operation, job, cls, status_code N/A
loki_kv_request_duration_seconds_sum Unknown ins, instance, role, ip, kv_name, type, operation, job, cls, status_code N/A
loki_log_flushes_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_log_flushes_count Unknown ins, instance, ip, job, cls N/A
loki_log_flushes_sum Unknown ins, instance, ip, job, cls N/A
loki_log_messages_total Unknown ins, instance, ip, level, job, cls N/A
loki_logql_querystats_bytes_processed_per_seconds_bucket Unknown ins, instance, range, ip, le, sharded, type, job, cls, status_code, latency_type N/A
loki_logql_querystats_bytes_processed_per_seconds_count Unknown ins, instance, range, ip, sharded, type, job, cls, status_code, latency_type N/A
loki_logql_querystats_bytes_processed_per_seconds_sum Unknown ins, instance, range, ip, sharded, type, job, cls, status_code, latency_type N/A
loki_logql_querystats_chunk_download_latency_seconds_bucket Unknown ins, instance, range, ip, le, type, job, cls, status_code N/A
loki_logql_querystats_chunk_download_latency_seconds_count Unknown ins, instance, range, ip, type, job, cls, status_code N/A
loki_logql_querystats_chunk_download_latency_seconds_sum Unknown ins, instance, range, ip, type, job, cls, status_code N/A
loki_logql_querystats_downloaded_chunk_total Unknown ins, instance, range, ip, type, job, cls, status_code N/A
loki_logql_querystats_duplicates_total Unknown ins, instance, ip, job, cls N/A
loki_logql_querystats_ingester_sent_lines_total Unknown ins, instance, ip, job, cls N/A
loki_logql_querystats_latency_seconds_bucket Unknown ins, instance, range, ip, le, type, job, cls, status_code N/A
loki_logql_querystats_latency_seconds_count Unknown ins, instance, range, ip, type, job, cls, status_code N/A
loki_logql_querystats_latency_seconds_sum Unknown ins, instance, range, ip, type, job, cls, status_code N/A
loki_panic_total Unknown ins, instance, ip, job, cls N/A
loki_querier_index_cache_corruptions_total Unknown ins, instance, ip, job, cls N/A
loki_querier_index_cache_encode_errors_total Unknown ins, instance, ip, job, cls N/A
loki_querier_index_cache_gets_total Unknown ins, instance, ip, job, cls N/A
loki_querier_index_cache_hits_total Unknown ins, instance, ip, job, cls N/A
loki_querier_index_cache_puts_total Unknown ins, instance, ip, job, cls N/A
loki_querier_query_frontend_clients gauge ins, instance, ip, job, cls The current number of clients connected to query-frontend.
loki_querier_query_frontend_request_duration_seconds_bucket Unknown ins, instance, ip, le, operation, job, cls, status_code N/A
loki_querier_query_frontend_request_duration_seconds_count Unknown ins, instance, ip, operation, job, cls, status_code N/A
loki_querier_query_frontend_request_duration_seconds_sum Unknown ins, instance, ip, operation, job, cls, status_code N/A
loki_querier_tail_active gauge ins, instance, ip, job, cls Number of active tailers
loki_querier_tail_active_streams gauge ins, instance, ip, job, cls Number of active streams being tailed
loki_querier_tail_bytes_total Unknown ins, instance, ip, job, cls N/A
loki_querier_worker_concurrency gauge ins, instance, ip, job, cls Number of concurrent querier workers
loki_querier_worker_inflight_queries gauge ins, instance, ip, job, cls Number of queries being processed by the querier workers
loki_query_frontend_log_result_cache_hit_total Unknown ins, instance, ip, job, cls N/A
loki_query_frontend_log_result_cache_miss_total Unknown ins, instance, ip, job, cls N/A
loki_query_frontend_partitions_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_query_frontend_partitions_count Unknown ins, instance, ip, job, cls N/A
loki_query_frontend_partitions_sum Unknown ins, instance, ip, job, cls N/A
loki_query_frontend_shard_factor_bucket Unknown ins, instance, ip, le, mapper, job, cls N/A
loki_query_frontend_shard_factor_count Unknown ins, instance, ip, mapper, job, cls N/A
loki_query_frontend_shard_factor_sum Unknown ins, instance, ip, mapper, job, cls N/A
loki_query_scheduler_enqueue_count Unknown ins, instance, ip, level, user, job, cls N/A
loki_rate_store_expired_streams_total Unknown ins, instance, ip, job, cls N/A
loki_rate_store_max_stream_rate_bytes gauge ins, instance, ip, job, cls The maximum stream rate for any stream reported by ingesters during a sync operation. Sharded Streams are combined.
loki_rate_store_max_stream_shards gauge ins, instance, ip, job, cls The number of shards for a single stream reported by ingesters during a sync operation.
loki_rate_store_max_unique_stream_rate_bytes gauge ins, instance, ip, job, cls The maximum stream rate for any stream reported by ingesters during a sync operation. Sharded Streams are considered separate.
loki_rate_store_stream_rate_bytes_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_rate_store_stream_rate_bytes_count Unknown ins, instance, ip, job, cls N/A
loki_rate_store_stream_rate_bytes_sum Unknown ins, instance, ip, job, cls N/A
loki_rate_store_stream_shards_bucket Unknown ins, instance, ip, le, job, cls N/A
loki_rate_store_stream_shards_count Unknown ins, instance, ip, job, cls N/A
loki_rate_store_stream_shards_sum Unknown ins, instance, ip, job, cls N/A
loki_rate_store_streams gauge ins, instance, ip, job, cls The number of unique streams reported by all ingesters. Sharded streams are combined
loki_request_duration_seconds_bucket Unknown ins, instance, method, ip, le, ws, route, job, cls, status_code N/A
loki_request_duration_seconds_count Unknown ins, instance, method, ip, ws, route, job, cls, status_code N/A
loki_request_duration_seconds_sum Unknown ins, instance, method, ip, ws, route, job, cls, status_code N/A
loki_request_message_bytes_bucket Unknown ins, instance, method, ip, le, route, job, cls N/A
loki_request_message_bytes_count Unknown ins, instance, method, ip, route, job, cls N/A
loki_request_message_bytes_sum Unknown ins, instance, method, ip, route, job, cls N/A
loki_response_message_bytes_bucket Unknown ins, instance, method, ip, le, route, job, cls N/A
loki_response_message_bytes_count Unknown ins, instance, method, ip, route, job, cls N/A
loki_response_message_bytes_sum Unknown ins, instance, method, ip, route, job, cls N/A
loki_results_cache_version_comparisons_total Unknown ins, instance, ip, job, cls N/A
loki_store_chunks_downloaded_total Unknown ins, instance, ip, status, job, cls N/A
loki_store_chunks_per_batch_bucket Unknown ins, instance, ip, le, status, job, cls N/A
loki_store_chunks_per_batch_count Unknown ins, instance, ip, status, job, cls N/A
loki_store_chunks_per_batch_sum Unknown ins, instance, ip, status, job, cls N/A
loki_store_series_total Unknown ins, instance, ip, status, job, cls N/A
loki_stream_sharding_count unknown ins, instance, ip, job, cls Total number of times the distributor has sharded streams
loki_tcp_connections gauge ins, instance, ip, protocol, job, cls Current number of accepted TCP connections.
loki_tcp_connections_limit gauge ins, instance, ip, protocol, job, cls The max number of TCP connections that can be accepted (0 means no limit).
net_conntrack_dialer_conn_attempted_total counter ins, instance, ip, dialer_name, job, cls Total number of connections attempted by the given dialer a given name.
net_conntrack_dialer_conn_closed_total counter ins, instance, ip, dialer_name, job, cls Total number of connections closed which originated from the dialer of a given name.
net_conntrack_dialer_conn_established_total counter ins, instance, ip, dialer_name, job, cls Total number of connections successfully established by the given dialer a given name.
net_conntrack_dialer_conn_failed_total counter ins, instance, ip, dialer_name, reason, job, cls Total number of connections failed to dial by the dialer a given name.
net_conntrack_listener_conn_accepted_total counter ins, instance, ip, listener_name, job, cls Total number of connections opened to the listener of a given name.
net_conntrack_listener_conn_closed_total counter ins, instance, ip, listener_name, job, cls Total number of connections closed that were made to the listener of a given name.
nginx_connections_accepted counter ins, instance, ip, job, cls Accepted client connections
nginx_connections_active gauge ins, instance, ip, job, cls Active client connections
nginx_connections_handled counter ins, instance, ip, job, cls Handled client connections
nginx_connections_reading gauge ins, instance, ip, job, cls Connections where NGINX is reading the request header
nginx_connections_waiting gauge ins, instance, ip, job, cls Idle client connections
nginx_connections_writing gauge ins, instance, ip, job, cls Connections where NGINX is writing the response back to the client
nginx_exporter_build_info gauge revision, version, ins, instance, ip, tags, goarch, goversion, job, cls, branch, goos A metric with a constant ‘1’ value labeled by version, revision, branch, goversion from which nginx_exporter was built, and the goos and goarch for the build.
nginx_http_requests_total counter ins, instance, ip, job, cls Total http requests
nginx_up gauge ins, instance, ip, job, cls Status of the last metric scrape
plugins_active_instances gauge ins, instance, ip, job, cls The number of active plugin instances
plugins_datasource_instances_total Unknown ins, instance, ip, job, cls N/A
process_cpu_seconds_total counter ins, instance, ip, job, cls Total user and system CPU time spent in seconds.
process_max_fds gauge ins, instance, ip, job, cls Maximum number of open file descriptors.
process_open_fds gauge ins, instance, ip, job, cls Number of open file descriptors.
process_resident_memory_bytes gauge ins, instance, ip, job, cls Resident memory size in bytes.
process_start_time_seconds gauge ins, instance, ip, job, cls Start time of the process since unix epoch in seconds.
process_virtual_memory_bytes gauge ins, instance, ip, job, cls Virtual memory size in bytes.
process_virtual_memory_max_bytes gauge ins, instance, ip, job, cls Maximum amount of virtual memory available in bytes.
prometheus_api_remote_read_queries gauge ins, instance, ip, job, cls The current number of remote read queries being executed or waiting.
prometheus_build_info gauge revision, version, ins, instance, ip, tags, goarch, goversion, job, cls, branch, goos A metric with a constant ‘1’ value labeled by version, revision, branch, goversion from which prometheus was built, and the goos and goarch for the build.
prometheus_config_last_reload_success_timestamp_seconds gauge ins, instance, ip, job, cls Timestamp of the last successful configuration reload.
prometheus_config_last_reload_successful gauge ins, instance, ip, job, cls Whether the last configuration reload attempt was successful.
prometheus_engine_queries gauge ins, instance, ip, job, cls The current number of queries being executed or waiting.
prometheus_engine_queries_concurrent_max gauge ins, instance, ip, job, cls The max number of concurrent queries.
prometheus_engine_query_duration_seconds summary ins, instance, ip, job, cls, quantile, slice Query timings
prometheus_engine_query_duration_seconds_count Unknown ins, instance, ip, job, cls, slice N/A
prometheus_engine_query_duration_seconds_sum Unknown ins, instance, ip, job, cls, slice N/A
prometheus_engine_query_log_enabled gauge ins, instance, ip, job, cls State of the query log.
prometheus_engine_query_log_failures_total counter ins, instance, ip, job, cls The number of query log failures.
prometheus_engine_query_samples_total counter ins, instance, ip, job, cls The total number of samples loaded by all queries.
prometheus_http_request_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls, handler N/A
prometheus_http_request_duration_seconds_count Unknown ins, instance, ip, job, cls, handler N/A
prometheus_http_request_duration_seconds_sum Unknown ins, instance, ip, job, cls, handler N/A
prometheus_http_requests_total counter ins, instance, ip, job, cls, code, handler Counter of HTTP requests.
prometheus_http_response_size_bytes_bucket Unknown ins, instance, ip, le, job, cls, handler N/A
prometheus_http_response_size_bytes_count Unknown ins, instance, ip, job, cls, handler N/A
prometheus_http_response_size_bytes_sum Unknown ins, instance, ip, job, cls, handler N/A
prometheus_notifications_alertmanagers_discovered gauge ins, instance, ip, job, cls The number of alertmanagers discovered and active.
prometheus_notifications_dropped_total counter ins, instance, ip, job, cls Total number of alerts dropped due to errors when sending to Alertmanager.
prometheus_notifications_errors_total counter ins, instance, ip, alertmanager, job, cls Total number of errors sending alert notifications.
prometheus_notifications_latency_seconds summary ins, instance, ip, alertmanager, job, cls, quantile Latency quantiles for sending alert notifications.
prometheus_notifications_latency_seconds_count Unknown ins, instance, ip, alertmanager, job, cls N/A
prometheus_notifications_latency_seconds_sum Unknown ins, instance, ip, alertmanager, job, cls N/A
prometheus_notifications_queue_capacity gauge ins, instance, ip, job, cls The capacity of the alert notifications queue.
prometheus_notifications_queue_length gauge ins, instance, ip, job, cls The number of alert notifications in the queue.
prometheus_notifications_sent_total counter ins, instance, ip, alertmanager, job, cls Total number of alerts sent.
prometheus_ready gauge ins, instance, ip, job, cls Whether Prometheus startup was fully completed and the server is ready for normal operation.
prometheus_remote_storage_exemplars_in_total counter ins, instance, ip, job, cls Exemplars in to remote storage, compare to exemplars out for queue managers.
prometheus_remote_storage_highest_timestamp_in_seconds gauge ins, instance, ip, job, cls Highest timestamp that has come into the remote storage via the Appender interface, in seconds since epoch.
prometheus_remote_storage_histograms_in_total counter ins, instance, ip, job, cls HistogramSamples in to remote storage, compare to histograms out for queue managers.
prometheus_remote_storage_samples_in_total counter ins, instance, ip, job, cls Samples in to remote storage, compare to samples out for queue managers.
prometheus_remote_storage_string_interner_zero_reference_releases_total counter ins, instance, ip, job, cls The number of times release has been called for strings that are not interned.
prometheus_rule_evaluation_duration_seconds summary ins, instance, ip, job, cls, quantile The duration for a rule to execute.
prometheus_rule_evaluation_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
prometheus_rule_evaluation_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
prometheus_rule_evaluation_failures_total counter ins, instance, ip, job, cls, rule_group The total number of rule evaluation failures.
prometheus_rule_evaluations_total counter ins, instance, ip, job, cls, rule_group The total number of rule evaluations.
prometheus_rule_group_duration_seconds summary ins, instance, ip, job, cls, quantile The duration of rule group evaluations.
prometheus_rule_group_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
prometheus_rule_group_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
prometheus_rule_group_interval_seconds gauge ins, instance, ip, job, cls, rule_group The interval of a rule group.
prometheus_rule_group_iterations_missed_total counter ins, instance, ip, job, cls, rule_group The total number of rule group evaluations missed due to slow rule group evaluation.
prometheus_rule_group_iterations_total counter ins, instance, ip, job, cls, rule_group The total number of scheduled rule group evaluations, whether executed or missed.
prometheus_rule_group_last_duration_seconds gauge ins, instance, ip, job, cls, rule_group The duration of the last rule group evaluation.
prometheus_rule_group_last_evaluation_samples gauge ins, instance, ip, job, cls, rule_group The number of samples returned during the last rule group evaluation.
prometheus_rule_group_last_evaluation_timestamp_seconds gauge ins, instance, ip, job, cls, rule_group The timestamp of the last rule group evaluation in seconds.
prometheus_rule_group_rules gauge ins, instance, ip, job, cls, rule_group The number of rules.
prometheus_sd_azure_cache_hit_total counter ins, instance, ip, job, cls Number of cache hit during refresh.
prometheus_sd_azure_failures_total counter ins, instance, ip, job, cls Number of Azure service discovery refresh failures.
prometheus_sd_consul_rpc_duration_seconds summary endpoint, ins, instance, ip, job, cls, call, quantile The duration of a Consul RPC call in seconds.
prometheus_sd_consul_rpc_duration_seconds_count Unknown endpoint, ins, instance, ip, job, cls, call N/A
prometheus_sd_consul_rpc_duration_seconds_sum Unknown endpoint, ins, instance, ip, job, cls, call N/A
prometheus_sd_consul_rpc_failures_total counter ins, instance, ip, job, cls The number of Consul RPC call failures.
prometheus_sd_discovered_targets gauge ins, instance, ip, config, job, cls Current number of discovered targets.
prometheus_sd_dns_lookup_failures_total counter ins, instance, ip, job, cls The number of DNS-SD lookup failures.
prometheus_sd_dns_lookups_total counter ins, instance, ip, job, cls The number of DNS-SD lookups.
prometheus_sd_failed_configs gauge ins, instance, ip, job, cls Current number of service discovery configurations that failed to load.
prometheus_sd_file_mtime_seconds gauge ins, instance, ip, filename, job, cls Timestamp (mtime) of files read by FileSD. Timestamp is set at read time.
prometheus_sd_file_read_errors_total counter ins, instance, ip, job, cls The number of File-SD read errors.
prometheus_sd_file_scan_duration_seconds summary ins, instance, ip, job, cls, quantile The duration of the File-SD scan in seconds.
prometheus_sd_file_scan_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
prometheus_sd_file_scan_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
prometheus_sd_file_watcher_errors_total counter ins, instance, ip, job, cls The number of File-SD errors caused by filesystem watch failures.
prometheus_sd_http_failures_total counter ins, instance, ip, job, cls Number of HTTP service discovery refresh failures.
prometheus_sd_kubernetes_events_total counter event, ins, instance, role, ip, job, cls The number of Kubernetes events handled.
prometheus_sd_kuma_fetch_duration_seconds summary ins, instance, ip, job, cls, quantile The duration of a Kuma MADS fetch call.
prometheus_sd_kuma_fetch_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
prometheus_sd_kuma_fetch_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
prometheus_sd_kuma_fetch_failures_total counter ins, instance, ip, job, cls The number of Kuma MADS fetch call failures.
prometheus_sd_kuma_fetch_skipped_updates_total counter ins, instance, ip, job, cls The number of Kuma MADS fetch calls that result in no updates to the targets.
prometheus_sd_linode_failures_total counter ins, instance, ip, job, cls Number of Linode service discovery refresh failures.
prometheus_sd_nomad_failures_total counter ins, instance, ip, job, cls Number of nomad service discovery refresh failures.
prometheus_sd_received_updates_total counter ins, instance, ip, job, cls Total number of update events received from the SD providers.
prometheus_sd_updates_total counter ins, instance, ip, job, cls Total number of update events sent to the SD consumers.
prometheus_target_interval_length_seconds summary ins, instance, interval, ip, job, cls, quantile Actual intervals between scrapes.
prometheus_target_interval_length_seconds_count Unknown ins, instance, interval, ip, job, cls N/A
prometheus_target_interval_length_seconds_sum Unknown ins, instance, interval, ip, job, cls N/A
prometheus_target_metadata_cache_bytes gauge ins, instance, ip, scrape_job, job, cls The number of bytes that are currently used for storing metric metadata in the cache
prometheus_target_metadata_cache_entries gauge ins, instance, ip, scrape_job, job, cls Total number of metric metadata entries in the cache
prometheus_target_scrape_pool_exceeded_label_limits_total counter ins, instance, ip, job, cls Total number of times scrape pools hit the label limits, during sync or config reload.
prometheus_target_scrape_pool_exceeded_target_limit_total counter ins, instance, ip, job, cls Total number of times scrape pools hit the target limit, during sync or config reload.
prometheus_target_scrape_pool_reloads_failed_total counter ins, instance, ip, job, cls Total number of failed scrape pool reloads.
prometheus_target_scrape_pool_reloads_total counter ins, instance, ip, job, cls Total number of scrape pool reloads.
prometheus_target_scrape_pool_sync_total counter ins, instance, ip, scrape_job, job, cls Total number of syncs that were executed on a scrape pool.
prometheus_target_scrape_pool_target_limit gauge ins, instance, ip, scrape_job, job, cls Maximum number of targets allowed in this scrape pool.
prometheus_target_scrape_pool_targets gauge ins, instance, ip, scrape_job, job, cls Current number of targets in this scrape pool.
prometheus_target_scrape_pools_failed_total counter ins, instance, ip, job, cls Total number of scrape pool creations that failed.
prometheus_target_scrape_pools_total counter ins, instance, ip, job, cls Total number of scrape pool creation attempts.
prometheus_target_scrapes_cache_flush_forced_total counter ins, instance, ip, job, cls How many times a scrape cache was flushed due to getting big while scrapes are failing.
prometheus_target_scrapes_exceeded_body_size_limit_total counter ins, instance, ip, job, cls Total number of scrapes that hit the body size limit
prometheus_target_scrapes_exceeded_native_histogram_bucket_limit_total counter ins, instance, ip, job, cls Total number of scrapes that hit the native histogram bucket limit and were rejected.
prometheus_target_scrapes_exceeded_sample_limit_total counter ins, instance, ip, job, cls Total number of scrapes that hit the sample limit and were rejected.
prometheus_target_scrapes_exemplar_out_of_order_total counter ins, instance, ip, job, cls Total number of exemplar rejected due to not being out of the expected order.
prometheus_target_scrapes_sample_duplicate_timestamp_total counter ins, instance, ip, job, cls Total number of samples rejected due to duplicate timestamps but different values.
prometheus_target_scrapes_sample_out_of_bounds_total counter ins, instance, ip, job, cls Total number of samples rejected due to timestamp falling outside of the time bounds.
prometheus_target_scrapes_sample_out_of_order_total counter ins, instance, ip, job, cls Total number of samples rejected due to not being out of the expected order.
prometheus_target_sync_failed_total counter ins, instance, ip, scrape_job, job, cls Total number of target sync failures.
prometheus_target_sync_length_seconds summary ins, instance, ip, scrape_job, job, cls, quantile Actual interval to sync the scrape pool.
prometheus_target_sync_length_seconds_count Unknown ins, instance, ip, scrape_job, job, cls N/A
prometheus_target_sync_length_seconds_sum Unknown ins, instance, ip, scrape_job, job, cls N/A
prometheus_template_text_expansion_failures_total counter ins, instance, ip, job, cls The total number of template text expansion failures.
prometheus_template_text_expansions_total counter ins, instance, ip, job, cls The total number of template text expansions.
prometheus_treecache_watcher_goroutines gauge ins, instance, ip, job, cls The current number of watcher goroutines.
prometheus_treecache_zookeeper_failures_total counter ins, instance, ip, job, cls The total number of ZooKeeper failures.
prometheus_tsdb_blocks_loaded gauge ins, instance, ip, job, cls Number of currently loaded data blocks
prometheus_tsdb_checkpoint_creations_failed_total counter ins, instance, ip, job, cls Total number of checkpoint creations that failed.
prometheus_tsdb_checkpoint_creations_total counter ins, instance, ip, job, cls Total number of checkpoint creations attempted.
prometheus_tsdb_checkpoint_deletions_failed_total counter ins, instance, ip, job, cls Total number of checkpoint deletions that failed.
prometheus_tsdb_checkpoint_deletions_total counter ins, instance, ip, job, cls Total number of checkpoint deletions attempted.
prometheus_tsdb_clean_start gauge ins, instance, ip, job, cls -1: lockfile is disabled. 0: a lockfile from a previous execution was replaced. 1: lockfile creation was clean
prometheus_tsdb_compaction_chunk_range_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
prometheus_tsdb_compaction_chunk_range_seconds_count Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_compaction_chunk_range_seconds_sum Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_compaction_chunk_samples_bucket Unknown ins, instance, ip, le, job, cls N/A
prometheus_tsdb_compaction_chunk_samples_count Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_compaction_chunk_samples_sum Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_compaction_chunk_size_bytes_bucket Unknown ins, instance, ip, le, job, cls N/A
prometheus_tsdb_compaction_chunk_size_bytes_count Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_compaction_chunk_size_bytes_sum Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_compaction_duration_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
prometheus_tsdb_compaction_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_compaction_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_compaction_populating_block gauge ins, instance, ip, job, cls Set to 1 when a block is currently being written to the disk.
prometheus_tsdb_compactions_failed_total counter ins, instance, ip, job, cls Total number of compactions that failed for the partition.
prometheus_tsdb_compactions_skipped_total counter ins, instance, ip, job, cls Total number of skipped compactions due to disabled auto compaction.
prometheus_tsdb_compactions_total counter ins, instance, ip, job, cls Total number of compactions that were executed for the partition.
prometheus_tsdb_compactions_triggered_total counter ins, instance, ip, job, cls Total number of triggered compactions for the partition.
prometheus_tsdb_data_replay_duration_seconds gauge ins, instance, ip, job, cls Time taken to replay the data on disk.
prometheus_tsdb_exemplar_exemplars_appended_total counter ins, instance, ip, job, cls Total number of appended exemplars.
prometheus_tsdb_exemplar_exemplars_in_storage gauge ins, instance, ip, job, cls Number of exemplars currently in circular storage.
prometheus_tsdb_exemplar_last_exemplars_timestamp_seconds gauge ins, instance, ip, job, cls The timestamp of the oldest exemplar stored in circular storage. Useful to check for what timerange the current exemplar buffer limit allows. This usually means the last timestampfor all exemplars for a typical setup. This is not true though if one of the series timestamp is in future compared to rest series.
prometheus_tsdb_exemplar_max_exemplars gauge ins, instance, ip, job, cls Total number of exemplars the exemplar storage can store, resizeable.
prometheus_tsdb_exemplar_out_of_order_exemplars_total counter ins, instance, ip, job, cls Total number of out of order exemplar ingestion failed attempts.
prometheus_tsdb_exemplar_series_with_exemplars_in_storage gauge ins, instance, ip, job, cls Number of series with exemplars currently in circular storage.
prometheus_tsdb_head_active_appenders gauge ins, instance, ip, job, cls Number of currently active appender transactions
prometheus_tsdb_head_chunks gauge ins, instance, ip, job, cls Total number of chunks in the head block.
prometheus_tsdb_head_chunks_created_total counter ins, instance, ip, job, cls Total number of chunks created in the head
prometheus_tsdb_head_chunks_removed_total counter ins, instance, ip, job, cls Total number of chunks removed in the head
prometheus_tsdb_head_chunks_storage_size_bytes gauge ins, instance, ip, job, cls Size of the chunks_head directory.
prometheus_tsdb_head_gc_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_head_gc_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_head_max_time gauge ins, instance, ip, job, cls Maximum timestamp of the head block. The unit is decided by the library consumer.
prometheus_tsdb_head_max_time_seconds gauge ins, instance, ip, job, cls Maximum timestamp of the head block.
prometheus_tsdb_head_min_time gauge ins, instance, ip, job, cls Minimum time bound of the head block. The unit is decided by the library consumer.
prometheus_tsdb_head_min_time_seconds gauge ins, instance, ip, job, cls Minimum time bound of the head block.
prometheus_tsdb_head_out_of_order_samples_appended_total counter ins, instance, ip, job, cls Total number of appended out of order samples.
prometheus_tsdb_head_samples_appended_total counter ins, instance, ip, type, job, cls Total number of appended samples.
prometheus_tsdb_head_series gauge ins, instance, ip, job, cls Total number of series in the head block.
prometheus_tsdb_head_series_created_total counter ins, instance, ip, job, cls Total number of series created in the head
prometheus_tsdb_head_series_not_found_total counter ins, instance, ip, job, cls Total number of requests for series that were not found.
prometheus_tsdb_head_series_removed_total counter ins, instance, ip, job, cls Total number of series removed in the head
prometheus_tsdb_head_truncations_failed_total counter ins, instance, ip, job, cls Total number of head truncations that failed.
prometheus_tsdb_head_truncations_total counter ins, instance, ip, job, cls Total number of head truncations attempted.
prometheus_tsdb_isolation_high_watermark gauge ins, instance, ip, job, cls The highest TSDB append ID that has been given out.
prometheus_tsdb_isolation_low_watermark gauge ins, instance, ip, job, cls The lowest TSDB append ID that is still referenced.
prometheus_tsdb_lowest_timestamp gauge ins, instance, ip, job, cls Lowest timestamp value stored in the database. The unit is decided by the library consumer.
prometheus_tsdb_lowest_timestamp_seconds gauge ins, instance, ip, job, cls Lowest timestamp value stored in the database.
prometheus_tsdb_mmap_chunk_corruptions_total counter ins, instance, ip, job, cls Total number of memory-mapped chunk corruptions.
prometheus_tsdb_mmap_chunks_total counter ins, instance, ip, job, cls Total number of chunks that were memory-mapped.
prometheus_tsdb_out_of_bound_samples_total counter ins, instance, ip, type, job, cls Total number of out of bound samples ingestion failed attempts with out of order support disabled.
prometheus_tsdb_out_of_order_samples_total counter ins, instance, ip, type, job, cls Total number of out of order samples ingestion failed attempts due to out of order being disabled.
prometheus_tsdb_reloads_failures_total counter ins, instance, ip, job, cls Number of times the database failed to reloadBlocks block data from disk.
prometheus_tsdb_reloads_total counter ins, instance, ip, job, cls Number of times the database reloaded block data from disk.
prometheus_tsdb_retention_limit_bytes gauge ins, instance, ip, job, cls Max number of bytes to be retained in the tsdb blocks, configured 0 means disabled
prometheus_tsdb_retention_limit_seconds gauge ins, instance, ip, job, cls How long to retain samples in storage.
prometheus_tsdb_size_retentions_total counter ins, instance, ip, job, cls The number of times that blocks were deleted because the maximum number of bytes was exceeded.
prometheus_tsdb_snapshot_replay_error_total counter ins, instance, ip, job, cls Total number snapshot replays that failed.
prometheus_tsdb_storage_blocks_bytes gauge ins, instance, ip, job, cls The number of bytes that are currently used for local storage by all blocks.
prometheus_tsdb_symbol_table_size_bytes gauge ins, instance, ip, job, cls Size of symbol table in memory for loaded blocks
prometheus_tsdb_time_retentions_total counter ins, instance, ip, job, cls The number of times that blocks were deleted because the maximum time limit was exceeded.
prometheus_tsdb_tombstone_cleanup_seconds_bucket Unknown ins, instance, ip, le, job, cls N/A
prometheus_tsdb_tombstone_cleanup_seconds_count Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_tombstone_cleanup_seconds_sum Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_too_old_samples_total counter ins, instance, ip, type, job, cls Total number of out of order samples ingestion failed attempts with out of support enabled, but sample outside of time window.
prometheus_tsdb_vertical_compactions_total counter ins, instance, ip, job, cls Total number of compactions done on overlapping blocks.
prometheus_tsdb_wal_completed_pages_total counter ins, instance, ip, job, cls Total number of completed pages.
prometheus_tsdb_wal_corruptions_total counter ins, instance, ip, job, cls Total number of WAL corruptions.
prometheus_tsdb_wal_fsync_duration_seconds summary ins, instance, ip, job, cls, quantile Duration of write log fsync.
prometheus_tsdb_wal_fsync_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_wal_fsync_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_wal_page_flushes_total counter ins, instance, ip, job, cls Total number of page flushes.
prometheus_tsdb_wal_segment_current gauge ins, instance, ip, job, cls Write log segment index that TSDB is currently writing to.
prometheus_tsdb_wal_storage_size_bytes gauge ins, instance, ip, job, cls Size of the write log directory.
prometheus_tsdb_wal_truncate_duration_seconds_count Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_wal_truncate_duration_seconds_sum Unknown ins, instance, ip, job, cls N/A
prometheus_tsdb_wal_truncations_failed_total counter ins, instance, ip, job, cls Total number of write log truncations that failed.
prometheus_tsdb_wal_truncations_total counter ins, instance, ip, job, cls Total number of write log truncations attempted.
prometheus_tsdb_wal_writes_failed_total counter ins, instance, ip, job, cls Total number of write log writes that failed.
prometheus_web_federation_errors_total counter ins, instance, ip, job, cls Total number of errors that occurred while sending federation responses.
prometheus_web_federation_warnings_total counter ins, instance, ip, job, cls Total number of warnings that occurred while sending federation responses.
promhttp_metric_handler_requests_in_flight gauge ins, instance, ip, job, cls Current number of scrapes being served.
promhttp_metric_handler_requests_total counter ins, instance, ip, job, cls, code Total number of scrapes by HTTP status code.
pushgateway_build_info gauge revision, version, ins, instance, ip, tags, goarch, goversion, job, cls, branch, goos A metric with a constant ‘1’ value labeled by version, revision, branch, goversion from which pushgateway was built, and the goos and goarch for the build.
pushgateway_http_requests_total counter ins, instance, method, ip, job, cls, code, handler Total HTTP requests processed by the Pushgateway, excluding scrapes.
querier_cache_added_new_total Unknown ins, instance, ip, job, cache, cls N/A
querier_cache_added_total Unknown ins, instance, ip, job, cache, cls N/A
querier_cache_entries gauge ins, instance, ip, job, cache, cls The total number of entries
querier_cache_evicted_total Unknown ins, instance, ip, job, reason, cache, cls N/A
querier_cache_gets_total Unknown ins, instance, ip, job, cache, cls N/A
querier_cache_memory_bytes gauge ins, instance, ip, job, cache, cls The current cache size in bytes
querier_cache_misses_total Unknown ins, instance, ip, job, cache, cls N/A
querier_cache_stale_gets_total Unknown ins, instance, ip, job, cache, cls N/A
ring_member_heartbeats_total Unknown ins, instance, ip, job, cls N/A
ring_member_tokens_owned gauge ins, instance, ip, job, cls The number of tokens owned in the ring.
ring_member_tokens_to_own gauge ins, instance, ip, job, cls The number of tokens to own in the ring.
scrape_duration_seconds Unknown ins, instance, ip, job, cls N/A
scrape_samples_post_metric_relabeling Unknown ins, instance, ip, job, cls N/A
scrape_samples_scraped Unknown ins, instance, ip, job, cls N/A
scrape_series_added Unknown ins, instance, ip, job, cls N/A
up Unknown ins, instance, ip, job, cls N/A

PING 指标

PING 任务包含有 54 类可用监控指标,由 blackbox_epxorter 提供。

Metric Name Type Labels Description
agent_up Unknown ins, ip, job, instance, cls N/A
probe_dns_lookup_time_seconds gauge ins, ip, job, instance, cls Returns the time taken for probe dns lookup in seconds
probe_duration_seconds gauge ins, ip, job, instance, cls Returns how long the probe took to complete in seconds
probe_icmp_duration_seconds gauge ins, ip, job, phase, instance, cls Duration of icmp request by phase
probe_icmp_reply_hop_limit gauge ins, ip, job, instance, cls Replied packet hop limit (TTL for ipv4)
probe_ip_addr_hash gauge ins, ip, job, instance, cls Specifies the hash of IP address. It’s useful to detect if the IP address changes.
probe_ip_protocol gauge ins, ip, job, instance, cls Specifies whether probe ip protocol is IP4 or IP6
probe_success gauge ins, ip, job, instance, cls Displays whether or not the probe was a success
scrape_duration_seconds Unknown ins, ip, job, instance, cls N/A
scrape_samples_post_metric_relabeling Unknown ins, ip, job, instance, cls N/A
scrape_samples_scraped Unknown ins, ip, job, instance, cls N/A
scrape_series_added Unknown ins, ip, job, instance, cls N/A
up Unknown ins, ip, job, instance, cls N/A

PUSH 指标

PushGateway 提供 44 类监控指标。

Metric Name Type Labels Description
agent_up Unknown job, cls, instance, ins, ip N/A
go_gc_duration_seconds summary job, cls, instance, ins, quantile, ip A summary of the pause duration of garbage collection cycles.
go_gc_duration_seconds_count Unknown job, cls, instance, ins, ip N/A
go_gc_duration_seconds_sum Unknown job, cls, instance, ins, ip N/A
go_goroutines gauge job, cls, instance, ins, ip Number of goroutines that currently exist.
go_info gauge job, cls, instance, ins, ip, version Information about the Go environment.
go_memstats_alloc_bytes counter job, cls, instance, ins, ip Total number of bytes allocated, even if freed.
go_memstats_alloc_bytes_total counter job, cls, instance, ins, ip Total number of bytes allocated, even if freed.
go_memstats_buck_hash_sys_bytes gauge job, cls, instance, ins, ip Number of bytes used by the profiling bucket hash table.
go_memstats_frees_total counter job, cls, instance, ins, ip Total number of frees.
go_memstats_gc_sys_bytes gauge job, cls, instance, ins, ip Number of bytes used for garbage collection system metadata.
go_memstats_heap_alloc_bytes gauge job, cls, instance, ins, ip Number of heap bytes allocated and still in use.
go_memstats_heap_idle_bytes gauge job, cls, instance, ins, ip Number of heap bytes waiting to be used.
go_memstats_heap_inuse_bytes gauge job, cls, instance, ins, ip Number of heap bytes that are in use.
go_memstats_heap_objects gauge job, cls, instance, ins, ip Number of allocated objects.
go_memstats_heap_released_bytes gauge job, cls, instance, ins, ip Number of heap bytes released to OS.
go_memstats_heap_sys_bytes gauge job, cls, instance, ins, ip Number of heap bytes obtained from system.
go_memstats_last_gc_time_seconds gauge job, cls, instance, ins, ip Number of seconds since 1970 of last garbage collection.
go_memstats_lookups_total counter job, cls, instance, ins, ip Total number of pointer lookups.
go_memstats_mallocs_total counter job, cls, instance, ins, ip Total number of mallocs.
go_memstats_mcache_inuse_bytes gauge job, cls, instance, ins, ip Number of bytes in use by mcache structures.
go_memstats_mcache_sys_bytes gauge job, cls, instance, ins, ip Number of bytes used for mcache structures obtained from system.
go_memstats_mspan_inuse_bytes gauge job, cls, instance, ins, ip Number of bytes in use by mspan structures.
go_memstats_mspan_sys_bytes gauge job, cls, instance, ins, ip Number of bytes used for mspan structures obtained from system.
go_memstats_next_gc_bytes gauge job, cls, instance, ins, ip Number of heap bytes when next garbage collection will take place.
go_memstats_other_sys_bytes gauge job, cls, instance, ins, ip Number of bytes used for other system allocations.
go_memstats_stack_inuse_bytes gauge job, cls, instance, ins, ip Number of bytes in use by the stack allocator.
go_memstats_stack_sys_bytes gauge job, cls, instance, ins, ip Number of bytes obtained from system for stack allocator.
go_memstats_sys_bytes gauge job, cls, instance, ins, ip Number of bytes obtained from system.
go_threads gauge job, cls, instance, ins, ip Number of OS threads created.
process_cpu_seconds_total counter job, cls, instance, ins, ip Total user and system CPU time spent in seconds.
process_max_fds gauge job, cls, instance, ins, ip Maximum number of open file descriptors.
process_open_fds gauge job, cls, instance, ins, ip Number of open file descriptors.
process_resident_memory_bytes gauge job, cls, instance, ins, ip Resident memory size in bytes.
process_start_time_seconds gauge job, cls, instance, ins, ip Start time of the process since unix epoch in seconds.
process_virtual_memory_bytes gauge job, cls, instance, ins, ip Virtual memory size in bytes.
process_virtual_memory_max_bytes gauge job, cls, instance, ins, ip Maximum amount of virtual memory available in bytes.
pushgateway_build_info gauge job, goversion, cls, branch, instance, tags, revision, goarch, ins, ip, version, goos A metric with a constant ‘1’ value labeled by version, revision, branch, goversion from which pushgateway was built, and the goos and goarch for the build.
pushgateway_http_requests_total counter job, cls, method, code, handler, instance, ins, ip Total HTTP requests processed by the Pushgateway, excluding scrapes.
scrape_duration_seconds Unknown job, cls, instance, ins, ip N/A
scrape_samples_post_metric_relabeling Unknown job, cls, instance, ins, ip N/A
scrape_samples_scraped Unknown job, cls, instance, ins, ip N/A
scrape_series_added Unknown job, cls, instance, ins, ip N/A
up Unknown job, cls, instance, ins, ip N/A

9.6 - 常见问题

Pigsty INFRA 基础设施模块常见问题答疑

INFRA 模块中包含了哪些组件?

严格按当前源码区分,infra 角色直接管理以下组件:

  • Nginx:暴露 Grafana、VictoriaMetrics(VMUI)、Alertmanager 等 WebUI,并托管本地 YUM/APT 仓库。
  • DNSMasq:提供 DNS 注册与解析。
  • VictoriaMetrics 套件:VictoriaMetrics、VMAlert、VictoriaLogs 与 VictoriaTraces。
  • Alertmanager、Blackbox Exporter 与 Grafana:告警分发、黑盒探测与可视化。

infra.yml 还会串联 CA、软件仓库、NODE、HAProxy 与节点监控角色,因此会在 Infra 节点上配置自签名 CA、Chronyd、Node Exporter 和 Vector 等配套能力。ETCD、PostgreSQL 与 Docker 是独立模块,不由 infra.yml 部署;应分别运行 etcd.ymlpgsql.ymldocker.yml


如何重新向 VictoriaMetrics 注册监控目标?

VictoriaMetrics 通过 /infra/targets/<job>/*.yml 目录进行静态服务发现。如果目标文件被误删,可使用如下命令重新注册:

./infra.yml  -t infra_register   # 重新渲染 Infra 自监控目标
./node.yml   -t node_register    # 重新渲染节点 / HAProxy / Vector 目标
./etcd.yml   -t etcd_register    # 重新渲染 Etcd 目标
./minio.yml  -t minio_register   # 重新渲染 Silo 模块目标
./pgsql.yml  -t pg_register      # 重新渲染 PGSQL/Patroni 目标
./redis.yml  -t redis_register   # 重新渲染 Redis 目标

其他模块(如 pg_monitor.ymlmysql.yml)也提供了对应的 *_register 标签,可按需执行。


如何重新向 Grafana 注册 PostgreSQL 数据源?

pg_databases 中定义的 PGSQL 数据库默认会被注册为 Grafana 数据源(以供 PGCAT 应用使用)。

如果你不小心删除了在 Grafana 中注册的 postgres 数据源,你可以使用以下命令再次注册它们:

# 将所有(在 pg_databases 中定义的) pgsql 数据库注册为 grafana 数据源
./pgsql.yml -t add_ds

如何重新向 Nginx 注册节点的 Haproxy 管控界面?

如果你不小心删除了 /etc/nginx/conf.d/haproxy 中的已注册 haproxy 代理设置,你可以使用以下命令再次恢复它们:

./node.yml -t register_nginx     # 在 infra 节点上向 nginx 注册所有 haproxy 管理页面的代理设置

如何恢复 DNSMASQ 中的域名注册记录?

PGSQL 集群/实例域名默认注册到 infra 节点的 /etc/dnsmasq.d/pigsty/<name>。你可以使用以下命令再次恢复它们:

./pgsql.yml -t pg_dns    # 在 infra 节点上向 dnsmasq 注册 pg 的 DNS 名称

如何使用Nginx对外暴露新的上游服务?

尽管您可以直接通过 IP:Port 的方式访问服务,但我们依然建议收敛访问入口,使用域名并统一从 Nginx 代理访问各类带有 Web 界面的服务。 这样有利于统一收口访问,减少暴露的端口,便于进行访问控制与审计。

如果你希望通过 Nginx 门户公开新的 WebUI 服务,你可以将服务定义添加到 infra_portal 参数中。 例如,下面是 Pigsty 官方 Demo 使用的 Infra 门户配置,对外暴露了几种额外的服务:

infra_portal:
  home         : { domain: home.pigsty.cc }
  grafana      : { domain: demo.pigsty.cc ,endpoint: "${admin_ip}:3000" ,websocket: true }
  vmetrics     : { domain: p.pigsty.cc ,endpoint: "${admin_ip}:8428" }
  alertmanager : { domain: a.pigsty.cc ,endpoint: "${admin_ip}:9059" }
  blackbox     : { endpoint: "${admin_ip}:9115" }
  vmalert      : { endpoint: "${admin_ip}:8880" }
  # 新增的 Web 门户
  minio        : { domain: m.pigsty.cc ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }
  postgrest    : { domain: api.pigsty.cc  ,endpoint: "127.0.0.1:8884"   }
  pgadmin      : { domain: adm.pigsty.cc  ,endpoint: "127.0.0.1:8885"   }
  pgweb        : { domain: cli.pigsty.cc  ,endpoint: "127.0.0.1:8886"   }
  bytebase     : { domain: ddl.pigsty.cc  ,endpoint: "127.0.0.1:8887"   }
  gitea        : { domain: git.pigsty.cc  ,endpoint: "127.0.0.1:8889"   }
  wiki         : { domain: wiki.pigsty.cc ,endpoint: "127.0.0.1:9002"   }
  noco         : { domain: noco.pigsty.cc ,endpoint: "127.0.0.1:9003"   }
  supa         : { domain: supa.pigsty.cc ,endpoint: "127.0.0.1:8000", websocket: true }

完成 Nginx 上游服务定义后,使用以下配置与命令,向 Nginx 注册新的服务。

./infra.yml -t nginx_config           # 重新生成 Nginx 配置文件
./infra.yml -t nginx_launch           # 更新并应用 Nginx 配置。

# 您也可以使用 Ansible 手工重载 Nginx 配置
ansible infra -b -a 'nginx -s reload'  # 重载Nginx配置

如果你希望通过 HTTPS 访问,你必须删除 files/pki/csr/pigsty.csrfiles/pki/nginx/pigsty.{key,crt} 以强制重新生成 Nginx SSL/TLS 证书以包括新上游的域名。 如果您希望使用权威机构签发的 SSL 证书,而不是 Pigsty 自签名 CA 颁发的证书,可以将其放置于 /etc/nginx/conf.d/cert/ 目录中并修改相应配置:/etc/nginx/conf.d/<name>.conf


如何手动向节点添加上游仓库的Repo文件?

Pigsty 有一个内置的包装脚本 bin/repo-add,它将调用 ansible 剧本 node.yml 来将 repo 文件添加到相应的节点。

bin/repo-add <selector> [modules]
bin/repo-add 10.10.10.10           # 为节点 10.10.10.10 添加 node 源
bin/repo-add infra   node,infra    # 为 infra 分组添加 node 和 infra 源
bin/repo-add infra   node,local    # 为 infra 分组添加节点仓库和本地pigsty源
bin/repo-add pg-test node,pgsql    # 为 pg-test 分组添加 node 和 pgsql 源

9.7 - 管理预案

基础设施组件与 Infra 集群管理 SOP:创建,销毁,扩容,缩容,证书,仓库……

本章节介绍 Pigsty 部署的日常管理和运维操作。

9.7.1 - Nginx 管理

Nginx 管理,Web 门户配置,Web Server,暴露上游服务

Pigsty 在 INFRA 节点上安装 Nginx 作为所有 Web 服务的入口,默认监听在 80/443 标准端口上。

在 Pigsty 中,你可以通过修改配置清单,让 nginx 对外提供多种服务:

  • 对外暴露 Grafana、VictoriaMetrics(VMUI)、Alertmanager、VictoriaLogs 等监控组件的 Web 界面
  • 提供静态文件服务(如软件仓库、文档站,网站等)
  • 代理自定义的应用服务(如内部应用、数据库管理界面,Docker 应用的界面等)
  • 自动签发自签名的 HTTPS 证书,或者使用 certbot 申请免费的 Let’s Encrypt 证书
  • 通过不同的子域名,使用单一端口对外暴露服务

基础配置

您可以通过 infra_portal 参数定制 Nginx 的行为:

infra_portal:
  home: { domain: i.pigsty }

infra_portal 是一个字典,每个键定义一个服务,值为服务的配置选项。 只有定义了 domain 的服务才会生成对应的 Nginx 配置文件。

  • home:特殊的默认服务器,用于处理首页和内置监控组件的反向代理
  • 代理服务:通过 endpoint 指定上游服务地址,进行反向代理
  • 静态服务:通过 path 指定本地目录,提供静态文件服务

服务器参数

基本参数

参数 说明
domain 可选的代理域名
endpoint 上游服务地址(IP:PORT 或 socket)
path 静态内容的本地目录
scheme 协议类型(http/https),默认 http
domains 额外的域名列表(别名)

SSL/TLS 选项

参数 说明
certbot 启用 Let’s Encrypt 证书管理,值为证书名称
cert 自定义证书文件路径
key 自定义私钥文件路径
enforce_https 强制跳转 HTTPS(301 重定向)

高级设置

参数 说明
config 自定义 Nginx 配置片段
index 启用目录列表(用于静态服务)
log 自定义日志文件名称
websocket 启用 WebSocket 支持
auth 启用 Basic Auth 认证
realm Basic Auth 认证提示语

配置示例

反向代理服务

grafana: { domain: g.pigsty, endpoint: "${admin_ip}:3000", websocket: true }
pgadmin: { domain: adm.pigsty, endpoint: "127.0.0.1:8885" }

静态文件与目录列表

repo: { domain: repo.pigsty.cc, path: "/www/repo", index: true }

自定义 SSL 证书

secure_app:
  domain: secure.pigsty.cc
  endpoint: "${admin_ip}:8443"
  cert: "/etc/ssl/certs/custom.crt"
  key: "/etc/ssl/private/custom.key"

使用 Let’s Encrypt 证书

grafana:
  domain: demo.pigsty.cc
  endpoint: "${admin_ip}:3000"
  websocket: true
  certbot: pigsty.demo    # 证书名称,多个域名可共用同一证书

强制 HTTPS 跳转

web.io:
  domain: en.pigsty.cc
  path: "/www/web.io"
  certbot: pigsty.doc
  enforce_https: true

自定义配置片段

web.cc:
  domain: pigsty.cc
  path: "/www/web.cc"
  domains: [ zh.pigsty.cc ]
  certbot: pigsty.doc
  config: |
    # rewrite /zh/ to /
        location /zh/ {
            rewrite ^/zh/(.*)$ /$1 permanent;
        }

管理命令

./infra.yml -t nginx           # 完整重新配置 Nginx
./infra.yml -t nginx_config    # 重新生成配置文件
./infra.yml -t nginx_launch    # 重启 Nginx 服务
./infra.yml -t nginx_cert      # 重新生成 SSL 证书
./infra.yml -t nginx_certbot   # 使用 certbot 签发证书
./infra.yml -t nginx_reload    # 重新加载 Nginx 配置

域名解析

有三种方式将域名解析到 Pigsty 服务器:

  1. 公网域名:通过 DNS 服务商配置
  2. 内网 DNS 服务器:配置内部 DNS 解析
  3. 本地 hosts 文件:修改 /etc/hosts

本地开发时,在 /etc/hosts 中添加:

<your_public_ip_address> i.pigsty

Pigsty 内置了 dnsmasq 服务,可以通过 dns_records 参数配置内部 DNS 解析。


HTTPS 配置

通过 nginx_sslmode 参数配置 HTTPS:

模式 说明
disable 仅监听 HTTP(nginx_port
enable 同时监听 HTTPS(nginx_ssl_port),默认签发自签名证书
enforce 强制跳转到 HTTPS,所有 80 端口请求都会 301 重定向

对于自签名证书,有以下几种访问方式:

  • 在浏览器中信任自签名 CA(下载地址 http://<ip>/ca.crt
  • 使用浏览器安全绕过(Chrome 中输入 “thisisunsafe”)
  • 为生产环境配置正规 CA 签发的证书或使用 Let’s Encrypt

Certbot 证书

Pigsty 支持使用 Certbot 申请免费的 Let’s Encrypt 证书。

启用 Certbot

  1. infra_portal 中为服务添加 certbot 参数,指定证书名称
  2. 配置 certbot_email 为有效的邮箱地址
  3. 设置 certbot_signtrue 在部署时自动签发
certbot_sign: true
certbot_email: [email protected]

手动签发证书

./infra.yml -t nginx_certbot   # 签发 Let's Encrypt 证书

或直接运行服务器上的脚本:

/etc/nginx/sign-cert           # 签发证书
/etc/nginx/link-cert           # 链接证书到 Nginx 配置目录

更多信息,请参阅 Certbot:申请与更新 HTTPS 证书


默认首页

Pigsty 的默认首页 home 服务器提供以下内置路由:

路径 说明
/ 首页导航
/zh 中文首页
/ui/ Grafana 监控面板
/vmetrics/ VictoriaMetrics VMUI
/vlogs/ VictoriaLogs 日志查询
/vtraces/ VictoriaTraces 链路追踪
/vmalert/ VMAlert 告警规则
/alertmgr/ AlertManager 告警管理
/blackbox/ Blackbox Exporter
/pev PostgreSQL Explain 可视化工具
/haproxy/<cluster>/ HAProxy 管理界面(如有)

这些路由允许通过单一入口访问所有监控组件,无需配置多个域名。


最佳实践

  • 使用域名而非 IP:PORT 访问服务
  • 正确配置 DNS 解析或 hosts 文件
  • 为实时应用启用 WebSocket(如 Grafana、Jupyter)
  • 生产环境启用 HTTPS
  • 使用有意义的子域名组织服务
  • 监控 Let’s Encrypt 证书过期时间
  • 利用 config 参数添加自定义 Nginx 配置

完整示例

以下是 Pigsty 公开演示站点 demo.pigsty.cc 使用的 Nginx 配置:

infra_portal:
  home         : { domain: i.pigsty }
  cc           : { domain: pigsty.cc      ,path: "/www/pigsty.cc"   ,cert: /etc/cert/pigsty.cc.crt ,key: /etc/cert/pigsty.cc.key }
  minio        : { domain: m.pigsty.cc    ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }
  postgrest    : { domain: api.pigsty.cc  ,endpoint: "127.0.0.1:8884" }
  pgadmin      : { domain: adm.pigsty.cc  ,endpoint: "127.0.0.1:8885" }
  pgweb        : { domain: cli.pigsty.cc  ,endpoint: "127.0.0.1:8886" }
  bytebase     : { domain: ddl.pigsty.cc  ,endpoint: "127.0.0.1:8887" }
  jupyter      : { domain: lab.pigsty.cc  ,endpoint: "127.0.0.1:8888" ,websocket: true }
  gitea        : { domain: git.pigsty.cc  ,endpoint: "127.0.0.1:8889" }
  wiki         : { domain: wiki.pigsty.cc ,endpoint: "127.0.0.1:9002" }
  noco         : { domain: noco.pigsty.cc ,endpoint: "127.0.0.1:9003" }
  supa         : { domain: supa.pigsty.cc ,endpoint: "10.10.10.10:8000" ,websocket: true }
  dify         : { domain: dify.pigsty.cc ,endpoint: "10.10.10.10:8001" ,websocket: true }
  odoo         : { domain: odoo.pigsty.cc ,endpoint: "127.0.0.1:8069"   ,websocket: true }
  mm           : { domain: mm.pigsty.cc   ,endpoint: "10.10.10.10:8065" ,websocket: true }

9.7.2 - 软件仓库

使用 SOW 创建和维护 Pigsty 本地 RPM/APT 软件仓库,理解完成标记、ModuleMD 与强制重建语义。

Pigsty 的 REPO 角色会下载所需软件包,并在 /www/pigsty 创建可由 Nginx 提供服务的本地 YUM/APT 仓库。当前候选软件包版本为 SOW 0.3.0,源码统一使用 SOW 生成两类仓库元数据,不再分别调用 createrepo_cmodifyrepo_cdpkg-scanpackages


快速开始

将软件包加入 repo_packagesrepo_extra_packages,然后执行:

./infra.yml -t repo_build   # 仅当仓库不存在时下载并构建
./node.yml -t node_repo     # 刷新各节点的软件仓库配置与缓存

如果 /www/pigsty/repo_complete 已存在,默认 repo_build 会跳过构建。需要强制重建时必须显式覆盖:

./infra.yml -t repo_build -e repo_build=true

只重建已有软件包的元数据,不下载新包:

./infra.yml -t repo_create

SOW 前置条件

repo_createcache_create 都要求目标节点上已经安装 sow。全新在线构建会把 infra 自动加入 repo_modules,从 Pigsty INFRA 上游仓库安装 SOW。

早于此次改造的离线包或本地仓库可能不含 SOW。使用旧介质重建前,应先刷新离线包/本地仓库,或从 Pigsty INFRA 仓库安装当前候选的 SOW 0.3.0;不能假定旧环境仍可回退到 createrepo_c

全新安装时,如果 /www 不存在,角色会创建 /data/nginx 并令 /www 指向它;已经存在的目录或符号链接会被保留,不会被强制替换。


构建流程

任务 作用
repo_check 检查 repo_complete,判断本地仓库是否已完成
repo_prepare 配置并使用已有仓库
repo_dir 创建 /www/pigsty 与 ACME 目录
repo_upstream 备份/添加上游 YUM 或 APT 定义
repo_url_pkg 下载 URL 直链软件包
repo_cache 执行 yum makecacheapt update
repo_boot_pkg 安装 sow 以及 RPM 平台所需的 dnf-utils / yum-utils
repo_pkg 下载软件包及依赖
repo_create 执行 SOW,清理并原子发布仓库元数据
repo_use 写入本机的 Pigsty local repo 定义
repo_nginx 在没有现有服务时启动临时 Nginx

repo_create 的实际命令是:

sow create --pigsty --timeout 10m -- /www/pigsty

--pigsty 会清理不需要或容易冲突的软件包,并在元数据完整生成后再原子发布结果。典型结构如下:

/www/pigsty/
├── *.rpm / *.deb
├── repodata/            # RPM 仓库
├── Packages             # APT 仓库
├── Packages.gz
└── repo_complete        # 仓库文件的 SHA-256 校验清单与完成标记

不要把 repo_complete 当作空哨兵文件;它包含 SHA-256 校验内容。该文件存在表示 SOW 已完整发布本地仓库元数据,但不证明远端镜像、签名仓库或离线包已经同步完成。


DNF 模块流

Pigsty 不再为聚合本地仓库伪造 modules.yaml / ModuleMD 元数据。系统上游仓库保留原生 DNF 模块过滤;只有确实需要替代 EL 模块流的软件源,才在 repo_upstreammeta 中显式设置:

- name: example
  module: pgsql
  # ... releases、arch、baseurl ...
  meta: { module_hotfixes: 1 }

Pigsty 聚合本地仓库自身会以 module_hotfixes=1 配置,避免本地 PostgreSQL 软件包被系统模块流隐藏。这与生成虚假的 ModuleMD 是两回事。


软件包别名

默认 repo_packages 使用以下别名组:

[node-bootstrap, infra-package, infra-addons, node-package1,
 node-package2, node-package3, pgsql-utility, extra-modules]

其中 node-bootstrap 包含 Ansible、Python 依赖、SOW 与 SSH 工具;infra-package 包含 Nginx、etcd、HAProxy、Victoria exporters、Redis/Valkey、Silo、mcli、SOW 与 Pig。具体包名会随操作系统映射,始终以 roles/node_id/vars/<os>.<arch>.yml 为准。


常用命令

./infra.yml -t repo                         # 检查、准备或构建,并启动仓库服务
./infra.yml -t repo_check,repo_prepare      # 只检查并使用已有仓库
./infra.yml -t repo_upstream                # 刷新上游仓库定义
./infra.yml -t repo_pkg                     # 下载配置的软件包及依赖
./infra.yml -t repo_create                  # 用 SOW 重建现有目录元数据
./infra.yml -t repo_build -e repo_build=true  # 强制执行完整构建阶段
./infra.yml -t repo_nginx                   # 配置/启动仓库 Nginx
./node.yml -t node_repo                     # 刷新受管节点仓库缓存
./cache.yml                                 # 用 SOW 重建元数据后制作离线包

9.7.3 - 域名管理

配置本地或公网域名访问 Pigsty 服务

使用域名代替 IP 地址访问 Pigsty 的各项 Web 服务。


快速开始

将以下静态解析记录添加到 /etc/hosts

10.10.10.10 i.pigsty

将 IP 地址替换为实际 Pigsty 节点的 IP。


为什么使用域名

  • 比 IP 地址更易于记忆
  • 灵活指向不同 IP
  • 通过 Nginx 统一管理服务
  • 支持 HTTPS 加密
  • 防止某些地区的 ISP 劫持
  • 允许通过代理访问内部绑定的服务

DNS 机制

DNS 协议:将域名解析为 IP 地址。多个域名可以指向同一个 IP。

HTTP 协议:使用 Host 头将请求路由到同一端口(80/443)上的不同站点。


默认域名

Pigsty 预定义了以下默认域名:

域名 服务 端口 用途
i.pigsty Nginx 80/443 默认首页、本地仓库与统一入口
m.pigsty Silo 9001 对象存储控制台

Grafana、VictoriaMetrics、Alertmanager 默认通过 i.pigsty 下的 /ui//vmetrics//alertmgr/ 子路径访问。若需要 g.pigstyp.pigstya.pigsty 这类独立域名,请在 infra_portaldns_records 中显式配置。


解析方式

本地静态解析

在客户端机器的 /etc/hosts 中添加条目:

# Linux/macOS
sudo vim /etc/hosts

# Windows
notepad C:\Windows\System32\drivers\etc\hosts

添加内容:

10.10.10.10 i.pigsty m.pigsty

内网动态解析

Pigsty 内置了 dnsmasq 服务作为内网 DNS 服务器。配置被管理的节点使用 INFRA 节点作为 DNS 服务器:

node_dns_servers: ['${admin_ip}']   # 使用 INFRA 节点作为 DNS 服务器
node_dns_method: add                # 将其添加到现有 DNS 服务器列表

通过 dns_records 参数配置 dnsmasq 解析的域名记录:

dns_records:
  - "${admin_ip} i.pigsty"
  - "${admin_ip} m.pigsty supa.pigsty api.pigsty adm.pigsty cli.pigsty ddl.pigsty"

公网域名

购买域名并添加 DNS A 记录指向公网 IP:

  1. 在域名服务商处购买域名(如 example.com
  2. 配置 A 记录指向服务器公网 IP
  3. infra_portal 中使用真实域名

内置 DNS 服务

Pigsty 在 INFRA 节点上运行 dnsmasq 作为 DNS 服务器。

相关参数

参数 默认值 说明
dns_enabled true 是否启用 DNS 服务
dns_port 53 DNS 监听端口
dns_records 见下文 默认 DNS 记录列表

默认的 DNS 记录:

dns_records:
  - "${admin_ip} i.pigsty"
  - "${admin_ip} m.pigsty supa.pigsty api.pigsty adm.pigsty cli.pigsty ddl.pigsty"

动态 DNS 注册

Pigsty 会自动为 PostgreSQL 集群和实例注册 DNS 记录:

  • 实例级 DNS<pg_instance> 指向实例 IP(如 pg-meta-1
  • 集群级 DNS<pg_cluster> 指向主库 IP 或 VIP(如 pg-meta

集群级 DNS 目标由 pg_dns_target 参数控制:

说明
auto 自动选择:有 VIP 用 VIP,否则用主库 IP
primary 始终指向主库 IP
vip 始终指向 VIP(需启用 VIP)
none 不注册集群 DNS
<ip> 指定固定 IP 地址

通过 pg_dns_suffix 可为集群 DNS 添加后缀。


节点 DNS 配置

Pigsty 管理被纳管节点的 DNS 配置。

静态 hosts 记录

通过 node_etc_hosts 配置静态 /etc/hosts 记录:

node_etc_hosts:
  - "${admin_ip} i.pigsty"
  - "${admin_ip} sss.pigsty"      # 可选:Silo S3 接入域名
  - "10.10.10.20 db.example.com"

DNS 服务器配置

参数 默认值 说明
node_dns_method add DNS 配置方式
node_dns_servers ['${admin_ip}'] DNS 服务器列表
node_dns_options 见下文 resolv.conf 选项

node_dns_method 可选值:

说明
add 添加到现有 DNS 服务器列表前面
overwrite 完全覆盖 DNS 服务器配置
none 不修改 DNS 配置

默认的 DNS 选项:

node_dns_options:
  - options single-request-reopen timeout:1

HTTPS 证书

Pigsty 默认使用自签名证书。可选方案包括:

  • 忽略警告,使用 HTTP
  • 信任自签名 CA 证书(下载地址 http://<ip>/ca.crt
  • 使用真实 CA 或通过 Certbot 获取免费公网域名证书

详见 CA 与证书 文档。


扩展域名

Pigsty 扩展预留了以下域名用于各种应用服务:

域名 用途
adm.pigsty PgAdmin 管理界面
ddl.pigsty Bytebase DDL 管理
cli.pigsty PgWeb 命令行界面
api.pigsty PostgREST API 服务
lab.pigsty Jupyter 实验环境
git.pigsty Gitea Git 服务
wiki.pigsty Wiki.js 文档
noco.pigsty NocoDB
supa.pigsty Supabase
dify.pigsty Dify AI
odoo.pigsty Odoo ERP
mm.pigsty Mattermost

使用这些域名需要在 infra_portal 中配置相应的服务。


管理命令

./infra.yml -t dns            # 完整配置 DNS 服务
./infra.yml -t dns_config     # 重新生成 dnsmasq 配置
./infra.yml -t dns_record     # 更新默认 DNS 记录
./infra.yml -t dns_launch     # 重启 dnsmasq 服务

./node.yml -t node_hosts      # 配置节点 /etc/hosts
./node.yml -t node_resolv     # 配置节点 DNS 解析器

./pgsql.yml -t pg_dns         # 注册 PostgreSQL DNS 记录
./pgsql.yml -t pg_dns_ins     # 仅注册实例级 DNS
./pgsql.yml -t pg_dns_cls     # 仅注册集群级 DNS

9.7.4 - 模块管理

Infra 模块本身的管理 SOP:定义,创建,销毁,扩容,缩容

本文介绍 INFRA 模块的日常管理操作,包括安装、卸载、扩容、以及各组件的管理维护。


安装 Infra 模块

使用 infra.yml 剧本在 infra 分组上安装 INFRA 模块:

./infra.yml     # 在 infra 分组上安装 INFRA 模块

卸载 Infra 模块

使用 infra-rm.yml 剧本从 infra 分组上卸载 INFRA 模块:

./infra-rm.yml -l infra # 全量移除:注销、停服、删配置/环境/数据并卸载软件包

该剧本没有防误删开关,且全量执行会删除 infra_datanginx_datanginx_home(默认 /www)和 /var/lib/grafana。 如果只需要停止服务或注销目标,应使用 -t service-t deregister;执行前请阅读 移除剧本的完整范围 并备份所需数据。


扩容 Infra 模块

在配置清单中为新节点分配 infra_seq 并加入 infra 分组:

all:
  children:
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }  # 原有节点
        10.10.10.11: { infra_seq: 2 }  # 新节点

使用限制选项 -l 仅在新节点上执行剧本:

./infra.yml -l 10.10.10.11    # 在新节点上安装 INFRA 模块

管理本地软件仓库

本地软件仓库相关的管理任务:

./infra.yml -t repo              # 从互联网或离线包创建仓库
./infra.yml -t repo_upstream     # 添加上游仓库
./infra.yml -t repo_pkg          # 下载包及依赖
./infra.yml -t repo_create       # 创建本地 yum/apt 仓库

完整子任务列表:

./infra.yml -t repo_dir          # 创建本地软件仓库
./infra.yml -t repo_check        # 检查本地软件仓库是否存在
./infra.yml -t repo_prepare      # 直接使用已有仓库
./infra.yml -t repo_build        # 从上游构建仓库
./infra.yml -t repo_upstream     # 添加上游仓库
./infra.yml -t repo_remove       # 删除现有仓库文件
./infra.yml -t repo_add          # 添加仓库到系统目录
./infra.yml -t repo_url_pkg      # 从互联网下载包
./infra.yml -t repo_cache        # 创建元数据缓存
./infra.yml -t repo_boot_pkg     # 安装引导包
./infra.yml -t repo_pkg          # 下载包及依赖
./infra.yml -t repo_create       # 创建本地仓库
./infra.yml -t repo_use          # 添加新建仓库到系统
./infra.yml -t repo_nginx        # 启动 nginx 文件服务器

管理 Nginx

Nginx 相关的管理任务:

./infra.yml -t nginx                       # 重置 Nginx 组件
./infra.yml -t nginx_index                 # 重新渲染首页
./infra.yml -t nginx_config,nginx_reload   # 重新渲染配置并重载

申请 HTTPS 证书:

./infra.yml -t nginx_certbot,nginx_reload -e certbot_sign=true

管理基础设施组件

基础设施各组件的管理命令:

./infra.yml -t infra           # 配置基础设施
./infra.yml -t infra_user      # 设置操作系统用户
./infra.yml -t infra_dir       # 创建基础设施目录
./infra.yml -t infra_env       # 配置环境变量
./infra.yml -t infra_pkg       # 安装软件包
./infra.yml -t infra_cert      # 颁发证书
./infra.yml -t dns             # 配置 DNSMasq
./infra.yml -t nginx           # 配置 Nginx
./infra.yml -t victoria        # 配置 VictoriaMetrics/Logs/Traces
./infra.yml -t alertmanager    # 配置 AlertManager
./infra.yml -t blackbox        # 配置 Blackbox Exporter
./infra.yml -t grafana         # 配置 Grafana
./infra.yml -t infra_register  # 注册到 VictoriaMetrics/Grafana

常用维护命令:

./infra.yml -t nginx_index                        # 重新渲染首页
./infra.yml -t nginx_config,nginx_reload          # 重新配置并重载
./infra.yml -t vmetrics_config,vmetrics_launch    # 重新生成 VictoriaMetrics 配置并重启
./infra.yml -t vlogs_config,vlogs_launch          # 更新 VictoriaLogs 配置
./infra.yml -t grafana_provision                  # 重新加载 Grafana 仪表盘与数据源定义

管理 Grafana 密码

Grafana 有两个密码参数:grafana_admin_password(默认 pigsty)和 grafana_view_password(默认 DBUser.Viewer):

参数 渲染到的配置文件
grafana_admin_password /etc/grafana/grafana.ini/infra/env/pigsty
grafana_view_password /etc/grafana/provisioning/datasources/pigsty.yml

这两个密码一旦初始化之后,就只能通过 grafana 界面进行修改。

Pigsty 会在初始化 Grafana 监控面板,注册 Grafana 数据源的时候,使用 grafana_admin_password。 所以如果你通过 Grafana GUI 修改了这个密码,请相应调整配置文件里面的配置。另外,您可以使用以下命令渲染新的密码到环境变量中。

./infra.yml -t env_var            # 重新渲染环境变量

grafana_view_password 是 Grafana 中默认的 Meta PostgreSQL 数据源用户 dbuser_view 的密码。 如果你修改了这个密码,请在 Grafana 数据源管理界面中同步修改密码。

9.7.5 - CA 与证书

管理 Pigsty 自签名 CA、服务证书与面向公网的 Certbot 证书。

Pigsty 默认在管理节点维护一套自签名证书颁发机构(CA),为 PostgreSQL、Patroni、etcd、Silo、Nginx 和其他内部服务签发证书。面向公网的 Nginx 入口可以按 infra_portal 配置改用 Certbot/Let’s Encrypt 证书。

保护 CA 私钥

files/pki/ca/ca.key 是整个部署的信任根私钥。不要打印、提交、上传或通过不受保护的渠道传输它;应将它与 ca.crt 成对加密备份,并严格限制读权限。


自签名 CA

infra.ymlca 阶段在 执行 Ansible 的管理节点本地 创建或复用 CA,不是在远端 Infra 节点生成私钥。默认路径如下:

files/pki/
├── ca/                       # CA 私钥、证书与 OpenSSL CA 状态
│   ├── ca.key
│   └── ca.crt
├── csr/                      # 证书签名请求
├── misc/                     # cert.yml 签发的通用证书
├── etcd/
├── infra/
├── kafka/
├── minio/                    # MINIO 模块(Silo)证书
├── mongo/
├── mysql/
├── nginx/
└── pgsql/

核心默认值与 v4.5.0 角色一致:

参数 默认值 含义
ca_create true ca.key 缺失时是否允许创建
ca_cn pigsty-ca CA 证书的 Common Name
cert_validity 7300d 一般内部服务/客户端证书的默认有效期(20 年)
nginx_cert_validity 397d Nginx 自签名 HTTPS 证书有效期

CA 证书在角色中固定为 36500d(约 100 年)。这些长期证书适用于受控内部信任域,不代表它们会被公网浏览器信任;客户端仍需显式信任 ca.crt。公网入口应使用公开受信 CA 签发的证书。

初始化本地 CA 阶段:

./infra.yml -t ca

实际执行 ./infra.yml -t ca 会在缺失时创建密钥或证书,属于 PKI 状态变更;执行前应确认管理节点、配置与现有 CA 备份。


使用外部 CA

如需复用企业 CA:

  1. pigsty.yml 设置 ca_create: false
  2. 在管理节点预先放置匹配的一对 files/pki/ca/ca.keyfiles/pki/ca/ca.crt
  3. 设置目录/文件权限,并用公钥摘要确认私钥与证书匹配。
chmod 700 files/pki/ca
chmod 600 files/pki/ca/ca.key
chmod 644 files/pki/ca/ca.crt

# 两条命令输出的公钥摘要应一致;不会输出私钥内容
openssl pkey -in files/pki/ca/ca.key -pubout -outform PEM | openssl sha256
openssl x509 -in files/pki/ca/ca.crt -pubkey -noout | openssl sha256

ca_create: false 只阻止在私钥缺失时自动生成新私钥。如果 ca.key 存在但 ca.crt 缺失,角色仍会用该私钥重新生成一个自签名 CA 证书;因此必须成对恢复两者,不要依赖自动补齐证书。

执行 CA 阶段前,应核对将要使用的文件、现有 CA 备份与管理节点。


备份与恢复 CA

至少保留以下内容:

  • files/pki/ca/ca.keyca.crt
  • ca.srlindex.txt、CRL 等 CA 状态文件(若已用于签发/撤销管理)
  • 备份时间、CA 证书 SHA-256 指纹与恢复说明
# 只查看公开 CA 证书的标识与指纹
openssl x509 -in files/pki/ca/ca.crt -noout -subject -issuer -dates -fingerprint -sha256

备份必须加密并保存到受控的离线介质或密钥管理系统;不要留下未加密的 tar 包。恢复时先放到隔离临时目录,核对文件数量、类型、权限、公钥匹配与证书指纹,再替换目标文件。

丢失 ca.key 不会让已签发证书立刻无法验证:只要客户端仍信任 ca.crt,既有证书可继续验证到失效或撤销。但您将无法用原 CA 签发、续发或撤销证书,通常需要建立新 CA、重新签发全部证书并滚动更新信任链。


使用 cert.yml 签发证书

cert.yml 只在管理节点本地运行,使用 Pigsty CA 签发通用证书。请显式传入 cn,避免使用脚本中的通用默认值:

./cert.yml -e cn=dbuser_dba

默认输出为:

files/pki/misc/<cn>.key   # 0600
files/pki/misc/<cn>.crt   # 0600
files/pki/csr/<cn>.csr
参数 默认值 说明
cn pigsty Common Name;实际使用时应显式指定
san [DNS:localhost, IP:127.0.0.1] Subject Alternative Names
org pigsty Organization
unit pigsty Organizational Unit
expire 7300d 有效期
key files/pki/misc/<cn>.key 私钥输出路径
crt files/pki/misc/<cn>.crt 证书输出路径

高级示例:

# 签发带 DNS/IP SAN 的证书,SAN 必须使用 JSON 列表传入
./cert.yml -e cn=myservice \
  -e '{"san":["DNS:myservice.local","DNS:myservice","IP:10.10.10.50"]}'

# 签发一年期证书
./cert.yml -e cn=myservice \
  -e '{"san":["DNS:myservice.local","DNS:myservice","IP:10.10.10.50"]}' \
  -e expire=365d

# 自定义 key/crt 时必须同时给出两者
./cert.yml -e cn=custom \
  -e key=/secure/path/custom.key \
  -e crt=/secure/path/custom.crt

签发后验证证书,不要查看或复制私钥内容:

openssl x509 -in files/pki/misc/myservice.crt -noout -subject -issuer -dates -ext subjectAltName
openssl verify -CAfile files/pki/ca/ca.crt files/pki/misc/myservice.crt

PostgreSQL 客户端证书的 cn 必须与 HBA/cert 认证预期的数据库角色一致。将证书、私钥与根证书安装到客户端时,私钥应为 0600,且连接串使用 sslmode=verify-full 时,目标主机名必须出现在服务器证书 SAN 中。


信任 CA 证书

仅分发公开的 ca.crt,绝不分发 ca.key。安装前先通过独立可信渠道核对 SHA-256 指纹。

Debian / Ubuntu

sudo cp ca.crt /usr/local/share/ca-certificates/pigsty-ca.crt
sudo update-ca-certificates

RHEL / Rocky / AlmaLinux

sudo cp ca.crt /etc/pki/ca-trust/source/anchors/pigsty-ca.crt
sudo update-ca-trust

macOS

sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain ca.crt

Windows(管理员 PowerShell)

Import-Certificate -FilePath .\ca.crt -CertStoreLocation Cert:\LocalMachine\Root

Infra Nginx 默认可在 http://<infra_ip>/ca.crt 提供公开 CA 证书。下载后仍应核对指纹;HTTP 传输本身不能证明证书真实性。


Nginx 与 Let’s Encrypt

每个 infra_portal 条目都可以指定 certbot 证书名称。Pigsty 的 /etc/nginx/sign-cert 使用 Certbot webroot 模式,聚合同一证书名下的 domaindomains,签发后由 /etc/nginx/link-cert 将证书链接到 Nginx。

前置条件:

  • 公网 DNS A/AAAA 记录准确指向目标 Infra 节点。
  • 公网可访问 HTTP-01 所需的 80 端口;Nginx 已提供 ACME webroot。
  • certbot_email 是有效邮箱,Certbot 软件包已安装。
  • infra_portal 的域名、额外域名与证书名准确无误。
certbot_email: [email protected]
infra_portal:
  home:
    domain: example.com
    domains: [www.example.com]
    certbot: example.com
  grafana:
    domain: grafana.example.com
    endpoint: "${admin_ip}:3000"
    websocket: true
    certbot: grafana.example.com

更新 Nginx 配置并签发证书:

dig +short example.com
./infra.yml -l infra -t nginx_config,nginx_launch

./infra.yml -l infra -t nginx_certbot,nginx_reload -e certbot_sign=true
必须单独验证签发结果

v4.5.0 的 nginx_certbot 任务设置了 ignore_errors: true。Playbook 继续执行或总体成功不代表证书已签发;必须检查 Certbot 状态、证书文件、Nginx 配置和真实 TLS 握手。

certbot certificates
test -r /etc/letsencrypt/live/example.com/fullchain.pem
nginx -t
openssl s_client -connect example.com:443 -servername example.com </dev/null

续期调度由所用发行版的 Certbot 软件包决定,不要在未检查现有 timer/cron 前重复添加任务:

systemctl list-timers --all | grep -i certbot
certbot renew --dry-run

Certbot 更新磁盘上的证书后,Nginx 还需要 reload 才会加载新证书。应配置并验证续期 deploy hook(例如 systemctl reload nginx),或建立等价的受管流程;完成一次真实或 staging 续期演练后再视为自动续期可用。


故障排查与验收

现象 核对项
浏览器不信任内部证书 客户端是否安装了正确 ca.crt;主机名是否在 SAN;系统时间是否准确
verify-full 失败 连接主机名、证书 SAN、证书链与根证书是否一致
Certbot HTTP-01 失败 DNS、80 端口、Nginx ACME webroot、代理/CDN 与速率限制
Playbook 成功但仍是旧证书 nginx_certbot 错误是否被忽略;link-cert 链接与 Nginx reload 是否完成
权限错误 私钥 0600(部署后的 Nginx key 为 0640 root:nginx);证书/目录属主是否正确
CA 轮换后服务互信失败 是否按客户端信任 → 服务证书 → 服务重载的顺序完成滚动更新

最终验收应分别证明:证书内容与 SAN 正确、链验证成功、服务实际加载新证书、目标客户端信任、续期任务存在且 dry-run 成功。生成了文件或 playbook 返回成功,都不能替代这些检查。

9.7.6 - Grafana 高可用部署:使用 PostgreSQL 后端数据库

使用 PostgreSQL 而不是 SQLite 作为 Grafana 后端使用的远程存储数据库,获取更好的性能与可用性。

您可以使用 PostgreSQL 作为 Grafana 后端使用的数据库。

这是了解 Pigsty 部署系统使用方式的好机会,完成此教程,您会了解:


太长不看

vi pigsty.yml # 取消注释DB/User定义:dbuser_grafana  grafana 
bin/pgsql-user  pg-meta  dbuser_grafana
bin/pgsql-db    pg-meta  grafana

psql postgres://dbuser_grafana:DBUser.Grafana@meta:5436/grafana -c \
  'CREATE TABLE t(); DROP TABLE t;' # 检查连接串可用性
  
vi /etc/grafana/grafana.ini # 修改 [database] type url
systemctl restart grafana-server

创建数据库集群

我们可以在 pg-meta 上定义一个新的数据库 grafana,也可以在新的机器节点上创建一个专用于 Grafana 的数据库集群:pg-grafana

定义集群

如果需要创建新的专用数据库集群 pg-grafana,部署在 10.10.10.1110.10.10.12 两台机器上,可以使用以下配置文件:

pg-grafana: 
  hosts: 
    10.10.10.11: {pg_seq: 1, pg_role: primary}
    10.10.10.12: {pg_seq: 2, pg_role: replica}
  vars:
    pg_cluster: pg-grafana
    pg_databases:
      - name: grafana
        owner: dbuser_grafana
        revokeconn: true
        comment: grafana primary database
    pg_users:
      - name: dbuser_grafana
        password: DBUser.Grafana
        pgbouncer: true
        roles: [dbrole_admin]
        comment: admin user for grafana database

创建集群

使用以下命令完成数据库集群 pg-grafana 的创建:pgsql.yml

./pgsql.yml -l pg-grafana    # 初始化pg-grafana集群

该命令是 Ansible Playbook pgsql.yml,用于创建数据库集群。

定义在 pg_userspg_databases 中的业务用户与业务数据库会在集群初始化时自动创建,因此使用该配置时,集群创建完毕后,(在没有 DNS 支持的情况下)您可以使用以下连接串 访问 数据库(任一即可):

postgres://dbuser_grafana:[email protected]:5432/grafana # 主库直连
postgres://dbuser_grafana:[email protected]:5436/grafana # 直连default服务
postgres://dbuser_grafana:[email protected]:5433/grafana # 连接串读写服务

postgres://dbuser_grafana:[email protected]:5432/grafana # 主库直连
postgres://dbuser_grafana:[email protected]:5436/grafana # 直连default服务
postgres://dbuser_grafana:[email protected]:5433/grafana # 连接串读写服务

因为默认情况下 Pigsty 安装在 单个元节点 上,接下来的步骤我们会在已有的 pg-meta 数据库集群上创建 Grafana 所需的用户与数据库,而并非使用这里创建的 pg-grafana 集群。


创建Grafana业务用户

通常业务对象管理的惯例是:先创建用户,再创建数据库。 因为如果为数据库配置了 owner,数据库对相应的用户存在依赖。

定义用户

要在 pg-meta 集群上创建用户 dbuser_grafana,首先将以下用户定义添加至 pg-meta集群定义 中:

添加位置:all.children.pg-meta.vars.pg_users

- name: dbuser_grafana
  password: DBUser.Grafana
  comment: admin user for grafana database
  pgbouncer: true
  roles: [ dbrole_admin ]

如果您在这里定义了不同的密码,请在后续步骤中将相应参数替换为新密码

创建用户

使用以下命令完成 dbuser_grafana 用户的创建(任一均可)。

bin/pgsql-user pg-meta dbuser_grafana # 在pg-meta集群上创建`dbuser_grafana`用户

实际上调用了 Ansible Playbook pgsql-user.yml 创建用户

./pgsql-user.yml -l pg-meta -e pg_user=dbuser_grafana  # Ansible

dbrole_admin 角色具有在数据库中执行 DDL 变更的权限,这正是 Grafana 所需要的。


创建Grafana业务数据库

定义数据库

创建业务数据库的方式与业务用户一致,首先在 pg-meta 的集群定义中添加新数据库 grafana定义

添加位置:all.children.pg-meta.vars.pg_databases

- { name: grafana, owner: dbuser_grafana, revokeconn: true }

创建数据库

使用以下命令完成 grafana 数据库的创建(任一均可)。

bin/pgsql-db pg-meta grafana # 在`pg-meta`集群上创建`grafana`数据库

实际上调用了 Ansible Playbook pgsql-db.yml 创建数据库

./pgsql-db.yml -l pg-meta -e pg_database=grafana # 实际执行的Ansible剧本

使用Grafana业务数据库

检查连接串可达性

您可以使用不同的 服务接入 方式访问数据库,例如:

postgres://dbuser_grafana:DBUser.Grafana@meta:5432/grafana # 直连
postgres://dbuser_grafana:DBUser.Grafana@meta:5436/grafana # default服务
postgres://dbuser_grafana:DBUser.Grafana@meta:5433/grafana # primary服务

这里,我们将使用通过负载均衡器直接访问主库的 Default服务 访问数据库。

首先检查连接串是否可达,以及是否有权限执行 DDL 命令。

psql postgres://dbuser_grafana:DBUser.Grafana@meta:5436/grafana -c \
  'CREATE TABLE t(); DROP TABLE t;'

直接修改Grafana配置

为了让 Grafana 使用 Postgres 数据源,您需要编辑 /etc/grafana/grafana.ini,并修改配置项:

[database]
;type = sqlite3
;host = 127.0.0.1:3306
;name = grafana
;user = root
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
;password =
;url =

将默认的配置项修改为:

[database]
type = postgres
url =  postgres://dbuser_grafana:DBUser.Grafana@meta/grafana

随后重启 Grafana 即可:

systemctl restart grafana-server

从监控系统中看到新增的 grafana 数据库已经开始有活动,则说明 Grafana 已经开始使用 Postgres 作为首要后端数据库了。 但一个新的问题是,Grafana 中原有的 Dashboards 与 Datasources 都消失了!这里需要重新导入 监控面板Postgres数据源


管理Grafana监控面板

您可以使用管理用户前往 Pigsty 目录下的 files/grafana 目录,执行 grafana.py init 重新加载 Pigsty 监控面板。

cd ~/pigsty/files/grafana
./grafana.py init    # 使用当前目录下的Dashboards初始化Grafana监控面板

执行结果:

vagrant@meta:~/pigsty/files/grafana
$ ./grafana.py init
Grafana API: admin:pigsty @ http://10.10.10.10:3000
init dashboard : home.json
init folder pgcat
init dashboard: pgcat / pgcat-table.json
init dashboard: pgcat / pgcat-bloat.json
init dashboard: pgcat / pgcat-query.json
init folder pgsql
init dashboard: pgsql / pgsql-replication.json
init dashboard: pgsql / pgsql-table.json
init dashboard: pgsql / pgsql-activity.json
init dashboard: pgsql / pgsql-cluster.json
init dashboard: pgsql / pgsql-node.json
init dashboard: pgsql / pgsql-database.json
init dashboard: pgsql / pgsql-xacts.json
init dashboard: pgsql / pgsql-overview.json
init dashboard: pgsql / pgsql-session.json
init dashboard: pgsql / pgsql-tables.json
init dashboard: pgsql / pgsql-instance.json
init dashboard: pgsql / pgsql-queries.json
init dashboard: pgsql / pgsql-alert.json
init dashboard: pgsql / pgsql-service.json
init dashboard: pgsql / pgsql-persist.json
init dashboard: pgsql / pgsql-proxy.json
init dashboard: pgsql / pgsql-query.json
init folder pglog
init dashboard: pglog / pglog-instance.json
init dashboard: pglog / pglog-analysis.json
init dashboard: pglog / pglog-session.json

该脚本会通过 Grafana API 导入仪表盘。你可以使用环境变量显式指定 Grafana 访问参数:

export GRAFANA_ENDPOINT=http://10.10.10.10:3000
export GRAFANA_USERNAME=admin
export GRAFANA_PASSWORD=pigsty

题外话,使用 grafana.py clean 会清空目标监控面板,使用 grafana.py load 会加载当前目录下所有监控面板,当 Pigsty 的监控面板发生变更,可以使用这两个命令升级所有的监控面板。

管理Postgres数据源

当使用 pgsql.yml 创建新 PostgreSQL 集群,或使用 pgsql-db.yml 创建新业务数据库时,Pigsty 会在 Grafana 中注册新的 PostgreSQL 数据源,您可以使用默认的监控用户通过 Grafana 直接访问目标数据库实例。应用 pgcat 的绝大部分功能有赖于此。

要注册 Postgres 数据库数据源,可以使用 pgsql.yml 中的 add_ds 任务(或使用更全面的 pg_register):

./pgsql.yml -t add_ds             # 重新注册当前环境中所有 PostgreSQL 数据源
./pgsql.yml -t add_ds -l pg-test  # 仅重新注册 pg-test 集群的数据源

一步到位更新Grafana

您可以直接通过修改 Pigsty 配置文件,更改 Grafana 使用的后端数据源,一步到位的完成切换 Grafana 后端数据库的工作。编辑 pigsty.ymlgrafana_pgurl 参数,将其修改为:

grafana_pgurl: postgres://dbuser_grafana:DBUser.Grafana@meta:5436/grafana

然后重新执行 infra.yml 中的 grafana 任务,即可完成 Grafana 升级

./infra.yml -t grafana

10 - 模块:NODE

配置目标服务器,纳管主机节点,并将其调整至描述的状态。也包括节点上的 VIP,HAProxy 以及监控组件。

配置目标服务器,纳管主机节点,并将其调整至描述的状态。也包括节点上的 VIP,HAProxy 以及监控组件。

10.1 - 集群配置

根据需求场景选择合适的 Node 部署类型,并对外提供可靠的接入。

Pigsty 使用 IP 地址 作为 节点 的唯一身份标识,该 IP 地址应当是数据库实例监听并对外提供服务的内网 IP 地址

node-test:
  hosts:
    10.10.10.11: { nodename: node-test-1 }
    10.10.10.12: { nodename: node-test-2 }
    10.10.10.13: { nodename: node-test-3 }
  vars:
    node_cluster: node-test

该 IP 地址必须是数据库实例监听并对外提供服务的 IP 地址,但不宜使用公网 IP 地址。尽管如此,用户并不一定非要通过该 IP 地址连接至该数据库。例如,通过 SSH 隧道或跳板机中转的方式间接操作管理目标节点也是可行的。但在标识数据库节点时,首要 IPv4 地址依然是节点的核心标识符。这一点非常重要,用户应当在配置时保证这一点

IP 地址即配置清单中主机的 inventory_hostname,体现为 <cluster>.hosts 对象中的 key。除此之外,每个节点还有两个额外的身份参数:

名称 类型 层级 必要性 说明
inventory_hostname ip - 必选 节点 IP 地址
nodename string I 可选 节点名称
node_cluster string C 可选 节点集群名称

nodenamenode_cluster 两个参数是可选的,如果不提供,会使用节点现有的主机名,和固定值 nodes 作为默认值。在 Pigsty 的监控系统中,这两者将会被用作节点的 集群标识cls)与 实例标识ins)。

对于 PGSQL节点 来说,因为 Pigsty 默认采用 PG:节点独占1:1部署,因此可以通过 node_id_from_pg 参数,将 PostgreSQL 实例的身份参数(pg_clusterpg_seq)借用至节点的 inscls 标签上,从而让数据库与节点的监控指标拥有相同的标签,便于交叉分析。

#nodename:                # [实例] # 节点实例标识,如缺失则使用现有主机名,可选,无默认值
node_cluster: nodes       # [集群] # 节点集群标识,如缺失则使用默认值'nodes',可选
nodename_overwrite: true          # 用 nodename 覆盖节点的主机名吗?
nodename_exchange: false          # 在剧本主机之间交换 nodename 吗?
node_id_from_pg: true             # 如果可行,是否借用 postgres 身份作为节点身份?

您还可以为主机集群配置丰富的功能参数,例如,使用节点集群上的 HAProxy 对外提供负载均衡,暴露服务,或者为集群绑定一个 L2 VIP。

10.2 - 参数列表

NODE 模块提供了 11 组共 74 个配置参数

NODE 模块负责将主机节点调整到期待的目标状态,并将其纳入 Pigsty 的监控系统中。


参数组 功能说明
NODE_ID NODE_ID 相关参数
NODE_DNS NODE_DNS 相关参数
NODE_PACKAGE NODE_PACKAGE 相关参数
NODE_TUNE NODE_TUNE 相关参数
NODE_SEC NODE_SEC 安全相关参数
NODE_ADMIN NODE_ADMIN 相关参数
NODE_TIME NODE_TIME 相关参数
NODE_VIP NODE_VIP 相关参数
HAPROXY HAPROXY 相关参数
NODE_EXPORTER NODE_EXPORTER 相关参数
VECTOR VECTOR 日志收集相关参数

参数概览

NODE_ID 参数组用于定义节点的身份标识参数,包括节点名称、集群名称,以及是否从 PostgreSQL 借用身份。

参数 类型 级别 说明
nodename string I node 实例标识,如缺失则使用主机名,可选
node_cluster string C node 集群标识,如缺失则使用默认值’nodes’,可选
nodename_overwrite bool C 用 nodename 覆盖节点的主机名吗?
nodename_exchange bool C 在剧本主机之间交换 nodename 吗?
node_id_from_pg bool C 如果可行,是否借用 postgres 身份作为节点身份?

NODE_DNS 参数组用于配置节点的 DNS 解析,包括静态 hosts 记录与动态 DNS 服务器。

参数 类型 级别 说明
node_write_etc_hosts bool G/C/I 是否修改目标节点上的 /etc/hosts
node_default_etc_hosts string[] G /etc/hosts 中的静态 DNS 记录
node_etc_hosts string[] C /etc/hosts 中的额外静态 DNS 记录
node_dns_method enum C 如何处理现有 DNS 服务器:add,none,overwrite
node_dns_servers string[] C /etc/resolv.conf 中的动态域名服务器列表
node_dns_options string[] C /etc/resolv.conf 中的 DNS 解析选项

NODE_PACKAGE 参数组用于配置节点的软件源与软件包安装,以及 uv Python 虚拟环境。

参数 类型 级别 说明
node_repo_modules enum C 在节点上启用哪些软件源模块?默认为 local
node_repo_remove bool C 配置节点软件仓库时,删除节点上现有的仓库吗?
node_packages string[] C 要在当前节点上安装的软件包列表
node_default_packages string[] G 默认在所有节点上安装的软件包列表
node_uv_env path C uv venv 路径,默认 /data/venv,空则跳过
node_pip_packages string C 在 uv venv 中安装的 pip 包

NODE_TUNE 参数组用于配置节点的内核参数、特性开关与性能调优模板。

参数 类型 级别 说明
node_disable_numa bool C 禁用节点 numa,禁用需要重启
node_disable_swap bool C 禁用节点 Swap,谨慎使用
node_static_network bool C 重启后保留 DNS 解析器设置,即静态网络,默认启用
node_disk_prefetch bool C 在 HDD 上配置磁盘预取以提高性能
node_kernel_modules string[] C 在此节点上启用的内核模块列表
node_hugepage_count int C 主机节点分配的 2MB 大页数量,优先级比比例更高
node_hugepage_ratio float C 主机节点分配的内存大页占总内存比例,0 默认禁用
node_overcommit_ratio float C 节点内存允许的 OverCommit 超额比率 (50-100),0 默认禁用
node_tune enum C 节点调优配置文件:无,oltp,olap,crit,tiny
node_tuned_profile_dir path C tuned 配置文件目录,由发行版映射确定
node_sysctl_params dict C 额外的 sysctl 配置参数,k:v 格式

NODE_SEC 参数组用于配置节点的安全相关选项,包括 SELinux、防火墙等。

参数 类型 级别 说明
node_selinux_mode enum C SELinux 模式:disabled, permissive, enforcing
node_firewall_mode enum C 防火墙模式:zone(默认启用),off(关闭),none(自管)
node_firewall_intranet cidr[] C 内网 CIDR 列表,用于配置防火墙规则
node_firewall_public_port port[] C 公网开放端口列表,默认为 [22, 80, 443]

NODE_ADMIN 参数组用于配置节点的管理员用户、数据目录与命令别名。

参数 类型 级别 说明
node_data path C 节点主数据目录,默认为 /data
node_admin_enabled bool C 在目标节点上创建管理员用户吗?
node_admin_uid int C 节点管理员用户的 uid 和 gid
node_admin_username username C 节点管理员用户的名称,默认为 dba
node_admin_sudo enum C 管理员用户的 sudo 权限:nopass, all, limit
node_admin_ssh_exchange bool C 是否在节点集群之间交换管理员 ssh 密钥
node_admin_pk_current bool C 将当前用户的 ssh 公钥添加到管理员的 authorized_keys 中吗?
node_admin_pk_list string[] C 要添加到管理员用户的 ssh 公钥
node_aliases dict C 配置主机上的 Shell Alias 命令,KV 字典

NODE_TIME 参数组用于配置节点的时区、NTP 时间同步与定时任务。

参数 类型 级别 说明
node_timezone string C 设置主机节点时区,空字符串跳过
node_ntp_enabled bool C 启用 chronyd 时间同步服务吗?
node_ntp_servers string[] C /etc/chrony.conf 中的 ntp 服务器列表
node_crontab_overwrite bool C 写入 /etc/crontab 时,追加写入还是全部覆盖?
node_crontab string[] C 在 /etc/crontab 中的 crontab 条目

NODE_VIP 参数组用于配置节点集群的 L2 VIP,由 keepalived 实现。

参数 类型 级别 说明
vip_enabled bool C 在此节点集群上启用 L2 vip 吗?
vip_address ip C 节点 vip 地址的 ipv4 格式,启用 vip 时为必要参数
vip_vrid int C 所需的整数,1-254,在同一 VLAN 中应唯一
vip_role enum I 可选,master/backup,默认为 backup
vip_preempt bool C/I 可选,true/false,默认为 false,启用 vip 抢占
vip_interface string C/I 节点 vip 网络接口监听,默认为 auto
vip_dns_suffix string C 节点 vip DNS 名称后缀,默认为空字符串
vip_auth_pass password C VRRP 认证密码,空则使用 <cls>-<vrid> 作为默认值
vip_exporter_port port C keepalived exporter 监听端口,默认为 9650

HAPROXY 参数组用于配置节点上的 HAProxy 负载均衡器与服务暴露。

参数 类型 级别 说明
haproxy_enabled bool C 在此节点上启用 haproxy 吗?
haproxy_clean bool G/C/A 清除所有现有的 haproxy 配置吗?
haproxy_reload bool A 配置后重新加载 haproxy 吗?
haproxy_auth_enabled bool G 启用 haproxy 管理页面的身份验证?
haproxy_admin_username username G haproxy 管理用户名,默认为 admin
haproxy_admin_password password G haproxy 管理密码,默认为 pigsty
haproxy_exporter_port port C haproxy exporter 的端口,默认为 9101
haproxy_client_timeout interval C haproxy 客户端连接超时,默认为 24h
haproxy_server_timeout interval C haproxy 服务器端连接超时,默认为 24h
haproxy_services service[] C 要在节点上对外暴露的 haproxy 服务列表

NODE_EXPORTER 参数组用于配置节点监控 Exporter。

参数 类型 级别 说明
node_exporter_enabled bool C 在此节点上配置 node_exporter 吗?
node_exporter_port port C node exporter 监听端口,默认为 9100
node_exporter_options arg C node_exporter 的额外服务器选项

VECTOR 参数组用于配置 Vector 日志收集器。

参数 类型 级别 说明
vector_enabled bool C 启用 vector 日志收集器吗?
vector_clean bool G/A 初始化期间清除 vector 数据目录吗?
vector_data path C vector 数据目录,默认为 /data/vector
vector_port port C vector 指标监听端口,默认为 9598
vector_read_from enum C vector 从头还是从尾开始读取日志
vector_log_endpoint string[] C 日志发送目标端点,默认发送至 infra 组

NODE_ID

每个节点都有 身份参数,通过在<cluster>.hosts<cluster>.vars中的相关参数进行配置。

Pigsty 使用 IP 地址 作为 数据库节点 的唯一标识,该 IP 地址必须是数据库实例监听并对外提供服务的 IP 地址,但不宜使用公网 IP 地址。 尽管如此,用户并不一定非要通过该 IP 地址连接至该数据库。例如,通过 SSH 隧道或跳板机中转的方式间接操作管理目标节点也是可行的。 但在标识数据库节点时,首要 IPv4 地址依然是节点的核心标识符。这一点非常重要,用户应当在配置时保证这一点。 IP 地址即配置清单中主机的 inventory_hostname,体现为<cluster>.hosts对象中的 key

node-test:
  hosts:
    10.10.10.11: { nodename: node-test-1 }
    10.10.10.12: { nodename: node-test-2 }
    10.10.10.13: { nodename: node-test-3 }
  vars:
    node_cluster: node-test

除此之外,在 Pigsty 监控系统中,节点还有两个重要的身份参数:nodenamenode_cluster,这两者将在监控系统中被用作节点的 实例标识ins) 与 集群标识cls)。

node_load1{cls="pg-meta", ins="pg-meta-1", ip="10.10.10.10", job="nodes"}
node_load1{cls="pg-test", ins="pg-test-1", ip="10.10.10.11", job="nodes"}
node_load1{cls="pg-test", ins="pg-test-2", ip="10.10.10.12", job="nodes"}
node_load1{cls="pg-test", ins="pg-test-3", ip="10.10.10.13", job="nodes"}

在执行默认的 PostgreSQL 部署时,因为 Pigsty 默认采用节点独占1:1部署,因此可以通过 node_id_from_pg 参数,将数据库实例的身份参数(pg_cluster 借用至节点的 inscls 标签上。

名称 类型 层级 必要性 说明
inventory_hostname ip - 必选 节点 IP 地址
nodename string I 可选 节点名称
node_cluster string C 可选 节点集群名称
#nodename:                # [实例] # 节点实例标识,如缺失则使用现有主机名,可选,无默认值
node_cluster: nodes       # [集群] # 节点集群标识,如缺失则使用默认值'nodes',可选
nodename_overwrite: true          # 用 nodename 覆盖节点的主机名吗?
nodename_exchange: false          # 在剧本主机之间交换 nodename 吗?
node_id_from_pg: true             # 如果可行,是否借用 postgres 身份作为节点身份?

nodename

参数名称: nodename, 类型: string, 层次:I

主机节点的身份参数,如果没有显式设置,则会使用现有的主机 Hostname 作为节点名。本参数虽然是身份参数,但因为有合理默认值,所以是可选项。

如果启用了 node_id_from_pg 选项(默认启用),且 nodename 没有被显式指定, 那么 nodename 会尝试使用 ${pg_cluster}-${pg_seq} 作为实例身份参数,如果集群没有定义 PGSQL 模块,那么会回归到默认值,也就是主机节点的 HOSTNAME。

node_cluster

参数名称: node_cluster, 类型: string, 层次:C

该选项可为节点显式指定一个集群名称,通常在节点集群层次定义才有意义。使用默认空值将直接使用固定值 nodes 作为节点集群标识。

如果启用了 node_id_from_pg 选项(默认启用),且 node_cluster 没有被显式指定,那么 node_cluster 会尝试使用 ${pg_cluster} 作为集群身份参数,如果集群没有定义 PGSQL 模块,那么会回归到默认值 nodes

nodename_overwrite

参数名称: nodename_overwrite, 类型: bool, 层次:C

是否使用 nodename 覆盖主机名?默认值为 true,在这种情况下,如果你设置了一个非空的 nodename,那么它会被用作当前主机的 HOSTNAME。

nodename 配置为空时,如果 node_id_from_pg 参数被配置为 true (默认为真),那么 Pigsty 会尝试借用1:1定义在节点上的 PostgreSQL 实例的身份参数作为主机的节点名。 也就是 {{ pg_cluster }}-{{ pg_seq }},如果该节点没有安装 PGSQL 模块,则会回归到默认什么都不做的状态。

因此,如果您将 nodename 留空,并且没有启用 node_id_from_pg 参数时,Pigsty 不会对现有主机名进行任何修改。

nodename_exchange

参数名称: nodename_exchange, 类型: bool, 层次:C

是否在剧本节点间交换主机名?默认值为:false

启用此参数时,同一批组执行 node.yml 剧本的节点之间会相互交换节点名称,写入 /etc/hosts 中。

node_id_from_pg

参数名称: node_id_from_pg, 类型: bool, 层次:C

从节点上 1:1 部署的 PostgreSQL 实例/集群上借用身份参数? 默认值为 true

Pigsty 中的 PostgreSQL 实例与节点默认使用 1:1 部署,因此,您可以从数据库实例上“借用” 身份参数。 此参数默认启用,这意味着一套 PostgreSQL 集群如果没有特殊配置,主机节点集群和实例的身份参数默认值是与数据库身份参数保持一致的。对于问题分析,监控数据处理都提供了额外便利。


NODE_DNS

Pigsty 会为节点配置静态 DNS 解析记录与动态 DNS 服务器。

如果您的节点供应商已经为您配置了 DNS 服务器,您可以将 node_dns_method 设置为 none 跳过 DNS 设置。

node_write_etc_hosts: true        # modify `/etc/hosts` on target node?
node_default_etc_hosts:           # static dns records in `/etc/hosts`
  - "${admin_ip} i.pigsty"
node_etc_hosts: []                # extra static dns records in `/etc/hosts`
node_dns_method: add              # how to handle dns servers: add,none,overwrite
node_dns_servers: ['${admin_ip}'] # dynamic nameserver in `/etc/resolv.conf`
node_dns_options:                 # dns resolv options in `/etc/resolv.conf`
  - options single-request-reopen timeout:1

node_write_etc_hosts

参数名称: node_write_etc_hosts, 类型: bool, 层次:G|C|I

是否修改目标节点上的 /etc/hosts?默认值为 true。例如,在容器环境中通常不允许修改此配置文件,此时可设为 false 跳过。

node_default_etc_hosts

参数名称: node_default_etc_hosts, 类型: string[], 层次:G

默认写入所有节点 /etc/hosts 的静态 DNS 记录,默认值为:

["${admin_ip} i.pigsty"]

node_default_etc_hosts 是一个数组,每个元素都是一条 DNS 记录,格式为 <ip> <name>,您可以指定多个用空格分隔的域名。

这个参数是用于配置全局静态 DNS 解析记录的,如果您希望为单个集群与实例配置特定的静态 DNS 解析,则可以使用 node_etc_hosts 参数。

node_etc_hosts

参数名称: node_etc_hosts, 类型: string[], 层次:C

写入节点 /etc/hosts 的额外的静态 DNS 记录,默认值为:[] 空数组。

本参数与 node_default_etc_hosts,形式一样,但用途不同:适合在集群/实例层面进行配置。

node_dns_method

参数名称: node_dns_method, 类型: enum, 层次:C

如何配置 DNS 服务器?有三种选项:addnoneoverwrite,默认值为 add

  • add:将 node_dns_servers 中的记录 追加/etc/resolv.conf,并保留已有 DNS 服务器。(默认)
  • overwrite:使用将 node_dns_servers 中的记录覆盖 /etc/resolv.conf
  • none:跳过 DNS 服务器配置,如果您的环境中已经配置有 DNS 服务器,则可以直接跳过 DNS 配置。

node_dns_servers

参数名称: node_dns_servers, 类型: string[], 层次:C

配置 /etc/resolv.conf 中的动态 DNS 服务器列表:默认值为: ["${admin_ip}"],即将管理节点作为首要 DNS 服务器。

node_dns_options

参数名称: node_dns_options, 类型: string[], 层次:C

/etc/resolv.conf 中的 DNS 解析选项,默认值为:

- "options single-request-reopen timeout:1"

如果 node_dns_method 配置为 addoverwrite,则本配置项中的记录会被首先写入 /etc/resolv.conf 中。具体格式请参考 Linux 文档关于 /etc/resolv.conf 的说明


NODE_PACKAGE

Pigsty 会为纳入管理的节点配置 Yum 源,并安装软件包,以及配置 uv Python 虚拟环境。

node_repo_modules: local          # upstream repo to be added on node, local by default.
node_repo_remove: true            # remove existing repo on node?
node_packages: [openssh-server]   # packages to be installed current nodes with latest version
#node_default_packages:           # default packages to be installed on all nodes
node_uv_env: /data/venv           # uv venv path, /data/venv by default, empty to skip
node_pip_packages: ''             # pip packages to be installed in uv venv

node_repo_modules

参数名称: node_repo_modules, 类型: string, 层次:C/A

需要在节点上添加的软件源模块列表,形式同 repo_modules。默认值为 local,即使用 repo_upstreamlocal 所指定的本地软件源。

当 Pigsty 纳管节点时,会根据此参数的值来过滤 repo_upstream 中的条目,只有 module 字段与此参数值匹配的条目才会被添加到节点的软件源中。

node_repo_remove

参数名称: node_repo_remove, 类型: bool, 层次:C/A

是否移除节点已有的软件仓库定义?默认值为:true

如果启用,则 Pigsty 会 移除 节点上 /etc/yum.repos.d 中原有的配置文件,并备份至 /etc/yum.repos.d/backup。 在 Debian/Ubuntu 系统上,则是 /etc/apt/sources.list(.d) 备份至 /etc/apt/backup

node_packages

参数名称: node_packages, 类型: string[], 层次:C

在当前节点上要安装并升级的软件包列表,默认值为:[openssh-server],即在安装时会将 sshd 升级到最新版本(避免安全漏洞)。

每一个数组元素都是字符串:由逗号分隔的软件包名称。形式上与 node_default_packages 相同。本参数通常用于在节点/集群层面指定需要额外安装的软件包。

在本参数中指定的软件包,会 升级到可用的最新版本,如果您需要保持现有节点软件版本不变(存在即可),请使用 node_default_packages 参数。

node_default_packages

参数名称: node_default_packages, 类型: string[], 层次:G

默认在所有节点上安装的软件包。该参数本身没有单一的跨平台默认值;如果用户未显式设置,node_id 角色会根据操作系统版本和 CPU 架构,从 roles/node_id/vars 对应的 <os>.<arch>.yml 文件中加载 node_packages_default

这是字符串数组类型,每一行都是 由逗号分隔 的软件包列表字符串。不同发行版、版本与架构的映射可能不同,不能把某一份 EL 或 Debian 列表视为所有同族系统的通用默认值。

在此变量中指定的软件包,只要求 存在,而不要求 最新。如果您需要安装最新版本的软件包,请使用 node_packages 参数。

例如,当前 EL 9 x86_64 的平台映射值为:

- bash,python3,sudo,acl,ca-certificates,openssl,curl,wget,lz4,zstd,unzip,bzip2,gzip,tar,tzdata,chrony,openssh-server,util-linux,rsync,psmisc,logrotate
- pv,jq,git,make,patch,lsof,less,ncdu,htop,iotop,socat,net-tools,telnet,ipvsadm,tuned,numactl,nvme-cli,sysstat,keepalived,etcd,haproxy,vector,pig,uv
- zlib,readline,xz,glibc-langpack-en,cronie,openssh-clients,node-exporter,bind-utils,iproute,iputils,nmap-ncat,procps-ng,vim-minimal,yum,audit,grubby,chkconfig

当前 Debian 13 x86_64 的平台映射值为:

- bash,python3,sudo,acl,ca-certificates,openssl,curl,wget,lz4,zstd,unzip,bzip2,gzip,tar,tzdata,chrony,openssh-server,util-linux,rsync,psmisc,logrotate
- pv,jq,git,make,patch,lsof,less,ncdu,htop,iotop,socat,net-tools,telnet,ipvsadm,tuned,numactl,nvme-cli,sysstat,keepalived,etcd,haproxy,vector,pig,uv
- zlib1g,libreadline-dev,xz-utils,locales,cron,openssh-client,node-exporter,bind9-dnsutils,iproute2,iputils-ping,netcat-openbsd,procps,vim-tiny

本参数形式上与 node_packages 相同,但通常用于全局层面覆盖平台映射,指定所有节点都必须安装的软件包。

node_uv_env

参数名称: node_uv_env, 类型: path, 层次:C

uv 虚拟环境路径,默认值为:/data/venv。设置为空字符串 '' 则跳过 uv 虚拟环境的配置。

当此参数非空时,Pigsty 会在节点上使用 uv venv 命令创建 Python 虚拟环境,并根据 node_pip_packages 安装指定的 pip 包。

在中国区域(region: china)时,会自动配置 /etc/uv/uv.toml 使用腾讯云 PyPI 镜像 https://mirrors.cloud.tencent.com/pypi/simple/ 加速下载。

node_pip_packages

参数名称: node_pip_packages, 类型: string, 层次:C

在 uv 虚拟环境中安装的 pip 包列表,默认值为:空字符串 ''

使用空格分隔多个包名,例如:'ansible pgcli requests pandas'

仅当 node_uv_env 非空时此参数才会生效。


NODE_TUNE

主机节点特性、内核模块与参数调优模板。

node_disable_numa: false          # disable node numa, reboot required
node_disable_swap: false          # disable node swap, use with caution
node_static_network: true         # preserve dns resolver settings after reboot
node_disk_prefetch: false         # setup disk prefetch on HDD to increase performance
node_kernel_modules: [ softdog, ip_vs, ip_vs_rr, ip_vs_wrr, ip_vs_sh ]
node_hugepage_count: 0            # number of 2MB hugepage, take precedence over ratio
node_hugepage_ratio: 0            # node mem hugepage ratio, 0 disable it by default
node_overcommit_ratio: 0          # node mem overcommit ratio, 0 disable it by default
node_tune: oltp                   # node tuned profile: none,oltp,olap,crit,tiny
node_tuned_profile_dir: /etc/tuned # node tuned profile directory
node_sysctl_params:               # sysctl parameters in k:v format in addition to tuned
  fs.nr_open: 8388608

node_disable_numa

参数名称: node_disable_numa, 类型: bool, 层次:C

是否关闭 NUMA?默认不关闭 NUMA:false

注意,关闭 NUMA 需要重启机器后方可生效!如果您不清楚如何绑核,在生产环境使用数据库时建议关闭 NUMA。

node_disable_swap

参数名称: node_disable_swap, 类型: bool, 层次:C

是否关闭 SWAP? 默认不关闭 SWAP:false

通常情况下不建议关闭 SWAP,例外情况是如果您有足够的内存用于独占式 PostgreSQL 部署,则可以关闭 SWAP 提高性能。

例外:当您的节点用于部署 Kubernetes 模块时,应当禁用 SWAP。

node_static_network

参数名称: node_static_network, 类型: bool, 层次:C

是否使用静态 DNS 服务器,类型:bool,层级:C,默认值为:true,默认启用。

启用静态网络,意味着您的 DNS Resolv 配置不会因为机器重启与网卡变动被覆盖,建议启用,或由网络工程师负责配置。

node_disk_prefetch

参数名称: node_disk_prefetch, 类型: bool, 层次:C

是否启用磁盘预读?默认不启用:false

针对 HDD 部署的实例可以优化性能,使用机械硬盘时建议启用。

node_kernel_modules

参数名称: node_kernel_modules, 类型: string[], 层次:C

启用哪些内核模块?默认启用以下内核模块:

node_kernel_modules: [ softdog, ip_vs, ip_vs_rr, ip_vs_wrr, ip_vs_sh ]

形式上是由内核模块名称组成的数组,声明了需要在节点上安装的内核模块。

node_hugepage_count

参数名称: node_hugepage_count, 类型: int, 层次:C

在节点上分配 2MB 大页的数量,默认为 0,另一个相关的参数是 node_hugepage_ratio

如果这两个参数 node_hugepage_countnode_hugepage_ratio 都为 0(默认),则大页将完全被禁用,本参数的优先级相比 node_hugepage_ratio 更高,因为它更加精确。

如果设定了一个非零值,它将被写入 /etc/sysctl.d/hugepage.conf 中应用生效;负值将不起作用,高于 90% 节点内存的数字将被限制为节点内存的 90%

如果不为零,它应该略大于 pg_shared_buffer_ratio 的对应值,这样才能让 PostgreSQL 用上大页。

node_hugepage_ratio

参数名称: node_hugepage_ratio, 类型: float, 层次:C

节点内存大页占内存的比例,默认为 0,有效范围:0 ~ 0.40

此内存比例将以大页的形式分配,并为 PostgreSQL 预留。 node_hugepage_count 是具有更高优先级和精度的参数版本。

默认值:0,这将设置 vm.nr_hugepages=0 并完全不使用大页。

本参数应该等于或略大于 pg_shared_buffer_ratio,如果不为零。

例如,如果您为 Postgres 共享缓冲区默认分配了25%的内存,您可以将此值设置为 0.27 ~ 0.30,并在初始化后使用 /pg/bin/pg-tune-hugepage 精准回收浪费的大页。

node_overcommit_ratio

参数名称: node_overcommit_ratio, 类型: int, 层次:C

节点内存超额分配比率,默认为:0。这是一个从 0100+ 的整数。

默认值:0,这将设置 vm.overcommit_memory=0,否则将使用 vm.overcommit_memory=2, 并使用此值作为 vm.overcommit_ratio

建议在 pgsql 独占节点上设置 vm.overcommit_ratio,避免内存过度提交。

node_tune

参数名称: node_tune, 类型: enum, 层次:C

针对机器进行调优的预制方案,基于 tuned 提供服务。有四种预制模式:

  • tiny:微型虚拟机
  • oltp:常规 OLTP 模板,优化延迟(默认值)
  • olap:常规 OLAP 模板,优化吞吐量
  • crit:核心金融业务模板,优化脏页数量

通常,数据库的调优模板 pg_conf 应当与机器调优模板配套。

node_tuned_profile_dir

参数名称:node_tuned_profile_dir,类型:path,层次:C

Pigsty 写入 tinyoltpolapcrit 调优配置的目录。角色默认值为 /etc/tuned,随后由平台变量适配发行版目录布局:EL 10、Debian 13 与 Ubuntu 26 使用 /etc/tuned/profiles;EL 8/9、Debian 12 与 Ubuntu 22/24 使用 /etc/tuned

通常无需手工覆盖;仅当目标系统的 tuned 配置目录偏离 Pigsty 已知平台映射时才应设置本参数。

node_sysctl_params

参数名称: node_sysctl_params, 类型: dict, 层次:C

使用 K:V 形式的 sysctl 内核参数(通过 Ansible sysctl 模块写入并立即生效),作为 tuned profile 的补充。

默认值为:

node_sysctl_params:
  fs.nr_open: 8388608

默认设置 fs.nr_open=8388608 用于确保内核每进程 FD 上限不小于 Pigsty systemd unit 中的 LimitNOFILE=8388608,避免在部分发行版 / systemd 组合上服务启动时 setrlimit 失败。

这是一个 KV 结构的字典参数,Key 是内核 sysctl 参数名,Value 是参数值。你也可以考虑直接在 roles/node/templates 中的 tuned 模板中直接定义额外的 sysctl 参数。


NODE_SEC

节点安全相关参数,包括 SELinux 与防火墙配置。

node_selinux_mode: permissive             # selinux mode: disabled, permissive, enforcing
node_firewall_mode: zone                  # firewall mode: zone (default, enabled), off (disable), none (skip & self-managed)
node_firewall_intranet:           # which intranet cidr considered as internal network
  - 10.0.0.0/8
  - 192.168.0.0/16
  - 172.16.0.0/12
node_firewall_public_port:        # expose these ports to public network in zone mode
  - 22                            # enable ssh access
  - 80                            # enable http access
  - 443                           # enable https access

node_selinux_mode

参数名称: node_selinux_mode, 类型: enum, 层次:C

SELinux 运行模式,默认值为:permissive(宽容模式)。

可选值:

  • disabled:完全禁用 SELinux(等同于旧版本的 node_disable_selinux: true
  • permissive:宽容模式,记录违规但不阻止(推荐,默认值)
  • enforcing:强制模式,严格执行 SELinux 策略

如果您没有专业的操作系统/安全专家,建议使用 permissivedisabled 模式。

请注意,SELinux 默认只在 EL 系列系统上启用,如果你想要在 Debian/Ubuntu 系统上启用 SELinux,请自行安装并启用 SELinux 配置。 另外,SELinux 模式的更改可能需要重启系统才能完全生效。

node_firewall_mode

参数名称: node_firewall_mode, 类型: enum, 层次:C

防火墙运行模式,默认值为:zone(启用防火墙并按分区规则管理)。 自 v4.1 起,默认值从 none 调整为 zone,即默认启用防火墙。

可选值:

  • zone:启用防火墙并配置规则:内网信任,公网只开放指定端口(默认值)。
  • off:关闭并禁用防火墙(等同于旧版本的 node_disable_firewall: true)。
  • none:不修改防火墙状态与规则,由用户完全自管。

在 EL 系统上使用 firewalld 服务,在 Debian/Ubuntu 系统上使用 ufw 服务。为保证跨发行版行为一致,Pigsty 默认采用 zone 模式:自动启用系统防火墙,内网全通,公网仅开放 node_firewall_public_port

如果您需要完全自行维护防火墙规则(例如仅依赖云安全组,或已有企业级防火墙策略),可以设置为 none 跳过 Pigsty 的防火墙管理;若要显式关闭系统防火墙,请使用 off

需要公网暴露的生产环境建议使用 zone 模式,配合 node_firewall_intranetnode_firewall_public_port 进行精细化访问控制。zone 模式会在防火墙未运行时自动启用防火墙。

node_firewall_intranet

参数名称: node_firewall_intranet, 类型: cidr[], 层次:C

内网 CIDR 地址列表(自 v4.0 版本引入),默认值为:

node_firewall_intranet:
  - 10.0.0.0/8
  - 172.16.0.0/12
  - 192.168.0.0/16

此参数定义了被视为“内部网络”的 IP 地址范围。来自这些网络的流量将被允许访问所有服务端口,而无需单独配置开放规则。

这些 CIDR 范围内的主机将被视为可信内网主机,享有更宽松的防火墙规则。同时,在 PG/PGB HBA 规则 中,这里定义的内网范围也会被视作 “内网” 对待。 由于默认防火墙模式为 zone,该列表在默认配置下即生效。

node_firewall_public_port

参数名称: node_firewall_public_port, 类型: port[], 层次:C

公网开放端口列表,默认值为:[22, 80, 443]

此参数定义了对公网(非内网 CIDR)开放的端口列表。默认开放的端口包括:

  • 22:SSH 服务端口
  • 80:HTTP 服务端口
  • 443:HTTPS 服务端口

您可以根据实际需求调整此列表。例如,如果您需要对外暴露 PostgreSQL,可以显式添加 5432

node_firewall_public_port: [22, 80, 443, 5432]

Pigsty 中 PostgreSQL 默认安全策略仅允许管理员通过公网访问数据库端口。 如果您想要让其他用户也能通过公网访问数据库,请确保在 PG/PGB HBA 规则中正确配置相应的访问权限。

如果你想要将其他服务端口对公网开放,也可以将它们添加到此列表中。 建议始终保持最小暴露原则,只开放真正需要的服务端口。

请注意,只有当 node_firewall_mode 设置为 zone 时,此参数才会生效;若设置为 noneoff 则不会应用此端口策略。


NODE_ADMIN

这一节关于主机节点上的管理员,谁能登陆,怎么登陆。

node_data: /data                  # node main data directory, `/data` by default
node_admin_enabled: true          # create a admin user on target node?
node_admin_uid: 88                # uid and gid for node admin user
node_admin_username: dba          # name of node admin user, `dba` by default
node_admin_sudo: nopass           # admin user's sudo privilege: nopass, all, limit
node_admin_ssh_exchange: true     # exchange admin ssh key among node cluster
node_admin_pk_current: true       # add current user's ssh pk to admin authorized_keys
node_admin_pk_list: []            # ssh public keys to be added to admin user
node_aliases: {}                  # shell aliases to write into `/etc/profile.d/node.alias.sh`

node_data

参数名称: node_data, 类型: path, 层次:C

节点的主数据目录,默认为 /data

如果该目录不存在,则该目录会被创建。该目录由 root:root 拥有,权限为 0755

node_admin_enabled

参数名称: node_admin_enabled, 类型: bool, 层次:C

是否在本节点上创建一个专用管理员用户?默认值为:true

Pigsty 默认会在每个节点上创建一个管理员用户(拥有免密 sudo 与 ssh 权限),默认的管理员名为 dba (uid=88) 的管理用户,可以从元节点上通过 SSH 免密访问环境中的其他节点并执行免密 sudo。

node_admin_uid

参数名称: node_admin_uid, 类型: int, 层次:C

管理员用户 UID,默认值为:88

请尽可能确保 UID 在所有节点上都相同,可以避免一些无谓的权限问题。

如果默认 UID 88 已经被占用,您可以选择一个其他 UID,手工分配时请注意 UID 命名空间冲突。

node_admin_username

参数名称: node_admin_username, 类型: username, 层次:C

管理员用户名,默认为 dba

node_admin_sudo

参数名称: node_admin_sudo, 类型: enum, 层次:C

管理员用户的 sudo 权限级别,默认值为:nopass(免密 sudo)。

可选值:

  • nopass:授予免密 sudo 权限(默认,允许执行所有命令但无需密码)
  • all:授予完整 sudo 权限(需要密码)
  • limit:授予有限的 sudo 权限(仅允许执行特定命令)

Pigsty 默认使用 nopass 模式,管理员用户可以无需密码执行任意 sudo 命令,这对于自动化运维非常方便。

在安全要求较高的生产环境中,您可能需要将此参数调整为 limitall,以限制管理员的权限范围。

node_admin_ssh_exchange

参数名称: node_admin_ssh_exchange, 类型: bool, 层次:C

在节点集群间交换节点管理员 SSH 密钥,类型:bool,层级:C,默认值为:true

启用时,Pigsty 会在执行剧本时,在成员间交换 SSH 公钥,允许管理员 node_admin_username 从不同节点上相互访问。

node_admin_pk_current

参数名称: node_admin_pk_current, 类型: bool, 层次:C

是否将当前节点 & 用户的公钥加入管理员账户,默认值是: true

启用时,将会把当前节点上执行此剧本的管理用户的 SSH 公钥(~/.ssh/id_rsa.pub)拷贝至目标节点管理员用户的 authorized_keys 中。

生产环境部署时,请务必注意此参数,此参数会将当前执行命令用户的默认公钥安装至所有机器的管理用户上。

node_admin_pk_list

参数名称: node_admin_pk_list, 类型: string[], 层次:C

可登陆管理员的公钥列表,默认值为:[] 空数组。

数组的每一个元素为字符串,内容为写入到管理员用户 ~/.ssh/authorized_keys 中的公钥,持有对应私钥的用户可以以管理员身份登录。

生产环境部署时,请务必注意此参数,仅将信任的密钥加入此列表中。

node_aliases

参数名称: node_aliases, 类型: dict, 层次:C

用于写入主机 /etc/profile.d/node.alias.sh 的 shell 别名,默认值为:{} 空字典。

此参数允许您为主机的 shell 环境配置方便使用的 alias,此处定义的 K:V 字典将以 alias k=v 的形式写入到目标节点的 profile.d 文件中生效。

例如,以下命令声明了一个名为 dp 的别名,用于快速执行 docker compose pull 命令:

node_aliases:
  dp: 'docker compose pull'

NODE_TIME

关于主机时间/时区/NTP/定时任务的相关配置。

时间同步对于数据库服务来说非常重要,请确保系统 chronyd 授时服务正常运行。

node_timezone: ''                 # 设置节点时区,空字符串表示跳过
node_ntp_enabled: true            # 启用chronyd时间同步服务?
node_ntp_servers:                 # `/etc/chrony.conf`中的ntp服务器
  - pool pool.ntp.org iburst
node_crontab_overwrite: true      # 覆盖还是追加到`/etc/crontab`?
node_crontab: [ ]                 # `/etc/crontab`中的crontab条目

node_timezone

参数名称: node_timezone, 类型: string, 层次:C

设置节点时区,空字符串表示跳过。默认值是空字符串,默认不会修改默认的时区(即使用通常的默认值 UTC)

在中国地区使用时,建议设置为 Asia/Hong_Kong / Asia/ShangHai

node_ntp_enabled

参数名称: node_ntp_enabled, 类型: bool, 层次:C

启用 chronyd 时间同步服务?默认值为:true

此时 Pigsty 将使用 node_ntp_servers 中指定的 NTP 服务器列表覆盖节点的 /etc/chrony.conf

如果您的节点已经配置好了 NTP 服务器,那么可以将此参数设置为 false 跳过时间同步配置。

node_ntp_servers

参数名称: node_ntp_servers, 类型: string[], 层次:C

/etc/chrony.conf 中使用的 NTP 服务器列表。默认值为:["pool pool.ntp.org iburst"]

本参数是一个数组,每一个数组元素是一个字符串,代表一行 NTP 服务器配置。仅当 node_ntp_enabled 启用时生效。

Pigsty 默认使用全球 NTP 服务器 pool.ntp.org,您可以根据自己的网络环境修改此参数,例如 cn.pool.ntp.org iburst,或内网的时钟服务。

您也可以在配置中使用 ${admin_ip} 占位符,使用管理节点上的时间服务器。

node_ntp_servers: [ 'pool ${admin_ip} iburst' ]

node_crontab_overwrite

参数名称: node_crontab_overwrite, 类型: bool, 层次:C

处理 node_crontab 中的定时任务时,是追加还是覆盖?默认值为:true,即覆盖。

如果您希望在节点上追加定时任务,可以将此参数设置为 false,Pigsty 将会在节点的 crontab 上 追加,而非 覆盖所有 定时任务。

node_crontab

参数名称: node_crontab, 类型: string[], 层次:C

定义在节点 /etc/crontab 中的定时任务:默认值为:[] 空数组。

每一个数组元素都是一个字符串,代表一行定时任务。使用标准的系统 crontab 格式:分 时 日 月 周 用户 命令

node_crontab:
  - '00 03 * * * root /usr/bin/some-system-task'

注意:对于 PostgreSQL 备份等 postgres 用户的定时任务,请使用 pg_crontab 参数, 而非 node_crontab。因为 node_crontab 在 NODE 初始化阶段写入 /etc/crontab,此时 postgres 用户可能尚未创建, 会导致 cron 报错 bad username 并忽略整个 crontab 文件。

node_crontab_overwritetrue(默认)时,移除节点时会恢复默认的 /etc/crontab


NODE_VIP

您可以为节点集群绑定一个可选的 L2 VIP,默认不启用此特性。L2 VIP 只对一组节点集群有意义,该 VIP 会根据配置的优先级在集群中的节点之间进行切换,确保节点服务的高可用。

请注意,L2 VIP 只能 在同一 L2 网段中使用,这可能会对您的网络拓扑产生额外的限制,如果不想受此限制,您可以考虑使用 DNS LB 或者 Haproxy 实现类似的功能。

当启用此功能时,您需要为这个 L2 VIP 显式分配可用的 vip_addressvip_vrid,用户应当确保这两者在同一网段内唯一。

请注意,NODE VIP 与 PG VIP 不同,PG VIP 是为 PostgreSQL 实例服务的 VIP,由 vip-manager 组件管理并绑定在 PG 集群主库上。 而 NODE VIP 由 Keepalived 组件管理,绑定在节点集群上。可以是主备模式,也可以是负载均衡模式,两者可以并存。

vip_enabled: false                # enable vip on this node cluster?
# vip_address:         [IDENTITY] # node vip address in ipv4 format, required if vip is enabled
# vip_vrid:            [IDENTITY] # required, integer, 1-254, should be unique among same VLAN
vip_role: backup                  # optional, `master/backup`, backup by default, use as init role
vip_preempt: false                # optional, `true/false`, false by default, enable vip preemption
vip_interface: auto               # node vip network interface to listen, `auto` by default
vip_dns_suffix: ''                # node vip dns name suffix, empty string by default
vip_auth_pass: ''                 # vrrp auth password, empty to use `<cls>-<vrid>` as default
vip_exporter_port: 9650           # keepalived exporter listen port, 9650 by default

vip_enabled

参数名称: vip_enabled, 类型: bool, 层次:C

是否在当前这个节点集群中配置一个由 Keepalived 管理的 L2 VIP? 默认值为: false

vip_address

参数名称: vip_address, 类型: ip, 层次:C

节点 VIP 地址,IPv4 格式(不带 CIDR 网段后缀),当节点启用 vip_enabled 时,这是一个必选参数。

本参数没有默认值,这意味着您必须显式地为节点集群分配一个唯一的 VIP 地址。

vip_vrid

参数名称: vip_vrid, 类型: int, 层次:C

VRID 是一个范围从 1254 的正整数,用于标识一个网络中的 VIP,当节点启用 vip_enabled 时,这是一个必选参数。

本参数没有默认值,这意味着您必须显式地为节点集群分配一个网段内唯一的 ID。

vip_role

参数名称: vip_role, 类型: enum, 层次:I

节点 VIP 角色,可选值为: masterbackup,默认值为 backup

该参数的值会被设置为 keepalived 的初始状态。

vip_preempt

参数名称: vip_preempt, 类型: bool, 层次:C/I

是否启用 VIP 抢占?可选参数,默认值为 false,即不抢占 VIP。

所谓抢占,是指一个 backup 角色的节点,当其优先级高于当前存活且正常工作的 master 角色的节点时,是否取抢占其 VIP?

vip_interface

参数名称: vip_interface, 类型: string, 层次:C/I

节点 VIP 监听使用的网卡,默认为 auto。Pigsty 会根据 inventory 中的节点 IP 自动探测对应网卡。

您应当使用与节点主 IP 地址(即:你填入清单中 IP 地址)所使用网卡相同的名称。

自动探测不适用于非标准路由、策略路由等特殊网络环境时,可以在实例/节点层次显式覆盖网卡名称。

vip_dns_suffix

参数名称: vip_dns_suffix, 类型: string, 层次:C/I

节点集群 L2 VIP 使用的 DNS 名称,默认是空字符串,即直接使用集群名本身作为 DNS 名。

vip_auth_pass

参数名称: vip_auth_pass, 类型: password, 层次:C

VRRP 认证密码,用于 keepalived VRRP 协议认证。默认为空字符串。

当为空时,Pigsty 会自动使用 <cluster_name>-<vrid> 模式生成密码。 在有安全要求的生产环境中,建议设置一个显式的强密码。

vip_exporter_port

参数名称: vip_exporter_port, 类型: port, 层次:C/I

keepalived exporter 监听端口号,默认为:9650


HAPROXY

HAProxy 默认在所有节点上安装启用,并以类似于 Kubernetes NodePort 的方式对外暴露服务。

PGSQL 模块对外 服务 使用到了 Haproxy。

haproxy_enabled: true             # 在此节点上启用haproxy?
haproxy_clean: false              # 清理所有现有的haproxy配置?
haproxy_reload: true              # 配置后重新加载haproxy?
haproxy_auth_enabled: true        # 为haproxy管理页面启用身份验证
haproxy_admin_username: admin     # haproxy管理用户名,默认为`admin`
haproxy_admin_password: pigsty    # haproxy管理密码,默认为`pigsty`
haproxy_exporter_port: 9101       # haproxy管理/导出端口,默认为9101
haproxy_client_timeout: 24h       # 客户端连接超时,默认为24小时
haproxy_server_timeout: 24h       # 服务器端连接超时,默认为24小时
haproxy_services: []              # 需要在节点上暴露的haproxy服务列表

haproxy_enabled

参数名称: haproxy_enabled, 类型: bool, 层次:C

在此节点上启用 haproxy?默认值为: true

haproxy_clean

参数名称: haproxy_clean, 类型: bool, 层次:G/C/A

清理所有现有的 haproxy 配置?默认值为 false

haproxy_reload

参数名称: haproxy_reload, 类型: bool, 层次:A

配置后重新加载 haproxy?默认值为 true,配置更改后会重新加载 haproxy。

如果您希望在应用配置前进行手工检查,您可以使用命令参数关闭此选项,并进行检查后再应用。

haproxy_auth_enabled

参数名称: haproxy_auth_enabled, 类型: bool, 层次:G

为 haproxy 管理页面启用身份验证,默认值为 true,它将要求管理页面进行 http 基本身份验证。

建议不要禁用认证,因为您的流量控制页面将对外暴露,这是比较危险的。

haproxy_admin_username

参数名称: haproxy_admin_username, 类型: username, 层次:G

haproxy 管理员用户名,默认为:admin

haproxy_admin_password

参数名称: haproxy_admin_password, 类型: password, 层次:G

haproxy 管理密码,默认为 pigsty

在生产环境中请务必修改此密码!

haproxy_exporter_port

参数名称: haproxy_exporter_port, 类型: port, 层次:C

haproxy 流量管理/指标对外暴露的端口,默认为:9101

haproxy_client_timeout

参数名称: haproxy_client_timeout, 类型: interval, 层次:C

客户端连接超时,默认为 24h

设置一个超时可以避免难以清理的超长的连接,但如果您真的需要一个长连接,您可以将其设置为更长的时间。

haproxy_server_timeout

参数名称: haproxy_server_timeout, 类型: interval, 层次:C

服务端连接超时,默认为 24h

设置一个超时可以避免难以清理的超长的连接,但如果您真的需要一个长连接,您可以将其设置为更长的时间。

haproxy_services

参数名称: haproxy_services, 类型: service[], 层次:C

需要在此节点上通过 Haproxy 对外暴露的服务列表,默认值为: [] 空数组。

每一个数组元素都是一个服务定义,下面是一个服务定义的例子:

haproxy_services:                   # list of haproxy service

  # expose pg-test read only replicas
  - name: pg-test-ro                # [REQUIRED] service name, unique
    port: 5440                      # [REQUIRED] service port, unique
    ip: "*"                         # [OPTIONAL] service listen addr, "*" by default
    protocol: tcp                   # [OPTIONAL] service protocol, 'tcp' by default
    balance: leastconn              # [OPTIONAL] load balance algorithm, roundrobin by default (or leastconn)
    maxconn: 20000                  # [OPTIONAL] max allowed front-end connection, 20000 by default
    default: 'inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100'
    options:
      - option httpchk
      - option http-keep-alive
      - http-check send meth OPTIONS uri /read-only
      - http-check expect status 200
    servers:
      - { name: pg-test-1 ,ip: 10.10.10.11 , port: 5432 , options: check port 8008 , backup: true }
      - { name: pg-test-2 ,ip: 10.10.10.12 , port: 5432 , options: check port 8008 }
      - { name: pg-test-3 ,ip: 10.10.10.13 , port: 5432 , options: check port 8008 }

每个服务定义会被渲染为 /etc/haproxy/conf.d/<service.name>.cfg 配置文件,并在 HAProxy 重载后生效;主配置固定为 /etc/haproxy/haproxy.cfg

Pigsty 将 HAProxy 单元写入 /etc/systemd/system/haproxy.service。可选的环境文件为 /etc/default/haproxy,其中仅识别 EXTRAOPTS;不要在这里重复传入 -f,否则会与单元中固定的主配置和配置目录冲突。若覆盖 EXTRAOPTS,请保留默认的 -S /run/haproxy-master.sock,以免破坏无缝重载;修改后需要重启服务才能生效。


NODE_EXPORTER

node_exporter_enabled: true       # setup node_exporter on this node?
node_exporter_port: 9100          # node exporter listen port, 9100 by default
node_exporter_options: '--no-collector.softnet --no-collector.nvme --collector.tcpstat --collector.processes'

node_exporter_enabled

参数名称: node_exporter_enabled, 类型: bool, 层次:C

在当前节点上启用节点指标收集器?默认启用:true

node_exporter_port

参数名称: node_exporter_port, 类型: port, 层次:C

对外暴露节点指标使用的端口,默认为 9100

node_exporter_options

参数名称: node_exporter_options, 类型: arg, 层次:C

节点指标采集器的命令行参数,默认值为:

--no-collector.softnet --no-collector.nvme --collector.tcpstat --collector.processes

该选项会启用/禁用一些指标收集器,请根据您的需要进行调整。


VECTOR

Vector 是 Pigsty 自 v4 起使用的日志收集组件,会收集各个模块产生的日志并发送至基础设施节点上的 VictoriaLogs 服务。

  • INFRA: 基础设施组件的日志只会在 Infra 节点上收集。

    • nginx-access: /var/log/nginx/access.log
    • nginx-error: /var/log/nginx/error.log
    • grafana: /var/log/grafana/grafana.log
  • NODES:主机相关日志,所有节点上都会启用收集。

    • 通过 journald 统一采集系统服务日志(job=syslog),不依赖固定的 /var/log/* 文件路径。
  • PGSQL:PostgreSQL 相关的日志,只有节点配置了 PGSQL 模块才会启用收集。

    • postgres: /pg/log/postgres/*
    • patroni: /pg/log/patroni/patroni.logjob=patroni
    • pgbouncer: /pg/log/pgbouncer/pgbouncer.log
    • pgbackrest: /pg/log/pgbackrest/*.log
  • REDIS:Redis 相关日志,只有节点配置了 REDIS 模块才会启用收集。

    • redis: /var/log/redis/*.log

日志目录会根据这些参数的配置自动调整:pg_log_dir, patroni_log_dir, pgbouncer_log_dir, pgbackrest_log_dir

vector_enabled: true              # 启用 vector 日志收集器吗?
vector_clean: false               # 初始化时清除 vector 数据目录吗?
vector_data: /data/vector         # vector 数据目录,默认为 /data/vector
vector_port: 9598                 # vector 指标端口,默认为 9598
vector_read_from: beginning       # vector 从头还是从尾开始读取日志
vector_log_endpoint: [ infra ]    # 日志发送目标端点,默认发送至 infra 组

vector_enabled

参数名称: vector_enabled, 类型: bool, 层次:C

是否启用 Vector 日志收集服务?默认值为: true

Vector 是 Pigsty 自 v4 起使用的日志收集代理,替代了之前版本使用的 Promtail,用于收集节点和服务的日志并发送至 VictoriaLogs。

vector_clean

参数名称: vector_clean, 类型: bool, 层次:G/A

是否在安装 Vector 时清除已有数据目录?默认值为: false

默认不会清理,当您选择清理时,Pigsty 会在部署 Vector 时移除现有数据目录 vector_data,这意味着 Vector 会重新收集当前节点上的所有日志并发送至 VictoriaLogs。

vector_data

参数名称: vector_data, 类型: path, 层次:C

Vector 数据目录路径,默认值为:/data/vector

Vector 会将日志读取的偏移量和缓冲数据存储在此目录中。

vector_port

参数名称: vector_port, 类型: port, 层次:C

Vector 指标监听端口号,默认为:9598

此端口用于暴露 Vector 自身的监控指标,可被 VictoriaMetrics 抓取。

vector_read_from

参数名称: vector_read_from, 类型: enum, 层次:C

Vector 日志读取起始位置,默认值为:beginning

可选值为 beginning(从头开始)或 end(从尾开始)。beginning 会读取现有日志文件的全部内容,end 只读取新产生的日志。

vector_log_endpoint

参数名称: vector_log_endpoint, 类型: string[], 层次:C

日志发送目标端点列表,默认值为:[ infra ]

指定将日志发送至哪个节点组的 VictoriaLogs 服务。默认发送至 infra 组的节点。

10.3 - 预置剧本

如何使用预置的 ansible 剧本来管理 Node 集群,常用管理命令速查。

Pigsty 提供两个与 NODE 模块相关的剧本:

  • node.yml:纳管节点,调整节点到期望状态
  • node-rm.yml:从 Pigsty 中移除纳管节点

另提供两个包装命令工具:bin/node-addbin/node-rm,用于快速调用剧本。


node.yml

向 Pigsty 添加节点的 node.yml 包含以下子任务:

node-id       :生成节点身份标识
node_name     :设置主机名
node_hosts    :配置 /etc/hosts 记录
node_resolv   :配置 DNS 解析器 /etc/resolv.conf
node_firewall :设置防火墙 & selinux
node_ca       :添加并信任CA证书
node_repo     :添加上游软件仓库
node_pkg      :安装 rpm/deb 软件包
node_uv       :配置 uv Python 虚拟环境
node_feature  :配置 numa、grub、静态网络等特性
node_kernel   :配置操作系统内核模块
node_tune     :配置 tuned 调优模板
node_sysctl   :设置额外的 sysctl 参数
node_profile  :写入 /etc/profile.d/node.sh
node_alias    :写入 /etc/profile.d/node.alias.sh
node_ulimit   :配置资源限制
node_data     :配置数据目录
node_admin    :配置管理员用户和ssh密钥
node_timezone :配置时区
node_ntp      :配置 NTP 服务器/客户端
node_crontab  :添加/覆盖 crontab 定时任务
node_vip      :为节点集群设置可选的 L2 VIP
haproxy       :在节点上设置 haproxy 以暴露服务
monitor       :配置节点监控:node_exporter & vector

node-rm.yml

从 Pigsty 中移除节点的剧本 node-rm.yml 包含以下子任务:

node_deregister   : 移除节点注册信息(VictoriaMetrics / Vector / DNS)
  - rm_metrics    : 移除已注册的 VictoriaMetrics 监控目标
  - rm_logs       : 移除已注册的 Vector 日志采集配置
  - rm_dns        : 移除已注册的 Node VIP DNS 解析记录
haproxy_deregister: 移除用于 haproxy 管理界面的 nginx 代理记录
  - rm_proxy      : 移除 nginx upstream/location 记录
vip            : 移除节点的 keepalived 与 L2 VIP(如果启用 VIP)
haproxy        : 移除 haproxy 负载均衡器
node_exporter  : 移除节点监控:Node Exporter
vip_exporter   : 移除 keepalived_exporter (如果启用 VIP)
vector         : 移除日志收集代理 vector
node_crontab   : 恢复默认 /etc/crontab(当 node_crontab_overwrite=true 时)
profile        : 移除 /etc/profile.d/node.sh 环境配置文件

node-rm.yml 的作用是解除 Pigsty 纳管并停止 NODE 相关服务,并不是操作系统销毁或完整卸载:

  • 会注销 Node、Docker、Ping、VIP 等监控目标以及 HAProxy 管理入口;
  • 会停止并禁用 HAProxy、Node Exporter、Vector,以及启用时的 Keepalived/Exporter;
  • 会删除 HAProxy 配置、Node 的 Vector 配置,并删除 vector_data(默认 /data/vector);
  • 不会卸载软件包、删除管理员用户、删除 node_data,也不会停止 Docker 服务或删除 Docker 数据。

当前移除角色会直接删除 vector_data,并未使用安装角色中的 vector_clean 开关;执行前应确认其中没有需要保留的 Vector 缓冲数据。


常用命令速查

# 基础节点管理
./node.yml -l <cls|ip|group>          # 向 Pigsty 中添加节点
./node-rm.yml -l <cls|ip|group>       # 从 Pigsty 中移除节点

# 节点管理快捷命令
bin/node-add node-test                 # 初始化节点集群 'node-test'
bin/node-add 10.10.10.10               # 初始化节点 '10.10.10.10'
bin/node-rm node-test                  # 移除节点集群 'node-test'
bin/node-rm 10.10.10.10                # 移除节点 '10.10.10.10'

# 节点主体初始化
./node.yml -t node                     # 完成节点主体初始化(haproxy,监控除外)
./node.yml -t haproxy                  # 在节点上设置 haproxy
./node.yml -t monitor                  # 配置节点监控:node_exporter & vector

# VIP 管理
./node.yml -t node_vip                 # 为节点集群设置可选的 L2 VIP
./node.yml -t vip_config,vip_reload    # 刷新节点 L2 VIP 配置

# HAProxy 管理
./node.yml -t haproxy_config,haproxy_reload   # 刷新节点上的服务定义

# 注册管理
./node.yml -t node_register            # 重新将节点注册到 VictoriaMetrics 中
./node.yml -t register_nginx           # 重新将节点 haproxy 管控界面注册到 Nginx 中

# 具体任务
./node.yml -t node-id                  # 生成节点身份标识
./node.yml -t node_name                # 设置主机名
./node.yml -t node_hosts               # 配置节点 /etc/hosts 记录
./node.yml -t node_resolv              # 配置节点 DNS 解析器 /etc/resolv.conf
./node.yml -t node_firewall            # 配置防火墙 & selinux
./node.yml -t node_ca                  # 配置节点的CA证书
./node.yml -t node_repo                # 配置节点上游软件仓库
./node.yml -t node_pkg                 # 在节点上安装 yum 软件包
./node.yml -t node_uv                  # 配置 uv Python 虚拟环境
./node.yml -t node_feature             # 配置 numa、grub、静态网络等特性
./node.yml -t node_kernel              # 配置操作系统内核模块
./node.yml -t node_tune                # 配置 tuned 调优模板
./node.yml -t node_sysctl              # 设置额外的 sysctl 参数
./node.yml -t node_profile             # 配置节点环境变量:/etc/profile.d/node.sh
./node.yml -t node_alias               # 配置节点命令别名:/etc/profile.d/node.alias.sh
./node.yml -t node_ulimit              # 配置节点资源限制
./node.yml -t node_data                # 配置节点首要数据目录
./node.yml -t node_admin               # 配置管理员用户和ssh密钥
./node.yml -t node_timezone            # 配置节点时区
./node.yml -t node_ntp                 # 配置节点 NTP 服务器/客户端
./node.yml -t node_crontab             # 添加/覆盖 crontab 定时任务

10.4 - 管理预案

Node 集群管理 SOP:创建,销毁,扩容,缩容,节点故障与磁盘故障的处理。

下面是 Node 模块中常用的管理操作:

更多问题请参考 FAQ:NODE


添加节点

要将节点添加到 Pigsty,您需要对该节点具有无密码的 ssh/sudo 访问权限。

您也可以选择一次性添加一个集群,或使用通配符匹配配置清单中要加入 Pigsty 的节点。

# ./node.yml -l <cls|ip|group>        # 向 Pigsty 中添加节点的实际剧本
# bin/node-add <selector|ip...>       # 向 Pigsty 中添加节点
bin/node-add node-test                # 初始化节点集群 'node-test'
bin/node-add 10.10.10.10              # 初始化节点 '10.10.10.10'

示例:将 PG 集群 pg-test 的三个节点纳入 Pigsty 管理

demo/node-add.cast

移除节点

要从 Pigsty 中移除一个节点,您可以使用以下命令:

先确认目标节点上所有业务模块都已按各自流程移除,并检查需要保留的 vector_data 缓冲。 确认精确目标后调用脚本:

# ./node-rm.yml -l <cls|ip|group>    # 从 Pigsty 中移除节点的实际剧本
# bin/node-rm <cls|ip|selector> ...  # 从 pigsty 中移除节点
bin/node-rm node-test                # 移除节点集群 'node-test'
bin/node-rm 10.10.10.10              # 移除节点 '10.10.10.10'

您也可以选择一次性移除一个集群,或使用通配符匹配配置清单中要从 Pigsty 移除的节点。

这里的“移除节点”是解除 NODE 纳管:剧本会注销监控/日志/HAProxy 入口,停止 NODE Exporter、Vector、HAProxy 及可选 VIP 服务,并删除 vector_data(默认 /data/vector)。 它不会卸载软件包、删除管理员用户或 node_data,也不会停止 Docker 服务或删除 Docker 数据。详细边界参阅 node-rm.yml

demo/node-rm.cast

创建管理员

如果当前用户没有对节点的无密码 ssh/sudo 访问权限,您可以使用另一个管理员用户来初始化该节点:

node.yml -t node_admin -k -K -e ansible_user=<另一个管理员>   # 为另一个管理员输入 ssh/sudo 密码以完成此任务

绑定VIP

您可以在节点集群上绑定一个可选的 L2 VIP,使用 vip_enabled 参数。

proxy:
  hosts:
    10.10.10.29: { nodename: proxy-1 }   # 您可以显式指定初始的 VIP 角色:MASTER / BACKUP
    10.10.10.30: { nodename: proxy-2 }   # , vip_role: master }
  vars:
    node_cluster: proxy
    vip_enabled: true
    vip_vrid: 128
    vip_address: 10.10.10.99
    vip_interface: eth1
./node.yml -l proxy -t node_vip     # 首次启用 VIP
./node.yml -l proxy -t vip_refresh  # 刷新 vip 配置(例如指定 master)

添加节点监控

如果您想要在现有节点上添加或重新配置监控,可以使用以下命令:

./node.yml -t node_exporter,node_register  # 配置监控并注册
./node.yml -t vector                        # 配置日志收集

其他常见任务

# Play
./node.yml -t node                            # 完成节点主体初始化(haproxy,监控除外)
./node.yml -t haproxy                         # 在节点上设置 haproxy
./node.yml -t monitor                         # 配置节点监控:node_exporter & vector
./node.yml -t node_vip                        # 为没启用过 VIP 的集群安装、配置、启用 L2 VIP
./node.yml -t vip_config,vip_reload           # 刷新节点 L2 VIP 配置
./node.yml -t haproxy_config,haproxy_reload   # 刷新节点上的服务定义
./node.yml -t node_register                   # 重新将节点注册到 VictoriaMetrics 中
./node.yml -t register_nginx                  # 重新将节点 haproxy 管控界面注册到 Nginx 中

# Task
./node.yml -t node-id        # 生成节点身份标识
./node.yml -t node_name      # 设置主机名
./node.yml -t node_hosts     # 配置节点 /etc/hosts 记录
./node.yml -t node_resolv    # 配置节点 DNS 解析器 /etc/resolv.conf
./node.yml -t node_firewall  # 配置防火墙 & selinux
./node.yml -t node_ca        # 配置节点的CA证书
./node.yml -t node_repo      # 配置节点上游软件仓库
./node.yml -t node_pkg       # 在节点上安装 yum 软件包
./node.yml -t node_feature   # 配置 numa、grub、静态网络等特性
./node.yml -t node_kernel    # 配置操作系统内核模块
./node.yml -t node_tune      # 配置 tuned 调优模板
./node.yml -t node_sysctl    # 设置额外的 sysctl 参数
./node.yml -t node_profile   # 配置节点环境变量:/etc/profile.d/node.sh
./node.yml -t node_alias     # 配置节点命令别名:/etc/profile.d/node.alias.sh
./node.yml -t node_ulimit    # 配置节点资源限制
./node.yml -t node_data      # 配置节点首要数据目录
./node.yml -t node_admin     # 配置管理员用户和ssh密钥
./node.yml -t node_timezone  # 配置节点时区
./node.yml -t node_ntp       # 配置节点 NTP 服务器/客户端
./node.yml -t node_crontab   # 添加/覆盖 crontab 定时任务
./node.yml -t node_vip       # 为节点集群设置可选的 L2 VIP

管理 HAProxy 密码

haproxy_admin_password(默认 pigsty)用于 HAProxy 管理界面认证,渲染到 /etc/haproxy/haproxy.cfg 中。

修改密码后,使用以下命令刷新配置(热重载,不中断连接):

./node.yml -l <目标节点> -t haproxy_config,haproxy_reload

防火墙管理

Pigsty 使用 node_firewall_mode 控制防火墙行为。 在 RHEL/Rocky 系统上使用 firewalld,在 Debian/Ubuntu 系统上使用 ufw

自 v4.1 起,默认情况下这个参数是 zone:Pigsty 会在各发行版上统一启用系统防火墙,并应用“内网信任、公网最小暴露”的规则。 在 zone 模式下,内网流量不受防火墙限制,但非内网网段只能访问特定端口。 如果你希望完全自行维护防火墙,请将该参数设置为 none(Pigsty 不再管理防火墙状态与规则)。 如果您在云服务器上部署并对互联网开放,这一点尤为重要。

我们建议你只开放必要的端口,例如:22 (SSH), 80/443 (HTTP/HTTPS),这三个是必要的端口,谨慎对外开放 5432 数据库端口。

应用防火墙规则

默认就是 zone。如果之前设置过 none/off,可以改回 zone 以重新启用并应用分区规则:

node_firewall_mode: zone              # 启用防火墙并配置区域规则
node_firewall_intranet:               # 信任这些网段(完全放行)
  - 10.0.0.0/8
  - 192.168.0.0/16
  - 172.16.0.0/12
node_firewall_public_port:            # 对公网开放这些端口
  - 22                                # SSH
  - 80                                # HTTP
  - 443                               # HTTPS

然后执行:./node.yml -l <目标> -t node_firewall

开放更多端口

要开放更多端口,将其添加到 node_firewall_public_port 并重新执行:

node_firewall_public_port: [22, 80, 443, 5432, 6379]  # 添加 PostgreSQL 和 Redis 端口
./node.yml -l <目标> -t node_firewall

配置内网网段

node_firewall_intranet 中的网段会被添加到 trusted 区域,拥有完全访问权限:

node_firewall_intranet:
  - 10.0.0.0/8           # A 类私网
  - 192.168.0.0/16       # C 类私网
  - 172.16.0.0/12        # B 类私网
  - 100.64.0.0/10        # 运营商级 NAT(如需要)

删除规则(手动)

重要提示:Pigsty 的防火墙管理是 只增不删 的。从配置中移除条目并重新执行 不会 删除已存在的规则。您需要手动删除规则。

EL (firewalld)
# 从 public 区域删除指定端口
sudo firewall-cmd --zone=public --remove-port=5432/tcp
sudo firewall-cmd --runtime-to-permanent

# 从 trusted 区域删除指定网段
sudo firewall-cmd --zone=trusted --remove-source=10.0.0.0/8
sudo firewall-cmd --runtime-to-permanent

# 查看当前规则
sudo firewall-cmd --zone=public --list-ports
sudo firewall-cmd --zone=trusted --list-sources

# 重置为初始状态(删除所有自定义规则)
sudo firewall-cmd --complete-reload
Debian (ufw)
# 删除指定端口规则
sudo ufw delete allow 5432/tcp

# 删除指定网段规则
sudo ufw delete allow from 10.0.0.0/8

# 查看当前规则(带编号)
sudo ufw status numbered

# 按编号删除规则
sudo ufw delete <规则编号>

# 重置为初始状态(删除所有规则,保持 ufw 启用状态)
sudo ufw reset

关闭防火墙

要完全关闭防火墙,将 node_firewall_mode 设置为 off

node_firewall_mode: off    # 完全禁用防火墙
./node.yml -l <目标> -t node_firewall

或者手动关闭:

EL (firewalld)
sudo systemctl disable --now firewalld
Debian (ufw)
sudo ufw disable

10.5 - 监控告警

如何在 Pigsty 中监控 Node?如何使用 Node 本身的管控面板?有哪些告警规则值得关注?

Pigsty 当前在 NODE 仪表盘目录中提供 10 个监控面板和完善的告警规则。


监控面板

NODE 仪表盘目录当前包含 10 个监控仪表板;其中 JuiceFS 与 Claude Code 面板只有在部署并产生相应指标后才会有数据。

NODE Overview

展示当前环境所有主机节点的总体情况概览。

node-overview.jpg

NODE Cluster

显示特定主机集群的详细监控数据。

node-cluster.jpg

Node Instance

呈现单个主机节点的详细监控信息。

node-instance.jpg

NODE Alert

集中展示环境中所有主机的告警信息。

node-alert.jpg

NODE VIP

监控 L2 虚拟 IP 的详细状态。

node-vip.jpg

Node Haproxy

追踪 HAProxy 负载均衡器的运行情况。

node-haproxy.jpg

Node Disk

聚焦单盘 I/O 延迟、吞吐与队列深度等存储指标。

node-disk.webp

Node Vector

查看 Vector 采集与转发状态,以及日志管道健康度。

node-vector.webp

Node JuiceFS

查看 JuiceFS 客户端的缓存、对象存储、元数据操作与读写性能。

打开 Node JuiceFS Dashboard

Claude Code

查看 Claude Code 通过 OpenTelemetry 上报的会话、Token、成本与日志数据。

打开 Claude Code Dashboard


告警规则

Pigsty 针对 NODE 实现了以下告警规则:

可用性告警

规则 级别 说明
NodeDown CRIT 节点离线
HaproxyDown CRIT HAProxy 服务离线
VectorDown WARN 日志收集代理离线(Vector)
DockerDown WARN 容器引擎离线
KeepalivedDown WARN Keepalived 守护进程离线

CPU 告警

规则 级别 说明
NodeCpuHigh WARN CPU 使用率超过 70%

调度告警

规则 级别 说明
NodeLoadHigh WARN 标准化负载超过 100%

内存告警

规则 级别 说明
NodeOutOfMem WARN 可用内存少于 10%
NodeMemSwapped WARN Swap 使用率超过 1%

文件系统告警

规则 级别 说明
NodeFsSpaceFull WARN 磁盘使用率超过 90%
NodeFsFilesFull WARN Inode 使用率超过 90%
NodeFdFull WARN 文件描述符使用率超过 90%

磁盘告警

规则 级别 说明
NodeDiskSlow INFO 读写延迟超过 32ms

网络协议告警

规则 级别 说明
NodeTcpErrHigh WARN TCP 错误率超过 1/分钟
NodeTcpRetransHigh INFO TCP 重传率超过 1%

时间同步告警

规则 级别 说明
NodeTimeDrift WARN 系统时间未同步

10.6 - 指标列表

Pigsty NODE 模块提供的完整监控指标列表与释义

本页快照记录 NODE 模块的 727 类监控指标;实际运行时的指标集合会随软件包版本、启用的采集器和目标状态变化。

Metric Name Type Labels Description
ALERTS Unknown alertname, ip, level, severity, ins, job, alertstate, category, instance, cls N/A
ALERTS_FOR_STATE Unknown alertname, ip, level, severity, ins, job, category, instance, cls N/A
deprecated_flags_inuse_total Unknown instance, ins, job, ip, cls N/A
go_gc_duration_seconds summary quantile, instance, ins, job, ip, cls A summary of the pause duration of garbage collection cycles.
go_gc_duration_seconds_count Unknown instance, ins, job, ip, cls N/A
go_gc_duration_seconds_sum Unknown instance, ins, job, ip, cls N/A
go_goroutines gauge instance, ins, job, ip, cls Number of goroutines that currently exist.
go_info gauge version, instance, ins, job, ip, cls Information about the Go environment.
go_memstats_alloc_bytes gauge instance, ins, job, ip, cls Number of bytes allocated and still in use.
go_memstats_alloc_bytes_total counter instance, ins, job, ip, cls Total number of bytes allocated, even if freed.
go_memstats_buck_hash_sys_bytes gauge instance, ins, job, ip, cls Number of bytes used by the profiling bucket hash table.
go_memstats_frees_total counter instance, ins, job, ip, cls Total number of frees.
go_memstats_gc_sys_bytes gauge instance, ins, job, ip, cls Number of bytes used for garbage collection system metadata.
go_memstats_heap_alloc_bytes gauge instance, ins, job, ip, cls Number of heap bytes allocated and still in use.
go_memstats_heap_idle_bytes gauge instance, ins, job, ip, cls Number of heap bytes waiting to be used.
go_memstats_heap_inuse_bytes gauge instance, ins, job, ip, cls Number of heap bytes that are in use.
go_memstats_heap_objects gauge instance, ins, job, ip, cls Number of allocated objects.
go_memstats_heap_released_bytes gauge instance, ins, job, ip, cls Number of heap bytes released to OS.
go_memstats_heap_sys_bytes gauge instance, ins, job, ip, cls Number of heap bytes obtained from system.
go_memstats_last_gc_time_seconds gauge instance, ins, job, ip, cls Number of seconds since 1970 of last garbage collection.
go_memstats_lookups_total counter instance, ins, job, ip, cls Total number of pointer lookups.
go_memstats_mallocs_total counter instance, ins, job, ip, cls Total number of mallocs.
go_memstats_mcache_inuse_bytes gauge instance, ins, job, ip, cls Number of bytes in use by mcache structures.
go_memstats_mcache_sys_bytes gauge instance, ins, job, ip, cls Number of bytes used for mcache structures obtained from system.
go_memstats_mspan_inuse_bytes gauge instance, ins, job, ip, cls Number of bytes in use by mspan structures.
go_memstats_mspan_sys_bytes gauge instance, ins, job, ip, cls Number of bytes used for mspan structures obtained from system.
go_memstats_next_gc_bytes gauge instance, ins, job, ip, cls Number of heap bytes when next garbage collection will take place.
go_memstats_other_sys_bytes gauge instance, ins, job, ip, cls Number of bytes used for other system allocations.
go_memstats_stack_inuse_bytes gauge instance, ins, job, ip, cls Number of bytes in use by the stack allocator.
go_memstats_stack_sys_bytes gauge instance, ins, job, ip, cls Number of bytes obtained from system for stack allocator.
go_memstats_sys_bytes gauge instance, ins, job, ip, cls Number of bytes obtained from system.
go_threads gauge instance, ins, job, ip, cls Number of OS threads created.
haproxy:cls:usage Unknown job, cls N/A
haproxy:ins:uptime Unknown instance, ins, job, ip, cls N/A
haproxy:ins:usage Unknown instance, ins, job, ip, cls N/A
haproxy_backend_active_servers gauge proxy, instance, ins, job, ip, cls Total number of active UP servers with a non-zero weight
haproxy_backend_agg_check_status gauge state, proxy, instance, ins, job, ip, cls Backend’s aggregated gauge of servers’ state check status
haproxy_backend_agg_server_check_status gauge state, proxy, instance, ins, job, ip, cls [DEPRECATED] Backend’s aggregated gauge of servers’ status
haproxy_backend_agg_server_status gauge state, proxy, instance, ins, job, ip, cls Backend’s aggregated gauge of servers’ status
haproxy_backend_backup_servers gauge proxy, instance, ins, job, ip, cls Total number of backup UP servers with a non-zero weight
haproxy_backend_bytes_in_total counter proxy, instance, ins, job, ip, cls Total number of request bytes since process started
haproxy_backend_bytes_out_total counter proxy, instance, ins, job, ip, cls Total number of response bytes since process started
haproxy_backend_check_last_change_seconds gauge proxy, instance, ins, job, ip, cls How long ago the last server state changed, in seconds
haproxy_backend_check_up_down_total counter proxy, instance, ins, job, ip, cls Total number of failed checks causing UP to DOWN server transitions, per server/backend, since the worker process started
haproxy_backend_client_aborts_total counter proxy, instance, ins, job, ip, cls Total number of requests or connections aborted by the client since the worker process started
haproxy_backend_connect_time_average_seconds gauge proxy, instance, ins, job, ip, cls Avg. connect time for last 1024 successful connections.
haproxy_backend_connection_attempts_total counter proxy, instance, ins, job, ip, cls Total number of outgoing connection attempts on this backend/server since the worker process started
haproxy_backend_connection_errors_total counter proxy, instance, ins, job, ip, cls Total number of failed connections to server since the worker process started
haproxy_backend_connection_reuses_total counter proxy, instance, ins, job, ip, cls Total number of reused connection on this backend/server since the worker process started
haproxy_backend_current_queue gauge proxy, instance, ins, job, ip, cls Number of current queued connections
haproxy_backend_current_sessions gauge proxy, instance, ins, job, ip, cls Number of current sessions on the frontend, backend or server
haproxy_backend_downtime_seconds_total counter proxy, instance, ins, job, ip, cls Total time spent in DOWN state, for server or backend
haproxy_backend_failed_header_rewriting_total counter proxy, instance, ins, job, ip, cls Total number of failed HTTP header rewrites since the worker process started
haproxy_backend_http_cache_hits_total counter proxy, instance, ins, job, ip, cls Total number of HTTP requests not found in the cache on this frontend/backend since the worker process started
haproxy_backend_http_cache_lookups_total counter proxy, instance, ins, job, ip, cls Total number of HTTP requests looked up in the cache on this frontend/backend since the worker process started
haproxy_backend_http_comp_bytes_bypassed_total counter proxy, instance, ins, job, ip, cls Total number of bytes that bypassed HTTP compression for this object since the worker process started (CPU/memory/bandwidth limitation)
haproxy_backend_http_comp_bytes_in_total counter proxy, instance, ins, job, ip, cls Total number of bytes submitted to the HTTP compressor for this object since the worker process started
haproxy_backend_http_comp_bytes_out_total counter proxy, instance, ins, job, ip, cls Total number of bytes emitted by the HTTP compressor for this object since the worker process started
haproxy_backend_http_comp_responses_total counter proxy, instance, ins, job, ip, cls Total number of HTTP responses that were compressed for this object since the worker process started
haproxy_backend_http_requests_total counter proxy, instance, ins, job, ip, cls Total number of HTTP requests processed by this object since the worker process started
haproxy_backend_http_responses_total counter ip, proxy, ins, code, job, instance, cls Total number of HTTP responses with status 100-199 returned by this object since the worker process started
haproxy_backend_internal_errors_total counter proxy, instance, ins, job, ip, cls Total number of internal errors since process started
haproxy_backend_last_session_seconds gauge proxy, instance, ins, job, ip, cls How long ago some traffic was seen on this object on this worker process, in seconds
haproxy_backend_limit_sessions gauge proxy, instance, ins, job, ip, cls Frontend/listener/server’s maxconn, backend’s fullconn
haproxy_backend_loadbalanced_total counter proxy, instance, ins, job, ip, cls Total number of requests routed by load balancing since the worker process started (ignores queue pop and stickiness)
haproxy_backend_max_connect_time_seconds gauge proxy, instance, ins, job, ip, cls Maximum observed time spent waiting for a connection to complete
haproxy_backend_max_queue gauge proxy, instance, ins, job, ip, cls Highest value of queued connections encountered since process started
haproxy_backend_max_queue_time_seconds gauge proxy, instance, ins, job, ip, cls Maximum observed time spent in the queue
haproxy_backend_max_response_time_seconds gauge proxy, instance, ins, job, ip, cls Maximum observed time spent waiting for a server response
haproxy_backend_max_session_rate gauge proxy, instance, ins, job, ip, cls Highest value of sessions per second observed since the worker process started
haproxy_backend_max_sessions gauge proxy, instance, ins, job, ip, cls Highest value of current sessions encountered since process started
haproxy_backend_max_total_time_seconds gauge proxy, instance, ins, job, ip, cls Maximum observed total request+response time (request+queue+connect+response+processing)
haproxy_backend_queue_time_average_seconds gauge proxy, instance, ins, job, ip, cls Avg. queue time for last 1024 successful connections.
haproxy_backend_redispatch_warnings_total counter proxy, instance, ins, job, ip, cls Total number of server redispatches due to connection failures since the worker process started
haproxy_backend_requests_denied_total counter proxy, instance, ins, job, ip, cls Total number of denied requests since process started
haproxy_backend_response_errors_total counter proxy, instance, ins, job, ip, cls Total number of invalid responses since the worker process started
haproxy_backend_response_time_average_seconds gauge proxy, instance, ins, job, ip, cls Avg. response time for last 1024 successful connections.
haproxy_backend_responses_denied_total counter proxy, instance, ins, job, ip, cls Total number of denied responses since process started
haproxy_backend_retry_warnings_total counter proxy, instance, ins, job, ip, cls Total number of server connection retries since the worker process started
haproxy_backend_server_aborts_total counter proxy, instance, ins, job, ip, cls Total number of requests or connections aborted by the server since the worker process started
haproxy_backend_sessions_total counter proxy, instance, ins, job, ip, cls Total number of sessions since process started
haproxy_backend_status gauge state, proxy, instance, ins, job, ip, cls Current status of the service, per state label value.
haproxy_backend_total_time_average_seconds gauge proxy, instance, ins, job, ip, cls Avg. total time for last 1024 successful connections.
haproxy_backend_uweight gauge proxy, instance, ins, job, ip, cls Server’s user weight, or sum of active servers’ user weights for a backend
haproxy_backend_weight gauge proxy, instance, ins, job, ip, cls Server’s effective weight, or sum of active servers’ effective weights for a backend
haproxy_frontend_bytes_in_total counter proxy, instance, ins, job, ip, cls Total number of request bytes since process started
haproxy_frontend_bytes_out_total counter proxy, instance, ins, job, ip, cls Total number of response bytes since process started
haproxy_frontend_connections_rate_max gauge proxy, instance, ins, job, ip, cls Highest value of connections per second observed since the worker process started
haproxy_frontend_connections_total counter proxy, instance, ins, job, ip, cls Total number of new connections accepted on this frontend since the worker process started
haproxy_frontend_current_sessions gauge proxy, instance, ins, job, ip, cls Number of current sessions on the frontend, backend or server
haproxy_frontend_denied_connections_total counter proxy, instance, ins, job, ip, cls Total number of incoming connections blocked on a listener/frontend by a tcp-request connection rule since the worker process started
haproxy_frontend_denied_sessions_total counter proxy, instance, ins, job, ip, cls Total number of incoming sessions blocked on a listener/frontend by a tcp-request connection rule since the worker process started
haproxy_frontend_failed_header_rewriting_total counter proxy, instance, ins, job, ip, cls Total number of failed HTTP header rewrites since the worker process started
haproxy_frontend_http_cache_hits_total counter proxy, instance, ins, job, ip, cls Total number of HTTP requests not found in the cache on this frontend/backend since the worker process started
haproxy_frontend_http_cache_lookups_total counter proxy, instance, ins, job, ip, cls Total number of HTTP requests looked up in the cache on this frontend/backend since the worker process started
haproxy_frontend_http_comp_bytes_bypassed_total counter proxy, instance, ins, job, ip, cls Total number of bytes that bypassed HTTP compression for this object since the worker process started (CPU/memory/bandwidth limitation)
haproxy_frontend_http_comp_bytes_in_total counter proxy, instance, ins, job, ip, cls Total number of bytes submitted to the HTTP compressor for this object since the worker process started
haproxy_frontend_http_comp_bytes_out_total counter proxy, instance, ins, job, ip, cls Total number of bytes emitted by the HTTP compressor for this object since the worker process started
haproxy_frontend_http_comp_responses_total counter proxy, instance, ins, job, ip, cls Total number of HTTP responses that were compressed for this object since the worker process started
haproxy_frontend_http_requests_rate_max gauge proxy, instance, ins, job, ip, cls Highest value of http requests observed since the worker process started
haproxy_frontend_http_requests_total counter proxy, instance, ins, job, ip, cls Total number of HTTP requests processed by this object since the worker process started
haproxy_frontend_http_responses_total counter ip, proxy, ins, code, job, instance, cls Total number of HTTP responses with status 100-199 returned by this object since the worker process started
haproxy_frontend_intercepted_requests_total counter proxy, instance, ins, job, ip, cls Total number of HTTP requests intercepted on the frontend (redirects/stats/services) since the worker process started
haproxy_frontend_internal_errors_total counter proxy, instance, ins, job, ip, cls Total number of internal errors since process started
haproxy_frontend_limit_session_rate gauge proxy, instance, ins, job, ip, cls Limit on the number of sessions accepted in a second (frontend only, ‘rate-limit sessions’ setting)
haproxy_frontend_limit_sessions gauge proxy, instance, ins, job, ip, cls Frontend/listener/server’s maxconn, backend’s fullconn
haproxy_frontend_max_session_rate gauge proxy, instance, ins, job, ip, cls Highest value of sessions per second observed since the worker process started
haproxy_frontend_max_sessions gauge proxy, instance, ins, job, ip, cls Highest value of current sessions encountered since process started
haproxy_frontend_request_errors_total counter proxy, instance, ins, job, ip, cls Total number of invalid requests since process started
haproxy_frontend_requests_denied_total counter proxy, instance, ins, job, ip, cls Total number of denied requests since process started
haproxy_frontend_responses_denied_total counter proxy, instance, ins, job, ip, cls Total number of denied responses since process started
haproxy_frontend_sessions_total counter proxy, instance, ins, job, ip, cls Total number of sessions since process started
haproxy_frontend_status gauge state, proxy, instance, ins, job, ip, cls Current status of the service, per state label value.
haproxy_process_active_peers gauge instance, ins, job, ip, cls Current number of verified active peers connections on the current worker process
haproxy_process_build_info gauge version, instance, ins, job, ip, cls Build info
haproxy_process_busy_polling_enabled gauge instance, ins, job, ip, cls 1 if busy-polling is currently in use on the worker process, otherwise zero (config.busy-polling)
haproxy_process_bytes_out_rate gauge instance, ins, job, ip, cls Number of bytes emitted by current worker process over the last second
haproxy_process_bytes_out_total counter instance, ins, job, ip, cls Total number of bytes emitted by current worker process since started
haproxy_process_connected_peers gauge instance, ins, job, ip, cls Current number of peers having passed the connection step on the current worker process
haproxy_process_connections_total counter instance, ins, job, ip, cls Total number of connections on this worker process since started
haproxy_process_current_backend_ssl_key_rate gauge instance, ins, job, ip, cls Number of SSL keys created on backends in this worker process over the last second
haproxy_process_current_connection_rate gauge instance, ins, job, ip, cls Number of front connections created on this worker process over the last second
haproxy_process_current_connections gauge instance, ins, job, ip, cls Current number of connections on this worker process
haproxy_process_current_frontend_ssl_key_rate gauge instance, ins, job, ip, cls Number of SSL keys created on frontends in this worker process over the last second
haproxy_process_current_run_queue gauge instance, ins, job, ip, cls Total number of active tasks+tasklets in the current worker process
haproxy_process_current_session_rate gauge instance, ins, job, ip, cls Number of sessions created on this worker process over the last second
haproxy_process_current_ssl_connections gauge instance, ins, job, ip, cls Current number of SSL endpoints on this worker process (front+back)
haproxy_process_current_ssl_rate gauge instance, ins, job, ip, cls Number of SSL connections created on this worker process over the last second
haproxy_process_current_tasks gauge instance, ins, job, ip, cls Total number of tasks in the current worker process (active + sleeping)
haproxy_process_current_zlib_memory gauge instance, ins, job, ip, cls Amount of memory currently used by HTTP compression on the current worker process (in bytes)
haproxy_process_dropped_logs_total counter instance, ins, job, ip, cls Total number of dropped logs for current worker process since started
haproxy_process_failed_resolutions counter instance, ins, job, ip, cls Total number of failed DNS resolutions in current worker process since started
haproxy_process_frontend_ssl_reuse gauge instance, ins, job, ip, cls Percent of frontend SSL connections which did not require a new key
haproxy_process_hard_max_connections gauge instance, ins, job, ip, cls Hard limit on the number of per-process connections (imposed by Memmax_MB or Ulimit-n)
haproxy_process_http_comp_bytes_in_total counter instance, ins, job, ip, cls Number of bytes submitted to the HTTP compressor in this worker process over the last second
haproxy_process_http_comp_bytes_out_total counter instance, ins, job, ip, cls Number of bytes emitted by the HTTP compressor in this worker process over the last second
haproxy_process_idle_time_percent gauge instance, ins, job, ip, cls Percentage of last second spent waiting in the current worker thread
haproxy_process_jobs gauge instance, ins, job, ip, cls Current number of active jobs on the current worker process (frontend connections, master connections, listeners)
haproxy_process_limit_connection_rate gauge instance, ins, job, ip, cls Hard limit for ConnRate (global.maxconnrate)
haproxy_process_limit_http_comp gauge instance, ins, job, ip, cls Limit of CompressBpsOut beyond which HTTP compression is automatically disabled
haproxy_process_limit_session_rate gauge instance, ins, job, ip, cls Hard limit for SessRate (global.maxsessrate)
haproxy_process_limit_ssl_rate gauge instance, ins, job, ip, cls Hard limit for SslRate (global.maxsslrate)
haproxy_process_listeners gauge instance, ins, job, ip, cls Current number of active listeners on the current worker process
haproxy_process_max_backend_ssl_key_rate gauge instance, ins, job, ip, cls Highest SslBackendKeyRate reached on this worker process since started (in SSL keys per second)
haproxy_process_max_connection_rate gauge instance, ins, job, ip, cls Highest ConnRate reached on this worker process since started (in connections per second)
haproxy_process_max_connections gauge instance, ins, job, ip, cls Hard limit on the number of per-process connections (configured or imposed by Ulimit-n)
haproxy_process_max_fds gauge instance, ins, job, ip, cls Hard limit on the number of per-process file descriptors
haproxy_process_max_frontend_ssl_key_rate gauge instance, ins, job, ip, cls Highest SslFrontendKeyRate reached on this worker process since started (in SSL keys per second)
haproxy_process_max_memory_bytes gauge instance, ins, job, ip, cls Worker process’s hard limit on memory usage in byes (-m on command line)
haproxy_process_max_pipes gauge instance, ins, job, ip, cls Hard limit on the number of pipes for splicing, 0=unlimited
haproxy_process_max_session_rate gauge instance, ins, job, ip, cls Highest SessRate reached on this worker process since started (in sessions per second)
haproxy_process_max_sockets gauge instance, ins, job, ip, cls Hard limit on the number of per-process sockets
haproxy_process_max_ssl_connections gauge instance, ins, job, ip, cls Hard limit on the number of per-process SSL endpoints (front+back), 0=unlimited
haproxy_process_max_ssl_rate gauge instance, ins, job, ip, cls Highest SslRate reached on this worker process since started (in connections per second)
haproxy_process_max_zlib_memory gauge instance, ins, job, ip, cls Limit on the amount of memory used by HTTP compression above which it is automatically disabled (in bytes, see global.maxzlibmem)
haproxy_process_nbproc gauge instance, ins, job, ip, cls Number of started worker processes (historical, always 1)
haproxy_process_nbthread gauge instance, ins, job, ip, cls Number of started threads (global.nbthread)
haproxy_process_pipes_free_total counter instance, ins, job, ip, cls Current number of allocated and available pipes in this worker process
haproxy_process_pipes_used_total counter instance, ins, job, ip, cls Current number of pipes in use in this worker process
haproxy_process_pool_allocated_bytes gauge instance, ins, job, ip, cls Amount of memory allocated in pools (in bytes)
haproxy_process_pool_failures_total counter instance, ins, job, ip, cls Number of failed pool allocations since this worker was started
haproxy_process_pool_used_bytes gauge instance, ins, job, ip, cls Amount of pool memory currently used (in bytes)
haproxy_process_recv_logs_total counter instance, ins, job, ip, cls Total number of log messages received by log-forwarding listeners on this worker process since started
haproxy_process_relative_process_id gauge instance, ins, job, ip, cls Relative worker process number (1)
haproxy_process_requests_total counter instance, ins, job, ip, cls Total number of requests on this worker process since started
haproxy_process_spliced_bytes_out_total counter instance, ins, job, ip, cls Total number of bytes emitted by current worker process through a kernel pipe since started
haproxy_process_ssl_cache_lookups_total counter instance, ins, job, ip, cls Total number of SSL session ID lookups in the SSL session cache on this worker since started
haproxy_process_ssl_cache_misses_total counter instance, ins, job, ip, cls Total number of SSL session ID lookups that didn’t find a session in the SSL session cache on this worker since started
haproxy_process_ssl_connections_total counter instance, ins, job, ip, cls Total number of SSL endpoints on this worker process since started (front+back)
haproxy_process_start_time_seconds gauge instance, ins, job, ip, cls Start time in seconds
haproxy_process_stopping gauge instance, ins, job, ip, cls 1 if the worker process is currently stopping, otherwise zero
haproxy_process_unstoppable_jobs gauge instance, ins, job, ip, cls Current number of unstoppable jobs on the current worker process (master connections)
haproxy_process_uptime_seconds gauge instance, ins, job, ip, cls How long ago this worker process was started (seconds)
haproxy_server_bytes_in_total counter proxy, instance, ins, job, server, ip, cls Total number of request bytes since process started
haproxy_server_bytes_out_total counter proxy, instance, ins, job, server, ip, cls Total number of response bytes since process started
haproxy_server_check_code gauge proxy, instance, ins, job, server, ip, cls layer5-7 code, if available of the last health check.
haproxy_server_check_duration_seconds gauge proxy, instance, ins, job, server, ip, cls Total duration of the latest server health check, in seconds.
haproxy_server_check_failures_total counter proxy, instance, ins, job, server, ip, cls Total number of failed individual health checks per server/backend, since the worker process started
haproxy_server_check_last_change_seconds gauge proxy, instance, ins, job, server, ip, cls How long ago the last server state changed, in seconds
haproxy_server_check_status gauge state, proxy, instance, ins, job, server, ip, cls Status of last health check, per state label value.
haproxy_server_check_up_down_total counter proxy, instance, ins, job, server, ip, cls Total number of failed checks causing UP to DOWN server transitions, per server/backend, since the worker process started
haproxy_server_client_aborts_total counter proxy, instance, ins, job, server, ip, cls Total number of requests or connections aborted by the client since the worker process started
haproxy_server_connect_time_average_seconds gauge proxy, instance, ins, job, server, ip, cls Avg. connect time for last 1024 successful connections.
haproxy_server_connection_attempts_total counter proxy, instance, ins, job, server, ip, cls Total number of outgoing connection attempts on this backend/server since the worker process started
haproxy_server_connection_errors_total counter proxy, instance, ins, job, server, ip, cls Total number of failed connections to server since the worker process started
haproxy_server_connection_reuses_total counter proxy, instance, ins, job, server, ip, cls Total number of reused connection on this backend/server since the worker process started
haproxy_server_current_queue gauge proxy, instance, ins, job, server, ip, cls Number of current queued connections
haproxy_server_current_sessions gauge proxy, instance, ins, job, server, ip, cls Number of current sessions on the frontend, backend or server
haproxy_server_current_throttle gauge proxy, instance, ins, job, server, ip, cls Throttling ratio applied to a server’s maxconn and weight during the slowstart period (0 to 100%)
haproxy_server_downtime_seconds_total counter proxy, instance, ins, job, server, ip, cls Total time spent in DOWN state, for server or backend
haproxy_server_failed_header_rewriting_total counter proxy, instance, ins, job, server, ip, cls Total number of failed HTTP header rewrites since the worker process started
haproxy_server_idle_connections_current gauge proxy, instance, ins, job, server, ip, cls Current number of idle connections available for reuse on this server
haproxy_server_idle_connections_limit gauge proxy, instance, ins, job, server, ip, cls Limit on the number of available idle connections on this server (server ‘pool_max_conn’ directive)
haproxy_server_internal_errors_total counter proxy, instance, ins, job, server, ip, cls Total number of internal errors since process started
haproxy_server_last_session_seconds gauge proxy, instance, ins, job, server, ip, cls How long ago some traffic was seen on this object on this worker process, in seconds
haproxy_server_limit_sessions gauge proxy, instance, ins, job, server, ip, cls Frontend/listener/server’s maxconn, backend’s fullconn
haproxy_server_loadbalanced_total counter proxy, instance, ins, job, server, ip, cls Total number of requests routed by load balancing since the worker process started (ignores queue pop and stickiness)
haproxy_server_max_connect_time_seconds gauge proxy, instance, ins, job, server, ip, cls Maximum observed time spent waiting for a connection to complete
haproxy_server_max_queue gauge proxy, instance, ins, job, server, ip, cls Highest value of queued connections encountered since process started
haproxy_server_max_queue_time_seconds gauge proxy, instance, ins, job, server, ip, cls Maximum observed time spent in the queue
haproxy_server_max_response_time_seconds gauge proxy, instance, ins, job, server, ip, cls Maximum observed time spent waiting for a server response
haproxy_server_max_session_rate gauge proxy, instance, ins, job, server, ip, cls Highest value of sessions per second observed since the worker process started
haproxy_server_max_sessions gauge proxy, instance, ins, job, server, ip, cls Highest value of current sessions encountered since process started
haproxy_server_max_total_time_seconds gauge proxy, instance, ins, job, server, ip, cls Maximum observed total request+response time (request+queue+connect+response+processing)
haproxy_server_need_connections_current gauge proxy, instance, ins, job, server, ip, cls Estimated needed number of connections
haproxy_server_queue_limit gauge proxy, instance, ins, job, server, ip, cls Limit on the number of connections in queue, for servers only (maxqueue argument)
haproxy_server_queue_time_average_seconds gauge proxy, instance, ins, job, server, ip, cls Avg. queue time for last 1024 successful connections.
haproxy_server_redispatch_warnings_total counter proxy, instance, ins, job, server, ip, cls Total number of server redispatches due to connection failures since the worker process started
haproxy_server_response_errors_total counter proxy, instance, ins, job, server, ip, cls Total number of invalid responses since the worker process started
haproxy_server_response_time_average_seconds gauge proxy, instance, ins, job, server, ip, cls Avg. response time for last 1024 successful connections.
haproxy_server_responses_denied_total counter proxy, instance, ins, job, server, ip, cls Total number of denied responses since process started
haproxy_server_retry_warnings_total counter proxy, instance, ins, job, server, ip, cls Total number of server connection retries since the worker process started
haproxy_server_safe_idle_connections_current gauge proxy, instance, ins, job, server, ip, cls Current number of safe idle connections
haproxy_server_server_aborts_total counter proxy, instance, ins, job, server, ip, cls Total number of requests or connections aborted by the server since the worker process started
haproxy_server_sessions_total counter proxy, instance, ins, job, server, ip, cls Total number of sessions since process started
haproxy_server_status gauge state, proxy, instance, ins, job, server, ip, cls Current status of the service, per state label value.
haproxy_server_total_time_average_seconds gauge proxy, instance, ins, job, server, ip, cls Avg. total time for last 1024 successful connections.
haproxy_server_unsafe_idle_connections_current gauge proxy, instance, ins, job, server, ip, cls Current number of unsafe idle connections
haproxy_server_used_connections_current gauge proxy, instance, ins, job, server, ip, cls Current number of connections in use
haproxy_server_uweight gauge proxy, instance, ins, job, server, ip, cls Server’s user weight, or sum of active servers’ user weights for a backend
haproxy_server_weight gauge proxy, instance, ins, job, server, ip, cls Server’s effective weight, or sum of active servers’ effective weights for a backend
haproxy_up Unknown instance, ins, job, ip, cls N/A
inflight_requests gauge instance, ins, job, route, ip, cls, method Current number of inflight requests.
jaeger_tracer_baggage_restrictions_updates_total Unknown instance, ins, job, result, ip, cls N/A
jaeger_tracer_baggage_truncations_total Unknown instance, ins, job, ip, cls N/A
jaeger_tracer_baggage_updates_total Unknown instance, ins, job, result, ip, cls N/A
jaeger_tracer_finished_spans_total Unknown instance, ins, job, sampled, ip, cls N/A
jaeger_tracer_reporter_queue_length gauge instance, ins, job, ip, cls Current number of spans in the reporter queue
jaeger_tracer_reporter_spans_total Unknown instance, ins, job, result, ip, cls N/A
jaeger_tracer_sampler_queries_total Unknown instance, ins, job, result, ip, cls N/A
jaeger_tracer_sampler_updates_total Unknown instance, ins, job, result, ip, cls N/A
jaeger_tracer_span_context_decoding_errors_total Unknown instance, ins, job, ip, cls N/A
jaeger_tracer_started_spans_total Unknown instance, ins, job, sampled, ip, cls N/A
jaeger_tracer_throttled_debug_spans_total Unknown instance, ins, job, ip, cls N/A
jaeger_tracer_throttler_updates_total Unknown instance, ins, job, result, ip, cls N/A
jaeger_tracer_traces_total Unknown state, instance, ins, job, sampled, ip, cls N/A
loki_experimental_features_in_use_total Unknown instance, ins, job, ip, cls N/A
loki_internal_log_messages_total Unknown level, instance, ins, job, ip, cls N/A
loki_log_flushes_bucket Unknown instance, ins, job, le, ip, cls N/A
loki_log_flushes_count Unknown instance, ins, job, ip, cls N/A
loki_log_flushes_sum Unknown instance, ins, job, ip, cls N/A
loki_log_messages_total Unknown level, instance, ins, job, ip, cls N/A
loki_logql_querystats_duplicates_total Unknown instance, ins, job, ip, cls N/A
loki_logql_querystats_ingester_sent_lines_total Unknown instance, ins, job, ip, cls N/A
loki_querier_index_cache_corruptions_total Unknown instance, ins, job, ip, cls N/A
loki_querier_index_cache_encode_errors_total Unknown instance, ins, job, ip, cls N/A
loki_querier_index_cache_gets_total Unknown instance, ins, job, ip, cls N/A
loki_querier_index_cache_hits_total Unknown instance, ins, job, ip, cls N/A
loki_querier_index_cache_puts_total Unknown instance, ins, job, ip, cls N/A
net_conntrack_dialer_conn_attempted_total counter ip, ins, job, instance, cls, dialer_name Total number of connections attempted by the given dialer a given name.
net_conntrack_dialer_conn_closed_total counter ip, ins, job, instance, cls, dialer_name Total number of connections closed which originated from the dialer of a given name.
net_conntrack_dialer_conn_established_total counter ip, ins, job, instance, cls, dialer_name Total number of connections successfully established by the given dialer a given name.
net_conntrack_dialer_conn_failed_total counter ip, ins, job, reason, instance, cls, dialer_name Total number of connections failed to dial by the dialer a given name.
node:cls:avail_bytes Unknown job, cls N/A
node:cls:cpu_count Unknown job, cls N/A
node:cls:cpu_usage Unknown job, cls N/A
node:cls:cpu_usage_15m Unknown job, cls N/A
node:cls:cpu_usage_1m Unknown job, cls N/A
node:cls:cpu_usage_5m Unknown job, cls N/A
node:cls:disk_io_bytes_rate1m Unknown job, cls N/A
node:cls:disk_iops_1m Unknown job, cls N/A
node:cls:disk_mreads_rate1m Unknown job, cls N/A
node:cls:disk_mreads_ratio1m Unknown job, cls N/A
node:cls:disk_mwrites_rate1m Unknown job, cls N/A
node:cls:disk_mwrites_ratio1m Unknown job, cls N/A
node:cls:disk_read_bytes_rate1m Unknown job, cls N/A
node:cls:disk_reads_rate1m Unknown job, cls N/A
node:cls:disk_write_bytes_rate1m Unknown job, cls N/A
node:cls:disk_writes_rate1m Unknown job, cls N/A
node:cls:free_bytes Unknown job, cls N/A
node:cls:mem_usage Unknown job, cls N/A
node:cls:network_io_bytes_rate1m Unknown job, cls N/A
node:cls:network_rx_bytes_rate1m Unknown job, cls N/A
node:cls:network_rx_pps1m Unknown job, cls N/A
node:cls:network_tx_bytes_rate1m Unknown job, cls N/A
node:cls:network_tx_pps1m Unknown job, cls N/A
node:cls:size_bytes Unknown job, cls N/A
node:cls:space_usage Unknown job, cls N/A
node:cls:space_usage_max Unknown job, cls N/A
node:cls:stdload1 Unknown job, cls N/A
node:cls:stdload15 Unknown job, cls N/A
node:cls:stdload5 Unknown job, cls N/A
node:cls:time_drift_max Unknown job, cls N/A
node:cpu:idle_time_irate1m Unknown ip, ins, job, cpu, instance, cls N/A
node:cpu:sched_timeslices_rate1m Unknown ip, ins, job, cpu, instance, cls N/A
node:cpu:sched_wait_rate1m Unknown ip, ins, job, cpu, instance, cls N/A
node:cpu:time_irate1m Unknown ip, mode, ins, job, cpu, instance, cls N/A
node:cpu:total_time_irate1m Unknown ip, ins, job, cpu, instance, cls N/A
node:cpu:usage Unknown ip, ins, job, cpu, instance, cls N/A
node:cpu:usage_avg15m Unknown ip, ins, job, cpu, instance, cls N/A
node:cpu:usage_avg1m Unknown ip, ins, job, cpu, instance, cls N/A
node:cpu:usage_avg5m Unknown ip, ins, job, cpu, instance, cls N/A
node:dev:disk_avg_queue_size Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_io_batch_1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_io_bytes_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_io_rt_1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_io_time_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_iops_1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_mreads_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_mreads_ratio1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_mwrites_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_mwrites_ratio1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_read_batch_1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_read_bytes_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_read_rt_1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_read_time_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_reads_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_util_1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_write_batch_1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_write_bytes_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_write_rt_1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_write_time_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:disk_writes_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:network_io_bytes_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:network_rx_bytes_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:network_rx_pps1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:network_tx_bytes_rate1m Unknown ip, device, ins, job, instance, cls N/A
node:dev:network_tx_pps1m Unknown ip, device, ins, job, instance, cls N/A
node:env:avail_bytes Unknown job N/A
node:env:cpu_count Unknown job N/A
node:env:cpu_usage Unknown job N/A
node:env:cpu_usage_15m Unknown job N/A
node:env:cpu_usage_1m Unknown job N/A
node:env:cpu_usage_5m Unknown job N/A
node:env:device_space_usage_max Unknown device, mountpoint, job, fstype N/A
node:env:free_bytes Unknown job N/A
node:env:mem_avail Unknown job N/A
node:env:mem_total Unknown job N/A
node:env:mem_usage Unknown job N/A
node:env:size_bytes Unknown job N/A
node:env:space_usage Unknown job N/A
node:env:stdload1 Unknown job N/A
node:env:stdload15 Unknown job N/A
node:env:stdload5 Unknown job N/A
node:fs:avail_bytes Unknown ip, device, mountpoint, ins, cls, job, instance, fstype N/A
node:fs:free_bytes Unknown ip, device, mountpoint, ins, cls, job, instance, fstype N/A
node:fs:inode_free Unknown ip, device, mountpoint, ins, cls, job, instance, fstype N/A
node:fs:inode_total Unknown ip, device, mountpoint, ins, cls, job, instance, fstype N/A
node:fs:inode_usage Unknown ip, device, mountpoint, ins, cls, job, instance, fstype N/A
node:fs:inode_used Unknown ip, device, mountpoint, ins, cls, job, instance, fstype N/A
node:fs:size_bytes Unknown ip, device, mountpoint, ins, cls, job, instance, fstype N/A
node:fs:space_deriv1h Unknown ip, device, mountpoint, ins, cls, job, instance, fstype N/A
node:fs:space_exhaust Unknown ip, device, mountpoint, ins, cls, job, instance, fstype N/A
node:fs:space_predict_1d Unknown ip, device, mountpoint, ins, cls, job, instance, fstype N/A
node:fs:space_usage Unknown ip, device, mountpoint, ins, cls, job, instance, fstype N/A
node:ins Unknown id, ip, ins, job, nodename, instance, cls N/A
node:ins:avail_bytes Unknown instance, ins, job, ip, cls N/A
node:ins:cpu_count Unknown instance, ins, job, ip, cls N/A
node:ins:cpu_usage Unknown instance, ins, job, ip, cls N/A
node:ins:cpu_usage_15m Unknown instance, ins, job, ip, cls N/A
node:ins:cpu_usage_1m Unknown instance, ins, job, ip, cls N/A
node:ins:cpu_usage_5m Unknown instance, ins, job, ip, cls N/A
node:ins:ctx_switch_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:disk_io_bytes_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:disk_iops_1m Unknown instance, ins, job, ip, cls N/A
node:ins:disk_mreads_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:disk_mreads_ratio1m Unknown instance, ins, job, ip, cls N/A
node:ins:disk_mwrites_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:disk_mwrites_ratio1m Unknown instance, ins, job, ip, cls N/A
node:ins:disk_read_bytes_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:disk_reads_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:disk_write_bytes_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:disk_writes_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:fd_alloc_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:fd_usage Unknown instance, ins, job, ip, cls N/A
node:ins:forks_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:free_bytes Unknown instance, ins, job, ip, cls N/A
node:ins:inode_usage Unknown instance, ins, job, ip, cls N/A
node:ins:interrupt_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:mem_avail Unknown instance, ins, job, ip, cls N/A
node:ins:mem_commit_ratio Unknown instance, ins, job, ip, cls N/A
node:ins:mem_kernel Unknown instance, ins, job, ip, cls N/A
node:ins:mem_rss Unknown instance, ins, job, ip, cls N/A
node:ins:mem_usage Unknown instance, ins, job, ip, cls N/A
node:ins:network_io_bytes_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:network_rx_bytes_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:network_rx_pps1m Unknown instance, ins, job, ip, cls N/A
node:ins:network_tx_bytes_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:network_tx_pps1m Unknown instance, ins, job, ip, cls N/A
node:ins:pagefault_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:pagein_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:pageout_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:pgmajfault_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:sched_wait_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:size_bytes Unknown instance, ins, job, ip, cls N/A
node:ins:space_usage_max Unknown instance, ins, job, ip, cls N/A
node:ins:stdload1 Unknown instance, ins, job, ip, cls N/A
node:ins:stdload15 Unknown instance, ins, job, ip, cls N/A
node:ins:stdload5 Unknown instance, ins, job, ip, cls N/A
node:ins:swap_usage Unknown instance, ins, job, ip, cls N/A
node:ins:swapin_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:swapout_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:tcp_active_opens_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:tcp_dropped_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:tcp_error Unknown instance, ins, job, ip, cls N/A
node:ins:tcp_error_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:tcp_insegs_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:tcp_outsegs_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:tcp_overflow_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:tcp_passive_opens_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:tcp_retrans_ratio1m Unknown instance, ins, job, ip, cls N/A
node:ins:tcp_retranssegs_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:tcp_segs_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:time_drift Unknown instance, ins, job, ip, cls N/A
node:ins:udp_in_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:udp_out_rate1m Unknown instance, ins, job, ip, cls N/A
node:ins:uptime Unknown instance, ins, job, ip, cls N/A
node_arp_entries gauge ip, device, ins, job, instance, cls ARP entries by device
node_boot_time_seconds gauge instance, ins, job, ip, cls Node boot time, in unixtime.
node_context_switches_total counter instance, ins, job, ip, cls Total number of context switches.
node_cooling_device_cur_state gauge instance, ins, job, type, ip, cls Current throttle state of the cooling device
node_cooling_device_max_state gauge instance, ins, job, type, ip, cls Maximum throttle state of the cooling device
node_cpu_guest_seconds_total counter ip, mode, ins, job, cpu, instance, cls Seconds the CPUs spent in guests (VMs) for each mode.
node_cpu_seconds_total counter ip, mode, ins, job, cpu, instance, cls Seconds the CPUs spent in each mode.
node_disk_discard_time_seconds_total counter ip, device, ins, job, instance, cls This is the total number of seconds spent by all discards.
node_disk_discarded_sectors_total counter ip, device, ins, job, instance, cls The total number of sectors discarded successfully.
node_disk_discards_completed_total counter ip, device, ins, job, instance, cls The total number of discards completed successfully.
node_disk_discards_merged_total counter ip, device, ins, job, instance, cls The total number of discards merged.
node_disk_filesystem_info gauge ip, usage, version, device, uuid, ins, type, job, instance, cls Info about disk filesystem.
node_disk_info gauge minor, ip, major, revision, device, model, serial, path, ins, job, instance, cls Info of /sys/block/<block_device>.
node_disk_io_now gauge ip, device, ins, job, instance, cls The number of I/Os currently in progress.
node_disk_io_time_seconds_total counter ip, device, ins, job, instance, cls Total seconds spent doing I/Os.
node_disk_io_time_weighted_seconds_total counter ip, device, ins, job, instance, cls The weighted # of seconds spent doing I/Os.
node_disk_read_bytes_total counter ip, device, ins, job, instance, cls The total number of bytes read successfully.
node_disk_read_time_seconds_total counter ip, device, ins, job, instance, cls The total number of seconds spent by all reads.
node_disk_reads_completed_total counter ip, device, ins, job, instance, cls The total number of reads completed successfully.
node_disk_reads_merged_total counter ip, device, ins, job, instance, cls The total number of reads merged.
node_disk_write_time_seconds_total counter ip, device, ins, job, instance, cls This is the total number of seconds spent by all writes.
node_disk_writes_completed_total counter ip, device, ins, job, instance, cls The total number of writes completed successfully.
node_disk_writes_merged_total counter ip, device, ins, job, instance, cls The number of writes merged.
node_disk_written_bytes_total counter ip, device, ins, job, instance, cls The total number of bytes written successfully.
node_dmi_info gauge bios_vendor, ip, product_family, product_version, product_uuid, system_vendor, bios_version, ins, bios_date, cls, job, product_name, instance, chassis_version, chassis_vendor, product_serial A metric with a constant ‘1’ value labeled by bios_date, bios_release, bios_vendor, bios_version, board_asset_tag, board_name, board_serial, board_vendor, board_version, chassis_asset_tag, chassis_serial, chassis_vendor, chassis_version, product_family, product_name, product_serial, product_sku, product_uuid, product_version, system_vendor if provided by DMI.
node_entropy_available_bits gauge instance, ins, job, ip, cls Bits of available entropy.
node_entropy_pool_size_bits gauge instance, ins, job, ip, cls Bits of entropy pool.
node_exporter_build_info gauge ip, version, revision, goversion, branch, ins, goarch, job, tags, instance, cls, goos A metric with a constant ‘1’ value labeled by version, revision, branch, goversion from which node_exporter was built, and the goos and goarch for the build.
node_filefd_allocated gauge instance, ins, job, ip, cls File descriptor statistics: allocated.
node_filefd_maximum gauge instance, ins, job, ip, cls File descriptor statistics: maximum.
node_filesystem_avail_bytes gauge ip, device, mountpoint, ins, cls, job, instance, fstype Filesystem space available to non-root users in bytes.
node_filesystem_device_error gauge ip, device, mountpoint, ins, cls, job, instance, fstype Whether an error occurred while getting statistics for the given device.
node_filesystem_files gauge ip, device, mountpoint, ins, cls, job, instance, fstype Filesystem total file nodes.
node_filesystem_files_free gauge ip, device, mountpoint, ins, cls, job, instance, fstype Filesystem total free file nodes.
node_filesystem_free_bytes gauge ip, device, mountpoint, ins, cls, job, instance, fstype Filesystem free space in bytes.
node_filesystem_readonly gauge ip, device, mountpoint, ins, cls, job, instance, fstype Filesystem read-only status.
node_filesystem_size_bytes gauge ip, device, mountpoint, ins, cls, job, instance, fstype Filesystem size in bytes.
node_forks_total counter instance, ins, job, ip, cls Total number of forks.
node_hwmon_chip_names gauge chip_name, ip, ins, chip, job, instance, cls Annotation metric for human-readable chip names
node_hwmon_energy_joule_total counter sensor, ip, ins, chip, job, instance, cls Hardware monitor for joules used so far (input)
node_hwmon_sensor_label gauge sensor, ip, ins, chip, job, label, instance, cls Label for given chip and sensor
node_intr_total counter instance, ins, job, ip, cls Total number of interrupts serviced.
node_ipvs_connections_total counter instance, ins, job, ip, cls The total number of connections made.
node_ipvs_incoming_bytes_total counter instance, ins, job, ip, cls The total amount of incoming data.
node_ipvs_incoming_packets_total counter instance, ins, job, ip, cls The total number of incoming packets.
node_ipvs_outgoing_bytes_total counter instance, ins, job, ip, cls The total amount of outgoing data.
node_ipvs_outgoing_packets_total counter instance, ins, job, ip, cls The total number of outgoing packets.
node_load1 gauge instance, ins, job, ip, cls 1m load average.
node_load15 gauge instance, ins, job, ip, cls 15m load average.
node_load5 gauge instance, ins, job, ip, cls 5m load average.
node_memory_Active_anon_bytes gauge instance, ins, job, ip, cls Memory information field Active_anon_bytes.
node_memory_Active_bytes gauge instance, ins, job, ip, cls Memory information field Active_bytes.
node_memory_Active_file_bytes gauge instance, ins, job, ip, cls Memory information field Active_file_bytes.
node_memory_AnonHugePages_bytes gauge instance, ins, job, ip, cls Memory information field AnonHugePages_bytes.
node_memory_AnonPages_bytes gauge instance, ins, job, ip, cls Memory information field AnonPages_bytes.
node_memory_Bounce_bytes gauge instance, ins, job, ip, cls Memory information field Bounce_bytes.
node_memory_Buffers_bytes gauge instance, ins, job, ip, cls Memory information field Buffers_bytes.
node_memory_Cached_bytes gauge instance, ins, job, ip, cls Memory information field Cached_bytes.
node_memory_CommitLimit_bytes gauge instance, ins, job, ip, cls Memory information field CommitLimit_bytes.
node_memory_Committed_AS_bytes gauge instance, ins, job, ip, cls Memory information field Committed_AS_bytes.
node_memory_DirectMap1G_bytes gauge instance, ins, job, ip, cls Memory information field DirectMap1G_bytes.
node_memory_DirectMap2M_bytes gauge instance, ins, job, ip, cls Memory information field DirectMap2M_bytes.
node_memory_DirectMap4k_bytes gauge instance, ins, job, ip, cls Memory information field DirectMap4k_bytes.
node_memory_Dirty_bytes gauge instance, ins, job, ip, cls Memory information field Dirty_bytes.
node_memory_FileHugePages_bytes gauge instance, ins, job, ip, cls Memory information field FileHugePages_bytes.
node_memory_FilePmdMapped_bytes gauge instance, ins, job, ip, cls Memory information field FilePmdMapped_bytes.
node_memory_HardwareCorrupted_bytes gauge instance, ins, job, ip, cls Memory information field HardwareCorrupted_bytes.
node_memory_HugePages_Free gauge instance, ins, job, ip, cls Memory information field HugePages_Free.
node_memory_HugePages_Rsvd gauge instance, ins, job, ip, cls Memory information field HugePages_Rsvd.
node_memory_HugePages_Surp gauge instance, ins, job, ip, cls Memory information field HugePages_Surp.
node_memory_HugePages_Total gauge instance, ins, job, ip, cls Memory information field HugePages_Total.
node_memory_Hugepagesize_bytes gauge instance, ins, job, ip, cls Memory information field Hugepagesize_bytes.
node_memory_Hugetlb_bytes gauge instance, ins, job, ip, cls Memory information field Hugetlb_bytes.
node_memory_Inactive_anon_bytes gauge instance, ins, job, ip, cls Memory information field Inactive_anon_bytes.
node_memory_Inactive_bytes gauge instance, ins, job, ip, cls Memory information field Inactive_bytes.
node_memory_Inactive_file_bytes gauge instance, ins, job, ip, cls Memory information field Inactive_file_bytes.
node_memory_KReclaimable_bytes gauge instance, ins, job, ip, cls Memory information field KReclaimable_bytes.
node_memory_KernelStack_bytes gauge instance, ins, job, ip, cls Memory information field KernelStack_bytes.
node_memory_Mapped_bytes gauge instance, ins, job, ip, cls Memory information field Mapped_bytes.
node_memory_MemAvailable_bytes gauge instance, ins, job, ip, cls Memory information field MemAvailable_bytes.
node_memory_MemFree_bytes gauge instance, ins, job, ip, cls Memory information field MemFree_bytes.
node_memory_MemTotal_bytes gauge instance, ins, job, ip, cls Memory information field MemTotal_bytes.
node_memory_Mlocked_bytes gauge instance, ins, job, ip, cls Memory information field Mlocked_bytes.
node_memory_NFS_Unstable_bytes gauge instance, ins, job, ip, cls Memory information field NFS_Unstable_bytes.
node_memory_PageTables_bytes gauge instance, ins, job, ip, cls Memory information field PageTables_bytes.
node_memory_Percpu_bytes gauge instance, ins, job, ip, cls Memory information field Percpu_bytes.
node_memory_SReclaimable_bytes gauge instance, ins, job, ip, cls Memory information field SReclaimable_bytes.
node_memory_SUnreclaim_bytes gauge instance, ins, job, ip, cls Memory information field SUnreclaim_bytes.
node_memory_ShmemHugePages_bytes gauge instance, ins, job, ip, cls Memory information field ShmemHugePages_bytes.
node_memory_ShmemPmdMapped_bytes gauge instance, ins, job, ip, cls Memory information field ShmemPmdMapped_bytes.
node_memory_Shmem_bytes gauge instance, ins, job, ip, cls Memory information field Shmem_bytes.
node_memory_Slab_bytes gauge instance, ins, job, ip, cls Memory information field Slab_bytes.
node_memory_SwapCached_bytes gauge instance, ins, job, ip, cls Memory information field SwapCached_bytes.
node_memory_SwapFree_bytes gauge instance, ins, job, ip, cls Memory information field SwapFree_bytes.
node_memory_SwapTotal_bytes gauge instance, ins, job, ip, cls Memory information field SwapTotal_bytes.
node_memory_Unevictable_bytes gauge instance, ins, job, ip, cls Memory information field Unevictable_bytes.
node_memory_VmallocChunk_bytes gauge instance, ins, job, ip, cls Memory information field VmallocChunk_bytes.
node_memory_VmallocTotal_bytes gauge instance, ins, job, ip, cls Memory information field VmallocTotal_bytes.
node_memory_VmallocUsed_bytes gauge instance, ins, job, ip, cls Memory information field VmallocUsed_bytes.
node_memory_WritebackTmp_bytes gauge instance, ins, job, ip, cls Memory information field WritebackTmp_bytes.
node_memory_Writeback_bytes gauge instance, ins, job, ip, cls Memory information field Writeback_bytes.
node_netstat_Icmp6_InErrors unknown instance, ins, job, ip, cls Statistic Icmp6InErrors.
node_netstat_Icmp6_InMsgs unknown instance, ins, job, ip, cls Statistic Icmp6InMsgs.
node_netstat_Icmp6_OutMsgs unknown instance, ins, job, ip, cls Statistic Icmp6OutMsgs.
node_netstat_Icmp_InErrors unknown instance, ins, job, ip, cls Statistic IcmpInErrors.
node_netstat_Icmp_InMsgs unknown instance, ins, job, ip, cls Statistic IcmpInMsgs.
node_netstat_Icmp_OutMsgs unknown instance, ins, job, ip, cls Statistic IcmpOutMsgs.
node_netstat_Ip6_InOctets unknown instance, ins, job, ip, cls Statistic Ip6InOctets.
node_netstat_Ip6_OutOctets unknown instance, ins, job, ip, cls Statistic Ip6OutOctets.
node_netstat_IpExt_InOctets unknown instance, ins, job, ip, cls Statistic IpExtInOctets.
node_netstat_IpExt_OutOctets unknown instance, ins, job, ip, cls Statistic IpExtOutOctets.
node_netstat_Ip_Forwarding unknown instance, ins, job, ip, cls Statistic IpForwarding.
node_netstat_TcpExt_ListenDrops unknown instance, ins, job, ip, cls Statistic TcpExtListenDrops.
node_netstat_TcpExt_ListenOverflows unknown instance, ins, job, ip, cls Statistic TcpExtListenOverflows.
node_netstat_TcpExt_SyncookiesFailed unknown instance, ins, job, ip, cls Statistic TcpExtSyncookiesFailed.
node_netstat_TcpExt_SyncookiesRecv unknown instance, ins, job, ip, cls Statistic TcpExtSyncookiesRecv.
node_netstat_TcpExt_SyncookiesSent unknown instance, ins, job, ip, cls Statistic TcpExtSyncookiesSent.
node_netstat_TcpExt_TCPSynRetrans unknown instance, ins, job, ip, cls Statistic TcpExtTCPSynRetrans.
node_netstat_TcpExt_TCPTimeouts unknown instance, ins, job, ip, cls Statistic TcpExtTCPTimeouts.
node_netstat_Tcp_ActiveOpens unknown instance, ins, job, ip, cls Statistic TcpActiveOpens.
node_netstat_Tcp_CurrEstab unknown instance, ins, job, ip, cls Statistic TcpCurrEstab.
node_netstat_Tcp_InErrs unknown instance, ins, job, ip, cls Statistic TcpInErrs.
node_netstat_Tcp_InSegs unknown instance, ins, job, ip, cls Statistic TcpInSegs.
node_netstat_Tcp_OutRsts unknown instance, ins, job, ip, cls Statistic TcpOutRsts.
node_netstat_Tcp_OutSegs unknown instance, ins, job, ip, cls Statistic TcpOutSegs.
node_netstat_Tcp_PassiveOpens unknown instance, ins, job, ip, cls Statistic TcpPassiveOpens.
node_netstat_Tcp_RetransSegs unknown instance, ins, job, ip, cls Statistic TcpRetransSegs.
node_netstat_Udp6_InDatagrams unknown instance, ins, job, ip, cls Statistic Udp6InDatagrams.
node_netstat_Udp6_InErrors unknown instance, ins, job, ip, cls Statistic Udp6InErrors.
node_netstat_Udp6_NoPorts unknown instance, ins, job, ip, cls Statistic Udp6NoPorts.
node_netstat_Udp6_OutDatagrams unknown instance, ins, job, ip, cls Statistic Udp6OutDatagrams.
node_netstat_Udp6_RcvbufErrors unknown instance, ins, job, ip, cls Statistic Udp6RcvbufErrors.
node_netstat_Udp6_SndbufErrors unknown instance, ins, job, ip, cls Statistic Udp6SndbufErrors.
node_netstat_UdpLite6_InErrors unknown instance, ins, job, ip, cls Statistic UdpLite6InErrors.
node_netstat_UdpLite_InErrors unknown instance, ins, job, ip, cls Statistic UdpLiteInErrors.
node_netstat_Udp_InDatagrams unknown instance, ins, job, ip, cls Statistic UdpInDatagrams.
node_netstat_Udp_InErrors unknown instance, ins, job, ip, cls Statistic UdpInErrors.
node_netstat_Udp_NoPorts unknown instance, ins, job, ip, cls Statistic UdpNoPorts.
node_netstat_Udp_OutDatagrams unknown instance, ins, job, ip, cls Statistic UdpOutDatagrams.
node_netstat_Udp_RcvbufErrors unknown instance, ins, job, ip, cls Statistic UdpRcvbufErrors.
node_netstat_Udp_SndbufErrors unknown instance, ins, job, ip, cls Statistic UdpSndbufErrors.
node_network_address_assign_type gauge ip, device, ins, job, instance, cls Network device property: address_assign_type
node_network_carrier gauge ip, device, ins, job, instance, cls Network device property: carrier
node_network_carrier_changes_total counter ip, device, ins, job, instance, cls Network device property: carrier_changes_total
node_network_carrier_down_changes_total counter ip, device, ins, job, instance, cls Network device property: carrier_down_changes_total
node_network_carrier_up_changes_total counter ip, device, ins, job, instance, cls Network device property: carrier_up_changes_total
node_network_device_id gauge ip, device, ins, job, instance, cls Network device property: device_id
node_network_dormant gauge ip, device, ins, job, instance, cls Network device property: dormant
node_network_flags gauge ip, device, ins, job, instance, cls Network device property: flags
node_network_iface_id gauge ip, device, ins, job, instance, cls Network device property: iface_id
node_network_iface_link gauge ip, device, ins, job, instance, cls Network device property: iface_link
node_network_iface_link_mode gauge ip, device, ins, job, instance, cls Network device property: iface_link_mode
node_network_info gauge broadcast, ip, device, operstate, ins, job, adminstate, duplex, address, instance, cls Non-numeric data from /sys/class/net/, value is always 1.
node_network_mtu_bytes gauge ip, device, ins, job, instance, cls Network device property: mtu_bytes
node_network_name_assign_type gauge ip, device, ins, job, instance, cls Network device property: name_assign_type
node_network_net_dev_group gauge ip, device, ins, job, instance, cls Network device property: net_dev_group
node_network_protocol_type gauge ip, device, ins, job, instance, cls Network device property: protocol_type
node_network_receive_bytes_total counter ip, device, ins, job, instance, cls Network device statistic receive_bytes.
node_network_receive_compressed_total counter ip, device, ins, job, instance, cls Network device statistic receive_compressed.
node_network_receive_drop_total counter ip, device, ins, job, instance, cls Network device statistic receive_drop.
node_network_receive_errs_total counter ip, device, ins, job, instance, cls Network device statistic receive_errs.
node_network_receive_fifo_total counter ip, device, ins, job, instance, cls Network device statistic receive_fifo.
node_network_receive_frame_total counter ip, device, ins, job, instance, cls Network device statistic receive_frame.
node_network_receive_multicast_total counter ip, device, ins, job, instance, cls Network device statistic receive_multicast.
node_network_receive_nohandler_total counter ip, device, ins, job, instance, cls Network device statistic receive_nohandler.
node_network_receive_packets_total counter ip, device, ins, job, instance, cls Network device statistic receive_packets.
node_network_speed_bytes gauge ip, device, ins, job, instance, cls Network device property: speed_bytes
node_network_transmit_bytes_total counter ip, device, ins, job, instance, cls Network device statistic transmit_bytes.
node_network_transmit_carrier_total counter ip, device, ins, job, instance, cls Network device statistic transmit_carrier.
node_network_transmit_colls_total counter ip, device, ins, job, instance, cls Network device statistic transmit_colls.
node_network_transmit_compressed_total counter ip, device, ins, job, instance, cls Network device statistic transmit_compressed.
node_network_transmit_drop_total counter ip, device, ins, job, instance, cls Network device statistic transmit_drop.
node_network_transmit_errs_total counter ip, device, ins, job, instance, cls Network device statistic transmit_errs.
node_network_transmit_fifo_total counter ip, device, ins, job, instance, cls Network device statistic transmit_fifo.
node_network_transmit_packets_total counter ip, device, ins, job, instance, cls Network device statistic transmit_packets.
node_network_transmit_queue_length gauge ip, device, ins, job, instance, cls Network device property: transmit_queue_length
node_network_up gauge ip, device, ins, job, instance, cls Value is 1 if operstate is ‘up’, 0 otherwise.
node_nf_conntrack_entries gauge instance, ins, job, ip, cls Number of currently allocated flow entries for connection tracking.
node_nf_conntrack_entries_limit gauge instance, ins, job, ip, cls Maximum size of connection tracking table.
node_nf_conntrack_stat_drop gauge instance, ins, job, ip, cls Number of packets dropped due to conntrack failure.
node_nf_conntrack_stat_early_drop gauge instance, ins, job, ip, cls Number of dropped conntrack entries to make room for new ones, if maximum table size was reached.
node_nf_conntrack_stat_found gauge instance, ins, job, ip, cls Number of searched entries which were successful.
node_nf_conntrack_stat_ignore gauge instance, ins, job, ip, cls Number of packets seen which are already connected to a conntrack entry.
node_nf_conntrack_stat_insert gauge instance, ins, job, ip, cls Number of entries inserted into the list.
node_nf_conntrack_stat_insert_failed gauge instance, ins, job, ip, cls Number of entries for which list insertion was attempted but failed.
node_nf_conntrack_stat_invalid gauge instance, ins, job, ip, cls Number of packets seen which can not be tracked.
node_nf_conntrack_stat_search_restart gauge instance, ins, job, ip, cls Number of conntrack table lookups which had to be restarted due to hashtable resizes.
node_os_info gauge id, ip, version, version_id, ins, instance, job, pretty_name, id_like, cls A metric with a constant ‘1’ value labeled by build_id, id, id_like, image_id, image_version, name, pretty_name, variant, variant_id, version, version_codename, version_id.
node_os_version gauge id, ip, ins, instance, job, id_like, cls Metric containing the major.minor part of the OS version.
node_processes_max_processes gauge instance, ins, job, ip, cls Number of max PIDs limit
node_processes_max_threads gauge instance, ins, job, ip, cls Limit of threads in the system
node_processes_pids gauge instance, ins, job, ip, cls Number of PIDs
node_processes_state gauge state, instance, ins, job, ip, cls Number of processes in each state.
node_processes_threads gauge instance, ins, job, ip, cls Allocated threads in system
node_processes_threads_state gauge instance, ins, job, thread_state, ip, cls Number of threads in each state.
node_procs_blocked gauge instance, ins, job, ip, cls Number of processes blocked waiting for I/O to complete.
node_procs_running gauge instance, ins, job, ip, cls Number of processes in runnable state.
node_schedstat_running_seconds_total counter ip, ins, job, cpu, instance, cls Number of seconds CPU spent running a process.
node_schedstat_timeslices_total counter ip, ins, job, cpu, instance, cls Number of timeslices executed by CPU.
node_schedstat_waiting_seconds_total counter ip, ins, job, cpu, instance, cls Number of seconds spent by processing waiting for this CPU.
node_scrape_collector_duration_seconds gauge ip, collector, ins, job, instance, cls node_exporter: Duration of a collector scrape.
node_scrape_collector_success gauge ip, collector, ins, job, instance, cls node_exporter: Whether a collector succeeded.
node_selinux_enabled gauge instance, ins, job, ip, cls SELinux is enabled, 1 is true, 0 is false
node_sockstat_FRAG6_inuse gauge instance, ins, job, ip, cls Number of FRAG6 sockets in state inuse.
node_sockstat_FRAG6_memory gauge instance, ins, job, ip, cls Number of FRAG6 sockets in state memory.
node_sockstat_FRAG_inuse gauge instance, ins, job, ip, cls Number of FRAG sockets in state inuse.
node_sockstat_FRAG_memory gauge instance, ins, job, ip, cls Number of FRAG sockets in state memory.
node_sockstat_RAW6_inuse gauge instance, ins, job, ip, cls Number of RAW6 sockets in state inuse.
node_sockstat_RAW_inuse gauge instance, ins, job, ip, cls Number of RAW sockets in state inuse.
node_sockstat_TCP6_inuse gauge instance, ins, job, ip, cls Number of TCP6 sockets in state inuse.
node_sockstat_TCP_alloc gauge instance, ins, job, ip, cls Number of TCP sockets in state alloc.
node_sockstat_TCP_inuse gauge instance, ins, job, ip, cls Number of TCP sockets in state inuse.
node_sockstat_TCP_mem gauge instance, ins, job, ip, cls Number of TCP sockets in state mem.
node_sockstat_TCP_mem_bytes gauge instance, ins, job, ip, cls Number of TCP sockets in state mem_bytes.
node_sockstat_TCP_orphan gauge instance, ins, job, ip, cls Number of TCP sockets in state orphan.
node_sockstat_TCP_tw gauge instance, ins, job, ip, cls Number of TCP sockets in state tw.
node_sockstat_UDP6_inuse gauge instance, ins, job, ip, cls Number of UDP6 sockets in state inuse.
node_sockstat_UDPLITE6_inuse gauge instance, ins, job, ip, cls Number of UDPLITE6 sockets in state inuse.
node_sockstat_UDPLITE_inuse gauge instance, ins, job, ip, cls Number of UDPLITE sockets in state inuse.
node_sockstat_UDP_inuse gauge instance, ins, job, ip, cls Number of UDP sockets in state inuse.
node_sockstat_UDP_mem gauge instance, ins, job, ip, cls Number of UDP sockets in state mem.
node_sockstat_UDP_mem_bytes gauge instance, ins, job, ip, cls Number of UDP sockets in state mem_bytes.
node_sockstat_sockets_used gauge instance, ins, job, ip, cls Number of IPv4 sockets in use.
node_tcp_connection_states gauge state, instance, ins, job, ip, cls Number of connection states.
node_textfile_scrape_error gauge instance, ins, job, ip, cls 1 if there was an error opening or reading a file, 0 otherwise
node_time_clocksource_available_info gauge ip, device, ins, clocksource, job, instance, cls Available clocksources read from ‘/sys/devices/system/clocksource’.
node_time_clocksource_current_info gauge ip, device, ins, clocksource, job, instance, cls Current clocksource read from ‘/sys/devices/system/clocksource’.
node_time_seconds gauge instance, ins, job, ip, cls System time in seconds since epoch (1970).
node_time_zone_offset_seconds gauge instance, ins, job, time_zone, ip, cls System time zone offset in seconds.
node_timex_estimated_error_seconds gauge instance, ins, job, ip, cls Estimated error in seconds.
node_timex_frequency_adjustment_ratio gauge instance, ins, job, ip, cls Local clock frequency adjustment.
node_timex_loop_time_constant gauge instance, ins, job, ip, cls Phase-locked loop time constant.
node_timex_maxerror_seconds gauge instance, ins, job, ip, cls Maximum error in seconds.
node_timex_offset_seconds gauge instance, ins, job, ip, cls Time offset in between local system and reference clock.
node_timex_pps_calibration_total counter instance, ins, job, ip, cls Pulse per second count of calibration intervals.
node_timex_pps_error_total counter instance, ins, job, ip, cls Pulse per second count of calibration errors.
node_timex_pps_frequency_hertz gauge instance, ins, job, ip, cls Pulse per second frequency.
node_timex_pps_jitter_seconds gauge instance, ins, job, ip, cls Pulse per second jitter.
node_timex_pps_jitter_total counter instance, ins, job, ip, cls Pulse per second count of jitter limit exceeded events.
node_timex_pps_shift_seconds gauge instance, ins, job, ip, cls Pulse per second interval duration.
node_timex_pps_stability_exceeded_total counter instance, ins, job, ip, cls Pulse per second count of stability limit exceeded events.
node_timex_pps_stability_hertz gauge instance, ins, job, ip, cls Pulse per second stability, average of recent frequency changes.
node_timex_status gauge instance, ins, job, ip, cls Value of the status array bits.
node_timex_sync_status gauge instance, ins, job, ip, cls Is clock synchronized to a reliable server (1 = yes, 0 = no).
node_timex_tai_offset_seconds gauge instance, ins, job, ip, cls International Atomic Time (TAI) offset.
node_timex_tick_seconds gauge instance, ins, job, ip, cls Seconds between clock ticks.
node_udp_queues gauge ip, queue, ins, job, exported_ip, instance, cls Number of allocated memory in the kernel for UDP datagrams in bytes.
node_uname_info gauge ip, sysname, version, domainname, release, ins, job, nodename, instance, cls, machine Labeled system information as provided by the uname system call.
node_up Unknown instance, ins, job, ip, cls N/A
node_vmstat_oom_kill unknown instance, ins, job, ip, cls /proc/vmstat information field oom_kill.
node_vmstat_pgfault unknown instance, ins, job, ip, cls /proc/vmstat information field pgfault.
node_vmstat_pgmajfault unknown instance, ins, job, ip, cls /proc/vmstat information field pgmajfault.
node_vmstat_pgpgin unknown instance, ins, job, ip, cls /proc/vmstat information field pgpgin.
node_vmstat_pgpgout unknown instance, ins, job, ip, cls /proc/vmstat information field pgpgout.
node_vmstat_pswpin unknown instance, ins, job, ip, cls /proc/vmstat information field pswpin.
node_vmstat_pswpout unknown instance, ins, job, ip, cls /proc/vmstat information field pswpout.
process_cpu_seconds_total counter instance, ins, job, ip, cls Total user and system CPU time spent in seconds.
process_max_fds gauge instance, ins, job, ip, cls Maximum number of open file descriptors.
process_open_fds gauge instance, ins, job, ip, cls Number of open file descriptors.
process_resident_memory_bytes gauge instance, ins, job, ip, cls Resident memory size in bytes.
process_start_time_seconds gauge instance, ins, job, ip, cls Start time of the process since unix epoch in seconds.
process_virtual_memory_bytes gauge instance, ins, job, ip, cls Virtual memory size in bytes.
process_virtual_memory_max_bytes gauge instance, ins, job, ip, cls Maximum amount of virtual memory available in bytes.
prometheus_remote_storage_exemplars_in_total counter instance, ins, job, ip, cls Exemplars in to remote storage, compare to exemplars out for queue managers.
prometheus_remote_storage_histograms_in_total counter instance, ins, job, ip, cls HistogramSamples in to remote storage, compare to histograms out for queue managers.
prometheus_remote_storage_samples_in_total counter instance, ins, job, ip, cls Samples in to remote storage, compare to samples out for queue managers.
prometheus_remote_storage_string_interner_zero_reference_releases_total counter instance, ins, job, ip, cls The number of times release has been called for strings that are not interned.
prometheus_sd_azure_failures_total counter instance, ins, job, ip, cls Number of Azure service discovery refresh failures.
prometheus_sd_consul_rpc_duration_seconds summary ip, call, quantile, ins, job, instance, cls, endpoint The duration of a Consul RPC call in seconds.
prometheus_sd_consul_rpc_duration_seconds_count Unknown ip, call, ins, job, instance, cls, endpoint N/A
prometheus_sd_consul_rpc_duration_seconds_sum Unknown ip, call, ins, job, instance, cls, endpoint N/A
prometheus_sd_consul_rpc_failures_total counter instance, ins, job, ip, cls The number of Consul RPC call failures.
prometheus_sd_consulagent_rpc_duration_seconds summary ip, call, quantile, ins, job, instance, cls, endpoint The duration of a Consul Agent RPC call in seconds.
prometheus_sd_consulagent_rpc_duration_seconds_count Unknown ip, call, ins, job, instance, cls, endpoint N/A
prometheus_sd_consulagent_rpc_duration_seconds_sum Unknown ip, call, ins, job, instance, cls, endpoint N/A
prometheus_sd_consulagent_rpc_failures_total Unknown instance, ins, job, ip, cls N/A
prometheus_sd_dns_lookup_failures_total counter instance, ins, job, ip, cls The number of DNS-SD lookup failures.
prometheus_sd_dns_lookups_total counter instance, ins, job, ip, cls The number of DNS-SD lookups.
prometheus_sd_file_read_errors_total counter instance, ins, job, ip, cls The number of File-SD read errors.
prometheus_sd_file_scan_duration_seconds summary quantile, instance, ins, job, ip, cls The duration of the File-SD scan in seconds.
prometheus_sd_file_scan_duration_seconds_count Unknown instance, ins, job, ip, cls N/A
prometheus_sd_file_scan_duration_seconds_sum Unknown instance, ins, job, ip, cls N/A
prometheus_sd_file_watcher_errors_total counter instance, ins, job, ip, cls The number of File-SD errors caused by filesystem watch failures.
prometheus_sd_kubernetes_events_total counter ip, event, ins, job, role, instance, cls The number of Kubernetes events handled.
prometheus_target_scrape_pool_exceeded_label_limits_total counter instance, ins, job, ip, cls Total number of times scrape pools hit the label limits, during sync or config reload.
prometheus_target_scrape_pool_exceeded_target_limit_total counter instance, ins, job, ip, cls Total number of times scrape pools hit the target limit, during sync or config reload.
prometheus_target_scrape_pool_reloads_failed_total counter instance, ins, job, ip, cls Total number of failed scrape pool reloads.
prometheus_target_scrape_pool_reloads_total counter instance, ins, job, ip, cls Total number of scrape pool reloads.
prometheus_target_scrape_pools_failed_total counter instance, ins, job, ip, cls Total number of scrape pool creations that failed.
prometheus_target_scrape_pools_total counter instance, ins, job, ip, cls Total number of scrape pool creation attempts.
prometheus_target_scrapes_cache_flush_forced_total counter instance, ins, job, ip, cls How many times a scrape cache was flushed due to getting big while scrapes are failing.
prometheus_target_scrapes_exceeded_body_size_limit_total counter instance, ins, job, ip, cls Total number of scrapes that hit the body size limit
prometheus_target_scrapes_exceeded_sample_limit_total counter instance, ins, job, ip, cls Total number of scrapes that hit the sample limit and were rejected.
prometheus_target_scrapes_exemplar_out_of_order_total counter instance, ins, job, ip, cls Total number of exemplar rejected due to not being out of the expected order.
prometheus_target_scrapes_sample_duplicate_timestamp_total counter instance, ins, job, ip, cls Total number of samples rejected due to duplicate timestamps but different values.
prometheus_target_scrapes_sample_out_of_bounds_total counter instance, ins, job, ip, cls Total number of samples rejected due to timestamp falling outside of the time bounds.
prometheus_target_scrapes_sample_out_of_order_total counter instance, ins, job, ip, cls Total number of samples rejected due to not being out of the expected order.
prometheus_template_text_expansion_failures_total counter instance, ins, job, ip, cls The total number of template text expansion failures.
prometheus_template_text_expansions_total counter instance, ins, job, ip, cls The total number of template text expansions.
prometheus_treecache_watcher_goroutines gauge instance, ins, job, ip, cls The current number of watcher goroutines.
prometheus_treecache_zookeeper_failures_total counter instance, ins, job, ip, cls The total number of ZooKeeper failures.
promhttp_metric_handler_errors_total counter ip, cause, ins, job, instance, cls Total number of internal errors encountered by the promhttp metric handler.
promhttp_metric_handler_requests_in_flight gauge instance, ins, job, ip, cls Current number of scrapes being served.
promhttp_metric_handler_requests_total counter ip, ins, code, job, instance, cls Total number of scrapes by HTTP status code.
request_duration_seconds_bucket Unknown instance, ins, job, status_code, route, ws, le, ip, cls, method N/A
request_duration_seconds_count Unknown instance, ins, job, status_code, route, ws, ip, cls, method N/A
request_duration_seconds_sum Unknown instance, ins, job, status_code, route, ws, ip, cls, method N/A
request_message_bytes_bucket Unknown instance, ins, job, route, le, ip, cls, method N/A
request_message_bytes_count Unknown instance, ins, job, route, ip, cls, method N/A
request_message_bytes_sum Unknown instance, ins, job, route, ip, cls, method N/A
response_message_bytes_bucket Unknown instance, ins, job, route, le, ip, cls, method N/A
response_message_bytes_count Unknown instance, ins, job, route, ip, cls, method N/A
response_message_bytes_sum Unknown instance, ins, job, route, ip, cls, method N/A
scrape_duration_seconds Unknown instance, ins, job, ip, cls N/A
scrape_samples_post_metric_relabeling Unknown instance, ins, job, ip, cls N/A
scrape_samples_scraped Unknown instance, ins, job, ip, cls N/A
scrape_series_added Unknown instance, ins, job, ip, cls N/A
tcp_connections gauge instance, ins, job, protocol, ip, cls Current number of accepted TCP connections.
tcp_connections_limit gauge instance, ins, job, protocol, ip, cls The max number of TCP connections that can be accepted (0 means no limit).
up Unknown instance, ins, job, ip, cls N/A

10.7 - 常见问题

Pigsty NODE 主机节点模块常见问题答疑

如何配置主机节点上的NTP服务?

NTP 对于生产环境各项服务非常重要,如果没有配置 NTP,您可以使用公共 NTP 服务,或管理节点上的 Chronyd 作为标准时间。

如果您的节点已经配置了 NTP,可以通过设置 node_ntp_enabledfalse 来保留现有配置,不进行任何变更。

否则,如果您有互联网访问权限,可以使用公共 NTP 服务,例如 pool.ntp.org

如果您没有互联网访问权限,可以使用以下方式,确保所有环境内的节点与管理节点时间是同步的,或者使用其他内网环境的 NTP 授时服务。

node_ntp_servers:                 # /etc/chrony.conf 中的 ntp 服务器列表
  - pool cn.pool.ntp.org iburst
  - pool ${admin_ip} iburst       # 假设其他节点都没有互联网访问,那么至少与 Admin 节点保持时间同步。

如何在节点上强制同步时间?

为了使用 chronyc 来同步时间。您首先需要配置 NTP 服务。

ansible all -b -a 'chronyc -a makestep'     # 同步时间

您可以用任何组或主机 IP 地址替换 all,以限制执行范围。


远程节点无法通过SSH访问怎么办?

如果目标机器隐藏在 SSH 跳板机后面, 或者进行了一些无法直接使用 ssh ip 访问的自定义操作, 可以使用诸如 ansible_portansible_host 这一类 Ansible连接参数 来指定各种 SSH 连接信息,如下所示:

pg-test:
  vars: { pg_cluster: pg-test }
  hosts:
    10.10.10.11: {pg_seq: 1, pg_role: primary, ansible_host: node-1 }
    10.10.10.12: {pg_seq: 2, pg_role: replica, ansible_port: 22223, ansible_user: admin }
    10.10.10.13: {pg_seq: 3, pg_role: offline, ansible_port: 22224 }

远程节点SSH与SUDO需要密码怎么办?

执行部署和更改时,使用的管理员用户 必须 对所有节点拥有 sshsudo 权限。无需密码免密登录。

您可以在执行剧本时通过 -k|-K 参数传入 ssh 和 sudo 密码,甚至可以通过 -e ansible_user=<another_user> 使用另一个用户来运行剧本。

但是,Pigsty 强烈建议为管理员用户配置 SSH 无密码登录 以及无密码的 sudo


如何使用现有管理员创建专用管理员用户?

使用以下命令,使用该节点上现有的管理员用户,创建由 node_admin_username 定义的新的标准的管理员用户。

./node.yml -k -K -e ansible_user=<another_admin> -t node_admin

如何使用节点上的HAProxy对外暴露服务?

您可以在配置中中使用 haproxy_services 来暴露服务,并使用 node.yml -t haproxy_config,haproxy_reload 来更新配置。

以下是使用它暴露 Silo 服务的示例:Silo 服务接入


为什么我的 /etc/yum.repos.d/* 全没了?

Pigsty 会在 infra 节点上构建的本地软件仓库源中包含所有依赖项。而所有普通节点会根据 node_repo_modules 的默认配置 local 来引用并使用 Infra 节点上的本地软件源。

这一设计从而避免了互联网访问,增强了安装过程的稳定性与可靠性。所有原有的源定义文件会被移动到 /etc/yum.repos.d/backup 目录中,您只要按需复制回来即可。

如果您想在普通节点安装过程中保留原有的源定义文件,将 node_repo_remove 设置为 false 即可。

如果您想在 Infra 节点构建本地源的过程中保留原有的源定义文件,将 repo_remove 设置为 false 即可。


为什么我的命令行提示符变样了?怎么恢复?

Pigsty 使用的 Shell 命令行提示符是由环境变量 PS1 指定,定义在 /etc/profile.d/node.sh 文件中。

如果您不喜欢,想要修改或恢复原样,可以将这个文件移除,重新登陆即可。


为什么我的主机名变了?

在两种情况下,Pigsty 会修改您的节点主机名:

  • 显式定义了 nodename 的值(默认为空)
  • 节点上声明了 PGSQL 模块,且启用了 node_id_from_pg 参数(默认为 true

如果您不希望修改主机名,可以在全局/集群/实例层面修改 nodename_overwrite 参数为 false (默认值为 true)。

详情请参考 NODE_ID 一节。


腾讯云的 OpenCloudOS 有什么兼容性问题?

OpenCloudOS 上的 softdog 内核模块不可用,需要从 node_kernel_modules 中移除。在配置文件全局变量中添加以下配置项以覆盖:

node_kernel_modules: [ ip_vs, ip_vs_rr, ip_vs_wrr, ip_vs_sh ]

Debian 系统有哪些常见问题?

在 Debian/Ubuntu 系统上使用 Pigsty 时,可能遇到以下问题:

本地语言环境缺失

如果系统提示 locale 相关错误,可以使用以下命令修复:

localedef -i en_US -f UTF-8 en_US.UTF-8

缺少 rsync 工具

Pigsty 依赖 rsync 进行文件同步,如果系统未安装,可以使用以下命令安装:

apt-get install rsync

11 - 模块:ETCD

Pigsty 可部署 etcd 模块,作为 DCS 为 PostgreSQL 高可用提供可靠的分布式配置存储支持。

ETCD 是一个分布式的、可靠的键-值存储,用于存放系统中最为关键的配置数据。

Pigsty 使用 etcd 作为 DCS(分布式配置存储),它对于 PostgreSQL 的高可用性与自动故障转移至关重要。

ETCD 模块依赖 NODE 模块,同时被 PGSQL 模块依赖。因此在安装 ETCD 模块之前,您需要安装 NODE 模块将节点纳管。 在部署任何 PGSQL 集群之前,你必须先部署一套 ETCD 集群,因为 PostgreSQL 高可用所需的 patronivip-manager 会依赖 etcd 实现高可用与 L2 VIP 主库绑定。

flowchart LR
    subgraph PGSQL [PGSQL]
        patroni[Patroni]
        vip[VIP Manager]
    end
    
    subgraph ETCD [ETCD]
        etcd[DCS 服务]
    end
    
    subgraph NODE [NODE]
        node[软件仓库]
    end
    
    PGSQL -->|依赖| ETCD -->|依赖| NODE
    
    style PGSQL fill:#3E668F,stroke:#2d4a66,color:#fff
    style ETCD fill:#5B9CD5,stroke:#4178a8,color:#fff
    style NODE fill:#FCDB72,stroke:#d4b85e,color:#333
    
    style patroni fill:#2d4a66,stroke:#1e3347,color:#fff
    style vip fill:#2d4a66,stroke:#1e3347,color:#fff
    style etcd fill:#4178a8,stroke:#2d5a7a,color:#fff
    style node fill:#d4b85e,stroke:#b89a4a,color:#333

在一套 Pigsty 部署中,只需要一套 etcd 集群。同一套 etcd 集群可以为多套 PostgreSQL 集群提供 DCS 服务支持。 Pigsty 中的 etcd 默认启用 RBAC,不同 PostgreSQL 集群使用独立的用户名与密码访问 etcd,从而实现多租户管理隔离。 管理员使用 etcd root 用户,拥有对所有 PostgreSQL 集群的管理权限。

11.1 - 集群配置

根据需求场景选择合适的 Etcd 集群规模,并对外提供可靠的接入。

在部署 Etcd 之前,你需要在 配置清单 中定义一个 Etcd 集群,通常来说,你可以选择:

  • 单节点:没有高可用性,适用于开发、测试、演示,或者依赖外部 S3 备份进行 PITR 的无高可用单机部署
  • 三节点:具有基本的高可用性,可以容忍一个节点的故障,适用于中小规模的生产环境
  • 五节点:具有更好的高可用性,可以容忍两个节点的故障,适用于大规模生产环境

偶数成员的 Etcd 集群在技术上有效,但不会比少一个成员的奇数集群提高故障容忍数,反而会增加部署与仲裁成本。 因此,生产环境通常采用单节点、三节点或五节点;超过五节点的集群并不常见。

集群规模 仲裁数 容忍故障数 适用场景
1 节点 1 0 开发、测试、演示
3 节点 2 1 中小规模生产环境
5 节点 3 2 大规模生产环境
7 节点 4 3 特殊高可用需求

单节点

在 Pigsty 中,定义一个单例 Etcd 实例非常简单,只需要一行配置即可:

etcd: { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }

在 Pigsty 提供的所有单机配置模板中,都有这样一项,其中的占位 IP 地址:10.10.10.10 默认会被替换为当前管理节点的 IP。

除了 IP 地址外,这里唯一必要的参数是 etcd_seqetcd_cluster,它们会唯一标识每一个 Etcd 实例。


三节点

三节点的 Etcd 集群最为常见,它可以容忍一个节点的故障,适用于中小规模的生产环境。

例如,Pigsty 的三节点模板:triosafe 就使用了三节点的 Etcd 集群,如下所示:

etcd: 
  hosts:
    10.10.10.10: { etcd_seq: 1 }  # etcd_seq (etcd实例号)是必须指定的身份参数
    10.10.10.11: { etcd_seq: 2 }  # 实例号是正整数,一般从 0 或 1 开始依次分配
    10.10.10.12: { etcd_seq: 3 }  # 实例号应当终生不可变,一旦分配就不再回收使用。
  vars: # 集群层面的参数
    etcd_cluster: etcd    # 默认情况下,etcd 集群名就叫 etcd, 除非您想要部署多套 etcd 集群,否则不要改这个名字
    etcd_safeguard: false # 是否打开 etcd 的防误删安全保险? 在生产环境初始化完成后,可以考虑打开这个选项,避免误删。

五节点

五节点的 Etcd 集群可以容忍两个节点的故障,适用于大规模生产环境。

例如,Pigsty 的生产仿真模板:ha/simu 中就使用了一个五节点的 Etcd 集群:

etcd:
  hosts:
    10.10.10.21 : { etcd_seq: 1 }
    10.10.10.22 : { etcd_seq: 2 }
    10.10.10.23 : { etcd_seq: 3 }
    10.10.10.24 : { etcd_seq: 4 }
    10.10.10.25 : { etcd_seq: 5 }
  vars: { etcd_cluster: etcd    }

使用 etcd 的服务

目前 Pigsty 中使用 etcd 的服务有:

服务 用途 配置文件
Patroni PostgreSQL 高可用,存储集群状态和配置 /etc/patroni/patroni.yml
VIP-Manager 在 PostgreSQL 集群上绑定 L2 VIP /etc/default/vip-manager.yml

当 etcd 集群的成员信息发生永久性变更时,您应当 重载相关服务的配置,以确保服务能够正确访问 Etcd 集群。

更新 Patroni 的 etcd 端点引用

./pgsql.yml -t pg_conf                            # 重新生成 patroni 配置
ansible all -f 1 -b -a 'systemctl reload patroni' # 重新加载 patroni 配置

更新 VIP-Manager 的 etcd 端点引用(仅当使用 PGSQL L2 VIP 时需要):

./pgsql.yml -t pg_vip_config                           # 重新生成 vip-manager 配置
ansible all -f 1 -b -a 'systemctl restart vip-manager' # 重启 vip-manager

RBAC 认证配置

Pigsty 自 v4.0 起默认启用 etcd 的 RBAC 认证机制。相关配置参数:

参数 说明 默认值
etcd_root_password etcd root 用户密码 Etcd.Root
pg_etcd_password Patroni 连接 etcd 的密码 空(使用集群名)

生产环境建议

all:
  vars:
    etcd_root_password: 'YourSecureEtcdPassword'  # 修改默认密码

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_safeguard: true    # 生产环境开启防误删保护

文件系统布局

etcd 模块在目标主机上创建以下目录和文件:

路径 用途 权限
/etc/etcd/ 配置目录 0750, etcd:etcd
/etc/etcd/etcd.conf 主配置文件 0644, etcd:etcd
/etc/etcd/etcd.pass root 密码文件 0640, root:etcd
/etc/etcd/ca.crt CA 证书 0644, etcd:etcd
/etc/etcd/server.crt 服务器证书 0644, etcd:etcd
/etc/etcd/server.key 服务器私钥 0600, etcd:etcd
/var/lib/etcd/ 备用数据目录 0770, etcd:etcd
/data/etcd/ 主数据目录(可配置) 0700, etcd:etcd
/etc/profile.d/etcdctl.sh 客户端环境变量 0644, root:root
/etc/systemd/system/etcd.service Systemd 服务定义 0644, root:root

11.2 - 参数列表

ETCD 模块提供了 13 个配置参数,用于精细控制集群的行为表现。

ETCD 模块的参数列表,共有 13 个参数,分为两个部分:

  • ETCD:10 个参数,用于 etcd 集群的部署与配置
  • ETCD_REMOVE:3 个参数,控制 etcd 集群的移除
架构变化:Pigsty v3.6+

自 Pigsty v3.6 起,etcd.yml 剧本不再包含移除功能,移除相关参数已迁移至独立的 etcd_remove 角色。v4.0 起默认启用 RBAC 认证,新增 etcd_root_password 参数。


参数概览

ETCD 参数组用于 etcd 集群的部署与配置,包括实例标识、集群名称、数据目录、端口以及认证密码。

参数 类型 级别 说明
etcd_seq int I etcd 实例标识符,必填
etcd_cluster string C etcd 集群名,默认固定为 etcd
etcd_learner bool I/A 是否以 learner 模式初始化 etcd 实例?
etcd_data path C etcd 数据目录,默认为 /data/etcd
etcd_port port C etcd 客户端端口,默认为 2379
etcd_peer_port port C etcd 同伴端口,默认为 2380
etcd_init enum C etcd 初始集群状态,新建或已存在
etcd_election_timeout int C etcd 选举超时,默认为 1000ms
etcd_heartbeat_interval int C etcd 心跳间隔,默认为 100ms
etcd_root_password password G etcd root 用户密码,用于 RBAC 认证

ETCD_REMOVE 参数组控制 etcd 集群的移除行为,包括防误删保险、数据清理以及软件包卸载。

参数 类型 级别 说明
etcd_safeguard bool G/C/A true 时无条件拒绝移除操作
etcd_rm_data bool G/C/A 移除时是否删除 etcd 数据?默认为 true
etcd_rm_pkg bool G/C/A 移除时是否卸载 etcd 软件包?默认为 false

ETCD

本节包含 etcd 角色的参数, 这些是 etcd.yml 剧本使用的操作标志参数。

相关参数定义于 roles/etcd/defaults/main.yml

#etcd_seq: 1                      # etcd 实例标识符,需要显式指定(必填)
etcd_cluster: etcd                # etcd 集群和组名称,默认为 etcd
etcd_learner: false               # etcd 实例是否以 learner 模式运行?默认为 false
etcd_data: /data/etcd             # etcd 数据目录,默认为 /data/etcd
etcd_port: 2379                   # etcd 客户端端口,默认为 2379
etcd_peer_port: 2380              # etcd 对等端口,默认为 2380
etcd_init: new                    # etcd 初始集群状态,new 或 existing
etcd_election_timeout: 1000       # etcd 选举超时,默认为 1000ms
etcd_heartbeat_interval: 100      # etcd 心跳间隔,默认为 100ms
etcd_root_password: Etcd.Root     # etcd root 用户密码,用于 RBAC 认证(请修改!)

etcd_seq

参数名称: etcd_seq, 类型: int, 层次:I

etcd 实例标号, 这是必选参数,必须为每一个 etcd 实例指定一个唯一的标号。

以下是一个3节点 etcd 集群的示例,分配了 1 ~ 3 三个标号。

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 }  # use odd numbers
  vars: # cluster level parameter override roles/etcd
    etcd_cluster: etcd  # mark etcd cluster name etcd
    etcd_safeguard: false # safeguard against purging

etcd_cluster

参数名称: etcd_cluster, 类型: string, 层次:C

etcd 集群 & 分组名称,默认值为硬编码值 etcd

当您想要部署另外的 etcd 集群备用时,可以修改此参数并使用其他集群名。

etcd_learner

参数名称: etcd_learner, 类型: bool, 层次:I/A

是否以 learner 模式初始化 etcd 实例?默认值为 false

当设置为 true 时,etcd 实例将以 learner(学习者)模式初始化,这意味着该实例不能在 etcd 集群中参与投票选举。

使用场景

  • 集群扩容:向现有集群添加新成员时,使用 learner 模式可以避免在数据同步完成前影响集群的仲裁
  • 安全迁移:在滚动升级或迁移场景中,先以 learner 模式加入,确认数据同步完成后再提升

操作流程

  1. 设置 etcd_learner: true,以 learner 模式初始化新成员
  2. 等待数据同步完成(通过 etcdctl endpoint status 检查)
  3. 使用 etcdctl member promote <member_id> 将其提升为正式成员
注意

Learner 实例不计入集群仲裁成员数。例如,3 节点集群中有 1 个 learner,实际投票成员数为 2,不能容忍任何节点故障。

etcd_data

参数名称: etcd_data, 类型: path, 层次:C

etcd 数据目录,默认为 /data/etcd

etcd_port

参数名称: etcd_port, 类型: port, 层次:C

etcd 客户端端口号,默认为 2379

etcd_peer_port

参数名称: etcd_peer_port, 类型: port, 层次:C

etcd peer 端口,默认为 2380

etcd_init

参数名称: etcd_init, 类型: enum, 层次:C

etcd 初始集群状态,可以是 newexisting,默认值:new

可选值说明

说明 使用场景
new 创建新的 etcd 集群 首次部署、集群重建
existing 加入现有 etcd 集群 集群扩容、添加新成员

重要说明

扩容时必须使用 existing

向现有 etcd 集群添加新成员时,必须 设置 etcd_init=existing。否则新实例会尝试创建独立的新集群,导致脑裂或初始化失败。

使用示例

# 创建新集群(默认行为)
./etcd.yml

# 向现有集群添加新成员
./etcd.yml -l <new_ip> -e etcd_init=existing

# 或使用便捷脚本(自动设置 etcd_init=existing)
bin/etcd-add <new_ip>

etcd_election_timeout

参数名称: etcd_election_timeout, 类型: int, 层次:C

etcd 选举超时,默认为 1000 (毫秒),也就是 1 秒。

etcd_heartbeat_interval

参数名称: etcd_heartbeat_interval, 类型: int, 层次:C

etcd 心跳间隔,默认为 100 (毫秒)。

etcd_root_password

参数名称: etcd_root_password, 类型: password, 层次:G

etcd root 用户密码,用于 RBAC 认证,默认值为 Etcd.Root

Pigsty 自 v4.0 起默认启用 etcd 的 RBAC(基于角色的访问控制)认证机制。在集群初始化时,etcd_auth 任务会自动创建 root 用户并启用认证。

密码存储位置

  • 密码存储在 /etc/etcd/etcd.pass 文件中
  • 文件权限为 0640(root 所有,etcd 组可读)
  • etcdctl 环境变量脚本 /etc/profile.d/etcdctl.sh 会自动读取此文件

与其他组件的配合

  • Patroni 通过 pg_etcd_password 参数配置连接 etcd 的密码
  • 如果 pg_etcd_password 为空,Patroni 会使用集群名称作为密码(不推荐)
  • VIP-Manager 也需要使用相同的认证信息连接 etcd

安全建议

生产环境安全

在生产环境中,强烈建议修改默认密码 Etcd.Root。可以在全局配置或集群配置中设置:

etcd_root_password: 'YourSecurePassword'

使用 configure -g 参数可以自动生成并替换 etcd_root_password


ETCD_REMOVE

本节包含 etcd_remove 角色的参数, 这些是 etcd-rm.yml 剧本使用的操作标志参数。

相关参数定义于 roles/etcd_remove/defaults/main.yml

etcd_safeguard: false             # 为 true 时无条件拒绝移除操作
etcd_rm_data: true                # 移除时是否删除 etcd 数据和配置文件?
etcd_rm_pkg: false                # 移除时是否卸载 etcd 软件包?

etcd_safeguard

参数名称: etcd_safeguard, 类型: bool, 层次:G/C/A

防误删保险参数,默认值为 false。设置为 true 时,etcd-rm.yml 会在注销、退群、停服和删除之前直接中止;它是静态布尔开关,不会探测实例是否正在运行。 需要显式使用命令行参数 -e etcd_safeguard=false 才能覆盖。

使用建议

环境 建议值 说明
开发/测试 false 方便快速重建和测试
生产环境 true 防止误操作导致服务中断

紧急情况下,可以使用命令行参数覆盖配置:

./etcd-rm.yml -l etcd -e etcd_safeguard=false # 覆盖保险并移除目标 Etcd 集群

etcd_rm_data

参数名称: etcd_rm_data, 类型: bool, 层次:G/C/A

移除时是否删除 etcd 数据和配置文件?默认值为 true

启用此选项后,etcd-rm.yml 剧本在移除集群或成员时会同时删除以下内容:

  • /etc/etcd/ - 配置目录(包括证书和密码文件)
  • /var/lib/etcd/ - 备用数据目录
  • {{ etcd_data }} - 主数据目录(默认 /data/etcd
  • /etc/systemd/system/etcd.service - Systemd 服务单元文件
  • /etc/profile.d/etcdctl.sh - 客户端环境变量脚本
  • /etc/vector/etcd.yaml - Vector 日志采集配置

使用场景

场景 建议值 说明
彻底移除 true(默认) 完全清理,释放磁盘空间
仅停止服务 false 保留数据,便于故障排查或恢复
# 仅停止服务,保留数据
./etcd-rm.yml -l etcd -e etcd_rm_data=false

etcd_rm_pkg

参数名称: etcd_rm_pkg, 类型: bool, 层次:G/C/A

移除时是否卸载 etcd 软件包?默认值为 false

启用此选项后,etcd-rm.yml 剧本在移除集群或成员时会同时卸载 etcd 软件包。

使用场景

场景 建议值 说明
常规移除 false(默认) 保留软件包,便于快速重建
彻底清理 true 完全卸载,节省磁盘空间
# 移除时同时卸载软件包
./etcd-rm.yml -l etcd -e etcd_rm_pkg=true
提示

通常不需要卸载 etcd 软件包。保留软件包可以加快后续的重新部署速度,因为不需要重新下载和安装。

11.3 - 管理预案

etcd 集群管理 SOP:创建,销毁,扩缩容,更新配置,RBAC 配置的详细说明。

以下是一些常见的 etcd 管理任务 SOP(预案):

  • 创建集群:如何初始化 etcd 集群?
  • 销毁集群:如何销毁 etcd 集群?
  • 环境变量:如何配置 etcd 客户端,以访问 etcd 服务器集群?
  • RBAC 认证:如何使用 etcd 的 RBAC 认证?
  • 重载配置:如何更新客户端使用的 etcd 服务器成员列表?
  • 添加成员:如何向现有 etcd 集群添加新成员?
  • 移除成员:如何从 etcd 集群移除老成员?
  • 便捷脚本:使用 bin/etcd-addbin/etcd-rm 简化操作

更多问题请参考 FAQ:ETCD


创建集群

要创建一个集群,首先需要在 配置清单 中定义 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.yml 剧本即可。

./etcd.yml  # 初始化 etcd 集群
架构变化:Pigsty v3.6+

自 Pigsty v3.6 起,etcd.yml 剧本专注于集群安装和成员添加,不再包含移除功能。所有移除操作请使用独立的 etcd-rm.yml 剧本。

对于已初始化的生产环境 etcd 集群,可以打开防误删保护 etcd_safeguard,避免误删现有的 etcd 实例。


销毁集群

要销毁一个 Etcd 集群,请使用独立的 etcd-rm.yml 剧本。默认的 etcd_rm_data: true 会删除本机数据与配置;请先确认没有 PostgreSQL 集群仍将它用作 DCS,并核验近期备份和精确目标名。

./etcd-rm.yml -l etcd                            # 确认后销毁整个 etcd 集群
./etcd-rm.yml -l etcd -e etcd_safeguard=false   # 仅在清单已启用保险时显式覆盖

或使用便捷脚本:

bin/etcd-rm                           # 移除整个 etcd 集群

移除剧本会尊重 etcd_safeguard 防误删保险的配置。如果该参数设置为 true,剧本将在退群、注销、停服和删除之前中止;其默认值为 false,不能把未显式覆盖保险当作一次确认。

注意

在移除 etcd 集群之前,请确保没有 PostgreSQL 集群正在使用该 etcd 作为 DCS 服务。否则会导致 PostgreSQL 高可用功能失效。


环境变量

Pigsty 默认使用 etcd v3 API(v3.6+ 已移除 v2 API 支持)。Pigsty 会在 etcd 节点上自动配置环境变量脚本 /etc/profile.d/etcdctl.sh,登录后会自动加载。

以下是 etcd 客户端配置环境变量的示例:

alias e="etcdctl"
alias em="etcdctl member"
export ETCDCTL_ENDPOINTS=https://10.10.10.10:2379
export ETCDCTL_CACERT=/etc/etcd/ca.crt
export ETCDCTL_CERT=/etc/etcd/server.crt
export ETCDCTL_KEY=/etc/etcd/server.key

Pigsty 自 v4.0 起为 etcd 默认启用 RBAC 认证,当前版本仍需配置用户认证:

export ETCDCTL_USER="root:$(cat /etc/etcd/etcd.pass)"

配置好客户端环境变量后,你可以使用以下命令进行 etcd CRUD 操作:

e put a 10 ; e get a; e del a   # 基本 KV 操作
e member list                    # 列出集群成员
e endpoint health                # 检查端点健康状态
e endpoint status                # 查看端点状态

RBAC 认证

Pigsty 自 v4.0 起默认启用 etcd 的 RBAC(基于角色的访问控制)认证机制。在集群初始化时,etcd_auth 任务会自动创建 root 用户并启用认证。

root 用户密码etcd_root_password 参数指定,默认值为 Etcd.Root。密码存储在 /etc/etcd/etcd.pass 文件中,权限为 0640(root 所有,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_root_password: 'YourSecurePassword'  # 修改默认密码

客户端认证方式

# 方式一:使用环境变量(推荐,已自动配置在 /etc/profile.d/etcdctl.sh)
export ETCDCTL_USER="root:$(cat /etc/etcd/etcd.pass)"

# 方式二:在命令行中指定
etcdctl --user root:YourSecurePassword member list

重载配置

如果 etcd 集群的成员发生变化(添加或移除成员),我们需要刷新对 etcd 服务端点的引用。目前 Pigsty 中有以下几处 etcd 引用需要更新:

配置位置 配置文件 更新方式
etcd 成员配置 /etc/etcd/etcd.conf ./etcd.yml -t etcd_conf
etcdctl 环境变量 /etc/profile.d/etcdctl.sh ./etcd.yml -t etcd_config
Patroni DCS 配置 /etc/patroni/patroni.yml ./pgsql.yml -t pg_conf
VIP-Manager 配置 /etc/default/vip-manager.yml ./pgsql.yml -t pg_vip_config

刷新 etcd 成员配置文件

./etcd.yml -t etcd_conf                           # 刷新 /etc/etcd/etcd.conf
ansible etcd -f 1 -b -a 'systemctl restart etcd'  # 可选:逐一重启 etcd 实例

刷新 etcdctl 客户端环境变量

./etcd.yml -t etcd_config                         # 刷新 /etc/profile.d/etcdctl.sh

更新 Patroni DCS 端点配置

./pgsql.yml -t pg_conf                            # 重新生成 patroni 配置
ansible all -f 1 -b -a 'systemctl reload patroni' # 重新加载 patroni 配置

更新 VIP-Manager 端点配置(仅当使用 PGSQL L2 VIP 时需要):

./pgsql.yml -t pg_vip_config                           # 重新生成 vip-manager 配置
ansible all -f 1 -b -a 'systemctl restart vip-manager' # 重启 vip-manager
提示

使用 bin/etcd-addbin/etcd-rm 便捷脚本时,脚本会在操作完成后提示您需要执行的配置刷新命令。


添加成员

ETCD 参考: 添加成员

推荐方式:使用便捷脚本

使用 bin/etcd-add 脚本是向现有 etcd 集群添加新成员的 推荐方式

# 首先在配置清单中添加新成员定义,然后执行:
bin/etcd-add <ip>              # 添加单个新成员
bin/etcd-add <ip1> <ip2> ...   # 添加多个新成员

脚本会自动完成以下操作:

  • 验证 IP 地址有效性
  • 执行 etcd.yml 剧本(自动设置 etcd_init=existing
  • 提供安全警告和倒计时
  • 操作完成后提示配置刷新命令

手动方式:分步操作

向现有的 etcd 集群添加新成员需要以下步骤:

  1. 更新配置清单:将新实例添加到 etcd
  2. 通知集群:执行 etcdctl member add 命令(可选,剧本会自动执行)
  3. 初始化新成员:使用 etcd_init=existing 参数运行剧本
  4. 提升成员:将学习者提升为正式成员(可选,使用 etcd_learner=true 时需要)
  5. 重载配置:更新所有客户端的 etcd 端点引用
# 配置清单更新后,初始化新成员
./etcd.yml -l <new_ins_ip> -e etcd_init=existing

# 如果使用 learner 模式,需要手动提升
etcdctl member promote <new_ins_server_id>
重要

添加新成员时必须使用 etcd_init=existing 参数,否则新实例会尝试创建新集群而非加入现有集群。

详细步骤:向 etcd 集群添加成员

下面是具体操作的详细细节,让我们从一个单实例 etcd 集群开始:

etcd:
  hosts:
    10.10.10.10: { etcd_seq: 1 } # <--- 集群中原本存在的唯一实例
    10.10.10.11: { etcd_seq: 2 } # <--- 将此新成员定义添加到清单中
  vars: { etcd_cluster: etcd }

使用便捷脚本添加新成员(推荐):

$ bin/etcd-add 10.10.10.11

或者手动操作。首先使用 etcdctl member add 向现有 etcd 集群宣告新的学习者实例 etcd-2 即将到来:

$ etcdctl member add etcd-2 --learner=true --peer-urls=https://10.10.10.11:2380
Member 33631ba6ced84cf8 added to cluster 6646fbcf5debc68f

ETCD_NAME="etcd-2"
ETCD_INITIAL_CLUSTER="etcd-2=https://10.10.10.11:2380,etcd-1=https://10.10.10.10:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://10.10.10.11:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"

使用 etcdctl member list(或 em list)检查成员列表,我们可以看到一个 unstarted 新成员:

33631ba6ced84cf8, unstarted, , https://10.10.10.11:2380, , true       # 这里有一个未启动的新成员
429ee12c7fbab5c1, started, etcd-1, https://10.10.10.10:2380, https://10.10.10.10:2379, false

接下来使用 etcd.yml 剧本初始化新的 etcd 实例 etcd-2,完成后,我们可以看到新成员已经启动:

$ ./etcd.yml -l 10.10.10.11 -e etcd_init=existing    # 一定要添加 existing 参数
...
33631ba6ced84cf8, started, etcd-2, https://10.10.10.11:2380, https://10.10.10.11:2379, true
429ee12c7fbab5c1, started, etcd-1, https://10.10.10.10:2380, https://10.10.10.10:2379, false

新成员初始化完成并稳定运行后,可以将新成员从学习者提升为追随者:

$ etcdctl member promote 33631ba6ced84cf8   # 将学习者提升为追随者
Member 33631ba6ced84cf8 promoted in cluster 6646fbcf5debc68f

$ em list                # 再次检查,新成员已提升为正式成员
33631ba6ced84cf8, started, etcd-2, https://10.10.10.11:2380, https://10.10.10.11:2379, false
429ee12c7fbab5c1, started, etcd-1, https://10.10.10.10:2380, https://10.10.10.10:2379, false

新成员添加完成,请不要忘记 重载配置,让所有客户端也知道新成员的存在。

重复以上步骤,可以添加更多成员。记住,生产环境中至少要使用 3 个成员。


移除成员

推荐方式:使用便捷脚本

使用 bin/etcd-rm 脚本是从 etcd 集群移除成员的 推荐方式

bin/etcd-rm <ip>              # 移除指定成员
bin/etcd-rm <ip1> <ip2> ...   # 移除多个成员
bin/etcd-rm                   # 移除整个 etcd 集群

脚本会依次尝试以下操作:

  • 从集群中优雅地移除成员
  • 停止并禁用 etcd 服务
  • 清理数据和配置文件
  • 从监控系统中注销

底层移除角色会容忍部分退群与清理错误,因此脚本结束后仍必须核对 etcdctl member list、端点健康、剩余仲裁,以及目标服务和数据目录的实际状态。

手动方式:分步操作

要从 etcd 集群中删除一个成员实例,通常需要以下步骤:

  1. 保持成员仍在配置清单中:移除剧本需要清单里的 etcd_seq、集群成员和连接端点信息
  2. 清理实例:对目标运行 etcd-rm.yml;剧本会先尝试 member remove,再停服并按参数清理
  3. 更新配置清单:成功后再从配置清单中注释或删除该实例
  4. 重载引用:按 重载配置 刷新其余 etcd 成员及 Patroni/VIP-Manager 的端点
# 此时 <ip> 必须仍在 etcd 清单组中
./etcd-rm.yml -l <ip>                  # 自动退出集群并清理实例
# 成功后编辑 pigsty.yml 删除该成员,再刷新其余成员与客户端配置

不要在运行移除剧本前先从清单删除目标;etcd-rm.ymlhosts: etcd 将无法再选中它,也无法从清单推导实例身份和集群端点。 也不需要在移除剧本前后额外重复执行 etcdctl member remove

详细步骤:从 etcd 集群移除成员

让我们以一个 3 节点的 etcd 集群为例,从中移除 3 号实例。

方法一:使用便捷脚本(推荐)

$ bin/etcd-rm 10.10.10.12

脚本会尝试从集群中移除成员、停止服务并清理数据;结束后仍需按上文检查成员列表、仲裁与目标文件状态。

方法二:手动操作

首先保持待删除成员仍在清单中,使用移除剧本:

$ ./etcd-rm.yml -l 10.10.10.12

剧本会依次尝试以下操作:

  1. 获取成员列表并找到对应的成员 ID
  2. 执行 etcdctl member remove 从集群中踢除
  3. 停止 etcd 服务
  4. 清理数据和配置文件

剧本会自动查询成员 ID 并执行 member remove。只有在排障时需要手工完成这一步:

$ etcdctl member list
429ee12c7fbab5c1, started, etcd-1, https://10.10.10.10:2380, https://10.10.10.10:2379, false
33631ba6ced84cf8, started, etcd-2, https://10.10.10.11:2380, https://10.10.10.11:2379, false
93fcf23b220473fb, started, etcd-3, https://10.10.10.12:2380, https://10.10.10.12:2379, false  # <--- 移除这个

$ etcdctl member remove 93fcf23b220473fb  # 从集群中踢除
Member 93fcf23b220473fb removed from cluster 6646fbcf5debc68f

手工踢除后仍需在目标尚存于清单时运行 ./etcd-rm.yml -l 10.10.10.12 完成停服、注销和清理;其退出步骤找不到已删除的成员时会跳过。

确认成员已经离开现场集群、剩余成员保持仲裁且目标服务与文件符合预期后,才从配置清单中删除 10.10.10.12,并按 重载配置 刷新其余 Etcd 成员和所有客户端引用,移除成员至此完成。

重复以上步骤,可以移除更多成员,与 添加成员 配合使用,可以对 etcd 集群进行滚动升级搬迁。


便捷脚本

Pigsty v3.6+ 提供了便捷脚本简化 etcd 集群的扩容和缩容操作:

bin/etcd-add

向现有 etcd 集群添加新成员:

bin/etcd-add <ip>              # 添加单个新成员
bin/etcd-add <ip1> <ip2> ...   # 添加多个新成员

脚本功能:

  • 验证 IP 地址格式
  • 自动设置 etcd_init=existing 参数
  • 执行 etcd.yml 剧本完成成员添加
  • 操作完成后提示配置刷新命令

bin/etcd-rm

从 etcd 集群移除成员或整个集群:

bin/etcd-rm <ip>              # 移除指定成员
bin/etcd-rm <ip1> <ip2> ...   # 移除多个成员
bin/etcd-rm                   # 移除整个 etcd 集群

脚本功能:

  • 提供安全警告和确认倒计时
  • 自动执行 etcd-rm.yml 剧本
  • 优雅地从集群中移除成员
  • 清理数据和配置文件

管理 Etcd 密码

etcd_root_password 参数定义了 etcd 集群的 root 用户密码。

要修改此密码,你需要访问到 etcd 端点,例如在 INFRA节点ETCD节点 上使用 管理用户 执行:

e user passwd root  # 修改 etcd root 用户密码

然后你应该刷新所有对 etcd root 密码的引用,包括 INFRA 节点上的 Patroni 客户端配置与 etcdctl 客户端环境变量:

./infra.yml -t env_patroni    # 刷新 /infra/conf/patronictl.yml 对 etcd root 密码的引用
./etcd.yml  -t etcd_conf      # 刷新 /etc/etcd/etcd.pass 与 /etc/profile.d/etcdctl.sh

11.4 - 预置剧本

如何使用预置的 ansible 剧本来管理 Etcd 集群,常用管理命令速查。

Etcd 模块提供了两个核心剧本:etcd.yml 用于安装与配置 Etcd 集群,etcd-rm.yml 用于移除 Etcd 集群或成员。

架构变化:Pigsty v3.6+

自 Pigsty v3.6 起,etcd.yml 剧本专注于集群安装和成员添加,所有移除操作已迁移至独立的 etcd-rm.yml 剧本和 etcd_remove 角色。


etcd.yml

剧本原始文件:etcd.yml

执行本剧本,将会在硬编码的固定分组 etcd 上安装配置 Etcd 集群,并启动 etcd 服务。

etcd.yml 中,提供了以下是可用的任务子集:

  • etcd_assert:验证 etcd 身份参数(etcd_seq 必须定义且为非负整数)
  • etcd_install:安装 etcd 软件包
  • etcd_dir:创建 etcd 数据和配置目录
  • etcd_config:生成 etcd 配置
    • etcd_conf:生成 etcd 主配置文件 /etc/etcd/etcd.conf
    • etcd_cert:生成 etcd TLS 证书(CA、服务器证书、私钥)
  • etcd_member:将新成员添加到现有集群(仅当 etcd_init=existing 时执行)
  • etcd_launch:启动 etcd 服务
  • etcd_auth:启用 RBAC 认证(创建 root 用户并启用认证)
  • etcd_register:将 etcd 注册到 VictoriaMetrics 监控

etcd-rm.yml

剧本原始文件:etcd-rm.yml

用于移除 Etcd 集群或单个成员的专用剧本。在 etcd-rm.yml 中,提供了以下可用的任务子集:

  • etcd_safeguard:检查防误删保险,如果启用则中止执行
  • etcd_pause:暂停 3 秒,允许用户使用 Ctrl-C 中止执行
  • etcd_deregister:从 VictoriaMetrics 监控目标中移除 etcd 注册
  • etcd_leave:在清理前尝试优雅地离开 etcd 集群
  • etcd_svc:使用 systemd 停止并禁用 etcd 服务
  • etcd_data:移除 etcd 数据(可通过 etcd_rm_data=false 禁用)
  • etcd_pkg:卸载 etcd 软件包(需通过 etcd_rm_pkg=true 显式启用)

移除剧本使用 etcd_remove 角色,支持以下可配置参数:

  • etcd_safeguard:设置为 true 时阻止意外移除
  • etcd_rm_data:控制是否删除 ETCD 数据(默认:true
  • etcd_rm_pkg:控制是否卸载 ETCD 软件包(默认:false
危险操作

etcd_safeguard 默认是 falseetcd_rm_data 默认是 true。因此,完整执行 etcd-rm.yml 会尝试将目标退群、注销并停服,随后删除本机 Etcd 数据、配置、单元和客户端环境文件。 剧本会忽略部分退群与清理错误,也不会证明剩余成员仍有仲裁;每次都应使用精确的 -l,并核对近期备份、成员列表与剩余仲裁。


执行演示

asciicast


命令速查

Etcd 安装与配置:

./etcd.yml                                      # 初始化 etcd 集群
./etcd.yml -t etcd_launch                       # 重启整个 etcd 集群
./etcd.yml -t etcd_conf                         # 使用最新状态刷新 /etc/etcd/etcd.conf
./etcd.yml -t etcd_cert                         # 重新生成 etcd TLS 证书
./etcd.yml -l 10.10.10.12 -e etcd_init=existing # 扩容节点:添加新成员到现有集群

Etcd 移除与清理:

./etcd-rm.yml -l 10.10.10.12                     # 退群、注销、停服并默认删除本机数据
./etcd-rm.yml -l 10.10.10.12 -e etcd_rm_data=false # 退群、注销并停服,保留本机数据与配置
./etcd-rm.yml -l 10.10.10.12 -e etcd_rm_pkg=true # 同时卸载 etcd 软件包
./etcd-rm.yml -l etcd                            # 销毁整个 etcd 集群及其本机数据

便捷脚本:

bin/etcd-add <ip>                               # 向现有集群添加新成员(推荐)
bin/etcd-rm <ip>                                # 从集群中移除指定成员(推荐)
bin/etcd-rm                                     # 移除整个 etcd 集群

保护机制

出于防止误删的目的,Pigsty 的 ETCD 模块提供了防误删保险,由 etcd_safeguard 参数控制,默认为 false,即默认不打开防误删保护。

对于生产环境已经初始化好的 etcd 集群,建议打开防误删保护,避免误删现有的 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_safeguard: true  # 打开防误删保护

etcd_safeguard 设置为 true 时,etcd-rm.yml 会在任何注销、退群、停服或删除动作前直接中止;它是布尔保护开关,并不探测实例是否存活。您可以使用命令行参数来覆盖这一行为:

./etcd-rm.yml -l <exact-target> -e etcd_safeguard=false  # 仅在确认目标与备份后覆盖保险

无论保护开关取值如何,真实运行后都要重新检查 etcdctl member list、端点健康和剩余仲裁;任务返回成功不能替代这些运行态验收。

11.5 - 监控告警

etcd 监控面板,指标,以及告警规则。

监控面板

ETCD 模块提供了一个监控面板:Etcd Overview。

ETCD Overview Dashboard

ETCD Overview:ETCD 集群概览

这个监控面板提供了 ETCD 状态的关键信息:最值得关注的是 ETCD Aliveness,它显示了 ETCD 集群整体的服务状态。

红色的条带标识着实例不可用的时间段,而底下蓝灰色的条带标识着整个集群处于不可用的时间段。

etcd-overview.jpg


告警规则

Pigsty 针对 Etcd 提供了以下五条预置告警规则,定义于 files/victoria/rules/etcd.yml

  • EtcdServerDown:Etcd 节点宕机,严重警报
  • EtcdNoLeader:Etcd 集群没有领导者,严重警报
  • EtcdQuotaFull:Etcd 配额使用超过 90%,警告
  • EtcdNetworkPeerRTSlow:Etcd 网络时延缓慢,提醒
  • EtcdWalFsyncSlow:Etcd 磁盘刷盘缓慢,提醒

以下片段原样反映当前规则源码。当前只随 Pigsty 提供 etcd-overview 仪表盘;两条延迟告警注释中的 /ui/d/etcd-instance 目标并不存在,应改用 /ui/d/etcd-overview 查看集群状态。这是规则注释中的已知源码偏差,不影响告警表达式本身。

#==============================================================#
#                         Aliveness                            #
#==============================================================#
# etcd server instance down
- alert: EtcdServerDown
  expr: etcd_up < 1
  for: 1m
  labels: { level: 0, severity: CRIT, category: etcd }
  annotations:
    summary: "CRIT EtcdServerDown {{ $labels.ins }}@{{ $labels.instance }}"
    description: |
      etcd_up[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value }} < 1
      /ui/d/etcd-overview

#==============================================================#
#                         Error                                #
#==============================================================#
# Etcd no Leader triggers a P0 alert immediately
# if dcs_failsafe mode is not enabled, this may lead to global outage
- alert: EtcdNoLeader
  expr: min(etcd_server_has_leader) by (cls) < 1
  for: 15s
  labels: { level: 0, severity: CRIT, category: etcd }
  annotations:
    summary: "CRIT EtcdNoLeader: {{ $labels.cls }} {{ $value }}"
    description: |
      etcd_server_has_leader[cls={{ $labels.cls }}] = {{ $value }} < 1
      /ui/d/etcd-overview?from=now-5m&to=now&var-cls={{$labels.cls}}

#==============================================================#
#                        Saturation                            #
#==============================================================#
- alert: EtcdQuotaFull
  expr: etcd:cls:quota_usage > 0.90
  for: 1m
  labels: { level: 1, severity: WARN, category: etcd }
  annotations:
    summary: "WARN EtcdQuotaFull: {{ $labels.cls }}"
    description: |
      etcd:cls:quota_usage[cls={{ $labels.cls }}] = {{ $value | printf "%.3f" }} > 90%

#==============================================================#
#                         Latency                              #
#==============================================================#
# etcd network peer rt p95 > 200ms for 1m
- alert: EtcdNetworkPeerRTSlow
  expr: etcd:ins:network_peer_rt_p95_5m > 0.200
  for: 1m
  labels: { level: 2, severity: INFO, category: etcd }
  annotations:
    summary: "INFO EtcdNetworkPeerRTSlow: {{ $labels.cls }} {{ $labels.ins }}"
    description: |
      etcd:ins:network_peer_rt_p95_5m[cls={{ $labels.cls }}, ins={{ $labels.ins }}] = {{ $value }} > 200ms
      /ui/d/etcd-instance?from=now-10m&to=now&var-cls={{ $labels.cls }}

# Etcd wal fsync rt p95 > 50ms
- alert: EtcdWalFsyncSlow
  expr: etcd:ins:wal_fsync_rt_p95_5m > 0.050
  for: 1m
  labels: { level: 2, severity: INFO, category: etcd }
  annotations:
    summary: "INFO EtcdWalFsyncSlow: {{ $labels.cls }} {{ $labels.ins }}"
    description: |
      etcd:ins:wal_fsync_rt_p95_5m[cls={{ $labels.cls }}, ins={{ $labels.ins }}] = {{ $value }} > 50ms
      /ui/d/etcd-instance?from=now-10m&to=now&var-cls={{ $labels.cls }}

11.6 - 指标列表

Pigsty ETCD 模块提供的完整监控指标列表与释义

本页快照记录 ETCD 模块的 177 类监控指标;实际运行时的指标集合会随软件包版本、启用的采集器和目标状态变化。

Metric Name Type Labels Description
etcd:ins:backend_commit_rt_p95_5m Unknown cls, ins, instance, job, ip N/A
etcd:ins:wal_fsync_rt_p95_5m Unknown cls, ins, instance, job, ip N/A
etcd:ins:network_peer_rt_p95_5m Unknown cls, To, ins, instance, job, ip N/A
etcd_cluster_version gauge cls, cluster_version, ins, instance, job, ip Which version is running. 1 for ‘cluster_version’ label with current cluster version
etcd_debugging_auth_revision gauge cls, ins, instance, job, ip The current revision of auth store.
etcd_debugging_disk_backend_commit_rebalance_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_disk_backend_commit_rebalance_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_disk_backend_commit_rebalance_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_disk_backend_commit_spill_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_disk_backend_commit_spill_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_disk_backend_commit_spill_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_disk_backend_commit_write_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_disk_backend_commit_write_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_disk_backend_commit_write_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_lease_granted_total counter cls, ins, instance, job, ip The total number of granted leases.
etcd_debugging_lease_renewed_total counter cls, ins, instance, job, ip The number of renewed leases seen by the leader.
etcd_debugging_lease_revoked_total counter cls, ins, instance, job, ip The total number of revoked leases.
etcd_debugging_lease_ttl_total_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_lease_ttl_total_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_lease_ttl_total_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_compact_revision gauge cls, ins, instance, job, ip The revision of the last compaction in store.
etcd_debugging_mvcc_current_revision gauge cls, ins, instance, job, ip The current revision of store.
etcd_debugging_mvcc_db_compaction_keys_total counter cls, ins, instance, job, ip Total number of db keys compacted.
etcd_debugging_mvcc_db_compaction_last gauge cls, ins, instance, job, ip The unix time of the last db compaction. Resets to 0 on start.
etcd_debugging_mvcc_db_compaction_pause_duration_milliseconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_mvcc_db_compaction_pause_duration_milliseconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_db_compaction_pause_duration_milliseconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_db_compaction_total_duration_milliseconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_mvcc_db_compaction_total_duration_milliseconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_db_compaction_total_duration_milliseconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_events_total counter cls, ins, instance, job, ip Total number of events sent by this member.
etcd_debugging_mvcc_index_compaction_pause_duration_milliseconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_mvcc_index_compaction_pause_duration_milliseconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_index_compaction_pause_duration_milliseconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_mvcc_keys_total gauge cls, ins, instance, job, ip Total number of keys.
etcd_debugging_mvcc_pending_events_total gauge cls, ins, instance, job, ip Total number of pending events to be sent.
etcd_debugging_mvcc_range_total counter cls, ins, instance, job, ip Total number of ranges seen by this member.
etcd_debugging_mvcc_slow_watcher_total gauge cls, ins, instance, job, ip Total number of unsynced slow watchers.
etcd_debugging_mvcc_total_put_size_in_bytes gauge cls, ins, instance, job, ip The total size of put kv pairs seen by this member.
etcd_debugging_mvcc_watch_stream_total gauge cls, ins, instance, job, ip Total number of watch streams.
etcd_debugging_mvcc_watcher_total gauge cls, ins, instance, job, ip Total number of watchers.
etcd_debugging_server_lease_expired_total counter cls, ins, instance, job, ip The total number of expired leases.
etcd_debugging_snap_save_marshalling_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_snap_save_marshalling_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_snap_save_marshalling_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_snap_save_total_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_debugging_snap_save_total_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_debugging_snap_save_total_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_debugging_store_expires_total counter cls, ins, instance, job, ip Total number of expired keys.
etcd_debugging_store_reads_total counter cls, action, ins, instance, job, ip Total number of reads action by (get/getRecursive), local to this member.
etcd_debugging_store_watch_requests_total counter cls, ins, instance, job, ip Total number of incoming watch requests (new or reestablished).
etcd_debugging_store_watchers gauge cls, ins, instance, job, ip Count of currently active watchers.
etcd_debugging_store_writes_total counter cls, action, ins, instance, job, ip Total number of writes (e.g. set/compareAndDelete) seen by this member.
etcd_disk_backend_commit_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_disk_backend_commit_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_disk_backend_commit_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_disk_backend_defrag_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_disk_backend_defrag_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_disk_backend_defrag_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_disk_backend_snapshot_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_disk_backend_snapshot_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_disk_backend_snapshot_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_disk_defrag_inflight gauge cls, ins, instance, job, ip Whether or not defrag is active on the member. 1 means active, 0 means not.
etcd_disk_wal_fsync_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_disk_wal_fsync_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_disk_wal_fsync_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_disk_wal_write_bytes_total gauge cls, ins, instance, job, ip Total number of bytes written in WAL.
etcd_grpc_proxy_cache_hits_total gauge cls, ins, instance, job, ip Total number of cache hits
etcd_grpc_proxy_cache_keys_total gauge cls, ins, instance, job, ip Total number of keys/ranges cached
etcd_grpc_proxy_cache_misses_total gauge cls, ins, instance, job, ip Total number of cache misses
etcd_grpc_proxy_events_coalescing_total counter cls, ins, instance, job, ip Total number of events coalescing
etcd_grpc_proxy_watchers_coalescing_total gauge cls, ins, instance, job, ip Total number of current watchers coalescing
etcd_mvcc_db_open_read_transactions gauge cls, ins, instance, job, ip The number of currently open read transactions
etcd_mvcc_db_total_size_in_bytes gauge cls, ins, instance, job, ip Total size of the underlying database physically allocated in bytes.
etcd_mvcc_db_total_size_in_use_in_bytes gauge cls, ins, instance, job, ip Total size of the underlying database logically in use in bytes.
etcd_mvcc_delete_total counter cls, ins, instance, job, ip Total number of deletes seen by this member.
etcd_mvcc_hash_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_mvcc_hash_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_mvcc_hash_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_mvcc_hash_rev_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_mvcc_hash_rev_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_mvcc_hash_rev_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_mvcc_put_total counter cls, ins, instance, job, ip Total number of puts seen by this member.
etcd_mvcc_range_total counter cls, ins, instance, job, ip Total number of ranges seen by this member.
etcd_mvcc_txn_total counter cls, ins, instance, job, ip Total number of txns seen by this member.
etcd_network_active_peers gauge cls, ins, Local, instance, job, ip, Remote The current number of active peer connections.
etcd_network_client_grpc_received_bytes_total counter cls, ins, instance, job, ip The total number of bytes received from grpc clients.
etcd_network_client_grpc_sent_bytes_total counter cls, ins, instance, job, ip The total number of bytes sent to grpc clients.
etcd_network_peer_received_bytes_total counter cls, ins, instance, job, ip, From The total number of bytes received from peers.
etcd_network_peer_round_trip_time_seconds_bucket Unknown cls, To, ins, instance, job, le, ip N/A
etcd_network_peer_round_trip_time_seconds_count Unknown cls, To, ins, instance, job, ip N/A
etcd_network_peer_round_trip_time_seconds_sum Unknown cls, To, ins, instance, job, ip N/A
etcd_network_peer_sent_bytes_total counter cls, To, ins, instance, job, ip The total number of bytes sent to peers.
etcd_server_apply_duration_seconds_bucket Unknown cls, version, ins, instance, job, le, success, ip, op N/A
etcd_server_apply_duration_seconds_count Unknown cls, version, ins, instance, job, success, ip, op N/A
etcd_server_apply_duration_seconds_sum Unknown cls, version, ins, instance, job, success, ip, op N/A
etcd_server_client_requests_total counter client_api_version, cls, ins, instance, type, job, ip The total number of client requests per client version.
etcd_server_go_version gauge cls, ins, instance, job, server_go_version, ip Which Go version server is running with. 1 for ‘server_go_version’ label with current version.
etcd_server_has_leader gauge cls, ins, instance, job, ip Whether or not a leader exists. 1 is existence, 0 is not.
etcd_server_health_failures counter cls, ins, instance, job, ip The total number of failed health checks
etcd_server_health_success counter cls, ins, instance, job, ip The total number of successful health checks
etcd_server_heartbeat_send_failures_total counter cls, ins, instance, job, ip The total number of leader heartbeat send failures (likely overloaded from slow disk).
etcd_server_id gauge cls, ins, instance, job, server_id, ip Server or member ID in hexadecimal format. 1 for ‘server_id’ label with current ID.
etcd_server_is_leader gauge cls, ins, instance, job, ip Whether or not this member is a leader. 1 if is, 0 otherwise.
etcd_server_is_learner gauge cls, ins, instance, job, ip Whether or not this member is a learner. 1 if is, 0 otherwise.
etcd_server_leader_changes_seen_total counter cls, ins, instance, job, ip The number of leader changes seen.
etcd_server_learner_promote_successes counter cls, ins, instance, job, ip The total number of successful learner promotions while this member is leader.
etcd_server_proposals_applied_total gauge cls, ins, instance, job, ip The total number of consensus proposals applied.
etcd_server_proposals_committed_total gauge cls, ins, instance, job, ip The total number of consensus proposals committed.
etcd_server_proposals_failed_total counter cls, ins, instance, job, ip The total number of failed proposals seen.
etcd_server_proposals_pending gauge cls, ins, instance, job, ip The current number of pending proposals to commit.
etcd_server_quota_backend_bytes gauge cls, ins, instance, job, ip Current backend storage quota size in bytes.
etcd_server_read_indexes_failed_total counter cls, ins, instance, job, ip The total number of failed read indexes seen.
etcd_server_slow_apply_total counter cls, ins, instance, job, ip The total number of slow apply requests (likely overloaded from slow disk).
etcd_server_slow_read_indexes_total counter cls, ins, instance, job, ip The total number of pending read indexes not in sync with leader’s or timed out read index requests.
etcd_server_snapshot_apply_in_progress_total gauge cls, ins, instance, job, ip 1 if the server is applying the incoming snapshot. 0 if none.
etcd_server_version gauge cls, server_version, ins, instance, job, ip Which version is running. 1 for ‘server_version’ label with current version.
etcd_snap_db_fsync_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_snap_db_fsync_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_snap_db_fsync_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_snap_db_save_total_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_snap_db_save_total_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_snap_db_save_total_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_snap_fsync_duration_seconds_bucket Unknown cls, ins, instance, job, le, ip N/A
etcd_snap_fsync_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
etcd_snap_fsync_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
etcd_up Unknown cls, ins, instance, job, ip N/A
go_gc_duration_seconds summary cls, ins, instance, quantile, job, ip A summary of the pause duration of garbage collection cycles.
go_gc_duration_seconds_count Unknown cls, ins, instance, job, ip N/A
go_gc_duration_seconds_sum Unknown cls, ins, instance, job, ip N/A
go_goroutines gauge cls, ins, instance, job, ip Number of goroutines that currently exist.
go_info gauge cls, version, ins, instance, job, ip Information about the Go environment.
go_memstats_alloc_bytes gauge cls, ins, instance, job, ip Number of bytes allocated and still in use.
go_memstats_alloc_bytes_total counter cls, ins, instance, job, ip Total number of bytes allocated, even if freed.
go_memstats_buck_hash_sys_bytes gauge cls, ins, instance, job, ip Number of bytes used by the profiling bucket hash table.
go_memstats_frees_total counter cls, ins, instance, job, ip Total number of frees.
go_memstats_gc_cpu_fraction gauge cls, ins, instance, job, ip The fraction of this program’s available CPU time used by the GC since the program started.
go_memstats_gc_sys_bytes gauge cls, ins, instance, job, ip Number of bytes used for garbage collection system metadata.
go_memstats_heap_alloc_bytes gauge cls, ins, instance, job, ip Number of heap bytes allocated and still in use.
go_memstats_heap_idle_bytes gauge cls, ins, instance, job, ip Number of heap bytes waiting to be used.
go_memstats_heap_inuse_bytes gauge cls, ins, instance, job, ip Number of heap bytes that are in use.
go_memstats_heap_objects gauge cls, ins, instance, job, ip Number of allocated objects.
go_memstats_heap_released_bytes gauge cls, ins, instance, job, ip Number of heap bytes released to OS.
go_memstats_heap_sys_bytes gauge cls, ins, instance, job, ip Number of heap bytes obtained from system.
go_memstats_last_gc_time_seconds gauge cls, ins, instance, job, ip Number of seconds since 1970 of last garbage collection.
go_memstats_lookups_total counter cls, ins, instance, job, ip Total number of pointer lookups.
go_memstats_mallocs_total counter cls, ins, instance, job, ip Total number of mallocs.
go_memstats_mcache_inuse_bytes gauge cls, ins, instance, job, ip Number of bytes in use by mcache structures.
go_memstats_mcache_sys_bytes gauge cls, ins, instance, job, ip Number of bytes used for mcache structures obtained from system.
go_memstats_mspan_inuse_bytes gauge cls, ins, instance, job, ip Number of bytes in use by mspan structures.
go_memstats_mspan_sys_bytes gauge cls, ins, instance, job, ip Number of bytes used for mspan structures obtained from system.
go_memstats_next_gc_bytes gauge cls, ins, instance, job, ip Number of heap bytes when next garbage collection will take place.
go_memstats_other_sys_bytes gauge cls, ins, instance, job, ip Number of bytes used for other system allocations.
go_memstats_stack_inuse_bytes gauge cls, ins, instance, job, ip Number of bytes in use by the stack allocator.
go_memstats_stack_sys_bytes gauge cls, ins, instance, job, ip Number of bytes obtained from system for stack allocator.
go_memstats_sys_bytes gauge cls, ins, instance, job, ip Number of bytes obtained from system.
go_threads gauge cls, ins, instance, job, ip Number of OS threads created.
grpc_server_handled_total counter cls, ins, instance, grpc_code, job, grpc_method, grpc_type, ip, grpc_service Total number of RPCs completed on the server, regardless of success or failure.
grpc_server_msg_received_total counter cls, ins, instance, job, grpc_type, grpc_method, ip, grpc_service Total number of RPC stream messages received on the server.
grpc_server_msg_sent_total counter cls, ins, instance, job, grpc_type, grpc_method, ip, grpc_service Total number of gRPC stream messages sent by the server.
grpc_server_started_total counter cls, ins, instance, job, grpc_type, grpc_method, ip, grpc_service Total number of RPCs started on the server.
os_fd_limit gauge cls, ins, instance, job, ip The file descriptor limit.
os_fd_used gauge cls, ins, instance, job, ip The number of used file descriptors.
process_cpu_seconds_total counter cls, ins, instance, job, ip Total user and system CPU time spent in seconds.
process_max_fds gauge cls, ins, instance, job, ip Maximum number of open file descriptors.
process_open_fds gauge cls, ins, instance, job, ip Number of open file descriptors.
process_resident_memory_bytes gauge cls, ins, instance, job, ip Resident memory size in bytes.
process_start_time_seconds gauge cls, ins, instance, job, ip Start time of the process since unix epoch in seconds.
process_virtual_memory_bytes gauge cls, ins, instance, job, ip Virtual memory size in bytes.
process_virtual_memory_max_bytes gauge cls, ins, instance, job, ip Maximum amount of virtual memory available in bytes.
promhttp_metric_handler_requests_in_flight gauge cls, ins, instance, job, ip Current number of scrapes being served.
promhttp_metric_handler_requests_total counter cls, ins, instance, job, ip, code Total number of scrapes by HTTP status code.
scrape_duration_seconds Unknown cls, ins, instance, job, ip N/A
scrape_samples_post_metric_relabeling Unknown cls, ins, instance, job, ip N/A
scrape_samples_scraped Unknown cls, ins, instance, job, ip N/A
scrape_series_added Unknown cls, ins, instance, job, ip N/A
up Unknown cls, ins, instance, job, ip N/A

11.7 - 常见问题

Pigsty etcd 模块常见问题答疑

etcd集群起什么作用?

etcd 是一个分布式的、可靠的键-值存储,用于存放系统中最为关键的数据,Pigsty 使用 etcd 作为 Patroni 的 DCS(分布式配置存储)服务,用于存储 PostgreSQL 集群的高可用状态信息。

Patroni 将通过 etcd,实现集群故障检测、自动故障转移、主从切换,集群配置管理等功能。

etcd 对 PostgreSQL 集群的高可用至关重要;其自身的可用性取决于多数派成员持续可达。生产环境通常把成员分散到独立故障域,并采用 3 或 5 个投票成员。


etcd集群使用多大规模合适?

如果超过集群成员数一半(包括正好一半)的 etcd 实例不可用,那么 etcd 集群将进入不可用状态,拒绝对外提供服务。

例如:使用 3 节点的 etcd 集群允许最多一个节点宕机,而其他两个节点仍然可以正常工作;而使用 5 节点的 etcd 集群则可以容忍 2 节点失效。

请注意,etcd 集群中的 学习者(Learner)实例不计入成员数,因此在 3 节点 etcd 集群中,如果有一个学习者实例,那么实际上成员数量为 2,不能容忍任一节点失效。

在生产环境中,我们建议使用奇数个 etcd 实例,对于生产环境,建议使用 3 节点或 5 节点的 etcd 集群部署以确保足够的可靠性。


etcd集群不可用会有什么影响?

如果 etcd 集群不可用,那么会影响 PostgreSQL 的管控平面,但不会影响数据平面 —— 现有的 PostgreSQL 集群将继续运行,但通过 Patroni 进行的管理操作将无法执行。

etcd 故障期间,PostgreSQL 高可用将无法实现自动故障转移,您也无法使用 patronictl 对 PostgreSQL 集群发起管理操作,例如修改配置,执行手动故障转移等。 通过 Ansible 发起的管理命令不受 etcd 故障影响:例如创建数据库,创建用户,刷新 HBA 与 Service 配置等,etcd 故障期间,您依然可以直接操作 PostgreSQL 集群来实现这些功能。

请注意,以上描述的行为仅适用于较新版本的 Patroni (>=3.0,对应 Pigsty >= 2.0)。如果您使用的是较老版本的 Patroni (<3.0,对应 Pigsty 版本为 1.x),则 etcd / consul 故障会引发极为严重的全局性影响: 所有 PostgreSQL 集群将发生降级:主库将降级为从库,拒绝写请求,etcd 故障将放大为全局性 PostgreSQL 故障。在 Patroni 3.0 引入 DCS Failsafe 功能后,这种情况得到了显著改善。


etcd集群中存储着什么数据?

在 Pigsty 的默认用途里,etcd 用作 Patroni 的 DCS,保存 PostgreSQL 高可用所需的领导者租约、成员状态与动态配置等协调数据;Pigsty 本身不会再把业务数据存入其中。

这些 DCS 数据由 Patroni 生成和管理。在受控维护中,Patroni 通常可以依据仍然健康的 PostgreSQL 集群重新建立协调状态,但这并不等于 etcd 没有状态,也不能把直接删除 DCS 数据视作无风险操作。

重建 etcd 会中断自动故障转移和 patronictl 管理能力,并清除当时的 DCS 状态。操作前应先核对 Patroni 拓扑、当前主库、剩余仲裁与近期备份,在维护窗口内按明确的恢复步骤执行。

如果您将 etcd 用于其他目的,例如作为 Kubernetes 的元数据存储,或自行存储其他数据,那么您需要自行备份 etcd 数据,并在 etcd 集群恢复后进行数据恢复。


如何从etcd故障中恢复?

Pigsty 默认只把 etcd 用作 Patroni DCS。服务重启与整簇重建是两种风险完全不同的操作:前者保留 DCS 数据,后者会清除协调状态,并在恢复前使 PostgreSQL 高可用失去 DCS 仲裁。因此应优先诊断并恢复现有成员;只有在确认拓扑、备份和恢复路径后,才考虑整簇重建。

重启 etcd 集群,您可以使用以下 Ansible 命令:

./etcd.yml -t etcd_launch

确需 重置/重建 etcd 集群时,应在维护窗口内先清理再重建,并在完成后核对 etcdctl endpoint healthetcdctl member listpatronictl list

./etcd-rm.yml -l etcd          # 核对备份和目标后清理集群
./etcd.yml -l etcd             # 按清单重新部署 etcd 集群

如果您自行使用 etcd 存储了其他数据,那么通常需要备份 etcd 数据,并在 etcd 集群恢复后进行数据恢复。


维护etcd有什么注意事项?

简单的版本是:不要写爆 etcd 就好

Pigsty 默认启用了 etcd 自动压实(Auto Compact),当前后端存储配额为 8 GiB。通常无需担心写满 etcd,但仍应监控实际用量。

etcd 的 数据模型 使得每一次写入都会产生一个新的版本。 因此如果您的 etcd 集群频繁写入,即使只有极个别的 Key,etcd 数据库的大小也可能会不断增长。 当达到容量上限时,etcd 将会拒绝写入请求,这可能导致依赖 etcd 的 PostgreSQL 高可用机制无法正常工作。

Pigsty 默认的 etcd 配置已包含以下优化:

auto-compaction-mode: periodic      # 周期性自动压缩
auto-compaction-retention: "24h"    # 保留 24 小时历史
quota-backend-bytes: 8589934592     # 8 GiB 配额

更多维护细节请阅读 etcd 官方文档维护指南

提示

对于 Pigsty v2.6 之前的版本,请参照下面的说明手动启用 etcd 自动垃圾回收。


如何启动etcd自动垃圾回收?

如果您使用的早先版本的 Pigsty (v2.0 - v2.5),我们强烈建议您通过以下步骤,在生产环境中启用 etcd 的自动压实功能,从而避免 etcd 容量配额写满导致的 etcd 不可用故障。

在 Pigsty 源码目录中,编辑 etcd 配置文件模板:roles/etcd/templates/etcd.conf,添加以下三条配置项:

auto-compaction-mode: periodic
auto-compaction-retention: "24h"
quota-backend-bytes: 17179869184

然后将所有相关 PostgreSQL 集群设置为 维护模式 后,重新使用 ./etcd.yml 覆盖部署 etcd 集群即可。

该配置会将 etcd 默认的容量配额从 2 GiB 提高到 16 GiB,并确保只保留最近一天的写入历史版本,从而避免了 etcd 数据库大小的无限增长。


etcd中的PostgreSQL高可用数据存储在哪里?

默认情况下,Patroni 使用 pg_namespace 指定的前缀(默认为 /pg)作为所有元数据键的前缀,随后是 PostgreSQL 集群名称。 例如,名为 pg-meta 的 PG 集群,其元数据键将存储在 /pg/pg-meta 下。

etcdctl get /pg/pg-meta --prefix

其中的数据样本如下所示:

/pg/pg-meta/config
{"ttl":30,"loop_wait":10,"retry_timeout":10,"primary_start_timeout":10,"maximum_lag_on_failover":1048576,"maximum_lag_on_syncnode":-1,"primary_stop_timeout":30,"synchronous_mode":false,"synchronous_mode_strict":false,"failsafe_mode":true,"pg_version":16,"pg_cluster":"pg-meta","pg_shard":"pg-meta","pg_group":0,"postgresql":{"use_slots":true,"use_pg_rewind":true,"remove_data_directory_on_rewind_failure":true,"parameters":{"max_connections":100,"superuser_reserved_connections":10,"max_locks_per_transaction":200,"max_prepared_transactions":0,"track_commit_timestamp":"on","wal_level":"logical","wal_log_hints":"on","max_worker_processes":16,"max_wal_senders":50,"max_replication_slots":50,"password_encryption":"scram-sha-256","ssl":"on","ssl_cert_file":"/pg/cert/server.crt","ssl_key_file":"/pg/cert/server.key","ssl_ca_file":"/pg/cert/ca.crt","shared_buffers":"7969MB","maintenance_work_mem":"1993MB","work_mem":"79MB","max_parallel_workers":8,"max_parallel_maintenance_workers":2,"max_parallel_workers_per_gather":0,"hash_mem_multiplier":8.0,"huge_pages":"try","temp_file_limit":"7GB","vacuum_cost_delay":"20ms","vacuum_cost_limit":2000,"bgwriter_delay":"10ms","bgwriter_lru_maxpages":800,"bgwriter_lru_multiplier":5.0,"min_wal_size":"7GB","max_wal_size":"28GB","max_slot_wal_keep_size":"42GB","wal_buffers":"16MB","wal_writer_delay":"20ms","wal_writer_flush_after":"1MB","commit_delay":20,"commit_siblings":10,"checkpoint_timeout":"15min","checkpoint_completion_target":0.8,"archive_mode":"on","archive_timeout":300,"archive_command":"pgbackrest --stanza=pg-meta archive-push %p","max_standby_archive_delay":"10min","max_standby_streaming_delay":"3min","wal_receiver_status_interval":"1s","hot_standby_feedback":"on","wal_receiver_timeout":"60s","max_logical_replication_workers":8,"max_sync_workers_per_subscription":6,"random_page_cost":1.1,"effective_io_concurrency":1000,"effective_cache_size":"23907MB","default_statistics_target":200,"log_destination":"csvlog","logging_collector":"on","log_directory":"/pg/log/postgres","log_filename":"postgresql-%Y-%m-%d.log","log_checkpoints":"on","log_lock_waits":"on","log_replication_commands":"on","log_statement":"ddl","log_min_duration_statement":100,"track_io_timing":"on","track_functions":"all","track_activity_query_size":8192,"log_autovacuum_min_duration":"1s","autovacuum_max_workers":2,"autovacuum_naptime":"1min","autovacuum_vacuum_cost_delay":-1,"autovacuum_vacuum_cost_limit":-1,"autovacuum_freeze_max_age":1000000000,"deadlock_timeout":"50ms","idle_in_transaction_session_timeout":"10min","shared_preload_libraries":"timescaledb, pg_stat_statements, auto_explain","auto_explain.log_min_duration":"1s","auto_explain.log_analyze":"on","auto_explain.log_verbose":"on","auto_explain.log_timing":"on","auto_explain.log_nested_statements":true,"pg_stat_statements.max":5000,"pg_stat_statements.track":"all","pg_stat_statements.track_utility":"off","pg_stat_statements.track_planning":"off","timescaledb.telemetry_level":"off","timescaledb.max_background_workers":8,"citus.node_conninfo":"sslm
ode=prefer"}}}
/pg/pg-meta/failsafe
{"pg-meta-2":"http://10.10.10.11:8008/patroni","pg-meta-1":"http://10.10.10.10:8008/patroni"}
/pg/pg-meta/initialize
7418384210787662172
/pg/pg-meta/leader
pg-meta-1
/pg/pg-meta/members/pg-meta-1
{"conn_url":"postgres://10.10.10.10:5432/postgres","api_url":"http://10.10.10.10:8008/patroni","state":"running","role":"primary","version":"4.0.1","tags":{"clonefrom":true,"version":"16","spec":"8C.32G.125G","conf":"tiny.yml"},"xlog_location":184549376,"timeline":1}
/pg/pg-meta/members/pg-meta-2
{"conn_url":"postgres://10.10.10.11:5432/postgres","api_url":"http://10.10.10.11:8008/patroni","state":"running","role":"replica","version":"4.0.1","tags":{"clonefrom":true,"version":"16","spec":"8C.32G.125G","conf":"tiny.yml"},"xlog_location":184549376,"replication_state":"streaming","timeline":1}
/pg/pg-meta/status
{"optime":184549376,"slots":{"pg_meta_2":184549376,"pg_meta_1":184549376},"retain_slots":["pg_meta_1","pg_meta_2"]}

如何使用一个外部的已经存在的 etcd 集群?

配置清单中硬编码了所使用 etcd 的分组名为 etcd,这个分组里的成员将被用作 PGSQL 的 DCS 服务器。您可以使用 etcd.yml 对它们进行初始化,或直接假设它是一个已存在的外部 etcd 集群。

要使用现有的外部 etcd 集群,只要像往常一样定义它们即可,您可以跳过 etcd.yml 剧本的执行,因为集群已经存在,不需要部署。

但用户必须确保 现有 etcd 集群证书是由 Pigsty 使用的相同 CA 签名颁发的。否则客户端无法使用 Pigsty 自签名 CA 颁发的证书来访问外部的 etcd 集群。


如何向现有etcd集群添加新的成员?

详细过程,请参考 向 etcd 集群添加成员

推荐方式:使用便捷脚本

# 首先在配置清单中添加新成员定义,然后执行:
bin/etcd-add <ip>      # 添加单个新成员
bin/etcd-add <ip1>     # 添加多个新成员

手动方式:

etcdctl member add <etcd-?> --learner=true --peer-urls=https://<new_ins_ip>:2380 # 宣告新成员加入
./etcd.yml -l <new_ins_ip> -e etcd_init=existing                                 # 初始化新成员
etcdctl member promote <new_ins_server_id>                                       # 提升为正式成员

请注意,我们建议一次只添加一个新成员。


如何从现有etcd集群中移除成员?

详细过程,请参考 从 etcd 集群中移除成员

推荐方式:使用便捷脚本

bin/etcd-rm <ip>              # 移除指定成员
bin/etcd-rm                   # 移除整个 etcd 集群

手动方式:

./etcd-rm.yml -l <ins_ip>                    # 退群、停服并默认清理本机数据

etcd-rm.yml 已经包含 etcdctl member remove 步骤,不要在正常流程中前后重复执行。只有排障时才手工 member remove;之后仍可在目标尚存于清单时运行一次移除剧本完成本机停服、注销和清理,并核对剩余仲裁。


如何配置 etcd RBAC 认证?

Pigsty 自 v4.0 起默认启用 etcd 的 RBAC 认证。root 用户密码由 etcd_root_password 参数控制,默认值为 Etcd.Root

在生产环境中,强烈建议修改默认密码

all:
  vars:
    etcd_root_password: 'YourSecurePassword'

客户端认证

# 在 etcd 节点上,环境变量已自动配置
source /etc/profile.d/etcdctl.sh
etcdctl member list

# 手动配置认证
export ETCDCTL_USER="root:YourSecurePassword"
export ETCDCTL_CACERT=/etc/etcd/ca.crt
export ETCDCTL_CERT=/etc/etcd/server.crt
export ETCDCTL_KEY=/etc/etcd/server.key

更多详情请参考 RBAC 认证

12 - 模块:MINIO

使用 MINIO 兼容模块部署 Silo S3 对象存储,并作为 PostgreSQL 备份仓库。

MINIO 是 Pigsty 中 S3 兼容对象存储的兼容模块名。当前角色部署 Silo,并且 minio_type 只接受 silo

Silo 沿用 MinIO 的 S3/Admin API、MINIO_* 环境变量、磁盘格式与 mcli 客户端接口,可用作 PostgreSQL pgBackRest 备份仓库。模块名、参数前缀和监控 job 继续使用 MINIO / minio_*,以保持现有清单和运维入口兼容。

重要

miniorustfs 不再是有效的 minio_type,会在身份检查阶段失败。升级由旧版本管理的 MinIO 集群前,必须先完成备份、MinIO → Silo 兼容性验证与回滚演练;不能把软件包替换当作已经验收的数据迁移。外部 MinIO、RustFS 或其他 S3 服务仍可作为 pgBackRest 仓库,但不由当前 MINIO 角色管理。

MINIO 是 可选模块。若将它用作 pgBackRest 的 S3 仓库,应在 PGSQL 模块之前部署;TLS 证书与主机基线由 NODE / CA 能力提供。


快速开始

以下配置显式定义一个单节点 Silo 集群。minio_clusterminio_seq 都是必填身份参数;生产清单应显式写出 minio_type: silo

minio:
  hosts:
    10.10.10.10: { minio_seq: 1 }
  vars:
    minio_cluster: minio
    minio_type: silo
./minio.yml -l minio    # 在 minio 分组上部署 Silo

清单分组名可以与 minio_cluster 不同,角色按每台主机的 minio_cluster 身份计算实际成员。不要在 all.vars 中定义 minio_cluster,否则所有主机都会被视为对象存储成员。

部署完成后可通过以下入口访问:

  • S3 APIhttps://sss.pigsty:9000(域名需要显式配置 DNS 或 /etc/hosts
  • 管理界面https://<node-ip>:9001
  • 命令行mcli ls sss/(管理节点与集群成员上会写入预配置别名)

默认管理员凭证为 minioadmin / S3User.MinIO,只适合演示;生产部署前必须修改。


部署模式

Silo 使用以下 Pigsty 清单部署模式:

模式 说明 适用场景
单机单盘(SNSD) 单节点、单个数据目录 开发、测试、演示
单机多盘(SNMD) 单节点、多块磁盘 资源受限的小规模部署
多机单盘(MNSD) 多节点、每节点一个数据盘 紧凑高可用部署
多机多盘(MNMD) 多节点、每节点多块磁盘 生产环境推荐

minio_data 始终是目录路径。分布式与多盘部署要求这些目录位于非根盘的独立持久文件系统上;例如 /data/minio 可以是独立挂载点 /data 下的子目录,但不能只是根文件系统中的普通目录。

minio_volumes 的多池扩容语义来自 Silo 保留的 MinIO 兼容接口;生产扩缩容前仍应按实际 Silo 版本验证操作与回滚流程。


核心能力

  • 兼容接口:Silo 沿用 minio_* 参数、S3 端口、TLS 和 mcli 置备流程
  • 高可用拓扑:支持单节点、多节点单盘与多节点多盘部署,可在同一清单中定义多套独立集群
  • 备份仓库:可作为 pgBackRest 的 S3 远程仓库
  • 安全基线:默认启用 HTTPS,并由 Pigsty CA 为每个实例签发证书
  • 可观测性:通过 /minio/metrics/v3 采集 Silo 指标,并提供 Grafana 面板与告警
  • 兼容运维:模块名、目标目录、监控标签和客户端别名保留 MINIO 命名空间

12.1 - 使用方法

快速使用 MINIO 模块部署的 Silo,并通过 mcli、rclone 与 pgBackRest 接入。

当您 配置 并执行 剧本 部署 Silo 后,可以参考本页通过 S3 与 mcli 兼容接口使用它。


部署集群

首先在 配置清单 中定义单机单盘对象存储集群,并显式锁定引擎:

minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio, minio_type: silo } }

然后,针对定义的分组(这里为 minio)执行 Pigsty 提供的 minio.yml 剧本即可:

./minio.yml -l minio

请注意在 deploy.yml 中,事先定义好的 Silo 集群会自动创建,无需手动再次执行 minio.yml 剧本。

生产多节点部署应通读 Pigsty 配置文档,并核对实际 Silo 版本的操作约束。


接入集群

生产环境建议通过域名与 HTTPS 访问对象存储(默认配置也是 HTTPS)。 如果您显式设置 minio_httpsfalse,也可以使用 HTTP 访问。 无论哪种方式,都请确保对象存储服务域名(默认为 sss.pigsty)正确指向服务节点或负载均衡器。

  1. 您可以在 node_etc_hosts 中添加静态解析记录,或者手工修改 /etc/hosts 文件
  2. 您可以在内网的 DNS 服务器上添加一条记录,如果已经有了现成的 DNS 服务
  3. 如果您启用了 Infra 节点上的 DNS 服务器,可以在 dns_records 中添加记录

生产环境通常建议使用第一种方式:静态 DNS 解析记录,避免对象存储服务依赖动态 DNS。

应将 S3 服务域名指向 Silo 节点或负载均衡器的 IP 地址与服务端口。 Pigsty 默认使用 sss.pigsty 作为 S3 服务域名,并在 9000 端口提供服务;角色不会自动为 minio_domain 创建全局 DNS 解析,需要按上文显式配置。

部分示例在 Silo 集群上部署 HAProxy 对外暴露服务,此时模板使用 9002 作为统一服务端口。


添加别名

要使用 mcli 客户端访问 minio 服务器集群,首先要配置服务器的别名(alias):

mcli alias ls  # 列出 minio 别名(默认使用sss)
mcli alias set sss https://sss.pigsty:9000 minioadmin S3User.MinIO            # root 用户
mcli alias set sss https://sss.pigsty:9002 minioadmin S3User.MinIO            # root 用户,使用负载均衡器 9002 端口

mcli alias set pgbackrest https://sss.pigsty:9000 pgbackrest S3User.Backup    # 使用备份用户

完整执行 minio.yml 且启用 minio_provision 后,角色会为所有 Infra 节点与按 minio_cluster 发现的实际对象存储成员上的 Ansible 执行用户配置默认别名;同一主机同时属于两者时只写入一次。

MinIO 客户端工具 mcli 的完整功能参考,请查阅文档: MinIO 客户端

注意:请使用您实际配置的密码

上述示例中的密码 S3User.MinIO 是 Pigsty 的默认值。如果您在部署时修改了 minio_secret_key,请使用您实际配置的密码。


用户管理

使用 mcli 可以管理 Silo 中的业务用户。默认置备已经创建 pgbackrests3user_metas3user_data;下面创建一个额外用户,并附加默认生成的 data 桶策略:

mcli admin user list sss
set +o history
mcli admin user add sss appuser 'Replace.With.Strong.Password'
mcli admin policy attach sss data --user=appuser
set -o history

存储桶管理

您可以对 Silo 中的存储桶进行增删改查

mcli ls sss/                         # 列出别名 'sss' 的所有桶
mcli mb --ignore-existing sss/hello  # 创建名为 'hello' 的桶
mcli rb --force sss/hello            # 强制删除 'hello' 桶

对象管理

您也可以对存储桶内的对象进行增删改查,详情请参考官方文档:对象管理

mcli cp /www/pigsty/* sss/data/      # 将本地软件源的内容上传到默认创建的 data 桶中
mcli cp sss/data/plugins.tgz /tmp/   # 从 Silo 下载文件到本地
mcli ls sss/data                     # 列出 data 桶中的所有文件
mcli rm sss/data/plugins.tgz         # 删除 data 桶中的特定文件
mcli cat sss/data/repo_complete      # 查看 data 桶中的文件内容

使用rclone

Pigsty 仓库中提供了 rclone,一个方便的多云对象存储客户端,可以用它访问 Silo 服务。

yum install rclone;  # EL 系列系统
apt install rclone;  # Debian/Ubuntu 系统

mkdir -p ~/.config/rclone/;
tee ~/.config/rclone/rclone.conf > /dev/null <<EOF
[sss]
type = s3
access_key_id = minioadmin
secret_access_key = S3User.MinIO
endpoint = https://sss.pigsty:9000
EOF

rclone ls sss:/
注意:HTTPS 与证书信任

如果 Silo 使用 HTTPS(默认配置),需要确保客户端信任 Pigsty CA 证书(/etc/pki/ca.crt),或者在 rclone 配置中添加 no_check_certificate = true 跳过证书验证(不建议在生产环境使用)。


配置备份仓库

在 Pigsty 中,MINIO 模块的主要用例是作为 pgBackRest 的 S3 备份仓库。 当您将 pgbackrest_method 设为 minio 时,PGSQL 模块会使用同名的 S3 兼容仓库预设;MINIO 模块部署的 Silo 可以直接使用该预设。

pgbackrest_method: local          # pgbackrest repo method: local,minio,[user-defined...]
pgbackrest_repo:                  # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
  local:                          # default pgbackrest repo with local posix fs
    path: /pg/backup              # local backup directory, `/pg/backup` by default
    retention_full_type: count    # retention full backups by count
    retention_full: 2             # keep 2, at most 3 full backup when using local fs repo
  minio:                          # optional minio repo for pgbackrest
    type: s3                      # minio is s3-compatible, so s3 is used
    s3_endpoint: sss.pigsty       # minio endpoint domain name, `sss.pigsty` by default
    s3_region: us-east-1          # minio region, us-east-1 by default, useless for minio
    s3_bucket: pgsql              # minio bucket name, `pgsql` by default
    s3_key: pgbackrest            # minio user access key for pgbackrest
    s3_key_secret: S3User.Backup  # minio user secret key for pgbackrest
    s3_uri_style: path            # use path style uri for minio rather than host style
    path: /pgbackrest             # minio backup path, default is `/pgbackrest`
    storage_port: 9000            # minio port, 9000 by default
    storage_ca_file: /etc/pki/ca.crt  # minio ca file path, `/etc/pki/ca.crt` by default
    bundle: y                     # bundle small files into a single file
    cipher_type: aes-256-cbc      # enable AES encryption for remote backup repo
    cipher_pass: pgBackRest       # AES encryption password, default is 'pgBackRest'
    retention_full_type: time     # retention full backup by time on minio repo
    retention_full: 14            # keep full backup for last 14 days

如果使用多节点 Silo 集群并通过负载均衡器对外提供服务,需要相应修改这里的 s3_endpointstorage_port

12.2 - 集群配置

使用 MINIO 模块部署 Silo,并按单机、多盘、多节点模式配置可靠的 S3 对象存储接入。

在部署 MINIO 模块之前,需要在 配置清单 中定义 Silo 对象存储集群。当前角色要求 minio_type: silo,支持以下清单部署模式:

  • 单机单盘:SNSD:单机单盘模式,可以使用任意目录作为数据盘,仅作为开发、测试、演示使用。
  • 单机多盘:SNMD:折中模式,在单台服务器上使用多块磁盘 (>=2),仅当资源极为有限时使用。
  • 多机单盘:MNSD:多台服务器各使用一个独立数据盘,提供紧凑的节点级高可用能力。
  • 多机多盘:MNMD:多机多盘模式,标准生产环境部署,具有最好的可靠性,但需要多台服务器。

SNSD 适合开发测试,三节点 MNSD 适合资源受限的紧凑高可用部署,MNMD 适合对容量、吞吐和磁盘冗余有更高要求的生产环境。SNMD 只解决单机内的磁盘故障,不能容忍整机故障。

此外,Silo 可以使用 多池部署 扩容,或直接部署 多套集群

使用多节点集群时,访问任意成员都可以获取 S3 服务,因此最佳实践是在集群前使用负载均衡与 高可用服务接入机制


后端选择

minio_type: silo   # 当前唯一合法值

minio_type 是为后续扩展保留的选择器,但当前部署与移除角色都只接受 silo。它对应 silo 软件包、silo.service/etc/default/silo~/.minio/certs/。为支持原地迁移,silo.service 会先读取旧的 /etc/default/minio,再读取优先级更高的 /etc/default/silo,并与旧 minio.service 冲突;新部署只应维护 Silo 配置文件。

旧清单中的 minio_type: miniominio_type: rustfs 会在身份检查阶段失败。升级已有 MinIO 部署前,应先验证 MinIO → Silo 的数据兼容性、备份与回滚路径。下文引用 MinIO 上游拓扑术语和链接,是因为 Silo 保留对应兼容接口,并不表示当前角色仍安装 minio 软件包。


核心参数

Pigsty 使用 minio_volumes 描述成员与磁盘,并将其渲染为 Silo 的 MINIO_VOLUMES。角色会根据清单自动生成该值,也允许显式覆盖。

  • 单机单盘:minio_volumes 指向本机上的普通目录,默认由 minio_data 生成,默认位置为 /data/minio
  • 单机多盘:minio_volumes 指向本机上的序列挂载点,同样由 minio_data 生成,例如 /data{1...4}
  • 多机单盘:minio_volumes 指向每台服务器上的一个数据目录,例如 https://minio-{1...3}.pigsty:9000/data/minio
  • 多机多盘:minio_volumes 指向多台服务器上的序列挂载点,由以下两部分自动组合生成:
    • 首先要使用 minio_data 指定集群每个成员的磁盘挂载点序列 /data{1...4}
    • 还需要使用 minio_node 指定节点的命名模式 ${minio_cluster}-${minio_seq}.pigsty
  • 多池部署:需要显式指定 minio_volumes 来分配每个存储池的节点。

存储路径与挂载

minio_data 配置的是文件系统目录,不是裸块设备。磁盘、云盘、独立分区或 LVM 逻辑卷应先格式化并挂载,再把挂载点或其子目录交给 Silo;不要把 /dev/sdb 直接写入 minio_data

MINIO 角色会创建数据目录并设置属主与权限,但不会替生产服务器完成磁盘格式化和持久化挂载。不同拓扑对目录背后的文件系统有不同要求:

  • 单机单盘可以使用根文件系统中的普通目录,但只适合开发、测试与演示。
  • 单机多盘中的每个数据路径都应对应独立文件系统,不能用同一块盘上的多个普通目录冒充多盘。
  • 多节点分布式 Silo 会识别并拒绝根文件系统上的数据路径,错误为 drive is part of root drive, will not be used

因此,/data/minio 可以是普通子目录,前提是 /data 本身已经挂载到独立持久化文件系统;如果 /data 只是 / 下的普通目录,则不满足分布式部署要求。绑定挂载根文件系统中的另一个目录也不会形成新的磁盘故障域。

可以在部署前检查实际挂载关系:

findmnt -T /
findmnt -T /data/minio

第二条命令应显示 /data/data/minio 对应的独立挂载点,而不是 /。生产环境还应确保挂载写入 /etc/fstab 或由等效的持久化机制管理,并为同一存储池使用容量接近的数据盘。


单机单盘

SNSD 模式,兼容拓扑参考:MinIO 单机单盘部署

在 Pigsty 中,定义一个单例 Silo 实例非常简单:

# 1 节点 1 数据目录
minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio, minio_type: silo } }

单机模式下,必要的身份参数是 minio_seqminio_cluster,它们会唯一标识每一个对象存储实例。

单节点单磁盘模式仅用于开发目的,因此您可以使用一个普通的目录作为数据目录,该目录由参数 minio_data 默认为 /data/minio

使用 Silo 时,强烈建议通过静态解析的域名记录访问服务。例如,假设 minio_domain 使用默认的 sss.pigsty, 那么您可以在所有节点上添加一个静态解析,便于其他节点访问此服务。

node_etc_hosts: ["10.10.10.10 sss.pigsty"] # domain name to access minio from all nodes (required)
SNSD 仅适用于开发测试

单节点单盘模式应当仅用于开发、测试、演示目的,因为它无法容忍任何硬件故障,也无法带来多磁盘的性能改善。生产环境请使用 多机多盘 模式。


单机多盘

SNMD 模式,兼容拓扑参考:MinIO 单机多盘部署

要在单节点上使用多块磁盘,所需的操作与 单机单盘 基本一致,但用户需要以 {{ prefix }}{x...y} 的特定格式指定 minio_data,该格式定义了序列磁盘挂载点。

minio:
  hosts: { 10.10.10.10: { minio_seq: 1 } }
  vars:
    minio_cluster: minio         # 对象存储集群标识,必填
    minio_data: '/data{1...4}'   # minio 数据目录,使用 {x...y} 记号来指定多块磁盘
请使用真实磁盘挂载点

SNMD 模式中的每个数据路径都必须位于独立文件系统上。如果多个路径实际落在同一个文件系统中,Silo 会拒绝把它们作为多块盘使用。生产环境建议使用 XFS;Vagrant 在 XFS 工具不可用时也支持以 ext4 准备测试数据盘。

例如 Vagrant 对象存储 沙箱 定义了一个带有 4 块磁盘的单节点 Silo 集群:/data1/data2/data3/data4。启动 Silo 前,需要正确挂载并使用 xfs 格式化这些磁盘:

mkfs.xfs /dev/vdb; mkdir /data1; mount -t xfs /dev/vdb /data1;   # 挂载第1块盘……
mkfs.xfs /dev/vdc; mkdir /data2; mount -t xfs /dev/vdc /data2;   # 挂载第2块盘……
mkfs.xfs /dev/vdd; mkdir /data3; mount -t xfs /dev/vdd /data3;   # 挂载第3块盘……
mkfs.xfs /dev/vde; mkdir /data4; mount -t xfs /dev/vde /data4;   # 挂载第4块盘……

挂载磁盘属于服务器置备的部分,超出 Pigsty 的处理范畴。挂载的磁盘应该同时写入 /etc/fstab 以便在服务器重启后可以自动挂载。

/dev/vdb /data1 xfs defaults,noatime,nodiratime 0 0
/dev/vdc /data2 xfs defaults,noatime,nodiratime 0 0
/dev/vdd /data3 xfs defaults,noatime,nodiratime 0 0
/dev/vde /data4 xfs defaults,noatime,nodiratime 0 0

SNMD 模式可以利用单机上的多块磁盘,提供更高的性能和容量,并且容忍部分磁盘故障。 但单节点模式无法容忍整个节点的故障,而且您无法在运行时添加新的节点,因此如果没有特殊原因,我们不建议在生产环境中使用 SNMD 模式。


多机单盘

MNSD 模式在多台服务器上各使用一个数据盘。以下配置定义了一个三节点单盘 Silo 集群,也是 ha/trio 使用的存储拓扑:

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_type: silo
    minio_data: /data/minio

角色会生成 https://minio-{1...3}.pigsty:9000/data/minio。三条路径分别位于三台服务器上,每台服务器的 /data/minio 都必须落在非根盘的独立持久文件系统中。

三盘存储集默认使用 EC:1:每个对象拆分为 2 份数据和 1 份校验,读写仲裁都是 2,因此允许一个节点或一个数据盘不可用。使用容量相同的磁盘时,扣除文件系统与元数据开销前,可用容量约为原始容量的三分之二,并由最小磁盘容量限制。

这是资源占用较低的紧凑高可用拓扑,消除了单节点对象存储故障,但每个节点仍只有一个数据盘。需要更高容量、吞吐或节点内磁盘冗余时,应使用 多机多盘 模式。

既有单节点存储池不能通过直接增加两个成员原地改成三节点存储池。需要创建新的三节点集群、迁移对象并切换客户端入口。


多机多盘

MNMD 模式,兼容拓扑参考:MinIO 多机多盘部署

除了使用 单机多盘 模式中的 minio_data 指定磁盘,还需要使用 minio_node 指定多节点名称模式。

例如,以下配置定义了一个 Silo 集群,其中有四个节点,每个节点有四块磁盘:

minio:
  hosts:
    10.10.10.10: { minio_seq: 1 }  # 实际节点名: minio-1.pigsty
    10.10.10.11: { minio_seq: 2 }  # 实际节点名: minio-2.pigsty
    10.10.10.12: { minio_seq: 3 }  # 实际节点名: minio-3.pigsty
    10.10.10.13: { minio_seq: 4 }  # 实际节点名: minio-4.pigsty
  vars:
    minio_cluster: minio
    minio_data: '/data{1...4}'                         # 每个节点使用四块磁盘
    minio_node: '${minio_cluster}-${minio_seq}.pigsty' # minio 节点名称规则

minio_node 参数指定 MINIO 模块内部的节点名称模式,用于生成每个节点的唯一名称。 默认情况下,节点名称是 ${minio_cluster}-${minio_seq}.pigsty,其中 ${minio_cluster} 是集群名称,${minio_seq} 是节点序号。 实例名称会自动写入各 Silo 节点的 /etc/hosts 中进行静态解析,供集群成员互相识别和访问。

在这种情况下,派生的 minio_volumeshttps://minio-{1...4}.pigsty:9000/data{1...4},以标识四个节点上的四块盘;角色再将其写入 Silo 使用的兼容环境变量。 您可以直接在对象存储集群中指定 minio_volumes,覆盖自动生成的值。 但通常不需要这样做,因为 Pigsty 会自动根据配置清单生成它。


多池部署

Silo 保留通过添加新存储池扩容的兼容能力。在 Pigsty 中,可以显式指定 minio_volumes 为每个存储池分配节点。

例如,假设您已经创建了 多机多盘 样例中的 Silo 集群,现在需要添加一个同样由四个节点构成的新存储池。

那么,你需要直接覆盖指定 minio_volumes 参数:

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 }
    
    10.10.10.14: { minio_seq: 5 }
    10.10.10.15: { minio_seq: 6 }
    10.10.10.16: { minio_seq: 7 }
    10.10.10.17: { minio_seq: 8 }
  vars:
    minio_cluster: minio
    minio_data: "/data{1...4}"
    minio_node: '${minio_cluster}-${minio_seq}.pigsty' # minio 节点名称规则
    minio_volumes: 'https://minio-{1...4}.pigsty:9000/data{1...4} https://minio-{5...8}.pigsty:9000/data{1...4}'

在这里,空格分隔的两个参数分别代表两个存储池,每个存储池有四个节点,每个节点有四块磁盘。更多信息见 管理预案:集群扩容


多套集群

您可以将新节点部署为独立的 Silo 集群。以下配置使用不同身份声明两套对象存储集群:

minio1:
  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: minio1
    minio_data: "/data{1...4}"

minio2:
  hosts:    
    10.10.10.14: { minio_seq: 5 }
    10.10.10.15: { minio_seq: 6 }
    10.10.10.16: { minio_seq: 7 }
    10.10.10.17: { minio_seq: 8 }
  vars:
    minio_cluster: minio2
    minio_data: "/data{1...4}"
    minio_alias: sss2
    minio_domain: sss2.pigsty
    minio_endpoint: https://sss2.pigsty:9000

minio_cluster 没有默认值,每套集群都必须显式定义。多集群共存时,还必须使用不同的 minio_aliasminio_domainminio_endpoint,否则 Infra 节点上的共享客户端别名或域名会互相覆盖。Ansible 分组名可以与 minio_cluster 不同,角色按身份参数从整个清单发现成员。


服务接入

Silo 默认使用 9000 端口提供 S3 服务。多节点集群可以通过访问 任意一个成员 来访问服务。

服务接入属于 NODE 模块的功能范畴,这里仅做基本介绍。

多节点对象存储集群的高可用接入可以使用 L2 VIP 或 HAProxy 实现。例如,可用 keepalived 绑定 L2 VIP,或使用 NODE 模块提供的 haproxy 组件暴露 S3 服务。

# object storage cluster with 4 nodes and 4 drives per node
minio:
  hosts:
    10.10.10.10: { minio_seq: 1 , nodename: minio-1 }
    10.10.10.11: { minio_seq: 2 , nodename: minio-2 }
    10.10.10.12: { minio_seq: 3 , nodename: minio-3 }
    10.10.10.13: { minio_seq: 4 , nodename: minio-4 }
  vars:
    minio_cluster: minio
    minio_data: '/data{1...4}'
    minio_buckets: [ { name: pgsql }, { name: infra }, { name: redis } ]
    minio_users:
      - { access_key: dba , secret_key: S3User.DBA, policy: consoleAdmin }
      - { access_key: pgbackrest , secret_key: S3User.SomeNewPassWord , policy: readwrite }

    # bind a node l2 vip (10.10.10.9) to minio cluster (optional)
    node_cluster: minio
    vip_enabled: true
    vip_vrid: 128
    vip_address: 10.10.10.9
    vip_interface: eth1

    # expose minio service with haproxy on all nodes
    haproxy_services:
      - name: minio                    # [REQUIRED] service name, unique
        port: 9002                     # [REQUIRED] service port, unique
        balance: leastconn             # [OPTIONAL] load balancer algorithm
        options:                       # [OPTIONAL] minio health check
          - 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' }
          - { name: minio-4 ,ip: 10.10.10.13 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }

例如,上面的配置块在 Silo 集群的所有节点上启用 HAProxy,通过 9002 端口暴露 S3 服务,并为集群绑定一个二层 VIP。 使用时应将 sss.pigsty 解析到 VIP 10.10.10.9,并通过 9002 端口访问。任意节点故障时,VIP 会切换到其他节点。

在这种情况下,还需要修改全局域名解析以及 minio_endpoint,更新写入管理节点的 mcli Alias 端点:

minio_endpoint: https://sss.pigsty:9002   # 覆盖默认值: https://sss.pigsty:9000
node_etc_hosts: ["10.10.10.9 sss.pigsty"] # 其他节点使用 sss.pigsty 访问 Silo

专用负载均衡

Pigsty 允许用户使用专用的负载均衡服务器组,而不是集群本身来运行 VIP 与 HAProxy。例如 ha/simu 模板中就使用了这种方式。

proxy:
  hosts:
    10.10.10.18 : { nodename: proxy1 ,node_cluster: proxy ,vip_interface: eth1 ,vip_role: master }
    10.10.10.19 : { nodename: proxy2 ,node_cluster: proxy ,vip_interface: eth1 ,vip_role: backup }
  vars:
    vip_enabled: true
    vip_address: 10.10.10.20
    vip_vrid: 20
    
    haproxy_services:      # expose minio service : sss.pigsty:9002
      - name: minio        # [REQUIRED] service name, unique
        port: 9002         # [REQUIRED] service port, unique
        balance: leastconn # Use leastconn algorithm and minio health check
        options: [ "option httpchk", "option http-keep-alive", "http-check send meth OPTIONS uri /minio/health/live", "http-check expect status 200" ]
        servers:           # reload service with ./node.yml -t haproxy_config,haproxy_reload
          - { name: minio-1 ,ip: 10.10.10.21 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
          - { name: minio-2 ,ip: 10.10.10.22 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
          - { name: minio-3 ,ip: 10.10.10.23 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
          - { name: minio-4 ,ip: 10.10.10.24 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
          - { name: minio-5 ,ip: 10.10.10.25 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }

在这种情况下,还需要将 sss.pigsty 指向负载均衡器,并修改 minio_endpoint,更新管理节点上的 mcli Alias 端点:

minio_endpoint: https://sss.pigsty:9002    # overwrite the defaults: https://sss.pigsty:9000
node_etc_hosts: ["10.10.10.20 sss.pigsty"] # domain name to access minio from all nodes (required)

访问服务

如果要从 PGSQL 访问上面通过 HAProxy 暴露的 Silo,可以在 pgbackrest_repo 中添加新的备份仓库定义:

# 新增的 HA S3 Repo 定义,替代之前的单机配置
minio_ha:
  type: s3
  s3_endpoint: minio-1.pigsty   # s3_endpoint 可以是任何一个负载均衡器:10.10.10.1{0,1,2},或指向任意 3 个节点的域名
  s3_region: us-east-1          # 你可以使用外部域名:sss.pigsty,该域名指向任一成员(`minio_domain`)
  s3_bucket: pgsql              # 你可使用实例名和节点名:minio-1.pigsty minio-1.pigsty minio-1.pigsty minio-1 minio-2 minio-3
  s3_key: pgbackrest            # 为 Silo 的 pgbackrest 用户使用专用密码
  s3_key_secret: S3User.SomeNewPassWord
  s3_uri_style: path
  path: /pgbackrest
  storage_port: 9002            # 使用负载均衡器的端口 9002 代替默认的 9000(直接访问)
  storage_ca_file: /etc/pki/ca.crt
  bundle: y
  cipher_type: aes-256-cbc      # 在您的生产环境中最好使用新的加密密码,这里可以使用集群名作为密码的一部分。
  cipher_pass: pgBackRest.With.Some.Extra.PassWord.And.Salt.${pg_cluster}
  retention_full_type: time
  retention_full: 14

暴露管控

Silo 默认通过 9001 端口(由 minio_admin_port 指定)提供 Web 管控界面。

将后台管理界面暴露给外部可能存在安全隐患。如果确实需要,请将 Silo 添加到 infra_portal 并刷新 Nginx 配置。

# ./infra.yml -t nginx
infra_portal:
  home         : { domain: h.pigsty }
  grafana      : { domain: g.pigsty ,endpoint: "${admin_ip}:3000" , websocket: true }
  vmetrics     : { domain: v.pigsty ,endpoint: "${admin_ip}:8428" }
  alertmanager : { domain: a.pigsty ,endpoint: "${admin_ip}:9059" }
  blackbox     : { endpoint: "${admin_ip}:9115" }
  vlogs        : { endpoint: "${admin_ip}:9428" }

  # 对象存储管理页面需要 HTTPS / Websocket
  minio        : { domain: m.pigsty     ,endpoint: "10.10.10.10:9001" ,scheme: https ,websocket: true }
  minio10      : { domain: m10.pigsty   ,endpoint: "10.10.10.10:9001" ,scheme: https ,websocket: true }
  minio11      : { domain: m11.pigsty   ,endpoint: "10.10.10.11:9001" ,scheme: https ,websocket: true }
  minio12      : { domain: m12.pigsty   ,endpoint: "10.10.10.12:9001" ,scheme: https ,websocket: true }
  minio13      : { domain: m13.pigsty   ,endpoint: "10.10.10.13:9001" ,scheme: https ,websocket: true }

不要 在生产环境中暴露未加密的对象存储管控页面。

这意味着,通常需要在 DNS 服务器或本机 /etc/hosts 中添加 m.pigsty 解析记录,以便访问 Silo 管控页面。

与此同时,如果您使用的是 Pigsty 自签名的 CA 而不是一个正规的公共 CA,通常您还需要手工信任该 CA 或证书,才能跳过浏览器中的 “不安全” 提示信息。

12.3 - 参数列表

MINIO 模块提供 22 个公开参数,用于部署、配置与移除 Silo 对象存储集群。

MINIO 模块共有 22 个公开参数,分为两个部分:

  • MINIO:19 个参数,用于部署 Silo 对象存储集群
  • MINIO_REMOVE:3 个参数,控制对象存储集群的移除
架构变化:Pigsty v3.6+

自 Pigsty v3.6 起,minio.yml 剧本不再包含移除功能,移除相关参数已迁移至独立的 minio_remove 角色和 minio-rm.yml 剧本。


参数概览

MINIO 参数组用于配置 Silo 对象存储集群,包括身份、存储路径、端口、认证凭据以及存储桶和用户置备。

参数 类型 级别 说明
minio_type enum G/C 保留的后端选择器,当前只接受 silo
minio_seq int I minio 实例标识符,必填
minio_cluster string C 对象存储集群名称,必填
minio_user username C minio 操作系统用户,默认为 minio
minio_https bool G/C 是否为对象存储启用 HTTPS?默认为 true
minio_node string C minio 节点名模式
minio_data path C minio 数据目录,使用 {x...y} 指定多个磁盘
minio_volumes string C minio 核心参数,指定成员节点与磁盘,默认不指定
minio_domain string G minio 外部域名,默认为 sss.pigsty
minio_port port C minio 服务端口,默认为 9000
minio_admin_port port C minio 控制台端口,默认为 9001
minio_access_key username C 根访问密钥,默认为 minioadmin
minio_secret_key password C 根密钥,默认为 S3User.MinIO
minio_extra_vars string C minio 服务器的额外环境变量
minio_provision bool G/C 是否执行 minio 资源置备任务?默认为 true
minio_alias string G minio 部署的客户端别名
minio_endpoint string C minio 部署的客户端别名对应的端点
minio_buckets bucket[] C 待创建的 minio 存储桶列表
minio_users user[] C 待创建的 minio 用户列表

MINIO_REMOVE 参数组控制对象存储集群的移除行为,包括防误删保险、数据清理以及软件包卸载。

参数 类型 级别 说明
minio_safeguard bool G/C/A 防止意外删除?默认为 false
minio_rm_data bool G/C/A 移除时是否删除 Silo 数据?默认为 true
minio_rm_pkg bool G/C/A 移除时是否卸载 Silo 与 mcli?默认为 false

其中,minio_volumesminio_endpoint 为自动生成的参数,但您可以显式覆盖指定这两个参数。


默认参数

MINIO:19 个公开参数,定义于 roles/minio/defaults/main.yml

#-----------------------------------------------------------------
# SILO
#-----------------------------------------------------------------
minio_type: silo                  # 保留的对象存储后端选择器,当前只接受 silo
#minio_seq: 1                     # minio 实例标识符,必填
#minio_cluster: minio             # minio 集群标识符,必填
minio_user: minio                 # minio 操作系统用户,默认为 `minio`
minio_https: true                 # 是否为 Silo 启用 HTTPS?默认为 true
minio_node: '${minio_cluster}-${minio_seq}.pigsty' # minio 节点名模式
minio_data: '/data/minio'         # minio 数据目录,使用 `{x...y}` 指定多个磁盘
#minio_volumes:                   # minio 核心参数,如果未指定,则使用拼接生成的默认值
minio_domain: sss.pigsty          # minio 外部域名,默认为 `sss.pigsty`
minio_port: 9000                  # minio 服务端口,默认为 9000
minio_admin_port: 9001            # minio 控制台端口,默认为 9001
minio_access_key: minioadmin      # 根访问密钥,默认为 `minioadmin`
minio_secret_key: S3User.MinIO    # 根密钥,默认为 `S3User.MinIO`
minio_extra_vars: ''              # minio 服务器的额外环境变量
minio_provision: true             # 是否执行 minio 资源置备任务?
minio_alias: sss                  # minio 部署的客户端别名
#minio_endpoint: https://sss.pigsty:9000 # minio 别名对应的接入点,如果未指定,则使用拼接生成的默认值
minio_buckets:                    # 待创建的 minio 存储桶列表
  - { name: pgsql }
  - { name: meta ,versioning: true }
  - { name: data }
minio_users:                      # 待创建的 minio 用户列表
  - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
  - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
  - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }

MINIO_REMOVE:3 个参数,定义于 roles/minio_remove/defaults/main.yml

#-----------------------------------------------------------------
# MINIO_REMOVE
#-----------------------------------------------------------------
minio_safeguard: false            # 防止意外删除?默认为 false
minio_rm_data: true               # 移除时是否删除 minio 数据?默认为 true
minio_rm_pkg: false               # 移除时是否卸载 minio 软件包?默认为 false
# MINIO(引用)
minio_type: silo                  # 对象存储引擎,当前必须为 silo

MINIO

本节包含 minio 角色的参数, 这些是 minio.yml 剧本使用的操作标志参数。

minio_type

参数名称:minio_type,类型:enum,层次:G/C

保留的对象存储后端选择器,默认值与当前唯一合法值都是 silo。Silo 沿用 MinIO S3/Admin API、MINIO_* 环境变量与磁盘格式。

miniorustfs 不再是有效取值,会在角色身份检查阶段失败。旧 MinIO 集群升级到 v4.5 前,必须独立验证备份、MinIO → Silo 数据兼容性与回滚方案;修改参数本身不会执行数据迁移。

部署与移除角色都将 minio_type 默认为 silo。执行 minio-rm.yml 时仍必须提供 minio_clusterminio_seq 身份参数,并受 minio_safeguard、数据与软件包清理开关约束;默认引擎值不会绕过这些删除保护。


minio_seq

参数名称: minio_seq, 类型: int, 层次:I

对象存储实例标识符,必需的身份参数。没有默认值,您必须手动分配这些序列号。

通常的最佳实践是,从 1 开始分配,依次加 1,并永远不使用已经分配的序列号。 序列号与集群名称 minio_cluster 一起,唯一标识每一个对象存储实例(例如:minio-1)。

在多节点部署中,序列号还会用于生成节点名称,写入 /etc/hosts 文件中进行静态解析。


minio_cluster

参数名称: minio_cluster, 类型: string, 层次:C

对象存储集群名称,必填且没有默认值。当部署多个集群时,使用此参数区分各自的成员与监控身份。

集群名称与序列号 minio_seq 一起,唯一标识每一个对象存储实例。 例如,当集群名为 minio,序列号为 1 时,实例名称为 minio-1

角色会在整个清单中按主机的 minio_cluster 值查找成员,因此 Ansible Group 名称可以与集群标识不同。请在对象存储分组的集群变量中显式定义本参数,不要放入 all.vars,否则会把所有主机标记为 MINIO 模块成员。

部署多套集群时,还应分别设置 minio_aliasminio_domainminio_endpoint,避免共享客户端别名与域名冲突。


minio_user

参数名称: minio_user, 类型: username, 层次:C

对象存储操作系统用户名,默认为 minio

Silo 将以此用户身份运行,证书位于 ~/.minio/certs/


minio_https

参数名称: minio_https, 类型: bool, 层次:G/C

是否为对象存储服务启用 HTTPS?默认为 true

Pigsty 默认的 pgBackRest minio 仓库预设使用 HTTPS,并通过 /etc/pki/ca.crt 校验证书,因此按默认配置使用时应保持本参数为 true。pgBackRest 本身并不强制 Silo 使用 HTTPS;若显式改用 HTTP,还必须同步调整 pgbackrest_repo 的存储 TLS 选项,不能只切换本参数。

启用 HTTPS 后,Pigsty 会自动为所选服务端签发证书,证书包含 minio_domain 指定的域名以及各个节点的 IP 地址。


minio_node

参数名称: minio_node, 类型: string, 层次:C

对象存储节点名称模式,用于 多机单盘多机多盘 部署。

默认值为:${minio_cluster}-${minio_seq}.pigsty,即以实例名 + .pigsty 后缀作为默认的节点名。

在这里指定的域名模式用于生成节点名,并写入所有 Silo 节点的 /etc/hosts


minio_data

参数名称: minio_data, 类型: path, 层次:C

Silo 数据目录,默认值为 /data/minio。该参数填写文件系统目录,而不是 /dev/sdb 之类的裸块设备;MINIO 角色会创建目录并设置权限,但不会格式化或挂载生产服务器的数据盘。

单机单盘 可以使用根文件系统中的普通目录,但只适合开发测试。多机单盘多机多盘单机多盘 应使用非根盘的独立持久文件系统。分布式 Silo 会拒绝根文件系统上的数据路径。

/data/minio 可以是独立挂载点 /data 下的子目录;如果 /data 只是 / 下的普通目录,则仍属于根盘。对于多盘部署,可以使用 {x...y} 记法指定多个挂载点,例如 /data{1...4}/minio,每个展开后的路径应对应独立文件系统。

完整的挂载要求与检查方法参见 集群配置:存储路径与挂载


minio_volumes

参数名称: minio_volumes, 类型: string, 层次:C

Silo 核心卷参数,默认不指定;留空时会自动使用以下规则拼接生成:

minio_volumes: "{% if minio_cluster_size|int > 1 %}{% if minio_https|bool %}https{% else %}http{% endif %}://{{ minio_node|replace('${minio_cluster}', minio_cluster)|replace('${minio_seq}',minio_seq_range) }}:{{ minio_port|default(9000) }}{% endif %}{{ minio_data }}"
  • 在单机部署(无论是单盘还是多盘)模式下,minio_volumes 直接使用 minio_data 的值,进行单机部署。
  • 在多机部署模式下,minio_volumes 会使用 minio_node, minio_port, minio_data 参数的值生成多节点的地址,用于多机部署。
  • 在多池部署模式下,通常需要您直接指定并覆盖 minio_volumes 的值,以指定多个节点池的地址。

指定本参数时,您需要确保使用的参数与 minio_node, minio_port, minio_data 三者匹配。


minio_domain

参数名称: minio_domain, 类型: string, 层次:G

Silo 服务域名,默认为 sss.pigsty

客户端可以通过此域名访问 Silo S3 服务;该名称会包含在角色签发的 SSL 证书 SAN(Subject Alternative Name)字段中,但 MINIO 角色不会自动为 minio_domain 创建 DNS 记录。请通过 node_etc_hostsdns_records 显式添加解析,将它指向 Silo 节点 IP(单机部署)或负载均衡器 VIP(多节点部署)。


minio_port

参数名称: minio_port, 类型: port, 层次:C

Silo 服务端口,默认为 9000

这是 Silo S3 API 的监听端口,客户端通过此端口访问对象存储服务。在多节点部署中,此端口也用于节点间通信。


minio_admin_port

参数名称: minio_admin_port, 类型: port, 层次:C

Silo 控制台端口,默认为 9001

这是 Silo Web 管理控制台的监听端口。可以通过 https://<minio-ip>:9001 访问图形化管理界面。

如果希望通过 Nginx 对外暴露 Silo 控制台,可以将其添加到 infra_portal 中。控制台需要使用 HTTPS 和 WebSocket。


minio_access_key

参数名称: minio_access_key, 类型: username, 层次:C

根访问用户名(access key),默认为 minioadmin

这是 Silo 的超级管理员用户名,拥有对所有存储桶和对象的完全访问权限。建议在生产环境中修改此默认值。


minio_secret_key

参数名称: minio_secret_key, 类型: password, 层次:C

根访问密钥(secret key),默认为 S3User.MinIO

这是 Silo 超级管理员密码,与 minio_access_key 配合使用。

安全警告:请务必修改默认密码!

使用默认密码是高危行为!请务必在您的生产环境部署中修改此密码。

提示:执行 ./configure -g 时,会随机化配置向导识别的默认密码;完整范围见 默认凭证清单


minio_extra_vars

参数名称: minio_extra_vars, 类型: string, 层次:C

传递给 Silo 的额外环境变量。Silo 沿用 MINIO_* 变量名。

默认值为空字符串,您可以使用多行字符串来传递多个环境变量。例如:

minio_extra_vars: |
  MINIO_BROWSER_REDIRECT_URL=https://minio.example.com
  MINIO_SERVER_URL=https://s3.example.com

minio_provision

参数名称: minio_provision, 类型: bool, 层次:G/C

是否执行 Silo 资源置备任务?默认为 true

当启用时,Pigsty 将自动创建 minio_bucketsminio_users 中定义的存储桶和用户。 如果您不需要自动置备这些资源,可以将此参数设置为 false


minio_alias

参数名称: minio_alias, 类型: string, 层次:G

本地 Silo 集群的 mcli 客户端别名,默认值为 sss

启用 minio_provision 时,此别名会写入所有 Infra 节点与 Silo 成员上 Ansible 执行用户的 mcli 配置文件(~/.mcli/config.json);分组重叠的节点不会重复写入。 随后可以直接使用 mcli <alias> 命令访问 Silo,例如 mcli ls sss/

如果部署多个 Silo 集群,需要为每个集群指定不同的别名以避免冲突。


minio_endpoint

参数名称:minio_endpoint, 类型: string, 层次:C

部署的客户端别名对应的端点。如果指定,minio_endpoint(例如 https://sss.pigsty:9002)会替代自动拼接的 <scheme>://<minio_domain>:<minio_port>,作为 Infra 节点与 Silo 成员上客户端别名的目标端点。

mcli alias set {{ minio_alias }} {% if minio_endpoint is defined and minio_endpoint != '' %}{{ minio_endpoint }}{% else %}{% if minio_https|bool %}https{% else %}http{% endif %}://{{ minio_domain }}:{{ minio_port }}{% endif %} {{ minio_access_key }} {{ minio_secret_key }}

以上命令由角色以 Ansible 执行用户身份,在 Infra 节点与 Silo 成员上执行。


minio_buckets

参数名称: minio_buckets, 类型: bucket[], 层次:C

默认创建的 Silo 存储桶列表:

minio_buckets:
  - { name: pgsql }
  - { name: meta ,versioning: true }
  - { name: data }

默认创建三个存储桶,各有不同的用途和策略:

  • pgsql 存储桶:默认用于 PostgreSQL 的 pgBackREST 备份存储。
  • meta 存储桶:开放式存储桶,启用了版本控制(versioning),适合存储需要版本管理的重要元数据。
  • data 存储桶:开放式存储桶,用于其他用途,例如 Supabase 模板可能使用此存储桶存储业务数据。

每个存储桶都会创建一个同名的访问策略,例如 pgsql 策略拥有对 pgsql 存储桶的所有权限,以此类推。

您还可以在存储桶定义中添加 lock 标志,启用对象锁定功能,防止存储桶中的对象被意外删除。


minio_users

参数名称: minio_users, 类型: user[], 层次:C

要创建的 Silo 用户列表,默认值:

minio_users:
  - { access_key: pgbackrest  ,secret_key: S3User.Backup ,policy: pgsql }
  - { access_key: s3user_meta ,secret_key: S3User.Meta   ,policy: meta  }
  - { access_key: s3user_data ,secret_key: S3User.Data   ,policy: data  }

默认配置会创建三个用户,分别对应三个默认存储桶:

  • pgbackrest:用于 PostgreSQL pgBackREST 备份,拥有 pgsql 存储桶的访问权限。
  • s3user_meta:用于访问 meta 存储桶。
  • s3user_data:用于访问 data 存储桶。
使用默认密码是高危行为!请务必在您的部署中调整这些凭证!

提示:./configure -g 会默认修改配置文件模板中的这些密码,如果这些默认密码出现在模版文件中。


MINIO_REMOVE

本节包含 minio_remove 角色的参数, 这些是 minio-rm.yml 剧本使用的操作标志参数。

minio_safeguard

参数名称: minio_safeguard, 类型: bool, 层次:G/C/A

防止意外删除的保险开关,默认值为 false

如果启用此参数,minio-rm.yml 剧本将中止并拒绝移除 Silo 集群,从而提供防止意外删除的保护。

建议在生产环境中启用此保险开关,防止误操作导致数据丢失:

minio_safeguard: true   # 启用后,minio-rm.yml 将拒绝执行

minio_rm_data

参数名称: minio_rm_data, 类型: bool, 层次:G/C/A

移除时是否删除 Silo 数据与配置?默认值为 true

启用后,minio-rm.yml 会删除数据目录、/etc/default/silo.minio 用户目录,以及 /etc/systemd/system/silo.service。设置为 false 会保留这些数据与配置,但不会阻止服务注销、停止和禁用。


minio_rm_pkg

参数名称: minio_rm_pkg, 类型: bool, 层次:G/C/A

移除时是否卸载 Silo 软件包?默认值为 false

启用后,minio-rm.yml 会卸载 silomcli。默认禁用此选项,以便保留软件包供后续使用。

12.4 - 预置剧本

使用预置 Ansible 剧本部署或移除 Silo 对象存储集群。

MINIO 模块提供两个内置剧本:


minio.yml

minio.ymlhosts: all 运行,但会在预任务阶段跳过没有定义 minio_cluster 的主机。进入角色后还会校验:

  • minio_cluster 已定义且非空
  • minio_seq 已定义且为非负整数
  • minio_type 必须等于 silo

因此,minio_cluster 是模块成员门控,而 minio_seqminio_type 的错误会让身份校验明确失败。不要在 all.vars 中定义 minio_cluster

主要任务标签如下:

  • minio-id:校验身份,并按 minio_cluster 从整个清单计算实际成员、节点名与卷参数
  • minio_install:创建 minio OS 用户,安装 Silo 与 mcli,准备数据目录
    • minio_os_user
    • minio_pkg
    • minio_dir
  • minio_config:渲染 /etc/default/silo/etc/systemd/system/silo.service、证书和 DNS
    • minio_conf
    • minio_cert
    • minio_dns
  • minio_launch:启动或重启 silo.service
  • minio_register:写入 VictoriaMetrics FileSD 目标
  • minio_provision:由集群首个成员执行一次 mcli 别名、存储桶与用户置备

重新执行 minio.yml 可能重启正在运行的对象存储服务,但不会主动重建数据。生产环境应按集群故障预算安排执行窗口。


minio-rm.yml

minio-rm.yml 使用相同的 minio_cluster 成员门控和身份校验,并执行:

  • minio_safeguard:防误删检查,默认 false
  • minio_pause:暂停 3 秒,允许 Ctrl+C 中止
  • minio_deregister:删除 VictoriaMetrics 目标与 DNS 记录
  • minio_svc:停止并禁用 Silo 服务
  • minio_data:按 minio_rm_data 删除数据与配置
  • minio_pkg:按 minio_rm_pkg 卸载 Silo 与 mcli
危险操作

minio_rm_data 默认为 true。完整执行移除剧本会删除展开后的所有 minio_data 目录;运行前必须核对 minio_clusterminio_seqminio_type: silo 与磁盘挂载路径。只想退役服务并保留数据时,请显式设置 -e minio_rm_data=false

部署与移除角色都默认 minio_type: silo,其他取值会被拒绝。下面的删除示例仍显式传入该值,作为复核软件包、服务、证书目录和数据路径的一部分;它不是额外的交互确认门。


命令速查

./minio.yml -l <group>                         # 部署该限域内具有 minio_cluster 身份的成员
./minio.yml -l minio -t minio_install         # 安装 Silo 与 mcli,准备目录
./minio.yml -l minio -t minio_config          # 重新渲染配置、证书和 DNS
./minio.yml -l minio -t minio_launch          # 重启 Silo 服务
./minio.yml -l minio -t minio_register        # 刷新监控目标
./minio.yml -l minio -t minio_provision       # 重新置备别名、存储桶和用户

./minio-rm.yml -l minio -e minio_type=silo                         # 移除 Silo 服务、配置与数据
./minio-rm.yml -l minio -e minio_type=silo -e minio_rm_data=false  # 移除服务但保留数据和配置
./minio-rm.yml -l minio -e minio_type=silo -e minio_rm_pkg=true    # 同时卸载 Silo 与 mcli

如果配置组名与 minio_cluster 不同,-l 使用的是 Ansible 分组或主机模式,而不是逻辑集群名;请用能覆盖完整目标成员的限域表达式。


保护机制

生产集群建议在集群变量中启用防误删保险:

minio_safeguard: true

确需销毁时,可在充分核对目标和备份后显式覆盖:

./minio-rm.yml -l minio -e minio_type=silo -e minio_safeguard=false

执行演示

asciicast

12.5 - 管理预案

Silo 对象存储集群的创建、销毁、升级、扩缩容与故障处理。

创建集群

要创建一个集群,在配置清单中定义好后,执行 minio.yml 剧本即可。

minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio, minio_type: silo } }

例如,上面的配置定义了一个 SNSD 单机单盘 Silo 集群,使用以下命令即可创建所选对象存储集群:

./minio.yml -l minio  # 在 minio 分组上安装 Silo

销毁集群

要销毁一个集群,执行专用的 minio-rm.yml 剧本即可:

./minio-rm.yml -l minio -e minio_type=silo                         # 移除 Silo 集群
./minio-rm.yml -l minio -e minio_type=silo -e minio_rm_data=false  # 移除集群但保留数据与配置
./minio-rm.yml -l minio -e minio_type=silo -e minio_rm_pkg=true    # 移除集群并卸载软件包

删除角色也将 minio_type 默认为 silo,当前其他取值会被拒绝。

架构变更:Pigsty v3.6+

从 Pigsty v3.6 开始,集群移除操作已从 minio.yml 剧本迁移至专用的 minio-rm.yml 剧本。旧的 minio_clean 任务已被弃用。

移除剧本会依次尝试以下操作:

  • 从 VictoriaMetrics 监控系统中注销对象存储目标
  • 从 INFRA 节点的 DNS 服务中移除记录
  • 停止并禁用 silo.service
  • 删除数据目录和 Silo 配置(由 minio_rm_data 控制,默认执行)
  • 卸载 Silo 与 mcli 软件包(由 minio_rm_pkg 控制,默认不执行)

该剧本启用了错误容忍,返回状态不能单独证明服务、数据、DNS 与监控目标已经全部按预期处理;真实运行后应逐项核对现场。


集群扩容

本节使用 Silo 保留的 MinIO 兼容管理接口。生产操作前必须按实际 Silo 版本核对上游约束并完成专项演练。

Silo 不能直接改变既有存储池的节点或磁盘数量,但可以通过新增存储池扩容。

假设您有 这样一个 四节点 Silo 集群,希望通过新增四节点存储池将容量扩展一倍。

minio:
  hosts:
    10.10.10.10: { minio_seq: 1 , nodename: minio-1 }
    10.10.10.11: { minio_seq: 2 , nodename: minio-2 }
    10.10.10.12: { minio_seq: 3 , nodename: minio-3 }
    10.10.10.13: { minio_seq: 4 , nodename: minio-4 }
  vars:
    minio_type: silo
    minio_cluster: minio
    minio_data: '/data{1...4}'
    minio_buckets: [ { name: pgsql }, { name: infra }, { name: redis } ]
    minio_users:
      - { access_key: dba , secret_key: S3User.DBA, policy: consoleAdmin }
      - { access_key: pgbackrest , secret_key: S3User.SomeNewPassWord , policy: readwrite }

    # bind a node l2 vip (10.10.10.9) to minio cluster (optional)
    node_cluster: minio
    vip_enabled: true
    vip_vrid: 128
    vip_address: 10.10.10.9
    vip_interface: eth1

    # expose minio service with haproxy on all nodes
    haproxy_services:
      - name: minio                    # [REQUIRED] service name, unique
        port: 9002                     # [REQUIRED] service port, unique
        balance: leastconn             # [OPTIONAL] load balancer algorithm
        options:                       # [OPTIONAL] minio health check
          - 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' }
          - { name: minio-4 ,ip: 10.10.10.13 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }

首先,修改 Silo 集群定义,新增四台节点,按顺序分配序列号 5 到 8。 这里的关键一步是修改 minio_volumes 参数,将新的四个节点指定为一个新的 存储池

minio:
  hosts:
    10.10.10.10: { minio_seq: 1 , nodename: minio-1 }
    10.10.10.11: { minio_seq: 2 , nodename: minio-2 }
    10.10.10.12: { minio_seq: 3 , nodename: minio-3 }
    10.10.10.13: { minio_seq: 4 , nodename: minio-4 }
    # 新增的四个节点
    10.10.10.14: { minio_seq: 5 , nodename: minio-5 }
    10.10.10.15: { minio_seq: 6 , nodename: minio-6 }
    10.10.10.16: { minio_seq: 7 , nodename: minio-7 }
    10.10.10.17: { minio_seq: 8 , nodename: minio-8 }

  vars:
    minio_type: silo
    minio_cluster: minio
    minio_data: '/data{1...4}'
    minio_volumes: 'https://minio-{1...4}.pigsty:9000/data{1...4} https://minio-{5...8}.pigsty:9000/data{1...4}'  # 新增的集群配置
    # …… 省略其他配置

第二步,将这些节点交由 Pigsty 纳管:

./node.yml -l 10.10.10.14,10.10.10.15,10.10.10.16,10.10.10.17

第三步,在新节点上使用 Ansible 剧本 安装并准备 Silo:

./minio.yml -l 10.10.10.14,10.10.10.15,10.10.10.16,10.10.10.17 -t minio_install

第四步,在 整个集群 上使用 Ansible 剧本 重新配置 Silo:

./minio.yml -l minio -t minio_config

这一步会更新现有四个节点的 MINIO_VOLUMES 配置

第五步,一次性重启整个 Silo 集群(请注意,不要滚动重启!):

./minio.yml -l minio -t minio_launch -f 10   # 最多 10 并发,确保 8 个节点同时重启

第六步(可选):如果您使用了负载均衡,那么请确保负载均衡器的配置也已经更新。例如,将新的四个节点加入到负载均衡器的配置中:

# expose minio service with haproxy on all nodes
haproxy_services:
  - name: minio                    # [REQUIRED] service name, unique
    port: 9002                     # [REQUIRED] service port, unique
    balance: leastconn             # [OPTIONAL] load balancer algorithm
    options:                       # [OPTIONAL] minio health check
      - 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' }
      - { name: minio-4 ,ip: 10.10.10.13 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }

      - { name: minio-5 ,ip: 10.10.10.14 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
      - { name: minio-6 ,ip: 10.10.10.15 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
      - { name: minio-7 ,ip: 10.10.10.16 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }
      - { name: minio-8 ,ip: 10.10.10.17 ,port: 9000 ,options: 'check-ssl ca-file /etc/pki/ca.crt check port 9000' }

然后,执行 node.yml 剧本的 haproxy 子任务,更新负载均衡器配置:

./node.yml -l minio -t haproxy_config,haproxy_reload   # 更新负载均衡器配置并在线加载

如果您使用 L2 VIP 来确保可靠的负载均衡器接入,那么还需要将新的节点(如果有)加入到现有 NODE VIP 分组中:

./node.yml -l minio -t node_vip  # 刷新集群 L2 VIP 配置 

集群缩容

Silo 不能直接缩减既有存储池的节点或磁盘数量,但可以在存储池层次退役:先新增存储池,将旧池数据排干迁移,再退役旧池。


集群升级

首先,将新版 silomcli 软件包下载至 INFRA 节点的本地软件仓库,然后使用 SOW 重建仓库索引:

./infra.yml -t repo_create

其次,升级 Silo 服务端与 mcli 兼容客户端:

ansible minio -m package -b -a 'name=silo state=latest'  # 服务端
ansible minio -m package -b -a 'name=mcli state=latest'  # 兼容客户端

最后,使用角色重启完整 Silo 集群:

./minio.yml -l minio -t minio_config,minio_launch

软件包升级与从旧 MinIO 迁移到 Silo 是两件事。前者针对已经运行 Silo 的集群;后者必须另行完成数据兼容性验证、备份、停机窗口与回滚演练,不能直接套用本节的升级命令。


替换故障节点

# 1. 从集群中下线故障节点
bin/node-rm <your_old_node_ip>

# 2. 替换故障节点,保留原节点名称(如果 IP 变化,需要修改 Silo 集群定义)
bin/node-add <your_new_node_ip>

# 3. 在新节点上安装配置 Silo
./minio.yml -l <your_new_node_ip>

# 4. 指示 Silo 执行恢复动作
mcli admin heal

替换故障磁盘

# 1. 从集群中删除故障磁盘
umount /dev/<your_disk_device>

# 2. 替换故障磁盘,使用xfs格盘
mkfs.xfs /dev/sdb -L DRIVE1

# 3. 不要忘记设置开机自动挂载
vi /etc/fstab
# LABEL=DRIVE1     /mnt/drive1    xfs     defaults,noatime  0       2

# 4. 重新挂载
mount -a

# 5. 指示 Silo 执行恢复动作
mcli admin heal

管理 Silo 密码

minio_secret_key(默认 S3User.MinIO)是 Silo root 用户密码,渲染到 /etc/default/silo

修改密码后,使用以下命令刷新配置并重启服务(需同时重启整个集群):

./minio.yml -l minio -t minio_config,minio_launch,minio_alias -f 30  # 重新渲染配置文件,写入 Alias

如果要修改 Silo 普通用户的密码,例如 pgbackrest,请在可以访问 Silo 的节点上执行:

set +o history
mcli admin user passwd sss pgbackrest <YOUR_NEW_PASSWORD>
set -o history

然后还要修改引用该用户密码的所有配置。例如,当 pgBackRest 使用 minio S3 兼容仓库预设时,需要同步更新访问密钥密码:

./pgsql.yml -t pgbackrest_config

12.6 - 监控告警

Pigsty 如何监控 Silo,包括 Metrics V3 指标入口、Grafana 面板和告警规则。

管理界面

Silo 默认通过 minio_admin_port9001)提供管理界面,可直接访问 https://<node-ip>:9001

部分配置模板还会通过 m.pigsty 暴露管理入口。登录凭证由 minio_access_keyminio_secret_key 指定。

HTTPS 与证书信任

对象存储默认使用 Pigsty CA 签发的 HTTPS 证书。浏览器和容器客户端必须信任该 CA;生产环境不要以忽略证书校验代替正确配置证书信任。


采集链路

Silo 沿用 job="minio"clsinsipinstance 这组稳定身份标签,并使用 flavor="silo"

后端 指标链路 目标与标签
Silo VictoriaMetrics 拉取 https://<instance>:9000/minio/metrics/v3 job=minioflavor=silo

每个实例的 FileSD 目标写入 /infra/targets/minio/<minio_cluster>-<minio_seq>.yml

Silo 只注册一个 Metrics V3 根端点。该端点同时提供集群、系统、API 与聚合用量指标;Pigsty 会丢弃 bucket 标签非空的样本,不再单独注册按桶和复制端点,以控制时序基数。


Grafana 面板

Pigsty 提供 MinIO Overview / MinIO Instance 两个兼容命名的面板,用于展示 Silo Metrics V3 指标、系统日志与实例状态。

minio-overview.jpg


告警规则

当前 files/victoria/rules/minio.yml 为 Silo 定义了五条告警:

告警 条件摘要 级别
MinioServerDown minio_up < 1 持续 1 分钟 CRIT
MinioNodeOffline 5 分钟平均离线节点数大于 0,持续 3 分钟 WARN
MinioDiskOffline 5 分钟平均离线磁盘数大于 0,持续 3 分钟 WARN
MinioErasureSetUnhealthy 任一纠删码集合总体健康值小于 1,持续 1 分钟 CRIT
MinioClusterCapacityHigh 可用容量使用率超过 90%,持续 15 分钟 WARN

关键表达式使用 Metrics V3 指标名:

minio_up < 1

max by (cls) (
  avg_over_time(minio_cluster_health_nodes_offline_count{job="minio"}[5m])
) > 0

max by (cls) (
  avg_over_time(minio_cluster_health_drives_offline_count{job="minio"}[5m])
) > 0

min by (cls) (
  minio_cluster_erasure_set_overall_health{job="minio"}
  or (minio_cluster_erasure_set_overall_write_quorum{job="minio"} * 0)
) < 1

max by (cls) (
  1 - (
    (minio_cluster_health_capacity_usable_free_bytes{job="minio"}
     or (minio_cluster_health_capacity_usable_total_bytes{job="minio"} * 0))
    / minio_cluster_health_capacity_usable_total_bytes{job="minio"}
  )
) > 0.90

12.7 - 指标列表

Pigsty MINIO 模块监控 Silo 使用的 Metrics V3 接口、关键指标和稳定标签。

MINIO 模块通过 /minio/metrics/v3 采集 Silo 指标。指标集合会随服务端版本和实际启用功能变化,因此本页列出当前仪表盘与告警依赖的稳定接口,不把某个版本的完整抓取快照当作长期契约。


稳定身份标签

所有对象存储目标都使用以下 Pigsty 标签:

标签 含义 示例
job 固定模块命名空间 minio
flavor 实际后端 silo
cls minio_cluster 集群标识 minio
ins <minio_cluster>-<minio_seq> 实例标识 minio-1
ip 清单管理地址 10.10.10.10
instance 指标目标地址 10.10.10.10:9000

查询与记录规则应优先使用 clsinsip 这些稳定身份标签。


Silo Metrics V3

每个 Silo 实例只抓取 V3 根端点 /minio/metrics/v3。当前关键指标如下:

类别 关键指标 含义
存活 minio_up Pigsty 对该实例的抓取/健康状态
节点 minio_cluster_health_nodes_online_countminio_cluster_health_nodes_offline_count 在线与离线节点数
磁盘 minio_cluster_health_drives_online_countminio_cluster_health_drives_offline_count 在线与离线磁盘数
容量 minio_cluster_health_capacity_raw_total_bytes 原始总容量
容量 minio_cluster_health_capacity_usable_total_bytesminio_cluster_health_capacity_usable_free_bytes 可用总容量与剩余容量
对象 minio_cluster_usage_objects_countminio_cluster_usage_objects_total_bytes 对象数量与使用字节数
存储桶 minio_cluster_usage_objects_buckets_count 聚合存储桶数量
纠删码 minio_cluster_erasure_set_overall_healthminio_cluster_erasure_set_overall_write_quorum 纠删码集合健康与写入法定人数
API minio_api_requests_totalminio_api_requests_errors_totalminio_api_requests_4xx_errors_total API 请求与错误计数
API minio_api_requests_inflight_totalminio_api_requests_incoming_total 并发与进入请求
流量 minio_api_requests_traffic_received_bytesminio_api_requests_traffic_sent_bytes 收发字节数
延迟 minio_api_requests_ttfb_seconds_distribution 首字节延迟分布
进程 minio_system_process_cpu_total_secondsminio_system_process_resident_memory_bytes 进程 CPU 与常驻内存
系统 minio_system_drive_free_bytesminio_system_drive_used_bytesminio_system_drive_health 单盘容量与健康状态
审计 minio_audit_total_messages 审计消息计数

Pigsty 在抓取阶段丢弃 bucket 标签非空的样本,并且不注册专用 per-bucket 与 replication 端点。这是刻意的基数控制策略;如果业务确实需要逐桶指标,应单独评估时序规模后自行增加采集任务。

12.8 - 常见问题

Pigsty MINIO 对象存储模块常见问题答疑

MINIO 模块默认部署哪个引擎?

v4.5.0 当前源码部署并且只部署 Silo,minio_type 唯一合法值是 silo。MINIO 是兼容模块名,不表示运行 MinIO 服务端。

  • 新建集群建议显式写出 minio_type: silo
  • minio_type: miniominio_type: rustfs 都会在身份检查阶段失败。
  • 外部 MinIO、RustFS 或其他 S3 服务仍可作为 pgBackRest 仓库,但不由当前 MINIO 角色管理。
  • 升级由旧版本管理的 MinIO 集群前,必须先验证 MinIO → Silo 的数据兼容性、备份和回滚流程。

Pigsty 仓库为什么仍有 MinIO 或 RustFS 软件包?

MinIO 上游在 2025-10-15 改为仅分发源码,在 2025-12-03 将代码库标记为维护模式,并于 2026-04-25 归档仓库。这里的“仅分发源码”是停止提供新的社区预编译二进制,而不只是停止 RPM/DEB。

Pigsty 因此曾维护自己的 MinIO 分支 与软件包。MinIO CVE-2025-62506 影响 RELEASE.2025-10-15T17-29-55Z 之前的版本,并在该版本修复;Pigsty 后续 MinIO 分支和当前 Silo 代码都包含这一修复。

您仍可以在 Pigsty Infra 仓库中找到 MinIO/RustFS 的 RPM/DEB 包以及构建脚本,但“仓库提供软件包”不等于“v4.5 MINIO 模块支持该后端”。当前角色只接受 Silo;其他服务需要自行部署和维护。


为什么对象存储默认启用 HTTPS?

Pigsty 默认的 pgBackRest minio 仓库配置使用 HTTPS,并通过 /etc/pki/ca.crt 校验证书,以保护备份流量。pgBackRest 并非绝对禁止 HTTP;如果明确选择 HTTP,除了关闭 minio_https,还必须同步修改 pgbackrest_repo 的 TLS 选项,不能只改服务端开关。


从容器中访问 Silo 提示证书无效?

对象存储服务端证书默认由 Pigsty 私有 CA 签发;它不是服务端自签名证书,但容器镜像通常不信任这套私有 CA,因此 mcli、rclone、AWS CLI 等客户端会提示证书链无效。

例如,对于 Node.js 应用程序,可以把 Pigsty CA 证书挂载到容器内,并通过环境变量 NODE_EXTRA_CA_CERTS 指定路径:

    environment:
      NODE_EXTRA_CA_CERTS: /etc/pki/ca.crt
    volumes:
      - /etc/pki/ca.crt:/etc/pki/ca.crt:ro

如果 Silo 没有用作 pgBackRest 备份仓库,也可以选择关闭 HTTPS、改用 HTTP;同时应评估明文传输风险。


Silo 数据目录可以使用普通目录吗?

minio_data 填写的是目录路径,不是裸磁盘设备。/data/minio 可以是普通子目录,但在多节点或多盘部署中,它背后必须是非根盘的独立持久文件系统。

  • 如果 /data 已经挂载到独立本地盘、云盘、分区或 LVM 逻辑卷,那么 /data/minio 可以直接使用。
  • 如果 /data/minio 只是根文件系统 / 下创建的目录,分布式 Silo 会将其标记为根盘并拒绝使用,错误为 drive is part of root drive, will not be used
  • 单机多盘的每个路径都应对应独立文件系统,不能用同一块盘上的多个目录模拟多盘。
  • 只有 单机单盘 模式可以直接使用根文件系统中的普通目录,且仅适合开发测试或非关键场合。

使用下面的命令检查实际挂载点:

findmnt -T /
findmnt -T /data/minio

详细说明参见 集群配置:存储路径与挂载;三节点单盘拓扑参见 多机单盘


如何向已有的 Silo 集群中添加新的成员?

在部署之前应规划好 Silo 集群容量,因为新增存储池需要全局重启。

可以通过为现有集群增加一组服务器节点,创建新的存储池来扩容。

不能直接修改既有存储池的节点数与磁盘数,只能通过添加新存储池扩容。

详细步骤请参考 Pigsty 文档:集群扩容,以及 MinIO 官方文档:扩展 MinIO 部署


如何移除 Silo 集群?

从 Pigsty v3.6 开始,移除 MinIO 集群需要使用专用的 minio-rm.yml 剧本:

./minio-rm.yml -l minio -e minio_type=silo                         # 移除 Silo 集群
./minio-rm.yml -l minio -e minio_type=silo -e minio_rm_data=false  # 移除集群但保留数据

删除角色也把 minio_type 默认为 silo,其他取值会被拒绝。示例仍显式写出该值,方便删除前连同集群身份和路径一起复核。

minio_rm_data 默认为 true,而移除角色会容忍部分清理错误。真实执行前应核对精确的 -l 目标和近期备份,执行后再检查服务、数据目录、DNS 与监控目标,不能只凭剧本返回状态判断清理完成。

如果您启用了 minio_safeguard 保护,需要显式覆盖才能执行移除:

./minio-rm.yml -l minio -e minio_type=silo -e minio_safeguard=false

mcli 命令与 mc 命令有什么区别?

Pigsty 将兼容的 MinIO 客户端以 mcli 命令和软件包名交付,而不是使用上游的 mc 名称,从而避免与同名的 Midnight Commander 文件管理器冲突。

mcli 是 Pigsty 对兼容客户端的交付名称,CLI 接口沿用 mc;具体版本仍可能随 Pigsty 打包更新。您可以在 MinIO 客户端文档 中查阅命令参考。


如何监控 Silo 集群状态?

Pigsty 为 Silo 提供了开箱即用的监控能力;面板与指标仍保留 MinIO 兼容命名:

  • Grafana 面板MinIO OverviewMinIO Instance
  • 告警规则:包括 MinIO 宕机、节点离线、磁盘离线等告警
  • Silo 内置控制台:通过 https://<minio-ip>:9001 访问

详情请参阅 监控告警 文档

13 - 模块:REDIS

使用统一的 REDIS 模块部署 Redis 或 Valkey,并支持独立主从、原生集群与 Sentinel 三种模式。

REDIS 是 Pigsty 的 Redis 兼容缓存模块。您可以通过 redis_type 选择 RedisValkey,默认仍为 redis。 两种引擎都支持主从复制、Sentinel 与原生集群模式,并复用相同的配置路径、实例服务名、监控和日志入口。

redis_type: redis   # 默认;也可设置为 valkey

角色会安装所选引擎与 redis-exporter,实例进程分别使用 redis-server / redis-clivalkey-server / valkey-cli。切换 redis_type 会改变软件包和二进制,并不会自动验证数据格式、复制拓扑或回滚路径;已有集群切换前应先演练,且同一逻辑集群的所有节点必须使用同一引擎。

默认 Redis 软件包继续采用 7.2 BSD 分支;不同操作系统仓库中的小版本可能不同,应以目标仓库元数据为准。

13.1 - 集群配置

根据需求场景选择合适的 Redis 模式,并通过配置清单表达您的需求

概念

Redis 的实体概念模型与 PostgreSQL 几乎相同,同样包括 集群(Cluster)实例(Instance) 的概念。注意这里的 Cluster 指的不是 Redis 原生集群方案中的集群。

REDIS 模块与 PGSQL 模块核心的区别在于,Redis 通常采用 单机多实例 部署,而不是 PostgreSQL 的 1:1 部署:一个物理/虚拟机节点上通常会部署 多个 Redis 实例,以充分利用多核 CPU。因此 配置管理 Redis 实例的方式与 PGSQL 稍有不同。

在 Pigsty 管理的 Redis 中,节点完全隶属于集群,即目前尚不允许在一个节点上部署两个不同集群的 Redis 实例,但这并不影响您在一个节点上部署多个独立 Redis 主从实例。当然这样也会有一些局限性,例如在这种情况下您就无法为同一个节点上的不同实例指定不同的密码了。

服务端实现由 redis_type 选择:默认 redis,也可设为 valkey。 该参数应在集群层统一设置;角色会切换软件包、*-server*-cli 二进制,但继续使用 /etc/redis/data/redis、实例 systemd 单元名和 redis 监控命名空间。 已有集群切换引擎前必须单独验证数据与回滚路径。


身份参数

Redis 身份参数 是定义 Redis 集群时必须提供的信息,包括:

名称 属性 说明 例子
redis_cluster 必选,集群级别 集群名 redis-test
redis_node 必选,节点级别 节点号 1,2
redis_instances 必选,节点级别 实例定义 { 6001 : {} ,6002 : {}}
  • redis_cluster:Redis 集群名称,作为集群资源的顶层命名空间。
  • redis_node:Redis 节点标号,整数,在集群内唯一,用于区分不同节点。
  • redis_instances:JSON 对象,Key 为实例端口号,Value 为包含实例其他配置 JSON 对象。

工作模式

Redis 有三种不同的工作模式,由 redis_mode 参数指定:

  • standalone:默认的独立主从模式
  • cluster:Redis 原生分布式集群模式
  • sentinel:哨兵模式,可以为主从模式的 Redis 提供高可用能力

下面给出了三种 Redis 集群的定义样例:

  • 一个1节点,一主一从的 Redis Standalone 集群:redis-ms
  • 一个1节点,3实例的 Redis Sentinel 集群:redis-sentinel
  • 一个2节点,6实例的 Redis Cluster 集群: redis-cluster
redis-ms: # redis 经典主从集群
  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 哨兵 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 原生集群: 3主 x 3从
  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 }

以上示例省略了 redis_type,因此使用默认 Redis。若要部署 Valkey,在对应集群的 vars 中增加 redis_type: valkey;不要在同一逻辑集群内混用两种引擎。


局限性

  • 一个节点只能属于一个 Redis 集群,这意味着您不能将一个节点同时分配给两个不同的 Redis 集群。
  • 在每个 Redis 节点上,您需要为 Redis 实例 分配唯一的端口号,避免端口冲突。
  • 通常同一个 Redis 集群会使用同一个密码,但一个 Redis 节点上的多个 Redis 实例无法设置不同的密码(因为 redis_exporter 只允许使用一个密码)
  • Redis Cluster 自带高可用,而 Redis 主从的高可用需要在 Sentinel 中额外进行手工配置:因为我们不知道您是否会部署 Sentinel。
  • 好在配置 Redis 主从实例的高可用非常简单,可以通过 Sentinel 进行配置,详情请参考 管理-设置Redis主从高可用

典型配置示例

以下是一些常见场景的 Redis 配置示例:

缓存集群(纯内存)

适用于对数据持久性要求不高的纯缓存场景:

redis-cache:
  hosts:
    10.10.10.10: { redis_node: 1 , redis_instances: { 6379: { }, 6380: { } } }
    10.10.10.11: { redis_node: 2 , redis_instances: { 6379: { }, 6380: { } } }
  vars:
    redis_cluster: redis-cache
    redis_password: 'cache.password'
    redis_max_memory: 2GB
    redis_mem_policy: allkeys-lru    # 内存满时淘汰最近最少使用的Key
    redis_rdb_save: []               # 禁用 RDB 持久化
    redis_aof_enabled: false         # 禁用 AOF 持久化

Session 存储集群

适用于 Web 应用 Session 存储,需要一定的持久性:

redis-session:
  hosts:
    10.10.10.10: { redis_node: 1 , redis_instances: { 6379: { }, 6380: { replica_of: '10.10.10.10 6379' } } }
  vars:
    redis_cluster: redis-session
    redis_password: 'session.password'
    redis_max_memory: 1GB
    redis_mem_policy: volatile-lru   # 只淘汰设置了过期时间的Key
    redis_rdb_save: ['300 1']        # 5分钟至少1个变更时保存
    redis_aof_enabled: false

消息队列集群

适用于简单的消息队列场景,需要较高的数据可靠性:

redis-queue:
  hosts:
    10.10.10.10: { redis_node: 1 , redis_instances: { 6379: { }, 6380: { replica_of: '10.10.10.10 6379' } } }
  vars:
    redis_cluster: redis-queue
    redis_password: 'queue.password'
    redis_max_memory: 4GB
    redis_mem_policy: noeviction     # 内存满时拒绝写入,不淘汰数据
    redis_rdb_save: ['60 1']         # 1分钟至少1个变更时保存
    redis_aof_enabled: true          # 启用 AOF 获得更好的持久性

高可用主从集群

带有 Sentinel 自动故障转移的主从集群:

# 主从集群
redis-ha:
  hosts:
    10.10.10.10: { redis_node: 1 , redis_instances: { 6379: { } } }                              # 主库
    10.10.10.11: { redis_node: 2 , redis_instances: { 6379: { replica_of: '10.10.10.10 6379' } } } # 从库1
    10.10.10.12: { redis_node: 3 , redis_instances: { 6379: { replica_of: '10.10.10.10 6379' } } } # 从库2
  vars:
    redis_cluster: redis-ha
    redis_password: 'ha.password'
    redis_max_memory: 8GB

# 哨兵集群(管理上述主从集群)
redis-sentinel:
  hosts:
    10.10.10.10: { redis_node: 1 , redis_instances: { 26379: { } } }
    10.10.10.11: { redis_node: 2 , redis_instances: { 26379: { } } }
    10.10.10.12: { redis_node: 3 , redis_instances: { 26379: { } } }
  vars:
    redis_cluster: redis-sentinel
    redis_password: 'sentinel.password'
    redis_mode: sentinel
    redis_max_memory: 64MB
    redis_sentinel_monitor:
      - { name: redis-ha, host: 10.10.10.10, port: 6379, password: 'ha.password', quorum: 2 }

大容量原生集群

适用于大数据量、高吞吐场景的原生分布式集群:

redis-cluster:
  hosts:
    10.10.10.10: { redis_node: 1 , redis_instances: { 6379: { }, 6380: { }, 6381: { } } }
    10.10.10.11: { redis_node: 2 , redis_instances: { 6379: { }, 6380: { }, 6381: { } } }
    10.10.10.12: { redis_node: 3 , redis_instances: { 6379: { }, 6380: { }, 6381: { } } }
    10.10.10.13: { redis_node: 4 , redis_instances: { 6379: { }, 6380: { }, 6381: { } } }
  vars:
    redis_cluster: redis-cluster
    redis_password: 'cluster.password'
    redis_mode: cluster
    redis_cluster_replicas: 1        # 每个主分片1个从库
    redis_max_memory: 16GB           # 每个实例最大内存
    redis_rdb_save: ['900 1']
    redis_aof_enabled: false

# 这将创建一个 6主6从 的原生集群
# 总容量约 96GB (6 * 16GB)

安全加固配置

生产环境推荐的安全配置:

redis-secure:
  hosts:
    10.10.10.10: { redis_node: 1 , redis_instances: { 6379: { } } }
  vars:
    redis_cluster: redis-secure
    redis_password: 'StrongP@ssw0rd!'  # 使用强密码
    redis_bind_address: ''             # 绑定到内网IP而非 0.0.0.0
    redis_max_memory: 4GB
    redis_rename_commands:             # 重命名危险命令
      FLUSHDB: 'DANGEROUS_FLUSHDB'
      FLUSHALL: 'DANGEROUS_FLUSHALL'
      DEBUG: ''                        # 禁用命令
      CONFIG: 'ADMIN_CONFIG'

13.2 - 参数列表

REDIS 模块提供 19 个部署参数与 3 个移除参数,可选择 Redis 或 Valkey 引擎。

REDIS 模块的参数列表,共有 22 个参数,分为两个部分:

  • REDIS:19 个参数,用于 Redis/Valkey 集群的部署与配置
  • REDIS_REMOVE:3 个参数,控制 Redis 集群的移除
架构变化:Pigsty v3.6+

自 Pigsty v3.6 起,redis.yml 剧本不再包含移除功能,移除相关参数已迁移至独立的 redis_remove 角色和 redis-rm.yml 剧本。


参数概览

REDIS 参数组用于 Redis 集群的部署与配置,包括身份标识、实例定义、工作模式、内存配置、持久化以及监控。

参数 类型 级别 说明
redis_cluster string C Redis 数据库集群名称,必选身份参数
redis_instances dict I Redis 节点上的实例定义
redis_node int I Redis 节点编号,正整数,集群内唯一,必选身份参数
redis_fs_main path C Redis 主数据目录,默认为 /data/redis
redis_exporter_enabled bool C Redis Exporter 是否启用?
redis_exporter_port port C Redis Exporter 监听端口
redis_exporter_options string C/I Redis Exporter 命令参数
redis_type enum G/C 服务端引擎:redis(默认)或 valkey
redis_mode enum C Redis 集群模式:sentinel,cluster,standalone
redis_conf string C Redis 配置文件模板,sentinel 除外
redis_bind_address ip C Redis 监听地址,默认值 0.0.0.0,留空则绑定主机 IP
redis_max_memory size C/I Redis 可用的最大内存
redis_mem_policy enum C Redis 内存逐出策略
redis_password password C Redis 密码,默认留空则禁用密码
redis_rdb_save string[] C Redis RDB 保存指令,字符串列表,空数组则禁用 RDB
redis_aof_enabled bool C Redis AOF 是否启用?
redis_rename_commands dict C Redis 危险命令重命名列表
redis_cluster_replicas int C Redis 原生集群中每个主库配几个从库?
redis_sentinel_monitor master[] C Redis 哨兵监控的主库列表,只在哨兵集群上使用

REDIS_REMOVE 参数组控制 Redis 集群的移除行为,包括防误删保险、数据清理以及软件包卸载。

参数 类型 级别 说明
redis_safeguard bool G/C/A true 时无条件拒绝移除操作
redis_rm_data bool G/C/A 移除 Redis 实例时是否一并移除数据目录?
redis_rm_pkg bool G/C/A 移除时是否卸载所选引擎与 redis-exporter?

默认参数

REDIS:19 个参数,定义于 roles/redis/defaults/main.yml

#-----------------------------------------------------------------
# REDIS
#-----------------------------------------------------------------
#redis_cluster:             <集群> # Redis数据库集群名称,必选身份参数
#redis_node: 1              <节点> # Redis节点编号,正整数,集群内唯一,必选身份参数
#redis_instances: {}        <节点> # Redis节点上的实例定义
redis_fs_main: /data/redis        # Redis主数据目录,默认为 `/data/redis`
redis_exporter_enabled: true      # Redis Exporter 是否启用?
redis_exporter_port: 9121         # Redis Exporter监听端口
redis_exporter_options: ''        # Redis Exporter命令参数
redis_type: redis                 # 服务端引擎:redis 或 valkey
redis_mode: standalone            # Redis集群模式:sentinel,cluster,standalone
redis_conf: redis.conf            # Redis配置文件模板,sentinel 除外
redis_bind_address: '0.0.0.0'     # Redis监听地址,默认 `0.0.0.0`,留空则会绑定主机IP
redis_max_memory: 1GB             # Redis可用的最大内存
redis_mem_policy: allkeys-lru     # Redis内存逐出策略
redis_password: ''                # Redis密码,默认留空则禁用密码
redis_rdb_save: ['1200 1']        # Redis RDB 保存指令,字符串列表,空数组则禁用RDB
redis_aof_enabled: false          # Redis AOF 是否启用?
redis_rename_commands: {}         # Redis危险命令重命名列表
redis_cluster_replicas: 1         # Redis原生集群中每个主库配几个从库?
redis_sentinel_monitor: []        # Redis哨兵监控的主库列表,仅用于哨兵集群

REDIS_REMOVE:3 个参数,定义于 roles/redis_remove/defaults/main.yml

#-----------------------------------------------------------------
# REDIS_REMOVE
#-----------------------------------------------------------------
redis_safeguard: false            # 为 true 时无条件拒绝移除操作
redis_rm_data: true               # 移除Redis实例时是否一并移除数据目录?
redis_rm_pkg: false               # 是否卸载所选引擎与 redis-exporter?

REDIS

本节包含 redis 角色的参数, 这些是 redis.yml 剧本使用的操作标志参数。

redis_cluster

参数名称: redis_cluster, 类型: string, 层次:C

身份参数,必选参数,必须显式在集群层面配置,将用作集群内资源的命名空间。

需要遵循特定命名规则:[a-z][a-z0-9-]*,以兼容不同约束对身份标识的要求,建议使用 redis- 作为集群名前缀。

redis_node

参数名称: redis_node, 类型: int, 层次:I

Redis 节点序列号,身份参数,必选参数,必须显式在节点(Host)层面配置。

自然数,在集群中应当是唯一的,用于区别与标识集群内的不同节点,从0或1开始分配。

redis_instances

参数名称: redis_instances, 类型: dict, 层次:I

当前 Redis 节点上的 Redis 实例定义,必选参数,必须显式在节点(Host)层面配置。

内容为 JSON KV 对象格式。Key 为数值类型端口号,Value 为该实例特定的 JSON 配置项。

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 }

每一个 Redis 实例在对应节点上监听一个唯一端口,实例配置项中 replica_of 用于设置一个实例的上游主库地址,构建主从复制关系。

redis_instances:
    6379: {}
    6380: { replica_of: '10.10.10.13 6379' }
    6381: { replica_of: '10.10.10.13 6379' }

redis_fs_main

参数名称: redis_fs_main, 类型: path, 层次:C

Redis 使用的主数据目录,默认为 /data/redis

部署阶段不允许使用旧值 /dataredis 角色的 identity assert 会直接报错);移除阶段为兼容旧配置,redis-rm.ymlredis_fs_main=/data 时会按 /data/redis 执行删除。

数据目录的属主为操作系统用户 redis,内部结构详情请参考 FHS:Redis

redis_exporter_enabled

参数名称: redis_exporter_enabled, 类型: bool, 层次:C

是否启用 Redis 监控组件 Redis Exporter?

默认启用,在每个 Redis 节点上部署一个,默认监听 redis_exporter_port 9121 端口。所有本节点上 Redis 实例的监控指标都由它负责抓取。

将此参数设为 false 时,roles/redis/tasks/exporter.yml 仍会渲染配置文件,但会跳过 redis_exporter systemd 服务的启动步骤(redis_exporter_launch 任务带有 when: redis_exporter_enabled|bool 判断),可用于在节点上保留手工配置的 exporter。 redis_register 仍会写入该节点的 VictoriaMetrics 文件发现目标;如果没有自行提供同端口的 Exporter,应同时处理该监控目标,避免持续抓取失败。

redis_exporter_port

参数名称: redis_exporter_port, 类型: port, 层次:C

Redis Exporter 监听端口,默认值为:9121

redis_exporter_options

参数名称: redis_exporter_options, 类型: string, 层次:C/I

传给 Redis Exporter 的额外命令行参数,会被渲染到 /etc/default/redis_exporter 中(参见 roles/redis/tasks/exporter.yml),默认为空字符串。REDIS_EXPORTER_OPTS 最终会附加到 systemd 服务的 ExecStart=/bin/redis_exporter $REDIS_EXPORTER_OPTS,可用于配置额外的抓取目标或过滤行为。

redis_type

参数名称:redis_type,类型:enum,层次:G/C

选择 REDIS 模块使用的服务端实现,允许值为 redisvalkey,默认 redis

角色会安装与该值同名的软件包,并在实例 systemd 单元中调用 /bin/redis-server / /bin/redis-cli/bin/valkey-server / /bin/valkey-cli。配置路径、数据目录、实例服务名、Exporter 与监控标签仍使用 redis 命名空间,以保持现有清单和运维入口兼容。

应在集群层为所有成员设置相同值。修改 redis_type 只会改变角色选择的软件包和二进制,不会自动验证 RDB/AOF、复制、Sentinel 或 Cluster 的跨版本兼容性;已有集群切换前应先演练并准备回滚。

redis_mode

参数名称: redis_mode, 类型: enum, 层次:C

Redis 集群的工作模式,有三种选项:standalone, cluster, sentinel,默认值为 standalone

  • standalone:默认,独立的 Redis 主从模式
  • cluster: Redis 原生集群模式
  • sentinel:Redis 高可用组件:哨兵

当使用 standalone 模式时,Pigsty 会根据 replica_of 参数设置 Redis 主从复制关系。

当使用 cluster 模式时,Pigsty 会根据 redis_cluster_replicas 参数使用所有定义的实例创建原生 Redis 集群。

redis_mode=sentinel 时,redis.yml 会执行 redis-ha 阶段,将 redis_sentinel_monitor 中的目标批量下发到所有哨兵;当 redis_mode=cluster 时还会执行 redis-join 阶段,调用所选引擎的 redis-clivalkey-cli 执行 --cluster create。这两个阶段均在普通 ./redis.yml -l <cluster> 中自动触发,也可以通过 -t redis-ha-t redis-join 单独运行。

redis_conf

参数名称: redis_conf, 类型: string, 层次:C

Redis 配置模板路径,Sentinel 除外。

默认值:redis.conf,这是一个模板文件,位于 roles/redis/templates/redis.conf

如果你想使用自己的 Redis 配置模板,你可以将它放在 templates/ 目录中,并设置此参数为模板文件名。

注意: Redis Sentinel 使用的是另一个不同的模板文件,即 roles/redis/templates/redis-sentinel.conf

redis_bind_address

参数名称: redis_bind_address, 类型: ip, 层次:C

Redis 服务器绑定的 IP 地址,空字符串将使用配置清单中定义的主机名。

默认值:0.0.0.0,这将绑定到此主机上的所有可用 IPv4 地址。

在生产环境中出于安全性考虑,建议仅绑定内网 IP,即将此值设置为空字符串 ''

当该值为空字符串时,模板 roles/redis/templates/redis.conf 会使用 inventory_hostname 渲染 bind <ip>,从而绑定到清单中声明的管理地址。

redis_max_memory

参数名称: redis_max_memory, 类型: size, 层次:C/I

每个 Redis 实例使用的最大内存配置,默认值:1GB

redis_mem_policy

参数名称: redis_mem_policy, 类型: enum, 层次:C

Redis 内存回收策略,默认值:allkeys-lru

  • noeviction:内存达限时不保存新值:当使用主从复制时仅适用于主库
  • allkeys-lru:保持最近使用的键;删除最近最少使用的键(LRU)
  • allkeys-lfu:保持频繁使用的键;删除最少频繁使用的键(LFU)
  • volatile-lru:删除带有真实过期字段的最近最少使用的键
  • volatile-lfu:删除带有真实过期字段的最少频繁使用的键
  • allkeys-random:随机删除键以为新添加的数据腾出空间
  • volatile-random:随机删除带有过期字段的键
  • volatile-ttl:删除带有真实过期字段和最短剩余生存时间(TTL)值的键。

详情请参阅 Redis内存回收策略

redis_password

参数名称: redis_password, 类型: password, 层次:C/N

Redis 密码,空字符串将禁用密码,这是默认行为。

注意,由于 redis_exporter 的实现限制,您每个节点只能设置一个 redis_password。这通常不是问题,因为 pigsty 不允许在同一节点上部署两个不同的 Redis 集群。

Pigsty 会自动将此密码写入 /etc/default/redis_exporterREDIS_PASSWORD=...),并通过 REDISCLI_AUTH 传给 redis-haredis-join 所选的 redis-cli / valkey-cli,避免把密码直接放在命令行参数中。

请在生产环境中使用强密码

redis_rdb_save

参数名称: redis_rdb_save, 类型: string[], 层次:C

Redis RDB 保存指令,使用空列表则禁用 RDB。

默认值是 ["1200 1"]:如果最近20分钟至少有1个键更改,则将数据集转储到磁盘。

详情请参考 Redis持久化

redis_aof_enabled

参数名称: redis_aof_enabled, 类型: bool, 层次:C

启用 Redis AOF 吗?默认值是 false,即不使用 AOF。

redis_rename_commands

参数名称: redis_rename_commands, 类型: dict, 层次:C

重命名 Redis 危险命令,这是一个 k:v 字典:old: new,old 是待重命名的命令名称,new 是重命名后的名字。

默认值:{},你可以通过设置此值来隐藏像 FLUSHDBFLUSHALL 这样的危险命令,下面是一个例子:

{
  "keys": "op_keys",
  "flushdb": "op_flushdb",
  "flushall": "op_flushall",
  "config": "op_config"  
}

redis_cluster_replicas

参数名称: redis_cluster_replicas, 类型: int, 层次:C

在 Redis 原生集群中,应当为一个 Master/Primary 实例配置多少个从库?默认值为: 1,即每个主库配一个从库。

redis_sentinel_monitor

参数名称: redis_sentinel_monitor, 类型: master[], 层次:C

Redis 哨兵监控的主库列表,只在哨兵集群上使用。每个待纳管的主库定义方式如下所示:

redis_sentinel_monitor:  # primary list for redis sentinel, use cls as name, primary ip:port
  - { name: redis-src, host: 10.10.10.45, port: 6379 ,password: redis.src, quorum: 1 }
  - { name: redis-dst, host: 10.10.10.48, port: 6379 ,password: redis.dst, quorum: 1 }

其中,namehost 是必选参数,portpasswordquorum 是可选参数,quorum 用于设置判定主库失效所需的法定人数数,通常大于哨兵实例数的一半(默认为1)。

从 Pigsty 4.0 开始还可以为某个条目添加 remove: true,此时 redis-ha 阶段只会执行 SENTINEL REMOVE <name>,用于清理不再需要的目标。


REDIS_REMOVE

本节包含 redis_remove 角色的参数, 这些是 redis-rm.yml 剧本使用的操作标志参数。

redis_safeguard

参数名称: redis_safeguard, 类型: bool, 层次:G/C/A

Redis 的防误删安全保险开关,默认值为 false。设置为 true 时,redis-rm.yml 会在注销、停服和删除之前 直接中止;它是静态布尔开关,不会探测 Redis 实例是否正在运行。

可以通过命令行参数 -e redis_safeguard=false 强制覆盖此保护。

redis_rm_data

参数名称: redis_rm_data, 类型: bool, 层次:G/C/A

移除 Redis 实例时,是否一并移除 Redis 数据目录?默认为 true

数据目录(默认 /data/redis/,即 redis_fs_main)包含了 Redis 的 RDB 与 AOF 文件,如果不移除它们,那么新部署的 Redis 实例将会从这些备份文件中加载数据。

设置为 false 可以保留数据目录用于后续恢复。

redis_rm_pkg

参数名称: redis_rm_pkg, 类型: bool, 层次:G/C/A

移除 Redis 节点时,是否一并卸载 redis_type 指定的引擎与 redis-exporter 软件包?默认为 false。指定 redis_port 只移除单个实例时不会卸载共享软件包。

通常情况下不需要卸载软件包,仅当需要彻底清理节点时才需要启用此选项。

13.3 - 预置剧本

如何使用预置的 ansible 剧本来管理 Redis 集群,常用管理命令速查。

REDIS 模块提供了两个剧本,用于部署/移除 Redis 集群/节点/实例:


redis.yml

用于部署 Redis 的 redis.yml 剧本包含以下子任务:

redis_node        : 初始化redis节点
  - redis_install : 按 `redis_type` 安装 Redis 或 Valkey,并安装 `redis-exporter`
  - redis_user    : 创建操作系统用户 redis
  - redis_dir     : 配置 redis的FHS目录结构
redis_exporter    : 配置 redis_exporter 监控
  - redis_exporter_config  : 生成redis_exporter配置
  - redis_exporter_launch  : 启动redis_exporter
redis_instance    : 初始化并重启redis集群/节点/实例
  - redis_config  : 生成redis实例配置
  - redis_launch  : 启动redis实例
redis_register    : 将redis注册到基础设施中
redis_ha          : 配置redis哨兵(仅sentinel模式)
redis_join        : 组建redis原生集群(仅cluster模式)

操作级别

redis.yml 支持三种操作级别,通过 -l 限制目标范围,通过 -e redis_port=<port> 指定单个实例:

操作级别 限制参数 说明
集群 -l <cluster> 部署整个 Redis 集群的所有节点和实例
节点 -l <ip> 部署指定节点上的所有 Redis 实例
实例 -l <ip> -e redis_port=<port> 仅部署指定节点上的单个实例

集群级别操作

部署整个 Redis 集群,包括所有节点上的所有实例:

./redis.yml -l redis-ms           # 部署名为 redis-ms 的整个集群
./redis.yml -l redis-test         # 部署名为 redis-test 的整个集群
./redis.yml -l redis-sentinel     # 部署哨兵集群

集群级别操作会:

  • redis_type 安装 Redis 或 Valkey,并安装 redis-exporter
  • 在所有节点上创建 redis 用户和目录结构
  • 启动所有节点上的 redis_exporter
  • 部署并启动所有定义的 Redis 实例
  • 将所有实例注册到监控系统
  • 如果是 sentinel 模式,配置哨兵监控目标
  • 如果是 cluster 模式,组建原生集群

节点级别操作

仅部署指定节点上的所有 Redis 实例:

./redis.yml -l 10.10.10.10        # 部署该节点上的所有实例
./redis.yml -l 10.10.10.11        # 部署另一个节点

节点级别操作适用于:

  • 向现有集群 扩容新节点
  • 重新部署某个节点上的所有实例
  • 节点故障恢复后重新初始化

注意:节点级别命令仍会进入 redis-ha / redis-join 的模式判断:在 sentinel 模式下会刷新哨兵纳管目标;在 cluster 模式下,剧本先使用所选 CLI 检查种子实例的 cluster_state:ok,已健康则退出,否则执行 --cluster create。这个检查不会替代扩容流程,向既有原生集群加节点仍应手工执行 redis-cli / valkey-cli --cluster add-nodereshard

实例级别操作

通过 -e redis_port=<port> 参数指定单个实例进行操作:

# 仅部署 10.10.10.10 上的 6379 端口实例
./redis.yml -l 10.10.10.10 -e redis_port=6379

# 仅部署 10.10.10.11 上的 6380 端口实例
./redis.yml -l 10.10.10.11 -e redis_port=6380

实例级别操作适用于:

  • 向现有节点 添加新实例
  • 重新部署单个故障实例
  • 更新单个实例的配置

当指定 redis_port 时:

  • 仅渲染该端口对应的配置文件
  • 仅启动/重启该端口对应的 systemd 服务
  • 会重写该节点的监控注册文件(内容来自 redis_instances 全量定义)
  • 不会 启停 redis_exporter 或重载 Vector 日志配置
  • 不会 影响同节点上的其他 Redis 实例进程

常用标签

可以通过 -t <tag> 参数选择性执行部分任务:

# 仅安装软件包,不启动服务
./redis.yml -l redis-ms -t redis_node

# 仅更新配置并重启实例
./redis.yml -l redis-ms -t redis_config,redis_launch

# 仅更新监控注册
./redis.yml -l redis-ms -t redis_register

# 仅配置哨兵监控目标(sentinel模式)
./redis.yml -l redis-sentinel -t redis-ha

# 仅组建原生集群(cluster模式,首次部署后自动执行)
./redis.yml -l redis-cluster -t redis-join

幂等性说明

redis.yml 的大部分任务可安全重复执行;原生集群初始化仍需注意拓扑状态:

  • redis_node / redis_exporter / redis_instance / redis_register 重复执行会覆盖配置并重启实例
  • redis-ha 重复执行会按 redis_sentinel_monitor 重新下发 SENTINEL REMOVE/MONITOR
  • redis-join 会先检查种子实例是否已经达到 cluster_state:ok,健康集群会直接退出;未完成、损坏或正在扩容的拓扑不会由这个检查自动修复,不能把它当作通用的 add-node/reshard 操作

提示:如果只想更新配置而不想重启所有实例,可以使用 -t redis_config 仅渲染配置,然后手动重启需要的实例。

Redis/Valkey 采用 Type=notify。实例启动时 systemd 最多等待 1800s 收到就绪通知,以覆盖大型 RDB/AOF 加载与恢复;


redis-rm.yml

用于移除 Redis 的 redis-rm.yml 剧本包含以下子任务:

redis_safeguard  : 安全检查,当 redis_safeguard=true 时拒绝执行
redis_deregister : 从监控系统移除注册信息
  - rm_metrics   : 删除 /infra/targets/redis/*.yml
  - rm_logs      : 撤销 /etc/vector/redis.yaml
redis_exporter   : 停止并禁用 redis_exporter
redis            : 停止并禁用 redis 实例
redis_data       : 删除数据目录(当 redis_rm_data=true)
redis_pkg        : 卸载所选引擎与 redis-exporter(当 redis_rm_pkg=true)

标签化执行遵循数据/卸包开关:-t redis 总会进入实例停服阶段; 单独运行 -t redis_data 只有在 redis_rm_data=true 时才停服, 单独运行 -t redis_pkg 只有在 redis_rm_pkg=true 时才停服。 换言之,-t redis_data -e redis_rm_data=false-t redis_pkg -e redis_rm_pkg=false 不会仅因选中标签就停止 Redis。真实移除前应核对完全相同的 -l、标签与 extra-vars。

操作级别

redis-rm.yml 同样支持三种操作级别:

操作级别 限制参数 说明
集群 -l <cluster> 移除整个 Redis 集群的所有节点和实例
节点 -l <ip> 移除指定节点上的所有 Redis 实例
实例 -l <ip> -e redis_port=<port> 仅移除指定节点上的单个实例

集群级别移除

移除整个 Redis 集群:

./redis-rm.yml -l redis-ms        # 移除整个 redis-ms 集群
./redis-rm.yml -l redis-test      # 移除整个 redis-test 集群

集群级别移除会:

  • 从监控系统注销所有节点的所有实例
  • 停止所有节点上的 redis_exporter
  • 停止并禁用所有 Redis 实例
  • 删除所有数据目录(如果 redis_rm_data=true
  • 卸载 redis_type 指定的引擎与 redis-exporter(如果 redis_rm_pkg=true

节点级别移除

仅移除指定节点上的所有 Redis 实例:

./redis-rm.yml -l 10.10.10.10     # 移除该节点上的所有实例
./redis-rm.yml -l 10.10.10.11     # 移除另一个节点

节点级别移除适用于:

  • 集群 缩容,下线整个节点
  • 节点退役前的清理
  • 节点迁移前的准备

节点级别移除会:

  • 从监控系统注销该节点的所有实例
  • 停止该节点上的 redis_exporter
  • 停止该节点上的所有 Redis 实例
  • 删除该节点上的所有数据目录
  • 删除该节点上的 Vector 日志配置

实例级别移除

通过 -e redis_port=<port> 参数指定移除单个实例:

# 仅移除 10.10.10.10 上的 6379 端口实例
./redis-rm.yml -l 10.10.10.10 -e redis_port=6379

# 仅移除 10.10.10.11 上的 6380 端口实例
./redis-rm.yml -l 10.10.10.11 -e redis_port=6380

实例级别移除适用于:

  • 移除节点上的 单个从库
  • 移除不再需要的实例
  • 主从切换后移除原主库

当指定 redis_port 时的行为差异:

组件 节点级别(无 redis_port) 实例级别(有 redis_port)
监控注册 删除整个节点的注册文件 仅从注册文件中移除该实例
redis_exporter 停止并禁用 不操作(其他实例还需要)
Redis 实例 停止所有实例 仅停止指定端口的实例
数据目录 删除 redis_fs_main(默认 /data/redis/)整个目录 仅删除 redis_fs_main/<cluster>-<node>-<port>/redis_fs_main=/data 时按 /data/redis 兼容处理)
Vector 配置 删除 /etc/vector/redis.yaml 不操作(其他实例还需要)
软件包 可选卸载 不操作

控制参数

redis-rm.yml 提供以下控制参数:

参数 默认值 说明
redis_safeguard false 安全保险,设为 true 时拒绝执行移除操作
redis_rm_data true 是否删除数据目录(RDB/AOF 文件)
redis_rm_pkg false 是否卸载所选引擎与 redis-exporter

使用示例:

# 移除集群但保留数据目录
./redis-rm.yml -l redis-ms -e redis_rm_data=false

# 移除集群并卸载软件包
./redis-rm.yml -l redis-ms -e redis_rm_pkg=true

# 仅在清单已启用保险且已核对备份与目标后覆盖
./redis-rm.yml -l redis-ms -e redis_safeguard=false
危险操作

redis_safeguard 默认是 falseredis_rm_data 默认是 true。移除剧本还会容忍多项停服、注销、删数据和卸包错误;真实运行后必须检查目标进程、数据目录与监控注册,不能只凭剧本返回状态判定完成。

安全保险机制

当集群配置了 redis_safeguard: true 时,redis-rm.yml 会拒绝执行:

redis-production:
  vars:
    redis_safeguard: true    # 生产环境开启保护
$ ./redis-rm.yml -l redis-production
TASK [ABORT due to redis_safeguard enabled] ***
fatal: [10.10.10.10]: FAILED! => {"msg": "Abort due to redis_safeguard..."}

需要显式覆盖才能执行:

./redis-rm.yml -l redis-production -e redis_safeguard=false

快速参考

部署操作速查

# 部署整个集群
./redis.yml -l <cluster>

# 扩容:部署新节点(cluster 模式下随后手工 add-node)
./redis.yml -l <new-node-ip>

# 扩容:在现有节点上添加新实例(先在配置中添加定义)
./redis.yml -l <ip> -e redis_port=<new-port>

# 更新配置并重启
./redis.yml -l <cluster> -t redis_config,redis_launch

# 仅更新单个实例配置
./redis.yml -l <ip> -e redis_port=<port> -t redis_config,redis_launch

移除操作速查

# 移除整个集群
./redis-rm.yml -l <cluster>

# 缩容:移除整个节点
./redis-rm.yml -l <ip>

# 缩容:移除单个实例
./redis-rm.yml -l <ip> -e redis_port=<port>

# 移除但保留数据
./redis-rm.yml -l <cluster> -e redis_rm_data=false

# 彻底清理(包括软件包)
./redis-rm.yml -l <cluster> -e redis_rm_pkg=true

包装脚本

Pigsty 提供了便捷的包装脚本:

# 部署
bin/redis-add <cluster>           # 部署集群
bin/redis-add <ip>                # 部署节点
bin/redis-add <ip> <port>         # 部署实例

# 移除
bin/redis-rm <cluster>            # 移除集群
bin/redis-rm <ip>                 # 移除节点
bin/redis-rm <ip> <port>          # 移除实例

示例演示

使用 Redis 剧本初始化 Redis 集群:

asciicast

13.4 - 管理预案

Redis 集群管理 SOP,创建、销毁、扩容、缩容与高可用的详细说明

以下是一些常见的 Redis 管理任务 SOP(预案):

REDIS 模块默认使用 redis_type: redis;选择 redis_type: valkey 时,服务端与客户端命令分别改为 valkey-server / valkey-cli。 本文命令行示例使用默认的 redis-cli,Valkey 集群请替换为 valkey-cli;剧本内部会自动选择正确的 CLI。

基础运维

高可用管理

扩缩容与迁移

故障排查

更多问题请参考 FAQ:REDIS


初始化Redis

您可以使用 redis.yml 剧本来初始化 Redis 集群、节点、或实例:

# 初始化集群内所有 Redis 实例
./redis.yml -l <cluster>      # 初始化 redis 集群

# 初始化特定节点上的所有 Redis 实例
./redis.yml -l 10.10.10.10    # 初始化 redis 节点

# 初始化特定 Redis 实例:  10.10.10.11:6379
./redis.yml -l 10.10.10.11 -e redis_port=6379 -t redis

你也可以使用包装脚本命令行脚本来初始化:

bin/redis-add redis-ms          # 初始化 redis 集群 'redis-ms'
bin/redis-add 10.10.10.10       # 初始化 redis 节点 '10.10.10.10'
bin/redis-add 10.10.10.10 6379  # 初始化 redis 实例 '10.10.10.10:6379'

下线Redis

您可以使用 redis-rm.yml 剧本来下线 Redis 集群、节点、或实例:

redis_rm_data 默认为 true。先核对 RDB/AOF 备份、当前主从/哨兵/集群拓扑并让操作者确认精确目标;下面命令会直接执行相应的下线操作。

# 下线 Redis 集群 `redis-test`
./redis-rm.yml -l redis-test

# 下线 Redis 集群 `redis-test` 并卸载所选引擎与 exporter
./redis-rm.yml -l redis-test -e redis_rm_pkg=true

# 下线 Redis 节点 10.10.10.13 上的所有实例
./redis-rm.yml -l 10.10.10.13

# 下线特定 Redis 实例 10.10.10.13:6379
./redis-rm.yml -l 10.10.10.13 -e redis_port=6379

你也可以使用包装脚本来下线 Redis 集群/节点/实例:

bin/redis-rm redis-ms          # 下线 redis 集群 'redis-ms'
bin/redis-rm 10.10.10.10       # 下线 redis 节点 '10.10.10.10'
bin/redis-rm 10.10.10.10 6379  # 下线 redis 实例 '10.10.10.10:6379'

重新配置Redis

您可以部分执行 redis.yml 剧本来重新配置 Redis 集群、节点、或实例:

./redis.yml -l <cluster> -t redis_config,redis_launch

请注意,redis 无法在线重载配置,您只能使用 launch 任务进行重启来让配置生效。


使用Redis客户端

默认 Redis 引擎使用 redis-cli 访问实例;Valkey 使用 valkey-cli,参数与下列示例相同:

$ redis-cli -h 10.10.10.10 -p 6379 # <--- 使用 Host 与 Port 访问对应 Redis 实例
10.10.10.10:6379> auth redis.ms    # <--- 使用密码验证
OK
10.10.10.10:6379> set a 10         # <--- 设置一个Key
OK
10.10.10.10:6379> get a            # <--- 获取 Key 的值
"10"

Redis 提供了 redis-benchmark 工具,可以用于 Redis 的性能评估,或生成一些负载用于测试。

redis-benchmark -h 10.10.10.13 -p 6379

手工设置Redis从库

https://redis.io/commands/replicaof/

# 将一个 Redis 实例提升为主库
> REPLICAOF NO ONE
"OK"

# 将一个 Redis 实例设置为另一个实例的从库
> REPLICAOF 127.0.0.1 6379
"OK"

设置Redis主从高可用

Redis 独立主从集群可以通过 Redis 哨兵集群配置自动高可用,详细用户请参考 Sentinel官方文档

以四节点 沙箱 为例,一套 Redis Sentinel 集群 redis-meta,可以用来管理很多套独立 Redis 主从集群。

以一主一从的 Redis 普通主从集群 redis-ms 为例,您需要在每个 Sentinel 实例上,使用 SENTINEL MONITOR 添加目标,并使用 SENTINEL SET 提供密码,高可用就配置完毕了。

# 对于每一个 sentinel,将 redis 主服务器纳入哨兵管理:(26379,26380,26381)
$ redis-cli -h 10.10.10.11 -p 26379 -a redis.meta
10.10.10.11:26379> SENTINEL MONITOR redis-ms 10.10.10.10 6379 1
10.10.10.11:26379> SENTINEL SET redis-ms auth-pass redis.ms      # 如果启用了授权,需要配置密码

如果您想移除某个由 Sentinel 管理的 Redis 主从集群,使用 SENTINEL REMOVE <name> 移除即可。

您可以使用定义在 Sentinel 集群上的 redis_sentinel_monitor 参数,来自动配置管理哨兵监控管理的主库列表。

redis_sentinel_monitor:  # 需要被监控的主库列表,端口、密码、法定人数(应为1/2以上的哨兵数量)为可选参数
  - { name: redis-src, host: 10.10.10.45, port: 6379 ,password: redis.src, quorum: 1 }
  - { name: redis-dst, host: 10.10.10.48, port: 6379 ,password: redis.dst, quorum: 1 }

redis.yml 中的 redis-ha 阶段会根据该列表在每个哨兵实例上渲染 /tmp/<cluster>.monitor 并依次执行 SENTINEL REMOVESENTINEL MONITOR 命令, 从而保证哨兵纳管状态与清单保持一致。如果只想移除某个目标而不再重新添加,可以在监控对象上设置 remove: true,剧本会在 SENTINEL REMOVE 后跳过重新注册。

使用以下命令刷新 Redis 哨兵集群上的纳管主库列表:

./redis.yml -l redis-meta -t redis-ha   # 如果您的 Sentinel 集群名称不是 redis-meta,请在这里替换。

初始化 Redis 原生集群

redis_mode 设置为 cluster 时,redis.yml 会额外执行 redis-join 阶段: 剧本会使用 redis_type 对应的 CLI 执行 --cluster create --cluster-yes ... --cluster-replicas {{ redis_cluster_replicas }},把所有清单实例拼成原生集群。 该步骤在首次部署时自动运行;后续执行 ./redis.yml -l <cluster> -t redis-join 会先检查种子实例的 cluster_state:ok,健康集群会直接退出。该保护不负责 add-node、reshard 或修复部分初始化的拓扑,只有确认当前拓扑状态后才应单独触发。


扩容Redis节点

扩容独立主从集群

向现有的 Redis 主从集群添加新节点/实例时,首先在配置清单中添加新的定义:

redis-ms:
  hosts:
    10.10.10.10: { redis_node: 1 , redis_instances: { 6379: { }, 6380: { replica_of: '10.10.10.10 6379' } } }
    10.10.10.11: { redis_node: 2 , redis_instances: { 6379: { replica_of: '10.10.10.10 6379' } } }  # 新增节点
  vars: { redis_cluster: redis-ms ,redis_password: 'redis.ms' ,redis_max_memory: 64MB }

然后仅针对新节点执行部署:

./redis.yml -l 10.10.10.11   # 仅部署新增的节点

扩容原生集群

向 Redis 原生集群添加新节点需要额外的步骤:

# 1. 在配置清单中添加新节点
# 2. 部署新节点
./redis.yml -l 10.10.10.14

# 3. 将新节点添加到集群中(手动执行)
redis-cli --cluster add-node 10.10.10.14:6379 10.10.10.12:6379

# 4. 重新分配槽位(如需要)
redis-cli --cluster reshard 10.10.10.12:6379

扩容哨兵集群

向 Sentinel 集群添加新实例后,需要同时完成实例部署与纳管目标刷新:

# 1. 在配置清单中添加新的哨兵实例,部署实例
./redis.yml -l <sentinel-cluster> -t redis_instance

# 2. 重新下发 redis_sentinel_monitor 到所有哨兵
./redis.yml -l <sentinel-cluster> -t redis-ha

缩容Redis节点

缩容独立主从集群

# 1. 如果要移除的是从库,直接移除即可
./redis-rm.yml -l 10.10.10.11 -e redis_port=6379

# 2. 如果要移除的是主库,先进行主从切换
redis-cli -h 10.10.10.10 -p 6380 REPLICAOF NO ONE      # 提升从库
redis-cli -h 10.10.10.10 -p 6379 REPLICAOF 10.10.10.10 6380  # 降级原主库

# 3. 然后移除原主库
./redis-rm.yml -l 10.10.10.10 -e redis_port=6379

# 4. 更新配置清单,移除相关定义

缩容原生集群

# 1. 先迁移数据槽位
redis-cli --cluster reshard 10.10.10.12:6379 \
  --cluster-from <node-id> --cluster-to <target-node-id> --cluster-slots <count>

# 2. 从集群中移除节点
redis-cli --cluster del-node 10.10.10.12:6379 <node-id>

# 3. 下线实例
./redis-rm.yml -l 10.10.10.14

# 4. 更新配置清单

数据备份与恢复

手动备份

# 触发 RDB 快照
redis-cli -h 10.10.10.10 -p 6379 -a <password> BGSAVE

# 查看快照状态
redis-cli -h 10.10.10.10 -p 6379 -a <password> LASTSAVE

# 复制 RDB 文件(默认位置)
cp /data/redis/redis-ms-1-6379/dump.rdb /backup/redis-ms-$(date +%Y%m%d).rdb

数据恢复

# 1. 停止 Redis 实例
sudo systemctl stop redis-ms-1-6379

# 2. 替换 RDB 文件
cp /backup/redis-ms-20241231.rdb /data/redis/redis-ms-1-6379/dump.rdb
chown redis:redis /data/redis/redis-ms-1-6379/dump.rdb

# 3. 启动 Redis 实例
sudo systemctl start redis-ms-1-6379

使用 AOF 持久化

如果需要更高的数据安全性,可以启用 AOF:

redis-ms:
  vars:
    redis_aof_enabled: true
    redis_rdb_save: ['900 1', '300 10', '60 10000']  # 同时保留 RDB

重新部署以应用 AOF 配置:

./redis.yml -l redis-ms -t redis_config,redis_launch

常见问题诊断

连接问题排查

# 检查 Redis 服务状态
systemctl status redis-ms-1-6379

# 检查端口监听
ss -tlnp | grep 6379

# 检查防火墙
sudo iptables -L -n | grep 6379

# 测试连接
redis-cli -h 10.10.10.10 -p 6379 PING

内存问题排查

# 查看内存使用情况
redis-cli -h 10.10.10.10 -p 6379 INFO memory

# 查看大 Key
redis-cli -h 10.10.10.10 -p 6379 --bigkeys

# 查看内存分析报告
redis-cli -h 10.10.10.10 -p 6379 MEMORY DOCTOR

性能问题排查

# 查看慢查询日志
redis-cli -h 10.10.10.10 -p 6379 SLOWLOG GET 10

# 实时监控命令
redis-cli -h 10.10.10.10 -p 6379 MONITOR

# 查看客户端连接
redis-cli -h 10.10.10.10 -p 6379 CLIENT LIST

复制问题排查

# 查看复制状态
redis-cli -h 10.10.10.10 -p 6379 INFO replication

# 检查复制延迟
redis-cli -h 10.10.10.10 -p 6380 INFO replication | grep lag

性能调优

内存优化

redis-cache:
  vars:
    redis_max_memory: 4GB           # 根据可用内存设置
    redis_mem_policy: allkeys-lru   # 缓存场景推荐 LRU
    redis_conf: redis.conf

持久化优化

# 纯缓存场景:禁用持久化
redis-cache:
  vars:
    redis_rdb_save: []              # 禁用 RDB
    redis_aof_enabled: false        # 禁用 AOF

# 数据安全场景:同时启用 RDB 和 AOF
redis-data:
  vars:
    redis_rdb_save: ['900 1', '300 10', '60 10000']
    redis_aof_enabled: true

连接池配置建议

客户端应用连接 Redis 时,建议:

  • 使用连接池,避免频繁创建连接
  • 设置合理的超时时间(推荐 1-3 秒)
  • 启用 TCP keepalive
  • 对于高并发场景,考虑使用 Pipeline 批量操作

监控关键指标

通过 Grafana 仪表盘关注以下指标:

  • 内存使用率redis:ins:mem_usage > 80% 时需要关注
  • CPU 使用率redis:ins:cpu_usage > 70% 时需要关注
  • QPS:关注突增和异常波动
  • 响应时间redis:ins:rt > 1ms 时需要排查
  • 连接数:关注连接数增长趋势
  • 复制延迟:主从复制场景下需要关注

13.5 - 监控告警

如何监控 redis?有哪些告警规则值得关注?

监控面板

REDIS 模块提供了 3 个监控面板

  • Redis Overview:redis 集群概览
  • Redis Cluster:redis 集群详情
  • Redis Instance:redis 实例详情

监控

Pigsty 提供了三个与 REDIS 模块有关的监控仪表盘:


Redis Overview

Redis Overview:关于所有 Redis 集群/实例的详细信息

redis-overview.jpg


Redis Cluster

Redis Cluster:关于单个 Redis 集群的详细信息

Redis Cluster Dashboard

redis-cluster.jpg


Redis Instance

Redis Instance: 关于单个 Redis 实例的详细信息

Redis Instance Dashboard

redis-instance


告警规则

Pigsty 针对 redis 提供了以下六条预置告警规则,定义于 files/victoria/rules/redis.yml

  • RedisDown:redis 实例不可用
  • RedisRejectConn:redis 实例拒绝连接
  • RedisRTHigh:redis 实例响应时间过高
  • RedisCPUHigh:redis 实例 CPU 使用率过高
  • RedisMemHigh:redis 实例内存使用率过高
  • RedisQPSHigh:redis 实例 QPS 过高

实际触发条件以规则的 expr 为准:响应时间 >160µs 持续 1 分钟,CPU 与内存使用率均为 >70% 持续 1 分钟,QPS 为 >32000 持续 5 分钟。以下片段原样反映当前规则源码;其中 CPU、内存和 QPS 的 description 仍残留 60%80%16000 等旧阈值,RedisRTHigh 注释中的指标名也误写为 pg:ins:query_rt,这些注释不会改变实际表达式。

#==============================================================#
#                         Error                                #
#==============================================================#
# redis down triggers a P0 alert
- alert: RedisDown
  expr: redis_up < 1
  for: 1m
  labels: { level: 0, severity: CRIT, category: redis }
  annotations:
    summary: "CRIT RedisDown: {{ $labels.ins }} {{ $labels.instance }} {{ $value }}"
    description: |
      redis_up[ins={{ $labels.ins }}, instance={{ $labels.instance }}] = {{ $value }} == 0
      /ui/d/redis-instance?from=now-5m&to=now&var-ins={{$labels.ins}}

# redis reject connection in last 5m
- alert: RedisRejectConn
  expr: redis:ins:conn_reject > 0
  labels: { level: 0, severity: CRIT, category: redis }
  annotations:
    summary: "CRIT RedisRejectConn: {{ $labels.ins }} {{ $labels.instance }} {{ $value }}"
    description: |
      redis:ins:conn_reject[cls={{ $labels.cls }}, ins={{ $labels.ins }}][5m] = {{ $value }} > 0
      /ui/d/redis-instance?from=now-10m&to=now&viewPanel=88&fullscreen&var-ins={{ $labels.ins }}



#==============================================================#
#                         Latency                              #
#==============================================================#
# redis avg query response time > 160 µs
- alert: RedisRTHigh
  expr: redis:ins:rt > 0.00016
  for: 1m
  labels: { level: 1, severity: WARN, category: redis }
  annotations:
    summary: "WARN RedisRTHigh: {{ $labels.cls }} {{ $labels.ins }}"
    description: |
      pg:ins:query_rt[cls={{ $labels.cls }}, ins={{ $labels.ins }}] = {{ $value }} > 160µs
      /ui/d/redis-instance?from=now-10m&to=now&viewPanel=97&fullscreen&var-ins={{ $labels.ins }}



#==============================================================#
#                        Saturation                            #
#==============================================================#
# redis cpu usage more than 70% for 1m
- alert: RedisCPUHigh
  expr: redis:ins:cpu_usage > 0.70
  for: 1m
  labels: { level: 1, severity: WARN, category: redis }
  annotations:
    summary: "WARN RedisCPUHigh: {{ $labels.cls }} {{ $labels.ins }}"
    description: |
      redis:ins:cpu_all[cls={{ $labels.cls }}, ins={{ $labels.ins }}] = {{ $value }} > 60%
      /ui/d/redis-instance?from=now-10m&to=now&viewPanel=43&fullscreen&var-ins={{ $labels.ins }}

# redis mem usage more than 70% for 1m
- alert: RedisMemHigh
  expr: redis:ins:mem_usage > 0.70
  for: 1m
  labels: { level: 1, severity: WARN, category: redis }
  annotations:
    summary: "WARN RedisMemHigh: {{ $labels.cls }} {{ $labels.ins }}"
    description: |
      redis:ins:mem_usage[cls={{ $labels.cls }}, ins={{ $labels.ins }}] = {{ $value }} > 80%
      /ui/d/redis-instance?from=now-10m&to=now&viewPanel=7&fullscreen&var-ins={{ $labels.ins }}

#==============================================================#
#                         Traffic                              #
#==============================================================#
# redis qps more than 32000 for 5m
- alert: RedisQPSHigh
  expr: redis:ins:qps > 32000
  for: 5m
  labels: { level: 2, severity: INFO, category: redis }
  annotations:
    summary: "INFO RedisQPSHigh: {{ $labels.cls }} {{ $labels.ins }}"
    description: |
      redis:ins:qps[cls={{ $labels.cls }}, ins={{ $labels.ins }}] = {{ $value }} > 16000
      /ui/d/redis-instance?from=now-10m&to=now&viewPanel=96&fullscreen&var-ins={{ $labels.ins }}

13.6 - 指标列表

Pigsty REDIS 模块提供的完整监控指标列表与释义

本页快照记录 REDIS 模块的 275 类监控指标;实际运行时的指标集合会随软件包版本、启用的采集器和目标状态变化。

Metric Name Type Labels Description
ALERTS Unknown cls, ip, level, severity, instance, category, ins, alertname, job, alertstate N/A
ALERTS_FOR_STATE Unknown cls, ip, level, severity, instance, category, ins, alertname, job N/A
redis:cls:aof_rewrite_time Unknown cls, job N/A
redis:cls:blocked_clients Unknown cls, job N/A
redis:cls:clients Unknown cls, job N/A
redis:cls:cmd_qps Unknown cls, cmd, job N/A
redis:cls:cmd_rt Unknown cls, cmd, job N/A
redis:cls:cmd_time Unknown cls, cmd, job N/A
redis:cls:conn_rate Unknown cls, job N/A
redis:cls:conn_reject Unknown cls, job N/A
redis:cls:cpu_sys Unknown cls, job N/A
redis:cls:cpu_sys_child Unknown cls, job N/A
redis:cls:cpu_usage Unknown cls, job N/A
redis:cls:cpu_usage_child Unknown cls, job N/A
redis:cls:cpu_user Unknown cls, job N/A
redis:cls:cpu_user_child Unknown cls, job N/A
redis:cls:fork_time Unknown cls, job N/A
redis:cls:key_evict Unknown cls, job N/A
redis:cls:key_expire Unknown cls, job N/A
redis:cls:key_hit Unknown cls, job N/A
redis:cls:key_hit_rate Unknown cls, job N/A
redis:cls:key_miss Unknown cls, job N/A
redis:cls:mem_max Unknown cls, job N/A
redis:cls:mem_usage Unknown cls, job N/A
redis:cls:mem_usage_max Unknown cls, job N/A
redis:cls:mem_used Unknown cls, job N/A
redis:cls:net_traffic Unknown cls, job N/A
redis:cls:qps Unknown cls, job N/A
redis:cls:qps_mu Unknown cls, job N/A
redis:cls:qps_realtime Unknown cls, job N/A
redis:cls:qps_sigma Unknown cls, job N/A
redis:cls:rt Unknown cls, job N/A
redis:cls:rt_mu Unknown cls, job N/A
redis:cls:rt_sigma Unknown cls, job N/A
redis:cls:rx Unknown cls, job N/A
redis:cls:size Unknown cls, job N/A
redis:cls:tx Unknown cls, job N/A
redis:env:blocked_clients Unknown job N/A
redis:env:clients Unknown job N/A
redis:env:cmd_qps Unknown cmd, job N/A
redis:env:cmd_rt Unknown cmd, job N/A
redis:env:cmd_time Unknown cmd, job N/A
redis:env:conn_rate Unknown job N/A
redis:env:conn_reject Unknown job N/A
redis:env:cpu_usage Unknown job N/A
redis:env:cpu_usage_child Unknown job N/A
redis:env:key_evict Unknown job N/A
redis:env:key_expire Unknown job N/A
redis:env:key_hit Unknown job N/A
redis:env:key_hit_rate Unknown job N/A
redis:env:key_miss Unknown job N/A
redis:env:mem_usage Unknown job N/A
redis:env:net_traffic Unknown job N/A
redis:env:qps Unknown job N/A
redis:env:qps_mu Unknown job N/A
redis:env:qps_realtime Unknown job N/A
redis:env:qps_sigma Unknown job N/A
redis:env:rt Unknown job N/A
redis:env:rt_mu Unknown job N/A
redis:env:rt_sigma Unknown job N/A
redis:env:rx Unknown job N/A
redis:env:tx Unknown job N/A
redis:ins Unknown cls, id, instance, ins, job N/A
redis:ins:blocked_clients Unknown cls, ip, instance, ins, job N/A
redis:ins:clients Unknown cls, ip, instance, ins, job N/A
redis:ins:cmd_qps Unknown cls, cmd, ip, instance, ins, job N/A
redis:ins:cmd_rt Unknown cls, cmd, ip, instance, ins, job N/A
redis:ins:cmd_time Unknown cls, cmd, ip, instance, ins, job N/A
redis:ins:conn_rate Unknown cls, ip, instance, ins, job N/A
redis:ins:conn_reject Unknown cls, ip, instance, ins, job N/A
redis:ins:cpu_sys Unknown cls, ip, instance, ins, job N/A
redis:ins:cpu_sys_child Unknown cls, ip, instance, ins, job N/A
redis:ins:cpu_usage Unknown cls, ip, instance, ins, job N/A
redis:ins:cpu_usage_child Unknown cls, ip, instance, ins, job N/A
redis:ins:cpu_user Unknown cls, ip, instance, ins, job N/A
redis:ins:cpu_user_child Unknown cls, ip, instance, ins, job N/A
redis:ins:key_evict Unknown cls, ip, instance, ins, job N/A
redis:ins:key_expire Unknown cls, ip, instance, ins, job N/A
redis:ins:key_hit Unknown cls, ip, instance, ins, job N/A
redis:ins:key_hit_rate Unknown cls, ip, instance, ins, job N/A
redis:ins:key_miss Unknown cls, ip, instance, ins, job N/A
redis:ins:lsn_rate Unknown cls, ip, instance, ins, job N/A
redis:ins:mem_usage Unknown cls, ip, instance, ins, job N/A
redis:ins:net_traffic Unknown cls, ip, instance, ins, job N/A
redis:ins:qps Unknown cls, ip, instance, ins, job N/A
redis:ins:qps_mu Unknown cls, ip, instance, ins, job N/A
redis:ins:qps_realtime Unknown cls, ip, instance, ins, job N/A
redis:ins:qps_sigma Unknown cls, ip, instance, ins, job N/A
redis:ins:rt Unknown cls, ip, instance, ins, job N/A
redis:ins:rt_mu Unknown cls, ip, instance, ins, job N/A
redis:ins:rt_sigma Unknown cls, ip, instance, ins, job N/A
redis:ins:rx Unknown cls, ip, instance, ins, job N/A
redis:ins:tx Unknown cls, ip, instance, ins, job N/A
redis:node:ip Unknown cls, ip, instance, ins, job N/A
redis:node:mem_alloc Unknown cls, ip, job N/A
redis:node:mem_total Unknown cls, ip, job N/A
redis:node:mem_used Unknown cls, ip, job N/A
redis:node:qps Unknown cls, ip, job N/A
redis_active_defrag_running gauge cls, ip, instance, ins, job active_defrag_running metric
redis_allocator_active_bytes gauge cls, ip, instance, ins, job allocator_active_bytes metric
redis_allocator_allocated_bytes gauge cls, ip, instance, ins, job allocator_allocated_bytes metric
redis_allocator_frag_bytes gauge cls, ip, instance, ins, job allocator_frag_bytes metric
redis_allocator_frag_ratio gauge cls, ip, instance, ins, job allocator_frag_ratio metric
redis_allocator_resident_bytes gauge cls, ip, instance, ins, job allocator_resident_bytes metric
redis_allocator_rss_bytes gauge cls, ip, instance, ins, job allocator_rss_bytes metric
redis_allocator_rss_ratio gauge cls, ip, instance, ins, job allocator_rss_ratio metric
redis_aof_current_rewrite_duration_sec gauge cls, ip, instance, ins, job aof_current_rewrite_duration_sec metric
redis_aof_enabled gauge cls, ip, instance, ins, job aof_enabled metric
redis_aof_last_bgrewrite_status gauge cls, ip, instance, ins, job aof_last_bgrewrite_status metric
redis_aof_last_cow_size_bytes gauge cls, ip, instance, ins, job aof_last_cow_size_bytes metric
redis_aof_last_rewrite_duration_sec gauge cls, ip, instance, ins, job aof_last_rewrite_duration_sec metric
redis_aof_last_write_status gauge cls, ip, instance, ins, job aof_last_write_status metric
redis_aof_rewrite_in_progress gauge cls, ip, instance, ins, job aof_rewrite_in_progress metric
redis_aof_rewrite_scheduled gauge cls, ip, instance, ins, job aof_rewrite_scheduled metric
redis_blocked_clients gauge cls, ip, instance, ins, job blocked_clients metric
redis_client_recent_max_input_buffer_bytes gauge cls, ip, instance, ins, job client_recent_max_input_buffer_bytes metric
redis_client_recent_max_output_buffer_bytes gauge cls, ip, instance, ins, job client_recent_max_output_buffer_bytes metric
redis_clients_in_timeout_table gauge cls, ip, instance, ins, job clients_in_timeout_table metric
redis_cluster_connections gauge cls, ip, instance, ins, job cluster_connections metric
redis_cluster_current_epoch gauge cls, ip, instance, ins, job cluster_current_epoch metric
redis_cluster_enabled gauge cls, ip, instance, ins, job cluster_enabled metric
redis_cluster_known_nodes gauge cls, ip, instance, ins, job cluster_known_nodes metric
redis_cluster_messages_received_total gauge cls, ip, instance, ins, job cluster_messages_received_total metric
redis_cluster_messages_sent_total gauge cls, ip, instance, ins, job cluster_messages_sent_total metric
redis_cluster_my_epoch gauge cls, ip, instance, ins, job cluster_my_epoch metric
redis_cluster_size gauge cls, ip, instance, ins, job cluster_size metric
redis_cluster_slots_assigned gauge cls, ip, instance, ins, job cluster_slots_assigned metric
redis_cluster_slots_fail gauge cls, ip, instance, ins, job cluster_slots_fail metric
redis_cluster_slots_ok gauge cls, ip, instance, ins, job cluster_slots_ok metric
redis_cluster_slots_pfail gauge cls, ip, instance, ins, job cluster_slots_pfail metric
redis_cluster_state gauge cls, ip, instance, ins, job cluster_state metric
redis_cluster_stats_messages_meet_received gauge cls, ip, instance, ins, job cluster_stats_messages_meet_received metric
redis_cluster_stats_messages_meet_sent gauge cls, ip, instance, ins, job cluster_stats_messages_meet_sent metric
redis_cluster_stats_messages_ping_received gauge cls, ip, instance, ins, job cluster_stats_messages_ping_received metric
redis_cluster_stats_messages_ping_sent gauge cls, ip, instance, ins, job cluster_stats_messages_ping_sent metric
redis_cluster_stats_messages_pong_received gauge cls, ip, instance, ins, job cluster_stats_messages_pong_received metric
redis_cluster_stats_messages_pong_sent gauge cls, ip, instance, ins, job cluster_stats_messages_pong_sent metric
redis_commands_duration_seconds_total counter cls, cmd, ip, instance, ins, job Total amount of time in seconds spent per command
redis_commands_failed_calls_total counter cls, cmd, ip, instance, ins, job Total number of errors prior command execution per command
redis_commands_latencies_usec_bucket Unknown cls, cmd, ip, le, instance, ins, job N/A
redis_commands_latencies_usec_count Unknown cls, cmd, ip, instance, ins, job N/A
redis_commands_latencies_usec_sum Unknown cls, cmd, ip, instance, ins, job N/A
redis_commands_processed_total counter cls, ip, instance, ins, job commands_processed_total metric
redis_commands_rejected_calls_total counter cls, cmd, ip, instance, ins, job Total number of errors within command execution per command
redis_commands_total counter cls, cmd, ip, instance, ins, job Total number of calls per command
redis_config_io_threads gauge cls, ip, instance, ins, job config_io_threads metric
redis_config_maxclients gauge cls, ip, instance, ins, job config_maxclients metric
redis_config_maxmemory gauge cls, ip, instance, ins, job config_maxmemory metric
redis_connected_clients gauge cls, ip, instance, ins, job connected_clients metric
redis_connected_slave_lag_seconds gauge cls, ip, slave_ip, instance, slave_state, ins, slave_port, job Lag of connected slave
redis_connected_slave_offset_bytes gauge cls, ip, slave_ip, instance, slave_state, ins, slave_port, job Offset of connected slave
redis_connected_slaves gauge cls, ip, instance, ins, job connected_slaves metric
redis_connections_received_total counter cls, ip, instance, ins, job connections_received_total metric
redis_cpu_sys_children_seconds_total counter cls, ip, instance, ins, job cpu_sys_children_seconds_total metric
redis_cpu_sys_main_thread_seconds_total counter cls, ip, instance, ins, job cpu_sys_main_thread_seconds_total metric
redis_cpu_sys_seconds_total counter cls, ip, instance, ins, job cpu_sys_seconds_total metric
redis_cpu_user_children_seconds_total counter cls, ip, instance, ins, job cpu_user_children_seconds_total metric
redis_cpu_user_main_thread_seconds_total counter cls, ip, instance, ins, job cpu_user_main_thread_seconds_total metric
redis_cpu_user_seconds_total counter cls, ip, instance, ins, job cpu_user_seconds_total metric
redis_db_keys gauge cls, ip, instance, ins, db, job Total number of keys by DB
redis_db_keys_expiring gauge cls, ip, instance, ins, db, job Total number of expiring keys by DB
redis_defrag_hits gauge cls, ip, instance, ins, job defrag_hits metric
redis_defrag_key_hits gauge cls, ip, instance, ins, job defrag_key_hits metric
redis_defrag_key_misses gauge cls, ip, instance, ins, job defrag_key_misses metric
redis_defrag_misses gauge cls, ip, instance, ins, job defrag_misses metric
redis_dump_payload_sanitizations counter cls, ip, instance, ins, job dump_payload_sanitizations metric
redis_errors_total counter cls, ip, err, instance, ins, job Total number of errors per error type
redis_evicted_keys_total counter cls, ip, instance, ins, job evicted_keys_total metric
redis_expired_keys_total counter cls, ip, instance, ins, job expired_keys_total metric
redis_expired_stale_percentage gauge cls, ip, instance, ins, job expired_stale_percentage metric
redis_expired_time_cap_reached_total gauge cls, ip, instance, ins, job expired_time_cap_reached_total metric
redis_exporter_build_info gauge cls, golang_version, ip, commit_sha, instance, version, ins, job, build_date redis exporter build_info
redis_exporter_last_scrape_connect_time_seconds gauge cls, ip, instance, ins, job exporter_last_scrape_connect_time_seconds metric
redis_exporter_last_scrape_duration_seconds gauge cls, ip, instance, ins, job exporter_last_scrape_duration_seconds metric
redis_exporter_last_scrape_error gauge cls, ip, instance, ins, job The last scrape error status.
redis_exporter_scrape_duration_seconds_count Unknown cls, ip, instance, ins, job N/A
redis_exporter_scrape_duration_seconds_sum Unknown cls, ip, instance, ins, job N/A
redis_exporter_scrapes_total counter cls, ip, instance, ins, job Current total redis scrapes.
redis_instance_info gauge cls, ip, os, role, instance, run_id, redis_version, tcp_port, process_id, ins, redis_mode, maxmemory_policy, redis_build_id, job Information about the Redis instance
redis_io_threaded_reads_processed counter cls, ip, instance, ins, job io_threaded_reads_processed metric
redis_io_threaded_writes_processed counter cls, ip, instance, ins, job io_threaded_writes_processed metric
redis_io_threads_active gauge cls, ip, instance, ins, job io_threads_active metric
redis_keyspace_hits_total counter cls, ip, instance, ins, job keyspace_hits_total metric
redis_keyspace_misses_total counter cls, ip, instance, ins, job keyspace_misses_total metric
redis_last_key_groups_scrape_duration_milliseconds gauge cls, ip, instance, ins, job Duration of the last key group metrics scrape in milliseconds
redis_last_slow_execution_duration_seconds gauge cls, ip, instance, ins, job The amount of time needed for last slow execution, in seconds
redis_latency_percentiles_usec summary cls, cmd, ip, instance, quantile, ins, job A summary of latency percentile distribution per command
redis_latency_percentiles_usec_count Unknown cls, cmd, ip, instance, ins, job N/A
redis_latency_percentiles_usec_sum Unknown cls, cmd, ip, instance, ins, job N/A
redis_latest_fork_seconds gauge cls, ip, instance, ins, job latest_fork_seconds metric
redis_lazyfree_pending_objects gauge cls, ip, instance, ins, job lazyfree_pending_objects metric
redis_loading_dump_file gauge cls, ip, instance, ins, job loading_dump_file metric
redis_master_last_io_seconds_ago gauge cls, ip, master_host, instance, ins, job, master_port Master last io seconds ago
redis_master_link_up gauge cls, ip, master_host, instance, ins, job, master_port Master link status on Redis slave
redis_master_repl_offset gauge cls, ip, instance, ins, job master_repl_offset metric
redis_master_sync_in_progress gauge cls, ip, master_host, instance, ins, job, master_port Master sync in progress
redis_mem_clients_normal gauge cls, ip, instance, ins, job mem_clients_normal metric
redis_mem_clients_slaves gauge cls, ip, instance, ins, job mem_clients_slaves metric
redis_mem_fragmentation_bytes gauge cls, ip, instance, ins, job mem_fragmentation_bytes metric
redis_mem_fragmentation_ratio gauge cls, ip, instance, ins, job mem_fragmentation_ratio metric
redis_mem_not_counted_for_eviction_bytes gauge cls, ip, instance, ins, job mem_not_counted_for_eviction_bytes metric
redis_memory_max_bytes gauge cls, ip, instance, ins, job memory_max_bytes metric
redis_memory_used_bytes gauge cls, ip, instance, ins, job memory_used_bytes metric
redis_memory_used_dataset_bytes gauge cls, ip, instance, ins, job memory_used_dataset_bytes metric
redis_memory_used_lua_bytes gauge cls, ip, instance, ins, job memory_used_lua_bytes metric
redis_memory_used_overhead_bytes gauge cls, ip, instance, ins, job memory_used_overhead_bytes metric
redis_memory_used_peak_bytes gauge cls, ip, instance, ins, job memory_used_peak_bytes metric
redis_memory_used_rss_bytes gauge cls, ip, instance, ins, job memory_used_rss_bytes metric
redis_memory_used_scripts_bytes gauge cls, ip, instance, ins, job memory_used_scripts_bytes metric
redis_memory_used_startup_bytes gauge cls, ip, instance, ins, job memory_used_startup_bytes metric
redis_migrate_cached_sockets_total gauge cls, ip, instance, ins, job migrate_cached_sockets_total metric
redis_module_fork_in_progress gauge cls, ip, instance, ins, job module_fork_in_progress metric
redis_module_fork_last_cow_size gauge cls, ip, instance, ins, job module_fork_last_cow_size metric
redis_net_input_bytes_total counter cls, ip, instance, ins, job net_input_bytes_total metric
redis_net_output_bytes_total counter cls, ip, instance, ins, job net_output_bytes_total metric
redis_number_of_cached_scripts gauge cls, ip, instance, ins, job number_of_cached_scripts metric
redis_process_id gauge cls, ip, instance, ins, job process_id metric
redis_pubsub_channels gauge cls, ip, instance, ins, job pubsub_channels metric
redis_pubsub_patterns gauge cls, ip, instance, ins, job pubsub_patterns metric
redis_pubsubshard_channels gauge cls, ip, instance, ins, job pubsubshard_channels metric
redis_rdb_bgsave_in_progress gauge cls, ip, instance, ins, job rdb_bgsave_in_progress metric
redis_rdb_changes_since_last_save gauge cls, ip, instance, ins, job rdb_changes_since_last_save metric
redis_rdb_current_bgsave_duration_sec gauge cls, ip, instance, ins, job rdb_current_bgsave_duration_sec metric
redis_rdb_last_bgsave_duration_sec gauge cls, ip, instance, ins, job rdb_last_bgsave_duration_sec metric
redis_rdb_last_bgsave_status gauge cls, ip, instance, ins, job rdb_last_bgsave_status metric
redis_rdb_last_cow_size_bytes gauge cls, ip, instance, ins, job rdb_last_cow_size_bytes metric
redis_rdb_last_save_timestamp_seconds gauge cls, ip, instance, ins, job rdb_last_save_timestamp_seconds metric
redis_rejected_connections_total counter cls, ip, instance, ins, job rejected_connections_total metric
redis_repl_backlog_first_byte_offset gauge cls, ip, instance, ins, job repl_backlog_first_byte_offset metric
redis_repl_backlog_history_bytes gauge cls, ip, instance, ins, job repl_backlog_history_bytes metric
redis_repl_backlog_is_active gauge cls, ip, instance, ins, job repl_backlog_is_active metric
redis_replica_partial_resync_accepted gauge cls, ip, instance, ins, job replica_partial_resync_accepted metric
redis_replica_partial_resync_denied gauge cls, ip, instance, ins, job replica_partial_resync_denied metric
redis_replica_resyncs_full gauge cls, ip, instance, ins, job replica_resyncs_full metric
redis_replication_backlog_bytes gauge cls, ip, instance, ins, job replication_backlog_bytes metric
redis_second_repl_offset gauge cls, ip, instance, ins, job second_repl_offset metric
redis_sentinel_master_ckquorum_status gauge cls, ip, message, instance, ins, master_name, job Master ckquorum status
redis_sentinel_master_ok_sentinels gauge cls, ip, instance, ins, master_address, master_name, job The number of okay sentinels monitoring this master
redis_sentinel_master_ok_slaves gauge cls, ip, instance, ins, master_address, master_name, job The number of okay slaves of the master
redis_sentinel_master_sentinels gauge cls, ip, instance, ins, master_address, master_name, job The number of sentinels monitoring this master
redis_sentinel_master_setting_ckquorum gauge cls, ip, instance, ins, master_address, master_name, job Show the current ckquorum config for each master
redis_sentinel_master_setting_down_after_milliseconds gauge cls, ip, instance, ins, master_address, master_name, job Show the current down-after-milliseconds config for each master
redis_sentinel_master_setting_failover_timeout gauge cls, ip, instance, ins, master_address, master_name, job Show the current failover-timeout config for each master
redis_sentinel_master_setting_parallel_syncs gauge cls, ip, instance, ins, master_address, master_name, job Show the current parallel-syncs config for each master
redis_sentinel_master_slaves gauge cls, ip, instance, ins, master_address, master_name, job The number of slaves of the master
redis_sentinel_master_status gauge cls, ip, master_status, instance, ins, master_address, master_name, job Master status on Sentinel
redis_sentinel_masters gauge cls, ip, instance, ins, job The number of masters this sentinel is watching
redis_sentinel_running_scripts gauge cls, ip, instance, ins, job Number of scripts in execution right now
redis_sentinel_scripts_queue_length gauge cls, ip, instance, ins, job Queue of user scripts to execute
redis_sentinel_simulate_failure_flags gauge cls, ip, instance, ins, job Failures simulations
redis_sentinel_tilt gauge cls, ip, instance, ins, job Sentinel is in TILT mode
redis_slave_expires_tracked_keys gauge cls, ip, instance, ins, job slave_expires_tracked_keys metric
redis_slave_info gauge cls, ip, master_host, instance, read_only, ins, job, master_port Information about the Redis slave
redis_slave_priority gauge cls, ip, instance, ins, job slave_priority metric
redis_slave_repl_offset gauge cls, ip, master_host, instance, ins, job, master_port Slave replication offset
redis_slowlog_last_id gauge cls, ip, instance, ins, job Last id of slowlog
redis_slowlog_length gauge cls, ip, instance, ins, job Total slowlog
redis_start_time_seconds gauge cls, ip, instance, ins, job Start time of the Redis instance since unix epoch in seconds.
redis_target_scrape_request_errors_total counter cls, ip, instance, ins, job Errors in requests to the exporter
redis_total_error_replies counter cls, ip, instance, ins, job total_error_replies metric
redis_total_reads_processed counter cls, ip, instance, ins, job total_reads_processed metric
redis_total_system_memory_bytes gauge cls, ip, instance, ins, job total_system_memory_bytes metric
redis_total_writes_processed counter cls, ip, instance, ins, job total_writes_processed metric
redis_tracking_clients gauge cls, ip, instance, ins, job tracking_clients metric
redis_tracking_total_items gauge cls, ip, instance, ins, job tracking_total_items metric
redis_tracking_total_keys gauge cls, ip, instance, ins, job tracking_total_keys metric
redis_tracking_total_prefixes gauge cls, ip, instance, ins, job tracking_total_prefixes metric
redis_unexpected_error_replies counter cls, ip, instance, ins, job unexpected_error_replies metric
redis_up gauge cls, ip, instance, ins, job Information about the Redis instance
redis_uptime_in_seconds gauge cls, ip, instance, ins, job uptime_in_seconds metric
scrape_duration_seconds Unknown cls, ip, instance, ins, job N/A
scrape_samples_post_metric_relabeling Unknown cls, ip, instance, ins, job N/A
scrape_samples_scraped Unknown cls, ip, instance, ins, job N/A
scrape_series_added Unknown cls, ip, instance, ins, job N/A
up Unknown cls, ip, instance, ins, job N/A

13.7 - 常见问题

Pigsty REDIS 模块常见问题答疑

Redis移除失败:ABORT due to redis_safeguard enabled

这意味着正准备移除的 Redis 实例打开了防误删保险:当 redis_safeguard 设置为 true 时,redis-rm.yml 会无条件拒绝执行。 该开关不会探测实例是否正在运行。

确认精确的 -l/redis_port 目标、近期备份以及 redis_rm_data 的取值后,通过 -e redis_safeguard=false 覆盖保护并执行移除。该参数只解除保险,不会替您验证目标或数据可恢复性。


如何在某个节点上添加一个新的Redis实例?

使用 bin/redis-add <ip> <port> 在节点上部署一个新的 redis 实例。


如何从节点上移除一个特定实例?

使用 bin/redis-rm <ip> <port> 从节点上移除一个单独的 redis 实例。


如何选择 Redis 或 Valkey?

当前源码默认使用 redis_type: redis,同时已经支持显式设置 redis_type: valkey。 角色会据此安装 redisvalkey 软件包,并在实例单元中调用对应的 redis-server / valkey-server 与 CLI; 配置路径、实例服务名、监控 job 和参数前缀仍保留 redis 命名空间。

默认 Redis 软件包继续采用 7.2 BSD 分支,不同操作系统渠道里的小版本可能不同,请以实际仓库元数据为准。 已有集群改用 Valkey 不等于自动迁移:切换前应核对目标版本的数据文件兼容性、复制与 Sentinel/Cluster 行为,并准备回滚方案。

14 - 模块:DOCKER

Docker Daemon 服务,允许用户一键拉起容器化的无状态软件工具模板,加装各种功能。

Docker 是最流行的容器化平台,提供了标准化的软件交付能力。

Pigsty 本身并不依赖 Docker 部署任何组件,相反,它提供了部署安装 Docker 的能力,这是一个 可选模块

Pigsty 提供一系列 Docker 软件/工具/应用模板,供您按需选用。 这允许用户快速拉起各种容器化的无状态软件工具模板,加装各种功能。 您可以使用外部由 Pigsty 托管的高可用数据库集群,将无状态的应用放入容器之中。

在执行 configure 时,Pigsty 会根据 region(如中国大陆网络环境)自动选择合适的软件源与镜像加速配置,以提升拉取镜像的速度与可用性。 您可以轻松配置 Registry 与 Proxy,以便灵活访问不同的镜像源。

14.1 - 使用方法

Docker 模块快速上手,安装,卸载,下载,仓库,镜像,代理,拉取,关于 Docker 你需要知道的内容。

Pigsty 内置了 Docker 支持,您可以用它来快速部署容器化的应用软件。


上手

Docker 是一个 可选模块。在 Pigsty 中,Docker 是否安装由节点上的 docker_enabled 控制,默认不启用。

docker-ce 上游仓库归属于 infra 模块。若你需要在离线仓库中显式加入 Docker 包,可通过 repo_extra_packages 指定 docker 包别名(映射为 docker-cedocker-compose-plugin)。

repo_modules: infra,node,pgsql     # <--- 保持 infra 模块(Docker 上游在 infra 中)
repo_extra_packages:
  - pgsql-main
  - docker                         # <--- 下载 Docker(docker-ce + docker-compose-plugin)

Docker 下载完之后,您需要在待安装 Docker 的节点上配置 docker_enabled: true 标记,并按需配置 其他参数

infra:
  hosts:
    10.10.10.10: { infra_seq: 1 ,nodename: infra-1 }
    10.10.10.11: { infra_seq: 2 ,nodename: infra-2 }
  vars:
    docker_enabled: true  # 在这个分组上安装 Docker !

最后,您可以使用 docker.yml 剧本将其安装到节点上:

./docker.yml -l infra    # 在 infra 分组上安装 Docker

安装

如果您只是临时性的希望在某些节点上,直接从互联网安装 Docker,那么可以考虑使用以下命令:

./node.yml -e '{"node_repo_modules":"node,infra","node_packages":["docker-ce","docker-compose-plugin"]}' -t node_repo,node_pkg -l <select_group_ip>

这条命令会在目标节点上,首先启用 node,infra 两个模块对应的上游软件源,然后安装 docker-cedocker-compose-plugin 两个软件包(EL/Debian 同名)。

如果您希望的是在 Pigsty 初始化的时候就自动下载好 Docker 相关软件包,请参考下面的说明。


卸载

因为过于简单,Pigsty 不提供 Docker 模块的卸载剧本,你可以直接使用 Ansible 指令移除 Docker

ansible <selector> -m package -b -a 'name=docker-ce,docker-compose-plugin state=absent'  # 卸载 docker

下载

想要在 Pigsty 安装过程中下载 Docker,在 配置清单 中确认 repo_modules 包含 infra(Docker 上游所在模块), 然后在 repo_packagesrepo_extra_packages 参数中指定下载 Docker 软件包。

repo_modules: infra,node,pgsql         # <--- Docker 上游仓库归属 infra 模块
repo_packages: 
  - node-bootstrap, infra-package, infra-addons, node-package1, node-package2, pgsql-common, docker
repo_extra_packages:
  - pgsql-main
  - docker  # <--- 也可以在这里指定

这里指定的 docker(实际对应 docker-cedocker-compose-plugin 两个软件包)会在默认的 deploy.yml 过程中自动下载到本地软件源中。 下载完成后的 Docker 软件包可以通过本地软件源,对所有节点可用。

如果您已经完成了 Pigsty 安装,本地软件源已经初始化完毕,您可以在修改配置之后执行 ./infra.yml -t repo_build 重新下载并构建离线软件源。

安装 Docker 需要用到 Docker 的 YUM/APT 仓库。该仓库在 v4.x 的默认 repo_upstream 中归属于 infra 模块,通常已经可用。


仓库

下载 Docker 需要用到互联网上游软件仓库,已定义在默认的 repo_upstream 中,模块名为 infra

- { name: docker-ce ,description: 'Docker CE' ,module: infra  ,releases: [8,9,10] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.docker.com/linux/centos/$releasever/$basearch/stable'    ,china: 'https://mirrors.aliyun.com/docker-ce/linux/centos/$releasever/$basearch/stable'  ,europe: 'https://mirrors.xtom.de/docker-ce/linux/centos/$releasever/$basearch/stable' }}
- { name: docker-ce ,description: 'Docker'    ,module: infra  ,releases: [11,12,13,22,24,26] ,arch: [x86_64, aarch64] ,baseurl: { default: 'https://download.docker.com/linux/${distro_name} ${distro_codename} stable' ,china: 'https://mirrors.aliyun.com/docker-ce/linux/${distro_name} ${distro_codename} stable' }}

您可以在 repo_modulesnode_repo_modules 两个参数中,使用 infra 模块名引用这个仓库。

请注意,Docker 的官方软件仓库在中国大陆默认处于 封锁 状态,您需要使用中国地区的镜像站点才能正常完成下载。

如果您处在中国大陆地区遇到 Docker 本身下载失败的问题,请检查您的配置清单中,region 是否被设置为了 default,默认情况下自动配置的 region: china 可以解决这个问题。


代理

如果您的网络环境需要使用代理服务器才能访问互联网,您可以在 Pigsty 的配置清单中配置 proxy_env 参数,这个参数会被写入到 Docker 的配置文件中的 proxy 相关配置中。

proxy_env:
  no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.aliyuncs.com,mirrors.tuna.tsinghua.edu.cn,mirrors.zju.edu.cn"
  #http_proxy: 'http://username:[email protected]'
  #https_proxy: 'http://username:[email protected]'
  #all_proxy: 'http://username:[email protected]'

在执行 configure 的过程中如果指定了 -x 参数,当前环境中的代理服务器配置会自动生成到 Pigsty 配置文件到 proxy_env 中。

除了使用代理服务器之外,您还可以通过配置 Docker镜像站点 的方式来规避封锁。


镜像站

您可以通过参数 docker_registry_mirrors 指定 Docker 的 Registry Mirrors 参数,使用未被墙掉的镜像站点:

普通墙外用户,除了官方默认的 DockerHub 站点外,还可以考虑使用 quay.io 镜像站点。如果您的内网环境已经有了成熟的镜像基础设施,您可以使用内网的 Docker 镜像站点,避免受到外网镜像站点的影响,提高下载速度。

使用公有云厂商服务的用户可以考虑使用内网免费的 Docker 镜像。例如,如果您使用阿里云,可以使用阿里云提供的内网 Docker 镜像站点(需要登陆):

["https://registry.cn-hangzhou.aliyuncs.com"]   # 阿里云镜像站点,需要显式登陆

如果你使用腾讯云,可以使用腾讯云提供的内网 Docker 镜像站点(需要内网):

["https://ccr.ccs.tencentyun.com"]   # 腾讯云镜像站点,内网专用

此外,您还可以使用 CF-Workers-docker.io 快速拉起您自己的 Docker 镜像代理。 也可以考虑使用免费的 Docker代理镜像 (风险自负!)


拉取镜像

参数 docker_imagedocker_image_cache 可用于直接指定在 Docker 安装时,需要拉取的镜像列表。

使用这一功能,可以让 Docker 装好之后就带有指定的镜像(前提是可以成功拉取,此任务失败会自动忽略跳过)

例如,您可以在配置清单中指定需要拉取的镜像:

infra:
  hosts:
    10.10.10.10: { infra_seq: 1 }
  vars:
    docker_enabled: true  # 在这个分组上安装 Docker !
    docker_image:
      - redis:latest      # 拉取最新版本的 Redis 镜像

另一种预先加载镜像的方式是使用本地 savetgz 压缩包:如果您预先使用 docker save xxx | gzip -c > /tmp/docker/xxx.tgz 将 Docker 镜像导出保存在本地。 那么这些导出的镜像文件可以通过参数 docker_image_cache 指定的 glob 被自动加载。默认的位置是: /tmp/docker/*.tgz

这意味着你可以事先把镜像放在 /tmp/docker 目录中,然后执行 docker.yml 安装 docker 后会自动加载这些镜像包。

例如,在 supabase自建教程 中就使用了这种技术,在拉起 Supabase,安装 Docker 之前,把本地 /tmp/supabase 目录的 *.tgz 镜像压缩包都拷贝到了目标节点的 /tmp/docker 目录下。

- name: copy local docker images
  copy: src="{{ item }}" dest="/tmp/docker/"
  with_fileglob: "{{ supa_images }}"
  vars: # you can override this with -e cli args
    supa_images: /tmp/supabase/*.tgz

应用

Pigsty 提供了一系列开箱即用的,基于 Docker Compose 的 软件模板,您可以用它们一键拉起使用外部由 Pigsty 管理数据库集群的业务软件。

14.2 - 参数列表

DOCKER 模块提供了 8 个配置参数

DOCKER 模块提供了 8 个配置参数。

参数概览

DOCKER 参数组用于 Docker 容器引擎的部署与配置,包括启用开关、数据目录、存储驱动、镜像加速以及监控。

参数 类型 级别 说明
docker_enabled bool G/C/I 在当前节点上启用 Docker?默认不启用
docker_data path G/C/I Docker 数据目录,默认为 /data/docker
docker_storage_driver enum G/C/I Docker 存储驱动,默认为 overlay2
docker_cgroups_driver enum G/C/I Docker CGroup 文件系统驱动:cgroupfs,systemd
docker_registry_mirrors string[] G/C/I Docker 仓库镜像列表
docker_exporter_port port G Docker 监控指标导出端口,默认为 9323
docker_image string[] G/C/I Docker 待拉取的镜像列表,默认为空列表
docker_image_cache path G/C/I Docker 待导入的镜像压缩包路径,默认为 /tmp/docker/*.tgz

您可以使用 docker.yml 剧本,在节点上安装并启用 Docker。

Docker 的默认参数定义于 roles/docker/defaults/main.yml

docker_enabled: false             # 在当前节点启用 Docker?
docker_data: /data/docker         # Docker 数据目录,默认为 /data/docker
docker_storage_driver: overlay2   # Docker 存储驱动,可选 zfs, btrfs 等
docker_cgroups_driver: systemd    # Docker CGroup 驱动:cgroupfs 或 systemd
docker_registry_mirrors: []       # Docker 镜像仓库加速列表
docker_exporter_port: 9323        # Docker 监控指标导出端口,默认 9323
docker_image: []                  # Docker 启动后待拉取的镜像列表
docker_image_cache: /tmp/docker/*.tgz # Docker 镜像缓存 tarball 匹配模式

docker_enabled

参数名称: docker_enabled, 类型: bool, 层次:G/C/I

是否在当前节点启用 Docker?默认为: false,即不启用。

docker_data

参数名称: docker_data, 类型: path, 层次:G/C/I

Docker 数据目录,默认为 /data/docker

此目录用于存储 Docker 的镜像、容器、卷等数据。如果您有独立的数据磁盘,建议将此目录指向该磁盘的挂载点。

docker_storage_driver

参数名称: docker_storage_driver, 类型: enum, 层次:G/C/I

Docker 存储驱动,默认为 overlay2

请参考官方文档:https://docs.docker.com/engine/storage/drivers/select-storage-driver/

可选的存储驱动包括:

  • overlay2:推荐的默认驱动,适用于大多数场景
  • fuse-overlayfs:用于无 root 权限的容器场景
  • btrfs:使用 Btrfs 文件系统时
  • zfs:使用 ZFS 文件系统时
  • vfs:用于测试目的,不推荐生产使用

docker_cgroups_driver

参数名称: docker_cgroups_driver, 类型: enum, 层次:G/C/I

Docker 使用的 CGroup FS 驱动,可以是 cgroupfssystemd,默认值为: systemd

docker_registry_mirrors

参数名称: docker_registry_mirrors, 类型: string[], 层次:G/C/I

Docker 镜像仓库加速地址列表,默认值为:[] 空数组。

您可以使用 Docker 镜像站点加速镜像拉取,下面是一些中国大陆可用的镜像站点示例:

docker_registry_mirrors:                        # 可任选一个或多个
  - https://docker.m.daocloud.io                # DaoCloud 镜像站点
  - https://docker.1ms.run                      # 毫秒镜像站点
  - https://mirror.ccs.tencentyun.com           # 腾讯云内网镜像站点
  - https://registry.cn-hangzhou.aliyuncs.com   # 阿里云镜像站点,需要登录

您也可以考虑使用 Cloudflare Worker 搭建 Docker Proxy 来加速访问。

如果拉取速度仍然太慢,您也可以考虑使用其他 Registry:docker login quay.io

docker_exporter_port

参数名称: docker_exporter_port, 类型: port, 层次:G

Docker 监控指标导出端口,默认为 9323

Docker 守护进程会在此端口暴露 Prometheus 格式的监控指标,供监控基础设施采集。

docker_image

参数名称: docker_image, 类型: string[], 层次:G/C/I

Docker 待拉取的镜像列表,默认为空列表 []

在这里指定的 Docker 镜像名称会在安装阶段自动拉取。

docker_image_cache

参数名称: docker_image_cache, 类型: path, 层次:G/C/I

本地 Docker 镜像离线缓存包 glob 匹配模式,默认为 /tmp/docker/*.tgz

您可以使用 docker save | gzip 的方式将镜像打包,并通过此参数在 Docker 安装阶段自动导入。

匹配该模式的 .tgz 后缀 tarball 文件将使用以下方式逐个导入 Docker 中:

cat *.tgz | gzip -d -c - | docker load

14.3 - 预置剧本

如何使用预置的 ansible 剧本来管理 Docker,常用管理命令速查。

Docker 模块提供了一个默认的剧本 docker.yml,用于安装 Docker Daemon 与 Docker Compose。


docker.yml

剧本原始文件:docker.yml

执行本剧本,将会在带有 docker_enabled: true 标记的目标节点上安装 docker-cedocker-compose-plugin,启用 dockerd 服务

以下是 docker.yml 剧本中可用的任务子集:

  • docker_install: 在节点上安装 Docker,Docker Compose 软件包
  • docker_admin: 将指定的用户加入 Docker 管理员用户组中
  • docker_dir: 创建 Docker 相关目录
  • docker_config: 生成 Docker 守护进程服务配置文件
  • docker_launch: 启动 Docker 守护进程服务
  • docker_register: 将 Docker 守护进程注册为监控目标(别名标签:register / add_metrics
  • docker_image: 尝试从 /tmp/docker/*.tgz 加载预置镜像压缩包(如果存在)

Docker 模块没有提供专门的卸载剧本,如果您需要卸载 Docker,可以手工停止 docker 后卸载:

systemctl stop docker                        # 停止 Docker 守护进程服务
yum remove docker-ce docker-compose-plugin   # 在 EL 系统上卸载 Docker 
apt remove docker-ce docker-compose-plugin   # 在 Debian 系统上卸载 Docker

docker_enabled 改为 false 只会让 docker.yml 跳过整个 Docker 角色,不会停止或卸载已部署的 Docker,也不会删除 /data/docker。 上面的手工命令同样不会删除数据目录;Docker 的 VictoriaMetrics 文件发现目标可由 node-rm.ymlnode_deregister 任务一并注销。

14.4 - 指标列表

Pigsty Docker 模块提供的完整监控指标列表与释义

本页快照记录 DOCKER 模块的 123 类监控指标;实际运行时的指标集合会随软件包版本、启用的采集器和目标状态变化。

Metric Name Type Labels Description
builder_builds_failed_total counter ip, cls, reason, ins, job, instance Number of failed image builds
builder_builds_triggered_total counter ip, cls, ins, job, instance Number of triggered image builds
docker_up Unknown ip, cls, ins, job, instance N/A
engine_daemon_container_actions_seconds_bucket Unknown ip, cls, ins, job, instance, le, action N/A
engine_daemon_container_actions_seconds_count Unknown ip, cls, ins, job, instance, action N/A
engine_daemon_container_actions_seconds_sum Unknown ip, cls, ins, job, instance, action N/A
engine_daemon_container_states_containers gauge ip, cls, ins, job, instance, state The count of containers in various states
engine_daemon_engine_cpus_cpus gauge ip, cls, ins, job, instance The number of cpus that the host system of the engine has
engine_daemon_engine_info gauge ip, cls, architecture, ins, job, instance, os_version, kernel, version, graphdriver, os, daemon_id, commit, os_type The information related to the engine and the OS it is running on
engine_daemon_engine_memory_bytes gauge ip, cls, ins, job, instance The number of bytes of memory that the host system of the engine has
engine_daemon_events_subscribers_total gauge ip, cls, ins, job, instance The number of current subscribers to events
engine_daemon_events_total counter ip, cls, ins, job, instance The number of events logged
engine_daemon_health_checks_failed_total counter ip, cls, ins, job, instance The total number of failed health checks
engine_daemon_health_check_start_duration_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
engine_daemon_health_check_start_duration_seconds_count Unknown ip, cls, ins, job, instance N/A
engine_daemon_health_check_start_duration_seconds_sum Unknown ip, cls, ins, job, instance N/A
engine_daemon_health_checks_total counter ip, cls, ins, job, instance The total number of health checks
engine_daemon_host_info_functions_seconds_bucket Unknown ip, cls, ins, job, instance, le, function N/A
engine_daemon_host_info_functions_seconds_count Unknown ip, cls, ins, job, instance, function N/A
engine_daemon_host_info_functions_seconds_sum Unknown ip, cls, ins, job, instance, function N/A
engine_daemon_image_actions_seconds_bucket Unknown ip, cls, ins, job, instance, le, action N/A
engine_daemon_image_actions_seconds_count Unknown ip, cls, ins, job, instance, action N/A
engine_daemon_image_actions_seconds_sum Unknown ip, cls, ins, job, instance, action N/A
engine_daemon_network_actions_seconds_bucket Unknown ip, cls, ins, job, instance, le, action N/A
engine_daemon_network_actions_seconds_count Unknown ip, cls, ins, job, instance, action N/A
engine_daemon_network_actions_seconds_sum Unknown ip, cls, ins, job, instance, action N/A
etcd_debugging_snap_save_marshalling_duration_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
etcd_debugging_snap_save_marshalling_duration_seconds_count Unknown ip, cls, ins, job, instance N/A
etcd_debugging_snap_save_marshalling_duration_seconds_sum Unknown ip, cls, ins, job, instance N/A
etcd_debugging_snap_save_total_duration_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
etcd_debugging_snap_save_total_duration_seconds_count Unknown ip, cls, ins, job, instance N/A
etcd_debugging_snap_save_total_duration_seconds_sum Unknown ip, cls, ins, job, instance N/A
etcd_disk_wal_fsync_duration_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
etcd_disk_wal_fsync_duration_seconds_count Unknown ip, cls, ins, job, instance N/A
etcd_disk_wal_fsync_duration_seconds_sum Unknown ip, cls, ins, job, instance N/A
etcd_disk_wal_write_bytes_total gauge ip, cls, ins, job, instance Total number of bytes written in WAL.
etcd_snap_db_fsync_duration_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
etcd_snap_db_fsync_duration_seconds_count Unknown ip, cls, ins, job, instance N/A
etcd_snap_db_fsync_duration_seconds_sum Unknown ip, cls, ins, job, instance N/A
etcd_snap_db_save_total_duration_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
etcd_snap_db_save_total_duration_seconds_count Unknown ip, cls, ins, job, instance N/A
etcd_snap_db_save_total_duration_seconds_sum Unknown ip, cls, ins, job, instance N/A
etcd_snap_fsync_duration_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
etcd_snap_fsync_duration_seconds_count Unknown ip, cls, ins, job, instance N/A
etcd_snap_fsync_duration_seconds_sum Unknown ip, cls, ins, job, instance N/A
go_gc_duration_seconds summary ip, cls, ins, job, instance, quantile A summary of the pause duration of garbage collection cycles.
go_gc_duration_seconds_count Unknown ip, cls, ins, job, instance N/A
go_gc_duration_seconds_sum Unknown ip, cls, ins, job, instance N/A
go_goroutines gauge ip, cls, ins, job, instance Number of goroutines that currently exist.
go_info gauge ip, cls, ins, job, version, instance Information about the Go environment.
go_memstats_alloc_bytes counter ip, cls, ins, job, instance Total number of bytes allocated, even if freed.
go_memstats_alloc_bytes_total counter ip, cls, ins, job, instance Total number of bytes allocated, even if freed.
go_memstats_buck_hash_sys_bytes gauge ip, cls, ins, job, instance Number of bytes used by the profiling bucket hash table.
go_memstats_frees_total counter ip, cls, ins, job, instance Total number of frees.
go_memstats_gc_sys_bytes gauge ip, cls, ins, job, instance Number of bytes used for garbage collection system metadata.
go_memstats_heap_alloc_bytes gauge ip, cls, ins, job, instance Number of heap bytes allocated and still in use.
go_memstats_heap_idle_bytes gauge ip, cls, ins, job, instance Number of heap bytes waiting to be used.
go_memstats_heap_inuse_bytes gauge ip, cls, ins, job, instance Number of heap bytes that are in use.
go_memstats_heap_objects gauge ip, cls, ins, job, instance Number of allocated objects.
go_memstats_heap_released_bytes gauge ip, cls, ins, job, instance Number of heap bytes released to OS.
go_memstats_heap_sys_bytes gauge ip, cls, ins, job, instance Number of heap bytes obtained from system.
go_memstats_last_gc_time_seconds gauge ip, cls, ins, job, instance Number of seconds since 1970 of last garbage collection.
go_memstats_lookups_total counter ip, cls, ins, job, instance Total number of pointer lookups.
go_memstats_mallocs_total counter ip, cls, ins, job, instance Total number of mallocs.
go_memstats_mcache_inuse_bytes gauge ip, cls, ins, job, instance Number of bytes in use by mcache structures.
go_memstats_mcache_sys_bytes gauge ip, cls, ins, job, instance Number of bytes used for mcache structures obtained from system.
go_memstats_mspan_inuse_bytes gauge ip, cls, ins, job, instance Number of bytes in use by mspan structures.
go_memstats_mspan_sys_bytes gauge ip, cls, ins, job, instance Number of bytes used for mspan structures obtained from system.
go_memstats_next_gc_bytes gauge ip, cls, ins, job, instance Number of heap bytes when next garbage collection will take place.
go_memstats_other_sys_bytes gauge ip, cls, ins, job, instance Number of bytes used for other system allocations.
go_memstats_stack_inuse_bytes gauge ip, cls, ins, job, instance Number of bytes in use by the stack allocator.
go_memstats_stack_sys_bytes gauge ip, cls, ins, job, instance Number of bytes obtained from system for stack allocator.
go_memstats_sys_bytes gauge ip, cls, ins, job, instance Number of bytes obtained from system.
go_threads gauge ip, cls, ins, job, instance Number of OS threads created.
logger_log_entries_size_greater_than_buffer_total counter ip, cls, ins, job, instance Number of log entries which are larger than the log buffer
logger_log_read_operations_failed_total counter ip, cls, ins, job, instance Number of log reads from container stdio that failed
logger_log_write_operations_failed_total counter ip, cls, ins, job, instance Number of log write operations that failed
process_cpu_seconds_total counter ip, cls, ins, job, instance Total user and system CPU time spent in seconds.
process_max_fds gauge ip, cls, ins, job, instance Maximum number of open file descriptors.
process_open_fds gauge ip, cls, ins, job, instance Number of open file descriptors.
process_resident_memory_bytes gauge ip, cls, ins, job, instance Resident memory size in bytes.
process_start_time_seconds gauge ip, cls, ins, job, instance Start time of the process since unix epoch in seconds.
process_virtual_memory_bytes gauge ip, cls, ins, job, instance Virtual memory size in bytes.
process_virtual_memory_max_bytes gauge ip, cls, ins, job, instance Maximum amount of virtual memory available in bytes.
promhttp_metric_handler_requests_in_flight gauge ip, cls, ins, job, instance Current number of scrapes being served.
promhttp_metric_handler_requests_total counter ip, cls, ins, job, instance, code Total number of scrapes by HTTP status code.
scrape_duration_seconds Unknown ip, cls, ins, job, instance N/A
scrape_samples_post_metric_relabeling Unknown ip, cls, ins, job, instance N/A
scrape_samples_scraped Unknown ip, cls, ins, job, instance N/A
scrape_series_added Unknown ip, cls, ins, job, instance N/A
swarm_dispatcher_scheduling_delay_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
swarm_dispatcher_scheduling_delay_seconds_count Unknown ip, cls, ins, job, instance N/A
swarm_dispatcher_scheduling_delay_seconds_sum Unknown ip, cls, ins, job, instance N/A
swarm_manager_configs_total gauge ip, cls, ins, job, instance The number of configs in the cluster object store
swarm_manager_leader gauge ip, cls, ins, job, instance Indicates if this manager node is a leader
swarm_manager_networks_total gauge ip, cls, ins, job, instance The number of networks in the cluster object store
swarm_manager_nodes gauge ip, cls, ins, job, instance, state The number of nodes
swarm_manager_secrets_total gauge ip, cls, ins, job, instance The number of secrets in the cluster object store
swarm_manager_services_total gauge ip, cls, ins, job, instance The number of services in the cluster object store
swarm_manager_tasks_total gauge ip, cls, ins, job, instance, state The number of tasks in the cluster object store
swarm_node_manager gauge ip, cls, ins, job, instance Whether this node is a manager or not
swarm_raft_snapshot_latency_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
swarm_raft_snapshot_latency_seconds_count Unknown ip, cls, ins, job, instance N/A
swarm_raft_snapshot_latency_seconds_sum Unknown ip, cls, ins, job, instance N/A
swarm_raft_transaction_latency_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
swarm_raft_transaction_latency_seconds_count Unknown ip, cls, ins, job, instance N/A
swarm_raft_transaction_latency_seconds_sum Unknown ip, cls, ins, job, instance N/A
swarm_store_batch_latency_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
swarm_store_batch_latency_seconds_count Unknown ip, cls, ins, job, instance N/A
swarm_store_batch_latency_seconds_sum Unknown ip, cls, ins, job, instance N/A
swarm_store_lookup_latency_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
swarm_store_lookup_latency_seconds_count Unknown ip, cls, ins, job, instance N/A
swarm_store_lookup_latency_seconds_sum Unknown ip, cls, ins, job, instance N/A
swarm_store_memory_store_lock_duration_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
swarm_store_memory_store_lock_duration_seconds_count Unknown ip, cls, ins, job, instance N/A
swarm_store_memory_store_lock_duration_seconds_sum Unknown ip, cls, ins, job, instance N/A
swarm_store_read_tx_latency_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
swarm_store_read_tx_latency_seconds_count Unknown ip, cls, ins, job, instance N/A
swarm_store_read_tx_latency_seconds_sum Unknown ip, cls, ins, job, instance N/A
swarm_store_write_tx_latency_seconds_bucket Unknown ip, cls, ins, job, instance, le N/A
swarm_store_write_tx_latency_seconds_count Unknown ip, cls, ins, job, instance N/A
swarm_store_write_tx_latency_seconds_sum Unknown ip, cls, ins, job, instance N/A
up Unknown ip, cls, ins, job, instance N/A

14.5 - 常见问题

Pigsty Docker 模块常见问题答疑

谁能执行Docker命令?

默认情况下,Pigsty 会将当前远程节点执行剧本的管理用户(即目标节点上 ssh 远程登陆的用户),以及参数 node_admin_username 中指定的管理用户加入到 Docker 操作系统用户组中。 在这个用户组(docker)中的所有用户,可以使用 docker CLI 命令对 Docker 发起管理。

如果你想让其他用户也可以执行 Docker 命令,可以将该操作系统用户加入到 docker 组中:

usermod -aG docker <username>

使用代理服务器

在 Docker 安装过程中,如果 proxy_env 参数存在, 这里的 HTTP 代理服务器配置会被写入到 /etc/docker/daemon.json 配置文件中。

Docker 在从上游 Registry 拉取镜像时,会使用此代理服务器。

小提示,在执行 configure 过程中使用 -x 参数会将当前环境中的代理服务器配置写入到 proxy_env 中。


使用镜像站点

如果您在中国大陆网络环境下访问 DockerHub 较慢,可以优先考虑:

  • 使用 docker_registry_mirrors 配置可用镜像站点
  • 或配置 proxy_env 通过代理拉取镜像
  • 也可直接使用其他公开 Registry(例如 quay.io
docker login quay.io    # 输入用户名密码,完成登陆

将Docker纳入监控

在 Docker 模块安装过程中,针对节点单独执行监控目标注册子任务 docker_register(或别名标签 add_metrics)即可:

./docker.yml -l <your-node-selector> -t docker_register

使用软件模板

Pigsty 提供了一系列使用 Docker Compose 拉起的软件 工具模板,可以开箱即用。

但需要首先安装 Docker 模块。

15 - 模块:JUICE

使用 JuiceFS 分布式文件系统,以 PostgreSQL 作为元数据引擎,提供可共享的 POSIX 存储。

JuiceFS 是一款高性能、POSIX 兼容的分布式文件系统,可以将对象存储/数据库挂载为本地文件系统。

JUICE 模块依赖 NODE 的基础设施与软件仓库,通常使用 PGSQL 作为元数据引擎。 数据存储可以使用 PostgreSQL(数据写入 jfs_blob 表),或 MINIO 模块提供的 Silo / S3 等对象存储。监控集成依赖 INFRA 的 VictoriaMetrics。

flowchart LR
    subgraph Client["应用/用户"]
        app["POSIX 访问"]
    end

    subgraph JUICE["JUICE"]
        jfs["JuiceFS Mount"]
    end

    subgraph PGSQL["PGSQL"]
        meta["Metadata DB"]
        blob["Data DB / jfs_blob(可选)"]
    end

    subgraph Object["对象存储(可选)"]
        s3["Silo / S3"]
    end

    subgraph INFRA["INFRA(可选)"]
        vm["VictoriaMetrics"]
    end

    app --> jfs
    jfs --> meta
    jfs -.->|二选一的数据后端| blob
    jfs -.->|二选一的数据后端| s3
    jfs -->|/metrics| vm

    style JUICE fill:#5B9CD5,stroke:#4178a8,color:#fff
    style PGSQL fill:#3E668F,stroke:#2d4a66,color:#fff
    style Object fill:#FCDB72,stroke:#d4b85e,color:#333
    style INFRA fill:#999,stroke:#666,color:#fff

模块特点

  • PostgreSQL 元数据:元数据存储于 PostgreSQL,便于管理与备份
  • 多实例:单节点可挂载多个独立文件系统实例
  • 多种数据后端:支持 PostgreSQL、Silo/MinIO、S3 等;元数据与文件数据是两个独立角色
  • 监控集成 每实例暴露 Prometheus / Victoria 格式指标端口
  • 配置简洁:以 juice_instances 字典描述实例

快速开始

最小配置示例(单实例):

juice_instances:
  jfs:
    path: /fs
    meta: postgres://dbuser_meta:[email protected]:5432/meta
    data: --storage postgres --bucket 10.10.10.10:5432/meta --access-key dbuser_meta --secret-key DBUser.Meta
    port: 9567

部署:

./juice.yml -l <host>

15.1 - 集群配置

JUICE 模块配置说明:实例定义、存储后端与挂载参数。

概念与实现

JuiceFS 由 元数据引擎数据存储 两部分组成。 当前版本中,meta 会原样透传给 juicefs 作为元数据引擎 URL,生产场景通常使用 PostgreSQL。 数据存储通过 data 参数传入 juicefs format 选项决定。

JUICE 模块执行逻辑与关键命令:

# 格式化(仅首次创建有效)
juicefs format --no-update <data> "<meta>" "<name>"

# 挂载
juicefs mount <mount_opts> --cache-dir <juice_cache> --metrics 0.0.0.0:<port> <meta> <path>

说明:

  • --no-update 确保已存在的文件系统不会被覆盖。
  • data 仅用于 首次格式化,文件系统已存在时不会生效。
  • mount 仅用于挂载阶段,可按需传入缓存与并发参数。

模块参数

JUICE 模块仅有两个参数:

参数 类型 级别 说明
juice_cache path C JuiceFS 共享缓存目录
juice_instances dict I JuiceFS 实例字典(可为空)
  • juice_cache:所有实例共享的本地缓存目录,默认 /data/juice
  • juice_instances:在 实例级别 定义的实例字典,Key 为文件系统名称;空字典表示不管理实例

实例配置

juice_instances 的每个条目代表一个 JuiceFS 实例:

字段 必选 默认值 说明
path - 挂载点路径,如 /fs
meta - 元数据引擎 URL(建议 PostgreSQL)
data '' juicefs format 选项(存储后端)
unit juicefs-<name> systemd 服务名
mount '' juicefs mount 额外参数
port 9567 指标端口(同节点需唯一)
owner root 挂载点属主
group root 挂载点属组
mode 0755 挂载点权限
state create create / absent
重要
  • 建议在 首次格式化 时显式设置 data,以明确存储后端。
  • 同一节点多个实例必须配置不同的 port

配置示例:

juice_instances:
  jfs:
    path: /fs
    meta: postgres://dbuser_meta:[email protected]:5432/meta
    data: --storage postgres --bucket 10.10.10.10:5432/meta --access-key dbuser_meta --secret-key DBUser.Meta
    port: 9567

存储后端

data 字段直接拼接到 juicefs format,可配置任意支持的后端。 以下为常见示例:

PostgreSQL 数据后端

juice_instances:
  jfs:
    path: /fs
    meta: postgres://dbuser_meta:[email protected]:5432/meta
    data: --storage postgres --bucket 10.10.10.10:5432/meta --access-key dbuser_meta --secret-key DBUser.Meta

JuiceFS 会在 --bucket 指定的数据库中创建 jfs_blob 表存储文件数据。 这里的 PostgreSQL 数据后端与 meta 元数据引擎是两个独立角色;它们可以使用同一个数据库,也可以分别部署。数据库和具有读写权限的用户必须预先存在。

Silo / MinIO 兼容对象存储

juice_instances:
  jfs:
    path: /fs
    meta: postgres://dbuser_meta:[email protected]:5432/meta
    data: --storage minio --bucket https://sss.pigsty:9000/juice --access-key <s3_access_key> --secret-key <s3_secret_key>

S3 兼容存储

juice_instances:
  jfs:
    path: /fs
    meta: postgres://dbuser_meta:[email protected]:5432/meta
    data: --storage s3 --bucket https://s3.amazonaws.com/my-bucket --access-key AKIAXXXXXXXX --secret-key XXXXXXXXXX

典型配置

多实例(同节点)

juice_instances:
  pgfs:
    path: /pgfs
    meta: postgres://dbuser_meta:[email protected]:5432/meta
    data: --storage postgres --bucket 10.10.10.10:5432/meta --access-key dbuser_meta --secret-key DBUser.Meta
    port: 9567
  shared:
    path: /shared
    meta: postgres://dbuser_meta:[email protected]:5432/shared
    data: --storage minio --bucket https://sss.pigsty:9000/shared --access-key <s3_access_key> --secret-key <s3_secret_key>
    port: 9568
    owner: postgres
    group: postgres

多节点共享挂载

多个节点挂载同一个 JuiceFS:

app:
  hosts:
    10.10.10.11: { juice_instances: { shared: { path: /shared, meta: "postgres://...", port: 9567 } } }
    10.10.10.12: { juice_instances: { shared: { path: /shared, meta: "postgres://...", port: 9567 } } }

第一次格式化由任一节点执行即可,其余节点会通过 --no-update 自动跳过。


注意事项

  • port 会暴露在 0.0.0.0,请结合防火墙或安全组控制访问。
  • data 变更不会更新已存在的文件系统,如需切换后端请手动处理。
  • metadata 可能包含数据库或对象存储凭据;请限制 pigsty.yml 的读取权限,并使用独立的最小权限账号,生产环境不要沿用示例密码。

15.2 - 参数列表

JUICE 模块参数说明(共 2 项)。

JUICE 模块参数共 2 项:


参数概览

参数 类型 级别 说明
juice_cache path C JuiceFS 共享缓存目录
juice_instances dict I JuiceFS 实例定义字典(可为空)

级别说明C 为集群级别,I 为实例级别。


默认参数

参数定义于 roles/juice/defaults/main.yml

#-----------------------------------------------------------------
# JUICE
#-----------------------------------------------------------------
juice_cache: /data/juice
juice_instances: {}

juice_cache

参数名称:juice_cache,类型:path,级别:C

所有 JuiceFS 实例共享的本地缓存目录,默认 /data/juice。 JuiceFS 会在此目录下按文件系统 UUID 进行隔离。

juice_cache: /data/juice

juice_instances

参数名称:juice_instances,类型:dict,级别:I

JuiceFS 实例定义字典,通常在实例级别定义。 默认值为空字典(表示不部署实例);Key 为文件系统名称,Value 为实例配置对象。

juice_instances:
  jfs:
    path: /fs
    meta: postgres://u:p@h:5432/db
    data: --storage postgres --bucket ...
    port: 9567

实例字段说明:

字段 必选 默认值 说明
path - 挂载点路径
meta - 元数据引擎 URL(建议 PostgreSQL)
data '' juicefs format 选项(仅首次创建生效)
unit juicefs-<name> systemd 服务名
mount '' juicefs mount 额外参数
port 9567 指标端口(同节点需唯一)
owner root 挂载点属主
group root 挂载点属组
mode 0755 挂载点权限
state create create / absent
注意
  • data 仅用于 juicefs format,文件系统创建后不会再更新。
  • 同一节点多实例必须使用不同的 port

15.3 - 预置剧本

JUICE 模块剧本使用说明。

JUICE 模块提供 juice.yml 剧本,用于部署与移除 JuiceFS 实例。


juice.yml

juice.yml 的任务结构如下:

juice_id        : 校验配置、检查端口冲突
juice_install   : 安装 juicefs 软件包
juice_cache     : 创建共享缓存目录
juice_clean     : 移除实例(state=absent)
juice_instance  : 创建实例(state=create)
  - juice_init  : 格式化文件系统(--no-update)
  - juice_dir   : 创建挂载点目录
  - juice_config: 渲染环境文件与 systemd 服务单元
  - juice_launch: 启动服务并等待指标端口就绪
juice_register  : 注册到 VictoriaMetrics 目标文件

运行粒度

粒度 限制参数 说明
节点 -l <host> 部署该节点所有实例
实例 -l <host> -e fsname=<name> 只处理指定实例

示例:

./juice.yml -l 10.10.10.10                 # 部署该节点所有实例
./juice.yml -l 10.10.10.10 -e fsname=jfs   # 仅部署 jfs 实例

常用标签

标签 说明
juice_id 校验 juice_instances 与端口冲突
juice_install 安装 juicefs 软件包
juice_cache 创建共享缓存目录
juice_clean 移除实例(state=absent)
juice_instance 创建实例(伞形标签)
juice_init 格式化文件系统
juice_dir 创建挂载点目录
juice_config 渲染配置文件
juice_launch 启动服务
juice_register 写入 VictoriaMetrics 目标文件

配置更新

仅更新配置文件(不重启服务):

./juice.yml -l <host> -t juice_config

更新配置并确保服务在线(不强制重启):

./juice.yml -l <host> -t juice_config,juice_launch

如需让新的挂载参数立即生效,请手动重启对应实例服务:

systemctl restart juicefs-<name>

移除实例

移除流程:

  1. 将实例 state 置为 absent
  2. 执行 juice_clean
juice_instances:
  jfs:
    path: /fs
    meta: postgres://...
    state: absent
./juice.yml -l <host> -t juice_clean,juice_register
./juice.yml -l <host> -e fsname=jfs -t juice_clean,juice_register

移除动作包括:停止服务、懒卸载、删除 systemd 单元与环境文件、重载 systemd;随后 juice_register 会重写该节点的目标文件并移除陈旧抓取地址。只执行 juice_clean 不会更新监控 Target。 不会删除 PostgreSQL 元数据、PostgreSQL jfs_blob 数据表或对象存储数据。


监控注册

juice_register 会在 infra 节点 写入目标文件:

/infra/targets/juice/<hostname>.yml

如需手动重新注册:

./juice.yml -l <host> -t juice_register

15.4 - 管理预案

JUICE 模块运维与故障排查手册。

常见运维场景如下:

更多问题参见 FAQ


初始化实例

./juice.yml -l <host>
./juice.yml -l <host> -e fsname=<name>

初始化流程:

  • 安装 juicefs 软件包
  • 创建共享缓存目录(默认 /data/juice
  • 执行 juicefs format --no-update(仅首次创建有效)
  • 创建挂载点目录并设置权限
  • 渲染 systemd 单元与环境文件
  • 启动服务并等待指标端口就绪
  • 注册到 VictoriaMetrics(若存在 infra 节点)

重新配置

修改配置后,建议执行以下命令(更新配置并确保服务在线):

./juice.yml -l <host> -t juice_config,juice_launch

仅渲染配置文件而不触碰服务状态:

./juice.yml -l <host> -t juice_config

说明:

  • juice_config,juice_launch 会确保服务处于 started,但不会强制重启已运行实例
  • data 仅在首次 format 时生效
  • 变更 mount 参数后,请手动重启对应服务(systemctl restart juicefs-<name>

移除实例

  1. 将实例 state 设为 absent
  2. 执行 juice_clean
juice_instances:
  jfs:
    path: /fs
    meta: postgres://...
    state: absent
./juice.yml -l <host> -t juice_clean,juice_register
./juice.yml -l <host> -e fsname=jfs -t juice_clean,juice_register

移除动作:

  • 停止 systemd 服务
  • umount -l 懒卸载
  • 删除 unit 与环境文件
  • 重载 systemd
  • 重写该节点的 VictoriaMetrics 目标文件,移除 state=absent 的实例

不会删除 PostgreSQL 元数据、PostgreSQL jfs_blob 数据表或对象存储数据。

只执行 -t juice_clean 不会更新监控目标,会暂时留下已移除实例的陈旧抓取地址;因此上面的命令同时执行 juice_register


添加新实例

在配置中新增实例,确保端口唯一:

juice_instances:
  newfs:
    path: /newfs
    meta: postgres://...
    data: --storage minio --bucket https://sss.pigsty:9000/newfs --access-key <s3_access_key> --secret-key <s3_secret_key>
    port: 9568

部署:

./juice.yml -l <host> -e fsname=newfs

多节点共享挂载

多个节点配置相同的 meta 与实例名:

app:
  hosts:
    10.10.10.11: { juice_instances: { shared: { path: /shared, meta: "postgres://...", port: 9567 } } }
    10.10.10.12: { juice_instances: { shared: { path: /shared, meta: "postgres://...", port: 9567 } } }

首次格式化由任一节点完成,其余节点会通过 --no-update 自动跳过。


PITR 恢复

JuiceFS 元数据与数据必须恢复到相互一致的状态。 执行任何恢复前,请停止所有写入方并卸载/停止每个客户端上的对应 JuiceFS 服务,明确目标 PostgreSQL 集群和时间点,并先确认可用备份:

# 核对 Patroni 集群成员;在数据库节点核对目标 stanza 的备份
pig pt list <cluster>
pig pb info -s <stanza>

# 在目标数据库节点以 postgres 用户执行恢复
sudo -iu postgres pg-pitr -s <stanza> -t "2026-08-14 10:30:00+08"
PITR 会覆盖 PostgreSQL 数据目录

确认准确的集群名、近期备份、恢复时间点与回滚方案后,按照 PostgreSQL PITR 教程 停止 Patroni/PostgreSQL 并执行恢复。pg-pitr 不负责停止服务、恢复 Patroni/DCS、验证数据或重建副本,不要把上述命令当作完整恢复流程。

当元数据与 --storage postgresjfs_blob 位于同一个被恢复的 PostgreSQL 数据库中时,数据库级 PITR 可以把两者恢复到同一时间点。 若两者位于不同数据库或集群,必须设计一致的联合恢复点。

如果文件数据位于 Silo/S3,对 PostgreSQL 做 PITR 只会回滚元数据,不会回滚对象: 目标时间点之后的新对象可能残留,而已删除或回收的旧对象可能无法找回。恢复能否得到完整文件系统取决于对象版本、回收站与生命周期策略;验证完成前不要运行垃圾回收。


故障排查

挂载失败

systemctl status juicefs-jfs
journalctl -u juicefs-jfs -f
mountpoint /fs

元数据连接问题

psql "postgres://dbuser_meta:[email protected]:5432/meta" -c "SELECT 1"

指标端口检查

ss -tlnp | grep 9567
curl http://localhost:9567/metrics

性能调优

通过 mount 传入 juicefs mount 选项:

juice_instances:
  jfs:
    path: /fs
    meta: postgres://...
    mount: --cache-size 102400 --prefetch 3 --max-uploads 50

常用关注指标:

  • juicefs_blockcache_hits/juicefs_blockcache_miss:缓存命中率
  • juicefs_object_request_durations_histogram_seconds:对象存储延迟
  • juicefs_transaction_durations_histogram_seconds:元数据事务延迟

15.5 - 监控告警

JUICE 模块监控与指标说明。

JuiceFS 实例通过 juicefs mount --metrics 暴露 Prometheus 指标。 在 JUICE 模块中,指标监听地址为 0.0.0.0:<port>,默认端口 9567


监控架构

JuiceFS Mount (metrics: 0.0.0.0:<port>)
VictoriaMetrics (scrape)
Grafana Dashboard

若已部署 INFRAjuice_register 会自动写入抓取目标:

/infra/targets/juice/<hostname>.yml

当前源码随附 Node JuiceFS 仪表盘(UID:node-juice), 用于查看单个节点上各 JuiceFS 挂载实例的容量、缓存、对象存储、元数据事务与客户端资源指标。


目标文件示例

- labels: { ip: 10.10.10.10, ins: "node-jfs", cls: "jfs" }
  targets: [ 10.10.10.10:9567 ]

如需手动注册:

./juice.yml -l <host> -t juice_register

关键指标

对象存储

指标 类型 说明
juicefs_object_request_durations_histogram_seconds histogram 对象存储请求延迟
juicefs_object_request_errors counter 对象存储错误数

缓存

指标 类型 说明
juicefs_blockcache_hits counter 缓存命中次数
juicefs_blockcache_miss counter 缓存未命中次数

元数据事务

指标 类型 说明
juicefs_transaction_durations_histogram_seconds histogram 元数据事务延迟(直方图)
juicefs_transaction_durations_histogram_seconds_count counter 元数据事务请求计数

常用 PromQL

缓存命中率:

rate(juicefs_blockcache_hits[5m]) /
(rate(juicefs_blockcache_hits[5m]) + rate(juicefs_blockcache_miss[5m]))

对象存储 P99 延迟:

histogram_quantile(0.99, rate(juicefs_object_request_durations_histogram_seconds_bucket[5m]))

15.6 - 常见问题

JUICE 模块常见问题解答。

端口冲突怎么办?

同一节点上的多个实例必须使用不同的 port。示例:

juice_instances:
  fs1:
    path: /fs1
    meta: postgres://...
    port: 9567
  fs2:
    path: /fs2
    meta: postgres://...
    port: 9568

为什么 data 变更不生效?

data 仅用于 juicefs format --no-update,文件系统创建后不会再更新。 如需切换后端,请手动迁移与重新格式化。


如何添加新实例?

  1. 在配置中新增实例定义
  2. 执行:
./juice.yml -l <host> -e fsname=<name>

如何移除实例?

  1. 将实例 state 设为 absent
  2. 执行:
./juice.yml -l <host> -t juice_clean,juice_register

移除不会删除 PostgreSQL 元数据或对象存储数据。 juice_register 用于同步刷新目标文件;只运行 juice_clean 会留下陈旧的监控抓取地址。


文件数据存储在哪里?

取决于 data 参数:

  • --storage postgres:JuiceFS 在 --bucket 指定的 PostgreSQL 数据库中创建 jfs_blob 表存储数据
  • --storage minio/s3:数据存于 Silo/S3 兼容对象存储的 bucket

元数据存储在 meta 指定的元数据引擎中(Pigsty 生产场景通常使用 PostgreSQL)。


多节点挂载注意事项?

  • 多节点使用相同的 meta 与实例名
  • 首次格式化仅需执行一次,其余节点会自动跳过
  • 确保 port 在每个节点上不冲突

监控目标没有生成?

juice_register 仅在存在 infra 组时写入 /infra/targets/juice/。 可手动执行:

./juice.yml -l <host> -t juice_register

如何修改挂载参数?

在实例中调整 mount 后,先刷新配置,再手动重启服务:

./juice.yml -l <host> -t juice_config,juice_launch
systemctl restart juicefs-<name>

16 - 模块:VIBE

使用 Pigsty 部署 AI 编程沙箱:Code-Server、JupyterLab、Node.js、Claude Code 与 Codex CLI。

VIBE 模块提供一套 浏览器化开发环境,包含 Code-Server、JupyterLab、Node.js、Claude Code 与 Codex CLI, 并可与 JUICE 共享存储和 PGSQL 数据库能力配合使用。

VIBE 依赖 NODEINFRA

  • NODE 负责基础软件与 Python uv 环境
  • INFRA 提供 Nginx 反向代理、Grafana 等可视化入口

组件一览

组件 说明 本地端口 访问路径
Code-Server VS Code 浏览器版 8443 /code/
JupyterLab 交互式 Notebook 8888 /jupyter/
Node.js 运行时与 npm - CLI
Claude Code CLI + 可观测性配置 - CLI / Grafana
Codex CLI CLI 安装,不托管配置 - CLI

说明:

  • Code-Server 仅监听 127.0.0.1:8443,通过 Nginx 暴露
  • JupyterLab 监听 0.0.0.0:8888,默认基路径为 /jupyter/
  • 模块默认 jupyter_enabled: false,而 conf/vibe.yml 模板会显式开启 Jupyter

快速开始

./configure -c vibe
./deploy.yml        # 部署清单中已定义的 NODE、INFRA、ETCD、MINIO 与 PGSQL
./juice.yml         # 可选,部署共享存储
./vibe.yml          # 部署 VIBE

默认访问入口(通过 infra_portal.home):

  • Code-Server:https://<domain>/code/
  • JupyterLab:https://<domain>/jupyter/
  • Claude Dashboard:https://<domain>/ui/d/claude-code

模块特点

  • 统一工作区vibe_data 作为 Code-Server 与 Jupyter 的根目录
  • 可选共享存储:配合 JUICE 实现多节点共享
  • 可观测性:Claude Code OpenTelemetry 默认对接 VictoriaMetrics/VictoriaLogs
  • 可组件化:Code/Jupyter/Node.js/Claude/Codex 可按需启用

文档目录

16.1 - 功能配置

VIBE 模块配置说明(Code-Server、JupyterLab、Node.js 与 Claude Code)。

VIBE 模块支持按需启用组件,并通过统一的工作目录和 Nginx 入口对外提供服务。


配置概览

组件 启用参数 默认状态 说明
Code-Server code_enabled 启用 浏览器 VS Code
JupyterLab jupyter_enabled 禁用 Notebook/终端/编辑器
Node.js nodejs_enabled 启用 Node.js 运行时与 npm
Claude Code claude_enabled 启用 CLI 安装、配置与可观测性
Codex CLI codex_enabled 启用 仅安装 CLI,不托管配置

说明:模块默认 jupyter_enabled: false,但 conf/vibe.yml 预置模板会显式设置为 true

配置通常位于集群 vars,也可以在实例级别覆盖:

all:
  children:
    infra:
      hosts:
        10.10.10.10:
          vibe_data: /fs
          code_enabled: true
          jupyter_enabled: true
          claude_enabled: true
          codex_enabled: true

工作目录

vibe_data 作为 VIBE 的统一工作区:

  • Code-Server 默认打开目录
  • JupyterLab root_dir
  • Claude Code 的工作目录
  • 渲染 AGENTS.md 上下文文件,并创建指向它的 CLAUDE.md 符号链接

vibe_dir 任务会创建目录并写入上下文文件,文件属主为 node_user

vibe_data: /fs

Code-Server 配置

code_enabled: true
code_port: 8443
code_data: /data/code
code_password: Vibe.Coding
code_gallery: openvsx

说明:

  • 服务监听 127.0.0.1:<code_port>(默认 8443),通过 Nginx /code/ 访问
  • 配置文件:code_data/code-server/config.yaml(默认 /data/code/code-server/config.yaml
  • 环境文件:/etc/default/code,用于配置扩展市场

扩展市场:

  • code_gallery: microsoft 使用微软官方市场
  • region=china 时默认切换 Open VSX 清华镜像

JupyterLab 配置

jupyter_enabled: true
jupyter_port: 8888
jupyter_data: /data/jupyter
jupyter_password: Vibe.Coding
jupyter_venv: /data/venv

说明:

  • 服务监听 0.0.0.0:<jupyter_port>(默认 8888),基路径为 /jupyter/
  • 配置文件:jupyter_data/jupyter_config.py(默认 /data/jupyter/jupyter_config.py
  • 登录 Token:c.IdentityProvider.token
  • 不会自动创建 venv,建议通过 NODE 模块的 node_uv_env 预先创建

创建 venv 示例:

uv venv /data/venv

Node.js 配置

nodejs_enabled: true
nodejs_registry: ''
npm_packages: []

说明:

  • nodejs_registry 为空时,region=china 会自动使用 https://registry.npmmirror.com
  • npm_packages 用于安装额外的全局 npm 包,默认为空
  • Claude Code 与 Codex CLI 由各自的独立任务安装

Claude Code 配置

claude 子任务同时执行 CLI 安装(claude_install)与配置写入(claude_config)。

claude_enabled: true
claude_package: '@anthropic-ai/claude-code'
claude_env:
  ANTHROPIC_API_KEY: sk-ant-xxx

启用 Claude 或 Codex 时,VIBE 会确保 Node.js 运行时已经安装。需要替换 Claude npm 包时,可覆盖 claude_package

生成的文件:

  • ~/.claude.json
  • ~/.claude/settings.json

claude_env 会与默认 OpenTelemetry 环境变量合并,默认上报到 VictoriaMetrics / VictoriaLogs。


Codex CLI 配置

codex_enabled: true

codex 子任务执行 npm install -g @openai/codex。VIBE 仅安装 Codex CLI,不写入 Codex 配置,也不接入 VIBE 的 Claude Code 可观测性。


Nginx 入口

VIBE 通过 infra_portal 暴露服务。 默认 home 域名自动包含 /code//jupyter/ 子路径。

如需独立域名:

infra_portal:
  code: { domain: code.pigsty, endpoint: "127.0.0.1:8443", websocket: true, auth: true }
  jupyter: { domain: jupyter.pigsty, endpoint: "127.0.0.1:8888", websocket: true, auth: true }
nginx_users:
  devadmin: '<strong-password>'

16.2 - 参数列表

VIBE 模块参数详解(共 18 项)。

VIBE 模块共有 18 个参数,分为:

  • 通用参数
  • Code-Server 参数
  • JupyterLab 参数
  • Node.js 参数
  • Claude Code 参数
  • Codex CLI 参数

参数概览

参数 类型 级别 默认值 说明
vibe_data path C /fs 工作目录
code_enabled bool C true 启用 Code-Server
code_port port C 8443 Code-Server 端口
code_data path C /data/code Code-Server 数据目录
code_password string C Vibe.Coding Code-Server 密码
code_gallery enum C openvsx 扩展市场
jupyter_enabled bool C false 启用 JupyterLab
jupyter_port port C 8888 JupyterLab 端口
jupyter_data path C /data/jupyter JupyterLab 数据目录
jupyter_password string C Vibe.Coding JupyterLab Token
jupyter_venv path C /data/venv Python venv 路径
nodejs_enabled bool C true 启用 Node.js
nodejs_registry url C '' npm 镜像地址
npm_packages string[] C [] 额外全局 npm 包
claude_enabled bool C true 安装并配置 Claude Code
claude_package string C @anthropic-ai/claude-code Claude Code npm 包
claude_env dict C {} Claude 环境变量
codex_enabled bool C true 安装 Codex CLI

默认参数

定义于 roles/vibe/defaults/main.yml

vibe_data: /fs

code_enabled: true
code_port: 8443
code_data: /data/code
code_password: Vibe.Coding
code_gallery: 'openvsx'

jupyter_enabled: false
jupyter_port: 8888
jupyter_data: /data/jupyter
jupyter_password: Vibe.Coding
jupyter_venv: /data/venv

nodejs_enabled: true
nodejs_registry: ''
npm_packages: []

claude_enabled: true
claude_package: '@anthropic-ai/claude-code'
claude_env: {}

codex_enabled: true

通用参数

vibe_data

工作目录,默认值为 /fs。Code-Server 与 JupyterLab 默认以此作为工作区根目录;vibe_dir 会在这里渲染 AGENTS.md,并创建指向它的 CLAUDE.md 符号链接。


Code-Server

code_enabled

是否启用 Code-Server,默认值为 true

code_port

监听端口,默认值为 8443;绑定 127.0.0.1,由 Nginx /code/ 转发。

code_data

用户数据目录,配置文件位于 code_data/code-server/config.yaml(默认 /data/code/code-server/config.yaml)。

code_password

登录密码,默认值为 Vibe.Coding,生产环境必须修改。

扩展市场:openvsx / microsoft。 当 region=china 且选择 openvsx 时会自动使用清华镜像。


JupyterLab

jupyter_enabled

是否启用 JupyterLab。 模块默认值为 falseconf/vibe.yml 中会显式改为 true 以启用完整沙箱。

jupyter_port

监听端口,默认 0.0.0.0:8888

jupyter_data

数据目录,配置文件位于 jupyter_data/jupyter_config.py(默认 /data/jupyter/jupyter_config.py)。

jupyter_password

访问 Token,默认值为 Vibe.Coding,写入 c.IdentityProvider.token

jupyter_venv

JupyterLab 使用的 Python venv 路径,默认值为 /data/venv,需要预先创建(通常由 NODE 模块完成)。


Node.js

nodejs_enabled

是否启用独立的 Node.js 安装任务,默认值为 true

nodejs_registry

npm 镜像地址,region=china 且为空时自动使用 https://registry.npmmirror.com

npm_packages

额外全局安装的 npm 包列表,对应标签 nodejs_pkg,默认为空。 Claude Code 与 Codex CLI 由各自的独立任务安装,不需要加入此列表。


Claude Code

claude_enabled

启用 Claude Code 安装与配置任务,默认值为 trueclaude_install 安装 CLI,claude_config 写入配置。

claude_package

Claude Code 使用的 npm 包,默认为 @anthropic-ai/claude-code

claude_env

额外环境变量,合并至默认 OpenTelemetry 配置。

默认环境变量包括:

  • CLAUDE_CODE_ENABLE_TELEMETRY=1
  • OTEL_METRICS_EXPORTER=otlp
  • OTEL_LOGS_EXPORTER=otlp
  • OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf
  • OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=http/protobuf
  • OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://127.0.0.1:8428/opentelemetry/v1/metrics
  • OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://127.0.0.1:9428/insert/opentelemetry/v1/logs
  • OTEL_RESOURCE_ATTRIBUTES=ip=<inventory_hostname>,job=claude

Codex CLI

codex_enabled

是否安装 Codex CLI,默认为 true。启用后,codex_install 任务执行 npm install -g @openai/codex。 VIBE 只负责安装 Codex CLI,不托管 Codex 配置,也不为其配置 OpenTelemetry。

16.3 - 预置剧本

VIBE 模块的 Ansible 剧本使用说明。

VIBE 模块提供 vibe.yml 剧本,用于部署 Code-Server、JupyterLab、Node.js、Claude Code 与 Codex CLI。

vibe.yml 只包含 node_idvibe 角色,不包含 node/infra。 建议先执行 deploy.yml 或显式运行 node.ymlinfra.yml


vibe.yml

vibe.yml 内容:

- name: VIBE
  hosts: all
  become: true
  gather_facts: no
  roles:
    - { role: node_id, tags: id }
    - { role: vibe,    tags: vibe }

任务结构

vibe
├── vibe_dir          # 创建工作目录与上下文文件
├── code              # Code-Server
│   ├── code_install
│   ├── code_dir
│   ├── code_config
│   └── code_launch
├── jupyter           # JupyterLab
│   ├── jupyter_install
│   ├── jupyter_dir
│   ├── jupyter_config
│   └── jupyter_launch
├── nodejs            # Node.js Runtime 与额外 npm 包
│   ├── nodejs_install
│   ├── nodejs_config
│   └── nodejs_pkg
├── codex             # Codex CLI
│   └── codex_install
└── claude            # Claude Code
    ├── claude_install
    └── claude_config

说明:

  • jupyter_install 使用 uv pip,不会创建 venv
  • nodejs_pkg 只安装 npm_packages 中声明的额外包,默认列表为空
  • claude_install 使用 claude_package 安装 Claude CLI,claude_config 写入 ~/.claude 配置
  • codex_install 安装 @openai/codex,不托管 Codex 配置

常用命令

完整部署:

./vibe.yml -l <host>

组件级部署:

./vibe.yml -l <host> -t code
./vibe.yml -l <host> -t jupyter
./vibe.yml -l <host> -t nodejs
./vibe.yml -l <host> -t claude
./vibe.yml -l <host> -t codex

配置更新:

./vibe.yml -l <host> -t code_config,code_launch
./vibe.yml -l <host> -t jupyter_config
ssh <host> sudo systemctl restart jupyter
./vibe.yml -l <host> -t claude_config

在本次执行中跳过组件:

./vibe.yml -l <host> -e code_enabled=false
./vibe.yml -l <host> -e jupyter_enabled=false
./vibe.yml -l <host> -e nodejs_enabled=false
./vibe.yml -l <host> -e claude_enabled=false
./vibe.yml -l <host> -e codex_enabled=false

这些开关是任务执行条件:设为 false 只会跳过对应安装与配置任务,不会停止、禁用或卸载此前已经部署的服务/软件。若要退役 Code-Server 或 JupyterLab,需要另行执行 systemctl disable --now code-serversystemctl disable --now jupyter;VIBE 当前没有独立的移除剧本。

Node.js 是 Claude Code 与 Codex CLI 的运行时依赖:只设置 nodejs_enabled=false,但 claude_enabledcodex_enabled 仍为 true 时,nodejs 阶段依然会执行。只有三个开关都为 false 时才会跳过 Node.js 阶段。


部署顺序

./deploy.yml      # 清单中已定义的 NODE、INFRA、ETCD、MINIO 与 PGSQL
./juice.yml       # 可选共享存储
./vibe.yml        # VIBE

幂等性

vibe.yml 支持重复执行,配置变更后可直接重跑。

16.4 - 管理预案

VIBE 模块运维操作与常见管理任务。

服务管理

systemctl status code-server
systemctl restart code-server
systemctl status jupyter
systemctl restart jupyter

查看日志:

journalctl -u code-server -f
journalctl -u jupyter -f

工作目录与上下文

vibe_dir 会在 vibe_data 下创建:

  • AGENTS.md:由角色模板渲染的上下文文件
  • CLAUDE.md:指向 AGENTS.md 的符号链接

默认位置(可由 vibe_data 调整):

/fs/CLAUDE.md
/fs/AGENTS.md

密码与认证

Code-Server

修改配置:

vi /data/code/code-server/config.yaml
systemctl restart code-server

或通过 Ansible:

./vibe.yml -l <host> -e code_password='NewPassword' -t code_config,code_launch

JupyterLab

配置文件位置:/data/jupyter/jupyter_config.py

字段:c.IdentityProvider.token

vi /data/jupyter/jupyter_config.py
systemctl restart jupyter

Code-Server 扩展

code-server --install-extension ms-python.python
code-server --list-extensions
code-server --uninstall-extension ms-python.python

切换扩展市场:

code_gallery: microsoft

重新部署:

./vibe.yml -l <host> -t code_config,code_launch

JupyterLab 环境管理

VIBE 不会自动创建 venv,请确保 jupyter_venv 存在:

uv venv /data/venv

安装/更新 JupyterLab:

uv pip install --python /data/venv/bin/python jupyterlab ipykernel
systemctl restart jupyter

安装扩展(以 venv 为准):

source /data/venv/bin/activate
pip install jupyterlab-git
systemctl restart jupyter

Claude Code

claude_install 子任务安装 Claude CLI,claude_config 子任务写入配置文件。

which claude
claude --version

配置文件:

  • ~/.claude.json
  • ~/.claude/settings.json

更新配置:

./vibe.yml -l <host> -t claude_config

重装/补装 Claude CLI:

./vibe.yml -l <host> -t claude_install
# 或手工安装
npm install -g @anthropic-ai/claude-code

需要使用其他 npm 包时,可覆盖 claude_package


Codex CLI

VIBE 通过 codex_install 安装 @openai/codex,但不托管 Codex 配置:

which codex
codex --version
./vibe.yml -l <host> -t codex_install

如果需要配置到其他用户,请使用对应的远程登录用户执行或手动拷贝配置文件。


文件位置速查

组件 关键文件
Code-Server /data/code/code-server/config.yaml
Code-Server /etc/default/code
Code-Server /etc/systemd/system/code-server.service
JupyterLab /data/jupyter/jupyter_config.py
JupyterLab /etc/default/jupyter
JupyterLab /etc/systemd/system/jupyter.service
Claude Code ~/.claude.json / ~/.claude/settings.json

故障排查

端口检查:

ss -tlnp | grep 8443
ss -tlnp | grep 8888

Nginx 入口:

nginx -t
systemctl status nginx

16.5 - 监控告警

VIBE 模块监控说明,重点为 Claude Code 可观测性。

VIBE 的监控主要集中在 Claude Code 的 OpenTelemetry 数据。 Code-Server 与 JupyterLab 本身不暴露 Prometheus 指标,可通过 systemd 与日志进行健康检查。


Claude Code 可观测性

VIBE 在 ~/.claude/settings.json 中写入默认 OpenTelemetry 环境变量:

{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "OTEL_METRICS_EXPORTER": "otlp",
    "OTEL_LOGS_EXPORTER": "otlp",
    "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": "http/protobuf",
    "OTEL_EXPORTER_OTLP_LOGS_PROTOCOL": "http/protobuf",
    "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "http://127.0.0.1:8428/opentelemetry/v1/metrics",
    "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": "http://127.0.0.1:9428/insert/opentelemetry/v1/logs",
    "OTEL_RESOURCE_ATTRIBUTES": "ip=<host>,job=claude"
  }
}

claude_env 会与上述默认配置合并,可用于配置 API Key 或替换模型端点。


Grafana Dashboard

Grafana 默认包含 claude-code Dashboard:

  • Portal 入口:https://<domain>/ui/d/claude-code
  • 直接访问:http://<ip>:3000/d/claude-code

运行状态检查

systemctl status code-server
systemctl status jupyter
journalctl -u code-server -f
journalctl -u jupyter -f

端口检查:

ss -tlnp | grep 8443
ss -tlnp | grep 8888

Claude 日志查询

通过 VictoriaLogs:

curl -G 'http://127.0.0.1:9428/select/logsql/query' \
  --data-urlencode 'query=job:claude'

16.6 - 常见问题

VIBE 模块常见问题解答。

部署问题

code-server 软件包找不到

确认已部署 NODE 与仓库配置:

yum repolist    # EL
apt update      # Debian/Ubuntu
./infra.yml -t repo

JupyterLab 安装失败

jupyter_venv 必须存在:

uv venv /data/venv
./vibe.yml -l <host> -t jupyter

访问问题

无法访问 /code//jupyter/

  1. 检查服务状态
  2. 检查端口监听
  3. 检查 Nginx 配置
systemctl status code-server
systemctl status jupyter
ss -tlnp | grep 8443
ss -tlnp | grep 8888
nginx -t

WebSocket 连接失败

确保 Nginx 配置启用 WebSocket(默认已配置)。 若使用自定义 infra_portal,需配置 websocket: true


密码与 Token

修改 Code-Server 密码

./vibe.yml -l <host> -e code_password='NewPass' -t code_config,code_launch

修改 JupyterLab Token

./vibe.yml -l <host> -e jupyter_password='NewToken' -t jupyter_config
ssh <host> sudo systemctl restart jupyter

Claude Code

CLI 找不到命令

先检查 claude_install 是否完成:

which claude
npm list -g --depth=0 | grep '@anthropic-ai/claude-code'
./vibe.yml -l <host> -t claude_install

如果你禁用了 claude_enabled,可手工安装:

npm install -g @anthropic-ai/claude-code

需要替换 npm 包时,可通过 claude_package 指定。

Codex CLI 找不到命令

which codex
npm list -g --depth=0 | grep '@openai/codex'
./vibe.yml -l <host> -t codex_install

确认 codex_enabled: true。VIBE 仅安装 Codex CLI,不负责生成 Codex 配置。

API Key 未配置

export ANTHROPIC_API_KEY=sk-ant-xxx
# 或配置到 claude_env

监控数据不显示

检查本地 VictoriaMetrics/VictoriaLogs:

curl http://127.0.0.1:8428/api/v1/status/buildinfo
curl http://127.0.0.1:9428/select/logsql/stats_query

确保 ~/.claude/settings.json 中 OTEL 端点正确。


扩展与插件

Code-Server 扩展安装失败

  • 检查网络
  • 尝试切换 code_gallery
  • 或手动安装 VSIX
code-server --install-extension /path/to/extension.vsix

JupyterLab 扩展安装失败

source /data/venv/bin/activate
pip install jupyterlab-git
systemctl restart jupyter

17 - 模块:KAFKA

使用 Pigsty 部署、保护与监控 Apache Kafka 4.1+ 动态 KRaft 集群。

Kafka 是一个分布式事件流平台。Pigsty 的 KAFKA 模块使用 RPM/DEB 软件包,在纳管节点上部署 Apache Kafka 4.1+ 动态 KRaft 集群,并统一管理安全、资源、生命周期与可观测性。

当前状态:Beta 模块

当前 Kafka 模块处于 Beta 状态。用于严肃生产环境前请务必充分测试,确保满足业务需求。 包括动态 KRaft、严格滚动、TLS/SCRAM/ACL、声明式 Topic/User、凭据与证书轮换,以及完整监控链路。


模块能力

KAFKA 模块当前提供:

  • 原生动态 KRaft:不安装 ZooKeeper,也不渲染静态 controller.quorum.voters
  • 三种原生角色 combined / broker / controller,支持复合与控制面/数据面分离拓扑
  • 新集群随机生成 Cluster ID 与 Controller Directory ID,由最小 Bootstrap Manifest 冻结身份,冲突时失败关闭
  • 按实时健康状态自动选路:冷启动/修复、Broker 串行准入、Controller 动态加入或严格单节点滚动
  • 滚动前后检查 Controller 多数派与 Voter 追平、Offline Partition、Under Min ISR 与 ISR 追平
  • 成员退役与故障节点替换由剧本编排:kafka-rm.yml 真子集退役(含死节点),三条命令完成补换
  • 两种安全档位:plaintext 与生产 scram(TLS、SCRAM-SHA-512、Controller mTLS、ACL 与默认拒绝授权)
  • 声明式收敛 Topic、用户凭据、ACL 与 Quota,不隐式删除业务 Topic;内部凭据与证书支持保护性轮换
  • 完整可观测性:JMX 与协议双 Exporter、19 条 Recording Rule、15 条告警规则、4 个 Grafana Dashboard、日志入 VictoriaLogs

模块架构

KAFKA 模块依赖 NODE 完成节点纳管、仓库与基础监控,依赖 INFRA 提供 VictoriaMetrics、VictoriaLogs、Grafana 与 Alertmanager。

flowchart LR
    admin["Pigsty 管理节点"] -->|"kafka.yml / exact cluster"| kafka["Kafka 4.1+ / 动态 KRaft"]
    kafka --> jmx["每个 Kafka JVM / JMX :9404"]
    kafka --> exporter["最多两个 Broker / kafka_exporter :9308"]
    kafka --> journal["Journald"]
    jmx --> vm["VictoriaMetrics"]
    exporter --> vm
    journal --> vector["Vector"] --> vl["VictoriaLogs"]
    vm --> grafana["Grafana"]
    vl --> grafana
    vm --> alert["Alertmanager"]

    style kafka fill:#70C1B3,stroke:#4f968b,color:#fff
    style vm fill:#E66B7A,stroke:#b84e5c,color:#fff
    style vl fill:#C98367,stroke:#9e634e,color:#fff
    style grafana fill:#F29C64,stroke:#c77845,color:#fff

每个 Kafka JVM 都注入 JMX Exporter 并注册为 job=kafka。协议型 kafka_exporter 只在按 kafka_seq 排序后的前两个 Broker-capable 节点运行;单 Broker 集群只运行一个,纯 Controller 不运行。它们返回的是同一逻辑集群视图,Recording Rule 会先去重再聚合。


文档导航

文档 内容
快速上手 从单节点到三节点安全集群、客户端接入、参数修改与上线检查
集群配置 拓扑、动态 KRaft、网络、存储、安全与资源声明
参数参考 15 项持久公开参数及临时运维变量
日常管理 状态检查、Topic、消息、Consumer Group 与拓扑变更
预置剧本 kafka.yml 生命周期、任务标签、轮换与清理保护
监控告警 指标链路、Dashboard、日志查询与告警规则
指标定义 JMX、协议 Exporter 与 Recording Rule 指标字典
常见问题 角色、身份、安全、Exporter 与扩缩容答疑

第一次使用

快速上手 提供一条从零开始、由浅入深的完整路径:单节点开发集群 → 三节点 TLS/SCRAM/ACL 安全集群 → 应用客户端接入 → 参数与资源变更 → 上线检查。

如果您已经熟悉 Kafka 与 Pigsty,可以直接进入 集群配置参数参考


默认端口

端口 服务 部署范围 plaintext scram
9092 Kafka Broker Broker-capable 节点 PLAINTEXT SASL_SSL + SCRAM-SHA-512
9093 KRaft Controller Controller-capable 节点 PLAINTEXT 双向 TLS
9308 kafka_exporter 最多两个 Broker-capable 节点 HTTP 指标 HTTP 指标,后端使用 TLS/SCRAM
9404 JMX Exporter 所有 Kafka 节点 HTTP 指标 HTTP 指标

四个端口必须彼此不同,均可通过参数调整。JMX 与协议 Exporter 的 HTTP 端口仍应通过防火墙限制在监控网络内。


当前边界

当前角色提供的是 Kafka 核心部署基线,不替代完整的流平台或托管服务。下列能力仍需显式运行手册或独立组件:

  • Broker 扩容后的既有 Partition Reassignment 与副本再均衡(成员的加入/退役/替换已由剧本编排,数据搬迁仍需显式计划)
  • 扩容后提升冻结的 default.replication.factor:Kafka 4.3 需要显式数据迁移与静态配置维护窗口
  • 已有 Topic 的副本因子变更、Topic 删除与用户删除
  • 已格式化集群从 plaintext 在线迁移到 scram
  • Kafka 版本升级、Feature Level 终结、数据备份、恢复与灾难演练
  • 多 Listener、NAT/公网地址、同一 Broker 多客户端网络、Tiered Storage
  • Kafka Connect、Schema Registry、MirrorMaker 2、Cruise Control 与 Web UI

这些边界应在生产方案、审批流程与演练中明确记录,不能用普通清单重跑代替。

17.1 - 快速上手

从零部署单节点与三节点 Kafka,完成安全接入、参数调整和上线检查。

本教程从一个最小单节点集群开始,完成 Topic 创建与消息读写;随后部署一套独立的三节点安全集群,配置应用用户、ACL、Quota 和生产 Topic;最后演示核心参数修改、客户端接入、监控验证与上线检查。

教程范围

这里的“从零开始”是指从尚未部署 Kafka 开始。您需要先有一套可用的 Pigsty 管理节点,并已部署基础 INFRA 服务;如果还没有,请先完成 Pigsty 快速安装。目标节点需要 SSH/Sudo 权限,并可被 NODE 模块纳管。


学习路径

阶段 目标 最终结果
1 部署单节点开发集群 1 个 combined 节点、PLAINTEXT、RF=1 Topic、CLI 读写
2 部署三节点安全 HA 演示基线 3 个 combined 节点、动态 KRaft、TLS/SCRAM/ACL、RF=3/minISR=2
3 接入应用客户端 使用应用 Principal、Pigsty CA 与 SASL_SSL 生产/消费
4 修改核心参数 演示 Heap、Broker 参数、Topic Partition/保留和安全滚动
5 上线验收 检查 Quorum、ISR、端到端读写、监控、容量与运行手册
两个示例是独立集群

下面的 kf-devkf-main 是两套独立新集群。如果确有需要,也可以给单节点 kf-dev 声明两个新的 combined 节点后重跑 ./kafka.yml -l kf-dev,角色会逐个完成格式化、Observer 追平与 add-controller 提升,把它原地扩成三 Controller 集群——但演示环境仍建议直接建新集群,扩容语义详见 扩容集群


开始前准备

以下命令默认在 Pigsty 管理节点的项目目录执行:

cd ~/pigsty

开始前确认:

  • pigsty.yml 是当前环境的配置源,先备份并审阅现有内容;
  • Kafka 节点的 inventory_hostname 可以被所有 Kafka 成员和客户端直接解析、路由;
  • 管理节点与 Kafka 节点时间同步;
  • 9092909393089404 没有端口冲突;
  • /data/kafka 对应专用数据盘或专用目录,且没有混放其他数据;
  • 每次 kafka.yml 都使用 -l 精确选择同一 Kafka 集群的全部成员;
  • 真实变更前先执行 --check,审阅输出并取得变更批准。

配置清单必须保留 all.children 层级。下面的组应合并到现有 pigsty.yml,不要用示例覆盖已有的 all.varsinfraetcdpgsql 等配置。


一、部署单节点 Kafka

1. 定义集群

将以下 kf-dev 组加入 all.children。该节点省略 kafka_role,因此使用默认 combined,同时承担 Broker 与 Controller:

all:
  children:
    # 现有 infra、etcd、pgsql 等分组继续保留

    kf-dev:
      hosts:
        10.10.10.10: { kafka_seq: 1 }
      vars:
        kafka_cluster: kf-dev
        kafka_data: /data/kafka
        kafka_security: plaintext
        kafka_topics:
          - name: quickstart.events
            partitions: 1
            replication_factor: 1
            config:
              retention.ms: 86400000   # 1 天,仅用于教程

这个配置会得到:

  • 一个随机 Cluster ID;
  • 一个动态 KRaft combined 节点;
  • 默认 RF=1、minISR=1;
  • 一个名为 quickstart.events 的单 Partition Topic;
  • JMX Exporter :9404 与一个协议 Exporter :9308

plaintext 没有传输加密、认证和 ACL,只能用于本机开发或可信隔离网络。

2. 纳管节点

如果该主机尚未完成 NODE 初始化,先执行检查模式:

./node.yml --check -l kf-dev

审阅结果并取得批准后再纳管节点:

./node.yml -l kf-dev

已经由 Pigsty 纳管、软件仓库和时间同步均正常的节点可以跳过这一步。NODE 的完整准备与日常管理见 节点管理

3. 部署 Kafka

先对完整集群执行检查:

./kafka.yml --check -l kf-dev

确认目标确实只有 kf-dev 的完整成员,审阅数据路径、软件包、端口与配置变化后执行:

./kafka.yml -l kf-dev

角色会安装 Java 与 kafka-stack、生成随机身份和 Bootstrap Manifest、格式化 KRaft 存储、启动服务、创建 Topic,并注册监控目标。

4. 验证服务与 Quorum

登录 Kafka 节点,检查服务:

systemctl is-active kafka kafka_exporter
journalctl -u kafka --since '-10 min' --no-pager

使用角色自有健康检查:

sudo -u kafka /usr/local/bin/pigsty-kafka-health cluster \
  --bootstrap-server 10.10.10.10:9092 \
  --command-config /etc/kafka/admin.properties

返回 JSON 中应有 "healthy": true。继续检查动态 Quorum 与 Topic:

/opt/kafka/bin/kafka-metadata-quorum.sh \
  --bootstrap-server 10.10.10.10:9092 \
  --command-config /etc/kafka/admin.properties \
  describe --status

/opt/kafka/bin/kafka-topics.sh \
  --bootstrap-server 10.10.10.10:9092 \
  --command-config /etc/kafka/admin.properties \
  --describe --topic quickstart.events

应看到有效 LeaderId、包含本节点的 CurrentVoters,以及 RF=1、ISR=1 的 quickstart.events

5. 生产与消费消息

启动 Console Producer:

/opt/kafka/bin/kafka-console-producer.sh \
  --bootstrap-server 10.10.10.10:9092 \
  --command-config /etc/kafka/admin.properties \
  --topic quickstart.events

输入几行消息后按 Ctrl-D 结束。在另一个终端消费:

/opt/kafka/bin/kafka-console-consumer.sh \
  --bootstrap-server 10.10.10.10:9092 \
  --command-config /etc/kafka/admin.properties \
  --topic quickstart.events \
  --group quickstart.demo \
  --from-beginning

到这里,单节点部署、Topic 收敛和消息读写已经完成。进一步的状态检查见 日常管理


二、部署三节点安全 HA 演示基线

三节点示例是一套全新的 kf-main 集群,使用三个 combined 节点。它可以容忍一个 Controller 故障;业务 Topic 使用 RF=3/minISR=2,并启用 scram 生产安全档位。

1. 定义安全集群与资源

将以下组加入现有 all.children

all:
  children:
    # 现有分组继续保留

    kf-main:
      hosts:
        10.10.10.11: { kafka_seq: 1 }
        10.10.10.12: { kafka_seq: 2 }
        10.10.10.13: { kafka_seq: 3 }
      vars:
        kafka_cluster: kf-main
        kafka_data: /data/kafka
        kafka_heap_opts: '-Xms4G -Xmx4G'
        kafka_security: scram

        kafka_parameters:
          num.partitions: 12
          num.network.threads: 6
          num.io.threads: 16
          log.retention.hours: 168
          log.segment.bytes: 1073741824

        kafka_users:
          - name: quickstart-app
            password: "{{ vault_kafka_quickstart_password }}"
            acls:
              - resource: topic
                name: quickstart.
                pattern: prefixed
                operations: [Read, Write, Describe]
              - resource: group
                name: quickstart.
                pattern: prefixed
                operations: [Read]
              - resource: cluster
                name: kafka-cluster
                operations: [Describe, IdempotentWrite]
            quota:
              producer_byte_rate: 10485760
              consumer_byte_rate: 20971520

        kafka_topics:
          - name: quickstart.events
            partitions: 12
            replication_factor: 3
            config:
              min.insync.replicas: 2
              cleanup.policy: delete
              retention.ms: 604800000

vault_kafka_quickstart_password 必须由现有的 Ansible Vault、KMS 或其他秘密注入机制提供,至少 12 个字符。不要把真实密码直接提交到 Git、日志或工单。

这个配置的关键语义:

  • 三个节点全部省略 kafka_role,因此一致使用 combined
  • 新集群直接 Bootstrap 为动态 KRaft;
  • scram 同时启用节点 TLS、Controller mTLS、SCRAM-SHA-512、ACL 和默认拒绝;
  • 三 Broker 初始复制策略自动派生为 RF=3、minISR=2;
  • quickstart.events 显式创建 12 个 Partition、3 副本;
  • quickstart-app 可读写 quickstart.* Topic、读取 quickstart.* Group,并可使用幂等 Producer;
  • 最多两个 Broker 运行 kafka_exporter,三个 Kafka JVM 都运行 JMX Exporter。

如果三个 Broker 确实位于不同故障域,可以在 全部 节点上分别增加 kafka_rack: az-a/az-b/az-c。不要用虚构 Rack 标签制造不存在的容灾保证,详细规则见 集群配置:Rack

2. 纳管并部署

如果节点尚未纳管:

./node.yml --check -l kf-main
./node.yml -l kf-main

部署 Kafka 时必须选择全部三个成员:

./kafka.yml --check -l kf-main
./kafka.yml -l kf-main

不能只 -l 10.10.10.11:每个被选中的集群必须完整,部分选择会被拒绝。同时选择多个完整集群(-l kf-dev,kf-main)或不加 -l 裸跑全部集群则是允许的。

3. 验证三节点健康

从管理节点检查三个 Kafka 服务:

ansible kf-main -b -m command -a 'systemctl is-active kafka'

在任一 Broker 上执行完整健康检查:

sudo -u kafka /usr/local/bin/pigsty-kafka-health cluster \
  --bootstrap-server 10.10.10.11:9092 \
  --command-config /etc/kafka/admin.properties

查询 quorum 和 Topic:

/opt/kafka/bin/kafka-metadata-quorum.sh \
  --bootstrap-server 10.10.10.11:9092 \
  --command-config /etc/kafka/admin.properties \
  describe --status

/opt/kafka/bin/kafka-topics.sh \
  --bootstrap-server 10.10.10.11:9092 \
  --command-config /etc/kafka/admin.properties \
  --describe --topic quickstart.events

上线前应看到:一个 Active Controller、三个 Current Voters、三个可用 Broker;所有 quickstart.events Partition 均有三副本、ISR=3,没有 Offline、Under Replicated 或 Under Min ISR Partition。


三、接入应用客户端

1. 分发 CA 公钥证书

将管理节点上的公共 CA 证书安全复制到应用主机:

files/pki/ca/ca.crt  ->  /etc/kafka-client/pigsty-ca.crt

ca.crt 是可以分发的公钥证书。绝不要复制、暴露或分发 files/pki/ca/ca.key 应用主机上的 CA 文件建议由 root 管理并设为只读。已被 Pigsty 纳管的应用主机无需复制:NODE 模块已把同一 CA 安装在 /etc/pki/ca.crt,客户端可直接引用。

2. 创建客户端配置

在应用主机创建 /etc/kafka-client/client.properties

bootstrap.servers=10.10.10.11:9092,10.10.10.12:9092,10.10.10.13:9092

security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required username="quickstart-app" password="<secret-from-vault>";

ssl.truststore.type=PEM
ssl.truststore.location=/etc/kafka-client/pigsty-ca.crt
ssl.endpoint.identification.algorithm=https

Kafka Java 客户端支持 SASL_SSL + SCRAM,并支持 PEM Truststore。实际应用应在运行时从 Secret Manager 注入密码,而不是把包含密码的文件提交到仓库。完整字段见 Kafka 4.3 SASL/SCRAMProducer 配置

3. 为什么应用应直连多个 Broker

Kafka 客户端本身就具备集群感知能力。bootstrap.servers 只用于取得初始元数据;连接成功后,客户端根据元数据直接连接各 Partition 的 Leader Broker,并在 Leader 变化后刷新路由。因此生产环境的常规做法是:

  • bootstrap.servers 中配置至少两个、通常三个位于不同故障域的 Broker 地址;
  • 放通应用到 所有 Broker9092,并保证 Broker 宣告的 inventory_hostname 可解析、可路由;
  • 让 Producer/Consumer 使用 Kafka 客户端自身的重试、元数据刷新、幂等与 Consumer Group 协议;
  • 不把 HAProxy、Keepalived VIP、四层 LB 或七层反向代理放在 Kafka 数据面前方。

单个 VIP/LB 既不能替代元数据中的 Broker 地址,也不能把一个连接透明转发到正确的 Partition Leader,只会增加长连接状态、故障定位与容量规划的复杂度。若平台必须提供统一发现入口,DNS 名称或 TCP LB 可以只承担 bootstrap,但 advertised.listeners 仍必须返回客户端可直达的每个 Broker 地址,应用也不能只获准访问 LB。跨 NAT、公网、Kubernetes 或多网络场景需要为每个 Broker 设计独立的外部可达地址与额外 Listener;当前模块固定宣告清单地址,不支持这类映射。

4. 用应用身份验证读写

在安装了 Kafka 4.3 CLI 的应用主机上执行:

kafka-console-producer.sh \
  --bootstrap-server 10.10.10.11:9092,10.10.10.12:9092,10.10.10.13:9092 \
  --command-config /etc/kafka-client/client.properties \
  --topic quickstart.events

消费时使用 ACL 允许的 Group 前缀:

kafka-console-consumer.sh \
  --bootstrap-server 10.10.10.11:9092,10.10.10.12:9092,10.10.10.13:9092 \
  --command-config /etc/kafka-client/client.properties \
  --topic quickstart.events \
  --group quickstart.demo \
  --from-beginning

生产应用还应显式评审客户端语义:

客户端配置 建议起点 说明
acks all 与 RF=3/minISR=2 配合,避免只等待 Leader
enable.idempotence true 降低重试导致重复写入的风险,需要 IdempotentWrite ACL
group.id 独立稳定名称 不同业务/消费语义不要复用 Group
Offset 提交 按业务选择 自动提交简单;手动提交更容易绑定业务处理结果
client.id 可识别实例名 便于日志、Quota 与客户端诊断

客户端 acks、重试、幂等、批量、压缩和 Offset 策略属于应用配置,不应写入 Broker 的 kafka_parameters


四、修改核心参数

Kafka 的持久意图始终修改 pigsty.yml,不要直接编辑 /etc/kafka/server.properties。常见意图对应关系:

目标 参数 行为
调整 JVM Heap kafka_heap_opts 静态变化,健康集群进入严格单节点滚动
调整线程、保留、Segment kafka_parameters 非角色自有 Broker 参数;静态变化需要滚动
调整 Topic Partition/保留 kafka_topics 在线资源收敛;Partition 只增不减
调整应用密码/ACL/Quota kafka_users 在线资源收敛;密码由秘密系统提供
声明故障域 kafka_rack 所有 Broker-capable 节点全有或全无;变化会滚动但不搬迁数据
选择安全档位 kafka_security 只能在新集群 Bootstrap 时决定,不能普通重跑在线切换

示例:调整 Heap 与 Broker 默认参数

假设压测后决定将 Heap 调整为 6G、提高线程数,并把新 Topic 的默认保留时间改成 72 小时:

kf-main:
  vars:
    kafka_cluster: kf-main
    kafka_heap_opts: '-Xms6G -Xmx6G'
    kafka_parameters:
      num.partitions: 12
      num.network.threads: 8
      num.io.threads: 24
      log.retention.hours: 72
      log.segment.bytes: 1073741824

不要照抄 6G/8/24;这些值必须由 CPU、内存、连接数、消息大小、Partition 数、磁盘和 Page Cache 压测决定。

示例:增加 Partition 并缩短 Topic 保留

quickstart.events 从 12 个 Partition 增加到 24,并把保留时间改成三天:

kafka_topics:
  - name: quickstart.events
    partitions: 24
    replication_factor: 3
    config:
      min.insync.replicas: 2
      cleanup.policy: delete
      retention.ms: 259200000

Partition 不能减少。replication_factor 与现场不一致时,角色会拒绝普通收敛并要求显式 Partition Reassignment;不会自动搬迁既有副本。

应用变更

无论修改静态参数还是动态资源,都运行完整状态机:

./kafka.yml --check -l kf-main
./kafka.yml -l kf-main

不要只运行 -t kafka_config。角色会自动判断:静态变化执行严格逐节点滚动;只修改 Topic/User 等动态资源时不重启 Kafka。

以下键属于角色自身,不能放入 kafka_parameters

kafka_parameters:
  min.insync.replicas: 2          # 错误:角色拥有
  default.replication.factor: 3   # 错误:角色拥有
  listeners: ...                  # 错误:角色拥有

全部 15 项公开参数、默认值和保留键见 参数参考


五、上线前关键检查

拓扑与数据安全

  • 生产至少使用三个 Broker,并使用奇数 Controller;关键/大型集群考虑 3 Controller + N Broker 分离拓扑;
  • Topic RF、minISR 与生产者 acks 形成一致的故障模型;
  • kafka_rack 只表达真实故障域,且副本放置已经核验;
  • 数据盘容量、吞吐、延迟、保留时间、峰值写入和恢复时间已经压测;
  • 新 Broker 加入后有显式 Reassignment 计划,现有 Topic RF 不会自动提高;
  • 已明确 Kafka 数据备份/重建与灾难恢复流程,并演练过 故障节点三步替换 与成员退役。

安全与网络

  • 新生产集群从 Bootstrap 起就使用 kafka_security: scram
  • 应用密码由 Vault/KMS/Secret Manager 注入,未进入 Git 或日志;
  • 只向客户端分发 CA 公钥证书,不分发 CA 私钥;
  • 客户端可以解析并直达所有 Broker 的 inventory_hostname
  • 9092/9093 只向必要主体开放,9308/9404 只向监控网络开放;
  • 已建立应用 Principal、Topic/Group/Cluster ACL 与 Quota 审核清单;
  • 已安排内部凭据和证书的 受保护轮换

运行与监控

  • /usr/local/bin/pigsty-kafka-health cluster 返回健康;
  • 动态 Quorum 只有一个 Leader,所有预期 Controller 都在 Current Voters;
  • 没有 Offline、Under Replicated 或 Under Min ISR Partition;
  • 使用真实应用网络、真实 Principal 完成生产与消费验证;
  • Kafka OverviewKafka InstanceKafka TopicKafka Consumer 数据正常;
  • 告警路由、日志检索、容量阈值、值班责任和回退条件已经确认;
  • 升级、Feature Level、Topic 删除、用户删除与集群下线均有独立审批流程。

详细告警与 PromQL 见 监控告警,指标语义见 指标定义


文档索引与下一步

建议按以下路径继续阅读:

您接下来要做什么 对应文档
规划 combined 或 Controller/Broker 分离拓扑、网络、Rack、存储与安全 集群配置
查找 15 项公开参数、默认值、Schema 和保留键 参数参考
查看 Quorum、Topic、用户、消息、Consumer Group 与扩缩容操作 日常管理
理解 kafka.yml 生命周期、严格滚动、轮换与集群下线 预置剧本
使用 Dashboard、告警、PromQL 和 VictoriaLogs 监控告警
理解每一项 JMX/Exporter/Recording Rule 指标 指标定义
排查身份冲突、连接、SCRAM、Exporter、Lag 与扩缩容问题 常见问题
回到模块能力、默认端口与边界总览 Kafka 模块首页

一条推荐阅读链路是:快速上手 → 集群配置 → 参数参考 → 日常管理 → 预置剧本 → 监控告警 → 常见问题

17.2 - 集群配置

规划 Kafka 动态 KRaft 拓扑、身份、网络、存储、安全与声明式资源。

KAFKA 模块使用 15 项持久公开参数表达集群意图,其余拓扑、监听器、存储子目录、复制安全、授权与 Exporter 放置由角色统一推导。首次部署建议先完成 快速上手;完整字段见 参数参考

先规划,后格式化

kafka_seq 会写入 KRaft node.id;新集群的随机 Cluster ID、初始 Controller Identity、安全模式与初始复制策略会写入 Bootstrap Manifest。存储格式化后,不要随意修改身份、安全模式或 Controller 集合。角色会验证现场与 Manifest 并在冲突时失败关闭,不会自动覆盖或重新格式化数据。


部署前检查

填写清单前至少确认:

  • 目标主机已由 NODE 纳管,软件仓库可用,inventory_hostname 可被所有 Kafka 成员与客户端直接路由
  • 一次操作将用 -l 精确选择同一 kafka_cluster 的全部成员,而不是单节点、部分成员或多个集群
  • kafka_seq 在集群内唯一,Controller 为奇数,Broker 数量、故障域与容量目标匹配
  • 9092909393089404 互不冲突,Infra 节点可以访问两个指标端口
  • kafka_data 对应专用文件系统,并已按保留时间、写入峰值、复制流量、恢复时间与增长余量规划
  • 生产使用 kafka_security: scram;节点与管理端时间同步,Pigsty CA 可用,应用密码来自 Vault 等秘密来源
  • Topic 的 Partition、副本、min.insync.replicas、保留策略,以及客户端 acks、重试与消费恢复策略已经评审
  • 扩缩容、Partition Reassignment、升级、备份、恢复与 Controller 成员变更有独立运行手册

角色与拓扑

kafka_role 只接受三个值:

角色 Kafka process.roles Broker 端口 Controller 端口 JMX kafka_exporter
combined broker,controller 可被选择
broker broker 可被选择
controller controller

kafka_role 是全有或全无的:集群成员要么全部省略(一致使用 combined),要么全部显式声明——混写会在身份预检阶段被拒绝。集群必须至少包含一个 Controller-capable 节点和一个 Broker-capable 节点;偶数 Controller 会给出警告,生产通常使用 3 个 Controller。


单节点开发集群

单节点同时承担 Broker 与 Controller,无法容忍节点故障,只适合开发、测试与功能验证:

kf-dev:
  hosts:
    10.10.10.10: { kafka_seq: 1 }
  vars:
    kafka_cluster: kf-dev

角色会从初始 Broker 数量推导 RF=1、minISR=1。不要把单节点拓扑或默认 plaintext 安全模式直接用于生产。


三节点复合部署

三个节点都承担 Broker 与 Controller,是紧凑的生产起点。省略全部角色字段即可使用默认 combined

kf-main:
  hosts:
    10.10.10.11: { kafka_seq: 1 }
    10.10.10.12: { kafka_seq: 2 }
    10.10.10.13: { kafka_seq: 3 }
  vars:
    kafka_cluster: kf-main
    kafka_heap_opts: '-Xms4G -Xmx4G'
    kafka_security: scram
    kafka_parameters:
      num.partitions: 3
      num.network.threads: 6
      num.io.threads: 16
    kafka_topics:
      - name: order.events
        partitions: 12
        replication_factor: 3
        config:
          min.insync.replicas: 2
          cleanup.policy: delete

初始三个 Broker 会自动得到 RF=3、minISR=2 的角色自有复制策略,无需也不允许在 kafka_parameters 中覆盖内部 Topic RF、default.replication.factormin.insync.replicas。示例中的 4G Heap 只是写法示意;生产应通过压测平衡 JVM Heap、操作系统 Page Cache 与同机其他进程。


Controller 与 Broker 分离

关键或较大集群可以把控制面与数据面分离。因为存在显式角色,所有成员都必须声明角色:

kf-main:
  hosts:
    10.10.10.11: { kafka_seq: 1, kafka_role: controller }
    10.10.10.12: { kafka_seq: 2, kafka_role: controller }
    10.10.10.13: { kafka_seq: 3, kafka_role: controller }
    10.10.10.21: { kafka_seq: 4, kafka_role: broker }
    10.10.10.22: { kafka_seq: 5, kafka_role: broker }
    10.10.10.23: { kafka_seq: 6, kafka_role: broker }
  vars:
    kafka_cluster: kf-main
    kafka_security: scram

纯 Controller 不监听 9092,也不运行协议 Exporter;它仍通过 JMX 暴露 KRaft 与 JVM 状态。最多两个 kafka_exporter 会放在 kafka_seq 最小的 Broker-capable 节点上。


动态 KRaft 与 Bootstrap Manifest

新集群直接使用动态 Quorum:所有节点渲染 controller.quorum.bootstrap.servers,不会生成静态 controller.quorum.voters。首次格式化时:

  • Cluster ID 随机生成,不由集群名哈希;
  • 初始 Controller 的 Directory ID 随机生成并冻结;
  • 每个节点显式使用 --initial-controllers--no-initial-controllers 格式化模式;
  • 首次 Bootstrap 启动后,角色等待动态 Quorum 选出 Leader,并校验每个初始 Controller 的 Directory ID 都已进入现场 Quorum。

Bootstrap-only 事实保存在每个集群成员节点上:

/etc/kafka/manifest.yml

scram 集群的每个成员还持有 /etc/kafka/secrets.yml。管理节点不保存任何 Kafka 状态:Manifest 与 Secret 在每次运行时从任一成员副本解析,签发的节点证书放在共享 PKI 树 files/pki/kafka/(CSR 在 files/pki/csr/),丢失时直接用 Pigsty CA 重签。Manifest 只记录集群身份、初始 Controller Identity、安全模式和初始 RF/minISR。活集群始终是运行事实权威:

  • Manifest 与现场身份或安全模式冲突时,普通剧本失败关闭;
  • 旧 Manifest 存在但全部数据盘为空时拒绝复活旧集群;
  • 所有成员都找不到 Manifest 副本而存储已格式化时,失败关闭并提示先在任一成员上恢复该文件;
  • 已格式化的 scram 集群在所有成员都没有 Secret 副本时同样失败关闭。

Manifest 是集群的"出生证明":首次 Commission 之后,成员关系以 Raft 现场状态为权威。此后在清单中新增的 Combined/Controller 节点会由剧本编排加入动态 Quorum(全新格式化 → Observer 追平 → add-controller 提升),退役则由 kafka-rm.yml 真子集选择完成(自动 remove-controller 与 Broker 注销),详见 扩容集群缩容集群


身份参数

身份 来源 示例 约束
集群名 kafka_cluster kf-main 字母或数字开头,只含字母、数字、下划线和连字符
节点号 kafka_seq 1 非负整数,同一集群内唯一
实例名 自动生成 kf-main-1 ${kafka_cluster}-${kafka_seq}
节点角色 kafka_role combined 三种原生角色之一
KRaft Cluster ID Bootstrap 随机生成 22 字符 Kafka UUID kafka_cluster_id 仅作接管/恢复断言

已格式化节点会从 ${kafka_data}/metadata/meta.properties 读取 cluster.idnode.id,并与 Manifest 及清单交叉校验;初始 Controller 的 Directory ID 则在启动后与活 quorum 比对。身份不匹配是保护性失败,不应通过删除 meta.properties 或清空数据绕过。


网络与监听器

角色只公开端口,不公开 bind、advertised address 或 listener map:

参数 默认值 用途
kafka_port 9092 Broker、客户端与 Broker 间通信
kafka_controller_port 9093 KRaft Controller 仲裁
kafka_exporter_port 9308 协议 Exporter HTTP 指标
kafka_jmx_exporter_port 9404 JMX Exporter HTTP 指标

固定监听器约定如下:

  • Broker listener 绑定 0.0.0.0,Controller listener 绑定 inventory_hostname
  • Broker 的 advertised.listeners 使用 inventory_hostname
  • Controller bootstrap 地址也使用 inventory_hostname
  • plaintext:BROKER 与 CONTROLLER 都使用 PLAINTEXT;
  • scram:BROKER 使用 SASL_SSL + SCRAM-SHA-512,CONTROLLER 使用双向 TLS。

因此客户端必须能够解析并直达每一个 Broker 的 inventory_hostname。当前 v1 不支持 NAT、公网映射、同一 Broker 多客户端网络或任意 raw listener 覆盖;这些场景不能通过 kafka_parameters 拼装绕过。

Kafka 的标准接入模型是智能客户端直连 Broker:bootstrap.servers 配置多个种子地址,客户端获取集群元数据后直接连接 Partition Leader。HAProxy、Keepalived VIP、云 LB 不应作为常规 Kafka 数据面入口,因为它们不了解 Kafka 元数据和 Partition Leader,且无法免除客户端访问所有 advertised.listeners 地址的要求。DNS 或 TCP LB 最多作为可选的 bootstrap 发现入口;即使如此,应用网络仍必须直达全部 Broker。详见 快速上手:接入应用客户端

最小网络流向:

来源 目标 端口 用途
Kafka 客户端、其他 Broker 所有 Broker 9092 Produce、Fetch、元数据与 Broker 间通信
所有 Kafka 成员 所有 Controller 9093 KRaft 元数据仲裁
Infra/VictoriaMetrics 所有 Kafka 节点 9404 JVM/Kafka 指标
Infra/VictoriaMetrics 被选择的 Exporter 节点 9308 集群/Topic/Consumer 指标

指标端口为 HTTP,即使 Kafka 使用 scram,也应通过防火墙限制在监控网络内。


存储、Heap 与 Rack

用户只设置根目录:

kafka_data: /data/kafka

角色固定派生 Topic 数据目录 ${kafka_data}/data 与 KRaft 元数据目录 ${kafka_data}/metadatakafka_data 必须是专用绝对路径,不能是 //data/var/etc/opt/usr/home/root/pg

生产规划至少考虑保留时间、消息峰值、复制流量、Partition/Segment 数、磁盘延迟与吞吐、文件描述符、恢复时间、JVM Heap 与 Page Cache。当前角色只生成一个 log.dirs;多盘 JBOD、磁盘替换和自动数据迁移需要独立运行手册。

跨故障域部署可以在所有 Broker-capable 节点上一致声明 kafka_rack

10.10.10.21: { kafka_seq: 4, kafka_role: broker, kafka_rack: az-a }
10.10.10.22: { kafka_seq: 5, kafka_role: broker, kafka_rack: az-b }
10.10.10.23: { kafka_seq: 6, kafka_role: broker, kafka_rack: az-c }

Broker-capable 节点必须全部设置或全部省略 Rack。修改 Rack 会触发安全滚动,但不会自动迁移既有副本。


复制策略

首次 Bootstrap 根据初始 Broker 数量派生:

replication_factor = min(3, broker_count)
min_insync_replicas = max(1, replication_factor - 1)

初始的未来 Topic 默认 RF、内部 Topic RF 与集群 minISR 都会写入 Manifest 并冻结。扩容后:

  • default.replication.factor 保持初建值;Kafka 4.3 不允许通过动态 Broker 配置在线修改它;
  • 已有内部/业务 Topic 的 RF 不会自动提高;
  • 角色不会把“Broker 已加入”报告成“数据已均衡”;
  • RF 变化必须使用经过评审的 kafka-reassign-partitions.sh 计划;提升静态默认值还需要 Controller 高可用或明确维护窗口,并通过完整集群安全滚动生效。

生产者 acks、幂等、重试、批量和压缩属于客户端策略,不是 Kafka Broker 角色参数。


kafka_parameters

kafka_parameters 是唯一的 Broker 参数逃生舱,默认 {},只渲染到 Broker-capable 节点。它适合 num.partitions、线程数、Buffer、保留与 Segment 等非角色自有键。

以下模式由角色拥有,禁止覆盖:

process.roles
node.id
controller.quorum.*
listeners
advertised.listeners
listener.security.protocol.map
inter.broker.listener.name
controller.listener.names
log.dirs
metadata.log.dir
min.insync.replicas
default.replication.factor
offsets.topic.replication.factor
transaction.state.log.replication.factor
transaction.state.log.min.isr
share.coordinator.state.topic.replication.factor
share.coordinator.state.topic.min.isr
broker.rack
authorizer.class.name
super.users
allow.everyone.if.no.acl.found
sasl.*
ssl.*
listener.*

出现任一保留键时,身份预检会在写文件前直接失败。


安全与声明式资源

kafka_security: scram 是一个完整生产档位,而不是一组可任意组合的开关。它自动启用:

  • Pigsty CA 签发的每节点证书;
  • Controller listener 双向 TLS;
  • Broker/client 与 Broker 间 SASL_SSL + SCRAM-SHA-512;
  • StandardAuthorizer、默认拒绝,以及角色自有管理/监控身份;
  • 在协议 Exporter 启动前收敛其最小监控 ACL。

应用资源由两个领域对象声明:

kafka_security: scram
kafka_users:
  - name: order-service
    password: "{{ vault_kafka_order_password }}"
    acls:
      - resource: topic
        name: order.
        pattern: prefixed
        operations: [Read, Write, Describe]
      - resource: group
        name: order.
        pattern: prefixed
        operations: [Read]
    quota:
      producer_byte_rate: 10485760
      consumer_byte_rate: 20971520
kafka_topics:
  - name: order.events
    partitions: 12
    replication_factor: 3
    config:
      min.insync.replicas: 2
      cleanup.policy: delete

资源收敛语义:Topic 创建幂等、Partition 只增加、只更新显式声明的配置;RF 变化会拒绝并提示 Reassignment。声明用户的密码、ACL 与给出的 Quota 字段会幂等收敛。移除 Topic/User 条目不会作为隐式删除流程。

安全模式在 Bootstrap 后不能通过普通剧本切换。内部凭据与证书可以使用 受保护轮换,但 plaintextscram 的在线迁移仍需未来的显式状态机。


软件包与文件布局

角色通过平台映射安装 java-runtimekafka-stack。2026-07-16 验证的载荷为 Kafka 4.3.1、kafka_exporter 1.9.0、JMX Exporter 1.6.0;实际版本仍以目标平台仓库与已安装包为准。

路径 用途
/opt/kafka/ Kafka 程序与 CLI
/etc/kafka/server.properties 角色生成的服务配置
/etc/kafka/admin.properties 角色生成的 Broker 管理通道;CLI 应始终使用
/etc/kafka/controller.properties 角色生成的 Controller 管理通道
/etc/kafka/log4j2.yaml Journald 日志配置
/etc/kafka/jmx_exporter.yml 有界 JMX 指标规则
/etc/kafka/manifest.yml 节点上的 Bootstrap Manifest 权威副本
/etc/kafka/secrets.yml scram 节点上的内部 Secret 副本
/etc/kafka/.pigsty-applied-static.sha256 已证明生效的静态配置指纹,滚动重启的判定依据
/etc/kafka/pki/kafka.pem scram 节点 PEM 私钥与证书;信任锚使用系统 /etc/pki/ca.crt
${kafka_data}/data/ Topic 日志数据
${kafka_data}/metadata/ KRaft 元数据与 meta.properties
files/pki/kafka/ 管理节点上签发的节点证书(<cluster>-<seq>.key/.crt,CSR 在 files/pki/csr/

这些文件由角色管理。持久意图应写入 pigsty.yml,不要在节点上直接编辑生成文件,也不要把密码、私钥或角色自有 Secret 内容复制到清单、日志或工单。

17.3 - 参数参考

KAFKA 模块 15 项持久公开参数与临时受保护运维变量。

KAFKA 角色刻意只公开 15 项持久参数。拓扑、Listener、安全实现、存储子目录、复制安全与 Exporter 放置等细节由角色统一推导,不能作为额外持久变量覆盖。


参数概览

参数 层级 默认值 说明
kafka_cluster 集群 必填 Kafka 集群身份
kafka_seq 实例 必填 集群内唯一 KRaft node.id
kafka_role 实例 combined combinedbrokercontroller
kafka_cluster_id 集群 未设置 接管/恢复断言;新集群随机生成
kafka_data 实例 /data/kafka 角色自有数据根目录
kafka_heap_opts 实例 -Xms1G -Xmx1G Kafka JVM Heap
kafka_port 实例 9092 Broker/client 端口
kafka_controller_port 实例 9093 KRaft Controller 端口
kafka_rack 实例 未设置 Broker 故障域标签
kafka_parameters 集群/实例 {} 非角色自有 Broker 参数
kafka_jmx_exporter_port 实例 9404 JMX Exporter HTTP 端口
kafka_exporter_port 实例 9308 协议 Exporter HTTP 端口
kafka_security 集群 plaintext plaintext 或生产 scram 档位
kafka_users 集群 [] 用户凭据、ACL 与 Quota
kafka_topics 集群 [] 声明式 Topic

kafka_clusterkafka_seq 必须定义;kafka_role 有真实默认值。集群角色要么全部省略,要么全部显式声明。


身份与拓扑

kafka_cluster

必填的集群身份。必须以字母或数字开头,只能包含字母、数字、下划线和连字符:

kafka_cluster: kf-main

它用于发现完整集群成员、生成实例名和定位 Bootstrap Manifest。每次 kafka.yml 生命周期操作必须用精确 -l 选择该集群的全部成员。

kafka_seq

必填的非负整数,在同一 kafka_cluster 中唯一,直接成为 KRaft node.id

10.10.10.11: { kafka_seq: 1 }

实例名派生为 ${kafka_cluster}-${kafka_seq}。节点格式化后不要修改或复用仍有关联数据的序号。

kafka_role

默认 combined,只接受:

Kafka process.roles 语义
combined broker,controller Broker 与 Controller 合设
broker broker 纯 Broker
controller controller 纯 Controller

集群所有成员都省略时一致使用 combined;只要任一成员显式设置,所有成员都必须显式设置。不提供旧角色别名。

kafka_cluster_id

默认未设置,仅用于接管或恢复时断言现有集群身份,必须是 22 字符 Kafka UUID:

kafka_cluster_id: MkU3OEVBNTcwNTJENDM2Qk

普通新建集群不要设置。角色会随机生成 Cluster ID,并写入每个成员的 /etc/kafka/manifest.yml。该参数不会重新标记现有数据;与 Manifest 或 meta.properties 冲突时会失败关闭。

kafka_rack

可选的 Broker 故障域标签,渲染为 broker.rack

10.10.10.21: { kafka_seq: 4, kafka_role: broker, kafka_rack: az-a }

所有 Broker-capable 节点必须全部声明或全部省略。纯 Controller 不使用该值。修改 Rack 属于静态变化,会进入严格滚动,但不会重新分配既有副本。


存储、JVM 与网络

kafka_data

数据根目录,默认 /data/kafka

kafka_data: /data/kafka

角色固定派生 ${kafka_data}/data${kafka_data}/metadata。该路径必须是专用绝对路径,不能是 //data/var/etc/opt/usr/home/root/pgkafka-rm.yml 默认会删除整个根目录,因此不要混放其他服务或业务文件。

kafka_heap_opts

Kafka JVM Heap,默认:

kafka_heap_opts: '-Xms1G -Xmx1G'

生产应根据负载与内存压测设置,通常保持 XmsXmx 相同,并为操作系统 Page Cache 与其他进程留出足够内存。

kafka_port

Broker/client 监听端口,默认 9092,只在 Broker-capable 节点监听。plaintext 模式使用 PLAINTEXT;scram 模式使用 SASL_SSL + SCRAM-SHA-512。

kafka_controller_port

KRaft Controller 监听端口,默认 9093(Kafka KRaft 惯例端口),只在 Controller-capable 节点监听。与其他服务共用节点时请自行确认端口无冲突,角色不会自动检测跨服务端口占用。

四个公开端口必须彼此不同。Broker listener 绑定 0.0.0.0,Controller listener、Broker advertised address 与 Controller bootstrap address 固定使用 inventory_hostname,不另设地址参数。


kafka_parameters

默认 {},是唯一的 Kafka Broker 参数逃生舱,只渲染到 Broker-capable 节点:

kafka_parameters:
  num.partitions: 12
  num.network.threads: 6
  num.io.threads: 16
  log.retention.hours: 168
  log.segment.bytes: 1073741824

以下键或模式由角色拥有,不能通过该映射覆盖:

process.roles
node.id
controller.quorum.*
listeners
advertised.listeners
listener.security.protocol.map
inter.broker.listener.name
controller.listener.names
log.dirs
metadata.log.dir
min.insync.replicas
default.replication.factor
offsets.topic.replication.factor
transaction.state.log.replication.factor
transaction.state.log.min.isr
share.coordinator.state.topic.replication.factor
share.coordinator.state.topic.min.isr
broker.rack
authorizer.class.name
super.users
allow.everyone.if.no.acl.found
sasl.*
ssl.*
listener.*

身份、监听器、安全、存储与复制策略必须保持单一权威;包含保留键时预检会直接失败。


可观测性

kafka_jmx_exporter_port

JMX Exporter HTTP 端口,默认 9404。角色为每个 Kafka JVM 无条件注入 JMX Exporter Java Agent,并注册为 job=kafka;没有单独的开关参数。生命周期健康门禁使用角色自有 Kafka CLI/metadata 通道,不依赖 JMX。Infra 监控节点必须可以访问该端口;端点不因 kafka_security: scram 自动启用 HTTPS,应通过监控网络和防火墙保护。

kafka_exporter_port

协议型 kafka_exporter HTTP 端口,默认 9308。角色只在按 kafka_seq 排序后的前两个 Broker-capable 节点配置、启动与注册;单 Broker 集群只运行一个。监控 Target 文件每次完整运行都会按当前放置刷新,但曾经被选中节点上的旧 Exporter 服务不会被普通剧本自动停止。

Exporter 使用的 Kafka 协议版本、TLS/SCRAM 参数和副本放置均为角色内部约定,没有额外公开开关或 options 参数。


安全与资源

kafka_security

默认 plaintext,只接受:

Broker/client Controller 授权 用途
plaintext PLAINTEXT PLAINTEXT 开发或可信隔离网络
scram SASL_SSL + SCRAM-SHA-512 双向 TLS StandardAuthorizer,默认拒绝 生产安全基线

scram 同时配置 Pigsty CA 签发的节点证书、角色自有管理/监控/内部身份、TLS/SCRAM 与 ACL 启用顺序。安全模式写入 Bootstrap Manifest;集群格式化后,普通重跑不能把 plaintext 切换成 scram,也不能反向切换。

节点证书的有效期沿用 Pigsty 共享的 CA 参数 cert_validity(默认 7300d),KAFKA 模块不提供独立的证书有效期参数。

kafka_users

默认 [],仅允许在 scram 模式声明。集合必须是对象列表,每个对象只接受 namepasswordaclsquota;非对象条目或未知顶层字段会在资源收敛前失败:

kafka_users:
  - name: order-service
    password: "{{ vault_kafka_order_password }}"
    acls:
      - resource: topic
        name: order.
        pattern: prefixed
        operations: [Read, Write, Describe]
      - resource: group
        name: order.
        pattern: prefixed
        operations: [Read]
      - resource: transactional_id
        name: order.
        pattern: prefixed
        operations: [Write, Describe]
    quota:
      producer_byte_rate: 10485760
      consumer_byte_rate: 20971520

约束:

  • name 在列表中唯一;password 必填且至少 12 个字符,应引用秘密管理系统;
  • ACL resourcetopicgrouptransactional_idcluster
  • patternliteral(默认)或 prefixed
  • 操作为 ReadWriteCreateDeleteAlterDescribeClusterActionDescribeConfigsAlterConfigsIdempotentWrite
  • Quota 键为 producer_byte_rateconsumer_byte_raterequest_percentagecontroller_mutation_rate

角色为声明用户收敛 SCRAM 密码、完整 ACL 集合与显式给出的 Quota 字段。移除用户条目不会隐式删除 Principal 或凭据;删除/撤权需要独立受审操作。

kafka_topics

默认 []。集合必须是对象列表,每个对象只接受 namepartitionsreplication_factorconfig;非对象条目或未知顶层字段会在资源收敛前失败:

kafka_topics:
  - name: order.events
    partitions: 12
    replication_factor: 3
    config:
      min.insync.replicas: 2
      cleanup.policy: delete
      retention.ms: 604800000

身份预检只校验 name 在列表中唯一;Partition 数与 RF 的合法性(至少为 1、RF 不超过当前 Broker 数)由 Kafka 在创建时判定,因此这类错误会在资源收敛阶段暴露,而不是在 --check 阶段。收敛语义是:

  • Topic 不存在时幂等创建;
  • Partition 只允许增加,减少会失败;
  • RF 与现场不同时拒绝普通收敛,并要求显式 Reassignment;
  • 只更新 config 中声明的键;
  • 从列表中移除 Topic 永远不会删除 Topic。

临时受保护运维变量

以下变量只通过命令行 -e 用于一次性运维动作,不属于 15 项持久 API,也不应写入 pigsty.yml

动作 剧本 临时变量 保护条件
轮换内部凭据 kafka.yml kafka_rotate_credentials=truekafka_rotate_confirm=<cluster> 健康、全员已格式化的 scram 集群
轮换证书 kafka.yml kafka_rotate_certificates=truekafka_rotate_confirm=<cluster> 健康、全员已格式化的 scram 集群
下线集群 kafka-rm.yml kafka_rm_data(默认 true)、kafka_rm_pkg(默认 false)、kafka_safeguard(默认 false 强制显式 -lkafka_safeguard=true 时中止一切删除

两种轮换动作互斥,且必须以精确完整集群为目标。kafka-rm.yml 默认删除数据目录与节点上的 /etc/kafka 恢复状态;kafka_rm_data=false 会同时保留二者。执行前必须显式确认目标集群与备份/重建意图,命令与完整语义见 预置剧本

kafka_safeguard

仅供 kafka-rm.yml 使用,默认 false。设为 true 时,移除角色会在注销、退群、停服和删除之前直接中止;这是布尔保护开关,不会探测集群是否存活。

kafka_rm_data

仅供 kafka-rm.yml 使用,默认 true。启用时删除整个 kafka_data/etc/kafka;后者包含 Manifest、凭据副本及重新接管保留存储所需的恢复状态。设为 false 会同时保留这两处,但仍会注销监控目标、停止服务并删除运行时集成配置。

kafka_rm_pkg

仅供 kafka-rm.yml 使用,默认 false。设为 true 时卸载平台映射中的 kafka-stack 软件包(Kafka、Kafka Exporter 与 JMX Exporter 载荷);共享的 Java Runtime 不会被卸载。

17.4 - 日常管理

Kafka 集群的状态检查、Topic 与用户管理、配置变更、扩容缩容、故障节点替换与安全轮换。

KAFKA 模块把 Kafka 安装在 /opt/kafka,使用 Systemd 管理服务,并把持久意图保存在 pigsty.yml。节点上的生成文件不应手工修改。

以下 Kafka CLI 示例都使用角色生成的 /etc/kafka/admin.properties。即使当前是 plaintext 也建议始终保留 --command-config:切换到 scram 管理通道时命令结构不变。将 <broker>:9092 替换为可达的 inventory_hostname 与端口。

Console 工具的 –command-config 需要 Kafka 4.2+ CLI

KIP-1147 从 Kafka 4.2 起把所有 CLI 的配置文件参数统一为 --command-config、键值参数统一为 --command-property。节点上 /opt/kafka/bin 的 CLI 由 Pigsty 仓库提供(当前载荷 4.3.x),可直接使用;若从 4.1 或更早的外部 CLI 执行,Console Producer/Consumer 仍须使用旧名 --producer.config / --consumer.config。管理类工具(kafka-topics.shkafka-configs.shkafka-acls.shkafka-consumer-groups.shkafka-metadata-quorum.sh 等)一直使用 --command-config,不受影响。


速查手册

操作 命令 说明
创建集群 ./kafka.yml -l <cls> 创建或收敛 Kafka 集群,裸跑处理全部集群
扩容集群 ./kafka.yml -l <cls> 声明新成员后收敛:Broker 准入,Controller 加入
缩容集群 ./kafka-rm.yml -l <ip> 退役成员:摘除 Voter 条目与 Broker 注册
销毁集群 ./kafka-rm.yml -l <cls> 下线整个集群,默认删除数据
替换故障节点 退役 → 纳管 → 重入 三条命令补换死节点,自动继承副本分配
配置集群 ./kafka.yml -l <cls> 修改清单后在门禁保护下滚动生效
管理 Topic ./kafka.yml -l <cls> 声明式创建 Topic、扩分区、改配置
管理用户 ./kafka.yml -l <cls> 声明式收敛用户、ACL 与 Quota
轮换密钥证书 ./kafka.yml -e kafka_rotate_... 受保护的内部凭据 / 证书轮换

集群定义与参数详见 集群配置,剧本语义详见 预置剧本,监控排障详见 监控告警


状态检查

在任意 Kafka 节点检查服务与最近日志:

systemctl status kafka
systemctl is-enabled kafka
journalctl -u kafka --since '-30 min' --no-pager

协议 Exporter 只在 kafka_seq 最小的至多两个 Broker-capable 节点运行。被选择的节点再检查:

systemctl status kafka_exporter
journalctl -u kafka_exporter --since '-30 min' --no-pager

检查监听器与指标端点:

ss -lntp | grep -E ':9092|:9093|:9308|:9404'
curl -fsS http://<kafka-ip>:9404/metrics | grep -E '^(jmx_scrape_error|kafka_server_raft_state|kafka_server_broker_messages_in_total)'
curl -fsS http://<exporter-ip>:9308/metrics | grep -E '^(kafka_brokers|kafka_topic_partitions)'

kafka_upkafka_exporter_up 是 VictoriaMetrics 侧的记录指标,不一定出现在原始端点。JMX 端点应包含 jmx_scrape_error 0.0、JVM 指标和与节点角色匹配的 kafka_ 指标。


健康检查

角色的生命周期门禁不依赖 JMX,而是通过同一管理通道检查动态 Quorum、不可用 Partition、副本不足与 Under Min ISR:

sudo -u kafka /usr/local/bin/pigsty-kafka-health cluster \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties

返回 JSON 中 healthy: true 才表示该门禁通过。它适合只读诊断,但不能替代业务端到端验证。

该脚本还内置解析回归自检(pigsty-kafka-health selftest),每次剧本运行都会在安装后自动执行;若自检失败说明健康谓词本身不可信,应停止变更并排查。


KRaft 仲裁状态

从任一可用 Broker 查询动态 Quorum:

/opt/kafka/bin/kafka-metadata-quorum.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  describe --status

重点检查:

  • LeaderId 存在且对应预期 Controller;
  • CurrentVoters 与预期成员一致(加入中的新节点会先出现在 CurrentObservers);
  • MaxFollowerLagMaxFollowerLagTimeMs 没有持续增长;
  • Dashboard 中恰好有一个 Active Controller。

如需确认动态 Quorum(KIP-853)特性级别,可用 /opt/kafka/bin/kafka-features.sh ... describe 查看 kraft.version

查看 Controller 复制状态:

/opt/kafka/bin/kafka-metadata-quorum.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  describe --replication

如果没有 Leader、成员长期落后或 Voter 集合与预期不一致,应先停止其他变更,保留日志、Manifest 与 meta.properties 证据再分析。死掉的 Voter 用 缩容替换故障节点 流程摘除;不要手工改写 quorum 状态。


管理 Topic

生产 Topic 应优先在 pigsty.ymlkafka_topics 中声明:

kafka_topics:
  - name: orders
    partitions: 12
    replication_factor: 3
    config:
      min.insync.replicas: 2
      retention.ms: 604800000

修改声明后运行剧本收敛:

./kafka.yml --check -l kf-main
./kafka.yml -l kf-main

角色会幂等创建 Topic、只增加 Partition,并只修改声明的配置键。RF 变化会失败并要求显式 Partition Reassignment;从清单中移除条目不会删除 Topic。

只读查看 Topic:

/opt/kafka/bin/kafka-topics.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --list

/opt/kafka/bin/kafka-topics.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --describe --topic orders

临时或外部管理的 Topic 可以使用 Kafka CLI 创建,但不会自动写回 pigsty.yml。不要让声明式与手工管理同时拥有同一个 Topic。Topic 删除是业务数据删除动作,必须走独立审批、精确名称确认和恢复方案,本文不提供通用删除命令。


管理用户与权限

kafka_security: scram 时,应用身份应通过 kafka_users 管理:

kafka_users:
  - name: order-service
    password: "{{ vault_kafka_order_password }}"
    acls:
      - resource: topic
        name: orders
        operations: [Read, Write, Describe]
      - resource: group
        name: order-worker
        operations: [Read]
    quota:
      producer_byte_rate: 10485760
      consumer_byte_rate: 20971520

完整剧本会幂等收敛密码、该用户的 ACL 集合与显式给出的 Quota 字段。密码不要以明文提交到仓库或输出到日志。移除用户条目不会自动删除 Principal/凭据;删除或彻底撤权需要独立受审流程。


验证消息读写

使用测试 Topic 做端到端验证。Console Producer/Consumer 使用同一客户端配置文件:

/opt/kafka/bin/kafka-console-producer.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --topic ops-smoke

在另一个终端消费:

/opt/kafka/bin/kafka-console-consumer.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --topic ops-smoke \
  --from-beginning \
  --group ops-smoke-check

生产验收应从真实客户端网络执行,覆盖 DNS/advertised.listeners、证书校验、ACL、生产者 ACK、消费提交与端到端延迟,而不只验证 Broker 本机路径。


管理 Consumer Group

列出和查看 Consumer Group:

/opt/kafka/bin/kafka-consumer-groups.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --list

/opt/kafka/bin/kafka-consumer-groups.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --describe --group order-worker

Lag 要结合消费速率与业务 SLO 判断:短暂积压可能是批处理行为,持续增长且消费速率低于生产速率才表示无法追平。重置 Offset 可能造成重复消费或跳过消息,必须有独立审批、精确 Group/Topic 确认与回放方案。


配置集群

修改 pigsty.yml 后以完整集群为目标执行:

./kafka.yml --check -l kf-main
./kafka.yml -l kf-main

角色根据现场健康和静态指纹自动选择路径:

  • 集群不健康或停止:只启动已停止的 Controller,恢复并追平 Quorum 后再启动 Broker;若同时存在静态变化,仍在线成员随后进入严格滚动;
  • 存在待加入的 Controller-capable 节点:逐个以 Observer 追平后 add-controller 提升为 Voter;
  • 健康集群新增纯 Broker:逐个格式化、启动并确认注册;
  • 健康集群存在静态变化:严格逐节点滚动,每节点重启前后执行 Controller 零 Lag/最近追平、Quorum、Offline Partition、Under Min ISR 与 ISR 追平门禁;
  • 没有静态变化:不重启 Kafka。

不要用 -t kafka_config 绕过完整状态机。动态 Topic/User/ACL/Quota 收敛位于 kafka_provision 资源收敛阶段,静态变化是否重启由角色决定。


扩容集群

健康集群可以直接在清单中声明新成员:kafka_role: brokercombinedcontroller 都可以。为新节点分配从未使用过的 kafka_seq(一台主机同一时间只能属于一个 Kafka 集群),确保节点已被 Pigsty 纳管,然后仍以完整集群为目标:

./node.yml  --check -l 10.10.10.14    # 纳管新节点
./kafka.yml --check -l kf-main        # 先空跑
./kafka.yml -l kf-main                # 逐个准入 / 加入新成员

角色按成员类型自动选择路径,每次只处理一个新节点:

  • 纯 Broker:格式化、启动,并验证 Broker 已注册且未 Fenced(admit);
  • Combined / Controller:以 --no-initial-controllers 全新格式化、以 Observer 身份启动并追平元数据,再通过 add-controller 提升为 Voter,最后验证其已进入 Voter 集合且集群完整健康(join)。

运行结束时的 quorum-join-hosts / broker-admission-hosts 摘要会列出本次实际处理的节点。两点提醒:

  • 新增 Controller-capable 节点会改变所有成员的 controller.quorum.bootstrap.servers,因此存量节点会随之执行一轮门禁保护下的严格滚动,属于预期行为;
  • 扩出偶数个 Controller 时角色会打印警告:偶数 Quorum 不提升容错能力,请尽量保持奇数。

新 Broker 加入不会迁移已有 Partition。必须另外生成、评审并监控 kafka-reassign-partitions.sh 计划,控制磁盘/网络负载并准备回退。“服务已注册"不等于"扩容完成”。

复制策略也不会随 Broker 数自动放大。尤其是 Kafka 4.3 的 default.replication.factor 不能动态修改:由 1 Broker 扩到 3 Broker 后,它仍为初建的 RF=1,未来未显式指定 RF 的 Topic 也仍按 RF=1 创建。应先完成既有 Partition Reassignment,再规划 Controller 高可用或维护窗口,最后让新的静态默认值通过完整集群 安全滚动生效;不能为了改默认值绕过停机门禁。


缩容集群

kafka-rm.yml 选择集群的 真子集 即为成员退役(选择整个集群则是 集群下线)。退役会通过一台幸存成员,自动从现场元数据中摘除该节点:

./kafka-rm.yml -l 10.10.10.13     # 退役单个成员:摘除 Voter 条目、注销 Broker、清理本机

执行内容依次为:注销监控 Target → 停止服务 → remove-controller 摘除 KRaft Voter 条目(若该成员是 Voter;多成员退役时严格串行)→ kafka-cluster.sh unregister 注销 Broker → 清理本机配置与数据(受 kafka_rm_data 控制)。Broker 注销步骤容忍失败,以便重入与处理已失联成员;只有在核对现场 Quorum、Broker 注册、副本健康以及目标本机状态后,才从 pigsty.yml 删除该成员条目。

退役前请自行确认:剩余 Controller 仍构成多数派、保持奇数个 Controller、剩余 Broker 数不低于现有 Topic 的最大 RF。如果被退役 Broker 上仍有 Partition 副本,角色会打印警告:这些 Partition 将保持副本不足,直到同 kafka_seq 的替换节点重新加入(自动继承副本分配并补数据),或你显式执行 Reassignment 将副本迁走。计划内缩容应当先 Reassignment 排空、再退役


替换故障节点

节点永久损坏(磁盘丢失、机器报废)时,保持其 IP 与 kafka_seq 不变,三步完成补换:

./kafka-rm.yml -l 10.10.10.13     # ① 退役死者:摘除 Voter 条目与 Broker 注册(节点不可达也能执行)
./node.yml     -l 10.10.10.13     # ② 纳管替换机器(修复或换新,保持 IP)
./kafka.yml    -l kf-main         # ③ 重新加入:格式化、追平、准入/提升,自动继承原副本分配并补数据

第 ① 步的所有元数据操作都委派给幸存成员执行,因此对已经无法连接的死节点同样有效;它还会一并清理监控 Target,避免死节点持续触发 KafkaDown 告警。第 ③ 步中,同 kafka_seq 的 Broker 会自动继承原 Partition 分配并从副本重新同步数据,无需手工 Reassignment。

如果跳过第 ① 步直接重装节点并重跑 kafka.yml,角色会在配置阶段快速失败,并在报错中给出残留 Voter 条目的 Directory ID 与确切的 kafka-rm.yml 命令——按提示执行后重跑即可。加入流程可安全重入:任一步骤被中断后,重跑 kafka.yml 会从现场状态继续。


变更地址与端口

角色固定使用 inventory_hostname 作为 Broker advertised address 与 Controller bootstrap address。修改清单地址、kafka_portkafka_controller_port 会影响客户端元数据、Broker 通信或 Quorum,属于静态高风险变更;必须同步检查 DNS、证书 SAN、路由、防火墙、Bootstrap 地址、监控 Target 与所有成员。


轮换密钥与证书

已格式化且健康的 scram 集群支持两种互斥的受保护动作:内部凭据轮换和证书轮换。两者都要求精确完整集群、匹配的 kafka_rotate_confirm 确认字符串,并且建议先执行 --check。证书由同一 Pigsty CA 重新签发,新旧证书互信,轮换通过严格滚动逐节点生效。

具体命令和失败语义见 预置剧本:受保护轮换。安全模式本身是 Bootstrap-only 属性;这些动作不等于支持 plaintextscram 的在线迁移。


数据保护与恢复

Kafka 的数据保护依赖跨故障域副本、正确的 minISR、生产者 ACK 和经过演练的恢复流程。当前角色不提供 Kafka 数据备份、自动 Broker Drain(计划内缩容需先手工 Reassignment)或跨地域灾难恢复。

发生磁盘或节点故障时:

  1. 先查看 Kafka Overview/Instance、Quorum、ISR、Offline Partition 与 Under Min ISR;
  2. 保存 journalctl -u kafka、节点指标、Manifest、server.propertiesmeta.properties 证据;
  3. 确认节点角色、node.id、Cluster ID、Directory ID 与剩余副本可用性;
  4. 节点确认无法恢复时,按 替换故障节点 三步走:kafka-rm.yml 退役 → node.yml 纳管 → kafka.yml 重入;磁盘尚存、仅服务异常时 不要 急于退役或删除 meta.properties,先尝试普通收敛拉起;
  5. 对 Reassignment、RF 变更等数据搬迁操作仍使用独立评审的运行手册。

日志诊断

journalctl -u kafka -f
journalctl -u kafka_exporter -f
journalctl SYSLOG_IDENTIFIER=kafka --since today
journalctl SYSLOG_IDENTIFIER=kafka_exporter --since today

VictoriaLogs/Grafana 查询:

job:syslog unit:kafka
job:syslog app:kafka
job:syslog unit:kafka_exporter

常见诊断顺序是:服务日志 → 监听端口 → 管理通道健康 → 动态 Quorum → Broker/Partition/ISR → 客户端地址与证书/ACL → Consumer Lag。详细面板与告警映射见 监控告警

17.5 - 预置剧本

使用 kafka.yml 与 kafka-rm.yml 执行动态 KRaft 生命周期、严格滚动、资源收敛、轮换与下线。

KAFKA 模块提供两个剧本:kafka.yml 用于部署 Apache Kafka 4.1+ 动态 KRaft 集群并收敛其安全、 资源与监控状态;kafka-rm.yml 用于下线集群或移除成员。

集群完整性约束

每个被选中的 kafka_cluster 必须包含其全部成员:部分选择会在写入前失败;选择一个集群、多个完整集群或不加 -l 裸跑全部集群都是允许的。先对完全相同的目标执行 --check;真实运行前仍需人工核验备份/重建意图、容量、业务窗口、回退方案与变更批准。


kafka.yml

./kafka.yml --check -l kf-main   # 先空跑
./kafka.yml -l kf-main           # 创建或收敛单个集群
./kafka.yml                      # 裸跑:一次创建/收敛清单中的所有 Kafka 集群

Limit 规则是:每个被选中的集群必须完整。可以选择一个集群、多个集群,或不加 -l 对全部集群裸跑(集群内严格串行、集群间并发推进);但部分选择某个集群的成员会被直接拒绝。

检查模式验证公开 API、完整集群、角色、Rack、端口、Manifest 与可检查的文件变化,但会跳过格式化、服务启动和实时健康验收。因此 --check 成功不等于运行时一定成功。


执行阶段

kafka.yml 本身是一个薄封装:单一 Play 依次执行 node_idkafka 两个角色,与 pgsql.yml 的结构一致。角色内部把生命周期拆成六个任务阶段;所有跨节点排序(并行 Bootstrap、逐个 Controller 加入、逐个 Broker 准入、严格逐节点滚动)由启动阶段统一负责:

阶段 标签 作用
身份预检 kafka-id 派生并断言身份、集群完整性、角色、Rack、端口与保留键
安装 kafka_install 创建 kafka 系统用户,安装 java-runtimekafka-stack 软件包
配置 kafka_config 读取/恢复/创建 Manifest,签发安全材料,渲染配置,计算静态指纹,格式化空存储,判定生命周期路径
启动 kafka_launch 收敛不健康集群、逐个加入 Controller 与准入 Broker、严格滚动,确认 Manifest 与已生效静态状态
资源收敛 kafka_provision 收敛动态 minISR、用户凭据、ACL、Quota 与声明式 Topic,报告内部 Topic RF 漂移
监控 kafka_monitor 配置协议 Exporter 并注册 VictoriaMetrics Target

Play 使用 any_errors_fatal: true。某个阶段失败时,后续危险推进会停止;修正原因后可以重跑完整集群,角色会从现场状态和持久指纹恢复,而不是盲目重复格式化。


生命周期路径

配置阶段使用角色自有管理通道判断集群健康,并选择唯一后续路径:

冷启动、首次部署或修复

当集群停止或健康谓词不通过时,进入 Converge:

  1. 启动所有 Controller-capable 节点;
  2. 等待 Controller listener 与动态 Quorum Leader;
  3. 首次 Bootstrap 时验证初始 Controller Directory ID 已进入现场 Quorum;
  4. 启动纯 Broker;
  5. 等待 Broker listener 并要求完整集群健康;
  6. 只有配置已证明成功运行后,才持久化静态指纹。

JMX 不参与生命周期门禁:启动、准入与滚动的判定完全基于角色自有的 Kafka CLI/metadata 管理通道。

健康集群新增 Broker 或 Controller

新格式化的 kafka_role: broker 逐个准入(admit):启动后要求它已经注册且未 Fenced 才继续下一个。

新的 Combined/Controller 节点则逐个加入动态 Quorum(join):已 Commission 的集群以 --no-initial-controllers 全新格式化该节点,它以 Observer 身份启动并追平元数据,随后角色执行 add-controller 将其提升为 Voter,并用健康后置检查确认它进入 Voter 集合且集群完整健康。加入流程可重入:中断后重跑会从现场状态继续;若其 node.id 在 Quorum 中残留着死去前任的 Voter 条目,配置阶段会快速失败并给出先行 kafka-rm.yml 退役的确切命令。

准入/加入只证明服务成为成员;已有 Partition 不会自动迁移到新 Broker,必须另行执行显式 Reassignment。

健康集群静态变化

当渲染后的静态指纹变化时,严格滚动每次只处理一个节点:

  • 重启前检查 Controller 多数派、全部 Voter 零 Lag 且最近完成追平、Offline Partition、Under Replicated、Under Min ISR,以及移除目标后每个 Partition 的有效 ISR;
  • 重启后要求目标 Controller 回到 Voter 且重新追平、目标 Broker 注册且未 Fenced、其副本重新进入 ISR;
  • 任一门禁失败立即停止后续节点。

如果故障修复与静态变化同时存在,Converge 只启动已停止的成员,不并行重启仍在线成员;Quorum 恢复并追平后,尚未加载的静态变化继续进入严格滚动。

如果静态指纹没有变化,Kafka 不重启。动态资源变化仍会在资源收敛阶段在线生效。


任务标签

标签 阶段/作用
kafka-id 始终执行的身份、完整集群与拓扑派生断言
kafka_install 安装阶段总入口
kafka_user 创建 kafka 系统用户与用户组
kafka_pkg 按平台映射安装 java-runtimekafka-stack 软件包
kafka_config Manifest、安全材料、配置渲染、静态指纹、存储格式化与路径判定
kafka_launch Converge、Controller 串行加入、Broker 串行准入、严格滚动与 Manifest Commission
kafka_provision 动态 minISR、Topic、User、ACL 与 Quota 收敛
kafka_monitor / monitor 协议 Exporter 配置与监控注册总入口
kafka_register / register / add_metrics 仅刷新 VictoriaMetrics 文件发现 Target

正常配置变更应运行完整 kafka.yml,让角色自行选择生命周期路径。阶段标签主要用于开发、诊断和受控修复;不能用 -t kafka_config 或只限制单节点来绕过完整状态机。


身份、格式化与 Manifest

角色在写配置前校验:

  • 每个被选中的集群包含其全部成员;
  • kafka_seq 唯一,角色全部省略或全部显式;
  • 至少一个 Controller 和一个 Broker;
  • Rack 在所有 Broker-capable 节点上全有或全无;
  • 端口有效、互不冲突,角色自有键未被 kafka_parameters 覆盖;
  • Manifest、安全模式、meta.properties 与现场集群身份一致。

新集群随机生成 Cluster ID 和初始 Controller Directory ID,并以显式动态 Quorum 模式格式化每个节点。已有 ${kafka_data}/metadata/meta.properties 时在本地验证 Cluster ID 与 Node ID;初始 Controller Directory ID 只在首次 Bootstrap 启动后与现场 Quorum 比对,Commission 之后成员关系以 Raft 现场状态为准。角色不会自动重新格式化已有存储。

Bootstrap Manifest 的权威副本位于每个集群成员上:

/etc/kafka/manifest.yml

scram 集群的每个成员另有 /etc/kafka/secrets.yml;管理节点不保存任何 Kafka 状态,每次运行时从任一成员副本解析。活集群是运行事实权威,但普通剧本不会在冲突时擅自改写任何一方:

  • 所有成员都没有 Manifest 副本而存储已格式化时,失败关闭并提示先在任一成员上恢复该文件;
  • Manifest 存在而所有数据盘为空时失败关闭;
  • Cluster ID、安全模式或 Controller Identity 冲突时失败关闭;
  • 新节点的 node.id 在 Quorum 中残留前任 Voter 条目时快速失败,要求先用 kafka-rm.yml 退役。

不要删除 meta.properties、Manifest 或 Secret 来绕过保护。


静态指纹与可恢复重跑

角色对影响 Kafka 进程的静态文件计算期望指纹,并只在以下条件之一成立后写入 /etc/kafka/.pigsty-applied-static.sha256

  • Converge 已经成功启动并通过全局健康检查;
  • 严格滚动已经让该节点重启、追平并通过后置门禁。

如果执行中断,未被证明生效的变化不会被记成“已应用”。下一次完整重跑仍能识别待处理的静态重启。


资源收敛与监控注册

完整健康后,资源收敛与监控阶段依次:

  1. 收敛角色拥有的动态 cluster minISR;
  2. 幂等处理 kafka_users 的凭据、ACL 与声明 Quota;
  3. 幂等处理 kafka_topics 的创建、Partition 增长与显式配置;
  4. 检查内部 Topic RF 漂移,但不自动 Reassignment;
  5. 在按 kafka_seq 排序后的前两个 Broker-capable 节点配置并启动协议 Exporter;
  6. 在全部 Infra 节点刷新文件发现 Target。

每个实例对应一个 Target 文件,JMX 目标与(被选中节点的)协议 Exporter 目标都在同一 kafka 采集任务下:

/infra/targets/kafka/<kafka_instance>.yml

Target 文件每次完整运行按当前 Exporter 放置刷新;Target 的删除由 kafka-rm.yml 的注销步骤完成。


受保护轮换

轮换变量是一次性 extra-vars,不应写入 pigsty.yml。两种动作互斥,每次只能执行其一;前提是所有成员已格式化、集群健康、安全模式为 scram、角色自有 Secret 材料存在,且 kafka_rotate_confirm 与集群名完全一致。

内部凭据轮换

./kafka.yml --check -l kf-main \
  -e kafka_rotate_credentials=true \
  -e kafka_rotate_confirm=kf-main

./kafka.yml -l kf-main \
  -e kafka_rotate_credentials=true \
  -e kafka_rotate_confirm=kf-main

角色使用 active/standby 内部身份:先通过活管理通道更新非活动凭据,再原子切换本地受保护记录,并进入正常严格滚动。旧 active 保留为下一轮 standby,使中断后的重跑可恢复。

证书轮换

./kafka.yml --check -l kf-main \
  -e kafka_rotate_certificates=true \
  -e kafka_rotate_confirm=kf-main

./kafka.yml -l kf-main \
  -e kafka_rotate_certificates=true \
  -e kafka_rotate_confirm=kf-main

角色废弃共享 PKI 树中已签发的节点证书,用同一 Pigsty CA 为每个节点重新签发私钥与证书,更新节点上的 PEM 证书包并进入严格滚动。新旧证书由同一 CA 签发、彼此互信,因此不需要分阶段互换信任;健康预检失败时不会开始轮换,节点上的现有证书保持不变。


kafka-rm.yml

移除动作不在 kafka.yml 中,而是使用独立的 kafka-rm.yml 剧本。 该剧本 强制要求非空 -l/--limit,裸跑会在进入角色前失败;-l 选中一个集群的 全部成员 即为集群下线,选中 真子集 即为成员退役,两者共用同一执行顺序:

注销 VictoriaMetrics Target(kafka_deregister)→ 停止并禁用 kafka/kafka_exporter 服务(kafka)→ 经幸存成员摘除 KRaft Voter 条目与 Broker 注册(kafka_retire,仅在选中真子集时有幸存成员可用) → 删除 Exporter 配置、Systemd 环境/Unit 与辅助脚本(kafka_config)→ 删除数据目录与节点上的 /etc/kafka 恢复状态(kafka_data,受 kafka_rm_data 控制)→ 可选卸载软件包(kafka_pkg,受 kafka_rm_pkg 控制)。

在任何注销或停服前,角色还会验证 kafka_data 是专用的安全绝对路径:不含 ./.. 路径段,且不能是 //data/var/etc/opt/usr/home/root/pg。 防误删开关是 kafka_safeguard:设置为 true(命令行或清单中)时剧本直接中止,不删除任何东西。身份冲突、Exporter 异常或一般启动失败都不是删除数据的理由——先用 kafka.yml 收敛并读取失败原因。

集群下线

./kafka-rm.yml -l kf-main                          # 移除集群:注销监控、停服务,默认删除数据与 /etc/kafka 恢复状态
./kafka-rm.yml -l kf-main -e kafka_rm_data=false   # 保留磁盘数据与 /etc/kafka 恢复状态,只移除服务集成
./kafka-rm.yml -l kf-main -e kafka_rm_pkg=true     # 同时卸载 kafka-stack 软件包(共享的 Java 运行时不会卸载)
永久删除

kafka_rm_data 默认为 true:一次默认参数的 kafka-rm.yml 就会删除所选节点的数据/KRaft 元数据与 /etc/kafka 恢复状态。剧本没有确认字符串等额外闸门,执行前必须人工核对 -l 目标、备份或明确重建意图,并评估生产者/消费者影响。

成员退役

./kafka-rm.yml -l 10.10.10.13                      # 退役单个成员:摘除 Voter 条目与 Broker 注册,再清理本机

部分退役要求 -l 之外至少保留一个 Broker-capable(combined/broker)成员和一个 Controller-capable(combined/controller)成员; 两者可以是同一台 Combined 节点。缺少任一幸存锚点时,剧本会在注销或停服前失败。 通过这些幸存成员,剧本尝试摘除目标的 KRaft Voter 条目(remove-controller,多成员时严格串行)并注销其 Broker 注册(unregister),再执行本机清理。 元数据操作委派给幸存成员,因此对已经死亡、无法连接的目标节点同样适用——这也是 替换故障节点 的第一步。 注销 Broker 的命令被设计为可重入并容忍失败;真实运行后必须检查现场 Quorum、Broker 注册和副本健康,不能只凭剧本返回状态判定退役完成。

退役自动化不等于免除规划:缩容后剩余 Controller 应保持奇数并构成多数派,剩余 Broker 数不能低于现有 Topic 的最大 RF;若被退役 Broker 仍持有 Partition 副本,剧本会打印警告——计划内缩容应当先完成 Reassignment 排空。


剧本边界

两个剧本都不会自动完成 Partition Reassignment 与数据均衡、Topic/用户删除、plaintextscram 的在线迁移、版本升级与 Feature Level 终结、数据备份与灾难恢复,也不部署 Connect、Schema Registry、MirrorMaker、Cruise Control 等生态组件。完整清单见 模块边界;日常只读检查和资源管理见 日常管理

17.6 - 监控告警

Kafka 指标采集、Grafana Dashboard、日志查询与告警规则。

Pigsty 为 KAFKA 模块提供指标、日志、Dashboard 与告警一体化的可观测能力。监控同时覆盖 Kafka JVM 内部状态与 Kafka 协议视角,避免只看到进程存活而看不到 Partition、ISR 与 Consumer Lag,也避免只看到集群元数据而看不到 JVM、请求队列与 KRaft Controller 健康。


采集架构

KAFKA 模块使用两个互补的 Exporter:

采集面 服务/方式 Job 节点范围 主要内容
JVM 与 Kafka 内部 JMX Exporter Java Agent :9404 kafka(带 role 标签) 所有 Kafka 节点 JVM、Broker 吞吐、复制、请求路径、KRaft、Controller
Kafka 协议视角 kafka_exporter :9308 kafka(无 role 标签) kafka_seq 最小的至多两个 Broker-capable 节点 Broker、Topic、Partition、Offset、Consumer Group、Lag
主机资源 node_exporter node 纳管节点 CPU、内存、磁盘、网络、文件系统
日志 Journald → Vector → VictoriaLogs syslog 所有 Kafka 节点 Kafka 与 Exporter 结构化检索日志

角色在每一个 Infra 节点为每个实例生成一个文件发现目标,JMX 目标与(被选中节点的)协议 Exporter 目标都在同一文件、同一 kafka 采集任务下:

/infra/targets/kafka/<kafka_instance>.yml

单 Broker 集群只运行一个协议 Exporter;多 Broker 集群最多运行两个。纯 Controller 只注册 JMX 目标;未被选择的 Broker 与纯 Controller 都没有协议 Exporter 目标,这是预期行为。Target 文件每次完整运行按当前放置刷新;实例 Target 的删除由 kafka-rm.yml 的注销步骤完成。


标签模型

两类目标都注册在同一 job=kafka 采集任务下,通过有无 role 标签区分。

JMX 目标

标签 含义 示例
job 采集任务 kafka
cls Kafka 集群名 kf-main
ins Kafka 实例名 kf-main-1
ip 清单主机地址 10.10.10.11
instance JMX 抓取端点 10.10.10.11:9404
role Pigsty Kafka 角色 combinedbrokercontroller
node_id KRaft 节点号 1

协议 Exporter 目标

协议 Exporter 目标只包含 clsinsipinstance10.10.10.11:9308),没有 role/node_id 标签。vmagent 端的记录规则据此区分两类可用性:kafka_upup{job="kafka",role=~".+"}kafka_exporter_upup{job="kafka",role=""}

Exporter 从 Broker 查询整个 Kafka 集群,因此同一集群的两个 Exporter 可能返回相同 Topic/Partition/Consumer Group 视图。集群级 Recording Rule 会先在 Exporter 实例间去重,再汇总逻辑集群速率。scram 模式下,Exporter 连接 Kafka 所需的 TLS/SCRAM 参数由角色自有监控身份自动生成。


Grafana Dashboard

Pigsty 提供四个互补 Dashboard:

Kafka Overview

集群与全局总览。cls=All 是全部 Kafka 集群的 Overview;选择具体 cls 后,同一 Dashboard 就成为该 Kafka Cluster 的总览,而不是另一套独立面板。

主要内容:

  • 集群、Broker、Topic、Partition 与 Consumer Group 清单
  • Broker 可用性、Exporter 健康与集群工作负载
  • Leaderless、Under Replicated、ISR Deficit、Non-Preferred Replica
  • Topic Offset 进展、Consumer Commit 进展与总 Lag
  • Consumer Group 成员、Lag 排名和 Topic/Group 下钻
  • Kafka/Exporter 日志量、Firing Alerts 与日志明细

常用变量:clsmemberstopicgrouptopk

Kafka Instance

ins 变量选择任意 Kafka Broker/Controller JVM,包括纯 Controller,并联动宿主机资源。

主要内容:

  • 实例身份、角色、JMX 可用性与抓取质量
  • JVM Heap、GC、Thread、Buffer Pool、CPU、FD 与 Uptime
  • Broker 吞吐、复制状态、请求错误/延迟/队列和 Handler/Network Idle
  • KRaft Member State、Metadata Log、Controller 健康与事件延迟
  • 节点 CPU/内存、磁盘 I/O、网络、文件系统与 Kafka 日志

常用变量:clsinsip

Kafka Topic

clstopic 选择逻辑 Topic,查看 Topic/Partition 的协议状态。

主要内容:

  • Topic 与 Partition 清单、Leader、副本、ISR 和 Preferred Leader
  • Current Offset、保留跨度与消息追加速率
  • Leaderless、ISR Deficit 和 Non-Preferred Replica
  • 关联 Consumer Group、提交进度与 Lag

常用变量:clstopictopk

Kafka Consumer

clsgroup 选择 Consumer Group,查看成员、提交 Offset、消费进展与积压。

主要内容:

  • Consumer Group 清单与成员数量
  • Group/Topic/Partition 的已提交 Offset
  • Commit Rate、总 Lag、最大 Partition Lag 与积压趋势
  • Group 到 Topic/Partition 的下钻

常用变量:clsgrouptopictopk


Dashboard 选择

问题 首选 Dashboard 下钻方向
哪个集群或 Topic 出现异常? Kafka Overview 选择 clstopicgroup
某个 Consumer Group 为什么积压? Kafka Consumer Group → Topic → Partition Offset
某个 Topic/Partition 是否异常? Kafka Topic Topic → Partition → Consumer
某个 Broker 是否过载? Kafka Instance 请求路径 → JVM → Node 资源
KRaft Controller 是否健康? Kafka Instance KRaft Metadata Plane → Controller Health
是否存在 Leaderless/URP/ISR 问题? Kafka Overview Cluster → Kafka Instance / Topic
Exporter 缺数还是 Kafka 本身异常? Overview + Instance 对比 kafka_exporter_upkafka_up

Recording Rule

Kafka 规则文件位于 /infra/rules/kafka.yml。主要记录指标如下:

指标 含义
kafka:topic:msg_rate1m/5m Topic 当前 Offset 的 1/5 分钟正向变化速率
kafka:cls:msg_rate1m/5m 去重后的集群消息追加速率
kafka:csg_topic:commit_rate5m Consumer Group/Topic 的 5 分钟提交进展速率
kafka:csg_topic:lag Consumer Group/Topic 的总 Lag
kafka:csg:lag Consumer Group 跨 Topic 的总 Lag
kafka:cls:lag Kafka 集群全部 Consumer Group 的总 Lag
kafka:ins:jvm_heap_used_ratio Kafka JVM Heap 使用率
kafka:ins:jvm_cpu_cores Kafka JVM 消耗的 CPU Core 数
kafka:ins:load / kafka:cls:load 实例最忙请求线程池与集群平均负载
kafka:ins:jvm_gc_time_rate5m 5 分钟 GC 时间速率
kafka:ins:messages_in_rate5m Broker 5 分钟消息接收速率
kafka:ins:bytes_in_rate5m Broker 5 分钟客户端入站字节速率
kafka:ins:bytes_out_rate5m Broker 5 分钟客户端出站字节速率
kafka:ins:request_error_rate5m Broker 5 分钟请求错误速率
kafka:cls:under_replicated_partitions 集群 Under Replicated Partition 总数
kafka:cls:offline_partitions 集群 Offline Partition 数

基于 Offset 变化得到的是进展速率,不是客户端请求数。日志截断、Offset 回退或 Exporter 重启可能造成瞬时负变化;规则使用 clamp_min(..., 0) 只保留正向进展。


告警规则

告警 条件 持续时间 级别 首选下钻
KafkaDown up{job="kafka",role=~".+"} < 1 1m CRIT Kafka Instance / ins
KafkaExporterDown up{job="kafka",role=""} < 1 1m CRIT Kafka Instance / ins
KafkaJmxScrapeError jmx_scrape_error{job="kafka"} > 0 3m WARN Kafka Instance / JMX Collector
KafkaJvmHeapHigh Heap 使用率 > 90% 15m WARN Kafka Instance / JVM Memory
KafkaJvmDeadlock JVM Deadlocked Thread > 0 1m CRIT Kafka Instance / JVM Threads
KafkaRequestHandlerSaturated Handler Idle < 10% 10m WARN Kafka Instance / Request Path
KafkaNetworkProcessorSaturated Network Processor Idle < 10% 10m WARN Kafka Instance / Request Path
KafkaUnderReplicatedPartitions URP > 0 5m WARN Kafka Instance / Replication
KafkaUnderMinISR Under Min ISR > 0 1m CRIT Kafka Instance / Replication
KafkaOfflineLogDirectory Offline Log Directory > 0 1m CRIT Kafka Instance / Disk Pressure
KafkaOfflinePartitions Controller Offline Partition > 0 1m CRIT Kafka Overview / cls
KafkaControllerCountMismatch Active Controller 数不等于 1 1m CRIT Kafka Overview / cls
KafkaFencedBrokers Fenced Broker > 0 5m WARN Kafka Overview / cls
KafkaUncleanLeaderElection 5 分钟出现不干净 Leader 选举 立即 CRIT Kafka Overview / cls
KafkaConsumerLagGrowing Group Lag > 100000 且 30 分钟仍增长 30m WARN Kafka Consumer / group

不干净 Leader 选举可能意味着数据丢失,应立即保留 Controller/Broker 日志,确认受影响 Topic 与副本,再决定恢复动作。


常用 PromQL

检查采集目标:

kafka_up
kafka_exporter_up
up{job="kafka"}

检查某集群复制健康:

sum by (cls) (kafka_server_replica_manager_under_replicated_partitions{job="kafka"})
sum by (cls) (kafka_server_replica_manager_under_min_isr_partitions{job="kafka"})
max by (cls) (kafka_controller_offline_partition_count{job="kafka"})

检查 Consumer Lag:

topk(20, kafka_consumergroup_lag_sum{cls="kf-main"})

检查请求饱和与延迟:

kafka_server_request_handler_idle_ratio{job="kafka",cls="kf-main"}
max by (ins,request,quantile) (
  kafka_network_request_total_time_seconds{job="kafka",cls="kf-main",quantile=~"0.95|0.99"}
)

日志查询

Kafka 服务把标准输出与错误写入 Journald,节点 Vector 的 Journald Source 会转发到 VictoriaLogs,统一使用 job:syslog

job:syslog unit:kafka
job:syslog app:kafka
job:syslog unit:kafka_exporter
ip:10.10.10.11 job:syslog (unit:kafka OR app:kafka)

Kafka Instance Dashboard 的日志面板使用类似查询,并展示时间、级别、Systemd Unit 与消息。诊断时应把日志与同一时间窗口内的 KRaft、ISR、请求队列、GC、磁盘 I/O 和网络指标对齐。


验证监控链路

在 Kafka 节点验证原始端点:

curl -fsS http://<kafka-ip>:9404/metrics | grep '^jmx_scrape_error'
curl -fsS http://127.0.0.1:9308/metrics | grep '^kafka_brokers'

在 Infra 节点检查文件发现(每实例一个文件,被选中节点的文件含 JMX 与协议 Exporter 两个目标):

ls -l /infra/targets/kafka/
cat /infra/targets/kafka/kf-main-1.yml

然后在 VictoriaMetrics 查询 up{job="kafka"}(或记录指标 kafka_upkafka_exporter_up)。自定义 exporter 指标在抓取失败后可能短暂保留旧样本,端点存活应以 Prometheus 原生 up 为准。若原始端点正常但记录指标缺失,依次检查文件发现、VictoriaMetrics Target、网络可达性、规则加载与标签;若 JMX HTTP 正常但 jmx_scrape_error1,检查 Kafka 日志和 /etc/kafka/jmx_exporter.yml 的 MBean 匹配情况。

完整指标语义参阅 指标定义

17.7 - 指标定义

Kafka JMX、协议 Exporter 与 Recording Rule 指标字典。

KAFKA 模块使用两类指标源,都注册在同一 job=kafka 采集任务下:JMX 目标(带 role 标签)采集每个 JVM 的内部状态;协议 Exporter 目标(无 role 标签)通过 Kafka 协议采集逻辑集群、Topic、Partition 与 Consumer Group 状态。协议 Exporter 只放在 kafka_seq 最小的至多两个 Broker-capable 节点上,单 Broker 集群只运行一个。

JMX 配置采用白名单,只导出 JVM 基线和有界的 Broker、复制、请求路径与 KRaft 指标;高基数的 per-client 与 per-partition JMX MBean 被有意排除,Partition 详情由协议 Exporter 提供。


公共标签

指标源 公共标签
JMX 目标(:9404 job, cls, ins, ip, instance, role, node_id
协议 Exporter 目标(:9308 job, cls, ins, ip, instance

两类目标的 job 都是 kafka;是否携带 role 标签是区分两类序列的依据。

部分指标还有 topicpartitionbrokerconsumergrouprequestversionerrorquantilestateoperation 等维度。


可用性与抓取指标

指标 类型 含义
kafka_up Gauge/Recording JMX 目标抓取可用性:up{job="kafka",role=~".+"}
kafka_exporter_up Gauge/Recording 协议 Exporter 目标抓取可用性:up{job="kafka",role=""}
up Gauge VictoriaMetrics 对原始 Target 的抓取状态
jmx_scrape_error Gauge JMX Exporter 最近一次抓取是否出错,健康值为 0
jmx_scrape_duration_seconds Gauge JMX 抓取耗时
jmx_scrape_cached_beans Gauge JMX Exporter 缓存的 MBean 数量
scrape_duration_seconds Gauge VictoriaMetrics 抓取 Exporter 的耗时
scrape_samples_scraped Gauge 本次抓取的样本数量

协议 Exporter 指标

以下指标来自协议 Exporter 目标。同一集群的多个 Exporter 会看到相同的逻辑集群状态,直接做集群聚合时必须按语义去重,不能简单把所有 ins 相加。

Broker 与 Topic

指标 类型 关键维度 含义
kafka_brokers Gauge 集群 Exporter 发现的 Broker 数量
kafka_broker_info Gauge id, address Broker 信息,以值 1 携带标签
kafka_topic_partitions Gauge topic Topic 的 Partition 数量
kafka_topic_partition_current_offset Gauge topic, partition Partition 当前 Log End Offset
kafka_topic_partition_oldest_offset Gauge topic, partition Partition 当前最早可读 Offset
kafka_topic_partition_leader Gauge topic, partition 当前 Leader Broker ID;无 Leader 时用于识别异常
kafka_topic_partition_replicas Gauge topic, partition, broker 分配给 Partition 的副本集合
kafka_topic_partition_in_sync_replica Gauge topic, partition, broker 当前 ISR 成员
kafka_topic_partition_under_replicated_partition Gauge topic, partition Partition 是否处于副本不足状态
kafka_topic_partition_leader_is_preferred Gauge topic, partition 当前 Leader 是否为 Preferred Replica

current_offset - oldest_offset 可以估计当前可保留的 Offset Span,但 Offset 数量不等于字节数,Compact Topic 也不等于精确消息条数。

Consumer Group

指标 类型 关键维度 含义
kafka_consumergroup_members Gauge consumergroup Group 当前成员数
kafka_consumergroup_current_offset Gauge consumergroup, topic, partition Group 已提交 Offset
kafka_consumergroup_current_offset_sum Gauge consumergroup, topic 已提交 Offset 汇总
kafka_consumergroup_lag Gauge consumergroup, topic, partition Partition 级消费滞后
kafka_consumergroup_lag_sum Gauge consumergroup, topic Group/Topic 消费滞后汇总

没有提交 Offset 的临时消费者、使用外部 Offset 存储的客户端,或尚未消费某 Topic 的 Group,不一定产生这些时间序列。

Exporter 自身

指标 类型 含义
kafka_exporter_build_info Gauge Exporter 版本、Revision 与构建信息
process_* Gauge/Counter Exporter 进程 CPU、内存、FD、启动时间等
go_* Gauge/Counter Exporter Go Runtime、GC、Goroutine 与内存状态
promhttp_metric_handler_* Counter /metrics 请求处理状态

JMX:JVM 基线

excludeJvmMetrics: false 使 JMX Exporter 暴露标准 JVM/进程指标。Kafka Instance Dashboard 主要使用:

指标 含义
jvm_memory_used_bytes 按 Heap/Non-Heap 与 Memory Pool 划分的已用内存
jvm_memory_committed_bytes JVM 已提交内存
jvm_memory_max_bytes JVM 可用最大内存
jvm_gc_collection_seconds_count GC 次数
jvm_gc_collection_seconds_sum GC 累计耗时
jvm_threads_state 按线程状态统计的线程数
jvm_threads_deadlocked 检测到的死锁线程循环数
jvm_buffer_pool_used_bytes Direct/Mapped Buffer Pool 使用量
process_cpu_seconds_total Kafka JVM 累计 CPU 时间
process_open_fds / process_max_fds 已打开与最大文件描述符
process_start_time_seconds Kafka JVM 启动时间

JMX:Broker 流量

指标 类型 含义
kafka_server_broker_messages_in_total Counter Broker 接收的消息总数
kafka_server_broker_bytes_in_total Counter Broker 接收的客户端字节总数
kafka_server_broker_bytes_out_total Counter Broker 发送的客户端字节总数
kafka_server_broker_replication_bytes_in_total Counter Broker 接收的复制字节总数
kafka_server_broker_replication_bytes_out_total Counter Broker 发送的复制字节总数
kafka_server_broker_produce_requests_total Counter Produce 请求总数
kafka_server_broker_failed_produce_requests_total Counter 失败 Produce 请求总数
kafka_server_broker_fetch_requests_total Counter Fetch 请求总数
kafka_server_broker_failed_fetch_requests_total Counter 失败 Fetch 请求总数

这些是 Broker 总量,不包含 Topic 维度,避免 JMX Series 随 Topic 数膨胀。Topic 级 Offset 与进展来自协议 Exporter。


JMX:复制与存储

指标 类型 含义
kafka_server_replica_manager_under_replicated_partitions Gauge ISR 少于已分配副本的 Partition 数
kafka_server_replica_manager_under_min_isr_partitions Gauge ISR 低于 min.insync.replicas 的 Partition 数
kafka_server_replica_manager_at_min_isr_partitions Gauge ISR 恰好等于 min.insync.replicas 的 Partition 数
kafka_server_replica_manager_offline_replicas Gauge 当前 Broker 上离线副本数
kafka_server_replica_manager_partitions Gauge 当前 Broker 承载的副本数
kafka_server_replica_manager_leaders Gauge 当前 Broker 领导的 Partition 数
kafka_server_replica_manager_isr_shrinks_total Counter ISR 收缩事件总数
kafka_server_replica_manager_isr_expands_total Counter ISR 扩张事件总数
kafka_server_replica_manager_failed_isr_updates_total Counter ISR 更新失败总数
kafka_server_replica_manager_reassigning_partitions Gauge 正在进行 Reassignment 的 Leader Partition 数
kafka_server_delayed_operation_purgatory_size Gauge operation 划分的延迟操作等待数
kafka_log_manager_offline_log_directories Gauge Kafka 标记为离线的日志目录数

Under Replicated 表示副本没有全部同步;Under Min ISR 更严重,表示写入可用性或持久性条件已经低于设置的最小 ISR。At Min ISR 虽未越线,但已经没有额外副本余量。


JMX:请求路径

指标 类型 额外标签 含义
kafka_network_request_total Counter request, version 各 Kafka API 请求总数
kafka_network_request_errors_total Counter request, error 各 API/错误码响应错误总数
kafka_network_request_total_time_seconds Gauge request, version, quantile API 总耗时 P50/P95/P99
kafka_network_request_queue_size Gauge 等待 Request Handler 的请求数
kafka_network_response_queue_size Gauge 等待 Network Processor 的响应数
kafka_server_request_handler_idle_ratio Gauge Request Handler 平均空闲比例
kafka_network_processor_idle_ratio Gauge Network Processor 平均空闲比例

排查高延迟时,应同时查看请求量、错误码、P95/P99、两个队列、Handler/Processor Idle、GC、CPU、磁盘 I/O 与网络。单独看到低 Idle 不足以判断瓶颈位置。


JMX:KRaft 与 Broker 元数据

指标 类型 含义
kafka_server_raft_state Gauge 当前成员的 KRaft 状态,以 state 标签表示
kafka_server_raft_current_leader Gauge 当前 KRaft Leader Node ID,-1 表示未知
kafka_server_raft_current_epoch Gauge 当前 KRaft Epoch
kafka_server_raft_high_watermark Gauge 元数据日志 High Watermark
kafka_server_raft_log_end_offset Gauge 元数据日志 Log End Offset
kafka_server_broker_metadata_last_applied_record_lag_seconds Gauge Broker 应用元数据记录的时间滞后
kafka_server_broker_metadata_load_errors_total Counter Broker 加载元数据错误总数
kafka_server_broker_metadata_apply_errors_total Counter Broker 应用元数据镜像错误总数
kafka_server_metadata_snapshot_bytes Gauge 最近生成或加载的元数据 Snapshot 大小
kafka_server_metadata_snapshot_age_seconds Gauge 最近元数据 Snapshot 的年龄

log_end_offset - high_watermark 可辅助判断元数据提交滞后;还应结合成员角色、当前 Leader、Epoch 和 Controller 事件延迟判断。


JMX:Controller

这些 MBean 只存在于带 Controller 角色的 Kafka 进程中:

指标 类型 含义
kafka_controller_active_controller_count Gauge Active Controller 上为 1,其他 Controller 为 0
kafka_controller_fenced_broker_count Gauge Active Controller 观察到的 Fenced Broker 数
kafka_controller_active_broker_count Gauge Active Broker 数
kafka_controller_global_topic_count Gauge Controller 观察到的 Topic 数
kafka_controller_global_partition_count Gauge Controller 观察到的 Partition 数
kafka_controller_offline_partition_count Gauge 离线的非内部 Partition 数
kafka_controller_preferred_replica_imbalance_count Gauge Leader 不是 Preferred Replica 的 Partition 数
kafka_controller_metadata_errors_total Counter Controller 元数据处理错误总数
kafka_controller_last_applied_record_lag_seconds Gauge Controller 应用元数据记录的时间滞后
kafka_controller_timed_out_broker_heartbeats_total Counter Broker Heartbeat 超时总数
kafka_controller_elections_total Counter 本节点观察到的新 Active Controller 选举总数
kafka_controller_unclean_leader_elections_total Counter 不干净 Leader 选举总数
kafka_controller_event_queue_time_seconds Gauge Controller 事件排队 P50/P95/P99
kafka_controller_event_processing_time_seconds Gauge Controller 事件处理 P50/P95/P99

健康集群应恰好存在一个 Active Controller。offline_partition_countmetadata_errors_totalunclean_leader_elections_total 的增加都应优先处理。


Recording Rule 指标

Offset 进展

指标 聚合层级 窗口 含义
kafka:topic:msg_rate1m Topic 1m Exporter 间去重后的 Current Offset 正向增长速率
kafka:topic:msg_rate5m Topic 5m Exporter 间去重后的 Current Offset 正向增长速率
kafka:cls:msg_rate1m 逻辑集群 1m Exporter 间去重后的消息追加速率
kafka:cls:msg_rate5m 逻辑集群 5m Exporter 间去重后的消息追加速率
kafka:csg_topic:commit_rate5m Group/Topic 5m Commit Offset 正向增长速率
kafka:csg_topic:lag Group/Topic 当前值 Partition Lag 去重后汇总
kafka:csg:lag Consumer Group 当前值 Group 跨 Topic 总 Lag
kafka:cls:lag 逻辑集群 当前值 集群跨 Consumer Group 总 Lag

JVM 与 Broker

指标 含义
kafka:ins:jvm_heap_used_ratio Heap Used / Heap Max
kafka:ins:jvm_cpu_cores 5 分钟 JVM CPU Core 消耗
kafka:ins:load 实例最忙请求线程池的饱和度
kafka:cls:load 集群实例平均负载
kafka:ins:jvm_gc_time_rate5m 5 分钟 GC 时间速率
kafka:ins:messages_in_rate5m 5 分钟 Broker 消息接收速率
kafka:ins:bytes_in_rate5m 5 分钟 Broker 客户端入站字节速率
kafka:ins:bytes_out_rate5m 5 分钟 Broker 客户端出站字节速率
kafka:ins:request_error_rate5m 5 分钟非 NONE 请求错误速率
kafka:cls:under_replicated_partitions 集群 Under Replicated Partition 总数
kafka:cls:offline_partitions 集群 Offline Partition 数

基数与解释注意事项

  • 不要把同一 cls 的多个 kafka_exporter 结果直接求和;它们可能是同一集群视图的副本。
  • kafka_topic_partition_current_offset 是 Offset,不是精确字节、请求或业务事件数量。
  • Consumer Lag 只覆盖 Kafka 中可见且已提交 Offset 的 Group。
  • 纯 Controller 缺少 Broker 指标和协议 Exporter 指标属于正常角色差异;未被选择的 Broker 没有协议 Exporter 指标也属于正常放置结果。
  • 某个 MBean 在具体 Kafka 版本/角色中不存在时,对应 JMX Series 也不会出现;应结合 role 判断。
  • per-client/per-partition JMX 指标被白名单排除,以避免不可预测的时间序列基数。

Dashboard 与告警使用方式参阅 监控告警

17.8 - 常见问题

Pigsty Kafka 4.1+ 动态 KRaft 模块常见问题与故障排查。

当前 KAFKA 模块是什么成熟度?

当前角色已实现生产级 v1 基线:动态 KRaft、完整集群护栏、冷启动/修复、Broker 串行准入与 Controller 动态加入、成员退役(含死节点)、故障节点三步替换、严格滚动、TLS/SCRAM/ACL、Topic/User 声明式收敛、内部凭据/证书轮换以及完整监控链路。

它不是托管 Kafka 产品。生产仍需使用 kafka_security: scram、奇数 Controller、足够 Broker/RF/minISR,并补充容量规划、Reassignment/数据均衡、升级、备份、恢复与故障演练。默认 plaintext 只适合开发或可信隔离网络。


为什么没有 ZooKeeper,也没有 controller.quorum.voters

本模块面向 Kafka 4.1+,使用原生动态 KRaft,不安装 ZooKeeper,也不创建静态 Quorum。所有成员渲染 controller.quorum.bootstrap.servers;新集群显式使用 --initial-controllers/--no-initial-controllers 格式化,启动后角色会校验初始 Controller 的 Directory ID 已进入现场 Quorum。

初始 Controller Identity 写入 Bootstrap Manifest,但它只是"出生证明":集群首次 Commission 之后,现场 Quorum 的成员关系以 Raft 自身为准。后续 Controller 的增删由剧本编排完成——新增走 kafka.yml 的 Observer 追平 + add-controller 加入流程,删除走 kafka-rm.yml 真子集退役(自动 remove-controller)——你只需要编辑 inventory 并运行对应剧本。


combinedbrokercontroller 有什么区别?

  • combined:同时承担 Broker 与 Controller,监听 90929093,是默认值;
  • broker:纯数据面,只监听 9092
  • controller:纯控制面,只监听 9093

集群角色要么全部省略并一致使用 combined,要么全部显式声明。不再提供旧角色别名。


Controller 端口 9093 会和 Alertmanager 冲突吗?

不冲突。Pigsty 的 Alertmanager 监听 alertmanager_port 9059,集群端口为 9094,与 KRaft Controller 的惯例端口 9093 错开。若你改动过这些端口而发生碰撞,为该集群调整 kafka_controller_port 即可——角色只强制 9092909393089404 四者互不相同,不会检测与其他服务的端口占用。


服务已启动,但远程客户端连不上?

Broker 的 advertised.listeners 固定使用 inventory_hostname。客户端连接 Bootstrap Server 后,还必须解析并访问元数据返回的每一个 Broker 地址。

依次检查:

grep '^advertised.listeners' /etc/kafka/server.properties
ss -lntp | grep ':9092'
getent hosts <inventory-hostname>

scram 客户端还要检查 CA、SASL mechanism、用户名/密码与 ACL。当前 v1 不提供自定义 advertised address、多 Listener 或 NAT/公网映射;如果客户端不能直接路由 inventory_hostname,该网络模型不在当前核心契约内,不能用 kafka_parameters 覆盖 raw listener 绕过。


为什么提示 Cluster ID、Node ID 或 Directory ID 不匹配?

角色会交叉校验 Bootstrap Manifest、${kafka_data}/metadata/meta.properties、inventory 与现场动态 Quorum。常见原因包括:

  • 修改了 kafka_clusterkafka_seq
  • 把其他集群的数据盘挂载到当前节点;
  • 恢复/接管时给出了错误的 kafka_cluster_id
  • Controller 数据目录或 Directory ID 与现场 Voter 记录不一致;
  • 选错了目标集群或使用了过期 Manifest。

这是保护性失败。不要删除 meta.properties、Manifest 或直接执行 kafka-rm.yml。先确认数据归属、剩余副本、真实 Cluster/Node/Directory Identity 与恢复目标。


Manifest 丢失或只剩旧 Manifest 会怎样?

每个集群成员都保留一份 Manifest 权威副本 /etc/kafka/manifest.ymlscram 集群另有 /etc/kafka/secrets.yml),管理节点不保存任何 Kafka 状态,每次运行时从任一成员副本解析,因此换管理节点或丢失本地检出都不影响集群管理。只有当所有成员的副本都丢失、而存储已经格式化时,角色才失败关闭并提示先在任一成员上恢复该文件;已格式化的 scram 集群在所有成员都找不到 Secret 副本时同样失败关闭。签发的节点证书缓存在 files/pki/kafka/,丢失时直接由 Pigsty CA 重签。

反过来,如果 Manifest 存在而全部 Kafka 数据盘为空,角色会失败关闭,避免用旧身份意外复活已消失的集群。确实要重建时必须先执行 kafka-rm.yml 和明确的重建流程。


为什么 kafka_parameters 中的某些键被拒绝?

身份、动态 Quorum、Listener、存储、复制、Rack 与安全必须保持单一权威,因此这些键由角色拥有:出现任意一个,身份预检都会在写文件前失败。完整保留列表见 kafka_parameters

请改用对应的公开参数。角色不提供地址、路径子目录、Listener Map 或 Exporter options 变量。


如何启用 TLS、SCRAM 与 ACL?

新集群设置:

kafka_security: scram

这会一次启用 Pigsty CA 节点证书、Controller mTLS、Broker/client SASL_SSL + SCRAM-SHA-512、StandardAuthorizer 与默认拒绝。应用用户通过 kafka_users 声明密码、ACL 和可选 Quota。

安全模式是 Bootstrap-only 属性。已格式化集群不能通过普通剧本从 plaintext 在线切换到 scram;这需要独立迁移状态机。健康 scram 集群可以使用受保护动作轮换内部凭据或证书。


kafka_topicskafka_users 会删除资源吗?

不会因为从清单移除条目而隐式删除 Topic 或用户。

Topic 会幂等创建、Partition 只增加、只更新声明的配置;RF 变化要求显式 Reassignment。声明用户会收敛密码、完整 ACL 集合与给出的 Quota 字段。Topic 删除、用户删除或彻底撤权都是独立受审操作。


JMX Exporter 与 kafka_exporter 有什么区别?

JMX Exporter 注入每个 Kafka JVM,采集 JVM、Broker、复制、请求路径与 KRaft 内部指标,注册为带 role 标签的 job=kafka 目标。

kafka_exporter 通过 Kafka 协议查询逻辑集群、Topic、Partition、Offset、Consumer Group 与 Lag,注册为同一 job=kafka 下不带 role 标签的目标。角色只在按 kafka_seq 排序后的前两个 Broker-capable 节点运行;单 Broker 集群运行一个,纯 Controller 不运行。

两者互补。生命周期健康门禁使用角色自有 Kafka CLI/metadata 通道,不依赖任一 Exporter。


为什么某个 Broker 或纯 Controller 没有 kafka_exporter?

这是预期的派生放置。协议 Exporter 返回的是整个逻辑集群视图,不是节点指标;最多两个副本可以避免监控单点,同时控制重复采集成本。

检查当前目标(每实例一个文件,被选中节点的文件里含 :9308 的协议 Exporter 目标):

ls -l /infra/targets/kafka/
grep 9308 /infra/targets/kafka/*.yml

完整运行会按当前放置刷新每个实例的 Target 文件,不应只针对单节点运行注册标签。注意:若 Exporter 放置因拓扑变化而转移,曾被选中节点上的旧 kafka_exporter 服务不会被普通剧本自动停止,需要手工或通过 kafka-rm.yml 清理。


为什么 JMX 端点可访问,但 jmx_scrape_error=1

HTTP 可访问只说明 Java Agent 已加载;jmx_scrape_error=1 表示本轮 MBean 采集失败:

journalctl -u kafka --since '-30 min' --no-pager
curl -fsS http://<kafka-ip>:9404/metrics | head -n 40

检查 /etc/kafka/jmx_exporter.yml 与当前 Kafka/JMX Exporter 包是否匹配,以及 JVM 是否已经过 startDelaySeconds。真实启动验收要求 jmx_scrape_error 0.0、JVM 指标和至少一项与角色匹配的 kafka_ 指标。


为什么 Consumer Lag 没有数据?

常见原因:Consumer 没使用 Group、未向 Kafka 提交 Offset、把 Offset 存在外部系统、Group 尚未消费目标 Topic,或协议 Exporter 的 TLS/SCRAM/ACL/网络异常。

/opt/kafka/bin/kafka-consumer-groups.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --describe --group <group>

再检查 kafka_exporter_up、Exporter 日志、Dashboard 变量和原始 kafka_consumergroup_* 指标。端点存活以 Prometheus 原生 up 为准,不要用抓取失败后可能短暂保留的自定义指标代替。


为什么两个 kafka_exporter 的集群指标不能相加?

两个 Exporter 查询同一逻辑集群,可能返回相同 Topic/Partition/Consumer Group 状态;直接求和会重复计算。Pigsty 的 kafka:cls:* Recording Rule 会先跨 Exporter 副本去重,再聚合到集群。


应用要经过 HAProxy、Keepalived VIP 或 LB 吗?

不要。Kafka Producer/Consumer 是集群感知的智能客户端:连上 bootstrap.servers 中任一种子取得元数据后,它直接连接各 Partition Leader。VIP 或通用 TCP LB 既不理解 Partition Leader,也不会改写元数据中的 Broker 地址,放在数据面只会增加长连接状态、故障点与排障复杂度。

若平台强制要求统一发现入口,DNS 或 TCP LB 可以只承担 bootstrap,但 advertised.listeners 仍返回每个 Broker 的可达地址,应用网络必须直达全部 Broker。跨 NAT、公网、多网络或 Kubernetes 暴露需要为每个 Broker 设计独立外部地址与额外 Listener,当前模块固定宣告清单地址,不支持这类映射。

详见 快速上手:为什么应用应直连多个 Broker集群配置:网络与监听器


可以直接增删 Broker 或 Controller 吗?

可以。编辑 inventory 后由剧本编排完成 KRaft 成员变更 的全部步骤:

  • 增加:在 inventory 中声明新成员(brokercombinedcontroller 均可),以 完整集群 为目标运行 ./kafka.yml -l <cls>(不能只 -l 新节点)。纯 Broker 逐个格式化、启动并验证注册;Combined/Controller 以 --no-initial-controllers 格式化,Observer 追平后 add-controller 提升为 Voter。全程逐节点、全程健康门禁。
  • 移除./kafka-rm.yml -l <ip>(集群真子集)经幸存成员执行 remove-controller 与 Broker 注销,节点不可达也能完成,随后从 inventory 删除该成员。

仍需自行保证:变更后 Controller 保持奇数且多数派存活;一次只做一个方向的成员变更;被移除 Broker 上的 Partition 副本先行排空(或由同 kafka_seq 的替换节点接管)。加入后既有 Partition 不会自动迁移,需独立执行并监控 Reassignment——“Broker 已注册”不等于“容量已均衡”。


软件包版本由哪个参数控制?

角色使用 package_map['java-runtime']package_map['kafka-stack'],不提供 kafka_versionscala_version 或 Exporter 版本参数。实际版本由目标平台的 Pigsty 仓库和已安装包决定。

2026-07-16 验证的载荷为 Kafka 4.3.1、kafka_exporter 1.9.0、JMX Exporter 1.6.0。升级仍需单独评审兼容性、备份/回退、滚动顺序与 Feature Level,不能只替换包。


如何安全清空 Kafka 数据?

kafka.yml 永远不执行清理,删除动作只在独立的 kafka-rm.yml 中:-l 选中整个集群(或裸跑选中全部集群)即为集群下线,选中真子集则是成员退役。默认 kafka_rm_data=true 会永久删除数据/KRaft 元数据、节点上的 /etc/kafka 恢复状态与监控 Target;kafka_rm_data=false 保留数据与恢复状态,kafka_safeguard=true 中止一切删除。

该剧本没有确认字符串等额外闸门。命令会直接执行删除;运行前必须人工确认精确 -l 目标、可恢复备份或明确重建意图与业务停用状态。成员退役中的 Broker 注销命令会容忍失败,真实运行后还必须核对 Quorum、Broker 注册与副本健康。完整语义见 预置剧本:kafka-rm.yml

18 - 模块:MYSQL

使用 Pigsty 部署原生 MySQL 8.4 LTS 单机或三节点 InnoDB Cluster,附带 TLS、每日备份与完整监控。

MySQL 是世界上最流行的开源关系型数据库之一。Pigsty 的 MYSQL 模块在纳管节点上部署固定的 原生 MySQL 8.4 LTS 平台:单机实例,或基于 Group Replication 的三节点单主 InnoDB Cluster,并统一管理 TLS、备份、监控与生命周期。

当前状态:Pilot 试点模块

MYSQL 是补充性的试点模块,定位是「简单、廉价、够用」的 MySQL 集群,不追求与 PGSQL 模块同级的完备性。 核心能力(部署收敛、高可用切换、每日备份、监控告警)已经过系统性测试; 完全停机恢复、物理备份恢复等破坏性流程刻意保留为手工运维操作,参见 日常管理 中的操作手册。


模块能力

MYSQL 模块当前提供:

  • 固定的原生 MySQL 8.4 LTS 平台:Server、Client、Shell、Router、XtraBackup 版本一致,开箱即用
  • 两种拓扑:单机实例,或三节点单主 InnoDB Cluster(MySQL Shell AdminAPI 创建与收敛)
  • 每个 HA 成员本机部署 MySQL Router,提供拓扑感知的读写(6446)与只读(6447)入口
  • 全链路强制 TLS:复用 Pigsty 共享 CA 签发节点叶证书,拒绝非加密连接
  • 声明式业务对象:mysql_databasesmysql_users 增量收敛,不隐式删除数据
  • mysql_parameters 参数覆盖:调整关键参数(如 max_connections),配置变更自动编排滚动重启
  • 每日全量物理备份:XtraBackup 备份并完成整备(prepare),带保留策略、并发锁与原子提交
  • 完整可观测性:mysqld_exporter 指标、68 条预置衍生规则、27 条告警规则、5 个 Grafana Dashboard、错误日志入 VictoriaLogs
  • 默认启用 sql_require_primary_key:拦截无主键表,保护 MGR 复制与灾难恢复
  • 收敛式运维:成员掉线、AdminAPI 状态漂移等场景重跑 mysql.yml 即可自愈;危险操作有安全护栏

模块架构

MYSQL 模块依赖 NODE 完成节点纳管、软件仓库与共享 CA,依赖 INFRA 提供 VictoriaMetrics、VictoriaLogs、Grafana 与 Alertmanager。不依赖 ETCDPGSQL

flowchart LR
    admin["Pigsty 管理节点"] -->|"mysql.yml"| mysqld["mysqld ×3 / MGR 单主<br>3306 · TLS"]
    client["业务客户端"] -->|"RW 6446 / RO 6447"| router["MySQL Router<br>(每个 HA 成员)"]
    router --> mysqld
    mysqld --> backup["XtraBackup 每日全备<br>(仅当前主库)"]
    mysqld --> exporter["mysqld_exporter :9104"]
    mysqld --> journal["错误日志 → Journald"]
    exporter --> vm["VictoriaMetrics"]
    journal --> vector["Vector"] --> vl["VictoriaLogs"]
    vm --> grafana["Grafana"]
    vl --> grafana
    vm --> alertmanager["Alertmanager"]

    style mysqld fill:#4479A1,stroke:#33618a,color:#fff
    style router fill:#70C1B3,stroke:#4f968b,color:#fff
    style vm fill:#E66B7A,stroke:#b84e5c,color:#fff
    style vl fill:#C98367,stroke:#9e634e,color:#fff

三节点模式下 mysql_seq=1 只是首次引导协调者:运行时 PRIMARY 由选举产生,重跑剧本不会把主库强制切回 1 号节点。


组件与端口

组件 用途 固定端点
mysqld 单机服务或 MGR 成员 Classic 3306、X Protocol 33060
Group Replication 三节点复制与共识(XCOM) 33061
MySQL Router HA 拓扑感知入口,每个成员均部署 RW 6446、RO 6447
MySQL Shell AdminAPI 生命周期管理 本机控制面
XtraBackup 每日全量物理备份 本地备份仓库
mysqld_exporter MySQL 与 MGR 指标 9104

角色创建并管理三个平台身份:

  • dbuser_cluster@'%':要求 TLS 的 AdminAPI 与 Router 引导身份(仅 HA 集群创建);
  • dbuser_monitor@'127.0.0.1':最小权限 Exporter 身份;
  • dbuser_backup@'localhost':本地 XtraBackup 身份。

平台支持

原生软件包平台门禁为:

架构 支持的系统
x86_64 EL 8/9/10、Debian 12/13、Ubuntu 22/24
aarch64 EL 9/10

Debian/Ubuntu ARM64 会被预检拒绝:Oracle APT 仓库的 MySQL 8.4 组件没有 arm64 载荷。ARM 环境请使用 EL 9/10(如 Rocky Linux)。


能力边界

MYSQL 是固定平台,不是通用 MySQL 安装器。以下事项 有意不做,使用前请确认可以接受:

  • 拓扑固定为 1 或 3 节点:不支持 1→3 原地升级、3→5 扩容或长期两节点拓扑;容量升级通过逻辑迁移完成,硬件更换通过 同地址替换 完成
  • 版本、端口、目录、字符集固定:不暴露相应参数;内存参数按节点规格自动推导,可用 mysql_parameters 覆盖关键参数
  • 备份为每日本地全量:无增量链、无 Binlog 连续归档、无 PITR;物理恢复是手工流程(附 操作手册
  • 完全停机恢复保留为手工操作:防止自动化误判造成脑裂,剧本失败信息会给出恢复指引
  • 无 VIP / DNS / HAProxy 接入层:客户端通过任一成员的 Router 端口或多地址 DSN 接入

文档目录

文档 说明
集群配置 拓扑规划、身份参数、业务库表用户、参数覆盖与备份配置
参数参考 11 项公开参数与固定平台约定
日常管理 状态检查、客户端接入、配置变更、故障处理与三份恢复手册
预置剧本 mysql.ymlmysql-rm.yml 的用法、标签与安全护栏
监控告警 Dashboard、衍生规则、告警规则与日志查询
指标定义 标签模型与衍生指标字典
常见问题 平台限制、主键要求、恢复与排障

快速开始

在清单中声明集群(完整模板见 conf/demo/mysql.yml):

all:
  children:
    my-test:
      hosts:
        10.10.10.11: { mysql_seq: 1 }
        10.10.10.12: { mysql_seq: 2 }
        10.10.10.13: { mysql_seq: 3 }
      vars:
        mysql_cluster: my-test
        mysql_databases: [ { name: app } ]
        mysql_users: [ { name: app, password: DBUser.App, priv: { 'app.*': 'ALL PRIVILEGES' } } ]

  vars:
    node_repo_modules: node,infra,mysql   # 软件仓库需包含 mysql 模块
    mysql_root_password: MySQL.Root       # 生产环境必须修改示例密码
    mysql_monitor_password: MySQL.Monitor
    mysql_cluster_password: MySQL.Cluster

完成 NODE 纳管后执行部署:

./node.yml  -l my-test             # 节点纳管:仓库、共享 CA、监控代理
./mysql.yml -l my-test --check     # 预检完整三节点集群
./mysql.yml -l my-test             # 真实部署,三节点约 2 分钟

mysql -h 10.10.10.11 -P 6446 -u app -pDBUser.App \
  --ssl-mode=VERIFY_CA --ssl-ca=/etc/pki/ca.crt app   # 通过 Router 读写入口接入

部署后访问 Grafana 的 MySQL Overview Dashboard 查看集群状态。

18.1 - 集群配置

规划 MySQL 拓扑与身份,声明业务数据库、用户、参数覆盖与备份策略。

MYSQL 模块通过清单(Inventory)声明集群,mysql.yml 将现场收敛到声明状态。本页介绍拓扑规划与全部配置项的写法;参数细节见 参数参考


部署前检查

  • 目标节点已完成 NODE 纳管,共享 CA 已安装到 /etc/pki/ca.crt(由 node_ca 负责,MySQL 角色只签发叶证书);
  • 软件仓库包含 mysql 模块:node_repo_modules: node,infra,mysql,或本地仓库已缓存 repo_extra_packages: [mysql]
  • 平台在支持矩阵内:x86_64 的 EL 8/9/10、Debian 12/13、Ubuntu 22/24,或 aarch64 的 EL 9/10;
  • 三个平台密码(mysql_root_passwordmysql_monitor_passwordmysql_cluster_password)已改为生产值——预检会拒绝 CHANGE_ME 开头的占位密码。

身份参数

每套集群由清单分组声明,两个身份参数必填:

参数 层级 说明
mysql_cluster 集群 集群名,必须与清单分组名一致(成员须位于同名分组);也是备份目录与监控 cls 标签
mysql_seq 实例 单机为 1;HA 为连续的 1..3,同时作为 server_id

拓扑由成员数量决定:1 个成员是单机,3 个成员是 InnoDB Cluster,其他数量会被预检拒绝。mysql_seq=1 只是首次引导协调者,不代表运行时主库。

实例名为 {{ mysql_cluster }}-{{ mysql_seq }}(如 my-test-1)。清单中的主机地址(IP 或可解析主机名)就是 MySQL 与 MGR 的通告地址,部署后不可通过普通重跑变更。


单机实例

最小可用的单机声明:

my-meta:
  hosts:
    10.10.10.10: { mysql_seq: 1 }
  vars:
    mysql_cluster: my-meta

单机没有 Router(6446/6447 不存在),客户端直连 3306。备份、监控、TLS 与 HA 模式完全一致。


三节点 InnoDB Cluster

my-test:
  hosts:
    10.10.10.11: { mysql_seq: 1 }
    10.10.10.12: { mysql_seq: 2 }
    10.10.10.13: { mysql_seq: 3 }
  vars:
    mysql_cluster: my-test
    mysql_databases:
      - { name: app }
    mysql_users:
      - name: app
        host: '%'
        password: DBUser.App
        connlimit: 20
        priv: { 'app.*': 'ALL PRIVILEGES' }

部署后形成单主 MGR:一个 PRIMARY 可写,两个 SECONDARY 只读,容忍一台故障。每个成员运行 Router,从任一成员的 6446 都能到达当前主库。

每次操作都要选择完整集群

所有 mysql.yml 操作必须用 -l 选中该集群的 全部成员(或不加 -l 收敛所有 MySQL 集群)。部分成员选择会在预检阶段被拒绝,这是防止拓扑分歧的刻意设计。


业务数据库

mysql_databases 是增量声明的数据库列表:

mysql_databases:
  - { name: app }                                              # 默认 utf8mb4 / utf8mb4_0900_ai_ci
  - { name: app2, encoding: utf8mb4, collate: utf8mb4_general_ci }
字段 默认值 说明
name 必填 库名,[A-Za-z0-9_$-],不能使用系统库名
encoding utf8mb4 字符集
collate utf8mb4_0900_ai_ci 排序规则

每个条目只接受以上三个字段;额外字段会在预检阶段被拒绝。

声明是 增量收敛:重跑会创建缺失的库,但从列表删除条目不会 DROP 数据库。删除数据属于手工运维操作。

所有表都必须有主键

平台默认启用 sql_require_primary_key=ON:创建无主键表会报 ERROR 3750。这不是刁难——无主键表在 MGR 下只读不可写,还会在灾难恢复时阻塞 AdminAPI 重建集群。请为所有表定义主键(或使用不可见列主键);确有特殊需要时可通过 mysql_parameters 关闭。


业务用户

mysql_users 是增量声明的用户与授权列表:

mysql_users:
  - name: app                        # 用户名
    host: '%'                        # 授权来源,默认 '%'
    password: DBUser.App             # 必填,支持特殊字符
    connlimit: 20                    # MAX_USER_CONNECTIONS,0 为不限
    priv:                            # 授权映射:'库.表' -> 权限列表
      'app.*': 'ALL PRIVILEGES'
      'app2.*': 'SELECT, INSERT, UPDATE, DELETE'

授权范围写作 '库.表',两侧都可以用 * 通配(如 '*.*''app.*');权限值为逗号分隔的权限名。预检会校验用户名、host、权限范围与权限词的合法性,拒绝畸形声明。

行为约定:

  • 用户不存在则创建,存在则按声明更新密码与连接数上限;
  • priv 中的授权会被执行(GRANT),但 移除映射不会自动 REVOKE
  • 不能声明 rootdbuser_monitordbuser_clusterdbuser_backup 这些平台身份;
  • 服务端强制 TLS:客户端默认的 PREFERRED 模式会自动协商加密,明文连接(DISABLED)会被拒绝;建议显式使用 VERIFY_CA 校验证书。

参数覆盖

mysql_parameters 用于覆盖 [mysqld] 配置,追加渲染在托管配置末尾(同名参数后写生效):

my-test:
  vars:
    mysql_cluster: my-test
    mysql_parameters:
      max_connections: 500
      long_query_time: 2
      innodb_print_all_deadlocks: true   # 布尔渲染为 ON/OFF

规则与安全边界:

  • 键名须为普通选项名(字母开头,可含 ._-),值必须是单行标量;
  • 渲染后的配置仍会经过 mysqld --validate-config 校验,非法参数在部署阶段即失败,不会影响运行中的服务;
  • 平台保留参数不可覆盖:身份与协议(userpid_fileserver_iddatadirsocketportbind_addressmysqlx_bind_addressreport_hostmysqlx 等)、复制与插件(gtid_modeenforce_gtid_consistencylog_binrelay_logplugin_load*cloneplugin_cloneplugin_mysqlxgroup_replication_* 等)以及 TLS(require_secure_transportssl_*)由角色统一管理,声明即拒绝;
  • 参数变更会触发 编排式滚动重启:从库先行、主库殿后。

内存基线无需配置:缓冲池为节点内存的 25%(下限 256MB),Redo 容量为缓冲池一半(128MB–4GB),复制并行度按 CPU 推导。需要精确控制时用 mysql_parameters 覆盖 innodb_buffer_pool_size 等参数即可。


备份配置

mysql_backup_enabled: true            # 默认开启每日备份
mysql_backup_repo:
  local:
    path: /data/backups/mysql         # 本地备份根目录
    retention: 7                      # 保留最近 7 份全量

备份契约(详见 日常管理):

  • 每日一次 XtraBackup 全量物理备份,备份后立即 prepare,产出可直接恢复的目录;
  • 单机在本机备份;HA 由每个成员的定时器各自触发,但 只有当前 PRIMARY 真正执行,其余成员自动跳过;
  • 目录布局 <path>/<cluster>/<UTC 时间戳>/latest 符号链接原子指向最新一份,按 retention 剪枝;
  • 没有增量链、Binlog 归档与 PITR;单机场景的恢复点就是最近一次备份。
备份位置跟随主库

HA 集群发生主从切换后,新备份会落在新主库的本地磁盘上。恢复前请在 所有成员 上检查 latest 指向的时间戳,取最新的一份。异地容灾请自行同步备份目录(如 rclone/rsync 定时任务)。


平台凭据

mysql_root_password: MySQL.Root          # 本地 root(root@localhost,仅本机套接字)
mysql_monitor_password: MySQL.Monitor    # Exporter 监控身份
mysql_cluster_password: MySQL.Cluster    # AdminAPI / Router / 备份身份

凭据的生命周期约定:

  • 密码不能包含换行,不能保留 CHANGE_ME 前缀,预检强制校验;
  • HA 集群的 mysql_cluster_password 不能通过普通重跑轮换:它已写入集群 Metadata 与 Router 密钥环,隐式轮换会被预检拒绝(单机实例无此绑定,改清单重跑即生效);
  • mysql_root_password 同样不能隐式重置:现场 root 密码与声明不一致时任务会明确报错,避免误配置静默改密。

凭据材料落盘在 /etc/mysql/pigsty/(root 属主:目录 0700、文件 0600),包括 root 与集群身份的客户端配置文件,可供本机运维直接使用:

mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf        # 本机 root 会话
mysql --defaults-extra-file=/etc/mysql/pigsty/cluster.cnf     # 经本机 Router 的集群会话(仅 HA 成员)

完整示例

单机加三节点的完整参考(对应四节点沙箱):

all:
  children:
    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }

    my-meta:
      hosts:
        10.10.10.10: { mysql_seq: 1 }
      vars: { mysql_cluster: my-meta, node_cluster: my-meta }

    my-test:
      hosts:
        10.10.10.11: { mysql_seq: 1 }
        10.10.10.12: { mysql_seq: 2 }
        10.10.10.13: { mysql_seq: 3 }
      vars:
        mysql_cluster: my-test
        node_cluster: my-test
        mysql_databases:
          - { name: app }
        mysql_users:
          - { name: app, password: DBUser.App, priv: { 'app.*': 'ALL PRIVILEGES' } }
        mysql_parameters:
          max_connections: 500

  vars:
    version: v4.5.0
    admin_ip: 10.10.10.10
    region: china                        # 中国大陆使用 USTC/腾讯镜像
    node_repo_modules: node,infra,mysql
    node_tune: oltp

    mysql_root_password: MySQL.Root
    mysql_monitor_password: MySQL.Monitor
    mysql_cluster_password: MySQL.Cluster

完整模板见 conf/demo/mysql.yml。注意 conf/mysql.yml 是 OpenHalo(PostgreSQL 内核的 MySQL 兼容方案)模板,与本模块无关。

18.2 - 参数参考

MYSQL 模块 13 项公开参数:11 项部署参数、2 项受保护移除参数,以及固定平台约定。

MYSQL 部署角色刻意只公开 11 项参数,移除角色另有 2 项受保护运维参数。软件版本、端口、目录、字符集、TLS 路径与定时器表达式由角色统一固定,内存基线按节点规格推导;需要调整服务器行为时使用 mysql_parameters


参数概览

参数 层级 默认值 说明
mysql_cluster 集群 必填 集群名与身份
mysql_seq 实例 必填 单机 1;HA 连续 1..3
mysql_root_password 集群 DBUser.Root 本地 root 密码
mysql_monitor_password 集群 DBUser.Monitor Exporter 监控身份密码
mysql_cluster_password 集群 DBUser.Cluster AdminAPI/Router/备份身份密码
mysql_databases 集群 [] 增量收敛的业务数据库
mysql_users 集群 [] 增量收敛的业务用户与授权
mysql_parameters 集群/实例 {} [mysqld] 参数覆盖
mysql_backup_enabled 集群 true 每日全量备份定时器
mysql_backup_repo 集群 见下文 本地备份目录与保留份数
mysql_exporter_enabled 集群 true Exporter 与监控 Target

移除参数由 mysql-rm.yml 使用:

参数 层级 默认值 说明
mysql_safeguard 全局/集群/命令行 true 默认拒绝执行移除
mysql_rm_confirm 命令行 '' 必须精确匹配实例名或集群名

旧版页面曾出现的 mysql_rolemysql_servicesmysql_packagesmysql_datamysql_portmysql_replication_*mysql_*_username 等变量已不属于公开接口,请勿使用。


身份参数

mysql_cluster

必填的集群身份,必须与清单分组名一致(预检要求成员位于同名分组)。字母、数字或下划线开头,可含 ._-,最长 63 字符:

mysql_cluster: my-test

用于生成实例名(my-test-1)、MGR Group UUID(由集群名确定性推导)、备份目录(<repo>/my-test/)与监控标签 cls

mysql_seq

必填的实例序号。单机为 1;三节点必须是连续的 1、2、3,并直接作为 server_id

10.10.10.11: { mysql_seq: 1 }

mysql_seq=1 仅表示首次引导时的协调者;运行时主库由 MGR 选举决定,重跑剧本不会迁回主库。


凭据参数

mysql_root_password

本地 root@'localhost' 密码,仅限本机使用(套接字或回环地址)。不能包含换行,不能保留 CHANGE_ME 前缀:

默认值为 DBUser.Root

mysql_root_password: DBUser.Root

首次启动时设置;此后如果现场密码与声明不一致,任务会 拒绝隐式重置 并明确报错——修改 root 密码需要先手工 ALTER USER 再同步清单。

mysql_monitor_password

dbuser_monitor@'127.0.0.1' 密码,供 mysqld_exporter 使用,仅限本机回环地址、最多 3 连接、只读权限:

默认值为 DBUser.Monitor

mysql_monitor_password: DBUser.Monitor

mysql_cluster_password

dbuser_cluster@'%'(要求 TLS)与 dbuser_backup@'localhost' 共用的平台密码,用于 AdminAPI 集群管理、Router 引导与 XtraBackup:

默认值为 DBUser.Cluster

mysql_cluster_password: DBUser.Cluster

HA 集群中该密码写入集群 Metadata 与 Router 密钥环,不能通过普通重跑轮换:现场值与声明不一致时预检直接拒绝。单机实例无此绑定,改清单重跑即生效。


业务对象

mysql_databases

增量收敛的业务数据库列表,仅接受 name / encoding / collate 三个字段:

mysql_databases:
  - { name: app }
  - { name: app2, encoding: utf8mb4, collate: utf8mb4_general_ci }

只创建与更新,不会因移除条目而删除数据库。写法与校验规则见 集群配置

mysql_users

增量收敛的业务用户列表,字段 name / host / password / connlimit / priv

mysql_users:
  - name: app
    host: '%'
    password: DBUser.App
    connlimit: 20
    priv: { 'app.*': 'ALL PRIVILEGES' }

授权只增不减(移除映射不会 REVOKE);平台身份(root、monitor、cluster、backup)不可声明。写法与校验规则见 集群配置


mysql_parameters

[mysqld] 段参数覆盖字典,渲染在托管配置末尾,同名参数后写生效:

mysql_parameters:
  max_connections: 500
  long_query_time: 2
  innodb_buffer_pool_size: 2G
  innodb_print_all_deadlocks: true    # true/false 渲染为 ON/OFF

约束与行为:

  • 键名 [A-Za-z][A-Za-z0-9_.-]{0,63},值为单行标量;渲染后仍经 mysqld --validate-config 校验,写错参数在部署阶段失败而不影响运行中的实例;
  • 保留参数拒绝覆盖-/_ 写法同判):userpid_fileserver_iddatadirsocketportbind_addressmysqlx_bind_addressreport_hostgtid_modeenforce_gtid_consistencylog_binrelay_logrequire_secure_transportssl_cassl_certssl_keyplugin_loadplugin_load_addcloneplugin_clonemysqlxplugin_mysqlx,以及 group_replication_*plugin_group_replication*plugin_mysqlx_bind_addressssl_* 全族;
  • 变更后重跑 mysql.yml 触发编排式滚动重启(从库先行、主库殿后),HA 集群预期仅主库切换瞬间有秒级写中断;
  • 平台默认值中可覆盖的典型项:sql_require_primary_key(默认 ON)、long_query_time(默认 1)、binlog_expire_logs_seconds(默认 7 天)、内存类参数。

会话级动态参数(AdminAPI 通过 SET PERSIST 管理的少数复制参数)以运行时为准;角色会在每次收敛时把 group_replication_group_seeds 钉回声明成员表,避免持久化漂移。


备份参数

mysql_backup_enabled

是否启用每日备份定时器(mysql-backup.timer,每日触发、随机延迟 30 分钟内):

mysql_backup_enabled: true

设为 false 停用定时器,但保留备份脚本与配置。注意:若备份目录从未创建过(备份从未启用),手工触发会因目录缺失直接退出。

mysql_backup_repo

本地备份仓库定义,当前只支持 local 一种方式:

mysql_backup_repo:
  local:
    path: /data/backups/mysql     # 绝对路径,不能与数据目录重叠
    retention: 7                  # 保留最近 N 份已提交全量(1-9999)

目录布局与恢复流程见 日常管理


监控参数

mysql_exporter_enabled

是否启用 mysqld_exporter 与 VictoriaMetrics Target 注册:

mysql_exporter_enabled: true

设为 false 时停用 Exporter 服务,并将 /infra/targets/mysql/<实例>.yml 收敛为空列表(不删除文件;文件只由 mysql-rm.yml 删除)。


移除参数

mysql_safeguard

受保护移除的保险开关,默认值为 true。执行 mysql-rm.yml 时必须显式设置为 false,否则角色会拒绝继续:

./mysql-rm.yml -l my-test -e mysql_safeguard=false -e mysql_rm_confirm=my-test

mysql_rm_confirm

目标名称确认字符串,默认值为空。移除单个成员时必须精确等于实例名(例如 my-test-3);移除完整集群或单机实例时必须精确等于 mysql_cluster。该参数与 mysql_safeguard=false 缺一不可。


固定平台约定

以下值由角色固定或推导,不是 清单参数,列出供运维参考:

项目
软件版本 MySQL Server/Client/Shell/Router 8.4 LTS、Percona XtraBackup 8.4
端口 3306(Classic)、33060(X Protocol,单机仅回环)、33061(MGR)、6446/6447(Router RW/RO)、9104(Exporter);INFRA 角色以只读参考常量 mysql_exporter_port: 9104 生成监控配置,它不是 MYSQL 的公开参数
数据目录 /var/lib/mysql(Binlog 于 binlog/ 子目录,7 天过期)
配置文件 EL:/etc/my.cnf.d/pigsty.cnf;Debian/Ubuntu:/etc/mysql/mysql.conf.d/pigsty.cnf
服务单元 MySQL:EL 为 mysqld,Debian/Ubuntu 为 mysql;Router:mysqlrouter;Exporter:mysqld_exporter
凭据与脚本 /etc/mysql/pigsty/(root 属主:目录 0700、文件 0600
日志 错误日志 /var/log/mysql/error.log 并镜像到 Journald;慢查询 /var/log/mysql/slow.log(阈值 1s)
TLS 强制加密(require_secure_transport=ON);CA /etc/pki/ca.crt,叶证书 /etc/mysql/pki/
字符集 utf8mb4 / utf8mb4_0900_ai_ci
内存基线 缓冲池 = max(节点内存 × 25%, 256MB);Redo = clamp(缓冲池 × 50%, 128MB, 4GB)
复制 GTID 强制、sql_require_primary_key=ON、MGR 单主、故障切换读一致性 BEFORE_ON_PRIMARY_FAILOVER
数据目录标记 .pigsty-mysql-initialized(属主校验)与 .pigsty-mysql-retired(退役防护)

18.3 - 日常管理

MySQL 集群的状态检查、客户端接入、配置变更、故障处理,以及成员替换、物理恢复与完全停机恢复三份操作手册。

本页覆盖 MYSQL 模块的日常运维操作。总原则:声明状态改清单,收敛现场跑剧本——成员掉线、AdminAPI 状态漂移等多数异常,重跑一次 ./mysql.yml -l <集群> 即可自愈;只有三类破坏性场景(替换成员、恢复备份、完全停机恢复)需要按本页手册人工介入。


速查手册

操作 命令
部署 / 收敛集群 ./mysql.yml -l <集群>
预检(不改现场) ./mysql.yml -l <集群> --check
本机 root 会话 mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf
查看 MGR 拓扑 SELECT MEMBER_HOST,MEMBER_STATE,MEMBER_ROLE FROM performance_schema.replication_group_members;
AdminAPI 状态 mysqlsh 连接后 dba.getCluster().status()
手工触发备份 systemctl start mysql-backup(HA 上仅主库真正执行)
退役一个从库 ./mysql-rm.yml -l <IP> -e mysql_safeguard=false -e mysql_rm_confirm=<实例名>
下线整个集群 ./mysql-rm.yml -l <集群> -e mysql_safeguard=false -e mysql_rm_confirm=<集群名>

状态检查

本页命令需以 root 在集群成员上执行(/etc/mysql/pigsty/ 下的客户端配置与密钥仅 root 可读)。示例以 EL 为准:Debian/Ubuntu 上 MySQL 服务单元名为 mysql 而非 mysqld

在任意成员上确认服务与拓扑:

systemctl status mysqld mysqlrouter mysqld_exporter mysql-backup.timer

mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf -e "
  SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE, MEMBER_VERSION
  FROM performance_schema.replication_group_members ORDER BY MEMBER_HOST;"

健康的三节点集群应显示 3 行 ONLINE,其中恰好 1 个 PRIMARY。需要 AdminAPI 视角时:

mysqlsh --js -e '
shell.options.useWizards=false;
var pw = os.loadTextFile("/etc/mysql/pigsty/cluster-password").replace(/[\r\n]+$/, "");
shell.connect({user:"dbuser_cluster", password:pw, host:"127.0.0.1", port:3306,
  "ssl-mode":"VERIFY_CA", "ssl-ca":"/etc/pki/ca.crt"});
print(dba.getCluster().status());'

集群级健康也可以直接看 Grafana MySQL Overview,或查询衍生指标 mysql:cls:health(2 健康 / 1 降级 / 0 危险)。


客户端接入

HA 集群通过任一成员的 Router 端口接入,Router 自动跟随主从切换:

# 读写入口(当前主库)
mysql -h <任一成员> -P 6446 -u app -pDBUser.App --ssl-mode=VERIFY_CA --ssl-ca=/etc/pki/ca.crt app

# 只读入口(从库轮询)
mysql -h <任一成员> -P 6447 -u app -pDBUser.App --ssl-mode=VERIFY_CA --ssl-ca=/etc/pki/ca.crt app

接入建议:

  • 服务端强制 TLS,明文连接会被拒绝;普通客户端默认的 PREFERRED 模式即可自动协商加密,建议显式 VERIFY_CA(JDBC:sslMode=VERIFY_CA)并信任 Pigsty CA;
  • 模块不提供 VIP/DNS 接入层。为避免单一 Router 节点成为断点,应用侧建议配置 多地址 DSN,例如 JDBC jdbc:mysql://10.10.10.11:6446,10.10.10.12:6446,10.10.10.13:6446/app,或在应用侧负载均衡器中列出全部成员;
  • 单机集群没有 Router,直连 3306
  • 成员被隔离或失去多数派时,本机 Router 会主动拒绝读写连接(fail-safe),不会提供过期读。

实测参考:主库优雅停机的写中断约 3–4 秒,主库崩溃(kill -9)约 20 秒出头(默认驱逐参数),滚动重启期间从库重启对客户端无感。


管理数据库与用户

在清单中修改 mysql_databases / mysql_users 声明,然后收敛:

./mysql.yml -l my-test                      # 全量收敛
./mysql.yml -l my-test -t mysql_provision   # 只收敛业务对象(更快)

HA 集群的对象变更只会在当前主库执行并经复制生效。声明是增量语义:不会删库、删用户或回收授权;这三类操作请手工执行后同步清单。


修改集群参数

参数覆盖统一走 mysql_parameters

mysql_parameters:
  max_connections: 500
  long_query_time: 2
./mysql.yml -l my-test --check    # 预检:确认将要发生的变更
./mysql.yml -l my-test            # 应用:自动编排滚动重启

滚动重启的编排语义(实测验证):

  1. 配置渲染后先做 mysqld --validate-config 校验,写错参数当场失败、不动服务;
  2. 重启前检查集群健康:降级集群(少于 3 个 ONLINE)拒绝滚动重启,先恢复再变更;
  3. 从库逐台重启,每台等待回归 ONLINE 后再处理下一台;主库最后重启;
  4. 主库重启会触发一次自动主从切换,预期数秒写中断;对切换时机敏感的业务请安排变更窗口。

单机集群直接原地重启。


主从切换

模块不自动编排计划内主从切换(Switchover);需要时用 AdminAPI 手工执行:

mysqlsh --js -e '
shell.options.useWizards=false;
var pw = os.loadTextFile("/etc/mysql/pigsty/cluster-password").replace(/[\r\n]+$/, "");
shell.connect({user:"dbuser_cluster", password:pw, host:"127.0.0.1", port:3306,
  "ssl-mode":"VERIFY_CA", "ssl-ca":"/etc/pki/ca.crt"});
dba.getCluster().setPrimaryInstance("10.10.10.12:3306");   // 指定新主库
'

切换后 Router 自动跟随,无需重新配置。之后重跑 ./mysql.yml -l <集群> 确认收敛(运行时主库位置不属于声明状态,剧本不会把主库切回去)。


成员故障与自愈

故障中无需人工介入:主库崩溃后 MGR 约 20 秒内选出新主,Router 自动改道;崩溃成员由 systemd 拉起并自动重新入组。以下场景才需要动手:

现象 处理
某成员 MEMBER_STATE 长期 OFFLINE(进程在、GR 停了) 重跑 ./mysql.yml -l <集群>,剧本会将其 rejoin 回集群
成员反复无法入组,日志报 peers not configured 同上:收敛会把 group_replication_group_seeds 钉回声明值
网络分区恢复后成员未回归 等待约 1 分钟自动重连;仍未回归则重跑剧本
全部成员 OFFLINE 完全停机场景,见 完全停机恢复
机器损坏无法修复 替换故障成员

对应告警:MySQLClusterMemberOffline(WARN)、MySQLClusterNoPrimary / MySQLClusterQuorumLost(CRIT)。


替换故障成员

替换契约:新机器复用故障机的服务地址(清单不变),三步完成。假设 my-test-310.10.10.13)损坏:

# 1. 摘除故障成员。机器仍可达时使用退役剧本:
./mysql-rm.yml -l 10.10.10.13 -e mysql_safeguard=false -e mysql_rm_confirm=my-test-3

# 1b. 机器已彻底失联(SSH 不可达)时,剧本无法在其上执行;
#     改在任一健康成员上用 AdminAPI 强制摘除:
mysqlsh --js -e '
shell.options.useWizards=false;
var pw = os.loadTextFile("/etc/mysql/pigsty/cluster-password").replace(/[\r\n]+$/, "");
shell.connect({user:"dbuser_cluster", password:pw, host:"127.0.0.1", port:3306,
  "ssl-mode":"VERIFY_CA", "ssl-ca":"/etc/pki/ca.crt"});
dba.getCluster("my-test").removeInstance("10.10.10.13:3306", {force: true});'

# 2. 用同一地址准备新机器(重装系统),完成节点纳管
./node.yml -l 10.10.10.13

# 3. 对完整集群重新收敛:新成员将通过 Clone 自动重建数据并入组
./mysql.yml -l my-test --check
./mysql.yml -l my-test

要点:

  • 第 1 步的本质是把该地址从集群 Metadata 中摘除——只有不在 Metadata 中的地址才会走全新 Clone 路径。退役剧本要求 目标可达(在线 SECONDARY 或已脱离集群的成员);死机场景用 1b 的强制摘除代替;
  • 新机器必须是 全新状态(空数据目录、无 Router 密钥残留)——重装系统即可保证;带残留状态的"半新机器"会被预检或 Router 引导拒绝;
  • Clone 会全量复制数据,耗时与数据量成正比,期间集群保持可用(1 主 1 从在线);
  • 不支持在替换时更换成员地址,也不支持长期两节点运行。

下线与复活集群

下线整个集群(停止服务、注销监控、保留全部数据):

./mysql-rm.yml -l my-test -e mysql_safeguard=false -e mysql_rm_confirm=my-test

下线后每个成员的数据目录会留下退役标记 /var/lib/mysql/.pigsty-mysql-retired,它会 阻止普通 mysql.yml 重新接管,防止误操作复活已退役实例。确认要原地复活时,删除标记后重新收敛:

ansible my-test -b -a 'rm -f /var/lib/mysql/.pigsty-mysql-retired'
./mysql.yml -l my-test

单机实例两条命令即可复活。HA 集群 多一步:重跑会把服务拉起,但三个成员的 GR 都处于 OFFLINE(防脑裂:无人自举),剧本会以完全停机报错退出——继续按 完全停机恢复 第 3-4 步重建仲裁即可。

彻底销毁(删除数据目录、备份、软件包)不由剧本代劳,属于确认过备份的手工操作。


管理备份

systemctl list-timers mysql-backup.timer          # 查看下次备份时间
systemctl start mysql-backup                      # 手工触发(HA 上仅主库真正执行,从库自动跳过)
journalctl -u mysql-backup --since today          # 查看备份日志

备份目录布局(在 当前主库 的本地磁盘上):

/data/backups/mysql/<集群名>/
├── 20260729T053900Z/          # 一份已 prepare 的全量备份(可直接恢复)
│   ├── backup.ok              # 提交标记:只有完整成功的备份才有
│   ├── backup.log             # XtraBackup 执行日志
│   └── ...                    # InnoDB 数据文件
├── ...                        # 按 retention 保留最近 N 份
└── latest -> 20260729T053900Z # 原子指向最新一份

检查备份新鲜度(HA 集群要在 所有成员 上检查,因为备份跟随主库落盘):

ansible my-test -b -a 'ls -l /data/backups/mysql/my-test/latest'
备份告警缺口

当前版本没有备份新鲜度指标与告警:备份失败只能从 mysql-backup 日志(已接入 VictoriaLogs,Instance Dashboard 的 Router / Backup Logs 面板可查)发现。重要环境建议为备份日志配置外部巡检,并定期演练下文的恢复流程。


恢复物理备份

以下手册将单机实例恢复到最近一次备份(破坏性操作:备份之后的写入将丢失。恢复前确认 latest 时间戳可接受)。HA 集群的整簇重建同理:先在一台恢复出主库,其余成员走 Clone 重建。

# 0. 确认备份可用:必须存在 backup.ok
BK=/data/backups/mysql/my-meta/latest
sudo test -f $BK/backup.ok && sudo cat $BK/backup.ok

# 1. 停库并保留残骸(便于事后取证,确认无误后再删除)
sudo systemctl stop mysqld
sudo mv /var/lib/mysql /var/lib/mysql.destroyed

# 2. 回拷备份(备份已 prepare,无需再执行 --prepare)
sudo mkdir -p /var/lib/mysql && sudo chown mysql:mysql /var/lib/mysql && sudo chmod 750 /var/lib/mysql
sudo xtrabackup --copy-back --target-dir=$BK
sudo rm -f /var/lib/mysql/backup.ok /var/lib/mysql/backup.log   # 清除随备份带入的记录文件

# 3. 重建备份不包含的运行目录
sudo mkdir -p /var/lib/mysql/binlog /var/lib/mysql/tmp
sudo chown -R mysql:mysql /var/lib/mysql
sudo chmod 750 /var/lib/mysql/binlog /var/lib/mysql/tmp

# 4. 重建 Pigsty 数据目录属主标记(cluster/instance/topology 按实际实例填写)
echo '{"version": 1, "cluster": "my-meta", "instance": "my-meta-1", "topology": "standalone"}' | \
  sudo tee /var/lib/mysql/.pigsty-mysql-initialized > /dev/null
sudo chown mysql:mysql /var/lib/mysql/.pigsty-mysql-initialized
sudo chmod 600 /var/lib/mysql/.pigsty-mysql-initialized

# 5. EL 系统恢复 SELinux 上下文,然后启动
sudo restorecon -RF /var/lib/mysql 2>/dev/null || true
sudo systemctl start mysqld

# 6. 验证数据与 GTID 位点,并确认剧本可正常收敛
sudo mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf -e 'SELECT @@gtid_executed; SHOW DATABASES;'
./mysql.yml -l my-meta        # 应全绿收敛(changed=0 或仅例行项)

第 4 步的标记文件是 Pigsty 的数据目录属主凭证:缺失或内容不匹配时,mysql.yml 会拒绝接管恢复出的数据目录。HA 场景的 topology 值为 innodb_cluster,实例名按成员各自填写。


完全停机恢复

三个成员全部 OFFLINE(机房断电、级联故障)时,MGR 出于防脑裂考虑 不会自动重建仲裁mysql.yml 也会明确拒绝并在报错中给出指引。恢复流程:

# 1. 确认所有成员的 mysqld 进程在运行(systemd 通常已自动拉起),GR 全部 OFFLINE
ansible my-test -b -a "mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf -NBe \
  \"SELECT COALESCE((SELECT MEMBER_STATE FROM performance_schema.replication_group_members \
  WHERE MEMBER_ID=@@server_uuid),'OFFLINE')\""

# 2. 选出数据最新的成员:比较各成员 GTID,选执行集最大(或相等任选)的一台
ansible my-test -b -a "mysql --defaults-extra-file=/etc/mysql/pigsty/root.cnf -NBe 'SELECT @@gtid_executed'"

# 3. 在最新成员上用 AdminAPI 重建集群(把 10.10.10.12 换成第 2 步选出的地址)
mysqlsh --js -e '
shell.options.useWizards=false;
var pw = os.loadTextFile("/etc/mysql/pigsty/cluster-password").replace(/[\r\n]+$/, "");
shell.connect({user:"dbuser_cluster", password:pw, host:"10.10.10.12", port:3306,
  "ssl-mode":"VERIFY_CA", "ssl-ca":"/etc/pki/ca.crt"});
var c = dba.rebootClusterFromCompleteOutage("my-test");
print(c.status().defaultReplicaSet.status);'

# 4. 重跑剧本:仍处于 OFFLINE 的其余成员会被自动 rejoin,随后全绿收敛
./mysql.yml -l my-test

要点:

  • 第 3 步通常已把所有可达成员一并带回;个别成员仍 OFFLINE 时由第 4 步的剧本收敛完成 rejoin,无需逐台手工处理;
  • 若在少数成员上重建(其余机器已损坏),先完成重建恢复写入,再按 替换故障成员 补齐;
  • 重建完成前集群无法写入(super_read_only);多数场景下各成员仍可只读访问,个别曾被驱逐的成员可能处于 offline_mode 拒绝普通连接;
  • 平台默认 sql_require_primary_key=ON 已从源头拦截会阻塞该流程的无主键表。

平台密码的边界

三个平台密码的运维边界(详见 参数参考):

  • mysql_monitor_password:改清单后重跑即可轮换(Exporter 配置随之更新);
  • mysql_root_password:不支持隐式重置。轮换流程:主库手工 ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码'; → 更新清单 → 重跑收敛凭据文件;
  • mysql_cluster_password:HA 集群中与 Metadata 和 Router 密钥环绑定,普通重跑拒绝轮换(单机无此限制,改清单重跑即生效);当前版本没有 HA 自动轮换流程,如必须轮换请通过 AdminAPI 手工操作并同步全部成员的凭据文件后再更新清单。

18.4 - 预置剧本

使用 mysql.yml 与 mysql-rm.yml 完成部署、收敛、参数变更、成员退役与集群下线。

MYSQL 模块提供两个剧本:mysql.yml 负责部署与收敛,mysql-rm.yml 负责受保护的退役与下线。前者重复执行会向声明状态收敛;后者是独立的生命周期操作,每次真实执行前都必须重新核对范围、备份与精确确认值。


mysql.yml

对选中集群执行「检查 → 安装 → 引导 → 接入 → 业务对象 → 备份 → 监控」的完整收敛:

./mysql.yml -l my-test --check     # 预检:校验声明与现场,不做变更
./mysql.yml -l my-test             # 收敛一个集群(必须选中全部成员)
./mysql.yml                        # 收敛清单中所有 MySQL 集群

使用约定:

  • HA 集群必须整簇选择-l 只选中部分成员会在预检被拒绝(防止拓扑分歧);可以同时选中多个完整集群或不加 -l
  • 幂等:现场已符合声明时重跑为 changed=0,秒级完成;AdminAPI 成员操作(rejoin/Clone)之后的下一次运行可能出现一次收敛性 changed(复制种子钉回声明值),属预期行为;
  • check 模式:对全新节点只能预演到软件包安装(后续步骤依赖已安装的现场),对已部署集群可完整预演;
  • 首次三节点部署约 2 分钟:证书签发 → 配置初始化 → AdminAPI 建群 → 两个从库 Clone → 每成员 Router 引导 → 业务对象 → 备份与监控注册。

执行阶段与任务标签

mysql
├── mysql_check       # 校验身份、平台、凭据、参数与数据目录属主(always)
├── mysql_install     # 安装固定的 MySQL 8.4 平台软件包
├── mysql_bootstrap
│   ├── mysql_cert    # 签发并安装节点 TLS 叶证书
│   ├── mysql_config  # 渲染配置(含 mysql_parameters)、初始化空数据目录
│   ├── mysql_launch  # 启动/滚动重启 mysqld,收敛 root 与 AdminAPI 身份
│   └── mysql_cluster # 建立或收敛三节点 InnoDB Cluster(rejoin/Clone)
├── mysql_access
│   └── mysql_router  # 在 HA 成员上引导并校验 Router
├── mysql_provision   # 收敛平台身份与声明的业务库、用户
├── mysql_backup      # 安装备份脚本与每日定时器
├── mysql_monitor     # 配置 Exporter 并注册监控 Target
└── mysql_done        # 输出实例摘要

常用标签化运行:

./mysql.yml -l my-test -t mysql_provision    # 只收敛业务库与用户
./mysql.yml -l my-test -t mysql_backup       # 只收敛备份配置与定时器
./mysql.yml -l my-test -t mysql_monitor      # 只收敛 Exporter 与监控注册

参数与配置变更建议执行完整剧本(涉及滚动重启编排,见下节)。


配置变更与滚动重启

mysql_launch 阶段包含变更编排逻辑,当配置文件、证书或 systemd 单元发生变化时:

  1. 健康前置检查:HA 集群必须 3 成员 ONLINE 才允许滚动重启,降级集群直接拒绝(先修复后变更);
  2. 从库先行:按当前运行时角色(而非 mysql_seq)排序,从库逐台重启并等待回归 ONLINE
  3. 主库殿后:最后重启主库,触发一次自动切换(秒级写中断)。

单机集群直接原地重启。配置渲染阶段的 mysqld --validate-config 保证非法参数在触碰服务之前失败。


安全护栏

mysql.yml 的预检与收敛在以下情况 主动拒绝,错误信息会说明原因与处置:

拒绝场景 说明
部分成员选择 HA 操作必须选中全部成员
非法拓扑 成员数只能是 1 或 3,mysql_seq 必须连续
平台不支持 架构/系统不在支持矩阵(如 Ubuntu ARM64)
占位密码 CHANGE_ME 前缀密码未替换
数据目录不属主 数据目录缺失 Pigsty 标记,或标记属于其他集群/实例/拓扑
退役标记存在 mysql-rm.yml 下线过的实例,防止误复活
隐式密码变更 mysql_cluster_password 或现场 root 密码与声明不一致
非法参数覆盖 mysql_parameters 含保留参数、畸形键名或多行值
降级集群滚动重启 少于 3 成员 ONLINE 时拒绝配置类重启
非全新 Clone 目标 更换的成员必须是空数据目录的全新机器
完全停机 不自动重建仲裁,报错给出手工恢复指引

这些护栏能显著降低误操作风险,但不构成“绝不丢数据”的保证。绕过护栏的每个动作(如删除标记或清理数据目录)都必须是经过备份验证与精确范围确认的人工决定。


mysql-rm.yml

退役剧本接受三种范围,全部需要双重确认(mysql_safeguard=false + mysql_rm_confirm 精确等于目标名):

# 退役 HA 集群中的一个成员(目标须可达:在线 SECONDARY 或已脱离集群的成员)
./mysql-rm.yml -l 10.10.10.13 --check -e mysql_safeguard=false -e mysql_rm_confirm=my-test-3
./mysql-rm.yml -l 10.10.10.13         -e mysql_safeguard=false -e mysql_rm_confirm=my-test-3

# 下线整个 HA 集群
./mysql-rm.yml -l my-test -e mysql_safeguard=false -e mysql_rm_confirm=my-test

# 下线单机实例
./mysql-rm.yml -l my-meta -e mysql_safeguard=false -e mysql_rm_confirm=my-meta

执行内容与边界:

  • 单成员退役:用 AdminAPI(force: false)从集群摘除 ONLINE SECONDARY(或确认已脱离集群成员的摘除状态),随后停止本机服务。摘除脚本在目标机上执行,因此 要求目标可达;机器已死亡时改用手工强制摘除(见 替换故障成员)。不允许直接退役主库(先 setPrimaryInstance 切走),也不允许一次退役 3 成员中的 2 个;
  • 整簇下线:停止 Router 与备份定时器 → 从库先停、主库最后 → 注销 Exporter 与监控 Target;
  • 每个数据目录写入退役标记 .pigsty-mysql-retired,阻止普通 mysql.yml 重新接管;
  • 保留一切数据:数据目录、备份、配置、证书、软件包、Metadata、Router 身份全部原样保留。彻底销毁是另一件事,请在确认备份后手工执行。

预览模式(--check)会完整展示将要发生的动作而不触碰现场。


剧本边界

以下操作 不属于 剧本职责,对应的人工流程见 日常管理

  • 计划内主从切换(setPrimaryInstance);
  • 不可达死机成员的强制摘除(removeInstance + force: true);
  • 完全停机后的仲裁重建(rebootClusterFromCompleteOutage);
  • 物理备份恢复(XtraBackup copy-back 手册);
  • 删除数据目录 / 备份 / 退役标记等销毁类动作;
  • 拓扑变形(1→3、3→5)与成员改址。

18.5 - 监控告警

MySQL 指标采集、Grafana Dashboard、告警规则与日志查询。

MYSQL 模块复用 Pigsty 的可观测性基座:指标经 mysqld_exporter 进入 VictoriaMetrics,错误日志经 Journald/Vector 进入 VictoriaLogs,Grafana 提供 5 个预置 Dashboard,vmalert 加载 68 条衍生规则与 27 条告警规则。


采集架构

每个 MySQL 节点运行一个 mysqld_exporter(端口 9104),以最小权限监控账号(dbuser_monitor@'127.0.0.1')采集服务器与 MGR 指标。部署时在 Infra 节点生成文件发现 Target:

/infra/targets/mysql/<实例名>.yml     # 如 my-test-1.yml

VictoriaMetrics 的 mysql 抓取任务消费该目录。mysql_exporter_enabled: false 会把 Target 收敛为空;只有 mysql-rm.yml 才删除 Target 文件。

Exporter 启用的采集器包括:全局状态/变量、Binlog 尺寸、InnoDB 指标、进程列表、性能模式语句摘要(Top 50 摘要)、表/索引 IO 等待,以及 MGR 成员与复制统计。


标签模型

所有 MySQL 指标携带统一标签:

标签 含义 示例
job 抓取任务 mysql
cls 集群名 my-test
ins 实例名 my-test-1
ip 成员地址 10.10.10.11
topology 拓扑类型 innodb_cluster / standalone

衍生规则以 mysql:ins:*(实例级)与 mysql:cls:*(集群级)命名,完整清单见 指标定义


Grafana Dashboard

Dashboard 用途
MySQL Overview 舰队总览:集群清单、健康度、QPS/TPS、活跃告警与实例清单
MySQL Cluster 单集群视角:成员状态、负载、节点资源与集群日志
MySQL Instance 单实例细节:连接、语句、InnoDB、临时表、锁与实例日志
MySQL Group Replication MGR 专题:成员角色、认证/应用队列、流控、只读安全与 GR 日志
MySQL Alert 告警汇总与关键平台日志

集群健康速读:mysql:cls:health 取值 2(健康)/ 1(降级仍可写)/ 0(危险或不可写),Overview 首屏的 Healthy Clusters 与 Cluster Health 时间线都基于它。

MySQL Group Replication Dashboard 仅对 innodb_cluster 拓扑有意义;选中单机集群时相关面板显示 No data 属预期现象。


告警规则

27 条告警规则按严重级分层(severity:CRIT / WARN / INFO),关键规则如下:

可用性与集群(响应优先)

告警 级别 触发条件
MySQLInstanceDown CRIT 实例连接失败超 1 分钟
MySQLClusterNoPrimary CRIT 集群无 ONLINE 主库超 1 分钟
MySQLClusterQuorumLost CRIT ONLINE 成员不足多数派超 1 分钟
MySQLClusterMultiplePrimary CRIT 出现多主(30 秒即告,脑裂信号)
MySQLSecondaryWritable CRIT 从库可写超 2 分钟(数据发散风险)
MySQLClusterMemberOffline WARN 声明成员离组超 5 分钟
MySQLPrimaryReadOnly WARN 主库只读超 5 分钟
MySQLExporterDown WARN Exporter 抓取失败超 2 分钟

容量与性能(观察优先)

连接压力(MySQLConnectionsHigh WARN 80% / MySQLConnectionsCritical CRIT 95%)、复制队列(MySQLGRQueueHigh WARN / MySQLGRQueueCritical CRIT)、流控(MySQLGRFlowControlHigh)、InnoDB(MySQLBufferPoolWaitsMySQLInnoDBLogWaitsMySQLRedoCapacityHighMySQLDeadlocksHighMySQLHistoryListLarge),以及 INFO 级的慢查询、磁盘临时表、全表连接、缓冲池命中率与重启提示。

实测行为参考:主库崩溃切换(约 20 秒)只会产生 pending 不会误报;真正的完全停机会在 2 分钟内让 ClusterNoPrimaryQuorumLost 进入 firing。


日志查询

MySQL 错误日志双写:本地文件 /var/log/mysql/error.log + Syslog → Journald → Vector → VictoriaLogs。日志条目携带 app=mysqld-<实例名> 标识,Dashboard 的日志面板开箱可用,也可直接用 LogsQL 查询:

# 某实例最近的错误日志
curl -s http://<infra>:9428/select/logsql/query \
  -d 'query=app:mysqld-my-test-1 level:err _time:1h'

# 某集群全部 MySQL 相关日志(含备份任务)
curl -s http://<infra>:9428/select/logsql/query \
  -d 'query=job:syslog cls:my-test (app:~"mysqld-" OR unit:mysql-backup) _time:1h | limit 100'

注意日志的 cls 标签取自 节点 集群名(node_cluster)——像配置示例那样保持 node_clustermysql_cluster 一致,指标与日志的标签才能对齐。

已知边界:

  • 慢查询日志slow.log,阈值 1 秒)仅落本地文件,不进入 VictoriaLogs;分析慢查询请登录实例查看文件,或使用性能模式语句摘要指标(mysql:ins:statement_latency 等);
  • Router 运行日志 写入 /var/log/mysqlrouter/,同样仅限本地文件。

验证监控链路

部署后可用以下命令自检全链路:

# Exporter 本体
curl -s http://<成员>:9104/metrics | grep -E '^mysql_up '

# VictoriaMetrics 抓取与衍生规则
curl -s 'http://<infra>:8428/api/v1/query?query=mysql_up'
curl -s 'http://<infra>:8428/api/v1/query?query=mysql:cls:health'

# vmalert 规则装载(应看到 mysql-rules 与 mysql-alerts 两组)
curl -s 'http://<infra>:8880/api/v1/rules' | grep -o '"name":"mysql-[a-z]*"'

# 日志入库
curl -s 'http://<infra>:9428/select/logsql/query' -d 'query=app:~"mysqld-" _time:1h | stats by (app) count()'

18.6 - 指标定义

MySQL 模块的标签模型、衍生指标字典与原始指标族。

MYSQL 模块的指标来自 mysqld_exporter(原始指标,mysql_ 前缀)与 vmalert 衍生规则(mysql:ins:* / mysql:cls:*)。Dashboard 与告警优先建立在衍生指标之上,本页是衍生指标的完整字典。


公共标签

所有指标携带 job=mysql 与身份标签 cls / ins / ip / topology(取值 standaloneinnodb_cluster)。实例级衍生指标保留全部身份标签,集群级指标聚合到 cls + topology


可用性

指标 含义
mysql:ins:exporter_up Exporter 抓取是否成功(传输层健康)
mysql:ins:up MySQL 连接探测是否成功(数据库健康)
mysql:ins:uptime 实例运行时长(秒)
mysql:cls:instances 集群声明实例数
mysql:cls:up 集群在线实例数
mysql:cls:health 集群健康度:2 健康 / 1 降级可写 / 0 危险

mysql:cls:health 对 HA 集群综合仲裁、单主与全员在线状态;对单机取 2 × mysql:cls:up


工作负载

指标 含义
mysql:ins:qps 每秒问询数(Questions)
mysql:ins:tps 每秒事务数(Commit + Rollback)
mysql:ins:read_qps / mysql:ins:write_qps 读类 / 写类命令速率
mysql:ins:row_ops InnoDB 行操作速率(读/插/改/删分维度)
mysql:ins:statement_rate 性能模式语句执行速率
mysql:ins:statement_latency 语句平均时延(秒)
mysql:ins:rows_examined_per_query 平均每查询扫描行数
mysql:ins:statement_errors 语句错误率
mysql:ins:slow_queries / mysql:ins:slow_query_ratio 慢查询速率与占比
mysql:ins:no_index_queries 未走索引查询速率

连接与会话

指标 含义
mysql:ins:connections 当前连接数(Threads_connected)
mysql:ins:connection_usage 连接数 / max_connections 使用率
mysql:ins:connection_rate 新建连接速率
mysql:ins:threads_running / mysql:ins:threads_cached 活跃 / 缓存线程数
mysql:ins:aborted_connects / mysql:ins:aborted_clients 失败握手 / 异常断开速率
mysql:ins:connection_errors 连接错误总速率
mysql:ins:rx_bytes / mysql:ins:tx_bytes 网络收 / 发字节率

临时表、扫描与缓存

指标 含义
mysql:ins:tmp_tables / mysql:ins:tmp_disk_tables 内存 / 磁盘临时表创建速率
mysql:ins:tmp_disk_ratio 磁盘临时表占比
mysql:ins:full_joins / mysql:ins:full_scans 无索引连接 / 全表扫描速率
mysql:ins:sort_merge_passes 排序归并趟数(sort_buffer 不足信号)
mysql:ins:table_open_cache_hit_ratio 表缓存命中率
mysql:ins:open_files_usage 打开文件数使用率

InnoDB

指标 含义
mysql:ins:buffer_pool_hit_ratio 缓冲池命中率
mysql:ins:buffer_pool_usage / mysql:ins:buffer_pool_dirty_ratio 缓冲池使用率 / 脏页占比
mysql:ins:buffer_pool_waits 缓冲池空闲页等待速率(内存压力信号)
mysql:ins:data_read_bytes / mysql:ins:data_write_bytes 数据文件读 / 写字节率
mysql:ins:data_reads / mysql:ins:data_writes / mysql:ins:data_fsyncs 数据文件 IO 与 fsync 速率
mysql:ins:redo_bytes Redo 写入字节率
mysql:ins:redo_utilization Redo 容量使用率(检查点落后度)
mysql:ins:log_waits Redo 缓冲等待速率
mysql:ins:row_lock_waits / mysql:ins:row_lock_time 行锁等待速率 / 耗时
mysql:ins:deadlocks 死锁速率
mysql:ins:history_list_length Purge 滞后(历史链表长度)
mysql:ins:binlog_bytes Binlog 当前磁盘占用总量(字节)

Group Replication

实例级成员状态(取值为 1 或缺失——不满足条件时序列不存在,告警据此用 unless 判断):

指标 含义
mysql:ins:gr_member 本实例处于任意 MGR 成员状态
mysql:ins:gr_online 本实例 ONLINE
mysql:ins:gr_primary / mysql:ins:gr_secondary 本实例为 ONLINE 主库 / 从库

集群级仲裁与拓扑:

指标 含义
mysql:cls:gr_online_members ONLINE 成员数
mysql:cls:gr_primary_members ONLINE 主库数
mysql:cls:gr_quorum 是否保有多数派(0/1)
mysql:cls:gr_single_primary 是否恰好单主(0/1)

复制管道(认证与应用):

指标 含义
mysql:ins:gr_certifier_queue / mysql:ins:gr_applier_queue 认证 / 应用队列积压事务数
mysql:ins:gr_certifier_queue_ratio / mysql:ins:gr_applier_queue_ratio 队列积压相对流控阈值的占比
mysql:ins:gr_checked_rate / mysql:ins:gr_applied_rate 事务认证 / 应用速率
mysql:ins:gr_conflict_rate 认证冲突速率(多写冲突信号,单主下应为 0)

原始指标族

衍生指标未覆盖的细节可直接查询 Exporter 原始指标,常用族:

前缀 内容
mysql_up / up 数据库连接探测 / 抓取状态
mysql_global_status_* SHOW GLOBAL STATUS 全量计数器
mysql_global_variables_* 关键系统变量(如 max_connections
mysql_perf_schema_events_statements_* 语句摘要(按 digest Top 50)
mysql_perf_schema_table_io_waits_* / ..._index_io_waits_* 表 / 索引 IO 等待
mysql_perf_schema_replication_group_member_info MGR 成员状态(member_state / member_role 维度)
mysql_perf_schema_transactions_* / mysql_perf_schema_conflicts_detected_total MGR 认证队列、应用队列与冲突统计
mysql_binlog_* Binlog 文件数与尺寸
mysql_info_schema_processlist_* 会话按状态分布

在 VictoriaMetrics 的 vmui(/select/vmui)中以 mysql_ 前缀浏览即可获得完整清单。

18.7 - 常见问题

Pigsty MySQL 试点模块常见问题与故障排查。

当前 MYSQL 模块是什么成熟度?

Pilot 试点模块,定位「简单、廉价、够用」的 MySQL 集群。部署收敛、高可用切换、每日备份、监控告警四大核心能力经过系统性实测(含故障注入与完全停机演练);恢复类破坏性流程刻意保留为手工操作并配有 操作手册。不追求与 PGSQL 模块同级的完备度:没有 PITR、没有接入层 VIP/DNS、没有自动扩缩容。用于严肃生产环境前,请按业务要求验证并演练恢复流程。

为什么固定 MySQL 8.4,不能选版本?

MYSQL 是「固定平台」而不是通用安装器:Server、Client、Shell、Router、XtraBackup 全线锁定 8.4 LTS,保证组件间兼容与行为可预期,省去版本矩阵的测试与踩坑成本。这是试点模块控制复杂度的核心取舍;需要其他版本或深度定制时,本模块不适合。

为什么只支持 1 或 3 节点?怎么扩容?

拓扑固定为单机或三节点单主 InnoDB Cluster,预检拒绝其他成员数,也不支持 1→3 原地升级(数据目录标记会拦截拓扑变更)。原因:动态成员数会引入仲裁、Router 重引导与收敛路径的组合复杂度,超出试点模块的收益。

扩容路径:

  • 纵向:换更大机器,走 同地址替换 逐台完成(滚动换硬件);
  • 单机 → HA:新建三节点集群,用 mysqldump/mysqlsh util.dumpInstance 逻辑迁移;
  • 读扩展:只读流量走 6447 由两个从库分担。

为什么建表报 ERROR 3750(要求主键)?

平台默认 sql_require_primary_key=ON。无主键表在 Group Replication 下 只读不可写,还会在完全停机恢复时阻塞 AdminAPI 重建集群——与其让它在灾难现场爆炸,不如在建表时拦截。请为所有表定义主键;接入既有系统确实无法改表时,可用参数覆盖关闭:

mysql_parameters: { sql_require_primary_key: false }

单机实例同样默认开启,以保证未来能平滑迁往 HA。

为什么 Ubuntu/Debian ARM64 被拒绝?

Oracle 的 APT 仓库没有为 MySQL 8.4 提供 arm64 软件包,这不是 Pigsty 能绕过的。ARM 环境(含 Apple Silicon 上的虚拟机)请使用 EL 9/10(Rocky/Alma),Oracle 的 YUM 仓库提供完整 aarch64 支持。

客户端应该连哪个端口?TLS 是必须的吗?

HA 集群连任一成员的 6446(读写)/6447(只读),Router 自动跟随主从切换;单机直连 3306。TLS 是强制的:服务端 require_secure_transport=ON,明文连接直接被拒(ERROR 3159)。普通客户端默认的 PREFERRED 模式即会自动协商加密(只有显式 DISABLED 才会被拒);建议显式 VERIFY_CA 并信任 /etc/pki/ca.crt

Router 是每节点本地部署,没有统一 VIP。应用侧请使用多地址 DSN(把三个成员的 6446 都写进连接串)以规避单节点故障。

主库切走了,会自动切回来吗?

不会,也不需要。mysql_seq=1 只是首次引导顺序,运行时主库由 MGR 选举决定;故障切换或滚动重启后主库落在哪台都是合法状态,重跑剧本不会移动主库。需要指定主库时用 setPrimaryInstance 手工切换。

某个成员掉线了怎么办?

绝大多数情况下什么都不用做:进程崩溃由 systemd 拉起并自动重新入组(实测主库崩溃约 20 秒完成切换与自愈)。如果成员长期停留在 OFFLINE(如网络分区恢复后、或 STOP GROUP_REPLICATION 之后),重跑一次 ./mysql.yml -l <集群> 即可将其 rejoin。仍失败时看剧本报错——错误信息会说明原因与下一步动作。

三台全挂了怎么恢复?

这是唯一需要手工介入的可用性场景(防脑裂的刻意设计):在数据最新的成员上执行 dba.rebootClusterFromCompleteOutage(),然后重跑剧本收敛其余成员。完整步骤见 完全停机恢复手册mysql.yml 在这种状态下的报错会直接给出该指引。

备份在哪里?能恢复到任意时间点吗?

备份是 每日一次的全量物理备份,落在 当前主库/data/backups/mysql/<集群>/ 下(主从切换后新备份跟随新主库,检查时要看所有成员)。没有增量与 Binlog 归档,因此 不支持 PITR:单机的恢复点就是最近一次备份(最坏损失一天写入);HA 集群的数据安全主要靠三副本同步复制,备份用于兜底与整簇重建。恢复步骤见 恢复物理备份手册。异地容灾请自行同步备份目录。

备份失败会有告警吗?

当前版本没有备份专属指标与告警(已知缺口)。备份日志已接入 VictoriaLogs(unit:mysql-backup),Instance Dashboard 的 Router / Backup Logs 面板可查;重要环境建议对备份日志做外部巡检,并定期做恢复演练验证备份可用性。

为什么 mysql_parameters 里有些参数被拒绝?

身份(server_iddatadir、端口等)、复制(gtid_modelog_bingroup_replication_*)与 TLS 全族是平台保证的一部分,被列为保留参数——覆盖它们会破坏集群身份或安全底线,预检直接拒绝(-_ 写法同判)。其余参数放行,且渲染后仍经 mysqld --validate-config 校验。完整保留清单见 参数参考

修改参数会导致停机吗?

会有一次可控的秒级抖动:参数变更触发编排式滚动重启,从库逐台先行(客户端无感),主库最后重启并触发一次自动切换(实测写中断约 3–4 秒)。降级集群会拒绝滚动重启,避免雪上加霜。对切换敏感的业务请安排变更窗口。

怎么修改 root 或平台密码?

  • mysql_monitor_password:改清单重跑即可(Exporter 配置随之刷新);
  • mysql_root_password:为防止误配置静默改密,剧本拒绝隐式重置——先手工 ALTER USER 'root'@'localhost' ...,再更新清单重跑;
  • mysql_cluster_password:HA 集群中与 Metadata、Router 密钥环绑定,普通重跑拒绝轮换(单机改清单重跑即生效),当前无 HA 自动轮换流程;如必须轮换,请通过 AdminAPI 手工操作并同步各成员凭据文件后再更新清单。

下线的集群怎么复活?误删了退役标记会怎样?

mysql-rm.yml 下线时保留全部数据并写入退役标记;复活 = 删除各成员的 /var/lib/mysql/.pigsty-mysql-retired 后重跑 mysql.yml(见 下线与复活集群)。单机两步即可;HA 集群还需按 完全停机恢复 重建仲裁。标记的意义是防止「下线后被无意重新拉起」;数据目录属主校验(.pigsty-mysql-initialized)独立存在,删除退役标记不会让别的集群接管这份数据。

conf/mysql.yml 模板怎么和这个模块对不上?

那是 OpenHalo 模板——基于 PostgreSQL 内核的 MySQL 线缆协议兼容方案(pg_mode: mysql),与本模块无关。原生 MySQL 模块的参考模板是 conf/demo/mysql.yml。选型参考:需要真 MySQL 生态兼容用本模块;PG 基础设施上跑 MySQL 协议应用可考虑 OpenHalo。

剧本失败显示 no ONLINE member holds the cluster

这是完全停机(或仅存成员不可达)的判定:没有任何 ONLINE 成员持有集群。按报错给出的指引执行 完全停机恢复。如果实际上有成员在线却报此错,先检查 seq=1 协调成员(收敛脚本在其上执行)到各成员 3306 的连通性,以及该成员上的 CA(/etc/pki/ca.crt)是否就位。

监控没有数据 / Dashboard 空白?

按链路排查:curl http://<成员>:9104/metrics | grep mysql_up(Exporter 本体)→ Infra 上确认 /infra/targets/mysql/ 有实例文件 → VictoriaMetrics 查询 up{job="mysql"}。GR Dashboard 选中了单机集群时 MGR 面板显示 No data 属正常现象。完整自检命令见 监控告警