Amazon EMRのチュートリアルをやってみました

記事タイトルとURLをコピーする

Amazon EMRを一度も利用したことがなかったので、data-analytics-specialty試験の学習ついでに実際にさわりながら自分へのメモを兼ねて情報を残します。

Amazon EMRとは

aws.amazon.com

Apache Spark、Apache Hive、Apache HBase、Apache Flink、Apache Hudi、Presto などのオープンソースのツールを 使用して膨大な量のデータを処理するための業界をリードするビッグデータのクラウドプラットフォーム との事です。

単にBigdata関係のOSSが動くエラスティックなインフラレイヤーを提供するというだけではなく、例えば以下のようなランタイム導入でパフォーマンス面でも付加価値を加えているようです。

Amazon EMR introduces EMR runtime for Apache Spark | AWS Big Data Blog

AWSサービスなので勿論、処理する/したデータでAmazon S3やAmazon Dynamo DB等と連携とかが可能で、過去に以下blogで書きましたが Lake formationとも連動できます。(そういえばEMRを指定できる項目がありました)

blog.serverworks.co.jp

用語の整理

この先、Amazon EMRの専門用語として登場するので、以下ドキュメントを参考に情報を整理しておくと
クラスターハードウェアとネットワークを構成する - Amazon EMR

クラスターとは

EC2インスタンスのコレクションの事を指し、そのクラスター内の各インスタンスはノードと呼ばれます。 Amazon EMR 用のデフォルトAMI または指定するカスタム Amazon Linux AMI を選べるようです。

以下、カスタムAMIに関するページに色々と細かい制約が書かれています。 https://docs.aws.amazon.com/ja_jp/emr/latest/ManagementGuide/emr-custom-ami.html

こちらにある記載を眺めるとOS中がどういう設定やら状態になっているのか想像出来て、なるほどな〜と思える内容も結構あります。

・作成するユーザーをアプリケーションと同じ名前 (hadoop、hdfs、yarn、spark など) にすると、エラーが発生します。
・/tmp、/var、および /emr のコンテンツ (AMI に存在する場合) はスタートアップ時にそれぞれ /mnt/tmp、/mnt/var、および /mnt/emr に移動されます。ファイルは保持されますが、大量のデータがあると、スタートアップに予想以上の時間がかかる場合があります。

クラスターは、以下公式ドキュメントの概要にある図のようにフルメッシュのような構成となります。

Amazon EMR の概要 - Amazon EMR

クラスターの種類

マスターノード

ノード間のデータやタスク分散の調整をするクラスターを管理するノード クラスターには必ずマスターノードが存在しており、最小構成だとマスターノード1台だけでも可能。

コアノード

タスクを実行し、HDFSにデータを保存する機能を持つノード

タスクノード

タスクを実行するのみでHDFSにデータを保存する機能を持たないノード


クラスターへの接続やらオペレーションについては、SSHを利用してマスターノードや必要に応じて他のノードに接続し、 インストール済みのアプリケーションが提供するインタフェースやツール(Hive等のHadoopエコシステム)を利用し、タスク実行する形となります。 あとは、AWSマネジメントコンソールに示されたリンクからブラウザ経由で利用出来るもの(YARN等)もあります。

さわってみる

今回は、公式にあるAmazon EMR によるビッグデータ分析入門 のチュートリアルがありましたのでやってみます。

docs.aws.amazon.com

ざっくりやることは以下です。

・チュートリアル用にS3バケットを1つ、EC2のキーペアを1つ作成
・Amazon EMRのクラスターを新規構築
・クラスターに対し自分のクライアントPCからSSH接続出来るようセキュリティグループで許可
・サンプルで用意されているHiveスクリプトを作成したクラスターにて実行
・データ処理結果を確認
・寄り道(チュートリアルに存在していない ssh接続、WebUIの接続確認 等)
・後片付け(リソース削除)

Step1: サンプルクラスターの前提条件の設定

S3バケット作成

任意の名前でtutorial用のS3バケットを作成します、

% aws s3 mb s3://ytamu-emr-tut
make_bucket: ytamu-emr-tut
%

EC2キーペアの新規作成

当該EMRクラスター専用として作っておくことが推奨となります。 名前は何でも良いですが、今回は emr-tut で作成しました。

% aws ec2 create-key-pair --key-name emr-tut --query 'KeyMaterial' --output text > ~/.ssh/emr-tut.pem
% sudo chmod 400 ~/.ssh/emr-tut.pem
%

Step2.サンプル Amazon EMR クラスターの起動

AWSマネジメントコンソールにて Amazon EMRの画面に接続

AWSのマネジメントコンソールより Amazon EMRを押下し、ようこそ画面より[クラスターの作成]を押下します

f:id:swx-tamura:20201214192929p:plain

クラスター作成に必要な設定項目を指定

以下のようなフォームが表示されるので、今回のチュートリアルで必要な内容を指定していきます。

f:id:swx-tamura:20201223131650p:plain

・クラスター名は My First EMR Cluster とし、
・S3 フォルダーの項目に 先に作成したS3バケットのURI を指定します
・コストを抑えたい場合インタンス数は1でも大丈夫ですが、今回はマスターノード以外も見てみたかったので 2 としました
・EC2キーペアは、先に作成した emr-tut を指定します


注意:ログ記録はクラスターの作成時にのみ有効にする事が出来て、設定は後から変更できません。 とあるので本番利用時には注意が必要そうです。

ソフトウェア設定のリリースについてはデフォルトですが、ドキュメントにも可能な限り最新のリリースバージョンを使用することをお勧めします。とあるのでそこも留意しておいたほうが良さそうです。

あと今回設定しませんでしたが、Cluster Scalingにチェックをつけると上の図にあるように直感的に最小と最大ノードを指定できるフォームが現れます。

(参考) Amazon EMR リリースについて - Amazon EMR

値を指定し、[クラスターを作成]を押下すると作成が始まり、今回の構成で私の環境では2minかからない程度で作成が完了しました。

f:id:swx-tamura:20201214195832p:plain

少し寄り道

せっかくなので他のタブも閲覧してみます。

アプリケーションの履歴 f:id:swx-tamura:20201215102552p:plain


モニタリング
モニタリングのタブの中に更にタブが3つ存在しており、CloudWatchと連動しクラスターステータス、ノードのステータス、IO という形で主要項目が可視化されています。

Amazon EMRのメトリクスに関する内容は以下に纏まっています。
CloudWatch でメトリクスをモニタリングする - Amazon EMR

f:id:swx-tamura:20201215102546p:plain


ハードウェア
裏で稼働しているEC2インスタンスの情報が参照できます。 インスタンスタイプぐらいしか指定した記憶がありませんが、自動的に64GiBのEBSがアタッチされているようです。 ここで注目すべきはコアノードで サイズ変更 が指定できる点と、タスクインスタングループを追加 からタスクノードを追加できる点です。

f:id:swx-tamura:20201225145020p:plain

タスクインスタングループを追加 を押下すると、以下のように追加する EC2インスタンスのタイプや数を指定し、スポットをリクエストが出来ます。

f:id:swx-tamura:20201215102529p:plain


設定
EMR バージョン 5.21.0 以降では、実行中のクラスター内のインスタンスグループごとに、クラスタ設定を上書きして追加の設定分類を指定が可能となっており、設定の一覧画面があります。

実行中のクラスター内のインスタンスグループの設定を指定する - Amazon EMR

f:id:swx-tamura:20201215102523p:plain


イベント
当該クラスターのイベント履歴が確認出来ます。 f:id:swx-tamura:20201215102517p:plain


ステップ
ステップとは、クラスターにインストールされたソフトウェアにより処理するためのデータを操作する指示が含まれる作業単位の事となります(この後のハンズオンでもここに処理を追加していきます)

Amazon EMR の概要 - Amazon EMR

f:id:swx-tamura:20201215102510p:plain

Step.3: クライアントから SSH 接続をクラスターに許可する

セキュリティグループの確認

最初のクラスターを作成すると時にAmazon EMR により、 マスターインスタンスに関連付けられたデフォルトの [ElasticMapReduce-master] コアノードとタスクノードに関連付けられたセキュリティグループ [ElasticMapReduce-slave] が作成されます。

デフォルトの状態で中を覗くとこんな感じになっています。

f:id:swx-tamura:20201214200116p:plain

自端末からSSHを許可

編集より、自分が接続する用途でPublic IPアドレスを SSH(TCP:22)の許可を加えます。

f:id:swx-tamura:20201214200538p:plain

Step4: Hive スクリプトをステップとして実行してデータを処理する

Hive サンプルスクリプトの確認

今回利用するサンプルスクリプトはAWSによって用意されており、以下に格納されています。
s3://region.elasticmapreduce.samples/cloudfront/code/Hive_CloudFront.q

※ regionの文字列は、利用するリージョンに置き換える必要があります

今回私の場合は、東京リージョン(ap-northeast-1)で指定しました。

Hive スクリプトをステップとして送信する

クラスターの「ステップ」タブから [ステップの追加]を押下 f:id:swx-tamura:20201215102452p:plain

