毎年参加しているServerless Conf Tokyoです。3回目になります。
http://tokyo.serverlessconf.io/tokyo.serverlessconf.io
他のセッション
引用は私のコメントです。
目次
- 目次
- Title
- Speaker
- 資料
- 導入するサービス
- これまでの流れ
- レガシーな構成のつらいところ
- 分析基盤の特性 : データ間の依存関係
- 改善プロジェクト : Migaloo (白鯨)
- リプレースの際の教訓
Title
The Design for Serverless ETL Pipeline
Speaker
山田雄
秋本大樹
白鳥昇治
資料
導入するサービス
リクルートの分析基盤。ここに各種リクルートサービスのデータを入れている。
これまでの流れ
運用しつつ改善を繰り返してきた。
- 2013 : Hadoop(オンプレ) + RedShift
- 2014 : TreasureData
- 2016 : RedShift MultiCluster
- 2017 : BigQuery + DataLake
- 2018 : TreasureData -> BigQuery, RedShift Spectrum, RegShift -> Single Node
2018 は構成の新婦柄を目指してるのね。
レガシーな構成のつらいところ
どうつらいのかというと、技術のつぎはぎがもっとも厳しい
- 800行のShell Script
- 本番環境が分離されてないので、開発いれてからじゃなくていきなり投入が必要...
- Python でSegmentation Fault
- 複数のシステムをツギハギするスケジュール実行
- 終了するタイミングを見計らって後続の処理を実行
- データ量に関連した処理の長時間化
あるあるつらさだ。スケジュール実行最低に面倒なやつ。Observable に購読するか、Push されてこないと延々ときびしい、かつデータがただしいかみないとか.... 長時間化はパラレル処理かなぁ?いけるなら。
分析基盤の特性 : データ間の依存関係
事業データを正規化して、データウェアハウス (RedShift / BigQueryなど) にいれる、で分析者が使うデータま0とを生成する。
ETL分析のものは優先度高く。アドホック分析は優先度落とす。など、優先度管理が必要。 優先度を変更する = 運用負荷につながっている。
そのため、JP1 でイベント受信機能を使って、優先度を実現している。優先度高いものが終わるまで、優先度低いものが開始せず、高いものが終わったら低いものがキックされるようにしている。
障害リカバリの大変さが半端ない
スケジュール実行での運用は、一度障害が起こるとずっと処理を待ち続けて、後続を流す、という運用が厳しい。 -> データドリブンに変更したい。
1つの実行単位に複数のテーブルを含めているので、テーブルごとに実行できない。
あるあるすぎる
自前サーバーでの開発が辛い
テスト環境がないので気軽にテストできない 本番にえいきょうが出るので、古いバージョンでのカイアh津を強いられている。 800行を超えるシェルスクリプトのメンテがつらすぎる。
なんでシェルスクリプトでかいたし..... 環境が複数あって、その環境の更新をインフラが嫌がってるのか.....
シェルスクリプトが1行ずつ読まれるから、デプロイも1行差し込めばいいじゃん。
改善プロジェクト : Migaloo (白鯨)
前回のServerlessconf Tokyo
サーバーレスおにしてサーバー管理を小さく イベントドリブンで処理をしましょう。
-> で、結果は?
データ : 増えてる 機会学習バッチのリソース使用量 : 増えてる バッチ : 1時間 -> 2時間に伸びた。
が、運用は全然なくなった。
Slack のアラート確認してるが、自動リトライ済み。 データ量もスケールするので関係ない。 システムモニタリング用途の Amazon Elasticsearch Serviice のリソース見直しの運用を実施。 AWS のSQS がおかしくなったときだけ、手動でリトライした。
今回もServerless で。
アーキテクチャ設計思想
サーバー管理を少なくパイプライン + 実行環境
データソース -> Pipeline (SQS -> Lambda -> StepFunctions) -> DataLake(S3) -> Pipeline (SQS -> Lamnda CloudWatch -> StepFunctions) -> RedShift Spectrum/BigQuery/S3
Pipeline = Step Functions + AWS Lambda で構築。
j拮抗環境あh、スケーラブルな、AWS BAtch / Glue / GKE を利用。 要件によって、一部はオンプレサーバーを利用 (じゃらん)。データ圧縮をしないとDirect Connect が詰まるので一部オンプレからServerless から呼び出しをして処理を行っている。
イベント・ドリブン
1 イベント = 1データがどこかに到達した時。 イベント・ドリブン = データが到達したときに次の処理が実行される。 (1イベント = 1 テーブル (これまでは複数テーブルをまとめて1処理 = 1イベントしていた))
Database やS3 などのイベントソースを受けて実行開始。など。
疎結合なパイプライン
RedShift = 時々メンテナンスが来るので、自動リトライ。 SQS は、リトライ = Dead Letter Queue を使って処理をしている。
- 障害発生時の影響の小ささ、リトライ
- デプロイは限定してそこだけに
パイプラインとスケーラビリティ + 並列数の管理
マネージドなパイプラインにより、無限にスケーラビリティが...。
でもRedShift は500接続まで。なので、この有限接続先との接続には、イベントの同時処理制御をするため、Lambda を挟んでいる。それが、RedSiftまでのPipelineでSQS +Lambda を行っている。(Lamnda で同時処理上限を制約)
ロード処理の宛先がスケールする場合は、気にせず実行
イベントのステータス管理と活用
メタデータ(データがどこからいつきたのか) は重要。
各パイプラインで現在の家bンとと処理ステータスを、DynamoDB を使って管理。
- Lambda の2重発火による重複起動を制御
- データロード後のマート作成実行を制御
- データロード完了時間を確認(いつデータロードが終わったかの鮮度が管理できる)
DynamoDB 使うのは筋だし、よいな。ようはスケールするKV DBなら何でもいいので、Azure ならBlob Table... 処理量でCosmos... うっ高い、使い勝手わるいな
イベントとステータスん変更履歴はRDS で管理 (DynamoDB Streams でアイテム変更をRDSへストリーミングインサート)
2000行のSQL..... その分析いやだなw
運用が楽になるロギング・モニタリング
AWS を主に使っているが、Cloud Watch Logs は見に行くい。 LogStreams が AWS Lamnda やAWS Batch で分かれるのが使いにくい。
わかる、Cloud Watch Logs 価格面でいいんだけど、めっちゃいや。
ということで、アプリケーションログとシステムモニタリングはDataDog へ。 重要な通知はSlackへ。
Lambda、AWS Batch、オンプレの様々な実行環境のプログラムログをまとめて流している。
妥当だった
Managed Service のメトリクスのアラートもDatadog に集約。重要な通知はSlackへ。 特にSQS のアラートは重要なので、キューの状況は注視。 Lambda は一度落ちるとコケるので、要注意、しきい値も常に改善したほうがいいと考え注意している。
SQS を始めとしたキューの監視がね、仕方ない。
リプレースの際の教訓
ETL 処理のリプレース処理をやっていて、2つ教訓がある。
既存の運用に設計が引きずられる
- なれた運用からの脱却
- ログの保存先の変更
- 新しいツールの学習
これらが、運用として変更時に負荷になる。 運用を替えないようにすると、今までのインターフェースに引きずられてサーバー依存の設計になりがちで厳しい。 運用も含めてリプレースの対象だという共通認識を作る。
あるあるすぎる。やりたいことにフォーカスして、ツールを変更を受け入れる、ツールに自分たちを合わせるの大事。
スコープの肥大化
今までのつらみを解消しようとして、スコープが肥大化しがち。銀の弾丸として見られるのは良くない、スコープを決めて「何ができる、何ができない、やるやらないの判断」は非常に重要。
金言。まじである。