夢とガラクタの集積場

落ちこぼれ三流エンジニアである管理人の夢想=『夢』と、潰えた夢=『ガラクタ』の集積場です。

Mesos-MasterをZooKeeperで冗長化させる

こんにちは。

では、MesosのZooKeeperによる冗長化を確認してみます。
尚、前回の記事で「Hadoopインストールした前提」としましたが、
備忘録のため環境構築手順も残しておくことにします。
楽にインストールするよりは構成をきちんと把握してインストールできる手順・・・としているので、
効率的には悪くなっている気もしますが^^;

Mesosについては「2.Mesos冗長化」からになりますので、適宜読み飛ばして下さい。

1.cdh4.4.0インストール

cdh4.4.0のうち、以下のコンポーネントをインストールします。

  • ZooKeeper(Mesos冗長化用)
  • HDFS(Sparkのデータソース用)
1-1.ZooKeeperインストール

・ZooKeeperダウンロード&インストール
http://archive.cloudera.com/cdh4/redhat/6/x86_64/cdh/4.4.0/RPMS/noarch/ からダウンロード

# cd /usr/local/src
# wget http://archive.cloudera.com/cdh4/redhat/6/x86_64/cdh/4.4.0/RPMS/noarch/bigtop-utils-0.6.0+140-1.cdh4.4.0.p0.24.el6.noarch.rpm
# wget http://archive.cloudera.com/cdh4/redhat/6/x86_64/cdh/4.4.0/RPMS/noarch/zookeeper-3.4.5+23-1.cdh4.4.0.p0.24.el6.noarch.rpm
# wget http://archive.cloudera.com/cdh4/redhat/6/x86_64/cdh/4.4.0/RPMS/noarch/zookeeper-server-3.4.5+23-1.cdh4.4.0.p0.24.el6.noarch.rpm
# rpm -ivh bigtop-utils-0.6.0+140-1.cdh4.4.0.p0.24.el6.noarch.rpm
# rpm -ivh zookeeper-3.4.5+23-1.cdh4.4.0.p0.24.el6.noarch.rpm
# rpm -ivh zookeeper-server-3.4.5+23-1.cdh4.4.0.p0.24.el6.noarch.rpm

・ZooKeeper設定

# vi /etc/zookeeper/conf/zoo.cfg
※内容を下記で修正
=====
# the directory where the snapshot is stored.
dataDir=/var/lib/zookeeper
# the port at which the clients will connect
clientPort=2181
=====
↓
=====
# the directory where the snapshot is stored.
dataDir=/home/zookeeper/data
# the port at which the clients will connect
clientPort=2181
server.1=spark1:2888:3888
server.2=spark2:2888:3888
server.3=spark3:2888:3888
=====

・ZooKeeper初期化

# mkdir -p /home/zookeeper/data
# chown -R zookeeper:zookeeper /home/zookeeper
※spark1で実施
# sudo -u zookeeper /usr/lib/zookeeper/bin/zkServer-initialize.sh --myid 1
※spark2で実施
# sudo -u zookeeper /usr/lib/zookeeper/bin/zkServer-initialize.sh --myid 2
※spark3で実施
# sudo -u zookeeper /usr/lib/zookeeper/bin/zkServer-initialize.sh --myid 3

・ZooKeeper起動

# service zookeeper-server start
JMX enabled by default
Using config: /etc/zookeeper/conf/zoo.cfg
Starting zookeeper ... STARTED
※以下のコマンドを実行し、ログファイル/データファイルが出力されることを確認
# ls -lR /home/zookeeper/data
# ls -lR /var/log/zookeeper

・データクリア処理設定

# crontab -e
※下記のCron設定を追加
=====
30 3 * * * /usr/lib/zookeeper/bin/zkCleanup.sh /home/zookeeper/data -n 3
=====
1-2.HDFSインストール

HDFSダウンロード&インストール
http://archive.cloudera.com/cdh4/redhat/6/x86_64/cdh/4.4.0/RPMS/x86_64/ からダウンロード
最初にncをインストールします。

