HadoopのException in BPOfferServiceにハマる

CDH4.3をかなり真面目にセットアップしていたら,こんなエラーに悩まされました.

CDH4.3のjarやetc/hadoop/*-site.xmlを全マシンに配置して,ネームノード(HA済み)→データノードの順に立ち上げていく時にエラーが出ました.


下記,データノードのログです.ネームノード側には何のエラーも出ていませんでした.アプリケーションマネージャが立ち上がっているかどうかも関係ありませんでした.

2013-10-30 16:02:33,400 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: For namenode activenamenode01/10.0.0.1:8020 using DELETEREPORT_INTERVAL of 300000 msec BLOCKREPORT_INTERVAL of 21600000msec Initial delay: 0msec; heartBeatInterval=3000
2013-10-30 16:02:33,400 ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: Exception in BPOfferService for Block pool BP-351553107-10.0.0.7-1383112458085 (storage id DS-867132266-10.0.0.7-50010-1383113343281) service to activenamenode01/10.0.0.1:8020
java.lang.NullPointerException
at org.apache.hadoop.hdfs.server.datanode.BPServiceActor.sendHeartBeat(BPServiceActor.java:435)
at org.apache.hadoop.hdfs.server.datanode.BPServiceActor.offerService(BPServiceActor.java:521)
at org.apache.hadoop.hdfs.server.datanode.BPServiceActor.run(BPServiceActor.java:673)
at java.lang.Thread.run(Thread.java:744)

よりによってヌルポです.
クラウデラをのせいかと思って,最新のApache Hadoop 2.2.0を入れてみたのですが,全く同じエラーが出たので,これはHadoopの設定ファイルをミスっているのだろうと.
ググったらネームノードをHigher Availabilityにしたらこのエラーが出たとか沢山出たので惑わされたのですが,原因はもっとマヌケで単純でした.


設定ファイルをミスっていました.


Hadoopの設定ファイルで,カンマ区切りで複数ディレクトリを書けるものは,ディレクトリが無いものは大抵無視されるので,次のような感じでデータの格納先を書いていました.


dfs.datanode.data.dir
file:///data1/data,file:///data2/data,file:///data3/data

If this is a comma-delimited list of directories then the name table is replicated in all of the directories, for redundancy.

「冗長性のために全てのディレクトリにレプリケートされます」と書いているのも誤解を招くもので,データ自体は書いた複数ディレクトリのどれか一つにストアされます.


これがなぜデータノードが立ち上がらない原因だったかと言うと,Hadoopに限らず(gridはともかく)clusterはマシンのスペックや構成を全部揃えるのが常識ですが,あるマシンは物理的なディスクが一つしか無いので/data1/dataしかなく,良いマシンは/data1から/data3まである,というふうに混在させていて,かつ設定ファイルを一台一台変えると管理が死ぬので,全部揃えていたせいでした.
要は,物理的なディスクが一つのマシンの設定ファイルにも,複数のディレクトリを記載していたと.



しかしHadoop様はそんなマヌケにも抜け穴を用意しておいてくれていて,


dfs.datanode.failed.volumes.tolerated
2

The number of volumes that are allowed to fail before a datanode stops offering service.
By default any volume failure will cause a datanode to shutdown.

例えば構成マシンのうち,とりあえず/data1は全部にあると.そして良いスペックのマシンは/data3まであって,貧弱なマシンは/data1しか無いような時,/data1から/data3のうち,/data2と/data3が無い2つエラーになっても良いよと許す設定があったので,こちらを設定したところ無事にCDH4.3で今までのアプリが動きました.

ネームノードは確かにActiveとStanbyの冗長構成にしていましたが,それとこのBPServiceActor.sendHeartBeatのエラーは関係ありませんでした.


立ち上がらなかった時はデフォルトのゼロになっていたので,貧弱なドライブが一つしか無いマシンでは記載した他のディレクトリが無いエラーが出て落ちていたようです.上記の例だと,2つまでエラーを許したので,記載した3つのディレクトリのうち2つがエラーになっても最低限一つのディレクトリがあれば立ち上がりました.