Slide 1

Slide 1 text

リクルートのデータ活用を加速させる セルフサービス型 A/B テスト基盤の 設計と実装 株式会社リクルート データ推進室 データプラットフォーム部 加藤 広大 1

Slide 2

Slide 2 text

※ 本資料のスコープ 本資料の A/B テストは Web サービスにおける 機械学習を始めとするレコメンドや 検索並び順最適化を行うサイト改善を指します 2

Slide 3

Slide 3 text

● 自己紹介・会社紹介 ● データ施策の業務フロー課題 ● データサイエンスチーム目線 ○ 全体像 ○ 各機能紹介 ○ A/B テストの設定方法 ● 内部実装編 ○ アーキテクチャ ○ 各機能の内部実装 ○ AB テスト機能の実装詳細 ● 課題・まとめ 目次 3

Slide 4

Slide 4 text

● 2018/04 現、株式会社リクルート入社 ○ データ分析によるサービス改善 ○ データ活用施策推進 ○ 社内データプロダクトの開発運用兼PdM ● 興味関心:k8s, Go, 開発生産性改善 ○ CKA/CKAD ○ techblog: Four Keys 〜自分たちの開発レベルを定 量化してイケてる DevOps チームになろう〜 ● 使用キーボード: moonlander 加藤 広大 Twitter: @ko_da_k 4

Slide 5

Slide 5 text

5 リクルートの事業について https://recruit-saiyo.jp/present/

Slide 6

Slide 6 text

6 所属組織について 事業領域 A 事業領域 B 事業領域 C データ推進室 事業領域 A データソリューション 事業領域 B データソリューション 事業領域 C データソリューション データエンジニアリング・データマネジメント

Slide 7

Slide 7 text

● 自己紹介・会社紹介 ● データ施策の業務フロー課題 ● データサイエンスチーム目線 ○ 全体像 ○ 各機能紹介 ○ A/B テストの設定方法 ● 内部実装編 ○ アーキテクチャ ○ 各機能の内部実装 ○ AB テスト機能の実装詳細 ● 課題・まとめ 目次 7

Slide 8

Slide 8 text

8 Step1: あなたはレコメンドモデル開発者です ユーザへおすすめアイテムを 表示するとします Q. どのようにレコメンドモデルを 連携していますか?

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

10 Step2: 先程のモデルを改良しました アルゴリズムを変更したモデルを 反映したいです Q. どのようにレコメンドモデルを 「更新」していますか?

Slide 11

Slide 11 text

11 Step3: 複数モデルの A/B テストをしたいです 複数モデルの比較を 行いたいです Q. どのようにレコメンドモデルを 「比較」していますか?

Slide 12

Slide 12 text

本日のテーマ データサイエンスチーム主導で モデルの更新や A/B テストを行える セルフサービス型のデータ基盤基盤の 設計と実装 12

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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 (ファイル連携パターンも対応)

Slide 16

Slide 16 text

● 自己紹介・会社紹介 ● データ施策の業務フロー課題 ● データサイエンスチーム目線 ○ 全体像 ○ 各機能紹介 ○ A/B テストの設定方法 ● 内部実装編 ○ アーキテクチャ ○ 各機能の内部実装 ○ AB テスト機能の実装詳細 ● 課題・まとめ 目次 16

Slide 17

Slide 17 text

データサイエンスチーム目線 17

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

19 モデル連携の方法 コード群と 設定ファイル Data Science Team Route KeyValue API Prediction API Functions . . . . . . ● 事前のモデル出力結果を連携する KeyValue API ○ ユースケース:類似アイテムレコメンド ● オンライン推論を行う Prediction API ○ ユースケース:閲覧状況に基づくリアルタイムレコメンド ● 複数 API 外部サービス連携を行う Functions ○ ユースケース: Team 専用 Repo mlops-community.example.com

Slide 20

Slide 20 text

1. BigQuery で key/value のカラムを 返す Queryをそのまま API に連携 2. Pandas DataFrame をそのまま API に連携するライブラリの提供 20 KeyValue API (UX)

Slide 21

Slide 21 text

● 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)

Slide 22

Slide 22 text

