使用VictoriaMetrics的Prometheus远程存储方案

描述

VictoriaMetrics高性能时序数据库:Prometheus远程存储方案

Prometheus单机存储在生产环境跑到一定规模就会碰壁——单节点磁盘容量有限,TSDB默认保留15天数据,想存半年以上的监控数据基本不现实。更麻烦的是Prometheus没有原生的高可用方案,两个Prometheus实例各采各的,数据不一致,查询时还得靠Thanos或者联邦来聚合。我们团队在2022年从Thanos迁移到VictoriaMetrics,集群稳定运行至今,存储成本降了约60%,查询延迟从秒级降到毫秒级。这篇文章把部署、对接、调优的完整流程写出来。

一、概述

1.1 背景介绍

Prometheus的本地TSDB设计目标是短期存储,官方建议保留时间不超过15-30天。一旦监控规模上去(比如我们的场景:200+节点、5万+活跃时间序列、每秒采集样本数约50万),单机Prometheus的内存和磁盘压力就很大。常见的解决思路有三种:

Thanos:Sidecar模式对接Prometheus,数据上传到对象存储。架构复杂,组件多(Sidecar、Store Gateway、Compactor、Query),运维成本高。

Cortex/Mimir:Grafana Labs的方案,依赖Consul/etcd做服务发现,还需要对象存储,部署门槛不低。

VictoriaMetrics:单二进制部署,兼容PromQL,压缩率比Prometheus高7-10倍,查询速度快,资源消耗低。

我们实测对比过:同样存储3个月的监控数据,Prometheus+Thanos占用约800GB磁盘,VictoriaMetrics只用了120GB左右。查询30天范围的聚合数据,Thanos需要3-5秒,VictoriaMetrics在200ms内返回。

1.2 技术特点

极高的压缩率:VictoriaMetrics使用自研的压缩算法,实测压缩比在10:1到15:1之间,比Prometheus的gorilla编码高出数倍。100万个时间序列、每15秒采集一次、存储1个月,磁盘占用约20-30GB。

完全兼容PromQL:支持MetricsQL(PromQL的超集),现有的Grafana Dashboard和告警规则可以直接迁移,不用改查询语句。额外支持了一些实用函数如range_median()、histogram_quantile()的优化版本。

部署运维简单:单机版就是一个二进制文件,启动参数配好就能跑。集群版也只有三个组件(vminsert、vmselect、vmstorage),没有外部依赖,不需要Consul、etcd、Kafka这些中间件。

1.3 适用场景

Prometheus长期存储:需要保留3个月以上监控数据的场景,直接用remote_write对接VictoriaMetrics,Prometheus只保留短期数据做热查询。

大规模监控集群:单集群超过500个节点、活跃时间序列超过1000万的场景,VictoriaMetrics集群版可以水平扩展,实测单集群支撑过5000万活跃序列。

多租户监控平台:集群版原生支持多租户,通过URL路径区分租户,不同业务线的数据隔离存储和查询,适合平台化的监控中台。

1.4 环境要求

组件 版本要求 说明
操作系统 CentOS 7+ / Ubuntu 18.04+ / Debian 10+ 推荐Ubuntu 22.04 LTS
VictoriaMetrics v1.93.0+ 本文基于v1.102.0,建议用最新稳定版
Prometheus v2.40+ 需要支持remote_write协议
Grafana v9.0+ 用于可视化查询,需要Prometheus数据源
CPU 单机版4核+,集群版每节点8核+ vmstorage对CPU要求不高,vmselect查询时CPU消耗大
内存 单机版8GB+,集群版每节点16GB+ 内存主要用于缓存和合并写入
磁盘 SSD推荐,容量按压缩后估算 HDD也能跑,但查询延迟会高2-3倍

二、详细步骤

2.1 准备工作

2.1.1 系统检查

 

# 检查系统版本
cat /etc/os-release

# 检查CPU和内存
nproc
free -h

# 检查磁盘空间,数据盘建议预留200GB以上
df -h

# 检查系统时间同步状态,时序数据库对时间敏感
timedatectl status

# 如果时间不同步,配置chrony
sudo apt install -y chrony
sudo systemctl enable --now chrony
chronyc tracking

 

2.1.2 创建用户和目录

 

# 创建专用用户,不给登录shell
sudo useradd -r -s /sbin/nologin victoriametrics

# 创建数据目录,生产环境建议挂载独立磁盘
sudo mkdir -p /data/victoriametrics
sudo mkdir -p /etc/victoriametrics
sudo mkdir -p /var/log/victoriametrics

# 设置目录权限
sudo chown -R victoriametrics:victoriametrics /data/victoriametrics
sudo chown -R victoriametrics:victoriametrics /var/log/victoriametrics

 

2.1.3 下载安装

 

# 设置版本号
VM_VERSION="v1.102.0"

# 下载单机版
cd /tmp
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/${VM_VERSION}/victoria-metrics-linux-amd64-${VM_VERSION}.tar.gz

# 解压安装
tar xzf victoria-metrics-linux-amd64-${VM_VERSION}.tar.gz
sudo mv victoria-metrics-prod /usr/local/bin/victoria-metrics
sudo chmod +x /usr/local/bin/victoria-metrics

# 验证安装
victoria-metrics --version

 

如果要部署集群版,需要额外下载集群组件:

 

# 下载集群版组件
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/${VM_VERSION}/victoria-metrics-linux-amd64-${VM_VERSION}-cluster.tar.gz

tar xzf victoria-metrics-linux-amd64-${VM_VERSION}-cluster.tar.gz
sudo mv vminsert-prod /usr/local/bin/vminsert
sudo mv vmselect-prod /usr/local/bin/vmselect
sudo mv vmstorage-prod /usr/local/bin/vmstorage
sudo chmod +x /usr/local/bin/vm{insert,select,storage}

# 下载vmagent(可选,替代Prometheus做采集)
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/${VM_VERSION}/vmutils-linux-amd64-${VM_VERSION}.tar.gz
tar xzf vmutils-linux-amd64-${VM_VERSION}.tar.gz
sudo mv vmagent-prod /usr/local/bin/vmagent
sudo mv vmctl-prod /usr/local/bin/vmctl
sudo chmod +x /usr/local/bin/vmagent /usr/local/bin/vmctl

 

2.2 核心配置

2.2.1 单机版部署

单机版适合中小规模场景(活跃时间序列500万以内),一个进程搞定读写存储。

 

# 创建systemd服务文件
sudo tee /etc/systemd/system/victoriametrics.service > /dev/null << 'EOF'
[Unit]
Description=VictoriaMetrics single-node
After=network.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/local/bin/victoria-metrics 
    -storageDataPath=/data/victoriametrics 
    -retentionPeriod=6 
    -httpListenAddr=:8428 
    -maxLabelsPerTimeseries=40 
    -search.maxUniqueTimeseries=5000000 
    -search.maxQueryDuration=60s 
    -search.maxConcurrentRequests=32 
    -memory.allowedPercent=60 
    -dedup.minScrapeInterval=15s 
    -loggerTimezone=Asia/Shanghai 
    -loggerOutput=stderr
