Hadoopセットアップ-その3(完全分散モード)

いやーかなり間が空いてしまいました…

重い腰をあげて3台(仮想環境に)セットアップしました!

3台にhadoopをセットアップする

ひとまず、前々回の記事の通り、hadooprpmからインストールしました。

ホスト名はそれぞれ、hadoop1、hadoop2、hadoop3です。(そのまんま…)

【追記(3/31)】 このあたりの話を別途再検証して記事にまとめました。併せてご参照ください。 Hadoopをとりあえず動かしてみるために

しばらく見ないうちにhadoop1.0.3が出てましたね。 今回私がインストールしたのは hadoop-1.0.3-1.x86_64.rpmになります。

とりあえずスタンドアロンモードで動作確認

インストールしたhadoopスタンドアロンモードで動くか確認します。 状態としては前々回の記事で設定する内容は全て設定してあります。

それではhadoop1にて実行します。

# hadoop jar /usr/share/hadoop/hadoop-examples-1.0.3.jar wordcount input output
12/06/03 21:55:09 INFO util.NativeCodeLoader: Loaded the native-hadoop library
12/06/03 21:55:09 INFO mapred.JobClient: Cleaning up the staging area file:/tmp/hadoop-root/mapred/staging/root-293008467/.staging/job_local_0001
12/06/03 21:55:09 ERROR security.UserGroupInformation: PriviledgedActionException as:root cause:java.net.UnknownHostException: hadoop1: hadoop1

ズコーorz

えー/etc/hostsに自ホスト名を登録していなかったようです。 今後の連携のために3台文登録しておきます。

xxx.xxx.xxx.xxx hadoop1
yyy.yyy.yyy.yyy hadoop2
zzz.zzz.zzz.zzz hadoop3

再実行!

# hadoop jar /usr/share/hadoop/hadoop-examples-1.0.3.jar wordcount input output
12/06/03 21:55:57 INFO util.NativeCodeLoader: Loaded the native-hadoop library
12/06/03 21:55:57 INFO input.FileInputFormat: Total input paths to process : 1

12/06/03 21:56:04 INFO mapred.JobClient: map 100% reduce 100%
12/06/03 21:56:04 INFO mapred.JobClient: Job complete: job_local_0001

動きました!引き続き、前回の設定内容を反映していきましょう。

SSH公開鍵認証の登録時には、hadoop1、hadoop2、hadoop3がそれぞれ相互にログインできるようにあらかじめ設定しておきました。 子ノード同士の通信が発生するのか不明なため、とりあえず全部ログイン可にしましたが、もしかするともっと限定できるかもしれません。

クラスタを設定する

今回はhadoop1を親、hadoop2、hadoop3を子に設定します。

ここからは、Running Hadoop On Ubuntu Linux (Multi-Node Cluster)を参考にさせていただきました。

各設定項目の詳細は前述のサイト、または、公式サイトのCluster Setupを参照してください。

上記サイトの通りに設定すると、私の環境では以下のような設定になりました。

hadoop1の/etc/hadoop/masters

hadoop1

hadoop1の/etc/hadoop/slaves

hadoop1
hadoop2
hadoop3

全サーバの/etc/hadoop/core-site.xml

<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://hadoop1:9000</value>
</property>
</configuration>

全サーバの/etc/hadoop/mapred-site.xml

<configuration>
<property>
<name>io.sort.mb</name>
<value>30</value>
</property>
<property>
<name>mapred.job.tracker</name>
<value>hadoop1:9001</value>
</property>
</configuration>

全サーバの/etc/hadoop/hdfs-site.xml

<configuration>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
</configuration>

また、.bashrcに環境変数HADOOP_HOMEを設定する必要があるようです。 rpmからインストールした場合、設定ファイルは/etc/hadoopに格納されています。 このサイトによるとhadoopは$HADOOP_HOME/conf配下の設定ファイルを読みにいくようです。が、RPMからインストールした場合、パスにconfが含まれません…どうしたものか…とりあえず設定せず放置してみます…

ついに起動

hadoop1にて以下のコマンドを実行します。

