Mahout の開発環境を Maven+Eclipse で作る (2) Hadoop セットアップ

Mahout はやっぱり Hadoop の上で使ってこそでしょ。というわけで開発用にも Hadoop をセットアップしなければならない。
基本的に HadoopLinux で使うべき。Linux 上での疑似分散くらいまでなら結構簡単にセットアップできる。ネット上にいっぱい情報がある。Cloudera 使ってもいい(まだ使ったこと無いけど)。
スタンドアローンなら Windows でもそんなには難しくない。けど、疑似分散になると途端にやっかい。


そんなこんなで Windows 2008 x64 に Hadoop 0.21.0 を疑似分散でセットアップにチャレンジ。
最初に結論から。


追記】Mahout 0.4 が Hadoop 0.20.2 なので、最初からそれを使うのがベストだった。0.5-SNAPSHOT も pom.xml を見る限り 0.20.2 なので、おとなしくそちらを使おう。【/追記

Java & Cygwin のインストール

いきなり最初の難関。
まず Hadoop 0.19 以降は JAVA_HOME に空白が入っているとエスケープしてもダブルクオートでくくっても正しく動作しない。そして Windows 2008 x64 には、ファイルパスの short name がない。したがってこの組み合わせで Java SDK のインストール先を Program Files 以下にすると、Hadoopスクリプトファイルを改造しない限りどうやっても動かない。


これ以上愚痴っていても仕方ないので、Java のインストール先を C:\Java\jdk1.6.0_23\ とかにする。Program Files に入れてしまっていたら、アンインストールして入れ直す。
Windows 2008 x64 でなくても、いらないところで引っかかる可能性がなくなるので、そうしておいたほうが吉。
もちろん環境変数 JAVA_HOME も設定しておく。