上のようにポップアップが表示されるので、

・ステップタイプと名前は Hive プログラム
・スクリプト S3場所は、 上に記載したサンプルスクリプトのURI
・S3の入力ファイルの場所は、サンプルスクリプトの格納DIRまでのURI
・S3の出力ファイルの場所は、Step1で自身で作成したtutorial用のS3バケットのURI
を指定し、[追加]を押下します

f:id:swx-tamura:20201215102447p:plain

処理が完了すると、ログファイルのタブから各ステップでのログを確認することができます。 f:id:swx-tamura:20201215102442p:plain

お目当てのログファイルを押下すると、当該マスターノード(EC2インスタンス)内の生ログを以下のようにブラウザで表示してくれます。

2020-11-17T01:38:57.802Z INFO Ensure step 2 jar file command-runner.jar
2020-11-17T01:38:57.802Z INFO StepRunner: Created Runner for step 2
INFO startExec 'hadoop jar /var/lib/aws/emr/step-runner/hadoop-jars/command-runner.jar hive-script --run-hive-script --args -f s3://ap-northeast-1.elasticmapreduce.samples/cloudfront/code/Hive_CloudFront.q -d INPUT=s3://ap-northeast-1.elasticmapreduce.samples -d OUTPUT=s3://ytamu-emr-tut/'
INFO Environment:
  PATH=/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
  HISTCONTROL=ignoredups
  HISTSIZE=1000
  HADOOP_ROOT_LOGGER=INFO,DRFA
  JAVA_HOME=/etc/alternatives/jre
  AWS_DEFAULT_REGION=ap-northeast-1
  LANG=en_US.UTF-8
  MAIL=/var/spool/mail/hadoop
  LOGNAME=hadoop
  PWD=/
  HADOOP_CLIENT_OPTS=-Djava.io.tmpdir=/mnt/var/lib/hadoop/steps/s-29LO60TWYQ0XU/tmp
  _=/etc/alternatives/jre/bin/java
  LESSOPEN=||/usr/bin/lesspipe.sh %s
  SHELL=/bin/bash
  QTINC=/usr/lib64/qt-3.3/include
  USER=hadoop
  HADOOP_LOGFILE=syslog
  HOSTNAME=ip-172-31-15-180
  QTDIR=/usr/lib64/qt-3.3
  HADOOP_LOG_DIR=/mnt/var/log/hadoop/steps/s-29LO60TWYQ0XU
  EMR_STEP_ID=s-29LO60TWYQ0XU
  QTLIB=/usr/lib64/qt-3.3/lib
  HOME=/home/hadoop
  SHLVL=1
  HADOOP_IDENT_STRING=hadoop
INFO redirectOutput to /mnt/var/log/hadoop/steps/s-29LO60TWYQ0XU/stdout
INFO redirectError to /mnt/var/log/hadoop/steps/s-29LO60TWYQ0XU/stderr
INFO Working dir /mnt/var/lib/hadoop/steps/s-29LO60TWYQ0XU
INFO ProcessRunner started child process 21264
2020-11-17T01:38:57.804Z INFO HadoopJarStepRunner.Runner: startRun() called for s-29LO60TWYQ0XU Child Pid: 21264
INFO Synchronously wait child process to complete : hadoop jar /var/lib/aws/emr/step-runner/hadoop-...
INFO waitProcessCompletion ended with exit code 0 : hadoop jar /var/lib/aws/emr/step-runner/hadoop-...
INFO total process run time: 50 seconds
2020-11-17T01:39:47.988Z INFO Step created jobs:
2020-11-17T01:39:47.989Z INFO Step succeeded with exitCode 0 and took 50 seconds

stderr

Logging initialized using configuration in file:/etc/hive/conf.dist/hive-log4j2.properties Async: false
OK
Time taken: 4.375 seconds
Query ID = hadoop_20201117013914_2f197e01-f59a-49a6-88e3-3fca5edb40ca
Total jobs = 1
Launching Job 1 out of 1
Status: Running (Executing on YARN cluster with App id application_1605576276602_0001)

Map 1: -/-  Reducer 2: 0/2
Map 1: 0/1    Reducer 2: 0/2
Map 1: 0(+1)/1   Reducer 2: 0/2
Map 1: 0(+1)/1   Reducer 2: 0/2
Map 1: 0(+1)/1   Reducer 2: 0/2
Map 1: 0(+1)/1   Reducer 2: 0/2
Map 1: 0(+1)/1   Reducer 2: 0/2
Map 1: 0(+1)/1   Reducer 2: 0/2
Map 1: 0(+1)/1   Reducer 2: 0/2
Map 1: 1/1    Reducer 2: 0(+1)/2
Map 1: 1/1    Reducer 2: 1(+1)/2
Map 1: 1/1    Reducer 2: 2/2
Moving data to directory s3://ytamu-emr-tut/os_requests
OK
Time taken: 30.873 seconds
Command exiting with ret '0'

