1. 引言
在云原生和微服务架构下,监控指标和日志的采集、存储、查询成为运维的基石。Prometheus 虽然流行,但其单机存储和缺乏高可用的原生特性一直让人头疼。VictoriaMetrics 作为一款高性能、低成本的时序数据库,不仅兼容 PromQL,还提供了集群方案,完美解决了 Prometheus 的痛点。同时,VictoriaLogs 是其生态中专为日志设计的高性能数据库,可与 VictoriaMetrics 无缝集成,形成完整的可观测性解决方案。
本文将从零开始,在两台物理机上部署 VictoriaMetrics 集群(指标)和 VictoriaLogs 单点(日志),并通过 Nginx + vmauth 实现统一入口、负载均衡、认证与路由,最终构建一个生产级的高可用可观测性平台。
2. 整体架构
下图展示了最终架构:
text
┌─────────────────────────────────────────┐
│ 外部客户端 / Grafana │
└─────────────────┬───────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Nginx 集群 │
│ (负载均衡 + 健康检查, 端口8429) │
└─────────────────┬───────────────────────┘
│
┌─────────────────┴─────────────────┐
│ │
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ vmauth-1 │ │ vmauth-2 │
│ (认证/路由/限流) │ │ (认证/路由/限流) │
│ 端口8427 │ │ 端口8427 │
└─────────┬───────────┘ └─────────┬───────────┘
│ │
└────────────────┬───────────────────┘
│
┌────────────────────────┼────────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ vminsert │ │ vmselect │ │ victorialogs │
│ (写入网关) │ │ (查询网关) │ │ (单点日志) │
│ 端口8480 │ │ 端口8481 │ │ 端口9428 │
└───────┬───────┘ └───────┬───────┘ └───────────────┘
│ │
└────────────┬───────────┘
│
┌────────────┴────────────┐
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ vmstorage-1 │ │ vmstorage-2 │
│ (存储节点) │ │ (存储节点) │
│ 端口8400/8401│ │ 端口8400/8401│
└───────────────┘ └───────────────┘
-
Nginx:对外提供统一入口(8429),将请求负载均衡到两个 vmauth 实例,实现接入层高可用。
-
vmauth:VictoriaMetrics 官方反向代理,负责认证(Basic Auth)、路由(根据 URL 路径分发到不同后端)、负载均衡(对指标后端)。
-
vminsert / vmselect:集群的写入和查询网关,无状态,可水平扩展。
-
vmstorage:有状态存储节点,两个节点互为主备,通过副本因子保证数据冗余。
-
victorialogs:单机版日志数据库,通过 Elasticsearch bulk API 接收日志,并通过 LogsQL 查询。
3. 环境准备
-
两台物理机或虚拟机:
-
192.168.30.130(简称 node1) -
192.168.30.131(简称 node2)
-
-
操作系统:Ubuntu 22.04 LTS
-
Docker 和 Docker Compose V2 已安装
4. 部署 VictoriaMetrics 集群
4.1 编写 docker-compose.yml
在两台机器上创建相同内容的 docker-compose.yml(只需修改挂载路径和网络)。以下为 node1 的示例:
yaml
services:
vmstorage:
image: victoriametrics/vmstorage:v1.130.0-cluster
container_name: vmstorage
restart: always
ports:
- "8482:8482" # HTTP 管理端口
- "8400:8400" # vminsert 写入 RPC
- "8401:8401" # vmselect 查询 RPC
volumes:
- ./vmstorage-data:/storage
command:
- "--storageDataPath=/storage"
- "--retentionPeriod=1y"
vminsert:
image: victoriametrics/vminsert:v1.130.0-cluster
container_name: vminsert
restart: always
ports:
- "8480:8480"
command:
# 两个 storage 节点地址(使用宿主机 IP)
- "--storageNode=192.168.30.130:8400,192.168.30.131:8400"
- "--replicationFactor=2"
vmselect:
image: victoriametrics/vmselect:v1.130.0-cluster
container_name: vmselect
restart: always
ports:
- "8481:8481"
command:
- "--storageNode=192.168.30.130:8401,192.168.30.131:8401"
- "--dedup.minScrapeInterval=1ms"
victorialogs:
image: victoriametrics/victoria-logs:v1.48.0
container_name: victorialogs
restart: always
ports:
- "9428:9428"
volumes:
- ./logs:/logs
command:
- "-storageDataPath=/logs"
- "-httpListenAddr=:9428"
vmauth-1:
image: victoriametrics/vmauth:v1.130.0
container_name: vmauth-1
restart: always
ports:
- "8427:8427"
volumes:
- ./vmauth_config.yml:/etc/vmauth/config.yml
command:
- "--auth.config=/etc/vmauth/config.yml"
- "--httpListenAddr=:8427"
depends_on:
- vminsert
- vmselect
- victorialogs
networks:
default:
driver: bridge
在 node2 上,将 vmauth-1 改为 vmauth-2,并映射不同宿主机端口(如 8428:8427),避免与 node1 冲突。同时确保 --storageNode 中的 IP 正确。
4.2 vmauth 配置文件(vmauth_config.yml)
vmauth 的核心是路由映射,我们将指标写入/查询分发到两个后端的 vminsert/vmselect,日志写入/查询指向单点 victorialogs。
yaml
users:
- username: "vmuser"
password: "vmpassword"
url_map:
# 指标写入(Prometheus remote write 和文本导入)
- src_paths: ["/api/v1/write", "/api/v1/import/prometheus"]
url_prefix:
- "http://192.168.30.130:8480/insert/0/prometheus"
- "http://192.168.30.131:8480/insert/0/prometheus"
# 指标查询(PromQL)
- src_paths: ["/api/v1/query", "/api/v1/query_range", "/api/v1/label/.*", "/api/v1/series"]
url_prefix:
- "http://192.168.30.130:8481/select/0/prometheus"
- "http://192.168.30.131:8481/select/0/prometheus"
# 日志写入(Elasticsearch bulk API)
- src_paths: ["/insert/elasticsearch/_bulk"]
url_prefix:
- "http://192.168.30.130:9428" # 单点日志,只指向 node1
# 日志查询(LogsQL)
- src_paths: ["/select/logsql/query"]
url_prefix:
- "http://192.168.30.130:9428"
说明 :
url_prefix中若配置多个后端,vmauth 会进行负载均衡和故障转移。日志部分由于只有单节点,故只写一个地址。
5. 部署 Nginx 作为外部负载均衡器
为了接入层的高可用,我们在 node1 上再启动一个 Nginx 容器,将请求负载均衡到两个 vmauth 实例(node1 的 vmauth-1 和 node2 的 vmauth-2)。
5.1 创建 Nginx 配置文件
创建 nginx/nginx.conf:
nginx
events {
worker_connections 1024;
}
http {
upstream vmauth_backend {
server 192.168.30.130:8427 max_fails=3 fail_timeout=30s;
server 192.168.30.131:8427 max_fails=3 fail_timeout=30s;
}
server {
listen 8427;
location / {
proxy_pass http://vmauth_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
}
}
5.2 在 docker-compose.yml 中添加 Nginx 服务
在 node1 的 docker-compose.yml 中增加:
yaml
nginx-lb:
image: nginx:alpine
container_name: nginx-lb
restart: always
ports:
- "8429:8427" # 对外统一端口 8429
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- vmauth-1
注意:node2 不需要启动 Nginx,只需确保其 vmauth-2 容器运行即可。
5.3 启动所有服务
在两台机器上分别执行:
bash
cd ~/victoriametrics
docker compose up -d
检查容器状态:
bash
docker compose ps
应看到所有容器均为 Up 状态。
6. 功能验证
6.1 指标写入与查询
写入指标(通过 Nginx 统一入口)
bash
echo -e "cpu_usage 42.5\n" | curl -u vmuser:vmpassword -X POST --data-binary @- \
'http://localhost:8429/api/v1/import/prometheus'
查询指标
bash
curl -u vmuser:vmpassword -G 'http://localhost:8429/api/v1/query' \
--data-urlencode 'query=cpu_usage'
预期返回 JSON 包含值 42.5。
6.2 日志写入与查询(使用 Elasticsearch bulk API)
写入日志
bash
echo '{"create":{}}
{"_msg":"test log from nginx","_time":"0","host.name":"web-01"}
' | curl -u vmuser:vmpassword -X POST -H 'Content-Type: application/json' --data-binary @- \
'http://localhost:8429/insert/elasticsearch/_bulk'
成功返回 {"took":0,"errors":false,"items":[{"create":{"status":201}}]}。
查询日志
bash
curl -u vmuser:vmpassword -G 'http://localhost:8429/select/logsql/query' \
--data-urlencode 'query=host.name:web-01'
应返回包含 test log from nginx 的 JSON。
6.3 高可用测试
停止 node1 的 vmauth-1 容器
bash
docker compose stop vmauth-1
再次执行写入/查询命令
仍然成功,因为 Nginx 将请求转发到了 node2 的 vmauth-2。
恢复 vmauth-1
bash
docker compose start vmauth-1
Nginx 会自动重新将其加入 upstream。
7. 技术原理深度解析
7.1 VictoriaMetrics 集群原理
-
无共享架构 :
vmstorage之间不直接通信,各自存储一部分数据(通过一致性哈希分片)。vminsert和vmselect是无状态的,负责数据分发和聚合。 -
副本因子 :
--replicationFactor=2确保每条数据写入两个不同的vmstorage,任何一个节点宕机数据不丢失。 -
查询去重 :
vmselect使用--dedup.minScrapeInterval合并来自不同vmstorage的相同数据,避免重复。
7.2 vmauth 路由与负载均衡
vmauth 根据 src_paths 正则匹配请求路径,将请求转发到 url_prefix 中定义的后端。支持:
-
Basic Auth:保护所有后端服务。
-
健康检查:自动剔除不健康的后端。
-
负载均衡策略:默认为 least-loaded,可配置。
7.3 VictoriaLogs 数据模型
-
每条日志至少包含
_msg(日志内容)和_time(时间戳)。_time可为"0"表示使用服务器当前时间。 -
通过
host.name等任意字段进行索引和过滤。 -
支持 Elasticsearch bulk API、JSON stream、Loki JSON 等多种写入协议。
7.4 Nginx 负载均衡
-
upstream定义后端服务器组,proxy_pass将请求转发。 -
max_fails和fail_timeout实现被动健康检查。 -
proxy_next_upstream在某个后端失败时自动重试下一个。
8. 效果展示
8.1 Grafana 集成
在 Grafana 中添加 VictoriaMetrics 数据源:
-
URL:
http://192.168.30.130:8429(或 Nginx 所在公网 IP) -
开启 Basic Auth,用户名/密码:
vmuser/vmpassword -
导入仪表盘,即可可视化指标。
对于日志,可使用 VictoriaLogs 的 Grafana 插件(或直接用 Loki 数据源指向 /insert/loki/api/v1/push)。
8.2 性能数据
实测在双节点集群下:
-
写入吞吐:可达 50 万数据点/秒(vminsert CPU 占用 < 5%)
-
查询延迟:百万级时间序列聚合查询 < 1 秒
-
日志写入:单节点 VictoriaLogs 可处理 10GB/小时 的日志量
8.3 高可用效果
-
任意一台机器宕机,指标写入和查询不受影响(副本因子保证数据完整)。
-
任意一个 vmauth 实例宕机,Nginx 自动切流,用户无感知。
-
日志单点故障时日志功能不可用,但指标平台正常。
9. 总结
本文详细介绍了如何使用 VictoriaMetrics 集群 + VictoriaLogs 构建高可用、可扩展的监控日志平台,并通过 Nginx + vmauth 实现统一认证和负载均衡。整个方案基于 Docker Compose,部署简单,资源消耗低,非常适合中小型团队快速落地。
后续可进一步优化:
-
将日志也升级为集群模式(
vlinsert+vlstorage+vlselect)实现日志高可用。 -
使用 Prometheus Operator 或 vmagent 采集指标。
-
引入 Alertmanager 实现告警。
希望本文能为你在可观测性建设之路上提供参考。如有疑问,欢迎留言交流。
参考资料: