Amazon EMRを一度も利用したことがなかったので、data-analytics-specialty試験の学習ついでに実際にさわりながら自分へのメモを兼ねて情報を残します。
Amazon EMRとは
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を指定できる項目がありました)
用語の整理
この先、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 に移動されます。ファイルは保持されますが、大量のデータがあると、スタートアップに予想以上の時間がかかる場合があります。
クラスターは、以下公式ドキュメントの概要にある図のようにフルメッシュのような構成となります。
クラスターの種類
マスターノード
ノード間のデータやタスク分散の調整をするクラスターを管理するノード クラスターには必ずマスターノードが存在しており、最小構成だとマスターノード1台だけでも可能。
コアノード
タスクを実行し、HDFSにデータを保存する機能を持つノード
タスクノード
タスクを実行するのみでHDFSにデータを保存する機能を持たないノード
クラスターへの接続やらオペレーションについては、SSHを利用してマスターノードや必要に応じて他のノードに接続し、 インストール済みのアプリケーションが提供するインタフェースやツール(Hive等のHadoopエコシステム)を利用し、タスク実行する形となります。 あとは、AWSマネジメントコンソールに示されたリンクからブラウザ経由で利用出来るもの(YARN等)もあります。
さわってみる
今回は、公式にあるAmazon EMR によるビッグデータ分析入門 のチュートリアルがありましたのでやってみます。
ざっくりやることは以下です。
・チュートリアル用に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を押下し、ようこそ画面より[クラスターの作成]を押下します
クラスター作成に必要な設定項目を指定
以下のようなフォームが表示されるので、今回のチュートリアルで必要な内容を指定していきます。
・クラスター名は My First EMR Cluster
とし、
・S3 フォルダーの項目に 先に作成したS3バケットのURI
を指定します
・コストを抑えたい場合インタンス数は1でも大丈夫ですが、今回はマスターノード以外も見てみたかったので 2
としました
・EC2キーペアは、先に作成した emr-tut
を指定します
注意:ログ記録はクラスターの作成時にのみ有効にする事が出来て、設定は後から変更できません。 とあるので本番利用時には注意が必要そうです。
ソフトウェア設定のリリースについてはデフォルトですが、ドキュメントにも可能な限り最新のリリースバージョンを使用することをお勧めします。とあるのでそこも留意しておいたほうが良さそうです。
あと今回設定しませんでしたが、Cluster Scalingにチェックをつけると上の図にあるように直感的に最小と最大ノードを指定できるフォームが現れます。
(参考) Amazon EMR リリースについて - Amazon EMR
値を指定し、[クラスターを作成]を押下すると作成が始まり、今回の構成で私の環境では2minかからない程度で作成が完了しました。
少し寄り道
せっかくなので他のタブも閲覧してみます。
アプリケーションの履歴
モニタリング
モニタリングのタブの中に更にタブが3つ存在しており、CloudWatchと連動しクラスターステータス、ノードのステータス、IO という形で主要項目が可視化されています。
Amazon EMRのメトリクスに関する内容は以下に纏まっています。
CloudWatch でメトリクスをモニタリングする - Amazon EMR
ハードウェア
裏で稼働しているEC2インスタンスの情報が参照できます。
インスタンスタイプぐらいしか指定した記憶がありませんが、自動的に64GiBのEBSがアタッチされているようです。
ここで注目すべきはコアノードで サイズ変更
が指定できる点と、タスクインスタングループを追加
からタスクノードを追加できる点です。
タスクインスタングループを追加
を押下すると、以下のように追加する
EC2インスタンスのタイプや数を指定し、スポットをリクエストが出来ます。
設定
EMR バージョン 5.21.0 以降では、実行中のクラスター内のインスタンスグループごとに、クラスタ設定を上書きして追加の設定分類を指定が可能となっており、設定の一覧画面があります。
実行中のクラスター内のインスタンスグループの設定を指定する - Amazon EMR
イベント
当該クラスターのイベント履歴が確認出来ます。
ステップ
ステップとは、クラスターにインストールされたソフトウェアにより処理するためのデータを操作する指示が含まれる作業単位の事となります(この後のハンズオンでもここに処理を追加していきます)
Step.3: クライアントから SSH 接続をクラスターに許可する
セキュリティグループの確認
最初のクラスターを作成すると時にAmazon EMR により、 マスターインスタンスに関連付けられたデフォルトの [ElasticMapReduce-master] コアノードとタスクノードに関連付けられたセキュリティグループ [ElasticMapReduce-slave] が作成されます。
デフォルトの状態で中を覗くとこんな感じになっています。
自端末からSSHを許可
編集より、自分が接続する用途でPublic IPアドレスを SSH(TCP:22)の許可を加えます。
Step4: Hive スクリプトをステップとして実行してデータを処理する
Hive サンプルスクリプトの確認
今回利用するサンプルスクリプトはAWSによって用意されており、以下に格納されています。
s3://region.elasticmapreduce.samples/cloudfront/code/Hive_CloudFront.q
※ regionの文字列は、利用するリージョンに置き換える必要があります
今回私の場合は、東京リージョン(ap-northeast-1)で指定しました。
Hive スクリプトをステップとして送信する
クラスターの「ステップ」タブから [ステップの追加]を押下
上のようにポップアップが表示されるので、
・ステップタイプと名前は Hive プログラム
・スクリプト S3場所は、 上に記載したサンプルスクリプトのURI
・S3の入力ファイルの場所は、サンプルスクリプトの格納DIRまでのURI
・S3の出力ファイルの場所は、Step1で自身で作成したtutorial用のS3バケットのURI
を指定し、[追加]を押下します
処理が完了すると、ログファイルのタブから各ステップでのログを確認することができます。
お目当てのログファイルを押下すると、当該マスターノード(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台起動している画面が表示され、これを見ているとなんか胃が痛くなってくるので、軽く覗くぐらいにしておきます。
クラスタ作成時に ノード(EC2インスタンス)のDISKに関する指定項目はありませんでしたが 執筆時点では、 gp2のディスクで上がってくるようです。
先程 マネジメントコンソールのEMRクラスターのまとめタブにあるリンクもしくは、Amazon EC2の画面にて当該EC2インスタンスへSSH接続を試みるとマスターノードに接続できます。
% 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から接続できるアプリケーション
AWSマネジメントコンソールのEMRの当該クラスターの[アプリケーションの履歴] タブにあるリンクにWebUIとしてアクセス可能な接続先の情報が纏まっているのでブラウザからも簡単に接続が出来ます。(Hadoop以外でクラスターを作成して覗いてみるのも面白いです)
(例)
YARN Timeline server
(例)Tez UI
ステップ 5: クラスターを終了してバケットを削除する
マネジメントコンソールの EMRから作成したクラスターを選択して終了(Terminate)するだけです。 念の為、EC2インスタンス一覧も見てみましたが当該インスタンスはTerminateのステータスとなっていました。
クラスター削除後も、そのクラスターで実行された処理内容や稼働時間等といった情報は残ります。 ちなみに完了したクラスターに関するメタデータ情報は 2 か月間無料で保管してくれるそうです。
あとは、このチュートリアル用に作成したS3バケットを必要に応じてお掃除なり削除をして終了となります。
% aws s3 rb s3://ytamu-emr-tut remove_bucket: ytamu-emr-tut %
チュートリアルをやってみて
私は今までオンプレミスでHadoop関連の業務に関わる機会に恵まれなかった人なので説得力に欠けるかもですが 今更かつ改めてですが、クラウドと相性がとても良いサービスだなと感じました。
Hadoopをオンプレミスでインフラから用意して〜となると大変敷居が高いものですが、すぐに利用出来て、実際にやりたい事(処理)に集中でき、ジョブが正常に終わった時やら失敗した時の動作もクラスタ削除のような指定もできるのでまさに使った分だけという従量課金を実現でき、膨大な処理を早める為に深夜の安い時間帯にスポットインスタンスを利用するといったイメージまでをチュートリアルで掴む事が出来たのでやってみてよかったです。
まとめ
短時間でEMRを触りながら概要レベルを学べる良いチュートリアルです