Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

ワークフローオーケストレーション入門

 ワークフローオーケストレーション入門

「Data Engineering Study #23 Data orchestration 特集」の発表資料です
イベントページ: https://forkwell.connpass.com/event/310011/

Satsuki Nagae

March 05, 2024
Tweet

More Decks by Satsuki Nagae

Other Decks in Technology

Transcript

  1. 長江 五月 自己紹介 4 @nsakki55 ブログ: https://nsakki55.hatenablog.com/ AWSでML基盤を構築する記事を書いてます 業務 ・MLOps

    ・MLモデリング ・広告データ分析 CyberAgent AI事業本部 Dynalyst データサイエンティスト マネージャー
  2. 28 ワークフローツール第1世代 2010 Hadoopジョブのオーケストレーションシステム Hadoopジョブやデータ取り込み・書き込みなど 長時間実行されるバッチジョブの管理 Yahoo Oozie 2012 Spotify

    Luigi 2014 LinkedIn Azkaban Hadoopジョブを実行するバッチワークフローの ジョブスケジューラー 2015 Airbnb Airflow ワークフローをプログラムで作成・スケジュール 監視するためのプラットフォーム 開発 名称 概要
  3. 31 Modern Data Stack Data Stackとは? データ基盤を構成する製品群のこと データベース・BIツール・ETL製品・ワークフローツールなど Modern Data

    Stackとは? 特定のアーキテクチャ・技術・ソリューションを指す言葉ではない 従来のData Stackの課題を解決しようする技術トレンドの総称
  4. 34 主要ワークフローツールの変遷まとめ CRON RDMS_JOB PowerCenter Oozie Luigi Azkaban Airflow Digdag

    Argo Prefect Dagster CRON時代 リレーショナル データベース時代 データウェアハウス・ データ統合時代 ビッグデータ時代 モダンデータ スタック時代
  5. 39 データパイプラインの課題 イベントログ マスターデータ 手動入力データ 抽出 クレンジング 結合 書き込み 抽出

    抽出 データ変換 Slack通知 書き込み 型変換 手動実行 バッチ実行 チームA管理 チームB管理 スクリプトで 処理を記述 レポートテーブル 日販管理
  6. 41 機械学習パイプラインの課題 生データ 抽出 前処理 学習 学習 学習 評価 デプロイ

    特徴量ストア モデルストア 並列学習 実験管理 GPU利用 jupyter notebookに処理を記述 データサイエンティストが管理
  7. 44 ワークフローとDAGの関係 A B C D A B C D

    DAG Not DAG 実行順序を事前に決定できる 最後のタスクが成功=ワークフローの成功 メリット
  8. 45 なぜDAGがワークフローツールに普及したか 初期のワークフローツールはHadoopジョブをマークアップ言語で記述 MapReduce マークアップ言語 Map Task Reduce Task 出力

    入力 Map Task Map Task YAML・XMLなど ループ・相互依存 を表現できない 全てのワークフロー をDAGとして表現 DAGにする必要性がない説もある You Probably Don’t Need a DAG
  9. 6つのワークフローツールの特徴比較 Step Functions 特徴 シンプル 手軽 k8sと連携 Python DAG 活用事例が豊富

    自然なPython 記法での開発 データ運用に特化 サーバレス AWSサービス ワークフロー 実装言語 digファイル (YAML) k8s manifest (YAML) Python (Operator) Python (Flow) Python (Job) GUI操作 JSON 利用形態 OSS OSS OSS SaaS クラウドマネージド OSS SaaS OSS SaaS クラウドマネージド 学習コスト 低 中 高 高 高 低
  10. 54 実装例 import json import pendulum from airflow.models.dag import DAG

    from airflow.operators.python import PythonOperator with DAG( "tutorial_dag", default_args={"retries": 2}, description="DAG tutorial", schedule="@daily", start_date=pendulum.datetime(2021, 1, 1, tz="UTC"), catchup=False, tags=["example"], ) as dag: DAGの設定 DAGコンテキストマネージャを使用 ・実行スケジュール ・リトライ
  11. 55 実装例 def extract(**kwargs): ti = kwargs["ti"] data_string = '{"1001":

    301.27, "1002": 433.21, "1003": 502.22}' ti.xcom_push("order_data", data_string) def transform(**kwargs): ti = kwargs["ti"] extract_data_string = ti.xcom_pull(task_ids="extract", key="order_data") order_data = json.loads(extract_data_string) total_order_value = 0 for value in order_data.values(): total_order_value += value total_value = {"total_order_value": total_order_value} total_value_json_string = json.dumps(total_value) ti.xcom_push("total_order_value", total_value_json_string) def load(**kwargs): ti = kwargs["ti"] total_value_string = ti.xcom_pull(task_ids="transform", key="total_order_value") total_order_value = json.loads(total_value_string) Python Operatorで実行する 関数を作成 タスク間のデータ受け渡し
  12. 56 実装例 extract_task = PythonOperator( task_id="extract", python_callable=extract, ) transform_task =

    PythonOperator( task_id="transform", python_callable=transform, ) load_task = PythonOperator( task_id="load", python_callable=load, ) extract_task >> transform_task >> load_task Operatorのインスタンスを作成 DAGの作成
  13. 61 Digdagの要素 Task Executor Task sh> py> email> bq> loop>

    redshift> if> ECS Operator Regisotry Command Executor
  14. 62 Digファイルでワークフローを記述 timezone: UTC +setup: echo>: start ${session_time} +disp_current_date: echo>:

    ${moment(session_time).utc().format('YYYY-MM-DD HH:mm:ss Z')} +repeat: for_each>: order: [first, second, third] animal: [dog, cat] _do: echo>: ${order} ${animal} _parallel: true +teardown: echo>: finish ${session_time} YAML記法 + Dig独自の記法
  15. 66 実装例 timezone: UTC schedule: daily>: 01:00:00 _export: !include: 'plugin.yml'

    workflow_name: sample_workflow task_date: ${moment(session_time).utc().format("YYYYMMDDHH")} +prepare: sh>: tasks/prepare_data1.sh +analyse: _export: bar: 2 +sub_step1: py>: tasks.MyWorkflow.analyze_step1 +sub_step2: py>: tasks.MyWorkflow.analyze_step2 スケジュール設定 外部プラグイン読み込み・変数宣言 ・JavaScriptプログラム展開 タスクグループ
  16. 71 6種類のTemplate Container Script Resource Suspend Steps Dags 実行コンテナの設定 コンテナ内での実行スクリプトの設定

    k8s clusterリソースを操作 一時停止 タスクの一連の実行ステップを作成 タスクの依存関係を作成 Definitions Invocators
  17. 72 実装例 apiVersion: argoproj.io/v1alpha1 kind: Workflow metadata: Name: sample-workflow spec:

    entrypoint: main templates: - name: main steps: - - name: step1 template: whalesay - - name: step2 template: gen-random-int - name: whalesay container: image: docker/whalesay:latest command: [cowsay] args: ["step1"] - name: gen-random-int script: image: python:alpine3.6 command: [python] source: | import random i = random.randint(1, 100) print(i) ワークフローの開始テンプレートを指定 spec.entrypointは必須 テンプレートの実行順序 タスクの処理内容であるテンプレートの作成
  18. 77 Prefectの要素 ワークフロー定義.py Prefect Cloud Worker Deployment Storage Work Pool

    ・実行インフラ ・コード管理 ・スケジュール  などの設定 docker S3 GCS Git kubernetes ECS Cloud Run ワークフロー実行 開発環境 管理画面 コード管理 実行環境 ワークフロー実行制御 LapTop
  19. 78 実装例 from prefect import flow, task import pandas as

    pd import s3_client @task def extract()-> pd.DataFrame: s3_client.download_file(S3_BUCKET, file_name) data = pd.read_csv(file_name) return data @task def transform(data: pd.DataFrame)-> pd.DataFrame: data_transformed = data.groupby('column') return data_transformed @task def load(data: pd.DataFrame): s3_client.upload(S3_BUCKET, file_name, data) @flow def etl(file_name: str): extracted_data = extract(file_name) transformed_data = transform(extracted_data) load(transformed_data) if __name__ == "__main__": etl(file_name=”sample.csv”) Task Task Task Flow Task = Python関数 Flow = 関数の依存関係 Task Flow Python関数に@taskデコレータをつけると Prefectはタスクとして認識する @flowデコレータでFlowとして認識する タスクの出力を次のタスクの入力にできる python workflow.py でCLI実行可能
  20. 79 GCP GKEでの実行例 ワークフロー定義.py Prefect Cloud Worker Deployment Kubernetes Work

    Pool Kubernetes Job 開発環境 管理画面 コード管理 実行環境 GKE Artifact Registory prefect.yaml image自動ビルド
  21. 80 実装例 name: flows prefect-version: 2.13.8 build: - prefect_docker.deployments.steps.build_docker_image: id:

    build-image requires: prefect-docker>=0.4.0 image_name: "asia-docker.pkg.dev/{{ $GCP_PROJECT_ID }}/repository/auto-image" tag: latest dockerfile: auto platform: "linux/amd64" push: - prefect_docker.deployments.steps.push_docker_image: requires: prefect-docker>=0.4.0 image_name: "{{ build-image.image_name }}" tag: "{{ build-image.tag }}" pull: - prefect.deployments.steps.set_working_directory: directory: /opt/prefect/auto_image ワークフローのコード管理・実行インフラ環境・スケ ジュールなどの設定を prefect.yaml に記述 ワークフローのdocker imageをビルド 自作のDockerfileでビルドも可能 Container Registryにpush ワークフロー実行時の コード取得先の設定
  22. 81 実装例 definitions: tags: &common_tags - "gke" work_pool: &**common_work_pool** name:

    "gke" job_variables: image: "{{ build-image.image }}" deployments: - name: "auto_image" tags: *common_tags schedule: - cron: "0 0 * * *" entrypoint: "flows/etl.py:etl" work_pool: *common_work_pool work poolの設定 実行したいインフラ環境 をここで変更 tag, scheduleなどを設定
  23. 87 Asset実装例 from dagster import asset from typing import Dict

    import pandas as pd from sklearn.linear_model import LinearRegression @asset def iris_dataset() -> pd.DataFrame: return pd.read_csv( "https://docs.dagster.io/assets/iris.csv", names=["sepal_length_cm","sepal_width_cm","petal_length_cm","petal_width_cm","species"] ) @asset def logistic_regression_model(iris_dataset: pd.DataFrame) -> LinearRegression: x = iris_dataset[["sepal_length_cm", "sepal_width_cm", "petal_length_cm", "petal_width_cm"]] y = iris_dataset["species"].map({"Iris-setosa": 0, "Iris-versicolor": 1, "Iris-virginica": 2}) return LinearRegression().fit(x, y) @asset def accuracy(logistic_regression_model: LinearRegression) -> Dict: return { "intercept": logistic_regression_model.intercept_, "coef": logistic_regression_model.coef_, } @assetデコレータでAssetを 作成 関数引数がAssetの依存関係 を表す
  24. 88 Asset Job実装例 from dagster import ( Definitions, load_assets_from_modules, define_asset_job,

    AssetSelection, FilesystemIOManager, ScheduleDefinition, ) from . import assets all_assets = load_assets_from_modules([assets2]) iris_job = define_asset_job("etl_job", selection=AssetSelection.all()) schedule = ScheduleDefinition( job=iris_job, cron_schedule="0 0 * * *", ) io_manager = FilesystemIOManager(base_dir="data") defs = Definitions( assets=all_assets, schedules=[schedule], resources={"io_manager": io_manager}, ) assetの実行・監視を 行う集合 Asset Asset Asset Asset Job asset jobの作成 実行スケジュールの作成 job実行に関わる設定をまとめる
  25. 90 Hybridの構成 Agent Code Location Deployment docker kubernetes ECS ワークフロー実行

    開発環境 管理画面 コード管理  実行環境 Job実行制御 GitHub Actions Deployment main feature dagster_cloud.yaml
  26. dagster_cloud.yaml 91 AWS ECSでの実行例 Agent Code Location Deployment ECR ECS

    ワークフロー実行 開発環境 管理画面 コード管理  実行環境 Job実行制御 ECS Service main 公式のGitHubテンプレート GitHub Actions 公式のCloud Formation
  27. 92 code locationの設定 location_name: my_dagster_project image:{aws_account_id}.dkr.ecr.ap-northeast-1.amazonaws.com/dagster-image:latest code_source: package_name: my_dagster_project build:

    directory: ./ registry:{aws_account_id}.dkr.ecr.ap-northeast-1.amazonaws.com/dagster-image:latest container_context: ecs: run_resources: cpu: "1024" memory: "2048" ECS Taskの起動image imageが自動buildされる ECS Taskのリソース設定 dagster_cloud.yaml Dagster Cloudに登録するcode locationの設定ファイル
  28. { "StartAt": "RunCrawler", "States": { // 中略 "ETL": { "Type":

    "Task", "Resource": "arn:aws:states:::glue:startJobRun.sync", "Parameters": { "JobName": "etlandpipeline" }, "Next": "StartTrainingJob" }, "StartTrainingJob": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:547760918250:function:lambdaModelTrain", "ResultPath": "$", "Next": "CheckStatusTraining" }, "CheckStatusTraining": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:547760918250:function:lambdaModelAwait", "ResultPath": "$", "Next": "CheckTrainingBranch" }, // 中略 } } 98 実装例(JSON) 実行するAWSリソースを指定 JSON形式のAmazonステートメント言語で ワークフローを記述 次の実行タスクの指定
  29. 6つのワークフローツールの特徴比較 Step Functions 特徴 シンプル 手軽 k8sと連携 Python DAG 活用事例が豊富

    自然なPython 記法での開発 データ運用に特化 サーバレス AWSサービス ワークフロー 実装言語 digファイル (YAML) k8s manifest (YAML) Python (Operator) Python (Flow) Python (Job) GUI操作 JSON 利用形態 OSS OSS OSS SaaS クラウドマネージド OSS SaaS OSS SaaS クラウドマネージド 学習コスト 低 中 高 高 高 低
  30. 108 Redditの議論 Orchestration: Thoughts on Dagster, Airflow and Prefect? Dagster:

    11 Prefect : 5 Airflow : 1 AirflowからDagster・Prefect・他ツールに移行した人が多い 好意的なコメント数
  31. 111 運用していたMLワークフロー N個のモデルの学習が毎日M回行われる データ取得 前処理 学習 オフライン評価 オンライン評価 データ分布評価 モデルデプロイ

    データ取得 前処理 学習 オフライン評価 データ取得 前処理 学習 オフライン評価 ・・・ 並列 実行 でワークフローを定期実行
  32. 112 運用していたMLワークフロー ECS Taskでタスクを実行 データ取得 前処理 学習 オフライン評価 オンライン評価 データ分布評価

    モデルデプロイ データ取得 前処理 学習 オフライン評価 データ取得 前処理 学習 オフライン評価 ・・・ ECS Task ECS Task ECS Task ECS Task でタスク実行を制御
  33. 118 Prefect移行後のイメージ 118 オンライン評価 データ分布評価 モデルデプロイ データ取得 前処理 学習 オフライン評価

    ・・・ ECS Task ECS Task ECS Task ECS Task ・ワークフローツールだけ変える ・既存のアプリケーションコードは変えない 変える・変えない要素
  34. 123 参考文献 • A Brief History of Workflow Orchestration •

    An Introduction to Workflow Orchestration • https://github.com/meirwah/awesome-workflow-engines • Data Orchestration: Definition, Parts, Examples, and Benefits • データエンジニアが最初に学ぶべき3つのポイント:「ETL」「データモデリング」「ワークフロー」 • [最終回] データパイプラインのためのワークフロー管理 • データパイプラインの管理 • Argo vs Airflow vs Prefect: How Are They Different • DigdagはなぜYAMLなのか? • 実践的データ基盤への処方箋〜 ビジネス価値創出のためのデータ・システム・ヒトのノウハウ • Orchestration: Thoughts on Dagster, Airflow and Prefect?