前言
Prometheus 默认采用 Pull 模型:它按采集周期访问目标的 /metrics 端点。这对 Web 服务、数据库等长期运行的进程非常合适,但在批处理监控中会碰到时间差。备份脚本执行完就退出,CI/CD 作业可能只运行几分钟;假如进程在两次抓取之间启动又结束,Prometheus 就未必能采到这次任务的执行结果。
Pushgateway 提供了一个中间指标入口。批量任务通过 HTTP 将成功状态、执行耗时、处理记录数等指标推送过去,Pushgateway 按分组键保存这些指标,Prometheus 再定期从它的 /metrics 端点拉取。需要注意,这并不是把 Prometheus 改成 Push 系统:Pushgateway 既不是日志库,也不会替你判断任务是不是按时执行,更不会自动清理已经停止的任务分组。实际应用时,要一并设计指标分组、过期判断和访问权限。
本篇沿用原始实验路线,在 Linux 虚拟机上分别演示二进制安装和 Docker 安装,配置 Prometheus 抓取目标,利用 curl、Shell 和 Python 完成不同任务的指标上报,再借助 cpolar 配置可从外部访问的地址。部署步骤、原有命令及截图均保留,并对版本记录、指标持久化、返回码判断和远程写入安全作必要说明,便于按图复现,也能知道哪些地方需要进一步完善后才能用于生产环境。

1. 为什么短任务需要 Pushgateway:环境与工作方式
Prometheus 通过周期性抓取获取监控数据,前提是采集时目标仍然能够提供指标。对于长期运行的服务,这种方式直观;但备份、流水线和临时数据处理作业通常执行完成就退出,下一次抓取未必来得及。Pushgateway 允许这些任务先把指标推送给一个持续运行的中间组件,然后由 Prometheus 照常采集它。这里的"离线任务"指不常驻、短生命周期的作业,并不是指任务在完全没有网络连接时也能实时上报。
本篇按原文的虚拟机环境演示,保留原始版本记录:
- 虚拟机:Oracle VirtualBox 5.1.20 r114628(Qt 5.6.2)。
- 系统:原文记录为
entOS Linux release 7.9.2009 (Core),应是 CentOS 7.9.2009 的笔误。 - Docker:26.1.4。
- Prometheus:v3.5.0。
- Pushgateway:环境清单写的是 1.0.0,但下方下载与解压命令使用的是 1.11.2;复现时以实际下载和运行的版本为准。
演示开始前需有可运行的 Prometheus。若尚未安装,可先参考原文提及的《监控不再局域网!Cpolar 让 Prometheus 走出内网限制!》完成基础环境。Pushgateway 适用于特定批处理任务,并不建议直接拿来替代一般服务的常规采集。
2. 安装 Pushgateway:二进制与 Docker 两种路线
两种安装方式任选其一即可。若都在同一台机器上启动,默认都会占用 9091 端口,应避免端口冲突。这里先保留原文的 systemd 部署方式,再介绍容器版本。
2.1 二进制安装及 systemd 托管
首先到项目发布页面选择对应平台的 Linux 二进制包,原文采用 pushgateway-1.11.2.linux-amd64.tar.gz。下载后将压缩包上传至 /app 目录。

上传完成:

在 /app 下执行解压命令:
shell
tar -zxvf pushgateway-1.11.2.linux-amd64.tar.gz

随后按原文将解压出的目录更名为 pushgateway,并删除已经用完的安装包。请确认压缩包已成功解压,再执行删除操作。
shell
mv pushgateway-1.11.2.linux-amd64 pushgateway
rm -rf pushgateway-1.11.2.linux-amd64.tar.gz

要让 Pushgateway 随系统启动,可以创建 systemd 服务文件:
shell
sudo vim /etc/systemd/system/pushgateway.service
写入以下服务配置,保持原文参数不变:
shell
[Unit]
Description=Pushgateway for Prometheus
Documentation=https://github.com/prometheus/pushgateway
After=network-online.target
[Service]
Type=simple
User=prometheus
Group=prometheus
ExecStart=/app/pushgateway/pushgateway \
--web.listen-address=:9091 \
--web.enable-admin-api \
--log.level=info
WorkingDirectory=/app/pushgateway
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=pushgateway
[Install]
WantedBy=multi-user.target

其中 ExecStart 指向 /app/pushgateway/pushgateway,监听端口是 9091;Restart=on-failure 用于异常退出后重启。服务指定了 User=prometheus 和 Group=prometheus,因此需要事先确认该账号及用户组存在,并能访问运行目录。配置中的 --web.enable-admin-api 还会开启全量清空指标的管理接口:仅演示时也应限制谁可以访问该端口,实际部署如不需要这个接口就不要启用。
然后设置目录归属和程序执行权限:
shell
sudo chown -R prometheus:prometheus /app/pushgateway
sudo chmod +x /app/pushgateway/pushgateway

