Weitere ähnliche Inhalte
Ähnlich wie AWS Glueを使った Serverless ETL の実装パターン (20)
Kürzlich hochgeladen (12)
AWS Glueを使った Serverless ETL の実装パターン
- 3. 3よくある話を少しする
AWS IoT Core Firehose S3
Amazon Athena
Amazon Redshift
Amazon EMR
Amazon QuickSight
Collection VisualizationAnalysis
- 4. 4よくある話を少しする
AWS IoT Core Firehose S3
Amazon Athena
Amazon Redshift
Amazon EMR
Amazon QuickSight
Collection VisualizationAnalysis
時系列データ
を収集
分析処理
ダッシュボード
で可視化
- 5. 5よくある話を少しする
AWS IoT Core Firehose S3
Amazon Athena
Amazon Redshift
Amazon EMR
Amazon QuickSight
Collection VisualizationAnalysis
時系列データ
を収集
分析処理
ダッシュボード
で可視化
そのままでは使えない場合が多い
データフォーマットがバラバラ
非構造化/半構造化データなど
- 7. 7ETL処理が必要
AWS IoT Core Firehose S3
Amazon Athena
Amazon Redshift
Amazon EMR
Amazon QuickSight
Collection VisualizationAnalysis
時系列データ
を収集
分析処理
ダッシュボード
で可視化
LoadTransformExtract
- 11. 11AWS Glueとは?
※ https://aws.amazon.com/jp/glue/ から引用
AWS Glue は抽出、変換、ロード (ETL) を行う完全マネージド型のサービスで、お
客様の分析用データの準備とロードを簡単にします。AWS マネジメントコンソール
で数回クリックするだけで、ETL ジョブを作成および実行できます。AWS Glue で
は、AWS に保存されたデータを指定するだけで AWS Glue によるデータ検索が行
われ、テーブル定義やスキーマなどの関連するメタデータが AWS Glue データカタ
ログに保存されます。
- 27. 27蓄積されているデータ
AWS IoT Core Firehose S3
IoT
sensor
IoT
sensor
[
{
"device_id": "A",
"timestamp": 1593007044,
"location": {
"lat": "35.698362",
"long": "139.773288"
}
}
…
- 28. 28蓄積されているデータ
AWS IoT Core Firehose S3
IoT
sensor
IoT
sensor
[
{
"device_id": "A",
"timestamp": 1593007044,
"location": {
"lat": "35.698362",
"long": "139.773288"
}
}
…
項目名を変えたい
- 29. 29蓄積されているデータ
AWS IoT Core Firehose S3
IoT
sensor
IoT
sensor
[
{
"device_id": "A",
"timestamp": 1593007044,
"location": {
"lat": "35.698362",
"long": "139.773288"
}
}
…
データ型を変えたい
- 37. 37実演の振り返り
AWS IoT Core Firehose S3
IoT
sensor
IoT
sensor
Amazon Redshift
AWS glue data
catalog
Crawler
AWS IoT Core Firehose S3
IoT
sensor
IoT
sensor
Amazon RedshiftAWS Glue Job
ETL
- 41. 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 … など多数
- 42. AWS Step Functions workflow
42Glue Workflow と StepFunctionsの比較
多少難易度は高いが、StepFunctionのほうが柔軟
AWS Glue
Workflow
AWS Step
Functions
複雑さ 低 中
柔軟さ 低 高
連携先 少ない 多い
- 56. 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. 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
Crawler
S3 AWS Glue Job
glue/aws-glue-libs/bin/
├── glue-setup.sh
├── gluepyspark
├── gluepytest
└── gluesparksubmit
.py
Pytestを利用する
- 58. テストコードを用意
58② 簡単なテストコードを用意
import sys
from 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
Crawler
S3 AWS Glue Job
.py
- 59. ソースコード
59② 簡単なソースコードを用意
def main_job():
# 引数取得
args = getResolvedOptions(sys.argv, [
"JOB_NAME",
"DB_NAME",
"TBL_NAME",
"OUTPUT_DEST",
])
# セットアップ
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args["JOB_NAME"], args)
# コミット
job.commit()
Amazon Redshift
Spectrum
S3
AWS Cloud
AWS glue data
catalog
Crawler
S3 AWS Glue Job
.py
- 60. Pytestを実行
60② pytestの実行
※ AWS のクレデンシャル情報をセットするのをお忘れなく
$ glue/aws-glue-libs/bin/gluepytest test/pyspark/test_timeseries_etl.py
Amazon Redshift
Spectrum
S3
AWS Cloud
AWS glue data
catalog
Crawler
S3 AWS Glue Job
.py
- 61. ソースコード
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
Crawler
S3 AWS Glue Job
.py
- 62. 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
Crawler
S3 AWS Glue Job
.py
- 63. 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
Crawler
S3 AWS Glue Job
.py
- 64. テストコード
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
Crawler
S3 AWS Glue Job
.py
- 65. 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.in
terpreterPath}",
"SPARK_CONF_DIR": "${workspaceRoot}/glue/aws-
glue-libs/conf",
"AWS_SECRET_ACCESS_KEY": “<your_access_key>",
"AWS_ACCESS_KEY_ID": "<your_key_id>",
"AWS_SESSION_TOKEN": "<your_token>"
},
"console": "internalConsole",
"internalConsoleOptions": "openOnSessionStart“
}
Amazon Redshift
Spectrum
S3
AWS Cloud
AWS glue data
catalog
Crawler
S3 AWS Glue Job
.py
- 68. ソースコード
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
Crawler
S3 AWS Glue Job
.py
- 71. テストコード
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"] == 200
job_run_id = exec_res["JobRunId"]
Amazon Redshift
Spectrum
S3
AWS Cloud
AWS glue data
catalog
Crawler
S3 AWS Glue Job
- 72. テストコード
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
Crawler
S3 AWS Glue Job
- 75. 75AWS Glueリソースのデプロイ
AWS Glue Job
AWS glue data
catalog
Crawler
AWS Cloud
# Glue
resource "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.n
ame
role = aws_iam_role.glue_iam_role.arn
schedule = "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.arn
timeout = 60
max_capacity = 2
glue_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"
…省略
- 78. 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"
イベントソースの定義 受け取れるイベント