82
AWS Glueを使った Serverless ETL の実装パターン 新井 成一 CX事業本部 MADチーム

AWS Glueを使った Serverless ETL の実装パターン2020/07/03  · Amazon QuickSight Collection Analysis Visualization 時系列データ を収集 分析処理 ダッシュボード

  • Upload
    others

  • View
    14

  • Download
    0

Embed Size (px)

Citation preview

  • AWS Glueを使ったServerless ETL の実装パターン

    新井成一CX事業本部MADチーム

  • 2自己紹介

    CX事業本部MADチーム所属

    サーバーサイドエンジニア

    普段の業務API/IoT用のバックエンドの仕組みをAWSで構築&開発

    データ分析&可視化する前のETL処理 ← ここ最近

  • 3よくある話を少しする

    AWS IoT Core Firehose S3

    Amazon Athena

    Amazon Redshift

    Amazon EMR

    Amazon QuickSight

    Collection VisualizationAnalysis

  • 4よくある話を少しする

    AWS IoT Core Firehose S3

    Amazon Athena

    Amazon Redshift

    Amazon EMR

    Amazon QuickSight

    Collection VisualizationAnalysis

    時系列データを収集

    分析処理ダッシュボードで可視化

  • 5よくある話を少しする

    AWS IoT Core Firehose S3

    Amazon Athena

    Amazon Redshift

    Amazon EMR

    Amazon QuickSight

    Collection VisualizationAnalysis

    時系列データを収集

    分析処理ダッシュボードで可視化

    そのままでは使えない場合が多い

    データフォーマットがバラバラ非構造化/半構造化データなど

  • 6

    ETL処理が必要

  • 7ETL処理が必要

    AWS IoT Core Firehose S3

    Amazon Athena

    Amazon Redshift

    Amazon EMR

    Amazon QuickSight

    Collection VisualizationAnalysis

    時系列データを収集

    分析処理ダッシュボードで可視化

    LoadTransformExtract

  • 8

    『ETLで使えるAWSサービスは?』

  • 9AWS ETL で検索すると

  • 10

    『なんか良さそう!』

  • 11AWS Glueとは?

    ※ https://aws.amazon.com/jp/glue/から引用

    AWS Glue は抽出、変換、ロード (ETL) を行う完全マネージド型のサービスで、お客様の分析用データの準備とロードを簡単にします。AWS マネジメントコンソールで数回クリックするだけで、ETL ジョブを作成および実行できます。AWS Glue では、AWS に保存されたデータを指定するだけで AWS Glue によるデータ検索が行われ、テーブル定義やスキーマなどの関連するメタデータが AWS Glue データカタログに保存されます。

    https://aws.amazon.com/jp/glue/

  • 12AWS Glue のコンソール画面

  • 13

    『なるほど、わからん...』

  • 14今回する・しない話

    今回する話AWS Glueの概要

    AWS Glueを中心としたETL処理の実装方法

    開発/テスト/デプロイ/モニタリング

    今回しない話ETLやサーバーレスの概念の話

    データ分析や可視化の手法の話

    Amazon EMRやAWS Batchの話

  • 15今回の発表の目的

    「AWS Glueというサービスの概要がわかった!」

    「AWS Glueでの実装イメージが湧いた!」

  • 16INDEX

    AWS Glueの概要 10min

    AWS Glueに関連するサービスの話 5min

    ETLの実装パターン 20min開発/テスト/デプロイ/モニタリング

  • 17

    AWS Glue の概要

  • 18

    『AWS Glue』よくわからん…

  • 19なぜわからないのか?

    1. 実態をつかみづらい

    機能が多い

    実は別のサービスの裏側で使われている

    2. 何を指しているのかわからない問題

    『Lambda』≒ Lambda Functionをイメージ

    『Dynamo』≒ DynamoDBのテーブルをイメージ

    『Glue』≒???

  • 20

    AWS Glueのメイン機能は2つ

  • 21AWS Glueのメイン機能

    AWS Glueのテーブルよく言われるデータカタログのこと

    データのスキーマ情報(カラム名やデータ型)を持っている

    データベース毎に管理する

    AWS GlueのジョブETL処理の実行基盤

    3種類から選択可能(Python Shell, Spark, Spark Streaming)

  • 22テーブルとジョブのイメージ

  • 23テーブルとジョブのイメージ

    テーブル

  • 24テーブルとジョブのイメージ

    ジョブ

  • 25

    実演

  • 26例えば

    IoTデバイスからセンサーデータがJSON形式で送信されている

    項目名やデータ型のなど分析基盤側で扱いづらい状態

    AWS IoT Core Firehose S3

    IoT

    sensor

    IoT

    sensor

    Amazon Redshift

    E

    • 保存されている生データを取得

    T

    • カラム名・データ型を変換

    L

    • 分析基盤へロード

    ETL

  • 27蓄積されているデータ

    AWS IoT Core Firehose S3

    IoT

    sensor

    IoT

    sensor

    [{"device_id": "A","timestamp": 1593007044,"location": {"lat": "35.698362","long": "139.773288"

    }}

  • 28蓄積されているデータ

    AWS IoT Core Firehose S3

    IoT

    sensor

    IoT

    sensor

    [{"device_id": "A","timestamp": 1593007044,"location": {"lat": "35.698362","long": "139.773288"

    }}

    項目名を変えたい

  • 29蓄積されているデータ

    AWS IoT Core Firehose S3

    IoT

    sensor

    IoT

    sensor

    [{"device_id": "A","timestamp": 1593007044,"location": {"lat": "35.698362","long": "139.773288"

    }}

    データ型を変えたい

  • 30テーブルの作成

    S3

    AWS glue data

    catalog

    Crawler

    クローラーでテーブルを自動作成

  • 31テーブルの作成

    テーブルスキーマが登録される

    S3

    AWS glue data

    catalog

    Crawler

  • 32ジョブの作成

    Glueが自動生成してくれるスクリプトを利用

  • 33ジョブの作成

    データソースの指定 データターゲットの指定

    ※Redshit ClusterやGlue Connectionは事前に作成済

  • 34ジョブの作成

    データのマッピングを指定

  • 35ジョブの作成

    Glue Jobのスクリプトが自動生成される

  • 36ジョブの実行

    Redshiftにデータが投入される

  • 37実演の振り返り

    AWS IoT Core Firehose S3

    IoT

    sensor

    IoT

    sensor

    Amazon Redshift

    AWS glue data

    catalog

    CrawlerAWS IoT Core Firehose S3

    IoT

    sensor

    IoT

    sensor

    Amazon RedshiftAWS Glue Job

    ETL

  • 38

    イメージ湧きましたか?

  • 39その他〜AWS Glueの機能〜

    ワークフロー

    ジョブやクローラの実行順序を定義できる

    トリガー

    ジョブやクローラーを起動タイミングを制御できる

    スケジュール実行などが可能

    開発エンドポイント

    Glue Jobと同等の実行環境を用意してくれる

    ジョブのスクリプトを開発するのに利用できる

  • 40

    AWS Glueに関連するサービスの話

  • 41Glue JobとLambdaの比較

    並列度を上げて処理したい場合はLambdaを検討すべき

    ※2020/06/04時点での東京リージョンでの比較

    AWS Glue Job (Python Shell) AWS Glue Job (Spark) AWS Lambda

    メモリ 1GB or 16GB 32GB - 128 - 3,008 MB

    実行時間 デフォルトで48h デフォルトで48h 最大15min

    同時実行数 アカウント内で50 アカウント内で50 リージョン毎に1,000

    課金額 従量課金≒性能 * 実行時間(s)(ただし最小10分)

    従量課金≒性能 * 実行時間(s)(ただし最小10分)

    従量課金≒性能 * 実行時間(100ms)

    起動のオーバーヘッド

    数十秒 -数分 数十秒 -数分 数ミリ秒 -数秒

    言語 Python Python or Scala Python, Node.js … など多数

  • AWS Step Functions workflow

    42Glue Workflow と StepFunctionsの比較

    多少難易度は高いが、StepFunctionのほうが柔軟

    AWS Glue

    Workflow

    AWS Step

    Functions

    複雑さ 低 中

    柔軟さ 低 高

    連携先 少ない 多い

  • 43実は裏側でGlueを使っているサービス

    AthenaのCREATE TABLEはGlueのデータカタログを利用

  • 44

    実装パターンの紹介

  • 45

    これ以降

    PySpark, Python Shell

    を前提とした話になります

  • 46実装の手順

    開発 テスト デプロイ モニタリング

  • 47開発とテスト

    開発 テスト デプロイ モニタリング

  • 48開発とテストのパターン

    LocalStack

    .py

    AWS Cloud AWS Cloud AWS Cloud

    AWS Glue

    開発エンドポイントAWS Glue Job

    .py

    ① ② ③ ④

    AWS Services

  • 49開発とテストのパターン

    LocalStack

    .py

    AWS Cloud AWS Cloud AWS Cloud

    AWS Glue

    開発エンドポイントAWS Glue Job

    .py

    ① ② ③ ④

    AWS Services

    実行環境がローカル

    実行環境がAWS Glue

  • 50開発とテストのパターン

    実行環境がローカルなので、デバッグやテストがやりやすい

    ジョブの実行時に発生する権限エラーやOMMなどには気づきにくい

    Sparkを利用する場合は、実行環境を整

    えるのが手間(バージョンの不一致やaws-glue-libsの既存の不具合などでハマ

    りやすい)、ある程度のマシンスペックが必要

    ①のケースでは、モックツールで利用可能なAWSサービスが限られていたり、モックツール自体の不具合がある

    LocalStack

    .py

    AWS Cloud

    .py

    ① ②

    AWS Services

  • 51開発とテストのパターン

    コードの実行環境がAWSなので、権限

    やメモリ割り当て量が適切か確認しやすい

    実行時間が計測しやすい

    AWS利用費が高くなりがち

    ④のケースでは、ジョブの終了までか

    なりの時間待たされるので、デバッグしずらい

    AWS Cloud AWS Cloud

    AWS Glue

    開発エンドポイントAWS Glue Job

    ③ ④

  • 52今回紹介するパターン

    ② ④

    LocalStack

    .py

    AWS Cloud AWS Cloud AWS Cloud

    AWS Glue

    開発エンドポイントAWS Glue Job

    .py

    ① ③

    AWS Services

  • 53

    これ以降コードが出てきますが

    分かりやすさ重視のため

    不要な箇所は省略しています

  • 54② AWSサービスを利用したローカル実行

    AWS Cloud

    .py

    AWS Services

  • 55②事前のセットアップ

    ※ https://docs.aws.amazon.com/ja_jp/glue/latest/dg/aws-glue-programming-etl-libraries.htmlを参照

    Version

    Python 3.6.9

    aws-glue-libs glue-1.0

    Apache Maven 3.6.0

    Apache Spark 2.4.3

    boto3 1.14.13

    pytest 5.4.3

    AWS Cloud

    .py

    AWS Services

    ※ aws-glue-libsの不具合: https://github.com/awslabs/aws-glue-libs/issues/25

    https://docs.aws.amazon.com/ja_jp/glue/latest/dg/aws-glue-programming-etl-libraries.htmlhttps://github.com/awslabs/aws-glue-libs/issues/25

  • 56②事前のセットアップ

    AWS Cloud

    .py

    AWS Services

    Dockerfileを作成するのもアリ

    Version

    Python 3.6.9

    aws-glue-libs glue-1.0

    Apache Maven 3.6.0

    Apache Spark 2.4.3

    boto3 1.14.13

    pytest 5.4.3

  • 57② aws-glue-libsにPytestが用意されている

    Amazon Redshift

    Spectrum

    S3

    AWS Cloud

    $ git clone -b glue-1.0 --depth 1

    https://github.com/awslabs/aws-glue-libs glue/aws-glue-libs

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

    glue/aws-glue-libs/bin/

    ├── glue-setup.sh

    ├── gluepyspark

    ├── gluepytest

    └── gluesparksubmit

    .py

    Pytestを利用する

  • テストコードを用意

    58②簡単なテストコードを用意

    import sysfrom src.pyspark.timeseries_etl import main_job

    class TestClass(object):

    def test_run_job(self):

    # 引数を指定args = {

    "--JOB_NAME": "timeseries_etl","--DB_NAME": "arai-test-

    devio2020_database","--TBL_NAME": "timeseries_data","--OUTPUT_DEST": "s3://arai-test-

    devio2020/pyspark-output",}sys.argv += [item for pair in args.items() fo

    r item in pair]

    # ジョブを起動main_job()

    Amazon Redshift

    Spectrum

    S3

    AWS Cloud

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

    .py

  • ソースコード

    59②簡単なソースコードを用意

    def main_job():

    # 引数取得args = getResolvedOptions(sys.argv, [

    "JOB_NAME","DB_NAME","TBL_NAME","OUTPUT_DEST",

    ])

    # セットアップsc = SparkContext()glueContext = GlueContext(sc)spark = glueContext.spark_sessionjob = Job(glueContext)job.init(args["JOB_NAME"], args)

    # コミットjob.commit()

    Amazon Redshift

    Spectrum

    S3

    AWS Cloud

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

    .py

  • Pytestを実行

    60② pytestの実行

    ※ AWS のクレデンシャル情報をセットするのをお忘れなく

    $ glue/aws-glue-libs/bin/gluepytest test/pyspark/test_timeseries_etl.pyAmazon Redshift

    Spectrum

    S3

    AWS Cloud

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

    .py

  • ソースコード

    61②徐々に育てていく

    # DynamicFrameの作成src_timeseries_dyf = glueContext.create_dynamic_f

    rame.from_catalog(database=args["DB_NAME"],table_name=args["TBL_NAME"],transformation_ctx="src_timeseries_dyf"

    )

    # マッピングmapping_list = [

    ("device_id", "string", "device_id", "string"),

    ("timestamp", "int", "timestamp", "int"),("location.lat", "string", "latitude", "doubl

    e"),("location.long", "string", "longitude", "dou

    ble")]map_timeseries_dyf = ApplyMapping.apply(

    frame=src_timeseries_dyf,mappings=mapping_list,transformation_ctx="timeseries_map_dyf"

    )

    Amazon Redshift

    Spectrum

    S3

    AWS Cloud

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

    .py

  • DataFrameへの変換

    62② SparkのDataFrameも活用

    # DataFrameに変換timeseries_df = map_timeseries_dyf.toDF()

    # カラム追加timeseries_df = timeseries_df.withColumn(

    "year", from_unixtime('timestamp', 'yyyy'))timeseries_df = timeseries_df.withColumn(

    "month", from_unixtime('timestamp', 'MM'))

    # 再パーティショニングtimeseries_df = timeseries_df.repartition('year',

    'month', 'device_id')

    # DataframeをDynamicFrameに変換timeseries_dyf = DynamicFrame.fromDF(

    timeseries_df, glueContext, "timeseries_dyf")

    Amazon Redshift

    Spectrum

    S3

    AWS Cloud

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

    .py

  • S3へ保存

    63②テスト用のバケットに出力し中身をチェック

    # 保存save_timeseries_dyf = glueContext.write_dynamic_f

    rame.from_options(frame=timeseries_dyf,connection_type="s3",connection_options={

    "path": args["OUTPUT_DEST"],"partitionKeys": [

    "year","month","device_id"

    ]},format="parquet",transformation_ctx="save_timeseries_dyf"

    )

    Amazon Redshift

    Spectrum

    S3

    AWS Cloud

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

    .py

  • テストコード

    64②テストの前後処理や結果のチェックを実装

    def pytest_runtest_setup():print('¥n-----setup-----¥n')# テストデータの作成TEST_BUCKET.create()

    …省略

    def pytest_runtest_teardown():print('¥n-----teardown-----¥n')# テストデータの削除TEST_BUCKET.objects.all().delete()

    …省略

    def test_run_job(self):…省略

    main()

    # 結果の取得res_data = self.get_result_data()# 正解の取得corr_data = self.get_correct_data()

    # 結果の確認assert res_data == corr_data

    Amazon Redshift

    Spectrum

    S3

    AWS Cloud

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

    .py

  • launch.json

    65②うまく設定すればデバッグ実行も可能

    {"name": "PyTest Glue","type": "python","request": "launch","stopOnEntry": false,"pythonPath": "${command:python.interpreterPath}","module": "pytest",“args”: [“-svv”, "${file}", "--color", "yes"],"cwd": "${workspaceRoot}","env": {"PYTHONPATH": "${workspaceRoot}/glue/aws-glue-

    libs:/usr/local/spark/python/lib/py4j-0.10.7-src.zip:/usr/local/spark/python/:${command:python.interpreterPath}",

    "SPARK_CONF_DIR": "${workspaceRoot}/glue/aws-glue-libs/conf",

    "AWS_SECRET_ACCESS_KEY": “","AWS_ACCESS_KEY_ID": "","AWS_SESSION_TOKEN": ""

    },"console": "internalConsole","internalConsoleOptions": "openOnSessionStart“

    }

    Amazon Redshift

    Spectrum

    S3

    AWS Cloud

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

    .py

  • 66② AWSサービスを利用したローカル実行

    AWS Cloud

    .py

    AWS Services

  • 67②事前のセットアップ

    Version

    Python 3.6.9

    boto3 1.14.13

    pytest 5.4.3

    Pandas 0.25.1

    AWS Cloud

    .py

    AWS Services

  • ソースコード

    68② Pandasが便利

    def main(plant_id_dpac, current_date):# 引数取得args = getResolvedOptions(sys.argv, [

    "JOB_NAME","DB_NAME","TBL_NAME","OUTPUT_DEST",

    ])

    # データの取得timeseries_list = get_timeseries_list()

    # 該当データがなければ即終了if not timeseries_list:

    logger.info("Timeseries data not found.")return

    # pandasのDataframeに変換timeseries_df = pd.DataFrame(timeseries_list)

    # TODO: 業務処理…省略

    Amazon Redshift

    Spectrum

    S3

    AWS Cloud

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

    .py

  • 69④ AWS Glue Job を直接実行して確認

    AWS Cloud

    AWS Glue Job

  • 70④事前のセットアップ

    AWS Cloud

    AWS Glue Job

    Version

    Python 3.6.9

    boto3 1.14.13

    pytest 5.4.3

  • テストコード

    71④ PytestでE2Eテストを実行

    def test_exec_job(self, mocker):

    # 引数をオーバーライドしてジョブを実行exec_res = glue_client.start_job_run(

    JobName=pytest.JOB_NAME,Arguments={

    "--DB_NAME": "arai-test-devio2020_database",

    "--TBL_NAME": "timeseries_data","—-OUTPUT_DEST”: "s3://arai-test-

    devio2020/pyspark-output"}

    )

    # ジョブの起動が成功していることを確認assert exec_res["ResponseMetadata"]["HTTPStatusCo

    de"] == 200job_run_id = exec_res["JobRunId"]

    Amazon Redshift

    Spectrum

    S3

    AWS Cloud

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

  • テストコード

    72④ Glue Jobが完了するのを待って結果の確認

    …省略

    # ジョブが完了するまで待つjob_status = wait_until_job_finished(pytest.JOB_N

    AME, job_run_id, 300)

    # ジョブが成功していることを確認assert job_status == "SUCCEEDED"

    # テスト結果の取得df_test_res = self.get_result_by_dataframe()

    # 結果の確認assert_frame_equal(df_test_res, df_corr_res)

    Amazon Redshift

    Spectrum

    S3

    AWS Cloud

    AWS glue data

    catalog

    CrawlerS3 AWS Glue Job

  • 73デプロイ

    開発 テスト デプロイ モニタリング

  • 74ソースコードと外部ライブラリのデプロイAWS Cloud

    from setuptools import setup

    setup(name="pandas",version="0.25.1",packages=[],install_requires=['pandas==0.25.1']

    )

    $ python setup.py bdist_wheel

    S3

    .py .whl

    AWS Glue Job

    参照

    Upload

  • 75AWS Glueリソースのデプロイ

    AWS Glue JobAWS glue data

    catalog

    Crawler

    AWS Cloud

    # Glueresource "aws_glue_catalog_database" "database" {name = "${var.system_name}_database"

    }

    resource "aws_glue_crawler" "timeseries_crawler" {name = "${var.system_name}_timeseries_crawler"

    database_name = aws_glue_catalog_database.database.namerole = aws_iam_role.glue_iam_role.arnschedule = "cron(0 */1 * * ? *)"table_prefix = "timeseries_"

    s3_target {path = "s3://${var.system_name}/Data"

    }}

    resource "aws_glue_job" "timeseries_etl" {name = "${var.system_name}_timeseries_etl"command {script_location = "s3://${var.system_name}/glue-

    script/pyspark/timeseries_etl.py"python_version = 3

    }role_arn = aws_iam_role.glue_iam_role.arntimeout = 60max_capacity = 2glue_version = "1.0"default_arguments = {"--job-language" = "python""--enable-metrics" = "true""--extra-py-

    files" = "s3://${var.system_name_prefix}-artifacts-store/glue/modules/pandas-0.25.1-py3-none-any.whl"

    "--job-bookmark-option" = "job-bookmark-enable"…省略

  • 76モニタリング

    開発 テスト デプロイ モニタリング

  • 77AWS Glue Jobでジョブメトリクスを有効化

    CloudWatch Metrics

  • 78アラート通知

    AWS Glue Job Amazon CloudWatch

    Events

    Amazon Simple

    Notification Service

    AWS Lambda Amazon CloudWatch

    Metrics

    …省略"source": "aws.glue","detail-type": "Glue Job State Change","time": "2020-01-09T09:33:40Z","region": "ap-northeast-1","resources": [],"detail": {"jobName": "glue-job-for-err-notification","severity": "ERROR","state": "FAILED","jobRunId": "jr_a56a071553c6038a20f1578f74a013

    6c94e1ea946a3e9516322b4b2bd2e3a5f4","message": "Command failed with exit code 1"

    イベントソースの定義 受け取れるイベント

  • 79Complete!

    開発 テスト デプロイ モニタリング

  • 80目的は達成できたか?

    「AWS Glueというサービスの概要がわかった!」

    「AWS Glueでの実装イメージが湧いた!」

  • 81

    ご清聴ありがとうございました