当 Prometheus 的活跃序列、保留时间或跨集群查询不断增长时,单机 TSDB 的磁盘与内存压力会迅速上升。本文保留 Prometheus 负责发现、规则和短期查询,把样本通过 remote_write 写入 VictoriaMetrics,形成“本地短保留 + 远端长保留”的渐进式架构;随后给出 vmagent 替代采集端的演进路径。
重要兼容边界:VictoriaMetrics 官方文档当前说明 Prometheus Remote Write 2.0 仍属实验且不受支持。本文显式使用兼容的 remote write 接口,不开启 RW 2.0。生产环境固定 Prometheus、VictoriaMetrics 与 Helm chart 版本,并以目标版本官方兼容说明为准。
一、架构选择与适用场景
模式 A:渐进改造
Targets -> Prometheus(7d 本地) -> remote_write -> VictoriaMetrics(180d) -> Grafana
└-> Rules/Alerts └-> 长周期查询
模式 B:高吞吐采集
Targets -> vmagent -> VictoriaMetrics(vmsingle 或 vmcluster) -> Grafana
└-> vmalert -> Alertmanager| 模式 | 优点 | 代价 | 适用阶段 |
|---|---|---|---|
| Prometheus + remote_write | 改动小,本地仍可查询和告警 | 数据写两份,Prometheus 内存增加 | 从现有监控平滑扩容 |
| vmagent + VMSingle | 资源低、部署简单 | 单写入/查询节点 | 单集群、中等规模 |
| vmagent + VMCluster | 写入、存储、查询可独立扩展 | 组件和容量规划更复杂 | 多集群、大规模生产 |
先测量再选型:记录每秒写入样本数、活跃序列、每日磁盘增量、P95 查询时间和远写积压。没有基线就无法判断“优化”是否有效。
二、准备命名空间、存储与版本
kubectl create namespace vm --dry-run=client -o yaml | kubectl apply -f -
helm repo add vm https://victoriametrics.github.io/helm-charts/
helm repo update
helm search repo vm/victoria-metrics-single -l | head
helm search repo vm/victoria-metrics-k8s-stack -l | head
export VM_SINGLE_CHART_VERSION='<经验证的版本>'
kubectl get storageclass本文先部署 VMSingle,便于理解完整链路。若预计单实例资源无法覆盖 12–18 个月增长,直接在预生产验证 VMCluster,避免以后在压力下迁移。存储应使用低延迟块存储;PVC 回收策略、快照和跨可用区恢复能力必须先确认。
三、部署 VMSingle 长期存储
3.1 values-vmsingle.yaml
server:
fullnameOverride: vmsingle
retentionPeriod: 6
persistentVolume:
enabled: true
storageClassName: fast-rwo
accessModes: [ReadWriteOnce]
size: 200Gi
resources:
requests:
cpu: "1"
memory: 4Gi
limits:
cpu: "4"
memory: 8Gi
extraArgs:
dedup.minScrapeInterval: 30s
search.maxConcurrentRequests: "16"
search.maxQueryDuration: 60s
service:
type: ClusterIP
podDisruptionBudget:
enabled: true
minAvailable: 1retentionPeriod: 6 表示按 chart 当前语义保留 6 个月,安装前必须用 helm show values 对照目标 chart 确认单位。dedup.minScrapeInterval 应与实际抓取周期一致,只有多个高可用采集器写入同一序列时才有意义。查询并发上限用于保护存储,不应靠无限提高来掩盖慢查询。
3.2 安装与健康检查
helm upgrade --install vm vm/victoria-metrics-single \
-n vm --version "$VM_SINGLE_CHART_VERSION" \
-f values-vmsingle.yaml --atomic --timeout 10m
kubectl -n vm get pods,pvc,svc
kubectl -n vm wait --for=condition=Ready pod -l app.kubernetes.io/name=victoria-metrics-single-server --timeout=5m
kubectl -n vm port-forward svc/vmsingle 8428:8428
curl -fsS http://127.0.0.1:8428/health
curl -fsS 'http://127.0.0.1:8428/api/v1/query?query=vm_rows_inserted_total'四、让 Prometheus 可靠地 remote_write
4.1 kube-prometheus-stack 配置
prometheus:
prometheusSpec:
retention: 7d
retentionSize: 40GB
externalLabels:
cluster: prod-shanghai-01
environment: production
remoteWrite:
- url: http://vmsingle.vm.svc.cluster.local:8428/api/v1/write
name: victoria-metrics
remoteTimeout: 30s
queueConfig:
capacity: 20000
maxShards: 30
minShards: 1
maxSamplesPerSend: 10000
batchSendDeadline: 5s
minBackoff: 30ms
maxBackoff: 5s
writeRelabelConfigs:
- sourceLabels: [__name__]
regex: 'go_.*|process_.*'
action: dropexternalLabels.cluster 必须在每个集群唯一,否则跨集群查询无法区分来源。writeRelabelConfigs 只应删除明确不需要长期保存的序列;先在预生产统计命中量,再上线。官方在高负载示例中给出了较大的 batch、capacity 和 shard 参数,但这些值不是通用答案:capacity 与 batch 越大,内存占用也越高。
helm upgrade monitoring prometheus-community/kube-prometheus-stack \
-n monitoring --version "$KPS_CHART_VERSION" \
-f values-monitoring.yaml -f values-remote-write.yaml \
--atomic --timeout 15m
# 验证远写指标
kubectl -n monitoring port-forward svc/monitoring-prometheus 9090:9090
curl -fsSG http://127.0.0.1:9090/api/v1/query \
--data-urlencode 'query=prometheus_remote_storage_shards'
curl -fsSG http://127.0.0.1:9090/api/v1/query \
--data-urlencode 'query=rate(prometheus_remote_storage_samples_failed_total[5m])'4.2 判定积压而不是只看“连接成功”
# 发送失败应长期为 0
sum(rate(prometheus_remote_storage_samples_failed_total[5m])) by (remote_name)
# 重试率持续升高说明远端或网络不稳定
sum(rate(prometheus_remote_storage_samples_retried_total[5m])) by (remote_name)
# 队列最高时间戳与当前时间之差,反映落后秒数
time() - max(prometheus_remote_storage_queue_highest_sent_timestamp_seconds)
# shard 到达上限且积压仍升高,说明吞吐不足
prometheus_remote_storage_shards / prometheus_remote_storage_shards_maxremote_write 的 WAL 能在短故障后补发,但它不是无限消息队列。远端不可用时间超过 WAL 保留窗口就可能产生数据缺口,因此必须对落后秒数、失败、重试和 shard 上限告警,并演练远端停机后的追赶速度。
五、配置 Grafana 查询 VictoriaMetrics
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-datasource-victoriametrics
namespace: monitoring
labels:
grafana_datasource: "1"
data:
victoriametrics.yaml: |
apiVersion: 1
datasources:
- name: VictoriaMetrics
uid: victoriametrics
type: prometheus
access: proxy
url: http://vmsingle.vm.svc.cluster.local:8428
isDefault: false
jsonData:
httpMethod: POST
timeInterval: 30s
queryTimeout: 60skubectl apply -f grafana-vm-datasource.yaml
kubectl -n monitoring get configmap grafana-datasource-victoriametrics
# 对比短期与长期数据源同一查询
curl -fsSG http://127.0.0.1:8428/api/v1/query \
--data-urlencode 'query=count(up) by (cluster)'仪表盘变量必须带 cluster,跨集群聚合时显式保留或移除该标签。迁移阶段可在 Grafana 同时保留 Prometheus 和 VictoriaMetrics 两个数据源,对最近 6 小时的关键查询进行数值对比;差异可接受后再把长周期面板切换到 VictoriaMetrics。
六、用 vmagent 降低采集开销
当 Prometheus 只剩采集与转发职责时,可改用 vmagent。VictoriaMetrics k8s stack 会安装 vmagent、规则、仪表盘与 operator,并能转换现有 Prometheus Operator 对象。迁移必须分批:先并行采集一个非关键 namespace,确认样本、标签和告警一致,再扩大范围。
nameOverride: vmks
vmsingle:
enabled: false
vmagent:
enabled: true
spec:
selectAllByDefault: false
scrapeInterval: 30s
externalLabels:
cluster: prod-shanghai-01
remoteWrite:
- url: http://vmsingle.vm.svc.cluster.local:8428/api/v1/write
resources:
requests: {cpu: 300m, memory: 512Mi}
limits: {cpu: "2", memory: 2Gi}
grafana:
enabled: falsehelm repo add vm https://victoriametrics.github.io/helm-charts/
helm repo update
export VM_STACK_CHART_VERSION='<经验证的版本>'
helm upgrade --install vmks vm/victoria-metrics-k8s-stack \
-n vm --version "$VM_STACK_CHART_VERSION" \
-f values-vmagent.yaml --dry-run --debug
# 审核渲染资源后再正式执行
helm upgrade --install vmks vm/victoria-metrics-k8s-stack \
-n vm --version "$VM_STACK_CHART_VERSION" \
-f values-vmagent.yaml --atomic --timeout 15mVictoriaMetrics Operator 默认可以转换 Prometheus Operator 对象。并存期间要明确由谁负责发现,避免 Prometheus 与 vmagent 同时写入同一后端却没有正确去重标签。
七、性能优化方法:一次只改一个变量
7.1 从源头治理序列
metricRelabelings:
- sourceLabels: [__name__]
regex: 'http_request_duration_seconds_bucket'
action: keep
- sourceLabels: [path]
regex: '/users/[0-9a-f-]+'
targetLabel: path
replacement: '/users/:id'
action: replace第一条只是示例,不能直接套到所有端点。正确流程是导出当前每个 job 的序列数,列出高基数 label,确认业务查询与告警依赖,再做 relabel。删除后的历史数据不会自动消失,只会按保留期自然过期。
7.2 分离写入、存储与查询压力
- 写入受限:观察插入速率、拒绝、CPU、磁盘写延迟和 remote_write backlog;先降低无价值样本,再扩写入端。
- 存储受限:观察每日数据增量、磁盘利用率和合并压力;提高磁盘吞吐或扩容,不要等到 90% 才处理。
- 查询受限:找出大时间范围、高基数正则和重复 dashboard 查询;用记录规则、缓存和查询并发保护。
- 网络受限:评估 remote_write 压缩后的出口带宽;跨地域写入应考虑链路抖动与故障域。
7.3 压测与对照表
| 指标 | 基线 | 变更后 | 判定 |
|---|---|---|---|
| 每秒写入样本 | 记录 30 分钟 P50/P95 | 同负载复测 | 不能以丢样本换吞吐 |
| remote_write 落后 | 正常接近 0 | 故障恢复后下降 | 必须在 WAL 窗口内追平 |
| P95 查询时间 | 按 1h/24h/7d | 同查询同范围 | 关键面板满足 SLO |
| CPU/内存/磁盘 | 峰值与余量 | 单变量比较 | 至少保留故障冗余 |
八、备份、迁移与回滚
VMSingle 的 PVC 快照必须与应用一致性策略结合。仅复制正在写入的数据目录可能得到不可恢复的快照;应使用 VictoriaMetrics 官方备份工具/快照流程,并定期在隔离命名空间完成恢复。迁移期间保留 Prometheus 本地数据,Grafana 数据源切换是可快速回滚的第一道保险。
# 保存 Helm 状态
helm -n vm get values vm -a > vm-values-backup.yaml
helm -n vm get manifest vm > vm-manifest-backup.yaml
# 升级 CRD 前查看差异(k8s stack 场景)
helm show crds vm/victoria-metrics-k8s-stack \
--version "$NEW_VM_STACK_VERSION" | kubectl diff -f -
# 回滚采集路径:先停止新增远写,再验证本地 Prometheus 查询和告警
helm -n monitoring rollback monitoring <上一成功修订号> --wait
PROMETHEUS_POD=$(kubectl -n monitoring get pod -l app.kubernetes.io/name=prometheus -o jsonpath='{.items[0].metadata.name}')
kubectl -n monitoring logs "$PROMETHEUS_POD" -c prometheus --since=10m九、常见故障定位
| 症状 | 证据 | 根因方向 | 处理顺序 |
|---|---|---|---|
| 远写积压上升 | queue highest timestamp | 远端慢/网络/shard 不足 | 看远端健康→链路→队列参数 |
| VM 数据重复 | 同标签多条样本 | HA 副本标签/去重周期错误 | 核对 external labels 和抓取周期 |
| 长期查询空 | VM query API | 数据源 URL/时间/写入过滤 | 查写入量→标签→Grafana 数据源 |
| 内存突增 | Prometheus heap/queue | capacity、batch、序列增长 | 先还原参数,再逐项调优 |
| 磁盘增长异常 | 每日增量/高基数 | 新 exporter 或动态标签 | 按 job、metric、label 定位 |
十、生产验收清单
- Prometheus 本地查询和告警不受远端故障影响,remote_write 恢复后能在约定时间追平。
- VictoriaMetrics 的 1h、24h、30d 查询与 Prometheus 重叠窗口结果一致。
- 每个集群有唯一 external label,高可用采集的去重策略经过故障演练。
- 对写入、查询、磁盘、remote_write 队列和备份失败建立告警。
- 完成 PVC/官方备份恢复演练,并记录 RPO、RTO 与操作人。
- 版本、values、CRD 差异、容量模型与回滚修订号已归档。
十一、总结
Prometheus 与 VictoriaMetrics 的组合价值在于平滑拆分短期采集/告警和长期高压缩存储,而不是简单增加一个数据库。最稳妥的路线是建立基线、启用 remote_write、双数据源比对、治理高基数,再决定是否用 vmagent 与 VMCluster 扩展。每一次参数调整都必须有同负载前后数据。