Milvus 测试体系实战指南:E2E 端到端测试与 Python 代码质量(ruff)全解析
【免费下载链接】milvusMilvus is a high-performance, cloud-native vector database built for scalable vector ANN search项目地址: https://gitcode.com/GitHub_Trending/mi/milvus
本指南以 Milvus 仓库 tests/README.md 为主体,系统讲解两条核心测试主线:基于 KinD + Helm 的E2E 端到端测试,以及基于ruff(via uv)的 Python 代码质量管控。读完本文,你将掌握在本地搭建 Milvus E2E 测试环境的完整流程、e2e-k8s.sh的每个命令行参数的真实含义,并能用与 CI 完全一致的方式对tests/下的 Python 代码执行 lint 与格式化。
一、tests/ 目录概览:两条并行测试主线
Milvus 仓库将测试体系集中在 tests/ 目录下,从 tests/README.md 可以看到两条明确的主线:
- E2E Test:在真实的 Kubernetes(KinD)集群中部署 Milvus,再通过 pytest 客户端套件验证完整功能链路;
- Python Code Quality:使用 ruff(经 uv 提供)对 tests/python_client、tests/restful_client、tests/restful_client_v2、
benchmark/、tests/scripts 下的全部 Python 代码做 lint 与格式化,并与 GitHub Actions 的 CI 流程对齐。
目录内还包含 tests/Makefile(Python lint 辅助入口)、tests/ruff.toml(ruff 配置)、tests/docker(pytest 测试容器)以及各客户端测试套件。下文分别深入展开。
二、E2E 测试:环境配置要求
E2E 测试并非在宿主机直接跑 pytest,而是先搭建一套完整的 Kubernetes 测试集群(默认使用 KinD),再通过 Helm Chart 部署 Milvus。因此对宿主机环境有明确的最低要求,原文档给出了三张要求表。
2.1 操作系统
| 操作系统 | 版本要求 |
|---|---|
| Amazon Linux | 2023 及以上 |
| Ubuntu | 20.04 及以上 |
| Mac | 10.14 及以上 |
2.2 硬件
| 硬件类型 | 推荐配置 |
|---|---|
| CPU | x86_64 架构 Intel CPU Sandy Bridge 及以上 CPU 指令集:SSE4_2、AVX、AVX2、AVX512;或 arm64 Linux/MacOS |
| 内存 | 16 GB 及以上 |
CPU 指令集要求与 Milvus 核心存储引擎(internal/core)在 CPU 侧向量化计算(如 AVX2 优化)直接相关,Sandy Bridge 之前的架构无法提供所需指令集。
2.3 软件依赖
| 软件名称 | 版本要求 |
|---|---|
| Docker | 19.05 及以上 |
| Docker Compose | 1.25.5 及以上 |
| jq | 1.3 及以上 |
| kubectl | 1.14 及以上 |
| helm | 3.0 及以上 |
| kind | 0.10.0 及以上 |
其中jq用于解析kubectl get ... -o json的 JSON 输出(详见下文 install_milvus.sh 中对 Pod 重启原因的分析);kind(Kubernetes in Docker)负责在 Docker 内拉起整个 Kubernetes 集群。
三、E2E 测试:依赖安装与 Docker 排障
3.1 确认 Docker 守护进程
运行 E2E 前首先要确认 Docker Daemon 是否在运行:
$ docker info原文档给出的排查路径包括:
- 确保 Docker 已安装(参考官方 Docker CE/EE 安装文档);
- 如果 Docker Daemon 未启动,请先启动它;
- 若希望免 root 运行 Docker,可创建名为
docker的用户组,将当前用户加入该组后重新登录终端:
$ sudo usermod -aG docker $USER需要注意的是,e2e-k8s.sh 在真正开始建集群前会再次校验 Docker:
if ! docker info > /dev/null 2>&1; then echo "KinD need docker to set up cluster - please start docker and try again!" exit 1 fi如果 Docker 未就绪,脚本会直接报错退出,而不是等到建集群时才失败。
3.2 检查 Docker Compose 版本
$ docker compose version版本信息形如:
docker compose version 1.25.5, build 8a1c60f6 docker-py version: 4.1.0 CPython version: 3.7.5 OpenSSL version: OpenSSL 1.1.1f 31 Mar 2020Docker Compose 在 E2E 中的用途是拉起 pytest 测试容器(详见 tests/docker/docker-compose.yml),例如 prepare_e2e.sh 中的docker compose pull pytest。
3.3 安装 jq、kubectl、helm、kind
- jq:从官方 jq 下载页获取,用于 JSON 解析;
- kubectl:参考 Kubernetes 官方工具安装文档;
- helm:参考 Helm 官方安装文档(Helm 3 系列);
- kind:参考 KinD 官方 Quick Start 安装文档。
值得注意的是,e2e-k8s.sh 内置了工具自举逻辑:当kubectl或kind不在 PATH 中时,会自动下载并安装指定版本(默认kubectl v1.20.2、kind v0.11.1)到${HOME}/tool_cache/下并加入 PATH,helm 缺失时同理(默认helm v3.5.4)。这意味着即使本机未预装这些工具,脚本也能尽量自动补齐,但推荐仍按原文档先手动装好。
四、E2E 测试:运行与参数全解析
4.1 基本运行方式
原文档给出的启动命令非常简洁:
$ cd tests/scripts $ ./e2e-k8s.sh获取帮助:
$ ./e2e-k8s.sh --help4.2 完整参数清单(源码级解析)
通过阅读 e2e-k8s.sh 的--help输出,我们可以得到脚本支持的全部参数,这是原文档未展开但极具实战价值的部分:
| 参数 | 说明 | 默认值 |
|---|---|---|
--node-image | KinD 节点镜像(用于运行嵌套容器、systemd 与 Kubernetes 组件的 Docker 镜像,可在 KinD releases 中查找) | kindest/node:v1.20.2 |
--kind-config | 启用不同 Kubernetes 特性的 KinD 配置 | 空 |
--build-command | 指定构建 Milvus 的命令 | CPU:make install use_disk_index=ON;GPU:make gpu-install |
--install-extra-arg | 安装 Milvus Helm Chart 的额外配置(如--set/--values覆盖 values) | 空 |
--test-extra-arg | 运行 E2E 测试的额外配置,例如--tags=L0 | 空 |
--test-timeout | E2E 测试超时时间(秒) | 不设置 |
--topology | KinD 集群拓扑:SINGLE_CLUSTER、MULTICLUSTER_SINGLE_NETWORK、MULTICLUSTER | SINGLE_CLUSTER |
--topology-config | KinD 集群拓扑配置文件 | build/config/topology/multicluster.json |
--skip-setup | 跳过 KinD 集群搭建 | 未设置 |
--skip-install | 跳过 Milvus Helm Chart 安装 | 未设置 |
--skip-cleanup | 跳过 KinD 集群清理 | 未设置 |
--skip-build | 跳过构建 Milvus 二进制 | 未设置 |
--skip-build-image | 跳过构建 Milvus 镜像 | 未设置 |
--skip-test | 跳过 E2E 测试 | 未设置 |
--skip-export-logs | 跳过 kind 导出日志 | 未设置 |
--manual | 手动模式:测试结束后暂停,等待按键才关闭集群 | 未设置 |
--disable-kind | 不使用/移除 KinD 集群(配合外部集群) | 未设置 |
--gpu | 以 GPU 模式构建与测试(MODE=gpu、TAG=gpu-latest) | CPU 模式 |
此外脚本还会导出若干可供外部覆盖的环境变量:HUB(镜像仓库,默认milvusdb)、TAG(镜像标签,CPU 为latest)、IP_FAMILY(默认ipv4)、SINGLE_CLUSTER_NAME(默认kind)等。
4.3 脚本执行流水线:从集群到测试
e2e-k8s.sh 的执行顺序清晰对应着几个阶段(可通过--skip-*参数跳过任意环节):
- 环境自检与自举:校验/安装
kubectl、kind、helm,确认 Docker 可用; - 搭建 KinD 集群(
--skip-setup跳过):单集群模式调用setup_kind_cluster;多集群模式读取拓扑 JSON、为每个集群注入 kubeconfig,并导出INTEGRATION_TEST_TOPOLOGY_FILE;同时启动本地镜像仓库kind-registry(localhost:5000),供 KinD 节点拉取构建出的镜像; - 构建 Milvus(
--skip-build跳过):执行build/builder.sh(CPU)或builder_gpu.sh(GPU),默认构建命令为make install use_disk_index=ON; - 构建并推送镜像(
--skip-build-image跳过):执行build/build_image.sh,然后docker push到本地 kind registry; - Helm 安装 Milvus(
--skip-install跳过):调用 install_milvus.sh,release 名由 get_release_name.sh 生成; - 执行 E2E 测试(
--skip-test跳过):调用 e2e.sh; - 手动模式挂起 / 正常清理退出:
--manual下等待按键,否则脚本结束(集群清理由后续流程处理)。
4.4 Helm 安装细节
install_milvus.sh 是安装阶段的核心,几个关键行为值得注意:
- 默认安装超时
MILVUS_INSTALL_TIMEOUT=800s(注释说明因 Pulsar 多了一个节点而从 500s 上调); - 安装前会先
helm uninstall清理同名 release,并删除关联的 PVC; - Standalone 模式(
MILVUS_CLUSTER_ENABLED=false)下默认关闭 Pulsar(pulsar.enabled=false)、使用独立 MinIO(minio.mode=standalone)、etcd 单副本;集群模式下则启用 Pulsar 双副本 broker; - 服务类型按环境选择:KinD + metallb 时用
LoadBalancer,否则默认ClusterIP; - 安装失败时会收集异常 Pod 的 events 辅助定位,并检查 Pod 重启原因(用 jq 解析
restartCount与lastState.terminated.reason)。
4.5 pytest 客户端如何连上 Milvus
e2e.sh 负责打通测试容器到 Milvus 服务的网络:
- 通过
kubectl get service -l "app.kubernetes.io/instance=...,component=standalone|proxy"解析服务 IP 与端口;当服务类型为 ClusterIP 时,使用kubectl port-forward将 Pod 端口转发到本机127.0.0.1,并在退出时trap清理转发进程; - 在 tests/docker 目录下以
docker compose run --rm pytest方式运行测试容器,默认并行数PARALLEL_NUM=6:
docker compose run --rm pytest /bin/bash -c "pytest -n 6 --host ${MILVUS_SERVICE_IP} --port ${MILVUS_SERVICE_PORT} ..."测试容器的工作目录为/milvus/tests/python_client,tests/docker/docker-compose.yml 将仓库根目录挂载进容器(../../:/milvus:delegated),并设置shm_size: 2G(供 pytest-xdist 多进程共享内存使用)。
而 CI 环境下的 ci_e2e.sh 则不经 Docker 容器,直接在 tests/python_client 目录下调用 pytest,并通过--minio_host额外传入 MinIO 服务名(以服务名而非 IP 访问,MILVUS_SERVICE_NAME=<release>-milvus.<namespace>,端口 19530),日志路径默认为/tmp/ci_logs/test。
五、Python 代码质量:ruff via uv
5.1 配置与作用范围
ruff 的配置位于 tests/ruff.toml,覆盖 tests/ 下所有 Python 代码,包括python_client/、restful_client/、restful_client_v2/、benchmark/、scripts/;各子目录继续通过各自的requirements.txt管理运行时依赖。
关键配置项:
line-length = 120:行宽上限 120 字符;target-version = "py312":目标 Python 版本 3.12;- 启用的规则组:
E(pycodestyle errors)、F(pyflakes)、W(pycodestyle warnings)、I(isort)、UP(pyupgrade); - 忽略项:
E501(行长交给 formatter 处理)、E741(测试代码中常见的l/I/O歧义变量名)、F841(测试代码刻意保留调用结果、且缺失断言的场景已修复)、UP031(printf 风格格式化属纯风格改写,27 处% (...)元组用法并不等价); - per-file-ignores:
__init__.py忽略F401,conftest.py忽略F401、F811; - 格式化风格:双引号、空格缩进、
line-ending = "auto"。
5.2 常用命令
原文档给出的核心命令:
$ cd tests/ $ ruff check . # lint $ ruff check . --fix # lint with auto-fix $ ruff format . # format in place $ ruff format --check . # format check only (CI-friendly)需要说明的是,ruff通过uv提供(uvx ruff@<version>),uv由 python-env.sh 负责引导——该脚本会根据 tests/.python-version(或PYTEST_PYTHON_VERSION,默认3.12)自动创建位于tests/.venv的虚拟环境,缺少uv时会用现有 Python 先安装 uv 再创建环境。
5.3 只 lint PR 变更文件:与 CI 精确对齐
原文档特别强调:直接对整个tests/树执行uv run ruff check .是过于粗糙的——大量历史文件的遗留风格早于当前 lint 配置,会命中无关规则而失败。因此 CI 只对每次 PR变更的tests/**/*.py执行ruff check与ruff format --check。
为在本地精确复现 CI 行为,请使用 tests/Makefile 提供的目标:
$ cd tests/ $ make ci # ruff check + format --check on PR-changed *.py (CI equivalent) $ make lint-fix # ruff check --fix on PR-changed *.py $ make format # ruff format on PR-changed *.py $ make help # show all targets and the detected BASE_REF各目标的行为(依据 Makefile 源码):
| 目标 | 等价命令(作用于 PR 变更文件) |
|---|---|
lint | ruff check <changed-files> |
format-check | ruff format --check --diff <changed-files> |
ci | lint+format-check |
lint-fix | ruff check --fix <changed-files> |
format | ruff format <changed-files> |
变更文件集合通过git diff --name-only --diff-filter=ACMR $(BASE_REF)...HEAD -- 'tests/**/*.py'(三点 diff,即从 merge-base 起算)计算。ruff 版本由RUFF_VERSION固定(默认0.15.11),与.github/workflows/python-lint.yaml工作流保持一致,保证本地与 CI 使用同一版本。
5.4 BASE_REF 自动检测与手动指定
BASE_REF是 diff 基准分支,Makefile 会尝试从当前分支的已开启 PR自动推导:
- 通过
gh pr view读取 PR URL 与baseRefName; - 从 PR URL 解析出 base 仓库
<owner>/<repo>; - 与本地
git remote -v匹配(不假设是origin——fork 场景通常 base 是upstream,直接 clone 场景则是origin),产出形如upstream/master、upstream/2.x、origin/main的基准。
当分支没有关联 PR(或gh未认证)时,BASE_REF为空,此时必须显式指定,否则make会报错BASE_REF is not set:
$ make ci BASE_REF=upstream/master同时需要uv(提供uvx)与已通过gh auth status认证的 GitHub CLI。可以先运行make help查看当前检测到的BASE_REF。
六、总结与最佳实践
综合原文档与源码,Milvus 测试体系的使用要点可归纳为:
- E2E 测试是"环境密集型"流程:先满足 tests/README.md 中的 OS/硬件/软件最低要求(Docker、Compose、jq、kubectl、helm、kind),再运行 e2e-k8s.sh;开发调试阶段可善用
--skip-build、--skip-install、--skip-test等参数只跑感兴趣的阶段,用--manual在测试结束后保留集群便于人工排查; - 测试真正的执行者是 pytest:无论是 e2e.sh 的 Docker 容器方式(
-n 6并行、port-forward转发),还是 ci_e2e.sh 的直接方式(服务名访问、--minio_host),最终都落到 tests/python_client 等套件上; - Python 质量管控与 CI 强对齐:不要对全量文件跑 ruff,应使用 tests/Makefile 的
make ci(自动检测BASE_REF),或在无 PR 时显式传入基准分支,从而只检查本次变更文件; - 配置即文档:ruff 的规则选择与例外都带注释说明意图,tests/ruff.toml 本身即是团队代码风格约定的最佳注脚。
遵循以上流程,你就可以在本地复现 Milvus 官方的 E2E 测试与 Python lint CI 行为,让每一次提交在进入 CI 前就获得与线上一致的质量保障。
【免费下载链接】milvusMilvus is a high-performance, cloud-native vector database built for scalable vector ANN search项目地址: https://gitcode.com/GitHub_Trending/mi/milvus
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考