# yum install nc
# wget http://archive.cloudera.com/cdh4/redhat/6/x86_64/cdh/4.4.0/RPMS/x86_64/hadoop-2.0.0+1475-1.cdh4.4.0.p0.23.el6.x86_64.rpm
# wget http://archive.cloudera.com/cdh4/redhat/6/x86_64/cdh/4.4.0/RPMS/x86_64/bigtop-jsvc-1.0.10-1.cdh4.4.0.p0.25.el6.x86_64.rpm
# wget http://archive.cloudera.com/cdh4/redhat/6/x86_64/cdh/4.4.0/RPMS/x86_64/hadoop-hdfs-2.0.0+1475-1.cdh4.4.0.p0.23.el6.x86_64.rpm
# wget http://archive.cloudera.com/cdh4/redhat/6/x86_64/cdh/4.4.0/RPMS/x86_64/hadoop-hdfs-namenode-2.0.0+1475-1.cdh4.4.0.p0.23.el6.x86_64.rpm(spark1のみ)
# wget http://archive.cloudera.com/cdh4/redhat/6/x86_64/cdh/4.4.0/RPMS/x86_64/hadoop-hdfs-datanode-2.0.0+1475-1.cdh4.4.0.p0.23.el6.x86_64.rpm
# rpm -ivh hadoop-2.0.0+1475-1.cdh4.4.0.p0.23.el6.x86_64.rpm
# rpm -ivh bigtop-jsvc-1.0.10-1.cdh4.4.0.p0.25.el6.x86_64.rpm
# rpm -ivh hadoop-hdfs-2.0.0+1475-1.cdh4.4.0.p0.23.el6.x86_64.rpm
# rpm -ivh hadoop-hdfs-namenode-2.0.0+1475-1.cdh4.4.0.p0.23.el6.x86_64.rpm(spark1のみ)
# rpm -ivh hadoop-hdfs-datanode-2.0.0+1475-1.cdh4.4.0.p0.23.el6.x86_64.rpm

HDFS設定

# vi /etc/hadoop/conf/core-site.xml
※内容の設定部分を下記の値にする
====
<configuration>
        <property>
                <name>fs.default.name</name>
                <value>hdfs://spark1:55000</value>
        </property>
        <property>
                <name>fs.checkpoint.dir</name>
                <value>/home/hdfs/checkpoint</value>
        </property>
        <property>
                <name>hadoop.tmp.dir</name>
                <value>/home/hdfs/tmp</value>
        </property>
</configuration>
====

# vi /etc/hadoop/conf/hdfs-site.xml
※内容の設定部分を下記の値にする
====
<configuration>
        <property>
                <name>dfs.name.dir</name>
                <value>/home/hdfs/name</value>
        </property>
        <property>
                <name>dfs.data.dir</name>
                <value>/home/hdfs/data</value>
        </property>
        <property>
                <name>dfs.replication</name>
                <value>3</value>
        </property>
</configuration>
====

# vi /etc/hadoop/conf/slaves
※内容を下記の値にする
====
spark1
spark2
spark3
====

HDFS初期化

# cd /home
# mkdir hdfs
# mkdir hdfs/checkpoint
# mkdir hdfs/tmp
# mkdir hdfs/name
# mkdir hdfs/data
# chown -R hdfs:hdfs hdfs
※spark1のみで以下のコマンドを実行
# sudo -u hdfs hdfs namenode -format
(省略)
13/11/12 08:58:12 INFO namenode.NNStorage: Storage directory /home/hdfs/name has been successfully formatted.
(省略)

HDFS起動

※spark1のみで以下のコマンドを実行
# service hadoop-hdfs-namenode start

※以後、spark1、spark2、spark3で実行
# service hadoop-hdfs-datanode start
→ http://spark1:50070/ にアクセスし、NameNodeと3台のDataNodeが表示されることを確認

これでZooKeeperとHDFSの準備は完了です。
では実際にMesosをZooKeeperと組み合わせて起動してみます。

2.Mesos冗長化

2-1.mesos-masterの設定/起動

まず、mesos-masterも複数起動するため、spark1、spark2、spark3の3台のmesos-master-env.shを設定する形になります。
3台とも以下の内容に設定を行います。

# cp -p /usr/local/var/mesos/deploy/mesos-master-env.sh.template /usr/local/var/mesos/deploy/mesos-master-env.sh
# vi /usr/local/var/mesos/deploy/mesos-master-env.sh
※内容を下記のように修正
=====
export LD_LIBRARY_PATH=/usr/lib/jvm/java-1.7.0-openjdk.x86_64/jre/lib/amd64/server

# Some options you're likely to want to set:
export MESOS_zk=zk://spark1:2181,spark2:2181,spark3:2181/mesos
export MESOS_log_dir=/var/log/mesos
=====

その上で、3台で以下のコマンドを実行して起動します。

