GlusterFS を現状のbeta3.3-1からbeta3.3-2へアップグレードしたが、色んな所でハマってしまった。また、HadoopのInputFormatへ対応させようとしたが、これもうまくいかなかった。結局アップグレードはせずに元に戻したが、今後再チャレンジするときのための備忘録
1 .GlusterFS 3.3-beta2
※ 3.3-beta2 でHadoopのInputFormatに対応するようになった。
# getfattr -m . -n trusted.glusterfs.pathinfo client_pathで物理的なロケーションを知ることができたのでこの対応は自然なように思える。このHadoop対応に伴ってbeta1とbeta2でそれなりに色々変更点があった。
1-1. trusted.glusterfs.pathinfo の出力の変更
beta2からは物理的なロケーション情報を得る際に取得できる項目が増えた。まずはその変更点をメモしておく。
# gluster volume info home Volume Name: home Type: Replicate Status: Started Number of Bricks: 2 Transport-type: tcp Bricks: Brick1: delta5:/home/doryokujin/test_vol_server Brick2: delta6:/home/doryokujin/test_vol_serverのようなReplicate Volumeに対して、
# mount -t glusterfs localhost:home /home/doryokujin/test_vol_clientでdelta6に" -t gluster" (fuse) オプションでマウントしておく。
※beta1:
# getfattr -m . -n trusted.glusterfs.pathinfo /home/doryokujin/test_vol_client/some_file getfattr: Removing leading '/' from absolute path names # file: home/doryokujin/test_vol_client/some_file trusted.glusterfs.pathinfo="( repository-dht delta6:home/doryokujin/test_vol_server/some_file )※beta2:
# getfattr -m . -n trusted.glusterfs.pathinfo /home/doryokujin/test_vol_client/some_file getfattr: Removing leading '/' from absolute path names # file: home/doryokujin/test_vol_client/some_file trusted.glusterfs.pathinfo="( <REPLICATE:home-replicate-0> <POSIX:delta5:/home/doryokujin/test_vol_server/some_file> <POSIX:delta6:/home/doryokujin/test_vol_server/some_file>)以上のようにReplicationしている場合はきちんとReplicaを含めたすべてのサーバーの物理ロケーションを表示してくれるようになった。また、Volume Type:"REPLICATE"などのフィールドが追加されている。これはHadoopのInputFormatとして扱う際に、<(.*):(.*)>のフィールドからVolume Typeと物理ロケーションを別々に読み取ってそれに応じたアクションを行うためである。この出力変更は自前のMapReduceを書く場合でもこのコマンドによって容易に物理ロケーションを知ることができ、大変有用である。
なお、
getfattr: Removing leading '/' from absolute path namesはエラー出力なのだがとりあえず放置(どこかにこのエラーについての言及があったと思うので後で追記)。
1-2. Volumeを再作成する際のidチェック(そしてエラー)
また、過去に作成したVolumeと同じserver pathにvolumeを作成しようとするとエラーが出て作成できなくなってしまった。このエラーのためにbeta2への更新は中断している。以下は過去に repository というVolumeを作っていたが、beta2への更新のためにいったん削除していたvolumeである。
# gluster volume create repository replica 2 transport tcp ¥ delta1:/repository delta11:/repository ¥ delta2:/repository delta12:/repository... ¥ delta6:/repository delta16:/repository 'delta6:/repository' has been part of a deleted volume with id fbbfeb57-4355-4a9b-a727-9c9f26b79220. Please re-create the brick directory.このように、「過去に削除したVolumeがあるのでbrickを再作成してね」というエラーが出て作成できない。beta1ではそんなこと聞かれなかったのに…同じようなバグはこちらのメーリングリストにも投稿されているが明確な回答は返ってきていない。以下のコマンドで現在の属性を確認する。
# attr -l /repository Attribute "gfid" has a 16 byte value for /repository Attribute "glusterfs.volume-id" has a 16 byte value for /repository Attribute "glusterfs.dht" has a 16 byte value for /repository Attribute "afr.repository-client-10" has a 12 byte value for /repository Attribute "afr.repository-client-11" has a 12 byte value for /repository過去の間違った操作で消えずになにか余計な属性が残ってしまっているのかな?ちなみにこれらの属性は
# sudo attr -r "gfid" /repository attr_remove: Operation not supported Could not remove "gfid" for /repositoryのような操作では削除できない。その後、この問題に対してGluserFS Developerの@vbellurさんから解決策を教えて頂いた。この方法できちんとVolumeの再作成ができた。
# setfattr -x "trusted.glusterfs.volume-id" /repository以上の2点がbeta2で新しく気づいた点である。ほかにもありそうだけど、結構大きな変更があった。しかしVolumeを作成した後も、途中でmountが解除されてしまうエラーが発生してうまくいかない。
[2011-09-07 17:45:43.277953] E [client-handshake.c:1157:client_query_portmap_cbk] 0-code-client-0: failed to get the port number for remote subvolume [2011-09-07 17:45:43.278083] E [client-handshake.c:1157:client_query_portmap_cbk] 0-code-client-1: failed to get the port number for remote subvolume [2011-09-07 17:46:28.412140] W [fuse-bridge.c:1751:fuse_readv_cbk] 0-glusterfs-fuse: 360: READ => -1 (No such file or directory) [2011-09-07 17:46:28.412182] E [mem-pool.c:468:mem_put] 0-mem-pool: invalid argument pending frames: patchset: git://git.gluster.com/glusterfs.git signal received: 11 time of crash: 2011-09-07 17:46:28 configuration details: argp 1 backtrace 1 dlfcn 1 fdatasync 1 libpthread 1 llistxattr 1 setfsid 1 spinlock 1 epoll.h 1 xattr.h 1 st_atim.tv_nsec 1 package-string: glusterfs 3.3beta2 /lib/x86_64-linux-gnu/libc.so.6(+0x33d80)[0x7f2593807d80] /lib/x86_64-linux-gnu/libpthread.so.0(pthread_spin_lock+0x0)[0x7f2593b748e0] /usr/local/lib/libglusterfs.so.0(fd_ref+0x23)[0x7f25943fb893] /usr/local/lib/glusterfs/3.3beta2/xlator/mount/fuse.so(+0x9a5d)[0x7f25927bda5d] /usr/local/lib/glusterfs/3.3beta2/xlator/mount/fuse.so(+0x181cf)[0x7f25927cc1cf] /lib/x86_64-linux-gnu/libpthread.so.0(+0x6d8c)[0x7f2593b6ed8c] /lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7f25938ba04d] ---------以下では上記のエラーが起きないようにテストVolumeを新たに作成してHadoopのインプットとしてGlusterFSから読み込ませようと試行錯誤した記録。
2. For Hadoop
2-1. 追加するConfigurationとその意味
まずドキュメントはこちら。conf/core-site.xml に次の項目を追記または変更する。
Hadoopが実行された時に、 fs.glusterfs.volname, fs.glusterfs.server, fs.glusterfs.mount を引数として、GlusterFSがきちんとマウントされているかを確認している。(GlusterFileSystem.java L82)。fs.glusterfs.impl org.apache.hadoop.fs.glusterfs.GlusterFileSystem $HADOOP_HOME/lib/ 以下に glusterfs-0.20.2-0.1.jar を fs.default.name glusterfs://namenode.geishatokyo.com:9000 namenodeのhost,port fs.glusterfs.volname repository 使用するGlusterFSのVolume名 fs.glusterfs.mount /mnt/disk1/glusterfs/client/repository Volumeのマウントポイント。ノードごとにmount先異なる場合は注意。 fs.glusterfs.server delta6 volumeのserverとなっているノードのhostnameを記述。 quick.slave.io Off
mountCmd = "mount -t glusterfs " + server + ":" + "/" + volname + " " + mount; # line 82 # ex.) mount -t glusterfs delta6:/repository /mnt/disk1/glusterfs/client/repositoryここでmountコマンド(他にも getfattr コマンド等)を内部で使用しているのでsudo権限がいるのでHadoop実行時にはsudo権限が必要。これらのパラメータの設定が不正確だとこの時点でエラーとなり、
System.out.println("Failed to initialize GlusterFS"); # line 127 System.exit(-1);となる。以下はPydoopでのip_countの実行例。conf.xmlに上記の設定を記述している。
# hadoop pipes -D mapred.reduce.tasks=12 ¥ -D hadoop.pipes.java.recordreader=true ¥ -D hadoop.pipes.java.recordwriter=true ¥ -D mapred.output.compress=false ¥ -conf conf.xml ¥ -program ip_count.py ¥ -input /mnt/disk1/glusterfs/client/repository/log_repository/some_file -output out_ip_count注意点:
- -program で指定したスクリプト名は fs.glusterfs.mount の値と結合したパス上から読み込まれる。
- -input 先頭に "gluster://" は不要。むしろエラーが出る。
java.lang.RuntimeException: java.lang.ClassNotFoundException: org.apache.hadoop.fs.glusterfs.GlusterFileSystem at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:996) at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:1508) at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:67) at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:1548) at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:1530) at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:228) at org.apache.hadoop.fs.Path.getFileSystem(Path.java:183) at org.apache.hadoop.mapred.JobHistory$JobInfo.logSubmitted(JobHistory.java:1243) at org.apache.hadoop.mapred.JobInProgress$3.run(JobInProgress.java:681) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:396) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1115) at org.apache.hadoop.mapred.JobInProgress.initTasks(JobInProgress.java:678) at org.apache.hadoop.mapred.JobTracker.initJob(JobTracker.java:4013) at org.apache.hadoop.mapred.EagerTaskInitializationListener$InitJob.run(EagerTaskInitializationListener.java:79) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662) Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.fs.glusterfs.GlusterFileSystem at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:248) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:943) at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:994) ... 17 more