2011/01/31

Hadoopのslaveの増やし方、減らし方の続き


xperiaにskypeをインストールしたらバッテリーが1日持たなくなってしまいました。
今は充電ケーブルに行動範囲を縛られてるleonです。

今回は、前回の続き「ご紹介したHadoopサーバーの増やし方、減らし方」のハマり話です。

ハマったのはincludeファイル、excludeファイルの記述する方法です。

答え、先言っちゃいますね。
includeファイルと、excludeファイルにはサーバーのFQDNを記述しなきゃ行けなかったんです。

最初、slavesファイルと同じホスト名を記述したんですが、Hadoopサービスを再起動するとslaveサーバーが接続されないんです。

「hadoop-hadoop-jobtracker-hdmaster.log」を見ると以下のようなログが出てました。
2010-10-20 14:05:35,769 INFO org.apache.hadoop.ipc.Server: IPC Server handler 15 on 9001, call heartbeat(org.apache.hadoop.mapred.TaskTrackerStatus@51c293f8, true, true, -1) from 192.168.0.xxx:44035: error: org.apache.hadoop.mapred.DisallowedTaskTrackerException: Tasktracker denied communication with jobtracker: tracker_hdslave1.domain.jp:localhost.localdomain/127.0.0.1:44034
org.apache.hadoop.mapred.DisallowedTaskTrackerException: Tasktracker denied communication with jobtracker: tracker_hdslave1.domain.jp:localhost.localdomain/127.0.0.1:44034
    at org.apache.hadoop.mapred.JobTracker.heartbeat(JobTracker.java:1246)
    at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:481)
    at org.apache.hadoop.ipc.Server$Handler.run(Server.java:890)
はて?jobtrackerからクラスタへの接続が許可されないとな?includeファイルが読めてない?
Haddop設定ファイルのdfs.hostsプロパティとmapred.hostsプロパティの値を見直しても間違ってませんよ。って感じであれこれ試行錯誤しました。

で、ホスト名をFQDNにしてみたらなんとslaveサーバーと接続されるじゃないですか。

前回説明した通りmasters/slavesファイルとinclude/excludeファイルは役割が異なる。役割が異なるから設定も異なるってことなんでしょうね。
masters/slavesファイルはHadoop起動制御のシェルスクリプトが参照し、include/excludeファイルはHadoopのjavaプロセスが参照しています。

これ、わかんないですよねー。

あと、masterサーバーとslaveサーバーのネットワーク接続状態を確認したところ、hadoopのjavaプロセスはIPv6でバインドされてました。

$ sudo netstat -plten | grep java
tcp        0      0 ::ffff:192.168.0.5:9000     :::*                        LISTEN      220        2464200901 8483/java
tcp        0      0 ::ffff:192.168.0.5:9001     :::*                        LISTEN      220        2464201589 8766/java
(省略)

弊社のネットワークはすべてIPv4で構築してます。なので、HadoopもIPv4でバインドするように変更しました。具体的には、hadoopコマンドのスクリプトを編集して明示的にIPv4で接続するしました。

258 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.root.logger=${HADOOP_ROOT_LOGGER:-INFO,console}"
    259 if [ "x$JAVA_LIBRARY_PATH" != "x" ]; then
    260   HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=$JAVA_LIBRARY_PATH"
    261 fi
→  262 HADOOP_OPTS="$HADOOP_OPTS -Djava.net.preferIPv4Stack=true"
    263
    264 # run it
    265 exec "$JAVA" $JAVA_HEAP_MAX $HADOOP_OPTS -classpath "$CLASSPATH" $CLASS "$@"
262行目の1行が編集した部分です。

hadoopを再起動して、ネットワーク接続状態を確認すると・・・

$ sudo netstat -plten | grep java
tcp        0      0 192.168.0.5:9000            0.0.0.0:*                   LISTEN      220        2480561580 29797/java
tcp        0      0 192.168.0.5:9001            0.0.0.0:*                   LISTEN      220        2480562441 30112/java
(省略)

IPv4でバインドされてますね。OKです。

ではでは

2011/01/25

Hadoopサーバーの増やし方、減らし方



