Amazon EMR 上の WebUI群 ( Hue や Zeppelin ) をSSHトンネルなしでブラウザ表示する方法

概要

EMR で構築したクラスタ上の WebUI をブラウザ表示するには SSH トンネリングを利用した接続が推奨されていますが、この方法は不便が多いため、より気軽な方法を模索しました

最終的に リバースプロキシ をおいて接続する方法 が良かったので共有します

構成

検証環境 : EMR-Release 5.2.1

SSH トンネリングによる構成

  • この図では master-public-dns-name に対してインターネット経由で SSH トンネルを作成しています
    (VPN 接続がある場合は、Local Netowark 内を通します)
  • EMR Master インスタンスのある SecurityGroup で SSH のポート(デフォルト22)を接続元指定で開け、各クライアントマシンと EMR Master インスタンス間で SSH トンネルを作成して、ポートフォワーディングによってブラウザで任意のWebUIと通信を行います

問題点

  • 各クライアント(各個人PC)マシン上で設定が必要になる(非エンジニアでは作業負荷が高い)
  • SSHで繋ぐため、クライアント(各個人PC)にEMR master への秘密鍵をばらまく必要がある(秘密鍵は隠したい)
  • 都度 SSHトンネル接続&Webブラウザアクセスの手順が面倒

Hue や Zeppelin などの分析ツールは大勢の非エンジニアが利用するケースもありえます
その場合各個人クライアントに鍵を配ったりターミナルでSSHトンネルを作成させたりする操作は煩雑でつらいものがあります

リバースプロキシをおく構成

  • プロキシサーバ に対してインターネット経由で接続します
    (SSHトンネルの例と同様、VPN 接続がある場合は Local Netowark 内を通します)
  • EMR Master とは別インスタンスでプロキシサーバを稼動させます
  • プロキシサーバまでは https、プロキシサーバから EMR master は private network 内を http で通信させます
    (個別のWebUIはSSL設定しなくて良い)
  • 各クライアント(各個人PC)マシンは追加設定不要
    (ブラウザアクセスするだけでOK)

EMRとは別にプロキシサーバを構築するため追加コストがかかりますが、個別クライアントは何の設定も要らず、ブラウザアクセスするだけで、Hue や Zeppelin などお好みの WebUI を参照できるようになります

構築手順

1. リバースプロキシを配置するサーバの Security Group 設定

外部から(またはLocalNetwork内)の https リクエストを許可します
ポートは、利用したい WebUI にあわせて必要な個数分開けます
後述 しますが、ドキュメントに載っていないポートが参照される場合があるので、適宜追加します)

タイプ    : カスタム TCP ルール 
プロトコル : TCP
ポート範囲 : 8888
ソース    : <アクセス元の Public IP (またはLocalNetwork内のアクセス元 Private IP )>

2. EMR Master の Security Group 設定

EMR Master の Security Group では、リバースプロキシ (private ip) からの http リクエストを許可します

タイプ    : すべてのトラフィック
プロトコル : すべて
ポート範囲 : すべて
ソース    : (Private Network のIP範囲) 

3. DNS設定

お好みのドメイン名を決め、そのドメインへのアクセスをプロキシサーバへ誘導するよう DNSレコード を設定します

ラベル : emr.your-site.com(管理下のお好みのドメイン名)
TTL   : 任意の時間 Time To Live
クラス : IN
タイプ : A
リソース : <リバースプロキシサーバの Public IP >

Route53などであれば次のような感じです(イメージ)

4. リバースプロキシの構築

プロキシサーバ上では、特定のドメイン/ポート指定でアクセスがきた場合に、EMR Master サーバの指定ポートへ代理アクセスするよう設定します
今回は EC2 で適当なインスタンスを確保し、Nginx を使ってプロキシさせます

Nginx インストール

リバースプロキシを配置するサーバにNginx をインストールします
(環境にあわせて、安定動作するものを選んでセットアップします)
https://www.nginx.com/resources/wiki/start/topics/tutorials/install/

SSL証明書の配置

SSL証明書を配置して、Nginx で https リクエストがきた場合に参照させます
(証明書は必要に応じて入手します)

