ここでは擬似分散(Pseudo-Distributed)モードでHadoopをインストールします。ClouderaのCDH3を利用しています。
前項で説明したように、HadoopはNameNode(HDFS親)とDataNode(HDFS子)、JobTracker(MapReduce親)とTaskTracker(MapReduce子)という親子関係で成り立っています。
擬似分散モードはこれら4つの機能を1台のマシンで動作させます。
つまり自分で「分散して処理をしろ」と命令し、自分で「はい、わかりました」と言って実行するするという、寂しい一人芝居をするモードです。
寂しくはありますが、NameNodeやDataNodeなどの機能をインストールして動かすことになるので、1台しかパソコンがない場合でもなんとなくHadoopの雰囲気を味わえます。
今回はClouderaが出しているCDH3(Cloudera Distribution including Apache Hadoop v3)を利用しています。
CDHは名前の通り、Cloudera社が出しているHadoopのディストリビューションです。
apt-getやyumでHadoopをインストールできたり、インストール時に行う必要がある面倒な作業の一部を肩代わりしてくれたりします。
Cloudera社はHadoopの開発者が多数在籍しており、Hadoop関連のソフトウェアをオープンソース(Hadoopと同じApacheライセンス)で提供してくれています。Scalaに対するTypeSafeみたいな会社と言えば一部の人には分かりやすいでしょうか。
ドキュメントとかもけっこう公開してくれています。
Cloudera : http://www.cloudera.com/
現在提供されているディストリビューションはHadoop0.20ベースになっていますが、一部0.21の機能も組み込まれているそうです。
Hadoopのインストールを始める前に、sshとかrsyncとかそれっぽいものを入れておきます。
// とりあえずsshは入れる
$ sudo apt-get install ssh
// rsyncも入れる
$ sudo apt-get install rsync
// ntpも入れとく
$ sudo apt-get install ntp
// curlも入れよう
$ sudo apt-get install curl
// OpenJDKではなくて故SunのJDKを入れる
$ sudo aptitude install python-software-properties
// 本例はUbuntu10.04なのでlucid partner
$ sudo add-apt-repository 'deb http://archive.canonical.com/ lucid partner'
$ sudo apt-get update
$ sudo apt-get install sun-java6-jdk
次にHadoopの擬似分散モードを入れます。
単純にapt-getと言うだけでは入らないので、レポジトリを追加したりしています。
// source.list.d配下にファイルを追加
$ sudo vi /etc/apt/sources.list.d/cloudera.list
deb http://archive.cloudera.com/debian lucid-cdh3 contrib
deb-src http://archive.cloudera.com/debian lucid-cdh3 contrib
$ curl -s http://archive.cloudera.com/debian/archive.key | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install hadoop-0.20-conf-pseudo
こんな感じで実行すると、以下のようなメッセージが出てきます。
以下のパッケージが新たにインストールされます:
hadoop-0.20 hadoop-0.20-conf-pseudo hadoop-0.20-datanode hadoop-0.20-jobtracker hadoop-0.20-namenode hadoop-0.20-native
hadoop-0.20-secondarynamenode hadoop-0.20-tasktracker liblzo2-2
以下のものがインストールされるようです。
hadoop-0.20 | Hadoopの本体 |
hadoop-0.20-conf-pseudo | 擬似分散モードの設定ファイル |
hadoop-0.20-namenode | NameNode |
hadoop-0.20-datanode | DataNode |
hadoop-0.20-jobtracker | JobTracker |
hadoop-0.20-tasktracker | TaskTracker |
hadoop-0.20-secondarynamenode | SecondaryNameNode |
hadoop-0.20-native | 圧縮関連のnativeライブラリ |
liblzo2-2 | LZO圧縮機能 |
Hadoop本体と設定ファイル、それからお馴染みのNameNode、DataNode、JobTracker、TaskTrackerが入ります。
SecondaryNameNodeは名前の通りNameNodeのサブ的な機能です。とりあえずはいなくても動くのでここでは説明を割愛。
これらは/etc/rc.dにも登録されます。ということで再起動するとNameNodeやDataNodeは自動的に立ち上がります。
また、/etc/init.dの中を覗くと以下のファイルが出来上がっています。
hadoop-0.20-namenode hadoop-0.20-datanode hadoop-0.20-jobtracker hadoop-0.20-tasktracker hadoop-0.20-secondarynamenode
ということでservice hadoop-0.20-namenode restart | start | stopのような形でnamenodeやdatanodeを起動したり終了したりできます。
Hadoopを導入する時に割と用意が面倒な設定ファイルたちも用意してくれています。/etc/hadoop-0.20/conf.pseudoの配下がそれです。
HDFSの操作をする時に利用するhdfsという名前のユーザと、MapReduce用にmapredというユーザも作成されています。
$ cat /etc/passwd | grep hdfs
$ cat /etc/passwd | grep mapred
要約すると、CDH3をインストールすると、いろんなものが入ったりいろんなものが作られたりします。
とりあえず再起動するとNameNodeやDataNodeは立ち上がります。
立ち上がっているかどうかはstatusでrunningと出ればOKです。
$ service hadoop-0.20-namenode status
hadoop-0.20-namenode is running
$ service hadoop-0.20-datanode status
hadoop-0.20-datanode is running
手動で立ち上げる場合はserviceでstartします。
$ service hadoop-0.20-namenode start
$ service hadoop-0.20-datanode start
$ service hadoop-0.20-jobtracker start
$ service hadoop-0.20-tasktracker start
完全分散モードだとstartした後、立ち上がったフリをして即効で落ちていることもけっこうある。そんな時は「/usr/lib/hadoop-0.20/logs」配下の対応するログを見ます。
$ view /usr/lib/hadoop-0.20/logs/hadoop-hadoop-namenode-*.log
namenode、datanode、jobtracker、tasktrackerがそれぞれにログを吐いてます。たいていのエラー原因はここを見れば分かります。
NameNodeとJobTrackerの状態は以下のアドレスで確認できます(それぞれNameNode、TaskTrackerが動いているマシンのlocalhost)。
NameNode: http://localhost:50070/
JobTracker: http://localhost:50030/
上記URLが表示されればとりあえずNameNodeとJobTrackerは無事起動しているはずです。
さっそくHDFSを使ってみましょう。HDFSは以下のようにhadoopコマンドにLinuxのコマンドっぽい引数を付けてあげると実行できます。
$ hadoop fs -ls
ls: Cannot access .: No such file or directory.
まず、試しにデータを1つHDFS上に置いてみましょう。データはputコマンドで置けます。
// ディレクトリを作る
$ hadoop fs -mkdir /user/yourname
// HDFS上に置くファイルを作る
$ echo test > test.txt
// putしてみる
$ hadoop fs -put test.txt /user/yourname
// 置けたことを確認
$ hadoop fs -ls /user/yourname
Found 1 items
-rw-r--r-- 1 yourname supergroup 5 2011-10-27 23:47 /user/yourname/test.txt
// catしてみる
$ hadoop fs -cat /user/yourname/test.txt
test
// HDFS上からローカルにファイルを移す
$ hadoop fs -get /user/yourname/test.txt foo.txt
// ディレクトリを削除する
$ hadoop fs -rmr
他にもたくさんコマンドはあります。詳細はこちらにまとめました。
触ってみると分かりますが、動作はとても重いです。分散したりネットワーク上で飛ばしたりいろいろやってるので仕方ないことですが。
現状の擬似分散モードではHDD1台にデータが登録されていますが、設定を書き換えればブロックごとに複数のマシン、複数のHDDに分散してデータを登録するようになります。
我が家のパソコンはHDDを4台積んでいるので、1台のパソコンでも分散のメリットを味わえます。多分、eSATAやUSB3.0のHDDとかなら外部接続でもメリットを享受できるんじゃないでしょうか。
試しにやってみましょう。HDFSの設定は「hdfs-site.xml」というファイルに記述します。
// /mnt/sda2,sdb1,sdc1,sdd1というパスがmountされてるとして
// とりあえずhdfsユーザ用の
$ sudo mkdir /mnt/sda2/hdfs
$ sudo mkdir /mnt/sdb1/hdfs
$ sudo mkdir /mnt/sdc1/hdfs
$ sudo mkdir /mnt/sdd1/hdfs
$ sudo chown hdfs:hdfs /mnt/sda2/hdfs
$ sudo chown hdfs:hdfs /mnt/sdb1/hdfs
$ sudo chown hdfs:hdfs /mnt/sdc1/hdfs
$ sudo chown hdfs:hdfs /mnt/sdd1/hdfs
// hdfs-site.xmlを編集
$ sudo vi /etc/hadoop-0.20/conf/hdfs-site.xml
// dfs.data.dirというnameのpropertyを追加して、カンマ区切りでパスを入れる
<property>
<name>dfs.data.dir</name>
<value>/mnt/sdb1/hdfs,/mnt/sdc1/hdfs,/mnt/sdd1/hdfs</value>
</property>
// datanodeを再起動してフォーマット
$ sudo service hadoop-0.20-datanode restart
$ sudo -u hdfs hadoop datanode format
これでhttp://localhost:50070/を見ると、Configured Capacityの容量が増えているはず。
3TBを4台繋げば12TBのデータを持てるHDFSの出来上がり。但し擬似分散モードはレプリカの設定が1(複製は持たない)になっているので、1台でもHDDが死ねば全データが失われる素敵な状態ではありますが。
長時間使って遊ぶ場合はdfs.replicationを2くらいにしておくと良いかもしれない。
以下のパスにMapReduceで処理を行うサンプルjarが用意されている。
/usr/lib/hadoop-0.20/hadoop-examples.jar
このjarにはいろんな機能が入っていて、grep、sort、join、単語数のカウント、円周率の計算なんかが入っている。ソースを落としてくればサンプルコードとしても役立つ。
ソースはこの辺から落とす
http://hadoop.apache.org/common/releases.html#Download
hadoop-0.20.205.0.tar.gzを落とした場合、src/examples/org/apache/hadoop/examples 配下にソースがいる。
注意点として、mapredパッケージを使っている機能とmapreduceパッケージを使っている機能の2種類がいる。mapredが古いAPIでmapreduceが新しいAPIで混在している。mapredにはあるけどmapreduceにはない(0.21には入ってる)ような機能もあるので扱いが難しい。
試しに単語数のカウント機能(英語用だから形態素解析とかは無理)を使ってみる。
// 適当な英文を出力する
$ vi i_have_a_dream.txt
I have a dream that one day this nation will rise up and live out the true meaning of its creed: We hold these truths to be self-evident: that all men are created equal.
// hdfsユーザになってhomeディレクトリを作っておく
$ sudo su hdfs
$ hadoop dfs -mkdir /user/hdfs
// putする
$ hadoop dfs -put i_have_a_dream.txt .
// word countを実行する
$ hadoop jar /usr/lib/hadoop-0.20/hadoop-examples.jar wordcount i_have_a_dream.txt outdir
これを実行すると、引数で指定したoutdirというディレクトリの中に結果が出力されます。
$ hadoop dfs -ls outdir
// 結果を見てみる
$ hadoop dfs -cat outdir/part-r-00000
上記のコマンドを実行すると、なにやら単語の一覧とカウントがタブ区切りで出力されます。
こんな感じで擬似分散モードは実際に利用するであろう環境に非常に近いものであり、設定ファイルを書き換えて反映させれば動作が変わったりもします。
1台のマシンでそこそこにHadoopの妙技を味わいたいという場合には、なかなかに便利です。
ただ、実際に完全分散モードを利用しないとHadoopの感動は味わえないので、安物でもいいのでなんとかパソコンを3台くらい揃えて分散させてみた方が世界が開けて見えたりすることもあると思います。