运维实战

Prometheus + VictoriaMetrics 生产优化:远程写入、长期存储与性能调优

以本地短保留加 VictoriaMetrics 长保留为主线,详解 remote_write、Grafana 双数据源、vmagent 演进、高基数治理、压测与恢复。

TY
Tycho
技术博主
• 2026-09-24 • 44 分钟阅读 • 2 次浏览
Prometheus + VictoriaMetrics 生产优化:远程写入、长期存储与性能调优

当 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: 1

retentionPeriod: 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: drop

externalLabels.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_max

remote_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: 60s
kubectl 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: false
helm 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 15m

VictoriaMetrics 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/queuecapacity、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 扩展。每一次参数调整都必须有同负载前后数据。

十二、官方资料

TY

Tycho

热爱分享技术知识,帮助开发者成长。

评论 (0)

评论功能当前已关闭
暂无评论,快来抢沙发吧!