【AWS】Amazon EMR ~ チュートリアルのすすめ ~

■ はじめに

最近、EMRに対して悪戦苦闘していて
開き直って、チュートリアルを行ったら
少し道が開いた感じになったので、
EMRのチュートリアルに関する有用性も含めてメモる。

目次

【1】EMRのチュートリアルの有用性
 1)ハマりポイントの回避
【2】チュートリアル
 0)前提条件
 ステップ 1: Amazon EMR クラスターを計画して設定する
 ステップ 2: Amazon EMR クラスターを管理する
 ステップ 3: Amazon EMR リソースをクリーンアップする
【3】トラブル
 エラー「AmazonS3Exception: Access Denied Status Code: 403」が発生する

【1】EMRのチュートリアルの有用性

1)ハマりポイントの回避

EMRには、以下の点でハマりポイントが(個人的には)多い
~~~~~~~~~~~
* IAMロール
* Security Group(Master/Slave/ServiceAccessなど)
など
~~~~~~~~~~~

また、エラーになった場合、起動前だとログすらでなく
エラーメッセージだけで判断しなくてはならず滅茶苦茶しんどい。

それらを事前に簡単な例でStepByStepでき、
次に自分のやりたい構成でやるのに、
動いていた実績のあるIAMロールやSecurity Groupを使って
構築できるので、もし、エラーが出ても変更した部分に
絞り込めるので、トラフィックルーティングも比較的に楽。

【2】チュートリアル

以下の公式ドキュメント

https://docs.aws.amazon.com/ja_jp/emr/latest/ManagementGuide/emr-gs.html

のチュートリアルは、分かりやすくて、シンプルでいい。

0)前提条件

* 以下を作成しておくこと
 + EMR用のS3バケット

補足:SG/IAMロールについて

* 本当は、以下を作成しておいた方がいいが、初めは、デフォルトで身を任せるのが吉、、、
 + Master/Slave/ServiceAccess 用のセキュリティグループ(Security Group)
 + IAMロール Service-linkedロール/EMR ロール/EC2 インスタンスプロファイル
 => 以下の関連記事を参照。

Amazon EMR ~ ネットワーク周り ~
https://dk521123.hatenablog.com/entry/2022/05/13/155755
Amazon EMR ~ IAM Role周り ~
https://dk521123.hatenablog.com/entry/2023/07/24/160124

ステップ 1: Amazon EMR クラスターを計画して設定する

[a] EMR PySpark 用のサンプルスクリプトを準備するには

[1] 以下「health_violations.py」をS3バケット内に保存
 => e.g. s3://your-s3-bucket/emr/health_violations.py

health_violations.py

import argparse

from pyspark.sql import SparkSession

def calculate_red_violations(data_source, output_uri):
    """
    Processes sample food establishment inspection data and queries the data to find the top 10 establishments
    with the most Red violations from 2006 to 2020.

    :param data_source: The URI of your food establishment data CSV, such as 's3://DOC-EXAMPLE-BUCKET/food-establishment-data.csv'.
    :param output_uri: The URI where output is written, such as 's3://DOC-EXAMPLE-BUCKET/restaurant_violation_results'.
    """
    with SparkSession.builder.appName("Calculate Red Health Violations").getOrCreate() as spark:
        # Load the restaurant violation CSV data
        if data_source is not None:
            restaurants_df = spark.read.option("header", "true").csv(data_source)

        # Create an in-memory DataFrame to query
        restaurants_df.createOrReplaceTempView("restaurant_violations")

        # Create a DataFrame of the top 10 restaurants with the most Red violations
        top_red_violation_restaurants = spark.sql("""SELECT name, count(*) AS total_red_violations 
          FROM restaurant_violations 
          WHERE violation_type = 'RED' 
          GROUP BY name 
          ORDER BY total_red_violations DESC LIMIT 10""")

        # Write the results to the specified output URI
        top_red_violation_restaurants.write.option("header", "true").mode("overwrite").csv(output_uri)

if __name__ == "__main__":
    print("Starting!!")
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--data_source', help="The URI for you CSV restaurant data, like an S3 bucket location.")
    parser.add_argument(
        '--output_uri', help="The URI where output is saved, like an S3 bucket location.")
    args = parser.parse_args()
    print("* Args start ***************")
    print(args)
    print("* Args end ***************")

    calculate_red_violations(args.data_source, args.output_uri)
    print("Done...")

[b] EMR 用のサンプル入力データを準備するには

[1] 以下からサンプルデータをダウンロードし、ZIPを解凍する

https://docs.aws.amazon.com/ja_jp/emr/latest/ManagementGuide/samples/food_establishment_data.zip

[2] 解凍したフォルダをS3バケットに置く
 => e.g. s3://your-s3-bucket/emr/food_establishment_data/food_establishment_data.csv

ステップ 2: Amazon EMR クラスターを管理する

[a] Spark アプリケーションを新しいコンソールでステップとして送信するには

[1] AWS Management Console にサインインして、Amazon EMR 画面を表示する

https://console.aws.amazon.com/emr

[2] 左側のナビゲーションペインの [EMR on EC2]-[Clusters] を選択し、
 作業を送信するクラスターを選択
 => クラスターの状態は [待機中(Waiting)] である必要がある
