The potential of Kubernetes as more than just an infrastructure to deploy

174 Views

January 31, 22

スライド概要

分散密ベクトル探索エンジンである Vald ( https://vald.vdaas.org ) は、 Kubernetesを単なるデプロイするためのインフラとしてだけではなく、Valdのアプリケーションロジックが直接Kubernetes APIを利用し分散密ベクトル探索エンジンValdの分散レイヤーの一部として利用しています。 ValdはGraph&Tree構造からなるベクトルインデックス構造をIn-Memory上に保持しており、 各Podは別々のGraph空間を有していてKubernetesのAPIから取得できる情報をもとに各Podのベクトルインデックスの管理を行っています。

このスライドでは、アプリケーションからcontroller-runtimeを利用し直接 Kubernetes API を利用する真の Kubernetes ネイティブアプリケーションであるValdの事例について紹介します。

profile-image

エンジニア・デザイナー向けのヤフー公式アカウント。イベント/登壇情報/ブログ記事など、ヤフーの技術・デザインに関わる情報を発信します。

シェア

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

The potential of Kubernetes as more than just an infrastructure to deploy KubeFest Tokyo 2020 Yusuke Kato/ Vdaas / Vald kpango (Yahoo Japan Corporation)

2.

kubectl -n vald get sa kpango -o yaml apiVersion: v1 kind: ServiceAccount metadata: name: kpango namespace: vald annotations: vald.vdaas.org: 開発者 yahoo.co.jp/tech-lab: テクノロジープロダクトオーナー yahoo.co.jp/kuro-obi: Go言語黒帯 yahoo.co.jp/ex-swat: 在籍した2016~2019年の間に21案件を鎮火 github.com: kpango twitter.com: @kpang0 creationTimestamp: "1992-01-14T07:13:00Z" Vdaas / Vald 2

3.

Agenda 🌲 ヤフーのベクトル検索について 🌲 Valdについて 🌲 controller-runtimeについて 🌲 controller-runtimeの応用 🌲 Valdの今後について 🌲 まとめ Vdaas / Vald 3

4.

ヤフーのベクトル検索について Vdaas / Vald 4

5.

ヤフーのベクトル検索について Data 深層学習を用い多種多様なデータを特徴ベクトル化 ベクトルの距離計算によりデータをNGTにIndexing 5 Vdaas / Vald icons from https://www.flaticon.com/authors/monkik

6.

ヤフーのベクトル検索について ~ NGTについて ~ NGT (Neighborhood Graph and Tree)はYahoo! JAPAN研究所で開発 された世界トップレベル(ann-benchmarks)の 高速高精度な近似近傍検索アルゴリズム メモリ上に全てのGraph and Tree構造のIndexを保持する サーバー実装としてNGTDがありREST / gRPC経由で ベクトルのCRUD処理を行うインターフェースを提供 Vdaas / Vald 6

7.

ヤフーのベクトル検索について ~サービスでの事例~ 類似商品画像検索 Vdaas / Vald 出品画像よりカテゴリを推定 7

8.

ヤフーのベクトル検索について 🌲 🌲 ~ 現状の課題について ~ データが増え続ければメモリは増え続けて減少する事はない – NGTサーバーはメモリ不足に 高価なハイスペックサーバ or シャーディングが必要に 8 Vdaas / Vald icons from https://www.flaticon.com/authors/monkik

9.

ヤフーのベクトル検索について ~ NGTのレガシーなシャーディング ~ /01/search /02/search /02/insert /01-80/search /02/insert VM /80/search search insert Envoyを用いてPathベースでルーティング VM Cluster Search時は全ての検索結果を集計 Vdaas / Vald 9

10.

ヤフーのベクトル検索について ~ NGTのレガシーなシャーディング ~ /01/search /02/search /02/insert VM 1. RAM使用率に偏りが生じやすい。 2. Indexの復旧管理が必要 3. VM変更はEnvoy再設定必須 4. PFクライアントのコードも要変更 /80/search search Insert VM Cluster Vdaas / Vald 10

11.

ヤフーのベクトル検索について ~ NGTのレガシーなシャーディング ~ /01/search /02/search /02/insert VM 1. RAM使用率に偏りが生じやすい。 2. Indexの復旧管理が必要 3. VM変更はEnvoy再設定必須 4. PFクライアントのコードも要変更 /80/search search Insert VM Cluster Vdaas / Vald 11

12.

ヤフーのベクトル検索について ~ 必要要件 ~ 🌲 データ量増加に耐えうるメモリ的スケーラビリティ 🌲 インデックスの自動管理機能 (復旧、更新、リバランス) 🌲 ハイパフォーマンス 🌲 分散をユーザーに意識させないインターフェース 🌲 運用コストの低減 🌲 拡張性 Vdaas / Vald 12

13.

ヤフーのベクトル検索について Vdaas / Vald ~ モダンなベクトル検索エンジンへ ~ 13

14.

Valdについて Vdaas / Vald 14

15.

Valdについて 🌲 Kubernetes上で動作する分散近似近傍密ベクトル検索エンジン 🌲 Cloud-Nativeなアーキテクチャ 🌲 数十億規模の特徴ベクトルデータから検索可能な水平スケーリング性 🌲 Go & C++を用いて実装 🌲 多言語サポート(Go, Java, Clojure, Node.js, Python) 🌲 様々な面で高いカスタマイズ性 🌲 https://vald.vdaas.org/ Vdaas / Vald 15

16.

Valdについて ~ Kubernetesの力を利用して膨大なIndexを管理できる ~ Vdaas / Vald 16

17.

Valdについて ~ インデックス管理機能 ~ 🌲 🌲 🌲 バックアップ – Insert/Update/Upsert時外部DBに変更をバックアップ – Index作成時にVolumeがある場合のみ書き出しS3にアップロード リカバリ – 外部DBからのリカバリ機能 – S3からの起動時リカバリ機能 ライブ更新 – 🌲 サービス停止する事なくインデックスを更新 レプリケーション – 複数Podに一定量の重複インデックスを保存 Vdaas / Vald 17

18.

Valdについて ~ フィルター機能 ~ 🌲 Egress – 近似近傍検索なので本当に正確で無ければいけない場 合フィルタリングをする – 例: レディースTシャツ画像で検索した場合に メンズのTシャツが出てしまうなど 🌲 Ingress – 任意のデータをVectorに変換する 層をフィルターとして利用し Tensorflowなどと連携する Vdaas / Vald 18

19.

Valdについて ~ コンポーネント ~ 🌲 代表的なコンポーネント – LB Gateway – – K8S API Agent – – ロードバランシング 近似近傍検索コアエンジン Discoverer – Kubernetes APIからの情報を元に サービスディスカバリを行う Vdaas / Vald 19

20.

Valdについて ~ Kubernetes Ready ~ 🌲 Kubernetesと親和性の高い設計 – – Helmベースでのデプロイ – Helm Operator – 本日13:40~14:15 Track1のセッションにて解説 YAMLベースの設定 – – gRPC Buffer Sizeなども設定変更可能 controller-runtimeを利用している Vdaas / Vald 20

21.

controller-runtimeについて Vdaas / Vald 21

22.

controller-runtimeについて 🌲 KubernetesCRD/APIの両方を操作する コントローラを構築するためのライブラリ 🌲 Reconcilerを実装しやすい 🌲 AdmissionWebHookなども実装できる 🌲 Go言語製 🌲 最新版はv0.6.0 🌲 KubebuilderやOperator SDKで利用されている Vdaas / Vald 22

23.

controller-runtimeについて ~ しくみ ~ Event Handler Controller Manager Event Handler K8S API Reconciler Reconciler Controller Cache Event Handler Reconciler Controller controller-runtime Vdaas / Vald 23

24.
[beta]
controller-runtimeについて ~ 使い方 (Controller Manager編) ~
import (
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/manager"
)
func NewManager() (manager.Manager, error) {
cfg, err := config.GetConfig() // Kubernetes API Serverと通信するための設定を取得
if err != nil {
return nil, err
}
return manager.New( // Controller Managerを生成
cfg,
manager.Options{
Scheme:
runtime.NewScheme(),
LeaderElection: true, // Leader Electionの有効無効を設定する
},
)
}

Vdaas / Vald

24

25.
[beta]
controller-runtimeについて ~ 使い方 (Controller Manager編) ~
import (
"context"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/manager"
)
type Reconciler struct {
mgr manager.Manage
}
func (r *Reconciler) Reconcile(req reconcile.Request) (res reconcile.Result, err error) {
client := r.mgr.GetClient() // ManagerよりKubernetes API Clientを取得
ps := &corev1.PodList{}
err =client.List(context.TODO(), ps) // Kubernetes API Clientを用いてPodListを取得
if err != nil {
return nil, err
}
// Do Something
}

Vdaas / Vald

25

26.
[beta]
controller-runtimeについて ~ 使い方 (Builder & 実行編) ~
import (
"context"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/manager"
)
func Run(ctx context.Context, mgr manager.Manager) error {
_, err := builder.ControllerManagedBy(mgr).
// Controller (Reconciler) をManagerに登録
Named("PodList Controller").
// Controllerの名前を設定
For(new(corev1.Pod).
// Event監視対象のリソースを設定
Build(&Reconciler{mgr})
// Reconcilerを登録
if err != nil {
return err
}
return mgr.Start(ctx.Done())
// Managerを実行
}

Vdaas / Vald

26

27.
[beta]
controller-runtimeについて ~ 使い方 (mainの例) ~
import (
"context"
)
func main() {
mgr, err := NewManager()
if err != nil {
log.Fatal(err)
}
err = Run(context.TODO(), mgr)
if err != nil {
log.Fatal(err)
}
}

Vdaas / Vald

27

28.

controller-runtimeの応用例 Vdaas / Vald 28

29.
[beta]
controller-runtimeの応用 ~ controller-runtimeの課題 ~
🌲

controller-runtimeではReconcileの中で使うcontextをどうするか
–

ひとまずcontext.TODOかcontext.Backgroundをセットしている例が多い

–

内部で外部APIなどを叩く場合適切なキャンセレーションができない

–

しかしGo言語ではstructフィールド(Reconciler struct)に
contextを持つのは推奨されていない (https://pkg.go.dev/context?tab=doc)

–

func (r *Reconciler) Reconcile(req reconcile.Request) (res reconcile.Result, err error) {
// reconcile.Requestにはcontextは含まれていない
client := r.mgr.GetClient()
ps := &corev1.PodList{}
err =client.List(context.TODO(), ps) // 仕方なくcontext.TODO()にする → コレをなんとかしたい
if err != nil {
return nil, err
}
}

Vdaas / Vald

29

30.

controller-runtimeの応用 ~ Valdにおける解決策 ~ 🌲 Controllerをコンストラクトメソッドを用いてcontextをReconcile structに伝搬させる 🌲 結果的にReconcile structフィールドにcontext.Contextを保持してしまっている – 解決策を模索中 (わかる方、教えてください) func NewReconciler(ctx context.Context, mgr manager.Manager) reconcile.Reconciler { return &Reconciler{ ctx: ctx, mgr: mgr, } } func (r *Reconciler) Reconcile(req reconcile.Request) (res reconcile.Result, err error) { // reconcile.Requestにはcontextは含まれていない client := r.mgr.GetClient() ps := &corev1.PodList{} err =client.List(r.ctx, ps) // structフィールドのcontextを利用する } Vdaas / Vald 30

31.

controller-runtimeの応用 ~ Valdにおける利用 ~ 🌲 Valdでは下記理由からcontroller-runtimeのラッパーを実装している – Reconcile内部でルートからContextを伝播したい – GoにおけるFunctional Option Patternを利用しているので 初期化処理をラップしたい – 下記Interfaceを満たすものをControllerとしてmanagerに登録させる type ResourceController interface { GetName() string NewReconciler(context.Context, manager.Manager) reconcile.Reconciler For() runtime.Object Owns() runtime.Object Watches() (*source.Kind, handler.EventHandler) } Vdaas / Vald 31

32.

controller-runtimeの応用 ~ Valdにおける利用 ~ 🌲 Valdでは1つのManagerに4つのController(Reconciler)管理 – Pod Resource Controller – – Node Resource Controller – – NodeのIP,Status, CPU/Mem Capなどを取得 PodMetrics Resource Controller – – PodのIP,Status, CPU/Mem Capなどを取得 PodのCPU/Mem Usageなどを取得 NodeMetrics Resource Controller – Vdaas / Vald NodeのCPU/Mem Usageなどを取得 32

33.

controller-runtimeの応用 ~ Valdにおける利用 ~ Agent Discovererはcontroller-runtimeを用いて Pod/NodeのCPU/RAM Metrics, Status, IP情報を K8S API rpc Discover キャッシュに格納 GatewayはDiscoverから情報を高頻度(2~10rps)に取得 Pods IPリストをRAMとCPUの使用率が少ない順番にNodeのデータ を重視でソートして保存 この情報をもとにGatewayはIndexの管理を行う Vdaas / Vald 33

34.

controller-runtimeの応用 ~ Valdにおける利用 ~ K8S API Watch arch e S rpc rpc Search rpc Search rpc Insert rpc Insert Search Insert Pods rpc Se arc h Watch 情報を元にGatewayが適切なバランシングを行う Pods クライアントはシャードを意識する必要がない Vdaas / Vald 34

35.

controller-runtimeの応用 ~ AgentのIPのソート ~ Node A Node B 70% -1 RAM 24% -4 Vdaas / Vald Node C 50% -2 RAM 19% -5 40% -3 RAM 20% Other Pod RAM 26% RAM 20% RAM 10% Other Pod Other Pod Other Pod RAM 20% RAM 10% RAM 10% 35

36.

controller-runtimeの応用 ~ AgentのIPのソート ~ 3 2 Node A 1 Node B 70% -1 RAM 24% -4 Vdaas / Vald Node C 50% -2 RAM 19% -5 40% -3 RAM 20% Other Pod RAM 26% RAM 20% RAM 10% Other Pod Other Pod Other Pod RAM 20% RAM 10% RAM 10% 36

37.

controller-runtimeの応用 ~ AgentのIPのソート ~ 3 2 Node A 1 Node B 70% 3 -1 RAM 24% -4 Vdaas / Vald Node C 50% 2 -2 RAM 19% -5 40% 1 -3 RAM 20% Other Pod RAM 26% RAM 20% RAM 10% Other Pod Other Pod Other Pod RAM 20% RAM 10% RAM 10% 37

38.

controller-runtimeの応用 ~ AgentのIPのソート ~ 3 2 Node A 1 Node B 70% 3 -1 RAM 24% -4 RAM 26% Other Pod Node C 50% 2 3 -2 RAM 19% -5 RAM 20% 40% 1 -3 RAM 20% Other Pod RAM 10% Other Pod Other Pod Index Replicaを考慮すると場合に同じ NodeにIndexが偏ってしまう RAM 20% mem 10% mem 10% Vdaas / Vald 38

39.

controller-runtimeの応用 ~ AgentのIPのソート ~ 3 2 Node A 1 Node B 70% 3 5 Vdaas / Vald -1 RAM 24% -4 RAM 26% Node C 50% 2 4 -2 RAM 19% -5 40% 1 -3 RAM 20% Other Pod RAM 20% RAM 10% Other Pod Other Pod Other Pod RAM 20% RAM 10% RAM 10% 39

40.

controller-runtimeの応用 ~ AgentのIPのソート ~ Node A Node B Sorted Agents Node C -3 70% -1 RAM 24% 50% -2 RAM 19% 40% -3 RAM 20% RAM 20% -2 RAM 19% -1 -4 RAM 26% -5 RAM 20% Other Pod RAM 24% RAM 10% -5 RAM 20% Other Pod Other Pod Other Pod RAM 20% RAM 10% RAM 10% -4 RAM 26% Vdaas / Vald 40

41.

controller-runtimeの応用 ~ Agentに対するInsert ~ Sorted Agents -3 RAM 20% K8S API -2 rpc Discover RAM 19% rpc Insert -1 RAM 24% Pods rpc Insert (Replica 3) -5 RAM 20% -4 RAM 26% Vdaas / Vald 41

42.

controller-runtimeの応用 ~ Agent Indexメモリ収容率の推移 Before ~ Podメモリが偏りすぎて Killされてしまっている バランシングされない Pod がある Vdaas / Vald 42

43.

controller-runtimeの応用 ~ Agent Indexメモリ収容率の推移 After ~ Vdaas / Vald 43

44.

controller-runtimeの応用 ~ Valdにおける利用② ~ 🌲 Valdのバックアップの機構はcontroller-runtimeを用いてPodの状態を監視し落ちたPodの Indexデータを復旧命令を復旧専用のコンポーネントに送信する – Reconcilerが複数ある場合に同時に複数回復旧命令が送られてしまう バックアップが二重に K8S API Pods Vdaas / Vald Pods 44

45.

controller-runtimeの応用 ~ Valdにおける利用② ~ 🌲 Valdのバックアップの機構はcontroller-runtimeを用いてPodの状態を監視し落ちたPodの Indexデータを復旧命令を復旧専用のコンポーネントに送信する – 複数のControllerがある場合に同時に複数回復旧命令が送られてしまう – LeaderElectionを利用すればいい r leade K8S API Pods Vdaas / Vald Pods 45

46.

controller-runtimeの応用 ~ Valdにおける利用② ~ 🌲 manager.OptionsのLeaderElectionのパラメータをtrueにすることで有効に出来る c.mgr, err = manager.New( cfg, manager.Options{ Scheme: runtime.NewScheme(), LeaderElection: c.leaderElection, // ここをtrueにする MetricsBindAddress: c.merticsAddr, }, ) Vdaas / Vald 46

47.

Valdの今後について Vdaas / Vald 47

48.

Valdの今後について ~ インデックス管理機能 ~ 🌲 独自のAgent用スケジューラーを開発予定 – 🌲 Valdのデプロイ用のOperatorを開発予定 – 🌲 AgentはOn-Memoryにデータを持つと言う特性上スケールが難しい Helm Operatorでは細かい事は出来ないため Configmapの一部共通設定などをCustomResourceとして 各コンポーネントからWatchするなどの設計の検討 – 🌲 Valdの検索エンジンのパラメーターを負荷に応じて動的に変更する BERT, ArcFaceなどの深層学習モデルと組み合わせて 多様な類似検索エンジンとしていく Vdaas / Vald 48

49.

まとめ Vdaas / Vald 49

50.

まとめ 🌲 Valdではcontroller-runtimeを用いてKubernetesをデプロイ環境としてだけではなく 分散ベクトルインデックスを管理する情報源として利用している。 🌲 controller-runtimeを用いればより柔軟なアプリケーションの設計が可能となる。 Vdaas / Vald 50

51.

We are Hiring! Vdaas / Vald 51

52.

参考 🌲 Vald (https://vald.vdaas.org/) – 🌲 NGT (https://github.com/yahoojapan/NGT) – 🌲 controller-runtime wrapper (https://github.com/vdaas/vald/tree/master/internal/k8s ) ANN-Benchmark (https://github.com/erikbern/ann-benchmarks) controller-runtime (https://github.com/kubernetes-sigs/controller-runtime) Vdaas / Vald 52