powered by TechFeed
表示モード
Deep Dive

200億ベクトルを38チームが利用するHubSpotのベクトル検索基盤 — HelmからKubernetes Operatorへ移行して運用を自動化するまで

6月26日、HubSpotが「Building the AI Retrieval Infrastructure Behind 20 Billion+ Vectors at HubSpot」と題した記事を公開した。この記事では、200億件以上のベクトルを支えるHubSpotの社内ベクトル検索インフラ「VaaS」の設計と、PoC段階から本番規模へのスケールアップの過程について詳しく紹介されている。

6月26日、HubSpotが「Building the AI Retrieval Infrastructure Behind 20 Billion+ Vectors at HubSpot」と題した記事を公開した。この記事では、200億件以上のベクトルを支えるHubSpotの社内ベクトル検索インフラ「VaaS」の設計と、PoC段階から本番規模へのスケールアップの過程について詳しく紹介されている。


なぜHubSpotはベクトル検索基盤を内製したのか

HubSpotではRAG(Retrieval Augmented Generation)を活用したAI機能、AIエージェント、コンタクト重複排除など、ベクトル検索を前提とするユースケースが急速に増加していた。こうした機能を複数の製品チームが独立して実装しようとすると、エンベディング生成・アクセス制御・データバージョニングといった共通処理を各チームが個別に構築することになり、コストと品質のばらつきが生じる。そこでHubSpotは、これらの共通機能を一元提供するプラットフォームとしてVaaSを整備することにした。社内の38を超えるチームが単一のAPIレイヤー経由でベクトル検索を利用できる環境を、少人数のプラットフォームチームが中央集権的に維持・管理するというモデルだ。


38チームが使う社内ベクトル検索基盤「VaaS」

HubSpotが構築したVaaS(Vector as a Service)は、ベクトルDBの前段に置くAPIレイヤーだ。アクセス制御・エンベディング生成・データバージョニング・フィードバック収集といった機能を提供し、内部ではオープンソースのベクトルDB「Qdrant」を使用する。

現在の規模は以下のとおりだ。

  • 利用チーム数: 38以上
  • インデックス数: 200以上
  • クラスタ数: 140以上(5リージョン・2環境)
  • 総ベクトル数: 200億以上(最大インデックス単体で95億件)
  • 書き込みRPS: 通常5,000超、スパイク時は10万RPS
  • 読み取りRPS: 全リージョン合計で1,000超

なぜQdrantをオンプレで動かすのか

HubSpotはQdrantをマネージドサービスとして使わず、AWS上でセルフホストしている。理由はいくつかある。

  • 社内インフラチームが持つトレーシング・コスト追跡・レートリミット・スケーリングなどの内部ツールとシームレスに統合できる
  • 法人向けAWSレートを活用したコスト管理が可能である
  • 顧客データの完全な管理権限とセキュリティポリシーを自社基準で適用できる

Qdrantを選んだ技術的な理由としては、Named Vectors・ハイブリッド検索・マルチステージクエリ・重み付き再ランキングといったモダンな検索機能を網羅したAPIが挙げられる。近傍探索アルゴリズムにはHNSWHierarchical Navigable Small World:グラフ構造を階層化することで高速な近似最近傍探索を実現するアルゴリズム)を採用しており、低レイテンシを実現する一方でメモリ消費量が大きい。この点はクォンタイズやオンディスクストレージなどのコスト最適化機能で調整する。


HelmからKubernetes Operatorへの移行が核心

記事でエンジニア的に最も読み応えがあるのが、HelmからKubernetes Operatorパターンへの移行だ。

2023年のPoCフェーズでは、Helm(KubernetesのパッケージマネージャーでYAMLテンプレートによるリソース定義を管理するツール)でクラスタ定義を管理していた。クラスタ数が少ないうちは問題なかったが、規模が拡大するにつれて以下の限界が露呈した。

  • API呼び出しができない
  • 外部メトリクスに基づく自動スケールができない
  • 複雑なステート管理ロジックを持てない

HubSpotは社内フレームワーク「Kube-operators」を持っており、Kubernetes Operatorパターン(Custom ResourceとコントローラーによってKubernetesのAPIを拡張し、アプリケーション固有のライフサイクル管理を自動化する手法)を実装することでQdrantクラスタのライフサイクル管理を自動化した。

Translatorによる自動化

Kube-operatorsの核心はTranslatorと呼ばれるコンポーネントだ。Custom Resource(CR)を監視し、60秒ごとに実態と定義済み状態の差分を検出して自動的に調整する。現在は以下の3つのTranslatorが稼働している。

  1. Cluster Translator: クラスタごとのK8s Namespaceと関連アーティファクトを作成する
  2. Qdrant Nodeset Translator: Qdrantクラスタ本体(Pod数・メモリ・ディスク等)を管理する
  3. Indexer Nodeset Translator: 書き込みトラフィックを処理するIndexerワーカーとKafkaトピック(分散メッセージキューであるKafka上の論理的なデータチャンネル)を管理する

移行に合わせてK8s Namespaceの戦略も変更し、全クラスタ共有からクラスタごとに独立したNamespaceへ移行した。これにより障害の影響範囲の局所化、Namespace単位のコスト追跡、リソース制限の個別設定が可能になった。


スケールダウンの自動化:4操作を1操作に

Kube-operators移行前、クラスタの水平スケールダウンは以下の4ステップを手動で実施する必要があった。

  1. 退役Peerからシャードを転送するジョブを手動実行する
  2. Helmチャートのpod数を変更する
  3. Helmチャートを適用する
  4. 削除したPodのPVCを手動削除する

Kube-operators移行後は、CRのreplica数を1箇所変更するだけでTranslatorが自動的に以下のシーケンスを実行する。

  1. 退役Pod上の全シャードを他Podへ転送する
  2. 全転送の完了を確認する
  3. PodをQdrant Consensusから除外する
  4. PVCを削除する

残存Pod数がレプリケーションファクター(データの冗長性を確保するためにシャードを複製して保持するPodの数)を下回る場合は処理を事前に拒否し、転送中にシャードがDeadステートになった場合は即座にアボートする安全機構も組み込まれている。


カスタムシャーディングと自動バランシング

数十億件規模のコレクションでは、クエリのファンアウトを最小化するためにユーザー定義シャーディングを採用している。ただしこれはシャードの偏りを生む可能性があり、Qdrantはデフォルトでベクトルをすべてメモリにロードする仕様上、偏りがあると最もヘビーなPodに合わせてスケールアップが必要になる。

HubSpotはシャード数とポイント数の両面でシャードを貪欲法でバランシングするアルゴリズムを設計し、Translatorの60秒ごとの調整ループに組み込んだ。偏りを検出すると自動的に再分散を実行する。


まとめ

HubSpotのVaaS構築で示されたのは、PoC段階の「動けばよい」構成が本番規模になったとき、いかに運用負荷が爆発するかという典型例だ。38以上のチームが利用する大規模ベクトル検索基盤を少人数のプラットフォームチームが維持できているのは、Helm→Kubernetes Operatorへの移行とTranslatorによるシャード管理の自動化によって、定常的な運用作業の大部分を排除したからに他ならない。

詳細はBuilding the AI Retrieval Infrastructure Behind 20 Billion+ Vectors at HubSpotを参照していただきたい。