Slide 1

Slide 1 text

digdag 中心の生活 小口 力也 ゲーム・エンターテイメント事業部 Publish 統括部分析部データエンジニアリンググループ 株式会社ディー・エヌ・エー 1

Slide 2

Slide 2 text

小口 力也 Rikiya Oguchi 2017 1st half - 2nd half ● 電機メーカーに新卒入社 ● IT 部門で社内システムの企画・開発に従事 2018 1st half - ● DeNA に JOIN ○ BQ 警察(コスト最適化) ○ ゲーム分析の ETL 設計・開発 ○ データエンジニア組織の立ち上げ ○ オープンデータの収集 ○ ML Ops ● 副業 ○ スポットバイトのマッチングアプリ 「Spotmate」の分析基盤の立ち上げ 自己紹介 2

Slide 3

Slide 3 text

2011 - 2015 ● 全社横断組織としてデータ分析組織が誕生 ● 様々な事業の分析を担当 2016 - 2018 ● ゲーム事業の分析組織が独立 ● 他の事業部にもそれぞれ分析担当が所属 2019 - ● 分析のエンジニア機能に特化した Gr として データエンジニアリング Gr が2月に発足 ● ゲーム以外の横断分析組織として分析推進部 も発足 DeNA分析部の紹介 3 ゲーム スポーツ オート モーティブ ヘルスケア エンターテイ ンメント

Slide 4

Slide 4 text

役割 ● ゲーム事業における意思決定支援 ○ ゲーム内外の施策の振り返り ○ 事業戦略立案サポート          メンバー ● データエンジニア(6名): 分析の効率化・高度化 ● データアナリスト(22名): 担当ゲームの意思決定支援 ● データサイエンティスト(2名): 高度な分析手法の探求 ● ゲームメカニクスのデザイナー(8名): ゲーム内の UX・経済設計 DeNA分析部の紹介 4

Slide 5

Slide 5 text

事業系 ● アナリストの意思決定支援のサポート ● 新規技術の獲得(Looker の PoC など) ● クラウド移行(全社戦略)     保守系 ● リファクタリング ● 運用設計・手順化 改善系 ● ML Ops ● コスト最適化(BQ 警察) ○ 【参考】Google Cloud Next Tokyo 2019 岩尾 一優/エルアズハリ ムラド 「BigQuery を使い倒せ! DeNA データエンジニアの取り組み事例」 https://cloud.withgoogle.com/next/tokyo/sessions?session=D2-2-S09 データエンジニアの役割 5

Slide 6

Slide 6 text

本日お話しすること 6 1 2 データ分析組織のエンジニアリングで辛かった話 digdag で幸せを取り戻した話

Slide 7

Slide 7 text

7 ところで

Slide 8

Slide 8 text

8

Slide 9

Slide 9 text

9

Slide 10

Slide 10 text

10

Slide 11

Slide 11 text

11

Slide 12

Slide 12 text

12

Slide 13

Slide 13 text

13

Slide 14

Slide 14 text

14

Slide 15

Slide 15 text

15

Slide 16

Slide 16 text

16 1 データ分析組織のエンジニアリングで辛かった話

Slide 17

Slide 17 text

辛かった話 17

Slide 18

Slide 18 text

その前に 18

Slide 19

Slide 19 text

簡単にDeNAゲーム事業部の分析基盤をご説明します 19

Slide 20

Slide 20 text

Medjed (内製バルクロードツール) ゲーム事業部の分析基盤(入社当時) 20 Log Collector Hadoop Vertica Argus(内製BI) App Server DB BigQuery gsec (Linux Server) Jenkins Hue log Service 分析基盤 GCP • 大規模データはオンプレミスの Hadoop に格納していた。 • データマートはオンプレの Vertica 上で行ってきたが、運用のしやすさ /機械学習を用いた分析の発展という観点から   GCPの高機能DBであるBigQuery への移行を進めてきた。 • アドホックな分析作業は Linux サーバに ssh でログインして実行。 • スケジュールバッチは Linux サーバ上で稼働する Jenkins で実行。 • HadoopからVertica/BQへのロードは内製のバルクロードツール medjedを使ってWebUIで設定しロードしていた

Slide 21

Slide 21 text