すべての地雷を踏む男leonです。

Hadoopカスタマイズをネタにブログを始めさせていただきました。
前回、Hadoopセットアップ手順を紹介させていただいたので、今回からカスタマイズ話をしたいと思います。

Hadoopのincludeファイル、excludeファイルにハマった・・・。
今日はそのお話をさせていただきます。

話を始める前にincludeファイル、excludeファイルとはなんですかを説明しないとですね。
このincludeファイルとexcludeファイルはサーバーのslave接続を終了させる際に、ノードからデータを退避して脱退させる為に使用します。

includeファイルはデータノードへの接続を許可されるデータノード、JobTrackerに接続可能なTaskTrackerのホスト名を記述するファイルです。includeファイルはdfs.hostsプロパティとmapred.hostsプロパティで指定します。

excludeファイルはデータノードへの接続を許可しないデータノード、JobTrackerに接続させないTaskTrackerのホスト名を記述するファイルです。excludeファイルはdst.hosts.excludeプロパティとmapred.hosts.excludeプロパティでシステムで指定します。

includeファイルとexcludeファイルを指定した場合のノード接続のルールは以下の通りです。

includeファイルexcludeファイル扱い
含まれていない含まれていないノードへ接続不可
含まれていない含まれているノードへ接続不可
含まれている含まれていないノードへ接続可
含まれている含まれているノードは接続可で、脱退させられる

JobTracker接続へのルールは以下の通りです。

includeファイルexcludeファイル扱い
含まれていない含まれていないTrackerへ接続不可
含まれていない含まれているTrackerへ接続不可
含まれている含まれていないTrackerへ接続可
含まれている含まれているTrackerへ接続不可

Hadoopにはmastersファイル、slavesファイルという設定ファイルがあり、slavesファイルとincludeファイルには同じような内容となりますが役割が異なります。

slavesファイルは、Hadoopのデーモン起動終了といったオペレーションの制御スクリプトで参照されます。

includeファイルは、Hadoopデーモンがノード接続、Tracker接続の許可不許可を確認するために参照しています。

ここまで偉そうに説明しましたが、includeファイル、excludeファイルのことは最近まで知らずデータの退避はできないと思っていました。
というのは、Hadoopにslave接続させるサーバーを増やしていく過程ではexcludeファイルはもちろん、includeファイルも必要なかったのです。

というのも、dfs.hostsプロパティ、mapred.hostsプロパティでincludeファイルを明示的に指定していなければ、ノード、Trackerへの接続はデフォルト許可だったんです。

うぅ~ん、まぁ、いい訳ですね。

さてさて、では、includeファイル/excludeファイルを指定してslavesサーバーを正しく脱退させる手順をご紹介していくことにします。

サーバー追加手順

  1. includeファイルに追加するslaveサーバーのホスト名を追記し、Hadoopサーバー全台に設定を同期します。
    $ echo "hdslave3.domain" >> /home/hadoop/hadoop/conf/hosts.include
    $ /home/hadoop/rsync.sh
    
    ※includeファイルにはサーバーのFQDNを記述します。
    ※rsync.shは前回のHadoopセットアップ手順を参照してください。

  2. hadoopコマンドでネームノードを更新します。
    $ /home/hadoop/hadoop/bin/hadoop dfsadmin -refreshNodes
    
  3. slavesファイルに追加するslaveサーバーのホスト名を追記し、設定を同期します。
    $ echo "hdslave3" >> /home/hadoop/hadoop/conf/slaves
    $ /home/hadoop/rsync.sh
    
  4. Hadoopシステムを再起動します。
    $ /home/hadoop/hadoop/bin/stop-all.sh
    $ /home/hadoop/hadoop/bin/start-all.sh
    

