オープンソースソフトウェア(OSS)の品質保証 - Milvusのケーススタディ
表紙画像
この記事はWenxing Zhuによって書かれ、Angela Niによって翻訳されました。
品質保証(QA)とは、製品やサービスが特定の要件を満たしているかどうかを判断する体系的なプロセスである。QAシステムは、その名の通り、製品の品質を保証するものであり、研究開発プロセスにおいて欠かすことのできないものである。
本記事では、Milvusベクターデータベースの開発において採用されたQAフレームワークを紹介し、貢献する開発者やユーザーがプロセスに参加するためのガイドラインを提供することを目的とする。また、Milvusの主要なテストモジュールや、QAテストの効率を向上させるために活用できる手法やツールについても取り上げます。
戻る
Milvus QAシステムの概要
QAテストを実施する上で、システムアーキテクチャは非常に重要です。QAエンジニアがシステムを熟知していればいるほど、合理的かつ効率的なテスト計画を立てることができます。
Milvusアーキテクチャ
Milvus2.0は、クラウドネイティブ、分散、レイヤードアーキテクチャを採用しており、SDKはMilvusにおけるデータの流れの主要な入り口となっている。MilvusユーザーはSDKを頻繁に利用するため、SDK側の機能テストが非常に必要となります。また、SDKの機能テストは、Milvusシステム内に存在するかもしれない内部的な問題を検出するのに役立ちます。機能テスト以外にも、ユニットテスト、デプロイテスト、信頼性テスト、安定性テスト、パフォーマンステストなど、様々な種類のテストがベクターデータベース上で実施される。
クラウドネイティブで分散型のアーキテクチャは、QAテストに利便性と課題の両方をもたらす。ローカルにデプロイされ実行されるシステムとは異なり、Kubernetesクラスタ上にデプロイされ実行されるMilvusインスタンスは、ソフトウェア開発と同じ状況下でソフトウェアテストを確実に実施することができる。しかし、デメリットとしては、分散アーキテクチャの複雑さが、システムのQAテストをさらに難しく、大変なものにする不確実性をもたらすことだ。例えば、Milvus 2.0では様々なコンポーネントのマイクロサービスを使用しているため、サービスやノードの数が増え、システムエラーが発生する可能性が高くなる。そのため、より洗練された包括的なQAプランが、テスト効率の向上のために必要となる。
QAテストと課題管理
MilvusにおけるQAには、テストの実施とソフトウェア開発中に発生した問題の管理の両方が含まれます。
QAテスト
Milvusでは、Milvusの機能やユーザーニーズに応じて、下図のような優先順位で様々なタイプのQAテストを実施しています。
QAテストの優先順位
MilvusのQAテストは、以下の優先順位で実施されます:
- 機能機能:機能や特徴が当初の設計通りに動作するかを検証する。
- デプロイメントMilvus スタンドアロン版と Milvus クラスタ版を異なる方法(Docker Compose、Helm、APT、YUM など)でデプロイ、再インストール、アップグレードできるかを確認する。
- パフォーマンス Milvusのデータ挿入、インデックス作成、ベクトル検索、クエリのパフォーマンスをテストする。
- 安定性Milvusが通常レベルのワークロードで5~10日間安定稼働するかを確認する。
- 信頼性特定のシステムエラーが発生した場合でも、Milvusが部分的に機能するかどうかをテストする。
- 設定:Milvusが特定の環境下で期待通りに動作するかを検証する。
- 互換性Milvusが異なるハードウェアやソフトウェアと互換性があるかどうかを検証する。
問題管理
ソフトウェア開発中には様々な問題が発生します。テンプレート化された問題の作成者は、QAエンジニア自身であったり、オープンソースコミュニティのMilvusユーザであったりします。QAチームはその問題を解決する責任を負います。
課題管理ワークフロー
課題が作成されると、まずトリアージが行われます。トリアージでは、新しいissueが精査され、issueの詳細が十分に提供されていることが確認されます。issueが確認されると、開発者に受け入れられ、開発者はissueの修正を試みます。開発が完了すると、issueの作成者はそれが修正されたかどうかを確認する必要があります。問題が修正された場合、その課題は最終的にクローズされます。
QAはいつ必要なのか?
よくある誤解として、QAと開発は互いに独立しているというものがある。しかし実際には、システムの品質を保証するためには、開発者とQAエンジニアの両方の努力が必要である。したがって、QAはライフサイクル全体を通して関わる必要がある。
QAライフサイクル
上の図に示すように、ソフトウェアの研究開発ライフサイクルには3つの段階がある。
初期段階では、開発者が設計文書を公開する一方で、QAエンジニアがテスト計画を立案し、リリース基準を定義し、QAタスクを割り当てます。開発者とQAエンジニアは、リリースの目的(機能、パフォーマンス、安定性、バグの収束など)についての相互理解が両チーム間で共有されるように、設計書とテスト計画の両方に精通している必要があります。
研究開発期間中、開発とQAテストは頻繁にやり取りを行い、機能や特徴の開発・検証を行い、オープンソースコミュニティから報告されたバグや問題も修正する。
最終段階では、リリース基準を満たした場合、Milvus新バージョンのDockerイメージがリリースされます。正式リリースには、新機能と修正されたバグに焦点を当てたリリースノートとリリースタグが必要です。その後、QAチームはこのリリースに関するテストレポートも公開します。
Milvusのテストモジュール
Milvusにはいくつかのテストモジュールがありますが、ここでは各モジュールについて詳しく説明します。
ユニットテスト
ユニットテスト
ユニットテストは、ソフトウェアのバグを早期に発見し、コード再構築の検証基準を提供するのに役立ちます。Milvusのプルリクエスト(PR)受け入れ基準によると、コードのユニットテストのカバレッジは80%である必要があります。
機能テスト
Milvusの機能テストは主にPyMilvusとSDKを中心に構成されています。機能テストの主な目的は、インタフェースが設計通りに動作するかどうかを検証することです。機能テストには2つの側面があります:
- 正しいパラメータが渡されたときにSDKが期待される結果を返すことができるかどうかのテスト。
- 間違ったパラメータが渡されたときに、SDKがエラーを処理し、妥当なエラーメッセージを返すことができるかどうかをテストする。
下図は、主流のpytestフレームワークに基づいている関数テストの現在のフレームワークを示しています。このフレームワークはPyMilvusにラッパーを追加し、自動化されたテストインタフェースでテストを強化します。
関数テスト
共有のテスト手法が必要であり、いくつかの関数を再利用する必要があることを考慮し、PyMilvusのインターフェースを直接使用するのではなく、上記のテストフレームワークを採用しています。check "モジュールもフレームワークに含まれ、期待値と実際の値の検証に利便性をもたらします。
2,700もの関数テストケースがtests/python_client/testcases
ディレクトリに組み込まれており、ほぼすべての PyMilvus インタフェースを完全にカバーしています。これらの関数テストは各PRの品質を厳密に監視します。
デプロイメントテスト
Milvusにはスタンドアロンと クラスタの2つのモードがあります。また、Milvusをデプロイする方法は大きく分けてDocker Composeを使う方法とHelmを使う方法があります。また、Milvusをデプロイした後、Milvusサービスの再起動やアップグレードを行うこともできる。デプロイテストには大きく分けて再起動テストとアップグレードテストの2種類がある。
再起動テストとは、データの永続性、つまり再起動後もデータが利用可能かどうかをテストするプロセスを指します。アップグレードテストとは、互換性のない形式のデータがmilvusに挿入される事態を防ぐために、データの互換性をテストするプロセスを指す。この2種類のデプロイメントテストは、下図のように同じワークフローを共有します。
配置テスト
再起動テストでは、2つのデプロイメントで同じ docker イメージを使用します。しかしアップグレードテストでは、1つ目のデプロイメントでは以前のバージョンの docker イメージを使用し、2つ目のデプロイメントではそれ以降のバージョンの docker イメージを使用します。テスト結果とデータはVolumes
ファイルまたは永続ボリュームクレーム(PVC)に保存される。
最初のテストを実行するとき、複数のコレクションが作成され、それぞれのコレクションに対して異なる操作が行われる。2番目のテストを実行する場合、作成されたコレクションがCRUD操作でまだ利用可能かどうか、新しいコレクションをさらに作成できるかどうかを検証することに主眼が置かれます。
信頼性テスト
クラウドネイティブ分散システムの信頼性に関するテストは、通常、エラーやシステム障害の芽を摘むことを目的としたカオスエンジニアリング手法を採用する。つまり、カオスエンジニアリングのテストでは、意図的にシステム障害を発生させることで、プレッシャーテストにおける問題を特定し、システム障害が本当に危険な状態になる前に修正する。Milvusのカオステストでは、カオスを作り出すツールとしてカオスメッシュを選択する。作成が必要な障害にはいくつかの種類がある:
- ポッドキル:ノードがダウンするシナリオのシミュレーション。
- ポッド障害:ワーカーノードのポッドの1つが故障した場合、システム全体がまだ動作し続けることができるかどうかをテストする。
- メモリ・ストレス:作業ノードがメモリとCPUリソースを大量に消費するシミュレーション。
- ネットワーク・パーティション:Milvusはストレージとコンピューティングを分離しているため、システムは様々なコンポーネント間の通信に大きく依存している。異なるMilvusコンポーネントの相互依存性をテストするために、異なるポッド間の通信がパーティション化されたシナリオのシミュレーションが必要である。
信頼性テスト
上図はMilvusの信頼性テストフレームワークを示しており、カオステストを自動化することができます。信頼性テストのワークフローは以下の通りである:
- デプロイメント設定を読み込んでMilvusクラスタを初期化する。
- クラスタの準備ができたら、
test_e2e.py
、Milvusの機能が利用可能かどうかをテストする。 hello_milvus.py
を実行してデータの永続性をテストする。データ挿入、フラッシュ、インデックス構築、ベクトル検索、クエリ用に "hello_milvus "という名前のコレクションを作成する。このコレクションは、テスト中に解放または削除されない。- create、insert、flush、index、search、query 操作を実行する6つのスレッドを開始する監視オブジェクトを作成する。
checkers = {
Op.create: CreateChecker(),
Op.insert: InsertFlushChecker(),
Op.flush: InsertFlushChecker(flush=True),
Op.index: IndexChecker(),
Op.search: SearchChecker(),
Op.query: QueryChecker()
}
- 最初のアサーションを行う。
- Chaos Meshを使用して、障害を定義するyamlファイルを解析し、Milvusにシステム障害を導入する。障害とは、例えば5秒ごとにクエリノードを停止させることである。
- システム障害を導入しながら2つ目のアサーションを行う - システム障害時にMilvusで行われた操作の返された結果が期待値と一致するかどうかを判断する。
- Chaos Meshで障害を排除する。
- Milvusサービスが回復したら(つまりすべてのポッドが準備できたら)、3番目のアサーションを行う。
- Milvus の機能が利用可能かどうかをテストするために
test_e2e.py
を実行する。カオスの間、3つ目のアサーションのためにいくつかのオペレーションがブロックされるかもしれない。また、カオスが解消された後でも、一部の操作がブロックされ続け、3つ目のアサーションが期待通りに成功しない可能性がある。このステップの目的は、3つ目のアサーションを容易にすることであり、Milvusサービスが回復したかどうかを確認する基準として機能することである。 hello_milvus.py
を実行し、作成されたコレクションをロードし、そのコレクションにCRUP操作 を実行する。次に、システム障害前に存在したデータが障害復旧後も利用可能かどうかをチェックする。- ログを収集する。
安定性テストと性能テスト
下図は、安定性テストと性能テストの目的、テストシナリオ、および測定基準を示している。
安定性テスト | パフォーマンステスト | |
---|---|---|
目的 | - Milvusが一定時間、通常のワークロードで円滑に動作することを確認する。 - Milvusサービス起動時にリソースが安定的に消費されることを確認する。 | - Milvusの全インターフェースの性能をテストする。 - パフォーマンステストにより最適なコンフィギュレーションを見つける。 - 将来のリリースのベンチマークとする。 - パフォーマンス向上の妨げとなるボトルネックを見つける。 |
シナリオ | - オフラインの読み取り集中型シナリオでは、データは挿入後ほとんど更新されず、各タイプのリクエストの処理割合は、検索リクエスト90%、挿入リクエスト5%、その他5%。 - オンライン書き込み集中型シナリオ:データの挿入と検索が同時に行われ、各リクエストの処理割合は、挿入リクエスト50%、検索リクエスト40%、その他10%。 | - データ挿入 - インデックス構築 - ベクトル検索 |
指標 | - メモリ使用量 - CPU消費量 - IOレイテンシ - Milvusポッドのステータス - Milvusサービスのレスポンスタイム その他 | - データ挿入時のデータスループット - インデックス構築にかかる時間 - ベクトル検索時の応答時間 - 1秒あたりのクエリー数 (QPS) - 1秒あたりのリクエスト数 - リコール率 などである。 |
安定性テストとパフォーマンス・テストは、同じワークフローを共有する:
安定性テストとパフォーマンス・テスト
- 設定を解析・更新し、メトリクスを定義する。
server-configmap
、milvusスタンドアロンまたはクラスタの設定に対応し、client-configmap
、テストケースの設定に対応する。 - サーバとクライアントの設定
- データの準備
- サーバとクライアント間のインタラクションを要求する。
- メトリクスのレポートと表示
QA 効率向上のためのツールと手法
モジュールテストのセクションを見ると、Milvusサーバとクライアントの設定変更、APIパラメータの受け渡しなど、ほとんどのテストの手順はほぼ同じであることがわかる。複数のコンフィギュレーションがある場合、異なるコンフィギュレーションの組み合わせが多様であればあるほど、これらの実験やテストはより多くのテストシナリオをカバーすることができる。その結果、コードと手順を再利用することが、テスト効率を高めるプロセスにとってより重要になります。
SDKテストフレームワーク
SDKテストフレームワーク
テストプロセスを加速するために、オリジナルのテストフレームワークにAPI_request
ラッパーを追加し、APIゲートウェイに似たものとして設定することができる。このAPIゲートウェイは、すべてのAPIリクエストを収集し、Milvusに渡してまとめてレスポンスを受け取る役割を担う。これらのレスポンスは、その後クライアントに引き渡される。このような設計により、パラメータや返された結果のような特定のログ情報の取得がより簡単になる。さらに、SDKテストフレームワークのチェッカーコンポーネントは、Milvusからの結果を検証し、検査することができます。そして、すべてのチェック方法はこのチェッカーコンポーネント内で定義することができます。
SDKテストフレームワークでは、いくつかの重要な初期化処理を1つの関数にまとめることができます。そうすることで、面倒なコードの大きな塊を省くことができます。
また、データの分離を確実にするために、個々のテストケースが固有のコレクションに関連付けられ ていることも注目すべき点です。
テストケースを実行する際には、pytest-xdist
(pytest拡張機能)を活用することで、個々のテストケースをすべて並行して実行することができ、効率が大幅に向上します。
GitHub アクション
GitHubアクション
GitHub Actionは、以下のような特徴からQAの効率化にも採用されている:
- GitHubと深く統合されたネイティブのCI/CDツールである。
- 統一されたマシン環境と、Docker、Docker Composeなどの一般的なソフトウェア開発ツールがプリインストールされている。
- Ubuntu、MacOs、Windows-serverなど、複数のオペレーティングシステムとバージョンをサポートしています。
- 豊富な拡張機能とすぐに使える機能を提供するマーケットプレイスがあります。
- マトリックスは同時実行ジョブをサポートし、同じテストフローを再利用して効率を向上させる。
上記の特徴とは別に、GitHub Actionを採用するもう一つの理由は、デプロイテストや信頼性テストには独立した隔離された環境が必要だからです。また、GitHub Actionは小規模なデータセットの日常的な検査チェックに最適です。
ベンチマークテスト用ツール
QAテストを効率化するために、多くのツールが使われています。
QAツール
- Argo: Kubernetes用のオープンソースツール群で、ワークフローを実行し、タスクをスケジューリングしてクラスタを管理する。複数のタスクを並行して実行することもできる。
- Kubernetesダッシュボード:
server-configmap
とclient-configmap
を可視化するためのウェブベースのKubernetesユーザーインターフェース。 - NAS: Network Attached Storage (NAS)は、一般的なANNベンチマークのデータセットを保管するためのファイルレベルのコンピュータデータストレージサーバー。
- InfluxDBと MongoDB:ベンチマークテストの結果を保存するためのデータベース。
- Grafana:サーバーのリソースメトリクスやクライアントのパフォーマンスメトリクスを監視するためのオープンソースの分析・監視ソリューション。
- Redash:データを可視化し、ベンチマークテストのチャートを作成するためのサービス。
ディープ・ダイブ・シリーズについて
Milvus 2.0の一般提供の正式発表に伴い、Milvusのアーキテクチャとソースコードの詳細な解釈を提供するために、このMilvus Deep Diveブログシリーズを企画しました。このブログシリーズで扱うトピックは以下の通りです:
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word