GCP Project A GCP Project X GKE Service A ゲーム事業部の分析基盤(クラウド移行後) 21 21 • 分析基盤を全て GCP 上に構築し、サービス毎に GCP プロジェクトを分ける。 • ログ / DB スナップショットは Google Cloud Storage に格納する(データレイク)。 • DWH / データマートは全て BQ へ移行する。 • アドホックな分析作業は BQ の Web UI、もしくは業務端末 ( mac /win )上の CLI で実行する。 • スケジュールバッチは digdag という OSS で実行する。digdag は GKE 上でコンテナとして実行する。 • 現在はクラウド移行中のため、新旧の環境が混在している状況 App Server DB log BigQuery digdag GCS Service B GCP Project B Service C GCP Project C Service ・・・ ・・・ 分析基盤 Argus(内製BI) Medjed (内製バルクロードツール)

Slide 22

Slide 22 text

ゲーム事業部のパイプライン数 22 × 27環境 ※GCPプロジェクト数ベース

Slide 23

Slide 23 text

改めて 23

Slide 24

Slide 24 text

辛かった話 24

Slide 25

Slide 25 text

データエンジニアGrが発足したての頃の話です 25

Slide 26

Slide 26 text

辛かった話 その1 コード管理ができていない 26

Slide 27

Slide 27 text

27 過去のパイプライン Github:e EC2-Instance A Jenkins ジョブ実行 Title A 中間集計のソースコード Title A BigQuery git clone

Slide 28

Slide 28 text

28 過去のパイプライン Github:e EC2-Instance A Jenkins create_common Title A common_summary.sql unique_summary.sql Title A BigQuery git clone なぜかタイトル個別のリポジトリに タイトル横断で汎用的に利用できるソースコードが置かれている

Slide 29

Slide 29 text

Github:e EC2-Instance A Jenkins create_common Title A common_summary.sql unique_summary.sql Title A BigQuery git clone Github:e EC2-Instance B Jenkins create_common Title B common_summary.sql unique_summary.sql Title B BigQuery git clone 過去のパイプライン 新規タイトルが立ち上がると便利なのでコピーされる でも、個別のリポジトリにコピーされている模様

Slide 30

Slide 30 text

いつの間にか汎用的に使えたはずのソースコードが 亜種になり始める Github:e EC2-Instance A Jenkins create_common Title A common_summary_亜種 unique_summary Title A BigQuery git clone Github:e EC2-Instance B Jenkins create_common Title B common_summary unique_summary Title B BigQuery git clone 過去のパイプライン

Slide 31

Slide 31 text

こっちも闇落ちしちゃう Github:e EC2-Instance A Jenkins create_common Title A common_summary_亜種 unique_summary Title A BigQuery git clone Github:e EC2-Instance B Jenkins create_common Title B common_summary_亜種2 unique_summary Title B BigQuery git clone 過去のパイプライン

Slide 32

Slide 32 text

32

Slide 33

Slide 33 text

33

Slide 34

Slide 34 text

34

Slide 35

Slide 35 text

辛かった話 その2 ワークフローが管理できていない 35

Slide 36

Slide 36 text

JenkinsのGUIで設定という仕様上 ワークフローもGitでコード管理できておらず、 背景や意図がわからないことも Github:e EC2-Instance A Jenkins create_common Title A common_summary_亜種 unique_summary Title A BigQuery git clone Github:e EC2-Instance B Jenkins create_common Title B common_summary_亜種2 unique_summary Title B BigQuery git clone 過去のパイプライン

Slide 37

Slide 37 text

ちなみに 37

Slide 38

Slide 38 text

38 触りたくない

Slide 39

Slide 39 text

なぜこんなことが起きるのか? 39

Slide 40

Slide 40 text

40 散らかる背景 ● 工数不足 ○ 全体最適でどうあるべきかを考える時間がない ■ 新規タイトルがどんどんリリースされる ■ 構築するパイプラインの数が多い ■ アナリストがタイトル間で掛け持ちするケースが多くなる ● 設計のバラつき ○ 全体最適でアーキテクチャを取りまとめ・設計する役割が定まっていなかった ■ 部のメンバー全員が全体最適でアーキテクチャを設計できるわけではない →インフラエンジニアとアナリストの間に立つ  データエンジニアリング Grが発足した背景でもあります

Slide 41

Slide 41 text

ちなみに 41

Slide 42

Slide 42 text

この状態でみなさんがジョインしたとして 42

Slide 43

Slide 43 text

秩序を取り戻すとします 43

Slide 44

Slide 44 text

もとに戻したい 44

Slide 45

Slide 45 text

