docker-compose で zookeeper のクラスタを立ち上げて動作確認する

タイトルの通り、docker で zookeeper のクラスタ (= アンサンブル) を立ち上げて動作確認してみた。

## クラスタ立ち上げ

作業ディレクトリを作って docker-compose.yml を作成する。

```
$ mkdir zookeeper
$ cd zookeeper
$ vi docker-compose.yml
```
[library/zookeeper \- Docker Hub](https://hub.docker.com/_/zookeeper/) に書いてある内容をそのまま書き込む。

```yaml
version: '2'
services:
    zoo1:
        image: zookeeper
        restart: always
        ports:
            - 2181:2181
        environment:
            ZOO_MY_ID: 1
            ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888

    zoo2:
        image: zookeeper
        restart: always
        ports:
            - 2182:2181
        environment:
            ZOO_MY_ID: 2
            ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888

    zoo3:
        image: zookeeper
        restart: always
        ports:
            - 2183:2181
        environment:
            ZOO_MY_ID: 3
            ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
```

ドッカーコンポーザップ。

```
$ docker-compose up -d
Starting zookeeper_zoo1_1
Starting zookeeper_zoo2_1
Starting zookeeper_zoo3_1
```

うまく立ち上がったっぽい。

```
$ docker-compose ps
      Name                    Command               State                     Ports                    
------------------------------------------------------------------------------------------------------
zookeeper_zoo1_1   /docker-entrypoint.sh zkSe ...   Up      0.0.0.0:2181->2181/tcp, 2888/tcp, 3888/tcp 
zookeeper_zoo2_1   /docker-entrypoint.sh zkSe ...   Up      0.0.0.0:2182->2181/tcp, 2888/tcp, 3888/tcp 
zookeeper_zoo3_1   /docker-entrypoint.sh zkSe ...   Up      0.0.0.0:2183->2181/tcp, 2888/tcp, 3888/tcp
```

## データの読み書きとレプリケーションの確認

クラスタ内の 1 コンテナの中で `zkCli.sh` という専用のシェルを起動してみる。

```
$ docker exec -ti zookeeper_zoo1_1 bin/zkCli.sh
```

`help` と打つと、なんかいろいろコマンドがあることが分かる。

```
[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
        stat path [watch]
        set path data [version]
        ls path [watch]
        delquota [-n|-b] path
        ls2 path [watch]
        setAcl path acl
        setquota -n|-b val path
        history 
        redo cmdno
        printwatches on|off
        delete path [version]
        sync path
        listquota path
        rmr path
        get path [watch]
        create [-s] [-e] path data acl
        addauth scheme auth
        quit 
        getAcl path
        close 
        connect host:port
```

とりあえず zknode を作って、値をセットしたりゲットしてみたりする。

zknode の作成。

```
[zk: localhost:2181(CONNECTED) 11] create /helloworld "this is test"
Created /helloworld
```

作成した zknode の値を取得。

```
[zk: localhost:2181(CONNECTED) 12] get /helloworld
this is test
cZxid = 0x500000006
ctime = Thu Jan 12 05:43:06 GMT 2017
mZxid = 0x500000006
mtime = Thu Jan 12 05:43:06 GMT 2017
pZxid = 0x500000006
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 12
numChildren = 0
```

値を `set` コマンドで更新してみる。

```
[zk: localhost:2181(CONNECTED) 13] set /helloworld "this is test updated"
cZxid = 0x500000006
ctime = Thu Jan 12 05:43:06 GMT 2017
mZxid = 0x500000007
mtime = Thu Jan 12 05:43:25 GMT 2017
pZxid = 0x500000006
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 20
numChildren = 0
```

正常に更新されたことが分かる。

```
[zk: localhost:2181(CONNECTED) 14] get /helloworld                       
this is test updated
cZxid = 0x500000006
ctime = Thu Jan 12 05:43:06 GMT 2017
mZxid = 0x500000007
mtime = Thu Jan 12 05:43:25 GMT 2017
pZxid = 0x500000006
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 20
numChildren = 0
```

ここで一回 `docker exec` を抜けて、別の zookeeper コンテナにアクセスしてみる。

```
docker exec -ti zookeeper_zoo1_1 bin/zkCli.sh -server zookeeper_zoo2_1:2181
```

zknode が正常に複製されていた。

```
[zk: zookeeper_zoo2_1:2181(CONNECTED) 0] get /helloworld
this is test updated
cZxid = 0x500000006
ctime = Thu Jan 12 05:43:06 GMT 2017
mZxid = 0x500000007
mtime = Thu Jan 12 05:43:25 GMT 2017
pZxid = 0x500000006
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 20
numChildren = 0
```

## まとめ

docker-compose で zookeeper のクラスタを立ち上げて基本的な動作確認を行うことができた。
フェイルオーバーを試せていないので、次はフェイルオーバーを試す。

## 参考資料

* [library/zookeeper \- Docker Hub](https://hub.docker.com/_/zookeeper/)
* [ZooKeeper Getting Started Guide](https://zookeeper.apache.org/doc/r3.3.3/zookeeperStarted.html)
* [zookeeper leader follower 確認　コマンド \- Qiita](http://qiita.com/pioho07/items/43e81656a46b51cebc37)
* [Hadoop本読書会 \- 13章 ZooKeeper \- 大規模分散技術勉強会 in 名古屋](http://seesaawiki.jp/dainagoya/d/Hadoop%CB%DC%C6%C9%BD%F1%B2%F1%20-%2013%BE%CF%20ZooKeeper)
* [Cannot use shell pipes with docker exec · Issue \#8679 · docker/docker](https://github.com/docker/docker/issues/8679)