重载服务配置,启动并设置开机自启,最后检查状态:
shell
# 重载配置
sudo systemctl daemon-reexec
sudo systemctl daemon-reload
# 启动并设置开机自启
sudo systemctl start pushgateway
sudo systemctl enable pushgateway
# 查看状态
sudo systemctl status pushgateway

服务启动不等于链路全部可用。继续检查进程、访问本机指标端点,并跟踪日志:
shell
# 检查进程
ps aux | grep pushgateway
# 访问指标端点(本地)
curl http://localhost:9091/metrics
# 查看日志
journalctl -u pushgateway -f

如果需要从别的机器访问 9091,原文还给出 CentOS 7 的防火墙放行操作:
shell
# CentOS 7 使用 firewalld
sudo firewall-cmd --permanent --add-port=9091/tcp
sudo firewall-cmd --reload
这里的放行应仅针对可信来源;它不是让 Pushgateway 可以直接暴露给所有互联网用户的建议。特别是启用了管理 API 的实例,更需要限制写入和管理权限。
浏览器输入 http://服务器IP:9091,可以打开 Web 页面。此时还没有任务主动上报,所以页面中不会出现自定义任务组。

访问 http://服务器IP:9091/metrics 时仍能看到 go_、process_ 等自身运行指标。这说明服务本身可以提供采集端点,不代表备份或批处理指标已经进来了。

还有一项要单独说明:原文这份 systemd 配置未启用 --persistence.file,因此不能声称已经完成指标磁盘持久化。 Pushgateway 默认不会把推送数据持久保存到磁盘;若需要重启后保留已推送的指标,应按官方文档配置持久化文件并安排相应的文件权限与备份。
2.2 使用 Docker 安装
已经有 Docker 环境的读者,可以直接拉取官方镜像:
shell
docker pull prom/pushgateway
随后按照原文运行容器,将宿主机 9091 映射至容器 9091:
shell
docker run -d \
--name=pg \
-p 9091:9091 \
prom/pushgateway

完成后,用浏览器访问示例地址:
shell
http://ip:9091/

实际使用时要把示例中的 ip 替换为服务器地址。原命令没有配置数据持久化参数或重启策略,不要将它误解为已经具备故障恢复后的指标保留能力。如果选择容器路线,下面 Prometheus 的抓取地址也要按容器和 Prometheus 的真实网络拓扑填写。
3. 让 Prometheus 定期采集 Pushgateway
Pushgateway 接收了任务指标,还需要 Prometheus 把它纳入采集目标。先找到并编辑原文的 Prometheus 配置文件:
shell
vi /app/prometheus/prometheus.yml
原文展示的新增目标片段如下:
shell
- targets: ['localhost:9091']
labels:
app: "pushgateway"

注意:这只是目标片段,不是一份可以独立运行的完整 prometheus.yml。 应将其放进适当的 scrape_configs / static_configs 结构,并沿用已有配置的缩进。Pushgateway 官方还建议在对应抓取任务中设置 honor_labels: true,以保留被推送指标的 job、instance 等标签,而不是让采集端的标签覆盖原有分组信息。localhost:9091 也仅适用于 Prometheus 与 Pushgateway 共享同一网络命名空间并能从该地址连通的情况;分属不同容器或主机时,需改为可达的实际地址。
改完后按照原文重启 Prometheus 并查看状态:
shell
systemctl restart prometheus
systemctl status prometheus

再打开 http://服务器IP:9090,在目标列表中确认 Pushgateway 对应的采集目标正常;也可以查询 Pushgateway 自身指标检查连通性。

要区分两个验证层次:目标显示正常表示 Prometheus 成功抓到了 Pushgateway;是否存在任务指标,还得等后续真的推送数据并查询对应名称。
4. 把自定义指标推送到 Pushgateway
Pushgateway 的写入地址以 /metrics/job/任务名 开始,后面可按分组需要继续追加 instance 等标签。URL 中这组标签构成分组键,同一任务不同分组的数据可以分开管理。下面先用一条简单数值完成端到端测试,再演示更复杂的数据与删除操作。
4.1 发送第一条测试指标
使用原文的 echo 和 curl 命令,将 test_metric 提交到 test_job 分组:
shell
echo "test_metric 123456" | curl --data-binary @- http://192.168.42.140:9091/metrics/job/test_job
返回 Pushgateway 页面后,就能查看新增的任务分组。Pushgateway 还会为每个已推送分组暴露 push_time_seconds、push_failure_time_seconds 等指标,用于观察最近成功或失败的推送时间。

随后在 Prometheus 的表达式查询页面查找 test_metric,确认抓取后能读到样本。