ロジックの詳細や背景を 作成した人に聞きに行きたい 45

Slide 46

Slide 46 text

46

Slide 47

Slide 47 text

ということも多いです。 47

Slide 48

Slide 48 text

48 課題 ● 辛かったこと①:コードが管理できていない ○ 汎用的なソースコードがタイトル個別のリポジトリに管理されている ○ せっかく汎用性があったのに独自進化してしまう ● 辛かったこと②:ワークフローが管理できていない ○ JenkinsのGUI設定の弊害で、ワークフローが Gitで管理できていない ○ 必ず実行されなければならないジョブが、 あるタイトルではされていて、あるタイトルではされていないということがある  →後々また少ない工数を奪う (=技術的負債)

Slide 49

Slide 49 text

49 2 digdagで幸せを取り戻した話

Slide 50

Slide 50 text

50 この辺りの話です

Slide 51

Slide 51 text

51 背景 ・もともと、VM で Jenkins をバッチ処理に使用していた ・クラウド移行にあたってインフラ側でバッチ処理に digdag が選択された ・Jenkins のジョブを digdag に移行する必要があった

Slide 52

Slide 52 text

52 digdagとは? ・Treasure Data 社が OSS で提供しているジョブ実行ツール ・YAML で柔軟なワークフローを定義できる ・Git でワークフローを管理できる

Slide 53

Slide 53 text

53 過去のパイプライン Github:e EC2-Instance A Jenkins create_common EC2-Instance B EC2-Instance C Title A common_summary unique_summary Title B common_summary unique_summary Title C common_summary unique_summary Title A Title B Title C BigQuery BigQuery BigQuery Jenkins create_common Jenkins create_common git clone

Slide 54

Slide 54 text

54 課題 ● 辛かったこと①:コードが管理できていない ○ 汎用的なソースコードがタイトル個別のリポジトリに管理されている ○ せっかく汎用性があったのに独自進化してしまう ● 辛かったこと②:ワークフローが管理できていない ○ JenkinsのGUI設定の弊害で、ワークフローが Gitで管理できていない ○ 必ず実行されなければならないジョブが、 あるタイトルではされていて、あるタイトルではされていないということがある

Slide 55

Slide 55 text

VPC DeNA Office Digdag Metadata Cloud SQL Cloud IAP DeNA Development Infra Analytics Data BigQuery Service Analytics Environment Digdag Task Log Cloud Storage Cloud NAT Cloud Armor Cloud Load Balancing Digdag Kubernetes Engine Logs & DB Snapshots Cloud Storage Analytics Tools Argus(BI) Medjed (Bulk Load) Service Environment logs & DB Snapshots Common Analytics Environment Container Registry Cloud DNS Cloud Build digdagのインフラ構成 【参考】「自由と統制のバランス 共通分析基盤のアプローチ」 DeNA長谷川さん       (Data Pipeline Casual Talk Vol3 登壇資料)  https://speakerdeck.com/ryoji_hasegawa/zi-you-totong-zhi-falsebaransu-fen-xi-ji-pan-falseapuroti

Slide 56

Slide 56 text

GKE 56 digdag以後のパイプライン Github:e pod Title A Title A summary.dig common_summary unique_summary Title B summary.dig common_summary unique_summary Title C summary.dig common_summary unique_summary BigQuery BigQuery BigQuery common common_summary submodule digdag push GKE pod Title B GKE pod Title C

Slide 57

Slide 57 text

● 辛かったこと①:コードが管理できていない問題 ○ Gitのサブモジュールを用いて再設計 ■ 汎用性のあるソースコードはタイトル横断用のリポジトリとして分離 ■ タイトル個別のリポジトリと共通リポジトリをサブモジュールで連携 57 改善した課題①

Slide 58

Slide 58 text

58 設計のポイント① - submodule   dena/common common_summary ├access ├consume ├install └session dena/title_A summary.dig unique_summary  └battle    ├create_battle.dig    └create_battle.sql common_summary ├access │├create_access.dig │└create_access.sql ├consume ├install └session git submodule add ● タイトル個別のリポジトリと共通用のリポジトリをサブモジュールで連携

Slide 59

Slide 59 text

● 辛かったこと②:ワークフローが管理できていない ○ digdag で YAML でワークフローをコード管理 ■ Jenkins時代にはできていなかったワークフローをコード管理 ■ .digでワークフローの雛形を作成し、設計のバラつきをなくす ■ サブモジュールで個別と共通リポジトリがシンクされているので digdag push だけで中間集計ジョブを作成可能な状態を実現 59 改善した課題②