ExecStop=/bin/kill -s SIGTERM $MAINPID
Restart=always
RestartSec=5
LimitNOFILE=65536
LimitNPROC=32000

[Install]
WantedBy=multi-user.target
EOF

 

参数说明(这些都是踩过坑调出来的):

-retentionPeriod=6:数据保留6个月,单位是月。改成6而不是180d,因为按月计算更直观。

-memory.allowedPercent=60:限制VictoriaMetrics使用系统60%的内存。默认不限制,在16GB内存的机器上跑,不设这个参数会把内存吃满导致OOM Killer干掉进程。生产环境必须设。

-dedup.minScrapeInterval=15s:去重间隔设为采集间隔。如果你跑了两个Prometheus做HA,两边都remote_write到VM,这个参数会自动去重,只保留一份数据。

-search.maxUniqueTimeseries=5000000:单次查询最大返回的时间序列数。默认30万,在大集群里查{__name__=~".+"}这种宽泛查询会报错,按需调大。

-maxLabelsPerTimeseries=40:每个时间序列最大标签数。默认30,有些业务自定义标签多的会超限,40基本够用。

2.2.2 集群版部署

集群版由三个组件组成,生产环境建议每个组件至少2个实例:

vmstorage:存储节点,负责数据持久化。部署在有SSD的机器上。

vminsert:写入网关,接收remote_write请求,按一致性哈希分发到vmstorage。无状态,可以随意扩缩。

vmselect:查询网关,接收PromQL查询,从所有vmstorage拉数据聚合。无状态。

假设我们有3台机器:

角色 IP 端口
vmstorage-1 10.0.1.11 8482(http) / 8400(vminsert) / 8401(vmselect)
vmstorage-2 10.0.1.12 8482(http) / 8400(vminsert) / 8401(vmselect)
vmstorage-3 10.0.1.13 8482(http) / 8400(vminsert) / 8401(vmselect)
vminsert 10.0.1.21 8480
vmselect 10.0.1.22 8481

vmstorage服务配置(三台存储节点都部署):

 

sudo tee /etc/systemd/system/vmstorage.service > /dev/null << 'EOF'
[Unit]
Description=VictoriaMetrics vmstorage
After=network.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/local/bin/vmstorage 
    -storageDataPath=/data/vmstorage 
    -retentionPeriod=6 
    -httpListenAddr=:8482 
    -vminsertAddr=:8400 
    -vmselectAddr=:8401 
    -dedup.minScrapeInterval=15s 
    -memory.allowedPercent=60 
    -search.maxUniqueTimeseries=5000000 
    -loggerTimezone=Asia/Shanghai
Restart=always
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

 

vminsert服务配置

 

sudo tee /etc/systemd/system/vminsert.service > /dev/null << 'EOF'
[Unit]
Description=VictoriaMetrics vminsert
After=network.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/local/bin/vminsert 
    -httpListenAddr=:8480 
    -storageNode=10.0.1.11:8400,10.0.1.12:8400,10.0.1.13:8400 
    -replicationFactor=2 
    -maxLabelsPerTimeseries=40 
    -maxConcurrentInserts=32 
    -loggerTimezone=Asia/Shanghai
Restart=always
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

 

-replicationFactor=2表示每条数据写入2个存储节点。这样挂掉1个vmstorage不丢数据。代价是存储空间翻倍,但数据安全比省磁盘重要。

vmselect服务配置

 

sudo tee /etc/systemd/system/vmselect.service > /dev/null << 'EOF'
[Unit]
Description=VictoriaMetrics vmselect
After=network.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/local/bin/vmselect 
    -httpListenAddr=:8481 
    -storageNode=10.0.1.11:8401,10.0.1.12:8401,10.0.1.13:8401 
    -dedup.minScrapeInterval=15s 
    -search.maxQueryDuration=120s 
    -search.maxConcurrentRequests=32 
    -search.maxUniqueTimeseries=5000000 
    -replicationFactor=2 
    -loggerTimezone=Asia/Shanghai
Restart=always
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

 

vmselect的-replicationFactor=2要和vminsert一致,这样查询时vmselect知道数据有副本,会自动去重。

2.2.3 Prometheus remote_write对接

在Prometheus配置文件中添加remote_write段:

 

# /etc/prometheus/prometheus.yml
global:
scrape_interval:15s
evaluation_interval:15s

remote_write:
-url:"http://10.0.1.21:8480/insert/0/prometheus/api/v1/write"
    queue_config:
      max_samples_per_send:10000
      capacity:20000
      max_shards:30
      min_shards:1
      batch_send_deadline:5s
    write_relabel_configs:
      -source_labels:[__name__]
        regex:"go_.*"
        action:drop

# 如果是单机版VM,URL改为:
# url: "http://VM_IP:8428/api/v1/write"

 

URL路径中的/insert/0/prometheus/里的0是租户ID。单租户场景用0就行,多租户按业务分配不同的数字。

queue_config的参数是调过的:

max_samples_per_send=10000:每批发送1万个样本,默认500太小,网络开销大。

max_shards=30:最大并发发送协程数。如果Prometheus采集量大(每秒超过10万样本),这个值要调到50以上。

batch_send_deadline=5s:批次发送超时。默认5s够用,网络差的环境调到10s。

write_relabel_configs用来过滤不需要远程存储的指标。go_*这类Go运行时指标一般不需要长期存储,直接drop掉能减少约10-15%的写入量。

2.2.4 vmagent替代Prometheus采集

如果你不需要Prometheus的告警功能(告警交给VMAlert或者独立的Alertmanager),可以用vmagent替代Prometheus做采集。vmagent内存占用只有Prometheus的1/3左右,支持同样的服务发现和relabel配置。

 

# vmagent配置文件
sudo tee /etc/victoriametrics/vmagent.yml > /dev/null << 'EOF'
global:
  scrape_interval: 15s
  external_labels:
    cluster: prod-bj
    env: production

scrape_configs:
  - job_name: "node-exporter"
    static_configs:
      - targets:
          - "10.0.1.11:9100"
          - "10.0.1.12:9100"
          - "10.0.1.13:9100"
    relabel_configs:
      - source_labels: [__address__]
        regex: "(.+):.*"
        target_label: instance
        replacement: "${1}"

  - job_name: "kubernetes-pods"
    kubernetes_sd_configs:
      - role: pod
        api_server: "https://10.0.1.100:6443"
        tls_config:
          ca_file: /etc/victoriametrics/ca.crt
          cert_file: /etc/victoriametrics/client.crt
          key_file: /etc/victoriametrics/client.key
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        regex: ([^:]+)(?::d+)?;(d+)
        replacement: $1:$2
        target_label: __address__
