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

リクルートのデータ活用を加速させるセルフサービス型 A/B テスト基盤の設計と実装 / MLOps_kato

Recruit
December 06, 2021

リクルートのデータ活用を加速させるセルフサービス型 A/B テスト基盤の設計と実装 / MLOps_kato

2021/12/08_第14回 MLOps勉強会での加藤の講演資料になります

Recruit

December 06, 2021
Tweet

More Decks by Recruit

Other Decks in Technology

Transcript

  1. • 自己紹介・会社紹介 • データ施策の業務フロー課題 • データサイエンスチーム目線 ◦ 全体像 ◦ 各機能紹介

    ◦ A/B テストの設定方法 • 内部実装編 ◦ アーキテクチャ ◦ 各機能の内部実装 ◦ AB テスト機能の実装詳細 • 課題・まとめ 目次 3
  2. • 2018/04 現、株式会社リクルート入社 ◦ データ分析によるサービス改善 ◦ データ活用施策推進 ◦ 社内データプロダクトの開発運用兼PdM •

    興味関心:k8s, Go, 開発生産性改善 ◦ CKA/CKAD ◦ techblog: Four Keys 〜自分たちの開発レベルを定 量化してイケてる DevOps チームになろう〜 • 使用キーボード: moonlander 加藤 広大 Twitter: @ko_da_k 4
  3. 6 所属組織について 事業領域 A 事業領域 B 事業領域 C データ推進室 事業領域

    A データソリューション 事業領域 B データソリューション 事業領域 C データソリューション データエンジニアリング・データマネジメント
  4. • 自己紹介・会社紹介 • データ施策の業務フロー課題 • データサイエンスチーム目線 ◦ 全体像 ◦ 各機能紹介

    ◦ A/B テストの設定方法 • 内部実装編 ◦ アーキテクチャ ◦ 各機能の内部実装 ◦ AB テスト機能の実装詳細 • 課題・まとめ 目次 7
  5. 9 Data Science Team Data Engineer Team Service Engineer Team

    学習/予測コード納品 予測結果ファイル連携 Data Science Team Data Engineer Team Service Engineer Team
  6. 13 Data Science Team Data Engineer Team Service Engineer Team

    学習/予測コード納品 予測結果ファイル連携 Data Science Team Data Engineer Team Service Engineer Team
  7. 14 Data Science Team Data Engineer Team Service Engineer Team

    学習/予測コード納品 予測結果ファイル連携 Data Science Team Data Engineer Team Service Engineer Team • エンジニアのリソース上限が施 策ごとの開発ボトルネック • プロダクトの機能開発・ 自動化・信頼性向上に 開発リソースを十分に割けない • エンジニアのリソース上限が 施策ごとの開発ボトルネック • プロダクトの機能開発・ 自動化・信頼性向上に 開発リソースを十分に割けない
  8. 15 結論:セルフサービス型のデータプロダクトを提供 Data Science Team Data Engineer Team Service Engineer

    Team Push/PR CI/CD Job API CI/CD ※ Job 基盤については以下の CNDT2021 の資料を御覧ください https://event.cloudnativedays.jp/cndt2021/talks/1212 Model Output (ファイル連携パターンも対応)
  9. • 自己紹介・会社紹介 • データ施策の業務フロー課題 • データサイエンスチーム目線 ◦ 全体像 ◦ 各機能紹介

    ◦ A/B テストの設定方法 • 内部実装編 ◦ アーキテクチャ ◦ 各機能の内部実装 ◦ AB テスト機能の実装詳細 • 課題・まとめ 目次 16
  10. 18 データサイエンスチームから見た業務フロー コード群と 設定ファイル Data Science Team Route mlops-community.example.com KeyValue

    API Prediction API Functions . . . . . . • チーム専用の GitHub Repository で code を管理 ◦ CI/CD 整備済みなのでデプロイやテストも自動化 • Model の API 連携方法は 3 つ (後述) • API の Host は Route という機能で自動生成(後述) Team 専用 Repo
  11. 19 モデル連携の方法 コード群と 設定ファイル Data Science Team Route KeyValue API

    Prediction API Functions . . . . . . • 事前のモデル出力結果を連携する KeyValue API ◦ ユースケース:類似アイテムレコメンド • オンライン推論を行う Prediction API ◦ ユースケース:閲覧状況に基づくリアルタイムレコメンド • 複数 API 外部サービス連携を行う Functions ◦ ユースケース: Team 専用 Repo mlops-community.example.com
  12. 1. BigQuery で key/value のカラムを 返す Queryをそのまま API に連携 2.

    Pandas DataFrame をそのまま API に連携するライブラリの提供 20 KeyValue API (UX)
  13. • Request/Response の型定義と predict method を実装すれば オンラインサービングが可能 • 学習済みモデルもまとめて Image

    に固める • API のデプロイは設定を書いた yaml を push するだけ 21 Prediction API (UX) class Petal(BaseModel): length: float width: float class RequestData(BaseModel): sepal_length: float sepal_width: float petal: Petal class ResponseData(BaseModel): predicted: int label: str class Predictor: def __init__(self): with (SRC_DIR / "my-model.pkl").open("rb") as f: self.model = pickle.load(f) def predict(self, data: RequestData, req: Request) -> ResponseData: # リクエストデータを predict に渡すために変換します features = [[data.sepal_length, data.sepal_width, data.petal.length, data.petal.width,]] # レスポンスデータを組み立てます results = self.model.predict(features) label = "Iris-Setosa" # dummy return ResponseData(predicted=results[0], label=label)
  14. • 複数の KeyValue API や Prediction API を呼び出したり外部サービス 連携などを任意の Handler

    として記述できる。 • Prediction API と同じく、任意の Handler 処理を書いたコードを Push 22 Functions (UX) ユースケース KeyValue API ① ユーザー特徴量 API KeyValue API ② アイテム特徴量 API Prediction API ① マッチングスコア予測 API Functions 外部サービス
  15. mlops-community.example.com 23 A/B テストの設定方法 コード群と 設定ファイル Data Science Team Route

    KeyValue API Prediction API Functions . . . . . . • チーム専用の GitHub Repository で code を管理 ◦ CI/CD 整備済みなのでデプロイやテストも自動化 • Model の API 連携方法は 3 つ (後述) • API の Host は Route という機能で自動生成(後述) Team 専用 Repo
  16. 24 Route (UX) apiVersion: api.config.knile.jp/v1alpha1 kind: Route metadata: name: mlops-community-sample

    spec: backend: # default の設定 name: "mlops-community-sample1" kind: KeyValue test: term: since: "2021-12-08T00:00:00+09:00" # 開始日時 until: "2021-12-31T00:00:00+09:00" # 終了日時 backends: # AB テスト用のバックエンド - name: "mlops-community-sample2" kind: Function slot: A # AB テストのスロット名 percentage: 50 # 50 % を A に割り振り allowedIPs: - 192.168.10.1/32 • 左のような yaml を push • name に応じて subdomain を 自動設定 • KeyValue/Prediction/Functions の Backend に好きな割り振り
  17. 25 Route の存在意義 Service Engineer Team model1.example.com model2.example.com • API

    の Interface は同じなのに Service Engineer Team は 呼び出し先変更をする 開発が必要 • 真に Data Science Team 主導で A/B テストをするなら、最初に API の仕様を決めてしまい モデルのアルゴリズムや パラメータ変更にサービス担当の エンジニアの工数を使わないのが 理想 Data Science Team
  18. 26 Route の存在意義 mlops-community-model1 mlops-community-model2 Route mlops-community.example..com Service Engineer Team

    Data Science Team • 呼び出し先固定で中のロジックを変えることで Service Engineer Team の工数はゼロ →Blue/Green Deployment や Canary Release の考え方を適用 • Data Science Team が自由にリリースを調整できるような設計
  19. • 自己紹介・会社紹介 • データ施策の業務フロー課題 • データサイエンスチーム目線 ◦ 全体像 ◦ 各機能紹介

    ◦ A/B テストの設定方法 • 内部実装編 ◦ アーキテクチャ ◦ 各機能の内部実装 ◦ AB テスト機能の実装詳細 • 課題・まとめ 目次 27
  20. 29 Kubernetes cluster istio-system namespace Cloud Load Balancing istio-ingressgateway Pod

    Team A Team B Istio Network Endpoint Group (NEG) knile-system namespace ※ knile は本資料で紹介している社内プラットフォーム名称です api-gateway Pod Team A namespace Team B namespace KeyValue 1 CustomResource KeyValue 2 CustomResource Functions 1 CustomResource KeyValue 1 CustomResource Prediction 1 CustomResource Route 1 CustomResource Route 1 CustomResource Logging Sink BigQuery Cloud Logging Console Team A Repo Team B Repo Team A Dashboard Team B Dashboard
  21. 30 Kubernetes cluster istio-system namespace Cloud Load Balancing istio-ingressgateway Pod

    Team A Team B Istio Network Endpoint Group (NEG) knile-system namespace ※ knile は本資料で紹介している社内プラットフォーム名称です api-gateway Pod Team A namespace Team B namespace KeyValue 1 CustomResource KeyValue 2 CustomResource Functions 1 CustomResource KeyValue 1 CustomResource Prediction 1 CustomResource Route 1 CustomResource Route 1 CustomResource Logging Sink BigQuery Cloud Logging Console Team A Repo Team B Repo Team A Dashboard Team B Dashboard
  22. 31 リポジトリ+インフラ環境の自動発行 Data Engineer Team Team A Resources Kubernetes Team

    A BigQuery Team A Cloud Storage Team B Resources Kubernetes Team B BigQuery Team B Cloud Storage • チームごとに CI/CD を整備した状態の専用 Repo や GCP/k8s Resource、Datadog Dashboard を提供 • これらの生成は Data Engineer Team がコードで集約管理 Infra Repo
  23. 32 Kubernetes cluster istio-system namespace Cloud Load Balancing istio-ingressgateway Pod

    Team A Team B Istio Network Endpoint Group (NEG) knile-system namespace ※ knile は本資料で紹介している社内プラットフォーム名称です api-gateway Pod Team A namespace Team B namespace KeyValue 1 CustomResource KeyValue 2 CustomResource Functions 1 CustomResource KeyValue 1 CustomResource Prediction 1 CustomResource Route 1 CustomResource Route 1 CustomResource Logging Sink BigQuery Cloud Logging Console Team A Repo Team B Repo Team A Dashboard Team B Dashboard
  24. データサイエンス チーム作成 Job • 演算結果を事前格納し API として提供 • キーの全件更新や差分更新も提供 •

    Pandas Dataframe や BigQuery の結果をそのまま API に連携できる ライブラリを提供 33 KeyValue API (内部実装) Cloud Bigtable Cloud Storage Pub/Sub BigQuery Kubernetes Engine data-loader (内製) Kubernetes Engine KeyValue API (内製) Write Read
  25. データサイエンス チーム作成 Job • 基盤側が提供するライブラリやインタフェースに従って、 モデルの Predict や Load 処理を実装(コードは

    Python) • GCR に API として起動する Image を Push (API 実装は FastAPI) • GitHub に設定ファイルを Push すると、該当 Model の API が起動 34 Prediction API (内部実装) Kubernetes Engine Prediction API Container Registry 基盤側で提供する インタフェースの実装 pull Push
  26. データサイエンス チーム作成 • 基盤側が提供するインタフェースに従って、 任意の Handler を実装 • GCR に

    API として起動する Image を Push • GitHub に設定ファイルを Push すると、該当の API が起動 35 Functions (内部実装) Kubernetes Engine Functions Container Registry 任意の Handler 実装 pull Push
  27. • 個別 API は社内の利用者環境からのみアクセス可能な ドメインを付与→開発時のテストやデバッグを可能に • Route は利用者記載の A/B テスト設定をもとに

    Service Engineer Team が呼び出せる VirtualService を発行 (詳細は後述) 36 Custom Controller によるリソース制御 KeyValue/Prediction/ Function KeyValue API Storage Cloud Bigtable Private Only host VirtualService Route A/B Test Settings VirtualService
  28. • 自己紹介・会社紹介 • データ施策の業務フロー課題 • データサイエンスチーム目線 ◦ 全体像 ◦ 各機能紹介

    ◦ A/B テストの設定方法 • 内部実装編 ◦ アーキテクチャ ◦ 各機能の内部実装 ◦ AB テスト機能の実装詳細 • 課題・まとめ 目次 37
  29. 38 Kubernetes cluster istio-system namespace Cloud Load Balancing istio-ingressgateway Pod

    Team A Team B Istio Network Endpoint Group (NEG) knile-system namespace ※ knile は本資料で紹介している社内プラットフォーム名称です api-gateway Pod Team A namespace Team B namespace KeyValue 1 CustomResource KeyValue 2 CustomResource Functions 1 CustomResource KeyValue 1 CustomResource Prediction 1 CustomResource Route 1 CustomResource Route 1 CustomResource Logging Sink BigQuery Cloud Logging Console Team A Repo Team B Repo Team A Dashboard Team B Dashboard
  30. • Istio の機能だけではカバーできないユースケース (後述) があるため 独自に Gateway を実装 39 A/B

    テストのルーティング設定 ※ 過去のテックブログもご覧ください  Istio で実現する A/B テスト基盤 istio-ingressgateway Pod api-gateway Pod Host ごとに異なる A/B 情報を Header に詰める Header の情報をもとに ルーティングを決める
  31. 40 apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: mlops-community-sample ...省略 spec:

    ...省略 hosts: - "mlops-community-sample.example.com" http: name: mlops-community-sample-rt route: - destination: host: api-gateway.knile-system.svc.cluster.local headers: request: set: x-knile-router-route-name: mlops-community-sample x-knile-router-testgroup-members: ‘[{“routeName”: “mlops-community-sample”, ...省略 }]’ x-knile-router-testgroup-name: autogen.mlops-community.team-a ...省略 apiVersion: api.config.knile.jp/v1alpha1 kind: Route metadata: name: mlops-community-sample spec: backend: # default の設定 name: "mlops-community-sample1" kind: KeyValue test: term: since: "2021-12-08T00:00:00+09:00" # 開始日時 until: "2021-12-31T00:00:00+09:00" # 終了日時 backends: # AB テスト用のバックエンド - name: "mlops-community-sample2" kind: Function slot: A # AB テストの識別子 percentage: 50 allowedIPs: - 192.168.0.1/32 ユーザ記述 Sample 変換後 VirtualService 抜粋
  32. 42 割り振り+ユーザ固定の両立ができなかった mlops-community-sample1 mlops-community-sample2 80 % 20 % • Istio

    の Weight-based Routing と Soft Session Affinity の同時利用かつ ユーザの割り振りの固定化ができなかった(基盤構築の 2019/12 時点) header: {“user-id”: “userA”} ※ 以下のテックブログもご覧ください   https://engineer.recruit-lifestyle.co.jp/techblog/2019-12-01-istio/
  33. 43 複数 API でのトラフィック制御 model-1 model-2 Route alpha-api.example.com model-3 model-4

    Route beta-api.example.com alpha-api.model-1 × beta-api.model-3 alpha-api.model-2 × beta-api.model-4 0 % 50 % 100 % 例:alpha-api の model-1 を引いたら beta-api の model-3 を強制したい
  34. • 自己紹介・会社紹介 • データ施策の業務フロー課題 • セルフサービス型 A/B テスト基盤の紹介 ◦ アーキテクチャ

    ◦ 機能紹介(UX / 内部実装) ◦ AB テスト機能の実装詳細 • 課題・まとめ 目次 44
  35. • チームごとに独立した リポジトリやリソース を発行 • 事前演算した結果を返す KeyValue API • オンライン推論の

    Prediction API • 複数 API を束ねる Functions • トラフィックルーティングを設定する Route • Istio の VirtualService で Host ごとに A/B テストの 設定情報を Header に詰めるように設定 • Header を受け取った api-gateway (内製) でルーティングを決定 • 独自の api-gateway が必要な理由は以下の2点 ◦ ユーザ単位で固定した Backend への重み付けした割り振りの実現 ◦ 複数 API をまたいだトラフィック制御 45 まとめ
  36. • スキーマ駆動開発 ◦ openapi.yaml の自動生成による開発生産性向上 ◦ Data Science Team の人に

    openapi.yaml を書いてもらうのは 分析・モデリングに注力してほしいという本題から逸れてしまう • チーム・API ごとのアラート ◦ Datadog Dashboard の自動生成及び Data Science Team への 展開は実装済み→レイテンシ・RPS などはチームごとに確認可能 ◦ 一方、アラートに関しては基盤チームが一次調査を担当している ◦ API 個別のアラート(Handler の実装ミスなど)を Data Science Team が検知できるような運用設計を検討する 46 これから改善していくこと
  37. • ちょうどいいイラスト • Icons made by https://www.freepik.com from www.flaticon.com •

    Updated 9/2021 Google Cloud Official Icons and Solution Architectures • pandas - Python Data Analysis Library • Go's New Brand • The Python Logo • Kubernetes icons • icono-k8s-0.3 • https://www.datadoghq.com/ja/about/resources/ • The Python Logo アイコン・イラスト参照先 48