ステップが正常に完了したら、サンプルスクリプトの実行結果を確認するため 出力先に指定したS3バケット内のデータを確認します。

% aws s3 ls --recursive s3://ytamu-emr-tut
2020-11-17 10:39:46         36 os_requests/000000_0
2020-11-17 10:39:46         24 os_requests/000001_0
2020-11-17 10:39:17          0 os_requests_$folder$
%

以下のようになっていたら正常に当該クラスターで指定したサンプル処理が実行出来ています。

% cat ~/Downloads/000000_0
Linux813
MacOS852
OSX799
iOS794
% cat ~/Downloads/000001_0
Android855
Windows883
%

次に Step5 といきたいところですが、、、

チュートリアルとしてはここまでで実質終わりで、次にやることは環境のクリーンアップ(削除)となっています。

step3でセキュリティグループでSSHの許可しましたが、チュートリアルでは一般的なセキュリティグループの穴あけの流れを紹介しただけで、実際の接続は実施せずに終えるというシナリオのようです。

せっかく起動したので、消す前に少し寄り道をして覗いてみます。
とはいえEC2インスタンス一覧画面をみると Nameタグ - として自身の検証環境でm5.xlargeが2台起動している画面が表示され、これを見ているとなんか胃が痛くなってくるので、軽く覗くぐらいにしておきます。

f:id:swx-tamura:20201215102436p:plain

クラスタ作成時に ノード(EC2インスタンス)のDISKに関する指定項目はありませんでしたが 執筆時点では、 gp2のディスクで上がってくるようです。

先程 マネジメントコンソールのEMRクラスターのまとめタブにあるリンクもしくは、Amazon EC2の画面にて当該EC2インスタンスへSSH接続を試みるとマスターノードに接続できます。

f:id:swx-tamura:20201223123201p:plain

% ssh -i "emr-tut.pem" ec2-user@ec2-XXX-XXX-XXX-XXX.ap-northeast-1.compute.amazonaws.com


       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
44 package(s) needed for security, out of 68 available
Run "sudo yum update" to apply all updates.

EEEEEEEEEEEEEEEEEEEE MMMMMMMM           MMMMMMMM RRRRRRRRRRRRRRR
E::::::::::::::::::E M:::::::M         M:::::::M R::::::::::::::R
EE:::::EEEEEEEEE:::E M::::::::M       M::::::::M R:::::RRRRRR:::::R
  E::::E       EEEEE M:::::::::M     M:::::::::M RR::::R      R::::R
  E::::E             M::::::M:::M   M:::M::::::M   R:::R      R::::R
  E:::::EEEEEEEEEE   M:::::M M:::M M:::M M:::::M   R:::RRRRRR:::::R
  E::::::::::::::E   M:::::M  M:::M:::M  M:::::M   R:::::::::::RR
  E:::::EEEEEEEEEE   M:::::M   M:::::M   M:::::M   R:::RRRRRR::::R
  E::::E             M:::::M    M:::M    M:::::M   R:::R      R::::R
  E::::E       EEEEE M:::::M     MMM     M:::::M   R:::R      R::::R
EE:::::EEEEEEEE::::E M:::::M             M:::::M   R:::R      R::::R
E::::::::::::::::::E M:::::M             M:::::M RR::::R      R::::R
EEEEEEEEEEEEEEEEEEEE MMMMMMM             MMMMMMM RRRRRRR      RRRRRR

[ec2-user@ip-XXX-XXX-XXX-XXX ~]$

主張がすごいです。

起動しているサービスは以下のような感じでした。