$ bin/hadoop namenode -format
12/06/03 23:47:54 INFO namenode.NameNode: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG: host = hadoop1/xxx.xxx.xxx.xxx
STARTUP_MSG: args = [-format]
STARTUP_MSG: version = 1.0.3
STARTUP_MSG: build = https://svn.apache.org/repos/asf/hadoop/common/branches/branch-1.0 -r 1335192; compiled by 'hortonfo' on Tue May 8 20:35:39 UTC 2012
************************************************************/
Re-format filesystem in /tmp/hadoop-hadoop/dfs/name ? (Y or N) Y
12/06/03 23:48:02 INFO util.GSet: VM type = 64-bit
12/06/03 23:48:02 INFO util.GSet: 2% max memory = 2.475 MB
12/06/03 23:48:02 INFO util.GSet: capacity = 2^18 = 262144 entries
12/06/03 23:48:02 INFO util.GSet: recommended=262144, actual=262144
12/06/03 23:48:02 INFO namenode.FSNamesystem: fsOwner=hadoop
12/06/03 23:48:02 INFO namenode.FSNamesystem: supergroup=supergroup
12/06/03 23:48:02 INFO namenode.FSNamesystem: isPermissionEnabled=true
12/06/03 23:48:02 INFO namenode.FSNamesystem: dfs.block.invalidate.limit=100
12/06/03 23:48:02 INFO namenode.FSNamesystem: isAccessTokenEnabled=false accessKeyUpdateInterval=0 min(s), accessTokenLifetime=0 min(s)
12/06/03 23:48:02 INFO namenode.NameNode: Caching file names occuring more than 10 times
12/06/03 23:48:02 INFO common.Storage: Image file of size 112 saved in 0 seconds.
12/06/03 23:48:02 INFO common.Storage: Storage directory /tmp/hadoop-hadoop/dfs/name has been successfully formatted.
12/06/03 23:48:02 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at hadoop1/xxx.xxx.xxx.xxx
************************************************************/

hadoop1にてHDFSデーモンを起動します。

$ start-dfs.sh
starting namenode, logging to /var/log/hadoop/hadoop/hadoop-hadoop-namenode-hadoop1.out
hadoop2: starting datanode, logging to /var/log/hadoop/hadoop/hadoop-hadoop-datanode-hadoop2.out
hadoop3: starting datanode, logging to /var/log/hadoop/hadoop/hadoop-hadoop-datanode-hadoop3.out
hadoop1: starting datanode, logging to /var/log/hadoop/hadoop/hadoop-hadoop-datanode-hadoop1.out
hadoop1: starting secondarynamenode, logging to /var/log/hadoop/hadoop/hadoop-hadoop-secondarynamenode-hadoop1.out
$

hadoop2のログを確認します。


2012-06-04 00:00:07,327 ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: java.io.IOException: Call to hadoop1/xxx.xxx.xxx.xxx:9000 failed on local exception: java.net.NoRouteToHostException: ホストへの経路がありません

あらら…orz よく見るとiptablesが有効になっておりfirewallではじかれているようなので、iptablesごと停止しました。(本来はちゃんとそのポートだけあけるように設定すべきだと思います。このサーバは今回限りのサーバなので落としました)

# service iptables stop
$ stop-dfs.sh

$ start-dfs.sh
starting namenode, logging to /var/log/hadoop/hadoop/hadoop-hadoop-namenode-hadoop1.out

$

ログファイルを確認すると…

2012-06-04 00:06:57,409 ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: jav a.io.IOException: Incompatible namespaceIDs in /tmp/hadoop-hadoop/dfs/data:…

…orz

よく見ると先ほど参考にさせていただいたサイトにしっかり解説がありました。 以前に疑似分散モードで動かした際のHDFSデータが残っているため、分散ディスクがバッティングしているようです。 hadoop2,hadoop3の分散ディスクを削除します。

分散ディスクの保存先を調べます。

$ find / -name "dfs" 2> /dev/null
/tmp/hadoop-hadoop/dfs

ふむ…ちょっと乱暴かもしれませんが、/tmpの下であれば設定ファイルごと消してしまいましょう。(注意:当然過去に分散ファイルシステムに保存したデータは消えてしまいます。)

hadoop2,hadoop3上で実行

# rm -r /tmp/hadoop-hadoop/

改めてstart-dfs.shで起動すると先ほどのようなエラーは出ていませんでした。

MapReduceのデーモンを起動します。