[3] [ステップ(Step)] タブを選択し、[ステップの追加(Add Step)] を選択
[4] 次のガイドラインに従ってステップを設定します。
 * 「タイプ」で「Spark アプリケーション」を選択
  Deploy モード、アプリケーションの場所、Spark 送信オプションのフィールドが追加
 * [名前] に新しい名前を入力
 * [アプリケーションの場所] には、Amazon S3 health_violations.py 内のスクリプトの場所
  (s3://DOC-EXAMPLE-BUCKET/health_violations.py など) を入力
 * Spark 送信オプションフィールドは空のまま
 * [引数] フィールドに、次の引数と値を入力
~~~~
--data_source s3://DOC-EXAMPLE-BUCKET/food_establishment_data.csv --output_uri s3://DOC-EXAMPLE-BUCKET/myOutputFolder                       
~~~~
 * 「ステップが失敗した場合のアクション」では、デフォルトのオプション「続行(Continue)」をそのまま

[5] [追加] を選択して、ステップを送信
 ステップが、[保留中] というステータスでコンソールに表示
[6] [保留中] から [実行中]、[完了] に変わるはず
 コンソールのステータスを更新するには、フィルターの右側にある更新アイコンを選択
 ステータスが「完了」に変わると、ステップは正常に完了

[b] 動作確認

[1] 成功していれば、S3内に以下のようなファイルが出力されているはず
 => health_violations.py 結果の例を次に示します。
~~~~~~~~~~
name, total_red_violations
SUBWAY, 322
T-MOBILE PARK, 315
WHOLE FOODS MARKET, 299
PCC COMMUNITY MARKETS, 251
TACO TIME, 240
MCDONALD'S, 177
THAI GINGER, 153
SAFEWAY INC #1508, 143
TAQUERIA EL RINCONSITO, 134
HIMITSU TERIYAKI, 128   
~~~~~~~~~~

ステップ 3: Amazon EMR リソースをクリーンアップする

[a] クラスターを終了する

[1] [Clusters] を選択し、終了するクラスターを選択
[2] 「アクション」ドロップダウンメニューで、「クラスターの終了」を選択
[3] ダイアログボックスで「終了」を選択
 => クラスター設定によっては、終了に 5~10 分間かかる場合がある

[b] S3 リソースを削除する

[1] S3バケット内の以下のファイルを削除する 
 * PySparkスクリプト
 * 入力データセット
 * 出力結果フォルダ
 * ログファイルフォルダ

【3】トラブル

1)エラー「AmazonS3Exception: Access Denied Status Code: 403」が発生する

エラー内容

Caused by:
com.amazon.ws.emr.hadoop.fs.shaded.com.amazonaws.services.s3.model.AmazonS3Exception:
Access Denied (Service: Amazon S3; Status Code: 403;
Error Code: AccessDenied; Request ID: REQUEST_ID;
S3 Extended Request ID: S3_EXTENDED_REQUEST_ID

確認点
https://repost.aws/ja/knowledge-center/emr-s3-403-access-denied

[1] Amazon EC2 インスタンスプロファイルロールのポリシーを確認する
[2] Amazon S3 VPC エンドポイントポリシーを確認する

https://youtu.be/hI64CFAjmig?t=485

[3] S3 のレプリケート元およびレプリケート先バケットポリシーを確認

原因

* Slave(EC2インスタンスプロファイル)のIAMロールに
 S3アクセス権限がなかったため。
 => EMR作成時に
 「Amazon EMRのEC2インスタンスプロファイル」の
 「インスタンスプロファイル作成」で「S3バケット」の「
 アカウント内の特定のS3バケットまたはプレフィックス」を選んでしまうと
 発生する可能がある

解決案

* Slave(EC2インスタンスプロファイル)のIAMロールにS3アクセス権限を追加する
 => まずは、切り分けのためにアクションで「"Action": ["s3:*"]」とかしてみるのもありかも。

参考文献
https://docs.aws.amazon.com/ja_jp/emr/latest/ManagementGuide/emr-troubleshoot-error-vpc.html
https://www.youtube.com/watch?v=3nRd9NUfZ14
https://www.youtube.com/watch?v=hI64CFAjmig
https://karukichi-blog.netlify.app/blogs/resolve-403-error-in-s3

関連記事

Amazon EMR ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/02/20/230519
Amazon EMR ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2020/05/27/175610
Amazon EMR ~ boto3 編 ~
https://dk521123.hatenablog.com/entry/2020/06/24/173334
Amazon EMR ~ ネットワーク周り ~
https://dk521123.hatenablog.com/entry/2022/05/13/155755
Amazon EMR ~ IAM Role周り ~
https://dk521123.hatenablog.com/entry/2023/07/24/160124
Amazon VPC ~ 基本編 / VPCエンドポイント ~
https://dk521123.hatenablog.com/entry/2022/03/20/000000
SSHクライアント
https://dk521123.hatenablog.com/entry/2019/10/18/233543
ssh コマンド / scp コマンド
https://dk521123.hatenablog.com/entry/2017/12/09/231200
sshポートフォワーディングを使って、Webサーバにアクセスする
https://dk521123.hatenablog.com/entry/2018/02/08/001413