Apache Hadoop 3でまずハマりそうなポイント


今年の9月にApache Hadoop 3.0.0-alpha1がリリースされました。2.0.0-alphaのリリースから実に4年以上が経過しており、かなり大規模なアップデートになっています。

ただ、Hadoop 1から2になってJobTrackerとTaskTrackerが消えてYARNが追加されたというような超大規模な変更はなく、Hadoop 3でも今まで通りResourceManagerやNodeManagerが動作するということになります。

本記事では、「Apache Hadoop 3を使ってみたい!」という人がハマりそうな点、つまり非互換な点について述べていきます。新機能については他の方々が説明してくれるでしょう。

## Java7サポートの打ち切り

Hadoop 2.7でJava6が使えなくなったことはもうご存知かもしれませんが、Hadoop 3ではJava7が使えなくなりました。ちなみに、Java9対応にはまだまだ時間がかかりそうです。Java9対応のつらい話については、別途記事を書こうかなと思っています。

## デフォルトポート番号の変更

いくつかのサービスのデフォルトポート番号がLinux ephemeral port range(32768-61000)に入っており、競合の可能性があったので変更されました。以下、対応表です。

|Service                 | old   | new  |
|:-----------------------|------:|-----:|
|KMS(HTTP)               | 16000 | 9600 |
|KMS(Admin)              | 16001 | 9601 |
|NameNode(RPC)           | 8020  | 9820 |
|DataNode(HTTP)          | 50075 | 9864 |
|DataNode(HTTPS)         | 50475 | 9865 |
|DataNode(RPC)           | 50010 | 9866 |
|DataNode(IPC)           | 50020 | 9867 |
|SecondaryNameNode(HTTP) | 50090 | 9868 |
|SecondaryNameNode(HTTPS)| 50091 | 9869 |
|NameNode(HTTP)          | 50070 | 9870 |
|NameNode(HTTPS)         | 50470 | 9871 |

KMSのポート番号が変わったのは、HBaseのHMasterと被ったため。

* 参考: https://issues.apache.org/jira/browse/HBASE-10123

## シェルスクリプトの書き直し

CDHやHDPなど、BigTopを利用してビルドされたものにはinitスクリプトが用意されているため、サービスの起動停止にはinitスクリプトを利用しますが、素のApache Hadoopを利用する場合には、`sbin/hadoop-daemon.sh`, `sbin/yarn-daemon.sh`などを叩く必要がありました。
Hadoop 3ではこれらのスクリプトを直接叩くのは非推奨となり、代わりに`--daemon`オプションを利用します。`--daemon`オプションを利用したサービス起動・停止コマンドは以下のようになります。

```sh:
$ hdfs --daemon start namenode
$ hdfs --daemon start datanode
$ yarn --daemon start resourcemanager
$ yarn --daemon start nodemanager

$ yarn --daemon stop nodemanager
$ yarn --daemon stop resourcemanager
$ hdfs --daemon stop namenode
$ hdfs --daemon stop datanode
```

また、環境変数周りが大きく変わりました。全体的にわかりやすいコードに書き換わっているのですが、それはつまり、過去のノウハウがリセットされているということになります。既に`hadoop-env.sh`などで環境変数をいじっている場合は注意が必要です。こちらについてはもう少し詳しく解説記事を書きたい気持ちです。

## (追記) MapReduceのApplicationMasterが停止する問題

MapReduceジョブを動かしてみると、ApplicationMasterが落ちます。

```
$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.0.0-alpha2-SNAPSHOT.jar pi 5 10000
(snip)
2016-12-02 04:54:52,413 INFO mapreduce.Job: Job job_1480654443168_0001 failed with state FAILED due to: Application application_1480654443168_0001 failed 2 times due to AM Container for appattempt_1480654443168_0001_000002 exited with  exitCode: 1
Failing this attempt.Diagnostics: Exception from container-launch.
Container id: container_1480654443168_0001_02_000001
Exit code: 1
Stack trace: ExitCodeException exitCode=1: 
	at org.apache.hadoop.util.Shell.runCommand(Shell.java:974)
	at org.apache.hadoop.util.Shell.run(Shell.java:878)
	at org.apache.hadoop.util.Shell$ShellCommandExecutor.execute(Shell.java:1172)
	at org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor.launchContainer(DefaultContainerExecutor.java:293)
	at org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.launchContainer(ContainerLaunch.java:419)
	at org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.call(ContainerLaunch.java:284)
	at org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.call(ContainerLaunch.java:88)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)


Container exited with a non-zero exit code 1. Last 4096 bytes of stderr :
Error: Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster
```

これは、[MAPREDUCE-6704](https://issues.apache.org/jira/browse/MAPREDUCE-6704)などで報告されており、以下の設定を追加することで解決します。(デフォルト値に`HADOOP_MAPRED_HOME`を追加)

```xml:yarn-site.xml
<property name="yarn.nodemanager.env-whitelist"　value="JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME"/>
```

これがデフォルトで設定されていない理由は、YARNの設定にMapReduce specificな設定をデフォルトで入れてしまうのは良くないからです。

ちなみに、Hadoop 3ではこのようなコンパクトな形式のXMLファイルもサポートしています。([HADOOP-6964](https://issues.apache.org/jira/browse/HADOOP-6964))

## MapReduceで利用するメモリの設定が簡単になった

これまで、MapタスクやReduceタスクのヒープサイズを設定するときには

* mapreduce.map/reduce.memory.mb (containerのメモリ設定)
* mapreduce.map/reduce.java.opts (Javaヒープサイズの設定)

の両方を設定する必要がありました。Hadoop 3系ではどちらか1つ設定すれば、もう片方は自動的に設定されるようになりました。計算式は以下の通りです。

```
mapreduce.map/reduce.java.opts = mapreduce.map/reduce.memory.mb * mapreduce.job.heap.memory-mb.ratio
```

## CLIの非互換性

Hadoop 2の間はCLIの出力は互換性をなるべく維持するようになっていましたが、Hadoop 3系になって互換性のない変更が入っています。例えば、

* duコマンドで、レプリケーションを考慮したディスク使用量を表示するようになった ([HADOOP-6857](https://issues.apache.org/jira/browse/HADOOP-6857))
* duコマンドの結果が整形された ([HADOOP-11657](https://issues.apache.org/jira/browse/HADOOP-11657))
* fsckコマンドでドットが表示されなくなった ([HDFS-2538](https://issues.apache.org/jira/browse/HDFS-2538))

何かのコマンドを実行した結果をパースしている人は要注意。

## HFTP/HSFTPはなくなりました

WebHDFSを使ってください。

## s3:// はなくなりました

s3a:// を使ってください。

* https://wiki.apache.org/hadoop/AmazonS3

## Hadoopエコシステムとの連携

現時点では、ほぼ未対応です。詳細は以下のwikiをご確認ください。

* https://cwiki.apache.org/confluence/display/HADOOP/Hadoop+3.0.0+release

## 参考資料へのリンク

公式ドキュメント

* http://hadoop.apache.org/docs/r3.0.0-alpha1/index.html

Hadoop Summit Tokyoでの、Hadoop 3に関する発表資料

* http://www.slideshare.net/HadoopSummit/whats-new-in-hadoop-common-and-hdfs (Tsuyoshi Ozawa)
* http://www.slideshare.net/HadoopSummit/apache-hadoop-30-whats-new-in-yarn-and-mapreduce (Junping Du)