HOME

Veeam Backup & Replication 13 接入 Zabbix 7.0 踩坑记录:从 401 到 API 版本不兼容

文章目录25 节

Veeam Backup & Replication 13 接入 Zabbix 7.0 踩坑记录:从 401 到 API 版本不兼容

一、这次接入为什么值得单独记录

在完成 Veeam Backup & Replication 13 存储库实验 后,我准备把 VBR 的作业、会话、Proxy 和存储库状态接入 Zabbix。

一开始我以为这只是“关联官方模板、填写账号密码”这样一个很短的操作。实际接入时却连续遇到了四类问题:

  1. Zabbix 官网的 Veeam 集成页面同时涉及 Enterprise Manager 与 VBR REST API,端口和适用对象并不相同。
  2. Veeam 的“添加用户”只给已有身份分配角色,不负责创建 Appliance 本地账户。
  3. 新建 Local User 需要先在 VBR Web UI 完成首次密码修改,否则 REST API 一直返回 401。
  4. 身份认证成功后,Zabbix 7.0 内置模板又因为硬编码旧 API 版本,无法处理 VBR 13 返回的 Stopped 状态。

最后真正解决问题的关键,不是继续猜用户名格式,而是把每一层证据拆开验证:

flowchart TD
    A["Zabbix 没有 Veeam 数据"] --> B["确认模板与 API 对象"]
    B --> C["确认 9398 与 9419 端口"]
    C --> D["确认 Bearer 认证链路"]
    D --> E["从 Zabbix Server 日志定位 401"]
    E --> F["完成 Appliance 本地用户首次密码修改"]
    F --> G["认证通过,但作业状态接口返回 500"]
    G --> H["检查模板中的 x-api-version"]
    H --> I["读取 VBR 13 本机 Swagger"]
    I --> J["确认 1.3-rev1 支持 Stopped"]
    J --> K["修改两处 API 版本并重新采集"]

本文按我实际排查的顺序记录失败、证据、修复和验证结果。公开内容中的地址、主机名、账户和资源标识均已替换;版本、端口、错误文本、API 字段和最终统计来自本次实验。

二、实验环境与验证边界

项目本次环境
Veeam Backup & ReplicationLinux Appliance,build 13.0.2.29
VBR Web UIHTTPS 443
VBR REST APIHTTPS 9419
Veeam Host ManagementHTTPS 10443
Zabbix ServerZabbix 7.0.26,Rocky Linux 9
Zabbix 模板Veeam Backup and Replication by HTTP,vendor version 7.0-1
数据采集方式Zabbix Script item 主动调用 VBR REST API
监控账户Appliance Local User,并在 VBR 中分配 Veeam Backup Viewer

这次已经验证:

  • Zabbix Server 能访问 VBR REST API。
  • 专用只读账户可以通过 OAuth2 password grant 获取令牌。
  • Proxy、受管服务器、存储库、作业状态和会话数据均能返回。
  • 修改 API 版本后,Zabbix 自动发现所需的原始 JSON 能正常生成。

这次没有验证:

  • VBR 或 Zabbix 后续升级是否会覆盖模板修改。
  • 使用正式 CA 签发证书后的完整证书校验链。
  • 大规模环境中超过 API 默认分页上限后的采集行为。
  • Zabbix 告警动作、通知媒介和长期告警降噪策略。

三、第一坑:Enterprise Manager 模板和 VBR 模板不是一回事

我最初参考的是 Zabbix 官方 Veeam 集成页面。页面中的 Enterprise Manager 模板依赖 Veeam Backup Enterprise Manager REST API,默认端口为 9398;它并不是直接访问 VBR 13 Appliance 的 443 Web UI。

我的环境没有部署 Enterprise Manager,但 VBR 13 自身提供了 REST API。为了避免仅凭产品名称判断,我直接从 Zabbix Server 测试了几个入口。

风险等级:INFO(只读网络探测)

作用: 从 Zabbix Server 检查 VBR Web UI、Enterprise Manager API 和 VBR REST API 的连通性与 HTTP 状态。 执行位置: Zabbix Server。 需要替换: VBR_HOST 应替换为自己的 VBR 地址;示例地址属于文档地址段。 注意事项: -k 会跳过 TLS 证书校验,只适合隔离实验环境的定位过程。生产环境应部署受信任证书并移除 -k。 完成判断: 端口 9419 返回 401 且带有 Bearer 认证要求,说明服务在线,只是尚未认证。

VBR_HOST='192.0.2.30'

