文鳥大好きエンジニアのガラクタ置き場

文鳥さんに日々癒されているエンジニアが業務で直面したものについてまとめていく…予定。

ZooKeeper のクラスタを構築してみる。

何をしようかと考えてみたのですが、特に思い浮かばなかったので ZooKeeper のクラスタを構築してみようと思います。

今回使うサーバ

今回は以下の条件でクラスタを構築していきたいと思います。

  • ホスト名 … ponteru.zk00[1-3]
  • ZooKeeper のバージョン … 3.4.10

前準備

ZooKeeper は実行時に Java が必要になるので前もって入れておきましょう。

$ sudo yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel

ZooKeeper のインストー

以下の手順で ZooKeeper をインストールしていきます。

# バイナリとかのダウンロード
$ wget http://ftp.riken.jp/net/apache/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz
  
# ダウンロードしたファイルの解凍
$ tar xzf zookeeper-3.4.10.tar.gz

今回は /usr/local/ 配下にダウンロードしたディレクトリを配置してリンクを生成しておきました。

# 今回は /usr/local に配置
$ sudo mv zookeeper-3.4.10 /usr/local
  
# シンボリックリンクを作っておく
$ sudo ln -s /usr/local/zookeeper-3.4.10 /usr/local/zookeeper

設定ファイルの編集

zoo.cfg の作成

今回は conf/zoo_sample.cfg を流用して設定ファイルを作成していくので conf/zoo_sample.cfg を conf/zoo.cfg としてコピーします。

$ sudo cp /usr/local/zookeeper/conf/zoo_sample.cfg /usr/local/zookeeper/conf/zoo.cfg

今回は zoo.cfg を以下のように編集しました。

# dataDir=/tmp のままだと情報が保持されないので保存先ディレクトリを変更
dataDir=/var/lib/zookeeper
  
# 末尾に quorum を構成する ZooKeeper 一覧を追記
server.1=ponteru.zk001:2182:2183
server.2=ponteru.zk002:2182:2183
server.3=ponteru.zk003:2182:2183

なお、zoo.cfg の末尾に追記した内容 server.=:<port_1>:<port_2> の規則に従っています。

変数名 説明
nodeId 各 ZooKeeper に割り当てる一意の値 (myid ファイルに記述)
hostname 割り当てた nodeId に対応した ZooKeeper のホスト名
port_1 他の ZooKeeper と通信するために使用するポート番号
port_2 リーダーと通信するために使用するポート番号
データディレクトリの作成

dataDir で指定したディレクトリがない場合は作成しておきましょう。

$ sudo mkdir /var/lib/zookeeper
myid ファイルの作成

各 ZooKeeper に対して、割り当てる nodeId を記述した myid ファイルをデータディレクトリ配下 (/var/lib/zookeeper) に作成します。

# ponteru.zk001 の場合
$ echo 1 | sudo tee /var/lib/zookeeper/myid
  
# ponteru.zk002 の場合
$ echo 2 | sudo tee /var/lib/zookeeper/myid
  
# ponteru.zk003 の場合
$ echo 3 | sudo tee /var/lib/zookeeper/myid

ZooKeeper の起動

以下のコマンドを全ホストで行えばおkです。

$ sudo /usr/local/zookeeper/bin/zkServer.sh start

ちょっと検証してみる

とりあえずクラスタが構築できているか確認するために status を確認してみます。

# ponteru.zk001 ... リーダーじゃない
$ /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: follower

# ponteru.zk002 ... リーダーじゃない
$ /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: follower
 
# ponteru.zk003 ... リーダー
$ /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: leader

上記の結果からクラスタが構築できていることがわかりました。

次にリーダーを落としてみます。

# ponteru.zk003
$ sudo /usr/local/zookeeper/bin/zkServer.sh stop
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED

# ponteru.zk002
$ /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: leader

# ponteru.zk001
$ /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: follower

リーダーが ponteru.zk002 に移りました!さらにリーダーを落としてみます。

# ponteru.zk002
$ sudo /usr/local/zookeeper/bin/zkServer.sh stop
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED

# ponteru.zk001
$ /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Error contacting service. It is probably not running.

クラスタとしての機能がなくなりました。(ZooKeeper のクラスタは多数決の原理で動作しているので、過半数のホストが落ちると機能しなくなります。)

まとめてきなもの

ZooKeeper のクラスタ構築方法についてまとめてみました。 意外と ZooKeeper を使うシーンは多いので、まだ構築したことないという方はぜひ!