Appearance
监控与运维
概述
生产环境中,向量数据库承载着搜索召回的核心职责,任何延迟抖动、内存泄漏或节点宕机都会直接影响上层业务。完善的监控与运维体系能帮你在故障发生前发现风险、在故障发生时快速定位,并在日常保障系统稳定运行。
为什么需要监控:
- 提前预警:在内存耗尽、磁盘写满前介入,避免服务中断
- 定位故障:通过指标与日志快速锁定异常组件(Proxy / QueryNode / DataNode / IndexNode)
- 容量规划:基于 QPS、数据量、资源使用趋势做扩缩容决策
- SLA 保障:量化 P99 延迟、可用性,向业务方提供可验证的承诺
Milvus 内置指标体系
Milvus 各组件通过 Prometheus 暴露 /metrics 端点(默认 9091 端口)。指标命名以 milvus_ 为前缀,按组件分类如下:
Proxy 指标
| 指标 | 说明 | 关注点 |
|---|---|---|
milvus_proxy_req_latency | 请求处理延迟(按接口分) | P99 是否在 SLA 内 |
milvus_proxy_req_count | 请求总数(按接口、状态分) | 错误率突增 |
milvus_proxy_search_latency | 搜索请求延迟 | 搜索链路瓶颈 |
milvus_proxy_collection_count | Collection 数量 | 是否超预期 |
milvus_proxy_uv_count | 活跃连接数 | 是否触达连接上限 |
QueryNode 指标
| 指标 | 说明 | 关注点 |
|---|---|---|
milvus_querynode_sq_req_count | 搜索/查询请求数 | 负载分布是否均衡 |
milvus_querynode_sq_req_latency | 搜索/查询延迟 | 慢节点拖累整体 |
milvus_querynode_collection_loaded_size | 已加载集合数据量 | 内存是否吃紧 |
milvus_querynode_collection_num | 已加载 Collection 数 | 单节点过载 |
milvus_querynode_read_seg_buffer_size | 读缓存占用 | 缓存命中率 |
DataNode 指标
| 指标 | 说明 | 关注点 |
|---|---|---|
milvus_datanode_segment_flush_count | 段刷盘次数 | 写入压力 |
milvus_datanode_segment_num | 各状态段数量 | growing 段是否堆积 |
milvus_datanode_consume_msg_rows_count | 消息消费行数 | 写入是否滞后 |
milvus_datanode_flush_latency | 刷盘延迟 | 落盘瓶颈 |
IndexNode 指标
| 指标 | 说明 | 关注点 |
|---|---|---|
milvus_indexnode_index_build_count | 索引构建任务数 | 构建积压 |
milvus_indexnode_index_build_latency | 索引构建延迟 | 大段构建耗时 |
milvus_indexnode_index_task_num | 队列任务数 | 是否需要扩容 IndexNode |
Prometheus 集成
开启监控
在 milvus.yaml 中确认监控配置已开启(单机版默认开启):
yaml
# milvus.yaml 片段
log:
level: info
file:
stdout: true
metric:
enable: true # 暴露 /metrics 端点集群部署时,每个组件 Pod 都会通过 9091 端口暴露指标。
Prometheus scrape 配置
yaml
# prometheus.yml
scrape_configs:
- job_name: 'milvus'
metrics_path: /metrics
file_sd_configs:
- files:
- /etc/prometheus/targets/milvus.yml
relabel_configs:
- source_labels: [__address__]
target_label: instance
- source_labels: [component]
target_label: component/etc/prometheus/targets/milvus.yml 静态目标示例:
yaml
- targets:
- milvus-proxy:9091
- milvus-querynode-0:9091
- milvus-querynode-1:9091
- milvus-datanode-0:9091
- milvus-indexnode-0:9091
labels:
component: milvusKubernetes ServiceMonitor
若在 K8s 中用 Prometheus Operator,使用 ServiceMonitor 自动发现各组件 Pod:
yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: milvus-monitor
namespace: milvus
labels:
release: prometheus
spec:
selector:
matchLabels:
app.kubernetes.io/instance: milvus
namespaceSelector:
matchNames:
- milvus
endpoints:
- port: metrics # 容器 9091 端口命名
interval: 15s
path: /metricsGrafana 仪表盘
导入官方仪表盘
Milvus 官方提供现成的 Grafana 仪表盘 JSON:
- 打开 Grafana → Dashboards → Import
- 在 Import via grafana.com 输入官方仪表盘 ID,或上传下载好的
milvus-dashboard.json - 选择已配置的 Prometheus 数据源,点击 Import
官方仪表盘 JSON 可从 milvus-io/milvus 仓库 deployments/monitor 目录获取。
关键面板说明
| 面板 | 指标来源 | 作用 |
|---|---|---|
| QPS | milvus_proxy_req_count(rate) | 实时搜索/查询吞吐 |
| 延迟 P99 | milvus_proxy_req_latency histogram_quantile | 是否满足 SLA |
| 内存使用 | milvus_querynode_collection_loaded_size + 容器 RSS | 是否接近内存上限 |
| 段数量 | milvus_datanode_segment_num | growing/sealed 段堆积 |
| 索引构建 | milvus_indexnode_index_build_count | 构建进度与积压 |
| 错误率 | milvus_proxy_req_count{status!="success"} | 异常请求占比 |
日志管理
调整日志级别
运行时通过 SDK 动态调整日志级别,无需重启服务:
python
from pymilvus import connections, utility
from pymilvus.client import types
# 连接(Config 在连接前后均可使用)
connections.connect(host="localhost", port="19530")
# 动态设置日志级别:debug / info / warn / error
utility.set_log_level("debug")
print("当前日志级别已调整为 debug")
# 排查完毕后调回 info
utility.set_log_level("info")日志收集方案
| 方案 | 适用场景 | 说明 |
|---|---|---|
| docker logs | 单机版快速排查 | docker compose logs -f milvus |
| kubectl logs | K8s 集群排查 | kubectl logs -n milvus <pod> |
| ELK / EFK | 集中化日志平台 | Filebeat 采集 → Logstash → Elasticsearch → Kibana |
| Loki + Promtail | 与 Prometheus 统一 | 标签体系与指标对齐,Grafana 内联动查询 |
日志格式
Milvus 默认输出 JSON 结构化日志,便于采集解析:
json
{
"level": "info",
"ts": "2024-08-01T10:23:45.123Z",
"caller": "proxy/impl.go:128",
"msg": "search request received",
"collection": "article_search",
"nq": 1,
"topk": 10
}健康检查
通过 SDK 检查
python
from pymilvus import connections, utility
connections.connect(host="localhost", port="19530")
# 1. 获取服务端版本,连通即视为基本可用
version = utility.get_server_version()
print(f"Milvus 服务版本: {version}")
# 2. 列出集合,确认元数据可访问
collections = utility.list_collections()
print(f"当前集合数: {len(collections)}")HTTP 端点检查
| 端点 | 方法 | 用途 |
|---|---|---|
http://<host>:9091/healthz | GET | 进程存活探针 |
http://<host>:9091/metrics | GET | Prometheus 指标 |
http://<host>:9091/api/v1/health | GET | 组件级健康状态 |
bash
# 健康探针,返回 ok 即健康
curl http://localhost:9091/healthz
# 拉取指标
curl http://localhost:9091/metrics | head -n 20Attu 健康面板
Attu 是 Milvus 官方可视化管理工具,提供图形化的健康面板:Collection 加载状态、索引进度、各节点资源占用一目了然。Docker 一行启动:
bash
docker run -d -p 8000:3000 -e MILVUS_URL=localhost:19530 zilliz/attu:v2.4浏览器访问 http://localhost:8000 即可。
告警规则示例
以下 Prometheus Alertmanager 规则覆盖三类典型故障,保存为 milvus-alerts.yaml:
yaml
groups:
- name: milvus-alerts
rules:
# 1. 搜索延迟 P99 过高
- alert: MilvusHighSearchLatency
expr: histogram_quantile(0.99, sum by (le) (rate(milvus_proxy_req_latency_bucket{app_name="proxy"}[5m]))) > 0.5
for: 5m
labels:
severity: warning
annotations:
summary: "Milvus 搜索 P99 延迟过高"
description: "Proxy 请求 P99 延迟 {{ $value }}s,超过 500ms 阈值,已持续 5 分钟。"
# 2. QueryNode 内存不足(已加载数据量占内存 > 85%)
- alert: MilvusQueryNodeMemoryHigh
expr: milvus_querynode_collection_loaded_size / (1024 * 1024 * 1024) > on(instance) (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) * 0.85 / (1024 * 1024 * 1024)
for: 10m
labels:
severity: critical
annotations:
summary: "QueryNode 内存吃紧"
description: "实例 {{ $labels.instance }} 已加载数据接近内存上限,建议扩容或下线部分 Collection。"
# 3. 节点宕机(指标消失超过 2 分钟)
- alert: MilvusNodeDown
expr: absent(up{job="milvus"} == 1) or count(up{job="milvus"} == 0) > 0
for: 2m
labels:
severity: critical
annotations:
summary: "Milvus 节点宕机"
description: "有 {{ $value }} 个 Milvus 实例指标抓取失败,请立即检查节点状态。"集群巡检脚本
下面是一个可定时运行的 Python 巡检脚本,输出集群关键状态报告:
python
from pymilvus import connections, utility, Collection
import time
def inspect_milvus(host="localhost", port="19530"):
"""Milvus 集群巡检:集合数、索引、加载状态、数据量、磁盘"""
connections.connect(host=host, port=port)
print(f"=== Milvus 巡检报告 {time.strftime('%Y-%m-%d %H:%M:%S')} ===")
# 1. 服务版本与连通性
version = utility.get_server_version()
print(f"[连通] 服务版本: {version}")
# 2. 集合清单与状态
collections = utility.list_collections()
print(f"[集合] 共 {len(collections)} 个集合")
total_rows = 0
for name in collections:
col = Collection(name)
rows = col.num_entities
total_rows += rows
# 索引状态
indexed = len(col.indexes) > 0
index_info = col.indexes[0].params if indexed else "无索引"
# 加载状态
load_state = utility.load_state(name)
print(f" - {name}: 行数={rows}, 索引={'有' if indexed else '无'}"
f"({index_info}), 加载状态={load_state}")
print(f"[数据] 总行数: {total_rows}")
# 3. 磁盘使用(通过 MinIO 段统计近似)
# 生产环境建议直接读取 node_filesystem_avail_bytes 指标
print("[磁盘] 建议结合 Prometheus node_filesystem_avail_bytes 监控")
connections.disconnect("default")
print("=== 巡检结束 ===\n")
if __name__ == "__main__":
inspect_milvus()预期输出:
=== Milvus 巡检报告 2024-08-01 10:00:00 ===
[连通] 服务版本: v2.4.0
[集合] 共 2 个集合
- article_search: 行数=10000, 索引=有({'index_type': 'HNSW', ...}), 加载状态=Loaded
- user_profile: 行数=5000, 索引=有({'index_type': 'IVF_FLAT', ...}), 加载状态=NotLoad
[数据] 总行数: 15000
[磁盘] 建议结合 Prometheus node_filesystem_avail_bytes 监控
=== 巡检结束 ===运维操作
手动 Compact
Compaction 合并小段、清理删除标记,提升搜索效率:
python
from pymilvus import Collection
collection = Collection("article_search")
# 触发 compaction,返回任务 ID
task_id = utility.compact("article_search")
print(f"Compaction 任务已提交: {task_id}")
# 查看进度
state = utility.get_compaction_state(task_id)
print(f"当前状态: {state}")手动 Flush
Flush 将 growing 段落盘为 sealed 段,使其可被索引和持久化:
python
collection = Collection("article_search")
collection.flush()
print("数据已 flush 到对象存储")数据 Rebalance
扩容后,让 QueryCoord 在 QueryNode 间重新均衡加载的数据:
python
from pymilvus import utility
# 触发负载均衡(2.4.x 通过 configmap 开启 queryCoord.autoBalance 后自动进行)
# 手动检查各节点负载分布
balance_info = utility.get_query_segment_info("article_search")
for seg in balance_info:
print(f"segment {seg.segment_id} -> node {seg.node_id}, rows={seg.num_rows}")节点管理
| 操作 | 命令 | 场景 |
|---|---|---|
| 滚动重启 | kubectl rollout restart deployment milvus-querynode -n milvus | 升级 / 配置变更 |
| 驱逐节点 | 给节点打 cordon 后逐 pod 迁移 | 维护单台机器 |
| 扩缩容 | helm upgrade 改 replicas | 详见 集群部署 |
最佳实践
- 指标分层告警:warning 用于提前感知,critical 用于必须人工介入;避免全部 critical 导致告警疲劳。
- 日志与指标联动:在 Grafana 面板中关联 Loki 日志,从 P99 延迟尖刺可直接跳转到对应时段日志。
- 定期巡检:把巡检脚本接入 cron / CI,每日生成报告,发现未加载集合或缺失索引及时处理。
- 容量预留:QueryNode 内存建议预留 20% 余量,避免 compact / 搜索峰值时 OOM。
- 变更窗口:compact、升级等重操作避开业务高峰,并在执行前确认有可回滚的备份。
- 指标保留期:Prometheus 建议至少保留 15 天历史,便于做月度容量趋势分析。
下一步
掌握监控与运维后,你可以: