Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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

分散密ベクトル探索エンジンである 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の事例について紹介します。

Yusuke Kato

June 13, 2020
Tweet

More Decks by Yusuke Kato

Other Decks in Technology

Transcript

  1. Vdaas / Vald The potential of Kubernetes as more than

    just an infrastructure to deploy KubeFest Tokyo 2020 Yusuke Kato/ kpango (Yahoo Japan Corporation)
  2. Vdaas / Vald kubectl -n vald get sa kpango -o

    yaml 2 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"
  3. Vdaas / Vald NGT (Neighborhood Graph and Tree)はYahoo! JAPAN研究所で開発 された世界トップレベル(ann-benchmarks)の

    高速高精度な近似近傍検索アルゴリズム メモリ上に全てのGraph and Tree構造のIndexを保持する サーバー実装としてNGTDがありREST / gRPC経由で ベクトルのCRUD処理を行うインターフェースを提供 ヤフーのベクトル検索について ~ NGTについて ~ 6
  4. Vdaas / Vald ヤフーのベクトル検索について ~ 現状の課題について ~ データが増え続ければメモリは増え続けて 減少する事はない –

    NGTサーバーはメモリ不足に 高価なハイスペックサーバ or シャーディングが必要に 8 icons from https://www.flaticon.com/authors/monkik
  5. Vdaas / Vald VM Cluster ヤフーのベクトル検索について ~ NGTのレガシーなシャーディング ~ 9

    Envoyを用いてPathベースでルーティング Search時は全ての検索結果を集計 /01/search /02/search /80/search search insert /02/insert VM /01-80/search /02/insert
  6. Vdaas / Vald ヤフーのベクトル検索について ~ NGTのレガシーなシャーディング ~ 10 1. RAM使用率に偏りが生じやすい。

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

    2. Indexの復旧管理が必要 3. VM変更はEnvoy再設定必須 4. PFクライアントのコードも要変更 /01/search /02/search /80/search VM Cluster search Insert /02/insert VM
  8. Vdaas / Vald バックアップ – Insert/Update/Upsert時外部DBに変更をバックアップ – Index作成時にVolumeがある場合のみ書き出しS3にアップロード リカバリ –

    外部DBからのリカバリ機能 – S3からの起動時リカバリ機能 ライブ更新 – サービス停止する事なくインデックスを更新 レプリケーション – 複数Podに一定量の重複インデックスを保存 Valdについて ~ インデックス管理機能 ~ 17
  9. Vdaas / Vald Egress – 近似近傍検索なので本当に正確で無ければいけない場 合フィルタリングをする – 例: レディースTシャツ画像で検索した場合に

    メンズのTシャツが出てしまうなど Ingress – 任意のデータをVectorに変換する 層をフィルターとして利用し Tensorflowなどと連携する Valdについて ~ フィルター機能 ~ 18
  10. Vdaas / Vald Valdについて ~ コンポーネント ~ 19 代表的なコンポーネント –

    LB Gateway – ロードバランシング – Agent – 近似近傍検索コアエンジン – Discoverer – Kubernetes APIからの情報を元に サービスディスカバリを行う K8S API
  11. Vdaas / Vald Valdについて ~ Kubernetes Ready ~ 20 Kubernetesと親和性の高い設計

    – Helmベースでのデプロイ – Helm Operator – 本日13:40~14:15 Track1のセッションにて解説 – YAMLベースの設定 – gRPC Buffer Sizeなども設定変更可能 – controller-runtimeを利用している
  12. Vdaas / Vald controller-runtimeについて ~ しくみ ~ 23 K8S API

    controller-runtime Manager Cache Controller Reconciler Event Handler Controller Reconciler Event Handler Controller Reconciler Event Handler
  13. Vdaas / Vald controller-runtimeについて ~ 使い方 (Controller Manager編) ~ 24

    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の有効無効を設定する }, ) }
  14. Vdaas / Vald controller-runtimeについて ~ 使い方 (Controller Manager編) ~ 25

    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 }
  15. Vdaas / Vald controller-runtimeについて ~ 使い方 (Builder & 実行編) ~

    26 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を実行 }
  16. Vdaas / Vald controller-runtimeについて ~ 使い方 (mainの例) ~ 27 import

    ( "context" ) func main() { mgr, err := NewManager() if err != nil { log.Fatal(err) } err = Run(context.TODO(), mgr) if err != nil { log.Fatal(err) } }
  17. Vdaas / Vald controller-runtimeではReconcileの中で使うcontextをどうするか – ひとまずcontext.TODOかcontext.Backgroundをセットしている例が多い – 内部で外部APIなどを叩く場合適切なキャンセレーションができない – しかしGo言語ではstructフィールド(Reconciler

    struct)に contextを持つのは推奨されていない (https://pkg.go.dev/context?tab=doc) – controller-runtimeの応用 ~ controller-runtimeの課題 ~ 29 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   } }
  18. Vdaas / Vald Controllerをコンストラクトメソッドを用いてcontextをReconcile structに伝搬させる 結果的にReconcile structフィールドにcontext.Contextを保持してしまっている – 解決策を模索中 (わかる方、教えてください)

    controller-runtimeの応用 ~ Valdにおける解決策 ~ 30 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を利用する }
  19. Vdaas / Vald Valdでは下記理由からcontroller-runtimeのラッパーを実装している – Reconcile内部でルートからContextを伝播したい – GoにおけるFunctional Option Patternを利用しているので

    初期化処理をラップしたい – 下記Interfaceを満たすものをControllerとしてmanagerに登録させる controller-runtimeの応用 ~ Valdにおける利用 ~ 31 type ResourceController interface { GetName() string NewReconciler(context.Context, manager.Manager) reconcile.Reconciler For() runtime.Object Owns() runtime.Object Watches() (*source.Kind, handler.EventHandler) }
  20. Vdaas / Vald Valdでは1つのManagerに4つのController(Reconciler)管理 – Pod Resource Controller – PodのIP,Status,

    CPU/Mem Capなどを取得 – Node Resource Controller – NodeのIP,Status, CPU/Mem Capなどを取得 – PodMetrics Resource Controller – PodのCPU/Mem Usageなどを取得 – NodeMetrics Resource Controller – NodeのCPU/Mem Usageなどを取得 controller-runtimeの応用 ~ Valdにおける利用 ~ 32
  21. Vdaas / Vald Pods controller-runtimeの応用 ~ Valdにおける利用 ~ 33 K8S

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

    ~ 34 情報を元にGatewayが適切なバランシングを行う クライアントはシャードを意識する必要がない Search Insert rpc Search rpc Insert rpc Search rpc Insert rpc Search rpc Search Watch Watch
  23. Vdaas / Vald Node A 70% RAM 24% -1 RAM

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

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

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

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

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

    RAM 20% -3 RAM 19% -2 RAM 24% -1 RAM 26% -4 RAM 20% -5 Node B 50% RAM 20% -5 RAM 19% -2 RAM 10% Other Pod Node A 70% RAM 24% -1 RAM 26% -4 RAM 20% Other Pod Node C 40% RAM 20% -3 RAM 10% Other Pod RAM 10% Other Pod
  29. Vdaas / Vald controller-runtimeの応用 ~ Agentに対するInsert ~ 41 Sorted Agents

    RAM 20% -3 RAM 19% -2 RAM 24% -1 RAM 26% -4 RAM 20% -5 K8S API Pods rpc Insert rpc Discover rpc Insert (Replica 3)
  30. Vdaas / Vald controller-runtimeの応用 ~ Agent Indexメモリ収容率の推移 Before ~ 42

    バランシングされない Pod がある Podメモリが偏りすぎて Killされてしまっている
  31. Vdaas / Vald manager.OptionsのLeaderElectionのパラメータをtrueにすることで有効に出来る controller-runtimeの応用 ~ Valdにおける利用② ~ 46 c.mgr,

    err = manager.New( cfg, manager.Options{ Scheme: runtime.NewScheme(), LeaderElection: c.leaderElection, // ここをtrueにする MetricsBindAddress: c.merticsAddr, }, )
  32. Vdaas / Vald 独自のAgent用スケジューラーを開発予定 – AgentはOn-Memoryにデータを持つと言う特性上スケールが難しい Valdのデプロイ用のOperatorを開発予定 – Helm Operatorでは細かい事は出来ないため

    Configmapの一部共通設定などをCustomResourceとして 各コンポーネントからWatchするなどの設計の検討 – Valdの検索エンジンのパラメーターを負荷に応じて動的に変更する BERT, ArcFaceなどの深層学習モデルと組み合わせて 多様な類似検索エンジンとしていく Valdの今後について ~ インデックス管理機能 ~ 48
  33. Vdaas / Vald Vald (https://vald.vdaas.org/) – controller-runtime wrapper (https://github.com/vdaas/vald/tree/master/internal/k8s )

    NGT (https://github.com/yahoojapan/NGT) – ANN-Benchmark (https://github.com/erikbern/ann-benchmarks) controller-runtime (https://github.com/kubernetes-sigs/controller-runtime) 参考 52