Slide 1

Slide 1 text

大量のデータを扱う分析基盤における、 クラウドネイティブなデータ処理連携と プログラマブルな戦略的管理について 株式会社サイバーエージェント @nnao45 1

Slide 2

Slide 2 text

⾃⼰紹介 2 ● 株式会社サイバーエージェント AI事業本部 リテールテックDiv AIRTRACKチーム所属(⻑ ● Scala/Javaで広告商材作ったり、AWSを管理する⼈ ● MLOpsチームでスクラムマスターやる⼈ ● 北陸先端技術科学⼤学院⼤学修⼠1年⽣ ○ バイナリ実⾏最適化か乱数エントロピーの研究を予定・・・。 ● 好きなAWSサービス ○ AWS Step Functions、Amazon Route53、ALB 横⼭尚弥 @nnao45

Slide 3

Slide 3 text

アジェンダ 1. AirTrackについて 2. 全体構成の紹介 3. 技術選定のお話 4. ナレッジ 5. 今後のAWSさんに期待する事 6. まとめ 3

Slide 4

Slide 4 text

1.AIR TRACKについて

Slide 5

Slide 5 text

小売 メーカー 大学 広告配信 広告出稿 消費者 店舗での(当該商品の)購買 5 ...more ● 実店舗への来店促進・購買促進を広告を通じて⾏うDSP 1. AIR TRACKとは データ分析/機械学習 DMP機 能 レポート/可視化 DSP機能 フィードバック

Slide 6

Slide 6 text

2. 全体構成の紹介

Slide 7

Slide 7 text

7 AIRTRACKのインフラ

Slide 8

Slide 8 text

2.全体構成の紹介 8 Data Collector DSP/Batch S3 Redshift RDS EMR Glue AWS Batch World Stepfunctions ML

Slide 9

Slide 9 text

9 2.全体構成の紹介 ● AirTrackのデータ量 All Data 0.7 PetaBytes+ Max Qps 30,000 QPS+ dayUU数 5,000,000 UU+ UU数 20,000,000 UU+

Slide 10

Slide 10 text

2.全体構成の紹介 10 Data Collector DSP/Batch S3 Redshift RDS EMR Glue AWS Batch World Stepfunctions ML ↓今日のお話はココ

Slide 11

Slide 11 text

11 AIRTRACKのバッチ処理

Slide 12

Slide 12 text

2.全体構成の紹介 Python CDK Stepfunctions ● 今⽇のお話の中⼼

Slide 13

Slide 13 text

2.全体構成の紹介 CDKのコード バッチのコード CI/CDによる自動テスト/デプロイ CDKによるAWSへの反映 Stepfunctionsによるバッチの一括管理 揮発性AWSリソース生成 開発者 運⽤者 フロー図 ありがてぇ・・・ deploy GUIで 履歴/実行確認

Slide 14

Slide 14 text

3. 技術選定

Slide 15

Slide 15 text

15 なぜ StepFunction︖

Slide 16

Slide 16 text

3. 技術選定 ● Stepfunctionsとは︖ ● いわゆるワークフローエンジン、サーバレスなAWSのマネージドサービス。 ● 並列実⾏、失敗時のリトライ、例外のキャッチ、awsリソースの作成やタス ク実⾏の終了までwaitする機能などワークフローエンジンの⼀通りの機能 ● ワークフローのフロー図をデフォルトで可視、進捗や失敗した時にどのステ ップかを反映してくれる。 ● AWS Batch、Lambda、SageMaker、EMR、Glue、EC2など幅広い AWSリソースをARN等を指定するだけでプログラマブルに処理を記述可能 Stepfunctions

Slide 17

Slide 17 text

3. 技術選定 Stepfunctions

Slide 18

Slide 18 text

3. 技術選定 Stepfunctions

Slide 19

Slide 19 text

19 AIRTRACKのStepfunctions作り

Slide 20

Slide 20 text

3. 技術選定 Start その全てのバッチ処理が絶 対に処理1個で済む/1個分 の実行しかダメ バッチが作りたい Stepfunctions使わない Stepfunctions使う 15分で事足りる/ 大した処理じゃない/ 複雑なエラーハンドルがない 大量のデータを扱わない/複 数のデータソースをまたぐ 処理でじゃない/Docker使い たい タスクにLambdaを選ぶ 以下追加する処理に割り当てる AWSリソースを選ぶ タスクにAWS Batchを選ぶ 機械学習処理ではない/処理重複が多い/ 細かいパラメータチューニングはしない/ ピュアなMapReduceをしない タスクにGlueを選ぶ タスクにEMRを選ぶ YES YES YES YES NO NO NO NO

Slide 21

Slide 21 text

21 なぜ CDK︖

Slide 22

Slide 22 text

3. 技術選定 ● この世に溢れる構成管理ツール・・・ CDK

Slide 23

Slide 23 text

3. 技術選定 ● AIRTRACKではStepfunctionsの管理にCDKを採⽤しました ● プログラミング⾔語でインフラを管理 ● AWS公式ツール、⽣成物もCloudformation ● YAMLやHCLでは出来ない参照跳び、便利な 各⾔語のライブラリが使える ● ユニットテスト出来る、インフラの記述を型/Classで縛れる ● ちょっぴり⼤変なStep functionsの記述に⼤活躍

Slide 24

Slide 24 text

3. 技術選定 ● StepfunctionsはデフォでASL(JSON)で書く・・・。 CDK { "StartAt": "workflow", "States": { "workflow": { "Type": "Parallel", "End": true, "Catch": [ { "ErrorEquals": [ "States.ALL" ], "Next": "[Lambda] notification_err" } ], "Branches": [ { "StartAt": "[Lambda] make_formatted_date", "States": { "[Lambda] make_formatted_date": { "Next": "[Lambda] select_emr_core_instance_type", "Type": "Task", "ResultPath": "$.formatted_date", "Resource": "arn:aws:states:::lambda:invoke", "Parameters": { "FunctionName": "${Token[TOKEN.143]}", "Payload": { "method": "format_date", "args": { "format_str": "%Y/%m/%d/%H", "date_str.$": "$.time", "sub_hour": 1 } } } },

Slide 25

Slide 25 text

3. 技術選定 ううう・・・やっぱり JSONを編集するのがきつい! ※個⼈的な感想です

Slide 26

Slide 26 text

3. 技術選定 CDK パァアアア・・・ !? あ、あなたは・・・!

Slide 27

Slide 27 text

3. 技術選定 ● CDKで書くと・・・あら綺麗・・・︕ CDK workflow: sf.Chain = sf.Chain ¥ .start(make_formatted_date_task) ¥ .next(make_select_emr_core_instance_type_task) ¥ .next(create_emr_cluster) ¥ .next(formatted_imp_click_summaries_arg_task) ¥ .next(ichica_imp_click_summaries) ¥ .next(post_definition) ¥ .to_single_state("workflow") workflow.add_catch(notification_err_task.next( job_failed), errors=["States.ALL"]) definition: sf.Parallel = sf.Parallel(self, id="definition") definition.branch(workflow) 定義ジャンプすれば変 数を⽬grepしないでい いのね・・・︕

Slide 28

Slide 28 text

3. 技術選定 ● CDKで書くと・・・あら綺麗・・・︕ glue_job: glue.CfnJob = glue.CfnJob( self, 'glue_job', name=config.GLUE_JOB_NAME, role='arn:aws:iam::XXXXXXXX:role/service-role/AWSGlueServiceRole-DefaultRole', execution_property=glue.CfnJob.ExecutionPropertyProperty( max_concurrent_runs=config.GLUE_MAX_CONCURRENT), allocated_capacity=config.GLUE_CAPACITY, command=glue.CfnJob.JobCommandProperty( name='glueetl', python_version=config.PYTHON_VERSION, script_location=config.GLUE_SOURCE_CODE_PATH ), glue_version=config.GLUE_VERSION, connections=connections) glue_job_task: tasks.GlueStartJobRun = tasks.GlueStartJobRun( self, '[Glue] glue_job_task', glue_job_name=config.GLUE_JOB_NAME, arguments=sf.TaskInput.from_object(obj={"--UTC_DATETIME": formatted_date}), integration_pattern=sf.IntegrationPattern.RUN_JOB, result_path="$.glue_job_result") workflow: sf.Chain = sf.Chain ¥ .start(make_formatted_date_task) ¥ .next(glue_job_task) ● Step functionsに組み込みたい AWSリソースを定義する。 右の例でGlueのジョブを管理している。 ● Step functionsに組み込むタスクとし て、⾚枠で定義したリソースを指定す る(既にCDK外で作成済なら⾚枠は省 略可能) ● 最後に⽔⾊枠で定義したタスクをStep functionsのワークフローに組み込む

Slide 29

Slide 29 text

29 なぜ CDK for Python︖

Slide 30

Slide 30 text

3. 技術選定 ● AIRTRACKではStepfunctionsの管理にCDKを採⽤しました ● 内部処理はTypeScriptで作られている・・・・。

Slide 31

Slide 31 text

3. 技術選定 ● なぜAIRTRACKではCDK for Pythonを選んだのか︖ ● AIRTRACKのチーム構成は、 ○ SW(+インフラ)5⼈、DS1⼈、ML4⼈の構成 ○ チームの半数が機械学習ジョブに携わる ● AIRTRACKは「全エンジニアが全て触れる」を理想としている・・・︕ ● 全員が触れる/触りやすい⾔語は、Pythonだった ● Stepfunctionsにフォーカスすると、Pythonでも不⾃由なかった ● TypeScriptの⽇本語ブログが溢れるが、Pythonも頑張ってる

Slide 32

Slide 32 text

● 意外にも、実はCDKのワード検索的にはpythonが優勢︖

Slide 33

Slide 33 text

3. 技術選定 ● 余談・・・Python︖型はどうしたんですかねえ・・・ いや〜わてくし、 動的スクリプト言語なの で・・・。

Slide 34

Slide 34 text

3. 技術選定 ● 余談・・・Python︖型はどうしたんですかねえ・・・ いやいや! Python3.5で 型ヒント来たんだ ったわ!!! from typing import TypeVar, Generic T = TypeVar('T') class LoggedVar(Generic[T]): def __init__(self, value: T, name: str, logger: Logger) -> None: self.name = name self.logger = logger self.value = value def set(self, new: T) -> None: self.log('Set ' + repr(self.value)) self.value = new def get(self) -> T: self.log('Get ' + repr(self.value)) return self.value def log(self, message: str) -> None: self.logger.info('{}: {}'.format(self.name message))

Slide 35

Slide 35 text

3. 技術選定 ● 余談・・・Python︖型はどうしたんですかねえ・・・ mypyでいい感じ にCIでつけ忘れと か静的チェックも できる! 型型言わせてく れ・・・。 https://github.com/python/mypy

Slide 36

Slide 36 text

4. ナレッジ

Slide 37

Slide 37 text

37 兎にも⾓にもLambda

Slide 38

Slide 38 text

4. ナレッジ Stepfunctions ● Stepfunctionsの標準機能で⾜らない痒い所は結構多い ● 時間⽂字列のフォーマット ● EMRのコマンドにStep functionの変数をいれる ● 例外に⾶んだときの通知 ● 処理の量(処理対象のs3のバケットのパーティションサイズ)に応じて、処理 を変化させる ● Glue Crawlerの起動/終了管理 ● ちょっとした計算がしたい

Slide 39

Slide 39 text

● Stepfunctionsの開発効率=息を吸うかのようにLambdaがデプロイ出来るようにしておく ● どっちの開発、デプロイ効率もよくできるよ、そう、CDKならね︕ 4. ナレッジ

Slide 40

Slide 40 text

40 result_pathの御⽤⼼

Slide 41

Slide 41 text

● Stepfunctionsの処理の⼊出⼒は「result_path」で管理 ● ただ、この「result_path」はnullでタスクを設定すると、過 去の出⼒内容が全部上書きされてしまうので注意 ● よくわからんくても「result_pathは必要なくてもなんらか $.hogeとか書いておく」を⼼がける 4. ナレッジ https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/connect-to-resource.html

Slide 42

Slide 42 text

42 CDKのsynthを信じすぎない

Slide 43

Slide 43 text

● CDKのsynthが通る=正しく動作するstepfunctionsではない︕︕ ● CDKもバリデーションをしてくれるが、それは当然完全ではない ● synthが通るからデプロイしていいわけではない︕ ● むしろsynthが通るのは当然で、そこからが本番 ● 必ずstagingや、ミニマル版のstepfunctionsで動作確認をするように ● ⼊出⼒だけ模擬するモックテスト環境があると最⾼ 4. ナレッジ CDK

Slide 44

Slide 44 text

5. 今後のAWSさんに期待すること

Slide 45

Slide 45 text

● Step functionsにCDKで⽤意されているEvaluateExpression(変数を受け取ってワンライ ナーな計算をして返してくれるLambda)をもっと⼿軽に使えるようにしてほしい︕ ● Step functions内で明らかに良く使うLambdasは⽤意してもらえると敷居が下が ります・・・。 ● Step functions、GlueのCrawlerの.sync対応頼む(⾎涙 ● Step functionsのコンソールから指定した所からやり直すとかできると良い な・・・ 5. 今後のAWSさんに期待すること

Slide 46

Slide 46 text

6. まとめ

Slide 47

Slide 47 text

● AWSでバッチ処理をするならStep functionsを使うと幸せになれる ● Step functionsを管理をするならCDKを使うと幸せになれる ● CDKを使う時に、TypeScriptもいいけどPythonもいいぞ︕ ● Step functionsの開発はとにかくアジャイルに︕トライ&エラーでよりよいワ ークフローは運⽤しながら改善 6. まとめ