今回も作業ログです.
自分用メモとも言う…
環境
ZooKeeper のクラスタは奇数台で構成される必要があるので, 少なくとも 3 台のサーバが必要になります.
借りている ConoHa VPS 3 台 を使ってクラスタを構築してみます.
3 台構成の場合 1 ノードが死んでもクラスタは正常に動作することが可能です.
ホスト名, スペック, OS は以下の通り.
- node01: ConoHa 1GB プラン, CentOS 7.3
- node02: ConoHa 1GB プラン, CentOS 7.3
- node03: ConoHa 2GB プラン, CentOS 7.3
ホスト名は各サーバの /etc/hosts
に書くなり, DNS で名前解決できるようにするなり適当に…
事前準備
ZooKeeper は実行時に Java が必要になるので, インストールしておきます.
$ sudo yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel
ZooKeeper 実行用のユーザを作成します.
あまり気にしない人は root で動かしても良いかもしれない?
$ sudo useradd -s /sbin/nologin -M zookeeper
インストール
執筆時点での最新版 (v3.4.9) をインストールします.
今回は /usr/local
にインストールすることにしました.
$ wget http://ftp.jaist.ac.jp/pub/apache/zookeeper/current/zookeeper-3.4.9.tar.gz
$ tar zxvf zookeeper-3.4.9.tar.gz
$ sudo mv zookeeper-3.4.9 /usr/local
$ sudo chown -R zookeeper.zookeeper /usr/local/zookeeper-3.4.9
$ sudo ln -s /usr/local/zookeeper-3.4.9 /usr/local/zookeeper
設定
ZooKeeper を運用するための最低限の設定をします.
$ sudo cp /usr/local/zookeeper/conf/zoo_sample.cfg /usr/local/zookeeper/conf/zoo.cfg
$ sudo vi /usr/local/zookeeper/conf/zoo.cfg
少なくともデータディレクトリだけは変更してください.
デフォルトの設定は /tmp
になっているのでサーバを再起動させるとデータが飛びます.
(データディレクトリの変更を忘れて, 何回か必要だったデータをふっ飛ばした経験が…)
dataDir=/var/lib/zookeeper
設定ファイル末尾にクラスタ構築用の設定を追加します.
<nodeId>
はクラスタ内で各ノードが一意となる数字です.
また <port1>
はリーダ接続用ポート, <port2>
はリーダ選出で使用されるポートです.
server.<nodeId>=<hostname>:<port1>:<port2>
今回は以下のように <nodeId>
とホスト名を関連付けました.
server.1=node01:2888:3888
server.2=node02:2888:3888
server.3=node03:2888:3888
次に, データディレクトリを用意します.
$ sudo mkdir /var/lib/zookeeper
$ sudo chown zookeeper.zookeeper /var/lib/zookeeper
各ノードが自分の <nodeId>
が認識できるようにデータディレクトリ直下に <nodeId>
が書かれた myid
ファイルを作成します.
$ echo <nodeId> | sudo tee /var/lib/zookeeper/myid
最後に systemd 用の service ファイルを書いておきます.
$ sudo vi /usr/lib/systemd/system/zookeeper.service
[Unit]
Description=Apache ZooKeeper
After=network.target
[Service]
User=zookeeper
ExecStart=/usr/local/zookeeper/bin/zkServer.sh start-foreground
KillMode=process
Restart=always
[Install]
WantedBy=multi-user.target
ファイアウォール設定
ZooKeeper は基本的に TCP でしか通信を行わないはずです.
クライアントが接続するポート (デフォルトは 2181/tcp) とノード間が通信するポート (前述した 2 つ) が接続できるようにしておきます.
$ sudo firewall-cmd --add-port 2181/tcp --add-port 2888/tcp --add-port 3888/tcp --permanent
$ sudo firewall-cmd --reload
起動
systemd に登録してあるのでサービスの起動は簡単です.
必要に応じて自動起動設定をしておきます.
$ sudo systemctl start zookeeper
$ sudo systemctl enable zookeeper // optional
確認
各ノードの状態を確認して, クラスタが正常に動作しているか確認してみます.
$ /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: follower
$ /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: follower
$ /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: leader
今回は node03 が leader となり, 他のノードは follower となりました.
ここで ZooKeepr クラスタの耐障害性を試すために leader である node03 を止めてみます.
$ sudo systemctl stop zookeeper
$ /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: follower
$ /usr/local/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: leader
今度は node02 が leader として選出されました.
最後に現在の leader である node02 を止めてみます.
$ sudo systemctl stop zookeeper
$ /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 クラスタが動作するためには以下の式で求められる数のノードが動作している必要があります.
最低ノード数 = \frac{クラスタ内の全ノード数}{2} + 1
今回は 3 ノードでクラスタを構成しているため, クラスタを動作するためには 2 ノード以上が動作している必要があります.
そのため 1 ノードだけ動作している状態ではエラーとなり, サービスを提供できません.
もちろんエラーになったクラスタも, 正常に動作しているノード数が最低以上になれば動作を再開することができます.
最後に
ZooKeeper は分散アプリケーションでよく用いられるミドルウェアなので, 構築方法を覚えておくと今後役立つかも??