OneUptime Proxmox Agent:基于 OpenTelemetry Collector 的 Proxmox VE 集群监控安装与排障实战
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
本文以 OneUptime 仓库中ProxmoxAgent/目录的安装文档为主线,完整讲解如何用一套「预配置 OpenTelemetry Collector + prometheus-pve-exporter」的 Agent 方案监控 Proxmox VE 集群(节点、QEMU 虚机、LXC 容器、存储与 HA 状态):从 API Token 创建、Docker Compose 部署、全量环境变量说明,到指标采集范围、id标签派生属性的源码原理、可选服务日志管道、systemd 托管,以及一个能给出「最终裁决」的官方诊断脚本。读完本文,你可以独立完成 Agent 的安装、升级、卸载与故障定位,并理解每一处配置背后的实现依据。
Agent 总体架构与数据流
OneUptime Proxmox Agent 本质上是一个纯配置型的 Collector 容器:标准的otel/opentelemetry-collector-contrib镜像,搭配一份经过调优的 otel-collector-config.yaml,其工作链路为:
Proxmox VE API (8006) │ 每次 scrape 都是一次真实 API 往返 ▼ prometheus-pve-exporter (可选内置, :9221, /pve 端点) │ collector 每 30s 拉取 ▼ OpenTelemetry Collector └─ processors: memory_limiter → transform/pve-identity → resource → batch └─ resource processor 为每条指标打上 proxmox.cluster.name │ OTLP/HTTP, x-oneuptime-token 头 ▼ OneUptime 实例 (<ONEUPTIME_URL>/otlp)关键实现事实(来自 otel-collector-config.yaml):
- Prometheus 接收器(
L7-L29):metrics_path: /pve,通过target参数把每次 scrape 代理到${env:PVE_HOST}指定的 PVE API 节点;cluster: ["1"]与node: ["1"]同时启用集群级与节点级采集器;scrape_interval: 30s—— 因为 pve-exporter 每次应答都是一次活的 PVE API 往返,30 秒间隔使 pveproxy 压力可忽略。 - OTLP 导出器(
L126-L130):endpoint: "${env:ONEUPTIME_URL}/otlp",请求头x-oneuptime-token携带遥测摄入令牌。 - 批处理与内存保护(
L118-L124):batch处理器timeout: 10s、send_batch_size: 1024;memory_limiter限制 256 MiB(尖峰余量 64 MiB,每 5s 检查),防止采集积压拖垮容器。 - 集群身份注入(
L101-L117):resource处理器把proxmox.cluster.nameupsert 到每条指标的资源属性上 —— 这是 OneUptime自动注册 Proxmox 集群的唯一依据,集群名称取自环境变量PROXMOX_CLUSTER_NAME。
同一个resource处理器还主动删除service.name与service.instance.id两个属性,源码注释解释了原因:prometheus receiver 按 Prometheus→OTLP 兼容规范会为每批数据合成这两个属性,而 OneUptime 优先按service.name路由数据批 —— 若保留,会注册出一个名为oneuptime-proxmox的「幽灵服务」,数据就无法落到按proxmox.cluster.name发现的 Proxmox 集群上(还会破坏按集群的保留期设置)。这也是官方标注「不要删除」的两行配置。
前置条件
- 一台能访问 Proxmox VE API(端口 8006)的机器,装有Docker Engine 20.10+与Docker Compose v2插件;
- 一个具有PVEAuditor角色(只读)的 Proxmox VE API Token;
- 一个OneUptime Telemetry 摄入令牌—— 在Project Settings → Telemetry & APM → Ingestion Keys中创建并复制其值。
创建 Proxmox API Token
最快路径 —— 在任一 PVE 节点上以 root 执行:
pveum user token add monitoring@pam oneuptime --privsep 1 pveum acl modify / --roles PVEAuditor --tokens 'monitoring@pam!oneuptime'如果monitoring@pam用户尚不存在,先执行pveum user add monitoring@pam创建 —— API Token 自带独立密钥,用户无需密码或系统账户。
ACL 必须挂在根路径/上,因为 PVEAuditor 需要读取 exporter 遍历的每一个节点、虚机与存储对象;授权在更窄的路径上会隐藏集群其余部分,并产生401/403 Permission check failed (/, Sys.Audit)错误。第一条命令会只打印一次Token 密钥,在你的.env中对应:
PVE_API_TOKEN_ID=monitoring@pam!oneuptime PVE_API_TOKEN_SECRET=<打印出的密钥>或者通过 Proxmox Web UI:
- 进入Datacenter → Permissions → API Tokens,点击Add;
- 选择(或新建)一个用户,Token ID 命名为
oneuptime之类,取消勾选 Privilege Separation(或在下一步为 Token 单独授权); - 在Datacenter → Permissions中,为路径
/上的该 Token 添加PVEAuditor角色; - 复制 Token ID(格式
user@realm!tokenname)与密钥 —— 密钥只显示一次。
部署位置建议
Agent 通过网络查询 PVE API,因此不必须、也最好不要放在集群节点上:把它运行在一台能扛住节点故障的机器上(独立硬件上的小型监控 VM、管理主机),或者把PVE_HOST指向 VIP / 轮询 DNS 名称而非某个节点的固定地址 —— 否则当 Agent 的 API 目标恰好是刚挂掉的那个节点时,你的监控会随之一起失效。唯一例外是可选的 journald 日志管道,它必须在 PVE 节点上运行(见下文服务日志)。
快速安装(安装脚本)
仓库为 Agent 提供了交互式安装脚本 install.sh。在本仓库的ProxmoxAgent/目录中执行:
bash install.sh脚本会依次提示输入:OneUptime URL、遥测摄入令牌、集群名称、Proxmox API 主机地址,然后:
- 检查 Docker 与 Compose v2 是否可用(不可用则直接退出并提示);
- 询问是否运行内置的 prometheus-pve-exporter(是,则要求提供 Token ID/密钥并启用
pve-exporterprofile;否,则要求提供已有 exporter 的host:port地址 —— 脚本会特别提示:Agent 运行在容器里,localhost永远指不到宿主机上的 exporter,必须用 LAN IP 或 DNS 名); - 安装到
/opt/oneuptime-proxmox-agent(可通过环境变量INSTALL_DIR覆盖),下载docker-compose.yml与otel-collector-config.yaml; - 生成
.env文件并chmod 600收紧权限,最后docker compose up -d启动。
手动安装 — Docker Compose
把 ProxmoxAgent/docker-compose.yml 和 ProxmoxAgent/otel-collector-config.yaml 两个文件复制到任意目录,然后在旁边创建.env文件:
ONEUPTIME_URL=YOUR_ONEUPTIME_URL ONEUPTIME_TELEMETRY_INGESTION_KEY=YOUR_TELEMETRY_INGESTION_TOKEN PROXMOX_CLUSTER_NAME=my-proxmox-cluster PVE_HOST=192.168.1.10 PVE_API_TOKEN_ID=oneuptime@pve!exporter PVE_API_TOKEN_SECRET=your-token-secret COMPOSE_PROFILES=pve-exporter启动(pve-exporterprofile 会同时启动内置的 exporter 容器):
docker compose up -d就这么多。Agent 连上之后,集群会自动出现在 OneUptime 仪表盘的Proxmox区域。
compose 文件中的 Token 拆分细节:内置 exporter 服务(docker-compose.yml)要求把 Token ID 拆成PVE_USER(用户部分)和PVE_TOKEN_NAME(令牌名部分)。因此 compose 文件用一段自定义 entrypoint 完成拆分:
entrypoint: ["/bin/sh", "-c"] command: - export PVE_USER="$${PVE_API_TOKEN_ID%%!*}" PVE_TOKEN_NAME="$${PVE_API_TOKEN_ID##*!}" && exec /usr/bin/pve_exporter$$用于屏蔽 docker compose 的插值,保证拆分在容器内完成 —— 这样.env里就可以原样粘贴 Web UI 中显示的完整user@realm!tokenname字符串,无需手工拆开。
已有 pve-exporter 时
如果你已经在别处运行 prometheus-pve-exporter,去掉.env中的COMPOSE_PROFILES、PVE_API_TOKEN_ID和PVE_API_TOKEN_SECRET,改为指向它:
PVE_EXPORTER_URL=your-exporter-host:9221环境变量全量说明
| 变量 | 是否必需 | 说明 |
|---|---|---|
ONEUPTIME_URL | 是 | 你的 OneUptime 实例 URL(如https://oneuptime.com或自托管地址) |
ONEUPTIME_TELEMETRY_INGESTION_KEY | 是 | 来自Project Settings → Telemetry & APM → Ingestion Keys的遥测摄入令牌 |
PROXMOX_CLUSTER_NAME | 是 | 在 OneUptime 中显示的集群标识,会被打上每条指标的proxmox.cluster.name资源属性。保持稳定—— 事后修改会注册出第二个集群。默认proxmox-cluster |
PVE_HOST | 是 | exporter 所查询的 Proxmox VE API 主机(集群任一节点),例如192.168.1.10 |
PVE_EXPORTER_URL | 否 | prometheus-pve-exporter 地址(host:port,不带协议)。默认指向内置 exporter(pve-exporter:9221) |
PVE_API_TOKEN_ID | 仅内置 exporter | 完整 Proxmox API Token ID,例如oneuptime@pve!exporter |
PVE_API_TOKEN_SECRET | 仅内置 exporter | Proxmox API Token 密钥 |
PVE_VERIFY_SSL | 否 | 是否校验 Proxmox API 的 TLS 证书。默认false,因为 Proxmox 出厂自签证书 |
COMPOSE_PROFILES | 否 | 设为pve-exporter以启动内置 exporter 容器 |
默认值行为在 compose 文件中可见:PROXMOX_CLUSTER_NAME缺省回落到proxmox-cluster(docker-compose.yml),PVE_EXPORTER_URL缺省回落到pve-exporter:9221,PVE_HOST缺省回落到localhost(仅当 exporter 直接跑在 PVE 节点上时才有效)。
验证安装
确认 Agent 在运行:
docker compose ps查看 Collector 日志:
docker logs -f oneuptime-proxmox-agent寻找这行:
"Everything is ready. Begin running and processing data."大约一分钟后,集群应当出现在 OneUptime 仪表盘并开始有指标流入。
采集了什么:指标全集
Agent 每 30 秒 scrape 一次 exporter,同时启用 cluster 与 node 两类采集器 —— 这也覆盖了 exporter 默认开启的backup-info(集群级)与replication(节点级)采集器。每条序列都带有id标签用于标识资源:node/<name>、qemu/<vmid>、lxc/<vmid>或storage/<node>/<storage>:
| 类别 | 指标 |
|---|---|
| 可用性 | pve_up、pve_uptime_seconds |
| 节点 | pve_node_info、pve_cpu_usage_ratio、pve_cpu_usage_limit、pve_memory_usage_bytes、pve_memory_size_bytes |
| 虚机 / LXC | pve_guest_info,以及qemu/*与lxc/*上的 CPU / 内存 / 网络序列(pve_network_receive_bytes、pve_network_transmit_bytes) |
| 存储 | pve_disk_usage_bytes、pve_disk_size_bytes、pve_storage_info |
| HA | pve_ha_state |
| 备份覆盖 | pve_not_backed_up_total(未被任何备份作业覆盖的虚机数量;集群级单序列,无id标签)、pve_not_backed_up_info(每个未覆盖虚机一条序列,带其id标签)。注意诚实边界:「被备份作业覆盖」指虚机被至少一个作业选中 —— pve-exporter 并不暴露备份是否近期运行或成功 |
| 复制 | pve_replication_failed_syncs、pve_replication_duration_seconds、pve_replication_last_sync_timestamp_seconds、pve_replication_last_try_timestamp_seconds、pve_replication_next_sync_timestamp_seconds、pve_replication_info—— 按存储复制作业划分,其id标签携带的是复制作业ID(如100-0),不是资源 ID |
派生身份属性:pve.scope/pve.type/pve.id
OneUptime 的监控条件与属性过滤是等值匹配而非前缀匹配,因此随附的 Collector 配置包含一个transform/pve-identity处理器(otel-collector-config.yaml),把id标签拆成三个额外的数据点属性 —— 内置 Proxmox 告警模板正是基于它们过滤的,所以请勿删除该处理器:
| 属性 | 取值 | qemu/100示例 |
|---|---|---|
pve.scope | node、guest、storage、cluster(qemu与lxc均映射到guest) | guest |
pve.type | node、qemu、lxc、storage(cluster/*序列上不设值) | qemu |
pve.id | id中第一个/之后的部分(pve1、100、pve1/local) | 100 |
实现上就是一组基于正则的 OTel transform 语句,例如:
- set(attributes["pve.scope"], "guest") where attributes["id"] != nil and IsMatch(attributes["id"], "^qemu/") - set(attributes["pve.type"], "qemu") where attributes["id"] != nil and IsMatch(attributes["id"], "^qemu/") - set(attributes["pve.id"], attributes["id"]) where attributes["id"] != nil and IsMatch(attributes["id"], "/") - replace_pattern(attributes["pve.id"], "^[^/]+/", "") where attributes["pve.id"] != nil处理器以error_mode: ignore运行(单点失败不阻断批次),且原始id标签保持不动—— 按组页面与拆分视图仍然使用它。
可选:向 OneUptime 发送 Proxmox 服务日志
默认 Agent只发送指标,Proxmox 仪表盘的 Logs 页签保持空白。PVE 控制面把日志写入 systemd journal 下的 8 个单元:pveproxy、pvedaemon、pve-firewall、pve-ha-crm、pve-ha-lrm、pvescheduler、pvestatd与qmeventd。随附的 otel-collector-config.yaml 中已包含一个注释掉的journald接收器,精确指向这 8 个单元(start_at: end避免重启重发历史,priority: info),并接到一段同样被注释的logs管道上 —— 该管道复用resource处理器打上proxmox.cluster.name,使日志落到你的集群名下。
启用步骤:
把 Agent 运行在 PVE 节点上。journal 是逐主机的,远程 Agent 读不到。这是唯一与前面「部署位置建议」冲突的设置;如果你希望指标 Agent 继续留在集群外,就在节点上另跑一个仅日志Collector(复制配置,删掉
prometheus接收器与metrics管道)。取消注释
otel-collector-config.yaml中的journald接收器与logs管道。取消注释
docker-compose.yml中的 journal 卷挂载(docker-compose.yml 中已备好):- /var/log/journal:/var/log/journal:ro - /etc/machine-id:/etc/machine-id:ro更换 Collector 镜像。标准的
otel/opentelemetry-collector-contrib镜像是FROM scratch构建的:既没有 journald 接收器需要 shell 调用的journalctl二进制,又以非 root 用户运行、无权读 journal。构建一个薄包装镜像并把 compose 中的image:指过去:FROM otel/opentelemetry-collector-contrib:latest AS otelcol FROM debian:stable-slim RUN apt-get update \ && apt-get install -y --no-install-recommends systemd \ && rm -rf /var/lib/apt/lists/* COPY --from=otelcol /otelcol-contrib /otelcol-contrib ENTRYPOINT ["/otelcol-contrib"] CMD ["--config", "/etc/otelcol-contrib/config.yaml"]systemd包仅为获取journalctl二进制;该镜像以 root 运行,这正是读 journal 所必需的。另一种做法:日志路径完全跳过 Docker,直接在节点上运行otelcol-contrib发行.deb—— 系统里本来就有journalctl。
日志是逐节点的:journald 接收器只发送 Agent 所在节点自己的 journal。要采集所有节点的服务日志,需在每个节点上分别运行第 1 步所述的仅日志 Collector。
不换镜像的兜底:filelog 读 /var/log/syslog
如果你希望保留标准镜像,可以改读 syslog:在节点上安装 rsyslog(apt install rsyslog—— Debian 12 / PVE 8 起默认不再附带),把/var/log目录挂进容器(挂目录而非文件,避免日志轮转后钉住旧 inode),并用filelog接收器替换 journald:
receivers: filelog: include: - /var/log/syslog start_at: end代价:失去按单元过滤(syslog 是「大杂烩」,不止 8 个 PVE 服务),且标准镜像的非 root 用户必须能读该文件;收益:无需换镜像。把它接进同一段被注释的logs管道即可(receivers: [filelog])。
零安装替代方案 — Proxmox VE 9+ 原生 OTel 推送
Proxmox VE 9.0 及以后版本内置OpenTelemetry 指标服务器,可把节点、虚机、存储指标直接推送到任意 OTLP/HTTP 端点 —— 无需安装任何 Agent 或 exporter。在Datacenter → Metric Server → Add → OpenTelemetry中配置:
| 字段 | 取值 |
|---|---|
| Server | 你的 OneUptime 主机,如oneuptime.com(或自托管主机) |
| Port | 443 |
| Protocol | https |
| Path | /otlp/v1/metrics |
| Headers | {"x-oneuptime-token": "YOUR_TELEMETRY_INGESTION_TOKEN"} |
两个需要知晓的取舍:
- 集群发现。集群自动注册由 Agent 路径驱动,因为它是为每条指标打上
proxmox.cluster.name资源属性的那条链路。使用原生推送时,请把 Metric Server 的Resource Attributes选项设为proxmox.cluster.name=my-proxmox-cluster,集群才会自我注册 —— 否则指标会进入项目,但不会出现任何 Proxmox 集群。 - 指标名不同。原生推送产出
proxmox_node_*/proxmox_vm_*/proxmox_storage_*序列,而 Agent 产出 pve-exporter 的pve_*序列。OneUptime 内置的 Proxmox 指标目录与告警模板针对的是pve_*命名,因此推荐 Agent 路径;原生推送适合作为零安装方式,把原始指标送入 Metrics Explorer 与自定义仪表盘。
两者也可以并存:原生推送提供低延迟原始指标,Agent 负责发现、Proxmox 仪表盘页面与告警模板。
进阶:用 Project Labels 自动打标签
ProxmoxAgent/README.md 还提供了一个扩展技巧:任何以oneuptime.label.开头的资源属性都会被提升为项目 Label 并附加到集群上(模式:oneuptime.label.<维度>=<值>→ 标签<维度>:<值>)。只需在resource处理器中追加:
- key: oneuptime.label.team value: platform action: upsert - key: oneuptime.label.env value: production action: upsert集群即会带上team:platform与env:production标签;标签匹配不区分大小写,已有的同名标签会被复用而非重复创建,手动添加的标签也绝不会被 Agent 删除。
以 systemd 服务运行
为让 Agent 在重启后存活而不只依赖 Docker 的 restart 策略,安装仓库自带的 oneuptime-proxmox-agent.service:
sudo cp systemd/oneuptime-proxmox-agent.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now oneuptime-proxmox-agent该 unit 假设 Agent 位于/opt/oneuptime-proxmox-agent(安装脚本默认值)。从 unit 内容看,它Requires=docker.service、After=network-online.target,并在WorkingDirectory=/opt/oneuptime-proxmox-agent下以docker compose pull(ExecStartPre)→docker compose up --remove-orphans(启动)/docker compose down(停止)管理生命周期,Restart=on-failure且RestartSec=30—— 也就是说开机自启时会自动拉取新镜像,等效于每次重启都执行一次升级流程。
升级、卸载与自托管
升级 Agent:
cd /opt/oneuptime-proxmox-agent docker compose pull docker compose up -d卸载 Agent:
cd /opt/oneuptime-proxmox-agent docker compose down自托管 OneUptime:把ONEUPTIME_URL指向你自己的实例即可:
ONEUPTIME_URL=https://your-oneuptime-host.example.com若实例仅支持 HTTP,改用http://加相应端口。
故障排查
第一步:先跑诊断脚本
Agent 附带一个「doctor」脚本 troubleshoot.sh,从安装 Agent 的机器上运行,它覆盖整条链路:容器运行时状态、exporter scrape、集群名注入、摄入令牌形态、Collector 自监控指标,以及一个确定性的服务端令牌校验。令牌校验是重点 —— OneUptime 的 OTLP 端点对非法摄入令牌故意返回静默的200(这样配置错误的 Collector 不会重试洪泛服务端),意味着 Collector 日志看起来一切正常,而每个数据点其实都在被丢弃。诊断脚本的解法:从 Agent 容器内部的网络命名空间发起GET <url>/otlp/v1/validate,换取真正的200(有效)/401(无效)裁决;老版本服务端没有该端点时,回退到POST /fluentd/v1/logs(走同一套鉴权但不是/otlp路径,坏令牌会返回400 Invalid service token)。
bash troubleshoot.sh # 若未装在 /opt/oneuptime-proxmox-agent,加 -d <dir>脚本以 8 个分节推进,最后输出 VERDICT 小节,直接点名最可能的根因。从源码看,其关键探测手段包括:
- 网络命名空间级探测:Collector 镜像是 distroless(无 shell、无 curl),脚本用
docker run --rm --network container:oneuptime-proxmox-agent curlimages/curl ...起一个共享 Agent 网络命名空间的 curl 兄弟容器,精确复刻 Collector 自己的出网路径(compose 网络、DNS、代理、防火墙、TLS); - exporter 抓取验证(
L209-L239):从 Collector 命名空间内请求http://<PVE_EXPORTER_URL>/pve?target=<PVE_HOST>&cluster=1&node=1,统计pve_*序列数并检查pve_up是否存在;返回 0 条序列时,直接给出「API Token 错误或权限不足」的结论,并自动从内置 exporter 日志中抓取 401/595/auth 相关行作为佐证;它还专门捕获一个隐蔽陷阱 ——PVE_EXPORTER_URL=localhost:*在容器内指向的是 Agent 自己,永远不会是宿主机上的 exporter; - 集群名注入检查(
L249-L268):确认PROXMOX_CLUSTER_NAME非空,且配置文件里确实存在proxmox.cluster.name资源处理器; - 令牌形态检查(
L273-L300):校验 UUID 形态,并专门检测夹带的空白字符(Collector 会原样发送带空格的令牌,导致服务端永远匹配不上); - Collector 自监控(
L303-L329):从命名空间内 scrape127.0.0.1:8888/metrics,汇总otelcol_receiver_accepted_metric_points、otelcol_exporter_sent_metric_points与otelcol_exporter_send_failed_*三组计数器 ——send_failed > 0说明出网/URL/TLS 有问题; - VERDICT(
L437-L484):按优先级裁决 —— 容器未运行 → 令牌被拒(经典陷阱)→ 出网失败 → exporter 无指标 → 集群名缺失 → 令牌含空白/形态错误 → 令牌有效且健康(此时若仪表盘仍显示 Disconnected,提示等待 2–5 分钟的状态翻转周期,并检查是否因改名出现了一个新集群条目)。
OneUptime 中不出现集群
- 查 Collector 日志:
docker logs oneuptime-proxmox-agent—— 导出时的401意味着摄入令牌有误,connection refused 意味着ONEUPTIME_URL不对; - 验证 exporter 抓取本身。内置 exporter 不向宿主机发布端口,需进入其网络命名空间测试:
docker run --rm --network container:oneuptime-pve-exporter curlimages/curl -s "http://localhost:9221/pve?target=YOUR_PVE_HOST" | head,应当打印出pve_*指标行(外置 exporter 则直接curl其host:9221); - 确认
PROXMOX_CLUSTER_NAME已设置 —— 发现机制就是围绕proxmox.cluster.name资源属性建立的。
exporter 日志出现 401 / 认证错误
API Token 错误或权限不足。重新核对 Token ID 格式(user@realm!tokenname)、密钥,以及该 Token 是否对路径/持有PVEAuditor角色(privilege separation 需关闭,或权限直接授给 Token 本身)。
只有节点指标,没有虚机指标
虚机序列(qemu/*、lxc/*)来自 exporter 的 cluster 采集器。随附配置已启用它(cluster=1scrape 参数)—— 如果你改过otel-collector-config.yaml,请恢复cluster: ["1"]参数。
指标落到了错误的集群下
OneUptime 按proxmox.cluster.name(取自PROXMOX_CLUSTER_NAME环境变量)自动注册 Proxmox 集群。首批发遥测之后再改这个值,只会新增一行集群,而不是给旧行改名。
延伸阅读
- 基于 Agent 采集的数据配置Proxmox Monitor,对节点、虚机、存储、HA、备份覆盖与复制状态设置告警,参见 Proxmox Monitor;
- 如果你的集群用 Ceph 作为存储后端,可参考本仓库的 CephAgent 与该 Agent 配套部署;
- 完整的安装文档源文件位于 App/FeatureSet/Docs/Content/en/telemetry/proxmox.md,Agent 目录说明见 ProxmoxAgent/README.md。
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考