做运维的同行应该都深有体会,Prometheus默认的本地存储机制,在实际生产环境中往往只能算一个“临时方案”。数据存储在本地磁盘,不仅容量有限、缺乏冗余,一旦节点发生故障数据就可能丢失。此外,长期(例如一个月以上)保留数据极易导致磁盘爆满,查询性能也会变得十分卡顿。
因此,在生产环境中为Prometheus搭建一个可靠、可扩展的长期存储后端,几乎是一项必须完成的运维基础工作。我们团队之前也陆续尝试过Thanos、Cortex等方案,最终选定了VMCluster(VictoriaMetrics Cluster版本)。它在稳定性、扩展性和性能之间取得了很好的平衡。本文将分享完整的部署流程、核心配置逻辑以及我们踩过的坑,所有配置和命令均可直接复制使用,希望能帮你省去自行摸索的时间。
一、方案选型:为什么最终选择VMCluster?
在对比了主流的Prometheus长期存储方案后,我们之所以锁定VMCluster,主要基于以下三点核心考量,这些都是贴合实际运维需求、踩过坑后总结出来的经验:
-
架构轻量,运维简单:VMCluster的核心组件只有三个——vmstorage(负责数据存储)、vminsert(数据写入入口)和vmselect(数据查询入口)。没有复杂的依赖,部署和水平扩容都相对简单。相比之下,像Thanos这样的方案还需要搭配对象存储、Sidecar等组件,整套系统部署和维护的复杂度与成本会高很多,对于小型团队来说负担较重。
-
性能出色,查询高效:VictoriaMetrics的存储引擎经过了深度优化,相比Prometheus原生存储可以节省一半以上的磁盘空间,并且能够承受较高的IO并发压力。在我们的实际场景中,面对千万级别的时间序列,查询监控图表依然可以做到秒级响应。而之前测试过的其他一些存储方案,在业务高峰期查询图表可能需要等待十几秒,严重影响了运维效率。
-
集群模式稳定,保障数据安全:它原生支持多副本和数据分片,能够根据业务压力进行水平扩容,从根本上解决了单节点存储“一挂全丢”的致命问题。对于生产环境而言,数据安全是重中之重,VMCluster在这方面完全符合要求。
二、完整配置文件(values.yaml)及核心逻辑拆解
下面是我们生产环境实际使用的values.yaml配置文件。每一行关键配置都附上了我们的配置逻辑和踩坑经验,理解了“为什么这么配”,你就不用再反复查阅官方文档进行试错了。
# 核心 values.yaml
vmsingle:
enabled: false # 重要提示:必须禁用!否则集群模式无法启用
# 踩坑记录:初次部署时未关闭此项,导致vmcluster组件始终无法启动,排查日志才发现问题。
# 单节点模式(vmsingle)与集群模式(vmcluster)是互斥的。启用vmsingle会强制禁用vmcluster。
# 切记:只要部署集群,此项必须设置为 false。
vmcluster:
enabled: true # 核心:启用VMCluster集群模式,作为Prometheus的后端存储
spec:
retentionPeriod: "30d" # 数据保留30天,生产环境建议不低于30天
# 可根据业务需求调整,若无需长期回溯,可设置为7-15天,但建议不低于7天。
replicationFactor: 2 # 数据副本数设为2,生产环境至少2副本以保证高可用
# 解读:每份数据会同步写入到2个不同的vmstorage节点。即使一个节点故障,数据依然可用。
# 切勿因省事设置为1,否则遭遇单点故障时将面临数据丢失风险。
# vmstorage:核心存储组件,所有监控数据最终落地于此
vmstorage:
replicaCount: 2 # Pod副本数,应与上方的数据副本数对应,设为2个
# 注意:Pod副本数必须 ≥ 数据副本数(replicationFactor),否则数据同步会失败。
storage:
volumeClaimTemplates:
spec:
storageClassName: "nfs-slow" # 警告:生产环境请务必替换为SSD存储类!
# 踩坑经历:初期为图方便使用了NFS,当数据量增长后,查询性能卡顿到无法忍受。
# NFS的IO并发能力不足,会导致查询监控图表时长时间等待。后续更换为SSD后体验丝滑。
# 生产环境务必使用本地SSD或高性能云盘创建的StorageClass(例如`ssd-sc`)。
resources:
requests:
storage: 10Gi # 初始分配10Gi,后续可根据数据增长情况扩容PVC
# vminsert:数据写入入口,Prometheus或vmagent的数据先发至此,由其分发给vmstorage
vminsert:
replicas: 2 # 生产环境建议至少2个副本,可水平扩展以应对写入峰值
# 解读:作为无状态组件,多副本可以分担写入压力,避免业务高峰期写入卡顿。
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1000m
memory: 2Gi
# 资源配置:根据实测,200m CPU和512Mi内存能满足常规写入负载。请根据实际业务压力调整。
service:
type: ClusterIP # 仅限集群内部访问,保证安全性
# vminsert无需对外暴露,只有集群内的Prometheus/vmagent会访问它。
# vmselect:数据查询入口,Grafana查图、日常运维查询均通过此组件
vmselect:
replicas: 2 # 生产环境建议至少2个副本,分担查询压力,避免单点故障导致无法查监控
# 解读:多副本保障查询高可用,即使千万级时间序列也能快速响应。
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1000m
memory: 2Gi
# 资源配置可参考vminsert,若查询非常频繁,可适当增加资源配额。
service:
type: ClusterIP # 集群内访问,供Grafana直接对接
# 若需要通过公网查询监控,可按需改为NodePort或LoadBalancer类型。
extraArgs:
search.maxUniqueTimeseries: 1000000 # 设置单次查询支持的最大唯一时间序列数为100万
# 此配置可防止因一次查询涉及的时间序列过多而导致组件崩溃。业务量大可酌情调高。
三、完整部署流程(基于K8s+Helm)
理解了核心配置,接下来是基于Kubernetes和Helm的实战部署步骤。以下命令均经过验证,复制后稍作修改(主要是存储类名称)即可运行。
1. 部署前置准备
确保你的环境满足以下条件,避免部署过程中报错:
- Kubernetes集群运行正常,节点间网络互通,具备必要的操作权限。
- 已安装Helm客户端,并且能够正常拉取外部Chart仓库。
- 至关重要:提前在K8s集群中创建好高性能存储类(如SSD),并准备好将上述
values.yaml文件中的storageClassName替换为你实际可用的存储类名称。
- 确保集群有足够的资源(建议至少预留2核CPU和4Gi内存)用于运行VMCluster的各个组件。
2. Helm部署VMCluster
全程使用Helm进行部署,高效且易于管理。
# 1. 添加VictoriaMetrics的官方Helm仓库
helm repo add vm https://victoriametrics.github.io/helm-charts/
# 2. 更新仓库,确保获取最新的Chart
helm repo update
# 3. 创建独立的命名空间(便于资源隔离和管理)
kubectl create ns monitoring
# 4. 将修改后的values.yaml文件上传到服务器(例如 /root/mon/values.yaml)
# 请务必确认已将文件中的 `storageClassName: "nfs-slow"` 修改为你自己的SSD存储类,如 `storageClassName: "ssd-sc"`
# 5. 执行Helm安装命令
helm install vmcluster vm/victoria-metrics-cluster \
-n monitoring \
-f /root/mon/values.yaml
# 6. 监控部署进度,等待所有Pod进入Running状态
kubectl get pods -n monitoring -w
# 重点观察三类Pod:vmcluster-vmstorage-*, vmcluster-vminsert-*, vmcluster-vmselect-*
# 全部显示为Running即表示部署成功。若长时间Pending,请检查资源配额或存储类配置。
3. 部署验证
部署完成后,不要急于对接Prometheus,先确保各个组件自身运行正常。