[ec2-user@ip-XXX-XXX-XXX-XXX log]$ systemctl list-units -t service |grep running
acpid.service                          loaded active running ACPI Event Daemon
amazon-ssm-agent.service               loaded active running amazon-ssm-agent
apppusher.service                      loaded active running EMR process for collecting metrics/logs from the cluster.
atd.service                            loaded active running Job spooling tools
auditd.service                         loaded active running Security Auditing Service
chronyd.service                        loaded active running NTP client/server
crond.service                          loaded active running Command Scheduler
dbus.service                           loaded active running D-Bus System Message Bus
getty@tty1.service                     loaded active running Getty on tty1
gssproxy.service                       loaded active running GSSAPI Proxy Daemon
hadoop-hdfs-namenode.service           loaded active running Hadoop namenode
hadoop-httpfs.service                  loaded active running Hadoop httpfs
hadoop-kms.service                     loaded active running Hadoop kms
hadoop-mapreduce-historyserver.service loaded active running Hadoop historyserver
hadoop-state-pusher.service            loaded active running Daemon process that processes and serves EMR metrics data.
hadoop-yarn-proxyserver.service        loaded active running Hadoop proxyserver
hadoop-yarn-resourcemanager.service    loaded active running Hadoop resourcemanager
hadoop-yarn-timelineserver.service     loaded active running Hadoop timelineserver
hive-hcatalog-server.service           loaded active running HCatalog server
hive-server2.service                   loaded active running Hive Server2
hue.service                            loaded active running Hue web server
ic-heartbeat-monitor.service           loaded active running Monitor of heartbeat file for instance controller
instance-controller.service            loaded active running EMR process on every node on an EMR cluster
irqbalance.service                     loaded active running irqbalance daemon
libstoragemgmt.service                 loaded active running libstoragemgmt plug-in server daemon
logpusher.service                      loaded active running EMR process on every node of an EMR cluster for collecting logs
lvm2-lvmetad.service                   loaded active running LVM2 metadata daemon
mariadb.service                        loaded active running MariaDB database server
metricscollector.service               loaded active running EMR metrics collector daemon
network.service                        loaded active running LSB: Bring up/down networking
oozie.service                          loaded active running Starts Oozie Server
postfix.service                        loaded active running Postfix Mail Transport Agent
rngd.service                           loaded active running Hardware RNG Entropy Gatherer Daemon
rpcbind.service                        loaded active running RPC bind service
rsyslog.service                        loaded active running System Logging Service
serial-getty@ttyS0.service             loaded active running Serial Getty on ttyS0
sshd.service                           loaded active running OpenSSH server daemon
systemd-journald.service               loaded active running Journal Service
systemd-logind.service                 loaded active running Login Service
systemd-udevd.service                  loaded active running udev Kernel Device Manager
tomcat.service                         loaded active running Apache Tomcat Web Application Container
[ec2-user@ip-XXX-XXX-XXX-XXX log]$

Hive

という事で、接続したらHiveをすぐ利用する事が出来ます。

[hadoop@ip-XXX-XXX-XXX-XXX ~]$ hive

Logging initialized using configuration in file:/etc/hive/conf.dist/hive-log4j2.properties Async: false
hive>

WebUIから接続できるアプリケーション

f:id:swx-tamura:20201223123209p:plain

AWSマネジメントコンソールのEMRの当該クラスターの[アプリケーションの履歴] タブにあるリンクにWebUIとしてアクセス可能な接続先の情報が纏まっているのでブラウザからも簡単に接続が出来ます。(Hadoop以外でクラスターを作成して覗いてみるのも面白いです)

(例) YARN Timeline server
f:id:swx-tamura:20201223123217p:plain

(例)Tez UI
f:id:swx-tamura:20201223123205p:plain

ステップ 5: クラスターを終了してバケットを削除する

f:id:swx-tamura:20201215102431p:plain

マネジメントコンソールの EMRから作成したクラスターを選択して終了(Terminate)するだけです。 念の為、EC2インスタンス一覧も見てみましたが当該インスタンスはTerminateのステータスとなっていました。

クラスター削除後も、そのクラスターで実行された処理内容や稼働時間等といった情報は残ります。 ちなみに完了したクラスターに関するメタデータ情報は 2 か月間無料で保管してくれるそうです。

あとは、このチュートリアル用に作成したS3バケットを必要に応じてお掃除なり削除をして終了となります。

% aws s3 rb s3://ytamu-emr-tut
remove_bucket: ytamu-emr-tut
%

チュートリアルをやってみて

私は今までオンプレミスでHadoop関連の業務に関わる機会に恵まれなかった人なので説得力に欠けるかもですが 今更かつ改めてですが、クラウドと相性がとても良いサービスだなと感じました。

Hadoopをオンプレミスでインフラから用意して〜となると大変敷居が高いものですが、すぐに利用出来て、実際にやりたい事(処理)に集中でき、ジョブが正常に終わった時やら失敗した時の動作もクラスタ削除のような指定もできるのでまさに使った分だけという従量課金を実現でき、膨大な処理を早める為に深夜の安い時間帯にスポットインスタンスを利用するといったイメージまでをチュートリアルで掴む事が出来たのでやってみてよかったです。

まとめ

短時間でEMRを触りながら概要レベルを学べる良いチュートリアルです