for url in \
  "https://$VBR_HOST/" \
  "https://$VBR_HOST:9398/api/sessionMngr/" \
  "https://$VBR_HOST:9419/api/v1/serverInfo"
do
  curl -k -sS \
    --connect-timeout 3 \
    --max-time 8 \
    -o /dev/null \
    -w "$url code=%{http_code} connect=%{time_connect} total=%{time_total}\n" \
    "$url" || true
done

本次现场结果可以概括为:

https://<VBR_HOST>/                              code=200
https://<VBR_HOST>:9398/api/sessionMngr/        code=000(连接超时)
https://<VBR_HOST>:9419/api/v1/serverInfo       code=401

这组结果说明:

  • 443 的 VBR Web UI 正常。
  • 9398 没有 Enterprise Manager API 服务。
  • 9419 的 VBR REST API 正常在线,并要求 Bearer Token。

因此我没有继续使用 Enterprise Manager 模板,而是选择 Zabbix 7.0 已经内置的:

Veeam Backup and Replication by HTTP

这个模板不需要 Zabbix Agent,也不需要为主机添加 Agent、SNMP 或 JMX 接口。主监控项是 Script item,由 Zabbix Server 主动访问 9419。

四、第二坑:Veeam 的“添加用户”不是创建本地账户

关联模板后,主机最初只有两个静态监控项:

  • Get metrics:登录 API 并获取所有原始 JSON。
  • Get errors:从主监控项中提取错误。

其余作业、会话、存储库和 Proxy 监控项都依赖低级别自动发现,因此 Get metrics 一旦失败,页面看起来就像“没有任何反应”。

模板要求三个主机宏:

示例值说明
{$VEEAM.API.URL}https://192.0.2.30:9419VBR REST API 根地址
{$VEEAM.USER}<MONITOR_USER>专用 Appliance Local User,替换为实际登录名
{$VEEAM.PASSWORD}使用秘密文本保存专用账户密码

我第一次在 VBR 的“用户和角色”页面直接输入一个新用户名,界面返回:

Invalid user name.

后来我确认,这个窗口只负责把 VBR 内置角色分配给一个已经存在的内部或外部身份,并不会创建 Appliance 本地账户。

正确顺序是:

  1. 登录 Veeam Host Management 的 10443 管理界面。
  2. 在 Users and Roles 中创建一个 Local User。
  3. 回到 VBR 443 Web UI 的用户管理页面。
  4. 将这个本地用户加入 VBR,并分配 Veeam Backup Viewer。
  5. 让该用户先登录一次 VBR 443 Web UI,完成首次密码修改。
  6. 最后把新密码写入 Zabbix 的秘密宏。

风险等级:CAUTION(创建持久化身份并保存 API 凭据)

作用: 为 Zabbix 创建专用最小权限账户,避免长期使用 VBR 管理员凭据。 影响: 操作会新增 Appliance 本地用户、VBR 角色分配和 Zabbix Secret macro。 注意事项: 不要把管理员密码作为长期监控凭据;不要在 Zabbix 的“测试监控项”截图中暴露宏解析后的秘密值。 回退: 先禁用或解除 Zabbix 主机关联,再从 VBR 撤销角色,最后在 Host Management 中删除确认不再使用的专用账户。 完成验证: 专用用户能登录 VBR 443 并完成首次密码修改,随后 Zabbix 不再返回 401。

Host Management 中的 Local User 和 Service Account 也不能混为一谈:

  • Local User 用于根据 VBR 分配的角色执行备份、还原和只读查看操作,首次登录需要修改密码。
  • Host Management 的 Service Account 主要用于独立备份代理和插件认证,不能交互登录管理控制台,也不要求周期轮换密码。

本次我使用 Local User,再给它分配 Veeam Backup Viewer。这个账户不能登录 10443 Host Management 页面是正常现象;它要首次登录的是 VBR 的 443 Web UI。

五、第三坑:页面没数据时,先看 Zabbix Server 日志

我最开始只在浏览器里反复点击“立即执行”,但自动发现始终没有生成数据。后来直接查看 Zabbix Server 日志,排查速度快了很多。

风险等级:INFO(只读日志检查)

作用: 从 Zabbix Server 日志中筛选 Veeam Script item、自动发现和不支持状态的错误。 执行位置: Zabbix Server;读取日志可能需要 sudo。 注意事项: 日志可能包含内部地址、主机名、用户名和 API 返回内容,对外分享前需要脱敏。tail 限定了读取范围,避免扫描完整历史日志。 预期结果: 能区分宏缺失、认证失败、API 服务错误和自动发现预处理错误。