# 1. 查看所有Pod状态
kubectl get pods -n monitoring
# 2. 查看创建的Service
kubectl get svc -n monitoring | grep vmcluster
# 3. 检查vmstorage日志,确认无报错
kubectl logs -f <vmstorage-pod名称> -n monitoring
# 正常会看到服务启动成功的日志,无连续的ERROR信息。
# 4. 检查vminsert日志
kubectl logs -f <vminsert-pod名称> -n monitoring
# 5. 检查vmselect日志
kubectl logs -f <vmselect-pod名称> -n monitoring
4. Prometheus对接VMCluster
当VMCluster自身验证无误后,即可配置Prometheus将数据远程写入(remote_write)到VMCluster。
# 1. 修改Prometheus配置文件 (prometheus.yml),添加remote_write配置。
# 首先,获取vminsert服务的Cluster-IP:
# kubectl get svc -n monitoring | grep vminsert | awk '{print $3}'
# 将以下配置加入prometheus.yml的相应部分:
remote_write:
- url: "http://<vminsert-service-cluster-ip>:8480/api/v1/write"
# 可选优化参数:
timeout: 30s # 写入超时时间
batch_send_deadline: 5s # 批量发送截止时间
queue_config:
capacity: 10000 # 队列容量
max_shards: 200 # 最大分片数
min_shards: 10 # 最小分片数
# 2. 重启Prometheus以使配置生效
# 例如,如果Prometheus是以Deployment方式部署的:
kubectl rollout restart deployment prometheus -n monitoring
# 3. 验证数据写入
# 查看任意vmstorage Pod的日志,应能看到持续不断的“write request”相关日志。
kubectl logs -f <vmstorage-pod名称> -n monitoring | grep -i write
# 4. 验证数据查询
# 通过vmselect查询一个Prometheus的基础指标,如`prometheus_up`,确认数据可读。
curl http://<vmselect-service-cluster-ip>:8481/api/v1/query?query=prometheus_up
四、核心总结与生产避坑指南
根据我们的实践经验,总结出以下必须遵守的原则和需要避开的“坑”。
1. 生产环境核心原则
- 高可用原则:
vmstorage、vminsert、vmselect的副本数以及replicationFactor均应设置为至少2,彻底杜绝单点故障。
- 存储性能原则:
vmstorage必须使用SSD或同等高性能存储,严禁使用NFS等网络文件系统,否则IO瓶颈将导致查询性能急剧下降。
- 资源规划原则:根据业务实际的监控数据量和查询压力,合理配置各组件的CPU和内存资源限额(
limits),既要避免资源不足导致服务崩溃,也要防止过度分配造成浪费。
- 部署顺序原则:务必遵循“先部署验证VMCluster,再对接Prometheus”的顺序,这样在出现问题时能够快速定位是存储后端还是Prometheus自身的问题。
2. 两个关键“坑点”
- 坑点一:
values.yaml中vmsingle.enabled必须设置为false。如果启用,整个部署将退化为单节点模式,集群功能失效。
- 坑点二:
vmstorage的storageClassName必须使用高性能存储(如SSD)。使用NFS等慢速存储是查询性能的“杀手”,会严重影响运维排障效率。
五、方案优势与适用场景
这套方案在我们生产环境平稳运行了大半年,表现稳定可靠。它尤其适合以下几类场景:
- 生产级Prometheus监控:需要数据高可用、长期保留(7天以上)且不允许丢失的业务监控场景。
- 海量监控数据处理:时间序列数量达到百万甚至千万级别,对存储和查询性能有较高要求的场景。
- 追求运维效率:无论是小团队还是大团队,都希望采用架构轻量、部署和维护简单的方案,以降低运维复杂度和成本。
相较于Prometheus单节点存储,它解决了数据易失、查询瓶颈和无法水平扩展的痛点。而与Thanos、Cortex等方案相比,它在满足核心需求的同时,依赖更少,架构更简洁,对于大多数企业,特别是云原生转型中的团队,是一个优先推荐的选择。
六、日常运维注意事项
- 健康检查:每日花少量时间检查
monitoring命名空间下所有VMCluster相关Pod的状态,确保均为Running。
- 容量监控:重点监控
vmstorage所使用的PVC磁盘使用率,设定告警阈值(如80%),并在达到阈值前及时扩容,防止因磁盘写满导致数据无法写入。
- 配置备份:妥善保管好经过验证的
values.yaml文件。后续任何扩容、参数调优都应在备份文件基础上修改,避免误操作。
- 扩容策略:业务增长时,建议优先增加
vminsert和vmselect的无状态副本数来应对写入和查询压力;其次再考虑扩容vmstorage的存储空间或Pod副本数。
- 故障排查路径:
- 数据写入失败 -> 首先检查
vminsert组件日志及网络连通性。
- 数据查询失败 -> 首先检查
vmselect组件日志及资源使用情况。
- 怀疑数据不一致或丢失 -> 检查
vmstorage各副本的日志及状态。
希望这篇结合了实战配置和踩坑经验的指南,能帮助你顺利部署并运维好Prometheus的长期存储后端。如果在实践中遇到其他问题,也欢迎在云栈社区的运维板块与其他开发者交流探讨。