Vald 是什么:云原生时代的向量搜索基础设施
在大模型和 RAG 应用爆发式增长的今天,向量搜索已经成为 AI 基础设施中不可或缺的一环。从 Milvus、Qdrant 到 Weaviate,市面上已有不少向量数据库方案。然而,这些方案在云原生场景下面临一个共同的痛点:它们大多以单体或伪分布式架构为主,真正与 Kubernetes 深度整合、支持自动伸缩和故障自愈的方案凤毛麟角。
Vald(Vector Search Engine for Distributed Architecture)正是为解决这一痛点而生的。它是由日本 Yahoo! JAPAN 开源、目前已进入 CNCF Sandbox 的云原生分布式向量搜索引擎。Vald 从设计之初就以 Kubernetes 为一等公民,所有核心组件均以微服务形式部署,天然支持水平扩展、滚动更新和故障恢复。
Vald 的核心优势可以概括为三点:
- 云原生架构:所有组件容器化,通过 gRPC 通信,与 Kubernetes 生态无缝集成
- 高性能索引引擎:底层基于 Yahoo! JAPAN 研发的 NGT(Neighborhood Graph and Tree)算法,在高维向量检索中表现优异
- 灵活的横向扩展:索引分片存储于独立 Pod,可按需增减 Agent 节点,Index Manager 自动管理分片均衡

核心架构解析:从 Gateway 到 Agent 的全链路设计
Vald 采用典型的微服务架构,核心组件包括 Gateway、Agent、Index Manager、Backup Manager 和 Discoverer。理解这些组件的职责和交互方式,是正确部署和调优 Vald 的基础。
Gateway:统一入口与请求路由
Gateway 是 Vald 集群对外暴露的唯一入口。它接收客户端的 gRPC 请求(Insert、Search、Update、Delete 等),根据向量 ID 哈希将请求路由到对应的 Agent 节点。Gateway 本身是无状态的,可以通过增加副本数来提升吞吐量。在 Kubernetes 中,通常以 Deployment + Service 形式部署,并通过 HPA(Horizontal Pod Autoscaler)实现自动扩缩容。
Gateway 的路由策略基于一致性哈希。当 Agent 节点增减时,仅影响少量向量的路由映射,避免大规模数据迁移。这一设计使得 Vald 可以在不中断服务的情况下进行节点扩缩容。
Agent:索引存储与检索执行器
Agent 是 Vald 的核心工作节点,每个 Agent 负责存储一部分索引分片并执行向量检索。Agent 以 StatefulSet 形式部署,确保每个 Pod 拥有稳定的网络标识和持久化存储。Agent 内部运行 NGT 索引引擎,支持自动索引构建和增量更新。
Agent 的关键设计特点包括:
- 增量索引构建:新插入的向量先写入缓冲区,达到阈值后触发后台索引构建,不影响在线检索性能
- 自动快照:定期将索引持久化到对象存储(如 S3、MinIO),确保故障恢复时数据不丢失
- 健康检查与自动修复:通过 Readiness/Liveness Probe 暴露索引状态,异常时由 Index Manager 触发重建
Index Manager:索引生命周期编排
Index Manager 是 Vald 的控制平面,负责索引的创建、删除、重建和分片均衡。它监听 Agent 的状态变化,当检测到节点故障或分片不均衡时,自动触发索引重建或迁移操作。Index Manager 还管理索引版本,支持滚动更新过程中的零停机切换。
Backup Manager 与 Discoverer
Backup Manager 负责将 Agent 的索引快照备份到外部存储,并在 Agent 恢复时提供数据还原。Discoverer 则是服务发现组件,基于 Kubernetes 的 Endpoints 机制动态感知 Agent 节点的上下线,并通知 Gateway 更新路由表。