EOF
# vmagent systemd服务
sudo tee /etc/systemd/system/vmagent.service > /dev/null << 'EOF'
[Unit]
Description=VictoriaMetrics vmagent
After=network.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/local/bin/vmagent 
    -promscrape.config=/etc/victoriametrics/vmagent.yml 
    -remoteWrite.url=http://10.0.1.21:8480/insert/0/prometheus/api/v1/write 
    -remoteWrite.maxDiskUsagePerURL=1GB 
    -remoteWrite.tmpDataPath=/data/vmagent-remotewrite-data 
    -httpListenAddr=:8429 
    -loggerTimezone=Asia/Shanghai
Restart=always
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

 

-remoteWrite.maxDiskUsagePerURL=1GB这个参数很关键:当远端VM不可用时,vmagent会把数据缓存到本地磁盘,等VM恢复后自动重传。默认不限制,磁盘可能被写满。设成1GB,按每秒10万样本算,大约能缓存2-3小时的数据,足够覆盖大多数故障恢复时间。

2.3 启动和验证

2.3.1 启动服务

 

# 单机版启动
sudo systemctl daemon-reload
sudo systemctl enable --now victoriametrics
sudo systemctl status victoriametrics

# 集群版启动(按顺序:先storage,再insert和select)
# 在三台存储节点上执行
sudo systemctl daemon-reload
sudo systemctl enable --now vmstorage
sudo systemctl status vmstorage

# 在vminsert节点执行
sudo systemctl enable --now vminsert
sudo systemctl status vminsert

# 在vmselect节点执行
sudo systemctl enable --now vmselect
sudo systemctl status vmselect

# 启动vmagent(如果使用)
sudo systemctl enable --now vmagent

 

2.3.2 功能验证

 

# 1. 检查VM单机版健康状态
curl -s http://localhost:8428/health
# 预期输出:空响应,HTTP 200

# 2. 检查集群各组件
curl -s http://10.0.1.11:8482/health   # vmstorage
curl -s http://10.0.1.21:8480/health   # vminsert
curl -s http://10.0.1.22:8481/health   # vmselect

# 3. 手动写入测试数据(单机版)
curl -d 'test_metric{job="test",instance="localhost"} 42' 
  http://localhost:8428/api/v1/import/prometheus

# 4. 查询验证
curl -s 'http://localhost:8428/api/v1/query?query=test_metric' | python3 -m json.tool
# 预期看到 test_metric 值为42

# 5. 集群版写入测试(通过vminsert)
curl -d 'test_metric{job="test"} 42' 
  http://10.0.1.21:8480/insert/0/prometheus/api/v1/import/prometheus

# 6. 集群版查询测试(通过vmselect)
curl -s 'http://10.0.1.22:8481/select/0/prometheus/api/v1/query?query=test_metric' | python3 -m json.tool

# 7. 检查Prometheus remote_write是否正常
# 在Prometheus的Web UI(:9090)查看 Status -> Runtime & Build Information
# 确认 remote_storage_samples_total 计数器在增长

# 8. 查看VM的内置监控指标
curl -s http://localhost:8428/metrics | grep vm_rows_inserted_total
# 这个计数器应该在持续增长

 

2.3.3 Grafana数据源配置

在Grafana中添加Prometheus类型的数据源:

单机版:URL填 http://VM_IP:8428

集群版:URL填 http://vmselect_IP:8481/select/0/prometheus

其他配置保持默认即可。添加完数据源后,导入一个Dashboard验证查询是否正常,推荐导入ID为11176的VictoriaMetrics官方Dashboard。

三、示例代码和配置

3.1 完整配置示例

3.1.1 集群版生产级部署配置

以下是我们线上跑了14个月的集群配置,3个vmstorage + 2个vminsert + 2个vmselect,承载约800万活跃时间序列,每秒写入约80万样本。

vmstorage启动参数(生产调优版)

 

# 文件路径:/etc/systemd/system/vmstorage.service
[Unit]
Description=VictoriaMetrics vmstorage - production
After=network.target
Wants=network-online.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/local/bin/vmstorage 
    -storageDataPath=/data/vmstorage 
    -retentionPeriod=6 
    -httpListenAddr=:8482 
    -vminsertAddr=:8400 
    -vmselectAddr=:8401 
    -dedup.minScrapeInterval=15s 
    -memory.allowedPercent=60 
    -search.maxUniqueTimeseries=10000000 
    -snapshotsMaxAge=72h 
    -finalMergeDelay=10s 
    -bigMergeConcurrency=2 
    -smallMergeConcurrency=4 
    -loggerTimezone=Asia/Shanghai 
    -loggerOutput=stderr 
    -loggerLevel=INFO
Restart=always
RestartSec=5
LimitNOFILE=131072
LimitNPROC=32000
# 防止OOM Killer杀掉进程
OOMScoreAdjust=-500
# 限制core dump大小
LimitCORE=0

[Install]
WantedBy=multi-user.target

 

参数解释:

-bigMergeConcurrency=2:大合并并发数。默认值等于CPU核数的一半,在32核机器上会起16个合并线程,IO压力很大。设成2,合并速度慢一点但不影响读写性能。

-smallMergeConcurrency=4:小合并并发数。小合并频繁但每次数据量小,4个线程够用。

-snapshotsMaxAge=72h:快照最大保留时间。做备份时会创建快照,72小时后自动清理,防止忘记删快照撑爆磁盘。

-finalMergeDelay=10s:最终合并延迟。数据写入后等10秒再做最终合并,减少写放大。

vminsert生产配置

 

# 文件路径:/etc/systemd/system/vminsert.service
[Unit]
Description=VictoriaMetrics vminsert - production
After=network.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/local/bin/vminsert 
    -httpListenAddr=:8480 
    -storageNode=10.0.1.11:8400,10.0.1.12:8400,10.0.1.13:8400 
    -replicationFactor=2 
    -maxLabelsPerTimeseries=40 
    -maxConcurrentInserts=64 
    -insert.maxQueueDuration=30s 
    -loggerTimezone=Asia/Shanghai
Restart=always
RestartSec=5
LimitNOFILE=131072

[Install]
WantedBy=multi-user.target

 

vmselect生产配置

 

# 文件路径:/etc/systemd/system/vmselect.service
[Unit]
Description=VictoriaMetrics vmselect - production
After=network.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/local/bin/vmselect 
    -httpListenAddr=:8481 
    -storageNode=10.0.1.11:8401,10.0.1.12:8401,10.0.1.13:8401 
    -dedup.minScrapeInterval=15s 
    -search.maxQueryDuration=120s 
    -search.maxConcurrentRequests=64 
    -search.maxUniqueTimeseries=10000000 
    -search.maxSamplesPerQuery=500000000 
    -search.cacheTimestampOffset=5m 
    -replicationFactor=2 
    -selectNode=10.0.1.22:8481 
    -loggerTimezone=Asia/Shanghai
Restart=always
RestartSec=5
LimitNOFILE=131072

[Install]
WantedBy=multi-user.target

 

-search.maxSamplesPerQuery=500000000:单次查询最大样本数。默认10亿,但如果有人写了个查全量数据的PromQL,会把vmselect内存打爆。5亿是个比较安全的上限。

3.1.2 vmagent生产级采集配置

 