Slide 60

Slide 60 text

digdag push 60 設計のポイント② - digdag push dena/title_A common_summary ├access │├create_access.dig │└create_access.sql ├consume ├install └session summary.dig unique_summary  └battle    ├create_battle.dig    └create_battle.sql digdag pod dena/title_A common_summary ├access │├create_access.dig │└create_access.sql ├consume ├install └session summary.dig unique_summary  └battle    ├create_battle.dig    └create_battle.sql ● digdag pushでgit cloneした内容をdigdag側にProjectとしてコピー

Slide 61

Slide 61 text

61 設計のポイント③ - 親dig・子dig summary.dig timezone: "Asia/Tokyo" schedule: daily>: 00:00:00 # 共通で使う環境変数を読み込む !include : 'config/config.dig' # 共通集計(アクセスログの集計) +create_access: call>: 'common_summary/access/create_access.dig' # タイトル個別の集計(バトルログの集計) +create_battle: call>: 'unique_summary/battle/create_battle.dig' 親dig = 全体のワークフローを定義する dig 子dig = 処理の詳細を定義する dig →目次とコンテンツ的な関係性

Slide 62

Slide 62 text

62 設計のポイント③ - 子dig summary.dig timezone: "Asia/Tokyo" schedule: daily>: 00:00:00 # 共通で使う環境変数を読み込む !include : 'config/config.dig' # 共通集計(アクセスログの集計) +create_access: call>: 'common_summary/access/create_access.dig' # タイトル個別の集計(バトルログの集計) +create_battle: call>: 'unique_summary/battle/create_battle.dig' create_access.dig +create_access: loop>: ${ moment(END_DATE).diff(moment(START_DATE), 'days') + 1 } _do: _export: DATE: ${ moment(START_DATE).add(i,'days').format("YYYY-MM-DD")} SUFFIX_DATE:${moment(START_DATE).add(i,'days').format("YYYYMMDD") } bq>: create_access.sql destination_table: access$${SUFFIX_DATE} dataset: summary write_disposition: WRITE_TRUNCATE ・再集計に耐えうるよう日付でループ処理する設計  →冪等性の担保 ・部の様々なメンバーが設置することも考慮し、  データセット名  テーブル名  クエリのファイル名  を入れ替えれば、基本的にどんな集計も実現できる設計にした

Slide 63

Slide 63 text

63 設計のポイント③ - config.dig summary.dig timezone: "Asia/Tokyo" schedule: daily>: 00:00:00 # 共通で使う環境変数を読み込む !include : 'config/config.dig' # 共通集計(アクセスログの集計) +create_access: call>: 'common_summary/access/create_access.dig' # タイトル個別の集計(バトルログの集計) +create_battle: call>: 'unique_summary/battle/create_battle.dig' config.dig _export: START_DATE: ${ moment().subtract(1, 'day').format('YYYY-MM-DD') } END_DATE: ${ moment().subtract(1, 'day').format('YYYY-MM-DD') } _retry: limit: 1 interval: 600 interval_type: constant ・どの処理でも使用する実行対象日やリトライの詳細を _exportで定義して config.digとして、ワークフローの最初で実行 ・config.digを!includeで実行すれば配下全ての処理で使用可能

Slide 64

Slide 64 text

GKE 64 digdag以後のパイプライン Github:e pod Title A Title A summary.dig common_summary unique_summary Title B summary.dig common_summary unique_summary Title C summary.dig common_summary unique_summary BigQuery BigQuery BigQuery common common_summary submodule digdag push GKE pod Title B GKE pod Title C

Slide 65

Slide 65 text

65 まとめ ● 課題①:コードが管理できていない問題 ○ Gitのサブモジュールを用いて再設計 ■ 汎用性のあるソースコードはタイトル横断用のリポジトリに分離 ■ タイトル個別のリポジトリと共通リポジトリをサブモジュールで連携 ● 課題②:ワークフローが管理できていない問題 ○ digdag で YAML でワークフローをコード管理 ■ Jenkins時代にはできていなかったワークフローをコード管理 ■ コードでワークフローの雛形を作成し、設計のバラつきをなくす ■ サブモジュールで個別と共通レポジトリがシンクされているので digdag push だけで中間集計ジョブを作成可能