● 複数の KeyValue API や Prediction API を呼び出したり外部サービス 連携などを任意の Handler として記述できる。 ● Prediction API と同じく、任意の Handler 処理を書いたコードを Push 22 Functions (UX) ユースケース KeyValue API ① ユーザー特徴量 API KeyValue API ② アイテム特徴量 API Prediction API ① マッチングスコア予測 API Functions 外部サービス

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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 に好きな割り振り

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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 が自由にリリースを調整できるような設計

Slide 27

Slide 27 text

● 自己紹介・会社紹介 ● データ施策の業務フロー課題 ● データサイエンスチーム目線 ○ 全体像 ○ 各機能紹介 ○ A/B テストの設定方法 ● 内部実装編 ○ アーキテクチャ ○ 各機能の内部実装 ○ AB テスト機能の実装詳細 ● 課題・まとめ 目次 27

Slide 28

Slide 28 text

内部実装編 28

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

データサイエンス チーム作成 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

Slide 34

Slide 34 text

データサイエンス チーム作成 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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

● 個別 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

Slide 37

Slide 37 text

● 自己紹介・会社紹介 ● データ施策の業務フロー課題 ● データサイエンスチーム目線 ○ 全体像 ○ 各機能紹介 ○ A/B テストの設定方法 ● 内部実装編 ○ アーキテクチャ ○ 各機能の内部実装 ○ AB テスト機能の実装詳細 ● 課題・まとめ 目次 37

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

● Istio の機能だけではカバーできないユースケース (後述) があるため 独自に Gateway を実装 39 A/B テストのルーティング設定 ※ 過去のテックブログもご覧ください  Istio で実現する A/B テスト基盤 istio-ingressgateway Pod api-gateway Pod Host ごとに異なる A/B 情報を Header に詰める Header の情報をもとに ルーティングを決める

Slide 40

Slide 40 text

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 抜粋

Slide 41

Slide 41 text

1. 特定のユーザが常に同じ Backend を引き続けることを 強制できなかったため 2. 複数 API でのトラフィック制御ができなかったため 41 なぜ Istio のみでは A/B テストを実現できないか

Slide 42

Slide 42 text

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/

Slide 43

Slide 43 text

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 を強制したい

Slide 44

Slide 44 text

● 自己紹介・会社紹介 ● データ施策の業務フロー課題 ● セルフサービス型 A/B テスト基盤の紹介 ○ アーキテクチャ ○ 機能紹介(UX / 内部実装) ○ AB テスト機能の実装詳細 ● 課題・まとめ 目次 44

Slide 45

Slide 45 text

● チームごとに独立した リポジトリやリソース を発行 ● 事前演算した結果を返す KeyValue API ● オンライン推論の Prediction API ● 複数 API を束ねる Functions ● トラフィックルーティングを設定する Route ● Istio の VirtualService で Host ごとに A/B テストの 設定情報を Header に詰めるように設定 ● Header を受け取った api-gateway (内製) でルーティングを決定 ● 独自の api-gateway が必要な理由は以下の2点 ○ ユーザ単位で固定した Backend への重み付けした割り振りの実現 ○ 複数 API をまたいだトラフィック制御 45 まとめ

Slide 46

Slide 46 text

● スキーマ駆動開発 ○ openapi.yaml の自動生成による開発生産性向上 ○ Data Science Team の人に openapi.yaml を書いてもらうのは 分析・モデリングに注力してほしいという本題から逸れてしまう ● チーム・API ごとのアラート ○ Datadog Dashboard の自動生成及び Data Science Team への 展開は実装済み→レイテンシ・RPS などはチームごとに確認可能 ○ 一方、アラートに関しては基盤チームが一次調査を担当している ○ API 個別のアラート(Handler の実装ミスなど)を Data Science Team が検知できるような運用設計を検討する 46 これから改善していくこと

Slide 47

Slide 47 text

● 採用情報 | 株式会社リクルート ● データプラットフォーム開発はじめ、様々な職種で 一緒に働く仲間を募集しております ● ご興味ありましたら上記ページや、加藤の Twitter 等に 気軽にご連絡いただければと思います。 47 さいごに

Slide 48

Slide 48 text

● ちょうどいいイラスト ● 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