ls /path/to/cert/*
/path/to/cert/your-site-ssl-certificate.crt
/path/to/cert/your-site-ssl-key.pem

Nginx 設定例(後でまとめて書きます)

ssl on;
ssl_certificate     /path/to/your-site-ssl-certificate.crt;
ssl_certificate_key /path/to/your-site-ssl-key.pem;

コンテンツ書き換え

WebUI群の中には、リンクを生成する際に 自身の名前 master-private-dns-name を使う場合があるため、ブラウザアクセスした場合に表示されるページ内のリンクが飛べない(名前解決できない)ケースが発生します
これを回避するために、Webサーバのコンテンツ書き換え機能を使って master-private-dns-name を名前解決できるドメイン(先ほどDNS登録した管理下のお好みのドメイン)に書き換える処理をはさんでおくとストレスなく使えるようになります

Nginx 設定例(後でまとめて書きます)

sub_filter '(master-private-dns-name)' 'emr.your-site.com(管理下のお好みのドメイン名)';
sub_filter_once off;

Nginx設定

利用したいWebUIのポートに対して、それぞれプロキシ設定を追加します
この際、上記で紹介したSSL設定とコンテンツ書き換えを加えて下記のように設定します

/path/to/nginx/nginx.conf

# hue wabapp
server {
    listen 8888 ssl;
    server_name emr.your-site.com;
    access_log /path/to/proxy-your-site.com.access.log main;

    ssl on;
    ssl_certificate     /path/to/your-site-ssl-certificate.crt;
    ssl_certificate_key /path/to/your-site-ssl-key.pem;

    location / {
        proxy_pass http://<master-private-ip>:8888/;
        sub_filter 'ip-xx-xx-xx-xx.region.compute.internal' 'emr.your-site.com';
        sub_filter_once off;
    }
}

# 
server {
    listen 8080 ssl;
..............(同様)
}

..............(必要なポート分設定)

この例では 共通のドメイン emr.your-site.com に対して ポートごとに振り分けさせていますが、もし個別のWebUIごとに別ドメインを割り当てるほうがお好みであれば、そのように設定することももちろん可能です
hue.your-site.com へのアクセスで <master-private-ip>:8888 へ誘導する など)
ただしURLの書き換えルールが複雑になってしまうので、そのあたり検討する必要がでてきます

対象となる WebUI 群

設定対象となる WebUI 群のリストは、Amazon EMR のドキュメント を参照します

なお利用するWebUIによってドキュメントに載っていないポートも参照されるため、状況に応じて必要なポートを登録します
(一応個人的に必要だったものを羅列します)

Web UI Name uri
Hue master-public-dns-name:8888/
Tez UI master-public-dns-name:8080/tez-ui/
Zeppelin master-public-dns-name:8890/
Yarn Web Proxy master-public-dns-name:20888/
YARN ResourceManager master-public-dns-name:8088/
Yarn ResourceManager? master-public-dns-name:8032/
Hadoop HDFS NameNode master-public-dns-name:50070/
Yarn timeline-service Webapp master-public-dns-name:8188/
Spark HistoryServer master-public-dns-name:18080/

設定を書き終えたら、Nginxのプロセスを起動させます

5. 動作確認

設定は以上です、実際にブラウザで 個別の WebUI を開いてみます

Hue
http:// emr.your-site.com :8888/

無事に個別のWebUIが開く & 表示されてるリンクへ正しく遷移できれば、設定完了です! :thumbsup:

まとめ

Amazon EMR 上の WebUI 群へのアクセスを リバースプロキシ経由 にすることで、以下の利点が得られます

  • WebUIへアクセスする チームメンバーの負担を大幅減できる
    (クライアントマシンの設定不要で、ブラウザアクセスですぐ使える)
    (SSHトンネル設定のように接続が切れることもない)
  • SSH秘密鍵をばらまかなくてよい
    (余計なリスクを負わなくてよい)
  • リバースプロキシで SSL設定をまとめて行うことができる
    (個別WebUIでSSL対応させなくてよく、設定を一元的に行える)
  • コンテンツ書き換え処理によって、 すべてのリンクをたどれるようにできる
    (単体の WebUI でなく、複数同時に公開可能)

ぜひおためしください!

参考資料

続きを読む

SparkアプリケーションのデバッグTIPS

Spark UIでスレッドダンプを見る

どこかで詰まってる/デッドロックしているなどを調べたい場合、スレッドダンプを見るのが有効ですが、それだけならSpark UI上でできます。

Screen Shot 2017-09-03 at 10.43.47 PM.png

Screen Shot 2017-09-03 at 10.44.12 PM.png

EMR上でJMXリモートデバッグ

ここではjvisualvmを使うことにします。

jvisualvmの準備

jvisualvmにプラグインを入れておくと捗ります。

Tools > Pluginsからプラグイン管理画面を開き、Threads Inspectorあたりは入れておくと便利です。

ステップを追加する

前提

  • アプリケーションはjarに固めてs3://path/to/app.jarに置いてあるとします
  • command-runner.jarspark-submitする方法でステップを実行します
  • EMRクラスタのmasterおよび各ノードは、22番が空いてるものとします

EMRにステップの追加

以下のようなコマンドラインオプションをつけてステップを追加します。

spark-submit --deploy-mode cluster --class com.example.Main --master yarn-cluster 
  --conf "spark.executor.extraJavaOptions=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=8002 -Dcom.sun.management.jmxremote.rmi.port=8002 -Djava.rmi.server.hostname=127.0.0.1" 
  --conf "spark.driver.extraJavaOptions=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=8003 -Dcom.sun.management.jmxremote.rmi.port=8003 -Djava.rmi.server.hostname=127.0.0.1" 
  --num-executors 3 --driver-memory 2g --executor-memory 5g --executor-cores 2  # このへんはお好みで
  s3://path/to/app.jar

これで、driverプロセスに対しては8003、executorプロセスに対しては8002でjmx接続できるようになります。

今回は、executorプロセスに接続してみます。

※注意

一つのノードで複数のexecutorが割り当てられうる設定で実行した場合、これだと8002がバッティングする可能性があります。

そういった場合はcom.sun.management.jmxremote.port=0として、動的にポートを取得するなどの手段をとる必要があります。

executorプロセスの実行されているノードの特定

YARNクラスタ上のどのノードでexecutorが実行されるかは動的に決まるため、各ノードにSSHで入ってlsofなどで8002番が使われているかどうか確認し、つなぐ先のノードを特定します。

ここでは、ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.comだったとします。

SSHトンネルを開く

手元のマシンで以下のコマンドを実行し、8002番のSSHトンネルを開きます。

$ ssh -i key.pem -NL 8002:ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com:8002 hadoop@ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com

jvisualvmから接続

あとは127.0.0.1:8002に対してjvisualvmから接続すればOKです。

IntelliJでステップ実行する(localモード)

IntelliJのリモートデバッグを使えば、Sparkアプリケーションをステップ実行などできます。

ここではlocalモードで行います。(EMR上でもできるはずだけど)

前提

  • sparkバイナリを落として/path/to/spark_homeに解凍しておきます
  • アプリケーションはjarに固めて/path/to/app.jarに置いておきます

IntelliJの前準備

IntelliJを起動し、Run > Edit Configurationsから、リモートデバッグ用のconfigurationを追加しておきます。

Screen Shot 2017-09-03 at 11.23.02 PM.png

+からRemoteを選択すれば勝手にこれが入力されています。

spark-submit

リモートデバッグ用のオプションをつけて、spark-submitします。

$ cd /path/to/spark_home
$ ./bin/spark-submit --master local 
    --driver-java-options "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005" 
    /path/to/app.jar

IntelliJでリモートデバッグを開始

少し経ってSparkアプリケーションが起動したら、さきほど作成したconfigurationを実行すれば、いつものようにブレークポイントを貼ったりスレッドの状態を見たりwatchを仕込んだりできます。

続きを読む

Hadoop (HDP) を0から構築する方法

Hadoop環境を構築したい

皆さんは自分用のHadoop環境をどの様に構築されていますか?
色んな方法があるようですが入り口からいろいろ模索してしまいました。
調査不足の面もあったり、構築の方法論にとどめていたりしますがご一読いただければと思います。

主な方法

  1. ローカルVMでSandoBox
  2. AzureでSandBox
  3. AWSでSandBox
  4. Hortonworks Data Cloud
  5. Ambariから構築

1. ローカルVMでSandoBox

Hortonworks Sandbox with VirtualBoxによると、メモリが自分のPCには厳しかったです。
最小4GB、AmbariやHBaseなどもろもろ載せるとホストOSに10GB、Sandboxに8GBが必要。

2.AzureでSandBox

kkitaseさまの記事が明快です。
Azureで、Hortonworks Sandboxを使い、Hadoop、Sparkを試してみよう
自分もこの方法は良いなと思いやってみましたが少し自分のほしい環境と異なっていました。
– HDP2.5が提供されている(2017/8/17現在) →希望はHDP2.6(現バージョン)
– Hive2が入ってなかったです。(HDP2.5では入っていない)
– 最小4ノード構成(仮想サーバーを4台使う)

3. AWSでSandBox

CommunityサイトHCCに似たような質問がありました。
HDP Sandbox on AWS?
ローカルVMをDLしてAWSのインストールイメージ(AMI)として使うのですが、AMIのところが自分には難しく、入力出来ない項目があり。
また、1回だけの作業ですが、10GB程度ローカルにDLするのとバケツにUPするのが一手間。
wgetとかできればいいのですが。

4. Hortonworks Data Cloud

手順など以下から。
Hortonworks Data Cloud
これは簡単でした。拡張の方法も同様に簡単です。
– 最小4ノード構成(仮想サーバーを4台使う)
– Hortonworksのソフトウェア・ライセンス費用が必要(若干ですが)

できれば

今更ですがこんなのは無いのかなと?
– 最新のVersionで
– 1台構成が可能で(自由に選択できる意味で)
– 構築手順がシンプルで
– 拡張時も同様の手順が使えて
– HiveやPigやecosystemのアプリ群はいろいろ入れたい
– 若干の費用は良いとして

5. Ambariから構築

そこでこれです。
あっさりAmbariから構築しちゃいましょう。
Ambariとはざっくり言うとHadoopの管理モジュールです。
yumで最新版を入れれます。アプリもクラスタ構成も好きにできます。1台でOKです。
Apache Ambari Installation
私はAWSのAmazon Linuxで構築しましたが問題なく、上述した自分の希望に一番あっている気がしました。

何かのお役に立てれば。

8/29 イントロの文言修正

続きを読む

ETLをサーバレス化するAWS Glueについての概要

AWS Glueが一般人でも使えるようになったというので、どんなものかと、調べてみました。
一人で調べ物した結果なので、機能を正しく把握できているかいまいち自信がありませんが、
理解した限りで公開します。全体像を理解できるような、概念的な話が中心です。

概要

AWS Glueは、日々行われるデータ集約やETL処理を自動化、およびサーバレス化するサービスです。

いま、未加工のCSVやJSONによるログデータや、
アプリケーションで使用している既存のデータベースなどがあるものの、
そのままでは分析が難しく、データ分析のために整備された領域が求められているとします。

AWS Glueの文脈では、前者をデータストア、後者をデータカタログと位置づけます。
データカタログは主に、フルマネージドなHDFS上のストレージ領域です。
たとえば、Amazon Athenaからデータカタログを分析することができます。

AWS Glueは以下の3要素からなります。

  • データ分析の中央リポジトリでありデータを一元管理するデータカタログ
  • 様々なデータストアからデータカタログにデータを集約するクローラ
  • データカタログ内のデータをETLするジョブ

AWS Glueによって、データ分析基盤のサーバレス化を進めることができます。たとえば、 (Customer's Application)-> S3 -(Glue Crawler)-> Data Catalog -> (Athena) は、データ収集から分析・可視化までをエンドツーエンドでサーバレスに構築する一例です。ここで、データの加工が必要であるならば、Data Catalog -(Glue Job)-> Data Catalogを加えればよいでしょう。

AWS Glueはフルマネージドであり、その処理はスケールアウトするため、ユーザはデータ規模やインフラ運用を意識することなく、データを加工するスクリプト(ETLの”T”に対応)の作成に集中することができます。ほかにも、AWS Glueは、データカタログ上のテーブルメタデータのバージョン管理機能や、クローラでの入力データからのスキーマ自動推論機能、クラシファイアでの検査に基づきスキーマの変更を検知する機能などを備えています。

クローラ

AWS Glueにおけるクローラとは、データストアのデータを、
データカタログに移住させるために使われる機能です。

クローラの目的は、散在する複数のデータストアそれぞれを見張らせ、
最新のデータを発見し、それらのデータをデータカタログへと集約し、データカタログを最新に保つことにあります。

クローラは、クラシファイアという要素を通じて、カラム名変更、型変換などの簡単な変換処理を行ったり、
半構造データをテーブルの形式に整えたり、スキーマの変更を検知できたりします。
クラシファイアは、デフォルトのものを使うことも、自分でカスタマイズすることもできます。

作成されたクローラには、ジョブ実行方法(オンデマンドか、スケジュールベースか、イベントベースか)が定義されています。
たとえば、クローラを定期実行させておくことで、データカタログがデータストアに対しおおむね最新であることが保証されます。

ジョブ

クローラを使って単にデータをデータカタログへと移住させただけでは、
クエリを叩けてもデータが使いにくく、ユーザにとって分析が難しい場合があります。
このとき、より分析に適した形にするために、ETL処理が必要です。

AWS Glueにおけるジョブとは、抽出・変換・ロード(ETL)作業を実行するビジネスロジックです。
ジョブが開始されると、そのジョブに対応するETL処理を行うスクリプトが実行されます。
こちらもクローラと同様に定期実行などの自動化が可能です。

ユーザは、ジョブ作成者として、抽出元(データソース)、およびロード先(データターゲット)を定義します。
ただし、データソースおよびデータターゲットは、どちらもデータカタログ上のデータです。
ユーザは、ジョブ処理環境を調整したり、生成されるスクリプトをビジネスニーズに基づいて編集したりします。

最終的に、Apache Spark API (PySpark) スクリプトが生成されます。
こうして作成されたジョブは、データカタログで管理されます。

参考文献

AWS Glue 概要

クローラ

ジョブ

続きを読む

EMR5.7でAmazonDynamoDBClientBuilderが上手く使えない対応

環境

EMRは5.7。
aws-java-sdk-dynamodbのバージョンは下記。

build.sbt
libraryDependencies += "com.amazonaws" % "aws-java-sdk-dynamodb" % "1.11.170"

sbt assembly で固めたFAT-JARをEMR上にデプロイ&実行するとエラーが発生。
ローカルでは上手く動くので原因がわからず少し困った。

事象

EMR5.7にて AmazonDynamoDBClientBuilder を利用すると NoClassDefFoundError
AmazonDynamoDBClientBuilder はパスを通している(FAT-JARに含まれている)ので、ClassNotFoundException では無いだろうと思っていたが、原因が特定できず戸惑った。

エラー1
17/08/14 10:17:39 INFO Client:
    (略)
java.lang.NoClassDefFoundError: Could not initialize class com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder
        at SparkApp$$anonfun$main$1$$anonfun$1.apply(SparkApp.scala:58)
        at SparkApp$$anonfun$main$1$$anonfun$1.apply(SparkApp.scala:51)
        at org.apache.spark.rdd.RDD$$anonfun$mapPartitions$1$$anonfun$apply$23.apply(RDD.scala:797)
        at org.apache.spark.rdd.RDD$$anonfun$mapPartitions$1$$anonfun$apply$23.apply(RDD.scala:797)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:323)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:287)
        (略)

しばらく動かしたりログを探すと、IllegalAccessErrorがでていた。
どうやらこれが原因なようだ。

エラー2
17/08/14 11:04:29 INFO Client:
    (略)
java.lang.IllegalAccessError: tried to access class com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientConfigurationFactory from class com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder
        at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder.<clinit>(AmazonDynamoDBClientBuilder.java:27)
        at SparkApp$$anonfun$main$1$$anonfun$1.apply(SparkApp.scala:58)
        at SparkApp$$anonfun$main$1$$anonfun$1.apply(SparkApp.scala:51)
        at org.apache.spark.rdd.RDD$$anonfun$mapPartitions$1$$anonfun$apply$23.apply(RDD.scala:797)
        at org.apache.spark.rdd.RDD$$anonfun$mapPartitions$1$$anonfun$apply$23.apply(RDD.scala:797)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:323)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:287)

調査

調べるといくつか出てきた。

どうやら、ERM5.7はaws-java-sdkのバージョンが 1.10.75.1 までしか対応していないとのこと。現在(※2017/08/15)は1.11系が出ているので、けっこう古い。というか本当なのか?

ということで、公式のドキュメントを調べると…

AWS SDK for Java が 1.10.75 にアップグレード
* http://docs.aws.amazon.com/ja_jp/emr/latest/ReleaseGuide/emr-whatsnew.html

と書いてあり、1.10.75 までは対応していることは見つけたが、それ以降のバージョンについては述べていない。うーむ、信頼できるのか?

対応

ということで、半信半疑ながらSDKのバージョンをダウングレードした。

build.sbt
libraryDependencies += "com.amazonaws" % "aws-java-sdk-dynamodb" % "1.10.75.1"

そうすると、AmazonDynamoDBClientBuilderが利用できないので、今ではdeplicatedになっているAmazonDynamoDBClientを利用して書き換えすることに。

OLD_dynamodbサンプル.scala
    val client = AmazonDynamoDBClientBuilder.standard
      .withRegion("ap-northeast-1")
      .build
    val dynamoDB = new DynamoDB(client)

こちら↑をすこし編集するのみで動いてくれた。

NEW_dynamodbサンプル.scala
    val client = new AmazonDynamoDBClient()
    client.setRegion(Region.getRegion(Regions.AP_NORTHEAST_1))
    val dynamoDB = new DynamoDB(client)

実行結果

実行すると…
上手く動いてくれた。さすがStackOverFlow!

なぜ IllegalAccessError が出てしまうかだが、ERM上でもaws-java-sdkがロードされていると思うので、かみ合わせが悪いのか?このあたりよく分かっていない。

まとめ

EMRでDynamoDBに書き込む時は、SDKのバージョンに気をつけよう。

続きを読む

SparkをEMRで使ってみたかった

下記サイトを参考、、というより、ほぼそのまま実施
http://www.atmarkit.co.jp/ait/articles/1609/27/news018.html

CSV作成

csvをrubyで作成。s3にアップロード

sbtプロジェクトを作成

build.sbt

name := "SparkExampleApp"

version := "1.0"

scalaVersion := "2.11.7"

libraryDependencies ++= Seq(
  "org.apache.spark" %% "spark-core" % "2.1.0",
  "org.apache.spark" %% "spark-mllib" % "2.1.0",
  "org.apache.spark" %% "spark-sql" % "2.1.0",
  "com.databricks" %% "spark-csv" % "1.4.0"
)

ソースコードは下記を丸コピ

https://github.com/nihitok/atmarkit-spark-articles/blob/master/src/main/scala/SparkExampleApp.scala

使用するsparkのspark-defaults.confに下記を追記

spark-defaults.conf
spark.jars.packages  com.amazonaws:aws-java-sdk:1.7.4,org.apache.hadoop:hadoop-aws:2.7.3

s3にフルアクセスできるユーザー作成

(若干ポリシー周りのUIが違うが気をつけて)

https://joppot.info/2014/06/14/1621

アクセスキーとシークレットキーをコピーしておく

先ほどのSparkExampleApp.scalaにアクセスキーとシークレットキーを貼り付け

実行

ローカルで実行

./bin/spark-submit --class SparkExampleApp --master local {自分の作成したjarファイルのpath} {S3に配置したdata.csvのパス) {S3の保存先のパス}

下記みたいな感じになる

./bin/spark-submit --class SparkExampleApp --master local ~/Desktop/SparkExampleApp/target/scala-2.11/spark-sample-project_2.11-1.0.jar s3n://my-bucket-name/data.csv s3n://my-bucket-name/output.csv

マシンの性能が足りないとtmpファイルがs3にアップロードされる

EMRではしっかり動くのであとは最初の記事通り設定すればOK

スクリーンショット 2017-03-24 2.51.33.png

続きを読む