# /usr/local/sbin/mesos-daemon.sh mesos-master

すると、Masterが起動するのは前回の通りなのですが、Slaveとなるspark2、spark3でも
mesos-masterのUIが表示され、自分がリーダーでないためリーダーのUIに遷移するよう求めてくるようになります。
・spark1

・spark2

・spark3

2-2.mesos-slaveの設定/起動

次はmesos-slaveです。
spark1、spark2、spark3の3台のmesos-slave-env.shを設定する形になります。
3台とも以下の内容に設定を行います。

# cp -p /usr/local/var/mesos/deploy/mesos-slave-env.sh.template /usr/local/var/mesos/deploy/mesos-slave-env.sh
# vi /usr/local/var/mesos/deploy/mesos-slave-env.sh
※内容を下記のように修正
=====
export LD_LIBRARY_PATH=/usr/lib/jvm/java-1.7.0-openjdk.x86_64/jre/lib/amd64/server

# You must at least set MESOS_master.

# The mesos master URL to contact. Should be host:port for
# non-ZooKeeper based masters, otherwise a zk:// or file:// URL.
export MESOS_master=zk://spark1:2181,spark2:2181,spark3:2181/mesos

# Other options you're likely to want to set:
export MESOS_log_dir=/var/log/mesos
export MESOS_work_dir=/var/run/mesos
=====

その上で、3台で以下のコマンドを実行して起動します。

# /usr/local/sbin/mesos-daemon.sh mesos-slave

するとmesos-masterのUIに以下のようにSlaveの一覧が表示されるようになります。

2-3.ZooKeeperの中身の確認

上記の状態において、ZooKeeperの中身がどうなっているかを確認してみると、以下のようになっていました。
とりあえずMasterのアドレスを登録したのみ・・のようですね。

mesos/  mesosのZookeeperルートディレクトリ(env.shで指定)
├―0000000000(ephemeral) → 内容:master@192.168.100.246:5050
├―0000000001(ephemeral) → 内容:master@192.168.100.247:5050
└―0000000002(ephemeral) → 内容:master@192.168.100.248:5050
2-4.mesos-masterを落とした場合の動作

では、mesos-masterを落として動作を確認してみます。
spark1で以下のコマンドを実行して、終了します。

# killall mesos-master

すると、spark2がmasterになった旨が表示されます。

また、mesos-masterのログファイルを確認してみるとリーダーの再選出が行われた旨が記録されています。
・mesos-masterログ(spark2)

I1116 17:11:58.006407 15302 detector.cpp:420] Master detector (master@192.168.100.247:5050)  found 2 registered masters
I1116 17:11:58.007773 15302 detector.cpp:467] Master detector (master@192.168.100.247:5050)  got new master pid: master@192.168.100.247:5050
I1116 17:11:58.011451 15302 master.cpp:645] Elected as master!
I1116 17:11:58.012563 15303 master.cpp:1168] Attempting to re-register slave 201311130859-4133791936-5050-15712-1 at slave(1)@192.168.100.247:5051 (spark2)
I1116 17:11:58.012693 15303 master.cpp:2138] Adding slave 201311130859-4133791936-5050-15712-1 at spark2 with cpus(*):2; mem(*):6848; disk(*):45276; ports(*):[31000-32000]
I1116 17:11:58.013744 15303 master.cpp:1168] Attempting to re-register slave 201311130859-4133791936-5050-15712-2 at slave(1)@192.168.100.246:5051 (spark1)
I1116 17:11:58.013919 15303 master.cpp:2138] Adding slave 201311130859-4133791936-5050-15712-2 at spark1 with cpus(*):2; mem(*):6848; disk(*):45276; ports(*):[31000-32000]
I1116 17:11:58.013783 15304 hierarchical_allocator_process.hpp:434] Added slave 201311130859-4133791936-5050-15712-1 (spark2) with cpus(*):2; mem(*):6848; disk(*):45276; ports(*):
[31000-32000] (and cpus(*):2; mem(*):6848; disk(*):45276; ports(*):[31000-32000] available)
I1116 17:11:58.014154 15303 master.cpp:1168] Attempting to re-register slave 201311130859-4133791936-5050-15712-0 at slave(1)@192.168.100.248:5051 (spark3)
I1116 17:11:58.014364 15304 hierarchical_allocator_process.hpp:434] Added slave 201311130859-4133791936-5050-15712-2 (spark1) with cpus(*):2; mem(*):6848; disk(*):45276; ports(*):[31000-32000] (and cpus(*):2; mem(*):6848; disk(*):45276; ports(*):[31000-32000] available)
I1116 17:11:58.014430 15303 master.cpp:2138] Adding slave 201311130859-4133791936-5050-15712-0 at spark3 with cpus(*):2; mem(*):6848; disk(*):45276; ports(*):[31000-32000]
I1116 17:11:58.014894 15303 hierarchical_allocator_process.hpp:434] Added slave 201311130859-4133791936-5050-15712-0 (spark3) with cpus(*):2; mem(*):6848; disk(*):45276; ports(*):[31000-32000] (and cpus(*):2; mem(*):6848; disk(*):45276; ports(*):[31000-32000] available)

