インフラエンジニアのためのCassandra情報 一覧取得 [Cassandra]
Cassandraを使っていると、登録したカラムの一覧や、キーの一覧を見たくなることがあり
ます。テストで登録したキーを削除しようにも、どんなキーを登録したのか分からないと
削除もできず、カラムをたくさん登録すると、カラム名が思い出せずに困ったり。
Cassandra0.7系では登録した情報をツリー形式で表示できるGUIなどもちらほら見かけますが
0.6系用には見つかりません。
そこで、Cassandraへのrubyでのアクセス方法の確認も兼ねて作った一覧取得スクリプトを
紹介しておきます。
中身は、レンジスキャンAPIを数珠繋ぎしてるだけの簡単なものです。
http://github.com/so-net-developer/Cassandra/blob/master/getrange.rb
使用するには、ruby用のCassandraライブラリを必要とします。
使用方法は、引数に何も指定しないと、キースペース一覧を表示、
キースペース名を指定すると、キースペース内のカラムファミリ一覧を表示
キースペース名とカラムファミリ名を指定すると、キー一覧を表示
(キー一覧や、カラムが100件以上ある場合は、100件までしか表示しません)
キースペース名とカラムファミリ名、キーを指定すると、カラム一覧を表示
キースペース名とカラムファミリ名、キー、カラム名まで指定すると、値が表示。
ます。テストで登録したキーを削除しようにも、どんなキーを登録したのか分からないと
削除もできず、カラムをたくさん登録すると、カラム名が思い出せずに困ったり。
Cassandra0.7系では登録した情報をツリー形式で表示できるGUIなどもちらほら見かけますが
0.6系用には見つかりません。
そこで、Cassandraへのrubyでのアクセス方法の確認も兼ねて作った一覧取得スクリプトを
紹介しておきます。
中身は、レンジスキャンAPIを数珠繋ぎしてるだけの簡単なものです。
http://github.com/so-net-developer/Cassandra/blob/master/getrange.rb
使用するには、ruby用のCassandraライブラリを必要とします。
$ sudo gem install cassandra
使用方法は、引数に何も指定しないと、キースペース一覧を表示、
$ ./getrange.rb usage: getkey.rb keyspacename columfamily key Keyspace1 system usertable
キースペース名を指定すると、キースペース内のカラムファミリ一覧を表示
$ ./getrange.rb Keyspace1 Standard1 Standard2 StandardByUUID1 Super1 Super2
キースペース名とカラムファミリ名を指定すると、キー一覧を表示
$ ./getrange.rb Keyspace1 Standard1 key01 key02 : key99
(キー一覧や、カラムが100件以上ある場合は、100件までしか表示しません)
キースペース名とカラムファミリ名、キーを指定すると、カラム一覧を表示
$ ./getrange.rb Keyspace1 Standard1 key02 column1 column2
キースペース名とカラムファミリ名、キー、カラム名まで指定すると、値が表示。
$ ./getrange.rb Keyspace1 Standard1 key02 column1 value0201
インフラエンジニアのためのkumofs情報 CASを試す [kumofs]
kumofsはCAS(Compare-And-Swap)をサポートしています。これは、ある値を更新したい
場合に、他のプロセスが同時に更新しようとして競合が発生してしまうのを防ぐしくみ
です。具体的には、ひとつのプロセスが値を更新しようとしたとき、内部でその値に関連
付けられたバージョン番号を同時に取得して、書き込み時にバージョン番号を比較、同じ
であれば値を更新します。そしてバージョン番号も変わります。
バージョン番号が一致しなければ、他のプロセスが値を更新していることになるので、値の
取得からやり直します。
実際に試してみます。
まず、CASを使わないで2つのプロセスから同時に一つの値を更新してみます。
以下のようなrubyサンプルを作ります。
一つのvalueを、引数に与えた数だけひたすらカウントアップするカウンターです。
実行前に、キー「counter」にvalueとして「0」を入れておきます。
2つのプロセスとして起動して、同時にvalueを更新してみます。
結果を見てみると、
となり、合計20000にはなっていません。
更新が競合し、ひとつのプロセスが更新した結果を、他のプロセスが読み直しをせずに
自分の値で上書きしてしまったため、値が小さくなってしまってます。
次にCASを使って更新してみます。
mem.cas()は、do~endまでのブロックで定義された操作を、あらかじめ取得しておいた
バージョン番号と現在のそれと比較し、一致すれば値(ここではvalue)を書き込みます。
書込みが正常に行われると、「STORED」を返します。「STORED」以外の値が返ってくる
場合は、valueの取得とブロック内の処理をやり直して、再度バージョン番号の比較を
して書き込みを試します。
実行してみましょう。
結果は、
無事、合計が20000になりました。
テストに使用した、サンプルスクリプトは以下を参照。
http://github.com/so-net-developer/kumofs/blob/master/counter.rb
http://github.com/so-net-developer/kumofs/blob/master/cascounter.rb
実行には、ruby用のmemcacheライブラリmemcache-client(1.8.5)が必要です。
場合に、他のプロセスが同時に更新しようとして競合が発生してしまうのを防ぐしくみ
です。具体的には、ひとつのプロセスが値を更新しようとしたとき、内部でその値に関連
付けられたバージョン番号を同時に取得して、書き込み時にバージョン番号を比較、同じ
であれば値を更新します。そしてバージョン番号も変わります。
バージョン番号が一致しなければ、他のプロセスが値を更新していることになるので、値の
取得からやり直します。
実際に試してみます。
まず、CASを使わないで2つのプロセスから同時に一つの値を更新してみます。
以下のようなrubyサンプルを作ります。
一つのvalueを、引数に与えた数だけひたすらカウントアップするカウンターです。
for i in 1..ARGV[0].to_i do value = mem.get('counter',true) value = value.to_i + 1 mem.set('counter',value,0, true) end
実行前に、キー「counter」にvalueとして「0」を入れておきます。
$ telnet localhost 11211 Trying 127.0.0.1... Connected to localhost.localdomain (127.0.0.1). Escape character is '^]'. set counter 0 0 1 0 STORED
2つのプロセスとして起動して、同時にvalueを更新してみます。
$ ./counter.rb 10000 & $ ./counter.rb 10000 &
結果を見てみると、
$ telnet localhost 11211 Trying 127.0.0.1... Connected to localhost.localdomain (127.0.0.1). Escape character is ']'. get counter VALUE counter 0 5 11184 END
となり、合計20000にはなっていません。
更新が競合し、ひとつのプロセスが更新した結果を、他のプロセスが読み直しをせずに
自分の値で上書きしてしまったため、値が小さくなってしまってます。
次にCASを使って更新してみます。
for i in 1..ARGV[0].to_i do begin ret = mem.cas('counter',0,true) do |value| value.to_i + 1 end end until ret == "STORED\r\n" end
mem.cas()は、do~endまでのブロックで定義された操作を、あらかじめ取得しておいた
バージョン番号と現在のそれと比較し、一致すれば値(ここではvalue)を書き込みます。
書込みが正常に行われると、「STORED」を返します。「STORED」以外の値が返ってくる
場合は、valueの取得とブロック内の処理をやり直して、再度バージョン番号の比較を
して書き込みを試します。
実行してみましょう。
$ ./cascounter.rb 10000 & $ ./cascounter.rb 10000 &
結果は、
$ telnet localhost 11211 Trying 127.0.0.1... Connected to localhost.localdomain (127.0.0.1). Escape character is ']'. get counter VALUE counter 0 5 20000 END
無事、合計が20000になりました。
テストに使用した、サンプルスクリプトは以下を参照。
http://github.com/so-net-developer/kumofs/blob/master/counter.rb
http://github.com/so-net-developer/kumofs/blob/master/cascounter.rb
実行には、ruby用のmemcacheライブラリmemcache-client(1.8.5)が必要です。
$ sudo gem install memcache-client
インフラエンジニアのためのkumofs情報 バックアップ [kumofs]
kumofsはkumoctlコマンドでバックアップを行えますが、このコマンドを投げただけだと
各ノードにハッシュ担当分のデータがコピーされて置かれるだけです。これだとノードの
構成が同じ状態のときしか、リストアには使えません。どんな状態でもリストアできる
ようにするためには、各ノードに作られたバックアップデータを1箇所に集めて、一つの
ファイルにマージしておく必要があります。
ノードの数が多くなると、手作業で実施するのは面倒です。簡単なスクリプトを作っておく
と良いでしょう。
社内で作ってみたPerlスクリプトを紹介しておきますので、参考にしてください。
http://github.com/so-net-developer/kumofs/blob/master/kumo-backup.pl
スクリプトでやっていることは、順番に以下のようになります。
kumofsの正常稼動の確認。(faultノードがあればバックアップは中止)
ノードリストの取得。
バックアップコマンド投入。
各ノードからバックアップファイルをFTPで取得する。
取得した全てのバックアップファイルをマージする。
スクリプトの実行には、以下のモジュールが必要なので、CPAN等からあらかじめ入れて
おきます。
Net::FTP
Memcached::Fast
内部から、kumoctlコマンドを呼び出しています。
設定は、スクリプト中の変数定義を書き換えて行います。
FTPはscpに置き換えても良いでしょう。
各ノードにハッシュ担当分のデータがコピーされて置かれるだけです。これだとノードの
構成が同じ状態のときしか、リストアには使えません。どんな状態でもリストアできる
ようにするためには、各ノードに作られたバックアップデータを1箇所に集めて、一つの
ファイルにマージしておく必要があります。
ノードの数が多くなると、手作業で実施するのは面倒です。簡単なスクリプトを作っておく
と良いでしょう。
社内で作ってみたPerlスクリプトを紹介しておきますので、参考にしてください。
http://github.com/so-net-developer/kumofs/blob/master/kumo-backup.pl
スクリプトでやっていることは、順番に以下のようになります。
kumofsの正常稼動の確認。(faultノードがあればバックアップは中止)
ノードリストの取得。
バックアップコマンド投入。
各ノードからバックアップファイルをFTPで取得する。
取得した全てのバックアップファイルをマージする。
スクリプトの実行には、以下のモジュールが必要なので、CPAN等からあらかじめ入れて
おきます。
Net::FTP
Memcached::Fast
内部から、kumoctlコマンドを呼び出しています。
設定は、スクリプト中の変数定義を書き換えて行います。
FTPはscpに置き換えても良いでしょう。
インフラエンジニアのためのkumofs情報 CentOS4 へのインストール その2 [kumofs]
次に、MessagePack for C++をconfigureしようとすると・・・
と言って止まってしまう。gcc41は間違いなくインストール済みなので、CPUアーキテクチャの
判定をミスっているもよう。言われたとおりのオプションを指定してやり直し。
MessagePack for Ruby
そして、kumofsのビルドに入るはずなのですが、configureすると・・・
まず、MessagePackの時と同様、CFLAGS指定を要求してくる。追加指定して、make
しようとすると・・・
なにやらincludeファイルのNot Foundが山のように出てくる。
ファイル名を頼りに調べると、boost(C++ライブラリ)が無いようです。これはCentOSの
あるバージョン以降からは標準で入っているようなのですが、CentOS4.8ではデフォルト
どころか、yumでも入らない。
仕方がないので、ソースを拾ってきて、指定どおりビルド。いちおうrpm化しましたが
ビルドの時しか使わないでしょう。
このライブラリ、とても大きく、ビルドだけで1時間近くかかる。
気を取り直してconfigureし直すも、まだだめ。ファイルだけじゃなく、そもそも存在
しないディレクトリを参照してる。
そこで、エラーの内容と、CentOS5の/usr/include以下のディレクトリ構成を参考にして
シンボリックリンクを張ってみる。
(g++4のバージョンに合わせて適宜読み替えてください)
これで無事kumofsのconfigureが通る。
ほかのマシンにもインストールする場合は、これまでに作ったrpmパッケージを順番に
インストールすればOKです。(bootsは要らない)
$ tar xzvf msgpack-0.4.3.tar.gz $ cd msgpack-0.4.3 $ CC=gcc4 CXX=g++4 ./configure : Note that gcc < 4.1 is not supported. If you are using gcc >= 4.1 and the default target CPU architecture is "i386", try to add CFLAGS="--march=i686" and CXXFLAGS="-march=i668" options to ./configure as follows: $ ./configure CFLAGS="-march=i686" CXXFLAGS="-march=i686"
と言って止まってしまう。gcc41は間違いなくインストール済みなので、CPUアーキテクチャの
判定をミスっているもよう。言われたとおりのオプションを指定してやり直し。
$ CC=gcc4 CXX=g++4 ./configure CFLAGS="-march=i686" CXXFLAGS="-march=i686" $ make $ sudo /usr/local/sbin/checkinstall --exclude=/selinux ... $ sudo rpm -ivh /usr/src/redhat/RPMS/i386/msgpack-0.4.3-1.i386.rpm
MessagePack for Ruby
$ sudo gem install msgpack
そして、kumofsのビルドに入るはずなのですが、configureすると・・・
まず、MessagePackの時と同様、CFLAGS指定を要求してくる。追加指定して、make
しようとすると・・・
なにやらincludeファイルのNot Foundが山のように出てくる。
ファイル名を頼りに調べると、boost(C++ライブラリ)が無いようです。これはCentOSの
あるバージョン以降からは標準で入っているようなのですが、CentOS4.8ではデフォルト
どころか、yumでも入らない。
仕方がないので、ソースを拾ってきて、指定どおりビルド。いちおうrpm化しましたが
ビルドの時しか使わないでしょう。
$ tar xzvf boost_1_44_0.tar.gz $ cd boost_1_44_0 $ ./bootstrap.sh --prefix=/usr $ sudo /usr/local/sbin/checkinstall ./bjam install $ sudo rpm -ivh /usr/src/redhat/RPMS/i386/boost_1_44_0-20100921-1.i386.rpm
このライブラリ、とても大きく、ビルドだけで1時間近くかかる。
気を取り直してconfigureし直すも、まだだめ。ファイルだけじゃなく、そもそも存在
しないディレクトリを参照してる。
そこで、エラーの内容と、CentOS5の/usr/include以下のディレクトリ構成を参考にして
シンボリックリンクを張ってみる。
$ cd /usr/include/c++ $ ls 3.4.3 $ g++4 -v cc バージョン 4.1.2 20080704 (Red Hat 4.1.2-44) $ sudo ln -s 3.4.3 4.1.2 $ ls -la drwxr-xr-x 7 root root 4096 9月 21日 18:32 3.4.3 lrwxrwxrwx 1 root root 5 9月 21日 18:34 4.1.2 -> 3.4.3 $ cd 4.1.2 $ sudo ln -s /usr/include/boost/tr1/tr1 tr1
(g++4のバージョンに合わせて適宜読み替えてください)
これで無事kumofsのconfigureが通る。
$ cd kumofs-0.4.5 $ CC=gcc4 CXX=g++4 ./configure CFLAGS="-march=i686" CXXFLAGS="-march=i686" $ make $ sudo /usr/local/sbin/checkinstall --exclude=/selinux ... $ sudo rpm -ivh /usr/src/redhat/RPMS/i386/kumofs-0.4.5-1.i386.rpm
ほかのマシンにもインストールする場合は、これまでに作ったrpmパッケージを順番に
インストールすればOKです。(bootsは要らない)
インフラエンジニアのためのkumofs情報 CentOS4 へのインストール その1 [kumofs]
kumofsは日本で生まれただけあって日本語の情報も豊富で、インストールや設定で苦労
することも無いようです。ここでは、事情により古いCentOS4.8で動かしてみた結果を
記しておきます。
作者のサイトhttp://github.com/etolabo/kumofs/blob/master/doc/doc.ja.md
を見ると、動作要件として「linux >= 2.6.18」と記されています。その他ライブラリに
ついてはなんとかなるとして、CentOS4.8(2.6.9)で動くのかどうか・・・
結論から言うと、問題なく動いてます。ただし、kumofsのパッケージのビルド環境として
あるていど新しいLinux環境(コンパイラ、ライブラリ、その他の配置等)を前提にして
いるので、それなりに工夫(というよりごまかし)が必要でした。
作業の方針として、rpmパッケージ化してインストールします。ただでさえ面倒なビルド作業
を、kumofsを動かしたい全ノードで実施しなければいかない手間を省くためです。
yumでインストールするコンパイラ類はなるべく最新のものを取得したいので、
http://wiki.centos.org/AdditionalResources/Repositories/RPMForge
を参考にして、rpmforgeをインストールしておきます。
それから、rpm化にはcheckinstallを使うことにします。これも
http://www.asic-linux.com.mx/~izto/checkinstall/
から拾って、インストールしておきます。CentOS4.xでも普通にmake,make installでいけます。
後から入れるMessagePack for C++がgcc4.1以上を要求してくるので、これをインストール。
本来ならgcc44あたりを入れないと、kumofsのconfigureがうまく動かないのですが、CentOS4.xにはgcc41しか用意されていないようです。
必要なライブラリ類をインストール。(ソース元は省略)
zlib-devel
bzip2
openssl-devel
ruby1.8.7
RubyGems
TokyoCabinet
ここまでは、CentOS4.8であることは特に意識することなく定石どおり。
することも無いようです。ここでは、事情により古いCentOS4.8で動かしてみた結果を
記しておきます。
作者のサイトhttp://github.com/etolabo/kumofs/blob/master/doc/doc.ja.md
を見ると、動作要件として「linux >= 2.6.18」と記されています。その他ライブラリに
ついてはなんとかなるとして、CentOS4.8(2.6.9)で動くのかどうか・・・
結論から言うと、問題なく動いてます。ただし、kumofsのパッケージのビルド環境として
あるていど新しいLinux環境(コンパイラ、ライブラリ、その他の配置等)を前提にして
いるので、それなりに工夫(というよりごまかし)が必要でした。
作業の方針として、rpmパッケージ化してインストールします。ただでさえ面倒なビルド作業
を、kumofsを動かしたい全ノードで実施しなければいかない手間を省くためです。
yumでインストールするコンパイラ類はなるべく最新のものを取得したいので、
http://wiki.centos.org/AdditionalResources/Repositories/RPMForge
を参考にして、rpmforgeをインストールしておきます。
それから、rpm化にはcheckinstallを使うことにします。これも
http://www.asic-linux.com.mx/~izto/checkinstall/
から拾って、インストールしておきます。CentOS4.xでも普通にmake,make installでいけます。
後から入れるMessagePack for C++がgcc4.1以上を要求してくるので、これをインストール。
本来ならgcc44あたりを入れないと、kumofsのconfigureがうまく動かないのですが、CentOS4.xにはgcc41しか用意されていないようです。
$ sudo yum -y install gcc4 gcc4-c++
必要なライブラリ類をインストール。(ソース元は省略)
zlib-devel
$ sudo yum -y install zlib-devel
bzip2
$ tar xzvf bzip2-1.0.5.tar.gz $ cd bzip2-1.0.5 $ make $ sudo /usr/local/sbin/checkinstall ... $ sudo rpm -ivh /usr/src/redhat/RPMS/i386/bzip2-1.0.5-1.i386.rpm
openssl-devel
$ sudo yum -y install openssl-devel
ruby1.8.7
$ tar xzvf ruby-1.8.7-p249.tar.gz $ cd ruby-1.8.7-p249 $ ./configure $ make $ sudo /usr/local/sbin/checkinstall --fstrans=no ... $ sudo rpm -ivh /usr/src/redhat/RPMS/i386/ruby-1.8.7-p249-1.i386.rpm
RubyGems
$ tar xzvf rubygems-1.3.6.tgz $ cd rubygems-1.3.6 $ sudo /usr/local/sbin/checkinstall -R "/usr/local/bin/ruby setup.rb" ... $ sudo rpm -ivh /usr/src/redhat/RPMS/i386/rubygems-1.3.6-1.i386.rpm
TokyoCabinet
$ tar xzvf tokyocabinet-1.4.43.tar.gz tar.gz $ cd tokyocabinet-1.4.43 $ ./configue $ make $ sudo /usr/local/sbin/checkinstall $ sudo rpm -ivh /usr/src/redhat/RPMS/i386/tokyocabinet-1.4.43-1.i386.rpm
ここまでは、CentOS4.8であることは特に意識することなく定石どおり。
インフラエンジニアのためのHadoop情報 CDH2のアップデート [Hadoop]
Cloudera版のCDH2パッケージは、不定期にマイナーバージョンアップをしているようです。
ここでは、CDH2のバージョンアップ方法について書いておきます。
但し、HDFSのレイアウト変更を伴うようなメジャーバージョンのアップについては、それぞれ
の版ごとに注意事項があるはずなので、それらについてはここでは触れません。
Hadoopのアップデートで気をつけなければいけない点は、以下のとおり。
複数ノードで運用中、1台づつアップグレードすることができません。たとえマイナーバージョンアップといえども、NameNodeとDataNodeの間でバージョン番号のチェックが行われて、アップデートしたノードは古いバージョン
のクラスタに登録できないからです。
もう一点は、一度新しいバージョンでサービスを起動すると、たとえHadoopサービスを前の
バージョンに戻しても、起動しなくなります。新しいバージョンの起動時にローカルのデータ
ストアにバージョン番号が書き込まれているようです。
そういう理由で、バージョンアップはクラスタ全体を停止して、いっぺんに全てのノードを
アップデートする必要があります。
きちんと計画的に実施しましょう。
作業の前には、fsckコマンドを実施してHDFSが健全な状態であることを確認します。
Hadoopの全ノードを停止します。
停止順は、NameNode、JobTracker、DataNode、TaskTracker、SecondaryNameNodeです。
サービスの停止が確認できたら、yumコマンドでアップデートを実施します。
無事バージョンがあがっているこを確認します。(必ず起動前に)
全てのノードでアップデートが完了したら、全ノードを起動します。
起動順は、停止順と同じです。
ここでは、CDH2のバージョンアップ方法について書いておきます。
但し、HDFSのレイアウト変更を伴うようなメジャーバージョンのアップについては、それぞれ
の版ごとに注意事項があるはずなので、それらについてはここでは触れません。
Hadoopのアップデートで気をつけなければいけない点は、以下のとおり。
複数ノードで運用中、1台づつアップグレードすることができません。たとえマイナーバージョンアップといえども、NameNodeとDataNodeの間でバージョン番号のチェックが行われて、アップデートしたノードは古いバージョン
のクラスタに登録できないからです。
もう一点は、一度新しいバージョンでサービスを起動すると、たとえHadoopサービスを前の
バージョンに戻しても、起動しなくなります。新しいバージョンの起動時にローカルのデータ
ストアにバージョン番号が書き込まれているようです。
そういう理由で、バージョンアップはクラスタ全体を停止して、いっぺんに全てのノードを
アップデートする必要があります。
きちんと計画的に実施しましょう。
作業の前には、fsckコマンドを実施してHDFSが健全な状態であることを確認します。
$ hadoop fsck / : The filesystem under path '/' is HEALTHY
Hadoopの全ノードを停止します。
停止順は、NameNode、JobTracker、DataNode、TaskTracker、SecondaryNameNodeです。
サービスの停止が確認できたら、yumコマンドでアップデートを実施します。
$ sudo yum install hadoop : ================================================= ====================================== Package Arch Version Repository Size ================================================= ====================================== Updating: hadoop-0.20 noarch 0.20.1+169.113-1 cloudera-cdh2 21 M Updating for dependencies: hadoop-0.20-conf-pseudo noarch 0.20.1+169.113-1 cloudera-cdh2 10 k Transaction Summary ================================================= ====================================== Install 0 Package(s) Upgrade 2 Package(s) Total download size: 21 M Is this ok [y/N]: y
無事バージョンがあがっているこを確認します。(必ず起動前に)
$ hadoop version Hadoop 0.20.1+169.113 Subversion -r 6c765a47a9291470d3d8814c98155115d109d715 Compiled by root on Sun Sep 12 01:29:03 EDT 2010
全てのノードでアップデートが完了したら、全ノードを起動します。
起動順は、停止順と同じです。
インフラエンジニアのためのHadoop情報 PuppetとHadoop [Hadoop]
Hadoopでは、各ノードの設定ファイルを基本的に同一にしておく必要があります。
(ローカル特有な設定は除く)
クラスタに係わる設定を変更したい時は、全てのノードの設定ファイルを変更しなければ
いけないので、大変です。
しかも、Cloudera版Hadoopは全てのノードのサービスを再起動する必要もあります。
Hadoopクラスタ内のどこか1台をマスタにして、他のホストと設定を同期するようにしましょう。使用するのは、システム管理ツールとして知られるPuppet。
Puppetのインストールと基本設定については、
http://gihyo.jp/admin/serial/01/puppet
に詳しく紹介されているので、参考にしてインストールします。
ここでは、Hadoopの設定ファイル同期について紹介します。
puppetにはpushモードとpullモードがあります。
pullモードは、各ノードが30分おきにサーバへ同期をとりにいきます。
Hadoopの設定ファイルをそんなに頻繁に書き換えることは無いだろうし、再起動のからみも
あるので、ここはpushモードにします。
マスタとしてインストールしたPuppetのあるノードで、Hadoopの設定ファイルを書き換えたら
その都度、手動でpuppetrunコマンドで同期します。
site.ppの設定は、
fileserver.confには、
allowの指定にはワイルドカードが使えるので、全ノードを指定します。
同期される側の各ノードの設定は、namespaceauth.confに
とします。
各ノード側のPuppetの起動時には、puppetrun待ちのオプション「--listen --no-client」を
付けます。
例)
Hadoopの設定ファイルを更新後、同期を実施するには
とすれば、マスタサーバでの変更がノードの設定ファイルにも反映されます。
このままでは、設定ファイルが書き換わるだけで、再起動をしていないノードのHadoopには反映
されません。
そこで、同期と同時にノード側のHadoopサービスを再起動させましょう。
site.ppに以下の設定を追加します。
こうすると、設定ファイルのあるディレクトリ以下のファイルが更新されていたらDataNodeと
TaskTrackerのサービスが再起動されます。
実際の運用を想定したサンプルを以下に置いておきます。
https://github.com/so-net-developer/Hadoop/tree/master/puppet/
Puppet自身を含めた設定ファイルの同期と、サービスの再起動、ノードの追加が自動化されます。
(ローカル特有な設定は除く)
クラスタに係わる設定を変更したい時は、全てのノードの設定ファイルを変更しなければ
いけないので、大変です。
しかも、Cloudera版Hadoopは全てのノードのサービスを再起動する必要もあります。
Hadoopクラスタ内のどこか1台をマスタにして、他のホストと設定を同期するようにしましょう。使用するのは、システム管理ツールとして知られるPuppet。
Puppetのインストールと基本設定については、
http://gihyo.jp/admin/serial/01/puppet
に詳しく紹介されているので、参考にしてインストールします。
ここでは、Hadoopの設定ファイル同期について紹介します。
puppetにはpushモードとpullモードがあります。
pullモードは、各ノードが30分おきにサーバへ同期をとりにいきます。
Hadoopの設定ファイルをそんなに頻繁に書き換えることは無いだろうし、再起動のからみも
あるので、ここはpushモードにします。
マスタとしてインストールしたPuppetのあるノードで、Hadoopの設定ファイルを書き換えたら
その都度、手動でpuppetrunコマンドで同期します。
site.ppの設定は、
$path = '/etc/hadoop-0.20/conf.cluster' file { $path: source => 'puppet://srv1.example.com/hadoop/conf.cluster', recurse => true, }
fileserver.confには、
[hadoop] path /etc/hadoop-0.20 allow [Hadoopノードのアドレス]
allowの指定にはワイルドカードが使えるので、全ノードを指定します。
同期される側の各ノードの設定は、namespaceauth.confに
[puppetrunner] allow [マスタサーバのアドレス]
とします。
各ノード側のPuppetの起動時には、puppetrun待ちのオプション「--listen --no-client」を
付けます。
例)
$ /usr/sbin/puppetd --server [マスタサーバのアドレス] --listen --no-client
Hadoopの設定ファイルを更新後、同期を実施するには
$ sudo /usr/bin/puppetrun --host [Hadoopノードのアドレス]
とすれば、マスタサーバでの変更がノードの設定ファイルにも反映されます。
このままでは、設定ファイルが書き換わるだけで、再起動をしていないノードのHadoopには反映
されません。
そこで、同期と同時にノード側のHadoopサービスを再起動させましょう。
site.ppに以下の設定を追加します。
exec { '/etc/init.d/hadoop-0.20-datanode restart': subscribe => File['/etc/hadoop-0.20/conf.cluster'], refreshonly => true } exec { '/etc/init.d/hadoop-0.20-tasktracker restart': subscribe => File['/etc/hadoop-0.20/conf.cluster'], refreshonly => true }
こうすると、設定ファイルのあるディレクトリ以下のファイルが更新されていたらDataNodeと
TaskTrackerのサービスが再起動されます。
実際の運用を想定したサンプルを以下に置いておきます。
https://github.com/so-net-developer/Hadoop/tree/master/puppet/
Puppet自身を含めた設定ファイルの同期と、サービスの再起動、ノードの追加が自動化されます。
インフラエンジニアのためのHadoop情報 Gangliaその2 [Hadoop]
Hadoopノード側のGangliaのインストールです。JMXメタデータを採取する側です。
ライブラリのインストール。
前回作ったrpmパッケージをインストール。
起動スクリプトは、監視サーバのものをコピー。
設定ファイルも監視サーバのものをコピー。
起動します。
Gangliaはデフォルトではマルチキャストで監視側と通信するので、Ganglia監視サーバ
が同一セグメントにいれば、これでノード側のサーバ情報はグラフで見れるようになる
はずです。
無事動いたところで、本題のHadoopのJMXデータを拾います。
Cloudera版のHadoopは設定ファイル「hadoop-metrics.properties」の中にGangliaContext
が定義されています。今回は、ganglia-3.1.7なので、GangliaContext31を有効にします。
サービスを再起動します。
しばらくすると、gangliaの画面にJMXの情報が表示されます。
ライブラリのインストール。
$ sudo yum install libconfuse $ sudo yum install rrdtool
前回作ったrpmパッケージをインストール。
$ sudo rpm -ivh ganglia-3.1.7-1.i386.rpm
起動スクリプトは、監視サーバのものをコピー。
$ sudo cp gmond /etc/init.d/
設定ファイルも監視サーバのものをコピー。
$ cp gmond.conf /etc/ganglia/
起動します。
$ sudo /sbin/service gmond start
Gangliaはデフォルトではマルチキャストで監視側と通信するので、Ganglia監視サーバ
が同一セグメントにいれば、これでノード側のサーバ情報はグラフで見れるようになる
はずです。
無事動いたところで、本題のHadoopのJMXデータを拾います。
Cloudera版のHadoopは設定ファイル「hadoop-metrics.properties」の中にGangliaContext
が定義されています。今回は、ganglia-3.1.7なので、GangliaContext31を有効にします。
dfs.class=org.apache.hadoop.metrics.ganglia.GangliaContext31 dfs.period=10 dfs.servers=[Ganglia監視側ホストのIP]:8649 mapred.class=org.apache.hadoop.metrics.ganglia.GangliaContext31 mapred.period=10 mapred.servers=[Ganglia監視側ホストのIP]:8649 jvm.class=org.apache.hadoop.metrics.ganglia.GangliaContext31 jvm.period=10 jvm.servers=[Ganglia監視側ホストのIP]:8649
サービスを再起動します。
$ sudo /sbin/service hadoop-0.20-datanode restart $ sudo /sbin/service hadoop-0.02-tasktracker restart
しばらくすると、gangliaの画面にJMXの情報が表示されます。
インフラエンジニアのためのHadoop情報 Gangliaその1 [Hadoop]
これまではHadoopの死活監視が目的のNagios設定を見てきましたが、HadoopはJMX
を通してメモリ使用状況、ジョブ(MapReduce)の進行状況を詳細に見ることができます。
このJMXの値を、Gangliaというグラフ表示の監視ツールを使って可視化しましょう。
ジョブの投入状況に合わせて、メモリやCPUの利用率が各ノード毎にグラフ化されて
見えるので、ボトルネックの発見に役立つはずです。
Gangliaのインストールは終わっているものとして・・・としたいところですが
Nagiosと違って、Hadoopの各ノード側全てにインストールしなければいけないので
ちょっと面倒。
rpmパッケージを作って、各ノードに配布しちゃいましょう。
まずは、Ganglia監視サーバ側を作成。
rpm化にはcheckinstallを使います。あらかじめインストールしておきます。
ビルドに必要なものを片っ端からインストール。
次にGangliaのサイトから「ganglia-3.1.7.tar.gz」を取得してきてビルド。
出来上がった「ganglia-3.1.7-1.i386.rpm」をインストール。
このあと、設定ファイル、作業ディレクトリ作成、パーミッション設定、起動スクリプト作成
その他いろいろしないと起動しないのですが、これらもrpm化したパッケージを作ったので
それで早道しちゃいます。
http://github.com/so-net-developer/Hadoop/blob/master/tools/ganglia-conf-1.0-0.noarch.rpm
rpm化に使ったSPECファイルも置いておくので、何をやっているかはこれを見てください。
http://github.com/so-net-developer/Hadoop/blob/master/tools/ganglia-conf-1.0.spec
Ganglia監視サーバの起動。
参考までに、SPECファイルを使ってganglia-conf-1.0-0.noarch.rpmを作る方法を書いて
おきます。
まず、下に示すようなディレクトリを作り、ファイルを配置します。設定ファイルや起動
スクリプトもgangliaのソースを展開すると見つかるので、環境に合わせて修正したものを
配置します。
そして、homeディレクトリに上に示したrpmディレクトリを示すファイル「.rpmmacros」
を作ります。
そして、以下のようにtarファイルをSOURCES以下に作成します。
最後にrpmbuildコマンドでspecファイルを指定すればrpm/RPMS以下にrpmファイルが作られます。
次回は、Hadoopノード側のインストール。
を通してメモリ使用状況、ジョブ(MapReduce)の進行状況を詳細に見ることができます。
このJMXの値を、Gangliaというグラフ表示の監視ツールを使って可視化しましょう。
ジョブの投入状況に合わせて、メモリやCPUの利用率が各ノード毎にグラフ化されて
見えるので、ボトルネックの発見に役立つはずです。
Gangliaのインストールは終わっているものとして・・・としたいところですが
Nagiosと違って、Hadoopの各ノード側全てにインストールしなければいけないので
ちょっと面倒。
rpmパッケージを作って、各ノードに配布しちゃいましょう。
まずは、Ganglia監視サーバ側を作成。
rpm化にはcheckinstallを使います。あらかじめインストールしておきます。
ビルドに必要なものを片っ端からインストール。
$ sudo yum install rpm-build $ sudo yum install checkinstall $ sudo yum install libconfuse $ sudo yum install libconfuse-devel $ sudo yum install rrdtool $ sudo yum install rrdtool-devel $ sudo yum install gcc $ sudo yum install apr-devel $ sudo yum install expat-devel $ sudo yum install pcre-devel $ sudo yum install php $ sudo yum install php-gd $ sudo yum install httpd
次にGangliaのサイトから「ganglia-3.1.7.tar.gz」を取得してきてビルド。
$ tar xvf ganglia-3.1.7.tar.gz $ cd ganglia-3.1.7 $ ./configure --with-gmetad --sysconfdir=/etc/ganglia $ make $ sudo /usr/sbin/checkinstall
出来上がった「ganglia-3.1.7-1.i386.rpm」をインストール。
$ sudo rpm -ivh ganglia-3.1.7-1.i386.rpm
このあと、設定ファイル、作業ディレクトリ作成、パーミッション設定、起動スクリプト作成
その他いろいろしないと起動しないのですが、これらもrpm化したパッケージを作ったので
それで早道しちゃいます。
http://github.com/so-net-developer/Hadoop/blob/master/tools/ganglia-conf-1.0-0.noarch.rpm
rpm化に使ったSPECファイルも置いておくので、何をやっているかはこれを見てください。
http://github.com/so-net-developer/Hadoop/blob/master/tools/ganglia-conf-1.0.spec
$ sudo rpm -ivh ganglia-conf-1.0-0.noarch.rpm
Ganglia監視サーバの起動。
$ sudo /sbin/service gmetad start $ sudo /sbin/service gmond start $ sudo /sbin/service httpd start
参考までに、SPECファイルを使ってganglia-conf-1.0-0.noarch.rpmを作る方法を書いて
おきます。
まず、下に示すようなディレクトリを作り、ファイルを配置します。設定ファイルや起動
スクリプトもgangliaのソースを展開すると見つかるので、環境に合わせて修正したものを
配置します。
|-- ganglia-conf-1.0 | |-- etc | | |-- ganglia ←ganglia(gmond)用設定ファイル | | | `-- gmond.conf | | `-- init.d ←gangliaの起動スクリプト | | |-- gmetad | | `-- gmond | `-- var | `-- www | `-- html | `-- ganglia ←gangliaのソース中にあるwebディレクトリ以下全部 | |-- index.php | |-- 省略 | `-- version.php.in `-- rpm |-- BUILD |-- RPMS |-- SOURCES |-- SPECS | `-- ganglia-conf-1.0.spec `-- SRPMS
そして、homeディレクトリに上に示したrpmディレクトリを示すファイル「.rpmmacros」
を作ります。
$ echo "%_topdir /home/so-net/rpm" > .rpmmacros
そして、以下のようにtarファイルをSOURCES以下に作成します。
$ tar czvf rpm/SOURCES/ganglia-conf-1.0.tar.gz ganglia-conf-1.0
最後にrpmbuildコマンドでspecファイルを指定すればrpm/RPMS以下にrpmファイルが作られます。
$ rpmbuild -ba rpm/SPECS/ganglia-conf-1.0.spec
次回は、Hadoopノード側のインストール。
インフラエンジニアのためのHadoop情報 状態監視その2 [Hadoop]
TaskTrackerもDataNodeと同じように監視できます。
JobTrackerのWebUI(http://[JobTrackerのIP]:50030/jobtracker.jsp)画面中に表示されている
TaskTrackerのノード数を確認することで監視を行います。
チェックプログラムはこちら。
http://github.com/so-net-developer/Hadoop/blob/master/scripts/check_hadoop-task.pl
http://exchange.nagios.org/directory/Plugins/Others/check-Hadoop-tasktrackers/details
commands.cfgはこうなる。
ARG1、ARG2はDataNodeのときと同じ。
services.cfgの例は
SecondaryNameNodeの稼動状況の確認は、ステータスを確認する機能が見当たらないので、
メタデータファイルの更新状況を確認して判断します。
ファイルの更新は、SecondaryNameNode内で行われるので、Nagiosサーバからそれを直接見に
いくことができません。そこでNagios用nrpeの登場です。
監視対象のSecondaryNameNode側にnrpeを設定してNagiosサーバに通知してもらいます。
SecondaryNameNodeへのnrpeのインストール、基本設定は済ませてください。
メタデータファイルの更新状況を確認するスクリプトを以下に挙げておきます。
http://github.com/so-net-developer/Hadoop/blob/master/scripts/secondarynamenode_check.sh
http://exchange.nagios.org/directory/Plugins/Others/check-Hadoop-secondarynamenode/details
120分以上更新されていないファイルが見つかったら、SecondaryNameNodeのチェックポイントに
異常が発生しているとみなして、アラートを発します。
SecondaryNameNode上のnrpeの設定ファイルnrpe.cfgに以下の行を追加する。
そして、Nagios側のcommands.cfgはこうなる。
ARG1には、nrpeコマンドの識別子「check_checkpoint」を代入するので、services.cfgの例は
Nagios監視の最後にHadoopのHDFSについてです。HadoopのHDFSは、付属ツールの
「hadoop fsck」コマンドを実行すると、HDFSブロックの整合性やレプリケーションの状態、
DataNode数などが表示されます。
実行例)
最後の行に、「HEALTHY」と出てくると安心します。
どうせだから、これもNagiosで監視してしまいましょう。
nrpeでコマンドを起動し、「HEALTHY」が表示されなければ、アラートをあげるようにします。
nrpeでfsckコマンドを起動して、「HEALTHY」表示を確認するチェックスクリプトはこちら。
http://github.com/so-net-developer/Hadoop/blob/master/scripts/check_hdfs.sh
http://exchange.nagios.org/directory/Plugins/Others/check-Hadoop-HDFS-healthy/details
(hadoopコマンドにパスが通っていること、HDFSブロック数が非常に多いとnrpeのタイムアウトに注意)
nrpeはPrimaryNameNodeで動かします。(そこでしかfsckが通らないから)
nrpeの設定ファイルnrpe.cfgに以下を追加。
Nagiosサーバ側の設定もいつものように。
commands.cfg
services.cfg
JobTrackerのWebUI(http://[JobTrackerのIP]:50030/jobtracker.jsp)画面中に表示されている
TaskTrackerのノード数を確認することで監視を行います。
チェックプログラムはこちら。
http://github.com/so-net-developer/Hadoop/blob/master/scripts/check_hadoop-task.pl
http://exchange.nagios.org/directory/Plugins/Others/check-Hadoop-tasktrackers/details
commands.cfgはこうなる。
define command { command_name check_remote_tasktracker command_line /usr/local/bin/check_hadoop-task.pl $HOSTADDRESS$ $ARG1$ $ARG2$ }
ARG1、ARG2はDataNodeのときと同じ。
services.cfgの例は
define service { use generic-service host_name [JobTrackerホスト名] service_description check_remote_tasktracker contact_groups admins check_command check_remote_tasktracker!15!13 }
SecondaryNameNodeの稼動状況の確認は、ステータスを確認する機能が見当たらないので、
メタデータファイルの更新状況を確認して判断します。
ファイルの更新は、SecondaryNameNode内で行われるので、Nagiosサーバからそれを直接見に
いくことができません。そこでNagios用nrpeの登場です。
監視対象のSecondaryNameNode側にnrpeを設定してNagiosサーバに通知してもらいます。
SecondaryNameNodeへのnrpeのインストール、基本設定は済ませてください。
メタデータファイルの更新状況を確認するスクリプトを以下に挙げておきます。
http://github.com/so-net-developer/Hadoop/blob/master/scripts/secondarynamenode_check.sh
http://exchange.nagios.org/directory/Plugins/Others/check-Hadoop-secondarynamenode/details
120分以上更新されていないファイルが見つかったら、SecondaryNameNodeのチェックポイントに
異常が発生しているとみなして、アラートを発します。
SecondaryNameNode上のnrpeの設定ファイルnrpe.cfgに以下の行を追加する。
command[check_checkpoint]=/usr/local/bin/secondarynamenode_check.sh
そして、Nagios側のcommands.cfgはこうなる。
define command { command_name check_nrpe_secondarynamenode command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c $ARG1$ }
ARG1には、nrpeコマンドの識別子「check_checkpoint」を代入するので、services.cfgの例は
define service { use generic-service host_name sdh02 service_description check_nrpe_secondarynamenode contact_groups admins check_command check_nrpe_secondarynamenode!check_checkpoint }
Nagios監視の最後にHadoopのHDFSについてです。HadoopのHDFSは、付属ツールの
「hadoop fsck」コマンドを実行すると、HDFSブロックの整合性やレプリケーションの状態、
DataNode数などが表示されます。
実行例)
$ hadoop fsck / Total size: 2235588327935 B Total dirs: 127 Total files: 454 Total blocks (validated): 33584 (avg. block size 66567065 B) Minimally replicated blocks: 33584 (100.0 %) Over-replicated blocks: 0 (0.0 %) Under-replicated blocks: 0 (0.0 %) Mis-replicated blocks: 0 (0.0 %) Default replication factor: 3 Average block replication: 3.001608 Corrupt blocks: 0 Missing replicas: 0 (0.0 %) Number of data-nodes: 16 Number of racks: 1 The filesystem under path '/' is HEALTHY
最後の行に、「HEALTHY」と出てくると安心します。
どうせだから、これもNagiosで監視してしまいましょう。
nrpeでコマンドを起動し、「HEALTHY」が表示されなければ、アラートをあげるようにします。
nrpeでfsckコマンドを起動して、「HEALTHY」表示を確認するチェックスクリプトはこちら。
http://github.com/so-net-developer/Hadoop/blob/master/scripts/check_hdfs.sh
http://exchange.nagios.org/directory/Plugins/Others/check-Hadoop-HDFS-healthy/details
(hadoopコマンドにパスが通っていること、HDFSブロック数が非常に多いとnrpeのタイムアウトに注意)
nrpeはPrimaryNameNodeで動かします。(そこでしかfsckが通らないから)
nrpeの設定ファイルnrpe.cfgに以下を追加。
command[check_hdfs]=/usr/local/bin/check_hdfs.sh
Nagiosサーバ側の設定もいつものように。
commands.cfg
define command { command_name check_nrpe_hdfs command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c $ARG1$ -t 30 }
services.cfg
define service { use generic-service host_name sdh01 service_description check_nrpe_hdfs contact_groups admins check_command check_nrpe_hdfs!check_hdfs }