次は Cygwin。インストール時に忘れずに OpenSSH と OpenSSL を追加。といっても、今回は最終的に ssh は使わない(ぇ
インストール後、sshd の設定。管理者権限で cygwin を開いて、ssh-host-config を実行。

ssh-host-config -y

サービス起動ユーザのパスワードを聞かれるので、適当に設定。
完了したら CYGWIN sshd サービスが登録されているので、コントロールパネルの管理ツール>サービスから起動。


次は疑似分散時に使うユーザがパスワード無しで ssh が出来るように設定。

ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

ssh localhost でパスワード無しログインが出来ることを確認。


同ユーザの .bashrc に JAVA_HOME の設定。パスに ':' が入っているとうまく動かないので(つまり Windows環境変数に設定してあるものだとアウト)、Cygwin 用に別途記述。
ついでに HADOOP_HOME の設定も書いておこう。

export JAVA_HOME=/cygdrive/c/Java/jdk1.6.0_23
export HADOOP_HOME=/cygdrive/c/opt/hadoop-0.21.0/


そして Windows のシステム環境変数 PATH に C:\Cygwin\bin を追加して再起動。

Hadoop のインストール

適当なディレクトリに展開(もちろん Program Files じゃあないところ!)したら、設定ファイルを編集。
0.19 以前と 0.20 以降で違うので注意。もちろんここのは 0.20 以降。

conf/core-site.xml にネームノードを記述。
<configuration>
  <property>
    <name>fs.default.name</name>
    <value>hdfs://localhost:9000</value>
  </property>
</configuration>
conf/mapred-site.xml に JobTracker を記述。
<configuration>
  <property>
    <name>mapred.job.tracker</name>
    <value>localhost:9001</value>
  </property>
</configuration>
conf/hdfs-site.xmlHDFS レプリケーションの個数を記述。
<configuration>
  <property>
    <name>dfs.replication</name>
    <value>1</value>
  </property>
</configuration>


次は HDFS のフォーマット。よく忘れるw
0.21 から HDFS 関連のコマンドが bin/hdfs に分離された。

bin/hdfs namenode -format


そして Hadoop 起動。start-all.sh は 0.21 から deprecated になった。


一応、標準的な起動方法はこちら。

bin/start-dfs.sh
bin/start-mapred.sh

だが、これでは結局うまくいかなかった(後述)。

動作確認

NameNode
http://localhost:50070/
JobTracker
http://localhost:50030/

管理ページが表示されないなど、なにがしかのトラブルが発生したら、 $HADOOP_HOME/logs/ を見る。ログがいっぱいあるが、どのデーモンが問題を起こしているのかわからない場合は namenode, datanode, その他の順で。
ログファイルを見ても意味がわからなかったら、c:\tmp\hadoop-* を削除して HDFS のフォーマットからやり直す(削除せずにフォーマットではゴミが残るらしく、問題が解決しない場合も多い)。もちろん HDFS に大事な物をおいちゃダメ。
これがトラブル時の鉄則。


管理ページがちゃんと表示されたら、次にサンプルの Grep を実行するというよくあるパターン。
HADOOP_HOME に移動して、conf の中身を HDFS 上の input に放り込む。

$ bin/hadoop fs -put conf input
11/02/08 18:14:26 INFO security.Groups: Group mapping impl=org.apache.hadoop.security.ShellBasedUnixGroupsMapping; cacheTimeout=300000
11/02/08 18:14:27 WARN conf.Configuration: mapred.task.id is deprecated. Instead, use mapreduce.task.attempt.id

おかしな WARNING がでる。これは 0.22 では解消されるとか。いや、こんなところでこのレベルのインターフェース不整合とかないわ……。
ちなみにこの種の WARNING は他にも何種類もあって、しかも1回の実行で大量に、何回も出る。
そしてドキュメント類もまだ更新が追いついていないようだ。というわけでヒトバシラー以外は 0.21.0 を使わない方がいい。


put で以下のようなエラーが出る場合は datanode のログを見る。
でもいくつかのケースでこれにお目にかかったが、結局どれも「c:\tmp\hadoop-* を削除して HDFS のフォーマット」で乗り切ったので、最初からそっちを試すのでもいいかも。

11/02/08 17:27:30 WARN hdfs.DFSClient: DataStreamer Exception: java.io.IOException: File /user/shuyo/input/capacity-scheduler.xml could only be replicated to 0 nodes, instead of 1
        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getAdditionalBlock(FSNamesystem.java:1448)
        (後略)


次に grep のタスクを実行してみる……が、動かない。INFO ログを1行吐いたところで固まる。
実は、今回の組み合わせ&手順で Hadoop のデーモンを起こすと、c:\tmp に Hadoop の起動を行ったユーザの hadoop-[ユーザ名] の他になぜか sshd の起動ユーザである cyg_server の分 ( c:\tmp\hadoop-cyg_server\ ) までできていて、HDFS のシステムファイル一部がそっちにできているという意味不明の状況に陥る。
もちろん、これではまともに動くわけがない。


ssh 経由ではなく、手動で Hadoop のデーモンを起こせば回避できる。
「c:\tmp\hadoop-* を削除して HDFS のフォーマット」してから、Cygwin にて

bin/hadoop-daemon.sh start namenode
bin/hadoop-daemon.sh start secondarynamenode
bin/hadoop-daemon.sh start datanode
bin/hadoop-daemon.sh start jobtracker
bin/hadoop-daemon.sh start tasktracker

これを実行した cygwin 窓で ctrl+C を押すとデーモンが終了してしまうので、最小化でもしておいて使わないように。
【※注】0.21.0 からは secondarynamenode は deprecated となり、checkpoint node か backup node を使うべし、に変わったらしいのだが、start-dfs.sh はあいかわらず secondarynamenode を起動するので、そちらにしたがっている。【/※注】


ようやく実行。

$ bin/hadoop jar hadoop-mapred-examples-0.21.0.jar grep input output 'de[a-z]+'
11/02/08 18:14:34 INFO security.Groups: Group mapping impl=org.apache.hadoop.security.ShellBasedUnixGroupsMapping; cacheTimeout=300000
11/02/08 18:14:34 WARN conf.Configuration: mapred.task.id is deprecated. Instead, use mapreduce.task.attempt.id
11/02/08 18:14:34 WARN mapreduce.JobSubmitter: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
11/02/08 18:14:34 WARN mapreduce.JobSubmitter: No job jar file set.  User classes may not be found. See Job or Job#setJar(String).
11/02/08 18:14:34 INFO input.FileInputFormat: Total input paths to process : 16
11/02/08 18:14:35 WARN conf.Configuration: mapred.map.tasks is deprecated. Instead, use mapreduce.job.maps
        (中略)
11/02/08 18:15:53 WARN mapreduce.JobSubmitter: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
11/02/08 18:15:53 WARN mapreduce.JobSubmitter: No job jar file set.  User classes may not be found. See Job or Job#setJar(String).
11/02/08 18:15:53 INFO input.FileInputFormat: Total input paths to process : 1
11/02/08 18:15:54 WARN conf.Configuration: mapred.map.tasks is deprecated. Instead, use mapreduce.job.maps
        (後略)

$ bin/hadoop fs -cat 'output/part-r-00000'
11/02/08 18:24:08 INFO security.Groups: Group mapping impl=org.apache.hadoop.security.ShellBasedUnixGroupsMapping; cacheTimeout=300000
11/02/08 18:24:08 WARN conf.Configuration: mapred.task.id is deprecated. Instead, use mapreduce.task.attempt.id
60      description
60      der
19      default
8       des
4       defined
2       dex
1       den
1       defining
1       ded
1       decisions


結局、Hadoop の(疑似)分散環境は Linux 上に作ることにした。もちろん Hadoop 0.20.2 のね!