milvus-ops

Milvus 集群运维:依赖组件、扩缩容、compaction 与监控排错。

补充说明

Milvus 分布式集群分四层:Proxy 接收请求,Coordinator 做元数据和调度,Streaming Node 消费 WAL,Query Node 加载 sealed segment 提供检索,Data Node 处理写入、索引和 compaction。外部依赖包括 etcd(元数据与服务注册)、对象存储 MinIO/S3/Azure Blob(segment 和索引文件)以及 WAL(Pulsar/Kafka,2.5 的 RocksMQ,2.6+ 的 Woodpecker)。

运维重点是依赖健康、collection 的 load/release、索引构建、compaction、Query Node 内存和水平扩容。standalone 用 etcd + MinIO + 单机 Milvus 三个容器,适合开发;生产要上集群并监控 etcd、对象存储和 WAL,否则单点故障会直接拖垮查询和写入。

升级前要确认消息队列类型:2.5 使用 RocksMQ 时需在配置中固定 mq.type: rocksmq,2.6+ 可用 Woodpecker;升级过程中不支持切换 MQ 类型。Coordinator 通常不能水平扩容,扩缩容主要针对 Query Node、Data Node 和 Proxy,具体以当前版本 Helm chart 为准。

常用示例

检查 standalone 容器和健康端点,注意 9091 是健康/指标端口,不是 19530:

docker compose ps
curl -f http://localhost:9091/healthz

分别检查 etcd 和 MinIO;对象存储不可用时写入和索引都会失败:

docker exec milvus-etcd etcdctl endpoint health
curl -f http://localhost:9000/minio/health/live

连接集群并列出 collection:

from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530", token="root:Milvus")
print(client.list_collections())

创建 schema、HNSW 索引并加载;search 前 collection 必须处于 Loaded:

from pymilvus import DataType
schema = client.create_schema(auto_id=True, enable_dynamic_field=True)
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=768)
schema.add_field("text", DataType.VARCHAR, max_length=2048)
client.create_collection("docs", schema=schema)
index_params = client.prepare_index_params()
index_params.add_index(field_name="vector", index_type="HNSW", metric_type="COSINE", params={"M": 16, "efConstruction": 200})
client.create_index("docs", index_params)
client.load_collection("docs")
print(client.get_load_state("docs"))

写入并 flush,然后查看 collection 统计:

client.insert("docs", [{"vector": [0.1] * 768, "text": "OOMKilled 排查"}])
client.flush("docs")
print(client.get_collection_stats("docs"))

删除数据后触发 L0 compaction,并轮询异步任务状态:

import time
job = client.compact(collection_name="docs", is_clustering=False, is_l0=True)
while client.get_compaction_state(job) == "Executing":
    time.sleep(5)
print(client.get_compaction_state(job))

释放不再查询的 collection,降低 Query Node 内存占用:

client.release_collection("docs")
print(client.get_load_state("docs"))

用 Helm 扩容 Query Node 副本,再观察查询延迟和内存:

helm upgrade milvus milvus/milvus -n milvus -f values.yaml --set queryNode.replicas=3

抓取指标并查看 Query Node 日志;指标名通常以 milvus_ 开头:

curl -s http://localhost:9091/metrics | grep '^milvus_' | head -20
kubectl -n milvus get pods
kubectl -n milvus logs <querynode-pod> --tail=200

易错点与排错

相关命令

读完自测

  1. Milvus 集群的三个关键外部依赖是什么?
  2. 删除数据后磁盘为什么不释放,怎么处理?
  3. Query Node OOM 如何排查和缓解?
答案
  1. etcd 保存元数据和服务注册,对象存储保存 segment/索引文件,WAL(Pulsar/Kafka/RocksMQ/Woodpecker)保存写入日志;三者都需要高可用。
  2. 删除先记录 delete,旧 segment 仍占磁盘;需要 compaction 合并 delete 并重写 segment,任务异步执行,用 compact 返回的 job id 轮询状态。
  3. 看 Query Node 的容器内存和已加载 collection/segment 数量,释放冷 collection、减少副本或扩容 Query Node,并检查缓存和 segment 大小配置。