Ubuntu 26.04 安装 postgres_exporter 0.20.1 指南
在 Ubuntu 26.04.1 LTS 单机实测 postgres_exporter 0.20.1 官方二进制安装(sha256 校验、静态链接自证)、systemd 常驻托管、连通性验证(pg_up/15 个默认 collector/自定义指标全就位),以及 6 则真实排障实录(sslmode 默认值、密码错误、权限两副面孔、坏 YAML、端口占用、非法超时静默降级)。
Ubuntu 26.04 安装 postgres_exporter 0.20.1 指南
目标:在 Ubuntu 26.04(x86_64)单机上完成 postgres_exporter 0.20.1 的官方二进制安装、systemd 常驻托管、连通性验证与常见故障处置。本文所有命令与回显均为 2026-10-28 在实测机上真实执行的结果;软件定位与选型背景见 A1 介绍与选型指南,参数语义与生效机制见 C1《配置参数详解》,命令细节见 D1《常用 CLI 命令与工具详解》。
一、部署形态选型与实测环境
1.1 上游发行形态实查
v0.20.1 的 GitHub Release(releases/tag/v0.20.1,2026-07-08 发布)为 30 余个平台组合(aix/darwin/dragonfly/freebsd/illumos/linux/netbsd/openbsd/plan9/solaris/windows × amd64/arm64/armv6/armv7/386/ppc64le/s390x 等)各发布一个 tar.gz,linux-amd64 包名为 postgres_exporter-0.20.1.linux-amd64.tar.gz、大小 10,557,302 字节。上游不提供各发行版的 apt/deb 仓库,因此单机部署的标准路径是:官方预构建二进制 + 手写 systemd 单元。本文即按此形态交付;若在 Kubernetes 平台托管,可参考上游 charts 仓库 prometheus-community/helm-charts 中的 prometheus-postgres-exporter 图表(本专栏不展开,聚焦单机 systemd 形态)。
1.2 实测环境
| 项 | 值 |
|---|---|
| 导出器宿主 | Ubuntu 26.04.1 LTS,x86_64,6 vCPU / 18 GiB |
| 被监控实例 | PostgreSQL 16.15(Debian 16.15-1.pgdg13+2 编译串),监听 10.89.74.10:5432,位于实验网段 10.89.74.0/24 内的独立实验机 |
| 导出器监听 | :8150(自定义端口;上游默认 :9187) |
| 数据库驱动语义 | lib/pq,连接串默认 sslmode=require(后文排障实录一的关键前提) |
拓扑一句话:Prometheus/PromQL 消费方 → 宿主机 8150 端口的 postgres_exporter(systemd 常驻)→ 实验网段内 PostgreSQL 16.15 实例的 5432 端口。
1.3 前置条件
- 宿主机具备 curl、tar、sha256sum、systemd(Ubuntu 26.04 原生满足)。
- 数据库侧可用的管理账号(本文用 postgres 超管执行授权,正式环境请走内部变更流程)。
- 宿主机到 10.89.74.10:5432 网络可达(用
pg_isready预检,见 4.1)。
二、获取并核验发行包
2.1 下载
$ curl -L -o postgres_exporter-0.20.1.linux-amd64.tar.gz \
https://github.com/prometheus-community/postgres_exporter/releases/download/v0.20.1/postgres_exporter-0.20.1.linux-amd64.tar.gz
外网波动如实记录:本次实测中 GitHub 资产直连两次中途断流(文件停在 5.8 MB、8.6 MB 即进程退出),改用断点续传完成后,最终字节数与 Release 页面标注的 10,557,302 完全一致。断点续传命令:
$ curl -L -C - --retry 3 --retry-delay 2 -o postgres_exporter-0.20.1.linux-amd64.tar.gz \
https://github.com/prometheus-community/postgres_exporter/releases/download/v0.20.1/postgres_exporter-0.20.1.linux-amd64.tar.gz
💡 下载不稳定的环境可预先配置 HTTPS 代理或使用国内加速下载代理;无论走哪条链路,都以下一步的 sha256 校验为准,不校验不上线。
2.2 校验与解包
$ sha256sum postgres_exporter-0.20.1.linux-amd64.tar.gz
89d4f7e7920cad48fdc3133f789556ef5253c330a9f5fdace3bdb6344c0a8b5a postgres_exporter-0.20.1.linux-amd64.tar.gz
$ tar xzf postgres_exporter-0.20.1.linux-amd64.tar.gz
$ ls -la postgres_exporter-0.20.1.linux-amd64/
total 20276
-rw-r--r-- 1 1001 1001 11357 Jul 8 09:50 LICENSE
-rw-r--r-- 1 1001 1001 70 Jul 8 09:50 NOTICE
-rwxr-xr-x 1 1001 1001 20742702 Jul 8 09:50 postgres_exporter
$ file postgres_exporter-0.20.1.linux-amd64/postgres_exporter
postgres_exporter-0.20.1.linux-amd64/postgres_exporter: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
statically linked, Go BuildID=..., with debug_info, not stripped
要点:静态链接的 Go ELF,约 20.7 MB,无任何运行时库依赖,拷贝即用;包内附 Apache-2.0 的 LICENSE 与 NOTICE,升级替换时随二进制一起保留即可。
三、安装二进制与规划目录
本机以 root 运行服务,本文统一采用如下布局(习惯 /usr/local/bin + /etc 布局的读者可整体替换路径,保持 unit 内三处引用一致即可):
| 用途 | 路径 |
|---|---|
| 二进制 | /root/.local/bin/postgres_exporter |
| 环境变量文件(含连接串) | /root/.local/share/postgres_exporter/postgres_exporter.env |
| 自定义查询 | /root/.local/share/postgres_exporter/queries.yaml |
| 多目标配置(可选) | /root/.local/share/postgres_exporter/postgres_exporter.yml |
$ install -m 0755 postgres_exporter-0.20.1.linux-amd64/postgres_exporter /root/.local/bin/
$ mkdir -p /root/.local/share/postgres_exporter
$ /root/.local/bin/postgres_exporter --version
postgres_exporter, version 0.20.1 (branch: HEAD, revision: 867fbcac31cd18c143e244190ea9168cca069827)
build user: root@f281ca536a03
build date: 20260708-01:46:52
go version: go1.26.4
platform: linux/amd64
tags: unknown
--version 回显与 Release 标签、构建日期(2026-07-08)一一对应,可作为安装正确的第一道检查。
四、数据库侧准备
4.1 连通性预检
$ pg_isready -h 10.89.74.10 -p 5432
10.89.74.10:5432 - accepting connections
4.2 监控账号与业务库
以管理员身份进入实例(实测机本地执行):
$ psql -U postgres
postgres=# CREATE ROLE exporter LOGIN PASSWORD 'exp2026';
CREATE ROLE
postgres=# GRANT pg_monitor TO exporter;
GRANT ROLE
postgres=# CREATE DATABASE appdb OWNER postgres;
CREATE DATABASE
在业务库内创建演示表并显式授予采集账号 SELECT(pg_monitor 不含业务表权限,这是排障实录三的根源):
$ psql -U postgres -d appdb
appdb=# CREATE TABLE orders (id serial primary key, amount numeric, created_at timestamptz default now());
CREATE TABLE
appdb=# INSERT INTO orders (amount) SELECT random()*100 FROM generate_series(1,500);
INSERT 0 500
appdb=# CREATE EXTENSION pg_stat_statements;
CREATE EXTENSION
appdb=# GRANT SELECT ON orders TO exporter;
GRANT
💡
pg_stat_statements扩展要求实例启动参数shared_preload_libraries=pg_stat_statements并重启实例后CREATE EXTENSION,否则--collector.stat_statements打开后该采集器报错(实测扩展版本 1.10 可正常出指标,见 C1/D1)。
4.3 环境变量文件
# /root/.local/share/postgres_exporter/postgres_exporter.env
DATA_SOURCE_NAME=postgresql://exporter:exp2026@10.89.74.10:5432/appdb?sslmode=disable
两处硬约束:sslmode=disable 必须显式给出(理由见排障实录一);文件权限收紧到 600,避免凭据泄露。
4.4 自定义查询文件(可选,验证自定义链路用)
# /root/.local/share/postgres_exporter/queries.yaml
app_orders_total:
query: "SELECT count(*) AS rows_total, coalesce(sum(amount),0) AS amount_sum FROM orders"
metrics:
- rows_total:
usage: "GAUGE"
description: "Total rows in orders table"
- amount_sum:
usage: "GAUGE"
description: "Sum of order amounts"
app_db_size:
query: "SELECT pg_database.datname, pg_database_size(pg_database.datname) AS size FROM pg_database"
metrics:
- datname:
usage: "LABEL"
description: "Name of the database"
- size:
usage: "GAUGE"
description: "Disk space used by the database"
五、systemd 常驻托管
5.1 推荐的持久化单元(读者机器上落地此文件)
# /etc/systemd/system/postgres-exporter.service
[Unit]
Description=Prometheus exporter for PostgreSQL
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
EnvironmentFile=/root/.local/share/postgres_exporter/postgres_exporter.env
ExecStart=/root/.local/bin/postgres_exporter --web.listen-address=:8150 \
--extend.query-path=/root/.local/share/postgres_exporter/queries.yaml
Restart=on-failure
NoNewPrivileges=true
ProtectSystem=strict
ReadOnlyPaths=/root/.local/share/postgres_exporter
[Install]
WantedBy=multi-user.target
启用:systemctl daemon-reload && systemctl enable --now postgres-exporter。生产环境建议将 User= 改为专用低权账号(如 postgres_exporter),并用 --web.config.file 启用 Basic 认证或 TLS。
本文实测机说明:验证环境以 systemd 瞬态单元承载与上述文件完全相同的 ExecStart 参数(systemd-run --unit=postgres-exporter --property=Restart=on-failure --property=EnvironmentFile=... /root/.local/bin/postgres_exporter ...),因此下文 systemctl/journalctl 回显中 Loaded 行显示 transient;除持久化能力外,管控语义与持久化单元一致。
5.2 启动与状态确认
$ systemctl status postgres-exporter --no-pager -l
● postgres-exporter.service - Prometheus exporter for PostgreSQL (lab)
Loaded: loaded (/run/systemd/transient/postgres-exporter.service; transient)
Transient: yes
Active: active (running) since Wed 2026-10-28 23:28:00 CST; 3s ago
Main PID: 173394 (postgres_export)
Tasks: 5 (limit: 19553)
Memory: 2.4M (peak: 3.2M)
CGroup: /system.slice/postgres-exporter.service
└─173394 /root/.local/bin/postgres_exporter --web.listen-address=:8150 --extend.query-path=/root/.local/share/postgres_exporter/queries.yaml
Oct 28 23:28:00 master systemd[1]: Started postgres-exporter.service - Prometheus exporter for PostgreSQL (lab).
Oct 28 23:28:00 master postgres_exporter[173394]: time=2026-10-28T23:28:00.110+08:00 level=WARN source=main.go:81 msg="Error loading config" err="error opening config file \"postgres_exporter.yml\": open postgres_exporter.yml: no such file or directory"
内存常驻仅约 2.4 MB;启动日志的 Error loading config 是 WARN 而非致命——未提供 --config.file 时它按默认名找一遍、找不到继续跑(多目标/auth_modules 场景才必需该文件)。
六、安装验证
6.1 端点与指标量
$ curl -s -o /tmp/metrics.txt -w 'HTTP %{http_code}, %{size_download} bytes\n' http://127.0.0.1:8150/metrics
HTTP 200, 91929 bytes
$ grep -c '^pg_' /tmp/metrics.txt
546
$ grep -E '^pg_up|^pg_exporter_last_scrape' /tmp/metrics.txt
pg_up 1
pg_exporter_last_scrape_duration_seconds 0.006441418
pg_exporter_last_scrape_error 0
6.2 自定义指标与采集器清单
$ grep -E '^app_orders_total|^app_db_size_size\{datname="appdb"' /tmp/metrics.txt
app_orders_total_rows_total{server="10.89.74.10:5432"} 500
app_orders_total_amount_sum{server="10.89.74.10:5432"} 25531.865537450296
app_db_size_size{datname="appdb",server="10.89.74.10:5432"} 7.978007e+06
$ grep -oE '^pg_scrape_collector_success\{collector="[a-z_]+"' /tmp/metrics.txt | grep -oE '[a-z_]+"$' | sort | tr '\n' ' '
database locks replication replication_slots roles settings stat_activity stat_archiver
stat_bgwriter stat_database statio_user_tables stat_progress_vacuum stat_replication
stat_user_tables wal
15 个默认启用的 collector 全部 success 1、pg_up 1、自定义 app_* 指标就位,即安装完成。首轮抓取日志里还能看到版本探测记录:level=INFO source=postgres_exporter.go:537 msg="Semantic version changed" server=10.89.74.10:5432 from=0.0.0 to=16.15.0。
七、升级与回滚
- 升级即替换二进制 +
systemctl restart postgres-exporter(transient 单元则为重新 systemd-run)。--version复核后观察一轮抓取日志无 ERROR 即完成。 - 跨 0.20.0 升级必须先读其 BREAKING CHANGES:复制槽 collector 与指标更名(
pg_replication_slot_*→pg_replication_slots_*)、--disable-settings-metrics/PG_EXPORTER_DISABLE_SETTINGS_METRICS移除、五类指标转独立 collector 后不再受--metric-prefix/constantLabels/--disable-default-metrics影响。A1 第四节有完整清单,相关失效项在 C1 有逐条实测佐证。 - 回滚:保留旧版本 tar.gz,按原路径还原二进制并重启即可;queries.yaml 与 env 文件格式在 0.18→0.20 区间未变化。
八、排障实录(全部真实回显)
实录一:未写 sslmode=disable,抓取全红
现象:/metrics 里 pg_up 0、pg_exporter_last_scrape_error 1。日志:
level=ERROR source=collector.go:191 msg="Error opening connection to database" err="error querying postgresql version: pq: SSL is not enabled on the server"
level=ERROR source=postgres_exporter.go:606 msg="error scraping dsn" err="Error opening connection to database (postgresql://exporter:PASSWORD_REMOVED@10.89.74.10:5432/appdb): pq: SSL is not enabled on the server" dsn=...
根因:驱动 lib/pq 默认 sslmode=require,而实验实例未启用 TLS。处置:连接串补 ?sslmode=disable(内网)或给实例配 TLS 后用 verify-full。注意日志中密码被自动脱敏为 PASSWORD_REMOVED,贴日志求助是安全的。
实录二:密码错误
level=ERROR source=collector.go:191 msg="Error opening connection to database" err="error querying postgresql version: pq: password authentication failed for user \"exporter\""
处置:核对 pg_roles 中账号与密码、pg_hba.conf 认证方式;改完 env 后 systemctl restart。
实录三:权限不足的两副面孔(本篇最重要的观测点)
- 业务表未授权(自定义查询):
level=INFO source=namespace.go:235 msg="error finding namespace" err="Error running query on database \"10.89.74.10:5432\": app_orders_total pq: permission denied for table orders",且pg_exporter_last_scrape_error 1。处置:GRANT SELECT ON orders TO exporter;后恢复pg_exporter_last_scrape_error 0、app_orders_total_rows_total 500。 - 函数权限缺失(内置 wal collector):用仅具备登录权限的
viewer角色实测,pg_up仍为 1、pg_exporter_last_scrape_error仍为 0,但日志出现单采集器失败:level=ERROR source=collector.go:227 msg="collector failed" name=wal duration_seconds=0.006775354 err="pq: permission denied for function pg_ls_waldir"。
结论:整库连不上才会拉低 pg_up/last_scrape_error;单采集器权限问题只体现为 pg_scrape_collector_success{collector="..."} 0 与对应指标缺失。告警规则必须两者都覆盖。
实录四:queries.yaml 损坏不致命
构造非法 YAML(缩进错误,python yaml 校验确认报 expected <block end>)。0.20.1 照常启动、照常服务默认指标,仅在首次抓取时打印:
level=ERROR source=postgres_exporter.go:564 msg="Failed to reload user queries" path=/tmp/bad_queries.yaml err="yaml: line 2: did not find expected key"
自定义指标全体消失但 pg_up 1、last_scrape_error 0。处置:改对 YAML 后重启进程(该路径不热加载)。
实录五:端口被占用
$ /root/.local/bin/postgres_exporter --web.listen-address=:8150
time=... level=ERROR source=main.go:168 msg="Error running HTTP server" err="listen tcp :8150: bind: address already in use"
(进程退出码 1)
处置:ss -ltnp | grep 8150 找到占用方;或换端口。--web.listen-address 可重复多次以同时监听多个地址。
实录六:非法超时值的"静默降级"
$ PG_EXPORTER_COLLECTION_TIMEOUT=0 postgres_exporter --web.listen-address=:8155
time=... level=WARN source=main.go:137 msg="Failed to create PostgresCollector" err="timeout must be greater than 1ms"
time=... level=INFO source=tls_config.go:372 msg="Listening on" address=[::]:8155
进程活着、端口在听,但 /metrics 只剩 29 条自观测指标(无任何 pg_stat_*)。升级/改配置后"服务绿但没数据"先查这条 WARN。
九、卸载
$ systemctl disable --now postgres-exporter # 持久化单元
$ rm /root/.local/bin/postgres_exporter /root/.local/share/postgres_exporter/postgres_exporter.env
$ rm /etc/systemd/system/postgres-exporter.service && systemctl daemon-reload
数据库侧回收:DROP ROLE exporter;(先 REVOKE 各对象授权)。
十、参考与延伸
- 本专栏系列:A1 介绍与选型指南;配置参数详解(C1)、常用 CLI 命令与工具详解(D1)。
- 上游:v0.20.1 Release 资产清单;README "Quick Start / Building and running" 章节;prometheus-community/helm-charts 仓库(Kubernetes 形态)。
- 站内延伸(姊妹组件):Rocky 9 安装 pgexporter 0.8.0 指南。