YARN上でジョブを走らせてみる（Spark編）



## Outline

HadoopのYARN上で色々なアプリを動かすことになったのでテスト環境を作ってみた。

今回はYARN上でSparkのjarを走らせてみる。
走らせるjarは、sparkパッケージに入ってるexampleと、自分で作ったやつ。

## 環境

### メインマシン

実際に動かしているハード。
WebUIなどの動作確認に使う。

### Client

OS: Ubuntu14.04 （AWS EC2）
Hadoop: 2.5.2
Java: 8

### Hadoopクラスタ

別記事を参照。
擬似分散モード：http://qiita.com/uryyyyyyy/items/a7ac8dc088b6fc2d115d
完全分散モード：http://qiita.com/uryyyyyyy/items/ebd732d3935ee404f4e7
ここではResourceManagerとnameNodeは同じhostにあるとする。

OS: Ubuntu14.04 （AWS EC2）
ユーザー: ubuntu
IP: PublicIP, PrivateIP
Hadoop: 2.5.2
port: 全開放（22, 80, 8020, 8032, 8088, 50070が開いてればたぶん大丈夫）

Clientとhadoopクラスタは同じsubnetにいて、privateIPでアクセスできる状態とする。

## 事前準備

以下、clientでの操作を基本とする。

### Clientへ各種インストール

```bash:terminal
# java
sudo add-apt-repository ppa:webupd8team/java -y
sudo apt-get update
sudo apt-get install oracle-java8-installer -y

# Hadoop
# めんどくさいのでHomeにそのまま置く
wget http://ftp.meisei-u.ac.jp/mirror/apache/dist/hadoop/common/hadoop-2.5.2/hadoop-2.5.2.tar.gz
tar zxvf hadoop-2.5.2.tar.gz

# Spark
# 素のHadoop2.5で動かすのでそれ用のdistributionを選ぶ。

# めんどくさいのでHomeにそのまま置く
wget http://d3kbcqa49mib13.cloudfront.net/spark-1.4.1-bin-hadoop2.4.tgz
tar zxvf spark-1.4.1-bin-hadoop2.4.tgz
```

### 環境変数など設定

http://qiita.com/uryyyyyyy/items/a7ac8dc088b6fc2d115d
別記事の通りに、

- hadoop-env.sh
- /etc/profile
- core-site.xml
- hdfs-site.xml

を編集する。

### HDFSにJarを置けるようにする。

別記事参照
http://qiita.com/uryyyyyyy/items/056e79ea0d326326f416


今回はmyJarsというフォルダを作る。

```
./hadoop-2.5.2/bin/hdfs dfs -mkdir /myJars

# YARN上でSparkのjarを動かすためのassemblyJarを配置する。
# 事前に置いておかない場合、spark-submit時に毎回このjarをHDFSへuploadすることになる。
./hadoop-2.5.2/bin/hdfs dfs -put spark-1.4.1-bin-hadoop2.4/lib/spark-assembly-1.4.1-hadoop2.4.0.jar /myJars/spark-assembly-1.4.1-hadoop2.4.0.jar
```

```
# spark-submit時に、ここにあるassemblyを使うように明示する。
export SPARK_JAR=hdfs://[PrivateIP]:8020/myJars/spark-assembly-1.4.1-hadoop2.4.0.jar
```

## spark-examplesを実行してみる。

### 実行

```bash:client_terminal
# 実行予定のjarをHDFSへ上げる
# 上げなくても動くが、毎回uploadすることになる。
./hadoop-2.5.2/bin/hdfs dfs -put spark-1.4.1-bin-hadoop2.4/lib/spark-examples-1.4.1-hadoop2.4.0.jar /myJars

# 対象のjarを指定して実行する。
./spark-1.4.1-bin-hadoop2.4/bin/spark-submit --class org.apache.spark.examples.SparkPi --master yarn-cluster --executor-memory 2G --num-executors 1 ./spark-1.4.1-bin-hadoop2.4/lib/spark-examples-1.4.1-hadoop2.4.0.jar 10
```

パラメータは適当に変えれます。

### 結果確認

YARNのWebUIをマスタマシンから確認すると、`org.apache.spark.examples.SparkPi`がSUCCEEDEDになっているはず。

## 自分で作ったjarを実行してみる。

### jar作成

今回はこんな感じ
https://github.com/uryyyyyyy/hadoopSample/tree/master/sparkBatchSample

```bash:client_terminal
# fatJarの生成
./activator assembly
```

### 実行

```bash:client_terminal
# 実行予定のjarをHDFSへ上げる
# 上げなくても動くが、毎回uploadすることになる。
./hadoop-2.5.2/bin/hdfs dfs -put ./sparkBatchSample-assembly-1.0.jar /myJars

# 対象のjarを指定して実行する。
# 引数には適当にテキストファイルを指定する。
./spark-1.4.1-bin-hadoop2.4/bin/spark-submit  --class com.example.spark.app.Main --master yarn-cluster --num-executors 1 --driver-memory 2g --executor-memory 1g --executor-cores 1 hdfs://172.31.3.4/myJars/sparkBatchSample-assembly-1.0.jar hdfs://172.31.3.4:8020/testDir/client.txt
```

### 結果確認

YARNのWebUIをマスタマシンから確認すると、`com.example.spark.app.Main`がSUCCEEDEDになっているはず。
historyから実行nodeのログをを見ると、
こんな感じで結果が出てくるはず。

```
----Start----
Lines with a: 12, Lines with b: 12
```


## ハマったところなど。

### yarn-clientモードで動かすとエラーになる。

```
./spark-1.4.1-bin-hadoop2.4/bin/spark-submit  --class org.apache.spark.examples.SparkPi --master yarn-client --num-executors 1 --driver-memory 2g --executor-memory 1g --executor-cores 1 spark-1.4.1-bin-hadoop2.4/lib/spark-examples-1.4.1-hadoop2.4.0.jar
```

実行はできてYARNにも登録されるんだけど、StatusがUNDEFINEDになってて、submitしたclientにｍ色々エラーが出ている。。。

stacoverflowなど見てもよく原因がわからない。
というか、そもそも`yarn-client`をどう使えばいいのかわからない。（普段の動作確認はlocalで、YARN上で動かしたいならclusterモードで良いのでは？）

ちなみに、YARN上でなくlocalでsparkを動かしたい場合はこんな感じ

```
./spark-1.4.1-bin-hadoop2.4/bin/spark-submit  --class com.example.spark.app.Main --master local[2] --num-executors 1 --driver-memory 2g --executor-memory 1g --executor-cores 1 ./sparkBatchSample-assembly-1.0.jar hdfs://172.31.3.4:8020/testDir/client.txt
```

なんか色々なログが流れて普通に完了するはず。今回の自作ジョブでは結果をそのまま出力するので見づらいが、`<submit command> | grep Lines`などとすれば結果が出てるのがわかる。

### Spark実行時にエラーが出る。
HADOOP_CONF_DIR or YARN_CONF_DIR must be set in the environment

みたまんま。ちゃんとResourceManagerにつなぐようにしないと厄介。

### ジョブがたまってると後続が動かない。

自分の手元では擬似分散モードで動かしたのでnodeが一つしかない。その状態でなんかの拍子に応答が帰ってこないジョブがあったりすると、以降のジョブ実行命令はずっと待機することになる。。

## まとめ

Sparkむずい。。。

というか、supark-submitコマンドを打つしかないようで、code側から管理する良い方法が見つからない。

後日、javaCodeからsparkJobの実行とstatus取得の記事を書きます。