サーバー脱退手順

  1. excludeファイルにslave接続から脱退させるサーバーのホスト名を追記し、設定を同期します。
    $ echo "hdslave3.domain" >> /home/hadoop/hadoop/conf/hosts.exclude
    $ /home/hadoop/rsync.sh
    
  2. HadoopシステムのMapReduceクラスタを再起動します。
    $ /home/hadoop/hadoop/bin/stop-mapred.sh
    $ /home/hadoop/hadoop/bin/start-mapred.sh
    
  3. hadoopコマンドでネームノードを更新します。
    $ /home/hadoop/hadoop/bin/hadoop dfsadmin -refreshNodes
    
  4. 脱退中のデータノードからデータが退避されるのをひたすら(弊社の規模では1?2日)待ちます。
    データが退避できたかどうかは、以下のコマンドで確認します。
    $ hadoop/home/hadoop/bin/hadoop dfsadmin -refreshNodes
    
    StateがDecommission in progress から Decommissionedへ変更したらデータ退避完了です。

  5. includeファイル、excludeファイル、slavesファイルから脱退させるサーバーのホスト名を削除し、設定を同期します。
    $ grep -v "hdslave3" /home/hadoop/hadoop/conf/hosts.include >> /home/hadoop/hadoop/conf/hosts.include
    $ grep -v "hdslave3" /home/hadoop/hadoop/conf/hosts.exclude >> /home/hadoop/hadoop/conf/hosts.exclude
    $ grep -v "hdslave3" /home/hadoop/hadoop/conf/slaves >> /home/hadoop/hadoop/conf/slaves
    $ /home/hadoop/rsync.sh
    
  6. Hadoopシステムを再起動します。
    $ /home/hadoop/hadoop/bin/stop-all.sh
    $ /home/hadoop/hadoop/bin/start-all.sh
    
  7. hadoopコマンドでネームノードを更新します。
    $ /home/hadoop/hadoop/bin/hadoop dfsadmin -refreshNodes
    

なんと、手順説明までで時間切れになってしまいました。
ハマったお話は次回とさせていただきます。
ではでは

2011/01/17

Hadoopのカスタマイズ



はじめましてミツバチワークスleonです。
TECHチームの一員としてブログ連載をさせていただく機会をいただきました。

テーマはHadoopカスタマイズにします。

Hadoopは既にstoneさんが現在の運用で使っているテクニックを記事にされています。
そこで私はHadoopのカスタマイズについてご紹介させていいただくことにします。
私自身がHadoop初心者ということもあり、私は初歩からスタートさせていただこうと思います。お付き合いのほどよろしくお願いします。

Hadoopとは?から始めるのが礼儀かと思いますが、そこはwikipediaなどにお任せします。ご容赦ください。

何はともあれ立ち上がっているサービスがないと話を始められません。
そこで、最初の最初はHADOOPのセットアップ手順のご紹介です。

実際、弊社ではHadoopに十数台のサーバーを投入していますが、わかりやすいように最小限のサービス構成で紹介します。
数十台で運用していても基本は同じです。
master : hdmaster
slave : hdslave1, hdslave2
client : hdclient1

なお、いくつか前提条件があります。
・ユーザーはhadoopを用意(homedirは/home/hadoop)
・ホスト間のhadoopユーザーはパスフレーズでsshログインできる
・サーバーのスペック差分なし
・サーバーにはJava 1.4.2のJREがインストールされている

Hadoopはversion 0.18.3を使用しています。現在の最新versionは0.21.0でいまから紹介するにはずいぶん古いですね。
弊社がHadoopを導入した当時でも最新は0.18ではなかったんですが、あえて0.18.3を採用したんだそうです。
これにはちょっとした経緯があります。
stoneさんがHadoop記事でも触れてますが、我々はhadoop-streamingを利用してPerlで作成したmapperとreducerを使用しています。hadoop-streamingは当時、0.18.3が一番安定していたんだそうです。
なんでも新しいものがよいという訳ではないんですね。勉強になります。

では、Hadoopセットアップ手順です。どうぞ

1. HADOOPセットアップ

1.1 マスターセットアップ

$ ssh hdmaster
$ sudo su - hadoop
$ umask 002
$ wget http://ftp.kddilabs.jp/infosystems/apache/hadoop/core/stable/hadoop-0.18.3.tar.gz
$ tar xzf hadoop-0.18.3.tar.gz
$ mv hadoop-0.18.3 hadoop
これで/home/hadoop/hadoopに展開されています。