$ start-mapred.sh
starting jobtracker, logging to /var/log/hadoop/hadoop/hadoop-hadoop-jobtracker-hadoop1.out
hadoop2: starting tasktracker, logging to /var/log/hadoop/hadoop/hadoop-hadoop-tasktracker-hadoop2.out
hadoop3: starting tasktracker, logging to /var/log/hadoop/hadoop/hadoop-hadoop-tasktracker-hadoop3.out
hadoop1: starting tasktracker, logging to /var/log/hadoop/hadoop/hadoop-hadoop-tasktracker-hadoop1.out

サンプルプログラム実行

前回と同様にデータを分散ファイルシステム上にアップロードします。

hadoop1で実行

$ pwd
/hadoop/test
$ ls
input output
$ hadoop fs -ls /
Found 1 items
drwxr-xr-x - hadoop supergroup 0 2012-06-04 00:21 /tmp
$ hadoop fs -put input /
12/06/04 00:28:33 INFO hdfs.DFSClient: Exception in createBlockOutputStream yyy.yyy.yyy.yyy:50010 java.net.NoRouteToHostException: ホストへの経路がありません
12/06/04 00:28:33 INFO hdfs.DFSClient: Abandoning block blk_4874660007000777417_1002
12/06/04 00:28:33 INFO hdfs.DFSClient: Excluding datanode yyy.yyy.yyy.yyy:50010
$ hadoop fs -ls /
Found 2 items
drwxr-xr-x - hadoop supergroup 0 2012-06-04 00:28 /input
drwxr-xr-x - hadoop supergroup 0 2012-06-04 00:21 /tmp

エラーがでました…がファイル自体はアップロードされているようです。

試しにhadoop2でも見てみましょう。

hadoop2で実行

$ hadoop fs -ls /
Found 2 items
drwxr-xr-x - hadoop supergroup 0 2012-06-04 00:28 /input
drwxr-xr-x - hadoop supergroup 0 2012-06-04 00:21 /tmp
$ hadoop fs -ls /input
Found 1 items
-rw-r--r-- 3 hadoop supergroup 500838 2012-06-04 00:28 /input/pg12429.txt
$

データは届いているようです…ネットで調べても原因がよく分からないのでとりあえず先に進みましょう。

hadoop1で実行

$ hadoop jar /usr/share/hadoop/hadoop-examples-1.0.3.jar wordcount /input /output
12/06/04 00:35:07 INFO hdfs.DFSClient: Exception in createBlockOutputStream zzz.zzz.zzz.zzz:50010 java.io.IOException: Bad connect ack with firstBadLink as yyy.yyy.yyy.yyy:50010
12/06/04 00:35:07 INFO hdfs.DFSClient: Abandoning block blk_-8843142491087234614_1003
12/06/04 00:35:07 INFO hdfs.DFSClient: Excluding datanode yyy.yyy.yyy.yyy:50010
12/06/04 00:35:07 INFO input.FileInputFormat: Total input paths to process : 1
12/06/04 00:35:07 INFO util.NativeCodeLoader: Loaded the native-hadoop library
12/06/04 00:35:07 WARN snappy.LoadSnappy: Snappy native library not loaded
12/06/04 00:35:07 INFO hdfs.DFSClient: Exception in createBlockOutputStream zzz.zzz.zzz.zzz:50010 java.io.IOException: Bad connect ack with firstBadLink as yyy.yyy.yyy.yyy:50010
12/06/04 00:35:07 INFO hdfs.DFSClient: Abandoning block blk_111384511553612831_1004
12/06/04 00:35:07 INFO hdfs.DFSClient: Excluding datanode yyy.yyy.yyy.yyy:50010
12/06/04 00:35:07 INFO hdfs.DFSClient: Exception in createBlockOutputStream zzz.zzz.zzz.zzz:50010 java.io.IOException: Bad connect ack with firstBadLink as yyy.yyy.yyy.yyy:50010
12/06/04 00:35:07 INFO hdfs.DFSClient: Abandoning block blk_-6241487032451864409_1005
12/06/04 00:35:07 INFO hdfs.DFSClient: Excluding datanode yyy.yyy.yyy.yyy:50010
12/06/04 00:35:07 INFO hdfs.DFSClient: Exception in createBlockOutputStream yyy.yyy.yyy.yyy:50010 java.net.NoRouteToHostException: ホストへの経路がありません