・mesos-masterログ(spark3)

I1116 17:11:59.284688 15288 detector.cpp:420] Master detector (master@192.168.100.248:5050)  found 2 registered masters
I1116 17:11:59.285804 15288 detector.cpp:467] Master detector (master@192.168.100.248:5050)  got new master pid: master@192.168.100.247:5050
I1116 17:11:59.288508 15288 master.cpp:643] Waiting to be master!

・mesos-slaveログ(共通)

I1116 17:11:49.717566 23612 slave.cpp:1978] master@192.168.100.246:5050 exited
W1116 17:11:49.717679 23612 slave.cpp:1981] Master disconnected! Waiting for a new master to be elected
I1116 17:11:59.641104 23612 detector.cpp:420] Master detector (slave(1)@192.168.100.246:5051)  found 2 registered masters
I1116 17:11:59.642663 23612 detector.cpp:467] Master detector (slave(1)@192.168.100.246:5051)  got new master pid: master@192.168.100.247:5050
I1116 17:11:59.646306 23612 slave.cpp:550] New master detected at master@192.168.100.247:5050
I1116 17:11:59.647213 23612 status_update_manager.cpp:157] New master detected at master@192.168.100.247:5050
I1116 17:11:59.649677 23614 slave.cpp:651] Re-registered with master master@192.168.100.247:5050

ZooKeeperの中身は下記のようになっていました。単純にspark1のエントリが消えただけのようですね。

mesos/  mesosのZookeeperルートディレクトリ(env.shで指定)
├―0000000001(ephemeral) → 内容:master@192.168.100.247:5050
└―0000000002(ephemeral) → 内容:master@192.168.100.248:5050
2-5.mesos-master再起動

では、spark1のmesos-masterを再起動します。

# /usr/local/sbin/mesos-daemon.sh mesos-master

するとspark1上のmesos-masterは起動しますが、リーダーは変わらずspark2のままとなります。

ログは以下の通り。加わったということだけ検知されているようです。
・mesos-masterログ(spark1)

I1116 17:21:33.621004 28984 detector.cpp:234] Master detector (master@192.168.100.246:5050) connected to ZooKeeper ...
I1116 17:21:33.621043 28984 detector.cpp:251] Trying to create path '/mesos' in ZooKeeper
I1116 17:21:33.626245 28984 detector.cpp:281] Created ephemeral/sequence znode at '/mesos/0000000003'
I1116 17:21:33.626687 28984 detector.cpp:420] Master detector (master@192.168.100.246:5050)  found 3 registered masters
I1116 17:21:33.627074 28984 detector.cpp:467] Master detector (master@192.168.100.246:5050)  got new master pid: master@192.168.100.247:5050

・mesos-masterログ(spark2)

I1116 17:21:31.991395 15301 detector.cpp:420] Master detector (master@192.168.100.247:5050)  found 3 registered masters

・mesos-masterログ(spark3)

I1116 17:21:33.265532 15289 detector.cpp:420] Master detector (master@192.168.100.248:5050)  found 3 registered masters

・mesos-slaveログ(共通)

I1116 17:21:33.624724 23612 detector.cpp:420] Master detector (slave(1)@192.168.100.246:5051)  found 3 registered masters

ZooKeeperの中身は下記のようになっており、後から起動したmesos-masterが後に追加されていく形をとっているようです。

mesos/  mesosのZookeeperルートディレクトリ(env.shで指定)
├―0000000001(ephemeral) → 内容:master@192.168.100.247:5050
├―0000000002(ephemeral) → 内容:master@192.168.100.248:5050
└―0000000003(ephemeral) → 内容:master@192.168.100.246:5050

・・・という形でmesos-masterが冗長化されることを確認できました。
次はSparkを実際に分散環境上で動かしてみる形になりますかね。