$ mkdir -p /home/hadoop/tmp
$ mkdir -p /home/hadoop/filesystem/dfs
$ mkdir -p /home/hadoop/logs
Hadoopで使用するディレクトの作成です。

$ vi /home/hadoop/hadoop/conf/masters
hdmaster
マスターのhostです。

$ vi /home/hadoop/hadoop/conf/slaves
hdslave1
hdslave2
スレーブのhost一覧です。スレーブを追加したらこのファイルにhostを追加していきます。

$ vi hadoop/conf/hadoop-env.sh
>>>
export JAVA_HOME=/usr/java/latest

export HADOOP_LOG_DIR=/home/hadoop/logs
>>>
Hadoop環境にJavaのパスを設定します。

$ vi hadoop/conf/hadoop-default.sh
>>>

<property></property>
  <name>hadoop.tmp.dir</name>
  <value>/home/hadoop/tmp/hadoop-${user.name}</value>
<description>A base for other temporary directories.</description>

>>>
Hadoopの一時ディレクトリのパスを設定します。

$ vi hadoop/conf/hadoop-site.sh
>>>
<configuration>

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

<property>
  <name>mapred.job.tracker</name>
  <value>hdmaster:9001</value>
</property>

<property>
  <name>dfs.name.dir</name>
  <value>/home/hadoop/filesystem/dfs/name</value>
</property>

<property>
  <name>dfs.data.dir</name>
  <value>/home/hadoop/filesystem/dfs/data</value>
</property>

<property>
  <name>mapred.system.dir</name>
  <value>/home/hadoop/filesystem/mapred/system</value>
</property>

<property>
  <name>mapred.local.dir</name>
  <value>/home/hadoop/filesystem/mapred/local</value>
</property>

<property>
  <name>dfs.replication</name>
  <value>1</value>
</property>

<property>
  <name>mapred.job.tracker.handler.count</name>
  <value>20</value>
</property>

<property>
  <name>mapred.map.tasks</name>
  <value>50</value>
</property>

<property>
  <name>mapred.reduce.tasks</name>
  <value>10</value>
</property>

</configuration>
>>>
サービス起動に必要な最低限の設定です。

1.2スレーブ&クライアントのセットアップ

$ ssh hdmaster
$ sudo su - hadoop
$ rsync --delete --progress -av hadoop hdslave1:
$ rsync --delete --progress -av hadoop hdslave2:
$ rsync --delete --progress -av hadoop hdclient:
基本的にスレーブとクライアントは同じ設定です。今後、スレーブやクライアントを増えていくことが予想される場合、以下のようにスクリプト準備しておくと便利です。
$ vi /home/hadoop/rsync.sh
#!/bin/sh

HOST_LIST="hdslave1, hdslave2, hdclient1"

cd /home/hadoop
for host in $HOST_LIST ; do
  rsync --delete --progress -av hadoop $host:
done
$ chmod 755 /home/hadoop/rsync.sh

1.3 サービスの起動

$ ssh hdmaster
$ sudo su - hadoop
$ /home/hadoop/hadoop/bin/hadoop namenode -format
$ /home/hadoop/hadoop/bin/bin/start-all.sh
namenodeのフォーマットはセットアップの際に1度行っておけばOKです。

1.4 動作確認

$ ssh hdclient
$ sudo su - hadoop
$ /home/hadoop/hadoop/bin/hadoop jar hadoop-0.18.3-examples.jar sudoku src/examples/org/apache/hadoop/examples/dancing/puzzle1.dta

これで準備OKです。
なお、ここまでは先人の叡智です。
私には既に動いているHadoopが与えられました。

私がHadoopに初めて触ったのはスレーブ追加作業からでして、そこで初ハマりがありました。
HADOOPスレーブの追加はスレーブのセットアップ後、マスターでサービスを再起動するだけだと教えていただいたのですが、サービス停止のスクリプトを実行してもスレーブで立ち上がっているjavaプロセスが終了しなかったんです。
そのときは、javaプロセスを直接killしちゃったんです。もう時効ですよね。

このあともHadoopのカスタマイズで四苦八苦を繰り返しています。
次回からは実体験のカスタマイズでハマったこと、気がついたことをご紹介していきたいと思います。

それでは