12/06/04 00:35:08 INFO mapred.JobClient: map 0% reduce 0%
12/06/04 00:35:23 INFO mapred.JobClient: map 100% reduce 0%
12/06/04 00:35:38 INFO mapred.JobClient: map 100% reduce 100%
12/06/04 00:35:43 INFO mapred.JobClient: Job complete: job_201206040021_0001

$ hadoop fs -ls /output
Found 3 items
-rw-r--r-- 3 hadoop supergroup 0 2012-06-04 00:35 /output/_SUCCESS
drwxr-xr-x - hadoop supergroup 0 2012-06-04 00:35 /output/_logs
-rw-r--r-- 3 hadoop supergroup 176845 2012-06-04 00:35 /output/part-r-00000

思いっきりエラー出てます…orz _SUCCESSが出ているのが救いでしょうか。(一部ノードにエラーが発生しても残ったノードだけで計算してくれるのですね。すばらしい。)

調べたところ同じ現象に遭遇した方がいらっしゃいました。 曰く、「firewallを止めたら動いた」…あれ…さっき止めたはず…と思ってみたらhadoop2だけ気の迷いで再起動していたのでした…(書いていませんでしたが…)

そうと分かれば話は早いと言う事でhadoop2のfirewallを改めてストップ。

ここより下の作業は全てhadoop1で実行します。

データを削除します。

$ stop-mapred.sh

$ stop-dfs.sh

$ start-dfs.sh

$ start-mapred.sh

$ hadoop fs -ls /
Found 3 items
drwxr-xr-x - hadoop supergroup 0 2012-06-04 00:28 /input
drwxr-xr-x - hadoop supergroup 0 2012-06-04 00:35 /output
drwxr-xr-x - hadoop supergroup 0 2012-06-04 00:21 /tmp
$ hadoop fs -rmr /output
Deleted hdfs://hadoop1:9000/output
$ hadoop fs -rmr /input
Deleted hdfs://hadoop1:9000/input
$ hadoop fs -ls /
Found 1 items
drwxr-xr-x - hadoop supergroup 0 2012-06-04 00:21 /tmp

引き続いてデータをアップロードします。

$ hadoop fs -put input /
$ hadoop fs -ls /
Found 2 items
drwxr-xr-x - hadoop supergroup 0 2012-06-04 01:02 /input
drwxr-xr-x - hadoop supergroup 0 2012-06-04 00:21 /tmp

実行!

$ hadoop jar /usr/share/hadoop/hadoop-examples-1.0.3.jar wordcount /input /output
12/06/04 01:06:13 INFO input.FileInputFormat: Total input paths to process : 1
12/06/04 01:06:13 INFO util.NativeCodeLoader: Loaded the native-hadoop library
12/06/04 01:06:13 WARN snappy.LoadSnappy: Snappy native library not loaded
12/06/04 01:06:13 INFO mapred.JobClient: Running job: job_201206040058_0001
12/06/04 01:06:14 INFO mapred.JobClient: map 0% reduce 0%
12/06/04 01:06:31 INFO mapred.JobClient: map 100% reduce 0%
12/06/04 01:06:40 INFO mapred.JobClient: map 100% reduce 33%
12/06/04 01:06:46 INFO mapred.JobClient: map 100% reduce 100%
12/06/04 01:06:51 INFO mapred.JobClient: Job complete: job_201206040058_0001

無事動いたようです! 結果を確認してみましょう。

$ hadoop fs -cat /output/part-r-00000 | head -8
"A 3
"Above 2
"Ah! 1
"Ah, 2
"Ah," 1
"An' 1
"And 1
"Announced 1
cat: Unable to write to output stream.

前回と同じ結果が得られました!よかった!

しかしこのくらいの量だと3台に分散されていないようです。 Webコンソールのactive task trackerを見るとこんな感じ。

Succeeded Tasks Since Start
hadoop34
hadoop20
hadoop10

全部hadoop3に飛んだらしいです…あまり意味が無いですね…通信はできてるようなのでよしとしますか…

まとめと次回

ここまででHadoopを使った分散計算ができるようになりました。 環境変数HADOOP_HOMEの謎は残りましたが、きちんと動作した事から推測すると、RPMからインストールした場合は自動的に各種変数がセットされていると考えるのが妥当でしょう。

次回は疑似分散モードに戻り、Hadoop上にApache Mahoutをインストールしようと思います。 Apache MahoutはHadoop上で動作する機械学習ライブラリです。 前から使ってみたかったので楽しみです。

参考