# 文件路径:/etc/victoriametrics/vmagent-prod.yml
# 这个配置在我们的K8s集群上跑了10个月,采集200+节点
global:
scrape_interval:15s
scrape_timeout:10s
external_labels:
    cluster:prod-bj-01
    env:production
    region:cn-north-1

scrape_configs:
# 节点监控
-job_name:"node-exporter"
    file_sd_configs:
      -files:
          -/etc/victoriametrics/targets/nodes/*.yml
        refresh_interval:30s
    metric_relabel_configs:
      # 丢弃不需要的高基数指标
      -source_labels:[__name__]
        regex:"node_scrape_collector_duration_seconds|node_scrape_collector_success"
        action:drop
      # 丢弃不需要的文件系统指标(tmpfs等)
      -source_labels:[__name__,fstype]
        regex:"node_filesystem_.+;(tmpfs|devtmpfs|rootfs)"
        action:drop

# Kubernetes API Server
-job_name:"kubernetes-apiservers"
    kubernetes_sd_configs:
      -role:endpoints
    scheme:https
    tls_config:
      ca_file:/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    bearer_token_file:/var/run/secrets/kubernetes.io/serviceaccount/token
    relabel_configs:
      -source_labels:[__meta_kubernetes_namespace,__meta_kubernetes_service_name,__meta_kubernetes_endpoint_port_name]
        action:keep
        regex:default;kubernetes;https

# kubelet和cAdvisor
-job_name:"kubelet"
    kubernetes_sd_configs:
      -role:node
    scheme:https
    tls_config:
      ca_file:/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      insecure_skip_verify:true
    bearer_token_file:/var/run/secrets/kubernetes.io/serviceaccount/token
    relabel_configs:
      -action:labelmap
        regex:__meta_kubernetes_node_label_(.+)

-job_name:"cadvisor"
    kubernetes_sd_configs:
      -role:node
    scheme:https
    tls_config:
      ca_file:/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      insecure_skip_verify:true
    bearer_token_file:/var/run/secrets/kubernetes.io/serviceaccount/token
    metrics_path:/metrics/cadvisor
    metric_relabel_configs:
      # cAdvisor指标非常多,只保留核心的
      -source_labels:[__name__]
        regex:"container_cpu_usage_seconds_total|container_memory_working_set_bytes|container_memory_rss|container_network_receive_bytes_total|container_network_transmit_bytes_total|container_fs_usage_bytes|container_fs_limit_bytes"
        action:keep

# 自动发现带prometheus注解的Pod
-job_name:"kubernetes-pods"
    kubernetes_sd_configs:
      -role:pod
    relabel_configs:
      -source_labels:[__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action:keep
        regex:true
      -source_labels:[__meta_kubernetes_pod_annotation_prometheus_io_scheme]
        action:replace
        target_label:__scheme__
        regex:(https?)
      -source_labels:[__meta_kubernetes_pod_annotation_prometheus_io_path]
        action:replace
        target_label:__metrics_path__
        regex:(.+)
      -source_labels:[__address__,__meta_kubernetes_pod_annotation_prometheus_io_port]
        action:replace
        regex:([^:]+)(?::d+)?;(d+)
        replacement:$1:$2
        target_label:__address__
      -action:labelmap
        regex:__meta_kubernetes_pod_label_(.+)
      -source_labels:[__meta_kubernetes_namespace]
        action:replace
        target_label:namespace
      -source_labels:[__meta_kubernetes_pod_name]
        action:replace
        target_label:pod

 

3.1.3 vmctl数据迁移脚本

从Prometheus迁移历史数据到VictoriaMetrics:

 

#!/bin/bash
# 文件名:migrate_prometheus_to_vm.sh
# 功能:将Prometheus历史数据迁移到VictoriaMetrics
# 实测迁移200GB Prometheus数据耗时约4小时

set -euo pipefail

PROM_URL="http://10.0.1.50:9090"
VM_URL="http://10.0.1.21:8480/insert/0/prometheus"
# 迁移时间范围:最近90天
START_TIME=$(date -d "90 days ago" +%s)
END_TIME=$(date +%s)
LOG_FILE="/var/log/victoriametrics/migration_$(date +%Y%m%d_%H%M%S).log"

echo"[$(date)] 开始迁移 Prometheus -> VictoriaMetrics" | tee -a "$LOG_FILE"
echo"[$(date)] 时间范围: $(date -d @$START_TIME) -> $(date -d @$END_TIME)" | tee -a "$LOG_FILE"

# vmctl native模式迁移,速度最快
/usr/local/bin/vmctl prometheus 
    --prom-snapshot="/data/prometheus/snapshots/$(ls -t /data/prometheus/snapshots/ | head -1)" 
    --vm-addr="$VM_URL" 
    --vm-concurrency=8 
    --vm-batch-size=200000 
    2>&1 | tee -a "$LOG_FILE"

# 如果没有快照,用API模式迁移(速度慢但不需要停Prometheus)
# /usr/local/bin/vmctl prometheus 
#     --prom-addr="$PROM_URL" 
#     --vm-addr="$VM_URL" 
#     --prom-start="$START_TIME" 
#     --prom-end="$END_TIME" 
#     --vm-concurrency=4 
#     --prom-concurrency=4 
#     2>&1 | tee -a "$LOG_FILE"

EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
    echo"[$(date)] 迁移完成" | tee -a "$LOG_FILE"
else
    echo"[$(date)] 迁移失败,退出码: $EXIT_CODE" | tee -a "$LOG_FILE"
    exit$EXIT_CODE
fi

# 验证迁移结果:对比源和目标的时间序列数
PROM_SERIES=$(curl -s "$PROM_URL/api/v1/label/__name__/values" | python3 -c "import sys,json; print(len(json.load(sys.stdin)['data']))")
VM_SERIES=$(curl -s "http://10.0.1.22:8481/select/0/prometheus/api/v1/label/__name__/values" | python3 -c "import sys,json; print(len(json.load(sys.stdin)['data']))")
echo"[$(date)] Prometheus指标数: $PROM_SERIES, VictoriaMetrics指标数: $VM_SERIES" | tee -a "$LOG_FILE"

 

3.2 实际应用案例

案例一:多租户监控平台

场景描述:公司有5个业务线,每个业务线有独立的Prometheus集群,需要统一存储和查询。用VictoriaMetrics集群版的多租户功能,每个业务线分配一个租户ID。

实现配置

 

# 业务线A的Prometheus配置
# 租户ID: 1
remote_write:
-url:"http://vminsert-lb:8480/insert/1/prometheus/api/v1/write"
    queue_config:
      max_samples_per_send:10000
      max_shards:20

# 业务线B的Prometheus配置
# 租户ID: 2
remote_write:
-url:"http://vminsert-lb:8480/insert/2/prometheus/api/v1/write"
    queue_config:
      max_samples_per_send:10000
      max_shards:20

# 业务线C的Prometheus配置
# 租户ID: 3
remote_write:
-url:"http://vminsert-lb:8480/insert/3/prometheus/api/v1/write"
    queue_config:
      max_samples_per_send:10000
      max_shards:15

 

Grafana中为每个业务线配置独立的数据源:

 

业务线A数据源URL: http://vmselect-lb:8481/select/1/prometheus
业务线B数据源URL: http://vmselect-lb:8481/select/2/prometheus
业务线C数据源URL: http://vmselect-lb:8481/select/3/prometheus

# 如果需要跨租户查询(运维团队全局视图):
全局数据源URL: http://vmselect-lb:8481/select/multitenant/prometheus

 

跨租户查询需要vmselect启动时加-search.tenantCacheExpireDuration=10s参数。实测跨5个租户查询聚合数据,延迟在500ms以内。

案例二:Prometheus HA + VictoriaMetrics去重

场景描述:两个Prometheus实例采集相同的目标做高可用,都remote_write到VictoriaMetrics。VM自动去重,Grafana只查VM。

架构

 

Prometheus-A (10.0.1.51) ──remote_write──> VictoriaMetrics
                                              ↑
Prometheus-B (10.0.1.52) ──remote_write──────┘
                                              │
                                    Grafana <─┘ (查询)

 

Prometheus-A配置

 

# /etc/prometheus/prometheus.yml (Prometheus-A)
global:
scrape_interval:15s
external_labels:
    replica:prom-a
    cluster:prod

remote_write:
-url:"http://10.0.1.21:8480/insert/0/prometheus/api/v1/write"
    queue_config:
      max_samples_per_send:10000
      max_shards:30

 

Prometheus-B配置(只有replica标签不同):

 

# /etc/prometheus/prometheus.yml (Prometheus-B)
global:
scrape_interval:15s
external_labels:
    replica:prom-b
    cluster:prod

remote_write:
-url:"http://10.0.1.21:8480/insert/0/prometheus/api/v1/write"
    queue_config:
      max_samples_per_send:10000
      max_shards:30

 

VictoriaMetrics端配置-dedup.minScrapeInterval=15s,VM会按时间戳对齐去重,两个Prometheus写入的相同指标只保留一份。去重后存储量和单Prometheus一样,但任何一个Prometheus挂了数据都不会断。

我们线上用这个方案跑了一年多,中间Prometheus-A因为机器故障重启过3次,每次都是Prometheus-B无缝接管,Grafana上看不到任何数据断点。

四、最佳实践和注意事项

4.1 最佳实践

4.1.1 存储容量规划

容量规划是上线前必须做的事,算错了要么磁盘爆满丢数据,要么浪费钱买了用不上的SSD。

计算公式:

 

磁盘用量 = 活跃时间序列数 × 每个样本压缩后大小 × 每天采样次数 × 保留天数 × 副本数

实际例子:
- 活跃时间序列:500万
- 采集间隔:15秒(每天5760次采样)
- 每个样本压缩后大小:约0.5-1.5字节(VM的压缩率)
- 保留6个月(180天)
- 副本数:2

磁盘用量 = 5,000,000 × 1.0 × 5,760 × 180 × 2 = 约10.4TB

 

实际使用中,VM的压缩率会随数据特征变化。我们的经验值:

计数器类指标(Counter):压缩后每样本约0.4字节

仪表盘类指标(Gauge):压缩后每样本约1.0-1.5字节

直方图类指标(Histogram):压缩后每样本约0.8字节

 

# 查看当前VM的实际压缩率
curl -s http://localhost:8428/api/v1/status/tsdb | python3 -m json.tool

# 查看磁盘使用详情
curl -s http://localhost:8428/internal/force_flush
du -sh /data/victoriametrics/data/

 

生产环境建议磁盘预留30%的余量,因为合并操作会临时占用额外空间。

4.1.2 降采样(Downsampling)配置

长期存储的数据不需要保持原始精度。比如3个月前的数据,1分钟一个点就够了,没必要保留15秒的原始精度。VictoriaMetrics企业版支持降采样,开源版可以用vmalert做recording rules实现类似效果。

 

# vmalert降采样规则
# 文件路径:/etc/victoriametrics/downsampling_rules.yml
groups:
-name:downsampling_5m
    interval:5m
    rules:
      # 将CPU使用率降采样为5分钟平均值
      -record:cpu_usage_avg:5m
        expr:avg_over_time(node_cpu_seconds_total{mode!="idle"}[5m])

      # 将内存使用降采样为5分钟平均值
      -record:memory_usage_avg:5m
        expr:avg_over_time(node_memory_MemAvailable_bytes[5m])

      # 将网络流量降采样为5分钟速率
      -record:network_receive_rate:5m
        expr:rate(node_network_receive_bytes_total[5m])

-name:downsampling_1h
    interval:1h
    rules:
      # 1小时粒度的聚合,用于月度报表
      -record:cpu_usage_avg:1h
        expr:avg_over_time(cpu_usage_avg:5m[1h])
      -record:memory_usage_avg:1h
        expr:avg_over_time(memory_usage_avg:5m[1h])

 

4.1.3 去重策略

跑双Prometheus HA时,去重配置不对会导致数据翻倍或者查询结果不稳定。

 

# VM端去重配置(单机版或vmstorage)
-dedup.minScrapeInterval=15s

# vmselect端也要配(集群版)
-dedup.minScrapeInterval=15s

 

去重的原理:VM按时间戳对齐,同一个时间序列在同一个时间窗口(15秒)内只保留一个样本。两个Prometheus采集同一个target,时间戳可能差几百毫秒,但在15秒窗口内会被合并。

踩坑经验:-dedup.minScrapeInterval的值必须等于或大于Prometheus的scrape_interval。如果Prometheus是15秒采集,这里设成10秒,会导致部分数据没被去重,查询时出现毛刺。

4.1.4 性能调优

 

# 1. 调整系统参数
# 增大文件描述符限制
echo"victoriametrics soft nofile 131072" >> /etc/security/limits.conf
echo"victoriametrics hard nofile 131072" >> /etc/security/limits.conf

# 调整内核参数
cat >> /etc/sysctl.conf << 'EOF'
# VictoriaMetrics优化
vm.max_map_count = 262144
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 65535
EOF
sudo sysctl -p

# 2. 磁盘IO优化(如果用的是SSD)
echo none > /sys/block/sda/queue/scheduler
echo 256 > /sys/block/sda/queue/nr_requests

 

4.1.5 安全加固

 

# 1. 用Nginx做反向代理,加上基础认证
sudo apt install -y nginx apache2-utils

# 创建认证文件
sudo htpasswd -bc /etc/nginx/.htpasswd vmuser 'StrongP@ssw0rd'

# Nginx配置
cat > /etc/nginx/conf.d/victoriametrics.conf << 'NGINX_EOF'
upstream vmselect {
    server 10.0.1.22:8481;
    keepalive 32;
}

upstream vminsert {
    server 10.0.1.21:8480;
    keepalive 32;
}

server {
    listen 443 ssl;
    server_name vm.example.com;

    ssl_certificate /etc/nginx/ssl/vm.crt;
    ssl_certificate_key /etc/nginx/ssl/vm.key;

    # 查询接口 - 需要认证
    location /select/ {
        auth_basic "VictoriaMetrics";
        auth_basic_user_file /etc/nginx/.htpasswd;
        proxy_pass http://vmselect;
        proxy_set_header Host $host;
        proxy_read_timeout 120s;
    }

    # 写入接口 - 用IP白名单替代认证(Prometheus不支持basic auth的remote_write)
    location /insert/ {
        allow 10.0.1.0/24;
        deny all;
        proxy_pass http://vminsert;
        proxy_set_header Host $host;
    }

    # 禁止访问管理接口
    location /internal/ {
        deny all;
    }
}
NGINX_EOF
# 2. 限制VM的监听地址(不要监听0.0.0.0)
# 在systemd服务文件中修改
-httpListenAddr=10.0.1.11:8482  # 只监听内网IP

# 3. 关闭不需要的API端点
# vmselect启动参数加上
-search.resetCacheAuthKey=your-secret-key  # 重置缓存需要密钥
-deleteAuthKey=your-delete-key              # 删除数据需要密钥
-snapshotAuthKey=your-snapshot-key          # 创建快照需要密钥
# 4. 配置防火墙规则
# 只允许特定IP访问VM端口
sudo ufw allow from 10.0.1.0/24 to any port 8428
sudo ufw allow from 10.0.1.0/24 to any port 8480
sudo ufw allow from 10.0.1.0/24 to any port 8481
sudo ufw allow from 10.0.1.0/24 to any port 8482
sudo ufw deny 8428
sudo ufw deny 8480
sudo ufw deny 8481
sudo ufw deny 8482

 

4.2 注意事项

4.2.1 配置注意事项

改retentionPeriod之前先算好磁盘:把保留时间从3个月改成12个月,磁盘用量会翻4倍。改之前先用上面的公式算一下,确认磁盘够用再改。改完重启VM,旧数据不会立即删除,要等到过期时间才会清理。

-retentionPeriod改小不会立即释放空间,VM的数据按月份分目录存储,只有整个月份过期后才会删除对应目录。比如从6个月改成3个月,要等3个月后才能看到空间释放。

集群版扩容vmstorage节点后,新节点不会自动均衡旧数据。新数据会均匀分布到所有节点,但旧数据还在原来的节点上。如果需要均衡,得用vmctl做数据迁移。

vminsert的-storageNode列表顺序很重要,改变顺序会导致数据分布变化。扩容时只在末尾追加新节点,不要调整已有节点的顺序。

4.2.2 常见错误

错误现象 原因分析 解决方案
cannot allocate memory  VM进程被OOM Kill 没设-memory.allowedPercent,VM吃满了系统内存 设置-memory.allowedPercent=60,同时检查是否有大范围查询
too many open files 文件描述符限制太低 systemd配置LimitNOFILE=131072,同时改/etc/security/limits.conf
Prometheus remote_write报context deadline exceeded VM写入队列满了或网络延迟高 增大vminsert的-maxConcurrentInserts,检查网络延迟
查询返回the number of unique timeseries exceeds 查询命中的时间序列数超过限制 调大-search.maxUniqueTimeseries,或优化PromQL缩小查询范围
集群版查询数据不一致 vmselect的-replicationFactor和vminsert不一致 确保两端的-replicationFactor值相同
磁盘空间持续增长不释放 快照没清理或合并操作积压 检查/data/vmstorage/snapshots/目录,清理过期快照

4.2.3 兼容性问题

PromQL兼容性:VictoriaMetrics兼容99%的PromQL语法,但有少数边界情况行为不同。比如rate()函数在数据有间断时,VM和Prometheus的插值逻辑略有差异。迁移后建议对比关键告警规则的查询结果。

remote_write协议版本:VM支持Prometheus remote_write v1和v2协议。Prometheus 2.47+默认用v2,如果VM版本低于1.93.0不支持v2,需要在Prometheus端强制用v1:remote_write.protocol_version: 1。

Grafana版本:Grafana 9.x以上对VM的兼容性最好。8.x版本在使用$__rate_interval变量时可能有问题,建议升级到9.x+。

五、故障排查和监控

5.1 故障排查

5.1.1 日志查看

 

# 查看VM单机版日志
sudo journalctl -u victoriametrics -f --no-pager

# 查看集群各组件日志
sudo journalctl -u vmstorage -f --no-pager
sudo journalctl -u vminsert -f --no-pager
sudo journalctl -u vmselect -f --no-pager

# 查看最近的错误日志
sudo journalctl -u victoriametrics --since "1 hour ago" | grep -i "error|warn|fatal"

# 查看vmagent日志
sudo journalctl -u vmagent -f --no-pager

# 如果配置了日志文件输出
tail -f /var/log/victoriametrics/vm.log | grep -v "DEBUG"

 

5.1.2 常见问题排查

问题一:数据写入延迟,Prometheus remote_write队列积压

 

# 在Prometheus端查看remote_write队列状态
curl -s http://localhost:9090/api/v1/query?query=prometheus_remote_storage_pending_samples | python3 -m json.tool

# 如果pending_samples持续增长,说明写入速度跟不上
# 检查vminsert的写入延迟
curl -s http://10.0.1.21:8480/metrics | grep vm_http_request_duration

# 检查vmstorage的磁盘IO
iostat -x 1 5

# 检查网络延迟
ping -c 10 10.0.1.21

 

解决方案

增大Prometheus的max_shards(从30调到50)

检查vmstorage所在机器的磁盘IO,如果IO util超过80%,考虑换SSD或增加存储节点

检查vminsert到vmstorage的网络延迟,超过5ms就需要排查网络问题

用write_relabel_configs过滤掉不需要的指标,减少写入量

问题二:查询慢,Grafana Dashboard加载超时

 

# 查看vmselect的查询延迟分布
curl -s http://10.0.1.22:8481/metrics | grep vm_request_duration_seconds

# 查看慢查询日志(需要启动时加参数)
# -search.logSlowQueryDuration=5s  记录超过5秒的查询
sudo journalctl -u vmselect | grep "slow query"

# 查看当前正在执行的查询
curl -s http://10.0.1.22:8481/api/v1/status/active_queries | python3 -m json.tool

 

解决方案

优化PromQL查询,避免{__name__=~".+"}这种全量匹配

缩小查询时间范围,30天的数据用step=5m而不是默认的15s

增加vmselect实例数,用Nginx做负载均衡

检查是否有高基数标签(比如把request_id作为标签),用/api/v1/status/tsdb查看top标签

问题三:磁盘空间不足,VM拒绝写入

 

# 查看磁盘使用
df -h /data/victoriametrics/

# 查看各月份数据目录大小
du -sh /data/victoriametrics/data/big/*/
du -sh /data/victoriametrics/data/small/*/

# 检查是否有未清理的快照
ls -la /data/victoriametrics/snapshots/

# 强制清理过期数据(谨慎操作)
curl -s http://localhost:8428/internal/force_merge?partition_prefix=2024_01

 

解决方案

清理过期快照:curl http://localhost:8428/snapshot/delete_all

缩短保留时间(临时措施):改-retentionPeriod后重启

扩容磁盘或增加存储节点

检查是否有异常的高基数指标占用大量空间

问题四:集群节点故障恢复

 

# 检查集群状态
# vminsert会自动跳过不可用的vmstorage节点
curl -s http://10.0.1.21:8480/metrics | grep vm_rpc_connection

# 查看哪些存储节点不可用
curl -s http://10.0.1.21:8480/metrics | grep "vm_rpc_dial_errors_total"

# 节点恢复后,检查数据完整性
# 如果replicationFactor=2,单节点故障不丢数据
# 节点恢复后自动重新加入集群,不需要手动操作

 

5.1.3 调试模式

 

# 开启详细日志
# 在systemd服务文件中修改启动参数
-loggerLevel=INFO   # 改为 -loggerLevel=DEBUG(排查完记得改回来)

# 开启慢查询日志
-search.logSlowQueryDuration=5s

# 开启HTTP请求日志(会产生大量日志,只在排查时开启)
-httpLogRequests

# 查看内部状态
curl -s http://localhost:8428/api/v1/status/tsdb | python3 -m json.tool
curl -s http://localhost:8428/api/v1/status/active_queries | python3 -m json.tool

# 查看内存使用详情
curl -s http://localhost:8428/metrics | grep process_resident_memory_bytes
curl -s http://localhost:8428/metrics | grep go_memstats_alloc_bytes

 

5.2 性能监控

5.2.1 关键指标监控

 

# 写入速率(每秒插入的行数)
curl -s http://localhost:8428/metrics | grep vm_rows_inserted_total

# 查询速率
curl -s http://localhost:8428/metrics | grep vm_http_requests_total

# 活跃时间序列数
curl -s http://localhost:8428/metrics | grep vm_cache_entries.*metricName

# 磁盘使用
curl -s http://localhost:8428/metrics | grep vm_data_size_bytes

# 合并操作状态
curl -s http://localhost:8428/metrics | grep vm_merges

 

5.2.2 监控指标说明

指标名称 正常范围 告警阈值 说明
vm_rows_inserted_total rate 根据采集量而定 突降50%以上 写入速率突降说明数据源异常
vm_slow_queries_total 0-5/min >10/min 慢查询过多说明需要优化查询或扩容
process_resident_memory_bytes >80%系统内存 内存使用过高有OOM风险
vm_free_disk_space_bytes >20%总容量 <10%总容量 磁盘空间不足会导致拒绝写入
vm_merge_need_free_disk_space 0 >0 合并操作因磁盘不足被阻塞
vm_http_request_duration_seconds p99 <1s >5s 查询延迟过高影响用户体验

5.2.3 Prometheus监控规则

 

# 文件路径:/etc/prometheus/rules/victoriametrics.yml
groups:
-name:victoriametrics_alerts
    interval:30s
    rules:
      # 写入速率突降
      -alert:VMWriteRateDrop
        expr:|
          rate(vm_rows_inserted_total[5m]) < 0.5 * rate(vm_rows_inserted_total[5m] offset 1h)
        for:10m
        labels:
          severity:warning
        annotations:
          summary:"VictoriaMetrics写入速率下降超过50%"
          description:"当前写入速率: {{ $value | humanize }}/s"

      # 磁盘空间不足
      -alert:VMDiskSpaceLow
        expr:|
          vm_free_disk_space_bytes / vm_available_disk_space_bytes < 0.15
        for:5m
        labels:
          severity:critical
        annotations:
          summary:"VictoriaMetrics磁盘剩余空间不足15%"
          description:"剩余空间: {{ $value | humanize1024 }}B"

      # 查询延迟过高
      -alert:VMSlowQueries
        expr:|
          histogram_quantile(0.99, rate(vm_request_duration_seconds_bucket[5m])) > 5
        for:10m
        labels:
          severity:warning
        annotations:
          summary:"VictoriaMetrics P99查询延迟超过5秒"

      # 内存使用过高
      -alert:VMHighMemoryUsage
        expr:|
          process_resident_memory_bytes{job="victoriametrics"} / node_memory_MemTotal_bytes > 0.8
        for:5m
        labels:
          severity:critical
        annotations:
          summary:"VictoriaMetrics内存使用超过80%"

      # vmstorage节点不可用(集群版)
      -alert:VMStorageNodeDown
        expr:|
          up{job="vmstorage"} == 0
        for:2m
        labels:
          severity:critical
        annotations:
          summary:"vmstorage节点 {{ $labels.instance }} 不可用"

      # 合并操作积压
      -alert:VMMergeQueueFull
        expr:|
          vm_assisted_merges_total > 0
        for:15m
        labels:
          severity:warning
        annotations:
          summary:"VictoriaMetrics合并操作积压,可能影响查询性能"

 

5.3 备份与恢复

5.3.1 备份策略

 

#!/bin/bash
# 文件名:vm_backup.sh
# VictoriaMetrics备份脚本
# 利用VM的快照功能做一致性备份

set -euo pipefail

VM_URL="http://localhost:8428"
BACKUP_DIR="/backup/victoriametrics"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_PATH="${BACKUP_DIR}/${DATE}"
RETENTION_DAYS=7
LOG_FILE="/var/log/victoriametrics/backup_${DATE}.log"

log() {
    echo"[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

log"开始VictoriaMetrics备份"

# 1. 创建快照
SNAPSHOT_RESPONSE=$(curl -s "${VM_URL}/snapshot/create")
SNAPSHOT_NAME=$(echo"$SNAPSHOT_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['snapshot'])")
log"创建快照: $SNAPSHOT_NAME"

SNAPSHOT_PATH="/data/victoriametrics/snapshots/${SNAPSHOT_NAME}"

# 2. 用rsync备份快照目录
mkdir -p "$BACKUP_PATH"
rsync -a --progress "$SNAPSHOT_PATH/""$BACKUP_PATH/" 2>&1 | tee -a "$LOG_FILE"
log"备份完成: $BACKUP_PATH"

# 3. 删除快照(释放空间)
curl -s "${VM_URL}/snapshot/delete?snapshot=${SNAPSHOT_NAME}" | tee -a "$LOG_FILE"
log"快照已删除: $SNAPSHOT_NAME"

# 4. 清理过期备份
find "$BACKUP_DIR" -maxdepth 1 -type d -mtime +${RETENTION_DAYS} -exec rm -rf {} ;
log"已清理${RETENTION_DAYS}天前的备份"

# 5. 记录备份大小
BACKUP_SIZE=$(du -sh "$BACKUP_PATH" | awk '{print $1}')
log"备份大小: $BACKUP_SIZE"

 

5.3.2 恢复流程

 

# 1. 停止VictoriaMetrics服务
sudo systemctl stop victoriametrics

# 2. 备份当前数据目录(以防恢复出问题)
sudo mv /data/victoriametrics /data/victoriametrics.bak.$(date +%Y%m%d)

# 3. 恢复备份数据
sudo mkdir -p /data/victoriametrics
sudo rsync -a /backup/victoriametrics/20250115_020000/ /data/victoriametrics/

# 4. 修复权限
sudo chown -R victoriametrics:victoriametrics /data/victoriametrics

# 5. 启动服务
sudo systemctl start victoriametrics

# 6. 验证数据完整性
sleep 10
curl -s 'http://localhost:8428/api/v1/query?query=count({__name__=~".+"})' | python3 -m json.tool
# 对比恢复前后的时间序列总数

# 7. 确认恢复成功后删除旧数据备份
# sudo rm -rf /data/victoriametrics.bak.*

 

六、总结

6.1 技术要点回顾

单机版一个二进制搞定:中小规模(500万活跃序列以内)用单机版就够了,部署简单,运维成本低。别一上来就搞集群,单机版的性能已经超过大多数场景的需求。

集群版三组件架构:vminsert/vmselect/vmstorage各司其职,vminsert和vmselect无状态可以随意扩缩,vmstorage有状态需要谨慎操作。扩容vmstorage时只在storageNode列表末尾追加,不要改变已有节点顺序。

去重机制是HA的基础:-dedup.minScrapeInterval必须等于或大于Prometheus的采集间隔,vminsert和vmselect两端都要配。双Prometheus HA + VM去重的方案经过生产验证,稳定可靠。

内存限制必须设:-memory.allowedPercent=60是生产环境必配参数,不设的话VM会吃满内存被OOM Killer干掉。这个坑我们踩过两次。

压缩率决定存储成本:实测压缩比在10:1到15:1之间,同样的数据量,VM的磁盘占用只有Prometheus的1/7到1/10。做容量规划时按每样本1字节估算比较安全。

remote_write调优不能忽略:Prometheus端的queue_config参数直接影响写入性能,max_shards和max_samples_per_send要根据实际采集量调整,默认值在大规模场景下不够用。

6.2 进阶学习方向

VMAlert + 告警管理:用VMAlert替代Prometheus的告警评估,支持从VictoriaMetrics直接查询数据做告警判断,减少对Prometheus的依赖。VMAlert支持recording rules和alerting rules,语法和Prometheus完全兼容。

学习资源:https://docs.victoriametrics.com/vmalert/

实践建议:先把现有的Prometheus告警规则迁移到VMAlert,验证告警结果一致后再下线Prometheus的告警功能

VictoriaMetrics Operator(K8s部署):如果你的基础设施跑在Kubernetes上,用VM Operator可以通过CRD声明式管理VM集群,自动处理扩缩容、滚动更新、备份等操作。

学习资源:https://docs.victoriametrics.com/operator/

实践建议:先在测试集群部署VMCluster CRD,熟悉各参数后再迁移生产环境

VictoriaLogs(日志存储):VictoriaMetrics团队推出的日志存储方案,和VictoriaMetrics指标存储配合使用,可以在Grafana中实现指标和日志的关联查询。目前还在快速迭代中,适合技术预研。

学习资源:https://docs.victoriametrics.com/victorialogs/

6.3 参考资料

VictoriaMetrics官方文档 - 最权威的参考,更新及时

VictoriaMetrics GitHub - 源码和Issue讨论

Prometheus remote_write配置 - remote_write协议和参数说明

VictoriaMetrics vs Thanos性能对比 - 官方的Benchmark数据

附录

A. 命令速查表

 

# 单机版启停
sudo systemctl start victoriametrics
sudo systemctl stop victoriametrics
sudo systemctl restart victoriametrics
sudo systemctl status victoriametrics

# 集群版启停(按顺序)
sudo systemctl start vmstorage && sudo systemctl start vminsert && sudo systemctl start vmselect
sudo systemctl stop vmselect && sudo systemctl stop vminsert && sudo systemctl stop vmstorage

# 健康检查
curl -s http://localhost:8428/health                    # 单机版
curl -s http://localhost:8480/health                    # vminsert
curl -s http://localhost:8481/health                    # vmselect
curl -s http://localhost:8482/health                    # vmstorage

# 查看TSDB状态
curl -s http://localhost:8428/api/v1/status/tsdb | python3 -m json.tool

# 查看活跃查询
curl -s http://localhost:8428/api/v1/status/active_queries | python3 -m json.tool

# 创建快照(备份用)
curl -s http://localhost:8428/snapshot/create

# 删除所有快照
curl -s http://localhost:8428/snapshot/delete_all

# 强制合并(减少磁盘碎片)
curl -s http://localhost:8428/internal/force_merge

# 手动写入测试数据
curl -d 'test{job="test"} 123' http://localhost:8428/api/v1/import/prometheus

# 查询测试
curl -s 'http://localhost:8428/api/v1/query?query=up' | python3 -m json.tool

# 查看标签值
curl -s 'http://localhost:8428/api/v1/label/__name__/values' | python3 -m json.tool

# 删除时间序列(需要配置deleteAuthKey)
curl -d 'match[]={job="test"}' http://localhost:8428/api/v1/admin/tsdb/delete_series

 

B. 配置参数详解

参数 默认值 建议值 说明
-retentionPeriod 1(月) 按需设置 数据保留时间,支持月(数字)和天(如180d)
-memory.allowedPercent 不限制 60 内存使用上限百分比,生产必设
-dedup.minScrapeInterval 0(不去重) 等于scrape_interval HA场景必设
-search.maxUniqueTimeseries 300000 5000000-10000000 单次查询最大时间序列数
-search.maxQueryDuration 30s 60s-120s 单次查询最大执行时间
-search.maxConcurrentRequests 16 32-64 最大并发查询数
-maxLabelsPerTimeseries 30 40 每个时间序列最大标签数
-replicationFactor 1 2 集群版数据副本数
-bigMergeConcurrency CPU/2 2 大合并并发数,降低IO压力
-smallMergeConcurrency CPU/2 4 小合并并发数
-search.logSlowQueryDuration 5s 5s 慢查询日志阈值
-remoteWrite.maxDiskUsagePerURL 不限制 1GB vmagent本地缓存上限

C. 术语表

术语 英文 解释
时间序列 Time Series 由指标名和标签集唯一标识的一组按时间排列的数据点
活跃序列 Active Time Series 最近一个采集周期内有新数据写入的时间序列
远程写入 Remote Write Prometheus将采集的数据通过HTTP协议发送到远端存储的机制
去重 Deduplication 多个数据源写入相同时间序列时,只保留一份数据的机制
降采样 Downsampling 将高精度数据聚合为低精度数据以节省存储空间
高基数 High Cardinality 某个标签的取值种类非常多(如用户ID),导致时间序列数爆炸
合并 Merge/Compaction 将多个小数据块合并为大数据块,提高查询效率和压缩率
租户 Tenant 集群版中用于隔离不同业务数据的逻辑单元,通过URL路径中的数字ID区分
快照 Snapshot 数据目录的只读副本,用于一致性备份
MetricsQL MetricsQL VictoriaMetrics扩展的查询语言,兼容PromQL并增加了额外函数

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分