VictoriaMetrics 单机房三机器三副本部署与单机故障扩容恢复 Runbook
1. 结论先说
是的:如果你的故障域是“机器”,并且每台机器有 3 块盘,通常应该是 每台机器启动 1 个 vmstorage,而不是每块盘启动 1 个 vmstorage。
推荐形态:
| |
每台机器的 3 块盘先在 OS 层做成一个数据卷,例如:
- RAID0/LVM stripe:容量和性能最好,但任意一块盘坏了就按这台机器故障处理。
- RAID5/RAIDZ1:能扛本机单盘故障,但写放大和恢复成本更高。
- 云盘/分布式盘:如果底层盘本身已有高可靠能力,可以直接挂到
-storageDataPath。
vmstorage 自己只关心一个 -storageDataPath。多块盘怎么组合,是文件系统/块设备/云盘层的事情。
2. 为什么不是每盘一个 vmstorage
如果一台机器 3 块盘、3 台机器一共 9 块盘,你把它拆成 9 个 vmstorage,再配置:
| |
问题是 VictoriaMetrics 的应用层副本是按 vmstorage 节点做的,不知道哪些 vmstorage 在同一台物理机上。官方文档说明:-replicationFactor=N 会把每个样本写到 N 个不同的 vmstorage 节点,并且为了在 N-1 个 storage 不可用时仍维持新写入的 N 副本,集群至少需要 2*N-1 个 vmstorage。
所以 RF=3 时,严格意义上至少需要 5 个 vmstorage 才能在故障期继续维持新写入三副本。9 个扁平 vmstorage 看起来满足数量,但不满足“机器故障域对齐”:一台机器挂掉会同时丢 3 个 vmstorage,副本是否跨机器并没有被保证。
因此在你的模型下,更自然的做法是:
- 3 台机器 = 3 个
vmstorage节点。 - 每台机器 3 块盘 = 这个
vmstorage的本地数据卷。 vminsert -replicationFactor=3= 每条样本写到三台机器各一份。
3. 需要接受的限制
3 台机器、3 个 vmstorage、RF=3 是一个很清晰的三副本模型,但它不是“故障期间仍能维持三副本写入”的模型。
官方的 2*N-1 约束意味着:RF=3 要在 N-1 个 storage 不可用时仍维持新写入三副本,需要至少 5 个 vmstorage。你只有 3 个 vmstorage 时:
- 正常状态下,每条样本三副本完整。
- 坏 1 台机器后,历史数据仍可从剩余副本查询。
- 坏 1 台机器期间,新写入无法同时落到 3 个
vmstorage,因为只剩 2 个可用节点。 - 默认情况下,
vminsert会把新样本重路由到剩余可用的vmstorage,所以故障期通常是降级写入;但架构上不能宣称这段时间仍满足三副本。
如果你要求“坏 1 台机器后,新写入也严格三副本”,需要至少 5 台机器或 5 个跨机器故障域,而不是 3 台机器。
4. 正常部署示例
4.1 机器与磁盘规划
| 机器 | vmstorage | 数据路径 | 物理盘 |
|---|---|---|---|
| host-a | vmstorage-a | /data/vmstorage | disk1 + disk2 + disk3 |
| host-b | vmstorage-b | /data/vmstorage | disk1 + disk2 + disk3 |
| host-c | vmstorage-c | /data/vmstorage | disk1 + disk2 + disk3 |
/data/vmstorage 是三块盘组合出来的一个挂载点。不要把 3 块盘分别挂成 3 个 VM 数据目录。
4.2 vmstorage
host-a:
| |
host-b、host-c 只需要替换主机名和 systemd 单元,不需要改端口。
4.3 vminsert
建议至少部署 2 个 vminsert,无状态,前面挂 LB 或 vmauth。
| |
外部 remote write 地址:
| |
4.4 vmselect
建议至少部署 2 个 vmselect,无状态,前面挂 LB 或 vmauth。
| |
如果你有两个 vmagent 或两套 Prometheus 同时采同一批 target,会产生非完全同 timestamp 的重复样本,那么把 -dedup.minScrapeInterval 设置为实际 scrape_interval,例如 15s。
4.5 vmagent
这种情况下,vmagent 只需要写一个 VictoriaMetrics Cluster 入口,不需要配置 3 个 -remoteWrite.url。官方也说明,VictoriaMetrics Cluster 自身支持复制,写入同一个集群时不需要给同一集群配置多个 remote write URL。
| |
vmagent 队列仍然很重要:如果 vminsert 入口临时不可用,数据可以先落到 -remoteWrite.tmpDataPath,恢复后补发。
5. 备份策略
5.1 备份对象
集群模式下,vmbackup 需要在每个 vmstorage 节点上分别运行。这个架构只有 3 个 vmstorage,所以是 3 份备份任务,不是 9 份。
备份目录必须按节点分开:
| |
5.2 每小时增量备份
host-a:
| |
host-b:
| |
host-c:
| |
5.3 每日保留点
可以每天从 latest 做服务端 copy,形成日期目录:
| |
三个节点都做。注意每日 copy 与小时增量不要同时跑。
5.4 备份巡检
每天检查:
- 3 个
vmbackup任务都成功。 - 每个备份目录都有最近更新时间。
- 备份耗时没有异常变长。
- 备份失败后用相同参数重跑,
vmbackup支持从中断点继续。 - 定期抽样
vmrestore演练。
6. 单机永久故障后的扩容恢复流程
以下假设 host-b 永久故障,需要新增 host-d 接替它。
6.1 事故确认
确认:
host-b:8400、host-b:8401、host-b:8482不可达。vminsert日志出现写入host-b失败或不可达。vmselect查询仍可用,但处于少一个副本的降级状态。host-a、host-c的 CPU、内存、磁盘 IO、磁盘空间正常。
此时不要把 host-b 从 vminsert/vmselect 配置里随手删除后就不管。你需要尽快恢复第三个 vmstorage,否则故障窗口内的新数据副本数不足。
6.2 新机器准备
新增 host-d:
- 规格不低于
host-b。 - 3 块盘按原方案组合成
/data/vmstorage。 - 文件系统、mount 参数、目录权限保持一致。
- 安装同版本 VictoriaMetrics。
- 配置 systemd、ulimit、监控采集、日志、对象存储凭证。
6.3 停止接收故障节点写入
恢复前先保证 host-d 的 vmstorage 不在运行。
如果你有 LB/DNS:
- 暂时不要把
host-b的名字指向host-d并立即接流量。 - 先完成
vmrestore,再切流量。
如果配置写死主机名:
- 准备好
vminsert和vmselect的新配置,把host-b替换为host-d,但先不要重启。
6.4 从备份恢复 vmstorage-b
在 host-d 上恢复原 vmstorage-b 的最近备份:
| |
注意:
vmrestore需要在对应 VictoriaMetrics 进程停止时运行。- 目标
-storageDataPath要确认无误。 latest只能恢复到最后一次成功备份的时间点。- 备份点之后、host-b 故障之前的数据,理论上还在 host-a 和 host-c 上。
- host-b 故障之后、host-d 加入之前的新数据,第三副本需要后续补齐;VictoriaMetrics 不会自动把已有历史数据从其他
vmstorage后台重平衡到新节点。
6.5 启动新 vmstorage
启动 host-d:
| |
检查:
| |
6.6 切换 vminsert/vmselect
把所有 vminsert 配置中的 host-b:8400 替换为 host-d:8400,并滚动重启:
| |
把所有 vmselect 配置中的 host-b:8401 替换为 host-d:8401,并滚动重启:
| |
如果使用稳定 DNS,例如 vmstorage-b.example,则可以把 DNS 指向 host-d,配置无需改。
6.7 恢复故障窗口的第三副本
这里要分清两类数据:
vmrestore之前已经在备份里的数据:host-d 已恢复出一份。- 备份之后缺在 host-d 上的数据:需要额外补齐,特别是 host-b 故障期间的新写入。
VictoriaMetrics Cluster 不会因为新节点加入而自动把历史数据重平衡到这个节点。因此如果你要求恢复严格三副本,需要从健康节点导出缺口时间段,再导入到新节点所在的集群入口。
可选流程:
- 确认缺口时间范围:
| |
- 从正常查询入口导出 native 数据:
| |
- 导入回集群入口:
| |
注意:这一步会让 vminsert 按当前 RF=3 写到 host-a、host-d、host-c。因为 host-a 和 host-c 已经有这段数据,查询侧必须依赖 dedup 去重。该流程 IO 和网络成本很高,建议按 tenant、核心指标或较短时间窗口分批执行。
如果你能接受“故障窗口内只有 2 副本”,可以不做回灌;但要在故障复盘里明确记录这个风险窗口。
6.8 恢复后的立即备份
host-d 恢复并补齐后,立即刷新它的备份:
| |
然后恢复正常的周期性备份。
7. 验收检查
恢复完成后检查:
- 所有
vminsert都能连通host-a:8400、host-d:8400、host-c:8400。 - 所有
vmselect都能连通host-a:8401、host-d:8401、host-c:8401。 - 查询最近 1 小时、24 小时、7 天核心指标正常。
isPartial不再异常出现。vmagent_remotewrite_pending_data_bytes下降到正常水位。vmagent_remotewrite_packets_dropped_total没有增长。- 新 host 的
vmbackup成功。
8. 监控与告警
必须告警:
- 任意
vmstorage不可达:vm_rpc_vmstorage_is_reachable == 0 - 任意
vmstorage只读:vm_storage_is_read_only == 1 vmagentremote write 积压持续增长:vmagent_remotewrite_pending_data_bytesvmagent丢弃数据:rate(vmagent_remotewrite_packets_dropped_total[5m]) > 0vmbackup失败或超时。vmstorage磁盘剩余空间低于 20%。- 查询响应出现非预期 partial。
建议面板:
- 每个
vmstorage的写入速率、查询速率、CPU、内存、IO wait、磁盘延迟。 - 每台机器
/data/vmstorage使用率。 vminsert到各 storage node 的错误率。vmagentpending bytes 和 dropped packets。- 每个
vmbackup最近成功时间和耗时。
9. 什么时候才需要每盘一个 vmstorage
只有在你明确想让“单块盘”成为独立调度/扩容/故障单元时,才考虑每盘一个 vmstorage。例如:
- 机器很多,单盘很多,想把每块盘都作为独立 storage shard。
- 能接受单台机器故障会同时损失多个
vmstorage,并且副本分布另有机制保证跨机器。 - 有足够节点数满足 RF 的
2*N-1约束,并能把同一副本的节点分散到不同机器故障域。
在你当前“三台机器、每台三盘、按机器故障扩容恢复”的需求里,每盘一个 vmstorage 反而会增加复杂度并制造误解。
10. 最终建议
你的场景推荐:
host-a/b/c各启动 1 个vmstorage。- 每台机器 3 块盘合成一个
/data/vmstorage。 vminsert配 3 个 storage node,并启用-replicationFactor=3。vmselect配 3 个 storage node,并启用-replicationFactor=3和 dedup。vmbackup只需要 3 份,分别对应 3 个vmstorage。- 单机永久故障时,新增一台机器,恢复故障节点的那一份
vmbackup,替换vminsert/vmselect中的 storage node;如需严格补齐故障窗口第三副本,再做 export/import 回灌。