sudo tail -n 2500 /var/log/zabbix/zabbix_server.log |
  grep -E 'VEEAM|veeam|get.metrics|unsupported|failed' |
  tail -n 120

第一阶段日志明确显示:

[ VEEAM ] ERROR: Required param is not set: user.
discovery rule "...veeam.job.state.discovery" became not supported

补齐用户名和密码后,错误变成:

[ VEEAM ] ERROR: Login failed with status code 401:
{"errorCode":"AccessDenied","message":"Authentication failed","status":401}

这两个错误代表不同阶段:

  • Required param is not set 说明 Zabbix 宏没有传进脚本。
  • 401 说明请求已经到达令牌接口,但身份认证失败。

我没有把 401 误判成网络问题,因为同一台 Zabbix Server 访问 9419 已经稳定返回 HTTP 响应。

六、401 的真正原因:首次密码修改没有完成

专用 Local User 创建并分配 Viewer 角色后,我曾尝试让它登录 10443。页面提示:

User "<MONITOR_USER>" is not allowed to login.

这个结果一度看起来像账户不可用。结合 Host Management 页面中的角色说明,我才确认 Local User 本来就不允许登录 Host Management 管理控制台。

它的首次登录入口是:

https://<VBR_HOST>/

也就是 VBR 443 Web UI。

我用专用账户登录 443,按提示修改临时密码,再把新密码更新到 Zabbix Secret macro。重新测试后,401 消失,说明网络、账户、密码与角色认证链路已经打通。

如果账户模式被设置为禁止交互登录,应先由管理员确认账户类型和服务账户配置,完成必要的首次密码设置后再用于无人值守监控。不要通过不断重复错误密码来试探,否则可能触发账户锁定。

七、第四坑:认证成功后,API 又返回 500

401 解决以后,Get metrics 没有马上成功,而是出现了新的 500:

Request failed with status code 500:
{
  "errorCode": "ServiceUnavailable",
  "message": "The value of enum EJobStatus is not supported (Parameter 'source')\nActual value was Stopped.",
  "status": 500
}

这个错误和认证已经无关。最重要的线索是:

EJobStatus
Actual value was Stopped

API 已经成功读取到了某个作业的真实状态 Stopped,但在把它转换成当前请求版本的 EJobStatus 时失败了。

此时有两个可能方向:

  1. VBR 13 自身不支持 Stopped。
  2. Zabbix 请求了一个过旧的 API 版本,而旧版本的枚举中没有 Stopped。

为了判断是哪一种,我同时检查了 Zabbix 模板脚本和 VBR 13 本机 Swagger。

八、我是怎么确认 API 版本不一致的

1. 先检查 Zabbix 模板实际发送的版本

Zabbix 7.0-1 模板的 Get metrics 脚本中,有两处硬编码:

login.addHeader('x-api-version: 1.0-rev2');
request.addHeader('x-api-version: 1.0-rev2');

第一处用于获取 Token,第二处用于访问 Proxy、受管服务器、存储库、作业和会话接口。也就是说,即使 VBR 13 支持更新版本,模板仍会强制让服务器按 1.0-rev2 返回数据。

2. 再读取 VBR 13 自己发布的 Swagger

VBR REST API 自带 Swagger,入口是:

https://<VBR_HOST>:9419/swagger/index.html

Swagger 页面加载的 index.js 会列出当前服务器实际支持的版本。本次环境的最高版本是:

1.3-rev1

风险等级:INFO(只读读取 API 定义)

作用: 读取当前 VBR 实例发布的 Swagger 规范,确认 API 版本和 EJobStatus 枚举,而不是依赖网上可能已经过期的截图或文章。 执行位置: 任意能访问 VBR 9419 的受控管理主机。 依赖: 需要 curl 和 jq。 注意事项: 示例继续使用 -k 跳过实验环境的自签名证书校验;生产环境应验证证书。 预期结果: info.version 返回当前版本,EJobStatus.enum 中包含 Stopped。

VBR_HOST='192.0.2.30'

curl -k -sS \
  "https://$VBR_HOST:9419/swagger/v1.3-rev1/swagger.json" |
  jq '{
    api_version: .info.version,
    job_status: .components.schemas.EJobStatus.enum
  }'

本次读取到的结果为:

{
  "api_version": "1.3-rev1",
  "job_status": [
    "Running",
    "Inactive",
    "Disabled",
    "Enabled",
    "Stopping",
    "Stopped",
    "Starting"
  ]
}

3. 把四条证据连起来

我最终确认版本不一致,依赖的是下面这条完整证据链:

  1. VBR 实际作业状态为 Stopped。
  2. 使用 1.0-rev2 请求作业状态时,服务端报告 EJobStatus 不支持 Stopped。
  3. VBR 13 本机发布的 1.3-rev1 Swagger 明确把 Stopped 列在 EJobStatus 中。
  4. Zabbix 模板脚本正好把所有请求硬编码成 1.0-rev2。

因此根因不是“VBR 作业状态异常”,也不是“Zabbix 7.0 太旧所以完全不能监控”,而是:

Zabbix 7.0 内置 Veeam 模板仍按旧 REST API 版本请求数据,与 VBR 13 当前返回的作业状态枚举不兼容。

这也解释了为什么认证失败时只看到 401;只有在认证成功、真正访问 jobs/states 以后,版本兼容问题才暴露出来。

九、修改模板中的两处 API 版本

我的实验环境当时只有一个 VBR 主机关联该模板,因此直接修改了模板。生产环境更稳妥的做法是克隆一份 VBR 13 专用模板,避免官方模板升级或重新导入时覆盖自定义内容。

风险等级:CAUTION(修改共享 Zabbix 模板脚本)

作用: 让 Token 请求和后续数据请求都使用 VBR 13 当前支持的 1.3-rev1。 执行前检查: 在 Zabbix 的模板页面确认有哪些主机正在使用该模板,并复制保存原脚本。 影响: 修改会影响所有关联该模板的主机;若环境中还有旧版 VBR,应拆分模板,而不是统一强制升级 API 版本。 回退: 把两处 x-api-version 恢复为 1.0-rev2,或重新导入修改前导出的模板。 完成验证: Get metrics 返回完整 JSON,Get errors 为空,自动发现规则恢复支持状态。

我将两处:

login.addHeader('x-api-version: 1.0-rev2');
request.addHeader('x-api-version: 1.0-rev2');

改为:

login.addHeader('x-api-version: 1.3-rev1');
request.addHeader('x-api-version: 1.3-rev1');

修改位置:

数据采集
  → 模板
  → Veeam Backup and Replication by HTTP
  → 监控项
  → Get metrics

保存模板后,我回到主机的 Get metrics 监控项执行“立即执行”,再检查 Get errors 和自动发现状态。

十、最终采集结果

修改 API 版本后,Get metrics 返回了完整 JSON,并且没有 error 字段。

本次采集到的对象数量为:

数据类型数量验证结果
Proxy2General Purpose Proxy 与 VMware Backup Proxy 均返回
受管服务器4vCenter、Windows Repository、Linux Repository 与 VBR Appliance 均为 Available
存储库3全部 isOnline=true,组件均未过期
备份作业2状态均为 Stopped,最近结果均为 Success,进度 100%
最近会话2923 个 Success、3 个 Warning、2 个 Failed、1 个 None/运行中

两个用于真实备份实验的作业均成功返回:

指标Linux XFS 加固存储库作业Windows ReFS 存储库作业
最近结果SuccessSuccess
最终状态StoppedStopped
进度100%100%
会话时长约 1 小时 09 分约 10 分钟
API 报告瓶颈TargetSource

存储库数据也与实验环境的容量变化对应:

存储库总容量可用空间已用空间在线
Linux XFS Hardened Repository约 499.7 GB约 430.5 GB约 65.7 GB
Windows ReFS Repository约 499.9 GB约 478.0 GB约 18.9 GB
Appliance 默认存储库约 206.9 GB约 202.4 GBAPI 报告约 0 GB

这些结果证明当前监控链路已经能够读取真实 VBR 对象和作业结果,而不只是“Token 获取成功”。

十一、自动发现完成后还要处理告警噪声

官方模板默认使用:

{$CREATED.AFTER}=7

也就是获取最近 7 天的会话。本次实验返回的 29 个会话中,包含历史卷发现失败和恶意软件检测失败记录。模板会为失败会话创建触发器,而且部分触发器需要手动关闭。

因此接入成功后可能立刻看到历史问题,这不代表刚刚配置的监控失败。

我准备根据实际监控目标继续调整:

  • {SESSION.NAME.MATCHES} 与 {SESSION.NAME.NOT_MATCHES}
  • {SESSION.TYPE.MATCHES} 与 {SESSION.TYPE.NOT_MATCHES}
  • {JOB.NAME.MATCHES} 与 {JOB.NAME.NOT_MATCHES}
  • 会话查询天数与历史问题保留范围

生产环境不应为了让页面“全绿”而无条件排除所有失败类型。更合理的做法是先判断哪些会话代表备份保护失败,哪些只是基础设施发现、组件更新或实验遗留任务,再分别设计严重性和恢复条件。

十二、这次排查中最容易误判的地方

1. 9419 返回 401 不代表 API 服务异常

未认证访问受保护接口时返回 401,反而证明 HTTPS 服务与路由已经工作。网络不可达通常表现为连接超时、拒绝连接或 TLS 握手失败。

2. 主机没有 Agent 接口不是问题

这个模板的主监控项是 Script item,由 Zabbix Server 主动请求 VBR API,不依赖 Zabbix Agent 接口。

3. Invalid user name 不只是字符格式问题

VBR 的“添加用户”页面需要一个已经存在的身份。没有先在 Host Management 或外部身份源中创建用户,即使改成“主机名加反斜杠加用户名”也仍会失败。

4. Local User 不能登录 10443 是正常边界

10443 是 Host Management 管理控制台。用于 VBR 操作的 Local User 需要登录的是 443 VBR Web UI,并在首次登录时修改密码。

5. 401 和 500 属于不同层

  • 401:身份认证没有通过。
  • 403:身份通过,但权限不足。
  • 500 加 EJobStatus/Stopped:数据已经进入接口处理阶段,问题转向 API 版本和模型兼容性。

6. “Zabbix 版本满足要求”不等于“模板兼容当前 VBR”

官方模板要求 Zabbix 7.0 或更高,但模板文档明确只测试过 VBR 11。兼容性至少要同时检查:

  • Zabbix Server 版本。
  • 模板 vendor version。
  • 模板请求的 x-api-version。
  • VBR 当前 Swagger 发布的 API 版本。
  • 实际返回字段和枚举。

十三、我最终保留的配置

主机级宏:

{$VEEAM.API.URL} = https://<VBR_HOST>:9419
{$VEEAM.USER} = <MONITOR_USER>
{$VEEAM.PASSWORD} = <SECRET_PASSWORD>
{$CREATED.AFTER} = 7

模板脚本:

x-api-version: 1.3-rev1

账户边界:

Appliance Local User
  → VBR 内置角色 Veeam Backup Viewer
  → Zabbix Secret macro
  → OAuth2 Token
  → VBR REST API 9419

我没有在文章中保留真实密码、内部地址、主机名、用户名、UUID、凭据 ID 或资源 ID。Zabbix 的“获取值并进行测试”页面会展开 Secret macro,截图和工单流转时尤其要注意。

十四、后续改进方向

这次为了快速验证,我直接修改了内置模板。后续更适合长期维护的方式是:

  1. 克隆出 VBR 13 专用模板,保留官方模板作为回退。
  2. 把 API 版本改成宏,例如 {$VEEAM.API.VERSION},避免继续硬编码。
  3. 根据 VBR 版本分别关联模板,避免旧服务器被迫使用新 API。
  4. 为 REST API 部署可信证书,去掉诊断阶段的 -k。
  5. 对专用监控账户实施密码轮换,并同步更新 Zabbix Secret macro。
  6. 调整会话发现过滤器,区分备份失败、基础设施发现失败与历史实验记录。
  7. 为作业失败、存储库离线和剩余容量建立独立告警动作。

我暂时不会把这次单次成功采集写成“所有后续版本都兼容”。真正的完成标准还包括连续采集、模板升级后的回归验证,以及 VBR 升级后重新比对本机 Swagger。

十五、结论

这次接入最终让我确认了三件事:

  • VBR 13 Appliance 应通过 9419 的 VBR REST API 监控,而不是在没有 Enterprise Manager 的环境中强行使用 9398 模板。
  • Local User、VBR 角色和首次密码修改属于三层不同的账户状态;其中任意一层没完成,Zabbix 都可能只看到 401。
  • 当 API 报告 EJobStatus 不支持 Stopped 时,应该检查请求版本和本机 Swagger,而不是把 Stopped 当成异常作业状态。

最终修复只有两行:

login.addHeader('x-api-version: 1.3-rev1');
request.addHeader('x-api-version: 1.3-rev1');

但真正重要的是找到这两行的证据链:端口探测证明选对 API,日志证明认证阶段,401 消失证明账户链路已通,500 中的 Stopped 指向枚举转换,再由 VBR 13 本机 Swagger 证明 1.3-rev1 已支持该枚举。

参考资料

Veeam Zabbix REST API 监控 故障排查 兼容性