- 数据库
- 运维
- 云原生
- 高可用
- 监控
【免费下载链接】pigsty
Enterprise-Grade OSS PostgreSQL Distribution with HA, PITR, IaC, Monitor, 12 kernel forks and 575 PG extensions. Best-of-breed products integrated as a platform. Self-host Postgres like a Pro!
本指南以 Pigsty 仓库中的 roles/pg_exporters/README.md 为骨架,结合 pgsql-monitor.yml、roles/pg_exporters/tasks 源码与 conf/demo/remote.yml 真实配置,系统讲解如何在不向目标主机部署任何 Agent 的前提下,把 AWS/Azure/GCP/阿里云 RDS 等非 Pigsty 托管的远程 PostgreSQL 实例纳入 Pigsty 统一监控体系。读完本文,你将掌握
pg_exporters的架构原理、清单配置语法、连接串生成规则、远程端 SQL/HBA 准备以及维多利亚指标(VictoriaMetrics)与 Grafana 注册的完整链路。
一、角色概览:什么是 pg_exporters
pg_exporters是 Pigsty 中负责远程 PostgreSQL 监控的 Ansible Role。它的核心思想是:不在远程 PostgreSQL 所在主机上安装任何采集组件,而是在infra 节点(监控节点)本地部署pg_exporter,通过数据库协议直连远端实例拉取指标,再接入本地监控栈。
从 roles/pg_exporters/meta/main.yml 可以看到,该角色在 Ansible Galaxy 中的定位是deploy multiple pg_exporters(部署多个 pg_exporter),支持 EL/Ubuntu/Debian 全系列平台。与本地监控角色 pg_monitor 和基础设施监控角色 infra 互为补充。
典型适用场景
- 监控云上 RDS 实例:AWS RDS、Azure Database、GCP Cloud SQL、阿里云 RDS/PolarDB 等托管数据库;
- 监控 Pigsty 之外的 PostgreSQL 集群:例如既有存量数据库、异构环境中的 PostgreSQL;
- 集中式监控:目标主机不允许安装 Agent(安全性、合规性或托管平台限制),只需一个可被 infra 节点访问的数据库端口即可。
一个重要边界
该角色只采集 PostgreSQL 本身的指标。远程实例的 Node、pgBouncer、Patroni、HAProxy 指标均不可用,日志采集同样不支持——这些依赖本机 Agent 的组件天然无法通过远程方式获得。
二、架构与数据流
pgsql-monitor.yml(Playbook 文件)是该功能唯一的入口,其内部头注释绘制了清晰的拓扑:
------ infra ------ | | | victoria | v---- pg-foo-1 ----v | ^ | metrics | ^ | | pg_exporter <-|------------|---- postgres | | (port: 20001) | | 10.10.10.10:5432 | | ^ | ^------------------^ | pg_exporter <-|------------|---- postgres | | (port: 20002) | | 10.10.10.11:5433 | ------------------- ^------------------^数据流分三段:
- 采集:infra 节点上每个
pg_exporter进程通过 PostgreSQL 协议连接远端实例(默认端口 5432,可配置),执行预定义的采集 SQL; - 暴露:
pg_exporter在本地监听一个独占端口(如 20001、20002),以 Prometheus 文本格式暴露/metrics端点; - 汇聚与展示:本地 VictoriaMetrics 按端口抓取这些指标,同时 Grafana 注册对应的 PostgreSQL 数据源,最终呈现监控面板。
从 roles/pg_exporters/tasks/main.yml 看,角色内部按三条流水线工作:
pg_exporter.yml:为每个条目渲染采集器配置、环境变量、systemd 单元并启动服务;add_metrics:把每个pg_cluster写入/infra/targets/pgrds/<cluster>.yml,作为 VictoriaMetrics 的抓取目标;add_ds:为每个pg_databases中声明的数据库生成并注册 Grafana PostgreSQL 数据源。
三、快速上手:Playbook 与 Tags
角色提供了清晰的标签(Tags)层级,便于精细控制执行范围:
pg_exporters # 设置远程 pg_exporter 实例 ├── pg_register # 注册到监控系统 │ ├── add_metrics # 注册到 Victoria Metrics │ └── add_ds # 注册到 Grafana 数据源常用命令示例(在仓库根目录执行):
# 设置所有远程 exporter ./pgsql-monitor.yml -t pg_exporters # 仅注册到监控(不重建 exporter) ./pgsql-monitor.yml -t pg_register # 仅操作指定集群 ./pgsql-monitor.yml -e clsname=pg-fooPlaybook 本身(pgsql-monitor.yml)定义如下:
- name: PGSQL MONITOR become: true hosts: infra gather_facts: no ignore_errors: true vars: { clsname: '' } # 指定时仅处理单个集群 roles: - { role: node_id , tags: id } # 获取节点身份(始终执行) - { role: pg_exporters , tags: exporter } # 设置 exporters注意hosts: infra:所有pg_exporter都部署在infra 节点上,且clsname变量可在命令行通过-e覆盖,实现"只初始化某个远程集群"的增量运维。ignore_errors: true保证了单个实例配置失败不会中断整批部署,配合wait_for轮询端口上线,具备一定的容错能力。
四、核心配置:pg_exporters 清单定义
pg_exporters是一个以本地端口为键(key)、以远程实例描述为值(value)的字典,定义在 infra 组变量中。每个条目把"一个本地端口"映射到"一个远程实例":
pg_exporters: <local_port>: pg_cluster: <cluster_name> # 必填:集群名称 pg_seq: <sequence_number> # 必填:实例序号 pg_host: <remote_ip> # 必填:远程 PostgreSQL IP 或域名 pg_port: 5432 # 可选:PostgreSQL 端口,默认 5432 pg_dbsu: postgres # 可选:数据库超级用户 pg_monitor_username: dbuser_monitor # 可选:监控用户 pg_monitor_password: DBUser.Monitor # 可选:监控密码 pg_exporter_url: '' # 可选:覆盖连接 URL pg_exporter_config: pg_exporter.yml # 可选:采集器配置文件名 pg_databases: [] # 可选:注册 Grafana 数据源的数据库列表字段的取值优先级从 tasks/main.yml 的实现可以明确看出:条目级 > 主机级(hostvars)> 全局默认值。例如pg_port的解析逻辑是:
"{% if 'pg_port' in item.value %}{{ item.value.pg_port }} {% elif 'pg_port' in hostvars[inventory_hostname] %}{{ hostvars[inventory_hostname].pg_port }} {% else %}5432{% endif %}"pg_monitor_username与pg_monitor_password同样遵循该三级回退规则(默认dbuser_monitor/DBUser.Monitor)。因此你既可以全局统一定义监控账号,也可以为个别实例单独覆盖——这是连接云上不同 RDS 账号时的关键能力。
生产级示例:监控阿里云 PolarDB 与 RDS
conf/demo/remote.yml 提供了完整的实战配置,涵盖域名主机、自定义端口、独立账号、数据库白名单与 Grafana 数据源:
infra: hosts: { 10.10.10.10: { infra_seq: 1 } } vars: pg_exporters: 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:DBUser.Monitor@10.10.10.12: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 集群名(身份标识) pg_seq: 1 # RDS 实例序号 pg_host: pxx.polardbpg.rds.aliyuncs.com # RDS 域名地址 pg_port: 1921 # RDS 端口 pg_exporter_include_database: 'test' # 仅监控该数据库列表 pg_monitor_username: dbuser_monitor # 覆盖默认监控用户 pg_monitor_password: DBUser_Monitor # 覆盖默认监控密码 pg_databases: [{ name: test }] # 注册到 Grafana 数据源的数据库 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 } ]该示例中pg_exporters也定义在infra.vars下,pg_host直接使用云厂商域名(如pgm-xx.pg.rds.aliyuncs.com),端口可以是非 5432(如 PolarDB 的 1921),并通过pg_monitor_username/pg_monitor_password为每个实例提供独立凭据,贴近真实混合云场景。
五、Exporter 参数与默认值
每个 exporter 实例还受以下全局/条目级参数控制(默认值见 defaults/main.yml):
| 变量 | 默认值 | 说明 |
|---|---|---|
pg_exporter_config | pg_exporter.yml | 采集器配置文件;使用其他文件名时从files/目录拷贝 |
pg_exporter_cache_ttls | 1,10,60,300 | 采集器 TTL 分级(秒),逗号分隔的四个阶段 |
pg_exporter_port | 9630 | pg_exporter 监听端口(条目级场景下被字典键覆盖) |
pg_exporter_params | sslmode=disable | DSN 附加连接参数 |
pg_exporter_url | '' | 显式覆盖自动生成的连接串 |
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_options | '' | 追加传给 pg_exporter 的额外启动参数 |
值得关注的是pg_exporter_cache_ttls:采集 SQL 按开销被划分为四个 TTL 档位(快/中/慢/最慢),例如基础信息用快速档(1 秒级),库大小统计用慢速档(60 秒级)。在 tasks/pg_exporter.yml 中它被解析为四个整数注入模板:
ttl_fast: "{{ pg_exporter_cache_ttls.split(',')[0]|int }}" ttl_norm: "{{ pg_exporter_cache_ttls.split(',')[1]|int }}" ttl_slow: "{{ pg_exporter_cache_ttls.split(',')[2]|int }}" ttl_slowest: "{{ pg_exporter_cache_ttls.split(',')[3]|int }}"六、连接 URL 的生成规则与覆盖
未显式指定pg_exporter_url时,连接串由 templates/pg_exporter.env 自动拼装:
postgres://<pg_monitor_username>:<pg_monitor_password>@<pg_host>:<pg_port>/postgres?<pg_exporter_params>例如默认参数下即为postgres://dbuser_monitor:DBUser.Monitor@<pg_host>:5432/postgres?sslmode=disable。该模板在渲染时的完整逻辑是:
{% if pg_exporter_url != '' %} # OVERWRITE by pg_exporter_url PG_EXPORTER_URL='{{ pg_exporter_url }}' {% else %} PG_EXPORTER_URL='postgres://{{ pg_monitor_username }}:{{ pg_monitor_password }}@{{ pg_host }}:{{ pg_port }}/postgres{% if pg_exporter_params != '' %}?{{ pg_exporter_params }}{% endif %}' {% endif %}当需要强制 SSL(如云 RDS 强制要求加密连接)或目标实例对账号/库有特殊要求时,可用pg_exporter_url整体覆盖:
pg_exporters: 20001: pg_cluster: pg-rds pg_seq: 1 pg_host: rds.example.com pg_exporter_url: 'postgres://monitor:password@rds.example.com:5432/postgres?sslmode=require'模板还会根据pg_exporter_auto_discovery布尔值生成PG_EXPORTER_AUTO_DISCOVERY=true/false,并写入PG_EXPORTER_EXCLUDE_DATABASE、PG_EXPORTER_INCLUDE_DATABASE、PG_EXPORTER_CONFIG、PG_EXPORTER_TELEMETRY_PATH(默认/metrics)、PG_EXPORTER_DISABLE_CACHE=false与PG_EXPORTER_CONNECT_TIMEOUT等环境变量,最终通过 systemd 的EnvironmentFile注入进程。
七、远程 PostgreSQL 端准备
在开始监控前,需要让远端实例接受 infra 节点的连接并授予监控权限。
1. 创建监控用户并授权
在目标 PostgreSQL 上执行(参考 pgsql-monitor.yml 注释):
-- 创建监控用户 CREATE USER dbuser_monitor PASSWORD 'DBUser.Monitor'; COMMENT ON ROLE dbuser_monitor IS 'system monitor user'; -- 授予监控权限(PolarDB for PostgreSQL 等定制内核可能不提供 pg_monitor 角色) GRANT pg_monitor TO dbuser_monitor; -- 创建必需的扩展(用于 pg_stat_statements 指标采集) CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "monitor";需要说明的是:GRANT pg_monitor是 PostgreSQL 10+ 内置的监控预定义角色,能覆盖绝大多数监控视图的只读权限;但部分云厂商定制内核(如 PolarDB)并不提供该角色,此时需要手动授予所需视图/函数的 SELECT 权限。
2. 配置 HBA(host-based authentication)
确保远端 PostgreSQL 的pg_hba.conf放行来自 infra 节点的连接,并使用强认证方式:
# pg_hba.conf host all dbuser_monitor <infra_ip>/32 scram-sha-256若 infra 与 RDS 之间存在 VPN/VPC 对等,请以实际可达地址为准;scram-sha-256优于md5,是较新的 PostgreSQL 默认推荐认证方式。
八、服务命名与 systemd 单元
每个 exporter 对应一个唯一的 systemd 服务,命名规则为:
pg_exporter_<cluster>-<seq>例如:
pg_exporter_pg-foo-1(监听 20001)pg_exporter_pg-foo-2(监听 20002)
该命名在 tasks/main.yml 中显式构造:pg_exporter_unit: "pg_exporter_{{ item.value.pg_cluster }}-{{ item.value.pg_seq|string }}",并用于配置文件、环境变量文件与服务的统一命名。
systemd 单元模板(templates/pg_exporter.svc)体现了 Pigsty 对采集器资源的克制管理:
[Unit] Description= PG Exporter @ {{ pg_exporter_port }} for {{ pg_cluster }}-{{ pg_seq }}@{{ pg_host }}:{{ pg_port }} After=network.target [Service] EnvironmentFile=-/etc/default/{{ pg_exporter_unit }} User={{ pg_dbsu }} ExecStart=/usr/bin/pg_exporter $PG_EXPORTER_OPTS ExecReload=/usr/bin/kill -HUP $MAINPID Restart=on-failure RestartSec=5 CPUQuota=10% #MemoryMax=200M [Install] WantedBy=multi-user.target要点解读:
- 以
postgres(pg_dbsu)身份运行,配置目录/etc/pg_exporter权限为0750,环境文件权限0600,避免监控凭据泄露; - 默认通过
PG_EXPORTER_OPTS指定--web.listen-address=:<port> --log.level=info(若设置pg_exporter_options则整体替换); CPUQuota=10%限定 CPU 占用上限,防止采集对监控节点造成冲击;- 进程异常退出时
Restart=on-failure自动拉起,ExecReload支持 SIGHUP 平滑重载配置。
部署任务(tasks/pg_exporter.yml)执行顺序为:创建/etc/pg_exporter目录 → 渲染或拷贝pg_exporter.yml采集配置 → 渲染pg_exporter.env环境文件 → 渲染 systemd 单元 →systemctl daemon-reload并重启服务 →wait_for等待本地端口在线(超时 10 秒)。
九、注册到监控栈:VictoriaMetrics 与 Grafana
1. 注册为 VictoriaMetrics 抓取目标(add_metrics)
tasks/main.yml 第二部分会按集群聚合所有条目,在 infra 节点生成/infra/targets/pgrds/<cluster>.yml:
# PGRDS: remote postgres service for pg-foo - labels: { cls: pg-foo, ins: pg-foo-1, ip: 10.10.10.10 } targets: [ 10.10.10.10:20001 ] - labels: { cls: pg-foo, ins: pg-foo-2, ip: 10.10.10.11 } targets: [ 10.10.10.10:20002 ]每个 target 带有cls(集群)、ins(实例)、ip(远端地址)标签,与 Pigsty 本地监控的标签体系保持一致,从而复用现有的pgsql系列 Grafana 面板与告警规则。文件属主victoria:infra、权限0640。
2. 注册 Grafana PostgreSQL 数据源(add_ds)
当条目声明了pg_databases(如[{ name: test }])时,角色会为每个数据库在全部 infra 节点上注册一个 Grafana 数据源,数据源名称格式为<cluster>-<seq>.<database>(如pg-polar-1.test)。
数据源 JSON 由 tasks/register_grafana_db.yml 生成,关键字段包括:type: postgres、access: proxy、url: <pg_host>:<pg_port>、监控账号与密码,以及连接池与sslmode: require等jsonData。随后通过 Grafana HTTP API 完成 upsert:
curl -X DELETE "http://127.0.0.1:{{ gf_port }}/ui/api/datasources/name/{{ ds_name }}" -u "{{ gf_user }}:{{ gf_pass }}" curl -X POST "http://127.0.0.1:{{ gf_port }}/ui/api/datasources/" -u "{{ gf_user }}:{{ gf_pass }}" -H 'Content-Type: application/json' -d @/infra/datasources/{{ ds_name }}.json该任务delegate_to每个 infra 节点并ignore_errors: true,即使 Grafana API 暂不可用也不会中断整体流程。pg_databases条目还支持register_datasource: false显式跳过注册。
十、采集器配置深度解析
默认采集配置由 templates/pg_exporter.yml 渲染(源文件是 2500+ 行的采集器定义,兼容 PostgreSQL 10~19+ 与 pgbouncer)。它本质上是"采集指标定义文件",每个 metric 块由 SQL 查询 + 指标元数据构成,例如基础状态采集(区分主库与备库,分别执行):
pg_primary_only: name: pg desc: PostgreSQL basic information (on primary) query: |- SELECT extract(EPOCH FROM CURRENT_TIMESTAMP) AS timestamp, extract(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime, pg_current_wal_lsn() - '0/0' AS lsn, ... pg_is_in_recovery() AS is_in_recovery; tags: [ cluster, primary ] ttl: {{ ttl_fast }} min_version: 100000 fatal: true metrics: - timestamp: { usage: GAUGE , description: current database timestamp in unix epoch } - uptime: { usage: GAUGE , description: seconds since postmaster start } - lsn: { usage: COUNTER , description: log sequence number, current write location } ...几个值得注意的设计:
- 版本自适应:
min_version/max_version字段让同一个指标名在不同 PG 大版本上执行不同的查询(如pg_meta_13/pg_meta_10、pg_repl_12/pg_repl_10、pg_slot_17/pg_slot_10等),兼容性由配置层解决; - TTL 分级:
ttl: {{ ttl_fast/norm/slow/slowest }}控制各类指标刷新频率,开销大的查询(如pg_size遍历目录)使用慢档; - 指标类型:
usage字段区分GAUGE、COUNTER、LABEL,其中LABEL用于把集群元数据(如cluster_name、version)作为标签注入序列; - 内置跳过项:
pg_origin默认skip: true,需要额外授权才启用;pg_stat_statements相关指标依赖监控 schema 中创建该扩展。
由于采集 SQL 全部在远端执行,远程监控获得的指标覆盖面与本地监控的pg_exporter一致,这是远程方案信息密度不减的关键原因。
十一、能力边界与限制
远程监控与本地监控的能力对比如下(摘自 README):
| 功能 | 本地监控 | 远程监控 |
|---|---|---|
| PostgreSQL 指标 | ✓ | ✓ |
| Node 指标 | ✓ | ✗ |
| pgBouncer 指标 | ✓ | ✗ |
| Patroni 指标 | ✓ | ✗ |
| HAProxy 指标 | ✓ | ✗ |
| 日志采集 | ✓ | ✗ |
决策建议:对于仍可安装 Agent 的自主部署 PostgreSQL,优先使用本地 pg_monitor 获得完整观测;pg_exporters适用于无法部署 Agent、但开放数据库端口的托管实例,作为统一可观测性拼图上的最后一环。
十二、参考
- 角色文档:roles/pg_exporters/README.md
- 默认变量:roles/pg_exporters/defaults/main.yml
- 任务实现:roles/pg_exporters/tasks/main.yml、roles/pg_exporters/tasks/pg_exporter.yml、roles/pg_exporters/tasks/register_grafana_db.yml
- 模板:roles/pg_exporters/templates/pg_exporter.env、roles/pg_exporters/templates/pg_exporter.svc、roles/pg_exporters/templates/pg_exporter.yml
- Playbook:pgsql-monitor.yml
- 配置示例:conf/demo/remote.yml
- 关联角色:本地监控 pg_monitor 与基础设施监控 infra
- 数据库
- 运维
- 云原生
- 高可用
- 监控
【免费下载链接】pigsty
Enterprise-Grade OSS PostgreSQL Distribution with HA, PITR, IaC, Monitor, 12 kernel forks and 575 PG extensions. Best-of-breed products integrated as a platform. Self-host Postgres like a Pro!
相关推荐
Pigsty pg_monitor 角色深度解析:PostgreSQL 集群监控 Exporter 的自动化部署与基础设施注册
Pigsty pg_monitor 角色深度解析:PostgreSQL 集群监控 Exporter 的自动化部署与基础设施注册 Pigsty 的 pg_moni
数据库运维云原生高可用监控Pigsty 应用实战:用 Docker 运行 pg_exporter 采集 PostgreSQL 监控指标
Pigsty 应用实战:用 Docker 运行 pg_exporter 采集 PostgreSQL 监控指标 本篇技术指南基于 Pigsty 仓库中的 app/
数据库运维云原生高可用监控Pigsty MinIO 实例卸载实战:minio_remove 角色的全流程拆除指南
Pigsty MinIO 实例卸载实战:minio_remove 角色的全流程拆除指南 本文以 Pigsty 仓库中 minio_remove 角色的官方文档为
数据库运维云原生高可用监控
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考