Skip to content

监控与运维

概述

生产环境中,向量数据库承载着搜索召回的核心职责,任何延迟抖动、内存泄漏或节点宕机都会直接影响上层业务。完善的监控与运维体系能帮你在故障发生前发现风险、在故障发生时快速定位,并在日常保障系统稳定运行。

为什么需要监控

  • 提前预警:在内存耗尽、磁盘写满前介入,避免服务中断
  • 定位故障:通过指标与日志快速锁定异常组件(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_countCollection 数量是否超预期
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: milvus

Kubernetes 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: /metrics

Grafana 仪表盘

导入官方仪表盘

Milvus 官方提供现成的 Grafana 仪表盘 JSON:

  1. 打开 Grafana → DashboardsImport
  2. Import via grafana.com 输入官方仪表盘 ID,或上传下载好的 milvus-dashboard.json
  3. 选择已配置的 Prometheus 数据源,点击 Import

官方仪表盘 JSON 可从 milvus-io/milvus 仓库 deployments/monitor 目录获取。

关键面板说明

面板指标来源作用
QPSmilvus_proxy_req_count(rate)实时搜索/查询吞吐
延迟 P99milvus_proxy_req_latency histogram_quantile是否满足 SLA
内存使用milvus_querynode_collection_loaded_size + 容器 RSS是否接近内存上限
段数量milvus_datanode_segment_numgrowing/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 logsK8s 集群排查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/healthzGET进程存活探针
http://<host>:9091/metricsGETPrometheus 指标
http://<host>:9091/api/v1/healthGET组件级健康状态
bash
# 健康探针,返回 ok 即健康
curl http://localhost:9091/healthz

# 拉取指标
curl http://localhost:9091/metrics | head -n 20

Attu 健康面板

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 upgradereplicas详见 集群部署

最佳实践

  • 指标分层告警:warning 用于提前感知,critical 用于必须人工介入;避免全部 critical 导致告警疲劳。
  • 日志与指标联动:在 Grafana 面板中关联 Loki 日志,从 P99 延迟尖刺可直接跳转到对应时段日志。
  • 定期巡检:把巡检脚本接入 cron / CI,每日生成报告,发现未加载集合或缺失索引及时处理。
  • 容量预留:QueryNode 内存建议预留 20% 余量,避免 compact / 搜索峰值时 OOM。
  • 变更窗口:compact、升级等重操作避开业务高峰,并在执行前确认有可回滚的备份。
  • 指标保留期:Prometheus 建议至少保留 15 天历史,便于做月度容量趋势分析。

下一步

掌握监控与运维后,你可以:

  1. 学习集群部署,理解分布式架构
  2. 了解数据备份与恢复方案
  3. 查阅常见问题与故障排查手册