So-net無料ブログ作成

インフラエンジニアのためのCassandra情報 一覧取得 [Cassandra]

Cassandraを使っていると、登録したカラムの一覧や、キーの一覧を見たくなることがあり
ます。テストで登録したキーを削除しようにも、どんなキーを登録したのか分からないと
削除もできず、カラムをたくさん登録すると、カラム名が思い出せずに困ったり。
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を、引数に与えた数だけひたすらカウントアップするカウンターです。
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に置き換えても良いでしょう。

インフラエンジニアのためのkumofs情報 CentOS4 へのインストール その2 [kumofs]

次に、MessagePack for C++をconfigureしようとすると・・・
$ 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しか用意されていないようです。
$ 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 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の設定は、
$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メタデータを採取する側です。
ライブラリのインストール。
$ 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を使います。あらかじめインストールしておきます。
ビルドに必要なものを片っ端からインストール。
$ 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ノード側のインストール。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。

×

この広告は1年以上新しい記事の更新がないブログに表示されております。