4.2 上报带标签的多条指标
下面这段原始示例将两条不同类型的指标写入 some_job / some_instance 分组:
shell
cat <<EOF | curl --data-binary @- http://192.168.42.140:9091/metrics/job/some_job/instance/some_instance
# TYPE some_metric counter
some_metric{label="val1"} 42
# TYPE another_metric gauge
# HELP another_metric Just an example.
another_metric 2398.283
EOF

# TYPE 和 # HELP 用于描述指标类型、含义;instance 是分组标签的一部分。推送前应确保同名指标的类型与标签结构不冲突。原文使用 curl --data-binary,其 HTTP POST 会在对应分组内按指标名称更新数据;如果需要整体替换某个分组的数据,则应按官方 API 语义选择 PUT。
4.3 清理不再需要的分组
临时任务结束后,Pushgateway 不会自动忘记以前收到的指标。如果组被废弃、实例改名,或不再希望 Prometheus 继续读取旧结果,就需要有明确的清理规则。
删除指定 job、instance 组合的全部指标:
curl -X DELETE http://192.168.42.140:9091/metrics/job/some_job/instance/some_instance
仅删除 some_job 这个分组:
curl -X DELETE http://192.168.42.140:9091/metrics/job/some_job
请特别注意:第二条命令针对的是只有 job=some_job 的那个分组,不会连带清除带 instance=some_instance 的另一个分组。DELETE 只对 URL 指定的完整分组键生效,不能当作模糊匹配的批量清理。
5. 两个批处理场景:Shell 备份与 Python 数据任务
测试指标能进来之后,再把相同方式嵌入短任务。这里保留原文的两段脚本及截图,便于照着复现;它们都是模拟演示,不能把示例中写死的成功状态和记录数当成真实业务结果。
5.1 Shell:汇报备份耗时和结果
示例先记录开始时间,使用 sleep 3 模拟备份过程,然后上报耗时和成功状态。原始脚本如下:
shell
#!/bin/bash
JOB_NAME="daily_backup"
INSTANCE="server01"
PUSHGATEWAY_URL="http://localhost:9091"
start_time=$(date +%s)
# 模拟备份操作
echo "Starting backup..."
sleep 3
backup_success=1 # 1 表示成功,0 表示失败(实际可由命令返回值决定)
end_time=$(date +%s)
duration=$((end_time - start_time))
# 构建指标
cat <<EOF | curl --data-binary @- http://localhost:9091/metrics/job/$JOB_NAME/instance/$INSTANCE
# HELP backup_duration_seconds Duration of the backup job in seconds
# TYPE backup_duration_seconds gauge
backup_duration_seconds $duration
# HELP backup_success Whether the backup succeeded (1) or failed (0)
# TYPE backup_success gauge
backup_success $backup_success
EOF
echo "Metrics pushed to Pushgateway."

执行后,打开 Pushgateway 查看这次上报的分组:

在 Prometheus 中查询时,示例指标表现为:
shell
backup_duration_seconds{job="daily_backup", instance="server01"} 3
backup_success{job="daily_backup", instance="server01"} 1
这两个指标分别回答"用了多少秒"和"是否成功"。在真正的备份脚本中,需要根据备份命令实际退出码设置 backup_success,不能固定写 1;同时应检查指标提交是否成功。原始脚本虽然定义了 PUSHGATEWAY_URL 变量,实际请求仍直接写了 localhost:9091,迁移到其他机器时也要同步检查请求目标。
5.2 Python:汇报处理量与执行状态
对于一次性 Python 数据任务,也可以把最后的处理结果转换为 Prometheus 文本格式,通过 HTTP 提交。原文脚本使用 requests,模拟处理 1500 条记录:
shell
import requests
import time
def push_metrics(job, instance, records_processed, success):
metrics = f"""
# HELP data_records_processed Number of records processed
# TYPE data_records_processed gauge
data_records_processed {records_processed}
# HELP data_job_success Job success status (1 = success, 0 = failure)
# TYPE data_job_success gauge
data_job_success {int(success)}
"""
url = f"http://localhost:9091/metrics/job/{job}/instance/{instance}"
response = requests.post(url, data=metrics.encode('utf-8'))
if response.status_code == 202:
print("Metrics pushed successfully.")
else:
print(f"Failed to push metrics: {response.status_code}")
# 模拟任务
start = time.time()
try:
# 模拟处理 1500 条数据
records = 1500
time.sleep(2)
success = True
except Exception as e:
records = 0
success = False
push_metrics(
job="data_pipeline",
instance="worker-node-01",
records_processed=records,
success=success
)
在准备好 Python 和 requests 依赖后,按原文方式执行文件:
shell
python3 1.py
访问 Pushgateway,查看是否收到 data_pipeline 任务数据:

Prometheus 中预期出现的示例指标如下:
shell
data_records_processed{job="data_pipeline", instance="worker-node-01"} 1500
data_job_success{job="data_pipeline", instance="worker-node-01"} 1
正式使用时,records 应来自实际处理结果,success 应由真实异常处理或退出状态得出。还要注意,原脚本只把 HTTP 202 判断为"推送成功";按官方 API,正常 POST/PUT 还可能返回 200,因此不能仅靠 status_code == 202 判定。应检查所有合适的成功状态,并为网络异常、超时和失败响应设置处理逻辑。
指标被保留不代表任务仍在运行。对每天一次的任务,最好结合 push_time_seconds 判断最近一次上报是否过期,再配合状态指标判断执行结果。
6. 通过 cpolar 为远程任务建立访问通道
到这里,本地任务已经能够将指标交给 Pushgateway,Prometheus 也能正常采集。如果备份脚本在另一台云服务器、远程 CI/CD 节点或其他网络中执行,而 Pushgateway 只部署在内网,就还需要解决网络连通问题。
cpolar 的作用是将本地运行的 HTTP 服务映射为可从外部访问的地址,不会改变 Pushgateway 的采集与存储方式。需要特别提醒的是:这次对外映射的是可写入指标的服务,不只是一个只读看板。Prometheus 官方指出,能访问 Pushgateway HTTP 端点的用户可以创建、修改和删除指标;因此应只允许可信任务上报,并做好认证、访问限制与监控。
6.1 安装 cpolar
在运行 Pushgateway 的 Linux 主机上执行原文安装命令:
shell
sudo curl https://get.cpolar.sh | sh

安装完成后检查服务是否启动:
shell
sudo systemctl status cpolar

随后在浏览器访问这台服务器的局域网 IP 加 9200 端口,使用 cpolar 账号登录 Web 管理界面。若是在同一台主机上操作,也可以使用本机地址;不要把示例中的 localhost 直接照搬到别的电脑浏览器中。

7. 创建用于 Pushgateway 的公网隧道
登录 cpolar Web UI,依次进入隧道管理 → 创建隧道。沿用原文截图中的参数:
- 隧道名称:
pushgateway(或另一个不重复的名称)。 - 协议:
http。 - 本地地址:
9091。 - 域名类型:随机域名。
- 地区:
China Top。

创建后进入状态 → 在线隧道列表,查看系统提供的公网地址。

使用异地网络验证页面是否可达:

这一步验证的是隧道和 Web 服务连通,不应直接视为远程推送全链路已经验证成功。对外部任务,还应在获得授权的前提下用实际 HTTPS 写入地址提交测试指标,再在 Pushgateway 和 Prometheus 中分别确认收到与采集。
由于写入端点没有天然的只读隔离,公网访问应当设置认证或其他访问限制,不宜只依赖随机网址难以猜到。原始二进制服务又开启了管理 API,尤其不要把管理权限直接向不受信任的网络开放。
8. 固定二级子域名:减少远程任务频繁改地址
临时测试可用随机域名;需要多个远程脚本长期上报时,固定地址更容易维护。原文使用 cpolar 的二级子域名保留功能,具体以账号当前可用权益为准。

先登录 cpolar 控制台,进入预留 → 保留二级子域名 ,按原文选择 China Top,自定义名称为 pushgateway(如已被占用则换一个),填写备注并保留。

再返回本地 cpolar 管理界面,打开隧道管理 → 隧道列表,找到对应隧道并点击编辑。

将域名类型切换为二级子域名 ,在 Sub Domain 中填写刚刚保留成功的名称,地区仍保持一致,然后更新。

更新后在在线隧道列表确认地址变化:

最后用固定的 HTTPS 地址再次测试页面可达性,并验证授权后的指标提交是否正常:

固定域名解决的是访问地址变化问题,并不是对服务的安全加固。对生产环境来说,认证、权限限制、任务分组清理和数据保留策略,仍然需要单独落实。
总结
Pushgateway 的价值在于为短生命周期的批量任务保留一次执行结果,补上 Prometheus 定时抓取与任务短暂运行之间的时间差。本文分别完成了二进制与 Docker 部署、Prometheus 采集目标配置、curl 推送与删除,以及 Shell 备份和 Python 数据处理两个示例;最后通过 cpolar 演示跨网络访问和固定地址的配置。
真正落地时,最容易遗漏的不是安装命令,而是指标的生命周期:任务上报后,Pushgateway 不会替你自动判断结果是否过期,也不会在任务退出时清掉历史分组。应根据业务周期观察最近推送时间、检查执行状态,清理无效分组,并按需要启用数据持久化。若允许外部写入,则必须控制访问权限,不能把公网 URL 当作安全措施。
做到这些,监控系统才不只是"看见了一条新指标",而是能持续回答一次备份、一次构建或一次数据处理究竟完成得怎样。