NGT 索引算法:为何 Vald 的检索速度如此之快
Vald 的底层索引引擎 NGT 是其高性能的关键。NGT 是由 Yahoo! JAPAN 研发的近似最近邻搜索算法,其核心思想是通过构建邻域图(Neighborhood Graph)实现高效的向量检索。与常见的 HNSW 算法相比,NGT 在多个公开数据集上展现出更优的检索速度和召回率平衡。
NGT 的工作原理分为三个阶段:
- 索引构建阶段:首先为所有向量构建 k-NN 图,每个节点与最近的 k 个邻居建立边。然后通过剪枝策略移除冗余边,保留高质量的导航路径
- 搜索阶段:从随机种子点出发,沿着图的边逐步向目标向量靠近,直到无法找到更近的邻居为止。通过多点起始搜索提升召回率
- 增量更新:新插入的向量通过搜索找到最近邻,建立边连接,并触发局部图优化以维持搜索效率
NGT 相较于 HNSW 的一个显著差异在于其动态索引优化能力。HNSW 的层级结构在建索引后基本固定,而 NGT 可以在增量更新过程中持续优化图的拓扑结构,这在频繁更新的生产场景中尤为重要。
以下是 NGT 与 HNSW 在 glove-100 数据集上的性能对比(官方基准):
| 算法 | QPS | Recall@10 | 索引构建时间 | 内存占用 |
|---|---|---|---|---|
| NGT (Anisotropic) | ~3800 | 0.995 | 中等 | 较高 |
| HNSW (ef=200) | ~3200 | 0.990 | 较快 | 中等 |
| IVFPQ | ~5500 | 0.850 | 较快 | 较低 |
可以看到,NGT 在保持接近完美召回率的同时,QPS 优于 HNSW。当然,这是以较高的内存占用为代价的——这也是 Vald 采用分布式架构的原因之一:通过 Agent 分片将内存压力分散到多个节点。
Kubernetes 生产部署实战
Vald 提供了完整的 Helm Chart,可以在 Kubernetes 集群中快速部署。以下是从零开始部署一个生产级 Vald 集群的完整步骤。
环境准备与 Helm 部署
首先确保你有一个运行中的 Kubernetes 集群(1.22+)和 Helm 3。添加 Vald 的 Helm 仓库:
1
2
3
4
5
6
7
8
9 # 添加 Vald Helm 仓库
helm repo add vald https://vald.vdaas.org/charts
helm repo update
# 查看可用的 Chart 版本
helm search repo vald/vald --versions
# 创建命名空间
kubectl create namespace vald
创建自定义的 values 文件来配置 Vald 集群:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 # vald-values.yaml
gateway:
replicas: 3
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2000m"
memory: "2Gi"
hpa:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 70
agent:
replicas: 5
ngt:
autoIndexDurationLimit: "30m"
autoIndexCheckDuration: "5m"
dimension: 768
distance_type: "cosine"
object_type: "float"
creation_edge_size: 60
search_edge_size: 30
resources:
requests:
cpu: "1000m"
memory: "4Gi"
limits:
cpu: "4000m"
memory: "16Gi"
persistence:
enabled: true
size: "50Gi"
storageClass: "ssd"
index_manager:
replicas: 1
autoIndex: true
autoSaveIndex: true
backup_manager:
enabled: true
storageType: "s3"
s3:
bucket: "vald-backup"
region: "us-east-1"
discoverer:
enabled: true
discoverer:
duration: "3s"
使用 Helm 部署 Vald:
1
2
3
4
5
6
7 helm install vald vald/vald \
-n vald \
-f vald-values.yaml \
--timeout 10m
# 验证所有 Pod 已启动
kubectl get pods -n vald -w

客户端接入与数据操作
Vald 提供了多语言 SDK(Go、Java、Python、Node.js),以下以 Python SDK 为例演示基本的向量操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 import vald
from vald.v1.vald import search_pb2, insert_pb2, object_pb2
# 创建客户端连接
channel = vald.connect("vald-gateway.vald.svc.cluster.local:8081")
stub = vald.v1.vald.vald_pb2_grpc.ValdStub(channel)
# 插入向量
vec = object_pb2.Object.Vector(id="doc-001", vector=[0.1] * 768)
insert_req = insert_pb2.Insert.Request(vector=vec)
stub.Insert(insert_req)
# 搜索向量
query = object_pb2.Object.Vector(vector=[0.12] * 768)
search_req = search_pb2.Search.Request(
vector=query,
config=search_pb2.Search.Config(
num=10, # 返回 Top-10 结果
radius=-1.0, # 不限制搜索半径
epsilon=0.01, # 搜索精度参数
min_num=5, # 最少返回结果数
)
)
results = stub.Search(search_req)
for hit in results.results:
print(f"ID: {hit.id}, Distance: {hit.distance}")
性能调优与生产最佳实践
在将 Vald 推向生产环境时,以下调优策略至关重要:
NGT 索引参数调优
NGT 的核心参数是
1 | creation_edge_size |
(建图时的边数)和
1 | search_edge_size |
(搜索时的边数)。较大的
1 | creation_edge_size |
会产生更精确的图,但增加索引构建时间和内存占用。一般建议:
-
1creation_edge_size
:设为 40-80 之间,维度越高取值越大
-
1search_edge_size
:设为
1creation_edge_size的 40%-60%
-
1autoIndexDurationLimit
:设为 15-30 分钟,避免缓冲区过大影响内存
Agent 分片策略
Vald 的分片基于向量 ID 的一致性哈希。在生产环境中,建议:
- Agent 节点数设为数据量 / 单节点内存容量的 1.2 倍(留出 20% 缓冲)
- 使用 SSD StorageClass 作为持久化存储,避免索引加载时的 I/O 瓶颈
- 开启 Backup Manager,设置每 6 小时自动备份索引快照
高可用与容灾
Vald 的高可用依赖 Kubernetes 的原生能力。关键配置包括:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 # Gateway 反亲和性,确保副本分布在不同节点
gateway:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: vald-gateway
topologyKey: kubernetes.io/hostname
# Agent PodDisruptionBudget
agent:
pdb:
enabled: true
minAvailable: "70%"
此外,建议在 Gateway 前部署一层 Nginx Ingress 或 Envoy 作为负载均衡和 TLS 终结,并配置健康检查路由:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: vald-ingress
namespace: vald
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
spec:
rules:
- host: vald-api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: vald-gateway
port:
number: 8081
Vald 与主流向量数据库的横向对比
在选型时,开发者需要根据具体场景权衡不同方案的优劣。以下是 Vald 与 Milvus、Qdrant 的对比:
| 特性 | Vald | Milvus | Qdrant |
|---|---|---|---|
| 架构模式 | 微服务/K8s原生 | 分层架构/支持K8s | 单体/支持分布式 |
| 索引算法 | NGT | HNSW/IVF/DiskANN | HNSW |
| 增量更新 | 原生支持 | 支持(需Compaction) | 原生支持 |
| 过滤搜索 | 有限支持 | 丰富支持 | 丰富支持 |
| K8s集成度 | 极高 | 中等 | 中等 |
| 水平扩展 | Agent级自动 | 手动/半自动 | 分片迁移 |
| 社区生态 | CNCF Sandbox | LF AI&Data | 独立开源 |
| 语言生态 | Go/Java/Python/Node | Python/Java/Go/Node | Python/Rust/Go |
如果你的场景满足以下条件,Vald 是一个值得认真考虑的选择:
- 基础架构以 Kubernetes 为核心,需要向量搜索服务与现有云原生体系深度整合
- 向量数据规模在千万到十亿级别,需要水平扩展能力
- 对增量更新和实时检索有较高要求
- 团队具备一定的 Kubernetes 运维能力
反之,如果你的场景更偏向快速原型验证、需要丰富的过滤搜索能力,或者团队对 Kubernetes 不太熟悉,Milvus 或 Qdrant 可能是更务实的选择。
总结与展望
Vald 作为 CNCF 生态中唯一的云原生向量搜索引擎,在 Kubernetes 深度集成这一维度上具有不可替代的差异化优势。其 NGT 索引引擎在高召回率场景下的性能表现也十分出色。
当然,Vald 也有其局限:过滤搜索能力相对薄弱、社区规模不如 Milvus 活跃、文档和最佳实践案例仍需完善。但随着向量搜索在 AI 基础设施中的地位日益重要,以及 CNCF 生态的持续壮大,Vald 有望在云原生向量搜索这一细分赛道上占据重要一席。
对于正在构建大规模 RAG 系统或语义搜索平台的团队,建议在技术选型阶段将 Vald 纳入评估范围,特别是在 Kubernetes 环境下运行时,Vald 的部署和运维体验会是其他方案难以比拟的。
汤不热吧